Compare commits

..
57 Commits
Author SHA1 Message Date
lealife 29413c0e52 debug 2017-12-01 10:52:48 +08:00
lealife 347e79610e add vendor agtorre/gocolorize 2017-12-01 10:52:41 +08:00
lealife c084792d32 prepare to release 2.6 2017-12-01 10:25:24 +08:00
lealife d77e636e53 remove unused 2017-12-01 10:25:08 +08:00
lealife 4729252c63 vendor 2017-11-30 20:18:21 +08:00
lealife 6cbb82a927 cmd 2017-11-30 20:15:28 +08:00
lealife bba9030f14 cmd 2017-11-30 20:11:10 +08:00
lealife 7cf6dbbe38 remove 2017-11-30 19:57:47 +08:00
lealife 00993e7fe1 Merge branch 'go-vendor-v2' 2017-11-30 19:55:54 +08:00
lealife 0fb92efbf3 go vendor 2017-11-30 19:55:33 +08:00
lealife 2856da6888 update travis 2017-11-30 19:14:42 +08:00
life c01a6dc9e9 Merge pull request #687 from wangduanduan/master
修改网页端博客文档导航无效的bug
2017-11-30 18:54:36 +08:00
lealife 845c96cd48 update travis 2017-11-30 18:50:44 +08:00
lealife 094d18be46 remove deprecated log 2017-11-30 18:46:30 +08:00
lealife c6937fd184 Compatible with revel 0.18 2017-11-30 18:10:59 +08:00
lealife 430744a324 build 2017-11-30 12:23:30 +08:00
lealife 98c1589a1a search replace tinymce 2017-11-30 12:23:30 +08:00
wang duanduan d81bb8c893 修改网页端博客文档导航无效的bug 2017-11-10 13:38:33 +08:00
life 21b774143b Merge pull request #641 from jjchern/patch-1
Fix a few typos in readme
2017-08-09 11:11:03 +08:00
jjchern 3925adc3f2 Fix a few typos in readme 2017-08-01 12:58:19 -05:00
lealife 371f5e23c3 realease 2017-07-27 20:25:54 +08:00
lealife 825fda5544 windows export pdf 2017-07-27 20:00:53 +08:00
lealife 6ede5c1559 for release 2017-07-27 15:31:52 +08:00
lealife 1ff90dacde Fix windows export pdf
https://github.com/leanote/leanote/issues/514
2017-07-27 15:08:34 +08:00
lealife 2654b684df upgrade revel to 0.16 2017-06-21 18:24:42 +08:00
life d424395d85 Update .travis.yml 2017-06-21 18:09:53 +08:00
life 54810b3458 Merge pull request #628 from samtux/master
Translation to Spanish
2017-06-21 17:57:56 +08:00
Samuel Mesa 1cf66ad6c0 Translation to Spanish 2017-06-19 21:10:49 -05:00
lealife 6dc334ca51 Chrome 58 cannot select image 2017-05-19 11:50:50 +08:00
life f9b4ead6be Merge pull request #590 from sundev126/patch-1
修复arm 32下/adminUser/index假死的bug
2017-04-16 21:36:13 +08:00
lealife 3bf6703929 blog paging configuration 2017-04-16 15:27:35 +08:00
Sunpy ec657b9dcb 修复arm 32下/adminUser/index假死的bug
如果pageSize为0,则计算页数的时候会造成浮点数除0.0,由于浮点数除0得到的结果是`+Inf`,转换为整数后的结果是`2,147,483,647`,所以在渲染page.html模板时需要很长时间。
2017-04-13 18:00:42 +08:00
lealife 4ffd048b2a Form submission canceled because the form is not connected 2017-04-12 15:58:55 +08:00
lealife 6af19670da Upgrade revel from 0.13 to 0.14
https://github.com/revel/revel/releases/tag/v0.14.0
2017-04-08 18:55:42 +08:00
lealife 721e375d76 mind map 2017-03-07 13:38:04 +08:00
lealife 41f95cf0e5 2.4 released 2017-02-20 13:57:24 +08:00
lealife ba411ef580 2.4 released 2017-02-20 13:51:07 +08:00
lealife 9dcf0ed53e delete unused 2017-02-20 13:48:26 +08:00
lealife d5d853ffd3 Support note list view and sorter 2017-02-18 20:01:43 +08:00
lealife ae29119664 set session.expires to 3h 2017-02-18 20:01:26 +08:00
lealife ad644258f5 Support for leanote-chrome plugin 2017-02-18 20:01:14 +08:00
lealife 8c98f4da5c markdown remove smartypants; support table align 2017-02-09 11:39:30 +08:00
lealife e2585bf695 2.3 released 2017-01-23 22:41:31 +08:00
lealife 3b9bc687c4 theme 2017-01-23 18:26:56 +08:00
lealife 2db182db1b 2.3 released 2017-01-23 17:43:41 +08:00
lealife f3e1eb6c3f Add leaui mind map plugin 2017-01-23 17:43:13 +08:00
lealife 956e1ba2bb fix upload image error [api] 2017-01-23 17:42:38 +08:00
lealife f294fa4124 fix cannot add deleted tags 2017-01-23 17:42:21 +08:00
lealife cabf89f9b8 like bug 2017-01-23 17:42:04 +08:00
lealife d183cd5a77 https://github.com/leanote/leanote/issues/513 2017-01-16 11:49:30 +08:00
lealife 000dfea92d 2.2.2 2017-01-07 15:55:31 +08:00
lealife a53398ebb4 Fix export note image to pdf error 2017-01-07 15:53:22 +08:00
lealife b23592229a update travis 2016-12-31 12:16:17 +08:00
lealife 584bde247e fix search deleted note 2016-12-31 12:10:27 +08:00
lealife 6774392807 2.2.1 2016-12-28 11:19:09 +08:00
lealife 964cf1a750 fix issue can't sync images on markdown notes 2016-12-28 10:27:08 +08:00
lealife 52128e6453 update qq groups 2016-12-26 15:45:48 +08:00
1043 changed files with 302069 additions and 2027 deletions

No files matched your search

-1
View File
@@ -7,7 +7,6 @@ bin/release
bin/test.sh bin/test.sh
bin/tmp bin/tmp
bin/test bin/test
bin/src
public/upload public/upload
app/routes/routes.go app/routes/routes.go
app/tmp/main.go app/tmp/main.go
-17
View File
@@ -1,17 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>leanote-public</name>
<comment>leanote, your own cloud note!</comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>com.googlecode.goclipse.goBuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>goclipse.goNature</nature>
</natures>
</projectDescription>
+2 -4
View File
@@ -1,5 +1,5 @@
language: go language: go
go: 1.4 go: 1.7
services: services:
- mongodb # 2.4.12 - mongodb # 2.4.12
@@ -16,9 +16,7 @@ install:
script: script:
- mongo --version - mongo --version
- mongorestore -h localhost -d leanote --directoryperdb ./mongodb_backup/leanote_install_data/ - mongorestore -h localhost -d leanote --dir ./mongodb_backup/leanote_install_data/
- go test github.com/leanote/leanote/app/tests
# gen tmp/main.go, routes/routes.go # gen tmp/main.go, routes/routes.go
- go run app/cmd/main.go - go run app/cmd/main.go
+2 -2
View File
@@ -28,7 +28,7 @@ gulp.task('concatDepJs', function() {
'js/jQuery-slimScroll-1.3.0/jquery.slimscroll-min.js', 'js/jQuery-slimScroll-1.3.0/jquery.slimscroll-min.js',
'js/contextmenu/jquery.contextmenu-min.js', 'js/contextmenu/jquery.contextmenu-min.js',
'js/bootstrap-min.js', 'js/bootstrap-min.js',
'js/object_id-min.js', 'js/object_id.js',
]; ];
for(var i in jss) { for(var i in jss) {
@@ -340,7 +340,7 @@ gulp.task('tinymce', function() {
var cp = require('child_process'); var cp = require('child_process');
var bundleCmd = 'grunt bundle --themes leanote --plugins autolink,link,leaui_image,lists,hr,paste,searchreplace,leanote_nav,leanote_code,tabfocus,table,directionality,textcolor'; var bundleCmd = 'grunt bundle --themes leanote --plugins autolink,link,leaui_image,leaui_mindmap,lists,hr,paste,searchreplace,leanote_nav,leanote_code,tabfocus,table,directionality,textcolor';
// build // build
cp.exec('grunt minify', {cwd: tinymceBase}, function(err, stdout, stderr) { cp.exec('grunt minify', {cwd: tinymceBase}, function(err, stdout, stderr) {
console.log('stdout: ' + stdout); console.log('stdout: ' + stdout);
+4 -5
View File
@@ -31,7 +31,7 @@ We have been using the popular note-taking software/service `Evernote` as our kn
* A more powerful editor: `Evernote`'s editor lacks the functionalities of **document navigation**, **syntax based code rendering** (as a programmer, syntax highlighted code rendering is a necessity), **image resizing** and so forth. * A more powerful editor: `Evernote`'s editor lacks the functionalities of **document navigation**, **syntax based code rendering** (as a programmer, syntax highlighted code rendering is a necessity), **image resizing** and so forth.
* Everybody loves *markdown*, however `Evernote` simply wouldn't add it despite of years' of requests from users. So we will do the favor and bring a *markdown* enabled editor to you, guess what, it is also rendered in real-time! * Everybody loves *markdown*, however `Evernote` simply wouldn't add it despite of years' of requests from users. So we will do the favor and bring a *markdown* enabled editor to you, guess what, it is also rendered in real-time!
* If you a developer and miss the `Vim` or `Emacs` ways of writing, we offer you the choice of `Vim` and `Emacs` editting modes. Equipped with *markdown* syntax for text formatting, you will never need to touch your mouse while writing. * If you a developer and miss the `Vim` or `Emacs` ways of writing, we offer you the choice of `Vim` and `Emacs` editing modes. Equipped with *markdown* syntax for text formatting, you will never need to touch your mouse while writing.
* We love managing knowledge and thoughts as much as sharing them, so everybody has their own note account (`Evernote`, `Onenote`, `Google doc`, `Wiz note` etc.) and social media account (`Facebook`, `Wordpress`, blogs, etc.). But why can’t those two be one? Leanote makes this first step to bridge the private note-taking and public knowledge sharing seamlessly. * We love managing knowledge and thoughts as much as sharing them, so everybody has their own note account (`Evernote`, `Onenote`, `Google doc`, `Wiz note` etc.) and social media account (`Facebook`, `Wordpress`, blogs, etc.). But why can’t those two be one? Leanote makes this first step to bridge the private note-taking and public knowledge sharing seamlessly.
* A complete and all-platform (sorry Windows phone) covering software suite: that includes Leanote Web & Server (this repository), [Desktop app](https://github.com/leanote/desktop-app), [iOS](https://github.com/leanote/leanote-ios), [Android](https://github.com/leanote/leanote-android). And they are all open source! * A complete and all-platform (sorry Windows phone) covering software suite: that includes Leanote Web & Server (this repository), [Desktop app](https://github.com/leanote/desktop-app), [iOS](https://github.com/leanote/leanote-ios), [Android](https://github.com/leanote/leanote-android). And they are all open source!
* ...... * ......
@@ -66,7 +66,7 @@ If you are a developer yourself and feel like to build on top of Leanote, please
## 6. Contributions ## 6. Contributions
Like or dislike Leanote, please leave your comments and suggestions to help us improve it. Like or dislike Leanote, please leave your comments and suggestions to help us improve it.
If you encounter any issue, we suggest you first do a search in the issues section to see whether a solution already exists, or open up a new one otherwise. If you encounter any issue, we suggest you first search the issues section to see whether a solution already exists, or open up a new one otherwise.
We’d like to acknowledge the contributions made by our [developers and contributors](https://github.com/leanote/leanote/graphs/contributors) to We’d like to acknowledge the contributions made by our [developers and contributors](https://github.com/leanote/leanote/graphs/contributors) to
this project. Leanote won’t exist without your hard work. Your help is much appreciated. this project. Leanote won’t exist without your hard work. Your help is much appreciated.
@@ -81,7 +81,7 @@ If you find any problems or have any good ideas, feature requests, please submit
## 8. Donation ## 8. Donation
If you like our product, consider supporting us via [donate us](http://leanote.org/#donate). If you like our product, consider supporting us via [donate us](http://leanote.org/#donate).
We acknowledge the donations make by all the [donators](http://leanote.leanote.com/post/leanote-donation-list). We acknowledge the donations made by all the [donators](http://leanote.leanote.com/post/leanote-donation-list).
## 9. Related projects ## 9. Related projects
@@ -184,6 +184,5 @@ Leanote还有很多问题, 如果你喜欢它, 欢迎加入我们一起完善Lea
## 联系&加入我们 ## 联系&加入我们
* Email: leanote@leanote.com * Email: leanote@leanote.com
* [Leanote 社区](http://bbs.leanote.com) * [Leanote 社区](http://bbs.leanote.com)
* QQ群: 326073529, 256076853, 158716820 * [QQ群](http://leanote.leanote.com/post/Leanote-groups)
* [Leanote Google Group](https://groups.google.com/forum/#!forum/leanote) * [Leanote Google Group](https://groups.google.com/forum/#!forum/leanote)
-73
View File
@@ -1,73 +0,0 @@
# Leanote
[![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/leanote/leanote?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
[![Build Status](https://travis-ci.org/leanote/leanote.svg)](https://travis-ci.org/leanote/leanote)
## 1. 介绍
Leanote, 不只是笔记!
![leanote.png](leanote.png "")
**特性**
* 知识管理: 通过leanote来管理知识, leanote有易操作的界面, 包含两款编辑器tinymce和markdown. 在leanote, 你可以尽情享受写作.
* 分享: 你也可以通过分享知识给好友, 让好友拥有你的知识.
* 协作: 在分享的同时也可以与好友一起协作知识.
* 博客: leanote也可以作为你的博客, 将知识公开成博客, 让leanote把你的知识传播的更远!
## 2. 为什么我们要创建leanote?
说实话, 我们曾是evernote的忠实粉丝, 但是我们也发现evernote的不足:
* evernote的编辑器不能满足我们的需求, 不能贴代码(格式会乱掉, 作为程序员, 代码是我们的基本需求啊), 图片不能缩放.
* 我们是markdown的爱好者, 可是evernote竟然没有.
* 我们也想将知识公开, 所以我们有自己的博客, 如wordpress, 但为什么这两者不能合二为一呢?
* 还有...
## 3.安装leanote
leanote是一款私有云笔记, 你可以下载它安装在自己的服务器上, 当然也可以在 http://leanote.com 上注册.
这里详细整理了leanote二进版和leanote开发版的安装教程, 请移步至:
* [leanote二进制详细安装教程](https://github.com/leanote/leanote/wiki/leanote%E4%BA%8C%E8%BF%9B%E5%88%B6%E7%89%88%E8%AF%A6%E7%BB%86%E5%AE%89%E8%A3%85%E6%95%99%E7%A8%8B)
* [leanote开发版详细安装教程](https://github.com/leanote/leanote/wiki/leanote%E5%BC%80%E5%8F%91%E7%89%88%E8%AF%A6%E7%BB%86%E5%AE%89%E8%A3%85%E6%95%99%E7%A8%8B)
## 4. 如何对leanote进行二次开发
请查看 [How-to-develop-leanote](https://github.com/leanote/leanote/wiki/How-to-develop-leanote-%E5%A6%82%E4%BD%95%E5%BC%80%E5%8F%91leanote)
## 5 相关文档
* [leanote二进制版详细安装教程](https://github.com/leanote/leanote/wiki/leanote%E4%BA%8C%E8%BF%9B%E5%88%B6%E7%89%88%E8%AF%A6%E7%BB%86%E5%AE%89%E8%A3%85%E6%95%99%E7%A8%8B)
* [leanote开发版详细安装教程](https://github.com/leanote/leanote/wiki/leanote%E5%BC%80%E5%8F%91%E7%89%88%E8%AF%A6%E7%BB%86%E5%AE%89%E8%A3%85%E6%95%99%E7%A8%8B)
* [Leanote source leanote源码导读](https://github.com/leanote/leanote/wiki/Leanote-source-leanote源码导读)
* [leanote blog theme api(中文版)](https://github.com/leanote/leanote/wiki/leanote-blog-theme-api)
* [How to develop leanote 如何开发leanote](https://github.com/leanote/leanote/wiki/How-to-develop-leanote-如何开发leanote)
更多文档请查看 [wiki](https://github.com/leanote/leanote/wiki).
## 6. 贡献者
多谢 [贡献者](https://github.com/leanote/leanote/graphs/contributors) 的贡献, leanote因有你们而更完美!
## 7. 加入我们
欢迎提交[pull requests](https://github.com/leanote/leanote/pulls) 到leanote.
有任何问题或建议, 欢迎提交[issue](https://github.com/leanote/leanote/issues).
Leanote还有很多问题, 如果你喜欢它, 欢迎加入我们一起完善leanote.
## 8. 捐赠
支持我们, [捐赠Leanote](http://leanote.org/#donate). 感谢[捐赠者](http://leanote.leanote.com/post/leanote-donation-list), 谢谢你们的鼓励, Leanote会一直坚持!
## 9. 其它相关项目
* [Leanote Desktop App](https://github.com/leanote/desktop-app), [下载地址](http://app.leanote.com)
* [Leanote IOS](https://github.com/leanote/leanote-ios), [从App Store下载](https://itunes.apple.com/zn/app/leanote/id1022302858?mt=8)
* [Leanote Android](https://github.com/Dminter/leanote-android-client), 开发阶段
欢迎加入我们!
## 联系&加入我们
* Email: leanote@leanote.com
* [leanote 社区](http://bbs.leanote.com)
* QQ群: 158716820, 256076853
* [Leanote Google Group](https://groups.google.com/forum/#!forum/leanote)
----------------------------------------------------------------
[English](README.md)
Executable
+26
View File
@@ -0,0 +1,26 @@
# Vendor
脱离 revel 每次升级不向下兼容 的控制!! 基于revel 0.18
## Install leanote_revel cmd
```
go install github.com/leanote/leanote/cmd/leanote_revel
leanote_revel run github.com/leanote/leanote
````
## build leanote
在当前目录生成了leanote二进制文件
```
go build -o ./leanote github.com/leanote/leanote/app/tmp
```
## 运行leanote
其中-importPath是必须的
```
./leanote -importPath=github.com/leanote/leanote -runMode=prod -port=9000
```
+5 -5
View File
@@ -23,11 +23,11 @@ func (c Album) Index() revel.Result {
// all albums by userId // all albums by userId
func (c Album) GetAlbums() revel.Result { func (c Album) GetAlbums() revel.Result {
re := albumService.GetAlbums(c.GetUserId()) re := albumService.GetAlbums(c.GetUserId())
return c.RenderJson(re) return c.RenderJSON(re)
} }
func (c Album) DeleteAlbum(albumId string) revel.Result { func (c Album) DeleteAlbum(albumId string) revel.Result {
re, msg := albumService.DeleteAlbum(c.GetUserId(), albumId) re, msg := albumService.DeleteAlbum(c.GetUserId(), albumId)
return c.RenderJson(info.Re{Ok: re, Msg: msg}) return c.RenderJSON(info.Re{Ok: re, Msg: msg})
} }
// add album // add album
@@ -40,13 +40,13 @@ func (c Album) AddAlbum(name string) revel.Result {
re := albumService.AddAlbum(album) re := albumService.AddAlbum(album)
if re { if re {
return c.RenderJson(album) return c.RenderJSON(album)
} else { } else {
return c.RenderJson(false) return c.RenderJSON(false)
} }
} }
// update alnum name // update alnum name
func (c Album) UpdateAlbum(albumId, name string) revel.Result { func (c Album) UpdateAlbum(albumId, name string) revel.Result {
return c.RenderJson(albumService.UpdateAlbum(albumId, c.GetUserId(), name)) return c.RenderJSON(albumService.UpdateAlbum(albumId, c.GetUserId(), name))
} }
+17 -11
View File
@@ -24,7 +24,7 @@ type Attach struct {
// 上传附件 // 上传附件
func (c Attach) UploadAttach(noteId string) revel.Result { func (c Attach) UploadAttach(noteId string) revel.Result {
re := c.uploadAttach(noteId) re := c.uploadAttach(noteId)
return c.RenderJson(re) return c.RenderJSON(re)
} }
func (c Attach) uploadAttach(noteId string) (re info.Re) { func (c Attach) uploadAttach(noteId string) (re info.Re) {
var fileId = "" var fileId = ""
@@ -46,14 +46,17 @@ func (c Attach) uploadAttach(noteId string) (re info.Re) {
return re return re
} }
file, handel, err := c.Request.FormFile("file") var data []byte
if err != nil { c.Params.Bind(&data, "file")
return re
}
defer file.Close()
data, err := ioutil.ReadAll(file) // file, handel, err := c.Request.FormFile("file")
if err != nil { // if err != nil {
// return re
// }
// defer file.Close()
// data, err := ioutil.ReadAll(file)
if data == nil || len(data) == 0 {
return re return re
} }
// > 5M? // > 5M?
@@ -71,10 +74,13 @@ func (c Attach) uploadAttach(noteId string) (re info.Re) {
newGuid := NewGuid() newGuid := NewGuid()
filePath := "files/" + GetRandomFilePath(c.GetUserId(), newGuid) + "/attachs" filePath := "files/" + GetRandomFilePath(c.GetUserId(), newGuid) + "/attachs"
dir := revel.BasePath + "/" + filePath dir := revel.BasePath + "/" + filePath
err = os.MkdirAll(dir, 0755) err := os.MkdirAll(dir, 0755)
if err != nil { if err != nil {
return re return re
} }
handel := c.Params.Files["file"][0]
// 生成新的文件名 // 生成新的文件名
filename := handel.Filename filename := handel.Filename
_, ext := SplitFilename(filename) // .doc _, ext := SplitFilename(filename) // .doc
@@ -118,7 +124,7 @@ func (c Attach) uploadAttach(noteId string) (re info.Re) {
func (c Attach) DeleteAttach(attachId string) revel.Result { func (c Attach) DeleteAttach(attachId string) revel.Result {
re := info.NewRe() re := info.NewRe()
re.Ok, re.Msg = attachService.DeleteAttach(attachId, c.GetUserId()) re.Ok, re.Msg = attachService.DeleteAttach(attachId, c.GetUserId())
return c.RenderJson(re) return c.RenderJSON(re)
} }
// get all attachs by noteId // get all attachs by noteId
@@ -126,7 +132,7 @@ func (c Attach) GetAttachs(noteId string) revel.Result {
re := info.NewRe() re := info.NewRe()
re.Ok = true re.Ok = true
re.List = attachService.ListAttachs(noteId, c.GetUserId()) re.List = attachService.ListAttachs(noteId, c.GetUserId())
return c.RenderJson(re) return c.RenderJSON(re)
} }
// 下载附件 // 下载附件
+29 -29
View File
@@ -17,29 +17,29 @@ type Auth struct {
//-------- //--------
// 登录 // 登录
func (c Auth) Login(email, from string) revel.Result { func (c Auth) Login(email, from string) revel.Result {
c.RenderArgs["title"] = c.Message("login") c.ViewArgs["title"] = c.Message("login")
c.RenderArgs["subTitle"] = c.Message("login") c.ViewArgs["subTitle"] = c.Message("login")
c.RenderArgs["email"] = email c.ViewArgs["email"] = email
c.RenderArgs["from"] = from c.ViewArgs["from"] = from
c.RenderArgs["openRegister"] = configService.IsOpenRegister() c.ViewArgs["openRegister"] = configService.IsOpenRegister()
sessionId := c.Session.Id() sessionId := c.Session.ID()
if sessionService.LoginTimesIsOver(sessionId) { if sessionService.LoginTimesIsOver(sessionId) {
c.RenderArgs["needCaptcha"] = true c.ViewArgs["needCaptcha"] = true
} }
c.SetLocale() c.SetLocale()
if c.Has("demo") { if c.Has("demo") {
c.RenderArgs["demo"] = true c.ViewArgs["demo"] = true
c.RenderArgs["email"] = "demo@leanote.com" c.ViewArgs["email"] = "demo@leanote.com"
} }
return c.RenderTemplate("home/login.html") return c.RenderTemplate("home/login.html")
} }
// 为了demo和register // 为了demo和register
func (c Auth) doLogin(email, pwd string) revel.Result { func (c Auth) doLogin(email, pwd string) revel.Result {
sessionId := c.Session.Id() sessionId := c.Session.ID()
var msg = "" var msg = ""
userInfo, err := authService.Login(email, pwd) userInfo, err := authService.Login(email, pwd)
@@ -49,13 +49,13 @@ func (c Auth) doLogin(email, pwd string) revel.Result {
} else { } else {
c.SetSession(userInfo) c.SetSession(userInfo)
sessionService.ClearLoginTimes(sessionId) sessionService.ClearLoginTimes(sessionId)
return c.RenderJson(info.Re{Ok: true}) return c.RenderJSON(info.Re{Ok: true})
} }
return c.RenderJson(info.Re{Ok: false, Item: sessionService.LoginTimesIsOver(sessionId), Msg: c.Message(msg)}) return c.RenderJSON(info.Re{Ok: false, Item: sessionService.LoginTimesIsOver(sessionId), Msg: c.Message(msg)})
} }
func (c Auth) DoLogin(email, pwd string, captcha string) revel.Result { func (c Auth) DoLogin(email, pwd string, captcha string) revel.Result {
sessionId := c.Session.Id() sessionId := c.Session.ID()
var msg = "" var msg = ""
// > 5次需要验证码, 直到登录成功 // > 5次需要验证码, 直到登录成功
@@ -70,16 +70,16 @@ func (c Auth) DoLogin(email, pwd string, captcha string) revel.Result {
} else { } else {
c.SetSession(userInfo) c.SetSession(userInfo)
sessionService.ClearLoginTimes(sessionId) sessionService.ClearLoginTimes(sessionId)
return c.RenderJson(info.Re{Ok: true}) return c.RenderJSON(info.Re{Ok: true})
} }
} }
return c.RenderJson(info.Re{Ok: false, Item: sessionService.LoginTimesIsOver(sessionId), Msg: c.Message(msg)}) return c.RenderJSON(info.Re{Ok: false, Item: sessionService.LoginTimesIsOver(sessionId), Msg: c.Message(msg)})
} }
// 注销 // 注销
func (c Auth) Logout() revel.Result { func (c Auth) Logout() revel.Result {
sessionId := c.Session.Id() sessionId := c.Session.ID()
sessionService.Clear(sessionId) sessionService.Clear(sessionId)
c.ClearSession() c.ClearSession()
return c.Redirect("/login") return c.Redirect("/login")
@@ -92,7 +92,7 @@ func (c Auth) Demo() revel.Result {
userInfo, err := authService.Login(email, pwd) userInfo, err := authService.Login(email, pwd)
if err != nil { if err != nil {
return c.RenderJson(info.Re{Ok: false}) return c.RenderJSON(info.Re{Ok: false})
} else { } else {
c.SetSession(userInfo) c.SetSession(userInfo)
return c.Redirect("/note") return c.Redirect("/note")
@@ -107,11 +107,11 @@ func (c Auth) Register(from, iu string) revel.Result {
return c.Redirect("/index") return c.Redirect("/index")
} }
c.SetLocale() c.SetLocale()
c.RenderArgs["from"] = from c.ViewArgs["from"] = from
c.RenderArgs["iu"] = iu c.ViewArgs["iu"] = iu
c.RenderArgs["title"] = c.Message("register") c.ViewArgs["title"] = c.Message("register")
c.RenderArgs["subTitle"] = c.Message("register") c.ViewArgs["subTitle"] = c.Message("register")
return c.RenderTemplate("home/register.html") return c.RenderTemplate("home/register.html")
} }
func (c Auth) DoRegister(email, pwd, iu string) revel.Result { func (c Auth) DoRegister(email, pwd, iu string) revel.Result {
@@ -145,22 +145,22 @@ func (c Auth) DoRegister(email, pwd, iu string) revel.Result {
// 找回密码 // 找回密码
func (c Auth) FindPassword() revel.Result { func (c Auth) FindPassword() revel.Result {
c.SetLocale() c.SetLocale()
c.RenderArgs["title"] = c.Message("findPassword") c.ViewArgs["title"] = c.Message("findPassword")
c.RenderArgs["subTitle"] = c.Message("findPassword") c.ViewArgs["subTitle"] = c.Message("findPassword")
return c.RenderTemplate("home/find_password.html") return c.RenderTemplate("home/find_password.html")
} }
func (c Auth) DoFindPassword(email string) revel.Result { func (c Auth) DoFindPassword(email string) revel.Result {
pwdService.FindPwd(email) pwdService.FindPwd(email)
re := info.NewRe() re := info.NewRe()
re.Ok = true re.Ok = true
return c.RenderJson(re) return c.RenderJSON(re)
} }
// 点击链接后, 先验证之 // 点击链接后, 先验证之
func (c Auth) FindPassword2(token string) revel.Result { func (c Auth) FindPassword2(token string) revel.Result {
c.SetLocale() c.SetLocale()
c.RenderArgs["title"] = c.Message("findPassword") c.ViewArgs["title"] = c.Message("findPassword")
c.RenderArgs["subTitle"] = c.Message("findPassword") c.ViewArgs["subTitle"] = c.Message("findPassword")
if token == "" { if token == "" {
return c.RenderTemplate("find_password2_timeout.html") return c.RenderTemplate("find_password2_timeout.html")
} }
@@ -168,10 +168,10 @@ func (c Auth) FindPassword2(token string) revel.Result {
if !ok { if !ok {
return c.RenderTemplate("home/find_password2_timeout.html") return c.RenderTemplate("home/find_password2_timeout.html")
} }
c.RenderArgs["findPwd"] = findPwd c.ViewArgs["findPwd"] = findPwd
c.RenderArgs["title"] = c.Message("updatePassword") c.ViewArgs["title"] = c.Message("updatePassword")
c.RenderArgs["subTitle"] = c.Message("updatePassword") c.ViewArgs["subTitle"] = c.Message("updatePassword")
return c.RenderTemplate("home/find_password2.html") return c.RenderTemplate("home/find_password2.html")
} }
+11 -11
View File
@@ -180,7 +180,7 @@ func (c BaseController) GetTotalPage(page, count int) int {
//------------- //-------------
func (c BaseController) E404() revel.Result { func (c BaseController) E404() revel.Result {
c.RenderArgs["title"] = "404" c.ViewArgs["title"] = "404"
return c.NotFound("", nil) return c.NotFound("", nil)
} }
@@ -199,12 +199,12 @@ func (c BaseController) SetLocale() string {
if !i18n.HasLang(locale) { if !i18n.HasLang(locale) {
lang = i18n.GetDefaultLang() lang = i18n.GetDefaultLang()
} }
c.RenderArgs["locale"] = lang c.ViewArgs["locale"] = lang
c.RenderArgs["siteUrl"] = configService.GetSiteUrl() c.ViewArgs["siteUrl"] = configService.GetSiteUrl()
c.RenderArgs["blogUrl"] = configService.GetBlogUrl() c.ViewArgs["blogUrl"] = configService.GetBlogUrl()
c.RenderArgs["leaUrl"] = configService.GetLeaUrl() c.ViewArgs["leaUrl"] = configService.GetLeaUrl()
c.RenderArgs["noteUrl"] = configService.GetNoteUrl() c.ViewArgs["noteUrl"] = configService.GetNoteUrl()
return lang return lang
} }
@@ -212,9 +212,9 @@ func (c BaseController) SetLocale() string {
// 设置userInfo // 设置userInfo
func (c BaseController) SetUserInfo() info.User { func (c BaseController) SetUserInfo() info.User {
userInfo := c.GetUserInfo() userInfo := c.GetUserInfo()
c.RenderArgs["userInfo"] = userInfo c.ViewArgs["userInfo"] = userInfo
if userInfo.Username == configService.GetAdminUsername() { if userInfo.Username == configService.GetAdminUsername() {
c.RenderArgs["isAdmin"] = true c.ViewArgs["isAdmin"] = true
} }
return userInfo return userInfo
} }
@@ -230,11 +230,11 @@ func (c BaseController) RenderTemplateStr(templatePath string) string {
tpl := &revel.RenderTemplateResult{ tpl := &revel.RenderTemplateResult{
Template: template, Template: template,
RenderArgs: c.RenderArgs, // 把args给它 ViewArgs: c.ViewArgs, // 把args给它
} }
var buffer bytes.Buffer var buffer bytes.Buffer
tpl.Template.Render(&buffer, c.RenderArgs) tpl.Template.Render(&buffer, c.ViewArgs)
return buffer.String() return buffer.String()
} }
@@ -263,5 +263,5 @@ func (c BaseController) RenderRe(re info.Re) revel.Result {
if strings.HasPrefix(re.Msg, "???") { if strings.HasPrefix(re.Msg, "???") {
re.Msg = oldMsg re.Msg = oldMsg
} }
return c.RenderJson(re) return c.RenderJSON(re)
} }
+100 -100
View File
@@ -6,7 +6,7 @@ import (
// "encoding/json" // "encoding/json"
"fmt" "fmt"
"github.com/leanote/leanote/app/info" "github.com/leanote/leanote/app/info"
. "github.com/leanote/leanote/app/lea" // . "github.com/leanote/leanote/app/lea"
"github.com/leanote/leanote/app/lea/blog" "github.com/leanote/leanote/app/lea/blog"
"gopkg.in/mgo.v2/bson" "gopkg.in/mgo.v2/bson"
// "github.com/leanote/leanote/app/types" // "github.com/leanote/leanote/app/types"
@@ -49,8 +49,8 @@ $.bootstrapJsUrl
func (c Blog) render(templateName string, themePath string) revel.Result { func (c Blog) render(templateName string, themePath string) revel.Result {
isPreview := false isPreview := false
if c.RenderArgs["isPreview"] != nil { if c.ViewArgs["isPreview"] != nil {
themePath2 := c.RenderArgs["themePath"] themePath2 := c.ViewArgs["themePath"]
if themePath2 == nil { if themePath2 == nil {
return c.E404() return c.E404()
} }
@@ -59,9 +59,9 @@ func (c Blog) render(templateName string, themePath string) revel.Result {
c.setPreviewUrl() c.setPreviewUrl()
// 因为common的themeInfo是从UserBlog.ThemeId来取的, 所以这里要fugai下 // 因为common的themeInfo是从UserBlog.ThemeId来取的, 所以这里要fugai下
c.RenderArgs["themeInfo"] = c.RenderArgs["themeInfoPreview"] c.ViewArgs["themeInfo"] = c.ViewArgs["themeInfoPreview"]
} }
return blog.RenderTemplate(templateName, c.RenderArgs, revel.BasePath+"/"+themePath, isPreview) return blog.RenderTemplate(templateName, c.ViewArgs, revel.BasePath+"/"+themePath, isPreview)
} }
// 404 // 404
@@ -77,7 +77,7 @@ func (c Blog) e404(themePath string) revel.Result {
// life.leanote.com // life.leanote.com
// lealife.com // lealife.com
func (c Blog) domain() (ok bool, userBlog info.UserBlog) { func (c Blog) domain() (ok bool, userBlog info.UserBlog) {
host := c.Request.Request.Host // a.cc.com:9000 host := c.Request.Host // a.cc.com:9000
hostArr := strings.Split(host, ".") hostArr := strings.Split(host, ".")
if strings.Contains(host, configService.GetDefaultDomain()) { if strings.Contains(host, configService.GetDefaultDomain()) {
// 有二级域名 a.leanoe.com 3个 // 有二级域名 a.leanoe.com 3个
@@ -125,19 +125,19 @@ func (c Blog) setPreviewUrl() {
archiveUrl = blogUrl + "/archives/" + userIdOrEmail // blog.leanote.com/archive/userId archiveUrl = blogUrl + "/archives/" + userIdOrEmail // blog.leanote.com/archive/userId
tagsUrl = blogUrl + "/tags/" + userIdOrEmail // blog.leanote.com/archive/userId tagsUrl = blogUrl + "/tags/" + userIdOrEmail // blog.leanote.com/archive/userId
c.RenderArgs["indexUrl"] = indexUrl c.ViewArgs["indexUrl"] = indexUrl
c.RenderArgs["cateUrl"] = cateUrl c.ViewArgs["cateUrl"] = cateUrl
c.RenderArgs["postUrl"] = postUrl c.ViewArgs["postUrl"] = postUrl
c.RenderArgs["searchUrl"] = searchUrl c.ViewArgs["searchUrl"] = searchUrl
c.RenderArgs["singleUrl"] = singleUrl // 单页 c.ViewArgs["singleUrl"] = singleUrl // 单页
c.RenderArgs["archiveUrl"] = archiveUrl c.ViewArgs["archiveUrl"] = archiveUrl
c.RenderArgs["archivesUrl"] = archiveUrl // 别名 c.ViewArgs["archivesUrl"] = archiveUrl // 别名
c.RenderArgs["tagsUrl"] = tagsUrl c.ViewArgs["tagsUrl"] = tagsUrl
c.RenderArgs["tagPostsUrl"] = blogUrl + "/tag/" + userIdOrEmail c.ViewArgs["tagPostsUrl"] = blogUrl + "/tag/" + userIdOrEmail
c.RenderArgs["tagUrl"] = c.RenderArgs["tagPostsUrl"] c.ViewArgs["tagUrl"] = c.ViewArgs["tagPostsUrl"]
// themeBaseUrl 本theme的路径url, 可以加载js, css, images之类的 // themeBaseUrl 本theme的路径url, 可以加载js, css, images之类的
c.RenderArgs["themeBaseUrl"] = "/" + theme.Path c.ViewArgs["themeBaseUrl"] = "/" + theme.Path
} }
// 各种地址设置 // 各种地址设置
@@ -152,36 +152,36 @@ func (c Blog) setUrl(userBlog info.UserBlog, userInfo info.User) {
// 分类 // 分类
// 搜索 // 搜索
// 查看 // 查看
c.RenderArgs["siteUrl"] = siteUrl c.ViewArgs["siteUrl"] = siteUrl
c.RenderArgs["indexUrl"] = blogUrls.IndexUrl c.ViewArgs["indexUrl"] = blogUrls.IndexUrl
c.RenderArgs["cateUrl"] = blogUrls.CateUrl c.ViewArgs["cateUrl"] = blogUrls.CateUrl
c.RenderArgs["postUrl"] = blogUrls.PostUrl c.ViewArgs["postUrl"] = blogUrls.PostUrl
c.RenderArgs["searchUrl"] = blogUrls.SearchUrl c.ViewArgs["searchUrl"] = blogUrls.SearchUrl
c.RenderArgs["singleUrl"] = blogUrls.SingleUrl // 单页 c.ViewArgs["singleUrl"] = blogUrls.SingleUrl // 单页
c.RenderArgs["archiveUrl"] = blogUrls.ArchiveUrl c.ViewArgs["archiveUrl"] = blogUrls.ArchiveUrl
c.RenderArgs["archivesUrl"] = blogUrls.ArchiveUrl // 别名 c.ViewArgs["archivesUrl"] = blogUrls.ArchiveUrl // 别名
c.RenderArgs["tagsUrl"] = blogUrls.TagsUrl c.ViewArgs["tagsUrl"] = blogUrls.TagsUrl
c.RenderArgs["tagPostsUrl"] = blogUrls.TagPostsUrl c.ViewArgs["tagPostsUrl"] = blogUrls.TagPostsUrl
c.RenderArgs["tagUrl"] = blogUrls.TagPostsUrl // 别名 c.ViewArgs["tagUrl"] = blogUrls.TagPostsUrl // 别名
// themeBaseUrl 本theme的路径url, 可以加载js, css, images之类的 // themeBaseUrl 本theme的路径url, 可以加载js, css, images之类的
c.RenderArgs["themeBaseUrl"] = "/" + userBlog.ThemePath c.ViewArgs["themeBaseUrl"] = "/" + userBlog.ThemePath
// 其它static js // 其它static js
c.RenderArgs["jQueryUrl"] = "/js/jquery-1.9.0.min.js" c.ViewArgs["jQueryUrl"] = "/js/jquery-1.9.0.min.js"
c.RenderArgs["prettifyJsUrl"] = "/js/google-code-prettify/prettify.js" c.ViewArgs["prettifyJsUrl"] = "/js/google-code-prettify/prettify.js"
c.RenderArgs["prettifyCssUrl"] = "/js/google-code-prettify/prettify.css" c.ViewArgs["prettifyCssUrl"] = "/js/google-code-prettify/prettify.css"
c.RenderArgs["blogCommonJsUrl"] = "/public/blog/js/common.js" c.ViewArgs["blogCommonJsUrl"] = "/public/blog/js/common.js"
c.RenderArgs["shareCommentCssUrl"] = "/public/blog/css/share_comment.css" c.ViewArgs["shareCommentCssUrl"] = "/public/blog/css/share_comment.css"
c.RenderArgs["shareCommentJsUrl"] = "/public/blog/js/share_comment.js" c.ViewArgs["shareCommentJsUrl"] = "/public/blog/js/share_comment.js"
c.RenderArgs["fontAwesomeUrl"] = "/css/font-awesome-4.2.0/css/font-awesome.css" c.ViewArgs["fontAwesomeUrl"] = "/css/font-awesome-4.2.0/css/font-awesome.css"
c.RenderArgs["bootstrapCssUrl"] = "/css/bootstrap.css" c.ViewArgs["bootstrapCssUrl"] = "/css/bootstrap.css"
c.RenderArgs["bootstrapJsUrl"] = "/js/bootstrap-min.js" c.ViewArgs["bootstrapJsUrl"] = "/js/bootstrap-min.js"
} }
// 笔记本分类 // 笔记本分类
@@ -265,8 +265,8 @@ func (c Blog) getCates(userBlog info.UserBlog) {
} }
} }
c.RenderArgs["cates"] = cates c.ViewArgs["cates"] = cates
c.RenderArgs["catesTree"] = catesTree c.ViewArgs["catesTree"] = catesTree
} }
// 单页 // 单页
@@ -281,7 +281,7 @@ func (c Blog) getSingles(userId string) {
singles2[i] = map[string]string{"title": page["Title"], "singleId": page["SingleId"]} singles2[i] = map[string]string{"title": page["Title"], "singleId": page["SingleId"]}
} }
*/ */
c.RenderArgs["singles"] = singles c.ViewArgs["singles"] = singles
} }
// $.blog = {userId, title, subTitle, desc, openComment, } // $.blog = {userId, title, subTitle, desc, openComment, }
@@ -300,11 +300,11 @@ func (c Blog) setBlog(userBlog info.UserBlog, userInfo info.User) {
"SubDomain": userBlog.SubDomain, "SubDomain": userBlog.SubDomain,
"Domain": userBlog.Domain, "Domain": userBlog.Domain,
} }
c.RenderArgs["blogInfo"] = blogInfo c.ViewArgs["blogInfo"] = blogInfo
} }
func (c Blog) setPaging(pageInfo info.Page) { func (c Blog) setPaging(pageInfo info.Page) {
c.RenderArgs["paging"] = pageInfo c.ViewArgs["paging"] = pageInfo
} }
// 公共 // 公共
@@ -315,13 +315,13 @@ func (c Blog) blogCommon(userId string, userBlog info.UserBlog, userInfo info.Us
return false, userBlog return false, userBlog
} }
} }
// c.RenderArgs["userInfo"] = userInfo // c.ViewArgs["userInfo"] = userInfo
// 最新笔记 // 最新笔记
_, recentBlogs := blogService.ListBlogs(userId, "", 1, 5, userBlog.SortField, userBlog.IsAsc) _, recentBlogs := blogService.ListBlogs(userId, "", 1, 5, userBlog.SortField, userBlog.IsAsc)
c.RenderArgs["recentPosts"] = blogService.FixBlogs(recentBlogs) c.ViewArgs["recentPosts"] = blogService.FixBlogs(recentBlogs)
c.RenderArgs["latestPosts"] = c.RenderArgs["recentPosts"] c.ViewArgs["latestPosts"] = c.ViewArgs["recentPosts"]
c.RenderArgs["tags"] = blogService.GetBlogTags(userId) c.ViewArgs["tags"] = blogService.GetBlogTags(userId)
// 语言, url地址 // 语言, url地址
c.SetLocale() c.SetLocale()
@@ -331,7 +331,7 @@ func (c Blog) blogCommon(userId string, userBlog info.UserBlog, userInfo info.Us
userBlog = blogService.GetUserBlog(userId) userBlog = blogService.GetUserBlog(userId)
} }
c.setBlog(userBlog, userInfo) c.setBlog(userBlog, userInfo)
// c.RenderArgs["userBlog"] = userBlog // c.ViewArgs["userBlog"] = userBlog
// 分类导航 // 分类导航
c.getCates(userBlog) c.getCates(userBlog)
@@ -342,12 +342,12 @@ func (c Blog) blogCommon(userId string, userBlog info.UserBlog, userInfo info.Us
c.setUrl(userBlog, userInfo) c.setUrl(userBlog, userInfo)
// 当前分类Id, 全设为"" // 当前分类Id, 全设为""
c.RenderArgs["curCateId"] = "" c.ViewArgs["curCateId"] = ""
c.RenderArgs["curSingleId"] = "" c.ViewArgs["curSingleId"] = ""
// 得到主题信息 // 得到主题信息
themeInfo := themeService.GetThemeInfo(userBlog.ThemeId.Hex(), userBlog.Style) themeInfo := themeService.GetThemeInfo(userBlog.ThemeId.Hex(), userBlog.Style)
c.RenderArgs["themeInfo"] = themeInfo c.ViewArgs["themeInfo"] = themeInfo
// Log(">>") // Log(">>")
// Log(userBlog.Style) // Log(userBlog.Style)
@@ -404,9 +404,9 @@ func (c Blog) Tags(userIdOrEmail string) (re revel.Result) {
return c.e404(userBlog.ThemePath) // 404 TODO 使用用户的404 return c.e404(userBlog.ThemePath) // 404 TODO 使用用户的404
} }
c.RenderArgs["curIsTags"] = true c.ViewArgs["curIsTags"] = true
tags := blogService.GetBlogTags(userId) tags := blogService.GetBlogTags(userId)
c.RenderArgs["tags"] = tags c.ViewArgs["tags"] = tags
return c.render("tags.html", userBlog.ThemePath) return c.render("tags.html", userBlog.ThemePath)
} }
@@ -443,15 +443,15 @@ func (c Blog) Tag(userIdOrEmail, tag string) (re revel.Result) {
tag = userIdOrEmail tag = userIdOrEmail
} }
c.RenderArgs["curIsTagPosts"] = true c.ViewArgs["curIsTagPosts"] = true
c.RenderArgs["curTag"] = tag c.ViewArgs["curTag"] = tag
page := c.GetPage() page := c.GetPage()
pageInfo, blogs := blogService.SearchBlogByTags([]string{tag}, userId, page, userBlog.PerPageSize, userBlog.SortField, userBlog.IsAsc) pageInfo, blogs := blogService.SearchBlogByTags([]string{tag}, userId, page, userBlog.PerPageSize, userBlog.SortField, userBlog.IsAsc)
c.setPaging(pageInfo) c.setPaging(pageInfo)
c.RenderArgs["posts"] = blogService.FixBlogs(blogs) c.ViewArgs["posts"] = blogService.FixBlogs(blogs)
tagPostsUrl := c.RenderArgs["tagPostsUrl"].(string) tagPostsUrl := c.ViewArgs["tagPostsUrl"].(string)
c.RenderArgs["pagingBaseUrl"] = tagPostsUrl + "/" + tag c.ViewArgs["pagingBaseUrl"] = tagPostsUrl + "/" + tag
return c.render("tag_posts.html", userBlog.ThemePath) return c.render("tag_posts.html", userBlog.ThemePath)
} }
@@ -490,16 +490,16 @@ func (c Blog) Archives(userIdOrEmail string, cateId string, year, month int) (re
} }
arcs := blogService.ListBlogsArchive(userId, notebookId, year, month, "PublicTime", false) arcs := blogService.ListBlogsArchive(userId, notebookId, year, month, "PublicTime", false)
c.RenderArgs["archives"] = arcs c.ViewArgs["archives"] = arcs
c.RenderArgs["curIsArchive"] = true c.ViewArgs["curIsArchive"] = true
if notebookId != "" { if notebookId != "" {
notebook := notebookService.GetNotebookById(notebookId) notebook := notebookService.GetNotebookById(notebookId)
c.RenderArgs["curCateTitle"] = notebook.Title c.ViewArgs["curCateTitle"] = notebook.Title
c.RenderArgs["curCateId"] = notebookId c.ViewArgs["curCateId"] = notebookId
} }
c.RenderArgs["curYear"] = year c.ViewArgs["curYear"] = year
c.RenderArgs["curMonth"] = month c.ViewArgs["curMonth"] = month
return c.render("archive.html", userBlog.ThemePath) return c.render("archive.html", userBlog.ThemePath)
} }
@@ -541,15 +541,15 @@ func (c Blog) Cate(userIdOrEmail string, notebookId string) (re revel.Result) {
page := c.GetPage() page := c.GetPage()
pageInfo, blogs := blogService.ListBlogs(userId, notebookId2, page, userBlog.PerPageSize, userBlog.SortField, userBlog.IsAsc) pageInfo, blogs := blogService.ListBlogs(userId, notebookId2, page, userBlog.PerPageSize, userBlog.SortField, userBlog.IsAsc)
blogs2 := blogService.FixBlogs(blogs) blogs2 := blogService.FixBlogs(blogs)
c.RenderArgs["posts"] = blogs2 c.ViewArgs["posts"] = blogs2
c.setPaging(pageInfo) c.setPaging(pageInfo)
c.RenderArgs["curCateTitle"] = notebook.Title c.ViewArgs["curCateTitle"] = notebook.Title
c.RenderArgs["curCateId"] = notebookId2 c.ViewArgs["curCateId"] = notebookId2
cateUrl := c.RenderArgs["cateUrl"].(string) cateUrl := c.ViewArgs["cateUrl"].(string)
c.RenderArgs["pagingBaseUrl"] = cateUrl + "/" + notebookId c.ViewArgs["pagingBaseUrl"] = cateUrl + "/" + notebookId
c.RenderArgs["curIsCate"] = true c.ViewArgs["curIsCate"] = true
return c.render("cate.html", userBlog.ThemePath) return c.render("cate.html", userBlog.ThemePath)
} }
@@ -594,12 +594,12 @@ func (c Blog) Index(userIdOrEmail string) (re revel.Result) {
page := c.GetPage() page := c.GetPage()
pageInfo, blogs := blogService.ListBlogs(userId, "", page, userBlog.PerPageSize, userBlog.SortField, userBlog.IsAsc) pageInfo, blogs := blogService.ListBlogs(userId, "", page, userBlog.PerPageSize, userBlog.SortField, userBlog.IsAsc)
blogs2 := blogService.FixBlogs(blogs) blogs2 := blogService.FixBlogs(blogs)
c.RenderArgs["posts"] = blogs2 c.ViewArgs["posts"] = blogs2
c.setPaging(pageInfo) c.setPaging(pageInfo)
c.RenderArgs["pagingBaseUrl"] = c.RenderArgs["indexUrl"] c.ViewArgs["pagingBaseUrl"] = c.ViewArgs["indexUrl"]
c.RenderArgs["curIsIndex"] = true c.ViewArgs["curIsIndex"] = true
return c.render("index.html", userBlog.ThemePath) return c.render("index.html", userBlog.ThemePath)
} }
@@ -609,7 +609,7 @@ func (c Blog) Post(userIdOrEmail, noteId string) (re revel.Result) {
hasDomain, userBlog := c.domain() hasDomain, userBlog := c.domain()
defer func() { defer func() {
if err := recover(); err != nil { if err := recover(); err != nil {
Log(err) // Log(err)
re = c.e404(userBlog.ThemePath) re = c.e404(userBlog.ThemePath)
} }
}() }()
@@ -631,9 +631,9 @@ func (c Blog) Post(userIdOrEmail, noteId string) (re revel.Result) {
} }
post := blogService.FixBlog(blogInfo) post := blogService.FixBlog(blogInfo)
c.RenderArgs["post"] = post c.ViewArgs["post"] = post
// c.RenderArgs["userInfo"] = userInfo // c.ViewArgs["userInfo"] = userInfo
c.RenderArgs["curIsPost"] = true c.ViewArgs["curIsPost"] = true
// 上一篇, 下一篇 // 上一篇, 下一篇
var baseTime interface{} var baseTime interface{}
@@ -649,10 +649,10 @@ func (c Blog) Post(userIdOrEmail, noteId string) (re revel.Result) {
prePost, nextPost := blogService.PreNextBlog(userId, userBlog.SortField, userBlog.IsAsc, post.NoteId, baseTime) prePost, nextPost := blogService.PreNextBlog(userId, userBlog.SortField, userBlog.IsAsc, post.NoteId, baseTime)
if prePost.NoteId != "" { if prePost.NoteId != "" {
c.RenderArgs["prePost"] = prePost c.ViewArgs["prePost"] = prePost
} }
if nextPost.NoteId != "" { if nextPost.NoteId != "" {
c.RenderArgs["nextPost"] = nextPost c.ViewArgs["nextPost"] = nextPost
} }
return c.render("post.html", userBlog.ThemePath) return c.render("post.html", userBlog.ThemePath)
} }
@@ -682,7 +682,7 @@ func (c Blog) Single(userIdOrEmail, singleId string) (re revel.Result) {
panic("") panic("")
} }
c.RenderArgs["single"] = map[string]interface{}{ c.ViewArgs["single"] = map[string]interface{}{
"SingleId": single.SingleId.Hex(), "SingleId": single.SingleId.Hex(),
"Title": single.Title, "Title": single.Title,
"UrlTitle": single.UrlTitle, "UrlTitle": single.UrlTitle,
@@ -690,8 +690,8 @@ func (c Blog) Single(userIdOrEmail, singleId string) (re revel.Result) {
"CreatedTime": single.CreatedTime, "CreatedTime": single.CreatedTime,
"UpdatedTime": single.UpdatedTime, "UpdatedTime": single.UpdatedTime,
} }
c.RenderArgs["curSingleId"] = single.SingleId.Hex() c.ViewArgs["curSingleId"] = single.SingleId.Hex()
c.RenderArgs["curIsSingle"] = true c.ViewArgs["curIsSingle"] = true
return c.render("single.html", userBlog.ThemePath) return c.render("single.html", userBlog.ThemePath)
} }
@@ -716,7 +716,7 @@ func (c Blog) Search(userIdOrEmail, keywords string) (re revel.Result) {
} else { } else {
userInfo = userService.GetUserInfoByAny(userIdOrEmail) userInfo = userService.GetUserInfoByAny(userIdOrEmail)
} }
// c.RenderArgs["userInfo"] = userInfo // c.ViewArgs["userInfo"] = userInfo
userId = userInfo.UserId.Hex() userId = userInfo.UserId.Hex()
var ok = false var ok = false
if ok, userBlog = c.blogCommon(userId, userBlog, userInfo); !ok { if ok, userBlog = c.blogCommon(userId, userBlog, userInfo); !ok {
@@ -727,11 +727,11 @@ func (c Blog) Search(userIdOrEmail, keywords string) (re revel.Result) {
pageInfo, blogs := blogService.SearchBlog(keywords, userId, page, userBlog.PerPageSize, userBlog.SortField, userBlog.IsAsc) pageInfo, blogs := blogService.SearchBlog(keywords, userId, page, userBlog.PerPageSize, userBlog.SortField, userBlog.IsAsc)
c.setPaging(pageInfo) c.setPaging(pageInfo)
c.RenderArgs["posts"] = blogService.FixBlogs(blogs) c.ViewArgs["posts"] = blogService.FixBlogs(blogs)
c.RenderArgs["keywords"] = keywords c.ViewArgs["keywords"] = keywords
searchUrl, _ := c.RenderArgs["searchUrl"].(string) searchUrl, _ := c.ViewArgs["searchUrl"].(string)
c.RenderArgs["pagingBaseUrl"] = searchUrl + "?keywords=" + keywords c.ViewArgs["pagingBaseUrl"] = searchUrl + "?keywords=" + keywords
c.RenderArgs["curIsSearch"] = true c.ViewArgs["curIsSearch"] = true
return c.render("search.html", userBlog.ThemePath) return c.render("search.html", userBlog.ThemePath)
} }
@@ -741,7 +741,7 @@ func (c Blog) setRenderUserInfo(userInfo info.User) {
if userInfo.Username == "" { if userInfo.Username == "" {
userInfo.Username = userInfo.Email userInfo.Username = userInfo.Email
} }
c.RenderArgs["userInfo"] = userInfo c.ViewArgs["userInfo"] = userInfo
} }
//---------------- //----------------
@@ -753,7 +753,7 @@ func (c Blog) GetPostStat(noteId string) revel.Result {
re.Ok = true re.Ok = true
statInfo := blogService.GetBlogStat(noteId) statInfo := blogService.GetBlogStat(noteId)
re.Item = statInfo re.Item = statInfo
return c.RenderJson(re) return c.RenderJSON(re)
} }
// jsonP // jsonP
@@ -778,7 +778,7 @@ func (c Blog) GetLikes(noteId string, callback string) revel.Result {
result["hasMoreLikedUser"] = hasMoreLikedUser result["hasMoreLikedUser"] = hasMoreLikedUser
re.Item = result re.Item = result
return c.RenderJsonP(callback, re) return c.RenderJSONP(callback, re)
} }
func (c Blog) GetLikesAndComments(noteId, callback string) revel.Result { func (c Blog) GetLikesAndComments(noteId, callback string) revel.Result {
userId := c.GetUserId() userId := c.GetUserId()
@@ -806,13 +806,13 @@ func (c Blog) GetLikesAndComments(noteId, callback string) revel.Result {
result["comments"] = comments result["comments"] = comments
result["commentUserInfo"] = commentUserInfo result["commentUserInfo"] = commentUserInfo
re.Item = result re.Item = result
return c.RenderJsonP(callback, re) return c.RenderJSONP(callback, re)
} }
func (c Blog) IncReadNum(noteId string) revel.Result { func (c Blog) IncReadNum(noteId string) revel.Result {
re := info.NewRe() re := info.NewRe()
re.Ok = blogService.IncReadNum(noteId) re.Ok = blogService.IncReadNum(noteId)
return c.RenderJson(re) return c.RenderJSON(re)
} }
// 点赞, 要用jsonp // 点赞, 要用jsonp
@@ -820,7 +820,7 @@ func (c Blog) LikePost(noteId string, callback string) revel.Result {
re := info.NewRe() re := info.NewRe()
userId := c.GetUserId() userId := c.GetUserId()
re.Ok, re.Item = blogService.LikeBlog(noteId, userId) re.Ok, re.Item = blogService.LikeBlog(noteId, userId)
return c.RenderJsonP(callback, re) return c.RenderJSONP(callback, re)
} }
func (c Blog) GetComments(noteId string, callback string) revel.Result { func (c Blog) GetComments(noteId string, callback string) revel.Result {
// 评论 // 评论
@@ -836,24 +836,24 @@ func (c Blog) GetComments(noteId string, callback string) revel.Result {
re.Item = result re.Item = result
if callback != "" { if callback != "" {
return c.RenderJsonP(callback, result) return c.RenderJSONP(callback, result)
} }
return c.RenderJson(re) return c.RenderJSON(re)
} }
// jsonp // jsonp
func (c Blog) DeleteComment(noteId, commentId string, callback string) revel.Result { func (c Blog) DeleteComment(noteId, commentId string, callback string) revel.Result {
re := info.NewRe() re := info.NewRe()
re.Ok = blogService.DeleteComment(noteId, commentId, c.GetUserId()) re.Ok = blogService.DeleteComment(noteId, commentId, c.GetUserId())
return c.RenderJsonP(callback, re) return c.RenderJSONP(callback, re)
} }
// jsonp // jsonp
func (c Blog) CommentPost(noteId, content, toCommentId string, callback string) revel.Result { func (c Blog) CommentPost(noteId, content, toCommentId string, callback string) revel.Result {
re := info.NewRe() re := info.NewRe()
re.Ok, re.Item = blogService.Comment(noteId, toCommentId, c.GetUserId(), content) re.Ok, re.Item = blogService.Comment(noteId, toCommentId, c.GetUserId(), content)
return c.RenderJsonP(callback, re) return c.RenderJSONP(callback, re)
} }
// jsonp // jsonp
@@ -862,7 +862,7 @@ func (c Blog) LikeComment(commentId string, callback string) revel.Result {
ok, isILikeIt, num := blogService.LikeComment(commentId, c.GetUserId()) ok, isILikeIt, num := blogService.LikeComment(commentId, c.GetUserId())
re.Ok = ok re.Ok = ok
re.Item = bson.M{"IsILikeIt": isILikeIt, "Num": num} re.Item = bson.M{"IsILikeIt": isILikeIt, "Num": num}
return c.RenderJsonP(callback, re) return c.RenderJSONP(callback, re)
} }
// 显示分类的最近博客, jsonp // 显示分类的最近博客, jsonp
@@ -898,5 +898,5 @@ func (c Blog) ListCateLatest(notebookId, callback string) revel.Result {
re := info.NewRe() re := info.NewRe()
re.Ok = true re.Ok = true
re.List = blogs re.List = blogs
return c.RenderJsonP(callback, re) return c.RenderJSONP(callback, re)
} }
+3 -1
View File
@@ -14,6 +14,7 @@ import (
// "path" // "path"
// "strconv" // "strconv"
"net/http" "net/http"
"io"
) )
// 验证码服务 // 验证码服务
@@ -30,7 +31,8 @@ func (r Ca) Apply(req *revel.Request, resp *revel.Response) {
func (c Captcha) Get() revel.Result { func (c Captcha) Get() revel.Result {
c.Response.ContentType = "image/png" c.Response.ContentType = "image/png"
image, str := captcha.Fetch() image, str := captcha.Fetch()
image.WriteTo(c.Response.Out) out := io.Writer(c.Response.GetWriter())
image.WriteTo(out)
sessionId := c.Session["_ID"] sessionId := c.Session["_ID"]
// LogJ(c.Session) // LogJ(c.Session)
+41 -25
View File
@@ -24,9 +24,9 @@ type File struct {
func (c File) UploadBlogLogo() revel.Result { func (c File) UploadBlogLogo() revel.Result {
re := c.uploadImage("blogLogo", "") re := c.uploadImage("blogLogo", "")
c.RenderArgs["fileUrlPath"] = re.Id c.ViewArgs["fileUrlPath"] = re.Id
c.RenderArgs["resultCode"] = re.Code c.ViewArgs["resultCode"] = re.Code
c.RenderArgs["resultMsg"] = re.Msg c.ViewArgs["resultMsg"] = re.Msg
return c.RenderTemplate("file/blog_logo.html") return c.RenderTemplate("file/blog_logo.html")
} }
@@ -54,16 +54,16 @@ func (c File) PasteImage(noteId string) revel.Result {
} }
} }
return c.RenderJson(re) return c.RenderJSON(re)
} }
// 头像设置 // 头像设置
func (c File) UploadAvatar() revel.Result { func (c File) UploadAvatar() revel.Result {
re := c.uploadImage("logo", "") re := c.uploadImage("logo", "")
c.RenderArgs["fileUrlPath"] = re.Id c.ViewArgs["fileUrlPath"] = re.Id
c.RenderArgs["resultCode"] = re.Code c.ViewArgs["resultCode"] = re.Code
c.RenderArgs["resultMsg"] = re.Msg c.ViewArgs["resultMsg"] = re.Msg
if re.Ok { if re.Ok {
re.Ok = userService.UpdateAvatar(c.GetUserId(), re.Id) re.Ok = userService.UpdateAvatar(c.GetUserId(), re.Id)
@@ -72,13 +72,13 @@ func (c File) UploadAvatar() revel.Result {
} }
} }
return c.RenderJson(re) return c.RenderJSON(re)
} }
// leaui image plugin upload image // leaui image plugin upload image
func (c File) UploadImageLeaui(albumId string) revel.Result { func (c File) UploadImageLeaui(albumId string) revel.Result {
re := c.uploadImage("", albumId) re := c.uploadImage("", albumId)
return c.RenderJson(re) return c.RenderJSON(re)
} }
// 上传图片, 公用方法 // 上传图片, 公用方法
@@ -97,11 +97,27 @@ func (c File) uploadImage(from, albumId string) (re info.Re) {
re.Ok = Ok re.Ok = Ok
}() }()
file, handel, err := c.Request.FormFile("file") // file, handel, err := c.Request.FormFile("file")
if err != nil { // if err != nil {
// return re
// }
// defer file.Close()
var data []byte
c.Params.Bind(&data, "file")
handel := c.Params.Files["file"][0]
if data == nil || len(data) == 0 {
return re return re
} }
defer file.Close()
// file, handel, err := c.Request.FormFile("file")
// if err != nil {
// return re
// }
// defer file.Close()
// data, err := ioutil.ReadAll(file)
// 生成上传路径 // 生成上传路径
newGuid := NewGuid() newGuid := NewGuid()
@@ -116,7 +132,7 @@ func (c File) uploadImage(from, albumId string) (re info.Re) {
} }
dir := revel.BasePath + "/" + fileUrlPath dir := revel.BasePath + "/" + fileUrlPath
err = os.MkdirAll(dir, 0755) err := os.MkdirAll(dir, 0755)
if err != nil { if err != nil {
return re return re
} }
@@ -136,11 +152,11 @@ func (c File) uploadImage(from, albumId string) (re info.Re) {
} }
filename = newGuid + ext filename = newGuid + ext
data, err := ioutil.ReadAll(file) // data, err := ioutil.ReadAll(file)
if err != nil { // if err != nil {
LogJ(err) // LogJ(err)
return re // return re
} // }
var maxFileSize float64 var maxFileSize float64
if from == "logo" { if from == "logo" {
@@ -201,19 +217,19 @@ func (c File) uploadImage(from, albumId string) (re info.Re) {
// get all images by userId with page // get all images by userId with page
func (c File) GetImages(albumId, key string, page int) revel.Result { func (c File) GetImages(albumId, key string, page int) revel.Result {
re := fileService.ListImagesWithPage(c.GetUserId(), albumId, key, page, 12) re := fileService.ListImagesWithPage(c.GetUserId(), albumId, key, page, 12)
return c.RenderJson(re) return c.RenderJSON(re)
} }
func (c File) UpdateImageTitle(fileId, title string) revel.Result { func (c File) UpdateImageTitle(fileId, title string) revel.Result {
re := info.NewRe() re := info.NewRe()
re.Ok = fileService.UpdateImageTitle(c.GetUserId(), fileId, title) re.Ok = fileService.UpdateImageTitle(c.GetUserId(), fileId, title)
return c.RenderJson(re) return c.RenderJSON(re)
} }
func (c File) DeleteImage(fileId string) revel.Result { func (c File) DeleteImage(fileId string) revel.Result {
re := info.NewRe() re := info.NewRe()
re.Ok, re.Msg = fileService.DeleteImage(c.GetUserId(), fileId) re.Ok, re.Msg = fileService.DeleteImage(c.GetUserId(), fileId)
return c.RenderJson(re) return c.RenderJSON(re)
} }
//----------- //-----------
@@ -235,7 +251,7 @@ func (c File) OutputImage(noteId, fileId string) revel.Result {
func (c File) CopyImage(userId, fileId, toUserId string) revel.Result { func (c File) CopyImage(userId, fileId, toUserId string) revel.Result {
re := info.NewRe() re := info.NewRe()
re.Ok, re.Id = fileService.CopyImage(userId, fileId, toUserId) re.Ok, re.Id = fileService.CopyImage(userId, fileId, toUserId)
return c.RenderJson(re) return c.RenderJSON(re)
} }
// 复制外网的图片 // 复制外网的图片
@@ -251,13 +267,13 @@ func (c File) CopyHttpImage(src string) revel.Result {
dir := revel.BasePath + "/" + fileUrlPath dir := revel.BasePath + "/" + fileUrlPath
err := os.MkdirAll(dir, 0755) err := os.MkdirAll(dir, 0755)
if err != nil { if err != nil {
return c.RenderJson(re) return c.RenderJSON(re)
} }
filesize, filename, _, ok := netutil.WriteUrl(src, dir) filesize, filename, _, ok := netutil.WriteUrl(src, dir)
if !ok { if !ok {
re.Msg = "copy error" re.Msg = "copy error"
return c.RenderJson(re) return c.RenderJSON(re)
} }
// File // File
@@ -273,5 +289,5 @@ func (c File) CopyHttpImage(src string) revel.Result {
// re.Item = fileInfo.Path // re.Item = fileInfo.Path
re.Ok, re.Msg = fileService.AddImage(fileInfo, "", c.GetUserId(), true) re.Ok, re.Msg = fileService.AddImage(fileInfo, "", c.GetUserId(), true)
return c.RenderJson(re) return c.RenderJSON(re)
} }
+3 -3
View File
@@ -23,8 +23,8 @@ func (c Index) Default() revel.Result {
// leanote展示页, 没有登录的, 或已登录明确要进该页的 // leanote展示页, 没有登录的, 或已登录明确要进该页的
func (c Index) Index() revel.Result { func (c Index) Index() revel.Result {
c.SetUserInfo() c.SetUserInfo()
c.RenderArgs["title"] = "leanote" c.ViewArgs["title"] = "leanote"
c.RenderArgs["openRegister"] = configService.GlobalStringConfigs["openRegister"] c.ViewArgs["openRegister"] = configService.GlobalStringConfigs["openRegister"]
c.SetLocale() c.SetLocale()
return c.RenderTemplate("home/index.html") return c.RenderTemplate("home/index.html")
@@ -40,5 +40,5 @@ func (c Index) Suggestion(addr, suggestion string) revel.Result {
emailService.SendEmail("leanote@leanote.com", "建议", "UserId: "+c.GetUserId()+" <br /> Suggestions: "+suggestion) emailService.SendEmail("leanote@leanote.com", "建议", "UserId: "+c.GetUserId()+" <br /> Suggestions: "+suggestion)
}() }()
return c.RenderJson(re) return c.RenderJSON(re)
} }
@@ -12,5 +12,5 @@ type NoteContentHistory struct {
func (c NoteContentHistory) ListHistories(noteId string) revel.Result { func (c NoteContentHistory) ListHistories(noteId string) revel.Result {
histories := noteContentHistoryService.ListHistories(noteId, c.GetUserId()) histories := noteContentHistoryService.ListHistories(noteId, c.GetUserId())
return c.RenderJson(histories) return c.RenderJSON(histories)
} }
+79 -44
View File
@@ -11,6 +11,7 @@ import (
"regexp" "regexp"
"strings" "strings"
"time" "time"
"runtime"
// "github.com/leanote/leanote/app/types" // "github.com/leanote/leanote/app/types"
// "io/ioutil" // "io/ioutil"
"fmt" "fmt"
@@ -36,7 +37,7 @@ func (c Note) Index(noteId, online string) revel.Result {
return c.Redirect("/login") return c.Redirect("/login")
} }
c.RenderArgs["openRegister"] = configService.IsOpenRegister() c.ViewArgs["openRegister"] = configService.IsOpenRegister()
// 已登录了, 那么得到所有信息 // 已登录了, 那么得到所有信息
notebooks := notebookService.GetNotebooks(userId) notebooks := notebookService.GetNotebooks(userId)
@@ -58,16 +59,16 @@ func (c Note) Index(noteId, online string) revel.Result {
noteContent = noteService.GetNoteContent(noteId, noteOwner) noteContent = noteService.GetNoteContent(noteId, noteOwner)
hasRightNoteId = true hasRightNoteId = true
c.RenderArgs["curNoteId"] = noteId c.ViewArgs["curNoteId"] = noteId
c.RenderArgs["curNotebookId"] = note.NotebookId.Hex() c.ViewArgs["curNotebookId"] = note.NotebookId.Hex()
// 打开的是共享的笔记, 那么判断是否是共享给我的默认笔记 // 打开的是共享的笔记, 那么判断是否是共享给我的默认笔记
if noteOwner != c.GetUserId() { if noteOwner != c.GetUserId() {
if shareService.HasReadPerm(noteOwner, c.GetUserId(), noteId) { if shareService.HasReadPerm(noteOwner, c.GetUserId(), noteId) {
// 不要获取notebook下的笔记 // 不要获取notebook下的笔记
// 在前端下发请求 // 在前端下发请求
c.RenderArgs["curSharedNoteNotebookId"] = note.NotebookId.Hex() c.ViewArgs["curSharedNoteNotebookId"] = note.NotebookId.Hex()
c.RenderArgs["curSharedUserId"] = noteOwner c.ViewArgs["curSharedUserId"] = noteOwner
// 没有读写权限 // 没有读写权限
} else { } else {
hasRightNoteId = false hasRightNoteId = false
@@ -97,7 +98,7 @@ func (c Note) Index(noteId, online string) revel.Result {
// 得到最近的笔记 // 得到最近的笔记
_, latestNotes := noteService.ListNotes(c.GetUserId(), "", false, c.GetPage(), 50, defaultSortField, false, false) _, latestNotes := noteService.ListNotes(c.GetUserId(), "", false, c.GetPage(), 50, defaultSortField, false, false)
c.RenderArgs["latestNotes"] = latestNotes c.ViewArgs["latestNotes"] = latestNotes
} }
// 没有传入笔记 // 没有传入笔记
@@ -106,27 +107,27 @@ func (c Note) Index(noteId, online string) revel.Result {
_, notes = noteService.ListNotes(c.GetUserId(), "", false, c.GetPage(), 50, defaultSortField, false, false) _, notes = noteService.ListNotes(c.GetUserId(), "", false, c.GetPage(), 50, defaultSortField, false, false)
if len(notes) > 0 { if len(notes) > 0 {
noteContent = noteService.GetNoteContent(notes[0].NoteId.Hex(), userId) noteContent = noteService.GetNoteContent(notes[0].NoteId.Hex(), userId)
c.RenderArgs["curNoteId"] = notes[0].NoteId.Hex() c.ViewArgs["curNoteId"] = notes[0].NoteId.Hex()
} }
} }
} }
// 当然, 还需要得到第一个notes的content // 当然, 还需要得到第一个notes的content
//... //...
c.RenderArgs["isAdmin"] = configService.GetAdminUsername() == userInfo.Username c.ViewArgs["isAdmin"] = configService.GetAdminUsername() == userInfo.Username
c.RenderArgs["userInfo"] = userInfo c.ViewArgs["userInfo"] = userInfo
c.RenderArgs["notebooks"] = notebooks c.ViewArgs["notebooks"] = notebooks
c.RenderArgs["shareNotebooks"] = shareNotebooks // note信息在notes列表中 c.ViewArgs["shareNotebooks"] = shareNotebooks // note信息在notes列表中
c.RenderArgs["sharedUserInfos"] = sharedUserInfos c.ViewArgs["sharedUserInfos"] = sharedUserInfos
c.RenderArgs["notes"] = notes c.ViewArgs["notes"] = notes
c.RenderArgs["noteContentJson"] = noteContent c.ViewArgs["noteContentJson"] = noteContent
c.RenderArgs["noteContent"] = noteContent.Content c.ViewArgs["noteContent"] = noteContent.Content
c.RenderArgs["tags"] = tagService.GetTags(c.GetUserId()) c.ViewArgs["tags"] = tagService.GetTags(c.GetUserId())
c.RenderArgs["globalConfigs"] = configService.GetGlobalConfigForUser() c.ViewArgs["globalConfigs"] = configService.GetGlobalConfigForUser()
// return c.RenderTemplate("note/note.html") // return c.RenderTemplate("note/note.html")
@@ -142,24 +143,34 @@ func (c Note) Index(noteId, online string) revel.Result {
// 否则, 转向登录页面 // 否则, 转向登录页面
func (c Note) ListNotes(notebookId string) revel.Result { func (c Note) ListNotes(notebookId string) revel.Result {
_, notes := noteService.ListNotes(c.GetUserId(), notebookId, false, c.GetPage(), pageSize, defaultSortField, false, false) _, notes := noteService.ListNotes(c.GetUserId(), notebookId, false, c.GetPage(), pageSize, defaultSortField, false, false)
return c.RenderJson(notes) return c.RenderJSON(notes)
} }
// 得到trash // 得到trash
func (c Note) ListTrashNotes() revel.Result { func (c Note) ListTrashNotes() revel.Result {
_, notes := noteService.ListNotes(c.GetUserId(), "", true, c.GetPage(), pageSize, defaultSortField, false, false) _, notes := noteService.ListNotes(c.GetUserId(), "", true, c.GetPage(), pageSize, defaultSortField, false, false)
return c.RenderJson(notes) return c.RenderJSON(notes)
} }
// 得到note和内容 // 得到note和内容
func (c Note) GetNoteAndContent(noteId string) revel.Result { func (c Note) GetNoteAndContent(noteId string) revel.Result {
return c.RenderJson(noteService.GetNoteAndContent(noteId, c.GetUserId())) return c.RenderJSON(noteService.GetNoteAndContent(noteId, c.GetUserId()))
}
func (c Note) GetNoteAndContentBySrc(src string) revel.Result {
noteId, noteAndContent := noteService.GetNoteAndContentBySrc(src, c.GetUserId())
ret := info.Re{}
if noteId != "" {
ret.Ok = true
ret.Item = noteAndContent
}
return c.RenderJSON(ret)
} }
// 得到内容 // 得到内容
func (c Note) GetNoteContent(noteId string) revel.Result { func (c Note) GetNoteContent(noteId string) revel.Result {
noteContent := noteService.GetNoteContent(noteId, c.GetUserId()) noteContent := noteService.GetNoteContent(noteId, c.GetUserId())
return c.RenderJson(noteContent) return c.RenderJSON(noteContent)
} }
// 这里不能用json, 要用post // 这里不能用json, 要用post
@@ -177,6 +188,7 @@ func (c Note) UpdateNoteOrContent(noteOrContent info.NoteOrContent) revel.Result
NoteId: bson.ObjectIdHex(noteOrContent.NoteId), NoteId: bson.ObjectIdHex(noteOrContent.NoteId),
NotebookId: bson.ObjectIdHex(noteOrContent.NotebookId), NotebookId: bson.ObjectIdHex(noteOrContent.NotebookId),
Title: noteOrContent.Title, Title: noteOrContent.Title,
Src: noteOrContent.Src, // 来源
Tags: strings.Split(noteOrContent.Tags, ","), Tags: strings.Split(noteOrContent.Tags, ","),
Desc: noteOrContent.Desc, Desc: noteOrContent.Desc,
ImgSrc: noteOrContent.ImgSrc, ImgSrc: noteOrContent.ImgSrc,
@@ -190,7 +202,7 @@ func (c Note) UpdateNoteOrContent(noteOrContent info.NoteOrContent) revel.Result
Abstract: noteOrContent.Abstract} Abstract: noteOrContent.Abstract}
note = noteService.AddNoteAndContentForController(note, noteContent, c.GetUserId()) note = noteService.AddNoteAndContentForController(note, noteContent, c.GetUserId())
return c.RenderJson(note) return c.RenderJSON(note)
} }
noteUpdate := bson.M{} noteUpdate := bson.M{}
@@ -222,22 +234,23 @@ func (c Note) UpdateNoteOrContent(noteOrContent info.NoteOrContent) revel.Result
} }
//------------- //-------------
afterContentUsn := 0 // afterContentUsn := 0
contentOk := false // contentOk := false
contentMsg := "" // contentMsg := ""
if c.Has("Content") { if c.Has("Content") {
// noteService.UpdateNoteContent(noteOrContent.UserId, c.GetUserId(), // noteService.UpdateNoteContent(noteOrContent.UserId, c.GetUserId(),
// noteOrContent.NoteId, noteOrContent.Content, noteOrContent.Abstract) // noteOrContent.NoteId, noteOrContent.Content, noteOrContent.Abstract)
contentOk, contentMsg, afterContentUsn = noteService.UpdateNoteContent(c.GetUserId(), // contentOk, contentMsg, afterContentUsn =
noteService.UpdateNoteContent(c.GetUserId(),
noteOrContent.NoteId, noteOrContent.Content, noteOrContent.Abstract, noteOrContent.NoteId, noteOrContent.Content, noteOrContent.Abstract,
needUpdateNote, -1, time.Now()) needUpdateNote, -1, time.Now())
} }
Log(afterContentUsn) // Log("usn", "afterContentUsn", afterContentUsn + "")
Log(contentOk) // Log(contentOk)
Log(contentMsg) // Log(contentMsg)
return c.RenderJson(true) return c.RenderJSON(true)
} }
// 删除note/ 删除别人共享给我的笔记 // 删除note/ 删除别人共享给我的笔记
@@ -247,19 +260,19 @@ func (c Note) DeleteNote(noteIds []string, isShared bool) revel.Result {
for _, noteId := range noteIds { for _, noteId := range noteIds {
trashService.DeleteNote(noteId, c.GetUserId()) trashService.DeleteNote(noteId, c.GetUserId())
} }
return c.RenderJson(true) return c.RenderJSON(true)
} }
for _, noteId := range noteIds { for _, noteId := range noteIds {
trashService.DeleteSharedNote(noteId, c.GetUserId()) trashService.DeleteSharedNote(noteId, c.GetUserId())
} }
return c.RenderJson(true) return c.RenderJSON(true)
} }
// 删除trash, 已弃用, 用DeleteNote // 删除trash, 已弃用, 用DeleteNote
func (c Note) DeleteTrash(noteId string) revel.Result { func (c Note) DeleteTrash(noteId string) revel.Result {
return c.RenderJson(trashService.DeleteTrash(noteId, c.GetUserId())) return c.RenderJSON(trashService.DeleteTrash(noteId, c.GetUserId()))
} }
// 移动note // 移动note
@@ -268,7 +281,7 @@ func (c Note) MoveNote(noteIds []string, notebookId string) revel.Result {
for _, noteId := range noteIds { for _, noteId := range noteIds {
noteService.MoveNote(noteId, notebookId, userId) noteService.MoveNote(noteId, notebookId, userId)
} }
return c.RenderJson(true) return c.RenderJSON(true)
} }
// 复制note // 复制note
@@ -281,7 +294,7 @@ func (c Note) CopyNote(noteIds []string, notebookId string) revel.Result {
re := info.NewRe() re := info.NewRe()
re.Ok = true re.Ok = true
re.Item = copyNotes re.Item = copyNotes
return c.RenderJson(re) return c.RenderJSON(re)
} }
// 复制别人共享的笔记给我 // 复制别人共享的笔记给我
@@ -294,7 +307,7 @@ func (c Note) CopySharedNote(noteIds []string, notebookId, fromUserId string) re
re := info.NewRe() re := info.NewRe()
re.Ok = true re.Ok = true
re.Item = copyNotes re.Item = copyNotes
return c.RenderJson(re) return c.RenderJSON(re)
} }
//------------ //------------
@@ -302,13 +315,13 @@ func (c Note) CopySharedNote(noteIds []string, notebookId, fromUserId string) re
// 通过title搜索 // 通过title搜索
func (c Note) SearchNote(key string) revel.Result { func (c Note) SearchNote(key string) revel.Result {
_, blogs := noteService.SearchNote(key, c.GetUserId(), c.GetPage(), pageSize, "UpdatedTime", false, false) _, blogs := noteService.SearchNote(key, c.GetUserId(), c.GetPage(), pageSize, "UpdatedTime", false, false)
return c.RenderJson(blogs) return c.RenderJSON(blogs)
} }
// 通过tags搜索 // 通过tags搜索
func (c Note) SearchNoteByTags(tags []string) revel.Result { func (c Note) SearchNoteByTags(tags []string) revel.Result {
_, blogs := noteService.SearchNoteByTags(tags, c.GetUserId(), c.GetPage(), pageSize, "UpdatedTime", false) _, blogs := noteService.SearchNoteByTags(tags, c.GetUserId(), c.GetPage(), pageSize, "UpdatedTime", false)
return c.RenderJson(blogs) return c.RenderJSON(blogs)
} }
// 生成PDF // 生成PDF
@@ -338,6 +351,8 @@ func (c Note) ToPdf(noteId, appKey string) revel.Result {
siteUrlPattern = strings.Replace(siteUrlPattern, "http", "https*", 1) siteUrlPattern = strings.Replace(siteUrlPattern, "http", "https*", 1)
} }
siteUrlPattern = "(?:" + siteUrlPattern + ")*"
regImage, _ := regexp.Compile(`<img .*?(src=('|")` + siteUrlPattern + `/(file/outputImage|api/file/getImage)\?fileId=([a-z0-9A-Z]{24})("|'))`) regImage, _ := regexp.Compile(`<img .*?(src=('|")` + siteUrlPattern + `/(file/outputImage|api/file/getImage)\?fileId=([a-z0-9A-Z]{24})("|'))`)
findsImage := regImage.FindAllStringSubmatch(contentStr, -1) // 查找所有的 findsImage := regImage.FindAllStringSubmatch(contentStr, -1) // 查找所有的
@@ -384,11 +399,11 @@ func (c Note) ToPdf(noteId, appKey string) revel.Result {
} else { } else {
note.Tags = nil note.Tags = nil
} }
c.RenderArgs["blog"] = note c.ViewArgs["blog"] = note
c.RenderArgs["content"] = contentStr c.ViewArgs["content"] = contentStr
c.RenderArgs["userInfo"] = userInfo c.ViewArgs["userInfo"] = userInfo
userBlog := blogService.GetUserBlog(noteUserId) userBlog := blogService.GetUserBlog(noteUserId)
c.RenderArgs["userBlog"] = userBlog c.ViewArgs["userBlog"] = userBlog
return c.RenderTemplate("file/pdf.html") return c.RenderTemplate("file/pdf.html")
} }
@@ -433,8 +448,12 @@ func (c Note) ExportPdf(noteId string) revel.Result {
binPath := configService.GetGlobalStringConfig("exportPdfBinPath") binPath := configService.GetGlobalStringConfig("exportPdfBinPath")
// 默认路径 // 默认路径
if binPath == "" { if binPath == "" {
if runtime.GOOS == "windows" {
binPath = `C:\Program Files\wkhtmltopdf\bin\wkhtmltopdf.exe`
} else {
binPath = "/usr/local/bin/wkhtmltopdf" binPath = "/usr/local/bin/wkhtmltopdf"
} }
}
url := configService.GetSiteUrl() + "/note/toPdf?noteId=" + noteId + "&appKey=" + appKey url := configService.GetSiteUrl() + "/note/toPdf?noteId=" + noteId + "&appKey=" + appKey
// cc := binPath + " --no-stop-slow-scripts --javascript-delay 10000 \"" + url + "\" \"" + path + "\"" // \"" + cookieDomain + "\" \"" + cookieName + "\" \"" + cookieValue + "\"" // cc := binPath + " --no-stop-slow-scripts --javascript-delay 10000 \"" + url + "\" \"" + path + "\"" // \"" + cookieDomain + "\" \"" + cookieName + "\" \"" + cookieValue + "\""
@@ -443,13 +462,29 @@ func (c Note) ExportPdf(noteId string) revel.Result {
// http://madalgo.au.dk/~jakobt/wkhtmltoxdoc/wkhtmltopdf_0.10.0_rc2-doc.html // http://madalgo.au.dk/~jakobt/wkhtmltoxdoc/wkhtmltopdf_0.10.0_rc2-doc.html
// wkhtmltopdf参数大全 // wkhtmltopdf参数大全
var cc string var cc string
// var cc []string
var ccWindows []string
if note.IsMarkdown { if note.IsMarkdown {
cc = binPath + " --lowquality --window-status done \"" + url + "\" \"" + path + "\"" // \"" + cookieDomain + "\" \"" + cookieName + "\" \"" + cookieValue + "\"" cc = binPath + " --lowquality --window-status done \"" + url + "\" \"" + path + "\"" // \"" + cookieDomain + "\" \"" + cookieName + "\" \"" + cookieValue + "\""
// cc = []string{binPath, "--lowquality", "--window-status", "done", "\"" + url + "\"", "\"" + path + "\""}
ccWindows = []string{"/C", binPath, "--lowquality", "--window-status", "done", url, path}
} else { } else {
cc = binPath + " --lowquality \"" + url + "\" \"" + path + "\"" // \"" + cookieDomain + "\" \"" + cookieName + "\" \"" + cookieValue + "\"" cc = binPath + " --lowquality \"" + url + "\" \"" + path + "\"" // \"" + cookieDomain + "\" \"" + cookieName + "\" \"" + cookieValue + "\""
// cc = []string{binPath, "--lowquality", "\"" + url + "\"", "\"" + path + "\""}
ccWindows = []string{"/C", binPath, "--lowquality", url, path}
} }
cmd := exec.Command("/bin/sh", "-c", cc) var cmd *exec.Cmd
// fmt.Println("-------1", runtime.GOOS, ccWindows)
if runtime.GOOS == "windows" {
fmt.Println(ccWindows)
// cmd = exec.Command("cmd", ccWindows...)
cmd = exec.Command(ccWindows[1], ccWindows[2:]...)
} else {
fmt.Println(cc)
cmd = exec.Command("/bin/sh", "-c", cc)
}
_, err := cmd.Output() _, err := cmd.Output()
if err != nil { if err != nil {
return c.RenderText("export pdf error. " + fmt.Sprintf("%v", err)) return c.RenderText("export pdf error. " + fmt.Sprintf("%v", err))
@@ -475,5 +510,5 @@ func (c Note) SetNote2Blog(noteIds []string, isBlog, isTop bool) revel.Result {
for _, noteId := range noteIds { for _, noteId := range noteIds {
noteService.ToBlog(c.GetUserId(), noteId, isBlog, isTop) noteService.ToBlog(c.GetUserId(), noteId, isBlog, isTop)
} }
return c.RenderJson(true) return c.RenderJSON(true)
} }
+9 -9
View File
@@ -14,18 +14,18 @@ type Notebook struct {
} }
func (c Notebook) Index(notebook info.Notebook, i int, name string) revel.Result { func (c Notebook) Index(notebook info.Notebook, i int, name string) revel.Result {
return c.RenderJson(notebook) return c.RenderJSON(notebook)
} }
// 得到用户的所有笔记本 // 得到用户的所有笔记本
func (c Notebook) GetNotebooks() revel.Result { func (c Notebook) GetNotebooks() revel.Result {
re := notebookService.GetNotebooks(c.GetUserId()) re := notebookService.GetNotebooks(c.GetUserId())
return c.RenderJson(re) return c.RenderJSON(re)
} }
func (c Notebook) DeleteNotebook(notebookId string) revel.Result { func (c Notebook) DeleteNotebook(notebookId string) revel.Result {
re, msg := notebookService.DeleteNotebook(c.GetUserId(), notebookId) re, msg := notebookService.DeleteNotebook(c.GetUserId(), notebookId)
return c.RenderJson(info.Re{Ok: re, Msg: msg}) return c.RenderJSON(info.Re{Ok: re, Msg: msg})
} }
// 添加notebook // 添加notebook
@@ -41,21 +41,21 @@ func (c Notebook) AddNotebook(notebookId, title, parentNotebookId string) revel.
re, notebook := notebookService.AddNotebook(notebook) re, notebook := notebookService.AddNotebook(notebook)
if re { if re {
return c.RenderJson(notebook) return c.RenderJSON(notebook)
} else { } else {
return c.RenderJson(false) return c.RenderJSON(false)
} }
} }
// 修改标题 // 修改标题
func (c Notebook) UpdateNotebookTitle(notebookId, title string) revel.Result { func (c Notebook) UpdateNotebookTitle(notebookId, title string) revel.Result {
return c.RenderJson(notebookService.UpdateNotebookTitle(notebookId, c.GetUserId(), title)) return c.RenderJSON(notebookService.UpdateNotebookTitle(notebookId, c.GetUserId(), title))
} }
// 排序 // 排序
// 无用 // 无用
// func (c Notebook) SortNotebooks(notebookId2Seqs map[string]int) revel.Result { // func (c Notebook) SortNotebooks(notebookId2Seqs map[string]int) revel.Result {
// return c.RenderJson(notebookService.SortNotebooks(c.GetUserId(), notebookId2Seqs)) // return c.RenderJSON(notebookService.SortNotebooks(c.GetUserId(), notebookId2Seqs))
// } // }
// 调整notebooks, 可能是排序, 可能是移动到其它笔记本下 // 调整notebooks, 可能是排序, 可能是移动到其它笔记本下
@@ -70,11 +70,11 @@ func (c Notebook) DragNotebooks(data string) revel.Result {
info := DragNotebooksInfo{} info := DragNotebooksInfo{}
json.Unmarshal([]byte(data), &info) json.Unmarshal([]byte(data), &info)
return c.RenderJson(notebookService.DragNotebooks(c.GetUserId(), info.CurNotebookId, info.ParentNotebookId, info.Siblings)) return c.RenderJSON(notebookService.DragNotebooks(c.GetUserId(), info.CurNotebookId, info.ParentNotebookId, info.Siblings))
} }
// 设置notebook <-> blog // 设置notebook <-> blog
func (c Notebook) SetNotebook2Blog(notebookId string, isBlog bool) revel.Result { func (c Notebook) SetNotebook2Blog(notebookId string, isBlog bool) revel.Result {
re := notebookService.ToBlog(c.GetUserId(), notebookId, isBlog) re := notebookService.ToBlog(c.GetUserId(), notebookId, isBlog)
return c.RenderJson(re) return c.RenderJSON(re)
} }
+12 -12
View File
@@ -32,10 +32,10 @@ func (c Preview) getPreviewThemeAbsolutePath(themeId string) bool {
} }
theme := themeService.GetTheme(c.GetUserId(), themeId) theme := themeService.GetTheme(c.GetUserId(), themeId)
c.RenderArgs["isPreview"] = true c.ViewArgs["isPreview"] = true
c.RenderArgs["themeId"] = themeId c.ViewArgs["themeId"] = themeId
c.RenderArgs["themeInfoPreview"] = theme.Info c.ViewArgs["themeInfoPreview"] = theme.Info
c.RenderArgs["themePath"] = theme.Path c.ViewArgs["themePath"] = theme.Path
if theme.Path == "" { if theme.Path == "" {
return false return false
} }
@@ -47,7 +47,7 @@ func (c Preview) Index(userIdOrEmail string, themeId string) revel.Result {
return c.E404() return c.E404()
} }
return c.Blog.Index(c.GetUserId()) return c.Blog.Index(c.GetUserId())
// return blog.RenderTemplate("index.html", c.RenderArgs, c.getPreviewThemeAbsolutePath(themeId)) // return blog.RenderTemplate("index.html", c.ViewArgs, c.getPreviewThemeAbsolutePath(themeId))
} }
func (c Preview) Tag(userIdOrEmail, tag string) revel.Result { func (c Preview) Tag(userIdOrEmail, tag string) revel.Result {
@@ -62,42 +62,42 @@ func (c Preview) Tags(userIdOrEmail string) revel.Result {
} }
return c.Blog.Tags(c.GetUserId()) return c.Blog.Tags(c.GetUserId())
// if tag == "" { // if tag == "" {
// return blog.RenderTemplate("tags.html", c.RenderArgs, c.getPreviewThemeAbsolutePath("")) // return blog.RenderTemplate("tags.html", c.ViewArgs, c.getPreviewThemeAbsolutePath(""))
// } // }
// return blog.RenderTemplate("tag_posts.html", c.RenderArgs, c.getPreviewThemeAbsolutePath("")) // return blog.RenderTemplate("tag_posts.html", c.ViewArgs, c.getPreviewThemeAbsolutePath(""))
} }
func (c Preview) Archives(userIdOrEmail string, notebookId string, year, month int) revel.Result { func (c Preview) Archives(userIdOrEmail string, notebookId string, year, month int) revel.Result {
if !c.getPreviewThemeAbsolutePath("") { if !c.getPreviewThemeAbsolutePath("") {
return c.E404() return c.E404()
} }
return c.Blog.Archives(c.GetUserId(), notebookId, year, month) return c.Blog.Archives(c.GetUserId(), notebookId, year, month)
// return blog.RenderTemplate("archive.html", c.RenderArgs, c.getPreviewThemeAbsolutePath("")) // return blog.RenderTemplate("archive.html", c.ViewArgs, c.getPreviewThemeAbsolutePath(""))
} }
func (c Preview) Cate(userIdOrEmail, notebookId string) revel.Result { func (c Preview) Cate(userIdOrEmail, notebookId string) revel.Result {
if !c.getPreviewThemeAbsolutePath("") { if !c.getPreviewThemeAbsolutePath("") {
return c.E404() return c.E404()
} }
return c.Blog.Cate(userIdOrEmail, notebookId) return c.Blog.Cate(userIdOrEmail, notebookId)
// return blog.RenderTemplate("cate.html", c.RenderArgs, c.getPreviewThemeAbsolutePath("")) // return blog.RenderTemplate("cate.html", c.ViewArgs, c.getPreviewThemeAbsolutePath(""))
} }
func (c Preview) Post(userIdOrEmail, noteId string) revel.Result { func (c Preview) Post(userIdOrEmail, noteId string) revel.Result {
if !c.getPreviewThemeAbsolutePath("") { if !c.getPreviewThemeAbsolutePath("") {
return c.E404() return c.E404()
} }
return c.Blog.Post(userIdOrEmail, noteId) return c.Blog.Post(userIdOrEmail, noteId)
// return blog.RenderTemplate("view.html", c.RenderArgs, c.getPreviewThemeAbsolutePath("")) // return blog.RenderTemplate("view.html", c.ViewArgs, c.getPreviewThemeAbsolutePath(""))
} }
func (c Preview) Single(userIdOrEmail, singleId string) revel.Result { func (c Preview) Single(userIdOrEmail, singleId string) revel.Result {
if !c.getPreviewThemeAbsolutePath("") { if !c.getPreviewThemeAbsolutePath("") {
return c.E404() return c.E404()
} }
return c.Blog.Single(userIdOrEmail, singleId) return c.Blog.Single(userIdOrEmail, singleId)
// return blog.RenderTemplate("single.html", c.RenderArgs, c.getPreviewThemeAbsolutePath("")) // return blog.RenderTemplate("single.html", c.ViewArgs, c.getPreviewThemeAbsolutePath(""))
} }
func (c Preview) Search(userIdOrEmail, keywords string) revel.Result { func (c Preview) Search(userIdOrEmail, keywords string) revel.Result {
if !c.getPreviewThemeAbsolutePath("") { if !c.getPreviewThemeAbsolutePath("") {
return c.E404() return c.E404()
} }
return c.Blog.Search(c.GetUserId(), keywords) return c.Blog.Search(c.GetUserId(), keywords)
// return blog.RenderTemplate("search.html", c.RenderArgs, c.getPreviewThemeAbsolutePath("")) // return blog.RenderTemplate("search.html", c.ViewArgs, c.getPreviewThemeAbsolutePath(""))
} }
+27 -27
View File
@@ -33,7 +33,7 @@ func (c Share) AddShareNote(noteId string, emails []string, perm int) revel.Resu
} }
} }
return c.RenderJson(status) return c.RenderJSON(status)
} }
// 添加共享notebook // 添加共享notebook
@@ -53,7 +53,7 @@ func (c Share) AddShareNotebook(notebookId string, emails []string, perm int) re
} }
} }
return c.RenderJson(status) return c.RenderJSON(status)
} }
// 得到notes // 得到notes
@@ -63,10 +63,10 @@ func (c Share) ListShareNotes(notebookId, userId string) revel.Result {
var notes []info.ShareNoteWithPerm var notes []info.ShareNoteWithPerm
if notebookId == "" { if notebookId == "" {
notes = shareService.ListShareNotes(c.GetUserId(), userId, c.GetPage(), pageSize, defaultSortField, false) notes = shareService.ListShareNotes(c.GetUserId(), userId, c.GetPage(), pageSize, defaultSortField, false)
return c.RenderJson(notes) return c.RenderJSON(notes)
} else { } else {
// 有notebookId的 // 有notebookId的
return c.RenderJson(shareService.ListShareNotesByNotebookId(notebookId, c.GetUserId(), userId, c.GetPage(), pageSize, defaultSortField, false)) return c.RenderJSON(shareService.ListShareNotesByNotebookId(notebookId, c.GetUserId(), userId, c.GetPage(), pageSize, defaultSortField, false))
} }
} }
@@ -74,7 +74,7 @@ func (c Share) ListShareNotes(notebookId, userId string) revel.Result {
// sharedUserId 是谁的笔记 // sharedUserId 是谁的笔记
func (c Share) GetShareNoteContent(noteId, sharedUserId string) revel.Result { func (c Share) GetShareNoteContent(noteId, sharedUserId string) revel.Result {
noteContent := shareService.GetShareNoteContent(noteId, c.GetUserId(), sharedUserId) noteContent := shareService.GetShareNoteContent(noteId, c.GetUserId(), sharedUserId)
return c.RenderJson(noteContent) return c.RenderJSON(noteContent)
} }
// 查看note的分享信息 // 查看note的分享信息
@@ -85,13 +85,13 @@ func (c Share) ListNoteShareUserInfo(noteId string) revel.Result {
note := noteService.GetNote(noteId, c.GetUserId()) note := noteService.GetNote(noteId, c.GetUserId())
noteShareUserInfos := shareService.ListNoteShareUserInfo(noteId, c.GetUserId()) noteShareUserInfos := shareService.ListNoteShareUserInfo(noteId, c.GetUserId())
c.RenderArgs["noteOrNotebookShareUserInfos"] = noteShareUserInfos c.ViewArgs["noteOrNotebookShareUserInfos"] = noteShareUserInfos
c.RenderArgs["noteOrNotebookShareGroupInfos"] = shareService.GetNoteShareGroups(noteId, c.GetUserId()) c.ViewArgs["noteOrNotebookShareGroupInfos"] = shareService.GetNoteShareGroups(noteId, c.GetUserId())
c.RenderArgs["isNote"] = true c.ViewArgs["isNote"] = true
c.RenderArgs["noteOrNotebookId"] = note.NoteId.Hex() c.ViewArgs["noteOrNotebookId"] = note.NoteId.Hex()
c.RenderArgs["title"] = note.Title c.ViewArgs["title"] = note.Title
return c.RenderTemplate("share/note_notebook_share_user_infos.html") return c.RenderTemplate("share/note_notebook_share_user_infos.html")
} }
@@ -99,14 +99,14 @@ func (c Share) ListNotebookShareUserInfo(notebookId string) revel.Result {
notebook := notebookService.GetNotebook(notebookId, c.GetUserId()) notebook := notebookService.GetNotebook(notebookId, c.GetUserId())
notebookShareUserInfos := shareService.ListNotebookShareUserInfo(notebookId, c.GetUserId()) notebookShareUserInfos := shareService.ListNotebookShareUserInfo(notebookId, c.GetUserId())
c.RenderArgs["noteOrNotebookShareUserInfos"] = notebookShareUserInfos c.ViewArgs["noteOrNotebookShareUserInfos"] = notebookShareUserInfos
c.RenderArgs["noteOrNotebookShareGroupInfos"] = shareService.GetNotebookShareGroups(notebookId, c.GetUserId()) c.ViewArgs["noteOrNotebookShareGroupInfos"] = shareService.GetNotebookShareGroups(notebookId, c.GetUserId())
LogJ(c.RenderArgs["noteOrNotebookShareGroupInfos"]) LogJ(c.ViewArgs["noteOrNotebookShareGroupInfos"])
c.RenderArgs["isNote"] = false c.ViewArgs["isNote"] = false
c.RenderArgs["noteOrNotebookId"] = notebook.NotebookId.Hex() c.ViewArgs["noteOrNotebookId"] = notebook.NotebookId.Hex()
c.RenderArgs["title"] = notebook.Title c.ViewArgs["title"] = notebook.Title
return c.RenderTemplate("share/note_notebook_share_user_infos.html") return c.RenderTemplate("share/note_notebook_share_user_infos.html")
} }
@@ -114,38 +114,38 @@ func (c Share) ListNotebookShareUserInfo(notebookId string) revel.Result {
//------------ //------------
// 改变share note 权限 // 改变share note 权限
func (c Share) UpdateShareNotePerm(noteId string, perm int, toUserId string) revel.Result { func (c Share) UpdateShareNotePerm(noteId string, perm int, toUserId string) revel.Result {
return c.RenderJson(shareService.UpdateShareNotePerm(noteId, perm, c.GetUserId(), toUserId)) return c.RenderJSON(shareService.UpdateShareNotePerm(noteId, perm, c.GetUserId(), toUserId))
} }
// 改变share notebook 权限 // 改变share notebook 权限
func (c Share) UpdateShareNotebookPerm(notebookId string, perm int, toUserId string) revel.Result { func (c Share) UpdateShareNotebookPerm(notebookId string, perm int, toUserId string) revel.Result {
return c.RenderJson(shareService.UpdateShareNotebookPerm(notebookId, perm, c.GetUserId(), toUserId)) return c.RenderJSON(shareService.UpdateShareNotebookPerm(notebookId, perm, c.GetUserId(), toUserId))
} }
//--------------- //---------------
// 删除share note // 删除share note
func (c Share) DeleteShareNote(noteId string, toUserId string) revel.Result { func (c Share) DeleteShareNote(noteId string, toUserId string) revel.Result {
return c.RenderJson(shareService.DeleteShareNote(noteId, c.GetUserId(), toUserId)) return c.RenderJSON(shareService.DeleteShareNote(noteId, c.GetUserId(), toUserId))
} }
// 删除share notebook // 删除share notebook
func (c Share) DeleteShareNotebook(notebookId string, toUserId string) revel.Result { func (c Share) DeleteShareNotebook(notebookId string, toUserId string) revel.Result {
return c.RenderJson(shareService.DeleteShareNotebook(notebookId, c.GetUserId(), toUserId)) return c.RenderJSON(shareService.DeleteShareNotebook(notebookId, c.GetUserId(), toUserId))
} }
// 删除share note, 被共享方删除 // 删除share note, 被共享方删除
func (c Share) DeleteShareNoteBySharedUser(noteId string, fromUserId string) revel.Result { func (c Share) DeleteShareNoteBySharedUser(noteId string, fromUserId string) revel.Result {
return c.RenderJson(shareService.DeleteShareNote(noteId, fromUserId, c.GetUserId())) return c.RenderJSON(shareService.DeleteShareNote(noteId, fromUserId, c.GetUserId()))
} }
// 删除share notebook, 被共享方删除 // 删除share notebook, 被共享方删除
func (c Share) DeleteShareNotebookBySharedUser(notebookId string, fromUserId string) revel.Result { func (c Share) DeleteShareNotebookBySharedUser(notebookId string, fromUserId string) revel.Result {
return c.RenderJson(shareService.DeleteShareNotebook(notebookId, fromUserId, c.GetUserId())) return c.RenderJSON(shareService.DeleteShareNotebook(notebookId, fromUserId, c.GetUserId()))
} }
// 删除fromUserId分享给我的所有note, notebook // 删除fromUserId分享给我的所有note, notebook
func (c Share) DeleteUserShareNoteAndNotebook(fromUserId string) revel.Result { func (c Share) DeleteUserShareNoteAndNotebook(fromUserId string) revel.Result {
return c.RenderJson(shareService.DeleteUserShareNoteAndNotebook(fromUserId, c.GetUserId())) return c.RenderJSON(shareService.DeleteUserShareNoteAndNotebook(fromUserId, c.GetUserId()))
} }
//------------- //-------------
@@ -155,14 +155,14 @@ func (c Share) DeleteUserShareNoteAndNotebook(fromUserId string) revel.Result {
func (c Share) AddShareNoteGroup(noteId, groupId string, perm int) revel.Result { func (c Share) AddShareNoteGroup(noteId, groupId string, perm int) revel.Result {
re := info.NewRe() re := info.NewRe()
re.Ok = shareService.AddShareNoteGroup(c.GetUserId(), noteId, groupId, perm) re.Ok = shareService.AddShareNoteGroup(c.GetUserId(), noteId, groupId, perm)
return c.RenderJson(re) return c.RenderJSON(re)
} }
// 删除 // 删除
func (c Share) DeleteShareNoteGroup(noteId, groupId string) revel.Result { func (c Share) DeleteShareNoteGroup(noteId, groupId string) revel.Result {
re := info.NewRe() re := info.NewRe()
re.Ok = shareService.DeleteShareNoteGroup(c.GetUserId(), noteId, groupId) re.Ok = shareService.DeleteShareNoteGroup(c.GetUserId(), noteId, groupId)
return c.RenderJson(re) return c.RenderJSON(re)
} }
// 更新, 也是一样, 先删后加 // 更新, 也是一样, 先删后加
@@ -176,14 +176,14 @@ func (c Share) UpdateShareNoteGroupPerm(noteId, groupId string, perm int) revel.
func (c Share) AddShareNotebookGroup(notebookId, groupId string, perm int) revel.Result { func (c Share) AddShareNotebookGroup(notebookId, groupId string, perm int) revel.Result {
re := info.NewRe() re := info.NewRe()
re.Ok = shareService.AddShareNotebookGroup(c.GetUserId(), notebookId, groupId, perm) re.Ok = shareService.AddShareNotebookGroup(c.GetUserId(), notebookId, groupId, perm)
return c.RenderJson(re) return c.RenderJSON(re)
} }
// 删除 // 删除
func (c Share) DeleteShareNotebookGroup(notebookId, groupId string) revel.Result { func (c Share) DeleteShareNotebookGroup(notebookId, groupId string) revel.Result {
re := info.NewRe() re := info.NewRe()
re.Ok = shareService.DeleteShareNotebookGroup(c.GetUserId(), notebookId, groupId) re.Ok = shareService.DeleteShareNotebookGroup(c.GetUserId(), notebookId, groupId)
return c.RenderJson(re) return c.RenderJSON(re)
} }
// 更新, 也是一样, 先删后加 // 更新, 也是一样, 先删后加
+2 -2
View File
@@ -18,7 +18,7 @@ func (c Tag) UpdateTag(tag string) revel.Result {
ret := info.NewRe() ret := info.NewRe()
ret.Ok = true ret.Ok = true
ret.Item = tagService.AddOrUpdateTag(c.GetUserId(), tag) ret.Item = tagService.AddOrUpdateTag(c.GetUserId(), tag)
return c.RenderJson(ret) return c.RenderJSON(ret)
} }
// 删除标签 // 删除标签
@@ -26,5 +26,5 @@ func (c Tag) DeleteTag(tag string) revel.Result {
ret := info.Re{} ret := info.Re{}
ret.Ok = true ret.Ok = true
ret.Item = tagService.DeleteTag(c.GetUserId(), tag) ret.Item = tagService.DeleteTag(c.GetUserId(), tag)
return c.RenderJson(ret) return c.RenderJSON(ret)
} }
+16 -16
View File
@@ -21,8 +21,8 @@ type User struct {
func (c User) Account(tab int) revel.Result { func (c User) Account(tab int) revel.Result {
userInfo := c.GetUserInfo() userInfo := c.GetUserInfo()
c.RenderArgs["userInfo"] = userInfo c.ViewArgs["userInfo"] = userInfo
c.RenderArgs["tab"] = tab c.ViewArgs["tab"] = tab
c.SetLocale() c.SetLocale()
return c.RenderTemplate("user/account.html") return c.RenderTemplate("user/account.html")
} }
@@ -70,18 +70,18 @@ func (c User) UpdateTheme(theme string) revel.Result {
if re.Ok { if re.Ok {
c.UpdateSession("Theme", theme) c.UpdateSession("Theme", theme)
} }
return c.RenderJson(re) return c.RenderJSON(re)
} }
// 发送邀请链接 // 发送邀请链接
func (c User) SendRegisterEmail(content, toEmail string) revel.Result { func (c User) SendRegisterEmail(content, toEmail string) revel.Result {
re := info.NewRe() re := info.NewRe()
if content == "" || !IsEmail(toEmail) { if content == "" || !IsEmail(toEmail) {
return c.RenderJson(re) return c.RenderJSON(re)
} }
re.Ok = emailService.SendInviteEmail(c.GetUserInfo(), toEmail, content) re.Ok = emailService.SendInviteEmail(c.GetUserInfo(), toEmail, content)
return c.RenderJson(re) return c.RenderJSON(re)
} }
//--------------------------- //---------------------------
@@ -90,7 +90,7 @@ func (c User) SendRegisterEmail(content, toEmail string) revel.Result {
func (c User) ReSendActiveEmail() revel.Result { func (c User) ReSendActiveEmail() revel.Result {
re := info.NewRe() re := info.NewRe()
re.Ok = emailService.RegisterSendActiveEmail(c.GetUserInfo(), c.GetEmail()) re.Ok = emailService.RegisterSendActiveEmail(c.GetUserInfo(), c.GetEmail())
return c.RenderJson(re) return c.RenderJSON(re)
} }
// 通过点击链接 // 通过点击链接
@@ -100,10 +100,10 @@ func (c User) UpdateEmail(token string) revel.Result {
ok, msg, email := userService.UpdateEmail(token) ok, msg, email := userService.UpdateEmail(token)
c.RenderArgs["title"] = "验证邮箱" c.ViewArgs["title"] = "验证邮箱"
c.RenderArgs["ok"] = ok c.ViewArgs["ok"] = ok
c.RenderArgs["msg"] = msg c.ViewArgs["msg"] = msg
c.RenderArgs["email"] = email c.ViewArgs["email"] = email
// 修改session // 修改session
if ok { if ok {
@@ -124,10 +124,10 @@ func (c User) ActiveEmail(token string) revel.Result {
c.UpdateSession("Verified", "1") c.UpdateSession("Verified", "1")
} }
c.RenderArgs["title"] = "验证邮箱" c.ViewArgs["title"] = "验证邮箱"
c.RenderArgs["ok"] = ok c.ViewArgs["ok"] = ok
c.RenderArgs["msg"] = msg c.ViewArgs["msg"] = msg
c.RenderArgs["email"] = email c.ViewArgs["email"] = email
return c.RenderTemplate("user/active_email.html") return c.RenderTemplate("user/active_email.html")
} }
@@ -144,7 +144,7 @@ func (c User) UpdateColumnWidth(notebookWidth, noteListWidth, mdEditorWidth int)
LogJ(c.Session) LogJ(c.Session)
} }
return c.RenderJson(re) return c.RenderJSON(re)
} }
func (c User) UpdateLeftIsMin(leftIsMin bool) revel.Result { func (c User) UpdateLeftIsMin(leftIsMin bool) revel.Result {
re := info.NewRe() re := info.NewRe()
@@ -156,5 +156,5 @@ func (c User) UpdateLeftIsMin(leftIsMin bool) revel.Result {
c.UpdateSession("LeftIsMin", "0") c.UpdateSession("LeftIsMin", "0")
} }
} }
return c.RenderJson(re) return c.RenderJSON(re)
} }
+1 -1
View File
@@ -46,7 +46,7 @@ func (c AdminBaseController) getSorter(sorterField string, isAsc bool, okSorter
} else { } else {
isAsc = false isAsc = false
} }
c.RenderArgs["sorter"] = sorter c.ViewArgs["sorter"] = sorter
return sorterField, isAsc return sorterField, isAsc
} }
+4 -4
View File
@@ -17,14 +17,14 @@ func (c AdminBlog) Index(sorter, keywords string) revel.Result {
pageNumber := c.GetPage() pageNumber := c.GetPage()
sorterField, isAsc := c.getSorter("CreatedTime", false, []string{"title", "userId", "isRecommed", "createdTime"}) sorterField, isAsc := c.getSorter("CreatedTime", false, []string{"title", "userId", "isRecommed", "createdTime"})
pageInfo, blogs := blogService.ListAllBlogs("", "", keywords, false, pageNumber, userPageSize, sorterField, isAsc) pageInfo, blogs := blogService.ListAllBlogs("", "", keywords, false, pageNumber, userPageSize, sorterField, isAsc)
c.RenderArgs["pageInfo"] = pageInfo c.ViewArgs["pageInfo"] = pageInfo
c.RenderArgs["blogs"] = blogs c.ViewArgs["blogs"] = blogs
c.RenderArgs["keywords"] = keywords c.ViewArgs["keywords"] = keywords
return c.RenderTemplate("admin/blog/list.html") return c.RenderTemplate("admin/blog/list.html")
} }
func (c AdminBlog) SetRecommend(noteId string, recommend bool) revel.Result { func (c AdminBlog) SetRecommend(noteId string, recommend bool) revel.Result {
re := info.NewRe() re := info.NewRe()
re.Ok = blogService.SetRecommend(noteId, recommend) re.Ok = blogService.SetRecommend(noteId, recommend)
return c.RenderJson(re) return c.RenderJSON(re)
} }
+9 -9
View File
@@ -14,23 +14,23 @@ type Admin struct {
func (c Admin) Index() revel.Result { func (c Admin) Index() revel.Result {
c.SetUserInfo() c.SetUserInfo()
c.RenderArgs["title"] = "leanote" c.ViewArgs["title"] = "leanote"
c.SetLocale() c.SetLocale()
c.RenderArgs["countUser"] = userService.CountUser() c.ViewArgs["countUser"] = userService.CountUser()
c.RenderArgs["countNote"] = noteService.CountNote("") c.ViewArgs["countNote"] = noteService.CountNote("")
c.RenderArgs["countBlog"] = noteService.CountBlog("") c.ViewArgs["countBlog"] = noteService.CountBlog("")
return c.RenderTemplate("admin/index.html") return c.RenderTemplate("admin/index.html")
} }
// 模板 // 模板
func (c Admin) T(t string) revel.Result { func (c Admin) T(t string) revel.Result {
c.RenderArgs["str"] = configService.GlobalStringConfigs c.ViewArgs["str"] = configService.GlobalStringConfigs
c.RenderArgs["arr"] = configService.GlobalArrayConfigs c.ViewArgs["arr"] = configService.GlobalArrayConfigs
c.RenderArgs["map"] = configService.GlobalMapConfigs c.ViewArgs["map"] = configService.GlobalMapConfigs
c.RenderArgs["arrMap"] = configService.GlobalArrMapConfigs c.ViewArgs["arrMap"] = configService.GlobalArrMapConfigs
c.RenderArgs["version"] = configService.GetVersion() c.ViewArgs["version"] = configService.GetVersion()
return c.RenderTemplate("admin/" + t + ".html") return c.RenderTemplate("admin/" + t + ".html")
} }
+5 -5
View File
@@ -26,33 +26,33 @@ func (c AdminData) Index() revel.Result {
backups2[j] = backups[i] backups2[j] = backups[i]
j++ j++
} }
c.RenderArgs["backups"] = backups2 c.ViewArgs["backups"] = backups2
return c.RenderTemplate("admin/data/index.html") return c.RenderTemplate("admin/data/index.html")
} }
func (c AdminData) Backup() revel.Result { func (c AdminData) Backup() revel.Result {
re := info.NewRe() re := info.NewRe()
re.Ok, re.Msg = configService.Backup("") re.Ok, re.Msg = configService.Backup("")
return c.RenderJson(re) return c.RenderJSON(re)
} }
// 还原 // 还原
func (c AdminData) Restore(createdTime string) revel.Result { func (c AdminData) Restore(createdTime string) revel.Result {
re := info.Re{} re := info.Re{}
re.Ok, re.Msg = configService.Restore(createdTime) re.Ok, re.Msg = configService.Restore(createdTime)
return c.RenderJson(re) return c.RenderJSON(re)
} }
func (c AdminData) Delete(createdTime string) revel.Result { func (c AdminData) Delete(createdTime string) revel.Result {
re := info.Re{} re := info.Re{}
re.Ok, re.Msg = configService.DeleteBackup(createdTime) re.Ok, re.Msg = configService.DeleteBackup(createdTime)
return c.RenderJson(re) return c.RenderJSON(re)
} }
func (c AdminData) UpdateRemark(createdTime, remark string) revel.Result { func (c AdminData) UpdateRemark(createdTime, remark string) revel.Result {
re := info.Re{} re := info.Re{}
re.Ok, re.Msg = configService.UpdateBackupRemark(createdTime, remark) re.Ok, re.Msg = configService.UpdateBackupRemark(createdTime, remark)
return c.RenderJson(re) return c.RenderJSON(re)
} }
func (c AdminData) Download(createdTime string) revel.Result { func (c AdminData) Download(createdTime string) revel.Result {
backup, ok := configService.GetBackup(createdTime) backup, ok := configService.GetBackup(createdTime)
+28 -28
View File
@@ -23,8 +23,8 @@ func (c AdminEmail) Email() revel.Result {
func (c AdminEmail) Blog() revel.Result { func (c AdminEmail) Blog() revel.Result {
recommendTags := configService.GetGlobalArrayConfig("recommendTags") recommendTags := configService.GetGlobalArrayConfig("recommendTags")
newTags := configService.GetGlobalArrayConfig("newTags") newTags := configService.GetGlobalArrayConfig("newTags")
c.RenderArgs["recommendTags"] = strings.Join(recommendTags, ",") c.ViewArgs["recommendTags"] = strings.Join(recommendTags, ",")
c.RenderArgs["newTags"] = strings.Join(newTags, ",") c.ViewArgs["newTags"] = strings.Join(newTags, ",")
return c.RenderTemplate("admin/setting/blog.html") return c.RenderTemplate("admin/setting/blog.html")
} }
func (c AdminEmail) DoBlogTag(recommendTags, newTags string) revel.Result { func (c AdminEmail) DoBlogTag(recommendTags, newTags string) revel.Result {
@@ -33,14 +33,14 @@ func (c AdminEmail) DoBlogTag(recommendTags, newTags string) revel.Result {
re.Ok = configService.UpdateGlobalArrayConfig(c.GetUserId(), "recommendTags", strings.Split(recommendTags, ",")) re.Ok = configService.UpdateGlobalArrayConfig(c.GetUserId(), "recommendTags", strings.Split(recommendTags, ","))
re.Ok = configService.UpdateGlobalArrayConfig(c.GetUserId(), "newTags", strings.Split(newTags, ",")) re.Ok = configService.UpdateGlobalArrayConfig(c.GetUserId(), "newTags", strings.Split(newTags, ","))
return c.RenderJson(re) return c.RenderJSON(re)
} }
// demo // demo
// blog标签设置 // blog标签设置
func (c AdminEmail) Demo() revel.Result { func (c AdminEmail) Demo() revel.Result {
c.RenderArgs["demoUsername"] = configService.GetGlobalStringConfig("demoUsername") c.ViewArgs["demoUsername"] = configService.GetGlobalStringConfig("demoUsername")
c.RenderArgs["demoPassword"] = configService.GetGlobalStringConfig("demoPassword") c.ViewArgs["demoPassword"] = configService.GetGlobalStringConfig("demoPassword")
return c.RenderTemplate("admin/setting/demo.html") return c.RenderTemplate("admin/setting/demo.html")
} }
func (c AdminEmail) DoDemo(demoUsername, demoPassword string) revel.Result { func (c AdminEmail) DoDemo(demoUsername, demoPassword string) revel.Result {
@@ -48,30 +48,30 @@ func (c AdminEmail) DoDemo(demoUsername, demoPassword string) revel.Result {
userInfo, err := authService.Login(demoUsername, demoPassword) userInfo, err := authService.Login(demoUsername, demoPassword)
if err != nil { if err != nil {
return c.RenderJson(info.Re{Ok: false}) return c.RenderJSON(info.Re{Ok: false})
} }
if userInfo.UserId == "" { if userInfo.UserId == "" {
re.Msg = "The User is Not Exists" re.Msg = "The User is Not Exists"
return c.RenderJson(re) return c.RenderJSON(re)
} }
re.Ok = configService.UpdateGlobalStringConfig(c.GetUserId(), "demoUserId", userInfo.UserId.Hex()) re.Ok = configService.UpdateGlobalStringConfig(c.GetUserId(), "demoUserId", userInfo.UserId.Hex())
re.Ok = configService.UpdateGlobalStringConfig(c.GetUserId(), "demoUsername", demoUsername) re.Ok = configService.UpdateGlobalStringConfig(c.GetUserId(), "demoUsername", demoUsername)
re.Ok = configService.UpdateGlobalStringConfig(c.GetUserId(), "demoPassword", demoPassword) re.Ok = configService.UpdateGlobalStringConfig(c.GetUserId(), "demoPassword", demoPassword)
return c.RenderJson(re) return c.RenderJSON(re)
} }
// ToImage // ToImage
// 长微博的bin路径phantomJs // 长微博的bin路径phantomJs
func (c AdminEmail) ToImage() revel.Result { func (c AdminEmail) ToImage() revel.Result {
c.RenderArgs["toImageBinPath"] = configService.GetGlobalStringConfig("toImageBinPath") c.ViewArgs["toImageBinPath"] = configService.GetGlobalStringConfig("toImageBinPath")
return c.RenderTemplate("admin/setting/toImage.html") return c.RenderTemplate("admin/setting/toImage.html")
} }
func (c AdminEmail) DoToImage(toImageBinPath string) revel.Result { func (c AdminEmail) DoToImage(toImageBinPath string) revel.Result {
re := info.NewRe() re := info.NewRe()
re.Ok = configService.UpdateGlobalStringConfig(c.GetUserId(), "toImageBinPath", toImageBinPath) re.Ok = configService.UpdateGlobalStringConfig(c.GetUserId(), "toImageBinPath", toImageBinPath)
return c.RenderJson(re) return c.RenderJSON(re)
} }
func (c AdminEmail) Set(emailHost, emailPort, emailUsername, emailPassword, emailSSL string) revel.Result { func (c AdminEmail) Set(emailHost, emailPort, emailUsername, emailPassword, emailSSL string) revel.Result {
@@ -82,7 +82,7 @@ func (c AdminEmail) Set(emailHost, emailPort, emailUsername, emailPassword, emai
re.Ok = configService.UpdateGlobalStringConfig(c.GetUserId(), "emailPassword", emailPassword) re.Ok = configService.UpdateGlobalStringConfig(c.GetUserId(), "emailPassword", emailPassword)
re.Ok = configService.UpdateGlobalStringConfig(c.GetUserId(), "emailSSL", emailSSL) re.Ok = configService.UpdateGlobalStringConfig(c.GetUserId(), "emailSSL", emailSSL)
return c.RenderJson(re) return c.RenderJSON(re)
} }
func (c AdminEmail) Template() revel.Result { func (c AdminEmail) Template() revel.Result {
re := info.NewRe() re := info.NewRe()
@@ -108,7 +108,7 @@ func (c AdminEmail) Template() revel.Result {
if !ok { if !ok {
re.Ok = false re.Ok = false
re.Msg = "Error key: " + key + "<br />" + msg re.Msg = "Error key: " + key + "<br />" + msg
return c.RenderJson(re) return c.RenderJSON(re)
} else { } else {
configService.UpdateGlobalStringConfig(userId, key, v) configService.UpdateGlobalStringConfig(userId, key, v)
} }
@@ -116,7 +116,7 @@ func (c AdminEmail) Template() revel.Result {
} }
re.Ok = true re.Ok = true
return c.RenderJson(re) return c.RenderJSON(re)
} }
// 发送Email // 发送Email
@@ -127,7 +127,7 @@ func (c AdminEmail) SendEmailToEmails(sendEmails, latestEmailSubject, latestEmai
if latestEmailSubject == "" || latestEmailBody == "" { if latestEmailSubject == "" || latestEmailBody == "" {
re.Msg = "subject or body is blank" re.Msg = "subject or body is blank"
return c.RenderJson(re) return c.RenderJSON(re)
} }
if saveAsOldEmail { if saveAsOldEmail {
@@ -140,7 +140,7 @@ func (c AdminEmail) SendEmailToEmails(sendEmails, latestEmailSubject, latestEmai
emails := strings.Split(sendEmails, "\n") emails := strings.Split(sendEmails, "\n")
re.Ok, re.Msg = emailService.SendEmailToEmails(emails, latestEmailSubject, latestEmailBody) re.Ok, re.Msg = emailService.SendEmailToEmails(emails, latestEmailSubject, latestEmailBody)
return c.RenderJson(re) return c.RenderJSON(re)
} }
// 发送Email // 发送Email
@@ -151,7 +151,7 @@ func (c AdminEmail) SendToUsers2(emails, latestEmailSubject, latestEmailBody str
if latestEmailSubject == "" || latestEmailBody == "" { if latestEmailSubject == "" || latestEmailBody == "" {
re.Msg = "subject or body is blank" re.Msg = "subject or body is blank"
return c.RenderJson(re) return c.RenderJSON(re)
} }
if saveAsOldEmail { if saveAsOldEmail {
@@ -168,7 +168,7 @@ func (c AdminEmail) SendToUsers2(emails, latestEmailSubject, latestEmailBody str
re.Ok, re.Msg = emailService.SendEmailToUsers(users, latestEmailSubject, latestEmailBody) re.Ok, re.Msg = emailService.SendEmailToUsers(users, latestEmailSubject, latestEmailBody)
return c.RenderJson(re) return c.RenderJSON(re)
} }
// send Email dialog // send Email dialog
@@ -176,9 +176,9 @@ func (c AdminEmail) SendEmailDialog(emails string) revel.Result {
emailsArr := strings.Split(emails, ",") emailsArr := strings.Split(emails, ",")
emailsNl := strings.Join(emailsArr, "\n") emailsNl := strings.Join(emailsArr, "\n")
c.RenderArgs["emailsNl"] = emailsNl c.ViewArgs["emailsNl"] = emailsNl
c.RenderArgs["str"] = configService.GlobalStringConfigs c.ViewArgs["str"] = configService.GlobalStringConfigs
c.RenderArgs["map"] = configService.GlobalMapConfigs c.ViewArgs["map"] = configService.GlobalMapConfigs
return c.RenderTemplate("admin/email/emailDialog.html") return c.RenderTemplate("admin/email/emailDialog.html")
} }
@@ -190,7 +190,7 @@ func (c AdminEmail) SendToUsers(userFilterEmail, userFilterWhiteList, userFilter
if latestEmailSubject == "" || latestEmailBody == "" { if latestEmailSubject == "" || latestEmailBody == "" {
re.Msg = "subject or body is blank" re.Msg = "subject or body is blank"
return c.RenderJson(re) return c.RenderJSON(re)
} }
if saveAsOldEmail { if saveAsOldEmail {
@@ -204,33 +204,33 @@ func (c AdminEmail) SendToUsers(userFilterEmail, userFilterWhiteList, userFilter
if users == nil || len(users) == 0 { if users == nil || len(users) == 0 {
re.Ok = false re.Ok = false
re.Msg = "no users" re.Msg = "no users"
return c.RenderJson(re) return c.RenderJSON(re)
} }
re.Ok, re.Msg = emailService.SendEmailToUsers(users, latestEmailSubject, latestEmailBody) re.Ok, re.Msg = emailService.SendEmailToUsers(users, latestEmailSubject, latestEmailBody)
if !re.Ok { if !re.Ok {
return c.RenderJson(re) return c.RenderJSON(re)
} }
re.Ok = true re.Ok = true
re.Msg = "users:" + strconv.Itoa(len(users)) re.Msg = "users:" + strconv.Itoa(len(users))
return c.RenderJson(re) return c.RenderJSON(re)
} }
// 删除emails // 删除emails
func (c AdminEmail) DeleteEmails(ids string) revel.Result { func (c AdminEmail) DeleteEmails(ids string) revel.Result {
re := info.NewRe() re := info.NewRe()
re.Ok = emailService.DeleteEmails(strings.Split(ids, ",")) re.Ok = emailService.DeleteEmails(strings.Split(ids, ","))
return c.RenderJson(re) return c.RenderJSON(re)
} }
func (c AdminEmail) List(sorter, keywords string) revel.Result { func (c AdminEmail) List(sorter, keywords string) revel.Result {
pageNumber := c.GetPage() pageNumber := c.GetPage()
sorterField, isAsc := c.getSorter("CreatedTime", false, []string{"email", "ok", "subject", "createdTime"}) sorterField, isAsc := c.getSorter("CreatedTime", false, []string{"email", "ok", "subject", "createdTime"})
pageInfo, emails := emailService.ListEmailLogs(pageNumber, userPageSize, sorterField, isAsc, keywords) pageInfo, emails := emailService.ListEmailLogs(pageNumber, userPageSize, sorterField, isAsc, keywords)
c.RenderArgs["pageInfo"] = pageInfo c.ViewArgs["pageInfo"] = pageInfo
c.RenderArgs["emails"] = emails c.ViewArgs["emails"] = emails
c.RenderArgs["keywords"] = keywords c.ViewArgs["keywords"] = keywords
return c.RenderTemplate("admin/email/list.html") return c.RenderTemplate("admin/email/list.html")
} }
+21 -21
View File
@@ -23,8 +23,8 @@ func (c AdminSetting) Email() revel.Result {
func (c AdminSetting) Blog() revel.Result { func (c AdminSetting) Blog() revel.Result {
recommendTags := configService.GetGlobalArrayConfig("recommendTags") recommendTags := configService.GetGlobalArrayConfig("recommendTags")
newTags := configService.GetGlobalArrayConfig("newTags") newTags := configService.GetGlobalArrayConfig("newTags")
c.RenderArgs["recommendTags"] = strings.Join(recommendTags, ",") c.ViewArgs["recommendTags"] = strings.Join(recommendTags, ",")
c.RenderArgs["newTags"] = strings.Join(newTags, ",") c.ViewArgs["newTags"] = strings.Join(newTags, ",")
return c.RenderTemplate("admin/setting/blog.html") return c.RenderTemplate("admin/setting/blog.html")
} }
func (c AdminSetting) DoBlogTag(recommendTags, newTags string) revel.Result { func (c AdminSetting) DoBlogTag(recommendTags, newTags string) revel.Result {
@@ -33,7 +33,7 @@ func (c AdminSetting) DoBlogTag(recommendTags, newTags string) revel.Result {
re.Ok = configService.UpdateGlobalArrayConfig(c.GetUserId(), "recommendTags", strings.Split(recommendTags, ",")) re.Ok = configService.UpdateGlobalArrayConfig(c.GetUserId(), "recommendTags", strings.Split(recommendTags, ","))
re.Ok = configService.UpdateGlobalArrayConfig(c.GetUserId(), "newTags", strings.Split(newTags, ",")) re.Ok = configService.UpdateGlobalArrayConfig(c.GetUserId(), "newTags", strings.Split(newTags, ","))
return c.RenderJson(re) return c.RenderJSON(re)
} }
// 共享设置 // 共享设置
@@ -43,14 +43,14 @@ func (c AdminSetting) ShareNote(registerSharedUserId string,
re := info.NewRe() re := info.NewRe()
re.Ok, re.Msg = configService.UpdateShareNoteConfig(registerSharedUserId, registerSharedNotebookPerms, registerSharedNotePerms, registerSharedNotebookIds, registerSharedNoteIds, registerCopyNoteIds) re.Ok, re.Msg = configService.UpdateShareNoteConfig(registerSharedUserId, registerSharedNotebookPerms, registerSharedNotePerms, registerSharedNotebookIds, registerSharedNoteIds, registerCopyNoteIds)
return c.RenderJson(re) return c.RenderJSON(re)
} }
// demo // demo
// blog标签设置 // blog标签设置
func (c AdminSetting) Demo() revel.Result { func (c AdminSetting) Demo() revel.Result {
c.RenderArgs["demoUsername"] = configService.GetGlobalStringConfig("demoUsername") c.ViewArgs["demoUsername"] = configService.GetGlobalStringConfig("demoUsername")
c.RenderArgs["demoPassword"] = configService.GetGlobalStringConfig("demoPassword") c.ViewArgs["demoPassword"] = configService.GetGlobalStringConfig("demoPassword")
return c.RenderTemplate("admin/setting/demo.html") return c.RenderTemplate("admin/setting/demo.html")
} }
func (c AdminSetting) DoDemo(demoUsername, demoPassword string) revel.Result { func (c AdminSetting) DoDemo(demoUsername, demoPassword string) revel.Result {
@@ -59,40 +59,40 @@ func (c AdminSetting) DoDemo(demoUsername, demoPassword string) revel.Result {
userInfo, err := authService.Login(demoUsername, demoPassword) userInfo, err := authService.Login(demoUsername, demoPassword)
if err != nil { if err != nil {
fmt.Println(err) fmt.Println(err)
return c.RenderJson(info.Re{Ok: false}) return c.RenderJSON(info.Re{Ok: false})
} }
if userInfo.UserId == "" { if userInfo.UserId == "" {
re.Msg = "The User is Not Exists" re.Msg = "The User is Not Exists"
return c.RenderJson(re) return c.RenderJSON(re)
} }
re.Ok = configService.UpdateGlobalStringConfig(c.GetUserId(), "demoUserId", userInfo.UserId.Hex()) re.Ok = configService.UpdateGlobalStringConfig(c.GetUserId(), "demoUserId", userInfo.UserId.Hex())
re.Ok = configService.UpdateGlobalStringConfig(c.GetUserId(), "demoUsername", demoUsername) re.Ok = configService.UpdateGlobalStringConfig(c.GetUserId(), "demoUsername", demoUsername)
re.Ok = configService.UpdateGlobalStringConfig(c.GetUserId(), "demoPassword", demoPassword) re.Ok = configService.UpdateGlobalStringConfig(c.GetUserId(), "demoPassword", demoPassword)
return c.RenderJson(re) return c.RenderJSON(re)
} }
func (c AdminSetting) ExportPdf(path string) revel.Result { func (c AdminSetting) ExportPdf(path string) revel.Result {
re := info.NewRe() re := info.NewRe()
re.Ok = configService.UpdateGlobalStringConfig(c.GetUserId(), "exportPdfBinPath", path) re.Ok = configService.UpdateGlobalStringConfig(c.GetUserId(), "exportPdfBinPath", path)
return c.RenderJson(re) return c.RenderJSON(re)
} }
func (c AdminSetting) DoSiteUrl(siteUrl string) revel.Result { func (c AdminSetting) DoSiteUrl(siteUrl string) revel.Result {
re := info.NewRe() re := info.NewRe()
re.Ok = configService.UpdateGlobalStringConfig(c.GetUserId(), "siteUrl", siteUrl) re.Ok = configService.UpdateGlobalStringConfig(c.GetUserId(), "siteUrl", siteUrl)
return c.RenderJson(re) return c.RenderJSON(re)
} }
// SubDomain // SubDomain
func (c AdminSetting) SubDomain() revel.Result { func (c AdminSetting) SubDomain() revel.Result {
c.RenderArgs["str"] = configService.GlobalStringConfigs c.ViewArgs["str"] = configService.GlobalStringConfigs
c.RenderArgs["arr"] = configService.GlobalArrayConfigs c.ViewArgs["arr"] = configService.GlobalArrayConfigs
c.RenderArgs["noteSubDomain"] = configService.GetGlobalStringConfig("noteSubDomain") c.ViewArgs["noteSubDomain"] = configService.GetGlobalStringConfig("noteSubDomain")
c.RenderArgs["blogSubDomain"] = configService.GetGlobalStringConfig("blogSubDomain") c.ViewArgs["blogSubDomain"] = configService.GetGlobalStringConfig("blogSubDomain")
c.RenderArgs["leaSubDomain"] = configService.GetGlobalStringConfig("leaSubDomain") c.ViewArgs["leaSubDomain"] = configService.GetGlobalStringConfig("leaSubDomain")
return c.RenderTemplate("admin/setting/subDomain.html") return c.RenderTemplate("admin/setting/subDomain.html")
} }
@@ -106,13 +106,13 @@ func (c AdminSetting) DoSubDomain(noteSubDomain, blogSubDomain, leaSubDomain, bl
re.Ok = configService.UpdateGlobalArrayConfig(c.GetUserId(), "blackSubDomains", strings.Split(blackSubDomains, ",")) re.Ok = configService.UpdateGlobalArrayConfig(c.GetUserId(), "blackSubDomains", strings.Split(blackSubDomains, ","))
re.Ok = configService.UpdateGlobalArrayConfig(c.GetUserId(), "blackCustomDomains", strings.Split(blackCustomDomains, ",")) re.Ok = configService.UpdateGlobalArrayConfig(c.GetUserId(), "blackCustomDomains", strings.Split(blackCustomDomains, ","))
return c.RenderJson(re) return c.RenderJSON(re)
} }
func (c AdminSetting) OpenRegister(openRegister string) revel.Result { func (c AdminSetting) OpenRegister(openRegister string) revel.Result {
re := info.NewRe() re := info.NewRe()
re.Ok = configService.UpdateGlobalStringConfig(c.GetUserId(), "openRegister", openRegister) re.Ok = configService.UpdateGlobalStringConfig(c.GetUserId(), "openRegister", openRegister)
return c.RenderJson(re) return c.RenderJSON(re)
} }
func (c AdminSetting) HomePage(homePage string) revel.Result { func (c AdminSetting) HomePage(homePage string) revel.Result {
@@ -121,7 +121,7 @@ func (c AdminSetting) HomePage(homePage string) revel.Result {
homePage = "" homePage = ""
} }
re.Ok = configService.UpdateGlobalStringConfig(c.GetUserId(), "homePage", homePage) re.Ok = configService.UpdateGlobalStringConfig(c.GetUserId(), "homePage", homePage)
return c.RenderJson(re) return c.RenderJSON(re)
} }
func (c AdminSetting) Mongodb(mongodumpPath, mongorestorePath string) revel.Result { func (c AdminSetting) Mongodb(mongodumpPath, mongorestorePath string) revel.Result {
@@ -129,7 +129,7 @@ func (c AdminSetting) Mongodb(mongodumpPath, mongorestorePath string) revel.Resu
re.Ok = configService.UpdateGlobalStringConfig(c.GetUserId(), "mongodumpPath", mongodumpPath) re.Ok = configService.UpdateGlobalStringConfig(c.GetUserId(), "mongodumpPath", mongodumpPath)
re.Ok = configService.UpdateGlobalStringConfig(c.GetUserId(), "mongorestorePath", mongorestorePath) re.Ok = configService.UpdateGlobalStringConfig(c.GetUserId(), "mongorestorePath", mongorestorePath)
return c.RenderJson(re) return c.RenderJSON(re)
} }
func (c AdminSetting) UploadSize(uploadImageSize, uploadAvatarSize, uploadBlogLogoSize, uploadAttachSize float64) revel.Result { func (c AdminSetting) UploadSize(uploadImageSize, uploadAvatarSize, uploadBlogLogoSize, uploadAttachSize float64) revel.Result {
@@ -138,5 +138,5 @@ func (c AdminSetting) UploadSize(uploadImageSize, uploadAvatarSize, uploadBlogLo
re.Ok = configService.UpdateGlobalStringConfig(c.GetUserId(), "uploadAvatarSize", fmt.Sprintf("%v", uploadAvatarSize)) re.Ok = configService.UpdateGlobalStringConfig(c.GetUserId(), "uploadAvatarSize", fmt.Sprintf("%v", uploadAvatarSize))
re.Ok = configService.UpdateGlobalStringConfig(c.GetUserId(), "uploadBlogLogoSize", fmt.Sprintf("%v", uploadBlogLogoSize)) re.Ok = configService.UpdateGlobalStringConfig(c.GetUserId(), "uploadBlogLogoSize", fmt.Sprintf("%v", uploadBlogLogoSize))
re.Ok = configService.UpdateGlobalStringConfig(c.GetUserId(), "uploadAttachSize", fmt.Sprintf("%v", uploadAttachSize)) re.Ok = configService.UpdateGlobalStringConfig(c.GetUserId(), "uploadAttachSize", fmt.Sprintf("%v", uploadAttachSize))
return c.RenderJson(re) return c.RenderJSON(re)
} }
@@ -20,11 +20,11 @@ func (c AdminUpgrade) UpgradeBlog() revel.Result {
func (c AdminUpgrade) UpgradeBetaToBeta2() revel.Result { func (c AdminUpgrade) UpgradeBetaToBeta2() revel.Result {
re := info.NewRe() re := info.NewRe()
re.Ok, re.Msg = upgradeService.UpgradeBetaToBeta2(c.GetUserId()) re.Ok, re.Msg = upgradeService.UpgradeBetaToBeta2(c.GetUserId())
return c.RenderJson(re) return c.RenderJSON(re)
} }
func (c AdminUpgrade) UpgradeBeta3ToBeta4() revel.Result { func (c AdminUpgrade) UpgradeBeta3ToBeta4() revel.Result {
re := info.NewRe() re := info.NewRe()
re.Ok, re.Msg = upgradeService.Api(c.GetUserId()) re.Ok, re.Msg = upgradeService.Api(c.GetUserId())
return c.RenderJson(re) return c.RenderJSON(re)
} }
+5 -5
View File
@@ -18,14 +18,14 @@ var userPageSize = 10
func (c AdminUser) Index(sorter, keywords string, pageSize int) revel.Result { func (c AdminUser) Index(sorter, keywords string, pageSize int) revel.Result {
pageNumber := c.GetPage() pageNumber := c.GetPage()
if userPageSize == 0 { if pageSize == 0 {
pageSize = userPageSize pageSize = userPageSize
} }
sorterField, isAsc := c.getSorter("CreatedTime", false, []string{"email", "username", "verified", "createdTime", "accountType"}) sorterField, isAsc := c.getSorter("CreatedTime", false, []string{"email", "username", "verified", "createdTime", "accountType"})
pageInfo, users := userService.ListUsers(pageNumber, pageSize, sorterField, isAsc, keywords) pageInfo, users := userService.ListUsers(pageNumber, pageSize, sorterField, isAsc, keywords)
c.RenderArgs["pageInfo"] = pageInfo c.ViewArgs["pageInfo"] = pageInfo
c.RenderArgs["users"] = users c.ViewArgs["users"] = users
c.RenderArgs["keywords"] = keywords c.ViewArgs["keywords"] = keywords
return c.RenderTemplate("admin/user/list.html") return c.RenderTemplate("admin/user/list.html")
} }
@@ -53,7 +53,7 @@ func (c AdminUser) Register(email, pwd string) revel.Result {
// 修改帐户 // 修改帐户
func (c AdminUser) ResetPwd(userId string) revel.Result { func (c AdminUser) ResetPwd(userId string) revel.Result {
userInfo := userService.GetUserInfo(userId) userInfo := userService.GetUserInfo(userId)
c.RenderArgs["userInfo"] = userInfo c.ViewArgs["userInfo"] = userInfo
return c.RenderTemplate("admin/user/reset_pwd.html") return c.RenderTemplate("admin/user/reset_pwd.html")
} }
+1 -1
View File
@@ -91,7 +91,7 @@ func AuthInterceptor(c *revel.Controller) revel.Result {
if c.Request.Header.Get("X-Requested-With") == "XMLHttpRequest" { if c.Request.Header.Get("X-Requested-With") == "XMLHttpRequest" {
re := info.NewRe() re := info.NewRe()
re.Msg = "NOTLOGIN" re.Msg = "NOTLOGIN"
return c.RenderJson(re) return c.RenderJSON(re)
} }
return c.Redirect("/login") return c.Redirect("/login")
+7 -7
View File
@@ -28,12 +28,12 @@ func (c ApiAuth) Login(email, pwd string) revel.Result {
if err == nil { if err == nil {
token := bson.NewObjectId().Hex() token := bson.NewObjectId().Hex()
sessionService.SetUserId(token, userInfo.UserId.Hex()) sessionService.SetUserId(token, userInfo.UserId.Hex())
return c.RenderJson(info.AuthOk{Ok: true, Token: token, UserId: userInfo.UserId, Email: userInfo.Email, Username: userInfo.Username}) return c.RenderJSON(info.AuthOk{Ok: true, Token: token, UserId: userInfo.UserId, Email: userInfo.Email, Username: userInfo.Username})
} else { } else {
// 登录错误, 则错误次数++ // 登录错误, 则错误次数++
msg = "wrongUsernameOrPassword" msg = "wrongUsernameOrPassword"
} }
return c.RenderJson(info.ApiRe{Ok: false, Msg: c.Message(msg)}) return c.RenderJSON(info.ApiRe{Ok: false, Msg: c.Message(msg)})
} }
// 注销 // 注销
@@ -43,7 +43,7 @@ func (c ApiAuth) Logout() revel.Result {
sessionService.Clear(token) sessionService.Clear(token)
re := info.NewApiRe() re := info.NewApiRe()
re.Ok = true re.Ok = true
return c.RenderJson(re) return c.RenderJSON(re)
} }
// 注册 // 注册
@@ -53,17 +53,17 @@ func (c ApiAuth) Register(email, pwd string) revel.Result {
re := info.NewApiRe() re := info.NewApiRe()
if !configService.IsOpenRegister() { if !configService.IsOpenRegister() {
re.Msg = "notOpenRegister" // 未开放注册 re.Msg = "notOpenRegister" // 未开放注册
return c.RenderJson(re) return c.RenderJSON(re)
} }
if re.Ok, re.Msg = Vd("email", email); !re.Ok { if re.Ok, re.Msg = Vd("email", email); !re.Ok {
return c.RenderJson(re) return c.RenderJSON(re)
} }
if re.Ok, re.Msg = Vd("password", pwd); !re.Ok { if re.Ok, re.Msg = Vd("password", pwd); !re.Ok {
return c.RenderJson(re) return c.RenderJSON(re)
} }
// 注册 // 注册
re.Ok, re.Msg = authService.Register(email, pwd, "") re.Ok, re.Msg = authService.Register(email, pwd, "")
return c.RenderJson(re) return c.RenderJSON(re)
} }
+34 -20
View File
@@ -53,16 +53,23 @@ func (c ApiBaseContrller) uploadAttach(name string, noteId string) (ok bool, msg
} }
*/ */
file, handel, err := c.Request.FormFile(name) var data []byte
if err != nil { c.Params.Bind(&data, name)
handel := c.Params.Files[name][0]
if data == nil || len(data) == 0 {
return return
} }
defer file.Close()
data, err := ioutil.ReadAll(file) // file, handel, err := c.Request.FormFile(name)
if err != nil { // if err != nil {
return // return
} // }
// defer file.Close()
// data, err := ioutil.ReadAll(file)
// if err != nil {
// return
// }
// > 5M? // > 5M?
maxFileSize := configService.GetUploadSize("uploadAttachSize") maxFileSize := configService.GetUploadSize("uploadAttachSize")
if maxFileSize <= 0 { if maxFileSize <= 0 {
@@ -79,7 +86,7 @@ func (c ApiBaseContrller) uploadAttach(name string, noteId string) (ok bool, msg
filePath := "files/" + GetRandomFilePath(userId, newGuid) + "/attachs" filePath := "files/" + GetRandomFilePath(userId, newGuid) + "/attachs"
dir := revel.BasePath + "/" + filePath dir := revel.BasePath + "/" + filePath
err = os.MkdirAll(dir, 0755) err := os.MkdirAll(dir, 0755)
if err != nil { if err != nil {
return return
} }
@@ -122,11 +129,18 @@ func (c ApiBaseContrller) upload(name string, noteId string, isAttach bool) (ok
if isAttach { if isAttach {
return c.uploadAttach(name, noteId) return c.uploadAttach(name, noteId)
} }
file, handel, err := c.Request.FormFile(name) // file, handel, err := c.Request.FormFile(name)
if err != nil { // if err != nil {
// return
// }
// defer file.Close()
var data []byte
c.Params.Bind(&data, name)
handel := c.Params.Files[name][0]
if data == nil || len(data) == 0 {
return return
} }
defer file.Close()
newGuid := NewGuid() newGuid := NewGuid()
// 生成上传路径 // 生成上传路径
@@ -135,23 +149,23 @@ func (c ApiBaseContrller) upload(name string, noteId string, isAttach bool) (ok
fileUrlPath := "files/" + GetRandomFilePath(userId, newGuid) + "/images" fileUrlPath := "files/" + GetRandomFilePath(userId, newGuid) + "/images"
dir := revel.BasePath + "/" + fileUrlPath dir := revel.BasePath + "/" + fileUrlPath
err = os.MkdirAll(dir, 0755) err := os.MkdirAll(dir, 0755)
if err != nil { if err != nil {
return return
} }
// 生成新的文件名 // 生成新的文件名
filename := handel.Filename filename := handel.Filename
_, ext := SplitFilename(filename) _, ext := SplitFilename(filename)
if ext != ".gif" && ext != ".jpg" && ext != ".png" && ext != ".bmp" && ext != ".jpeg" { // if ext != ".gif" && ext != ".jpg" && ext != ".png" && ext != ".bmp" && ext != ".jpeg" {
msg = "notImage" // msg = "notImage"
return // return
} // }
filename = newGuid + ext filename = newGuid + ext
data, err := ioutil.ReadAll(file) // data, err := ioutil.ReadAll(file)
if err != nil { // if err != nil {
return // return
} // }
maxFileSize := configService.GetUploadSize("uploadImageSize") maxFileSize := configService.GetUploadSize("uploadImageSize")
if maxFileSize <= 0 { if maxFileSize <= 0 {
+4 -4
View File
@@ -30,7 +30,7 @@ func (c ApiFile) CopyImage(userId, fileId, toUserId string) revel.Result {
re.Ok, re.Id = fileService.CopyImage(userId, fileId, toUserId) re.Ok, re.Id = fileService.CopyImage(userId, fileId, toUserId)
return c.RenderJson(re) return c.RenderJSON(re)
} }
// get all images by userId with page // get all images by userId with page
@@ -39,19 +39,19 @@ func (c ApiFile) GetImages(albumId, key string, page int) revel.Result {
re := info.NewRe() re := info.NewRe()
re.Ok = true re.Ok = true
re.Item = imagesPage re.Item = imagesPage
return c.RenderJson(re) return c.RenderJSON(re)
} }
func (c ApiFile) UpdateImageTitle(fileId, title string) revel.Result { func (c ApiFile) UpdateImageTitle(fileId, title string) revel.Result {
re := info.NewRe() re := info.NewRe()
re.Ok = fileService.UpdateImageTitle(c.getUserId(), fileId, title) re.Ok = fileService.UpdateImageTitle(c.getUserId(), fileId, title)
return c.RenderJson(re) return c.RenderJSON(re)
} }
func (c ApiFile) DeleteImage(fileId string) revel.Result { func (c ApiFile) DeleteImage(fileId string) revel.Result {
re := info.NewRe() re := info.NewRe()
re.Ok, re.Msg = fileService.DeleteImage(c.getUserId(), fileId) re.Ok, re.Msg = fileService.DeleteImage(c.getUserId(), fileId)
return c.RenderJson(re) return c.RenderJSON(re)
} }
*/ */
+40 -38
View File
@@ -52,7 +52,7 @@ func (c ApiNote) GetSyncNotes(afterUsn, maxEntry int) revel.Result {
maxEntry = 100 maxEntry = 100
} }
notes := noteService.GetSyncNotes(c.getUserId(), afterUsn, maxEntry) notes := noteService.GetSyncNotes(c.getUserId(), afterUsn, maxEntry)
return c.RenderJson(notes) return c.RenderJSON(notes)
} }
// 得到笔记本下的笔记 // 得到笔记本下的笔记
@@ -61,17 +61,17 @@ func (c ApiNote) GetNotes(notebookId string) revel.Result {
if notebookId != "" && !bson.IsObjectIdHex(notebookId) { if notebookId != "" && !bson.IsObjectIdHex(notebookId) {
re := info.NewApiRe() re := info.NewApiRe()
re.Msg = "notebookIdInvalid" re.Msg = "notebookIdInvalid"
return c.RenderJson(re) return c.RenderJSON(re)
} }
_, notes := noteService.ListNotes(c.getUserId(), notebookId, false, c.GetPage(), pageSize, defaultSortField, false, false) _, notes := noteService.ListNotes(c.getUserId(), notebookId, false, c.GetPage(), pageSize, defaultSortField, false, false)
return c.RenderJson(noteService.ToApiNotes(notes)) return c.RenderJSON(noteService.ToApiNotes(notes))
} }
// 得到trash // 得到trash
// [OK] // [OK]
func (c ApiNote) GetTrashNotes() revel.Result { func (c ApiNote) GetTrashNotes() revel.Result {
_, notes := noteService.ListNotes(c.getUserId(), "", true, c.GetPage(), pageSize, defaultSortField, false, false) _, notes := noteService.ListNotes(c.getUserId(), "", true, c.GetPage(), pageSize, defaultSortField, false, false)
return c.RenderJson(noteService.ToApiNotes(notes)) return c.RenderJSON(noteService.ToApiNotes(notes))
} }
@@ -127,17 +127,17 @@ func (c ApiNote) GetNote(noteId string) revel.Result {
if !bson.IsObjectIdHex(noteId) { if !bson.IsObjectIdHex(noteId) {
re := info.NewApiRe() re := info.NewApiRe()
re.Msg = "noteIdInvalid" re.Msg = "noteIdInvalid"
return c.RenderJson(re) return c.RenderJSON(re)
} }
note := noteService.GetNote(noteId, c.getUserId()) note := noteService.GetNote(noteId, c.getUserId())
if note.NoteId == "" { if note.NoteId == "" {
re := info.NewApiRe() re := info.NewApiRe()
re.Msg = "notExists" re.Msg = "notExists"
return c.RenderJson(re) return c.RenderJSON(re)
} }
apiNotes := noteService.ToApiNotes([]info.Note{note}) apiNotes := noteService.ToApiNotes([]info.Note{note})
return c.RenderJson(apiNotes[0]) return c.RenderJSON(apiNotes[0])
} }
// 得到note和内容 // 得到note和内容
@@ -148,7 +148,7 @@ func (c ApiNote) GetNoteAndContent(noteId string) revel.Result {
apiNotes := noteService.ToApiNotes([]info.Note{noteAndContent.Note}) apiNotes := noteService.ToApiNotes([]info.Note{noteAndContent.Note})
apiNote := apiNotes[0] apiNote := apiNotes[0]
apiNote.Content = noteService.FixContent(noteAndContent.Content, noteAndContent.IsMarkdown) apiNote.Content = noteService.FixContent(noteAndContent.Content, noteAndContent.IsMarkdown)
return c.RenderJson(apiNote) return c.RenderJSON(apiNote)
} }
// content里的image, attach链接是 // content里的image, attach链接是
@@ -166,18 +166,20 @@ func (c ApiNote) fixPostNotecontent(noteOrContent *info.ApiNote) {
if file.LocalFileId != "" { if file.LocalFileId != "" {
LogJ(file) LogJ(file)
if !file.IsAttach { if !file.IsAttach {
reg, _ := regexp.Compile(`"https*://[^/]*?/api/file/getImage\?fileId=`+file.LocalFileId) // <img src="https://"
// ![](http://demo.leanote.top/api/file/getImage?fileId=5863219465b68e4fd5000001)
reg, _ := regexp.Compile(`https*://[^/]*?/api/file/getImage\?fileId=`+file.LocalFileId)
// Log(reg) // Log(reg)
noteOrContent.Content = reg.ReplaceAllString(noteOrContent.Content, `"/api/file/getImage?fileId=`+file.FileId) noteOrContent.Content = reg.ReplaceAllString(noteOrContent.Content, `/api/file/getImage?fileId=`+file.FileId)
// // "http://a.com/api/file/getImage?fileId=localId" => /api/file/getImage?fileId=serverId // // "http://a.com/api/file/getImage?fileId=localId" => /api/file/getImage?fileId=serverId
// noteOrContent.Content = strings.Replace(noteOrContent.Content, // noteOrContent.Content = strings.Replace(noteOrContent.Content,
// baseUrl + "/api/file/getImage?fileId="+file.LocalFileId, // baseUrl + "/api/file/getImage?fileId="+file.LocalFileId,
// "/api/file/getImage?fileId="+file.FileId, -1) // "/api/file/getImage?fileId="+file.FileId, -1)
} else { } else {
reg, _ := regexp.Compile(`"https*://[^/]*?/api/file/getAttach\?fileId=`+file.LocalFileId) reg, _ := regexp.Compile(`https*://[^/]*?/api/file/getAttach\?fileId=`+file.LocalFileId)
Log(reg) // Log(reg)
noteOrContent.Content = reg.ReplaceAllString(noteOrContent.Content, `"/api/file/getAttach?fileId=`+file.FileId) noteOrContent.Content = reg.ReplaceAllString(noteOrContent.Content, `/api/file/getAttach?fileId=`+file.FileId)
/* /*
noteOrContent.Content = strings.Replace(noteOrContent.Content, noteOrContent.Content = strings.Replace(noteOrContent.Content,
baseUrl + "/api/file/getAttach?fileId="+file.LocalFileId, baseUrl + "/api/file/getAttach?fileId="+file.LocalFileId,
@@ -205,7 +207,7 @@ func (c ApiNote) GetNoteContent(noteId string) revel.Result {
Content: noteContent.Content, Content: noteContent.Content,
} }
return c.RenderJson(apiNoteContent) return c.RenderJSON(apiNoteContent)
} }
// 添加笔记 // 添加笔记
@@ -231,10 +233,10 @@ func (c ApiNote) AddNote(noteOrContent info.ApiNote) revel.Result {
LogJ(file) LogJ(file)
} }
*/ */
// return c.RenderJson(re) // return c.RenderJSON(re)
if noteOrContent.NotebookId == "" || !bson.IsObjectIdHex(noteOrContent.NotebookId) { if noteOrContent.NotebookId == "" || !bson.IsObjectIdHex(noteOrContent.NotebookId) {
re.Msg = "notebookIdNotExists" re.Msg = "notebookIdNotExists"
return c.RenderJson(re) return c.RenderJSON(re)
} }
noteId := bson.NewObjectId() noteId := bson.NewObjectId()
@@ -257,7 +259,7 @@ func (c ApiNote) AddNote(noteOrContent info.ApiNote) revel.Result {
} }
// 报不是图片的错误没关系, 证明客户端传来非图片的数据 // 报不是图片的错误没关系, 证明客户端传来非图片的数据
if msg != "notImage" { if msg != "notImage" {
return c.RenderJson(re) return c.RenderJSON(re)
} }
} else { } else {
// 建立映射 // 建立映射
@@ -269,7 +271,7 @@ func (c ApiNote) AddNote(noteOrContent info.ApiNote) revel.Result {
} }
} }
} else { } else {
return c.RenderJson(re) return c.RenderJSON(re)
} }
} }
} }
@@ -280,7 +282,7 @@ func (c ApiNote) AddNote(noteOrContent info.ApiNote) revel.Result {
// Log("Add") // Log("Add")
// LogJ(noteOrContent) // LogJ(noteOrContent)
// return c.RenderJson(re) // return c.RenderJSON(re)
note := info.Note{UserId: userId, note := info.Note{UserId: userId,
NoteId: noteId, NoteId: noteId,
@@ -316,7 +318,7 @@ func (c ApiNote) AddNote(noteOrContent info.ApiNote) revel.Result {
if note.NoteId == "" { if note.NoteId == "" {
re.Ok = false re.Ok = false
return c.RenderJson(re) return c.RenderJSON(re)
} }
// 添加需要返回的 // 添加需要返回的
@@ -330,7 +332,7 @@ func (c ApiNote) AddNote(noteOrContent info.ApiNote) revel.Result {
noteOrContent.Content = "" noteOrContent.Content = ""
noteOrContent.Abstract = "" noteOrContent.Abstract = ""
// apiNote := info.NoteToApiNote(note, noteOrContent.Files) // apiNote := info.NoteToApiNote(note, noteOrContent.Files)
return c.RenderJson(noteOrContent) return c.RenderJSON(noteOrContent)
} }
// 更新笔记 // 更新笔记
@@ -345,12 +347,12 @@ func (c ApiNote) UpdateNote(noteOrContent info.ApiNote) revel.Result {
if noteOrContent.NoteId == "" { if noteOrContent.NoteId == "" {
re.Msg = "noteIdNotExists" re.Msg = "noteIdNotExists"
return c.RenderJson(re) return c.RenderJSON(re)
} }
if noteOrContent.Usn <= 0 { if noteOrContent.Usn <= 0 {
re.Msg = "usnNotExists" re.Msg = "usnNotExists"
return c.RenderJson(re) return c.RenderJSON(re)
} }
// Log("_____________") // Log("_____________")
@@ -366,12 +368,12 @@ func (c ApiNote) UpdateNote(noteOrContent info.ApiNote) revel.Result {
note := noteService.GetNote(noteId, userId) note := noteService.GetNote(noteId, userId)
if note.NoteId == "" { if note.NoteId == "" {
re.Msg = "notExists" re.Msg = "notExists"
return c.RenderJson(re) return c.RenderJSON(re)
} }
if note.Usn != noteOrContent.Usn { if note.Usn != noteOrContent.Usn {
re.Msg = "conflict" re.Msg = "conflict"
Log("conflict") Log("conflict")
return c.RenderJson(re) return c.RenderJSON(re)
} }
Log("没有冲突") Log("没有冲突")
@@ -400,14 +402,14 @@ func (c ApiNote) UpdateNote(noteOrContent info.ApiNote) revel.Result {
} else { } else {
re.Msg = msg re.Msg = msg
} }
return c.RenderJson(re) return c.RenderJSON(re)
} else { } else {
// 建立映射 // 建立映射
file.FileId = fileId file.FileId = fileId
noteOrContent.Files[i] = file noteOrContent.Files[i] = file
} }
} else { } else {
return c.RenderJson(re) return c.RenderJSON(re)
} }
} }
} }
@@ -488,7 +490,7 @@ func (c ApiNote) UpdateNote(noteOrContent info.ApiNote) revel.Result {
if !noteOk { if !noteOk {
re.Ok = false re.Ok = false
re.Msg = noteMsg re.Msg = noteMsg
return c.RenderJson(re) return c.RenderJSON(re)
} }
} }
@@ -526,7 +528,7 @@ func (c ApiNote) UpdateNote(noteOrContent info.ApiNote) revel.Result {
} }
if !re.Ok { if !re.Ok {
return c.RenderJson(re) return c.RenderJSON(re)
} }
noteOrContent.Content = "" noteOrContent.Content = ""
@@ -537,14 +539,14 @@ func (c ApiNote) UpdateNote(noteOrContent info.ApiNote) revel.Result {
// LogJ(noteOrContent.Files) // LogJ(noteOrContent.Files)
noteOrContent.UserId = c.getUserId() noteOrContent.UserId = c.getUserId()
return c.RenderJson(noteOrContent) return c.RenderJSON(noteOrContent)
} }
// 删除trash // 删除trash
func (c ApiNote) DeleteTrash(noteId string, usn int) revel.Result { func (c ApiNote) DeleteTrash(noteId string, usn int) revel.Result {
re := info.NewReUpdate() re := info.NewReUpdate()
re.Ok, re.Msg, re.Usn = trashService.DeleteTrashApi(noteId, c.getUserId(), usn) re.Ok, re.Msg, re.Usn = trashService.DeleteTrashApi(noteId, c.getUserId(), usn)
return c.RenderJson(re) return c.RenderJSON(re)
} }
// 得到历史列表 // 得到历史列表
@@ -556,7 +558,7 @@ func (c ApiNote) GetHistories(noteId string) revel.Result {
re.Ok = true re.Ok = true
re.Item = histories re.Item = histories
} }
return c.RenderJson(re) return c.RenderJSON(re)
} }
*/ */
@@ -567,13 +569,13 @@ func (c ApiNote) ExportPdf(noteId string) revel.Result {
userId := c.getUserId() userId := c.getUserId()
if noteId == "" { if noteId == "" {
re.Msg = "noteNotExists" re.Msg = "noteNotExists"
return c.RenderJson(re) return c.RenderJSON(re)
} }
note := noteService.GetNoteById(noteId) note := noteService.GetNoteById(noteId)
if note.NoteId == "" { if note.NoteId == "" {
re.Msg = "noteNotExists" re.Msg = "noteNotExists"
return c.RenderJson(re) return c.RenderJSON(re)
} }
noteUserId := note.UserId.Hex() noteUserId := note.UserId.Hex()
@@ -582,7 +584,7 @@ func (c ApiNote) ExportPdf(noteId string) revel.Result {
// 是否是有权限协作的 // 是否是有权限协作的
if !note.IsBlog && !shareService.HasReadPerm(noteUserId, userId, noteId) { if !note.IsBlog && !shareService.HasReadPerm(noteUserId, userId, noteId) {
re.Msg = "noteNotExists" re.Msg = "noteNotExists"
return c.RenderJson(re) return c.RenderJSON(re)
} }
} }
@@ -592,7 +594,7 @@ func (c ApiNote) ExportPdf(noteId string) revel.Result {
dir := revel.BasePath + "/" + fileUrlPath dir := revel.BasePath + "/" + fileUrlPath
if !MkdirAll(dir) { if !MkdirAll(dir) {
re.Msg = "noDir" re.Msg = "noDir"
return c.RenderJson(re) return c.RenderJSON(re)
} }
filename := guid + ".pdf" filename := guid + ".pdf"
path := dir + "/" + filename path := dir + "/" + filename
@@ -621,12 +623,12 @@ func (c ApiNote) ExportPdf(noteId string) revel.Result {
_, err := cmd.Output() _, err := cmd.Output()
if err != nil { if err != nil {
re.Msg = "sysError" re.Msg = "sysError"
return c.RenderJson(re) return c.RenderJSON(re)
} }
file, err := os.Open(path) file, err := os.Open(path)
if err != nil { if err != nil {
re.Msg = "sysError" re.Msg = "sysError"
return c.RenderJson(re) return c.RenderJSON(re)
} }
filenameReturn := note.Title filenameReturn := note.Title
+7 -7
View File
@@ -53,7 +53,7 @@ func (c ApiNotebook) GetSyncNotebooks(afterUsn, maxEntry int) revel.Result {
maxEntry = 100 maxEntry = 100
} }
notebooks := notebookService.GeSyncNotebooks(c.getUserId(), afterUsn, maxEntry) notebooks := notebookService.GeSyncNotebooks(c.getUserId(), afterUsn, maxEntry)
return c.RenderJson(c.fixNotebooks(notebooks)) return c.RenderJSON(c.fixNotebooks(notebooks))
} }
// 得到用户的所有笔记本 // 得到用户的所有笔记本
@@ -61,7 +61,7 @@ func (c ApiNotebook) GetSyncNotebooks(afterUsn, maxEntry int) revel.Result {
// info.SubNotebooks // info.SubNotebooks
func (c ApiNotebook) GetNotebooks() revel.Result { func (c ApiNotebook) GetNotebooks() revel.Result {
notebooks := notebookService.GeSyncNotebooks(c.getUserId(), 0, 99999) notebooks := notebookService.GeSyncNotebooks(c.getUserId(), 0, 99999)
return c.RenderJson(c.fixNotebooks(notebooks)) return c.RenderJSON(c.fixNotebooks(notebooks))
} }
// 添加notebook // 添加notebook
@@ -77,9 +77,9 @@ func (c ApiNotebook) AddNotebook(title, parentNotebookId string, seq int) revel.
re := info.NewRe() re := info.NewRe()
re.Ok, notebook = notebookService.AddNotebook(notebook) re.Ok, notebook = notebookService.AddNotebook(notebook)
if !re.Ok { if !re.Ok {
return c.RenderJson(re) return c.RenderJSON(re)
} }
return c.RenderJson(c.fixNotebook(&notebook)) return c.RenderJSON(c.fixNotebook(&notebook))
} }
// 修改笔记 // 修改笔记
@@ -91,10 +91,10 @@ func (c ApiNotebook) UpdateNotebook(notebookId, title, parentNotebookId string,
if !ok { if !ok {
re.Ok = false re.Ok = false
re.Msg = msg re.Msg = msg
return c.RenderJson(re) return c.RenderJSON(re)
} }
LogJ(notebook) LogJ(notebook)
return c.RenderJson(c.fixNotebook(&notebook)) return c.RenderJSON(c.fixNotebook(&notebook))
} }
// 删除笔记本 // 删除笔记本
@@ -102,5 +102,5 @@ func (c ApiNotebook) UpdateNotebook(notebookId, title, parentNotebookId string,
func (c ApiNotebook) DeleteNotebook(notebookId string, usn int) revel.Result { func (c ApiNotebook) DeleteNotebook(notebookId string, usn int) revel.Result {
re := info.NewApiRe() re := info.NewApiRe()
re.Ok, re.Msg = notebookService.DeleteNotebookForce(c.getUserId(), notebookId, usn) re.Ok, re.Msg = notebookService.DeleteNotebookForce(c.getUserId(), notebookId, usn)
return c.RenderJson(re) return c.RenderJSON(re)
} }
+3 -3
View File
@@ -23,7 +23,7 @@ func (c ApiTag) GetSyncTags(afterUsn, maxEntry int) revel.Result {
maxEntry = 100 maxEntry = 100
} }
tags := tagService.GeSyncTags(c.getUserId(), afterUsn, maxEntry) tags := tagService.GeSyncTags(c.getUserId(), afterUsn, maxEntry)
return c.RenderJson(tags) return c.RenderJSON(tags)
} }
// 添加Tag // 添加Tag
@@ -44,7 +44,7 @@ func (c ApiTag) GetSyncTags(afterUsn, maxEntry int) revel.Result {
*/ */
func (c ApiTag) AddTag(tag string) revel.Result { func (c ApiTag) AddTag(tag string) revel.Result {
ret := tagService.AddOrUpdateTag(c.getUserId(), tag) ret := tagService.AddOrUpdateTag(c.getUserId(), tag)
return c.RenderJson(ret) return c.RenderJSON(ret)
} }
// 删除标签 // 删除标签
@@ -52,5 +52,5 @@ func (c ApiTag) AddTag(tag string) revel.Result {
func (c ApiTag) DeleteTag(tag string, usn int) revel.Result { func (c ApiTag) DeleteTag(tag string, usn int) revel.Result {
re := info.NewReUpdate() re := info.NewReUpdate()
re.Ok, re.Msg, re.Usn = tagService.DeleteTagApi(c.getUserId(), tag, usn) re.Ok, re.Msg, re.Usn = tagService.DeleteTagApi(c.getUserId(), tag, usn)
return c.RenderJson(re) return c.RenderJSON(re)
} }
+28 -21
View File
@@ -28,7 +28,7 @@ func (c ApiUser) Info() revel.Result {
userInfo := c.getUserInfo() userInfo := c.getUserInfo()
if userInfo.UserId == "" { if userInfo.UserId == "" {
return c.RenderJson(re) return c.RenderJSON(re)
} }
apiUser := info.ApiUser{ apiUser := info.ApiUser{
UserId: userInfo.UserId.Hex(), UserId: userInfo.UserId.Hex(),
@@ -37,7 +37,7 @@ func (c ApiUser) Info() revel.Result {
Logo: userInfo.Logo, Logo: userInfo.Logo,
Verified: userInfo.Verified, Verified: userInfo.Verified,
} }
return c.RenderJson(apiUser) return c.RenderJSON(apiUser)
} }
// 修改用户名 // 修改用户名
@@ -46,15 +46,15 @@ func (c ApiUser) UpdateUsername(username string) revel.Result {
re := info.NewApiRe() re := info.NewApiRe()
if c.GetUsername() == "demo" { if c.GetUsername() == "demo" {
re.Msg = "cannotUpdateDemo" re.Msg = "cannotUpdateDemo"
return c.RenderJson(re) return c.RenderJSON(re)
} }
if re.Ok, re.Msg = Vd("username", username); !re.Ok { if re.Ok, re.Msg = Vd("username", username); !re.Ok {
return c.RenderJson(re) return c.RenderJSON(re)
} }
re.Ok, re.Msg = userService.UpdateUsername(c.getUserId(), username) re.Ok, re.Msg = userService.UpdateUsername(c.getUserId(), username)
return c.RenderJson(re) return c.RenderJSON(re)
} }
// 修改密码 // 修改密码
@@ -63,23 +63,23 @@ func (c ApiUser) UpdatePwd(oldPwd, pwd string) revel.Result {
re := info.NewApiRe() re := info.NewApiRe()
if c.GetUsername() == "demo" { if c.GetUsername() == "demo" {
re.Msg = "cannotUpdateDemo" re.Msg = "cannotUpdateDemo"
return c.RenderJson(re) return c.RenderJSON(re)
} }
if re.Ok, re.Msg = Vd("password", oldPwd); !re.Ok { if re.Ok, re.Msg = Vd("password", oldPwd); !re.Ok {
return c.RenderJson(re) return c.RenderJSON(re)
} }
if re.Ok, re.Msg = Vd("password", pwd); !re.Ok { if re.Ok, re.Msg = Vd("password", pwd); !re.Ok {
return c.RenderJson(re) return c.RenderJSON(re)
} }
re.Ok, re.Msg = userService.UpdatePwd(c.getUserId(), oldPwd, pwd) re.Ok, re.Msg = userService.UpdatePwd(c.getUserId(), oldPwd, pwd)
return c.RenderJson(re) return c.RenderJSON(re)
} }
// 获得同步状态 // 获得同步状态
// [OK] // [OK]
func (c ApiUser) GetSyncState() revel.Result { func (c ApiUser) GetSyncState() revel.Result {
ret := bson.M{"LastSyncUsn": userService.GetUsn(c.getUserId()), "LastSyncTime": time.Now().Unix()} ret := bson.M{"LastSyncUsn": userService.GetUsn(c.getUserId()), "LastSyncTime": time.Now().Unix()}
return c.RenderJson(ret) return c.RenderJSON(ret)
} }
// 头像设置 // 头像设置
@@ -91,11 +91,11 @@ func (c ApiUser) UpdateLogo() revel.Result {
if ok { if ok {
ok = userService.UpdateAvatar(c.getUserId(), url) ok = userService.UpdateAvatar(c.getUserId(), url)
return c.RenderJson(map[string]string{"Logo": url}) return c.RenderJSON(map[string]string{"Logo": url})
} else { } else {
re := info.NewApiRe() re := info.NewApiRe()
re.Msg = msg re.Msg = msg
return c.RenderJson(re) return c.RenderJSON(re)
} }
} }
@@ -104,16 +104,23 @@ func (c ApiUser) uploadImage() (ok bool, msg, url string) {
var fileUrlPath = "" var fileUrlPath = ""
ok = false ok = false
file, handel, err := c.Request.FormFile("file") var data []byte
if err != nil { c.Params.Bind(&data, "file")
handel := c.Params.Files["file"][0]
if data == nil || len(data) == 0 {
return return
} }
defer file.Close()
// file, handel, err := c.Request.FormFile("file")
// if err != nil {
// return
// }
// defer file.Close()
// 生成上传路径 // 生成上传路径
fileUrlPath = "public/upload/" + c.getUserId() + "/images/logo" fileUrlPath = "public/upload/" + c.getUserId() + "/images/logo"
dir := revel.BasePath + "/" + fileUrlPath dir := revel.BasePath + "/" + fileUrlPath
err = os.MkdirAll(dir, 0755) err := os.MkdirAll(dir, 0755)
if err != nil { if err != nil {
return return
} }
@@ -129,11 +136,11 @@ func (c ApiUser) uploadImage() (ok bool, msg, url string) {
} }
filename = NewGuid() + ext filename = NewGuid() + ext
data, err := ioutil.ReadAll(file) // data, err := ioutil.ReadAll(file)
if err != nil { // if err != nil {
LogJ(err) // LogJ(err)
return // return
} // }
// > 5M? // > 5M?
if len(data) > 5*1024*1024 { if len(data) > 5*1024*1024 {
+2 -2
View File
@@ -75,7 +75,7 @@ func AuthInterceptor(c *revel.Controller) revel.Result {
noToken := false noToken := false
if token == "" { if token == "" {
// 若无, 则取sessionId // 若无, 则取sessionId
token = c.Session.Id() token = c.Session.ID()
noToken = true noToken = true
} }
c.Session["_token"] = token c.Session["_token"] = token
@@ -106,7 +106,7 @@ func AuthInterceptor(c *revel.Controller) revel.Result {
// 没有登录, 返回错误的信息, 需要登录 // 没有登录, 返回错误的信息, 需要登录
re := info.NewApiRe() re := info.NewApiRe()
re.Msg = "NOTLOGIN" re.Msg = "NOTLOGIN"
return c.RenderJson(re) return c.RenderJSON(re)
} }
func init() { func init() {
+1 -1
View File
@@ -103,7 +103,7 @@ func AuthInterceptor(c *revel.Controller) revel.Result {
if c.Request.Header.Get("X-Requested-With") == "XMLHttpRequest" { if c.Request.Header.Get("X-Requested-With") == "XMLHttpRequest" {
re := info.NewRe() re := info.NewRe()
re.Msg = "NOTLOGIN" re.Msg = "NOTLOGIN"
return c.RenderJson(re) return c.RenderJSON(re)
} }
return c.Redirect("/login") return c.Redirect("/login")
@@ -46,7 +46,7 @@ func (c MemberBaseController) getSorter(sorterField string, isAsc bool, okSorter
} else { } else {
isAsc = false isAsc = false
} }
c.RenderArgs["sorter"] = sorter c.ViewArgs["sorter"] = sorter
return sorterField, isAsc return sorterField, isAsc
} }
+92 -78
View File
@@ -21,13 +21,13 @@ type MemberBlog struct {
func (c MemberBlog) common() info.UserBlog { func (c MemberBlog) common() info.UserBlog {
userId := c.GetUserId() userId := c.GetUserId()
userInfo := userService.GetUserInfo(userId) userInfo := userService.GetUserInfo(userId)
c.RenderArgs["userInfo"] = userInfo c.ViewArgs["userInfo"] = userInfo
// 得到博客设置信息 // 得到博客设置信息
c.RenderArgs["allowCustomDomain"] = configService.GetGlobalStringConfig("allowCustomDomain") c.ViewArgs["allowCustomDomain"] = configService.GetGlobalStringConfig("allowCustomDomain")
userBlog := blogService.GetUserBlog(userId) userBlog := blogService.GetUserBlog(userId)
c.RenderArgs["userBlog"] = userBlog c.ViewArgs["userBlog"] = userBlog
c.SetUserInfo() c.SetUserInfo()
c.SetLocale() c.SetLocale()
@@ -62,7 +62,7 @@ func (c MemberBlog) getSorter(sorterField string, isAsc bool, okSorter []string)
} else { } else {
isAsc = false isAsc = false
} }
c.RenderArgs["sorter"] = sorter c.ViewArgs["sorter"] = sorter
return sorterField, isAsc return sorterField, isAsc
} }
@@ -72,18 +72,18 @@ var userPageSize = 15
func (c MemberBlog) Index(sorter, keywords string) revel.Result { func (c MemberBlog) Index(sorter, keywords string) revel.Result {
userId := c.GetUserId() userId := c.GetUserId()
userInfo := userService.GetUserInfo(userId) userInfo := userService.GetUserInfo(userId)
c.RenderArgs["userInfo"] = userInfo c.ViewArgs["userInfo"] = userInfo
c.RenderArgs["title"] = c.Message("Posts") c.ViewArgs["title"] = c.Message("Posts")
pageNumber := c.GetPage() pageNumber := c.GetPage()
sorterField, isAsc := c.getSorter("CreatedTime", false, []string{"title", "urlTitle", "updatedTime", "publicTime", "createdTime"}) sorterField, isAsc := c.getSorter("CreatedTime", false, []string{"title", "urlTitle", "updatedTime", "publicTime", "createdTime"})
pageInfo, blogs := blogService.ListAllBlogs(c.GetUserId(), "", keywords, false, pageNumber, userPageSize, sorterField, isAsc) pageInfo, blogs := blogService.ListAllBlogs(c.GetUserId(), "", keywords, false, pageNumber, userPageSize, sorterField, isAsc)
c.RenderArgs["pageInfo"] = pageInfo c.ViewArgs["pageInfo"] = pageInfo
c.RenderArgs["blogs"] = blogs c.ViewArgs["blogs"] = blogs
c.RenderArgs["keywords"] = keywords c.ViewArgs["keywords"] = keywords
userAndBlog := userService.GetUserAndBlog(c.GetUserId()) userAndBlog := userService.GetUserAndBlog(c.GetUserId())
c.RenderArgs["userAndBlog"] = userAndBlog c.ViewArgs["userAndBlog"] = userAndBlog
c.common() c.common()
@@ -94,48 +94,48 @@ func (c MemberBlog) Index(sorter, keywords string) revel.Result {
func (c MemberBlog) UpdateBlogUrlTitle(noteId, urlTitle string) revel.Result { func (c MemberBlog) UpdateBlogUrlTitle(noteId, urlTitle string) revel.Result {
re := info.NewRe() re := info.NewRe()
re.Ok, re.Item = blogService.UpateBlogUrlTitle(c.GetUserId(), noteId, urlTitle) re.Ok, re.Item = blogService.UpateBlogUrlTitle(c.GetUserId(), noteId, urlTitle)
return c.RenderJson(re) return c.RenderJSON(re)
} }
// 修改笔记的urlTitle // 修改笔记的urlTitle
func (c MemberBlog) UpdateBlogAbstract(noteId string) revel.Result { func (c MemberBlog) UpdateBlogAbstract(noteId string) revel.Result {
c.common() c.common()
c.RenderArgs["title"] = c.Message("Update Post Abstract") c.ViewArgs["title"] = c.Message("Update Post Abstract")
note := noteService.GetNoteAndContent(noteId, c.GetUserId()) note := noteService.GetNoteAndContent(noteId, c.GetUserId())
if !note.Note.IsBlog { if !note.Note.IsBlog {
return c.E404() return c.E404()
} }
c.RenderArgs["note"] = note c.ViewArgs["note"] = note
c.RenderArgs["noteId"] = noteId c.ViewArgs["noteId"] = noteId
return c.RenderTemplate("member/blog/update_abstract.html") return c.RenderTemplate("member/blog/update_abstract.html")
} }
func (c MemberBlog) DoUpdateBlogAbstract(noteId, imgSrc, desc, abstract string) revel.Result { func (c MemberBlog) DoUpdateBlogAbstract(noteId, imgSrc, desc, abstract string) revel.Result {
re := info.NewRe() re := info.NewRe()
re.Ok = blogService.UpateBlogAbstract(c.GetUserId(), noteId, imgSrc, desc, abstract) re.Ok = blogService.UpateBlogAbstract(c.GetUserId(), noteId, imgSrc, desc, abstract)
return c.RenderJson(re) return c.RenderJSON(re)
} }
// 基本信息设置 // 基本信息设置
func (c MemberBlog) Base() revel.Result { func (c MemberBlog) Base() revel.Result {
c.common() c.common()
c.RenderArgs["title"] = c.Message("Blog Base Info") c.ViewArgs["title"] = c.Message("Blog Base Info")
return c.RenderTemplate("member/blog/base.html") return c.RenderTemplate("member/blog/base.html")
} }
func (c MemberBlog) Comment() revel.Result { func (c MemberBlog) Comment() revel.Result {
c.common() c.common()
c.RenderArgs["title"] = c.Message("Comment") c.ViewArgs["title"] = c.Message("Comment")
return c.RenderTemplate("member/blog/comment.html") return c.RenderTemplate("member/blog/comment.html")
} }
func (c MemberBlog) Paging() revel.Result { func (c MemberBlog) Paging() revel.Result {
c.common() c.common()
c.RenderArgs["title"] = c.Message("Paging") c.ViewArgs["title"] = c.Message("Paging")
return c.RenderTemplate("member/blog/paging.html") return c.RenderTemplate("member/blog/paging.html")
} }
func (c MemberBlog) Cate() revel.Result { func (c MemberBlog) Cate() revel.Result {
userBlog := c.common() userBlog := c.common()
c.RenderArgs["title"] = c.Message("Category") c.ViewArgs["title"] = c.Message("Category")
notebooks := blogService.ListBlogNotebooks(c.GetUserId()) notebooks := blogService.ListBlogNotebooks(c.GetUserId())
notebooksMap := map[string]info.Notebook{} notebooksMap := map[string]info.Notebook{}
@@ -166,7 +166,7 @@ func (c MemberBlog) Cate() revel.Result {
i++ i++
} }
} }
c.RenderArgs["notebooks"] = notebooks2 c.ViewArgs["notebooks"] = notebooks2
return c.RenderTemplate("member/blog/cate.html") return c.RenderTemplate("member/blog/cate.html")
} }
@@ -175,54 +175,54 @@ func (c MemberBlog) Cate() revel.Result {
func (c MemberBlog) UpateCateIds(cateIds []string) revel.Result { func (c MemberBlog) UpateCateIds(cateIds []string) revel.Result {
re := info.NewRe() re := info.NewRe()
re.Ok = blogService.UpateCateIds(c.GetUserId(), cateIds) re.Ok = blogService.UpateCateIds(c.GetUserId(), cateIds)
return c.RenderJson(re) return c.RenderJSON(re)
} }
func (c MemberBlog) UpdateCateUrlTitle(cateId, urlTitle string) revel.Result { func (c MemberBlog) UpdateCateUrlTitle(cateId, urlTitle string) revel.Result {
re := info.NewRe() re := info.NewRe()
re.Ok, re.Item = blogService.UpateCateUrlTitle(c.GetUserId(), cateId, urlTitle) re.Ok, re.Item = blogService.UpateCateUrlTitle(c.GetUserId(), cateId, urlTitle)
return c.RenderJson(re) return c.RenderJSON(re)
} }
// 保存之, 包含增加与保存 // 保存之, 包含增加与保存
func (c MemberBlog) DoAddOrUpdateSingle(singleId, title, content string) revel.Result { func (c MemberBlog) DoAddOrUpdateSingle(singleId, title, content string) revel.Result {
re := info.NewRe() re := info.NewRe()
re.Ok = blogService.AddOrUpdateSingle(c.GetUserId(), singleId, title, content) re.Ok = blogService.AddOrUpdateSingle(c.GetUserId(), singleId, title, content)
return c.RenderJson(re) return c.RenderJSON(re)
} }
func (c MemberBlog) AddOrUpdateSingle(singleId string) revel.Result { func (c MemberBlog) AddOrUpdateSingle(singleId string) revel.Result {
c.common() c.common()
c.RenderArgs["title"] = c.Message("Add Single") c.ViewArgs["title"] = c.Message("Add Single")
c.RenderArgs["singleId"] = singleId c.ViewArgs["singleId"] = singleId
if singleId != "" { if singleId != "" {
c.RenderArgs["title"] = c.Message("Update Single") c.ViewArgs["title"] = c.Message("Update Single")
c.RenderArgs["single"] = blogService.GetSingle(singleId) c.ViewArgs["single"] = blogService.GetSingle(singleId)
} }
return c.RenderTemplate("member/blog/add_single.html") return c.RenderTemplate("member/blog/add_single.html")
} }
func (c MemberBlog) SortSingles(singleIds []string) revel.Result { func (c MemberBlog) SortSingles(singleIds []string) revel.Result {
re := info.NewRe() re := info.NewRe()
re.Ok = blogService.SortSingles(c.GetUserId(), singleIds) re.Ok = blogService.SortSingles(c.GetUserId(), singleIds)
return c.RenderJson(re) return c.RenderJSON(re)
} }
func (c MemberBlog) DeleteSingle(singleId string) revel.Result { func (c MemberBlog) DeleteSingle(singleId string) revel.Result {
re := info.NewRe() re := info.NewRe()
re.Ok = blogService.DeleteSingle(c.GetUserId(), singleId) re.Ok = blogService.DeleteSingle(c.GetUserId(), singleId)
return c.RenderJson(re) return c.RenderJSON(re)
} }
// 修改页面标题 // 修改页面标题
func (c MemberBlog) UpdateSingleUrlTitle(singleId, urlTitle string) revel.Result { func (c MemberBlog) UpdateSingleUrlTitle(singleId, urlTitle string) revel.Result {
re := info.NewRe() re := info.NewRe()
re.Ok, re.Item = blogService.UpdateSingleUrlTitle(c.GetUserId(), singleId, urlTitle) re.Ok, re.Item = blogService.UpdateSingleUrlTitle(c.GetUserId(), singleId, urlTitle)
return c.RenderJson(re) return c.RenderJSON(re)
} }
func (c MemberBlog) Single() revel.Result { func (c MemberBlog) Single() revel.Result {
c.common() c.common()
c.RenderArgs["title"] = c.Message("Single") c.ViewArgs["title"] = c.Message("Single")
c.RenderArgs["singles"] = blogService.GetSingles(c.GetUserId()) c.ViewArgs["singles"] = blogService.GetSingles(c.GetUserId())
return c.RenderTemplate("member/blog/single.html") return c.RenderTemplate("member/blog/single.html")
} }
@@ -231,12 +231,12 @@ func (c MemberBlog) Single() revel.Result {
func (c MemberBlog) Theme() revel.Result { func (c MemberBlog) Theme() revel.Result {
c.common() c.common()
activeTheme, otherThemes := themeService.GetUserThemes(c.GetUserId()) activeTheme, otherThemes := themeService.GetUserThemes(c.GetUserId())
c.RenderArgs["activeTheme"] = activeTheme c.ViewArgs["activeTheme"] = activeTheme
c.RenderArgs["otherThemes"] = otherThemes c.ViewArgs["otherThemes"] = otherThemes
c.RenderArgs["optionThemes"] = themeService.GetDefaultThemes() c.ViewArgs["optionThemes"] = themeService.GetDefaultThemes()
c.RenderArgs["title"] = c.Message("Theme") c.ViewArgs["title"] = c.Message("Theme")
return c.RenderTemplate("member/blog/theme.html") return c.RenderTemplate("member/blog/theme.html")
} }
@@ -253,11 +253,11 @@ func (c MemberBlog) UpdateTheme(themeId string, isNew int) revel.Result {
} }
c.common() c.common()
c.RenderArgs["title"] = c.Message("Update Theme") c.ViewArgs["title"] = c.Message("Update Theme")
c.RenderArgs["isNew"] = isNew c.ViewArgs["isNew"] = isNew
// 先复制之 // 先复制之
c.RenderArgs["themeId"] = themeId c.ViewArgs["themeId"] = themeId
// 得到脚本目录 // 得到脚本目录
userId := c.GetUserId() userId := c.GetUserId()
@@ -266,7 +266,7 @@ func (c MemberBlog) UpdateTheme(themeId string, isNew int) revel.Result {
if theme.ThemeId == "" { if theme.ThemeId == "" {
return c.E404() return c.E404()
} }
c.RenderArgs["theme"] = theme c.ViewArgs["theme"] = theme
path := revel.BasePath + "/" + theme.Path path := revel.BasePath + "/" + theme.Path
@@ -287,7 +287,7 @@ func (c MemberBlog) UpdateTheme(themeId string, isNew int) revel.Result {
} }
} }
c.RenderArgs["myTpls"] = myTpls c.ViewArgs["myTpls"] = myTpls
return c.RenderTemplate("member/blog/update_theme.html") return c.RenderTemplate("member/blog/update_theme.html")
} }
@@ -298,7 +298,7 @@ func (c MemberBlog) GetTplContent(themeId string, filename string) revel.Result
re.Ok = true re.Ok = true
re.Item = themeService.GetTplContent(c.GetUserId(), themeId, filename) re.Item = themeService.GetTplContent(c.GetUserId(), themeId, filename)
return c.RenderJson(re) return c.RenderJSON(re)
} }
func (c MemberBlog) UpdateTplContent(themeId, filename, content string) revel.Result { func (c MemberBlog) UpdateTplContent(themeId, filename, content string) revel.Result {
re := info.NewRe() re := info.NewRe()
@@ -309,7 +309,7 @@ func (c MemberBlog) UpdateTplContent(themeId, filename, content string) revel.Re
func (c MemberBlog) DeleteTpl(themeId, filename string) revel.Result { func (c MemberBlog) DeleteTpl(themeId, filename string) revel.Result {
re := info.NewRe() re := info.NewRe()
re.Ok = themeService.DeleteTpl(c.GetUserId(), themeId, filename) re.Ok = themeService.DeleteTpl(c.GetUserId(), themeId, filename)
return c.RenderJson(re) return c.RenderJSON(re)
} }
func (c MemberBlog) ListThemeImages(themeId string) revel.Result { func (c MemberBlog) ListThemeImages(themeId string) revel.Result {
@@ -320,22 +320,22 @@ func (c MemberBlog) ListThemeImages(themeId string) revel.Result {
images := ListDir(path) images := ListDir(path)
re.List = images re.List = images
re.Ok = true re.Ok = true
return c.RenderJson(re) return c.RenderJSON(re)
} }
func (c MemberBlog) DeleteThemeImage(themeId, filename string) revel.Result { func (c MemberBlog) DeleteThemeImage(themeId, filename string) revel.Result {
re := info.NewRe() re := info.NewRe()
path := themeService.GetThemeAbsolutePath(c.GetUserId(), themeId) + "/images/" + filename path := themeService.GetThemeAbsolutePath(c.GetUserId(), themeId) + "/images/" + filename
re.Ok = DeleteFile(path) re.Ok = DeleteFile(path)
return c.RenderJson(re) return c.RenderJSON(re)
} }
// 上传主题图片 // 上传主题图片
func (c MemberBlog) UploadThemeImage(themeId string) revel.Result { func (c MemberBlog) UploadThemeImage(themeId string) revel.Result {
re := c.uploadImage(themeId) re := c.uploadImage(themeId)
c.RenderArgs["fileUrlPath"] = re.Id c.ViewArgs["fileUrlPath"] = re.Id
c.RenderArgs["resultCode"] = re.Code c.ViewArgs["resultCode"] = re.Code
c.RenderArgs["resultMsg"] = re.Msg c.ViewArgs["resultMsg"] = re.Msg
return c.RenderTemplate("file/blog_logo.html") return c.RenderTemplate("file/blog_logo.html")
} }
func (c MemberBlog) uploadImage(themeId string) (re info.Re) { func (c MemberBlog) uploadImage(themeId string) (re info.Re) {
@@ -351,14 +351,21 @@ func (c MemberBlog) uploadImage(themeId string) (re info.Re) {
re.Ok = Ok re.Ok = Ok
}() }()
file, handel, err := c.Request.FormFile("file") var data []byte
if err != nil { c.Params.Bind(&data, "file")
handel := c.Params.Files["file"][0]
if data == nil || len(data) == 0 {
return re return re
} }
defer file.Close()
// file, handel, err := c.Request.FormFile("file")
// if err != nil {
// return re
// }
// defer file.Close()
// 生成上传路径 // 生成上传路径
dir := themeService.GetThemeAbsolutePath(c.GetUserId(), themeId) + "/images" dir := themeService.GetThemeAbsolutePath(c.GetUserId(), themeId) + "/images"
err = os.MkdirAll(dir, 0755) err := os.MkdirAll(dir, 0755)
if err != nil { if err != nil {
return re return re
} }
@@ -374,11 +381,11 @@ func (c MemberBlog) uploadImage(themeId string) (re info.Re) {
} }
filename = filename filename = filename
data, err := ioutil.ReadAll(file) // data, err := ioutil.ReadAll(file)
if err != nil { // if err != nil {
LogJ(err) // LogJ(err)
return re // return re
} // }
// > 2M? // > 2M?
if len(data) > 5*1024*1024 { if len(data) > 5*1024*1024 {
@@ -405,21 +412,21 @@ func (c MemberBlog) uploadImage(themeId string) (re info.Re) {
func (c MemberBlog) ActiveTheme(themeId string) revel.Result { func (c MemberBlog) ActiveTheme(themeId string) revel.Result {
re := info.NewRe() re := info.NewRe()
re.Ok = themeService.ActiveTheme(c.GetUserId(), themeId) re.Ok = themeService.ActiveTheme(c.GetUserId(), themeId)
return c.RenderJson(re) return c.RenderJSON(re)
} }
// 删除主题 // 删除主题
func (c MemberBlog) DeleteTheme(themeId string) revel.Result { func (c MemberBlog) DeleteTheme(themeId string) revel.Result {
re := info.NewRe() re := info.NewRe()
re.Ok = themeService.DeleteTheme(c.GetUserId(), themeId) re.Ok = themeService.DeleteTheme(c.GetUserId(), themeId)
return c.RenderJson(re) return c.RenderJSON(re)
} }
// 管理员公开主题 // 管理员公开主题
func (c MemberBlog) PublicTheme(themeId string) revel.Result { func (c MemberBlog) PublicTheme(themeId string) revel.Result {
re := info.NewRe() re := info.NewRe()
re.Ok = themeService.PublicTheme(c.GetUserId(), themeId) re.Ok = themeService.PublicTheme(c.GetUserId(), themeId)
return c.RenderJson(re) return c.RenderJSON(re)
} }
// 导出 // 导出
@@ -441,20 +448,27 @@ func (c MemberBlog) ExportTheme(themeId string) revel.Result {
func (c MemberBlog) ImportTheme() revel.Result { func (c MemberBlog) ImportTheme() revel.Result {
re := info.NewRe() re := info.NewRe()
file, handel, err := c.Request.FormFile("file") var data []byte
if err != nil { c.Params.Bind(&data, "file")
re.Msg = fmt.Sprintf("%v", err) handel := c.Params.Files["file"][0]
return c.RenderJson(re) if data == nil || len(data) == 0 {
return c.RenderJSON(re)
} }
defer file.Close() // file, handel, err := c.Request.FormFile("file")
// if err != nil {
// re.Msg = fmt.Sprintf("%v", err)
// return c.RenderJSON(re)
// }
// defer file.Close()
// 生成上传路径 // 生成上传路径
userId := c.GetUserId() userId := c.GetUserId()
dir := revel.BasePath + "/public/upload/" + userId + "/tmp" dir := revel.BasePath + "/public/upload/" + userId + "/tmp"
err = os.MkdirAll(dir, 0755) err := os.MkdirAll(dir, 0755)
if err != nil { if err != nil {
re.Msg = fmt.Sprintf("%v", err) re.Msg = fmt.Sprintf("%v", err)
return c.RenderJson(re) return c.RenderJSON(re)
} }
// 生成新的文件名 // 生成新的文件名
filename := handel.Filename filename := handel.Filename
@@ -463,26 +477,26 @@ func (c MemberBlog) ImportTheme() revel.Result {
_, ext = SplitFilename(filename) _, ext = SplitFilename(filename)
if ext != ".zip" { if ext != ".zip" {
re.Msg = "Please upload zip file" re.Msg = "Please upload zip file"
return c.RenderJson(re) return c.RenderJSON(re)
} }
filename = filename filename = filename
data, err := ioutil.ReadAll(file) // data, err := ioutil.ReadAll(file)
if err != nil { // if err != nil {
return c.RenderJson(re) // return c.RenderJSON(re)
} // }
// > 10M? // > 10M?
if len(data) > 10*1024*1024 { if len(data) > 10*1024*1024 {
re.Msg = "File is big than 10M" re.Msg = "File is big than 10M"
return c.RenderJson(re) return c.RenderJSON(re)
} }
toPath := dir + "/" + filename toPath := dir + "/" + filename
err = ioutil.WriteFile(toPath, data, 0777) err = ioutil.WriteFile(toPath, data, 0777)
if err != nil { if err != nil {
re.Msg = fmt.Sprintf("%v", err) re.Msg = fmt.Sprintf("%v", err)
return c.RenderJson(re) return c.RenderJSON(re)
} }
// 上传好后, 增加之 // 上传好后, 增加之
@@ -494,7 +508,7 @@ func (c MemberBlog) ImportTheme() revel.Result {
func (c MemberBlog) InstallTheme(themeId string) revel.Result { func (c MemberBlog) InstallTheme(themeId string) revel.Result {
re := info.NewRe() re := info.NewRe()
re.Ok = themeService.InstallTheme(c.GetUserId(), themeId) re.Ok = themeService.InstallTheme(c.GetUserId(), themeId)
return c.RenderJson(re) return c.RenderJSON(re)
} }
// 新建主题 // 新建主题
@@ -508,17 +522,17 @@ func (c MemberBlog) NewTheme() revel.Result {
func (c MemberBlog) SetUserBlogBase(userBlog info.UserBlogBase) revel.Result { func (c MemberBlog) SetUserBlogBase(userBlog info.UserBlogBase) revel.Result {
re := info.NewRe() re := info.NewRe()
re.Ok = blogService.UpdateUserBlogBase(c.GetUserId(), userBlog) re.Ok = blogService.UpdateUserBlogBase(c.GetUserId(), userBlog)
return c.RenderJson(re) return c.RenderJSON(re)
} }
func (c MemberBlog) SetUserBlogComment(userBlog info.UserBlogComment) revel.Result { func (c MemberBlog) SetUserBlogComment(userBlog info.UserBlogComment) revel.Result {
re := info.NewRe() re := info.NewRe()
re.Ok = blogService.UpdateUserBlogComment(c.GetUserId(), userBlog) re.Ok = blogService.UpdateUserBlogComment(c.GetUserId(), userBlog)
return c.RenderJson(re) return c.RenderJSON(re)
} }
func (c MemberBlog) SetUserBlogStyle(userBlog info.UserBlogStyle) revel.Result { func (c MemberBlog) SetUserBlogStyle(userBlog info.UserBlogStyle) revel.Result {
re := info.NewRe() re := info.NewRe()
re.Ok = blogService.UpdateUserBlogStyle(c.GetUserId(), userBlog) re.Ok = blogService.UpdateUserBlogStyle(c.GetUserId(), userBlog)
return c.RenderJson(re) return c.RenderJSON(re)
} }
func (c MemberBlog) SetUserBlogPaging(perPageSize int, sortField string, isAsc bool) revel.Result { func (c MemberBlog) SetUserBlogPaging(perPageSize int, sortField string, isAsc bool) revel.Result {
@@ -14,8 +14,8 @@ type MemberGroup struct {
func (c MemberGroup) Index() revel.Result { func (c MemberGroup) Index() revel.Result {
c.SetUserInfo() c.SetUserInfo()
c.SetLocale() c.SetLocale()
c.RenderArgs["title"] = c.Message("My Group") c.ViewArgs["title"] = c.Message("My Group")
c.RenderArgs["groups"] = groupService.GetGroupsAndUsers(c.GetUserId()) c.ViewArgs["groups"] = groupService.GetGroupsAndUsers(c.GetUserId())
return c.RenderTemplate("member/group/index.html") return c.RenderTemplate("member/group/index.html")
} }
@@ -23,13 +23,13 @@ func (c MemberGroup) Index() revel.Result {
func (c MemberGroup) AddGroup(title string) revel.Result { func (c MemberGroup) AddGroup(title string) revel.Result {
re := info.NewRe() re := info.NewRe()
re.Ok, re.Item = groupService.AddGroup(c.GetUserId(), title) re.Ok, re.Item = groupService.AddGroup(c.GetUserId(), title)
return c.RenderJson(re) return c.RenderJSON(re)
} }
func (c MemberGroup) UpdateGroupTitle(groupId, title string) revel.Result { func (c MemberGroup) UpdateGroupTitle(groupId, title string) revel.Result {
re := info.NewRe() re := info.NewRe()
re.Ok = groupService.UpdateGroupTitle(c.GetUserId(), groupId, title) re.Ok = groupService.UpdateGroupTitle(c.GetUserId(), groupId, title)
return c.RenderJson(re) return c.RenderJSON(re)
} }
func (c MemberGroup) DeleteGroup(groupId string) revel.Result { func (c MemberGroup) DeleteGroup(groupId string) revel.Result {
@@ -13,10 +13,10 @@ type MemberIndex struct {
// admin 主页 // admin 主页
func (c MemberIndex) Index() revel.Result { func (c MemberIndex) Index() revel.Result {
c.SetUserInfo() c.SetUserInfo()
c.RenderArgs["title"] = c.Message("Leanote Member Center") c.ViewArgs["title"] = c.Message("Leanote Member Center")
c.RenderArgs["countNote"] = noteService.CountNote(c.GetUserId()) c.ViewArgs["countNote"] = noteService.CountNote(c.GetUserId())
c.RenderArgs["countBlog"] = noteService.CountBlog(c.GetUserId()) c.ViewArgs["countBlog"] = noteService.CountBlog(c.GetUserId())
c.SetLocale() c.SetLocale()
@@ -25,10 +25,10 @@ func (c MemberIndex) Index() revel.Result {
// 模板 // 模板
func (c MemberIndex) T(t string) revel.Result { func (c MemberIndex) T(t string) revel.Result {
c.RenderArgs["str"] = configService.GlobalStringConfigs c.ViewArgs["str"] = configService.GlobalStringConfigs
c.RenderArgs["arr"] = configService.GlobalArrayConfigs c.ViewArgs["arr"] = configService.GlobalArrayConfigs
c.RenderArgs["map"] = configService.GlobalMapConfigs c.ViewArgs["map"] = configService.GlobalMapConfigs
c.RenderArgs["arrMap"] = configService.GlobalArrMapConfigs c.ViewArgs["arrMap"] = configService.GlobalArrMapConfigs
return c.RenderTemplate("admin/" + t + ".html") return c.RenderTemplate("admin/" + t + ".html")
} }
@@ -13,28 +13,28 @@ type MemberUser struct {
func (c MemberUser) Username() revel.Result { func (c MemberUser) Username() revel.Result {
c.SetUserInfo() c.SetUserInfo()
c.SetLocale() c.SetLocale()
c.RenderArgs["title"] = c.Message("Username") c.ViewArgs["title"] = c.Message("Username")
return c.RenderTemplate("member/user/username.html") return c.RenderTemplate("member/user/username.html")
} }
func (c MemberUser) Email() revel.Result { func (c MemberUser) Email() revel.Result {
c.SetUserInfo() c.SetUserInfo()
c.SetLocale() c.SetLocale()
c.RenderArgs["title"] = c.Message("Email") c.ViewArgs["title"] = c.Message("Email")
return c.RenderTemplate("member/user/email.html") return c.RenderTemplate("member/user/email.html")
} }
func (c MemberUser) Password() revel.Result { func (c MemberUser) Password() revel.Result {
c.SetUserInfo() c.SetUserInfo()
c.SetLocale() c.SetLocale()
c.RenderArgs["title"] = c.Message("Password") c.ViewArgs["title"] = c.Message("Password")
return c.RenderTemplate("member/user/password.html") return c.RenderTemplate("member/user/password.html")
} }
func (c MemberUser) Avatar() revel.Result { func (c MemberUser) Avatar() revel.Result {
c.SetUserInfo() c.SetUserInfo()
c.SetLocale() c.SetLocale()
c.RenderArgs["title"] = c.Message("Avatar") c.ViewArgs["title"] = c.Message("Avatar")
c.RenderArgs["globalConfigs"] = configService.GetGlobalConfigForUser() c.ViewArgs["globalConfigs"] = configService.GetGlobalConfigForUser()
return c.RenderTemplate("member/user/avatar.html") return c.RenderTemplate("member/user/avatar.html")
} }
+1 -1
View File
@@ -93,7 +93,7 @@ func AuthInterceptor(c *revel.Controller) revel.Result {
if c.Request.Header.Get("X-Requested-With") == "XMLHttpRequest" { if c.Request.Header.Get("X-Requested-With") == "XMLHttpRequest" {
re := info.NewRe() re := info.NewRe()
re.Msg = "NOTLOGIN" re.Msg = "NOTLOGIN"
return c.RenderJson(re) return c.RenderJSON(re)
} }
return c.Redirect("/login") return c.Redirect("/login")
+9
View File
@@ -15,6 +15,8 @@ type Note struct {
Title string `Title` // 标题 Title string `Title` // 标题
Desc string `Desc` // 描述, 非html Desc string `Desc` // 描述, 非html
Src string `Src,omitempty` // 来源, 2016/4/22
ImgSrc string `ImgSrc` // 图片, 第一张缩略图地址 ImgSrc string `ImgSrc` // 图片, 第一张缩略图地址
Tags []string `Tags,omitempty` Tags []string `Tags,omitempty`
@@ -92,6 +94,7 @@ type NoteOrContent struct {
UserId string UserId string
Title string Title string
Desc string Desc string
Src string
ImgSrc string ImgSrc string
Tags string Tags string
Content string Content string
@@ -101,3 +104,9 @@ type NoteOrContent struct {
FromUserId string // 为共享而新建 FromUserId string // 为共享而新建
IsBlog bool // 是否是blog, 更新note不需要修改, 添加note时才有可能用到, 此时需要判断notebook是否设为Blog IsBlog bool // 是否是blog, 更新note不需要修改, 添加note时才有可能用到, 此时需要判断notebook是否设为Blog
} }
// 分开的
type NoteAndContentSep struct {
NoteInfo Note
NoteContentInfo NoteContent
}
+7 -7
View File
@@ -129,7 +129,7 @@ func init() {
if tags == nil || len(tags) == 0 { if tags == nil || len(tags) == 0 {
return "" return ""
} }
locale, _ := renderArgs[revel.CurrentLocaleRenderArg].(string) locale, _ := renderArgs[revel.CurrentLocaleViewArg].(string)
tagStr := "" tagStr := ""
lenTags := len(tags) lenTags := len(tags)
@@ -148,7 +148,7 @@ func init() {
} }
classes += " label-post" classes += " label-post"
var url = tagPostUrl + "/" + url.QueryEscape(tag) var url = tagPostUrl + "/" + tag
tagStr += "<a class=\"" + classes + "\" href=\"" + url + "\">" + str + "</a>" tagStr += "<a class=\"" + classes + "\" href=\"" + url + "\">" + str + "</a>"
if i != lenTags-1 { if i != lenTags-1 {
tagStr += " " tagStr += " "
@@ -183,7 +183,7 @@ func init() {
} }
revel.TemplateFuncs["msg"] = func(renderArgs map[string]interface{}, message string, args ...interface{}) template.HTML { revel.TemplateFuncs["msg"] = func(renderArgs map[string]interface{}, message string, args ...interface{}) template.HTML {
str, ok := renderArgs[revel.CurrentLocaleRenderArg].(string) str, ok := renderArgs[revel.CurrentLocaleViewArg].(string)
if !ok { if !ok {
return "" return ""
} }
@@ -192,7 +192,7 @@ func init() {
// 不用revel的msg // 不用revel的msg
revel.TemplateFuncs["leaMsg"] = func(renderArgs map[string]interface{}, key string) template.HTML { revel.TemplateFuncs["leaMsg"] = func(renderArgs map[string]interface{}, key string) template.HTML {
locale, _ := renderArgs[revel.CurrentLocaleRenderArg].(string) locale, _ := renderArgs[revel.CurrentLocaleViewArg].(string)
str := i18n.Message(locale, key) str := i18n.Message(locale, key)
if strings.HasPrefix(str, "???") { if strings.HasPrefix(str, "???") {
str = key str = key
@@ -205,7 +205,7 @@ func init() {
if tags == nil || len(tags) == 0 { if tags == nil || len(tags) == 0 {
return "" return ""
} }
locale, _ := renderArgs[revel.CurrentLocaleRenderArg].(string) locale, _ := renderArgs[revel.CurrentLocaleViewArg].(string)
tagStr := "" tagStr := ""
lenTags := len(tags) lenTags := len(tags)
@@ -230,7 +230,7 @@ func init() {
classes += " label-default" classes += " label-default"
} }
classes += " label-post" classes += " label-post"
var url = tagPostUrl + url.QueryEscape(tag) var url = tagPostUrl + tag
tagStr += "<a class=\"" + classes + "\" href=\"" + url + "\">" + str + "</a>" tagStr += "<a class=\"" + classes + "\" href=\"" + url + "\">" + str + "</a>"
if i != lenTags-1 { if i != lenTags-1 {
tagStr += " " tagStr += " "
@@ -307,7 +307,7 @@ func init() {
// http://stackoverflow.com/questions/14226416/go-lang-templates-always-quotes-a-string-and-removes-comments // http://stackoverflow.com/questions/14226416/go-lang-templates-always-quotes-a-string-and-removes-comments
revel.TemplateFuncs["rawMsg"] = func(renderArgs map[string]interface{}, message string, args ...interface{}) template.JS { revel.TemplateFuncs["rawMsg"] = func(renderArgs map[string]interface{}, message string, args ...interface{}) template.JS {
str, ok := renderArgs[revel.CurrentLocaleRenderArg].(string) str, ok := renderArgs[revel.CurrentLocaleViewArg].(string)
if !ok { if !ok {
return "" return ""
} }
+7 -7
View File
@@ -6,21 +6,21 @@ import (
"github.com/revel/revel" "github.com/revel/revel"
) )
func Log(i ...interface{}) { func Log(msg string, i ...interface{}) {
revel.INFO.Println(i...) revel.AppLog.Info(msg, i...)
} }
func LogW(i ...interface{}) { func Logf(msg string, i ...interface{}) {
revel.WARN.Println(i...) revel.AppLog.Infof(msg, i...)
} }
func Log1(key, i interface{}) { func LogW(msg string, i ...interface{}) {
revel.INFO.Println(key, i) revel.AppLog.Warn(msg, i...)
} }
func LogJ(i interface{}) { func LogJ(i interface{}) {
b, _ := json.MarshalIndent(i, "", " ") b, _ := json.MarshalIndent(i, "", " ")
revel.INFO.Println(string(b)) revel.AppLog.Info(string(b))
} }
// 为test用 // 为test用
-1
View File
@@ -79,7 +79,6 @@ func SendEmailOld(to, subject, body string) bool {
err := smtp.SendMail(host+":"+port, auth, username, send_to, msg) err := smtp.SendMail(host+":"+port, auth, username, send_to, msg)
if err != nil { if err != nil {
Log(err)
return false return false
} }
return true return true
-1
View File
@@ -183,7 +183,6 @@ func PutFileStrContent(path, content string) bool {
// Log(path) // Log(path)
if err1 != nil { if err1 != nil {
Log(err1)
return false return false
} }
return true return true
-3
View File
@@ -400,9 +400,6 @@ func FixFilename(filename string) string {
func IsValidTime(t time.Time) bool { func IsValidTime(t time.Time) bool {
if t.Year() > 20 { if t.Year() > 20 {
now := time.Now() now := time.Now()
Log("------")
Log(t)
Log(now)
if t.Before(now) { if t.Before(now) {
return true return true
} }
+13 -13
View File
@@ -39,7 +39,7 @@ var CloneTemplate *template.Template
type RenderTemplateResult struct { type RenderTemplateResult struct {
Template *template.Template Template *template.Template
PathContent map[string]string PathContent map[string]string
RenderArgs map[string]interface{} ViewArgs map[string]interface{}
IsPreview bool // 是否是预览 IsPreview bool // 是否是预览
CurBlogTpl *BlogTpl CurBlogTpl *BlogTpl
@@ -62,7 +62,7 @@ func parseTemplateError(err error) (templateName string, line int, description s
return templateName, line, description return templateName, line, description
} }
func (r *RenderTemplateResult) render(req *revel.Request, resp *revel.Response, wr io.Writer) { func (r *RenderTemplateResult) render(req *revel.Request, resp *revel.Response, wr io.Writer) {
err := r.Template.Execute(wr, r.RenderArgs) err := r.Template.Execute(wr, r.ViewArgs)
if err == nil { if err == nil {
return return
} }
@@ -91,7 +91,7 @@ func (r *RenderTemplateResult) render(req *revel.Request, resp *revel.Response,
// 这里, 错误!! // 这里, 错误!!
// 这里应该导向到本主题的错误页面 // 这里应该导向到本主题的错误页面
resp.Status = 500 resp.Status = 500
ErrorResult{r.RenderArgs, compileError, r.IsPreview, r.CurBlogTpl}.Apply(req, resp) ErrorResult{r.ViewArgs, compileError, r.IsPreview, r.CurBlogTpl}.Apply(req, resp)
} }
func (r *RenderTemplateResult) Apply(req *revel.Request, resp *revel.Response) { func (r *RenderTemplateResult) Apply(req *revel.Request, resp *revel.Response) {
@@ -104,7 +104,7 @@ func (r *RenderTemplateResult) Apply(req *revel.Request, resp *revel.Response) {
chunked := revel.Config.BoolDefault("results.chunked", false) chunked := revel.Config.BoolDefault("results.chunked", false)
// If it's a HEAD request, throw away the bytes. // If it's a HEAD request, throw away the bytes.
out := io.Writer(resp.Out) out := io.Writer(resp.GetWriter())
if req.Method == "HEAD" { if req.Method == "HEAD" {
out = ioutil.Discard out = ioutil.Discard
} }
@@ -162,7 +162,7 @@ func RenderTemplate(name string, args map[string]interface{}, basePath string, i
r = &RenderTemplateResult{ r = &RenderTemplateResult{
Template: t, Template: t,
PathContent: BlogTplObject.PathContent, // 为了显示错误 PathContent: BlogTplObject.PathContent, // 为了显示错误
RenderArgs: args, // 把args给它 ViewArgs: args, // 把args给它
} }
} else { } else {
// 复制一份 // 复制一份
@@ -202,7 +202,7 @@ func RenderTemplate(name string, args map[string]interface{}, basePath string, i
r = &RenderTemplateResult{ r = &RenderTemplateResult{
Template: t, Template: t,
PathContent: newBlogTplObject.PathContent, // 为了显示错误 PathContent: newBlogTplObject.PathContent, // 为了显示错误
RenderArgs: args, ViewArgs: args,
CurBlogTpl: newBlogTplObject, CurBlogTpl: newBlogTplObject,
IsPreview: isPreview, IsPreview: isPreview,
} }
@@ -215,7 +215,7 @@ func RenderTemplate(name string, args map[string]interface{}, basePath string, i
// //
type ErrorResult struct { type ErrorResult struct {
RenderArgs map[string]interface{} ViewArgs map[string]interface{}
Error error Error error
IsPreview bool IsPreview bool
CurBlogTpl *BlogTpl CurBlogTpl *BlogTpl
@@ -280,18 +280,18 @@ func (r ErrorResult) Apply(req *revel.Request, resp *revel.Response) {
panic("no error provided") panic("no error provided")
} }
if r.RenderArgs == nil { if r.ViewArgs == nil {
r.RenderArgs = make(map[string]interface{}) r.ViewArgs = make(map[string]interface{})
} }
r.RenderArgs["Error"] = revelError r.ViewArgs["Error"] = revelError
r.RenderArgs["Router"] = revel.MainRouter r.ViewArgs["Router"] = revel.MainRouter
// 不是preview就不要显示错误了 // 不是preview就不要显示错误了
if r.IsPreview { if r.IsPreview {
var b bytes.Buffer var b bytes.Buffer
out := io.Writer(resp.Out) out := io.Writer(resp.GetWriter())
// out = ioutil.Discard // out = ioutil.Discard
err = tmpl.Execute(&b, r.RenderArgs) err = tmpl.Execute(&b, r.ViewArgs)
resp.WriteHeader(http.StatusOK, "text/html; charset=utf-8") resp.WriteHeader(http.StatusOK, "text/html; charset=utf-8")
b.WriteTo(out) b.WriteTo(out)
} }
+12 -11
View File
@@ -8,10 +8,11 @@ import (
"path/filepath" "path/filepath"
"regexp" "regexp"
"strings" "strings"
. "github.com/leanote/leanote/app/lea"
) )
const ( const (
CurrentLocaleRenderArg = "currentLocale" // The key for the current locale render arg value CurrentLocaleViewArg = "currentLocale" // The key for the current locale render arg value
messageFilesDirectory = "messages" messageFilesDirectory = "messages"
messageFilePattern = `^\w+\.conf$` messageFilePattern = `^\w+\.conf$`
@@ -146,15 +147,15 @@ func loadMessageFile(locale string, path string, info os.FileInfo, osError error
// If we have already parsed a message file for this locale, merge both // If we have already parsed a message file for this locale, merge both
if _, exists := messages[locale]; exists { if _, exists := messages[locale]; exists {
messages[locale].Merge(config) messages[locale].Merge(config)
revel.TRACE.Printf("Successfully merged messages for locale '%s'", locale) Logf("Successfully merged messages for locale '%s'", locale)
} else { } else {
messages[locale] = config messages[locale] = config
} }
revel.TRACE.Println("Successfully loaded messages from file", info.Name()) Logf("Successfully loaded messages from file", info.Name())
} }
} else { } else {
revel.TRACE.Printf("Ignoring file %s because it did not have a valid extension", info.Name()) Logf("Ignoring file %s because it did not have a valid extension", info.Name())
} }
return nil return nil
@@ -178,13 +179,13 @@ func init() {
func I18nFilter(c *revel.Controller, fc []revel.Filter) { func I18nFilter(c *revel.Controller, fc []revel.Filter) {
if foundCookie, cookieValue := hasLocaleCookie(c.Request); foundCookie { if foundCookie, cookieValue := hasLocaleCookie(c.Request); foundCookie {
revel.TRACE.Printf("Found locale cookie value: %s", cookieValue) // revel.TRACE.Printf("Found locale cookie value: %s", cookieValue)
setCurrentLocaleControllerArguments(c, cookieValue) setCurrentLocaleControllerArguments(c, cookieValue)
} else if foundHeader, headerValue := hasAcceptLanguageHeader(c.Request); foundHeader { } else if foundHeader, headerValue := hasAcceptLanguageHeader(c.Request); foundHeader {
revel.TRACE.Printf("Found Accept-Language header value: %s", headerValue) // revel.TRACE.Printf("Found Accept-Language header value: %s", headerValue)
setCurrentLocaleControllerArguments(c, headerValue) setCurrentLocaleControllerArguments(c, headerValue)
} else { } else {
revel.TRACE.Println("Unable to find locale in cookie or header, using empty string") // revel.TRACE.Println("Unable to find locale in cookie or header, using empty string")
setCurrentLocaleControllerArguments(c, "") setCurrentLocaleControllerArguments(c, "")
} }
fc[0](c, fc[1:]) fc[0](c, fc[1:])
@@ -193,7 +194,7 @@ func I18nFilter(c *revel.Controller, fc []revel.Filter) {
// Set the current locale controller argument (CurrentLocaleControllerArg) with the given locale. // Set the current locale controller argument (CurrentLocaleControllerArg) with the given locale.
func setCurrentLocaleControllerArguments(c *revel.Controller, locale string) { func setCurrentLocaleControllerArguments(c *revel.Controller, locale string) {
c.Request.Locale = locale c.Request.Locale = locale
c.RenderArgs[CurrentLocaleRenderArg] = locale c.ViewArgs[CurrentLocaleViewArg] = locale
} }
// Determine whether the given request has valid Accept-Language value. // Determine whether the given request has valid Accept-Language value.
@@ -210,12 +211,12 @@ func hasAcceptLanguageHeader(request *revel.Request) (bool, string) {
// Determine whether the given request has a valid language cookie value. // Determine whether the given request has a valid language cookie value.
func hasLocaleCookie(request *revel.Request) (bool, string) { func hasLocaleCookie(request *revel.Request) (bool, string) {
if request != nil && request.Cookies() != nil { if request != nil {
name := revel.Config.StringDefault(localeCookieConfigKey, revel.CookiePrefix+"_LANG") name := revel.Config.StringDefault(localeCookieConfigKey, revel.CookiePrefix+"_LANG")
if cookie, error := request.Cookie(name); error == nil { if cookie, error := request.Cookie(name); error == nil {
return true, cookie.Value return true, cookie.GetValue()
} else { } else {
revel.TRACE.Printf("Unable to read locale cookie with name '%s': %s", name, error.Error()) // revel.TRACE.Printf("Unable to read locale cookie with name '%s': %s", name, error.Error())
} }
} }
-2
View File
@@ -53,7 +53,6 @@ func WriteUrl(url string, toPath string) (length int64, newFilename, path string
func GetContent(url string) (content []byte, err error) { func GetContent(url string) (content []byte, err error) {
var resp *http.Response var resp *http.Response
resp, err = http.Get(url) resp, err = http.Get(url)
Log(err)
if resp != nil && resp.Body != nil { if resp != nil && resp.Body != nil {
defer resp.Body.Close() defer resp.Body.Close()
} else { } else {
@@ -65,7 +64,6 @@ func GetContent(url string) (content []byte, err error) {
var buf []byte var buf []byte
buf, err = ioutil.ReadAll(resp.Body) buf, err = ioutil.ReadAll(resp.Body)
if err != nil { if err != nil {
Log(err)
return return
} }
+20 -7
View File
@@ -14,15 +14,19 @@ var staticPrefix = []string{"/public", "/favicon.ico", "/css", "/js", "/images",
func RouterFilter(c *revel.Controller, fc []revel.Filter) { func RouterFilter(c *revel.Controller, fc []revel.Filter) {
// 补全controller部分 // 补全controller部分
path := c.Request.Request.URL.Path path := c.Request.URL.Path
// Figure out the Controller/Action // Figure out the Controller/Action
var route *revel.RouteMatch = revel.MainRouter.Route(c.Request.Request) // var route *revel.RouteMatch = revel.MainRouter.Route(c.Request.Request)
route := revel.MainRouter.Route(c.Request)
if route == nil { if route == nil {
c.Result = c.NotFound("No matching route found: " + c.Request.RequestURI) c.Result = c.NotFound("No matching route found: " + c.Request.GetRequestURI())
return return
} }
// Log("---------" + route.Action + " " + path)
// The route may want to explicitly return a 404. // The route may want to explicitly return a 404.
if route.Action == "404" { if route.Action == "404" {
c.Result = c.NotFound("(intentionally)") c.Result = c.NotFound("(intentionally)")
@@ -47,14 +51,23 @@ func RouterFilter(c *revel.Controller, fc []revel.Filter) {
// 检查mongodb 是否lost // 检查mongodb 是否lost
db.CheckMongoSessionLost() db.CheckMongoSessionLost()
// /api/file/getImage -> App\file (/api/file/getImage)
// App\auth
// App\note
// static\static
//
// Log("---------" + route.ControllerName + " " + path)
// api设置 // api设置
// leanote.com/api/user/get => ApiUser::Get // leanote.com/api/user/get => ApiUser::Get
//* /api/login ApiAuth.Login, 这里的设置, 其实已经转成了ApiAuth了 //* /api/login ApiAuth.Login, 这里的设置, 其实已经转成了ApiAuth了
if strings.HasPrefix(path, "/api") && !strings.HasPrefix(route.ControllerName, "Api") { if strings.HasPrefix(path, "/api") && !strings.HasPrefix(route.ControllerName, "App\\api") {
route.ControllerName = "Api" + route.ControllerName route.ControllerName = "App\\api" + strings.Split(route.ControllerName, "\\")[1]
} else if strings.HasPrefix(path, "/member") && !strings.HasPrefix(route.ControllerName, "Member") { // route.ControllerName = "App\\apifile"
} else if strings.HasPrefix(path, "/member") && !strings.HasPrefix(route.ControllerName, "App\\member") {
// member设置 // member设置
route.ControllerName = "Member" + route.ControllerName // route.ControllerName = "App\\Member" + route.ControllerName
route.ControllerName = "App\\member" + strings.Split(route.ControllerName, "\\")[1]
} }
// end // end
} }
+3 -4
View File
@@ -673,19 +673,18 @@ func (this *BlogService) LikeBlog(noteId, userId string) (ok bool, isLike bool)
noteIdO := bson.ObjectIdHex(noteId) noteIdO := bson.ObjectIdHex(noteId)
userIdO := bson.ObjectIdHex(userId) userIdO := bson.ObjectIdHex(userId)
var n int
if !db.Has(db.BlogLikes, bson.M{"NoteId": noteIdO, "UserId": userIdO}) { if !db.Has(db.BlogLikes, bson.M{"NoteId": noteIdO, "UserId": userIdO}) {
n = 1
// 添加之 // 添加之
db.Insert(db.BlogLikes, info.BlogLike{LikeId: bson.NewObjectId(), NoteId: noteIdO, UserId: userIdO, CreatedTime: time.Now()}) db.Insert(db.BlogLikes, info.BlogLike{LikeId: bson.NewObjectId(), NoteId: noteIdO, UserId: userIdO, CreatedTime: time.Now()})
isLike = true isLike = true
} else { } else {
// 已点过, 那么删除之 // 已点过, 那么删除之
n = -1
db.Delete(db.BlogLikes, bson.M{"NoteId": noteIdO, "UserId": userIdO}) db.Delete(db.BlogLikes, bson.M{"NoteId": noteIdO, "UserId": userIdO})
isLike = false isLike = false
} }
ok = db.Update(db.Notes, bson.M{"_id": noteIdO}, bson.M{"$inc": bson.M{"LikeNum": n}})
count := db.Count(db.BlogLikes, bson.M{"NoteId": noteIdO})
ok = db.UpdateByQI(db.Notes, bson.M{"_id": noteIdO}, bson.M{"LikeNum": count})
return return
} }
+1 -1
View File
@@ -606,5 +606,5 @@ func (this *ConfigService) HomePageIsAdminsBlog() bool {
} }
func (this *ConfigService) GetVersion() string { func (this *ConfigService) GetVersion() string {
return "2.2" return "2.6"
} }
+37 -2
View File
@@ -62,6 +62,35 @@ func (this *NoteService) GetNoteAndContent(noteId, userId string) (noteAndConten
return info.NoteAndContent{note, noteContent} return info.NoteAndContent{note, noteContent}
} }
func (this *NoteService) GetNoteBySrc(src, userId string) (note info.Note) {
note = info.Note{}
if src == "" {
return
}
notes := []info.Note{}
q := db.Notes.Find(bson.M{
"UserId": bson.ObjectIdHex(userId),
"Src": src,
})
q.Sort("-Usn").Limit(1).All(&notes)
if len(notes) > 0 {
return notes[0]
}
// db.GetByQ(db.Notes, bson.M{"Src": src, "UserId": bson.ObjectIdHex(userId), "IsDeleted": false}, &note)
return
}
func (this *NoteService) GetNoteAndContentBySrc(src, userId string) (noteId string, noteAndContent info.NoteAndContentSep) {
note := this.GetNoteBySrc(src, userId)
if (note.NoteId != "") {
noteId = note.NoteId.Hex()
noteContent := this.GetNoteContent(note.NoteId.Hex(), userId)
return noteId, info.NoteAndContentSep{note, noteContent}
}
return
}
// 获取同步的笔记 // 获取同步的笔记
// > afterUsn的笔记 // > afterUsn的笔记
func (this *NoteService) GetSyncNotes(userId string, afterUsn, maxEntry int) []info.ApiNote { func (this *NoteService) GetSyncNotes(userId string, afterUsn, maxEntry int) []info.ApiNote {
@@ -863,7 +892,13 @@ func (this *NoteService) searchNoteFromContent(notes []info.Note, userId, key st
notes2 := this.ListNotesByNoteIds(noteIds2) notes2 := this.ListNotesByNoteIds(noteIds2)
// 合并之 // 合并之
notes = append(notes, notes2...) // 不能是删除的
for _, n := range notes2 {
if !n.IsDeleted && !n.IsTrash {
// notes = append(notes, notes2...)
notes = append(notes, n)
}
}
return notes return notes
} }
@@ -1071,7 +1106,7 @@ func (this *NoteService) FixContent(content string, isMarkdown bool) string {
reg2, _ = regexp.Compile("<a(?:[^>]+?)(" + eachPattern["src"] + `=['"]*` + baseUrlPattern + eachPattern["middle"] + `\?` + eachPattern["param"] + `=([a-z0-9A-Z]{24})["']*)[^>]*>`) reg2, _ = regexp.Compile("<a(?:[^>]+?)(" + eachPattern["src"] + `=['"]*` + baseUrlPattern + eachPattern["middle"] + `\?` + eachPattern["param"] + `=([a-z0-9A-Z]{24})["']*)[^>]*>`)
} }
Log(reg2) // Log(reg2)
content = reg.ReplaceAllStringFunc(content, func(str string) string { content = reg.ReplaceAllStringFunc(content, func(str string) string {
// str=这样的 // str=这样的
+2 -2
View File
@@ -360,8 +360,8 @@ func (this *NotebookService) DragNotebooks(userId string, curNotebookId string,
func (this *NotebookService) ReCountNotebookNumberNotes(notebookId string) bool { func (this *NotebookService) ReCountNotebookNumberNotes(notebookId string) bool {
notebookIdO := bson.ObjectIdHex(notebookId) notebookIdO := bson.ObjectIdHex(notebookId)
count := db.Count(db.Notes, bson.M{"NotebookId": notebookIdO, "IsTrash": false, "IsDeleted": false}) count := db.Count(db.Notes, bson.M{"NotebookId": notebookIdO, "IsTrash": false, "IsDeleted": false})
Log(count) // Log(count)
Log(notebookId) // Log(notebookId)
return db.UpdateByQField(db.Notebooks, bson.M{"_id": notebookIdO}, "NumberNotes", count) return db.UpdateByQField(db.Notebooks, bson.M{"_id": notebookIdO}, "NumberNotes", count)
} }
+4 -4
View File
@@ -3,7 +3,7 @@ package service
import ( import (
"github.com/leanote/leanote/app/db" "github.com/leanote/leanote/app/db"
"github.com/leanote/leanote/app/info" "github.com/leanote/leanote/app/info"
. "github.com/leanote/leanote/app/lea" // . "github.com/leanote/leanote/app/lea"
"gopkg.in/mgo.v2/bson" "gopkg.in/mgo.v2/bson"
"time" "time"
// "strings" // "strings"
@@ -66,10 +66,10 @@ func (this *SessionService) GetCaptcha(sessionId string) string {
} }
func (this *SessionService) SetCaptcha(sessionId, captcha string) bool { func (this *SessionService) SetCaptcha(sessionId, captcha string) bool {
this.Get(sessionId) this.Get(sessionId)
Log(sessionId) // Log(sessionId)
Log(captcha) // Log(captcha)
ok := this.Update(sessionId, "Captcha", captcha) ok := this.Update(sessionId, "Captcha", captcha)
Log(ok) // Log(ok)
return ok return ok
} }
+9 -1
View File
@@ -3,7 +3,7 @@ package service
import ( import (
"github.com/leanote/leanote/app/db" "github.com/leanote/leanote/app/db"
"github.com/leanote/leanote/app/info" "github.com/leanote/leanote/app/info"
// . "github.com/leanote/leanote/app/lea" . "github.com/leanote/leanote/app/lea"
"gopkg.in/mgo.v2/bson" "gopkg.in/mgo.v2/bson"
"time" "time"
) )
@@ -61,6 +61,14 @@ func (this *TagService) AddOrUpdateTag(userId string, tag string) info.NoteTag {
noteTag.Count = count noteTag.Count = count
noteTag.UpdatedTime = time.Now() noteTag.UpdatedTime = time.Now()
// noteTag.Usn = userService.IncrUsn(userId), 更新count而已 // noteTag.Usn = userService.IncrUsn(userId), 更新count而已
// 之前删除过的, 现在要添加回来了
if noteTag.IsDeleted {
Log("之前删除过的, 现在要添加回来了: " + tag)
noteTag.Usn = userService.IncrUsn(userId)
noteTag.IsDeleted = false
}
db.UpdateByIdAndUserId(db.NoteTags, noteTag.TagId.Hex(), userId, noteTag) db.UpdateByIdAndUserId(db.NoteTags, noteTag.TagId.Hex(), userId, noteTag)
return noteTag return noteTag
} }
+12 -12
View File
@@ -311,7 +311,7 @@ func (this *ThemeService) UpdateTplContent(userId, themeId, filename, content st
basePath := this.GetThemeAbsolutePath(userId, themeId) basePath := this.GetThemeAbsolutePath(userId, themeId)
path := basePath + "/" + filename path := basePath + "/" + filename
if strings.Contains(filename, ".html") { if strings.Contains(filename, ".html") {
Log(">>") // Log(">>")
if ok, msg = this.ValidateTheme(basePath, filename, content); ok { if ok, msg = this.ValidateTheme(basePath, filename, content); ok {
// 模板 // 模板
if ok, msg = this.mustTpl(filename, content); ok { if ok, msg = this.mustTpl(filename, content); ok {
@@ -359,7 +359,7 @@ func (this *ThemeService) mustTpl(filename, content string) (ok bool, msg string
defer func() { defer func() {
if err := recover(); err != nil { if err := recover(); err != nil {
ok = false ok = false
Log(err) // Log(err)
msg = fmt.Sprintf("%v", err) msg = fmt.Sprintf("%v", err)
} }
}() }()
@@ -405,7 +405,7 @@ func (this *ThemeService) ExportTheme(userId, themeId string) (ok bool, path str
theme := this.GetThemeById(themeId) theme := this.GetThemeById(themeId)
// 打包 // 打包
// 验证路径, 别把整个项目打包了 // 验证路径, 别把整个项目打包了
Log(theme.Path) // Log(theme.Path)
if theme.Path == "" || if theme.Path == "" ||
(!strings.HasPrefix(theme.Path, "public/upload") && (!strings.HasPrefix(theme.Path, "public/upload") &&
!strings.HasPrefix(theme.Path, "public/blog/themes")) || !strings.HasPrefix(theme.Path, "public/blog/themes")) ||
@@ -417,12 +417,12 @@ func (this *ThemeService) ExportTheme(userId, themeId string) (ok bool, path str
targetPath := revel.BasePath + "/public/upload/" + userId + "/tmp" targetPath := revel.BasePath + "/public/upload/" + userId + "/tmp"
err := os.MkdirAll(targetPath, 0755) err := os.MkdirAll(targetPath, 0755)
if err != nil { if err != nil {
Log(err) // Log(err)
return return
} }
targetName := targetPath + "/" + theme.Name + ".zip" targetName := targetPath + "/" + theme.Name + ".zip"
Log(sourcePath) // Log(sourcePath)
Log(targetName) // Log(targetName)
ok = archive.Zip(sourcePath, targetName) ok = archive.Zip(sourcePath, targetName)
if !ok { if !ok {
return return
@@ -445,7 +445,7 @@ func (this *ThemeService) ImportTheme(userId, path string) (ok bool, msg string)
} }
if ok, msg = archive.Unzip(path, targetPath); !ok { if ok, msg = archive.Unzip(path, targetPath); !ok {
DeleteFile(targetPath) DeleteFile(targetPath)
Log("oh no") // Log("oh no")
return return
} }
@@ -558,8 +558,8 @@ func (this *ThemeService) InstallTheme(userId, themeId string) (ok bool) {
// 验证主题是否全法, 存在循环引用? // 验证主题是否全法, 存在循环引用?
// filename, newContent 表示在修改模板时要判断模板修改时是否有错误 // filename, newContent 表示在修改模板时要判断模板修改时是否有错误
func (this *ThemeService) ValidateTheme(path string, filename, newContent string) (ok bool, msg string) { func (this *ThemeService) ValidateTheme(path string, filename, newContent string) (ok bool, msg string) {
Log("theme Path") // Log("theme Path")
Log(path) // Log(path)
// 建立一个有向图 // 建立一个有向图
// 将该path下的所有文件提出, 得到文件的引用情况 // 将该path下的所有文件提出, 得到文件的引用情况
files := ListDir(path) files := ListDir(path)
@@ -613,9 +613,9 @@ func (this *ThemeService) ValidateTheme(path string, filename, newContent string
for _, includes := range finds { for _, includes := range finds {
include := includes[1] include := includes[1]
includeIndex, has := fileIndexMap[include] includeIndex, has := fileIndexMap[include]
Log(includeIndex) // Log(includeIndex)
Log("??") // Log("??")
Log(has) // Log(has)
if has { if has {
vector[thisIndex][includeIndex] = 1 vector[thisIndex][includeIndex] = 1
} }
+1 -1
View File
@@ -485,7 +485,7 @@ func (this *UserService) GetAllUserByFilter(userFilterEmail, userFilterWhiteList
users := []info.User{} users := []info.User{}
q := db.Users.Find(query) q := db.Users.Find(query)
q.All(&users) q.All(&users)
Log(len(users)) // Log(len(users))
return users return users
} }
+3 -3
View File
@@ -3,16 +3,16 @@
<div class="row"> <div class="row">
<div class="col-sm-6"> <div class="col-sm-8">
<form id="add_user_form"> <form id="add_user_form">
<section class="panel panel-default"> <section class="panel panel-default">
<div class="panel-body"> <div class="panel-body">
<div class="form-group"> <div class="form-group">
<label>Wkhtmltopdf Binary Path</label> <label>Wkhtmltopdf Binary Path</label>
<input type="text" class="form-control" placeholder="/usr/local/bin/wkhtmltopdf" name="path" value="{{.str.exportPdfBinPath}}"> <input type="text" class="form-control" placeholder="/usr/local/bin/wkhtmltopdf or C:\Program Files\wkhtmltopdf\bin\wkhtmltopdf.exe" name="path" value="{{.str.exportPdfBinPath}}">
Leanote use <a target="_blank" href="http://wkhtmltopdf.org">wkhtmltopdf</a> to export pdf. You should install it on your server. Leanote use <a target="_blank" href="http://wkhtmltopdf.org">wkhtmltopdf</a> to export pdf. You should install it on your server.
<br /> <br />
Please input the path that wkhtmltopdf installed, e.g. <code>/usr/local/bin/wkhtmltopdf</code> Please input the path that wkhtmltopdf installed, e.g. <code>/usr/local/bin/wkhtmltopdf</code> on mac os/linux or <code>C:\Program Files\wkhtmltopdf\bin\wkhtmltopdf.exe</code> on windows.
</div> </div>
</div> </div>
+1
View File
@@ -42,6 +42,7 @@ function log(o) {
<a data-lang="zh-cn">简体中文</a> <a data-lang="zh-cn">简体中文</a>
<a data-lang="zh-hk">繁体中文</a> <a data-lang="zh-hk">繁体中文</a>
<a data-lang="pt-pt">Portugu&ecirc;s</a> <a data-lang="pt-pt">Portugu&ecirc;s</a>
<a data-lang="es-co">Spanish</a>
</div> </div>
<ul class="nav navbar-nav navbar-left"> <ul class="nav navbar-nav navbar-left">
+1 -1
View File
@@ -24,7 +24,7 @@
name="sortField" name="sortField"
value=""> value="">
<option value="PublicTime" {{if eq $.userBlog.SortField "PublicTime"}}selected{{end}}>{{msg $ "publicTime"}}</option> <option value="PublicTime" {{if eq $.userBlog.SortField "PublicTime"}}selected{{end}}>{{msg $ "publicTime"}}</option>
<option value="CreatedTime" {{if eq $.userBlog.SortField "CreatedTimeTime"}}selected{{end}}>{{msg $ "createdTime"}}</option> <option value="CreatedTime" {{if eq $.userBlog.SortField "CreatedTime"}}selected{{end}}>{{msg $ "createdTime"}}</option>
<option value="UpdatedTime" {{if eq $.userBlog.SortField "UpdatedTime"}}selected{{end}}>{{msg $ "updatedTime"}}</option> <option value="UpdatedTime" {{if eq $.userBlog.SortField "UpdatedTime"}}selected{{end}}>{{msg $ "updatedTime"}}</option>
<option value="Title" {{if eq $.userBlog.SortField "Title"}}selected{{end}}>{{msg . "title"}}</option> <option value="Title" {{if eq $.userBlog.SortField "Title"}}selected{{end}}>{{msg . "title"}}</option>
</select> </select>
+47 -36
View File
@@ -345,63 +345,74 @@ function log(o) {
</div> </div>
<div id="noteList"> <div id="noteList">
<div class="clearfix" id="notesAndSort" style="position: relative"> <div class="clearfix" id="notesAndSort" style="position: relative">
<div class="pull-left"> <div class="pull-left">
<!-- 我的笔记本 --> <!-- 我的笔记本 -->
<div class="dropdown" id="myNotebookNavForListNav"> <div class="dropdown" id="myNotebookNavForListNav">
<a class="ios7-a dropdown-toggle" id="dropdownMenu1" data-toggle="dropdown"> <a class="ios7-a">
<span id="curNotebookForListNote">{{msg . "all"}}</span> <span id="curNotebookForListNote">{{msg . "all"}}</span>
<!--
<i class="fa fa-angle-down"></i>
-->
</a> </a>
<!-- 如果notebook过多, 则会产生滚动 弃用
<div class="dropdown-menu dropdown-list" style="left: 5px;">
<ul role="menu" aria-labelledby="dropdownMenu1" id="notebookNavForListNote"></ul>
</div>
-->
</div> </div>
<!-- 共享的笔记本 --> <!-- 共享的笔记本 -->
<div class="dropdown" id="sharedNotebookNavForListNav" style="display: none"> <div class="dropdown" id="sharedNotebookNavForListNav" style="display: none">
<a class="ios7-a dropdown-toggle" id="dropdownMenu2" data-toggle="dropdown"> <a class="ios7-a">
<span id="curSharedNotebookForListNote">{{msg . "all"}}</span> <span id="curSharedNotebookForListNote">{{msg . "all"}}</span>
<!--
<i class="fa fa-angle-down"></i>
-->
</a> </a>
<ul class="dropdown-menu" role="menu" </div>
aria-labelledby="dropdownMenu2" style="left: 5px;" id="sharedNotebookNavForListNote">
</ul>
</div> </div>
</div> <!-- tag search -->
<div class="pull-left" id="tagSearch"></div>
<div class="pull-left" id="tagSearch" style="line-height: 38px"> <!-- sort type -->
</div>
<div id="sortType"> <div id="sortType">
<div class="dropdown"> <div class="dropdown">
<a class="ios7-a dropdown-toggle" id="dropdownMenu1" <a class="ios7-a dropdown-toggle" id="dropdownMenu1"
data-toggle="dropdown"> data-toggle="dropdown">
<!-- </i><i class="fa fa-th-list"></i>
<i class="fa fa-sort-alpha-asc">
</i>Sort <i class="fa fa-angle-down"></i>
-->
</a> </a>
<!--
<ul class="dropdown-menu" role="menu" <ul class="dropdown-menu" role="menu"
aria-labelledby="dropdownMenu1" aria-labelledby="dropdownMenu1"
style="right: 3px; ! important; left: -100px; min-width: 100px;"> >
<li role="presentation"><a role="menuitem" tabindex="-1"
href="#">创建日期</a></li> <li role="presentation"><a data-view="snippet" class="view-style view-snippet" role="menuitem">
<li role="presentation"><a role="menuitem" tabindex="-1" <i class="fa fa-check"></i>
href="#">修改日期</a></li> {{leaMsg . "Snippet View"}}
<li role="presentation"><a role="menuitem" tabindex="-1" </a></li>
href="#">标题</a></li> <li role="presentation"><a data-view="list" class="view-style view-list" role="menuitem">
<i class="fa fa-check"></i>
{{leaMsg . "List View"}}
</a></li>
<li role="presentation" class="divider"></li> <li role="presentation" class="divider"></li>
<li role="presentation"><a role="menuitem" tabindex="-1" <li role="presentation"><a data-sorter="dateCreatedASC" class="sorter-style sorter-dateCreatedASC" role="menuitem">
href="#">Separated </a></li> <i class="fa fa-check"></i>
{{leaMsg . "Date Created"}} <i class="fa fa-sort-alpha-asc"></i>
</a></li>
<li role="presentation"><a data-sorter="dateCreatedDESC" class="sorter-style sorter-dateCreatedDESC" role="menuitem">
<i class="fa fa-check"></i>
{{leaMsg . "Date Created"}} <i class="fa fa-sort-alpha-desc"></i>
</a></li>
<li role="presentation" class="divider"></li>
<li role="presentation"><a data-sorter="dateUpdatedASC" class="sorter-style sorter-dateUpdatedASC" role="menuitem">
<i class="fa fa-check"></i>
{{leaMsg . "Date Updated"}} <i class="fa fa-sort-alpha-asc"></i>
</a></li>
<li role="presentation"><a data-sorter="dateUpdatedDESC" class="sorter-style sorter-dateUpdatedDESC checked" role="menuitem">
<i class="fa fa-check"></i>
{{leaMsg . "Date Updated"}} <i class="fa fa-sort-alpha-desc"></i>
</a></li>
<li role="presentation" class="divider"></li>
<li role="presentation"><a data-sorter="titleASC" class="sorter-style sorter-titleASC" role="menuitem">
<i class="fa fa-check"></i>
{{leaMsg . "Title"}} <i class="fa fa-sort-alpha-asc"></i>
</a></li>
<li role="presentation"><a data-sorter="titleDESC" class="sorter-style sorter-titleDESC" role="menuitem">
<i class="fa fa-check"></i>
{{leaMsg . "Title"}} <i class="fa fa-sort-alpha-desc"></i>
</a></li>
</ul> </ul>
-->
</div> </div>
</div> </div>
</div> </div>
@@ -856,7 +867,7 @@ function log(o) {
</div> </div>
<script> <script>
var LEA = {}; var LEA = {sPath: ''};
LEA.locale = "{{.locale}}"; LEA.locale = "{{.locale}}";
var UrlPrefix = '{{.siteUrl}}'; var UrlPrefix = '{{.siteUrl}}';
var UserInfo = {{.userInfo|jsonJs}}; var UserInfo = {{.userInfo|jsonJs}};
@@ -882,7 +893,7 @@ var GlobalConfigs = {{.globalConfigs|jsonJs}};
<!-- dev --> <!-- dev -->
<script src="/js/jquery-1.9.0.min.js"></script> <script src="/js/jquery-1.9.0.min.js"></script>
<script src="/js/jquery.ztree.all-3.5.js"></script> <script src="/js/jquery.ztree.all-3.5.js"></script>
<script src="/js/object_id-min.js"></script> <script src="/js/object_id.js"></script>
<!-- /dev --> <!-- /dev -->
<script src="/tinymce/tinymce.js"></script> <script src="/tinymce/tinymce.js"></script>
+43 -34
View File
@@ -333,58 +333,67 @@ function log(o) {
<div class="pull-left"> <div class="pull-left">
<!-- 我的笔记本 --> <!-- 我的笔记本 -->
<div class="dropdown" id="myNotebookNavForListNav"> <div class="dropdown" id="myNotebookNavForListNav">
<a class="ios7-a dropdown-toggle" id="dropdownMenu1" data-toggle="dropdown"> <a class="ios7-a">
<span id="curNotebookForListNote">{{msg . "all"}}</span> <span id="curNotebookForListNote">{{msg . "all"}}</span>
<!--
<i class="fa fa-angle-down"></i>
-->
</a> </a>
<!-- 如果notebook过多, 则会产生滚动 弃用
<div class="dropdown-menu dropdown-list" style="left: 5px;">
<ul role="menu" aria-labelledby="dropdownMenu1" id="notebookNavForListNote"></ul>
</div>
-->
</div> </div>
<!-- 共享的笔记本 --> <!-- 共享的笔记本 -->
<div class="dropdown" id="sharedNotebookNavForListNav" style="display: none"> <div class="dropdown" id="sharedNotebookNavForListNav" style="display: none">
<a class="ios7-a dropdown-toggle" id="dropdownMenu2" data-toggle="dropdown"> <a class="ios7-a">
<span id="curSharedNotebookForListNote">{{msg . "all"}}</span> <span id="curSharedNotebookForListNote">{{msg . "all"}}</span>
<!--
<i class="fa fa-angle-down"></i>
-->
</a> </a>
<ul class="dropdown-menu" role="menu"
aria-labelledby="dropdownMenu2" style="left: 5px;" id="sharedNotebookNavForListNote">
</ul>
</div> </div>
</div> </div>
<div class="pull-left" id="tagSearch" style="line-height: 38px"> <!-- tag search -->
</div> <div class="pull-left" id="tagSearch"></div>
<!-- sort type -->
<div id="sortType"> <div id="sortType">
<div class="dropdown"> <div class="dropdown">
<a class="ios7-a dropdown-toggle" id="dropdownMenu1" <a class="ios7-a dropdown-toggle" id="dropdownMenu1"
data-toggle="dropdown"> data-toggle="dropdown">
<!-- </i><i class="fa fa-th-list"></i>
<i class="fa fa-sort-alpha-asc">
</i>Sort <i class="fa fa-angle-down"></i>
-->
</a> </a>
<!--
<ul class="dropdown-menu" role="menu" <ul class="dropdown-menu" role="menu"
aria-labelledby="dropdownMenu1" aria-labelledby="dropdownMenu1"
style="right: 3px; ! important; left: -100px; min-width: 100px;"> >
<li role="presentation"><a role="menuitem" tabindex="-1" <li role="presentation"><a data-view="snippet" class="view-style view-snippet" role="menuitem">
href="#">创建日期</a></li> <i class="fa fa-check"></i>
<li role="presentation"><a role="menuitem" tabindex="-1" {{leaMsg . "Snippet View"}}
href="#">修改日期</a></li> </a></li>
<li role="presentation"><a role="menuitem" tabindex="-1" <li role="presentation"><a data-view="list" class="view-style view-list" role="menuitem">
href="#">标题</a></li> <i class="fa fa-check"></i>
{{leaMsg . "List View"}}
</a></li>
<li role="presentation" class="divider"></li> <li role="presentation" class="divider"></li>
<li role="presentation"><a role="menuitem" tabindex="-1" <li role="presentation"><a data-sorter="dateCreatedASC" class="sorter-style sorter-dateCreatedASC" role="menuitem">
href="#">Separated </a></li> <i class="fa fa-check"></i>
{{leaMsg . "Date Created"}} <i class="fa fa-sort-alpha-asc"></i>
</a></li>
<li role="presentation"><a data-sorter="dateCreatedDESC" class="sorter-style sorter-dateCreatedDESC" role="menuitem">
<i class="fa fa-check"></i>
{{leaMsg . "Date Created"}} <i class="fa fa-sort-alpha-desc"></i>
</a></li>
<li role="presentation" class="divider"></li>
<li role="presentation"><a data-sorter="dateUpdatedASC" class="sorter-style sorter-dateUpdatedASC" role="menuitem">
<i class="fa fa-check"></i>
{{leaMsg . "Date Updated"}} <i class="fa fa-sort-alpha-asc"></i>
</a></li>
<li role="presentation"><a data-sorter="dateUpdatedDESC" class="sorter-style sorter-dateUpdatedDESC checked" role="menuitem">
<i class="fa fa-check"></i>
{{leaMsg . "Date Updated"}} <i class="fa fa-sort-alpha-desc"></i>
</a></li>
<li role="presentation" class="divider"></li>
<li role="presentation"><a data-sorter="titleASC" class="sorter-style sorter-titleASC" role="menuitem">
<i class="fa fa-check"></i>
{{leaMsg . "Title"}} <i class="fa fa-sort-alpha-asc"></i>
</a></li>
<li role="presentation"><a data-sorter="titleDESC" class="sorter-style sorter-titleDESC" role="menuitem">
<i class="fa fa-check"></i>
{{leaMsg . "Title"}} <i class="fa fa-sort-alpha-desc"></i>
</a></li>
</ul> </ul>
-->
</div> </div>
</div> </div>
</div> </div>
@@ -828,7 +837,7 @@ function log(o) {
</div> </div>
</div> </div>
<script> <script>
var LEA = {}; var LEA = {sPath: ''};
LEA.locale = "{{.locale}}"; LEA.locale = "{{.locale}}";
var UrlPrefix = '{{.siteUrl}}'; var UrlPrefix = '{{.siteUrl}}';
var UserInfo = {{.userInfo|jsonJs}}; var UserInfo = {{.userInfo|jsonJs}};
+2 -4
View File
@@ -9,7 +9,7 @@ SP=$(cd "$(dirname "$0")"; pwd)
tmp="/Users/life/Desktop/leanote_release" tmp="/Users/life/Desktop/leanote_release"
# version # version
V="v2.2" V="v2.6"
##================================= ##=================================
# 1. 先build 成 3个平台, 2种bit = 6种 # 1. 先build 成 3个平台, 2种bit = 6种
@@ -32,7 +32,7 @@ function build()
suffix=".exe" suffix=".exe"
fi fi
GOOS=$1 GOARCH=$2 go build -o leanote-$1-$2$suffix ../app/tmp GOOS=$1 GOARCH=$2 go build -o leanote-$1-$2$suffix github.com/leanote/leanote/app/tmp
} }
build "linux" "386"; build "linux" "386";
@@ -42,7 +42,6 @@ build "linux" "arm";
build "windows" "386"; build "windows" "386";
build "windows" "amd64"; build "windows" "amd64";
# build "darwin" "386";
build "darwin" "amd64"; build "darwin" "amd64";
@@ -146,7 +145,6 @@ tarRelease "linux" "arm";
tarRelease "windows" "386"; tarRelease "windows" "386";
tarRelease "windows" "amd64"; tarRelease "windows" "amd64";
# tarRelease "darwin" "386";
tarRelease "darwin" "amd64"; tarRelease "darwin" "amd64";
# BLOCK' # BLOCK'
+4 -4
View File
@@ -4,13 +4,13 @@ cd..
set SCRIPTPATH=%cd% set SCRIPTPATH=%cd%
: top src directory : top src directory
set path="%SCRIPTPATH%\bin\src\github.com\leanote" set leanotePath="%SCRIPTPATH%\bin\src\github.com\leanote"
if not exist "%path%" mkdir "%path%" if not exist "%leanotePath%" mkdir "%leanotePath%"
: create software link : create software link
if exist "%path%\leanote" del /Q "%path%\leanote" if exist "%leanotePath%\leanote" del /Q "%leanotePath%\leanote"
mklink /D "%path%\leanote" %SCRIPTPATH% mklink /D "%leanotePath%\leanote" %SCRIPTPATH%
: set GOPATH : set GOPATH
set GOPATH="%SCRIPTPATH%\bin" set GOPATH="%SCRIPTPATH%\bin"
@@ -0,0 +1,7 @@
modules
=======
Set of officially supported modules for Revel applications
### Caution
this is a work in progress
@@ -0,0 +1,6 @@
modules/auth
===============
Basic user/auth module
This should be modeled after [flask-security](https://github.com/mattupstate/flask-security)
@@ -0,0 +1,78 @@
package auth
import (
// "errors"
)
var (
Store StorageDriver
)
// Store = gormauth.NewGormAuthDriver()
type UserAuth interface {
// getters/setters implemented by the app-level model
UserId() string
Secret() string
HashedSecret() string
SetHashedSecret(string)
SecretDriver
// // implemented by secret driver
// Authenticate() (bool, error)
}
type SecretDriver interface {
Authenticate() (bool, error)
HashSecret(args ...interface{}) (string, error)
// stuff for documentation
// UserContext is expected in these?
// Secret expects 0 or non-0 arguments
// When no parameter is passed, it acts as a getter
// When one or more parameters are passed, it acts as a setter
// A driver should specify the expected arguments and their meanings
// Register()
// Login()
// Logout()
}
type StorageDriver interface {
Save(user interface{}) error
// Load should take a partially filled struct
// (with values needed to look up)
// and fills in the rest
Load(user interface{}) error
}
// func init() {
// // auth.Store = gorm...
// }
// func (c App) Login(email, password string) {
// u := User {
// Email ...
// }
// good, err := auth.Authenticate(email, password)
// user, err := user_info.GetUserByEmail(email)
// }
// Bycrypt Authenticate() expects a single string argument of the plaintext password
// It returns true on success and false if error or password mismatch
// func Authenticate(attemptedUser UserAuth) (bool, error) {
// // check user in Store
// loadedUser, err := Store.Load(attemptedUser.UserId())
// if err != nil {
// return false, errors.New("User Not Found")
// }
// loadedUser.Authenticate(attemptedUser.Secret())
// // successfully authenticated
// return true, nil
// }
@@ -0,0 +1,134 @@
package auth_test
import (
"errors"
"testing"
"github.com/revel/modules/auth"
"github.com/revel/modules/auth/driver/secret"
)
type User struct {
email string
password string
hashpass string
secret.BcryptAuth // SecurityDriver for testing
}
func NewUser(email, pass string) *User {
u := &User{
email: email,
password: pass,
}
u.UserContext = u
return u
}
func (self *User) UserId() string {
return self.email
}
func (self *User) Secret() string {
return self.password
}
func (self *User) HashedSecret() string {
return self.hashpass
}
func (self *User) SetHashedSecret(hpass string) {
self.hashpass = hpass
}
// func (self *User) Load() string
type TestStore struct {
data map[string]string
}
func (self *TestStore) Save(user interface{}) error {
u, ok := user.(*User)
if !ok {
return errors.New("TestStore.Save() expected arg of type User")
}
hPass, err := u.HashSecret(u.Secret())
if err != nil {
return err
}
self.data[u.UserId()] = hPass
return nil
}
func (self *TestStore) Load(user interface{}) error {
u, ok := user.(*User)
if !ok {
return errors.New("TestStore.Load() expected arg of type User")
}
hpass, ok := self.data[u.UserId()]
if !ok {
return errors.New("Record Not Found")
}
u.SetHashedSecret(hpass)
return nil
}
func TestPasswordHash(t *testing.T) {
auth.Store = &TestStore{
data: make(map[string]string),
}
u := NewUser("demo@domain.com", "demopass")
fail := NewUser("demo@domain.com", "")
var err error
u.hashpass, err = u.HashSecret(u.password)
if err != nil {
t.Errorf("Should have hashed password, get error: %v\n", err)
}
fail.hashpass, err = fail.HashSecret(fail.password)
if err == nil {
t.Errorf("Should have failed hashing\n")
}
}
func TestAuthenticate(t *testing.T) {
auth.Store = &TestStore{
data: make(map[string]string),
}
// user registered a long time ago
u := NewUser("demo@domain.com", "demopass")
err := auth.Store.Save(u)
if err != nil {
t.Errorf("Should have saved user: %v", err)
}
// users now logging in
pass := NewUser("demo@domain.com", "demopass")
fail := NewUser("demo@domain.com", "invalid")
// valid user is now trying to login
// check user in DB
err = auth.Store.Load(pass)
if err != nil {
t.Errorf("Should have loaded pass user: %v\n", err)
}
// check credentials
ok, err := pass.Authenticate()
if !ok || err != nil {
t.Errorf("Should have authenticated user")
}
// invalid user is now trying to login
err = auth.Store.Load(fail)
if err != nil {
t.Errorf("Should have loaded fail user")
}
// this should fail
ok, err = fail.Authenticate()
if ok || err != nil {
t.Errorf("Should have failed to authenticate user: %v\n", err)
}
}
@@ -0,0 +1,27 @@
/* A basic user authentication module for Revel
list of concerns:
- Separating out the interface and driver
- Removing DB/Storage dependency
- UUID as default identifier?
- how to deal with password/secret or generally, method of authorization
- default {views,controllers,routes} for register/login/logut ?
- reset password in most basic ?
- activation (and other features) in a second / more sophisticated driver
- filter for checking that user is authenticated
I think a driver is made up of 2 parts
data prep and data storage
register and password reset are part of data prep
as is the auth hash method
they don't care how the data is stored
then there is the data store
perhaps each auth user model should instantiate 2 drivers instead of 1?
one for data prep components and one for storage
so the security driver and the storage driver
*/
package auth
@@ -0,0 +1,73 @@
package secret
import (
"errors"
"golang.org/x/crypto/bcrypt"
"github.com/revel/modules/auth"
)
// example implementation of a Revel auth security driver
// This driver should be embedded into your app-level User model
// It expects your User model to have `Password` and `HashedPassword` string fields
//
// Your User model also needs to set itself as the UserContext for the BcryptAuth driver
//
// func NewUser(email, pass string) *User {
// u := &User{
// email: email,
// password: pass,
// }
// u.UserContext = u
// }
//
type BcryptAuth struct {
UserContext auth.UserAuth
}
// Bcrypt Secret() returns the hashed version of the password.
// It expects an argument of type string, which is the plain text password
func (self *BcryptAuth) HashSecret(args ...interface{}) (string, error) {
if auth.Store == nil {
return "", errors.New("Auth module StorageDriver not set")
}
argLen := len(args)
if argLen == 0 {
// we are getting
return string(self.UserContext.HashedSecret()), nil
}
if argLen == 1 {
// we are setting
password, ok := args[0].(string)
if !ok {
return "", errors.New("Wrong argument type provided, expected plaintext password as string")
}
hPass, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
if err != nil {
return "", err
}
self.UserContext.SetHashedSecret(string(hPass))
return self.UserContext.HashedSecret(), nil
}
// bad argument count
return "", errors.New("Too many arguments provided, expected one")
}
// Bycrypt Authenticate() expects a single string argument of the plaintext password
// It returns true on success and false if error or password mismatch
func (self *BcryptAuth) Authenticate() (bool, error) {
// check password
err := bcrypt.CompareHashAndPassword([]byte(self.UserContext.HashedSecret()), []byte(self.UserContext.Secret()))
if err == bcrypt.ErrMismatchedHashAndPassword {
return false, nil
}
if err != nil {
return false, err
}
// successfully authenticated
return true, nil
}
@@ -0,0 +1,3 @@
Mysql Auth driver
==================
@@ -0,0 +1,3 @@
Postgresql Auth driver
==================
@@ -0,0 +1,3 @@
Sqlite Auth driver
==================
@@ -0,0 +1,17 @@
package auth
// var storageDriver auth.StorageDriver // postgres in example
// type AuthUserModel struct {
// userId string
// security *SecurityDriver // bcrypt in example
// }
// func (self *AuthUserModel) UserId() string {
// return self.userId
// }
// func (self *AuthUserModel) Secret() string {
// return self.security.Secret()
// }
@@ -0,0 +1,121 @@
package csrf
import (
"crypto/rand"
"crypto/subtle"
"encoding/hex"
"html/template"
"io"
"math"
"net/url"
"github.com/revel/revel"
)
// allowMethods are HTTP methods that do NOT require a token
var allowedMethods = map[string]bool{
"GET": true,
"HEAD": true,
"OPTIONS": true,
"TRACE": true,
}
func RandomString(length int) (string, error) {
buffer := make([]byte, int(math.Ceil(float64(length)/2)))
if _, err := io.ReadFull(rand.Reader, buffer); err != nil {
return "", nil
}
str := hex.EncodeToString(buffer)
return str[:length], nil
}
func RefreshToken(c *revel.Controller) {
token, err := RandomString(64)
if err != nil {
panic(err)
}
c.Session["csrf_token"] = token
}
// CsrfFilter enables CSRF request token creation and verification.
//
// Usage:
// 1) Add `csrf.CsrfFilter` to the app's filters (it must come after the revel.SessionFilter).
// 2) Add CSRF fields to a form with the template tag `{{ csrftoken . }}`. The filter adds a function closure to the `RenderArgs` that can pull out the secret and make the token as-needed, caching the value in the request. Ajax support provided through the `X-CSRFToken` header.
func CsrfFilter(c *revel.Controller, fc []revel.Filter) {
token, foundToken := c.Session["csrf_token"]
if !foundToken {
RefreshToken(c)
}
referer, refErr := url.Parse(c.Request.Header.Get("Referer"))
isSameOrigin := sameOrigin(c.Request.URL, referer)
// If the Request method isn't in the white listed methods
if !allowedMethods[c.Request.Method] && !IsExempt(c) {
// Token wasn't present at all
if !foundToken {
c.Result = c.Forbidden("REVEL CSRF: Session token missing.")
return
}
// Referer header is invalid
if refErr != nil {
c.Result = c.Forbidden("REVEL CSRF: HTTP Referer malformed.")
return
}
// Same origin
if !isSameOrigin {
c.Result = c.Forbidden("REVEL CSRF: Same origin mismatch.")
return
}
var requestToken string
// First check for token in post data
if c.Request.Method == "POST" {
requestToken = c.Request.FormValue("csrftoken")
}
// Then check for token in custom headers, as with AJAX
if requestToken == "" {
requestToken = c.Request.Header.Get("X-CSRFToken")
}
if requestToken == "" || !compareToken(requestToken, token) {
c.Result = c.Forbidden("REVEL CSRF: Invalid token.")
return
}
}
fc[0](c, fc[1:])
// Only add token to RenderArgs if the request is: not AJAX, not missing referer header, and is same origin.
if c.Request.Header.Get("X-CSRFToken") == "" && isSameOrigin {
c.RenderArgs["_csrftoken"] = token
}
}
func compareToken(requestToken, token string) bool {
// ConstantTimeCompare will panic if the []byte aren't the same length
if len(requestToken) != len(token) {
return false
}
return subtle.ConstantTimeCompare([]byte(requestToken), []byte(token)) == 1
}
// Validates same origin policy
func sameOrigin(u1, u2 *url.URL) bool {
return u1.Scheme == u2.Scheme && u1.Host == u2.Host
}
func init() {
revel.TemplateFuncs["csrftoken"] = func(renderArgs map[string]interface{}) template.HTML {
if tokenFunc, ok := renderArgs["_csrftoken"]; !ok {
panic("REVEL CSRF: _csrftoken missing from RenderArgs.")
} else {
return template.HTML(tokenFunc.(func() string)())
}
}
}
@@ -0,0 +1,169 @@
package csrf
import (
"bytes"
"net/http"
"net/http/httptest"
"net/url"
"strconv"
"testing"
"github.com/revel/revel"
)
var testFilters = []revel.Filter{
CsrfFilter,
func(c *revel.Controller, fc []revel.Filter) {
c.RenderHtml("{{ csrftoken . }}")
},
}
func TestTokenInSession(t *testing.T) {
resp := httptest.NewRecorder()
getRequest, _ := http.NewRequest("GET", "http://www.example.com/", nil)
c := revel.NewController(revel.NewRequest(getRequest), revel.NewResponse(resp))
c.Session = make(revel.Session)
testFilters[0](c, testFilters)
if _, ok := c.Session["csrf_token"]; !ok {
t.Fatal("token should be present in session")
}
}
func TestPostWithoutToken(t *testing.T) {
resp := httptest.NewRecorder()
postRequest, _ := http.NewRequest("POST", "http://www.example.com/", nil)
c := revel.NewController(revel.NewRequest(postRequest), revel.NewResponse(resp))
c.Session = make(revel.Session)
testFilters[0](c, testFilters)
if c.Response.Status != 403 {
t.Fatal("post without token should be forbidden")
}
}
func TestNoReferrer(t *testing.T) {
resp := httptest.NewRecorder()
postRequest, _ := http.NewRequest("POST", "http://www.example.com/", nil)
c := revel.NewController(revel.NewRequest(postRequest), revel.NewResponse(resp))
c.Session = make(revel.Session)
RefreshToken(c)
token := c.Session["csrf_token"]
// make a new request with the token
data := url.Values{}
data.Set("csrftoken", token)
formPostRequest, _ := http.NewRequest("POST", "http://www.example.com/", bytes.NewBufferString(data.Encode()))
formPostRequest.Header.Add("Content-Type", "application/x-www-form-urlencoded")
formPostRequest.Header.Add("Content-Length", strconv.Itoa(len(data.Encode())))
// and replace the old request
c.Request = revel.NewRequest(formPostRequest)
testFilters[0](c, testFilters)
if c.Response.Status != 403 {
t.Fatal("post without referer should be forbidden")
}
}
func TestRefererHttps(t *testing.T) {
resp := httptest.NewRecorder()
postRequest, _ := http.NewRequest("POST", "http://www.example.com/", nil)
c := revel.NewController(revel.NewRequest(postRequest), revel.NewResponse(resp))
c.Session = make(revel.Session)
RefreshToken(c)
token := c.Session["csrf_token"]
// make a new request with the token
data := url.Values{}
data.Set("csrftoken", token)
formPostRequest, _ := http.NewRequest("POST", "https://www.example.com/", bytes.NewBufferString(data.Encode()))
formPostRequest.Header.Add("Content-Type", "application/x-www-form-urlencoded")
formPostRequest.Header.Add("Content-Length", strconv.Itoa(len(data.Encode())))
formPostRequest.Header.Add("Referer", "http://www.example.com/")
// and replace the old request
c.Request = revel.NewRequest(formPostRequest)
testFilters[0](c, testFilters)
if c.Response.Status != 403 {
t.Fatal("posts to https should have an https referer")
}
}
func TestHeaderWithToken(t *testing.T) {
resp := httptest.NewRecorder()
postRequest, _ := http.NewRequest("POST", "http://www.example.com/", nil)
c := revel.NewController(revel.NewRequest(postRequest), revel.NewResponse(resp))
c.Session = make(revel.Session)
RefreshToken(c)
token := c.Session["csrf_token"]
// make a new request with the token
formPostRequest, _ := http.NewRequest("POST", "http://www.example.com/", nil)
formPostRequest.Header.Add("X-CSRFToken", token)
formPostRequest.Header.Add("Referer", "http://www.example.com/")
// and replace the old request
c.Request = revel.NewRequest(formPostRequest)
testFilters[0](c, testFilters)
if c.Response.Status == 403 {
t.Fatal("post with http header token should be allowed")
}
}
func TestFormPostWithToken(t *testing.T) {
resp := httptest.NewRecorder()
postRequest, _ := http.NewRequest("POST", "http://www.example.com/", nil)
c := revel.NewController(revel.NewRequest(postRequest), revel.NewResponse(resp))
c.Session = make(revel.Session)
RefreshToken(c)
token := c.Session["csrf_token"]
// make a new request with the token
data := url.Values{}
data.Set("csrftoken", token)
formPostRequest, _ := http.NewRequest("POST", "http://www.example.com/", bytes.NewBufferString(data.Encode()))
formPostRequest.Header.Add("Content-Type", "application/x-www-form-urlencoded")
formPostRequest.Header.Add("Content-Length", strconv.Itoa(len(data.Encode())))
formPostRequest.Header.Add("Referer", "http://www.example.com/")
// and replace the old request
c.Request = revel.NewRequest(formPostRequest)
testFilters[0](c, testFilters)
if c.Response.Status == 403 {
t.Fatal("form post with token should be allowed")
}
}
func TestNoTokenInArgsWhenCORs(t *testing.T) {
resp := httptest.NewRecorder()
getRequest, _ := http.NewRequest("GET", "http://www.example1.com/", nil)
getRequest.Header.Add("Referer", "http://www.example2.com/")
c := revel.NewController(revel.NewRequest(getRequest), revel.NewResponse(resp))
c.Session = make(revel.Session)
testFilters[0](c, testFilters)
if _, ok := c.RenderArgs["_csrftoken"]; ok {
t.Fatal("RenderArgs should not contain token when not same origin")
}
}
@@ -0,0 +1,36 @@
package csrf
import (
"fmt"
"strings"
"github.com/revel/revel"
)
var (
exemptPath = make(map[string]bool)
exemptAction = make(map[string]bool)
)
func MarkExempt(route string) {
if strings.HasPrefix(route, "/") {
// e.g. "/controller/action"
exemptPath[strings.ToLower(route)] = true
} else if routeParts := strings.Split(route, "."); len(routeParts) == 2 {
// e.g. "ControllerName.ActionName"
exemptAction[route] = true
} else {
err := fmt.Sprintf("csrf.MarkExempt() received invalid argument \"%v\". Either provide a path prefixed with \"/\" or controller action in the form of \"ControllerName.ActionName\".", route)
panic(err)
}
}
func IsExempt(c *revel.Controller) bool {
if _, ok := exemptPath[strings.ToLower(c.Request.Request.URL.Path)]; ok {
return true
} else if _, ok := exemptAction[c.Action]; ok {
return true
}
return false
}
@@ -0,0 +1,55 @@
package csrf
import (
"net/http"
"net/http/httptest"
"testing"
"github.com/revel/revel"
)
func TestExemptPath(t *testing.T) {
MarkExempt("/Controller/Action")
resp := httptest.NewRecorder()
postRequest, _ := http.NewRequest("POST", "http://www.example.com/Controller/Action", nil)
c := revel.NewController(revel.NewRequest(postRequest), revel.NewResponse(resp))
c.Session = make(revel.Session)
testFilters[0](c, testFilters)
if c.Response.Status == 403 {
t.Fatal("post to csrf exempt action should pass")
}
}
func TestExemptPathCaseInsensitive(t *testing.T) {
MarkExempt("/Controller/Action")
resp := httptest.NewRecorder()
postRequest, _ := http.NewRequest("POST", "http://www.example.com/controller/action", nil)
c := revel.NewController(revel.NewRequest(postRequest), revel.NewResponse(resp))
c.Session = make(revel.Session)
testFilters[0](c, testFilters)
if c.Response.Status == 403 {
t.Fatal("post to csrf exempt action should pass")
}
}
func TestExemptAction(t *testing.T) {
MarkExempt("Controller.Action")
resp := httptest.NewRecorder()
postRequest, _ := http.NewRequest("POST", "http://www.example.com/Controller/Action", nil)
c := revel.NewController(revel.NewRequest(postRequest), revel.NewResponse(resp))
c.Session = make(revel.Session)
c.Action = "Controller.Action"
testFilters[0](c, testFilters)
if c.Response.Status == 403 {
t.Fatal("post to csrf exempt action should pass")
}
}
@@ -0,0 +1,86 @@
// This module configures a database connection for the application.
//
// Developers use this module by importing and calling db.Init().
// A "Transactional" controller type is provided as a way to import interceptors
// that manage the transaction
//
// In particular, a transaction is begun before each request and committed on
// success. If a panic occurred during the request, the transaction is rolled
// back. (The application may also roll the transaction back itself.)
package db
import (
"database/sql"
"github.com/revel/revel"
)
var (
Db *sql.DB
Driver string
Spec string
)
func Init() {
// Read configuration.
var found bool
if Driver, found = revel.Config.String("db.driver"); !found {
revel.ERROR.Fatal("No db.driver found.")
}
if Spec, found = revel.Config.String("db.spec"); !found {
revel.ERROR.Fatal("No db.spec found.")
}
// Open a connection.
var err error
Db, err = sql.Open(Driver, Spec)
if err != nil {
revel.ERROR.Fatal(err)
}
}
type Transactional struct {
*revel.Controller
Txn *sql.Tx
}
// Begin a transaction
func (c *Transactional) Begin() revel.Result {
txn, err := Db.Begin()
if err != nil {
panic(err)
}
c.Txn = txn
return nil
}
// Rollback if it's still going (must have panicked).
func (c *Transactional) Rollback() revel.Result {
if c.Txn != nil {
if err := c.Txn.Rollback(); err != nil {
if err != sql.ErrTxDone {
panic(err)
}
}
c.Txn = nil
}
return nil
}
// Commit the transaction.
func (c *Transactional) Commit() revel.Result {
if c.Txn != nil {
if err := c.Txn.Commit(); err != nil {
if err != sql.ErrTxDone {
panic(err)
}
}
c.Txn = nil
}
return nil
}
func init() {
revel.InterceptMethod((*Transactional).Begin, revel.BEFORE)
revel.InterceptMethod((*Transactional).Commit, revel.AFTER)
revel.InterceptMethod((*Transactional).Rollback, revel.FINALLY)
}
@@ -0,0 +1,32 @@
package controllers
import (
"github.com/revel/revel"
"github.com/revel/modules/jobs/app/jobs"
"github.com/robfig/cron"
"strings"
)
type Jobs struct {
*revel.Controller
}
func (c Jobs) Status() revel.Result {
remoteAddress := c.Request.RemoteAddr
if revel.Config.BoolDefault("jobs.acceptproxyaddress", false) {
if proxiedAddress, isProxied := c.Request.Header["X-Forwarded-For"]; isProxied {
remoteAddress = proxiedAddress[0]
}
}
if !strings.HasPrefix(remoteAddress, "127.0.0.1") && !strings.HasPrefix(remoteAddress, "::1") {
return c.Forbidden("%s is not local", remoteAddress)
}
entries := jobs.MainCron.Entries()
return c.Render(entries)
}
func init() {
revel.TemplateFuncs["castjob"] = func(job cron.Job) *jobs.Job {
return job.(*jobs.Job)
}
}
@@ -0,0 +1,66 @@
package jobs
import (
"github.com/revel/revel"
"github.com/robfig/cron"
"reflect"
"runtime/debug"
"sync"
"sync/atomic"
)
type Job struct {
Name string
inner cron.Job
status uint32
running sync.Mutex
}
const UNNAMED = "(unnamed)"
func New(job cron.Job) *Job {
name := reflect.TypeOf(job).Name()
if name == "Func" {
name = UNNAMED
}
return &Job{
Name: name,
inner: job,
}
}
func (j *Job) Status() string {
if atomic.LoadUint32(&j.status) > 0 {
return "RUNNING"
}
return "IDLE"
}
func (j *Job) Run() {
// If the job panics, just print a stack trace.
// Don't let the whole process die.
defer func() {
if err := recover(); err != nil {
if revelError := revel.NewErrorFromPanic(err); revelError != nil {
revel.ERROR.Print(err, "\n", revelError.Stack)
} else {
revel.ERROR.Print(err, "\n", string(debug.Stack()))
}
}
}()
if !selfConcurrent {
j.running.Lock()
defer j.running.Unlock()
}
if workPermits != nil {
workPermits <- struct{}{}
defer func() { <-workPermits }()
}
atomic.StoreUint32(&j.status, 1)
defer atomic.StoreUint32(&j.status, 0)
j.inner.Run()
}
@@ -0,0 +1,64 @@
// A job runner for executing scheduled or ad-hoc tasks asynchronously from HTTP requests.
//
// It adds a couple of features on top of the cron package to make it play nicely with Revel:
// 1. Protection against job panics. (They print to ERROR instead of take down the process)
// 2. (Optional) Limit on the number of jobs that may run simulatenously, to
// limit resource consumption.
// 3. (Optional) Protection against multiple instances of a single job running
// concurrently. If one execution runs into the next, the next will be queued.
// 4. Cron expressions may be defined in app.conf and are reusable across jobs.
// 5. Job status reporting.
package jobs
import (
"github.com/revel/revel"
"github.com/robfig/cron"
"strings"
"time"
)
// Callers can use jobs.Func to wrap a raw func.
// (Copying the type to this package makes it more visible)
//
// For example:
// jobs.Schedule("cron.frequent", jobs.Func(myFunc))
type Func func()
func (r Func) Run() { r() }
func Schedule(spec string, job cron.Job) error {
// Look to see if given spec is a key from the Config.
if strings.HasPrefix(spec, "cron.") {
confSpec, found := revel.Config.String(spec)
if !found {
panic("Cron spec not found: " + spec)
}
spec = confSpec
}
sched, err := cron.Parse(spec)
if err != nil {
return err
}
MainCron.Schedule(sched, New(job))
return nil
}
// Run the given job at a fixed interval.
// The interval provided is the time between the job ending and the job being run again.
// The time that the job takes to run is not included in the interval.
func Every(duration time.Duration, job cron.Job) {
MainCron.Schedule(cron.Every(duration), New(job))
}
// Run the given job right now.
func Now(job cron.Job) {
go New(job).Run()
}
// Run the given job once, after the given delay.
func In(duration time.Duration, job cron.Job) {
go func() {
time.Sleep(duration)
New(job).Run()
}()
}
@@ -0,0 +1,32 @@
package jobs
import (
"fmt"
"github.com/revel/revel"
"github.com/robfig/cron"
)
const DEFAULT_JOB_POOL_SIZE = 10
var (
// Singleton instance of the underlying job scheduler.
MainCron *cron.Cron
// This limits the number of jobs allowed to run concurrently.
workPermits chan struct{}
// Is a single job allowed to run concurrently with itself?
selfConcurrent bool
)
func init() {
MainCron = cron.New()
revel.OnAppStart(func() {
if size := revel.Config.IntDefault("jobs.pool", DEFAULT_JOB_POOL_SIZE); size > 0 {
workPermits = make(chan struct{}, size)
}
selfConcurrent = revel.Config.BoolDefault("jobs.selfconcurrent", false)
MainCron.Start()
fmt.Println("Go to /@jobs to see job status.")
})
}
@@ -0,0 +1,39 @@
<html>
<head>
<style>
body {
font-size: 12px;
font-family: sans-serif;
}
table {
border-collapse: collapse;
border: none;
}
table td, table th {
padding: 4 10px;
border: none;
}
table tr:nth-child(odd) {
background-color: #f0f0f0;
}
th {
text-align: left;
}
</style>
</head>
<body>
<h1>Scheduled Jobs</h1>
<table>
<tr><th>Name</th><th>Status</th><th>Last run</th><th>Next run</th></tr>
{{range .entries}}
{{$job := castjob .Job}}
<tr>
<td>{{$job.Name}}</td>
<td>{{$job.Status}}</td>
<td>{{if not .Prev.IsZero}}{{.Prev.Format "2006-01-02 15:04:05"}}{{end}}</td>
<td>{{if not .Next.IsZero}}{{.Next.Format "2006-01-02 15:04:05"}}{{end}}</td>
</tr>
{{end}}
</table>
@@ -0,0 +1 @@
GET /@jobs Jobs.Status
@@ -0,0 +1,19 @@
Revel pprof module
============
#### How to use:
1. Open your app.conf file and add the following line:
`module.pprof=github.com/revel/modules/pprof`
This will enable the pprof module.
2. Next, open your routes file and add:
`module:pprof` **Note:** Do not change these routes. The pprof command-line tool by default assumes these routes.
Congrats! You can now profile your application. To use the web interface, visit `http://<host>:<port>/debug/pprof`. You can also use the `go tool pprof` command to profile your application and get a little deeper. Use the command by running `go tool pprof <binary> http://<host>:<port>`. For example, if you modified the booking sample, you would run: `go tool pprof $GOPATH/bin/booking http://localhost:9000` (assuming you used the default `revel run` arguments.
The command-line tool will take a 30-second CPU profile, and save the results to a temporary file in your `$HOME/pprof` directory. You can reference this file at a later time by using the same command as above, but by specifying the filename instead of the server address.
In order to fully utilize the command-line tool, you may need the graphviz utilities. If you're on OS X, you can install these easily using Homebrew: `brew install graphviz`.
To read more about profiling Go programs, here is some reading material: [The Go Blog](http://blog.golang.org/profiling-go-programs) : [net/pprof package documentation](http://golang.org/pkg/net/http/pprof/)
@@ -0,0 +1,39 @@
package controllers
import (
"github.com/revel/revel"
"net/http"
"net/http/pprof"
)
type Pprof struct {
*revel.Controller
}
// The PprofHandler type makes it easy to call the net/http/pprof handler methods
// since they all have the same method signature
type PprofHandler func(http.ResponseWriter, *http.Request)
func (r PprofHandler) Apply(req *revel.Request, resp *revel.Response) {
r(resp.Out, req.Request)
}
func (c Pprof) Profile() revel.Result {
return PprofHandler(pprof.Profile)
}
func (c Pprof) Symbol() revel.Result {
return PprofHandler(pprof.Symbol)
}
func (c Pprof) Cmdline() revel.Result {
return PprofHandler(pprof.Cmdline)
}
func (c Pprof) Trace() revel.Result {
return PprofHandler(pprof.Trace)
}
func (c Pprof) Index() revel.Result {
return PprofHandler(pprof.Index)
}
@@ -0,0 +1,6 @@
GET /pprof/profile Pprof.Profile
GET /pprof/symbol Pprof.Symbol
GET /debug/pprof/cmdline Pprof.Cmdline
GET /debug/pprof/trace Pprof.Trace
GET /debug/pprof/* Pprof.Index
GET /debug/pprof/ Pprof.Index
@@ -0,0 +1,121 @@
package controllers
import (
"github.com/revel/revel"
"os"
fpath "path/filepath"
"strings"
"syscall"
)
type Static struct {
*revel.Controller
}
// This method handles requests for files. The supplied prefix may be absolute
// or relative. If the prefix is relative it is assumed to be relative to the
// application directory. The filepath may either be just a file or an
// additional filepath to search for the given file. This response may return
// the following responses in the event of an error or invalid request;
// 403(Forbidden): If the prefix filepath combination results in a directory.
// 404(Not found): If the prefix and filepath combination results in a non-existent file.
// 500(Internal Server Error): There are a few edge cases that would likely indicate some configuration error outside of revel.
//
// Note that when defining routes in routes/conf the parameters must not have
// spaces around the comma.
// Bad: Static.Serve("public/img", "favicon.png")
// Good: Static.Serve("public/img","favicon.png")
//
// Examples:
// Serving a directory
// Route (conf/routes):
// GET /public/{<.*>filepath} Static.Serve("public")
// Request:
// public/js/sessvars.js
// Calls
// Static.Serve("public","js/sessvars.js")
//
// Serving a file
// Route (conf/routes):
// GET /favicon.ico Static.Serve("public/img","favicon.png")
// Request:
// favicon.ico
// Calls:
// Static.Serve("public/img", "favicon.png")
func (c Static) Serve(prefix, filepath string) revel.Result {
// Fix for #503.
prefix = c.Params.Fixed.Get("prefix")
if prefix == "" {
return c.NotFound("")
}
return serve(c, prefix, filepath)
}
// This method allows modules to serve binary files. The parameters are the same
// as Static.Serve with the additional module name pre-pended to the list of
// arguments.
func (c Static) ServeModule(moduleName, prefix, filepath string) revel.Result {
// Fix for #503.
prefix = c.Params.Fixed.Get("prefix")
if prefix == "" {
return c.NotFound("")
}
var basePath string
for _, module := range revel.Modules {
if module.Name == moduleName {
basePath = module.Path
}
}
absPath := fpath.Join(basePath, fpath.FromSlash(prefix))
return serve(c, absPath, filepath)
}
// This method allows static serving of application files in a verified manner.
func serve(c Static, prefix, filepath string) revel.Result {
var basePath string
if !fpath.IsAbs(prefix) {
basePath = revel.BasePath
}
basePathPrefix := fpath.Join(basePath, fpath.FromSlash(prefix))
fname := fpath.Join(basePathPrefix, fpath.FromSlash(filepath))
// Verify the request file path is within the application's scope of access
if !strings.HasPrefix(fname, basePathPrefix) {
revel.WARN.Printf("Attempted to read file outside of base path: %s", fname)
return c.NotFound("")
}
// Verify file path is accessible
finfo, err := os.Stat(fname)
if err != nil {
if os.IsNotExist(err) || err.(*os.PathError).Err == syscall.ENOTDIR {
revel.WARN.Printf("File not found (%s): %s ", fname, err)
return c.NotFound("File not found")
}
revel.ERROR.Printf("Error trying to get fileinfo for '%s': %s", fname, err)
return c.RenderError(err)
}
// Disallow directory listing
if finfo.Mode().IsDir() {
revel.WARN.Printf("Attempted directory listing of %s", fname)
return c.Forbidden("Directory listing not allowed")
}
// Open request file path
file, err := os.Open(fname)
if err != nil {
if os.IsNotExist(err) {
revel.WARN.Printf("File not found (%s): %s ", fname, err)
return c.NotFound("File not found")
}
revel.ERROR.Printf("Error opening '%s': %s", fname, err)
return c.RenderError(err)
}
return c.RenderFile(file, revel.Inline)
}
@@ -0,0 +1,248 @@
package controllers
import (
"bytes"
"encoding/json"
"fmt"
"html/template"
"reflect"
"strings"
"github.com/revel/revel"
"github.com/revel/revel/testing"
)
// TestRunner is a controller which is used for running application tests in browser.
type TestRunner struct {
*revel.Controller
}
// TestSuiteDesc is used for storing information about a single test suite.
// This structure is required by revel test cmd.
type TestSuiteDesc struct {
Name string
Tests []TestDesc
// Elem is reflect.Type which can be used for accessing methods
// of the test suite.
Elem reflect.Type
}
// TestDesc is used for describing a single test of some test suite.
// This structure is required by revel test cmd.
type TestDesc struct {
Name string
}
// TestSuiteResult stores the results the whole test suite.
// This structure is required by revel test cmd.
type TestSuiteResult struct {
Name string
Passed bool
Results []TestResult
}
// TestResult represents the results of running a single test of some test suite.
// This structure is required by revel test cmd.
type TestResult struct {
Name string
Passed bool
ErrorHTML template.HTML
ErrorSummary string
}
var (
testSuites []TestSuiteDesc // A list of all available tests.
none = []reflect.Value{} // It is used as input for reflect call in a few places.
// registeredTests simplifies the search of test suites by their name.
// "TestSuite.TestName" is used as a key. Value represents index in testSuites.
registeredTests map[string]int
)
/*
Controller's action methods are below.
*/
// Index is an action which renders the full list of available test suites and their tests.
func (c TestRunner) Index() revel.Result {
return c.Render(testSuites)
}
// Run runs a single test, given by the argument.
func (c TestRunner) Run(suite, test string) revel.Result {
// Check whether requested test exists.
suiteIndex, ok := registeredTests[suite+"."+test]
if !ok {
return c.NotFound("Test %s.%s does not exist", suite, test)
}
result := TestResult{Name: test}
// Found the suite, create a new instance and run the named method.
t := testSuites[suiteIndex].Elem
v := reflect.New(t)
func() {
// When the function stops executing try to recover from panic.
defer func() {
if err := recover(); err != nil {
// If panic error is empty, exit.
panicErr := revel.NewErrorFromPanic(err)
if panicErr == nil {
return
}
// Otherwise, prepare and format the response of server if possible.
testSuite := v.Elem().FieldByName("TestSuite").Interface().(testing.TestSuite)
res := formatResponse(testSuite)
// Render the error and save to the result structure.
var buffer bytes.Buffer
tmpl, _ := revel.MainTemplateLoader.Template("TestRunner/FailureDetail.html")
tmpl.Render(&buffer, map[string]interface{}{
"error": panicErr,
"response": res,
"postfix": suite + "_" + test,
})
result.ErrorSummary = errorSummary(panicErr)
result.ErrorHTML = template.HTML(buffer.String())
}
}()
// Initialize the test suite with a NewTestSuite()
testSuiteInstance := v.Elem().FieldByName("TestSuite")
testSuiteInstance.Set(reflect.ValueOf(testing.NewTestSuite()))
// Make sure After method will be executed at the end.
if m := v.MethodByName("After"); m.IsValid() {
defer m.Call(none)
}
// Start from running Before method of test suite if exists.
if m := v.MethodByName("Before"); m.IsValid() {
m.Call(none)
}
// Start the test method itself.
v.MethodByName(test).Call(none)
// No panic means success.
result.Passed = true
}()
return c.RenderJson(result)
}
// List returns a JSON list of test suites and tests.
// It is used by revel test command line tool.
func (c TestRunner) List() revel.Result {
return c.RenderJson(testSuites)
}
/*
Below are helper functions.
*/
// describeSuite expects testsuite interface as input parameter
// and returns its description in a form of TestSuiteDesc structure.
func describeSuite(testSuite interface{}) TestSuiteDesc {
t := reflect.TypeOf(testSuite)
// Get a list of methods of the embedded test type.
// It will be used to make sure the same tests are not included in multiple test suites.
super := t.Elem().Field(0).Type
superMethods := map[string]bool{}
for i := 0; i < super.NumMethod(); i++ {
// Save the current method's name.
superMethods[super.Method(i).Name] = true
}
// Get a list of methods on the test suite that take no parameters, return
// no results, and were not part of the embedded type's method set.
var tests []TestDesc
for i := 0; i < t.NumMethod(); i++ {
m := t.Method(i)
mt := m.Type
// Make sure the test method meets the criterias:
// - method of testSuite without input parameters;
// - nothing is returned;
// - has "Test" prefix;
// - doesn't belong to the embedded structure.
methodWithoutParams := (mt.NumIn() == 1 && mt.In(0) == t)
nothingReturned := (mt.NumOut() == 0)
hasTestPrefix := (strings.HasPrefix(m.Name, "Test"))
if methodWithoutParams && nothingReturned && hasTestPrefix && !superMethods[m.Name] {
// Register the test suite's index so we can quickly find it by test's name later.
registeredTests[t.Elem().Name()+"."+m.Name] = len(testSuites)
// Add test to the list of tests.
tests = append(tests, TestDesc{m.Name})
}
}
return TestSuiteDesc{
Name: t.Elem().Name(),
Tests: tests,
Elem: t.Elem(),
}
}
// errorSummary gets an error and returns its summary in human readable format.
func errorSummary(err *revel.Error) (message string) {
message = fmt.Sprintf("%4sStatus: %s\n%4sIn %s", "", err.Description, "", err.Path)
// If line of error isn't known return the message as is.
if err.Line == 0 {
return
}
// Otherwise, include info about the line number and the relevant
// source code lines.
message += fmt.Sprintf(" (around line %d): ", err.Line)
for _, line := range err.ContextSource() {
if line.IsError {
message += line.Source
}
}
return
}
// formatResponse gets *revel.TestSuite as input parameter and
// transform response related info into a readable format.
func formatResponse(t testing.TestSuite) map[string]string {
if t.Response == nil {
return map[string]string{}
}
// Beautify the response JSON to make it human readable.
resp, err := json.MarshalIndent(t.Response, "", " ")
if err != nil {
revel.ERROR.Println(err)
}
// Remove extra new line symbols so they do not take too much space on a result page.
// Allow no more than 1 line break at a time.
body := strings.Replace(string(t.ResponseBody), "\n\n", "\n", -1)
body = strings.Replace(body, "\r\n\r\n", "\r\n", -1)
return map[string]string{
"Headers": string(resp),
"Body": strings.TrimSpace(body),
}
}
func init() {
// Every time app is restarted convert the list of available test suites
// provided by the revel testing package into a format which will be used by
// the testrunner module and revel test cmd.
revel.OnAppStart(func() {
// Extracting info about available test suites from revel/testing package.
registeredTests = map[string]int{}
for _, testSuite := range testing.TestSuites {
testSuites = append(testSuites, describeSuite(testSuite))
}
})
}
@@ -0,0 +1,12 @@
package app
import (
"fmt"
"github.com/revel/revel"
)
func init() {
revel.OnAppStart(func() {
fmt.Println("Go to /@tests to run the tests.")
})
}
@@ -0,0 +1,45 @@
<div class="panel panel-default">
<div class="panel-heading">
<b>{{.error.Description}}</b>
</div>
<div class="panel-body">
<ul class="nav nav-tabs" role="tablist">
<li class="active"><a href="#error_{{.postfix}}" role="tab" data-toggle="tab">Error</a></li>
<li><a href="#stack_{{.postfix}}" role="tab" data-toggle="tab">Stack</a></li>
{{if .response}}
<li><a href="#headers_{{.postfix}}" role="tab" data-toggle="tab">Headers</a></li>
<li><a href="#body_{{.postfix}}" role="tab" data-toggle="tab">Response Body</a></li>
{{end}}
</ul>
<div class="tab-content" id="result_{{.postfix}}">
<div class="tab-pane active" id="error_{{.postfix}}">
<div class="panel panel-danger">
<div class="panel-heading">
In {{.error.Path}}{{if .error.Line}} (around {{if .error.Line}}line {{.error.Line}}{{end}}{{if .error.Column}} column {{.error.Column}}{{end}}){{end}}:
</div>
<div class="panel-body">
{{range .error.ContextSource}}
{{if .IsError}}
<pre><code class="go">{{.Source}}</code></pre>
{{end}}
{{end}}
</div>
</div>
</div>
<div class="tab-pane" id="stack_{{.postfix}}">
<pre><code class="bash">{{.error.Stack}}</code></pre>
</div>
{{if .response}}
<div class="tab-pane" id="headers_{{.postfix}}">
<pre><code class="json">{{.response.Headers}}</code></pre>
</div>
<div class="tab-pane" id="body_{{.postfix}}">
<pre><code class="html">{{.response.Body}}</code></pre>
</div>
{{end}}
</div>
</div>
</div>
@@ -0,0 +1,110 @@
<!DOCTYPE html>
<html>
<head>
<title>Revel Test Runner</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<link href="{{url `Root`}}/@tests/public/css/bootstrap.min.css" type="text/css" rel="stylesheet"></link>
<link href="{{url `Root`}}/@tests/public/css/github.css" type="text/css" rel="stylesheet"></link>
<script src="{{url `Root`}}/@tests/public/js/jquery-1.9.1.min.js" type="text/javascript"></script>
<script src="{{url `Root`}}/@tests/public/js/bootstrap.min.js" type="text/javascript"></script>
<script src="{{url `Root`}}/@tests/public/js/highlight.pack.js" type="text/javascript"></script>
<style>
header { padding:20px 0; background-color:#ADD8E6 }
.passed td { background-color: #90EE90 !important; }
.failed td { background-color: #FFB6C1 !important; }
.tests td.name, .tests td.result { padding-top: 13px; }
pre { font-size:10px; white-space: pre; }
.name { width: 25%; }
.w100 { width: 100%; }
</style>
</head>
<body>
<header>
<div class="container">
<table class="w100"><tr><td>
<h1>Test Runner</h1>
<p class="lead">Run all of your application's tests from here.</p>
</td><td style="padding-left:150px;" class="text-right">
<button class="btn btn-lg btn-success" all-tests="">Run All Tests</button>
</td></tr></table>
</div>
</header>
<div class="container">
{{range .testSuites}}
<p class="lead" style="margin-top:20px;">{{.Name}}</p>
<table class="table table-striped tests" suite="{{.Name}}">
{{range .Tests}}
<tr>
<td class="name">{{.Name}}</td>
<td class="result">
</td>
<td class="text-right"><button test="{{.Name}}" class="btn btn-success">Run</button></td>
</tr>
{{end}}
</table>
{{end}}
</div>
<script>
var buttons = [];
var running;
$("button[test]").click(function() {
var button = $(this).addClass("disabled").text("Running");
addToQueue(button);
});
$("button[all-tests]").click(function() {
var button = $(this).addClass("disabled").text("Running");
$("button[test]").click();
});
function addToQueue(button) {
buttons.push(button);
if (!running) {
running = true;
nextTest();
}
}
function nextTest() {
if (buttons.length == 0) {
running = false;
} else {
var next = buttons.shift();
runTest(next);
}
}
function runTest(button) {
var suite = button.parents("table").attr("suite");
var test = button.attr("test");
var row = button.parents("tr");
var resultCell = row.children(".result");
$.ajax({
dataType: "json",
url: "{{url `Root`}}/@tests/"+suite+"/"+test,
success: function(result) {
row.attr("class", result.Passed ? "passed" : "failed");
if (result.Passed) {
resultCell.html("");
} else {
resultCell.html(result.ErrorHTML);
$("#result_" + suite + "_" + test + " pre code").each(function(i, block) {
hljs.highlightBlock(block);
});
}
button.removeClass("disabled").text("Run");
if (buttons.length == 0) {
$("button[all-tests]").removeClass("disabled").text("Run All Tests");
}
nextTest();
}
});
}
</script>
</body>
</html>
Loaded 100 of 1043 files, more files were not shown because too many files have changed in this diff. Show more