Compare commits

..
148 Commits
Author SHA1 Message Date
lealife 816af11db2 防止Unzip文件恶意攻击 2016-10-27 16:37:12 +08:00
lealife eda03f0aa4 防止用"../../来获取其它文件" 2016-10-27 15:40:17 +08:00
lealife 6a06511405 防止用"../../来获取其它文件" 2016-10-27 15:09:10 +08:00
lealife 15d8ebdc0f New Chrome, Chinese input problem
https://github.com/leanote/leanote/issues/42
2016-09-24 10:44:10 +08:00
life 5dc929c4c0 Merge pull request #408 from zhang-yuan/master
Translation fixed
2016-08-26 09:55:50 +08:00
life a4d6a99fee Merge pull request #409 from alexsourcerer/patch-9
Update album.conf  (fr-fr)
2016-08-26 09:54:59 +08:00
life 15d3b847cb Merge pull request #411 from alexsourcerer/patch-11
Update member.conf (fr-fr)
2016-08-26 09:54:49 +08:00
life 065ac99942 Merge pull request #412 from alexsourcerer/patch-12
Update msg.conf (fr-fr)
2016-08-26 09:54:33 +08:00
life 08ec359b93 Merge pull request #413 from alexsourcerer/patch-13
Update tinymce_editor.conf (fr-fr)
2016-08-26 09:54:03 +08:00
life 2f81c04f41 Merge pull request #378 from lucienevans/master
auto number in MathJax (just blog)
2016-08-26 09:52:23 +08:00
life e8bff79425 Merge pull request #410 from alexsourcerer/patch-10
Update markdown.conf
2016-08-26 09:49:45 +08:00
alexsourcerer 4ca8e8cd83 Update tinymce_editor.conf
translation created & completed!
2016-08-23 12:41:32 +02:00
alexsourcerer c0cc08a3c2 Update msg.conf
translation updated!
2016-08-23 12:04:53 +02:00
alexsourcerer d32a6dd277 Update member.conf
updated translation to french
2016-08-23 11:57:22 +02:00
alexsourcerer 8bacc15309 Update markdown.conf
translated to french
2016-08-23 11:46:26 +02:00
alexsourcerer 8a3f24b9c6 Update album.conf
translated to french
2016-08-23 11:37:16 +02:00
haha 2a7d1fe7b5 Add translation 2016-08-23 14:09:53 +08:00
haha 9a05ffcd8f 翻译问题 2016-08-23 12:11:41 +08:00
lealife aa95e680f9 travis use go 1.4 2016-08-23 11:06:50 +08:00
life 874ab69c34 Merge pull request #406 from Xunius/patch-2
add vim and emacs modes to features
2016-08-23 10:33:13 +08:00
Xunius d43f5fd7ab add vim and emacs modes to features 2016-08-22 17:44:39 +08:00
life 6a048f0d9a Merge pull request #403 from Xunius/patch-1
rephrased English n Chinese, fixed links to docs.
2016-08-22 17:23:21 +08:00
Xunius cb3681f651 rephrased English n Chinese, fixed links to docs.
Fixed grammar errors in English and polished the wordings.
Changed order at one place to make the Doc part appear before develop.
Added links to installation tutorials
2016-08-19 19:12:30 +08:00
life dfd7159401 Merge pull request #361 from gaoyifan/patch-1
fix spelling mistake in README.md
2016-07-22 10:36:10 +08:00
lucien 929ec975da auto number in MathJax 2016-06-21 23:35:49 +08:00
life e826dc7b93 Merge pull request #374 from mhoffmann75/german_transl
add complete german translation
2016-06-10 17:12:21 +08:00
Martin Hoffmann 629a49e54b add complete german translation
- modify app/views/home/header.html to know de-de messages folder
- create messages/de-de folder with all german language files (album, blog, ...)
- create public/js/i18n/blog.de-de.js and ms.de-de.js files
- add public/tinymce/langs/de-de.js from tinymce project

Thanks to Marc Manthey (macbroadcast) who is the original author of the german translation for the leanote 1.x project (https://github.com/macbroadcast/leanote). I took his work as starting point for my complete german translation on leanote 2.0.
2016-06-10 09:46:31 +02:00
lealife 6ebedf94f0 app.conf 2016-05-25 17:33:38 +08:00
lealife a07bb25128 remove unused codes and add site'url configuration on admin 2016-05-25 16:05:47 +08:00
lealife a007b89ebb v2.0 2016-05-25 14:46:40 +08:00
lealife cc4b003503 markdown vim cursor fixed 2016-05-25 09:51:53 +08:00
lealife 091922175a box leanote logo 2016-05-22 16:12:51 +08:00
lealife 371c93912d build 2016-05-22 10:36:36 +08:00
lealife 27221acda7 new logo 2016-05-22 10:34:40 +08:00
lealife 5db724e80b new logo 2016-05-21 23:05:50 +08:00
Yifan Gao 14265d9de4 fix spelling mistake in README.md 2016-05-18 10:26:24 +08:00
lealife 5c9e95ed60 build 2016-04-16 14:53:30 +08:00
lealife 2fc97ed42d markdown editor prettify add linenums 2016-04-16 14:51:54 +08:00
lealife 45cca30cec lea++ -> Explore 2016-04-16 12:09:48 +08:00
lealife 31167b6aaf recount tags 2016-04-16 11:58:39 +08:00
lealife 139906b9d6 recount tags when public note 2016-04-16 11:31:27 +08:00
lealife a9d49369e2 upgrade markdown mathjax 2016-04-12 22:02:36 +08:00
life 303e0da5c0 Update README.md 2016-04-09 10:12:46 +08:00
life ff5523bfaa Merge pull request #340 from eric2100/patch-15
Update blog.conf
2016-04-08 17:07:20 +08:00
Tsunghan,Tsai 063dd0140d Update blog.conf
部分口語修改
2016-04-08 12:31:41 +08:00
life c52d388d5d Merge pull request #337 from eric2100/patch-14
Update msg.conf
2016-04-07 17:31:04 +08:00
eric2100 18bcdb48af Update msg.conf 2016-04-07 12:29:03 +08:00
life db8f132507 Merge pull request #333 from eric2100/patch-9
Update blog.conf
2016-04-05 10:14:31 +08:00
life 439d5212b0 Merge pull request #334 from eric2100/patch-10
Update markdown.conf
2016-04-05 10:13:40 +08:00
life 88e2320027 Merge pull request #335 from eric2100/patch-11
Update member.conf
2016-04-05 10:13:09 +08:00
life 659a4e590a Merge pull request #336 from eric2100/patch-12
Update tinymce_editor.conf
2016-04-05 10:12:19 +08:00
eric2100 ab7f2386e0 Update tinymce_editor.conf 2016-04-05 00:24:21 +08:00
eric2100 ec82ff18f2 Update member.conf 2016-04-05 00:16:00 +08:00
eric2100 f3f00626e6 Update markdown.conf 2016-04-05 00:03:27 +08:00
eric2100 80fbb56426 Update blog.conf 2016-04-05 00:01:46 +08:00
life a5c952882f Merge pull request #332 from eric2100/patch-8
Update album.conf
2016-04-03 21:30:30 +08:00
eric2100 973b452a7e Update album.conf 2016-04-02 21:12:30 +08:00
lealife 25bcd21ea9 overwrite revel.Message 2016-03-19 23:00:41 +08:00
lealife 09de5e1e83 Gulp js i18n generator 2016-03-19 15:46:41 +08:00
lealife 15b0ef21ff restructure messages 2016-03-19 15:37:36 +08:00
lealife 9cf9ded855 remove config langs. Gulp will get all langs by messages/ 2016-03-19 15:17:15 +08:00
lealife 7af433ebaf build 2016-03-19 14:36:47 +08:00
lealife 67b608b324 set langs to config and modify gulp build to support langs 2016-03-19 14:30:07 +08:00
lealife 2aa3f5a654 support 中文繁体 2016-03-19 14:05:09 +08:00
lealife f5538218bd remove baidu statistics Code
https://github.com/leanote/leanote/issues/318
2016-03-04 22:23:53 +08:00
lealife 0e3bdd177c md resize when toggle 2016-02-27 15:30:01 +08:00
lealife 12520cc09d mathjax 2.6.1 2016-02-27 14:20:31 +08:00
life cb67892124 Merge pull request #309 from alexsourcerer/patch-8
Update msg.fr
2016-02-18 14:55:17 +08:00
alexsourcerer 45c09c9a26 Update msg.fr
I updated the msg.fr file (note that the website isn't it french at all anymore for french users)
2016-02-03 23:10:50 +01:00
lealife 20951ea2dd build release 2015-12-25 23:59:57 +08:00
lealife 530f2368da v1.4.2 released 2015-12-25 23:45:38 +08:00
lealife e685a99628 member css for multi lang 2015-12-25 23:45:19 +08:00
lealife bfc5acc3ee 1.4.2 released 2015-12-25 11:50:34 +08:00
lealife 551e3d965e markdown todo-list style 2015-12-25 11:50:34 +08:00
lealife 7c479b5595 fix ace editor hide the last line part section text 2015-12-25 11:50:34 +08:00
lealife b135f9717f fix gen desc 2015-12-25 11:50:34 +08:00
lealife 08ae37cae0 markdown add todo-list feature 2015-12-25 11:50:34 +08:00
Yingbo CUI 315a7bbe62 Update README.md 2015-12-24 16:47:31 +08:00
life e173b18ddc Merge pull request #285 from eurafa/master
Portuguese (Brazil) language added
2015-12-17 10:29:10 +08:00
Rafael Andrade de Oliveira dcc25df679 Chinese translations 2015-12-13 09:09:02 -02:00
Rafael Andrade de Oliveira c561dec14c Portuguese (Brazil) language added 2015-12-13 09:03:50 -02:00
lealife 43e8f2e701 markdown editor inited 2015-12-06 15:48:05 +08:00
lealife dd9952c453 fix export pdf error 2015-12-04 17:50:14 +08:00
lealife 19517dd634 fix export pdf error 2015-12-04 17:37:57 +08:00
lealife a5b006aae7 添加全局 toggle modify with readonly; 发布1.4.1 2015-12-02 20:56:03 +08:00
lealife 90bd07cdcc * markdown v2, 修复笔记内容覆盖 2015-12-02 20:55:34 +08:00
lealife 92576e9239 arm run script 2015-11-29 13:05:26 +08:00
lealife c58e6874c2 paste image 名称是untitled 2015-11-28 21:47:50 +08:00
lealife cfebf00cf1 i18n js 2015-11-28 21:32:21 +08:00
lealife 19be0990da 注销后不再保存笔记 2015-11-28 21:31:56 +08:00
lealife 3f27e4b0d4 Failed to generate name for field. Make sure the field name is valid #201 2015-11-28 21:26:29 +08:00
lealife 4710fb6686 i18n 2015-11-28 18:57:58 +08:00
lealife 28324c0178 release v1.4 2015-11-28 18:00:45 +08:00
lealife f270ade8d7 1.4 2015-11-28 17:58:42 +08:00
lealife 3b3e665a9f paste image 2015-11-28 17:58:38 +08:00
lealife bfa85e2d34 Merge branch 'feature-v1.4' 2015-11-28 16:45:59 +08:00
lealife fcf270a521 reinit undo when toggle file 2015-11-28 16:44:59 +08:00
lealife eba113c73c dev tinymce 2015-11-28 16:40:50 +08:00
lealife 41f63156ea tinymce 不打包 2015-11-28 16:32:29 +08:00
lealife f54fe397c3 member view 2015-11-28 16:12:27 +08:00
lealife 6f157289d3 update member css 2015-11-28 16:09:33 +08:00
lealife 65792d020c move tinymce theme to /public/css/tinymce 2015-11-28 16:07:17 +08:00
lealife 926882dce6 build js 2015-11-28 15:56:25 +08:00
lealife f834f469fc update gulp build for i18n 2015-11-28 15:55:58 +08:00
lealife 06d42c36f0 i18n 2015-11-28 15:46:56 +08:00
lealife 17d513a9de fix note-dev 2015-11-28 15:42:39 +08:00
lealife 8cc00c1f66 format date config; for update note's date 2015-11-28 15:38:43 +08:00
lealife cb433d9392 theme; split by files 2015-11-28 15:36:12 +08:00
lealife 86ca1efd11 tinymce theme 2015-11-28 15:35:26 +08:00
lealife 263f978c54 import theme 2015-11-28 15:33:49 +08:00
lealife c8af7eda5d hide note and editor when search 2015-11-28 15:33:42 +08:00
lealife 3724811802 set md column width 2015-11-28 15:33:30 +08:00
lealife 10ff48267f clear undo 2015-11-28 15:33:13 +08:00
lealife cd0913aec0 paste for markdown v2 2015-11-28 15:33:06 +08:00
lealife f8d4c2ef20 markdown editor v2 2015-11-28 15:32:56 +08:00
lealife f16b5e816e Leanote upperCase 2015-11-28 15:23:33 +08:00
lealife 9a9968760a note i18n 2015-11-28 15:19:50 +08:00
lealife b1f36dfbf1 member i18n 2015-11-28 15:17:36 +08:00
lealife bc0e09f222 file upload path 统一化 GetRandomFilePath 2015-11-28 14:44:07 +08:00
lealife 0dab71e72b delete unused 2015-11-28 14:35:46 +08:00
lealife 10f23c19ab group i18n, pwd 重置密码优化 2015-11-28 14:28:51 +08:00
lealife bba57ea302 configservice 2015-11-28 14:25:45 +08:00
lealife f052117989 删除笔记时删除历史 2015-11-28 14:22:10 +08:00
lealife df4ec53647 api fixContent优化; exportPDF优化 2015-11-28 14:21:23 +08:00
lealife a7eaf6114a urlTitle 优化, 减少生成次数, 避免使用id作为urlTitle 2015-11-28 14:16:10 +08:00
lealife b25bf0e16c util 时间判断 2015-11-28 13:49:00 +08:00
lealife d13447e6d0 controller 支持传递时间 2015-11-28 13:47:59 +08:00
lealife 6a1e84da0c noteService支持传时间添加/更新笔记 2015-11-28 13:43:37 +08:00
lealife 51aeb7d46e build support linux-arm 2015-11-23 10:39:01 +08:00
lealife 2dbd025768 album js build 2015-11-22 23:26:59 +08:00
lealife d52d80d529 plugins compress 2015-11-22 23:18:07 +08:00
lealife 2000bc585b markdown editor v2 paste images 2015-11-22 23:01:30 +08:00
lealife 8301a1e515 js 优化
* 标题按tab切换到内容
* 左侧最小化用css控制
* resize markdown editor v2
* Ace剪切导致行数减少
* 删除不要的代码
2015-11-22 22:58:38 +08:00
lealife bee65eb36d markdown editor v2 editor mode i18n 2015-11-22 22:46:27 +08:00
lealife 78199583b0 mv dist -> md 2015-11-22 22:46:00 +08:00
lealife 28d5678349 remove unused files 2015-11-22 22:41:07 +08:00
lealife e97c468f6e gulp markdown v2 builder 2015-11-22 22:39:16 +08:00
lealife 5d18554542 tinymce build 2015-11-22 22:39:04 +08:00
lealife 3ff0a9e09c markdown editor v2 libs 2015-11-22 22:36:53 +08:00
lealife 6a753682b7 markdown editor v2 2015-11-22 22:33:07 +08:00
lealife ce491e62c3 insert image i18n 2015-11-22 22:28:51 +08:00
lealife e4b847b731 undo md 2015-11-22 22:21:59 +08:00
lealife a12b285a35 tinymce leanote code plugin i18n 2015-11-22 22:21:38 +08:00
lealife 7f0ada8016 update readme 2015-11-18 23:45:20 +08:00
lealife bac5ab4d79 update readme 2015-11-18 23:43:19 +08:00
life b362406819 Merge pull request #261 from alexsourcerer/patch-7
Update msg.fr
2015-11-18 13:13:54 +08:00
alexsourcerer 9e2edbb987 Update msg.fr 2015-11-16 21:56:12 +01:00
lealife 7809d00787 fmt all go file 2015-11-13 17:58:41 +08:00
1184 changed files with 36839 additions and 33386 deletions

No files matched your search

+1 -1
View File
@@ -1,5 +1,5 @@
language: go language: go
go: 1.3 go: 1.4
services: services:
- mongodb # 2.4.12 - mongodb # 2.4.12
+152 -88
View File
@@ -15,13 +15,15 @@ var base = leanoteBase + '/public'; // public base
var noteDev = leanoteBase + '/app/views/note/note-dev.html'; var noteDev = leanoteBase + '/app/views/note/note-dev.html';
var noteProBase = leanoteBase + '/app/views/note'; var noteProBase = leanoteBase + '/app/views/note';
var messagesPath = leanoteBase + 'messages';
// 合并Js, 这些js都是不怎么修改, 且是依赖 // 合并Js, 这些js都是不怎么修改, 且是依赖
// 840kb, 非常耗时!! // 840kb, 非常耗时!!
gulp.task('concatDepJs', function() { gulp.task('concatDepJs', function() {
var jss = [ var jss = [
'js/jquery-1.9.0.min.js', 'js/jquery-1.9.0.min.js',
'js/jquery.ztree.all-3.5-min.js', 'js/jquery.ztree.all-3.5-min.js',
'tinymce/tinymce.full.min.js', // 使用打成的包, 加载速度快 // 'tinymce/tinymce.full.min.js', // 使用打成的包, 加载速度快
// 'libs/ace/ace.js', // 'libs/ace/ace.js',
'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',
@@ -62,11 +64,39 @@ gulp.task('concatAppJs', function() {
.pipe(gulp.dest(base + '/js')); .pipe(gulp.dest(base + '/js'));
}); });
// plugins压缩
gulp.task('plugins', function() {
// gulp.src(base + '/js/plugins/libs/*.js')
// .pipe(uglify()) // 压缩
// // .pipe(concat('main.min.js'))
// .pipe(gulp.dest(base + '/js/plugins/libs-min'));
// 所有js合并成一个
var jss = [
'note_info',
'tips',
'history',
'attachment_upload',
'editor_drop_paste',
'main'
];
for(var i in jss) {
jss[i] = base + '/js/plugins/' + jss[i] + '.js';
}
jss.push(base + '/js/plugins/libs-min/fileupload.js');
return gulp.src(jss)
.pipe(uglify()) // 压缩
.pipe(concat('main.min.js'))
.pipe(gulp.dest(base + '/js/plugins'));
});
// 合并requirejs和markdown为一个文件 // 合并requirejs和markdown为一个文件
gulp.task('concatMarkdownJs', function() { gulp.task('concatMarkdownJs', function() {
var jss = [ var jss = [
'js/require.js', 'js/require.js',
'dist/main.min.js', 'md/main.min.js',
]; ];
for(var i in jss) { for(var i in jss) {
@@ -80,6 +110,24 @@ gulp.task('concatMarkdownJs', function() {
.pipe(gulp.dest(base + '/js')); .pipe(gulp.dest(base + '/js'));
}); });
// / 合并requirejs和markdown为一个文件
gulp.task('concatMarkdownJsV2', function() {
var jss = [
'js/require.js',
'md/main-v2.min.js',
];
for(var i in jss) {
jss[i] = base + '/' + jss[i];
}
return gulp
.src(jss)
.pipe(uglify()) // 压缩
.pipe(concat('markdown-v2.min.js'))
.pipe(gulp.dest(base + '/js'));
});
// note-dev.html -> note.html, 替换css, js // note-dev.html -> note.html, 替换css, js
// TODO 加?t=2323232, 强制浏览器更新, 一般只需要把app.min.js上加 // TODO 加?t=2323232, 强制浏览器更新, 一般只需要把app.min.js上加
gulp.task('devToProHtml', function() { gulp.task('devToProHtml', function() {
@@ -88,28 +136,40 @@ gulp.task('devToProHtml', function() {
.pipe(replace(/<!-- dev -->[.\s\S]+?<!-- \/dev -->/g, '')) // 把dev 去掉 .pipe(replace(/<!-- dev -->[.\s\S]+?<!-- \/dev -->/g, '')) // 把dev 去掉
.pipe(replace(/<!-- pro_dep_js -->/, '<script src="/js/dep.min.js"></script>')) // 替换 .pipe(replace(/<!-- pro_dep_js -->/, '<script src="/js/dep.min.js"></script>')) // 替换
.pipe(replace(/<!-- pro_app_js -->/, '<script src="/js/app.min.js"></script>')) // 替换 .pipe(replace(/<!-- pro_app_js -->/, '<script src="/js/app.min.js"></script>')) // 替换
.pipe(replace(/<!-- pro_markdown_js -->/, '<script src="/js/markdown.min.js"></script>')) // 替换 // .pipe(replace(/<!-- pro_markdown_js -->/, '<script src="/js/markdown.min.js"></script>')) // 替换
.pipe(replace(/<!-- pro_markdown_js -->/, '<script src="/js/markdown-v2.min.js"></script>')) // 替换
.pipe(replace('/tinymce/tinymce.js', '/tinymce/tinymce.full.min.js')) // 替换
.pipe(replace(/<!-- pro_tinymce_init_js -->/, "var tinyMCEPreInit = {base: '/public/tinymce', suffix: '.min'};")) // 替换 .pipe(replace(/<!-- pro_tinymce_init_js -->/, "var tinyMCEPreInit = {base: '/public/tinymce', suffix: '.min'};")) // 替换
.pipe(replace(/plugins\/main.js/, "plugins/main.min.js")) // 替换 .pipe(replace(/plugins\/main.js/, "plugins/main.min.js")) // 替换
// 连续两个空行换成一个空行, 没用 // 连续两个空行换成一个空行
.pipe(replace(/\n\n/g, '\n')) .pipe(replace(/\r\n\r\n/g, '\r\n'))
.pipe(replace(/\n\n/g, '\n')) .pipe(replace(/\r\n\r\n/g, '\r\n'))
.pipe(replace(/\r\n\r\n/g, '\r\n'))
.pipe(replace(/\r\n\r\n/g, '\r\n'))
.pipe(replace(/\r\n\r\n/g, '\r\n'))
.pipe(replace(/\r\n\r\n/g, '\r\n'))
.pipe(replace('console.log(o);', '')) .pipe(replace('console.log(o);', ''))
.pipe(replace('console.trace(o);', ''))
// .pipe(minifyHtml()) // 不行, 压缩后golang报错 // .pipe(minifyHtml()) // 不行, 压缩后golang报错
.pipe(rename('note.html')) .pipe(rename('note.html'))
.pipe(gulp.dest(noteProBase)); .pipe(gulp.dest(noteProBase));
}); });
// Get used keys
// 只获取需要js i18n的key // 只获取需要js i18n的key
var path = require('path'); var path = require('path');
gulp.task('i18n', function() { gulp.task('i18n', function() {
var keys = {}; var keys = {};
var reg = /getMsg\(["']+(.+?)["']+/g; var reg = /getMsg\(["']+(.+?)["']+/g;
// {rule: "required", msg: "inputNewPassword"},
var reg2 = /msg: ?"?([0-9a-zA-Z]*)"?/g;
function getKey(data) { function getKey(data) {
while(ret = reg.exec(data)) { while(ret = reg.exec(data)) {
keys[ret[1]] = 1; keys[ret[1]] = 1;
} }
while(ret2 = reg2.exec(data)) {
keys[ret2[1]] = 1;
}
} }
// 先获取需要的key // 先获取需要的key
function ls(ff) { function ls(ff) {
@@ -137,14 +197,17 @@ gulp.task('i18n', function() {
ls(base + '/admin'); ls(base + '/admin');
ls(base + '/blog'); ls(base + '/blog');
ls(base + '/dist'); ls(base + '/md');
ls(base + '/js'); ls(base + '/js');
ls(base + '/album'); ls(base + '/album');
ls(base + '/libs'); ls(base + '/libs');
ls(base + '/member'); ls(base + '/member');
ls(base + '/tinymce'); ls(base + '/tinymce');
ls(leanoteBase + '/app/views');
console.log('parsed'); console.log('parsed');
var langs = {}; // zh-cn: 1
// msg.zh // msg.zh
function getAllMsgs(fname) { function getAllMsgs(fname) {
@@ -169,10 +232,30 @@ gulp.task('i18n', function() {
return msg; return msg;
} }
// 得到所有的语言的后缀
// 返回{en-us: 1, }
function getAllLangs() {
var langs = {};
var files = fs.readdirSync(messagesPath);
for(fn in files) {
var fname = files[fn];
if (fname.indexOf('-') > 0) {
langs[fname] = 1;
}
}
return langs;
}
// msg.zh, msg.js // msg.zh, msg.js
function genI18nJsFile(fromFilename, keys) { function genI18nJsFile(targetFilename, lang, fromFilenames, keys) {
var msgs = getAllMsgs(leanoteBase + '/messages/' + fromFilename); var msgs = {};
var toFilename = fromFilename + '.js'; fromFilenames.forEach(function (name) {
var tmpMsgs = getAllMsgs(leanoteBase + '/messages/' + lang + '/' + name + '.conf');
for (var i in tmpMsgs) {
msgs[i] = tmpMsgs[i];
}
});
var toMsgs = {}; var toMsgs = {};
for (var i in msgs) { for (var i in msgs) {
// 只要需要的 // 只要需要的
@@ -190,18 +273,27 @@ gulp.task('i18n', function() {
'}' + '}' +
'return key;' + 'return key;' +
'}'; '}';
// 写入到文件中 // 写入到文件中
var toFilename = targetFilename + '.' + lang + '.js';
fs.writeFile(base + '/js/i18n/' + toFilename, str); fs.writeFile(base + '/js/i18n/' + toFilename, str);
} }
genI18nJsFile('msg.zh', keys); function genTinymceLang(lang) {
genI18nJsFile('msg.en', keys); var msgs = getAllMsgs(leanoteBase + 'messages/' + lang + '/tinymce_editor.conf');
genI18nJsFile('msg.fr', keys); var str = 'tinymce.addI18n("' + lang + '",' + JSON.stringify(msgs) + ');';
genI18nJsFile('blog.zh', keys); fs.writeFile(base + '/tinymce/langs/' + lang + '.js', str);
genI18nJsFile('blog.en', keys); }
genI18nJsFile('blog.fr', keys);
});
var langs = getAllLangs();
for (var lang in langs) {
genI18nJsFile('blog', lang, ['blog'], keys);
genI18nJsFile('msg', lang, ['msg', 'member', 'markdown', 'album'], keys);
genTinymceLang(lang);
}
});
// 合并album需要的js // 合并album需要的js
gulp.task('concatAlbumJs', function() { gulp.task('concatAlbumJs', function() {
@@ -236,75 +328,6 @@ gulp.task('concatAlbumJs', function() {
.pipe(gulp.dest(base + '/album/js')); .pipe(gulp.dest(base + '/album/js'));
}); });
// plugins压缩
gulp.task('plugins', function() {
gulp.src(base + '/js/plugins/libs/*.js')
.pipe(uglify()) // 压缩
// .pipe(concat('main.min.js'))
.pipe(gulp.dest(base + '/js/plugins/libs-min'));
// 所有js合并成一个
var jss = [
'note_info',
'tips',
'history',
'attachment_upload',
'editor_drop_paste',
'main'
];
for(var i in jss) {
jss[i] = base + '/js/plugins/' + jss[i] + '.js';
}
gulp.src(jss)
.pipe(uglify()) // 压缩
.pipe(concat('main.min.js'))
.pipe(gulp.dest(base + '/js/plugins'));
});
// mincss
var minifycss = require('gulp-minify-css');
gulp.task('minifycss', function() {
gulp.src(base + '/css/bootstrap.css')
.pipe(rename({suffix: '-min'}))
.pipe(minifycss())
.pipe(gulp.dest(base + '/css'));
gulp.src(base + '/css/font-awesome-4.2.0/css/font-awesome.css')
.pipe(rename({suffix: '-min'}))
.pipe(minifycss())
.pipe(gulp.dest(base + '/css/font-awesome-4.2.0/css'));
gulp.src(base + '/css/zTreeStyle/zTreeStyle.css')
.pipe(rename({suffix: '-min'}))
.pipe(minifycss())
.pipe(gulp.dest(base + '/css/zTreeStyle'));
gulp.src(base + '/dist/themes/default.css')
.pipe(rename({suffix: '-min'}))
.pipe(minifycss())
.pipe(gulp.dest(base + '/dist/themes'));
gulp.src(base + '/js/contextmenu/css/contextmenu.css')
.pipe(rename({suffix: '-min'}))
.pipe(minifycss())
.pipe(gulp.dest(base + '/js/contextmenu/css'));
// theme
// 用codekit
var as = ['default', 'simple', 'writting', /*'writting-overwrite', */ 'mobile'];
/*
for(var i = 0; i < as.length; ++i) {
gulp.src(base + '/css/theme/' + as[i] + '.css')
.pipe(minifycss())
.pipe(gulp.dest(base + '/css/theme'));
}
*/
});
// tinymce // tinymce
// please set the right path on your own env // please set the right path on your own env
var tinymceBase = '/Users/life/leanote/leanote-tools/tinymce_4.1.9_leanote_public'; var tinymceBase = '/Users/life/leanote/leanote-tools/tinymce_4.1.9_leanote_public';
@@ -340,6 +363,47 @@ gulp.task('concatCss', function() {
.pipe(gulp.dest(markdownMin)); .pipe(gulp.dest(markdownMin));
}); });
gulp.task('concat', ['concatDepJs', 'concatAppJs', 'concatMarkdownJs']); // mincss
var minifycss = require('gulp-minify-css');
gulp.task('minifycss', function() {
gulp.src(base + '/css/bootstrap.css')
.pipe(rename({suffix: '-min'}))
.pipe(minifycss())
.pipe(gulp.dest(base + '/css'));
gulp.src(base + '/css/font-awesome-4.2.0/css/font-awesome.css')
.pipe(rename({suffix: '-min'}))
.pipe(minifycss())
.pipe(gulp.dest(base + '/css/font-awesome-4.2.0/css'));
gulp.src(base + '/css/zTreeStyle/zTreeStyle.css')
.pipe(rename({suffix: '-min'}))
.pipe(minifycss())
.pipe(gulp.dest(base + '/css/zTreeStyle'));
gulp.src(base + '/md/themes/default.css')
.pipe(rename({suffix: '-min'}))
.pipe(minifycss())
.pipe(gulp.dest(base + '/md/themes'));
gulp.src(base + '/js/contextmenu/css/contextmenu.css')
.pipe(rename({suffix: '-min'}))
.pipe(minifycss())
.pipe(gulp.dest(base + '/js/contextmenu/css'));
// theme
// 用codekit
var as = ['default', 'simple', 'writting', /*'writting-overwrite', */ 'mobile'];
/*
for(var i = 0; i < as.length; ++i) {
gulp.src(base + '/css/theme/' + as[i] + '.css')
.pipe(minifycss())
.pipe(gulp.dest(base + '/css/theme'));
}
*/
});
gulp.task('concat', ['concatDepJs', 'concatAppJs', /* 'concatMarkdownJs', */'concatMarkdownJsV2']);
gulp.task('html', ['devToProHtml']); gulp.task('html', ['devToProHtml']);
gulp.task('default', ['concat', 'plugins', 'minifycss', 'i18n', 'concatAlbumJs', 'html']); gulp.task('default', ['concat', 'plugins', 'minifycss', 'i18n', 'concatAlbumJs', 'html']);
+91 -69
View File
@@ -1,72 +1,87 @@
# Leanote # 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) [![Build Status](https://travis-ci.org/leanote/leanote.svg)](https://travis-ci.org/leanote/leanote)
[![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/leanote/leanote?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
## 1. Introduction ## 1. Introduction
Leanote, Not Just A Notepad! Leanote, not just a notepad!
![leanote.png](leanote.png "") ![leanote.png](leanote.png "")
**Some Features** **Highlighted Features**
* Knowledge: Manage your knowledge in Leanote. Leanote contains the tinymce editor and a markdown editor, just enjoy yourself writing. * Note-taking made easy: Leanote incorporates a clean and intuitive interface, the `tinymce` rich-text editor and a dedicated *markdown* editor, making your writing/typing more efficient and enjoyable. For more advanced users, we even offer `Vim` and `Emacs` writing modes to help boost your writing speed to another level.
* Share: Share your knowledge with your friends in Leanote. You can invite your friends to join your notepad in the cloud so you can share knowledge. * Knowledge management: The flexible and versatile notebook-note-tagging system of Leanote makes it an ideal tool for knowledge management.
* Cooperation: Collaborate with friends to improve your skills. * Sharing: Share your knowledge, thoughts and experiences with friends via Leanote. Invite your friends to join your notepad in the cloud.
* Blog: Publish your knowledge and make Leanote your blog. * Cooperating: Collaborate with colleagues to improve skills, fertilize ideas and brainstorm on the fly.
* Blogging: Publish your work and make Leanote your personal blog.
**Other Features** **Other Features**
* Support Markdown * Markdown syntax support
* Writting mode * Distraction-free writing mode
* Export note to PDF * `Vim` and `Emacs` editing mode
* Note batch operation * Export notes to PDFs
* Custom theme for blog * Batch note operation
* Customizable themes for blogging
## 2. Why we created Leanote ## 2. Why we create Leanote
To be honest, our inspiration comes from Evernote. We use Evernote to manage our knowledge everyday. But we find that:
* Evernote's editor can't meet our needs, it does not have document navigation, it does not render code properly (as a programmer, syntax highlighted code rendering is a basic need), it cannot resize images and so forth We have been using the popular note-taking software/service `Evernote` as our knowledge management tool on a daily basis. Benefited from and inspired by `Evernote`, we decided to create a brand-new tool that provides everything `Evernote` has to offer, plus a bunch of new features that `Evernote` failed to deliver, such as:
* We like markdown, but Evernote does not support it.
* We want to share our knowledge, so all of us have our blogs (e.g. on Wordpress) and our Evernote accounts, but why can not those two be one! * 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!
* 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.
* 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!
* ...... * ......
## 3. How to install Leanote ## 3. How to get Leanote
Leanote contains: 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 all the products are open source! The Leanote software suite contains: 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).
You can install Leanote on your server, and use Leanote App (Desktop, iOs, Android) to sync notes with your self-hosted server. Interested in our product and want to try it out from your web browser? Welcome to sign up on https://leanote.com.
Welcome to sign up on https://leanote.com, Leanote team provide a stable and reliable service for you. Feeling suspicious about how those note-taking companies treat your personal data? You can install Leanote on your server, and use Leanote App (Desktop, iOS, Android) to sync notes with your self-hosted server.
More information about how to install Leanote please see: More information about how to install Leanote please see:
* [Leanote binary distribution installation tutorial](https://github.com/leanote/leanote/wiki/leanote-binary-distribution-installation-tutorial) * Leanote binary installation tutorial:
* [Leanote develop distribution installation tutorial](https://github.com/leanote/leanote/wiki/leanote-develop-distribution-installation-tutorial) * [Windows](https://github.com/leanote/leanote/wiki/leanote-source-installation-on-Windows-(En))
* [Mac and Linux](https://github.com/leanote/leanote/wiki/leanote-binary-installation-on-Mac-and-Linux-(En))
* Leanote source installation tutorial:
* [Windows](https://github.com/leanote/leanote/wiki/leanote-source-installation-on-Windows-(En))
* [Mac and Linux](https://github.com/leanote/leanote/wiki/Leanote-source-installation-on-Mac-and-Linux-(En))
## 4. How to develop Leanote ## 4. Documentation
Please see [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) Please see [wiki](https://github.com/leanote/leanote/wiki) for detailed instruction on how to install Leanote on various platforms, trouble shooting and configuration explanations.
## 5. Docs
* [Leanote binary distribution installation tutorial](https://github.com/leanote/leanote/wiki/leanote-binary-distribution-installation-tutorial)
* [Leanote develop distribution installation tutorial](https://github.com/leanote/leanote/wiki/leanote-develop-distribution-installation-tutorial)
More docs please see [wiki](https://github.com/leanote/leanote/wiki). ## 5. How to develop Leanote
## 6. Contributors If you are a developer yourself and feel like to build on top of Leanote, please refer to [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).
Thank you to all the [contributors](https://github.com/leanote/leanote/graphs/contributors) on
this project. Your help is much appreciated.
## 7.Join us
Please fork this repository and contribute back using [pull requests](https://github.com/leanote/leanote/pulls). ## 6. Contributions
If you find some problems or has some good ideas, please submit [issues](https://github.com/leanote/leanote/issues). 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.
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.
## 7. Join us
Please feel free to fork this repository and contribute back using [pull requests](https://github.com/leanote/leanote/pulls).
If you find any problems or have any good ideas, feature requests, please submit here [issues](https://github.com/leanote/leanote/issues).
You are always welcomed!
## 8. Donation ## 8. Donation
Support us, [donate us](http://leanote.org/#donate). And thanks [donators](http://leanote.leanote.com/post/leanote-donation-list).
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).
## 9. Related projects ## 9. Related projects
@@ -74,14 +89,14 @@ Support us, [donate us](http://leanote.org/#donate). And thanks [donators](http:
* [Leanote iOS](https://github.com/leanote/leanote-ios), [Download From App Store](https://itunes.apple.com/en/app/leanote/id1022302858?mt=8) * [Leanote iOS](https://github.com/leanote/leanote-ios), [Download From App Store](https://itunes.apple.com/en/app/leanote/id1022302858?mt=8)
* [Leanote Android](https://github.com/leanote/leanote-android), development phase * [Leanote Android](https://github.com/leanote/leanote-android), development phase
Yare are welcome to join us. You are welcome to join us.
## 9. Support & Join us ## 10. Contacts
* Email: leanote@leanote.com * Email: leanote@leanote.com
* [Leanote BBS](http://bbs.leanote.com) * [Leanote BBS](http://bbs.leanote.com)
* [Leanote Google Group](https://groups.google.com/forum/#!forum/leanote) * [Leanote Google Group](https://groups.google.com/forum/#!forum/leanote)
* QQ Group: 256076853, 158716820 * QQ Groups: 326073529, 256076853, 158716820
----------------------------------------------------------------------- -----------------------------------------------------------------------
@@ -93,64 +108,71 @@ Leanote, 不只是笔记!
**特性** **特性**
* 知识管理: 通过Leanote来管理知识, Leanote有易操作的界面, 包含两款编辑器富文本编辑器和Markdown编辑器. 在Leanote, 你可以尽情享受写作. * 高效笔记:Leanote 有易操作的界面, 包含一款富文本编辑器和Markdown编辑器,让您的笔记记录更轻松和高效。对高阶用户,我们还提供`Vim` 和`Emacs` 编辑模式,助推你的写作速度更上层楼。
* 博客: Leanote也可以作为你的博客, 将知识公开成博客, 让Leanote把你的知识传播的更远! * 知识管理: Leanote 灵活而强大的“笔记本-笔记-标签”系统,让它成为你个人知识管理的利器。
* 分享: 你也可以通过分享知识给好友, 让好友拥有你的知识. * 分享: 你可以通过Leanote同好友分享知识、想法和经历, 邀请好友加入你的笔记簿,通过云端交流信息。
* 协作: 在分享的同时也可以与好友一起协作知识. * 协作: Leanote协助你与同事之间相互协作,激荡新思路,随时随地头脑风暴。
* 博客: Leanote也可以作为你的个人博客, 把你的知识传播的更远!
**一些其它特性** **其它特性**
* 支持Markdown编辑 * 支持Markdown编辑
* 写作模式 * 写作模式
* `Vim` 及 `Emacs` 编辑模式
* 支持PDF导出 * 支持PDF导出
* 支持批量操作 * 支持批量操作
* 博客自定义主题, 实现高度定制化 * 博客自定义主题, 实现高度定制化
## 2. 为什么我们要创建Leanote? ## 2. 为什么我们要创建Leanote?
说实话, 我们曾是evernote的忠实粉丝, 但是我们也发现evernote的不足: 我们都曾是`Evernote`的忠实粉丝, 一直以来`Evernote`都是我们日常知识管理的有效工具。于是我们决定重新创造一款工具,提供`Evernote`所能提供的功能,同时弥补`Evernote`的不足,比如:
* evernote的编辑器不能满足我们的需求, 不能贴代码(格式会乱掉, 作为程序员, 代码是我们的基本需求啊), 图片不能缩放. * 功能更强的文本编辑器:`Evernote`的编辑器不能满足我们的需求, 不能实现文档导航、不能贴代码(格式会乱掉, 作为程序员, 代码是我们的基本需求啊), 图片不能缩放等。
* 我们是markdown的爱好者, 可是evernote竟然没有. * `Evernote` 不支持所有人都喜爱的markdown语法,于是我们为Leanote配备了一款可以实时渲染的markdown编辑器。
* 我们也想将知识公开, 所以我们有自己的博客, 如wordpress, 但为什么这两者不能合二为一呢? * 如果你是一名开发者,觉得手指怀念`Vim` 或 `Emacs` 了,那么我们还提供给你`Vim` 和 `Emacs` 写作模式,配合*markdown*的格式编辑,写作的时候再也不用去碰鼠标了。
* 知识积累和知识分享同样重要,因此大家都有自己的笔记账号和社交账号。但为什么这两者不能合二为一呢? Leanote 做到了将二者无缝衔接。
* 一套完整的、全平台覆盖的软件套装,包括了web、桌面、安卓、IOS设备,而且全部开源!
* 还有... * 还有...
## 3.安装Leanote ## 3. 获取Leanote
Leanote云笔记产品包括: Leanote Web & Server(即本仓库), 桌面客户端, ios, android. 4端全部开源! 你可以下载它安装在自己的服务器上, Leanote的客户端可以连接自建的服务. Leanote云笔记产品包括: Leanote Web & Server(即本仓库), 桌面客户端, IOS, android. 4端全部开源!
欢迎在 https://leanote.com 上注册, Leanote团队为你提供稳定可靠的服务. 如果想试用我们的产品,欢迎在 https://leanote.com 上注册, Leanote团队为你提供稳定可靠的服务。
担心服务厂商如何处理你的个人数据吗?你可以下载Leanote安装在自己的服务器上, 通过Leanote客户端连接与自建服务同步数据。
这里详细整理了Leanote二进版和Leanote开发版的安装教程, 请移步至: 这里详细整理了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二进制详细安装教程:
* [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) * [Windows](https://github.com/leanote/leanote/wiki/Leanote%E4%BA%8C%E8%BF%9B%E5%88%B6%E7%89%88%E5%AE%89%E8%A3%85%E6%95%99%E7%A8%8B---Windows)
* [Mac, Linux](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源码详细安装教程:
* [Windows](https://github.com/leanote/leanote/wiki/Leanote-%E6%BA%90%E7%A0%81%E7%89%88%E8%AF%A6%E7%BB%86%E5%AE%89%E8%A3%85%E6%95%99%E7%A8%8B----Windows)
* [Mac, Linux](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进行二次开发 ## 4. 相关文档
请查看 [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) 更多详细的安装说明、问题处理和配置说明文档,请查看 [wiki](https://github.com/leanote/leanote/wiki)。
## 5 相关文档 ## 5. 如何对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)
* [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). 如果您有兴趣基于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)。
## 6. 贡献者 ## 6. 贡献者
谢谢 [贡献者](https://github.com/leanote/leanote/graphs/contributors) 的贡献, Leanote因有你们而更完美! 在此对向Leanote贡献力量的[贡献者们](https://github.com/leanote/leanote/graphs/contributors) 表示感谢。Leanote因有你们而更完美!
## 7. 加入我们 ## 7. 加入我们
欢迎提交[pull requests](https://github.com/leanote/leanote/pulls) 到Leanote. 欢迎提交[pull requests](https://github.com/leanote/leanote/pulls) 到Leanote。
有任何问题或建议, 欢迎提交[issue](https://github.com/leanote/leanote/issues). 有任何问题或建议, 请先搜索[issue](https://github.com/leanote/leanote/issues)区是否已经有解决方法。如果没有,欢迎提交新issue。
Leanote还有很多问题, 如果你喜欢它, 欢迎加入我们一起完善Leanote. Leanote还有很多问题, 如果你喜欢它, 欢迎加入我们一起完善Leanote。
## 8. 捐赠 ## 8. 捐赠
支持我们, [捐赠Leanote](http://leanote.org/#donate). 感谢[捐赠者](http://leanote.leanote.com/post/leanote-donation-list), 谢谢你们的鼓励, Leanote会一直坚持!
如果您喜欢我们的产品,请考虑支持我们, [捐赠Leanote](http://leanote.org/#donate)。
感谢[这些捐赠者](http://leanote.leanote.com/post/leanote-donation-list), 谢谢你们的鼓励, Leanote会一直坚持!
## 9. 其它相关项目 ## 9. 其它相关项目
* [Leanote Desktop App](https://github.com/leanote/desktop-app), [下载地址](http://app.leanote.com) * [Leanote Desktop App](https://github.com/leanote/desktop-app), [下载地址](http://app.leanote.com)
@@ -162,6 +184,6 @@ Leanote还有很多问题, 如果你喜欢它, 欢迎加入我们一起完善Lea
## 联系&加入我们 ## 联系&加入我们
* Email: leanote@leanote.com * Email: leanote@leanote.com
* [Leanote 社区](http://bbs.leanote.com) * [Leanote 社区](http://bbs.leanote.com)
* QQ群: 256076853, 158716820(已满) * QQ群: 326073529, 256076853, 158716820
* [Leanote Google Group](https://groups.google.com/forum/#!forum/leanote) * [Leanote Google Group](https://groups.google.com/forum/#!forum/leanote)
+3 -3
View File
@@ -1,9 +1,9 @@
package main package main
import ( import (
"github.com/revel/revel"
"github.com/revel/cmd/harness"
"fmt" "fmt"
"github.com/revel/cmd/harness"
"github.com/revel/revel"
) )
func main() { func main() {
@@ -15,5 +15,5 @@ func main() {
panic(err) panic(err)
} }
fmt.Println("Ok") fmt.Println("Ok")
// panicOnError(reverr, "Failed to build") // panicOnError(reverr, "Failed to build")
} }
+1 -1
View File
@@ -16,7 +16,7 @@ type Album struct {
// 图片管理, iframe // 图片管理, iframe
func (c Album) Index() revel.Result { func (c Album) Index() revel.Result {
c.SetLocale(); c.SetLocale()
return c.RenderTemplate("album/index.html") return c.RenderTemplate("album/index.html")
} }
+79 -71
View File
@@ -2,18 +2,18 @@ package controllers
import ( import (
"github.com/revel/revel" "github.com/revel/revel"
// "encoding/json" // "encoding/json"
"gopkg.in/mgo.v2/bson" "archive/tar"
. "github.com/leanote/leanote/app/lea" "compress/gzip"
"fmt"
"github.com/leanote/leanote/app/info" "github.com/leanote/leanote/app/info"
. "github.com/leanote/leanote/app/lea"
"gopkg.in/mgo.v2/bson"
"io"
"io/ioutil" "io/ioutil"
"os" "os"
"strings" "strings"
"time" "time"
"io"
"fmt"
"archive/tar"
"compress/gzip"
) )
// 附件 // 附件
@@ -57,18 +57,20 @@ func (c Attach) uploadAttach(noteId string) (re info.Re) {
return re return re
} }
// > 5M? // > 5M?
maxFileSize := configService.GetUploadSize("uploadAttachSize"); maxFileSize := configService.GetUploadSize("uploadAttachSize")
if maxFileSize <= 0 { if maxFileSize <= 0 {
maxFileSize = 1000 maxFileSize = 1000
} }
if(float64(len(data)) > maxFileSize * float64(1024*1024)) { if float64(len(data)) > maxFileSize*float64(1024*1024) {
resultMsg = fmt.Sprintf("The file's size is bigger than %vM", maxFileSize) resultMsg = fmt.Sprintf("The file's size is bigger than %vM", maxFileSize)
return re return re
} }
// 生成上传路径 // 生成上传路径
filePath := "files/" + c.GetUserId() + "/attachs" // filePath := "files/" + c.GetUserId() + "/attachs"
dir := revel.BasePath + "/" + filePath newGuid := NewGuid()
filePath := "files/" + GetRandomFilePath(c.GetUserId(), newGuid) + "/attachs"
dir := revel.BasePath + "/" + filePath
err = os.MkdirAll(dir, 0755) err = os.MkdirAll(dir, 0755)
if err != nil { if err != nil {
return re return re
@@ -76,8 +78,8 @@ func (c Attach) uploadAttach(noteId string) (re info.Re) {
// 生成新的文件名 // 生成新的文件名
filename := handel.Filename filename := handel.Filename
_, ext := SplitFilename(filename) // .doc _, ext := SplitFilename(filename) // .doc
filename = NewGuid() + ext filename = newGuid + ext
toPath := dir + "/" + filename; toPath := dir + "/" + filename
err = ioutil.WriteFile(toPath, data, 0777) err = ioutil.WriteFile(toPath, data, 0777)
if err != nil { if err != nil {
return re return re
@@ -90,14 +92,14 @@ func (c Attach) uploadAttach(noteId string) (re info.Re) {
} }
filesize := GetFilesize(toPath) filesize := GetFilesize(toPath)
fileInfo = info.Attach{Name: filename, fileInfo = info.Attach{Name: filename,
Title: handel.Filename, Title: handel.Filename,
NoteId: bson.ObjectIdHex(noteId), NoteId: bson.ObjectIdHex(noteId),
UploadUserId: c.GetObjectUserId(), UploadUserId: c.GetObjectUserId(),
Path: filePath + "/" + filename, Path: filePath + "/" + filename,
Type: fileType, Type: fileType,
Size: filesize} Size: filesize}
id := bson.NewObjectId(); id := bson.NewObjectId()
fileInfo.AttachId = id fileInfo.AttachId = id
fileId = id.Hex() fileId = id.Hex()
Ok, resultMsg = attachService.AddAttach(fileInfo, false) Ok, resultMsg = attachService.AddAttach(fileInfo, false)
@@ -105,7 +107,7 @@ func (c Attach) uploadAttach(noteId string) (re info.Re) {
resultMsg = c.Message(resultMsg) resultMsg = c.Message(resultMsg)
} }
fileInfo.Path = ""; // 不要返回 fileInfo.Path = "" // 不要返回
if Ok { if Ok {
resultMsg = "success" resultMsg = "success"
} }
@@ -130,15 +132,15 @@ func (c Attach) GetAttachs(noteId string) revel.Result {
// 下载附件 // 下载附件
// 权限判断 // 权限判断
func (c Attach) Download(attachId string) revel.Result { func (c Attach) Download(attachId string) revel.Result {
attach := attachService.GetAttach(attachId, c.GetUserId()); // 得到路径 attach := attachService.GetAttach(attachId, c.GetUserId()) // 得到路径
path := attach.Path path := attach.Path
if path == "" { if path == "" {
return c.RenderText("") return c.RenderText("")
} }
fn := revel.BasePath + "/" + strings.TrimLeft(path, "/") fn := revel.BasePath + "/" + strings.TrimLeft(path, "/")
file, _ := os.Open(fn) file, _ := os.Open(fn)
return c.RenderBinary(file, attach.Title, revel.Attachment, time.Now()) // revel.Attachment return c.RenderBinary(file, attach.Title, revel.Attachment, time.Now()) // revel.Attachment
// return c.RenderFile(file, revel.Attachment) // revel.Attachment // return c.RenderFile(file, revel.Attachment) // revel.Attachment
} }
func (c Attach) DownloadAll(noteId string) revel.Result { func (c Attach) DownloadAll(noteId string) revel.Result {
@@ -153,11 +155,11 @@ func (c Attach) DownloadAll(noteId string) revel.Result {
} }
/* /*
dir := revel.BasePath + "/files/tmp" dir := revel.BasePath + "/files/tmp"
err := os.MkdirAll(dir, 0755) err := os.MkdirAll(dir, 0755)
if err != nil { if err != nil {
return c.RenderText("") return c.RenderText("")
} }
*/ */
filename := note.Title + ".tar.gz" filename := note.Title + ".tar.gz"
@@ -165,55 +167,61 @@ func (c Attach) DownloadAll(noteId string) revel.Result {
filename = "all.tar.gz" filename = "all.tar.gz"
} }
dir := revel.BasePath + "/files/attach_all"
if !MkdirAll(dir) {
return c.RenderText("error")
}
// file write // file write
fw, err := os.Create(revel.BasePath + "/files/" + filename) fw, err := os.Create(dir + "/" + filename)
if err != nil { if err != nil {
return c.RenderText("") return c.RenderText("error")
} }
// defer fw.Close() // 不需要关闭, 还要读取给用户下载 // defer fw.Close() // 不需要关闭, 还要读取给用户下载
// gzip write // gzip write
gw := gzip.NewWriter(fw) gw := gzip.NewWriter(fw)
defer gw.Close() defer gw.Close()
// tar write // tar write
tw := tar.NewWriter(gw) tw := tar.NewWriter(gw)
defer tw.Close() defer tw.Close()
// 遍历文件列表 // 遍历文件列表
for _, attach := range attachs { for _, attach := range attachs {
fn := revel.BasePath + "/" + strings.TrimLeft(attach.Path, "/") fn := revel.BasePath + "/" + strings.TrimLeft(attach.Path, "/")
fr, err := os.Open(fn) fr, err := os.Open(fn)
fileInfo, _ := fr.Stat() fileInfo, _ := fr.Stat()
if err != nil { if err != nil {
return c.RenderText("") return c.RenderText("")
} }
defer fr.Close() defer fr.Close()
// 信息头 // 信息头
h := new(tar.Header) h := new(tar.Header)
h.Name = attach.Title h.Name = attach.Title
h.Size = fileInfo.Size() h.Size = fileInfo.Size()
h.Mode = int64(fileInfo.Mode()) h.Mode = int64(fileInfo.Mode())
h.ModTime = fileInfo.ModTime() h.ModTime = fileInfo.ModTime()
// 写信息头 // 写信息头
err = tw.WriteHeader(h) err = tw.WriteHeader(h)
if err != nil { if err != nil {
panic(err) panic(err)
} }
// 写文件 // 写文件
_, err = io.Copy(tw, fr) _, err = io.Copy(tw, fr)
if err != nil { if err != nil {
panic(err) panic(err)
} }
} // for } // for
// tw.Close() // tw.Close()
// gw.Close() // gw.Close()
// fw.Close() // fw.Close()
// file, _ := os.Open(dir + "/" + filename) // file, _ := os.Open(dir + "/" + filename)
// fw.Seek(0, 0) // fw.Seek(0, 0)
return c.RenderBinary(fw, filename, revel.Attachment, time.Now()) // revel.Attachment return c.RenderBinary(fw, filename, revel.Attachment, time.Now()) // revel.Attachment
} }
+21 -13
View File
@@ -1,10 +1,11 @@
package controllers package controllers
import ( import (
"github.com/revel/revel"
"github.com/leanote/leanote/app/info" "github.com/leanote/leanote/app/info"
. "github.com/leanote/leanote/app/lea" . "github.com/leanote/leanote/app/lea"
// "strconv" "github.com/revel/revel"
"strings"
// "strconv"
) )
// 用户登录/注销/找回密码 // 用户登录/注销/找回密码
@@ -51,7 +52,7 @@ func (c Auth) doLogin(email, pwd string) revel.Result {
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()
@@ -66,15 +67,16 @@ func (c Auth) DoLogin(email, pwd string, captcha string) revel.Result {
// 登录错误, 则错误次数++ // 登录错误, 则错误次数++
msg = "wrongUsernameOrPassword" msg = "wrongUsernameOrPassword"
sessionService.IncrLoginTimes(sessionId) sessionService.IncrLoginTimes(sessionId)
} 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()
@@ -90,8 +92,8 @@ 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")
} }
@@ -117,15 +119,17 @@ func (c Auth) DoRegister(email, pwd, iu string) revel.Result {
return c.Redirect("/index") return c.Redirect("/index")
} }
re := info.NewRe(); re := info.NewRe()
if re.Ok, re.Msg = Vd("email", email); !re.Ok { if re.Ok, re.Msg = Vd("email", email); !re.Ok {
return c.RenderRe(re); return c.RenderRe(re)
} }
if re.Ok, re.Msg = Vd("password", pwd); !re.Ok { if re.Ok, re.Msg = Vd("password", pwd); !re.Ok {
return c.RenderRe(re); return c.RenderRe(re)
} }
email = strings.ToLower(email)
// 注册 // 注册
re.Ok, re.Msg = authService.Register(email, pwd, iu) re.Ok, re.Msg = authService.Register(email, pwd, iu)
@@ -140,6 +144,7 @@ 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.RenderArgs["title"] = c.Message("findPassword") c.RenderArgs["title"] = c.Message("findPassword")
c.RenderArgs["subTitle"] = c.Message("findPassword") c.RenderArgs["subTitle"] = c.Message("findPassword")
return c.RenderTemplate("home/find_password.html") return c.RenderTemplate("home/find_password.html")
@@ -150,14 +155,16 @@ func (c Auth) DoFindPassword(email string) revel.Result {
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.RenderArgs["title"] = c.Message("findPassword") c.RenderArgs["title"] = c.Message("findPassword")
c.RenderArgs["subTitle"] = c.Message("findPassword") c.RenderArgs["subTitle"] = c.Message("findPassword")
if token == "" { if token == "" {
return c.RenderTemplate("find_password2_timeout.html") return c.RenderTemplate("find_password2_timeout.html")
} }
ok, _, findPwd := tokenService.VerifyToken(token, info.TokenPwd); ok, _, findPwd := tokenService.VerifyToken(token, info.TokenPwd)
if !ok { if !ok {
return c.RenderTemplate("home/find_password2_timeout.html") return c.RenderTemplate("home/find_password2_timeout.html")
} }
@@ -168,12 +175,13 @@ func (c Auth) FindPassword2(token string) revel.Result {
return c.RenderTemplate("home/find_password2.html") return c.RenderTemplate("home/find_password2.html")
} }
// 找回密码修改密码 // 找回密码修改密码
func (c Auth) FindPasswordUpdate(token, pwd string) revel.Result { func (c Auth) FindPasswordUpdate(token, pwd string) revel.Result {
re := info.NewRe(); re := info.NewRe()
if re.Ok, re.Msg = Vd("password", pwd); !re.Ok { if re.Ok, re.Msg = Vd("password", pwd); !re.Ok {
return c.RenderRe(re); return c.RenderRe(re)
} }
// 修改之 // 修改之
+54 -44
View File
@@ -1,17 +1,18 @@
package controllers package controllers
import ( import (
"github.com/revel/revel"
"gopkg.in/mgo.v2/bson"
"encoding/json" "encoding/json"
"github.com/leanote/leanote/app/info" "github.com/leanote/leanote/app/info"
// . "github.com/leanote/leanote/app/lea" "github.com/leanote/leanote/app/lea/i18n"
// "io/ioutil" "github.com/revel/revel"
// "fmt" "gopkg.in/mgo.v2/bson"
// . "github.com/leanote/leanote/app/lea"
// "io/ioutil"
// "fmt"
"bytes"
"math" "math"
"strconv" "strconv"
"strings" "strings"
"bytes"
) )
// 公用Controller, 其它Controller继承它 // 公用Controller, 其它Controller继承它
@@ -19,6 +20,11 @@ type BaseController struct {
*revel.Controller *revel.Controller
} }
// 覆盖revel.Message
func (c *BaseController) Message(message string, args ...interface{}) (value string) {
return i18n.Message(c.Request.Locale, message, args...)
}
func (c BaseController) GetUserId() string { func (c BaseController) GetUserId() string {
if userId, ok := c.Session["UserId"]; ok { if userId, ok := c.Session["UserId"]; ok {
return userId return userId
@@ -56,29 +62,29 @@ func (c BaseController) GetUsername() string {
// 得到用户信息 // 得到用户信息
func (c BaseController) GetUserInfo() info.User { func (c BaseController) GetUserInfo() info.User {
if userId, ok := c.Session["UserId"]; ok && userId != "" { if userId, ok := c.Session["UserId"]; ok && userId != "" {
return userService.GetUserInfo(userId); return userService.GetUserInfo(userId)
/* /*
notebookWidth, _ := strconv.Atoi(c.Session["NotebookWidth"]) notebookWidth, _ := strconv.Atoi(c.Session["NotebookWidth"])
noteListWidth, _ := strconv.Atoi(c.Session["NoteListWidth"]) noteListWidth, _ := strconv.Atoi(c.Session["NoteListWidth"])
mdEditorWidth, _ := strconv.Atoi(c.Session["MdEditorWidth"]) mdEditorWidth, _ := strconv.Atoi(c.Session["MdEditorWidth"])
LogJ(c.Session) LogJ(c.Session)
user := info.User{UserId: bson.ObjectIdHex(userId), user := info.User{UserId: bson.ObjectIdHex(userId),
Email: c.Session["Email"], Email: c.Session["Email"],
Logo: c.Session["Logo"], Logo: c.Session["Logo"],
Username: c.Session["Username"], Username: c.Session["Username"],
UsernameRaw: c.Session["UsernameRaw"], UsernameRaw: c.Session["UsernameRaw"],
Theme: c.Session["Theme"], Theme: c.Session["Theme"],
NotebookWidth: notebookWidth, NotebookWidth: notebookWidth,
NoteListWidth: noteListWidth, NoteListWidth: noteListWidth,
MdEditorWidth: mdEditorWidth, MdEditorWidth: mdEditorWidth,
}
if c.Session["Verified"] == "1" {
user.Verified = true
} }
if c.Session["Verified"] == "1" { if c.Session["LeftIsMin"] == "1" {
user.Verified = true user.LeftIsMin = true
} }
if c.Session["LeftIsMin"] == "1" { return user
user.LeftIsMin = true
}
return user
*/ */
} }
return info.User{} return info.User{}
@@ -86,7 +92,7 @@ func (c BaseController) GetUserInfo() info.User {
func (c BaseController) GetUserAndBlogUrl() info.UserAndBlogUrl { func (c BaseController) GetUserAndBlogUrl() info.UserAndBlogUrl {
if userId, ok := c.Session["UserId"]; ok && userId != "" { if userId, ok := c.Session["UserId"]; ok && userId != "" {
return userService.GetUserAndBlogUrl(userId); return userService.GetUserAndBlogUrl(userId)
} }
return info.UserAndBlogUrl{} return info.UserAndBlogUrl{}
} }
@@ -139,7 +145,7 @@ func (c BaseController) UpdateSession(key, value string) {
// 返回json // 返回json
func (c BaseController) Json(i interface{}) string { func (c BaseController) Json(i interface{}) string {
// b, _ := json.MarshalIndent(i, "", " ") // b, _ := json.MarshalIndent(i, "", " ")
b, _ := json.Marshal(i) b, _ := json.Marshal(i)
return string(b) return string(b)
} }
@@ -157,9 +163,9 @@ func (c BaseController) GetPage() int {
// 判断是否含有某参数 // 判断是否含有某参数
func (c BaseController) Has(key string) bool { func (c BaseController) Has(key string) bool {
if _, ok := c.Params.Values[key]; ok { if _, ok := c.Params.Values[key]; ok {
return true; return true
} }
return false; return false
} }
/* /*
@@ -169,28 +175,32 @@ func (c Blog) GetPage(page, count int, list interface{}) info.Page {
*/ */
func (c BaseController) GetTotalPage(page, count int) int { func (c BaseController) GetTotalPage(page, count int) int {
return int(math.Ceil(float64(count)/float64(page))) return int(math.Ceil(float64(count) / float64(page)))
} }
//------------- //-------------
func (c BaseController) E404() revel.Result { func (c BaseController) E404() revel.Result {
c.RenderArgs["title"] = "404"; c.RenderArgs["title"] = "404"
return c.NotFound("", nil) return c.NotFound("", nil)
} }
// 设置本地 // 设置本地
func (c BaseController) SetLocale() string { func (c BaseController) SetLocale() string {
locale := string(c.Request.Locale) // zh-CN locale := string(c.Request.Locale) // zh-CN
// lang := locale
// if strings.Contains(locale, "-") {
// pos := strings.Index(locale, "-")
// lang = locale[0:pos]
// }
// if lang != "zh" && lang != "en" {
// lang = "en"
// }
lang := locale lang := locale
if strings.Contains(locale, "-") { if !i18n.HasLang(locale) {
pos := strings.Index(locale, "-") lang = i18n.GetDefaultLang()
lang = locale[0:pos]
} }
if lang != "zh" && lang != "en" { c.RenderArgs["locale"] = lang
lang = "en"; c.RenderArgs["siteUrl"] = configService.GetSiteUrl()
}
c.RenderArgs["locale"] = lang;
c.RenderArgs["siteUrl"] = configService.GetSiteUrl();
c.RenderArgs["blogUrl"] = configService.GetBlogUrl() c.RenderArgs["blogUrl"] = configService.GetBlogUrl()
c.RenderArgs["leaUrl"] = configService.GetLeaUrl() c.RenderArgs["leaUrl"] = configService.GetLeaUrl()
@@ -203,7 +213,7 @@ func (c BaseController) SetLocale() string {
func (c BaseController) SetUserInfo() info.User { func (c BaseController) SetUserInfo() info.User {
userInfo := c.GetUserInfo() userInfo := c.GetUserInfo()
c.RenderArgs["userInfo"] = userInfo c.RenderArgs["userInfo"] = userInfo
if(userInfo.Username == configService.GetAdminUsername()) { if userInfo.Username == configService.GetAdminUsername() {
c.RenderArgs["isAdmin"] = true c.RenderArgs["isAdmin"] = true
} }
return userInfo return userInfo
@@ -225,7 +235,7 @@ func (c BaseController) RenderTemplateStr(templatePath string) string {
var buffer bytes.Buffer var buffer bytes.Buffer
tpl.Template.Render(&buffer, c.RenderArgs) tpl.Template.Render(&buffer, c.RenderArgs)
return buffer.String(); return buffer.String()
} }
// json, result // json, result
@@ -234,7 +244,7 @@ func (c BaseController) RenderTemplateStr(templatePath string) string {
func (c BaseController) RenderRe(re info.Re) revel.Result { func (c BaseController) RenderRe(re info.Re) revel.Result {
oldMsg := re.Msg oldMsg := re.Msg
if re.Msg != "" { if re.Msg != "" {
if(strings.Contains(re.Msg, "-")) { if strings.Contains(re.Msg, "-") {
msgAndValues := strings.Split(re.Msg, "-") msgAndValues := strings.Split(re.Msg, "-")
if len(msgAndValues) == 2 { if len(msgAndValues) == 2 {
re.Msg = c.Message(msgAndValues[0], msgAndValues[1]) re.Msg = c.Message(msgAndValues[0], msgAndValues[1])
+25 -24
View File
@@ -59,7 +59,7 @@ 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.RenderArgs["themeInfo"] = c.RenderArgs["themeInfoPreview"]
} }
return blog.RenderTemplate(templateName, c.RenderArgs, revel.BasePath+"/"+themePath, isPreview) return blog.RenderTemplate(templateName, c.RenderArgs, revel.BasePath+"/"+themePath, isPreview)
} }
@@ -113,15 +113,15 @@ func (c Blog) setPreviewUrl() {
themeId := c.Session["themeId"] themeId := c.Session["themeId"]
theme := themeService.GetTheme(userId, themeId) theme := themeService.GetTheme(userId, themeId)
siteUrl := configService.GetSiteUrl() // siteUrl := configService.GetSiteUrl()
blogUrl := siteUrl + "/preview" // blog.leanote.com blogUrl := "/preview" // blog.leanote.com
indexUrl = blogUrl + "/" + userIdOrEmail indexUrl = blogUrl + "/" + userIdOrEmail
cateUrl = blogUrl + "/cate/" + userIdOrEmail // /notebookId cateUrl = blogUrl + "/cate/" + userIdOrEmail // /notebookId
postUrl = blogUrl + "/post/" + userIdOrEmail // /xxxxx postUrl = blogUrl + "/post/" + userIdOrEmail // /xxxxx
searchUrl = blogUrl + "/search/" + userIdOrEmail // blog.leanote.com/search/userId searchUrl = blogUrl + "/search/" + userIdOrEmail // blog.leanote.com/search/userId
singleUrl = blogUrl + "/single/" + userIdOrEmail // blog.leanote.com/single/singleId singleUrl = blogUrl + "/single/" + userIdOrEmail // blog.leanote.com/single/singleId
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
@@ -143,8 +143,8 @@ func (c Blog) setPreviewUrl() {
// 各种地址设置 // 各种地址设置
func (c Blog) setUrl(userBlog info.UserBlog, userInfo info.User) { func (c Blog) setUrl(userBlog info.UserBlog, userInfo info.User) {
// 主页 http://leanote.com/blog/life or http://blog.leanote.com/life or http:// xxxx.leanote.com or aa.com // 主页 http://leanote.com/blog/life or http://blog.leanote.com/life or http:// xxxx.leanote.com or aa.com
host := c.Request.Request.Host // host := c.Request.Request.Host
var staticUrl = configService.GetUserUrl(strings.Split(host, ":")[0]) // var staticUrl = configService.GetUserUrl(strings.Split(host, ":")[0])
// staticUrl == host, 为保证同源!!! 只有host, http://leanote.com, http://blog/leanote.com // staticUrl == host, 为保证同源!!! 只有host, http://leanote.com, http://blog/leanote.com
// life.leanote.com, lealife.com // life.leanote.com, lealife.com
siteUrl := configService.GetSiteUrl() siteUrl := configService.GetSiteUrl()
@@ -168,20 +168,20 @@ func (c Blog) setUrl(userBlog info.UserBlog, userInfo info.User) {
c.RenderArgs["themeBaseUrl"] = "/" + userBlog.ThemePath c.RenderArgs["themeBaseUrl"] = "/" + userBlog.ThemePath
// 其它static js // 其它static js
c.RenderArgs["jQueryUrl"] = siteUrl + "/js/jquery-1.9.0.min.js" c.RenderArgs["jQueryUrl"] = "/js/jquery-1.9.0.min.js"
c.RenderArgs["prettifyJsUrl"] = siteUrl + "/js/google-code-prettify/prettify.js" c.RenderArgs["prettifyJsUrl"] = "/js/google-code-prettify/prettify.js"
c.RenderArgs["prettifyCssUrl"] = siteUrl + "/js/google-code-prettify/prettify.css" c.RenderArgs["prettifyCssUrl"] = "/js/google-code-prettify/prettify.css"
c.RenderArgs["blogCommonJsUrl"] = siteUrl + "/public/blog/js/common.js" c.RenderArgs["blogCommonJsUrl"] = "/public/blog/js/common.js"
c.RenderArgs["shareCommentCssUrl"] = siteUrl + "/public/blog/css/share_comment.css" c.RenderArgs["shareCommentCssUrl"] = "/public/blog/css/share_comment.css"
c.RenderArgs["shareCommentJsUrl"] = siteUrl + "/public/blog/js/share_comment.js" c.RenderArgs["shareCommentJsUrl"] = "/public/blog/js/share_comment.js"
c.RenderArgs["fontAwesomeUrl"] = staticUrl + "/css/font-awesome-4.2.0/css/font-awesome.css" c.RenderArgs["fontAwesomeUrl"] = "/css/font-awesome-4.2.0/css/font-awesome.css"
c.RenderArgs["bootstrapCssUrl"] = siteUrl + "/css/bootstrap.css" c.RenderArgs["bootstrapCssUrl"] = "/css/bootstrap.css"
c.RenderArgs["bootstrapJsUrl"] = siteUrl + "/js/bootstrap-min.js" c.RenderArgs["bootstrapJsUrl"] = "/js/bootstrap-min.js"
} }
// 笔记本分类 // 笔记本分类
@@ -235,8 +235,8 @@ func (c Blog) getCates(userBlog info.UserBlog) {
} }
} }
// LogJ(">>") // LogJ(">>")
// LogJ(cates) // LogJ(cates)
// 建立层级 // 建立层级
hasParent := map[string]bool{} // 有父的cate hasParent := map[string]bool{} // 有父的cate
@@ -244,9 +244,9 @@ func (c Blog) getCates(userBlog info.UserBlog) {
parentCateId := cate.ParentCateId parentCateId := cate.ParentCateId
if parentCateId != "" { if parentCateId != "" {
if parentCate, ok := cateMap[parentCateId]; ok { if parentCate, ok := cateMap[parentCateId]; ok {
// Log("________") // Log("________")
// LogJ(parentCate) // LogJ(parentCate)
// LogJ(cate) // LogJ(cate)
if parentCate.Children == nil { if parentCate.Children == nil {
parentCate.Children = []*info.Cate{cate} parentCate.Children = []*info.Cate{cate}
} else { } else {
@@ -349,9 +349,9 @@ func (c Blog) blogCommon(userId string, userBlog info.UserBlog, userInfo info.Us
themeInfo := themeService.GetThemeInfo(userBlog.ThemeId.Hex(), userBlog.Style) themeInfo := themeService.GetThemeInfo(userBlog.ThemeId.Hex(), userBlog.Style)
c.RenderArgs["themeInfo"] = themeInfo c.RenderArgs["themeInfo"] = themeInfo
// Log(">>") // Log(">>")
// Log(userBlog.Style) // Log(userBlog.Style)
// Log(userBlog.ThemeId.Hex()) // Log(userBlog.ThemeId.Hex())
return true, userBlog return true, userBlog
} }
@@ -507,6 +507,7 @@ func (c Blog) Archives(userIdOrEmail string, cateId string, year, month int) (re
// 进入某个用户的博客 // 进入某个用户的博客
var blogPageSize = 5 var blogPageSize = 5
var searchBlogPageSize = 30 var searchBlogPageSize = 30
// 分类 /cate/xxxxxxxx?notebookId=1212 // 分类 /cate/xxxxxxxx?notebookId=1212
func (c Blog) Cate(userIdOrEmail string, notebookId string) (re revel.Result) { func (c Blog) Cate(userIdOrEmail string, notebookId string) (re revel.Result) {
// 自定义域名 // 自定义域名
+16 -15
View File
@@ -2,17 +2,17 @@ package controllers
import ( import (
"github.com/revel/revel" "github.com/revel/revel"
// "encoding/json" // "encoding/json"
// "gopkg.in/mgo.v2/bson" // "gopkg.in/mgo.v2/bson"
. "github.com/leanote/leanote/app/lea" . "github.com/leanote/leanote/app/lea"
"github.com/leanote/leanote/app/lea/captcha" "github.com/leanote/leanote/app/lea/captcha"
// "github.com/leanote/leanote/app/types" // "github.com/leanote/leanote/app/types"
// "io/ioutil" // "io/ioutil"
// "fmt" // "fmt"
// "math" // "math"
// "os" // "os"
// "path" // "path"
// "strconv" // "strconv"
"net/http" "net/http"
) )
@@ -22,8 +22,9 @@ type Captcha struct {
} }
type Ca string type Ca string
func (r Ca) Apply(req *revel.Request, resp *revel.Response) { func (r Ca) Apply(req *revel.Request, resp *revel.Response) {
resp.WriteHeader(http.StatusOK, "image/png") resp.WriteHeader(http.StatusOK, "image/png")
} }
func (c Captcha) Get() revel.Result { func (c Captcha) Get() revel.Result {
@@ -32,11 +33,11 @@ func (c Captcha) Get() revel.Result {
image.WriteTo(c.Response.Out) image.WriteTo(c.Response.Out)
sessionId := c.Session["_ID"] sessionId := c.Session["_ID"]
// LogJ(c.Session) // LogJ(c.Session)
// Log("------") // Log("------")
// Log(str) // Log(str)
// Log(sessionId) // Log(sessionId)
Log("..") Log("..")
sessionService.SetCaptcha(sessionId, str) sessionService.SetCaptcha(sessionId, str)
return c.Render() return c.Render()
+35 -30
View File
@@ -2,15 +2,15 @@ package controllers
import ( import (
"github.com/revel/revel" "github.com/revel/revel"
// "encoding/json" // "encoding/json"
"gopkg.in/mgo.v2/bson" "fmt"
"github.com/leanote/leanote/app/info"
. "github.com/leanote/leanote/app/lea" . "github.com/leanote/leanote/app/lea"
"github.com/leanote/leanote/app/lea/netutil" "github.com/leanote/leanote/app/lea/netutil"
"github.com/leanote/leanote/app/info" "gopkg.in/mgo.v2/bson"
"io/ioutil" "io/ioutil"
"os" "os"
"fmt" // "strconv"
// "strconv"
"strings" "strings"
) )
@@ -22,7 +22,7 @@ type File struct {
// 上传的是博客logo // 上传的是博客logo
// TODO logo不要设置权限, 另外的目录 // TODO logo不要设置权限, 另外的目录
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.RenderArgs["fileUrlPath"] = re.Id
c.RenderArgs["resultCode"] = re.Code c.RenderArgs["resultCode"] = re.Code
@@ -34,20 +34,22 @@ func (c File) UploadBlogLogo() revel.Result {
// 拖拉上传, pasteImage // 拖拉上传, pasteImage
// noteId 是为了判断是否是协作的note, 如果是则需要复制一份到note owner中 // noteId 是为了判断是否是协作的note, 如果是则需要复制一份到note owner中
func (c File) PasteImage(noteId string) revel.Result { func (c File) PasteImage(noteId string) revel.Result {
re := c.uploadImage("pasteImage", ""); re := c.uploadImage("pasteImage", "")
userId := c.GetUserId() if noteId != "" {
note := noteService.GetNoteById(noteId) userId := c.GetUserId()
if note.UserId != "" { note := noteService.GetNoteById(noteId)
noteUserId := note.UserId.Hex() if note.UserId != "" {
if noteUserId != userId { noteUserId := note.UserId.Hex()
// 是否是有权限协作的 if noteUserId != userId {
if shareService.HasUpdatePerm(noteUserId, userId, noteId) { // 是否是有权限协作的
// 复制图片之, 图片复制给noteUserId if shareService.HasUpdatePerm(noteUserId, userId, noteId) {
_, re.Id = fileService.CopyImage(userId, re.Id, noteUserId) // 复制图片之, 图片复制给noteUserId
} else { _, re.Id = fileService.CopyImage(userId, re.Id, noteUserId)
// 怎么可能在这个笔记下paste图片呢? } else {
// 正常情况下不会 // 怎么可能在这个笔记下paste图片呢?
// 正常情况下不会
}
} }
} }
} }
@@ -57,7 +59,7 @@ func (c File) PasteImage(noteId string) revel.Result {
// 头像设置 // 头像设置
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.RenderArgs["fileUrlPath"] = re.Id
c.RenderArgs["resultCode"] = re.Code c.RenderArgs["resultCode"] = re.Code
@@ -66,7 +68,7 @@ func (c File) UploadAvatar() revel.Result {
if re.Ok { if re.Ok {
re.Ok = userService.UpdateAvatar(c.GetUserId(), re.Id) re.Ok = userService.UpdateAvatar(c.GetUserId(), re.Id)
if re.Ok { if re.Ok {
c.UpdateSession("Logo", re.Id); c.UpdateSession("Logo", re.Id)
} }
} }
@@ -106,10 +108,11 @@ func (c File) uploadImage(from, albumId string) (re info.Re) {
userId := c.GetUserId() userId := c.GetUserId()
if(from == "logo" || from == "blogLogo") { if from == "logo" || from == "blogLogo" {
fileUrlPath = "public/upload/" + Digest3(userId) + "/" + userId + "/images/logo" fileUrlPath = "public/upload/" + Digest3(userId) + "/" + userId + "/images/logo"
} else { } else {
fileUrlPath = "files/" + Digest3(userId) + "/" + userId + "/" + Digest2(newGuid) + "/images" // fileUrlPath = "files/" + Digest3(userId) + "/" + userId + "/" + Digest2(newGuid) + "/images"
fileUrlPath = "files/" + GetRandomFilePath(userId, newGuid) + "/images"
} }
dir := revel.BasePath + "/" + fileUrlPath dir := revel.BasePath + "/" + fileUrlPath
@@ -122,6 +125,7 @@ func (c File) uploadImage(from, albumId string) (re info.Re) {
var ext string var ext string
if from == "pasteImage" { if from == "pasteImage" {
handel.Filename = c.Message("unTitled")
ext = ".png" // TODO 可能不是png类型 ext = ".png" // TODO 可能不是png类型
} else { } else {
_, ext = SplitFilename(filename) _, ext = SplitFilename(filename)
@@ -181,7 +185,7 @@ func (c File) uploadImage(from, albumId string) (re info.Re) {
fileInfo.FileId = id fileInfo.FileId = id
fileId = id.Hex() fileId = id.Hex()
if(from == "logo" || from == "blogLogo") { if from == "logo" || from == "blogLogo" {
fileId = fileUrlPath fileId = fileUrlPath
} }
@@ -217,13 +221,13 @@ func (c File) DeleteImage(fileId string) revel.Result {
// 输出image // 输出image
// 权限判断 // 权限判断
func (c File) OutputImage(noteId, fileId string) revel.Result { func (c File) OutputImage(noteId, fileId string) revel.Result {
path := fileService.GetFile(c.GetUserId(), fileId); // 得到路径 path := fileService.GetFile(c.GetUserId(), fileId) // 得到路径
if path == "" { if path == "" {
return c.RenderText("") return c.RenderText("")
} }
fn := revel.BasePath + "/" + strings.TrimLeft(path, "/") fn := revel.BasePath + "/" + strings.TrimLeft(path, "/")
file, _ := os.Open(fn) file, _ := os.Open(fn)
return c.RenderFile(file, revel.Inline) // revel.Attachment return c.RenderFile(file, revel.Inline) // revel.Attachment
} }
// 协作时复制图片到owner // 协作时复制图片到owner
@@ -242,7 +246,8 @@ func (c File) CopyHttpImage(src string) revel.Result {
// 生成上传路径 // 生成上传路径
newGuid := NewGuid() newGuid := NewGuid()
userId := c.GetUserId() userId := c.GetUserId()
fileUrlPath := "files/" + Digest3(userId) + "/" + userId + "/" + Digest2(newGuid) + "/images" // fileUrlPath := "files/" + Digest3(userId) + "/" + userId + "/" + Digest2(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 {
@@ -265,7 +270,7 @@ func (c File) CopyHttpImage(src string) revel.Result {
fileInfo.FileId = id fileInfo.FileId = id
re.Id = id.Hex() re.Id = id.Hex()
// 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)
+8 -7
View File
@@ -1,9 +1,9 @@
package controllers package controllers
import ( import (
"github.com/revel/revel"
"github.com/leanote/leanote/app/info" "github.com/leanote/leanote/app/info"
// . "github.com/leanote/leanote/app/lea" "github.com/revel/revel"
// . "github.com/leanote/leanote/app/lea"
) )
// 首页 // 首页
@@ -13,12 +13,13 @@ type Index struct {
} }
func (c Index) Default() revel.Result { func (c Index) Default() revel.Result {
if configService.HomePageIsAdminsBlog(){ if configService.HomePageIsAdminsBlog() {
blog := Blog{c.BaseController} blog := Blog{c.BaseController}
return blog.Index(configService.GetAdminUsername()); return blog.Index(configService.GetAdminUsername())
} }
return c.Index() return c.Index()
} }
// leanote展示页, 没有登录的, 或已登录明确要进该页的 // leanote展示页, 没有登录的, 或已登录明确要进该页的
func (c Index) Index() revel.Result { func (c Index) Index() revel.Result {
c.SetUserInfo() c.SetUserInfo()
@@ -26,7 +27,7 @@ func (c Index) Index() revel.Result {
c.RenderArgs["openRegister"] = configService.GlobalStringConfigs["openRegister"] c.RenderArgs["openRegister"] = configService.GlobalStringConfigs["openRegister"]
c.SetLocale() c.SetLocale()
return c.RenderTemplate("home/index.html"); return c.RenderTemplate("home/index.html")
} }
// 建议 // 建议
@@ -36,8 +37,8 @@ func (c Index) Suggestion(addr, suggestion string) revel.Result {
// 发给我 // 发给我
go func() { go func() {
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)
} }
+35 -52
View File
@@ -11,9 +11,9 @@ import (
"regexp" "regexp"
"strings" "strings"
"time" "time"
"fmt"
// "github.com/leanote/leanote/app/types" // "github.com/leanote/leanote/app/types"
// "io/ioutil" // "io/ioutil"
"fmt"
// "bytes" // "bytes"
// "os" // "os"
) )
@@ -67,13 +67,13 @@ func (c Note) Index(noteId, online string) revel.Result {
// 不要获取notebook下的笔记 // 不要获取notebook下的笔记
// 在前端下发请求 // 在前端下发请求
c.RenderArgs["curSharedNoteNotebookId"] = note.NotebookId.Hex() c.RenderArgs["curSharedNoteNotebookId"] = note.NotebookId.Hex()
c.RenderArgs["curSharedUserId"] = noteOwner; c.RenderArgs["curSharedUserId"] = noteOwner
// 没有读写权限 // 没有读写权限
} else { } else {
hasRightNoteId = false hasRightNoteId = false
} }
} else { } else {
_, notes = noteService.ListNotes(c.GetUserId(), note.NotebookId.Hex(), false, c.GetPage(), 50, defaultSortField, false, false); _, notes = noteService.ListNotes(c.GetUserId(), note.NotebookId.Hex(), false, c.GetPage(), 50, defaultSortField, false, false)
// 如果指定了某笔记, 则该笔记放在首位 // 如果指定了某笔记, 则该笔记放在首位
lenNotes := len(notes) lenNotes := len(notes)
@@ -84,7 +84,7 @@ func (c Note) Index(noteId, online string) revel.Result {
for _, note := range notes { for _, note := range notes {
if note.NoteId.Hex() != noteId { if note.NoteId.Hex() != noteId {
if i == lenNotes { // 防止越界 if i == lenNotes { // 防止越界
break; break
} }
notes2[i] = note notes2[i] = note
i++ i++
@@ -96,14 +96,14 @@ 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.RenderArgs["latestNotes"] = latestNotes
} }
// 没有传入笔记 // 没有传入笔记
// 那么得到最新笔记 // 那么得到最新笔记
if !hasRightNoteId { if !hasRightNoteId {
_, 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.RenderArgs["curNoteId"] = notes[0].NoteId.Hex()
@@ -162,50 +162,32 @@ func (c Note) GetNoteContent(noteId string) revel.Result {
return c.RenderJson(noteContent) return c.RenderJson(noteContent)
} }
// 更新note或content
// 肯定会传userId(谁的), NoteId
// 会传Title, Content, Tags, 一种或几种
type NoteOrContent struct {
NotebookId string
NoteId string
UserId string
Title string
Desc string
ImgSrc string
Tags string
Content string
Abstract string
IsNew bool
IsMarkdown bool
FromUserId string // 为共享而新建
IsBlog bool // 是否是blog, 更新note不需要修改, 添加note时才有可能用到, 此时需要判断notebook是否设为Blog
}
// 这里不能用json, 要用post // 这里不能用json, 要用post
func (c Note) UpdateNoteOrContent(noteOrContent NoteOrContent) revel.Result { func (c Note) UpdateNoteOrContent(noteOrContent info.NoteOrContent) revel.Result {
// 新添加note // 新添加note
if noteOrContent.IsNew { if noteOrContent.IsNew {
userId := c.GetObjectUserId(); userId := c.GetObjectUserId()
// myUserId := userId // myUserId := userId
// 为共享新建? // 为共享新建?
if noteOrContent.FromUserId != "" { if noteOrContent.FromUserId != "" {
userId = bson.ObjectIdHex(noteOrContent.FromUserId) userId = bson.ObjectIdHex(noteOrContent.FromUserId)
} }
note := info.Note{UserId: userId, note := info.Note{UserId: userId,
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,
Tags: strings.Split(noteOrContent.Tags, ","), Tags: strings.Split(noteOrContent.Tags, ","),
Desc: noteOrContent.Desc, Desc: noteOrContent.Desc,
ImgSrc: noteOrContent.ImgSrc, ImgSrc: noteOrContent.ImgSrc,
IsBlog: noteOrContent.IsBlog, IsBlog: noteOrContent.IsBlog,
IsMarkdown: noteOrContent.IsMarkdown, IsMarkdown: noteOrContent.IsMarkdown,
}; }
noteContent := info.NoteContent{NoteId: note.NoteId, noteContent := info.NoteContent{NoteId: note.NoteId,
UserId: userId, UserId: userId,
IsBlog: note.IsBlog, IsBlog: note.IsBlog,
Content: noteOrContent.Content, Content: noteOrContent.Content,
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)
@@ -217,20 +199,20 @@ func (c Note) UpdateNoteOrContent(noteOrContent NoteOrContent) revel.Result {
// Desc前台传来 // Desc前台传来
if c.Has("Desc") { if c.Has("Desc") {
needUpdateNote = true needUpdateNote = true
noteUpdate["Desc"] = noteOrContent.Desc; noteUpdate["Desc"] = noteOrContent.Desc
} }
if c.Has("ImgSrc") { if c.Has("ImgSrc") {
needUpdateNote = true needUpdateNote = true
noteUpdate["ImgSrc"] = noteOrContent.ImgSrc; noteUpdate["ImgSrc"] = noteOrContent.ImgSrc
} }
if c.Has("Title") { if c.Has("Title") {
needUpdateNote = true needUpdateNote = true
noteUpdate["Title"] = noteOrContent.Title; noteUpdate["Title"] = noteOrContent.Title
} }
if c.Has("Tags") { if c.Has("Tags") {
needUpdateNote = true needUpdateNote = true
noteUpdate["Tags"] = strings.Split(noteOrContent.Tags, ","); noteUpdate["Tags"] = strings.Split(noteOrContent.Tags, ",")
} }
// web端不控制 // web端不控制
@@ -244,10 +226,11 @@ func (c Note) UpdateNoteOrContent(noteOrContent NoteOrContent) revel.Result {
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, needUpdateNote, -1) noteOrContent.NoteId, noteOrContent.Content, noteOrContent.Abstract,
needUpdateNote, -1, time.Now())
} }
Log(afterContentUsn) Log(afterContentUsn)
@@ -333,11 +316,11 @@ func (c Note) ToPdf(noteId, appKey string) revel.Result {
// 虽然传了cookie但是这里还是不能得到userId, 所以还是通过appKey来验证之 // 虽然传了cookie但是这里还是不能得到userId, 所以还是通过appKey来验证之
appKeyTrue, _ := revel.Config.String("app.secret") appKeyTrue, _ := revel.Config.String("app.secret")
if appKeyTrue != appKey { if appKeyTrue != appKey {
return c.RenderText("error") return c.RenderText("auth error")
} }
note := noteService.GetNoteById(noteId) note := noteService.GetNoteById(noteId)
if note.NoteId == "" { if note.NoteId == "" {
return c.RenderText("error") return c.RenderText("no note")
} }
noteUserId := note.UserId.Hex() noteUserId := note.UserId.Hex()
@@ -426,13 +409,13 @@ func (c Note) ExportPdf(noteId string) revel.Result {
// 是否是有权限协作的 // 是否是有权限协作的
if !note.IsBlog && !shareService.HasReadPerm(noteUserId, userId, noteId) { if !note.IsBlog && !shareService.HasReadPerm(noteUserId, userId, noteId) {
re.Msg = "No Perm" re.Msg = "No Perm"
return c.RenderText("error") return c.RenderText("No Perm")
} }
} }
// path 判断是否需要重新生成之 // path 判断是否需要重新生成之
guid := NewGuid() guid := NewGuid()
fileUrlPath := "files/" + Digest3(noteUserId) + "/" + noteUserId + "/" + Digest2(guid) + "/images/pdf" fileUrlPath := "files/export_pdf"
dir := revel.BasePath + "/" + fileUrlPath dir := revel.BasePath + "/" + fileUrlPath
if !MkdirAll(dir) { if !MkdirAll(dir) {
return c.RenderText("error, no dir") return c.RenderText("error, no dir")
@@ -461,9 +444,9 @@ func (c Note) ExportPdf(noteId string) revel.Result {
// wkhtmltopdf参数大全 // wkhtmltopdf参数大全
var cc string var cc string
if note.IsMarkdown { if note.IsMarkdown {
cc = binPath + " --window-status done \"" + url + "\" \"" + path + "\"" // \"" + cookieDomain + "\" \"" + cookieName + "\" \"" + cookieValue + "\"" cc = binPath + " --lowquality --window-status done \"" + url + "\" \"" + path + "\"" // \"" + cookieDomain + "\" \"" + cookieName + "\" \"" + cookieValue + "\""
} else { } else {
cc = binPath + " \"" + url + "\" \"" + path + "\"" // \"" + cookieDomain + "\" \"" + cookieName + "\" \"" + cookieValue + "\"" cc = binPath + " --lowquality \"" + url + "\" \"" + path + "\"" // \"" + cookieDomain + "\" \"" + cookieName + "\" \"" + cookieValue + "\""
} }
cmd := exec.Command("/bin/sh", "-c", cc) cmd := exec.Command("/bin/sh", "-c", cc)
+14 -12
View File
@@ -1,12 +1,12 @@
package controllers package controllers
import ( import (
"github.com/revel/revel"
"encoding/json" "encoding/json"
"github.com/leanote/leanote/app/info" "github.com/leanote/leanote/app/info"
"github.com/revel/revel"
"gopkg.in/mgo.v2/bson" "gopkg.in/mgo.v2/bson"
// . "github.com/leanote/leanote/app/lea" // . "github.com/leanote/leanote/app/lea"
// "io/ioutil" // "io/ioutil"
) )
type Notebook struct { type Notebook struct {
@@ -31,21 +31,22 @@ func (c Notebook) DeleteNotebook(notebookId string) revel.Result {
// 添加notebook // 添加notebook
func (c Notebook) AddNotebook(notebookId, title, parentNotebookId string) revel.Result { func (c Notebook) AddNotebook(notebookId, title, parentNotebookId string) revel.Result {
notebook := info.Notebook{NotebookId: bson.ObjectIdHex(notebookId), notebook := info.Notebook{NotebookId: bson.ObjectIdHex(notebookId),
Title: title, Title: title,
Seq: -1, Seq: -1,
UserId: c.GetObjectUserId()} UserId: c.GetObjectUserId()}
if(parentNotebookId != "") { if parentNotebookId != "" {
notebook.ParentNotebookId = bson.ObjectIdHex(parentNotebookId) notebook.ParentNotebookId = bson.ObjectIdHex(parentNotebookId)
} }
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))
@@ -53,16 +54,17 @@ func (c Notebook) UpdateNotebookTitle(notebookId, title string) revel.Result {
// 排序 // 排序
// 无用 // 无用
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, 可能是排序, 可能是移动到其它笔记本下
type DragNotebooksInfo struct { type DragNotebooksInfo struct {
CurNotebookId string CurNotebookId string
ParentNotebookId string ParentNotebookId string
Siblings []string Siblings []string
} }
// 传过来的data是JSON.stringfy数据 // 传过来的data是JSON.stringfy数据
func (c Notebook) DragNotebooks(data string) revel.Result { func (c Notebook) DragNotebooks(data string) revel.Result {
info := DragNotebooksInfo{} info := DragNotebooksInfo{}
+17 -17
View File
@@ -2,13 +2,13 @@ package controllers
import ( import (
"github.com/revel/revel" "github.com/revel/revel"
// "strings" // "strings"
// "time" // "time"
// "encoding/json" // "encoding/json"
// "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"
// "io/ioutil" // "io/ioutil"
// "math" // "math"
@@ -23,7 +23,7 @@ type Preview struct {
// 得到要预览的主题绝对路径 // 得到要预览的主题绝对路径
func (c Preview) getPreviewThemeAbsolutePath(themeId string) bool { func (c Preview) getPreviewThemeAbsolutePath(themeId string) bool {
if themeId != "" { if themeId != "" {
c.Session["themeId"] = themeId // 存到session中, 下次的url就不能带了 c.Session["themeId"] = themeId // 存到session中, 下次的url就不能带了, 待优化, 有时会取不到
} else { } else {
themeId = c.Session["themeId"] // 直接从session中获取 themeId = c.Session["themeId"] // 直接从session中获取
} }
@@ -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.RenderArgs, c.getPreviewThemeAbsolutePath(themeId))
} }
func (c Preview) Tag(userIdOrEmail, tag string) revel.Result { func (c Preview) Tag(userIdOrEmail, tag string) revel.Result {
@@ -61,43 +61,43 @@ func (c Preview) Tags(userIdOrEmail string) revel.Result {
return c.E404() return c.E404()
} }
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.RenderArgs, c.getPreviewThemeAbsolutePath(""))
// } // }
// return blog.RenderTemplate("tag_posts.html", c.RenderArgs, c.getPreviewThemeAbsolutePath("")) // return blog.RenderTemplate("tag_posts.html", c.RenderArgs, 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.RenderArgs, 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.RenderArgs, 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.RenderArgs, 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.RenderArgs, 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.RenderArgs, c.getPreviewThemeAbsolutePath(""))
} }
+39 -35
View File
@@ -2,13 +2,13 @@ package controllers
import ( import (
"github.com/revel/revel" "github.com/revel/revel"
// "encoding/json" // "encoding/json"
// "gopkg.in/mgo.v2/bson" // "gopkg.in/mgo.v2/bson"
. "github.com/leanote/leanote/app/lea"
"github.com/leanote/leanote/app/info" "github.com/leanote/leanote/app/info"
// "github.com/leanote/leanote/app/types" . "github.com/leanote/leanote/app/lea"
// "io/ioutil" // "github.com/leanote/leanote/app/types"
// "fmt" // "io/ioutil"
// "fmt"
) )
type Share struct { type Share struct {
@@ -19,13 +19,13 @@ type Share struct {
func (c Share) AddShareNote(noteId string, emails []string, perm int) revel.Result { func (c Share) AddShareNote(noteId string, emails []string, perm int) revel.Result {
status := make(map[string]info.Re, len(emails)) status := make(map[string]info.Re, len(emails))
// 自己不能给自己添加共享 // 自己不能给自己添加共享
myEmail := c.GetEmail(); myEmail := c.GetEmail()
for _, email := range emails { for _, email := range emails {
if email == "" { if email == "" {
continue; continue
} }
if(myEmail != email) { if myEmail != email {
ok, msg, userId := shareService.AddShareNote(noteId, perm, c.GetUserId(), email); ok, msg, userId := shareService.AddShareNote(noteId, perm, c.GetUserId(), email)
status[email] = info.Re{Ok: ok, Msg: msg, Id: userId} status[email] = info.Re{Ok: ok, Msg: msg, Id: userId}
} else { } else {
@@ -40,13 +40,13 @@ func (c Share) AddShareNote(noteId string, emails []string, perm int) revel.Resu
func (c Share) AddShareNotebook(notebookId string, emails []string, perm int) revel.Result { func (c Share) AddShareNotebook(notebookId string, emails []string, perm int) revel.Result {
status := make(map[string]info.Re, len(emails)) status := make(map[string]info.Re, len(emails))
// 自己不能给自己添加共享 // 自己不能给自己添加共享
myEmail := c.GetEmail(); myEmail := c.GetEmail()
for _, email := range emails { for _, email := range emails {
if email == "" { if email == "" {
continue; continue
} }
if(myEmail != email) { if myEmail != email {
ok, msg, userId := shareService.AddShareNotebook(notebookId, perm, c.GetUserId(), email); ok, msg, userId := shareService.AddShareNotebook(notebookId, perm, c.GetUserId(), email)
status[email] = info.Re{Ok: ok, Msg: msg, Id: userId} status[email] = info.Re{Ok: ok, Msg: msg, Id: userId}
} else { } else {
status[email] = info.Re{Ok: false, Msg: "不能分享给自己"} status[email] = info.Re{Ok: false, Msg: "不能分享给自己"}
@@ -62,11 +62,11 @@ func (c Share) ListShareNotes(notebookId, userId string) revel.Result {
// 表示是默认笔记本, 不是某个特定notebook的共享 // 表示是默认笔记本, 不是某个特定notebook的共享
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))
} }
} }
@@ -90,7 +90,7 @@ func (c Share) ListNoteShareUserInfo(noteId string) revel.Result {
c.RenderArgs["noteOrNotebookShareGroupInfos"] = shareService.GetNoteShareGroups(noteId, c.GetUserId()) c.RenderArgs["noteOrNotebookShareGroupInfos"] = shareService.GetNoteShareGroups(noteId, c.GetUserId())
c.RenderArgs["isNote"] = true c.RenderArgs["isNote"] = true
c.RenderArgs["noteOrNotebookId"] = note.NoteId.Hex(); c.RenderArgs["noteOrNotebookId"] = note.NoteId.Hex()
c.RenderArgs["title"] = note.Title c.RenderArgs["title"] = note.Title
return c.RenderTemplate("share/note_notebook_share_user_infos.html") return c.RenderTemplate("share/note_notebook_share_user_infos.html")
@@ -105,7 +105,7 @@ func (c Share) ListNotebookShareUserInfo(notebookId string) revel.Result {
LogJ(c.RenderArgs["noteOrNotebookShareGroupInfos"]) LogJ(c.RenderArgs["noteOrNotebookShareGroupInfos"])
c.RenderArgs["isNote"] = false c.RenderArgs["isNote"] = false
c.RenderArgs["noteOrNotebookId"] = notebook.NotebookId.Hex(); c.RenderArgs["noteOrNotebookId"] = notebook.NotebookId.Hex()
c.RenderArgs["title"] = notebook.Title c.RenderArgs["title"] = notebook.Title
return c.RenderTemplate("share/note_notebook_share_user_infos.html") return c.RenderTemplate("share/note_notebook_share_user_infos.html")
@@ -114,74 +114,78 @@ 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()))
} }
//------------- //-------------
// 用户组 // 用户组
// 将笔记分享给分组 // 将笔记分享给分组
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)
} }
// 更新, 也是一样, 先删后加 // 更新, 也是一样, 先删后加
func (c Share) UpdateShareNoteGroupPerm(noteId, groupId string, perm int) revel.Result { func (c Share) UpdateShareNoteGroupPerm(noteId, groupId string, perm int) revel.Result {
return c.AddShareNoteGroup(noteId, groupId, perm) return c.AddShareNoteGroup(noteId, groupId, perm)
} }
//------ //------
// 将笔记分享给分组 // 将笔记分享给分组
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)
} }
// 更新, 也是一样, 先删后加 // 更新, 也是一样, 先删后加
func (c Share) UpdateShareNotebookGroupPerm(notebookId, groupId string, perm int) revel.Result { func (c Share) UpdateShareNotebookGroupPerm(notebookId, groupId string, perm int) revel.Result {
return c.AddShareNotebookGroup(notebookId, groupId, perm) return c.AddShareNotebookGroup(notebookId, groupId, perm)
+4 -4
View File
@@ -2,11 +2,11 @@ package controllers
import ( import (
"github.com/revel/revel" "github.com/revel/revel"
// "encoding/json" // "encoding/json"
// "gopkg.in/mgo.v2/bson" // "gopkg.in/mgo.v2/bson"
// . "github.com/leanote/leanote/app/lea" // . "github.com/leanote/leanote/app/lea"
"github.com/leanote/leanote/app/info" "github.com/leanote/leanote/app/info"
// "os/exec" // "os/exec"
) )
type Tag struct { type Tag struct {
+29 -65
View File
@@ -2,16 +2,16 @@ package controllers
import ( import (
"github.com/revel/revel" "github.com/revel/revel"
// "encoding/json" // "encoding/json"
// "gopkg.in/mgo.v2/bson" // "gopkg.in/mgo.v2/bson"
. "github.com/leanote/leanote/app/lea"
"github.com/leanote/leanote/app/info" "github.com/leanote/leanote/app/info"
// "github.com/leanote/leanote/app/types" . "github.com/leanote/leanote/app/lea"
// "io/ioutil" // "github.com/leanote/leanote/app/types"
// "fmt" // "io/ioutil"
// "math" // "fmt"
// "os" // "math"
// "path" // "os"
// "path"
"strconv" "strconv"
) )
@@ -32,18 +32,18 @@ func (c User) UpdateUsername(username string) revel.Result {
re := info.NewRe() re := info.NewRe()
if c.GetUserId() == configService.GetGlobalStringConfig("demoUserId") { if c.GetUserId() == configService.GetGlobalStringConfig("demoUserId") {
re.Msg = "cannotUpdateDemo" re.Msg = "cannotUpdateDemo"
return c.RenderRe(re); return c.RenderRe(re)
} }
if re.Ok, re.Msg = Vd("username", username); !re.Ok { if re.Ok, re.Msg = Vd("username", username); !re.Ok {
return c.RenderRe(re); return c.RenderRe(re)
} }
re.Ok, re.Msg = userService.UpdateUsername(c.GetUserId(), username) re.Ok, re.Msg = userService.UpdateUsername(c.GetUserId(), username)
if(re.Ok) { if re.Ok {
c.UpdateSession("Username", username) c.UpdateSession("Username", username)
} }
return c.RenderRe(re); return c.RenderRe(re)
} }
// 修改密码 // 修改密码
@@ -51,37 +51,37 @@ func (c User) UpdatePwd(oldPwd, pwd string) revel.Result {
re := info.NewRe() re := info.NewRe()
if c.GetUserId() == configService.GetGlobalStringConfig("demoUserId") { if c.GetUserId() == configService.GetGlobalStringConfig("demoUserId") {
re.Msg = "cannotUpdateDemo" re.Msg = "cannotUpdateDemo"
return c.RenderRe(re); return c.RenderRe(re)
} }
if re.Ok, re.Msg = Vd("password", oldPwd); !re.Ok { if re.Ok, re.Msg = Vd("password", oldPwd); !re.Ok {
return c.RenderRe(re); return c.RenderRe(re)
} }
if re.Ok, re.Msg = Vd("password", pwd); !re.Ok { if re.Ok, re.Msg = Vd("password", pwd); !re.Ok {
return c.RenderRe(re); return c.RenderRe(re)
} }
re.Ok, re.Msg = userService.UpdatePwd(c.GetUserId(), oldPwd, pwd) re.Ok, re.Msg = userService.UpdatePwd(c.GetUserId(), oldPwd, pwd)
return c.RenderRe(re); return c.RenderRe(re)
} }
// 更新主题 // 更新主题
func (c User) UpdateTheme(theme string) revel.Result { func (c User) UpdateTheme(theme string) revel.Result {
re := info.NewRe(); re := info.NewRe()
re.Ok = userService.UpdateTheme(c.GetUserId(), theme) re.Ok = userService.UpdateTheme(c.GetUserId(), theme)
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)
} }
//--------------------------- //---------------------------
@@ -93,25 +93,10 @@ func (c User) ReSendActiveEmail() revel.Result {
return c.RenderJson(re) return c.RenderJson(re)
} }
// 修改Email发送激活邮箱
func (c User) updateEmailSendActiveEmail(email, pwd string) revel.Result {
re := info.NewRe()
if c.GetUserId() == configService.GetGlobalStringConfig("demoUserId") {
re.Msg = "cannotUpdateDemo"
return c.RenderJson(re);
}
if re.Ok, re.Msg = Vd("email", email); !re.Ok {
return c.RenderRe(re);
}
re.Ok, re.Msg = emailService.UpdateEmailSendActiveEmail(c.GetUserInfo(), email)
return c.RenderRe(re)
}
// 通过点击链接 // 通过点击链接
// 修改邮箱 // 修改邮箱
func (c User) UpdateEmail(token string) revel.Result { func (c User) UpdateEmail(token string) revel.Result {
c.SetUserInfo(); c.SetUserInfo()
ok, msg, email := userService.UpdateEmail(token) ok, msg, email := userService.UpdateEmail(token)
@@ -130,13 +115,13 @@ func (c User) UpdateEmail(token string) revel.Result {
// 注册后激活邮箱 // 注册后激活邮箱
func (c User) ActiveEmail(token string) revel.Result { func (c User) ActiveEmail(token string) revel.Result {
c.SetUserInfo(); c.SetUserInfo()
ok, msg, email := userService.ActiveEmail(token) ok, msg, email := userService.ActiveEmail(token)
// 需要修改session // 需要修改session
if ok { if ok {
c.UpdateSession("Verified", "1"); c.UpdateSession("Verified", "1")
} }
c.RenderArgs["title"] = "验证邮箱" c.RenderArgs["title"] = "验证邮箱"
@@ -147,36 +132,15 @@ func (c User) ActiveEmail(token string) revel.Result {
return c.RenderTemplate("user/active_email.html") return c.RenderTemplate("user/active_email.html")
} }
//------------
// 第三方账号添加leanote账号
func (c User) AddAccount(email, pwd string) revel.Result {
re := info.NewRe()
if re.Ok, re.Msg = Vd("email", email); !re.Ok {
return c.RenderRe(re);
}
if re.Ok, re.Msg = Vd("password", pwd); !re.Ok {
return c.RenderRe(re);
}
re.Ok, re.Msg = userService.ThirdAddUser(c.GetUserId(), email, pwd)
if re.Ok {
c.UpdateSession("Email", email);
}
return c.RenderRe(re)
}
//----------------- //-----------------
// 用户偏爱 // 用户偏爱
func (c User) UpdateColumnWidth(notebookWidth, noteListWidth, mdEditorWidth int) revel.Result { func (c User) UpdateColumnWidth(notebookWidth, noteListWidth, mdEditorWidth int) revel.Result {
re := info.NewRe() re := info.NewRe()
re.Ok = userService.UpdateColumnWidth(c.GetUserId(), notebookWidth, noteListWidth, mdEditorWidth) re.Ok = userService.UpdateColumnWidth(c.GetUserId(), notebookWidth, noteListWidth, mdEditorWidth)
if re.Ok { if re.Ok {
c.UpdateSession("NotebookWidth", strconv.Itoa(notebookWidth)); c.UpdateSession("NotebookWidth", strconv.Itoa(notebookWidth))
c.UpdateSession("NoteListWidth", strconv.Itoa(noteListWidth)); c.UpdateSession("NoteListWidth", strconv.Itoa(noteListWidth))
c.UpdateSession("MdEditorWidth", strconv.Itoa(mdEditorWidth)); c.UpdateSession("MdEditorWidth", strconv.Itoa(mdEditorWidth))
LogJ(c.Session) LogJ(c.Session)
} }
@@ -187,9 +151,9 @@ func (c User) UpdateLeftIsMin(leftIsMin bool) revel.Result {
re.Ok = userService.UpdateLeftIsMin(c.GetUserId(), leftIsMin) re.Ok = userService.UpdateLeftIsMin(c.GetUserId(), leftIsMin)
if re.Ok { if re.Ok {
if leftIsMin { if leftIsMin {
c.UpdateSession("LeftIsMin", "1"); c.UpdateSession("LeftIsMin", "1")
} else { } else {
c.UpdateSession("LeftIsMin", "0"); c.UpdateSession("LeftIsMin", "0")
} }
} }
return c.RenderJson(re) return c.RenderJson(re)
+13 -13
View File
@@ -1,15 +1,15 @@
package admin package admin
import ( import (
// "github.com/revel/revel" // "github.com/revel/revel"
// "gopkg.in/mgo.v2/bson" // "gopkg.in/mgo.v2/bson"
// "encoding/json" // "encoding/json"
. "github.com/leanote/leanote/app/lea"
"github.com/leanote/leanote/app/controllers" "github.com/leanote/leanote/app/controllers"
// "io/ioutil" . "github.com/leanote/leanote/app/lea"
// "fmt" // "io/ioutil"
// "math" // "fmt"
// "strconv" // "math"
// "strconv"
"strings" "strings"
) )
@@ -20,23 +20,23 @@ type AdminBaseController struct {
// 得到sorterField 和 isAsc // 得到sorterField 和 isAsc
// okSorter = ['email', 'username'] // okSorter = ['email', 'username']
func (c AdminBaseController) getSorter(sorterField string, isAsc bool, okSorter []string) (string, bool){ func (c AdminBaseController) getSorter(sorterField string, isAsc bool, okSorter []string) (string, bool) {
sorter := "" sorter := ""
c.Params.Bind(&sorter, "sorter") c.Params.Bind(&sorter, "sorter")
if sorter == "" { if sorter == "" {
return sorterField, isAsc; return sorterField, isAsc
} }
// sorter形式 email-up, email-down // sorter形式 email-up, email-down
s2 := strings.Split(sorter, "-") s2 := strings.Split(sorter, "-")
if len(s2) != 2 { if len(s2) != 2 {
return sorterField, isAsc; return sorterField, isAsc
} }
// 必须是可用的sorter // 必须是可用的sorter
if okSorter != nil && len(okSorter) > 0 { if okSorter != nil && len(okSorter) > 0 {
if !InArray(okSorter, s2[0]) { if !InArray(okSorter, s2[0]) {
return sorterField, isAsc; return sorterField, isAsc
} }
} }
@@ -47,7 +47,7 @@ func (c AdminBaseController) getSorter(sorterField string, isAsc bool, okSorter
isAsc = false isAsc = false
} }
c.RenderArgs["sorter"] = sorter c.RenderArgs["sorter"] = sorter
return sorterField, isAsc; return sorterField, isAsc
} }
func (c AdminBaseController) updateConfig(keys []string) { func (c AdminBaseController) updateConfig(keys []string) {
+5 -5
View File
@@ -2,7 +2,7 @@ package admin
import ( import (
"github.com/revel/revel" "github.com/revel/revel"
// . "github.com/leanote/leanote/app/lea" // . "github.com/leanote/leanote/app/lea"
"github.com/leanote/leanote/app/info" "github.com/leanote/leanote/app/info"
) )
@@ -15,16 +15,16 @@ type AdminBlog struct {
// admin 主页 // admin 主页
func (c AdminBlog) Index(sorter, keywords string) revel.Result { 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.RenderArgs["pageInfo"] = pageInfo
c.RenderArgs["blogs"] = blogs c.RenderArgs["blogs"] = blogs
c.RenderArgs["keywords"] = keywords c.RenderArgs["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)
} }
+2 -2
View File
@@ -21,7 +21,7 @@ func (c Admin) Index() revel.Result {
c.RenderArgs["countNote"] = noteService.CountNote("") c.RenderArgs["countNote"] = noteService.CountNote("")
c.RenderArgs["countBlog"] = noteService.CountBlog("") c.RenderArgs["countBlog"] = noteService.CountBlog("")
return c.RenderTemplate("admin/index.html"); return c.RenderTemplate("admin/index.html")
} }
// 模板 // 模板
@@ -35,5 +35,5 @@ func (c Admin) T(t string) revel.Result {
} }
func (c Admin) GetView(view string) revel.Result { func (c Admin) GetView(view string) revel.Result {
return c.RenderTemplate("admin/" + view); return c.RenderTemplate("admin/" + view)
} }
+46 -46
View File
@@ -1,14 +1,14 @@
package admin package admin
import ( import (
"github.com/revel/revel" "archive/tar"
. "github.com/leanote/leanote/app/lea" "compress/gzip"
"github.com/leanote/leanote/app/info" "github.com/leanote/leanote/app/info"
"archive/tar" . "github.com/leanote/leanote/app/lea"
"compress/gzip" "github.com/revel/revel"
"os" "io"
"io" "os"
"time" "time"
) )
// 数据管理, 备份和恢复 // 数据管理, 备份和恢复
@@ -22,18 +22,18 @@ func (c AdminData) Index() revel.Result {
// 逆序之 // 逆序之
backups2 := make([]map[string]string, len(backups)) backups2 := make([]map[string]string, len(backups))
j := 0 j := 0
for i := len(backups)-1; i >= 0; i-- { for i := len(backups) - 1; i >= 0; i-- {
backups2[j] = backups[i] backups2[j] = backups[i]
j++ j++
} }
c.RenderArgs["backups"] = backups2 c.RenderArgs["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)
} }
// 还原 // 还原
@@ -62,53 +62,53 @@ func (c AdminData) Download(createdTime string) revel.Result {
dbname, _ := revel.Config.String("db.dbname") dbname, _ := revel.Config.String("db.dbname")
path := backup["path"] + "/" + dbname path := backup["path"] + "/" + dbname
allFiles := ListDir(path) allFiles := ListDir(path)
filename := "backup_" + dbname + "_" + backup["createdTime"] + ".tar.gz" filename := "backup_" + dbname + "_" + backup["createdTime"] + ".tar.gz"
// file write // file write
fw, err := os.Create(revel.BasePath + "/files/" + filename) fw, err := os.Create(revel.BasePath + "/files/" + filename)
if err != nil { if err != nil {
return c.RenderText("") return c.RenderText("")
} }
// defer fw.Close() // 不需要关闭, 还要读取给用户下载 // defer fw.Close() // 不需要关闭, 还要读取给用户下载
// gzip write // gzip write
gw := gzip.NewWriter(fw) gw := gzip.NewWriter(fw)
defer gw.Close() defer gw.Close()
// tar write // tar write
tw := tar.NewWriter(gw) tw := tar.NewWriter(gw)
defer tw.Close() defer tw.Close()
// 遍历文件列表 // 遍历文件列表
for _, file := range allFiles { for _, file := range allFiles {
fn := path + "/" + file fn := path + "/" + file
fr, err := os.Open(fn) fr, err := os.Open(fn)
fileInfo, _ := fr.Stat() fileInfo, _ := fr.Stat()
if err != nil { if err != nil {
return c.RenderText("") return c.RenderText("")
} }
defer fr.Close() defer fr.Close()
// 信息头 // 信息头
h := new(tar.Header) h := new(tar.Header)
h.Name = file h.Name = file
h.Size = fileInfo.Size() h.Size = fileInfo.Size()
h.Mode = int64(fileInfo.Mode()) h.Mode = int64(fileInfo.Mode())
h.ModTime = fileInfo.ModTime() h.ModTime = fileInfo.ModTime()
// 写信息头 // 写信息头
err = tw.WriteHeader(h) err = tw.WriteHeader(h)
if err != nil { if err != nil {
panic(err) panic(err)
} }
// 写文件 // 写文件
_, err = io.Copy(tw, fr) _, err = io.Copy(tw, fr)
if err != nil { if err != nil {
panic(err) panic(err)
} }
} // for } // for
return c.RenderBinary(fw, filename, revel.Attachment, time.Now()) // revel.Attachm return c.RenderBinary(fw, filename, revel.Attachment, time.Now()) // revel.Attachm
} }
+20 -21
View File
@@ -1,11 +1,11 @@
package admin package admin
import ( import (
"github.com/revel/revel"
. "github.com/leanote/leanote/app/lea"
"github.com/leanote/leanote/app/info" "github.com/leanote/leanote/app/info"
"strings" . "github.com/leanote/leanote/app/lea"
"github.com/revel/revel"
"strconv" "strconv"
"strings"
) )
// admin 首页 // admin 首页
@@ -25,7 +25,7 @@ func (c AdminEmail) Blog() revel.Result {
newTags := configService.GetGlobalArrayConfig("newTags") newTags := configService.GetGlobalArrayConfig("newTags")
c.RenderArgs["recommendTags"] = strings.Join(recommendTags, ",") c.RenderArgs["recommendTags"] = strings.Join(recommendTags, ",")
c.RenderArgs["newTags"] = strings.Join(newTags, ",") c.RenderArgs["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 {
re := info.NewRe() re := info.NewRe()
@@ -41,7 +41,7 @@ func (c AdminEmail) DoBlogTag(recommendTags, newTags string) revel.Result {
func (c AdminEmail) Demo() revel.Result { func (c AdminEmail) Demo() revel.Result {
c.RenderArgs["demoUsername"] = configService.GetGlobalStringConfig("demoUsername") c.RenderArgs["demoUsername"] = configService.GetGlobalStringConfig("demoUsername")
c.RenderArgs["demoPassword"] = configService.GetGlobalStringConfig("demoPassword") c.RenderArgs["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 {
re := info.NewRe() re := info.NewRe()
@@ -51,7 +51,7 @@ func (c AdminEmail) DoDemo(demoUsername, demoPassword string) revel.Result {
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)
} }
@@ -66,7 +66,7 @@ func (c AdminEmail) DoDemo(demoUsername, demoPassword string) revel.Result {
// 长微博的bin路径phantomJs // 长微博的bin路径phantomJs
func (c AdminEmail) ToImage() revel.Result { func (c AdminEmail) ToImage() revel.Result {
c.RenderArgs["toImageBinPath"] = configService.GetGlobalStringConfig("toImageBinPath") c.RenderArgs["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()
@@ -132,13 +132,13 @@ func (c AdminEmail) SendEmailToEmails(sendEmails, latestEmailSubject, latestEmai
if saveAsOldEmail { if saveAsOldEmail {
oldEmails := configService.GetGlobalMapConfig("oldEmails") oldEmails := configService.GetGlobalMapConfig("oldEmails")
oldEmails[latestEmailSubject] = latestEmailBody oldEmails[latestEmailSubject] = latestEmailBody
configService.UpdateGlobalMapConfig(c.GetUserId(), "oldEmails", oldEmails); configService.UpdateGlobalMapConfig(c.GetUserId(), "oldEmails", oldEmails)
} }
sendEmails = strings.Replace(sendEmails, "\r", "", -1) sendEmails = strings.Replace(sendEmails, "\r", "", -1)
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)
} }
@@ -156,7 +156,7 @@ func (c AdminEmail) SendToUsers2(emails, latestEmailSubject, latestEmailBody str
if saveAsOldEmail { if saveAsOldEmail {
oldEmails := configService.GetGlobalMapConfig("oldEmails") oldEmails := configService.GetGlobalMapConfig("oldEmails")
oldEmails[latestEmailSubject] = latestEmailBody oldEmails[latestEmailSubject] = latestEmailBody
configService.UpdateGlobalMapConfig(c.GetUserId(), "oldEmails", oldEmails); configService.UpdateGlobalMapConfig(c.GetUserId(), "oldEmails", oldEmails)
} }
emails = strings.Replace(emails, "\r", "", -1) emails = strings.Replace(emails, "\r", "", -1)
@@ -165,14 +165,13 @@ func (c AdminEmail) SendToUsers2(emails, latestEmailSubject, latestEmailBody str
users := userService.ListUserInfosByEmails(emailsArr) users := userService.ListUserInfosByEmails(emailsArr)
LogJ(emailsArr) LogJ(emailsArr)
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
func (c AdminEmail) SendEmailDialog(emails string) revel.Result{ 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")
@@ -180,7 +179,7 @@ func (c AdminEmail) SendEmailDialog(emails string) revel.Result{
c.RenderArgs["str"] = configService.GlobalStringConfigs c.RenderArgs["str"] = configService.GlobalStringConfigs
c.RenderArgs["map"] = configService.GlobalMapConfigs c.RenderArgs["map"] = configService.GlobalMapConfigs
return c.RenderTemplate("admin/email/emailDialog.html"); return c.RenderTemplate("admin/email/emailDialog.html")
} }
func (c AdminEmail) SendToUsers(userFilterEmail, userFilterWhiteList, userFilterBlackList, latestEmailSubject, latestEmailBody string, verified, saveAsOldEmail bool) revel.Result { func (c AdminEmail) SendToUsers(userFilterEmail, userFilterWhiteList, userFilterBlackList, latestEmailSubject, latestEmailBody string, verified, saveAsOldEmail bool) revel.Result {
@@ -196,19 +195,19 @@ func (c AdminEmail) SendToUsers(userFilterEmail, userFilterWhiteList, userFilter
if saveAsOldEmail { if saveAsOldEmail {
oldEmails := configService.GetGlobalMapConfig("oldEmails") oldEmails := configService.GetGlobalMapConfig("oldEmails")
oldEmails[latestEmailSubject] = latestEmailBody oldEmails[latestEmailSubject] = latestEmailBody
configService.UpdateGlobalMapConfig(c.GetUserId(), "oldEmails", oldEmails); configService.UpdateGlobalMapConfig(c.GetUserId(), "oldEmails", oldEmails)
} }
users := userService.GetAllUserByFilter(userFilterEmail, userFilterWhiteList, userFilterBlackList, verified) users := userService.GetAllUserByFilter(userFilterEmail, userFilterWhiteList, userFilterBlackList, verified)
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)
} }
@@ -227,10 +226,10 @@ func (c AdminEmail) DeleteEmails(ids string) revel.Result {
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.RenderArgs["pageInfo"] = pageInfo
c.RenderArgs["emails"] = emails c.RenderArgs["emails"] = emails
c.RenderArgs["keywords"] = keywords c.RenderArgs["keywords"] = keywords
return c.RenderTemplate("admin/email/list.html"); return c.RenderTemplate("admin/email/list.html")
} }
@@ -2,10 +2,10 @@ package admin
import ( import (
"github.com/revel/revel" "github.com/revel/revel"
// . "github.com/leanote/leanote/app/lea" // . "github.com/leanote/leanote/app/lea"
"fmt"
"github.com/leanote/leanote/app/info" "github.com/leanote/leanote/app/info"
"strings" "strings"
"fmt"
) )
// admin 首页 // admin 首页
@@ -25,7 +25,7 @@ func (c AdminSetting) Blog() revel.Result {
newTags := configService.GetGlobalArrayConfig("newTags") newTags := configService.GetGlobalArrayConfig("newTags")
c.RenderArgs["recommendTags"] = strings.Join(recommendTags, ",") c.RenderArgs["recommendTags"] = strings.Join(recommendTags, ",")
c.RenderArgs["newTags"] = strings.Join(newTags, ",") c.RenderArgs["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 {
re := info.NewRe() re := info.NewRe()
@@ -42,7 +42,7 @@ func (c AdminSetting) ShareNote(registerSharedUserId string,
registerSharedNotebookIds, registerSharedNoteIds, registerCopyNoteIds []string) revel.Result { registerSharedNotebookIds, registerSharedNoteIds, registerCopyNoteIds []string) revel.Result {
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)
} }
@@ -51,7 +51,7 @@ func (c AdminSetting) ShareNote(registerSharedUserId string,
func (c AdminSetting) Demo() revel.Result { func (c AdminSetting) Demo() revel.Result {
c.RenderArgs["demoUsername"] = configService.GetGlobalStringConfig("demoUsername") c.RenderArgs["demoUsername"] = configService.GetGlobalStringConfig("demoUsername")
c.RenderArgs["demoPassword"] = configService.GetGlobalStringConfig("demoPassword") c.RenderArgs["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 {
re := info.NewRe() re := info.NewRe()
@@ -62,7 +62,7 @@ func (c AdminSetting) DoDemo(demoUsername, demoPassword string) revel.Result {
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)
} }
@@ -79,6 +79,12 @@ func (c AdminSetting) ExportPdf(path string) revel.Result {
return c.RenderJson(re) return c.RenderJson(re)
} }
func (c AdminSetting) DoSiteUrl(siteUrl string) revel.Result {
re := info.NewRe()
re.Ok = configService.UpdateGlobalStringConfig(c.GetUserId(), "siteUrl", siteUrl)
return c.RenderJson(re)
}
// SubDomain // SubDomain
func (c AdminSetting) SubDomain() revel.Result { func (c AdminSetting) SubDomain() revel.Result {
c.RenderArgs["str"] = configService.GlobalStringConfigs c.RenderArgs["str"] = configService.GlobalStringConfigs
@@ -88,7 +94,7 @@ func (c AdminSetting) SubDomain() revel.Result {
c.RenderArgs["blogSubDomain"] = configService.GetGlobalStringConfig("blogSubDomain") c.RenderArgs["blogSubDomain"] = configService.GetGlobalStringConfig("blogSubDomain")
c.RenderArgs["leaSubDomain"] = configService.GetGlobalStringConfig("leaSubDomain") c.RenderArgs["leaSubDomain"] = configService.GetGlobalStringConfig("leaSubDomain")
return c.RenderTemplate("admin/setting/subDomain.html"); return c.RenderTemplate("admin/setting/subDomain.html")
} }
func (c AdminSetting) DoSubDomain(noteSubDomain, blogSubDomain, leaSubDomain, blackSubDomains, allowCustomDomain, blackCustomDomains string) revel.Result { func (c AdminSetting) DoSubDomain(noteSubDomain, blogSubDomain, leaSubDomain, blackSubDomains, allowCustomDomain, blackCustomDomains string) revel.Result {
re := info.NewRe() re := info.NewRe()
@@ -2,9 +2,9 @@ package admin
import ( import (
"github.com/revel/revel" "github.com/revel/revel"
// "encoding/json" // "encoding/json"
"github.com/leanote/leanote/app/info" "github.com/leanote/leanote/app/info"
// "io/ioutil" // "io/ioutil"
) )
// Upgrade controller // Upgrade controller
@@ -14,7 +14,7 @@ type AdminUpgrade struct {
func (c AdminUpgrade) UpgradeBlog() revel.Result { func (c AdminUpgrade) UpgradeBlog() revel.Result {
upgradeService.UpgradeBlog() upgradeService.UpgradeBlog()
return nil; return nil
} }
func (c AdminUpgrade) UpgradeBetaToBeta2() revel.Result { func (c AdminUpgrade) UpgradeBetaToBeta2() revel.Result {
+13 -12
View File
@@ -1,9 +1,9 @@
package admin package admin
import ( import (
"github.com/revel/revel"
. "github.com/leanote/leanote/app/lea" . "github.com/leanote/leanote/app/lea"
// "time" "github.com/revel/revel"
// "time"
"github.com/leanote/leanote/app/info" "github.com/leanote/leanote/app/info"
) )
@@ -15,32 +15,33 @@ type AdminUser struct {
// admin 主页 // admin 主页
var userPageSize = 10 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 userPageSize == 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.RenderArgs["pageInfo"] = pageInfo
c.RenderArgs["users"] = users c.RenderArgs["users"] = users
c.RenderArgs["keywords"] = keywords c.RenderArgs["keywords"] = keywords
return c.RenderTemplate("admin/user/list.html"); return c.RenderTemplate("admin/user/list.html")
} }
func (c AdminUser) Add() revel.Result { func (c AdminUser) Add() revel.Result {
return c.RenderTemplate("admin/user/add.html"); return c.RenderTemplate("admin/user/add.html")
} }
// 添加 // 添加
func (c AdminUser) Register(email, pwd string) revel.Result { func (c AdminUser) Register(email, pwd string) revel.Result {
re := info.NewRe(); re := info.NewRe()
if re.Ok, re.Msg = Vd("email", email); !re.Ok { if re.Ok, re.Msg = Vd("email", email); !re.Ok {
return c.RenderRe(re); return c.RenderRe(re)
} }
if re.Ok, re.Msg = Vd("password", pwd); !re.Ok { if re.Ok, re.Msg = Vd("password", pwd); !re.Ok {
return c.RenderRe(re); return c.RenderRe(re)
} }
// 注册 // 注册
@@ -53,13 +54,13 @@ 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.RenderArgs["userInfo"] = userInfo
return c.RenderTemplate("admin/user/reset_pwd.html"); return c.RenderTemplate("admin/user/reset_pwd.html")
} }
func (c AdminUser) DoResetPwd(userId, pwd string) revel.Result { func (c AdminUser) DoResetPwd(userId, pwd string) revel.Result {
re := info.NewRe(); re := info.NewRe()
if re.Ok, re.Msg = Vd("password", pwd); !re.Ok { if re.Ok, re.Msg = Vd("password", pwd); !re.Ok {
return c.RenderRe(re); return c.RenderRe(re)
} }
re.Ok, re.Msg = userService.ResetPwd(c.GetUserId(), userId, pwd) re.Ok, re.Msg = userService.ResetPwd(c.GetUserId(), userId, pwd)
return c.RenderRe(re) return c.RenderRe(re)
+30 -29
View File
@@ -1,11 +1,11 @@
package admin package admin
import ( import (
"github.com/leanote/leanote/app/service"
"github.com/leanote/leanote/app/info" "github.com/leanote/leanote/app/info"
// . "github.com/leanote/leanote/app/lea" "github.com/leanote/leanote/app/service"
// . "github.com/leanote/leanote/app/lea"
"github.com/revel/revel" "github.com/revel/revel"
// "strings" // "strings"
) )
var userService *service.UserService var userService *service.UserService
@@ -32,30 +32,31 @@ var upgradeService *service.UpgradeService
// 不需要拦截的url // 不需要拦截的url
// Index 除了Note之外都不需要 // Index 除了Note之外都不需要
var commonUrl = map[string]map[string]bool{"Index": map[string]bool{"Index": true, var commonUrl = map[string]map[string]bool{"Index": map[string]bool{"Index": true,
"Login": true, "Login": true,
"DoLogin": true, "DoLogin": true,
"Logout": true, "Logout": true,
"Register": true, "Register": true,
"DoRegister": true, "DoRegister": true,
"FindPasswword": true, "FindPasswword": true,
"DoFindPassword": true, "DoFindPassword": true,
"FindPassword2": true, "FindPassword2": true,
"FindPasswordUpdate": true, "FindPasswordUpdate": true,
"Suggestion": true, "Suggestion": true,
}, },
"Blog": map[string]bool{"Index": true, "Blog": map[string]bool{"Index": true,
"View": true, "View": true,
"AboutMe": true, "AboutMe": true,
"SearchBlog": true, "SearchBlog": true,
}, },
// 用户的激活与修改邮箱都不需要登录, 通过链接地址 // 用户的激活与修改邮箱都不需要登录, 通过链接地址
"User": map[string]bool{"UpdateEmail": true, "User": map[string]bool{"UpdateEmail": true,
"ActiveEmail":true, "ActiveEmail": true,
}, },
"Oauth": map[string]bool{"GithubCallback": true}, "Oauth": map[string]bool{"GithubCallback": true},
"File": map[string]bool{"OutputImage": true, "OutputFile": true}, "File": map[string]bool{"OutputImage": true, "OutputFile": true},
"Attach": map[string]bool{"Download": true, "DownloadAll": true}, "Attach": map[string]bool{"Download": true, "DownloadAll": true},
} }
func needValidate(controller, method string) bool { func needValidate(controller, method string) bool {
// 在里面 // 在里面
if v, ok := commonUrl[controller]; ok { if v, ok := commonUrl[controller]; ok {
@@ -66,18 +67,18 @@ func needValidate(controller, method string) bool {
return true return true
} else { } else {
// controller不在这里的, 肯定要验证 // controller不在这里的, 肯定要验证
return true; return true
} }
} }
func AuthInterceptor(c *revel.Controller) revel.Result { func AuthInterceptor(c *revel.Controller) revel.Result {
// 全部变成首字大写 // 全部变成首字大写
/* /*
var controller = strings.Title(c.Name) var controller = strings.Title(c.Name)
var method = strings.Title(c.MethodName) var method = strings.Title(c.MethodName)
// 是否需要验证? // 是否需要验证?
if !needValidate(controller, method) { if !needValidate(controller, method) {
return nil return nil
} }
*/ */
// 验证是否已登录 // 验证是否已登录
@@ -110,7 +111,7 @@ func InitService() {
tokenService = service.TokenS tokenService = service.TokenS
noteImageService = service.NoteImageS noteImageService = service.NoteImageS
fileService = service.FileS fileService = service.FileS
albumService= service.AlbumS albumService = service.AlbumS
attachService = service.AttachS attachService = service.AttachS
pwdService = service.PwdS pwdService = service.PwdS
suggestionService = service.SuggestionS suggestionService = service.SuggestionS
+29 -27
View File
@@ -4,11 +4,11 @@ import (
"github.com/revel/revel" "github.com/revel/revel"
"gopkg.in/mgo.v2/bson" "gopkg.in/mgo.v2/bson"
// "encoding/json" // "encoding/json"
. "github.com/leanote/leanote/app/lea"
"github.com/leanote/leanote/app/controllers" "github.com/leanote/leanote/app/controllers"
"github.com/leanote/leanote/app/info" "github.com/leanote/leanote/app/info"
. "github.com/leanote/leanote/app/lea"
"os" "os"
// "fmt" // "fmt"
"io/ioutil" "io/ioutil"
// "fmt" // "fmt"
// "math" // "math"
@@ -43,14 +43,14 @@ func (c ApiBaseContrller) getUserInfo() info.User {
// 上传附件 // 上传附件
func (c ApiBaseContrller) uploadAttach(name string, noteId string) (ok bool, msg string, id string) { func (c ApiBaseContrller) uploadAttach(name string, noteId string) (ok bool, msg string, id string) {
userId := c.getUserId(); userId := c.getUserId()
// 判断是否有权限为笔记添加附件 // 判断是否有权限为笔记添加附件
// 如果笔记还没有添加是不是会有问题 // 如果笔记还没有添加是不是会有问题
/* /*
if !shareService.HasUpdateNotePerm(noteId, userId) { if !shareService.HasUpdateNotePerm(noteId, userId) {
return return
} }
*/ */
file, handel, err := c.Request.FormFile(name) file, handel, err := c.Request.FormFile(name)
@@ -64,20 +64,21 @@ func (c ApiBaseContrller) uploadAttach(name string, noteId string) (ok bool, msg
return return
} }
// > 5M? // > 5M?
maxFileSize := configService.GetUploadSize("uploadAttachSize"); maxFileSize := configService.GetUploadSize("uploadAttachSize")
if maxFileSize <= 0 { if maxFileSize <= 0 {
maxFileSize = 1000 maxFileSize = 1000
} }
if(float64(len(data)) > maxFileSize * float64(1024*1024)) { if float64(len(data)) > maxFileSize*float64(1024*1024) {
msg = "fileIsTooLarge" msg = "fileIsTooLarge"
return return
} }
// 生成上传路径 // 生成上传路径
newGuid := NewGuid() newGuid := NewGuid()
filePath := "files/" + Digest3(userId) + "/" + userId + "/" + Digest2(newGuid) + "/attachs" // filePath := "files/" + Digest3(userId) + "/" + userId + "/" + Digest2(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
@@ -86,7 +87,7 @@ func (c ApiBaseContrller) uploadAttach(name string, noteId string) (ok bool, msg
filename := handel.Filename filename := handel.Filename
_, ext := SplitFilename(filename) // .doc _, ext := SplitFilename(filename) // .doc
filename = newGuid + ext filename = newGuid + ext
toPath := dir + "/" + filename; toPath := dir + "/" + filename
err = ioutil.WriteFile(toPath, data, 0777) err = ioutil.WriteFile(toPath, data, 0777)
if err != nil { if err != nil {
return return
@@ -98,14 +99,14 @@ func (c ApiBaseContrller) uploadAttach(name string, noteId string) (ok bool, msg
fileType = strings.ToLower(ext[1:]) fileType = strings.ToLower(ext[1:])
} }
filesize := GetFilesize(toPath) filesize := GetFilesize(toPath)
fileInfo := info.Attach{AttachId: bson.NewObjectId(), fileInfo := info.Attach{AttachId: bson.NewObjectId(),
Name: filename, Name: filename,
Title: handel.Filename, Title: handel.Filename,
NoteId: bson.ObjectIdHex(noteId), NoteId: bson.ObjectIdHex(noteId),
UploadUserId: bson.ObjectIdHex(userId), UploadUserId: bson.ObjectIdHex(userId),
Path: filePath + "/" + filename, Path: filePath + "/" + filename,
Type: fileType, Type: fileType,
Size: filesize} Size: filesize}
ok, msg = attachService.AddAttach(fileInfo, true) ok, msg = attachService.AddAttach(fileInfo, true)
if !ok { if !ok {
@@ -130,9 +131,10 @@ func (c ApiBaseContrller) upload(name string, noteId string, isAttach bool) (ok
newGuid := NewGuid() newGuid := NewGuid()
// 生成上传路径 // 生成上传路径
userId := c.getUserId() userId := c.getUserId()
fileUrlPath := "files/" + Digest3(userId) + "/" + userId + "/" + Digest2(newGuid) + "/images" // fileUrlPath := "files/" + Digest3(userId) + "/" + userId + "/" + Digest2(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
@@ -140,7 +142,7 @@ func (c ApiBaseContrller) upload(name string, noteId string, isAttach bool) (ok
// 生成新的文件名 // 生成新的文件名
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
} }
@@ -151,18 +153,18 @@ func (c ApiBaseContrller) upload(name string, noteId string, isAttach bool) (ok
return return
} }
maxFileSize := configService.GetUploadSize("uploadImageSize"); maxFileSize := configService.GetUploadSize("uploadImageSize")
if maxFileSize <= 0 { if maxFileSize <= 0 {
maxFileSize = 1000 maxFileSize = 1000
} }
// > 2M? // > 2M?
if(float64(len(data)) > maxFileSize * float64(1024*1024)) { if float64(len(data)) > maxFileSize*float64(1024*1024) {
msg = "fileIsTooLarge" msg = "fileIsTooLarge"
return return
} }
toPath := dir + "/" + filename; toPath := dir + "/" + filename
err = ioutil.WriteFile(toPath, data, 0777) err = ioutil.WriteFile(toPath, data, 0777)
if err != nil { if err != nil {
return return
@@ -175,10 +177,10 @@ func (c ApiBaseContrller) upload(name string, noteId string, isAttach bool) (ok
// File // File
fileInfo := info.File{FileId: bson.NewObjectId(), fileInfo := info.File{FileId: bson.NewObjectId(),
Name: filename, Name: filename,
Title: handel.Filename, Title: handel.Filename,
Path: fileUrlPath, Path: fileUrlPath,
Size: filesize} Size: filesize}
ok, msg = fileService.AddImage(fileInfo, "", c.getUserId(), true) ok, msg = fileService.AddImage(fileInfo, "", c.getUserId(), true)
if ok { if ok {
id = fileInfo.FileId.Hex() id = fileInfo.FileId.Hex()
+56 -57
View File
@@ -3,18 +3,18 @@ package api
import ( import (
"github.com/revel/revel" "github.com/revel/revel"
// "encoding/json" // "encoding/json"
// . "github.com/leanote/leanote/app/lea" // . "github.com/leanote/leanote/app/lea"
// "gopkg.in/mgo.v2/bson" // "gopkg.in/mgo.v2/bson"
// "github.com/leanote/leanote/app/lea/netutil" // "github.com/leanote/leanote/app/lea/netutil"
// "github.com/leanote/leanote/app/info" // "github.com/leanote/leanote/app/info"
// "io/ioutil" // "io/ioutil"
"os" "os"
// "strconv" // "strconv"
"archive/tar"
"compress/gzip"
"io" "io"
"time"
"strings" "strings"
"archive/tar" "time"
"compress/gzip"
) )
// 文件操作, 图片, 头像上传, 输出 // 文件操作, 图片, 头像上传, 输出
@@ -73,14 +73,14 @@ func (c ApiFile) GetImage(fileId string) revel.Result {
// 下载附件 // 下载附件
// [OK] // [OK]
func (c ApiFile) GetAttach(fileId string) revel.Result { func (c ApiFile) GetAttach(fileId string) revel.Result {
attach := attachService.GetAttach(fileId, c.getUserId()); // 得到路径 attach := attachService.GetAttach(fileId, c.getUserId()) // 得到路径
path := attach.Path path := attach.Path
if path == "" { if path == "" {
return c.RenderText("No Such File") return c.RenderText("No Such File")
} }
fn := revel.BasePath + "/" + strings.TrimLeft(path, "/") fn := revel.BasePath + "/" + strings.TrimLeft(path, "/")
file, _ := os.Open(fn) file, _ := os.Open(fn)
return c.RenderBinary(file, attach.Title, revel.Attachment, time.Now()) // revel.Attachment return c.RenderBinary(file, attach.Title, revel.Attachment, time.Now()) // revel.Attachment
} }
// 下载所有附件 // 下载所有附件
@@ -97,11 +97,11 @@ func (c ApiFile) GetAllAttachs(noteId string) revel.Result {
} }
/* /*
dir := revel.BasePath + "/files/tmp" dir := revel.BasePath + "/files/tmp"
err := os.MkdirAll(dir, 0755) err := os.MkdirAll(dir, 0755)
if err != nil { if err != nil {
return c.RenderText("") return c.RenderText("")
} }
*/ */
filename := note.Title + ".tar.gz" filename := note.Title + ".tar.gz"
@@ -110,55 +110,54 @@ func (c ApiFile) GetAllAttachs(noteId string) revel.Result {
} }
// file write // file write
fw, err := os.Create(revel.BasePath + "/files/" + filename) fw, err := os.Create(revel.BasePath + "/files/" + filename)
if err != nil { if err != nil {
return c.RenderText("") return c.RenderText("")
} }
// defer fw.Close() // 不需要关闭, 还要读取给用户下载 // defer fw.Close() // 不需要关闭, 还要读取给用户下载
// gzip write // gzip write
gw := gzip.NewWriter(fw) gw := gzip.NewWriter(fw)
defer gw.Close() defer gw.Close()
// tar write // tar write
tw := tar.NewWriter(gw) tw := tar.NewWriter(gw)
defer tw.Close() defer tw.Close()
// 遍历文件列表 // 遍历文件列表
for _, attach := range attachs { for _, attach := range attachs {
fn := revel.BasePath + "/" + strings.TrimLeft(attach.Path, "/") fn := revel.BasePath + "/" + strings.TrimLeft(attach.Path, "/")
fr, err := os.Open(fn) fr, err := os.Open(fn)
fileInfo, _ := fr.Stat() fileInfo, _ := fr.Stat()
if err != nil { if err != nil {
return c.RenderText("") return c.RenderText("")
} }
defer fr.Close() defer fr.Close()
// 信息头 // 信息头
h := new(tar.Header) h := new(tar.Header)
h.Name = attach.Title h.Name = attach.Title
h.Size = fileInfo.Size() h.Size = fileInfo.Size()
h.Mode = int64(fileInfo.Mode()) h.Mode = int64(fileInfo.Mode())
h.ModTime = fileInfo.ModTime() h.ModTime = fileInfo.ModTime()
// 写信息头 // 写信息头
err = tw.WriteHeader(h) err = tw.WriteHeader(h)
if err != nil { if err != nil {
panic(err) panic(err)
} }
// 写文件 // 写文件
_, err = io.Copy(tw, fr) _, err = io.Copy(tw, fr)
if err != nil { if err != nil {
panic(err) panic(err)
} }
} // for } // for
// tw.Close() // tw.Close()
// gw.Close() // gw.Close()
// fw.Close() // fw.Close()
// file, _ := os.Open(dir + "/" + filename) // file, _ := os.Open(dir + "/" + filename)
// fw.Seek(0, 0) // fw.Seek(0, 0)
return c.RenderBinary(fw, filename, revel.Attachment, time.Now()) // revel.Attachment return c.RenderBinary(fw, filename, revel.Attachment, time.Now()) // revel.Attachment
} }
+69 -115
View File
@@ -6,11 +6,10 @@ import (
"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"
"regexp" "os"
"os/exec"
"strings" "strings"
"time" "time"
"os/exec"
"os"
// "github.com/leanote/leanote/app/types" // "github.com/leanote/leanote/app/types"
// "io/ioutil" // "io/ioutil"
// "fmt" // "fmt"
@@ -85,7 +84,6 @@ func (c ApiNote) GetTrashNotes() revel.Result {
"Title": "asdfadsf--=", "Title": "asdfadsf--=",
"Desc": "", "Desc": "",
"Tags": [ "Tags": [
""
], ],
"Abstract": "", "Abstract": "",
"Content": "", "Content": "",
@@ -95,7 +93,7 @@ func (c ApiNote) GetTrashNotes() revel.Result {
"Usn": 8, "Usn": 8,
"Files": [ "Files": [
{ {
"FileId": "551975d599c37b970f000002", "FileId": "551975d599c37b970f000000",
"LocalFileId": "", "LocalFileId": "",
"Type": "", "Type": "",
"Title": "", "Title": "",
@@ -103,18 +101,18 @@ func (c ApiNote) GetTrashNotes() revel.Result {
"IsAttach": false "IsAttach": false
}, },
{ {
"FileId": "551975de99c37b970f000003", "FileId": "551975de99c37b970f000001",
"LocalFileId": "", "LocalFileId": "",
"Type": "doc", "Type": "doc",
"Title": "李铁-简历-ali-print-en.doc", "Title": "李铁-print-en.doc",
"HasBody": false, "HasBody": false,
"IsAttach": true "IsAttach": true
}, },
{ {
"FileId": "551975de99c37b970f000004", "FileId": "551975de99c37b970f000002",
"LocalFileId": "", "LocalFileId": "",
"Type": "doc", "Type": "doc",
"Title": "李铁-简历-ali-print.doc", "Title": "李铁-print.doc",
"HasBody": false, "HasBody": false,
"IsAttach": true "IsAttach": true
} }
@@ -148,68 +146,10 @@ 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 = noteAndContent.Content apiNote.Content = noteService.FixContent(noteAndContent.Content, noteAndContent.IsMarkdown)
return c.RenderJson(apiNote) return c.RenderJson(apiNote)
} }
// 处理笔记内容数据 http://leanote.com/file/outputImage -> https://leanote.com/api/file/getImage
// 图片, 附件都替换
func (c ApiNote) fixContent(content string) string {
// TODO, 这个url需要从config中取
// baseUrl := "http://leanote.com"
baseUrl := configService.GetSiteUrl()
// baseUrl := "http://localhost:9000"
patterns := []map[string]string{
map[string]string{"src": "src", "middle": "/file/outputImage", "param": "fileId", "to": "getImage?fileId="},
map[string]string{"src": "href", "middle": "/attach/download", "param": "attachId", "to": "getAttach?fileId="},
map[string]string{"src": "href", "middle": "/attach/downloadAll", "param": "noteId", "to": "getAllAttachs?noteId="},
}
for _, eachPattern := range patterns {
// src="http://leanote.com/file/outputImage?fileId=5503537b38f4111dcb0000d1"
// href="http://leanote.com/attach/download?attachId=5504243a38f4111dcb00017d"
// href="http://leanote.com/attach/downloadAll?noteId=55041b6a38f4111dcb000159"
regImage, _ := regexp.Compile(eachPattern["src"] + `=('|")`+ baseUrl + eachPattern["middle"] + `\?` + eachPattern["param"] + `=([a-z0-9A-Z]{24})("|')`)
findsImage := regImage.FindAllStringSubmatch(content, -1) // 查找所有的
// [[src='http://leanote.com/file/outputImage?fileId=54672e8d38f411286b000069" ' 54672e8d38f411286b000069 "] [src="http://leanote.com/file/outputImage?fileId=54672e8d38f411286b000069" " 54672e8d38f411286b000069 "] [src="http://leanote.com/file/outputImage?fileId=54672e8d38f411286b000069" " 54672e8d38f411286b000069 "] [src="http://leanote.com/file/outputImage?fileId=54672e8d38f411286b000069" " 54672e8d38f411286b000069 "]]
for _, eachFind := range findsImage {
// [src='http://leanote.com/file/outputImage?fileId=54672e8d38f411286b000069" ' 54672e8d38f411286b000069 "]
if len(eachFind) == 4 {
content = strings.Replace(content,
eachFind[0],
eachPattern["src"] + "=\"" + baseUrl + "/api/file/" + eachPattern["to"] + eachFind[2] + "\"",
1);
}
}
// markdown处理
// ![](http://leanote.com/file/outputImage?fileId=5503537b38f4111dcb0000d1)
// [selection 2.html](http://leanote.com/attach/download?attachId=5504262638f4111dcb00017f)
// [all.tar.gz](http://leanote.com/attach/downloadAll?noteId=5503b57d59f81b4eb4000000)
pre := "!" // 默认图片
if eachPattern["src"] == "href" { // 是attach
pre = ""
}
regImageMarkdown, _ := regexp.Compile(pre + `\[(.*?)\]\(`+ baseUrl + eachPattern["middle"] + `\?` + eachPattern["param"] + `=([a-z0-9A-Z]{24})\)`)
findsImageMarkdown := regImageMarkdown.FindAllStringSubmatch(content, -1) // 查找所有的
// [[![](http://leanote.com/file/outputImage?fileId=5503537b38f4111dcb0000d1) 5503537b38f4111dcb0000d1] [![你好啊, 我很好, 为什么?](http://leanote.com/file/outputImage?fileId=5503537b38f4111dcb0000d1) 5503537b38f4111dcb0000d1]]
for _, eachFind := range findsImageMarkdown {
// [![你好啊, 我很好, 为什么?](http://leanote.com/file/outputImage?fileId=5503537b38f4111dcb0000d1) 你好啊, 我很好, 为什么? 5503537b38f4111dcb0000d1]
if len(eachFind) == 3 {
content = strings.Replace(content, eachFind[0], pre + "[" + eachFind[1] + "](" + baseUrl + "/api/file/" + eachPattern["to"] + eachFind[2] + ")", 1);
}
}
}
return content
}
// content里的image, attach链接是 // content里的image, attach链接是
// https://leanote.com/api/file/getImage?fileId=xx // https://leanote.com/api/file/getImage?fileId=xx
// https://leanote.com/api/file/getAttach?fileId=xx // https://leanote.com/api/file/getAttach?fileId=xx
@@ -222,28 +162,28 @@ func (c ApiNote) fixPostNotecontent(noteOrContent *info.ApiNote) {
if files != nil && len(files) > 0 { if files != nil && len(files) > 0 {
for _, file := range files { for _, file := range files {
if file.LocalFileId != "" { if file.LocalFileId != "" {
noteOrContent.Content = strings.Replace(noteOrContent.Content, "fileId=" + file.LocalFileId, "fileId=" + file.FileId, -1) noteOrContent.Content = strings.Replace(noteOrContent.Content, "fileId="+file.LocalFileId, "fileId="+file.FileId, -1)
} }
} }
} }
} }
// 得到内容 // 得到内容
// [OK]
func (c ApiNote) GetNoteContent(noteId string) revel.Result { func (c ApiNote) GetNoteContent(noteId string) revel.Result {
userId := c.getUserId()
note := noteService.GetNote(noteId, userId)
// re := info.NewRe() // re := info.NewRe()
noteContent := noteService.GetNoteContent(noteId, c.getUserId()) noteContent := noteService.GetNoteContent(noteId, userId)
if noteContent.Content != "" { if noteContent.Content != "" {
noteContent.Content = c.fixContent(noteContent.Content) noteContent.Content = noteService.FixContent(noteContent.Content, note.IsMarkdown)
} }
apiNoteContent := info.ApiNoteContent{ apiNoteContent := info.ApiNoteContent{
NoteId: noteContent.NoteId, NoteId: noteContent.NoteId,
UserId: noteContent.UserId, UserId: noteContent.UserId,
Content: noteContent.Content, Content: noteContent.Content,
} }
// re.Item = noteContent
return c.RenderJson(apiNoteContent) return c.RenderJson(apiNoteContent)
} }
@@ -255,12 +195,13 @@ func (c ApiNote) AddNote(noteOrContent info.ApiNote) revel.Result {
myUserId := userId myUserId := userId
// 为共享新建? // 为共享新建?
/* /*
if noteOrContent.FromUserId != "" { if noteOrContent.FromUserId != "" {
userId = bson.ObjectIdHex(noteOrContent.FromUserId) userId = bson.ObjectIdHex(noteOrContent.FromUserId)
} }
*/ */
// Log(noteOrContent.Title) // Log(noteOrContent.Title)
// LogJ(noteOrContent) // LogJ(noteOrContent)
/* /*
LogJ(c.Params) LogJ(c.Params)
for name, _ := range c.Params.Files { for name, _ := range c.Params.Files {
@@ -315,8 +256,8 @@ func (c ApiNote) AddNote(noteOrContent info.ApiNote) revel.Result {
c.fixPostNotecontent(&noteOrContent) c.fixPostNotecontent(&noteOrContent)
// Log("Add") // Log("Add")
// LogJ(noteOrContent) // LogJ(noteOrContent)
// return c.RenderJson(re) // return c.RenderJson(re)
@@ -326,16 +267,21 @@ func (c ApiNote) AddNote(noteOrContent info.ApiNote) revel.Result {
Title: noteOrContent.Title, Title: noteOrContent.Title,
Tags: noteOrContent.Tags, Tags: noteOrContent.Tags,
Desc: noteOrContent.Desc, Desc: noteOrContent.Desc,
// ImgSrc: noteOrContent.ImgSrc, // ImgSrc: noteOrContent.ImgSrc,
IsBlog: noteOrContent.IsBlog, IsBlog: noteOrContent.IsBlog,
IsMarkdown: noteOrContent.IsMarkdown, IsMarkdown: noteOrContent.IsMarkdown,
AttachNum: attachNum, AttachNum: attachNum,
CreatedTime: noteOrContent.CreatedTime,
UpdatedTime: noteOrContent.UpdatedTime,
} }
noteContent := info.NoteContent{NoteId: note.NoteId, noteContent := info.NoteContent{NoteId: note.NoteId,
UserId: userId, UserId: userId,
IsBlog: note.IsBlog, IsBlog: note.IsBlog,
Content: noteOrContent.Content, Content: noteOrContent.Content,
Abstract: noteOrContent.Abstract} Abstract: noteOrContent.Abstract,
CreatedTime: noteOrContent.CreatedTime,
UpdatedTime: noteOrContent.UpdatedTime,
}
// 通过内容得到Desc, abstract // 通过内容得到Desc, abstract
if noteOrContent.Abstract == "" { if noteOrContent.Abstract == "" {
@@ -386,8 +332,8 @@ func (c ApiNote) UpdateNote(noteOrContent info.ApiNote) revel.Result {
return c.RenderJson(re) return c.RenderJson(re)
} }
// Log("_____________") // Log("_____________")
// LogJ(noteOrContent) // LogJ(noteOrContent)
/* /*
LogJ(c.Params.Files) LogJ(c.Params.Files)
LogJ(c.Request.Header) LogJ(c.Request.Header)
@@ -410,14 +356,14 @@ func (c ApiNote) UpdateNote(noteOrContent info.ApiNote) revel.Result {
// 如果传了files // 如果传了files
// TODO 测试 // TODO 测试
/* /*
for key, v := range c.Params.Values { for key, v := range c.Params.Values {
Log(key) Log(key)
Log(v) Log(v)
} }
*/ */
// Log(c.Has("Files[0]")) // Log(c.Has("Files[0]"))
if c.Has("Files[0][LocalFileId]") { if c.Has("Files[0][LocalFileId]") {
// LogJ(c.Params.Files) // LogJ(c.Params.Files)
if noteOrContent.Files != nil && len(noteOrContent.Files) > 0 { if noteOrContent.Files != nil && len(noteOrContent.Files) > 0 {
for i, file := range noteOrContent.Files { for i, file := range noteOrContent.Files {
if file.HasBody { if file.HasBody {
@@ -445,8 +391,9 @@ func (c ApiNote) UpdateNote(noteOrContent info.ApiNote) revel.Result {
} }
} }
// Log("after upload") // Log("after upload")
// LogJ(noteOrContent.Files) // LogJ(noteOrContent.Files)
} }
// 移到外面来, 删除最后一个file时也要处理, 不然总删不掉 // 移到外面来, 删除最后一个file时也要处理, 不然总删不掉
@@ -459,10 +406,10 @@ func (c ApiNote) UpdateNote(noteOrContent info.ApiNote) revel.Result {
noteUpdate["Desc"] = noteOrContent.Desc noteUpdate["Desc"] = noteOrContent.Desc
} }
/* /*
if c.Has("ImgSrc") { if c.Has("ImgSrc") {
needUpdateNote = true needUpdateNote = true
noteUpdate["ImgSrc"] = noteOrContent.ImgSrc noteUpdate["ImgSrc"] = noteOrContent.ImgSrc
} }
*/ */
if c.Has("Title") { if c.Has("Title") {
needUpdateNote = true needUpdateNote = true
@@ -509,6 +456,8 @@ func (c ApiNote) UpdateNote(noteOrContent info.ApiNote) revel.Result {
} }
} }
noteUpdate["UpdatedTime"] = noteOrContent.UpdatedTime
afterNoteUsn := 0 afterNoteUsn := 0
noteOk := false noteOk := false
noteMsg := "" noteMsg := ""
@@ -532,10 +481,16 @@ func (c ApiNote) UpdateNote(noteOrContent info.ApiNote) revel.Result {
if noteOrContent.Abstract == "" { if noteOrContent.Abstract == "" {
noteOrContent.Abstract = SubStringHTML(noteOrContent.Content, 200, "") noteOrContent.Abstract = SubStringHTML(noteOrContent.Content, 200, "")
} }
// Log("--------> afte fixed")
// Log(noteOrContent.Content) // Log("--------> afte fixed")
// Log(noteOrContent.Content)
contentOk, contentMsg, afterContentUsn = noteService.UpdateNoteContent(c.getUserId(), contentOk, contentMsg, afterContentUsn = noteService.UpdateNoteContent(c.getUserId(),
noteOrContent.NoteId, noteOrContent.Content, noteOrContent.Abstract, needUpdateNote, noteOrContent.Usn) noteOrContent.NoteId,
noteOrContent.Content,
noteOrContent.Abstract,
needUpdateNote,
noteOrContent.Usn,
noteOrContent.UpdatedTime)
} }
if needUpdateNote { if needUpdateNote {
@@ -556,8 +511,8 @@ func (c ApiNote) UpdateNote(noteOrContent info.ApiNote) revel.Result {
noteOrContent.Usn = re.Usn noteOrContent.Usn = re.Usn
noteOrContent.UpdatedTime = time.Now() noteOrContent.UpdatedTime = time.Now()
// Log("after upload") // Log("after upload")
// LogJ(noteOrContent.Files) // LogJ(noteOrContent.Files)
noteOrContent.UserId = c.getUserId() noteOrContent.UserId = c.getUserId()
return c.RenderJson(noteOrContent) return c.RenderJson(noteOrContent)
@@ -585,7 +540,6 @@ func (c ApiNote) GetHistories(noteId string) revel.Result {
// 0.2 新增 // 0.2 新增
// 导出成PDF // 导出成PDF
// test localhost:9000/api/note/exportPdf?noteId=554f07bf05fcd15fa9000000&token=562211dc99c37ba6a7000001
func (c ApiNote) ExportPdf(noteId string) revel.Result { func (c ApiNote) ExportPdf(noteId string) revel.Result {
re := info.NewApiRe() re := info.NewApiRe()
userId := c.getUserId() userId := c.getUserId()
@@ -612,7 +566,7 @@ func (c ApiNote) ExportPdf(noteId string) revel.Result {
// path 判断是否需要重新生成之 // path 判断是否需要重新生成之
guid := NewGuid() guid := NewGuid()
fileUrlPath := "files/" + Digest3(noteUserId) + "/" + noteUserId + "/" + Digest2(guid) + "/images/pdf" fileUrlPath := "files/export_pdf"
dir := revel.BasePath + "/" + fileUrlPath dir := revel.BasePath + "/" + fileUrlPath
if !MkdirAll(dir) { if !MkdirAll(dir) {
re.Msg = "noDir" re.Msg = "noDir"
@@ -635,15 +589,15 @@ func (c ApiNote) ExportPdf(noteId string) revel.Result {
url := configService.GetSiteUrl() + "/note/toPdf?noteId=" + noteId + "&appKey=" + appKey url := configService.GetSiteUrl() + "/note/toPdf?noteId=" + noteId + "&appKey=" + appKey
var cc string var cc string
if(note.IsMarkdown) { if note.IsMarkdown {
cc = binPath + " --window-status done \"" + url + "\" \"" + path + "\"" // \"" + cookieDomain + "\" \"" + cookieName + "\" \"" + cookieValue + "\"" cc = binPath + " --lowquality --window-status done \"" + url + "\" \"" + path + "\"" // \"" + cookieDomain + "\" \"" + cookieName + "\" \"" + cookieValue + "\""
} else { } else {
cc = binPath + " \"" + url + "\" \"" + path + "\"" // \"" + cookieDomain + "\" \"" + cookieName + "\" \"" + cookieValue + "\"" cc = binPath + " --lowquality \"" + url + "\" \"" + path + "\"" // \"" + cookieDomain + "\" \"" + cookieName + "\" \"" + cookieValue + "\""
} }
cmd := exec.Command("/bin/sh", "-c", cc) cmd := exec.Command("/bin/sh", "-c", cc)
_, 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)
} }
@@ -660,5 +614,5 @@ func (c ApiNote) ExportPdf(noteId string) revel.Result {
} else { } else {
filenameReturn += ".pdf" filenameReturn += ".pdf"
} }
return c.RenderBinary(file, filenameReturn, revel.Attachment, time.Now()) // revel.Attachment return c.RenderBinary(file, filenameReturn, revel.Attachment, time.Now()) // revel.Attachment
} }
+12 -12
View File
@@ -2,9 +2,9 @@ package api
import ( import (
"github.com/leanote/leanote/app/info" "github.com/leanote/leanote/app/info"
. "github.com/leanote/leanote/app/lea"
"github.com/revel/revel" "github.com/revel/revel"
"gopkg.in/mgo.v2/bson" "gopkg.in/mgo.v2/bson"
. "github.com/leanote/leanote/app/lea"
// "io/ioutil" // "io/ioutil"
) )
@@ -30,17 +30,17 @@ func (c ApiNotebook) fixNotebook(notebook *info.Notebook) info.ApiNotebook {
return info.ApiNotebook{} return info.ApiNotebook{}
} }
return info.ApiNotebook{ return info.ApiNotebook{
NotebookId : notebook.NotebookId, NotebookId: notebook.NotebookId,
UserId : notebook.UserId, UserId: notebook.UserId,
ParentNotebookId : notebook.ParentNotebookId, ParentNotebookId: notebook.ParentNotebookId,
Seq : notebook.Seq, Seq: notebook.Seq,
Title : notebook.Title, Title: notebook.Title,
UrlTitle : notebook.UrlTitle, UrlTitle: notebook.UrlTitle,
IsBlog : notebook.IsBlog, IsBlog: notebook.IsBlog,
CreatedTime : notebook.CreatedTime, CreatedTime: notebook.CreatedTime,
UpdatedTime : notebook.UpdatedTime, UpdatedTime: notebook.UpdatedTime,
Usn: notebook.Usn, Usn: notebook.Usn,
IsDeleted: notebook.IsDeleted, IsDeleted: notebook.IsDeleted,
} }
} }
+1 -1
View File
@@ -3,7 +3,7 @@ package api
import ( import (
"github.com/leanote/leanote/app/info" "github.com/leanote/leanote/app/info"
"github.com/revel/revel" "github.com/revel/revel"
// "gopkg.in/mgo.v2/bson" // "gopkg.in/mgo.v2/bson"
// . "github.com/leanote/leanote/app/lea" // . "github.com/leanote/leanote/app/lea"
// "io/ioutil" // "io/ioutil"
) )
+6 -7
View File
@@ -3,15 +3,15 @@ package api
import ( import (
"github.com/revel/revel" "github.com/revel/revel"
// "encoding/json" // "encoding/json"
"gopkg.in/mgo.v2/bson"
"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"
"time" "time"
// "github.com/leanote/leanote/app/types" // "github.com/leanote/leanote/app/types"
"io/ioutil" "io/ioutil"
// "fmt" // "fmt"
// "math" // "math"
"os" "os"
// "path" // "path"
// "strconv" // "strconv"
@@ -31,10 +31,10 @@ func (c ApiUser) Info() revel.Result {
return c.RenderJson(re) return c.RenderJson(re)
} }
apiUser := info.ApiUser{ apiUser := info.ApiUser{
UserId: userInfo.UserId.Hex(), UserId: userInfo.UserId.Hex(),
Username: userInfo.Username, Username: userInfo.Username,
Email: userInfo.Email, Email: userInfo.Email,
Logo: userInfo.Logo, Logo: userInfo.Logo,
Verified: userInfo.Verified, Verified: userInfo.Verified,
} }
return c.RenderJson(apiUser) return c.RenderJson(apiUser)
@@ -82,7 +82,6 @@ func (c ApiUser) GetSyncState() revel.Result {
return c.RenderJson(ret) return c.RenderJson(ret)
} }
// 头像设置 // 头像设置
// 参数file=文件 // 参数file=文件
// 成功返回{Logo: url} 头像新url // 成功返回{Logo: url} 头像新url
+4 -4
View File
@@ -3,7 +3,7 @@ package api
import ( import (
"github.com/leanote/leanote/app/info" "github.com/leanote/leanote/app/info"
"github.com/leanote/leanote/app/service" "github.com/leanote/leanote/app/service"
// . "github.com/leanote/leanote/app/lea" // . "github.com/leanote/leanote/app/lea"
"github.com/revel/revel" "github.com/revel/revel"
"strings" "strings"
) )
@@ -46,10 +46,10 @@ const (
// 不需要拦截的url // 不需要拦截的url
var commonUrl = map[string]map[string]bool{"ApiAuth": map[string]bool{"Login": true, var commonUrl = map[string]map[string]bool{"ApiAuth": map[string]bool{"Login": true,
"Register": true, "Register": true,
}, },
// 文件的操作也不用登录, userId会从session中获取 // 文件的操作也不用登录, userId会从session中获取
"ApiFile": map[string]bool{"GetImage": true, "ApiFile": map[string]bool{"GetImage": true,
"GetAttach": true, "GetAttach": true,
"GetAllAttachs": true, "GetAllAttachs": true,
}, },
} }
@@ -90,7 +90,7 @@ func AuthInterceptor(c *revel.Controller) revel.Result {
if noToken && userId == "" { if noToken && userId == "" {
// 从session中获取, api/file/getImage, api/file/getAttach, api/file/getAllAttach // 从session中获取, api/file/getImage, api/file/getAttach, api/file/getAllAttach
// 客户端 // 客户端
userId, _ = c.Session["UserId"]; userId, _ = c.Session["UserId"]
} }
c.Session["_userId"] = userId c.Session["_userId"] = userId
+3 -3
View File
@@ -1,10 +1,10 @@
package controllers package controllers
import ( import (
"github.com/leanote/leanote/app/service"
"github.com/leanote/leanote/app/info" "github.com/leanote/leanote/app/info"
"github.com/leanote/leanote/app/lea/blog" "github.com/leanote/leanote/app/lea/blog"
// . "github.com/leanote/leanote/app/lea" "github.com/leanote/leanote/app/service"
// . "github.com/leanote/leanote/app/lea"
"github.com/revel/revel" "github.com/revel/revel"
"strings" "strings"
) )
@@ -68,7 +68,7 @@ var commonUrl = map[string]map[string]bool{"Index": map[string]bool{"Index": tru
}, },
"Oauth": map[string]bool{"GithubCallback": true}, "Oauth": map[string]bool{"GithubCallback": true},
"File": map[string]bool{"OutputImage": true, "OutputFile": true}, "File": map[string]bool{"OutputImage": true, "OutputFile": true},
"Attach": map[string]bool{"Download": true/*, "DownloadAll": true*/}, "Attach": map[string]bool{"Download": true /*, "DownloadAll": true*/},
} }
func needValidate(controller, method string) bool { func needValidate(controller, method string) bool {
+13 -13
View File
@@ -1,15 +1,15 @@
package member package member
import ( import (
// "github.com/revel/revel" // "github.com/revel/revel"
// "gopkg.in/mgo.v2/bson" // "gopkg.in/mgo.v2/bson"
// "encoding/json" // "encoding/json"
. "github.com/leanote/leanote/app/lea"
"github.com/leanote/leanote/app/controllers" "github.com/leanote/leanote/app/controllers"
// "io/ioutil" . "github.com/leanote/leanote/app/lea"
// "fmt" // "io/ioutil"
// "math" // "fmt"
// "strconv" // "math"
// "strconv"
"strings" "strings"
) )
@@ -20,23 +20,23 @@ type MemberBaseController struct {
// 得到sorterField 和 isAsc // 得到sorterField 和 isAsc
// okSorter = ['email', 'username'] // okSorter = ['email', 'username']
func (c MemberBaseController) getSorter(sorterField string, isAsc bool, okSorter []string) (string, bool){ func (c MemberBaseController) getSorter(sorterField string, isAsc bool, okSorter []string) (string, bool) {
sorter := "" sorter := ""
c.Params.Bind(&sorter, "sorter") c.Params.Bind(&sorter, "sorter")
if sorter == "" { if sorter == "" {
return sorterField, isAsc; return sorterField, isAsc
} }
// sorter形式 email-up, email-down // sorter形式 email-up, email-down
s2 := strings.Split(sorter, "-") s2 := strings.Split(sorter, "-")
if len(s2) != 2 { if len(s2) != 2 {
return sorterField, isAsc; return sorterField, isAsc
} }
// 必须是可用的sorter // 必须是可用的sorter
if okSorter != nil && len(okSorter) > 0 { if okSorter != nil && len(okSorter) > 0 {
if !InArray(okSorter, s2[0]) { if !InArray(okSorter, s2[0]) {
return sorterField, isAsc; return sorterField, isAsc
} }
} }
@@ -47,7 +47,7 @@ func (c MemberBaseController) getSorter(sorterField string, isAsc bool, okSorter
isAsc = false isAsc = false
} }
c.RenderArgs["sorter"] = sorter c.RenderArgs["sorter"] = sorter
return sorterField, isAsc; return sorterField, isAsc
} }
func (c MemberBaseController) updateConfig(keys []string) { func (c MemberBaseController) updateConfig(keys []string) {
+15 -13
View File
@@ -74,7 +74,7 @@ func (c MemberBlog) Index(sorter, keywords string) revel.Result {
userInfo := userService.GetUserInfo(userId) userInfo := userService.GetUserInfo(userId)
c.RenderArgs["userInfo"] = userInfo c.RenderArgs["userInfo"] = userInfo
c.RenderArgs["title"] = "Posts" c.RenderArgs["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)
@@ -85,6 +85,8 @@ func (c MemberBlog) Index(sorter, keywords string) revel.Result {
userAndBlog := userService.GetUserAndBlog(c.GetUserId()) userAndBlog := userService.GetUserAndBlog(c.GetUserId())
c.RenderArgs["userAndBlog"] = userAndBlog c.RenderArgs["userAndBlog"] = userAndBlog
c.common()
return c.RenderTemplate("member/blog/list.html") return c.RenderTemplate("member/blog/list.html")
} }
@@ -97,7 +99,8 @@ func (c MemberBlog) UpdateBlogUrlTitle(noteId, urlTitle string) revel.Result {
// 修改笔记的urlTitle // 修改笔记的urlTitle
func (c MemberBlog) UpdateBlogAbstract(noteId string) revel.Result { func (c MemberBlog) UpdateBlogAbstract(noteId string) revel.Result {
c.RenderArgs["title"] = "Update Post Abstract" c.common()
c.RenderArgs["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()
@@ -107,7 +110,6 @@ func (c MemberBlog) UpdateBlogAbstract(noteId string) revel.Result {
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)
@@ -116,24 +118,24 @@ func (c MemberBlog) DoUpdateBlogAbstract(noteId, imgSrc, desc, abstract string)
// 基本信息设置 // 基本信息设置
func (c MemberBlog) Base() revel.Result { func (c MemberBlog) Base() revel.Result {
c.common() c.common()
c.RenderArgs["title"] = "Blog Base Info" c.RenderArgs["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"] = "Comment" c.RenderArgs["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"] = "Paging" c.RenderArgs["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"] = "Cate" c.RenderArgs["title"] = c.Message("Category")
notebooks := blogService.ListBlogNotebooks(c.GetUserId()) notebooks := blogService.ListBlogNotebooks(c.GetUserId())
notebooksMap := map[string]info.Notebook{} notebooksMap := map[string]info.Notebook{}
@@ -190,10 +192,10 @@ func (c MemberBlog) DoAddOrUpdateSingle(singleId, title, content string) revel.R
} }
func (c MemberBlog) AddOrUpdateSingle(singleId string) revel.Result { func (c MemberBlog) AddOrUpdateSingle(singleId string) revel.Result {
c.common() c.common()
c.RenderArgs["title"] = "Add Single" c.RenderArgs["title"] = c.Message("Add Single")
c.RenderArgs["singleId"] = singleId c.RenderArgs["singleId"] = singleId
if singleId != "" { if singleId != "" {
c.RenderArgs["title"] = "Update Single" c.RenderArgs["title"] = c.Message("Update Single")
c.RenderArgs["single"] = blogService.GetSingle(singleId) c.RenderArgs["single"] = blogService.GetSingle(singleId)
} }
return c.RenderTemplate("member/blog/add_single.html") return c.RenderTemplate("member/blog/add_single.html")
@@ -219,7 +221,7 @@ func (c MemberBlog) UpdateSingleUrlTitle(singleId, urlTitle string) revel.Result
func (c MemberBlog) Single() revel.Result { func (c MemberBlog) Single() revel.Result {
c.common() c.common()
c.RenderArgs["title"] = "Cate" c.RenderArgs["title"] = c.Message("Single")
c.RenderArgs["singles"] = blogService.GetSingles(c.GetUserId()) c.RenderArgs["singles"] = blogService.GetSingles(c.GetUserId())
return c.RenderTemplate("member/blog/single.html") return c.RenderTemplate("member/blog/single.html")
@@ -234,7 +236,7 @@ func (c MemberBlog) Theme() revel.Result {
c.RenderArgs["optionThemes"] = themeService.GetDefaultThemes() c.RenderArgs["optionThemes"] = themeService.GetDefaultThemes()
c.RenderArgs["title"] = "Theme" c.RenderArgs["title"] = c.Message("Theme")
return c.RenderTemplate("member/blog/theme.html") return c.RenderTemplate("member/blog/theme.html")
} }
@@ -251,7 +253,7 @@ func (c MemberBlog) UpdateTheme(themeId string, isNew int) revel.Result {
} }
c.common() c.common()
c.RenderArgs["title"] = "Upate Theme" c.RenderArgs["title"] = c.Message("Update Theme")
c.RenderArgs["isNew"] = isNew c.RenderArgs["isNew"] = isNew
// 先复制之 // 先复制之
@@ -443,8 +445,8 @@ func (c MemberBlog) ImportTheme() revel.Result {
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)
} }
defer file.Close() defer file.Close()
// 生成上传路径 // 生成上传路径
userId := c.GetUserId() userId := c.GetUserId()
@@ -1,8 +1,8 @@
package member package member
import ( import (
"github.com/revel/revel"
"github.com/leanote/leanote/app/info" "github.com/leanote/leanote/app/info"
"github.com/revel/revel"
) )
// 分组管理 // 分组管理
@@ -14,9 +14,9 @@ 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"] = "My Group" c.RenderArgs["title"] = c.Message("My Group")
c.RenderArgs["groups"] = groupService.GetGroupsAndUsers(c.GetUserId()) c.RenderArgs["groups"] = groupService.GetGroupsAndUsers(c.GetUserId())
return c.RenderTemplate("member/group/index.html"); return c.RenderTemplate("member/group/index.html")
} }
// 添加分组 // 添加分组
@@ -13,14 +13,14 @@ type MemberIndex struct {
// admin 主页 // admin 主页
func (c MemberIndex) Index() revel.Result { func (c MemberIndex) Index() revel.Result {
c.SetUserInfo() c.SetUserInfo()
c.RenderArgs["title"] = "Leanote Member Center" c.RenderArgs["title"] = c.Message("Leanote Member Center")
c.RenderArgs["countNote"] = noteService.CountNote(c.GetUserId()) c.RenderArgs["countNote"] = noteService.CountNote(c.GetUserId())
c.RenderArgs["countBlog"] = noteService.CountBlog(c.GetUserId()) c.RenderArgs["countBlog"] = noteService.CountBlog(c.GetUserId())
c.SetLocale() c.SetLocale()
return c.RenderTemplate("member/index.html"); return c.RenderTemplate("member/index.html")
} }
// 模板 // 模板
@@ -33,5 +33,5 @@ func (c MemberIndex) T(t string) revel.Result {
} }
func (c MemberIndex) GetView(view string) revel.Result { func (c MemberIndex) GetView(view string) revel.Result {
return c.RenderTemplate("admin/" + view); return c.RenderTemplate("admin/" + view)
} }
+8 -14
View File
@@ -13,34 +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"] = "Username" c.RenderArgs["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"] = "Email" c.RenderArgs["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"] = "Password" c.RenderArgs["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"] = "Avatar" c.RenderArgs["title"] = c.Message("Avatar")
c.RenderArgs["globalConfigs"] = configService.GetGlobalConfigForUser() c.RenderArgs["globalConfigs"] = configService.GetGlobalConfigForUser()
return c.RenderTemplate("member/user/avatar.html"); return c.RenderTemplate("member/user/avatar.html")
}
func (c MemberUser) AddAccount() revel.Result {
c.SetUserInfo()
c.SetLocale()
c.RenderArgs["title"] = "Add Account"
return c.RenderTemplate("member/user/add_account.html");
} }
+30 -29
View File
@@ -1,11 +1,11 @@
package member package member
import ( import (
"github.com/leanote/leanote/app/service"
"github.com/leanote/leanote/app/info" "github.com/leanote/leanote/app/info"
// . "github.com/leanote/leanote/app/lea" "github.com/leanote/leanote/app/service"
// . "github.com/leanote/leanote/app/lea"
"github.com/revel/revel" "github.com/revel/revel"
// "strings" // "strings"
) )
var userService *service.UserService var userService *service.UserService
@@ -34,30 +34,31 @@ var themeService *service.ThemeService
// 不需要拦截的url // 不需要拦截的url
// Index 除了Note之外都不需要 // Index 除了Note之外都不需要
var commonUrl = map[string]map[string]bool{"Index": map[string]bool{"Index": true, var commonUrl = map[string]map[string]bool{"Index": map[string]bool{"Index": true,
"Login": true, "Login": true,
"DoLogin": true, "DoLogin": true,
"Logout": true, "Logout": true,
"Register": true, "Register": true,
"DoRegister": true, "DoRegister": true,
"FindPasswword": true, "FindPasswword": true,
"DoFindPassword": true, "DoFindPassword": true,
"FindPassword2": true, "FindPassword2": true,
"FindPasswordUpdate": true, "FindPasswordUpdate": true,
"Suggestion": true, "Suggestion": true,
}, },
"Blog": map[string]bool{"Index": true, "Blog": map[string]bool{"Index": true,
"View": true, "View": true,
"AboutMe": true, "AboutMe": true,
"SearchBlog": true, "SearchBlog": true,
}, },
// 用户的激活与修改邮箱都不需要登录, 通过链接地址 // 用户的激活与修改邮箱都不需要登录, 通过链接地址
"User": map[string]bool{"UpdateEmail": true, "User": map[string]bool{"UpdateEmail": true,
"ActiveEmail":true, "ActiveEmail": true,
}, },
"Oauth": map[string]bool{"GithubCallback": true}, "Oauth": map[string]bool{"GithubCallback": true},
"File": map[string]bool{"OutputImage": true, "OutputFile": true}, "File": map[string]bool{"OutputImage": true, "OutputFile": true},
"Attach": map[string]bool{"Download": true, "DownloadAll": true}, "Attach": map[string]bool{"Download": true, "DownloadAll": true},
} }
func needValidate(controller, method string) bool { func needValidate(controller, method string) bool {
// 在里面 // 在里面
if v, ok := commonUrl[controller]; ok { if v, ok := commonUrl[controller]; ok {
@@ -68,18 +69,18 @@ func needValidate(controller, method string) bool {
return true return true
} else { } else {
// controller不在这里的, 肯定要验证 // controller不在这里的, 肯定要验证
return true; return true
} }
} }
func AuthInterceptor(c *revel.Controller) revel.Result { func AuthInterceptor(c *revel.Controller) revel.Result {
// 全部变成首字大写 // 全部变成首字大写
/* /*
var controller = strings.Title(c.Name) var controller = strings.Title(c.Name)
var method = strings.Title(c.MethodName) var method = strings.Title(c.MethodName)
// 是否需要验证? // 是否需要验证?
if !needValidate(controller, method) { if !needValidate(controller, method) {
return nil return nil
} }
*/ */
// 验证是否已登录 // 验证是否已登录
@@ -113,7 +114,7 @@ func InitService() {
tokenService = service.TokenS tokenService = service.TokenS
noteImageService = service.NoteImageS noteImageService = service.NoteImageS
fileService = service.FileS fileService = service.FileS
albumService= service.AlbumS albumService = service.AlbumS
attachService = service.AttachS attachService = service.AttachS
pwdService = service.PwdS pwdService = service.PwdS
suggestionService = service.SuggestionS suggestionService = service.SuggestionS
-2
View File
@@ -1,2 +0,0 @@
包括基本信息设置
博客设置
+12 -12
View File
@@ -2,8 +2,8 @@ package db
import ( import (
"fmt" "fmt"
"github.com/revel/revel"
. "github.com/leanote/leanote/app/lea" . "github.com/leanote/leanote/app/lea"
"github.com/revel/revel"
"gopkg.in/mgo.v2" "gopkg.in/mgo.v2"
"gopkg.in/mgo.v2/bson" "gopkg.in/mgo.v2/bson"
"strings" "strings"
@@ -360,15 +360,15 @@ func Err(err error) bool {
// 每个请求之前都要检查!! // 每个请求之前都要检查!!
func CheckMongoSessionLost() { func CheckMongoSessionLost() {
// fmt.Println("检查CheckMongoSessionLostErr") // fmt.Println("检查CheckMongoSessionLostErr")
err := Session.Ping() err := Session.Ping()
if err != nil { if err != nil {
Log("Lost connection to db!") Log("Lost connection to db!")
Session.Refresh() Session.Refresh()
err = Session.Ping() err = Session.Ping()
if err == nil { if err == nil {
Log("Reconnect to db successful.") Log("Reconnect to db successful.")
} else { } else {
Log("重连失败!!!! 警告") Log("重连失败!!!! 警告")
} }
} }
} }
-91
View File
@@ -1,91 +0,0 @@
package main
import (
"fmt"
"os"
"bufio"
"strings"
"encoding/json"
)
// convert revel msg to js msg
var msgBasePath = "/Users/life/Documents/Go/package2/src/github.com/leanote/leanote/messages/"
var targetBasePath = "/Users/life/Documents/Go/package2/src/github.com/leanote/leanote/public/js/i18n/"
func parse(filename string) {
file, err := os.Open(msgBasePath + filename)
reader := bufio.NewReader(file)
msg := map[string]string{}
if err != nil {
fmt.Println(err)
return
}
for true {
line, _, err := reader.ReadLine()
if err != nil {
break
}
if len(line) == 0 {
continue
}
// 对每一行进行处理
if line[0] == '#' || line[1] == '#' {
continue;
}
lineStr := string(line)
// 找到第一个=位置
pos := strings.Index(lineStr, "=")
if pos < 0 {
continue;
}
key := string(line[0:pos])
value := string(line[pos+1:])
// fmt.Println(lineStr)
// fmt.Println(value)
msg[key] = value
}
// JSON
b, _ := json.Marshal(msg)
str := string(b)
fmt.Println(str);
targetName := targetBasePath + filename + ".js"
file2, err2 := os.OpenFile(targetName, os.O_RDWR|os.O_CREATE, 0644)
if err2 != nil {
file2, err2 = os.Create(targetName)
}
file2.WriteString("var MSG = " + str + ";" + `
function getMsg(key, data) {
var msg = MSG[key]
if(msg) {
if(data) {
if(!isArray(data)) {
data = [data];
}
for(var i = 0; i < data.length; ++i) {
msg = msg.replace("%s", data[i]);
}
}
return msg;
}
return key;
}`)
}
// 生成js的i18n文件
func main() {
parse("msg.en")
parse("msg.zh")
parse("msg.fr")
parse("blog.zh")
parse("blog.en")
parse("blog.fr")
}
+29 -29
View File
@@ -1,20 +1,20 @@
package info package info
import ( import (
"time"
"gopkg.in/mgo.v2/bson" "gopkg.in/mgo.v2/bson"
"time"
) )
//--------- //---------
// 数据结构 // 数据结构
//--------- //---------
type NoteFile struct { type NoteFile struct {
FileId string // 服务器端Id FileId string // 服务器端Id
LocalFileId string // 客户端Id LocalFileId string // 客户端Id
Type string // images/png, doc, xls, 根据fileName确定 Type string // images/png, doc, xls, 根据fileName确定
Title string Title string
HasBody bool // 传过来的值是否要更新内容 HasBody bool // 传过来的值是否要更新内容
IsAttach bool // 是否是附件, 不是附件就是图片 IsAttach bool // 是否是附件, 不是附件就是图片
} }
type ApiNote struct { type ApiNote struct {
NoteId string NoteId string
@@ -22,32 +22,31 @@ type ApiNote struct {
UserId string UserId string
Title string Title string
Desc string Desc string
// ImgSrc string // ImgSrc string
Tags []string Tags []string
Abstract string Abstract string
Content string Content string
IsMarkdown bool IsMarkdown bool
// FromUserId string // 为共享而新建 // FromUserId string // 为共享而新建
IsBlog bool // 是否是blog, 更新note不需要修改, 添加note时才有可能用到, 此时需要判断notebook是否设为Blog IsBlog bool // 是否是blog, 更新note不需要修改, 添加note时才有可能用到, 此时需要判断notebook是否设为Blog
IsTrash bool IsTrash bool
IsDeleted bool IsDeleted bool
Usn int Usn int
Files []NoteFile Files []NoteFile
CreatedTime time.Time CreatedTime time.Time
UpdatedTime time.Time UpdatedTime time.Time
PublicTime time.Time PublicTime time.Time
} }
// 内容 // 内容
type ApiNoteContent struct { type ApiNoteContent struct {
NoteId bson.ObjectId `bson:"_id,omitempty"` NoteId bson.ObjectId `bson:"_id,omitempty"`
UserId bson.ObjectId `bson:"UserId"` UserId bson.ObjectId `bson:"UserId"`
Content string `Content` Content string `Content`
// CreatedTime time.Time `CreatedTime` // CreatedTime time.Time `CreatedTime`
// UpdatedTime time.Time `UpdatedTime` // UpdatedTime time.Time `UpdatedTime`
} }
// 转换 // 转换
@@ -61,11 +60,11 @@ func NoteToApiNote(note Note, files []NoteFile) ApiNote {
//---------- //----------
type ApiUser struct { type ApiUser struct {
UserId string UserId string
Username string Username string
Email string Email string
Verified bool Verified bool
Logo string Logo string
} }
//---------- //----------
@@ -81,8 +80,8 @@ type ApiNotebook struct {
IsBlog bool `IsBlog,omitempty` // 是否是Blog 2013/12/29 新加 IsBlog bool `IsBlog,omitempty` // 是否是Blog 2013/12/29 新加
CreatedTime time.Time `CreatedTime,omitempty` CreatedTime time.Time `CreatedTime,omitempty`
UpdatedTime time.Time `UpdatedTime,omitempty` UpdatedTime time.Time `UpdatedTime,omitempty`
Usn int `Usn` // UpdateSequenceNum Usn int `Usn` // UpdateSequenceNum
IsDeleted bool `IsDeleted` IsDeleted bool `IsDeleted`
} }
//--------- //---------
@@ -91,7 +90,7 @@ type ApiNotebook struct {
// 一般返回 // 一般返回
type ApiRe struct { type ApiRe struct {
Ok bool Ok bool
Msg string Msg string
} }
@@ -101,19 +100,20 @@ func NewApiRe() ApiRe {
// auth // auth
type AuthOk struct { type AuthOk struct {
Ok bool Ok bool
Token string Token string
UserId bson.ObjectId UserId bson.ObjectId
Email string Email string
Username string Username string
} }
// 供notebook, note, tag更新的返回数据用 // 供notebook, note, tag更新的返回数据用
type ReUpdate struct { type ReUpdate struct {
Ok bool Ok bool
Msg string Msg string
Usn int Usn int
} }
func NewReUpdate() ReUpdate { func NewReUpdate() ReUpdate {
return ReUpdate{Ok: false} return ReUpdate{Ok: false}
} }
+9 -9
View File
@@ -7,15 +7,15 @@ import (
// Attach belongs to note // Attach belongs to note
type Attach struct { type Attach struct {
AttachId bson.ObjectId `bson:"_id,omitempty"` // AttachId bson.ObjectId `bson:"_id,omitempty"` //
NoteId bson.ObjectId `bson:"NoteId"` // NoteId bson.ObjectId `bson:"NoteId"` //
UploadUserId bson.ObjectId `bson:"UploadUserId"` // 可以不是note owner, 协作者userId UploadUserId bson.ObjectId `bson:"UploadUserId"` // 可以不是note owner, 协作者userId
Name string `Name` // file name, md5, such as 13232312.doc Name string `Name` // file name, md5, such as 13232312.doc
Title string `Title` // raw file name Title string `Title` // raw file name
Size int64 `Size` // file size (byte) Size int64 `Size` // file size (byte)
Type string `Type` // file type, "doc" = word Type string `Type` // file type, "doc" = word
Path string `Path` // the file path such as: files/userId/attachs/adfadf.doc Path string `Path` // the file path such as: files/userId/attachs/adfadf.doc
CreatedTime time.Time `CreatedTime` CreatedTime time.Time `CreatedTime`
// FromFileId bson.ObjectId `bson:"FromFileId,omitempty"` // copy from fileId, for collaboration // FromFileId bson.ObjectId `bson:"FromFileId,omitempty"` // copy from fileId, for collaboration
} }
+29 -28
View File
@@ -7,51 +7,52 @@ import (
// 仅仅为了博客的主题 // 仅仅为了博客的主题
type BlogInfoCustom struct { type BlogInfoCustom struct {
UserId string UserId string
Username string Username string
UserLogo string UserLogo string
Title string Title string
SubTitle string SubTitle string
Logo string Logo string
OpenComment bool OpenComment bool
CommentType string CommentType string
ThemeId string ThemeId string
SubDomain string SubDomain string
Domain string Domain string
} }
type Post struct { type Post struct {
NoteId string NoteId string
Title string Title string
UrlTitle string UrlTitle string
ImgSrc string ImgSrc string
CreatedTime time.Time CreatedTime time.Time
UpdatedTime time.Time UpdatedTime time.Time
PublicTime time.Time PublicTime time.Time
Desc string Desc string
Abstract string Abstract string
Content string Content string
Tags []string Tags []string
CommentNum int CommentNum int
ReadNum int ReadNum int
LikeNum int LikeNum int
IsMarkdown bool IsMarkdown bool
} }
// 归档 // 归档
type ArchiveMonth struct { type ArchiveMonth struct {
Month int Month int
Posts []*Post Posts []*Post
} }
type Archive struct { type Archive struct {
Year int Year int
MonthAchives []ArchiveMonth MonthAchives []ArchiveMonth
Posts []*Post Posts []*Post
} }
type Cate struct { type Cate struct {
CateId string CateId string
ParentCateId string ParentCateId string
Title string Title string
UrlTitle string UrlTitle string
Children []*Cate Children []*Cate
} }
+22 -22
View File
@@ -10,16 +10,16 @@ import (
type BlogItem struct { type BlogItem struct {
Note Note
Abstract string Abstract string
Content string // 可能是content的一部分, 截取. 点击more后就是整个信息了 Content string // 可能是content的一部分, 截取. 点击more后就是整个信息了
HasMore bool // 是否是否还有 HasMore bool // 是否是否还有
User User // 用户信息 User User // 用户信息
} }
type UserBlogBase struct { type UserBlogBase struct {
Logo string `Logo` Logo string `Logo`
Title string `Title` // 标题 Title string `Title` // 标题
SubTitle string `SubTitle` // 副标题 SubTitle string `SubTitle` // 副标题
// AboutMe string `AboutMe` // 关于我 // AboutMe string `AboutMe` // 关于我
} }
type UserBlogComment struct { type UserBlogComment struct {
@@ -49,15 +49,15 @@ type UserBlog struct {
Style string `Style` // 风格 Style string `Style` // 风格
Css string `Css` // 自定义css Css string `Css` // 自定义css
ThemeId bson.ObjectId `ThemeId,omitempty` // 主题Id ThemeId bson.ObjectId `ThemeId,omitempty` // 主题Id
ThemePath string `bson:"ThemePath" json:"-"` // 不存值, 从Theme中获取, 相对路径 public/ ThemePath string `bson:"ThemePath" json:"-"` // 不存值, 从Theme中获取, 相对路径 public/
CateIds []string `CateIds,omitempty` // 分类Id, 排序好的 CateIds []string `CateIds,omitempty` // 分类Id, 排序好的
Singles []map[string]string `Singles,omitempty` // 单页, 排序好的, map包含: ["Title"], ["SingleId"] Singles []map[string]string `Singles,omitempty` // 单页, 排序好的, map包含: ["Title"], ["SingleId"]
PerPageSize int `PerPageSize,omitempty` PerPageSize int `PerPageSize,omitempty`
SortField string `SortField` // 排序字段 SortField string `SortField` // 排序字段
IsAsc bool `IsAsc,omitempty` // 排序类型, 降序, 升序, 默认是false, 表示降序 IsAsc bool `IsAsc,omitempty` // 排序类型, 降序, 升序, 默认是false, 表示降序
SubDomain string `SubDomain` // 二级域名 SubDomain string `SubDomain` // 二级域名
Domain string `Domain` // 自定义域名 Domain string `Domain` // 自定义域名
@@ -66,15 +66,15 @@ type UserBlog struct {
// 博客统计信息 // 博客统计信息
type BlogStat struct { type BlogStat struct {
NoteId bson.ObjectId `bson:"_id,omitempty"` NoteId bson.ObjectId `bson:"_id,omitempty"`
ReadNum int `ReadNum,omitempty` // 阅读次数 2014/9/28 ReadNum int `ReadNum,omitempty` // 阅读次数 2014/9/28
LikeNum int `LikeNum,omitempty` // 点赞次数 2014/9/28 LikeNum int `LikeNum,omitempty` // 点赞次数 2014/9/28
CommentNum int `CommentNum,omitempty` // 评论次数 2014/9/28 CommentNum int `CommentNum,omitempty` // 评论次数 2014/9/28
} }
// 单页 // 单页
type BlogSingle struct { type BlogSingle struct {
SingleId bson.ObjectId `bson:"_id,omitempty"` SingleId bson.ObjectId `bson:"_id,omitempty"`
UserId bson.ObjectId `UserId` UserId bson.ObjectId `UserId`
Title string `Title` Title string `Title`
UrlTitle string `UrlTitle` // 2014/11/11 UrlTitle string `UrlTitle` // 2014/11/11
@@ -117,12 +117,12 @@ type BlogCommentPublic struct {
} }
type BlogUrls struct { type BlogUrls struct {
IndexUrl string IndexUrl string
CateUrl string CateUrl string
SearchUrl string SearchUrl string
SingleUrl string SingleUrl string
PostUrl string PostUrl string
ArchiveUrl string ArchiveUrl string
TagsUrl string TagsUrl string
TagPostsUrl string TagPostsUrl string
} }
+3 -3
View File
@@ -10,9 +10,9 @@ type Config struct {
ConfigId bson.ObjectId `bson:"_id"` ConfigId bson.ObjectId `bson:"_id"`
UserId bson.ObjectId `UserId` UserId bson.ObjectId `UserId`
Key string `Key` Key string `Key`
ValueStr string `ValueStr,omitempty` // "1" ValueStr string `ValueStr,omitempty` // "1"
ValueArr []string `ValueArr,omitempty` // ["1","b","c"] ValueArr []string `ValueArr,omitempty` // ["1","b","c"]
ValueMap map[string]string `ValueMap,omitempty` // {"a":"bb", "CC":"xx"} ValueMap map[string]string `ValueMap,omitempty` // {"a":"bb", "CC":"xx"}
ValueArrMap []map[string]string `ValueArrMap,omitempty` // [{"a":"B"}, {}, {}] ValueArrMap []map[string]string `ValueArrMap,omitempty` // [{"a":"B"}, {}, {}]
IsArr bool `IsArr` // 是否是数组 IsArr bool `IsArr` // 是否是数组
IsMap bool `IsMap` // 是否是Map IsMap bool `IsMap` // 是否是Map
+21
View File
@@ -80,3 +80,24 @@ type NoteContentHistory struct {
UserId bson.ObjectId `bson:"UserId"` // 所属者 UserId bson.ObjectId `bson:"UserId"` // 所属者
Histories []EachHistory `Histories` Histories []EachHistory `Histories`
} }
// 为了NoteController接收参数
// 更新note或content
// 肯定会传userId(谁的), NoteId
// 会传Title, Content, Tags, 一种或几种
type NoteOrContent struct {
NotebookId string
NoteId string
UserId string
Title string
Desc string
ImgSrc string
Tags string
Content string
Abstract string
IsNew bool
IsMarkdown bool
FromUserId string // 为共享而新建
IsBlog bool // 是否是blog, 更新note不需要修改, 添加note时才有可能用到, 此时需要判断notebook是否设为Blog
}
+1 -1
View File
@@ -21,7 +21,7 @@ type Notebook struct {
UpdatedTime time.Time `UpdatedTime,omitempty` UpdatedTime time.Time `UpdatedTime,omitempty`
// 2015/1/15, 更新序号 // 2015/1/15, 更新序号
Usn int `Usn` // UpdateSequenceNum Usn int `Usn` // UpdateSequenceNum
IsDeleted bool `IsDeleted` IsDeleted bool `IsDeleted`
} }
+4 -5
View File
@@ -1,14 +1,13 @@
package info package info
import ( import ()
)
// controller ajax返回 // controller ajax返回
type Re struct { type Re struct {
Ok bool Ok bool
Code int Code int
Msg string Msg string
Id string Id string
List interface{} List interface{}
Item interface{} Item interface{}
} }
+1 -1
View File
@@ -14,7 +14,7 @@ type Session struct {
LoginTimes int `LoginTimes` // 登录错误时间 LoginTimes int `LoginTimes` // 登录错误时间
Captcha string `Captcha` // 验证码 Captcha string `Captcha` // 验证码
UserId string `UserId` // API时有值UserId UserId string `UserId` // API时有值UserId
CreatedTime time.Time `CreatedTime` CreatedTime time.Time `CreatedTime`
UpdatedTime time.Time `UpdatedTime` // 更新时间, expire这个时间会自动清空 UpdatedTime time.Time `UpdatedTime` // 更新时间, expire这个时间会自动清空
+14 -14
View File
@@ -18,28 +18,28 @@ type TagNote struct {
// 每个用户一条记录, 存储用户的所有tags // 每个用户一条记录, 存储用户的所有tags
type Tag struct { type Tag struct {
UserId bson.ObjectId `bson:"_id"` UserId bson.ObjectId `bson:"_id"`
Tags []string `Tags` Tags []string `Tags`
} }
// v2 版标签 // v2 版标签
type NoteTag struct { type NoteTag struct {
TagId bson.ObjectId `bson:"_id"` TagId bson.ObjectId `bson:"_id"`
UserId bson.ObjectId `UserId` // 谁的 UserId bson.ObjectId `UserId` // 谁的
Tag string `Tag` // UserId, Tag是唯一索引 Tag string `Tag` // UserId, Tag是唯一索引
Usn int `Usn` // Update Sequence Number Usn int `Usn` // Update Sequence Number
Count int `Count` // 笔记数 Count int `Count` // 笔记数
CreatedTime time.Time `CreatedTime` CreatedTime time.Time `CreatedTime`
UpdatedTime time.Time `UpdatedTime` UpdatedTime time.Time `UpdatedTime`
IsDeleted bool `IsDeleted` // 删除位 IsDeleted bool `IsDeleted` // 删除位
} }
type TagCount struct { type TagCount struct {
TagCountId bson.ObjectId `bson:"_id,omitempty"` TagCountId bson.ObjectId `bson:"_id,omitempty"`
UserId bson.ObjectId `UserId` // 谁的 UserId bson.ObjectId `UserId` // 谁的
Tag string `Tag` Tag string `Tag`
IsBlog bool `IsBlog` // 是否是博客的tag统计 IsBlog bool `IsBlog` // 是否是博客的tag统计
Count int `Count` // 统计数量 Count int `Count` // 统计数量
} }
/* /*
+1 -1
View File
@@ -18,7 +18,7 @@ type Theme struct {
Info map[string]interface{} `Info` // 所有信息 Info map[string]interface{} `Info` // 所有信息
IsActive bool `IsActive` // 是否在用 IsActive bool `IsActive` // 是否在用
IsDefault bool `IsDefault` // leanote默认主题, 如果用户修改了默认主题, 则先copy之. 也是admin用户的主题 IsDefault bool `IsDefault` // leanote默认主题, 如果用户修改了默认主题, 则先copy之. 也是admin用户的主题
Style string `Style,omitempty` // 之前的, 只有default的用户才有blog_default, blog_daqi, blog_left_fixed Style string `Style,omitempty` // 之前的, 只有default的用户才有blog_default, blog_daqi, blog_left_fixed
CreatedTime time.Time `CreatedTime` CreatedTime time.Time `CreatedTime`
+1 -1
View File
@@ -18,7 +18,7 @@ const (
// 过期时间 // 过期时间
const ( const (
PwdOverHours = 2.0 PwdOverHours = 2.0
ActiveEmailOverHours = 48.0 ActiveEmailOverHours = 48.0
UpdateEmailOverHours = 2.0 UpdateEmailOverHours = 2.0
) )
+2 -2
View File
@@ -73,8 +73,8 @@ type UserAccount struct {
// note主页需要 // note主页需要
type UserAndBlogUrl struct { type UserAndBlogUrl struct {
User User
BlogUrl string `BlogUrl` BlogUrl string `BlogUrl`
PostUrl string `PostUrl` PostUrl string `PostUrl`
} }
// 用户与博客信息结合, 公开 // 用户与博客信息结合, 公开
+4 -5
View File
@@ -4,14 +4,13 @@ import (
"math" "math"
) )
// 分页数据 // 分页数据
type Page struct { type Page struct {
CurPage int // 当前页码 CurPage int // 当前页码
TotalPage int // 总页 TotalPage int // 总页
PerPageSize int PerPageSize int
Count int // 总记录数 Count int // 总记录数
List interface{} List interface{}
} }
func NewPage(page, perPageSize, count int, list interface{}) Page { func NewPage(page, perPageSize, count int, list interface{}) Page {
+124 -114
View File
@@ -1,31 +1,32 @@
package app package app
import ( import (
"github.com/revel/revel" "encoding/json"
. "github.com/leanote/leanote/app/lea"
"github.com/leanote/leanote/app/service"
"github.com/leanote/leanote/app/db"
"github.com/leanote/leanote/app/controllers"
"github.com/leanote/leanote/app/controllers/api"
"github.com/leanote/leanote/app/controllers/admin"
"github.com/leanote/leanote/app/controllers/member"
_ "github.com/leanote/leanote/app/lea/binder"
"github.com/leanote/leanote/app/lea/route"
"reflect"
"fmt" "fmt"
"github.com/leanote/leanote/app/controllers"
"github.com/leanote/leanote/app/controllers/admin"
"github.com/leanote/leanote/app/controllers/api"
"github.com/leanote/leanote/app/controllers/member"
"github.com/leanote/leanote/app/db"
. "github.com/leanote/leanote/app/lea"
_ "github.com/leanote/leanote/app/lea/binder"
"github.com/leanote/leanote/app/lea/i18n"
"github.com/leanote/leanote/app/lea/route"
"github.com/leanote/leanote/app/service"
"github.com/revel/revel"
"html/template" "html/template"
"math" "math"
"strings"
"strconv"
"time"
"encoding/json"
"net/url" "net/url"
"reflect"
"strconv"
"strings"
"time"
) )
func init() { func init() {
// Filters is the default set of global filters. // Filters is the default set of global filters.
revel.Filters = []revel.Filter{ revel.Filters = []revel.Filter{
revel.PanicFilter, // Recover from panics and display an error page instead. revel.PanicFilter, // Recover from panics and display an error page instead.
route.RouterFilter, route.RouterFilter,
// revel.RouterFilter, // Use the routing table to select the right Action // revel.RouterFilter, // Use the routing table to select the right Action
// AuthFilter, // Invoke the action. // AuthFilter, // Invoke the action.
@@ -38,12 +39,13 @@ func init() {
// session.SessionFilter, // leanote session // session.SessionFilter, // leanote session
// session.MSessionFilter, // leanote memcache session // session.MSessionFilter, // leanote memcache session
revel.FlashFilter, // Restore and write the flash cookie. revel.FlashFilter, // Restore and write the flash cookie.
revel.ValidationFilter, // Restore kept validation errors and save new ones from cookie. revel.ValidationFilter, // Restore kept validation errors and save new ones from cookie.
revel.I18nFilter, // Resolve the requested language // revel.I18nFilter, // Resolve the requested language
revel.InterceptorFilter, // Run interceptors around the action. i18n.I18nFilter, // Resolve the requested language by leanote
revel.CompressFilter, // Compress the result. revel.InterceptorFilter, // Run interceptors around the action.
revel.ActionInvoker, // Invoke the action. revel.CompressFilter, // Compress the result.
revel.ActionInvoker, // Invoke the action.
} }
revel.TemplateFuncs["raw"] = func(str string) template.HTML { revel.TemplateFuncs["raw"] = func(str string) template.HTML {
@@ -62,16 +64,16 @@ func init() {
return str return str
} }
revel.TemplateFuncs["add"] = func(i int) string { revel.TemplateFuncs["add"] = func(i int) string {
i = i + 1; i = i + 1
return fmt.Sprintf("%v", i) return fmt.Sprintf("%v", i)
} }
revel.TemplateFuncs["sub"] = func(i int) int { revel.TemplateFuncs["sub"] = func(i int) int {
i = i - 1; i = i - 1
return i return i
} }
// 增加或减少 // 增加或减少
revel.TemplateFuncs["incr"] = func(n, i int) int { revel.TemplateFuncs["incr"] = func(n, i int) int {
n = n + i; n = n + i
return n return n
} }
revel.TemplateFuncs["join"] = func(arr []string) template.HTML { revel.TemplateFuncs["join"] = func(arr []string) template.HTML {
@@ -147,8 +149,8 @@ func init() {
classes += " label-post" classes += " label-post"
var url = tagPostUrl + "/" + url.QueryEscape(tag) var url = tagPostUrl + "/" + url.QueryEscape(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 += " "
} }
} }
@@ -172,22 +174,30 @@ func init() {
} }
classes += " label-post" classes += " label-post"
tagStr += "<span class=\"" + classes + "\" >" + str + "</span>"; tagStr += "<span class=\"" + classes + "\" >" + str + "</span>"
if i != lenTags - 1 { if i != lenTags-1 {
tagStr += " " tagStr += " "
} }
} }
return template.HTML(tagStr) return template.HTML(tagStr)
} }
revel.TemplateFuncs["msg"] = func(renderArgs map[string]interface{}, message string, args ...interface{}) template.HTML {
str, ok := renderArgs[revel.CurrentLocaleRenderArg].(string)
if !ok {
return ""
}
return template.HTML(i18n.Message(str, message, args...))
}
// 不用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.CurrentLocaleRenderArg].(string)
str := revel.Message(locale, key) str := i18n.Message(locale, key)
if strings.HasPrefix(str, "???") { if strings.HasPrefix(str, "???") {
str = key str = key
} }
return template.HTML(str); return template.HTML(str)
} }
// lea++ // lea++
@@ -201,11 +211,11 @@ func init() {
tagPostUrl := "http://lea.leanote.com/" tagPostUrl := "http://lea.leanote.com/"
if typeStr == "recommend" { if typeStr == "recommend" {
tagPostUrl += "?tag="; tagPostUrl += "?tag="
} else if typeStr == "latest" { } else if typeStr == "latest" {
tagPostUrl += "latest?tag="; tagPostUrl += "latest?tag="
} else { } else {
tagPostUrl += "subscription?tag="; tagPostUrl += "subscription?tag="
} }
for i, tag := range tags { for i, tag := range tags {
@@ -221,8 +231,8 @@ func init() {
} }
classes += " label-post" classes += " label-post"
var url = tagPostUrl + url.QueryEscape(tag) var url = tagPostUrl + url.QueryEscape(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 += " "
} }
} }
@@ -230,55 +240,55 @@ func init() {
} }
/* /*
revel.TemplateFuncs["blogTags"] = func(tags []string) template.HTML { revel.TemplateFuncs["blogTags"] = func(tags []string) template.HTML {
if tags == nil || len(tags) == 0 { if tags == nil || len(tags) == 0 {
return "" return ""
}
// TODO 这里判断语言, 从语言包中拿
tagMap := map[string]string{"red": "红色", "yellow": "黄色", "blue": "蓝色", "green": "绿色"}
tagStr := ""
lenTags := len(tags)
for i, tag := range tags {
if text, ok := tagMap[tag]; ok {
tagStr += text
} else {
tagStr += tag
} }
if i != lenTags - 1 { // TODO 这里判断语言, 从语言包中拿
tagStr += "," tagMap := map[string]string{"red": "红色", "yellow": "黄色", "blue": "蓝色", "green": "绿色"}
tagStr := ""
lenTags := len(tags)
for i, tag := range tags {
if text, ok := tagMap[tag]; ok {
tagStr += text
} else {
tagStr += tag
}
if i != lenTags - 1 {
tagStr += ","
}
} }
return template.HTML(tagStr)
} }
return template.HTML(tagStr)
}
*/ */
revel.TemplateFuncs["li"] = func(a string) string { revel.TemplateFuncs["li"] = func(a string) string {
return "" return ""
} }
// str连接 // str连接
revel.TemplateFuncs["urlConcat"] = func(url string, v... interface{}) string { revel.TemplateFuncs["urlConcat"] = func(url string, v ...interface{}) string {
html := "" html := ""
for i := 0; i < len(v); i = i + 2 { for i := 0; i < len(v); i = i + 2 {
item := v[i] item := v[i]
if i+1 == len(v) { if i+1 == len(v) {
break; break
} }
value := v[i+1] value := v[i+1]
if item != nil && value != nil { if item != nil && value != nil {
keyStr, _ := item.(string) keyStr, _ := item.(string)
valueStr, err := value.(string) valueStr, err := value.(string)
if !err { if !err {
valueInt, _ := value.(int) valueInt, _ := value.(int)
valueStr = strconv.Itoa(valueInt) valueStr = strconv.Itoa(valueInt)
} }
if keyStr != "" && valueStr != "" { if keyStr != "" && valueStr != "" {
s := keyStr + "=" + valueStr s := keyStr + "=" + valueStr
if html != "" { if html != "" {
html += "&" + s html += "&" + s
} else { } else {
html += s html += s
} }
} }
} }
} }
if html != "" { if html != "" {
@@ -308,32 +318,32 @@ func init() {
// 必须要返回HTMLAttr, 返回html, golang 会执行安全检查返回ZgotmplZ // 必须要返回HTMLAttr, 返回html, golang 会执行安全检查返回ZgotmplZ
// sorterI 可能是nil, 所以用interfalce{}来接收 // sorterI 可能是nil, 所以用interfalce{}来接收
/* /*
data-url="/adminUser/index" data-url="/adminUser/index"
data-sorter="email" data-sorter="email"
class="th-sortable {{if eq .sorter "email-up"}}th-sort-up{{else}}{{if eq .sorter "email-down"}}th-sort-down{{end}}{{end}}" class="th-sortable {{if eq .sorter "email-up"}}th-sort-up{{else}}{{if eq .sorter "email-down"}}th-sort-down{{end}}{{end}}"
*/ */
revel.TemplateFuncs["sorterTh"] = func(url, sorterField string, sorterI interface{}) template.HTMLAttr { revel.TemplateFuncs["sorterTh"] = func(url, sorterField string, sorterI interface{}) template.HTMLAttr {
sorter := "" sorter := ""
if sorterI != nil { if sorterI != nil {
sorter, _ = sorterI.(string) sorter, _ = sorterI.(string)
} }
html := "data-url=\"" + url + "\" data-sorter=\"" + sorterField + "\""; html := "data-url=\"" + url + "\" data-sorter=\"" + sorterField + "\""
html += " class=\"th-sortable "; html += " class=\"th-sortable "
if sorter == sorterField + "-up" { if sorter == sorterField+"-up" {
html += "th-sort-up\""; html += "th-sort-up\""
} else if(sorter == sorterField + "-down") { } else if sorter == sorterField+"-down" {
html += "th-sort-down"; html += "th-sort-down"
} }
html += "\""; html += "\""
return template.HTMLAttr(html) return template.HTMLAttr(html)
} }
// pagination // pagination
revel.TemplateFuncs["page"] = func(urlBase string, page, pageSize, count int) template.HTML { revel.TemplateFuncs["page"] = func(urlBase string, page, pageSize, count int) template.HTML {
if count == 0 { if count == 0 {
return ""; return ""
} }
totalPage := int(math.Ceil(float64(count)/float64(pageSize))) totalPage := int(math.Ceil(float64(count) / float64(pageSize)))
preClass := "" preClass := ""
prePage := page - 1 prePage := page - 1
@@ -344,7 +354,7 @@ func init() {
nextPage := page + 1 nextPage := page + 1
var preUrl, nextUrl string var preUrl, nextUrl string
preUrl = urlBase + "?page=" + strconv.Itoa(prePage) preUrl = urlBase + "?page=" + strconv.Itoa(prePage)
nextUrl = urlBase + "?page=" + strconv.Itoa(nextPage) nextUrl = urlBase + "?page=" + strconv.Itoa(nextPage)
// 没有上一页了 // 没有上一页了
@@ -364,47 +374,47 @@ func init() {
// http://play.golang.org/p/snygrVpQva // http://play.golang.org/p/snygrVpQva
// http://grokbase.com/t/gg/golang-nuts/142a6dhfh3/go-nuts-text-template-using-comparison-operators-eq-gt-etc-on-non-existent-variable-causes-the-template-to-stop-outputting-but-with-no-error-correct-behaviour // http://grokbase.com/t/gg/golang-nuts/142a6dhfh3/go-nuts-text-template-using-comparison-operators-eq-gt-etc-on-non-existent-variable-causes-the-template-to-stop-outputting-but-with-no-error-correct-behaviour
/* /*
revel.TemplateFuncs["gt"] = func(a1, a2 interface{}) bool { revel.TemplateFuncs["gt"] = func(a1, a2 interface{}) bool {
switch a1.(type) { switch a1.(type) {
case string:
switch a2.(type) {
case string: case string:
return reflect.ValueOf(a1).String() > reflect.ValueOf(a2).String() switch a2.(type) {
} case string:
case int, int8, int16, int32, int64: return reflect.ValueOf(a1).String() > reflect.ValueOf(a2).String()
switch a2.(type) { }
case int, int8, int16, int32, int64: case int, int8, int16, int32, int64:
return reflect.ValueOf(a1).Int() > reflect.ValueOf(a2).Int() switch a2.(type) {
} case int, int8, int16, int32, int64:
case uint, uint8, uint16, uint32, uint64: return reflect.ValueOf(a1).Int() > reflect.ValueOf(a2).Int()
switch a2.(type) { }
case uint, uint8, uint16, uint32, uint64: case uint, uint8, uint16, uint32, uint64:
return reflect.ValueOf(a1).Uint() > reflect.ValueOf(a2).Uint() switch a2.(type) {
} case uint, uint8, uint16, uint32, uint64:
case float32, float64: return reflect.ValueOf(a1).Uint() > reflect.ValueOf(a2).Uint()
switch a2.(type) { }
case float32, float64: case float32, float64:
return reflect.ValueOf(a1).Float() > reflect.ValueOf(a2).Float() switch a2.(type) {
case float32, float64:
return reflect.ValueOf(a1).Float() > reflect.ValueOf(a2).Float()
}
} }
return false
} }
return false
}
*/ */
/* /*
{{range $i := N 1 10}} {{range $i := N 1 10}}
<div>{{$i}}</div> <div>{{$i}}</div>
{{end}} {{end}}
*/ */
revel.TemplateFuncs["N"] = func(start, end int) (stream chan int) { revel.TemplateFuncs["N"] = func(start, end int) (stream chan int) {
stream = make(chan int) stream = make(chan int)
go func() { go func() {
for i := start; i <= end; i++ { for i := start; i <= end; i++ {
stream <- i stream <- i
} }
close(stream) close(stream)
}() }()
return return
} }
// init Email // init Email
+18 -10
View File
@@ -1,26 +1,34 @@
package lea package lea
import ( import (
"encoding/json" "encoding/json"
"github.com/revel/revel" "fmt"
"fmt" "github.com/revel/revel"
) )
func Log(i interface{}) { func Log(i ...interface{}) {
revel.INFO.Println(i) revel.INFO.Println(i...)
}
func LogW(i ...interface{}) {
revel.WARN.Println(i...)
}
func Log1(key, i interface{}) {
revel.INFO.Println(key, i)
} }
func LogJ(i interface{}) { func LogJ(i interface{}) {
b, _ := json.MarshalIndent(i, "", " ") b, _ := json.MarshalIndent(i, "", " ")
revel.INFO.Println(string(b)) revel.INFO.Println(string(b))
} }
// 为test用 // 为test用
func L(i interface{}) { func L(i interface{}) {
fmt.Println(i) fmt.Println(i)
} }
func LJ(i interface{}) { func LJ(i interface{}) {
b, _ := json.MarshalIndent(i, "", " ") b, _ := json.MarshalIndent(i, "", " ")
fmt.Println(string(b)) fmt.Println(string(b))
} }
+8 -6
View File
@@ -1,10 +1,11 @@
package lea package lea
import ( import (
"github.com/revel/revel"
"net/smtp" "net/smtp"
"strings" "strings"
"github.com/revel/revel"
) )
// 发送邮件 // 发送邮件
var host = "smtp.ym.163.com" var host = "smtp.ym.163.com"
var port = "25" var port = "25"
@@ -12,7 +13,7 @@ var username = "noreply@leanote.com"
var password = "---" var password = "---"
func InitEmail() { func InitEmail() {
config := revel.Config; config := revel.Config
host, _ = config.String("email.host") host, _ = config.String("email.host")
port, _ = config.String("email.port") port, _ = config.String("email.port")
username, _ = config.String("email.username") username, _ = config.String("email.username")
@@ -56,6 +57,7 @@ var bodyTpl = `
</body> </body>
</html> </html>
` `
func SendEmailOld(to, subject, body string) bool { func SendEmailOld(to, subject, body string) bool {
hp := strings.Split(host, ":") hp := strings.Split(host, ":")
auth := smtp.PlainAuth("", username, password, hp[0]) auth := smtp.PlainAuth("", username, password, hp[0])
@@ -64,15 +66,15 @@ func SendEmailOld(to, subject, body string) bool {
mailtype := "html" mailtype := "html"
if mailtype == "html" { if mailtype == "html" {
content_type = "Content-Type: text/"+ mailtype + "; charset=UTF-8" content_type = "Content-Type: text/" + mailtype + "; charset=UTF-8"
} else{ } else {
content_type = "Content-Type: text/plain" + "; charset=UTF-8" content_type = "Content-Type: text/plain" + "; charset=UTF-8"
} }
//body = strings.Replace(bodyTpl, "$body", body, 1) //body = strings.Replace(bodyTpl, "$body", body, 1)
//body = strings.Replace(body, "$title", title, 1) //body = strings.Replace(body, "$title", title, 1)
msg := []byte("To: " + to + "\r\nFrom: " + username + "<"+ username +">\r\nSubject: " + subject + "\r\n" + content_type + "\r\n\r\n" + body) msg := []byte("To: " + to + "\r\nFrom: " + username + "<" + username + ">\r\nSubject: " + subject + "\r\n" + content_type + "\r\n\r\n" + body)
send_to := strings.Split(to, ";") send_to := strings.Split(to, ";")
err := smtp.SendMail(host+":"+port, auth, username, send_to, msg) err := smtp.SendMail(host+":"+port, auth, username, send_to, msg)
@@ -85,5 +87,5 @@ func SendEmailOld(to, subject, body string) bool {
func SendToLeanoteOld(subject, title, body string) { func SendToLeanoteOld(subject, title, body string) {
to := "leanote@leanote.com" to := "leanote@leanote.com"
SendEmailOld(to, subject, body); SendEmailOld(to, subject, body)
} }
+2 -2
View File
@@ -116,13 +116,13 @@ func CopyDir(source string, dest string) (err error) {
// create sub-directories - recursively // create sub-directories - recursively
err = CopyDir(sourcefilepointer, destinationfilepointer) err = CopyDir(sourcefilepointer, destinationfilepointer)
if err != nil { if err != nil {
// fmt.Println(err) // fmt.Println(err)
} }
} else { } else {
// perform copy // perform copy
_, err = CopyFile(sourcefilepointer, destinationfilepointer) _, err = CopyFile(sourcefilepointer, destinationfilepointer)
if err != nil { if err != nil {
// fmt.Println(err) // fmt.Println(err)
} }
} }
} }
+57 -20
View File
@@ -1,19 +1,19 @@
package lea package lea
import ( import (
"fmt" "bytes"
"regexp"
"crypto/md5" "crypto/md5"
"crypto/rand" "crypto/rand"
"encoding/base64" "encoding/base64"
"encoding/hex" "encoding/hex"
"io" "fmt"
"gopkg.in/mgo.v2/bson"
"time"
"strings"
"github.com/PuerkitoBio/goquery" "github.com/PuerkitoBio/goquery"
"bytes" "gopkg.in/mgo.v2/bson"
"io"
math_rand "math/rand" math_rand "math/rand"
"regexp"
"strings"
"time"
) )
// 字符串 // 字符串
@@ -31,14 +31,14 @@ func Digest3(str string) string {
for _, k := range str { for _, k := range str {
b += k b += k
} }
return fmt.Sprintf("%d", b % 1000) return fmt.Sprintf("%d", b%1000)
} }
func Digest2(str string) string { func Digest2(str string) string {
var b rune = 0 var b rune = 0
for _, k := range str { for _, k := range str {
b += k b += k
} }
return fmt.Sprintf("%d", b % 100) return fmt.Sprintf("%d", b%100)
} }
// Guid // Guid
@@ -161,7 +161,7 @@ func SubStringHTMLToRaw(param string, length int) string {
continue continue
} else if temp == '>' { } else if temp == '>' {
isCode = false isCode = false
resultRune[n] = ' '; resultRune[n] = ' '
n++ n++
if n >= length { if n >= length {
@@ -170,7 +170,7 @@ func SubStringHTMLToRaw(param string, length int) string {
continue continue
} }
if !isCode { if !isCode {
resultRune[n] = temp; resultRune[n] = temp
// s += string(temp) // s += string(temp)
n++ n++
if n >= length { if n >= length {
@@ -198,7 +198,7 @@ func fixHtml(result string) string {
p, _ := regexp.Compile("<(/?[a-zA-Z]+)[^<>]*>") // 得到所有的<div>, </div>... p, _ := regexp.Compile("<(/?[a-zA-Z]+)[^<>]*>") // 得到所有的<div>, </div>...
strs := p.FindAllString(tempResult, -1) strs := p.FindAllString(tempResult, -1)
// fmt.Println(strs) // fmt.Println(strs)
stack := make([]string, len(strs)) stack := make([]string, len(strs))
stackP := -1 stackP := -1
for _, each := range strs { for _, each := range strs {
@@ -241,10 +241,10 @@ func SubStringHTML(param string, length int, end string) string {
} else { } else {
// 1 // 1
n := 0 n := 0
var temp rune // 中文问题, 用rune来解决 var temp rune // 中文问题, 用rune来解决
isCode := false //是不是HTML代码 isCode := false //是不是HTML代码
isHTML := false //是不是HTML特殊字符,如&nbsp; isHTML := false //是不是HTML特殊字符,如&nbsp;
var i = 0; var i = 0
for ; i < lenStr; i++ { for ; i < lenStr; i++ {
temp = rStr[i] temp = rStr[i]
if temp == '<' { if temp == '<' {
@@ -285,7 +285,7 @@ func SubStringHTML(param string, length int, end string) string {
// TODO 把style="float: left"去掉 // TODO 把style="float: left"去掉
return html return html
// 如果有错误, 则使用自己的方法补全, 有风险 // 如果有错误, 则使用自己的方法补全, 有风险
} else { } else {
return fixHtml(result) return fixHtml(result)
} }
@@ -305,7 +305,7 @@ func IsGoodPwd(pwd string) (bool, string) {
// 是否是email // 是否是email
func IsEmail(email string) bool { func IsEmail(email string) bool {
if email == "" { if email == "" {
return false; return false
} }
ok, _ := regexp.MatchString(`^([a-zA-Z0-9]+[_|\_|\.|\-]?)*[_a-z\-A-Z0-9]+@([a-zA-Z0-9]+[_|\_|\.|\-]?)*[a-zA-Z0-9\-]+\.[0-9a-zA-Z]{2,6}$`, email) ok, _ := regexp.MatchString(`^([a-zA-Z0-9]+[_|\_|\.|\-]?)*[_a-z\-A-Z0-9]+@([a-zA-Z0-9]+[_|\_|\.|\-]?)*[a-zA-Z0-9\-]+\.[0-9a-zA-Z]{2,6}$`, email)
return ok return ok
@@ -314,7 +314,7 @@ func IsEmail(email string) bool {
// 是否只包含数字, 字母 -, _ // 是否只包含数字, 字母 -, _
func IsUsername(username string) bool { func IsUsername(username string) bool {
if username == "" { if username == "" {
return false; return false
} }
ok, _ := regexp.MatchString(`[^0-9a-zA-Z_\-]`, username) ok, _ := regexp.MatchString(`[^0-9a-zA-Z_\-]`, username)
return !ok return !ok
@@ -351,7 +351,7 @@ func RandomPwd(num int) string {
chars[j] = byte(i) chars[j] = byte(i)
j++ j++
} }
j--; j--
str := "" str := ""
math_rand.Seed(time.Now().UnixNano()) math_rand.Seed(time.Now().UnixNano())
@@ -379,14 +379,14 @@ func InArray(arr []string, str string) bool {
func FixFilename(filename string) string { func FixFilename(filename string) string {
if filename != "" { if filename != "" {
// 把特殊字段给替换掉 // 把特殊字段给替换掉
// str := `life "%&()+,/:;<>=?@\|` // str := `life "%&()+,/:;<>=?@\|`
// . == \\. // . == \\.
// $ === \\$ // $ === \\$
reg, _ := regexp.Compile("\\.|/|#|\\$|!|\\^|\\*|'| |\"|%|&|\\(|\\)|\\+|\\,|/|:|;|<|>|=|\\?|@|\\||\\\\") reg, _ := regexp.Compile("\\.|/|#|\\$|!|\\^|\\*|'| |\"|%|&|\\(|\\)|\\+|\\,|/|:|;|<|>|=|\\?|@|\\||\\\\")
filename = reg.ReplaceAllString(filename, "-") filename = reg.ReplaceAllString(filename, "-")
filename = strings.Trim(filename, "-") // 左右单独的-去掉 filename = strings.Trim(filename, "-") // 左右单独的-去掉
// 把空格替换成- // 把空格替换成-
// filename = strings.Replace(filename, " ", "-", -1) // filename = strings.Replace(filename, " ", "-", -1)
for strings.Index(filename, "--") >= 0 { // 防止出现连续的-- for strings.Index(filename, "--") >= 0 { // 防止出现连续的--
filename = strings.Replace(filename, "--", "-", -1) filename = strings.Replace(filename, "--", "-", -1)
} }
@@ -394,3 +394,40 @@ func FixFilename(filename string) string {
} }
return filename return filename
} }
// 是否是合法的时间
// 不是, 0001-01-01T00:00:00Z, 且比今天小
func IsValidTime(t time.Time) bool {
if t.Year() > 20 {
now := time.Now()
Log("------")
Log(t)
Log(now)
if t.Before(now) {
return true
}
}
return false
}
// url传过来的时间没有时区信息, 转到本地时间
func ToLocalTime(t time.Time) time.Time {
return time.Date(t.Year(), t.Month(), t.Day(), t.Hour(), t.Minute(), t.Second(), 0, time.Local)
}
// 修复传过来的时间, 如果比今天大, 则设为现在
func FixUrlTime(t time.Time) time.Time {
localTime := ToLocalTime(t)
if IsValidTime(localTime) {
return localTime
}
return time.Now()
}
// 得到用户的随机文件路径 3位/userId/2位
func GetRandomFilePath(userId, uuid string) string {
if uuid == "" {
uuid = NewGuid()
}
return Digest3(userId) + "/" + userId + "/" + Digest2(uuid)
}
+12 -12
View File
@@ -2,8 +2,8 @@ package lea
import ( import (
"encoding/json" "encoding/json"
"strconv"
"regexp" "regexp"
"strconv"
) )
// 验证 // 验证
@@ -38,15 +38,15 @@ var rulesStr = `{
` `
var rulesMap map[string][]map[string]string var rulesMap map[string][]map[string]string
var rules = map[string]func(string, map[string]string)(bool, string) { var rules = map[string]func(string, map[string]string) (bool, string){
"required": func(value string, rule map[string]string)(ok bool, msg string) { "required": func(value string, rule map[string]string) (ok bool, msg string) {
if value == "" { if value == "" {
return return
} }
ok = true ok = true
return return
}, },
"minLength": func(value string, rule map[string]string)(ok bool, msg string) { "minLength": func(value string, rule map[string]string) (ok bool, msg string) {
if value == "" { if value == "" {
return return
} }
@@ -55,7 +55,7 @@ var rules = map[string]func(string, map[string]string)(bool, string) {
ok = len(value) >= dataI ok = len(value) >= dataI
return return
}, },
"min": func(value string, rule map[string]string)(ok bool, msg string) { "min": func(value string, rule map[string]string) (ok bool, msg string) {
if value == "" { if value == "" {
return return
} }
@@ -66,7 +66,7 @@ var rules = map[string]func(string, map[string]string)(bool, string) {
return return
}, },
"sortField": func(value string, rule map[string]string)(ok bool, msg string) { "sortField": func(value string, rule map[string]string) (ok bool, msg string) {
if value == "" { if value == "" {
return return
} }
@@ -75,21 +75,21 @@ var rules = map[string]func(string, map[string]string)(bool, string) {
return return
}, },
"password": func(value string, rule map[string]string)(ok bool, msg string) { "password": func(value string, rule map[string]string) (ok bool, msg string) {
if value == "" { if value == "" {
return return
} }
ok = len(value) >= 6 ok = len(value) >= 6
return return
}, },
"email": func(value string, rule map[string]string)(ok bool, msg string) { "email": func(value string, rule map[string]string) (ok bool, msg string) {
if value == "" { if value == "" {
return return
} }
ok = IsEmail(value) ok = IsEmail(value)
return return
}, },
"noSpecialChars": func(value string, rule map[string]string)(ok bool, msg string) { "noSpecialChars": func(value string, rule map[string]string) (ok bool, msg string) {
if value == "" { if value == "" {
return return
} }
@@ -98,7 +98,7 @@ var rules = map[string]func(string, map[string]string)(bool, string) {
}, },
// www.baidu.com // www.baidu.com
// //
"domain": func(value string, rule map[string]string)(ok bool, msg string) { "domain": func(value string, rule map[string]string) (ok bool, msg string) {
if value == "" { if value == "" {
ok = true ok = true
return // 可为空 return // 可为空
@@ -112,10 +112,10 @@ var rules = map[string]func(string, map[string]string)(bool, string) {
return return
}, },
// abcd // abcd
"subDomain": func(value string, rule map[string]string)(ok bool, msg string) { "subDomain": func(value string, rule map[string]string) (ok bool, msg string) {
if value == "" { if value == "" {
ok = true ok = true
return // 可为空 return // 可为空
} }
if len(value) < 4 { if len(value) < 4 {
ok = false ok = false
+173 -173
View File
@@ -1,12 +1,12 @@
package archive package archive
import ( import (
"archive/tar" "archive/tar"
"compress/gzip" "compress/gzip"
"fmt" "fmt"
"io" "io"
"os" "os"
"path" "path"
) )
// main functions shows how to TarGz a directory/file and // main functions shows how to TarGz a directory/file and
@@ -16,66 +16,66 @@ import (
func main() { func main() {
/* /*
os.Mkdir("/home/ty4z2008/tar", 0777) os.Mkdir("/home/ty4z2008/tar", 0777)
w, err := CopyFile("/home/ty4z2008/tar/1.pdf", "/home/ty4z2008/src/1.pdf") w, err := CopyFile("/home/ty4z2008/tar/1.pdf", "/home/ty4z2008/src/1.pdf")
//targetfile,sourcefile //targetfile,sourcefile
if err != nil { if err != nil {
fmt.Println(err.Error()) fmt.Println(err.Error())
} }
fmt.Println(w) fmt.Println(w)
TarGz("/home/ty4z2008/tar/1.pdf", "/home/ty4z2008/test.tar.gz") //压缩 TarGz("/home/ty4z2008/tar/1.pdf", "/home/ty4z2008/test.tar.gz") //压缩
//UnTarGz("/home/ty4z2008/1.tar.gz", "/home/ty4z2008") //解压 //UnTarGz("/home/ty4z2008/1.tar.gz", "/home/ty4z2008") //解压
os.RemoveAll("/home/ty4z2008/tar") os.RemoveAll("/home/ty4z2008/tar")
*/ */
// TaZip("/Users/life/Desktop/j", "/Users/life/Desktop/aaa.tar.gz") // TaZip("/Users/life/Desktop/j", "/Users/life/Desktop/aaa.tar.gz")
Zip("/Users/life/Desktop/j", "/Users/life/Desktop/aaa.zip") Zip("/Users/life/Desktop/j", "/Users/life/Desktop/aaa.zip")
fmt.Println("ok") fmt.Println("ok")
} }
func TarGz(srcDirPath string, destFilePath string) (ok bool) { func TarGz(srcDirPath string, destFilePath string) (ok bool) {
defer func() { //必须要先声明defer,否则不能捕获到panic异常 defer func() { //必须要先声明defer,否则不能捕获到panic异常
if err := recover(); err != nil { if err := recover(); err != nil {
ok = false ok = false
} }
}() }()
fw, err := os.Create(destFilePath) fw, err := os.Create(destFilePath)
if err != nil { if err != nil {
panic(err) panic(err)
} }
defer fw.Close() defer fw.Close()
// Gzip writer // Gzip writer
gw := gzip.NewWriter(fw) gw := gzip.NewWriter(fw)
defer gw.Close() defer gw.Close()
// Tar writer // Tar writer
tw := tar.NewWriter(gw) tw := tar.NewWriter(gw)
defer tw.Close() defer tw.Close()
// Check if it's a file or a directory // Check if it's a file or a directory
f, err := os.Open(srcDirPath) f, err := os.Open(srcDirPath)
if err != nil { if err != nil {
panic(err) panic(err)
} }
fi, err := f.Stat() fi, err := f.Stat()
if err != nil { if err != nil {
panic(err) panic(err)
} }
if fi.IsDir() { if fi.IsDir() {
// handle source directory // handle source directory
// fmt.Println("Cerating tar.gz from directory...") // fmt.Println("Cerating tar.gz from directory...")
tarGzDir(srcDirPath, path.Base(srcDirPath), tw) tarGzDir(srcDirPath, path.Base(srcDirPath), tw)
} else { } else {
// handle file directly // handle file directly
// fmt.Println("Cerating tar.gz from " + fi.Name() + "...") // fmt.Println("Cerating tar.gz from " + fi.Name() + "...")
tarGzFile(srcDirPath, fi.Name(), tw, fi) tarGzFile(srcDirPath, fi.Name(), tw, fi)
} }
ok = true ok = true
return return
} }
// Deal with directories // Deal with directories
@@ -83,148 +83,148 @@ func TarGz(srcDirPath string, destFilePath string) (ok bool) {
// Every recurrence append the base path to the recPath // Every recurrence append the base path to the recPath
// recPath is the path inside of tar.gz // recPath is the path inside of tar.gz
func tarGzDir(srcDirPath string, recPath string, tw *tar.Writer) { func tarGzDir(srcDirPath string, recPath string, tw *tar.Writer) {
// Open source diretory // Open source diretory
dir, err := os.Open(srcDirPath) dir, err := os.Open(srcDirPath)
if err != nil { if err != nil {
panic(err) panic(err)
} }
defer dir.Close() defer dir.Close()
// Get file info slice // Get file info slice
fis, err := dir.Readdir(0) fis, err := dir.Readdir(0)
if err != nil { if err != nil {
panic(err) panic(err)
} }
for _, fi := range fis { for _, fi := range fis {
// Append path // Append path
curPath := srcDirPath + "/" + fi.Name() curPath := srcDirPath + "/" + fi.Name()
// Check it is directory or file // Check it is directory or file
if fi.IsDir() { if fi.IsDir() {
// Directory // Directory
// (Directory won't add unitl all subfiles are added) // (Directory won't add unitl all subfiles are added)
// fmt.Printf("Adding path...%s\n", curPath) // fmt.Printf("Adding path...%s\n", curPath)
tarGzDir(curPath, recPath+"/"+fi.Name(), tw) tarGzDir(curPath, recPath+"/"+fi.Name(), tw)
} else { } else {
// File // File
// fmt.Printf("Adding file...%s\n", curPath) // fmt.Printf("Adding file...%s\n", curPath)
} }
tarGzFile(curPath, recPath+"/"+fi.Name(), tw, fi) tarGzFile(curPath, recPath+"/"+fi.Name(), tw, fi)
} }
} }
// Deal with files // Deal with files
func tarGzFile(srcFile string, recPath string, tw *tar.Writer, fi os.FileInfo) { func tarGzFile(srcFile string, recPath string, tw *tar.Writer, fi os.FileInfo) {
if fi.IsDir() { if fi.IsDir() {
// fmt.Println("??") // fmt.Println("??")
// Create tar header // Create tar header
hdr := new(tar.Header) hdr := new(tar.Header)
// if last character of header name is '/' it also can be directory // if last character of header name is '/' it also can be directory
// but if you don't set Typeflag, error will occur when you untargz // but if you don't set Typeflag, error will occur when you untargz
hdr.Name = recPath // + "/" hdr.Name = recPath // + "/"
// fmt.Println(hdr.Name) // fmt.Println(hdr.Name)
hdr.Typeflag = tar.TypeDir hdr.Typeflag = tar.TypeDir
// hdr.Size = 0 // hdr.Size = 0
//hdr.Mode = 0755 | c_ISDIR //hdr.Mode = 0755 | c_ISDIR
// hdr.Mode = int64(fi.Mode()) // 加这个会有错误!!! // hdr.Mode = int64(fi.Mode()) // 加这个会有错误!!!
// hdr.ModTime = fi.ModTime() // 加这个会有错误!! // hdr.ModTime = fi.ModTime() // 加这个会有错误!!
// Write hander // Write hander
err := tw.WriteHeader(hdr) err := tw.WriteHeader(hdr)
if err != nil { if err != nil {
panic(err) panic(err)
} }
} else { } else {
// File reader // File reader
fr, err := os.Open(srcFile) fr, err := os.Open(srcFile)
if err != nil { if err != nil {
panic(err) panic(err)
} }
defer fr.Close() defer fr.Close()
// Create tar header // Create tar header
hdr := new(tar.Header) hdr := new(tar.Header)
hdr.Name = recPath hdr.Name = recPath
// fmt.Println(hdr.Name) // fmt.Println(hdr.Name)
hdr.Size = fi.Size() hdr.Size = fi.Size()
hdr.Mode = int64(fi.Mode()) hdr.Mode = int64(fi.Mode())
hdr.ModTime = fi.ModTime() hdr.ModTime = fi.ModTime()
// Write hander // Write hander
err = tw.WriteHeader(hdr) err = tw.WriteHeader(hdr)
if err != nil { if err != nil {
panic(err) panic(err)
} }
// Write file data // Write file data
_, err = io.Copy(tw, fr) _, err = io.Copy(tw, fr)
if err != nil { if err != nil {
panic(err) panic(err)
} }
} }
} }
// Ungzip and untar from source file to destination directory // Ungzip and untar from source file to destination directory
// you need check file exist before you call this function // you need check file exist before you call this function
func UnTarGz(srcFilePath string, destDirPath string) { func UnTarGz(srcFilePath string, destDirPath string) {
// fmt.Println("UnTarGzing " + srcFilePath + "...") // fmt.Println("UnTarGzing " + srcFilePath + "...")
// Create destination directory // Create destination directory
os.Mkdir(destDirPath, os.ModePerm) os.Mkdir(destDirPath, os.ModePerm)
fr, err := os.Open(srcFilePath) fr, err := os.Open(srcFilePath)
if err != nil { if err != nil {
panic(err) panic(err)
} }
defer fr.Close() defer fr.Close()
// Gzip reader // Gzip reader
gr, err := gzip.NewReader(fr) gr, err := gzip.NewReader(fr)
if err != nil { if err != nil {
panic(err) panic(err)
} }
defer gr.Close() defer gr.Close()
// Tar reader // Tar reader
tr := tar.NewReader(gr) tr := tar.NewReader(gr)
for { for {
hdr, err := tr.Next() hdr, err := tr.Next()
if err == io.EOF { if err == io.EOF {
// End of tar archive // End of tar archive
break break
} }
//handleError(err) //handleError(err)
// fmt.Println("UnTarGzing file..." + hdr.Name) // fmt.Println("UnTarGzing file..." + hdr.Name)
// Check if it is diretory or file // Check if it is diretory or file
if hdr.Typeflag != tar.TypeDir { if hdr.Typeflag != tar.TypeDir {
// Get files from archive // Get files from archive
// Create diretory before create file // Create diretory before create file
os.MkdirAll(destDirPath+"/"+path.Dir(hdr.Name), os.ModePerm) os.MkdirAll(destDirPath+"/"+path.Dir(hdr.Name), os.ModePerm)
// Write data to file // Write data to file
fw, _ := os.Create(destDirPath + "/" + hdr.Name) fw, _ := os.Create(destDirPath + "/" + hdr.Name)
if err != nil { if err != nil {
panic(err) panic(err)
} }
_, err = io.Copy(fw, tr) _, err = io.Copy(fw, tr)
if err != nil { if err != nil {
panic(err) panic(err)
} }
} }
} }
// fmt.Println("Well done!") // fmt.Println("Well done!")
} }
// Copyfile // Copyfile
func CopyFile(dstName, srcName string) (written int64, err error) { func CopyFile(dstName, srcName string) (written int64, err error) {
src, err := os.Open(srcName) src, err := os.Open(srcName)
if err != nil { if err != nil {
return return
} }
defer src.Close() defer src.Close()
dst, err := os.OpenFile(dstName, os.O_WRONLY|os.O_CREATE, 0644) dst, err := os.OpenFile(dstName, os.O_WRONLY|os.O_CREATE, 0644)
if err != nil { if err != nil {
return return
} }
defer dst.Close() defer dst.Close()
return io.Copy(dst, src) return io.Copy(dst, src)
} }
+117 -110
View File
@@ -1,12 +1,13 @@
package archive package archive
import ( import (
"archive/zip" "archive/zip"
"fmt" "fmt"
"io"
"os"
"path"
"strings" "strings"
"io" "github.com/leanote/leanote/app/lea"
"os"
"path"
) )
// main functions shows how to TarGz a directory/file and // main functions shows how to TarGz a directory/file and
@@ -15,43 +16,43 @@ import (
// you need check file exist before you call this function // you need check file exist before you call this function
func Zip(srcDirPath string, destFilePath string) (ok bool) { func Zip(srcDirPath string, destFilePath string) (ok bool) {
defer func() { //必须要先声明defer,否则不能捕获到panic异常 defer func() { //必须要先声明defer,否则不能捕获到panic异常
if err := recover(); err != nil { if err := recover(); err != nil {
ok = false ok = false
} }
}() }()
fw, err := os.Create(destFilePath) fw, err := os.Create(destFilePath)
if err != nil { if err != nil {
panic(err) panic(err)
} }
defer fw.Close() defer fw.Close()
// Tar writer // Tar writer
tw := zip.NewWriter(fw) tw := zip.NewWriter(fw)
defer tw.Close() defer tw.Close()
// Check if it's a file or a directory // Check if it's a file or a directory
f, err := os.Open(srcDirPath) f, err := os.Open(srcDirPath)
if err != nil { if err != nil {
panic(err) panic(err)
} }
fi, err := f.Stat() fi, err := f.Stat()
if err != nil { if err != nil {
panic(err) panic(err)
} }
if fi.IsDir() { if fi.IsDir() {
// handle source directory // handle source directory
// fmt.Println("Cerating tar.gz from directory...") // fmt.Println("Cerating tar.gz from directory...")
zipDir(srcDirPath, path.Base(srcDirPath), tw) zipDir(srcDirPath, path.Base(srcDirPath), tw)
} else { } else {
// handle file directly // handle file directly
// fmt.Println("Cerating tar.gz from " + fi.Name() + "...") // fmt.Println("Cerating tar.gz from " + fi.Name() + "...")
zipFile(srcDirPath, fi.Name(), tw, fi) zipFile(srcDirPath, fi.Name(), tw, fi)
} }
ok = true ok = true
return return
} }
// Deal with directories // Deal with directories
@@ -59,69 +60,69 @@ func Zip(srcDirPath string, destFilePath string) (ok bool) {
// Every recurrence append the base path to the recPath // Every recurrence append the base path to the recPath
// recPath is the path inside of tar.gz // recPath is the path inside of tar.gz
func zipDir(srcDirPath string, recPath string, tw *zip.Writer) { func zipDir(srcDirPath string, recPath string, tw *zip.Writer) {
// Open source diretory // Open source diretory
dir, err := os.Open(srcDirPath) dir, err := os.Open(srcDirPath)
if err != nil { if err != nil {
panic(err) panic(err)
} }
defer dir.Close() defer dir.Close()
// Get file info slice // Get file info slice
fis, err := dir.Readdir(0) fis, err := dir.Readdir(0)
if err != nil { if err != nil {
panic(err) panic(err)
} }
for _, fi := range fis { for _, fi := range fis {
// Append path // Append path
curPath := srcDirPath + "/" + fi.Name() curPath := srcDirPath + "/" + fi.Name()
// Check it is directory or file // Check it is directory or file
if fi.IsDir() { if fi.IsDir() {
// Directory // Directory
// (Directory won't add unitl all subfiles are added) // (Directory won't add unitl all subfiles are added)
// fmt.Printf("Adding path...%s\n", curPath) // fmt.Printf("Adding path...%s\n", curPath)
zipDir(curPath, recPath+"/"+fi.Name(), tw) zipDir(curPath, recPath+"/"+fi.Name(), tw)
} else { } else {
// File // File
// fmt.Printf("Adding file...%s\n", curPath) // fmt.Printf("Adding file...%s\n", curPath)
} }
zipFile(curPath, recPath+"/"+fi.Name(), tw, fi) zipFile(curPath, recPath+"/"+fi.Name(), tw, fi)
} }
} }
// Deal with files // Deal with files
func zipFile(srcFile string, recPath string, tw *zip.Writer, fi os.FileInfo) { func zipFile(srcFile string, recPath string, tw *zip.Writer, fi os.FileInfo) {
if fi.IsDir() { if fi.IsDir() {
// fmt.Println("??") // fmt.Println("??")
// Create tar header // Create tar header
/* /*
fh, err := zip.FileInfoHeader(fi) fh, err := zip.FileInfoHeader(fi)
if err != nil { if err != nil {
panic(err) panic(err)
} }
fh.Name = recPath // + "/" fh.Name = recPath // + "/"
err = tw.WriteHeader(hdr) err = tw.WriteHeader(hdr)
tw.Create(recPath) tw.Create(recPath)
*/ */
} else { } else {
// File reader // File reader
fr, err := os.Open(srcFile) fr, err := os.Open(srcFile)
if err != nil { if err != nil {
panic(err) panic(err)
} }
defer fr.Close() defer fr.Close()
// Write hander // Write hander
w, err2 := tw.Create(recPath) w, err2 := tw.Create(recPath)
if err2 != nil { if err2 != nil {
panic(err) panic(err)
} }
// Write file data // Write file data
_, err = io.Copy(w, fr) _, err = io.Copy(w, fr)
if err != nil { if err != nil {
panic(err) panic(err)
} }
} }
} }
// Ungzip and untar from source file to destination directory // Ungzip and untar from source file to destination directory
@@ -130,7 +131,7 @@ func Unzip(srcFilePath string, destDirPath string) (ok bool, msg string) {
ok = false ok = false
msg = "" msg = ""
defer func() { //必须要先声明defer,否则不能捕获到panic异常 defer func() { //必须要先声明defer,否则不能捕获到panic异常
if err := recover(); err != nil { if err := recover(); err != nil {
msg = fmt.Sprintf("%v", err) msg = fmt.Sprintf("%v", err)
ok = false ok = false
@@ -138,24 +139,30 @@ func Unzip(srcFilePath string, destDirPath string) (ok bool, msg string) {
}() }()
os.Mkdir(destDirPath, os.ModePerm) os.Mkdir(destDirPath, os.ModePerm)
r, err := zip.OpenReader(srcFilePath); r, err := zip.OpenReader(srcFilePath)
if err != nil { if err != nil {
panic(err) panic(err)
} }
defer r.Close(); defer r.Close()
for _, f := range r.File { for _, f := range r.File {
// fmt.Println("FileName : ", f.Name); // j/aaa.zip // fmt.Println("FileName : ", f.Name); // j/aaa.zip
rc, err := f.Open(); rc, err := f.Open()
if err!=nil { if err != nil {
panic(err) panic(err)
} }
// 包含恶意目录
if strings.Contains(f.Name, "../") {
lea.LogW("恶意文件", f.Name);
continue
}
// 把首文件夹去掉, 即j去掉, 分离出文件夹和文件名 // 把首文件夹去掉, 即j去掉, 分离出文件夹和文件名
paths := strings.Split(f.Name, "/") paths := strings.Split(f.Name, "/")
prePath := "" prePath := ""
filename := "" filename := ""
l := len(paths) l := len(paths)
// fmt.Println(l) // fmt.Println(l)
if l > 1 { if l > 1 {
// 去掉第1个文件夹 // 去掉第1个文件夹
if l == 2 { if l == 2 {
@@ -167,24 +174,24 @@ func Unzip(srcFilePath string, destDirPath string) (ok bool, msg string) {
} else { } else {
filename = f.Name filename = f.Name
} }
// fmt.Println(prePath) // fmt.Println(prePath)
// 相对于目标文件件下的路径 // 相对于目标文件件下的路径
destPath := destDirPath + "/" + filename destPath := destDirPath + "/" + filename
if prePath != "" { if prePath != "" {
os.MkdirAll(destDirPath + "/" + prePath, os.ModePerm) os.MkdirAll(destDirPath+"/"+prePath, os.ModePerm)
destPath = destDirPath + "/" + prePath + "/" + filename destPath = destDirPath + "/" + prePath + "/" + filename
} }
// Write data to file // Write data to file
// fmt.Println(destPath) // fmt.Println(destPath)
fw, _ := os.Create(destPath) fw, _ := os.Create(destPath)
if err != nil { if err != nil {
panic(err) panic(err)
} }
_, err = io.Copy(fw, rc) _, err = io.Copy(fw, rc)
if err != nil { if err != nil {
panic(err) panic(err)
} }
} }
ok = true ok = true
+28 -28
View File
@@ -1,10 +1,9 @@
package binder package binder
import ( import (
"github.com/revel/revel"
"github.com/leanote/leanote/app/info" "github.com/leanote/leanote/app/info"
"github.com/leanote/leanote/app/controllers" "github.com/revel/revel"
// "github.com/leanote/leanote/app/controllers/api" // "github.com/leanote/leanote/app/controllers/api"
"fmt" "fmt"
"reflect" "reflect"
"strings" "strings"
@@ -54,55 +53,56 @@ func nextKey(key string) string {
} }
return key[:fieldLen] return key[:fieldLen]
} }
var leanoteStructBinder = revel.Binder{ var leanoteStructBinder = revel.Binder{
// name == "noteOrContent" // name == "noteOrContent"
Bind: func(params *revel.Params, name string, typ reflect.Type) reflect.Value { Bind: func(params *revel.Params, name string, typ reflect.Type) reflect.Value {
result := reflect.New(typ).Elem() // 创建一个该类型的, 然后其field从所有的param去取 result := reflect.New(typ).Elem() // 创建一个该类型的, 然后其field从所有的param去取
fieldValues := make(map[string]reflect.Value) fieldValues := make(map[string]reflect.Value)
// fmt.Println(name) // fmt.Println(name)
// fmt.Println(typ) // api.NoteFiles // fmt.Println(typ) // api.NoteFiles
// name = files[0], files[1], noteContent // name = files[0], files[1], noteContent
// fmt.Println(params.Values) // fmt.Println(params.Values)
/* /*
map[Title:[test1] METHOD:[POST] NotebookId:[54c4f51705fcd14031000002] map[Title:[test1] METHOD:[POST] NotebookId:[54c4f51705fcd14031000002]
files[1][FileId]:[] files[1][FileId]:[]
controller:[note] controller:[note]
files[1][LocalFileId]:[54c7ae27d98d0329dd000000] files[1][HasBody]:[true] files[0][FileId]:[] files[0][LocalFileId]:[54c7ae855e94ea2dba000000] action:[addNote] Content:[<p>lifedddddd</p><p><img src="app://leanote/data/54bdc65599c37b0da9000002/images/1422368307147_2.png" alt="" data-mce-src="app://leanote/data/54bdc65599c37b0da9000002/images/1422368307147_2.png" style="display: block; margin-left: auto; margin-right: auto;"></p><p><img src="http://127.0.0.1:8008/api/file/getImage?fileId=54c7ae27d98d0329dd000000" alt="" data-mce-src="http://127.0.0.1:8008/api/file/getImg?fileId=54c7ae27d98d0329dd000000"></p><p><br></p><p><img src="http://127.0.0.1:8008/api/file/getImage?fileId=54c7ae855e94ea2dba000000" alt="" data-mce-src="http://127.0.0.1:8008/api/file/getImage?fileId=54c7ae855e94ea2dba000000" style="display: block; margin-left: auto; margin-right: auto;"></p><p><br></p><p><br></p>] IsBlog:[false] token:[user1] files[1][LocalFileId]:[54c7ae27d98d0329dd000000] files[1][HasBody]:[true] files[0][FileId]:[] files[0][LocalFileId]:[54c7ae855e94ea2dba000000] action:[addNote] Content:[<p>lifedddddd</p><p><img src="app://leanote/data/54bdc65599c37b0da9000002/images/1422368307147_2.png" alt="" data-mce-src="app://leanote/data/54bdc65599c37b0da9000002/images/1422368307147_2.png" style="display: block; margin-left: auto; margin-right: auto;"></p><p><img src="http://127.0.0.1:8008/api/file/getImage?fileId=54c7ae27d98d0329dd000000" alt="" data-mce-src="http://127.0.0.1:8008/api/file/getImg?fileId=54c7ae27d98d0329dd000000"></p><p><br></p><p><img src="http://127.0.0.1:8008/api/file/getImage?fileId=54c7ae855e94ea2dba000000" alt="" data-mce-src="http://127.0.0.1:8008/api/file/getImage?fileId=54c7ae855e94ea2dba000000" style="display: block; margin-left: auto; margin-right: auto;"></p><p><br></p><p><br></p>] IsBlog:[false] token:[user1]
files[0][HasBody]:[true]] files[0][HasBody]:[true]]
*/ */
nameIsSlice := strings.Contains(name, "[") nameIsSlice := strings.Contains(name, "[")
// fmt.Println(params.Values["files[1]"]) // fmt.Println(params.Values["files[1]"])
// fmt.Println(params.Values["Title"]) // fmt.Println(params.Values["Title"])
for key, _ := range params.Values {// Title, Content, Files for key, _ := range params.Values { // Title, Content, Files
// 这里, 如果没有点, 默认就是a. // 这里, 如果没有点, 默认就是a.
// life // life
// fmt.Println("key:" + key); // files[0][LocalFileId] // fmt.Println("key:" + key); // files[0][LocalFileId]
// fmt.Println("name:" + name); // files[0][LocalFileId] // fmt.Println("name:" + name); // files[0][LocalFileId]
var suffix string var suffix string
var noPrefix = false var noPrefix = false
if nameIsSlice && strings.HasPrefix(key, name) { if nameIsSlice && strings.HasPrefix(key, name) {
suffix = key[len(name)+1:len(key)-1] // files[0][LocalFileId] 去掉 => LocalFileId suffix = key[len(name)+1 : len(key)-1] // files[0][LocalFileId] 去掉 => LocalFileId
} else if !strings.HasPrefix(key, name + ".") { } else if !strings.HasPrefix(key, name+".") {
noPrefix = true noPrefix = true
suffix = key suffix = key
// continue // continue
} else { } else {
// Get the name of the struct property. // Get the name of the struct property.
// Strip off the prefix. e.g. foo.bar.baz => bar.baz // Strip off the prefix. e.g. foo.bar.baz => bar.baz
suffix = key[len(name)+1:] suffix = key[len(name)+1:]
} }
// fmt.Println(suffix); // fmt.Println(suffix);
fieldName := nextKey(suffix) // e.g. bar => "bar", bar.baz => "bar", bar[0] => "bar" fieldName := nextKey(suffix) // e.g. bar => "bar", bar.baz => "bar", bar[0] => "bar"
// fmt.Println(fieldName); // fmt.Println(fieldName);
fieldLen := len(fieldName) fieldLen := len(fieldName)
if _, ok := fieldValues[fieldName]; !ok { if _, ok := fieldValues[fieldName]; !ok {
// Time to bind this field. Get it and make sure we can set it. // Time to bind this field. Get it and make sure we can set it.
fieldName = strings.Title(fieldName) // 传过来title, 但struct是Title fieldName = strings.Title(fieldName) // 传过来title, 但struct是Title
// fmt.Println("xx: " + fieldName) // fmt.Println("xx: " + fieldName)
fieldValue := result.FieldByName(fieldName) fieldValue := result.FieldByName(fieldName)
// fmt.Println(fieldValue) // fmt.Println(fieldValue)
if !fieldValue.IsValid() { if !fieldValue.IsValid() {
continue continue
} }
@@ -111,14 +111,14 @@ files[0][HasBody]:[true]]
} }
var boundVal reflect.Value var boundVal reflect.Value
// 没有name前缀 // 没有name前缀
if(noPrefix) { if noPrefix {
// life // life
// fmt.Println("<<") // fmt.Println("<<")
// fmt.Println(strings.Title(key[:fieldLen])); // fmt.Println(strings.Title(key[:fieldLen]));
boundVal = revel.Bind(params, key[:fieldLen], fieldValue.Type()) boundVal = revel.Bind(params, key[:fieldLen], fieldValue.Type())
} else { } else {
// fmt.Println("final") // fmt.Println("final")
// fmt.Println(key[:len(name)+1+fieldLen]) // files[0][HasBody // fmt.Println(key[:len(name)+1+fieldLen]) // files[0][HasBody
if nameIsSlice { if nameIsSlice {
fieldLen += 1 fieldLen += 1
} }
@@ -150,7 +150,7 @@ func init() {
revel.TypeBinders[reflect.TypeOf(info.UserBlogStyle{})] = leanoteStructBinder revel.TypeBinders[reflect.TypeOf(info.UserBlogStyle{})] = leanoteStructBinder
revel.TypeBinders[reflect.TypeOf(info.Notebook{})] = leanoteStructBinder revel.TypeBinders[reflect.TypeOf(info.Notebook{})] = leanoteStructBinder
revel.TypeBinders[reflect.TypeOf(info.UserAccount{})] = leanoteStructBinder revel.TypeBinders[reflect.TypeOf(info.UserAccount{})] = leanoteStructBinder
revel.TypeBinders[reflect.TypeOf(controllers.NoteOrContent{})] = leanoteStructBinder revel.TypeBinders[reflect.TypeOf(info.NoteOrContent{})] = leanoteStructBinder
revel.TypeBinders[reflect.TypeOf(info.ApiNote{})] = leanoteStructBinder revel.TypeBinders[reflect.TypeOf(info.ApiNote{})] = leanoteStructBinder
revel.TypeBinders[reflect.TypeOf(info.NoteFile{})] = leanoteStructBinder revel.TypeBinders[reflect.TypeOf(info.NoteFile{})] = leanoteStructBinder
} }
+9 -11
View File
@@ -6,8 +6,8 @@ import (
"html/template" "html/template"
"io/ioutil" "io/ioutil"
// "os" // "os"
"fmt"
"bytes" "bytes"
"fmt"
"io" "io"
"net/http" "net/http"
"regexp" "regexp"
@@ -41,7 +41,7 @@ type RenderTemplateResult struct {
PathContent map[string]string PathContent map[string]string
RenderArgs map[string]interface{} RenderArgs map[string]interface{}
IsPreview bool // 是否是预览 IsPreview bool // 是否是预览
CurBlogTpl *BlogTpl CurBlogTpl *BlogTpl
} }
@@ -139,7 +139,7 @@ func Init() {
fileBytes, _ := ioutil.ReadFile(revel.ViewsPath + "/Blog/" + path) fileBytes, _ := ioutil.ReadFile(revel.ViewsPath + "/Blog/" + path)
fileStr := string(fileBytes) fileStr := string(fileBytes)
path := "blog/" + path path := "blog/" + path
// path := path // path := path
BlogTplObject.PathContent[path] = fileStr BlogTplObject.PathContent[path] = fileStr
BlogTplObject.Template.New(path).Parse(fileStr) // 以blog为根 BlogTplObject.Template.New(path).Parse(fileStr) // 以blog为根
} }
@@ -157,7 +157,7 @@ func RenderTemplate(name string, args map[string]interface{}, basePath string, i
// 都不会为空的 // 都不会为空的
if basePath == "" { if basePath == "" {
path := "blog/" + name path := "blog/" + name
// path := name // path := name
t := BlogTplObject.Template.Lookup(path) t := BlogTplObject.Template.Lookup(path)
r = &RenderTemplateResult{ r = &RenderTemplateResult{
Template: t, Template: t,
@@ -181,7 +181,7 @@ func RenderTemplate(name string, args map[string]interface{}, basePath string, i
files := ListDir(basePath) files := ListDir(basePath)
for _, t := range files { for _, t := range files {
if !strings.Contains(t, ".html") { if !strings.Contains(t, ".html") {
continue; continue
} }
fileBytes, err := ioutil.ReadFile(basePath + "/" + t) fileBytes, err := ioutil.ReadFile(basePath + "/" + t)
if err != nil { if err != nil {
@@ -203,23 +203,21 @@ func RenderTemplate(name string, args map[string]interface{}, basePath string, i
Template: t, Template: t,
PathContent: newBlogTplObject.PathContent, // 为了显示错误 PathContent: newBlogTplObject.PathContent, // 为了显示错误
RenderArgs: args, RenderArgs: args,
CurBlogTpl: newBlogTplObject, CurBlogTpl: newBlogTplObject,
IsPreview: isPreview, IsPreview: isPreview,
} }
} }
return r return r
} }
//////////////////// ////////////////////
// //
type ErrorResult struct { type ErrorResult struct {
RenderArgs map[string]interface{} RenderArgs map[string]interface{}
Error error Error error
IsPreview bool IsPreview bool
CurBlogTpl *BlogTpl CurBlogTpl *BlogTpl
} }
@@ -240,7 +238,7 @@ func (r ErrorResult) Apply(req *revel.Request, resp *revel.Response) {
var err error var err error
templatePath := fmt.Sprintf("errors/%d.%s", status, format) templatePath := fmt.Sprintf("errors/%d.%s", status, format)
err = nil err = nil
// tmpl, err := revel.MainTemplateLoader.Template("index.html") // 这里找到错误页面主题 // tmpl, err := revel.MainTemplateLoader.Template("index.html") // 这里找到错误页面主题
// This func shows a plaintext error message, in case the template rendering // This func shows a plaintext error message, in case the template rendering
// doesn't work. // doesn't work.
+311 -309
View File
@@ -1,347 +1,349 @@
package captcha package captcha
import ( import (
"image" crand "crypto/rand"
"image/color" "image"
"image/png" "image/color"
"io" "image/png"
"math/rand" "io"
crand "crypto/rand" "math/rand"
"time" "strconv"
"strconv" "time"
)
const (
stdWidth = 100
stdHeight = 40
maxSkew = 2
) )
const ( const (
fontWidth = 5 stdWidth = 100
fontHeight = 8 stdHeight = 40
blackChar = 1 maxSkew = 2
)
const (
fontWidth = 5
fontHeight = 8
blackChar = 1
) )
var font = [][]byte{ var font = [][]byte{
{ // 0 { // 0
0, 1, 1, 1, 0, 0, 1, 1, 1, 0,
1, 0, 0, 0, 1, 1, 0, 0, 0, 1,
1, 0, 0, 0, 1, 1, 0, 0, 0, 1,
1, 0, 0, 0, 1, 1, 0, 0, 0, 1,
1, 0, 0, 0, 1, 1, 0, 0, 0, 1,
1, 0, 0, 0, 1, 1, 0, 0, 0, 1,
1, 0, 0, 0, 1, 1, 0, 0, 0, 1,
0, 1, 1, 1, 0, 0, 1, 1, 1, 0,
}, },
{ // 1 { // 1
0, 0, 1, 0, 0, 0, 0, 1, 0, 0,
0, 1, 1, 0, 0, 0, 1, 1, 0, 0,
1, 0, 1, 0, 0, 1, 0, 1, 0, 0,
0, 0, 1, 0, 0, 0, 0, 1, 0, 0,
0, 0, 1, 0, 0, 0, 0, 1, 0, 0,
0, 0, 1, 0, 0, 0, 0, 1, 0, 0,
0, 0, 1, 0, 0, 0, 0, 1, 0, 0,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
}, },
{ // 2 { // 2
0, 1, 1, 1, 0, 0, 1, 1, 1, 0,
1, 0, 0, 0, 1, 1, 0, 0, 0, 1,
0, 0, 0, 0, 1, 0, 0, 0, 0, 1,
0, 0, 0, 1, 1, 0, 0, 0, 1, 1,
0, 1, 1, 0, 0, 0, 1, 1, 0, 0,
1, 0, 0, 0, 0, 1, 0, 0, 0, 0,
1, 0, 0, 0, 0, 1, 0, 0, 0, 0,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
}, },
{ // 3 { // 3
1, 1, 1, 1, 0, 1, 1, 1, 1, 0,
0, 0, 0, 0, 1, 0, 0, 0, 0, 1,
0, 0, 0, 1, 0, 0, 0, 0, 1, 0,
0, 1, 1, 1, 0, 0, 1, 1, 1, 0,
0, 0, 0, 1, 0, 0, 0, 0, 1, 0,
0, 0, 0, 0, 1, 0, 0, 0, 0, 1,
0, 0, 0, 0, 1, 0, 0, 0, 0, 1,
1, 1, 1, 1, 0, 1, 1, 1, 1, 0,
}, },
{ // 4 { // 4
1, 0, 0, 1, 0, 1, 0, 0, 1, 0,
1, 0, 0, 1, 0, 1, 0, 0, 1, 0,
1, 0, 0, 1, 0, 1, 0, 0, 1, 0,
1, 0, 0, 1, 0, 1, 0, 0, 1, 0,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
0, 0, 0, 1, 0, 0, 0, 0, 1, 0,
0, 0, 0, 1, 0, 0, 0, 0, 1, 0,
0, 0, 0, 1, 0, 0, 0, 0, 1, 0,
}, },
{ // 5 { // 5
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 0, 0, 0, 0, 1, 0, 0, 0, 0,
1, 0, 0, 0, 0, 1, 0, 0, 0, 0,
1, 1, 1, 1, 0, 1, 1, 1, 1, 0,
0, 0, 0, 0, 1, 0, 0, 0, 0, 1,
0, 0, 0, 0, 1, 0, 0, 0, 0, 1,
0, 0, 0, 0, 1, 0, 0, 0, 0, 1,
1, 1, 1, 1, 0, 1, 1, 1, 1, 0,
}, },
{ // 6 { // 6
0, 0, 1, 1, 1, 0, 0, 1, 1, 1,
0, 1, 0, 0, 0, 0, 1, 0, 0, 0,
1, 0, 0, 0, 0, 1, 0, 0, 0, 0,
1, 1, 1, 1, 0, 1, 1, 1, 1, 0,
1, 0, 0, 0, 1, 1, 0, 0, 0, 1,
1, 0, 0, 0, 1, 1, 0, 0, 0, 1,
1, 0, 0, 0, 1, 1, 0, 0, 0, 1,
0, 1, 1, 1, 0, 0, 1, 1, 1, 0,
}, },
{ // 7 { // 7
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
0, 0, 0, 0, 1, 0, 0, 0, 0, 1,
0, 0, 0, 0, 1, 0, 0, 0, 0, 1,
0, 0, 0, 1, 0, 0, 0, 0, 1, 0,
0, 0, 1, 0, 0, 0, 0, 1, 0, 0,
0, 1, 0, 0, 0, 0, 1, 0, 0, 0,
0, 1, 0, 0, 0, 0, 1, 0, 0, 0,
0, 1, 0, 0, 0, 0, 1, 0, 0, 0,
}, },
{ // 8 { // 8
0, 1, 1, 1, 0, 0, 1, 1, 1, 0,
1, 0, 0, 0, 1, 1, 0, 0, 0, 1,
1, 0, 0, 0, 1, 1, 0, 0, 0, 1,
0, 1, 1, 1, 0, 0, 1, 1, 1, 0,
1, 0, 0, 0, 1, 1, 0, 0, 0, 1,
1, 0, 0, 0, 1, 1, 0, 0, 0, 1,
1, 0, 0, 0, 1, 1, 0, 0, 0, 1,
0, 1, 1, 1, 0, 0, 1, 1, 1, 0,
}, },
{ // 9 { // 9
0, 1, 1, 1, 0, 0, 1, 1, 1, 0,
1, 0, 0, 0, 1, 1, 0, 0, 0, 1,
1, 0, 0, 0, 1, 1, 0, 0, 0, 1,
1, 1, 0, 0, 1, 1, 1, 0, 0, 1,
0, 1, 1, 1, 1, 0, 1, 1, 1, 1,
0, 0, 0, 0, 1, 0, 0, 0, 0, 1,
0, 0, 0, 0, 1, 0, 0, 0, 0, 1,
1, 1, 1, 1, 0, 1, 1, 1, 1, 0,
}, },
} }
type Image struct { type Image struct {
*image.NRGBA *image.NRGBA
color *color.NRGBA color *color.NRGBA
width int //a digit width width int //a digit width
height int //a digit height height int //a digit height
dotsize int dotsize int
} }
func init(){
rand.Seed(int64(time.Second)) func init() {
rand.Seed(int64(time.Second))
} }
func NewImage(digits []byte, width, height int) *Image { func NewImage(digits []byte, width, height int) *Image {
img := new(Image) img := new(Image)
r := image.Rect(img.width, img.height, stdWidth, stdHeight) r := image.Rect(img.width, img.height, stdWidth, stdHeight)
img.NRGBA = image.NewNRGBA(r) img.NRGBA = image.NewNRGBA(r)
img.color = &color.NRGBA{ img.color = &color.NRGBA{
uint8(rand.Intn(129)), uint8(rand.Intn(129)),
uint8(rand.Intn(129)), uint8(rand.Intn(129)),
uint8(rand.Intn(129)), uint8(rand.Intn(129)),
0xFF, 0xFF,
} }
// Draw background (10 random circles of random brightness) // Draw background (10 random circles of random brightness)
img.calculateSizes(width, height, len(digits)) img.calculateSizes(width, height, len(digits))
img.fillWithCircles(10, img.dotsize) img.fillWithCircles(10, img.dotsize)
maxx := width - (img.width+img.dotsize)*len(digits) - img.dotsize maxx := width - (img.width+img.dotsize)*len(digits) - img.dotsize
maxy := height - img.height - img.dotsize*2 maxy := height - img.height - img.dotsize*2
x := rnd(img.dotsize*2, maxx) x := rnd(img.dotsize*2, maxx)
y := rnd(img.dotsize*2, maxy) y := rnd(img.dotsize*2, maxy)
// Draw digits. // Draw digits.
for _, n := range digits { for _, n := range digits {
img.drawDigit(font[n], x, y) img.drawDigit(font[n], x, y)
x += img.width + img.dotsize x += img.width + img.dotsize
} }
// Draw strike-through line. // Draw strike-through line.
// 中间线不要 // 中间线不要
//img.strikeThrough() //img.strikeThrough()
return img return img
} }
func (img *Image) WriteTo(w io.Writer) (int64, error) { func (img *Image) WriteTo(w io.Writer) (int64, error) {
return 0, png.Encode(w, img) return 0, png.Encode(w, img)
} }
func (img *Image) calculateSizes(width, height, ncount int) { func (img *Image) calculateSizes(width, height, ncount int) {
// Goal: fit all digits inside the image. // Goal: fit all digits inside the image.
var border int var border int
if width > height { if width > height {
border = height / 5 border = height / 5
} else { } else {
border = width / 5 border = width / 5
} }
// Convert everything to floats for calculations. // Convert everything to floats for calculations.
w := float64(width - border*2) //268 w := float64(width - border*2) //268
h := float64(height - border*2) //48 h := float64(height - border*2) //48
// fw takes into account 1-dot spacing between digits. // fw takes into account 1-dot spacing between digits.
fw := float64(fontWidth) + 1 //6 fw := float64(fontWidth) + 1 //6
fh := float64(fontHeight) //8 fh := float64(fontHeight) //8
nc := float64(ncount) //7 nc := float64(ncount) //7
// Calculate the width of a single digit taking into account only the // Calculate the width of a single digit taking into account only the
// width of the image. // width of the image.
nw := w / nc //38 nw := w / nc //38
// Calculate the height of a digit from this width. // Calculate the height of a digit from this width.
nh := nw * fh / fw //51 nh := nw * fh / fw //51
// Digit too high? // Digit too high?
if nh > h { if nh > h {
// Fit digits based on height. // Fit digits based on height.
nh = h //nh = 44 nh = h //nh = 44
nw = fw / fh * nh nw = fw / fh * nh
} }
// Calculate dot size. // Calculate dot size.
img.dotsize = int(nh / fh) img.dotsize = int(nh / fh)
// Save everything, making the actual width smaller by 1 dot to account // Save everything, making the actual width smaller by 1 dot to account
// for spacing between digits. // for spacing between digits.
img.width = int(nw) img.width = int(nw)
img.height = int(nh) - img.dotsize img.height = int(nh) - img.dotsize
} }
func (img *Image) fillWithCircles(n, maxradius int) { func (img *Image) fillWithCircles(n, maxradius int) {
color := img.color color := img.color
maxx := img.Bounds().Max.X maxx := img.Bounds().Max.X
maxy := img.Bounds().Max.Y maxy := img.Bounds().Max.Y
for i := 0; i < n; i++ { for i := 0; i < n; i++ {
setRandomBrightness(color, 255) setRandomBrightness(color, 255)
r := rnd(1, maxradius) r := rnd(1, maxradius)
img.drawCircle(color, rnd(r, maxx-r), rnd(r, maxy-r), r) img.drawCircle(color, rnd(r, maxx-r), rnd(r, maxy-r), r)
} }
} }
func (img *Image) drawHorizLine(color color.Color, fromX, toX, y int) { func (img *Image) drawHorizLine(color color.Color, fromX, toX, y int) {
for x := fromX; x <= toX; x++ { for x := fromX; x <= toX; x++ {
img.Set(x, y, color) img.Set(x, y, color)
} }
} }
func (img *Image) drawCircle(color color.Color, x, y, radius int) { func (img *Image) drawCircle(color color.Color, x, y, radius int) {
f := 1 - radius f := 1 - radius
dfx := 1 dfx := 1
dfy := -2 * radius dfy := -2 * radius
xx := 0 xx := 0
yy := radius yy := radius
img.Set(x, y+radius, color) img.Set(x, y+radius, color)
img.Set(x, y-radius, color) img.Set(x, y-radius, color)
img.drawHorizLine(color, x-radius, x+radius, y) img.drawHorizLine(color, x-radius, x+radius, y)
for xx < yy { for xx < yy {
if f >= 0 { if f >= 0 {
yy-- yy--
dfy += 2 dfy += 2
f += dfy f += dfy
} }
xx++ xx++
dfx += 2 dfx += 2
f += dfx f += dfx
img.drawHorizLine(color, x-xx, x+xx, y+yy) img.drawHorizLine(color, x-xx, x+xx, y+yy)
img.drawHorizLine(color, x-xx, x+xx, y-yy) img.drawHorizLine(color, x-xx, x+xx, y-yy)
img.drawHorizLine(color, x-yy, x+yy, y+xx) img.drawHorizLine(color, x-yy, x+yy, y+xx)
img.drawHorizLine(color, x-yy, x+yy, y-xx) img.drawHorizLine(color, x-yy, x+yy, y-xx)
} }
} }
func (img *Image) strikeThrough() { func (img *Image) strikeThrough() {
r := 0 r := 0
maxx := img.Bounds().Max.X maxx := img.Bounds().Max.X
maxy := img.Bounds().Max.Y maxy := img.Bounds().Max.Y
y := rnd(maxy/3, maxy-maxy/3) y := rnd(maxy/3, maxy-maxy/3)
for x := 0; x < maxx; x += r { for x := 0; x < maxx; x += r {
r = rnd(1, img.dotsize/3) r = rnd(1, img.dotsize/3)
y += rnd(-img.dotsize/2, img.dotsize/2) y += rnd(-img.dotsize/2, img.dotsize/2)
if y <= 0 || y >= maxy { if y <= 0 || y >= maxy {
y = rnd(maxy/3, maxy-maxy/3) y = rnd(maxy/3, maxy-maxy/3)
} }
img.drawCircle(img.color, x, y, r) img.drawCircle(img.color, x, y, r)
} }
} }
func (img *Image) drawDigit(digit []byte, x, y int) { func (img *Image) drawDigit(digit []byte, x, y int) {
skf := rand.Float64() * float64(rnd(-maxSkew, maxSkew)) skf := rand.Float64() * float64(rnd(-maxSkew, maxSkew))
xs := float64(x) xs := float64(x)
minr := img.dotsize / 2 // minumum radius minr := img.dotsize / 2 // minumum radius
maxr := img.dotsize/2 + img.dotsize/4 // maximum radius maxr := img.dotsize/2 + img.dotsize/4 // maximum radius
y += rnd(-minr, minr) y += rnd(-minr, minr)
for yy := 0; yy < fontHeight; yy++ { for yy := 0; yy < fontHeight; yy++ {
for xx := 0; xx < fontWidth; xx++ { for xx := 0; xx < fontWidth; xx++ {
if digit[yy*fontWidth+xx] != blackChar { if digit[yy*fontWidth+xx] != blackChar {
continue continue
} }
// Introduce random variations. // Introduce random variations.
or := rnd(minr, maxr) or := rnd(minr, maxr)
ox := x + (xx * img.dotsize) + rnd(0, or/2) ox := x + (xx * img.dotsize) + rnd(0, or/2)
oy := y + (yy * img.dotsize) + rnd(0, or/2) oy := y + (yy * img.dotsize) + rnd(0, or/2)
img.drawCircle(img.color, ox, oy, or) img.drawCircle(img.color, ox, oy, or)
} }
xs += skf xs += skf
x = int(xs) x = int(xs)
} }
} }
func setRandomBrightness(c *color.NRGBA, max uint8) { func setRandomBrightness(c *color.NRGBA, max uint8) {
minc := min3(c.R, c.G, c.B) minc := min3(c.R, c.G, c.B)
maxc := max3(c.R, c.G, c.B) maxc := max3(c.R, c.G, c.B)
if maxc > max { if maxc > max {
return return
} }
n := rand.Intn(int(max-maxc)) - int(minc) n := rand.Intn(int(max-maxc)) - int(minc)
c.R = uint8(int(c.R) + n) c.R = uint8(int(c.R) + n)
c.G = uint8(int(c.G) + n) c.G = uint8(int(c.G) + n)
c.B = uint8(int(c.B) + n) c.B = uint8(int(c.B) + n)
} }
func min3(x, y, z uint8) (o uint8) { func min3(x, y, z uint8) (o uint8) {
o = x o = x
if y < o { if y < o {
o = y o = y
} }
if z < o { if z < o {
o = z o = z
} }
return return
} }
func max3(x, y, z uint8) (o uint8) { func max3(x, y, z uint8) (o uint8) {
o = x o = x
if y > o { if y > o {
o = y o = y
} }
if z > o { if z > o {
o = z o = z
} }
return return
} }
// rnd returns a random number in range [from, to]. // rnd returns a random number in range [from, to].
func rnd(from, to int) int { func rnd(from, to int) int {
//println(to+1-from) //println(to+1-from)
return rand.Intn(to+1-from) + from return rand.Intn(to+1-from) + from
} }
const ( const (
// Standard length of uniuri string to achive ~95 bits of entropy. // Standard length of uniuri string to achive ~95 bits of entropy.
StdLen = 16 StdLen = 16
// Length of uniurl string to achive ~119 bits of entropy, closest // Length of uniurl string to achive ~119 bits of entropy, closest
// to what can be losslessly converted to UUIDv4 (122 bits). // to what can be losslessly converted to UUIDv4 (122 bits).
UUIDLen = 20 UUIDLen = 20
) )
// Standard characters allowed in uniuri string. // Standard characters allowed in uniuri string.
@@ -350,50 +352,50 @@ var StdChars = []byte("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz01234
// New returns a new random string of the standard length, consisting of // New returns a new random string of the standard length, consisting of
// standard characters. // standard characters.
func New() string { func New() string {
return NewLenChars(StdLen, StdChars) return NewLenChars(StdLen, StdChars)
} }
// NewLen returns a new random string of the provided length, consisting of // NewLen returns a new random string of the provided length, consisting of
// standard characters. // standard characters.
func NewLen(length int) string { func NewLen(length int) string {
return NewLenChars(length, StdChars) return NewLenChars(length, StdChars)
} }
// NewLenChars returns a new random string of the provided length, consisting // NewLenChars returns a new random string of the provided length, consisting
// of the provided byte slice of allowed characters (maximum 256). // of the provided byte slice of allowed characters (maximum 256).
func NewLenChars(length int, chars []byte) string { func NewLenChars(length int, chars []byte) string {
b := make([]byte, length) b := make([]byte, length)
r := make([]byte, length+(length/4)) // storage for random bytes. r := make([]byte, length+(length/4)) // storage for random bytes.
clen := byte(len(chars)) clen := byte(len(chars))
maxrb := byte(256 - (256 % len(chars))) maxrb := byte(256 - (256 % len(chars)))
i := 0 i := 0
for { for {
if _, err := io.ReadFull(crand.Reader, r); err != nil { if _, err := io.ReadFull(crand.Reader, r); err != nil {
panic("error reading from random source: " + err.Error()) panic("error reading from random source: " + err.Error())
} }
for _, c := range r { for _, c := range r {
if c >= maxrb { if c >= maxrb {
// Skip this number to avoid modulo bias. // Skip this number to avoid modulo bias.
continue continue
} }
b[i] = chars[c%clen] b[i] = chars[c%clen]
i++ i++
if i == length { if i == length {
return string(b) return string(b)
} }
} }
} }
panic("unreachable") panic("unreachable")
} }
func Fetch() (*Image, string) { func Fetch() (*Image, string) {
d := make([]byte, 4) d := make([]byte, 4)
s := NewLen(4) s := NewLen(4)
ss := "" ss := ""
d = []byte(s) d = []byte(s)
for v := range d { for v := range d {
d[v] %= 10 d[v] %= 10
ss += strconv.FormatInt(int64(d[v]), 32) ss += strconv.FormatInt(int64(d[v]), 32)
} }
return NewImage(d, 100, 40), ss return NewImage(d, 100, 40), ss
} }
-1
View File
@@ -7,4 +7,3 @@ import (
func Html2Image(userInfo info.User, note info.Note, content, toPath string) bool { func Html2Image(userInfo info.User, note info.Note, content, toPath string) bool {
return true return true
} }
+223
View File
@@ -0,0 +1,223 @@
package i18n
import (
"fmt"
"github.com/revel/revel"
"github.com/robfig/config"
"os"
"path/filepath"
"regexp"
"strings"
)
const (
CurrentLocaleRenderArg = "currentLocale" // The key for the current locale render arg value
messageFilesDirectory = "messages"
messageFilePattern = `^\w+\.conf$`
unknownValueFormat = "??? %s ???"
defaultLanguageOption = "i18n.default_language"
localeCookieConfigKey = "i18n.cookie"
)
var (
// All currently loaded message configs.
// en-us, zh-cn, zh-hk ->
messages map[string]*config.Config
)
func GetAllLangMessages() map[string]*config.Config {
return messages
}
func HasLang(lang string) bool {
_, ok := messages[lang]
return ok
}
func GetDefaultLang() string {
lang, _ := revel.Config.String(defaultLanguageOption)
return lang
}
// Return all currently loaded message languages.
func MessageLanguages() []string {
languages := make([]string, len(messages))
i := 0
for language, _ := range messages {
languages[i] = language
i++
}
return languages
}
// Perform a message look-up for the given locale and message using the given arguments.
//
// When either an unknown locale or message is detected, a specially formatted string is returned.
func Message(locale, message string, args ...interface{}) string {
language, region := parseLocale(locale)
langAndRegion := language + "-" + region
// revel.TRACE.Println(langAndRegion + " 怎么回事")
messageConfig, knownLanguage := messages[langAndRegion]
if !knownLanguage {
// revel.TRACE.Printf("Unsupported language for locale '%s' and message '%s', trying default language", locale, message)
if defaultLanguage, found := revel.Config.String(defaultLanguageOption); found {
// revel.TRACE.Printf("Using default language '%s'", defaultLanguage)
messageConfig, knownLanguage = messages[defaultLanguage]
if !knownLanguage {
// WARN.Printf("Unsupported default language for locale '%s' and message '%s'", defaultLanguage, message)
return fmt.Sprintf(unknownValueFormat, message)
}
} else {
// WARN.Printf("Unable to find default language option (%s); messages for unsupported locales will never be translated", defaultLanguageOption)
return fmt.Sprintf(unknownValueFormat, message)
}
}
// This works because unlike the goconfig documentation suggests it will actually
// try to resolve message in DEFAULT if it did not find it in the given section.
value, error := messageConfig.String(region, message)
if error != nil {
// WARN.Printf("Unknown message '%s' for locale '%s'", message, locale)
return fmt.Sprintf(unknownValueFormat, message)
}
if len(args) > 0 {
// revel.TRACE.Printf("Arguments detected, formatting '%s' with %v", value, args)
value = fmt.Sprintf(value, args...)
}
return value
}
func parseLocale(locale string) (language, region string) {
if strings.Contains(locale, "-") {
languageAndRegion := strings.Split(locale, "-")
return languageAndRegion[0], languageAndRegion[1]
}
return locale, ""
}
// Recursively read and cache all available messages from all message files on the given path.
func loadMessages(path string) {
messages = make(map[string]*config.Config)
if error := filepath.Walk(path, loadEachMessageLang); error != nil && !os.IsNotExist(error) {
// ERROR.Println("Error reading messages files:", error)
}
}
// 加载每一个文件夹
func loadEachMessageLang(parentPath string, parentInfo os.FileInfo, osError error) (err error) {
if !parentInfo.IsDir() {
return nil
}
if err := filepath.Walk(parentPath, func(path string, info os.FileInfo, osError error) error {
return loadMessageFile(parentInfo.Name(), path, info, osError)
}); err != nil && !os.IsNotExist(err) {
// ERROR.Println("Error reading messages files:", error)
}
return err
}
// Load a single message file
func loadMessageFile(locale string, path string, info os.FileInfo, osError error) error {
if osError != nil {
return osError
}
if info.IsDir() {
return nil
}
if matched, _ := regexp.MatchString(messageFilePattern, info.Name()); matched {
if config, error := parseMessagesFile(path); error != nil {
return error
} else {
// locale := parseLocaleFromFileName(info.Name())
// revel.TRACE.Print(locale + "----locale")
// If we have already parsed a message file for this locale, merge both
if _, exists := messages[locale]; exists {
messages[locale].Merge(config)
revel.TRACE.Printf("Successfully merged messages for locale '%s'", locale)
} else {
messages[locale] = config
}
revel.TRACE.Println("Successfully loaded messages from file", info.Name())
}
} else {
revel.TRACE.Printf("Ignoring file %s because it did not have a valid extension", info.Name())
}
return nil
}
func parseMessagesFile(path string) (messageConfig *config.Config, error error) {
messageConfig, error = config.ReadDefault(path)
return
}
func parseLocaleFromFileName(file string) string {
extension := filepath.Ext(file)[1:]
return strings.ToLower(extension)
}
func init() {
revel.OnAppStart(func() {
loadMessages(filepath.Join(revel.BasePath, messageFilesDirectory))
})
}
func I18nFilter(c *revel.Controller, fc []revel.Filter) {
if foundCookie, cookieValue := hasLocaleCookie(c.Request); foundCookie {
revel.TRACE.Printf("Found locale cookie value: %s", cookieValue)
setCurrentLocaleControllerArguments(c, cookieValue)
} else if foundHeader, headerValue := hasAcceptLanguageHeader(c.Request); foundHeader {
revel.TRACE.Printf("Found Accept-Language header value: %s", headerValue)
setCurrentLocaleControllerArguments(c, headerValue)
} else {
revel.TRACE.Println("Unable to find locale in cookie or header, using empty string")
setCurrentLocaleControllerArguments(c, "")
}
fc[0](c, fc[1:])
}
// Set the current locale controller argument (CurrentLocaleControllerArg) with the given locale.
func setCurrentLocaleControllerArguments(c *revel.Controller, locale string) {
c.Request.Locale = locale
c.RenderArgs[CurrentLocaleRenderArg] = locale
}
// Determine whether the given request has valid Accept-Language value.
//
// Assumes that the accept languages stored in the request are sorted according to quality, with top
// quality first in the slice.
func hasAcceptLanguageHeader(request *revel.Request) (bool, string) {
if request.AcceptLanguages != nil && len(request.AcceptLanguages) > 0 {
return true, request.AcceptLanguages[0].Language
}
return false, ""
}
// Determine whether the given request has a valid language cookie value.
func hasLocaleCookie(request *revel.Request) (bool, string) {
if request != nil && request.Cookies() != nil {
name := revel.Config.StringDefault(localeCookieConfigKey, revel.CookiePrefix+"_LANG")
if cookie, error := request.Cookie(name); error == nil {
return true, cookie.Value
} else {
revel.TRACE.Printf("Unable to read locale cookie with name '%s': %s", name, error.Error())
}
}
return false, ""
}
+30 -29
View File
@@ -1,12 +1,13 @@
package netutil package netutil
import ( import (
"strings"
"os" "os"
// "path/filepath" "strings"
// "path/filepath"
. "github.com/leanote/leanote/app/lea"
"io/ioutil"
"net" "net"
"net/http" "net/http"
"io/ioutil"
. "github.com/leanote/leanote/app/lea"
) )
// net的util // net的util
@@ -16,11 +17,11 @@ import (
// 返回文件的完整目录 // 返回文件的完整目录
func WriteUrl(url string, toPath string) (length int64, newFilename, path string, ok bool) { func WriteUrl(url string, toPath string) (length int64, newFilename, path string, ok bool) {
if url == "" { if url == "" {
return; return
} }
content, err := GetContent(url) content, err := GetContent(url)
if err != nil { if err != nil {
return; return
} }
length = int64(len(content)) length = int64(len(content))
@@ -31,15 +32,15 @@ func WriteUrl(url string, toPath string) (length int64, newFilename, path string
if toPath == "" { if toPath == "" {
toPath = "/tmp" toPath = "/tmp"
} }
// dir := filepath.Dir(toPath) // dir := filepath.Dir(toPath)
newFilename = NewGuid() + ext newFilename = NewGuid() + ext
fullPath := toPath + "/" + newFilename fullPath := toPath + "/" + newFilename
// 写到文件中 // 写到文件中
file, err := os.Create(fullPath) file, err := os.Create(fullPath)
defer file.Close() defer file.Close()
if err != nil { if err != nil {
return return
} }
file.Write(content) file.Write(content)
@@ -53,43 +54,43 @@ 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) Log(err)
if(resp != nil && resp.Body != nil) { if resp != nil && resp.Body != nil {
defer resp.Body.Close() defer resp.Body.Close()
} else { } else {
} }
if resp == nil || resp.Body == nil || err != nil || resp.StatusCode != http.StatusOK { if resp == nil || resp.Body == nil || err != nil || resp.StatusCode != http.StatusOK {
return
}
var buf []byte
buf, err = ioutil.ReadAll(resp.Body)
if(err != nil) {
Log(err)
return return
} }
content = buf; var buf []byte
err = nil buf, err = ioutil.ReadAll(resp.Body)
return if err != nil {
Log(err)
return
}
content = buf
err = nil
return
} }
// 将url ?, #后面的字符串去掉 // 将url ?, #后面的字符串去掉
func trimQueryParams(url string) string { func trimQueryParams(url string) string {
pos := strings.Index(url, "?"); pos := strings.Index(url, "?")
if pos != -1 { if pos != -1 {
url = Substr(url, 0, pos); url = Substr(url, 0, pos)
} }
pos = strings.Index(url, "#"); pos = strings.Index(url, "#")
if pos != -1 { if pos != -1 {
url = Substr(url, 0, pos); url = Substr(url, 0, pos)
} }
pos = strings.Index(url, "!"); pos = strings.Index(url, "!")
if pos != -1 { if pos != -1 {
url = Substr(url, 0, pos); url = Substr(url, 0, pos)
} }
return url; return url
} }
// 通过domain得到ip // 通过domain得到ip
+13 -13
View File
@@ -1,9 +1,9 @@
package route package route
import ( import (
"github.com/revel/revel"
"github.com/leanote/leanote/app/db" "github.com/leanote/leanote/app/db"
// . "github.com/leanote/leanote/app/lea" "github.com/revel/revel"
// . "github.com/leanote/leanote/app/lea"
"net/url" "net/url"
"strings" "strings"
) )
@@ -11,6 +11,7 @@ import (
// overwite revel RouterFilter // overwite revel RouterFilter
// /api/user/Info => ApiUser.Info() // /api/user/Info => ApiUser.Info()
var staticPrefix = []string{"/public", "/favicon.ico", "/css", "/js", "/images", "/tinymce", "/upload", "/fonts"} var staticPrefix = []string{"/public", "/favicon.ico", "/css", "/js", "/images", "/tinymce", "/upload", "/fonts"}
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.Request.URL.Path
@@ -31,15 +32,15 @@ func RouterFilter(c *revel.Controller, fc []revel.Filter) {
//---------- //----------
// life start // life start
/* /*
type URL struct { type URL struct {
Scheme string Scheme string
Opaque string // encoded opaque data Opaque string // encoded opaque data
User *Userinfo // username and password information User *Userinfo // username and password information
Host string // host or host:port Host string // host or host:port
Path string Path string
RawQuery string // encoded query values, without '?' RawQuery string // encoded query values, without '?'
Fragment string // fragment for references, without '#' Fragment string // fragment for references, without '#'
} }
*/ */
if route.ControllerName != "Static" { if route.ControllerName != "Static" {
@@ -49,7 +50,7 @@ func RouterFilter(c *revel.Controller, fc []revel.Filter) {
// 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, "Api") {
route.ControllerName = "Api" + route.ControllerName route.ControllerName = "Api" + route.ControllerName
} else if strings.HasPrefix(path, "/member") && !strings.HasPrefix(route.ControllerName, "Member") { } else if strings.HasPrefix(path, "/member") && !strings.HasPrefix(route.ControllerName, "Member") {
// member设置 // member设置
@@ -84,4 +85,3 @@ func RouterFilter(c *revel.Controller, fc []revel.Filter) {
fc[0](c, fc[1:]) fc[0](c, fc[1:])
} }
+32 -32
View File
@@ -2,11 +2,11 @@ package main
import ( import (
"fmt" "fmt"
"io/ioutil"
"os" "os"
"os/exec" "os/exec"
"io/ioutil"
"strings" "strings"
// "time" // "time"
) )
/* /*
@@ -54,13 +54,13 @@ func compressJs(filename string) {
to := base + filename + "-min.js" to := base + filename + "-min.js"
cmd := exec.Command(cmdPath, source, "-o", to) cmd := exec.Command(cmdPath, source, "-o", to)
_, err := cmd.CombinedOutput() _, err := cmd.CombinedOutput()
fmt.Println(source); fmt.Println(source)
cmdError(err) cmdError(err)
} }
func combineJs() { func combineJs() {
// 生成一个总文件 // 生成一个总文件
cmd := exec.Command("rm", base + "js/all.js") cmd := exec.Command("rm", base+"js/all.js")
_, err := cmd.CombinedOutput() _, err := cmd.CombinedOutput()
cmdError(err) cmdError(err)
@@ -70,10 +70,10 @@ func combineJs() {
compressJs(js) compressJs(js)
// 每个压缩后的文件放入之 // 每个压缩后的文件放入之
cmd2 := exec.Command("/bin/sh", "-c", "cat " + to + " >> " + base + "js/all.js") cmd2 := exec.Command("/bin/sh", "-c", "cat "+to+" >> "+base+"js/all.js")
_, err := cmd2.CombinedOutput() _, err := cmd2.CombinedOutput()
cmdError(err) cmdError(err)
cmd2 = exec.Command("/bin/sh", "-c", "cat \n >> " + base + "js/all.js") cmd2 = exec.Command("/bin/sh", "-c", "cat \n >> "+base+"js/all.js")
_, err = cmd2.CombinedOutput() _, err = cmd2.CombinedOutput()
cmdError(err) cmdError(err)
} }
@@ -83,21 +83,21 @@ func combineJs() {
func dev() { func dev() {
// 即替换note.js->note-min.js // 即替换note.js->note-min.js
m := map[string]string{"tinymce.dev.js": "tinymce.min.js", m := map[string]string{"tinymce.dev.js": "tinymce.min.js",
"tinymce.js": "tinymce.min.js", "tinymce.js": "tinymce.min.js",
"jquery.ztree.all-3.5.js": "jquery.ztree.all-3.5-min.js", "jquery.ztree.all-3.5.js": "jquery.ztree.all-3.5-min.js",
"note.js": "note-min.js", "note.js": "note-min.js",
"app.js": "app-min.js", "app.js": "app-min.js",
"page.js": "page-min.js", "page.js": "page-min.js",
"common.js": "common-min.js", "common.js": "common-min.js",
"notebook.js": "notebook-min.js", "notebook.js": "notebook-min.js",
"share.js": "share-min.js", "share.js": "share-min.js",
"tag.js": "tag-min.js", "tag.js": "tag-min.js",
"jquery.slimscroll.js": "jquery.slimscroll-min.js", "jquery.slimscroll.js": "jquery.slimscroll-min.js",
"jquery.contextmenu.js": "jquery.contextmenu-min.js", "jquery.contextmenu.js": "jquery.contextmenu-min.js",
"editor/editor.js": "editor/editor-min.js", "editor/editor.js": "editor/editor-min.js",
"/public/mdeditor/editor/scrollLink.js": "/public/mdeditor/editor/scrollLink-min.js", "/public/mdeditor/editor/scrollLink.js": "/public/mdeditor/editor/scrollLink-min.js",
"console.log(o);": "", "console.log(o);": "",
} }
path := base1 + "/src/views/note/note-dev.html" path := base1 + "/src/views/note/note-dev.html"
target := base1 + "/src/views/note/note.html" target := base1 + "/src/views/note/note.html"
@@ -108,28 +108,28 @@ func dev() {
content = strings.Replace(content, key, value, -1) content = strings.Replace(content, key, value, -1)
} }
// var time = time.Now().Unix() % 1000 // var time = time.Now().Unix() % 1000
// content = strings.Replace(content, "-min.js", fmt.Sprintf("-min.js?r=%d", time), -1) // content = strings.Replace(content, "-min.js", fmt.Sprintf("-min.js?r=%d", time), -1)
// content = strings.Replace(content, "default{{end}}.css", fmt.Sprintf("default{{end}}.css?r=%d", time), 1) // content = strings.Replace(content, "default{{end}}.css", fmt.Sprintf("default{{end}}.css?r=%d", time), 1)
// content = strings.Replace(content, "writting-overwrite.css", fmt.Sprintf("writting-overwrite.css?r=%d", time), 1) // content = strings.Replace(content, "writting-overwrite.css", fmt.Sprintf("writting-overwrite.css?r=%d", time), 1)
ioutil.WriteFile(target, []byte(content), os.ModeAppend) ioutil.WriteFile(target, []byte(content), os.ModeAppend)
} }
// 压缩js成一块 // 压缩js成一块
func tinymce() { func tinymce() {
// cmdStr := "node_modules/jake/bin/cli.js minify bundle[themes:modern,plugins:table,paste,advlist,autolink,link,image,lists,charmap,hr,searchreplace,visualblocks,visualchars,code,nav,tabfocus,contextmenu,directionality,codemirror,codesyntax,textcolor,fullpage]" // cmdStr := "node_modules/jake/bin/cli.js minify bundle[themes:modern,plugins:table,paste,advlist,autolink,link,image,lists,charmap,hr,searchreplace,visualblocks,visualchars,code,nav,tabfocus,contextmenu,directionality,codemirror,codesyntax,textcolor,fullpage]"
// cmd := exec.Command("/Users/life/Documents/eclipse-workspace/go/leanote_release/tinymce-master/node_modules/jake/bin/cli.js", "minify", "bundle[themes:modern,plugins:table,paste,advlist,autolink,link,image,lists,charmap,hr,searchreplace,visualblocks,visualchars,code,nav,tabfocus,contextmenu,directionality,codemirror,codesyntax,textcolor,fullpage]") // cmd := exec.Command("/Users/life/Documents/eclipse-workspace/go/leanote_release/tinymce-master/node_modules/jake/bin/cli.js", "minify", "bundle[themes:modern,plugins:table,paste,advlist,autolink,link,image,lists,charmap,hr,searchreplace,visualblocks,visualchars,code,nav,tabfocus,contextmenu,directionality,codemirror,codesyntax,textcolor,fullpage]")
cmd := exec.Command("/bin/sh", "-c", "grunt minify"); cmd := exec.Command("/bin/sh", "-c", "grunt minify")
cmd.Dir = base + "/tinymce_4.1.9" cmd.Dir = base + "/tinymce_4.1.9"
fmt.Println("正在build tinymce"); fmt.Println("正在build tinymce")
// 必须要先删除 // 必须要先删除
cmd2 := exec.Command("/bin/sh", "-c", "rm " + cmd.Dir + "/js/tinymce/tinymce.dev.js") cmd2 := exec.Command("/bin/sh", "-c", "rm "+cmd.Dir+"/js/tinymce/tinymce.dev.js")
cmd2.CombinedOutput() cmd2.CombinedOutput()
cmd2 = exec.Command("/bin/sh", "-c", "rm " + cmd.Dir + "/js/tinymce/tinymce.jquery.dev.js") cmd2 = exec.Command("/bin/sh", "-c", "rm "+cmd.Dir+"/js/tinymce/tinymce.jquery.dev.js")
c, _ := cmd2.CombinedOutput() c, _ := cmd2.CombinedOutput()
fmt.Println(string(c)) fmt.Println(string(c))
@@ -141,13 +141,13 @@ func main() {
// 压缩tinymce // 压缩tinymce
// tinymce() // tinymce()
dev(); dev()
// 其它零散的需要压缩的js // 其它零散的需要压缩的js
otherJss := []string{"js/main", "js/app/page", "js/contextmenu/jquery.contextmenu", otherJss := []string{"js/main", "js/app/page", "js/contextmenu/jquery.contextmenu",
"js/jquery.ztree.all-3.5", "js/jquery.ztree.all-3.5",
"js/jQuery-slimScroll-1.3.0/jquery.slimscroll", "js/jQuery-slimScroll-1.3.0/jquery.slimscroll",
} }
for _, js := range otherJss { for _, js := range otherJss {
compressJs(js) compressJs(js)
+2 -2
View File
@@ -2,7 +2,7 @@ package service
import ( import (
"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/db" "github.com/leanote/leanote/app/db"
"gopkg.in/mgo.v2/bson" "gopkg.in/mgo.v2/bson"
"time" "time"
@@ -32,7 +32,7 @@ func (this *AlbumService) GetAlbums(userId string) []info.Album {
func (this *AlbumService) DeleteAlbum(userId, albumId string) (bool, string) { func (this *AlbumService) DeleteAlbum(userId, albumId string) (bool, string) {
if db.Count(db.Files, bson.M{"AlbumId": bson.ObjectIdHex(albumId), if db.Count(db.Files, bson.M{"AlbumId": bson.ObjectIdHex(albumId),
"UserId": bson.ObjectIdHex(userId), "UserId": bson.ObjectIdHex(userId),
}) == 0 { }) == 0 {
return db.DeleteByIdAndUserId(db.Albums, albumId, userId), "" return db.DeleteByIdAndUserId(db.Albums, albumId, userId), ""
} }
return false, "has images" return false, "has images"
+8 -8
View File
@@ -49,13 +49,13 @@ func (this *AttachService) AddAttach(attach info.Attach, fromApi bool) (ok bool,
func (this *AttachService) updateNoteAttachNum(noteId bson.ObjectId, addNum int) bool { func (this *AttachService) updateNoteAttachNum(noteId bson.ObjectId, addNum int) bool {
num := db.Count(db.Attachs, bson.M{"NoteId": noteId}) num := db.Count(db.Attachs, bson.M{"NoteId": noteId})
/* /*
note := info.Note{} note := info.Note{}
note = noteService.GetNoteById(noteId.Hex()) note = noteService.GetNoteById(noteId.Hex())
note.AttachNum += addNum note.AttachNum += addNum
if note.AttachNum < 0 { if note.AttachNum < 0 {
note.AttachNum = 0 note.AttachNum = 0
} }
Log(note.AttachNum) Log(note.AttachNum)
*/ */
return db.UpdateByQField(db.Notes, bson.M{"_id": noteId}, "AttachNum", num) return db.UpdateByQField(db.Notes, bson.M{"_id": noteId}, "AttachNum", num)
} }
@@ -123,7 +123,7 @@ func (this *AttachService) DeleteAttach(attachId, userId string) (bool, string)
attach := info.Attach{} attach := info.Attach{}
db.Get(db.Attachs, attachId, &attach) db.Get(db.Attachs, attachId, &attach)
if(attach.AttachId != "") { if attach.AttachId != "" {
// 判断是否有权限为笔记添加附件 // 判断是否有权限为笔记添加附件
if !shareService.HasUpdateNotePerm(attach.NoteId.Hex(), userId) { if !shareService.HasUpdateNotePerm(attach.NoteId.Hex(), userId) {
return false, "No Perm" return false, "No Perm"
+11 -6
View File
@@ -518,7 +518,7 @@ func (this *BlogService) fixUserBlog(userBlog *info.UserBlog) {
// Logo路径问题, 有些有http: 有些没有 // Logo路径问题, 有些有http: 有些没有
if userBlog.Logo != "" && !strings.HasPrefix(userBlog.Logo, "http") { if userBlog.Logo != "" && !strings.HasPrefix(userBlog.Logo, "http") {
userBlog.Logo = strings.Trim(userBlog.Logo, "/") userBlog.Logo = strings.Trim(userBlog.Logo, "/")
userBlog.Logo = configService.GetSiteUrl() + "/" + userBlog.Logo userBlog.Logo = "/" + userBlog.Logo
} }
if userBlog.SortField == "" { if userBlog.SortField == "" {
@@ -919,7 +919,7 @@ func (this *BlogService) UpateCateUrlTitle(userId string, cateId, urlTitle strin
"UrlTitle": "", "UrlTitle": "",
}) })
*/ */
url = GetUrTitle(userId, urlTitle, "notebook") url = GetUrTitle(userId, urlTitle, "notebook", cateId)
ok = db.UpdateByIdAndUserIdMap(db.Notebooks, cateId, userId, bson.M{ ok = db.UpdateByIdAndUserIdMap(db.Notebooks, cateId, userId, bson.M{
"UrlTitle": url, "UrlTitle": url,
}) })
@@ -935,7 +935,7 @@ func (this *BlogService) UpateBlogUrlTitle(userId string, noteId, urlTitle strin
ok = db.UpdateByIdAndUserIdMap(db.Notes, noteId, userId, bson.M{ ok = db.UpdateByIdAndUserIdMap(db.Notes, noteId, userId, bson.M{
"UrlTitle": "", "UrlTitle": "",
}) })
url = GetUrTitle(userId, urlTitle, "note") url = GetUrTitle(userId, urlTitle, "note", noteId)
ok = db.UpdateByIdAndUserIdMap(db.Notes, noteId, userId, bson.M{ ok = db.UpdateByIdAndUserIdMap(db.Notes, noteId, userId, bson.M{
"UrlTitle": url, "UrlTitle": url,
}) })
@@ -1036,7 +1036,7 @@ func (this *BlogService) UpdateSingleUrlTitle(userId, singleId, urlTitle string)
"UrlTitle": "", "UrlTitle": "",
}) })
*/ */
url = GetUrTitle(userId, urlTitle, "single") url = GetUrTitle(userId, urlTitle, "single", singleId)
ok = db.UpdateByIdAndUserIdMap(db.BlogSingles, singleId, userId, bson.M{ ok = db.UpdateByIdAndUserIdMap(db.BlogSingles, singleId, userId, bson.M{
"UrlTitle": url, "UrlTitle": url,
}) })
@@ -1070,7 +1070,7 @@ func (this *BlogService) AddOrUpdateSingle(userId, singleId, title, content stri
UserId: bson.ObjectIdHex(userId), UserId: bson.ObjectIdHex(userId),
Title: title, Title: title,
Content: content, Content: content,
UrlTitle: GetUrTitle(userId, title, "single"), UrlTitle: GetUrTitle(userId, title, "single", singleId),
CreatedTime: time.Now(), CreatedTime: time.Now(),
} }
page.UpdatedTime = page.CreatedTime page.UpdatedTime = page.CreatedTime
@@ -1108,6 +1108,7 @@ func (this *BlogService) SortSingles(userId string, singleIds []string) (ok bool
// 得到用户的博客url // 得到用户的博客url
func (this *BlogService) GetUserBlogUrl(userBlog *info.UserBlog, username string) string { func (this *BlogService) GetUserBlogUrl(userBlog *info.UserBlog, username string) string {
/*
if userBlog != nil { if userBlog != nil {
if userBlog.Domain != "" && configService.AllowCustomDomain() { if userBlog.Domain != "" && configService.AllowCustomDomain() {
return configService.GetUserUrl(userBlog.Domain) return configService.GetUserUrl(userBlog.Domain)
@@ -1118,12 +1119,15 @@ func (this *BlogService) GetUserBlogUrl(userBlog *info.UserBlog, username string
username = userBlog.UserId.Hex() username = userBlog.UserId.Hex()
} }
} }
*/
return configService.GetBlogUrl() + "/" + username return configService.GetBlogUrl() + "/" + username
} }
// 得到所有url // 得到所有url
func (this *BlogService) GetBlogUrls(userBlog *info.UserBlog, userInfo *info.User) info.BlogUrls { func (this *BlogService) GetBlogUrls(userBlog *info.UserBlog, userInfo *info.User) info.BlogUrls {
var indexUrl, postUrl, searchUrl, cateUrl, singleUrl, tagsUrl, archiveUrl, tagPostsUrl string var indexUrl, postUrl, searchUrl, cateUrl, singleUrl, tagsUrl, archiveUrl, tagPostsUrl string
/*
if userBlog.Domain != "" && configService.AllowCustomDomain() { // http://demo.com if userBlog.Domain != "" && configService.AllowCustomDomain() { // http://demo.com
// ok // ok
indexUrl = configService.GetUserUrl(userBlog.Domain) indexUrl = configService.GetUserUrl(userBlog.Domain)
@@ -1144,6 +1148,7 @@ func (this *BlogService) GetBlogUrls(userBlog *info.UserBlog, userInfo *info.Use
tagsUrl = indexUrl + "/tags" tagsUrl = indexUrl + "/tags"
tagPostsUrl = indexUrl + "/tag" tagPostsUrl = indexUrl + "/tag"
} else { } else {
*/
// ok // ok
blogUrl := configService.GetBlogUrl() // blog.leanote.com blogUrl := configService.GetBlogUrl() // blog.leanote.com
userIdOrEmail := "" userIdOrEmail := ""
@@ -1162,7 +1167,7 @@ func (this *BlogService) GetBlogUrls(userBlog *info.UserBlog, userInfo *info.Use
archiveUrl = blogUrl + "/archives/" + userIdOrEmail // blog.leanote.com/archive/username archiveUrl = blogUrl + "/archives/" + userIdOrEmail // blog.leanote.com/archive/username
tagsUrl = blogUrl + "/tags/" + userIdOrEmail tagsUrl = blogUrl + "/tags/" + userIdOrEmail
tagPostsUrl = blogUrl + "/tag/" + userIdOrEmail // blog.leanote.com/archive/username tagPostsUrl = blogUrl + "/tag/" + userIdOrEmail // blog.leanote.com/archive/username
} // }
return info.BlogUrls{ return info.BlogUrls{
IndexUrl: indexUrl, IndexUrl: indexUrl,
+91 -81
View File
@@ -1,32 +1,33 @@
package service package service
import ( import (
"fmt"
"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"
"github.com/leanote/leanote/app/db"
"gopkg.in/mgo.v2/bson"
"github.com/revel/revel" "github.com/revel/revel"
"time" "gopkg.in/mgo.v2/bson"
"os" "os"
"os/exec" "os/exec"
"fmt"
"strings"
"strconv" "strconv"
"strings"
"time"
) )
// 配置服务 // 配置服务
// 只是全局的, 用户的配置没有 // 只是全局的, 用户的配置没有
type ConfigService struct { type ConfigService struct {
adminUserId string adminUserId string
siteUrl string siteUrl string
adminUsername string adminUsername string
// 全局的 // 全局的
GlobalAllConfigs map[string]interface{} GlobalAllConfigs map[string]interface{}
GlobalStringConfigs map[string]string GlobalStringConfigs map[string]string
GlobalArrayConfigs map[string][]string GlobalArrayConfigs map[string][]string
GlobalMapConfigs map[string]map[string]string GlobalMapConfigs map[string]map[string]string
GlobalArrMapConfigs map[string][]map[string]string GlobalArrMapConfigs map[string][]map[string]string
} }
// appStart时 将全局的配置从数据库中得到作为全局 // appStart时 将全局的配置从数据库中得到作为全局
func (this *ConfigService) InitGlobalConfigs() bool { func (this *ConfigService) InitGlobalConfigs() bool {
this.GlobalAllConfigs = map[string]interface{}{} this.GlobalAllConfigs = map[string]interface{}{}
@@ -66,11 +67,21 @@ func (this *ConfigService) InitGlobalConfigs() bool {
} }
} }
// site URL
if s, ok := this.GlobalStringConfigs["siteUrl"]; !ok || s != "" {
this.GlobalStringConfigs["siteUrl"] = this.siteUrl
}
return true return true
} }
func (this *ConfigService) GetSiteUrl() string { func (this *ConfigService) GetSiteUrl() string {
return this.siteUrl; s := this.GetGlobalStringConfig("siteUrl")
if s != "" {
return s
}
return this.siteUrl
} }
func (this *ConfigService) GetAdminUsername() string { func (this *ConfigService) GetAdminUsername() string {
return this.adminUsername return this.adminUsername
@@ -85,14 +96,14 @@ func (this *ConfigService) updateGlobalConfig(userId, key string, value interfac
if _, ok := this.GlobalAllConfigs[key]; !ok { if _, ok := this.GlobalAllConfigs[key]; !ok {
// 需要添加 // 需要添加
config := info.Config{ConfigId: bson.NewObjectId(), config := info.Config{ConfigId: bson.NewObjectId(),
UserId: bson.ObjectIdHex(userId), UserId: bson.ObjectIdHex(userId),
Key: key, Key: key,
IsArr: isArr, IsArr: isArr,
IsMap: isMap, IsMap: isMap,
IsArrMap: isArrMap, IsArrMap: isArrMap,
UpdatedTime: time.Now(), UpdatedTime: time.Now(),
} }
if(isArr) { if isArr {
v, _ := value.([]string) v, _ := value.([]string)
config.ValueArr = v config.ValueArr = v
this.GlobalArrayConfigs[key] = v this.GlobalArrayConfigs[key] = v
@@ -113,7 +124,7 @@ func (this *ConfigService) updateGlobalConfig(userId, key string, value interfac
} else { } else {
i := bson.M{"UpdatedTime": time.Now()} i := bson.M{"UpdatedTime": time.Now()}
this.GlobalAllConfigs[key] = value this.GlobalAllConfigs[key] = value
if(isArr) { if isArr {
v, _ := value.([]string) v, _ := value.([]string)
i["ValueArr"] = v i["ValueArr"] = v
this.GlobalArrayConfigs[key] = v this.GlobalArrayConfigs[key] = v
@@ -177,6 +188,7 @@ func (this *ConfigService) GetGlobalArrMapConfig(key string) []map[string]string
func (this *ConfigService) IsOpenRegister() bool { func (this *ConfigService) IsOpenRegister() bool {
return this.GetGlobalStringConfig("openRegister") != "" return this.GetGlobalStringConfig("openRegister") != ""
} }
//------- //-------
// 修改共享笔记的配置 // 修改共享笔记的配置
func (this *ConfigService) UpdateShareNoteConfig(registerSharedUserId string, func (this *ConfigService) UpdateShareNoteConfig(registerSharedUserId string,
@@ -188,7 +200,7 @@ func (this *ConfigService) UpdateShareNoteConfig(registerSharedUserId string,
ok = false ok = false
msg = fmt.Sprint(err) msg = fmt.Sprint(err)
} }
}(); }()
// 用户是否存在? // 用户是否存在?
if registerSharedUserId == "" { if registerSharedUserId == "" {
@@ -222,7 +234,7 @@ func (this *ConfigService) UpdateShareNoteConfig(registerSharedUserId string,
msg = "The user has no such notebook: " + notebookId msg = "The user has no such notebook: " + notebookId
return return
} else { } else {
perm := "0"; perm := "0"
if registerSharedNotebookPerms[i] == 1 { if registerSharedNotebookPerms[i] == 1 {
perm = "1" perm = "1"
} }
@@ -247,7 +259,7 @@ func (this *ConfigService) UpdateShareNoteConfig(registerSharedUserId string,
msg = "The user has no such note: " + noteId msg = "The user has no such note: " + noteId
return return
} else { } else {
perm := "0"; perm := "0"
if registerSharedNotePerms[i] == 1 { if registerSharedNotePerms[i] == 1 {
perm = "1" perm = "1"
} }
@@ -298,7 +310,7 @@ func (this *ConfigService) getBackupDirname() string {
} }
func (this *ConfigService) Backup(remark string) (ok bool, msg string) { func (this *ConfigService) Backup(remark string) (ok bool, msg string) {
binPath := configService.GetGlobalStringConfig("mongodumpPath") binPath := configService.GetGlobalStringConfig("mongodumpPath")
config := revel.Config; config := revel.Config
dbname, _ := config.String("db.dbname") dbname, _ := config.String("db.dbname")
host, _ := revel.Config.String("db.host") host, _ := revel.Config.String("db.host")
port, _ := revel.Config.String("db.port") port, _ := revel.Config.String("db.port")
@@ -320,18 +332,19 @@ func (this *ConfigService) Backup(remark string) (ok bool, msg string) {
} }
cmd := exec.Command("/bin/sh", "-c", binPath) cmd := exec.Command("/bin/sh", "-c", binPath)
Log(binPath); Log(binPath)
b, err := cmd.Output() b, err := cmd.Output()
if err != nil { if err != nil {
msg = fmt.Sprintf("%v", err) msg = fmt.Sprintf("%v", err)
ok = false ok = false
Log("error:......") Log("error:......")
Log(string(b)) Log(string(b))
return return
} }
ok = configService.AddBackup(dir, remark) ok = configService.AddBackup(dir, remark)
return ok, msg return ok, msg
} }
// 还原 // 还原
func (this *ConfigService) Restore(createdTime string) (ok bool, msg string) { func (this *ConfigService) Restore(createdTime string) (ok bool, msg string) {
backups := this.GetGlobalArrMapConfig("backups") // [{}, {}] backups := this.GetGlobalArrMapConfig("backups") // [{}, {}]
@@ -339,7 +352,7 @@ func (this *ConfigService) Restore(createdTime string) (ok bool, msg string) {
var backup map[string]string var backup map[string]string
for i, backup = range backups { for i, backup = range backups {
if backup["createdTime"] == createdTime { if backup["createdTime"] == createdTime {
break; break
} }
} }
if i == len(backups) { if i == len(backups) {
@@ -347,14 +360,14 @@ func (this *ConfigService) Restore(createdTime string) (ok bool, msg string) {
} }
// 先备份当前 // 先备份当前
ok, msg = this.Backup("Auto backup when restore from " + backup["createdTime"] ) ok, msg = this.Backup("Auto backup when restore from " + backup["createdTime"])
if !ok { if !ok {
return return
} }
// mongorestore -h localhost -d leanote --directoryperdb /home/user1/gopackage/src/github.com/leanote/leanote/mongodb_backup/leanote_install_data/ // mongorestore -h localhost -d leanote --directoryperdb /home/user1/gopackage/src/github.com/leanote/leanote/mongodb_backup/leanote_install_data/
binPath := configService.GetGlobalStringConfig("mongorestorePath") binPath := configService.GetGlobalStringConfig("mongorestorePath")
config := revel.Config; config := revel.Config
dbname, _ := config.String("db.dbname") dbname, _ := config.String("db.dbname")
host, _ := revel.Config.String("db.host") host, _ := revel.Config.String("db.host")
port, _ := revel.Config.String("db.port") port, _ := revel.Config.String("db.port")
@@ -375,15 +388,15 @@ func (this *ConfigService) Restore(createdTime string) (ok bool, msg string) {
binPath += " " + path binPath += " " + path
cmd := exec.Command("/bin/sh", "-c", binPath) cmd := exec.Command("/bin/sh", "-c", binPath)
Log(binPath); Log(binPath)
b, err := cmd.Output() b, err := cmd.Output()
if err != nil { if err != nil {
msg = fmt.Sprintf("%v", err) msg = fmt.Sprintf("%v", err)
ok = false ok = false
Log("error:......") Log("error:......")
Log(string(b)) Log(string(b))
return return
} }
return true, "" return true, ""
} }
@@ -393,7 +406,7 @@ func (this *ConfigService) DeleteBackup(createdTime string) (bool, string) {
var backup map[string]string var backup map[string]string
for i, backup = range backups { for i, backup = range backups {
if backup["createdTime"] == createdTime { if backup["createdTime"] == createdTime {
break; break
} }
} }
if i == len(backups) { if i == len(backups) {
@@ -419,13 +432,13 @@ func (this *ConfigService) UpdateBackupRemark(createdTime, remark string) (bool,
var backup map[string]string var backup map[string]string
for i, backup = range backups { for i, backup = range backups {
if backup["createdTime"] == createdTime { if backup["createdTime"] == createdTime {
break; break
} }
} }
if i == len(backups) { if i == len(backups) {
return false, "Backup Not Found" return false, "Backup Not Found"
} }
backup["remark"] = remark; backup["remark"] = remark
ok := this.UpdateGlobalArrMapConfig(this.adminUserId, "backups", backups) ok := this.UpdateGlobalArrMapConfig(this.adminUserId, "backups", backups)
return ok, "" return ok, ""
@@ -438,7 +451,7 @@ func (this *ConfigService) GetBackup(createdTime string) (map[string]string, boo
var backup map[string]string var backup map[string]string
for i, backup = range backups { for i, backup = range backups {
if backup["createdTime"] == createdTime { if backup["createdTime"] == createdTime {
break; break
} }
} }
if i == len(backups) { if i == len(backups) {
@@ -456,13 +469,13 @@ var port string
func init() { func init() {
revel.OnAppStart(func() { revel.OnAppStart(func() {
/* /*
不用配置的, 因为最终通过命令可以改, 而且有的使用nginx代理 不用配置的, 因为最终通过命令可以改, 而且有的使用nginx代理
port = strconv.Itoa(revel.HttpPort) port = strconv.Itoa(revel.HttpPort)
if port != "80" { if port != "80" {
port = ":" + port port = ":" + port
} else { } else {
port = ""; port = "";
} }
*/ */
siteUrl, _ := revel.Config.String("site.url") // 已包含:9000, http, 去掉成 leanote.com siteUrl, _ := revel.Config.String("site.url") // 已包含:9000, http, 去掉成 leanote.com
@@ -487,49 +500,36 @@ func init() {
} }
func (this *ConfigService) GetSchema() string { func (this *ConfigService) GetSchema() string {
return schema; return schema
} }
// 默认 // 默认
func (this *ConfigService) GetDefaultDomain() string { func (this *ConfigService) GetDefaultDomain() string {
return defaultDomain return defaultDomain
} }
// 包含http://
func (this *ConfigService) GetDefaultUrl() string {
return schema + defaultDomain
}
// note // note
func (this *ConfigService) GetNoteDomain() string { func (this *ConfigService) GetNoteDomain() string {
subDomain := this.GetGlobalStringConfig("noteSubDomain"); return "/note"
if subDomain != "" {
return subDomain + port
}
return this.GetDefaultDomain() + "/note"
} }
func (this *ConfigService) GetNoteUrl() string { func (this *ConfigService) GetNoteUrl() string {
return schema + this.GetNoteDomain(); return this.GetNoteDomain()
} }
// blog // blog
func (this *ConfigService) GetBlogDomain() string { func (this *ConfigService) GetBlogDomain() string {
subDomain := this.GetGlobalStringConfig("blogSubDomain"); return "/blog"
if subDomain != "" {
return subDomain + port
}
return this.GetDefaultDomain() + "/blog"
} }
func (this *ConfigService) GetBlogUrl() string { func (this *ConfigService) GetBlogUrl() string {
return schema + this.GetBlogDomain(); return this.GetBlogDomain()
} }
// lea // lea
func (this *ConfigService) GetLeaDomain() string { func (this *ConfigService) GetLeaDomain() string {
subDomain := this.GetGlobalStringConfig("leaSubDomain"); return "/lea"
if subDomain != "" {
return subDomain + port
}
return this.GetDefaultDomain() + "/lea"
} }
func (this *ConfigService) GetLeaUrl() string { func (this *ConfigService) GetLeaUrl() string {
return schema + this.GetLeaDomain(); return schema + this.GetLeaDomain()
} }
func (this *ConfigService) GetUserUrl(domain string) string { func (this *ConfigService) GetUserUrl(domain string) string {
@@ -543,6 +543,7 @@ func (this *ConfigService) GetUserSubUrl(subDomain string) string {
func (this *ConfigService) AllowCustomDomain() bool { func (this *ConfigService) AllowCustomDomain() bool {
return configService.GetGlobalStringConfig("allowCustomDomain") != "" return configService.GetGlobalStringConfig("allowCustomDomain") != ""
} }
// 是否是好的自定义域名 // 是否是好的自定义域名
func (this *ConfigService) IsGoodCustomDomain(domain string) bool { func (this *ConfigService) IsGoodCustomDomain(domain string) bool {
blacks := this.GetGlobalArrayConfig("blackCustomDomains") blacks := this.GetGlobalArrayConfig("blackCustomDomains")
@@ -567,20 +568,29 @@ func (this *ConfigService) IsGoodSubDomain(domain string) bool {
// 上传大小 // 上传大小
func (this *ConfigService) GetUploadSize(key string) float64 { func (this *ConfigService) GetUploadSize(key string) float64 {
f, _ := strconv.ParseFloat(this.GetGlobalStringConfig(key), 64) f, _ := strconv.ParseFloat(this.GetGlobalStringConfig(key), 64)
return f; return f
}
func (this *ConfigService) GetInt64(key string) int64 {
f, _ := strconv.ParseInt(this.GetGlobalStringConfig(key), 10, 64)
return f
}
func (this *ConfigService) GetInt32(key string) int32 {
f, _ := strconv.ParseInt(this.GetGlobalStringConfig(key), 10, 32)
return int32(f)
} }
func (this *ConfigService) GetUploadSizeLimit() map[string]float64 { func (this *ConfigService) GetUploadSizeLimit() map[string]float64 {
return map[string]float64{ return map[string]float64{
"uploadImageSize": this.GetUploadSize("uploadImageSize"), "uploadImageSize": this.GetUploadSize("uploadImageSize"),
"uploadBlogLogoSize":this.GetUploadSize("uploadBlogLogoSize"), "uploadBlogLogoSize": this.GetUploadSize("uploadBlogLogoSize"),
"uploadAttachSize":this.GetUploadSize("uploadAttachSize"), "uploadAttachSize": this.GetUploadSize("uploadAttachSize"),
"uploadAvatarSize":this.GetUploadSize("uploadAvatarSize"), "uploadAvatarSize": this.GetUploadSize("uploadAvatarSize"),
} }
} }
// 为用户得到全局的配置 // 为用户得到全局的配置
// NoteController调用 // NoteController调用
func (this *ConfigService) GetGlobalConfigForUser() map[string]interface{} { func (this *ConfigService) GetGlobalConfigForUser() map[string]interface{} {
uploadSizeConfigs := this.GetUploadSizeLimit(); uploadSizeConfigs := this.GetUploadSizeLimit()
config := map[string]interface{}{} config := map[string]interface{}{}
for k, v := range uploadSizeConfigs { for k, v := range uploadSizeConfigs {
config[k] = v config[k] = v
@@ -594,5 +604,5 @@ func (this *ConfigService) HomePageIsAdminsBlog() bool {
} }
func (this *ConfigService) GetVersion() string { func (this *ConfigService) GetVersion() string {
return "1.3.1" return "2.0"
} }
+112 -112
View File
@@ -1,17 +1,17 @@
package service package service
import ( import (
"github.com/leanote/leanote/app/info" "bytes"
"fmt"
"github.com/leanote/leanote/app/db" "github.com/leanote/leanote/app/db"
"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" "html/template"
"strings"
"net/smtp" "net/smtp"
"strconv" "strconv"
"fmt" "strings"
"html/template" "time"
"bytes"
) )
// 发送邮件 // 发送邮件
@@ -20,7 +20,7 @@ type EmailService struct {
tpls map[string]*template.Template tpls map[string]*template.Template
} }
func NewEmailService() (*EmailService) { func NewEmailService() *EmailService {
return &EmailService{tpls: map[string]*template.Template{}} return &EmailService{tpls: map[string]*template.Template{}}
} }
@@ -50,12 +50,12 @@ func (this *EmailService) SendEmail(to, subject, body string) (ok bool, e string
mailtype := "html" mailtype := "html"
if mailtype == "html" { if mailtype == "html" {
content_type = "Content-Type: text/"+ mailtype + "; charset=UTF-8" content_type = "Content-Type: text/" + mailtype + "; charset=UTF-8"
} else{ } else {
content_type = "Content-Type: text/plain" + "; charset=UTF-8" content_type = "Content-Type: text/plain" + "; charset=UTF-8"
} }
msg := []byte("To: " + to + "\r\nFrom: " + username + "<"+ username +">\r\nSubject: " + subject + "\r\n" + content_type + "\r\n\r\n" + body) msg := []byte("To: " + to + "\r\nFrom: " + username + "<" + username + ">\r\nSubject: " + subject + "\r\n" + content_type + "\r\n\r\n" + body)
send_to := strings.Split(to, ";") send_to := strings.Split(to, ";")
err := smtp.SendMail(host+":"+emailPort, auth, username, send_to, msg) err := smtp.SendMail(host+":"+emailPort, auth, username, send_to, msg)
@@ -75,10 +75,10 @@ func (this *EmailService) RegisterSendActiveEmail(userInfo info.User, email stri
return false return false
} }
subject := configService.GetGlobalStringConfig("emailTemplateRegisterSubject"); subject := configService.GetGlobalStringConfig("emailTemplateRegisterSubject")
tpl := configService.GetGlobalStringConfig("emailTemplateRegister"); tpl := configService.GetGlobalStringConfig("emailTemplateRegister")
if(tpl == "") { if tpl == "" {
return false return false
} }
@@ -86,8 +86,8 @@ func (this *EmailService) RegisterSendActiveEmail(userInfo info.User, email stri
// {siteUrl} {tokenUrl} {token} {tokenTimeout} {user.id} {user.email} {user.username} // {siteUrl} {tokenUrl} {token} {tokenTimeout} {user.id} {user.email} {user.username}
token2Value := map[string]interface{}{"siteUrl": configService.GetSiteUrl(), "tokenUrl": tokenUrl, "token": token, "tokenTimeout": strconv.Itoa(int(tokenService.GetOverHours(info.TokenActiveEmail))), token2Value := map[string]interface{}{"siteUrl": configService.GetSiteUrl(), "tokenUrl": tokenUrl, "token": token, "tokenTimeout": strconv.Itoa(int(tokenService.GetOverHours(info.TokenActiveEmail))),
"user": map[string]interface{}{ "user": map[string]interface{}{
"userId": userInfo.UserId.Hex(), "userId": userInfo.UserId.Hex(),
"email": userInfo.Email, "email": userInfo.Email,
"username": userInfo.Username, "username": userInfo.Username,
}, },
} }
@@ -118,8 +118,8 @@ func (this *EmailService) UpdateEmailSendActiveEmail(userInfo info.User, email s
return return
} }
subject := configService.GetGlobalStringConfig("emailTemplateUpdateEmailSubject"); subject := configService.GetGlobalStringConfig("emailTemplateUpdateEmailSubject")
tpl := configService.GetGlobalStringConfig("emailTemplateUpdateEmail"); tpl := configService.GetGlobalStringConfig("emailTemplateUpdateEmail")
// 发送邮件 // 发送邮件
tokenUrl := configService.GetSiteUrl() + "/user/updateEmail?token=" + token tokenUrl := configService.GetSiteUrl() + "/user/updateEmail?token=" + token
@@ -127,8 +127,8 @@ func (this *EmailService) UpdateEmailSendActiveEmail(userInfo info.User, email s
token2Value := map[string]interface{}{"siteUrl": configService.GetSiteUrl(), "tokenUrl": tokenUrl, "token": token, "tokenTimeout": strconv.Itoa(int(tokenService.GetOverHours(info.TokenActiveEmail))), token2Value := map[string]interface{}{"siteUrl": configService.GetSiteUrl(), "tokenUrl": tokenUrl, "token": token, "tokenTimeout": strconv.Itoa(int(tokenService.GetOverHours(info.TokenActiveEmail))),
"newEmail": email, "newEmail": email,
"user": map[string]interface{}{ "user": map[string]interface{}{
"userId": userInfo.UserId.Hex(), "userId": userInfo.UserId.Hex(),
"email": userInfo.Email, "email": userInfo.Email,
"username": userInfo.Username, "username": userInfo.Username,
}, },
} }
@@ -144,8 +144,8 @@ func (this *EmailService) UpdateEmailSendActiveEmail(userInfo info.User, email s
} }
func (this *EmailService) FindPwdSendEmail(token, email string) (ok bool, msg string) { func (this *EmailService) FindPwdSendEmail(token, email string) (ok bool, msg string) {
subject := configService.GetGlobalStringConfig("emailTemplateFindPasswordSubject"); subject := configService.GetGlobalStringConfig("emailTemplateFindPasswordSubject")
tpl := configService.GetGlobalStringConfig("emailTemplateFindPassword"); tpl := configService.GetGlobalStringConfig("emailTemplateFindPassword")
// 发送邮件 // 发送邮件
tokenUrl := configService.GetSiteUrl() + "/findPassword/" + token tokenUrl := configService.GetSiteUrl() + "/findPassword/" + token
@@ -164,15 +164,15 @@ func (this *EmailService) FindPwdSendEmail(token, email string) (ok bool, msg st
// 发送邀请链接 // 发送邀请链接
func (this *EmailService) SendInviteEmail(userInfo info.User, email, content string) bool { func (this *EmailService) SendInviteEmail(userInfo info.User, email, content string) bool {
subject := configService.GetGlobalStringConfig("emailTemplateInviteSubject"); subject := configService.GetGlobalStringConfig("emailTemplateInviteSubject")
tpl := configService.GetGlobalStringConfig("emailTemplateInvite"); tpl := configService.GetGlobalStringConfig("emailTemplateInvite")
token2Value := map[string]interface{}{"siteUrl": configService.GetSiteUrl(), token2Value := map[string]interface{}{"siteUrl": configService.GetSiteUrl(),
"registerUrl": configService.GetSiteUrl() + "/register?from=" + userInfo.Username, "registerUrl": configService.GetSiteUrl() + "/register?from=" + userInfo.Username,
"content": content, "content": content,
"user": map[string]interface{}{ "user": map[string]interface{}{
"username": userInfo.Username, "username": userInfo.Username,
"email": userInfo.Email, "email": userInfo.Email,
}, },
} }
var ok bool var ok bool
@@ -187,30 +187,30 @@ func (this *EmailService) SendInviteEmail(userInfo info.User, email, content str
// 发送评论 // 发送评论
func (this *EmailService) SendCommentEmail(note info.Note, comment info.BlogComment, userId, content string) bool { func (this *EmailService) SendCommentEmail(note info.Note, comment info.BlogComment, userId, content string) bool {
subject := configService.GetGlobalStringConfig("emailTemplateCommentSubject"); subject := configService.GetGlobalStringConfig("emailTemplateCommentSubject")
tpl := configService.GetGlobalStringConfig("emailTemplateComment"); tpl := configService.GetGlobalStringConfig("emailTemplateComment")
// title := "评论提醒" // title := "评论提醒"
/* /*
toUserId := note.UserId.Hex() toUserId := note.UserId.Hex()
// title := "评论提醒" // title := "评论提醒"
// 表示回复回复的内容, 那么发送给之前回复的 // 表示回复回复的内容, 那么发送给之前回复的
if comment.CommentId != "" { if comment.CommentId != "" {
toUserId = comment.UserId.Hex() toUserId = comment.UserId.Hex()
} }
toUserInfo := userService.GetUserInfo(toUserId) toUserInfo := userService.GetUserInfo(toUserId)
sendUserInfo := userService.GetUserInfo(userId) sendUserInfo := userService.GetUserInfo(userId)
subject := note.Title + " 收到 " + sendUserInfo.Username + " 的评论"; subject := note.Title + " 收到 " + sendUserInfo.Username + " 的评论";
if comment.CommentId != "" { if comment.CommentId != "" {
subject = "您在 " + note.Title + " 发表的评论收到 " + sendUserInfo.Username; subject = "您在 " + note.Title + " 发表的评论收到 " + sendUserInfo.Username;
if userId == note.UserId.Hex() { if userId == note.UserId.Hex() {
subject += "(作者)"; subject += "(作者)";
}
subject += " 的评论";
} }
subject += " 的评论";
}
*/ */
toUserId := note.UserId.Hex() toUserId := note.UserId.Hex()
@@ -227,21 +227,21 @@ func (this *EmailService) SendCommentEmail(note info.Note, comment info.BlogComm
// {commentedUser.userId} {commentedUser.username} {commentedUser.email} // {commentedUser.userId} {commentedUser.username} {commentedUser.email}
token2Value := map[string]interface{}{"siteUrl": configService.GetSiteUrl(), "blogUrl": configService.GetBlogUrl(), token2Value := map[string]interface{}{"siteUrl": configService.GetSiteUrl(), "blogUrl": configService.GetBlogUrl(),
"blog": map[string]string{ "blog": map[string]string{
"id": note.NoteId.Hex(), "id": note.NoteId.Hex(),
"title": note.Title, "title": note.Title,
"url": configService.GetBlogUrl() + "/view/" + note.NoteId.Hex(), "url": configService.GetBlogUrl() + "/view/" + note.NoteId.Hex(),
}, },
"commentContent": content, "commentContent": content,
// 评论者信息 // 评论者信息
"commentUser": map[string]interface{}{"userId": sendUserInfo.UserId.Hex(), "commentUser": map[string]interface{}{"userId": sendUserInfo.UserId.Hex(),
"username": sendUserInfo.Username, "username": sendUserInfo.Username,
"email": sendUserInfo.Email, "email": sendUserInfo.Email,
"isBlogAuthor": userId == note.UserId.Hex(), "isBlogAuthor": userId == note.UserId.Hex(),
}, },
// 被评论者信息 // 被评论者信息
"commentedUser": map[string]interface{}{"userId": toUserId, "commentedUser": map[string]interface{}{"userId": toUserId,
"username": toUserInfo.Username, "username": toUserInfo.Username,
"email": toUserInfo.Email, "email": toUserInfo.Email,
"isBlogAuthor": toUserId == note.UserId.Hex(), "isBlogAuthor": toUserId == note.UserId.Hex(),
}, },
} }
@@ -257,47 +257,46 @@ func (this *EmailService) SendCommentEmail(note info.Note, comment info.BlogComm
return ok return ok
} }
// 验证模板是否正确 // 验证模板是否正确
func (this *EmailService) ValidTpl(str string) (ok bool, msg string){ func (this *EmailService) ValidTpl(str string) (ok bool, msg string) {
defer func() { defer func() {
if err := recover(); err != nil { if err := recover(); err != nil {
ok = false ok = false
msg = fmt.Sprint(err) msg = fmt.Sprint(err)
} }
}(); }()
header := configService.GetGlobalStringConfig("emailTemplateHeader"); header := configService.GetGlobalStringConfig("emailTemplateHeader")
footer := configService.GetGlobalStringConfig("emailTemplateFooter"); footer := configService.GetGlobalStringConfig("emailTemplateFooter")
str = strings.Replace(str, "{{header}}", header, -1) str = strings.Replace(str, "{{header}}", header, -1)
str = strings.Replace(str, "{{footer}}", footer, -1) str = strings.Replace(str, "{{footer}}", footer, -1)
_, err := template.New("tpl name").Parse(str) _, err := template.New("tpl name").Parse(str)
if err != nil { if err != nil {
msg = fmt.Sprint(err) msg = fmt.Sprint(err)
return return
} }
ok = true ok = true
return return
} }
// ok, msg, subject, tpl // ok, msg, subject, tpl
func (this *EmailService) getTpl(str string) (ok bool, msg string, tpl *template.Template){ func (this *EmailService) getTpl(str string) (ok bool, msg string, tpl *template.Template) {
defer func() { defer func() {
if err := recover(); err != nil { if err := recover(); err != nil {
ok = false ok = false
msg = fmt.Sprint(err) msg = fmt.Sprint(err)
} }
}(); }()
var err error var err error
var has bool var has bool
if tpl, has = this.tpls[str]; !has { if tpl, has = this.tpls[str]; !has {
tpl, err = template.New("tpl name").Parse(str) tpl, err = template.New("tpl name").Parse(str)
if err != nil { if err != nil {
msg = fmt.Sprint(err) msg = fmt.Sprint(err)
return return
} }
this.tpls[str] = tpl this.tpls[str] = tpl
} }
ok = true ok = true
return return
@@ -310,63 +309,63 @@ func (this *EmailService) renderEmail(subject, body string, values map[string]in
defer func() { // 必须要先声明defer,否则不能捕获到panic异常 defer func() { // 必须要先声明defer,否则不能捕获到panic异常
if err := recover(); err != nil { if err := recover(); err != nil {
ok = false ok = false
msg = fmt.Sprint(err) // 这里的err其实就是panic传入的内容, msg = fmt.Sprint(err) // 这里的err其实就是panic传入的内容,
} }
}(); }()
var tpl *template.Template var tpl *template.Template
values["siteUrl"] = configService.GetSiteUrl(); values["siteUrl"] = configService.GetSiteUrl()
// subject // subject
if subject != "" { if subject != "" {
ok, msg, tpl = this.getTpl(subject) ok, msg, tpl = this.getTpl(subject)
if(!ok) { if !ok {
return return
} }
var buffer bytes.Buffer var buffer bytes.Buffer
err := tpl.Execute(&buffer, values) err := tpl.Execute(&buffer, values)
if err != nil { if err != nil {
msg = fmt.Sprint(err) msg = fmt.Sprint(err)
return return
} }
o = buffer.String() o = buffer.String()
} else { } else {
o = "" o = ""
} }
// content // content
header := configService.GetGlobalStringConfig("emailTemplateHeader"); header := configService.GetGlobalStringConfig("emailTemplateHeader")
footer := configService.GetGlobalStringConfig("emailTemplateFooter"); footer := configService.GetGlobalStringConfig("emailTemplateFooter")
body = strings.Replace(body, "{{header}}", header, -1) body = strings.Replace(body, "{{header}}", header, -1)
body = strings.Replace(body, "{{footer}}", footer, -1) body = strings.Replace(body, "{{footer}}", footer, -1)
values["subject"] = o values["subject"] = o
ok, msg, tpl = this.getTpl(body) ok, msg, tpl = this.getTpl(body)
if(!ok) { if !ok {
return return
} }
var buffer2 bytes.Buffer var buffer2 bytes.Buffer
err := tpl.Execute(&buffer2, values) err := tpl.Execute(&buffer2, values)
if err != nil { if err != nil {
msg = fmt.Sprint(err) msg = fmt.Sprint(err)
return return
} }
b = buffer2.String() b = buffer2.String()
return return
} }
// 发送email给用户 // 发送email给用户
// 需要记录 // 需要记录
func (this *EmailService) SendEmailToUsers(users []info.User, subject, body string) (ok bool, msg string) { func (this *EmailService) SendEmailToUsers(users []info.User, subject, body string) (ok bool, msg string) {
if(users == nil || len(users) == 0) { if users == nil || len(users) == 0 {
msg = "no users" msg = "no users"
return return
} }
// 尝试renderHtml // 尝试renderHtml
ok, msg, _, _ = this.renderEmail(subject, body, map[string]interface{}{}) ok, msg, _, _ = this.renderEmail(subject, body, map[string]interface{}{})
if(!ok) { if !ok {
Log(msg) Log(msg)
return return
} }
@@ -381,8 +380,8 @@ func (this *EmailService) SendEmailToUsers(users []info.User, subject, body stri
ok2, msg2, subject2, body2 := this.renderEmail(subject, body, m) ok2, msg2, subject2, body2 := this.renderEmail(subject, body, m)
ok = ok2 ok = ok2
msg = msg2 msg = msg2
if(ok2) { if ok2 {
sendOk, msg := this.SendEmail(user.Email, subject2, body2); sendOk, msg := this.SendEmail(user.Email, subject2, body2)
this.AddEmailLog(user.Email, subject, body, sendOk, msg) // 把模板记录下 this.AddEmailLog(user.Email, subject, body, sendOk, msg) // 把模板记录下
// 记录到Email Log // 记录到Email Log
if sendOk { if sendOk {
@@ -400,40 +399,40 @@ func (this *EmailService) SendEmailToUsers(users []info.User, subject, body stri
} }
func (this *EmailService) SendEmailToEmails(emails []string, subject, body string) (ok bool, msg string) { func (this *EmailService) SendEmailToEmails(emails []string, subject, body string) (ok bool, msg string) {
if(emails == nil || len(emails) == 0) { if emails == nil || len(emails) == 0 {
msg = "no emails" msg = "no emails"
return return
} }
// 尝试renderHtml // 尝试renderHtml
ok, msg, _, _ = this.renderEmail(subject, body, map[string]interface{}{}) ok, msg, _, _ = this.renderEmail(subject, body, map[string]interface{}{})
if(!ok) { if !ok {
Log(msg) Log(msg)
return return
} }
// go func() { // go func() {
for _, email := range emails { for _, email := range emails {
if email == "" { if email == "" {
continue continue
}
m := map[string]interface{}{}
m["email"] = email
ok, msg, subject, body = this.renderEmail(subject, body, m)
if(ok) {
sendOk, msg := this.SendEmail(email, subject, body);
this.AddEmailLog(email, subject, body, sendOk, msg)
// 记录到Email Log
if sendOk {
Log("ok " + email)
} else {
Log("no " + email)
}
} else {
Log(msg);
}
} }
// }() m := map[string]interface{}{}
m["email"] = email
ok, msg, subject, body = this.renderEmail(subject, body, m)
if ok {
sendOk, msg := this.SendEmail(email, subject, body)
this.AddEmailLog(email, subject, body, sendOk, msg)
// 记录到Email Log
if sendOk {
Log("ok " + email)
} else {
Log("no " + email)
}
} else {
Log(msg)
}
}
// }()
return return
} }
@@ -443,6 +442,7 @@ func (this *EmailService) AddEmailLog(email, subject, body string, ok bool, msg
log := info.EmailLog{LogId: bson.NewObjectId(), Email: email, Subject: subject, Body: body, Ok: ok, Msg: msg, CreatedTime: time.Now()} log := info.EmailLog{LogId: bson.NewObjectId(), Email: email, Subject: subject, Body: body, Ok: ok, Msg: msg, CreatedTime: time.Now()}
db.Insert(db.EmailLogs, log) db.Insert(db.EmailLogs, log)
} }
// 展示邮件日志 // 展示邮件日志
func (this *EmailService) DeleteEmails(ids []string) bool { func (this *EmailService) DeleteEmails(ids []string) bool {
@@ -461,7 +461,7 @@ func (this *EmailService) ListEmailLogs(pageNumber, pageSize int, sortField stri
if email != "" { if email != "" {
query["Email"] = bson.M{"$regex": bson.RegEx{".*?" + email + ".*", "i"}} query["Email"] = bson.M{"$regex": bson.RegEx{".*?" + email + ".*", "i"}}
} }
q := db.EmailLogs.Find(query); q := db.EmailLogs.Find(query)
// 总记录数 // 总记录数
count, _ := q.Count() count, _ := q.Count()
// 列表 // 列表
+40 -38
View File
@@ -43,17 +43,17 @@ func (this *FileService) ListImagesWithPage(userId, albumId, key string, pageNum
q := bson.M{"UserId": bson.ObjectIdHex(userId), "Type": ""} // life q := bson.M{"UserId": bson.ObjectIdHex(userId), "Type": ""} // life
if albumId != "" { if albumId != "" {
q["AlbumId"] = bson.ObjectIdHex(albumId); q["AlbumId"] = bson.ObjectIdHex(albumId)
} else { } else {
q["IsDefaultAlbum"] = true q["IsDefaultAlbum"] = true
} }
if key != "" { if key != "" {
q["Title"] = bson.M{"$regex": bson.RegEx{".*?" + key + ".*", "i"}} q["Title"] = bson.M{"$regex": bson.RegEx{".*?" + key + ".*", "i"}}
} }
// LogJ(q) // LogJ(q)
count := db.Count(db.Files, q); count := db.Count(db.Files, q)
db.Files. db.Files.
Find(q). Find(q).
@@ -92,7 +92,7 @@ func (this *FileService) DeleteImage(userId, fileId string) (bool, string) {
file := info.File{} file := info.File{}
db.GetByIdAndUserId(db.Files, fileId, userId, &file) db.GetByIdAndUserId(db.Files, fileId, userId, &file)
if(file.FileId != "") { if file.FileId != "" {
if db.DeleteByIdAndUserId(db.Files, fileId, userId) { if db.DeleteByIdAndUserId(db.Files, fileId, userId) {
// delete image // delete image
// TODO // TODO
@@ -203,30 +203,30 @@ func (this *FileService) GetFile(userId, fileId string) string {
for _, noteId := range noteIds { for _, noteId := range noteIds {
note := noteService.GetNoteById(noteId.Hex()) note := noteService.GetNoteById(noteId.Hex())
if shareService.HasReadPerm(note.UserId.Hex(), userId, noteId.Hex()) { if shareService.HasReadPerm(note.UserId.Hex(), userId, noteId.Hex()) {
return path;
}
}
/*
// 若有共享给我的笔记?
// 对该笔记可读?
if db.Has(db.ShareNotes, bson.M{"ToUserId": bson.ObjectIdHex(userId), "NoteId": bson.M{"$in": noteIds}}) {
return path
}
// 笔记本是否共享给我?
// 通过笔记得到笔记本
notes := []info.Note{}
db.ListByQWithFields(db.Notes, bson.M{"_id": bson.M{"$in": noteIds}}, []string{"NotebookId"}, &notes)
if notes != nil && len(notes) > 0 {
notebookIds := make([]bson.ObjectId, len(notes))
for i := 0; i < len(notes); i++ {
notebookIds[i] = notes[i].NotebookId
}
if db.Has(db.ShareNotebooks, bson.M{"ToUserId": bson.ObjectIdHex(userId), "NotebookId": bson.M{"$in": notebookIds}}) {
return path return path
} }
} }
/*
// 若有共享给我的笔记?
// 对该笔记可读?
if db.Has(db.ShareNotes, bson.M{"ToUserId": bson.ObjectIdHex(userId), "NoteId": bson.M{"$in": noteIds}}) {
return path
}
// 笔记本是否共享给我?
// 通过笔记得到笔记本
notes := []info.Note{}
db.ListByQWithFields(db.Notes, bson.M{"_id": bson.M{"$in": noteIds}}, []string{"NotebookId"}, &notes)
if notes != nil && len(notes) > 0 {
notebookIds := make([]bson.ObjectId, len(notes))
for i := 0; i < len(notes); i++ {
notebookIds[i] = notes[i].NotebookId
}
if db.Has(db.ShareNotebooks, bson.M{"ToUserId": bson.ObjectIdHex(userId), "NotebookId": bson.M{"$in": notebookIds}}) {
return path
}
}
*/ */
} }
@@ -242,17 +242,17 @@ func (this *FileService) GetFile(userId, fileId string) string {
return "" return ""
} }
// 复制共享的笔记时, 复制其中的图片到我本地
// 复制图片 // 复制图片
func (this *FileService) CopyImage(userId, fileId, toUserId string) (bool, string) { func (this *FileService) CopyImage(userId, fileId, toUserId string) (bool, string) {
// 是否已经复制过了 // 是否已经复制过了
file2 := info.File{} file2 := info.File{}
db.GetByQ(db.Files, bson.M{"UserId": bson.ObjectIdHex(toUserId), "FromFileId": bson.ObjectIdHex(fileId)}, &file2) db.GetByQ(db.Files, bson.M{"UserId": bson.ObjectIdHex(toUserId), "FromFileId": bson.ObjectIdHex(fileId)}, &file2)
if file2.FileId != "" { if file2.FileId != "" {
return true, file2.FileId.Hex(); return true, file2.FileId.Hex()
} }
// 复制之 // 复制之
file := info.File{} file := info.File{}
db.GetByIdAndUserId(db.Files, fileId, userId, &file) db.GetByIdAndUserId(db.Files, fileId, userId, &file)
@@ -261,27 +261,29 @@ func (this *FileService) CopyImage(userId, fileId, toUserId string) (bool, strin
} }
_, ext := SplitFilename(file.Name) _, ext := SplitFilename(file.Name)
newFilename := NewGuid() + ext guid := NewGuid()
newFilename := guid + ext
dir := "files/" + toUserId + "/images" // TODO 统一目录格式
// dir := "files/" + toUserId + "/images"
dir := "files/" + GetRandomFilePath(toUserId, guid) + "/images"
filePath := dir + "/" + newFilename filePath := dir + "/" + newFilename
err := os.MkdirAll(dir, 0755) err := os.MkdirAll(revel.BasePath+dir, 0755)
if err != nil { if err != nil {
return false, "" return false, ""
} }
_, err = CopyFile(revel.BasePath + "/" + file.Path, revel.BasePath + "/" + filePath) _, err = CopyFile(revel.BasePath+"/"+file.Path, revel.BasePath+"/"+filePath)
if err != nil { if err != nil {
Log(err)
return false, "" return false, ""
} }
fileInfo := info.File{Name: newFilename, fileInfo := info.File{Name: newFilename,
Title: file.Title, Title: file.Title,
Path: filePath, Path: filePath,
Size: file.Size, Size: file.Size,
FromFileId: file.FileId} FromFileId: file.FileId}
id := bson.NewObjectId(); id := bson.NewObjectId()
fileInfo.FileId = id fileInfo.FileId = id
fileId = id.Hex() fileId = id.Hex()
Ok, _ := this.AddImage(fileInfo, "", toUserId, false) Ok, _ := this.AddImage(fileInfo, "", toUserId, false)
@@ -296,7 +298,7 @@ func (this *FileService) CopyImage(userId, fileId, toUserId string) (bool, strin
func (this *FileService) IsMyFile(userId, fileId string) bool { func (this *FileService) IsMyFile(userId, fileId string) bool {
// 如果有问题会panic // 如果有问题会panic
if !bson.IsObjectIdHex(fileId) || !bson.IsObjectIdHex(userId) { if !bson.IsObjectIdHex(fileId) || !bson.IsObjectIdHex(userId) {
return false; return false
} }
return db.Has(db.Files, bson.M{"UserId": bson.ObjectIdHex(userId), "_id": bson.ObjectIdHex(fileId)}) return db.Has(db.Files, bson.M{"UserId": bson.ObjectIdHex(userId), "_id": bson.ObjectIdHex(fileId)})
} }
+39 -37
View File
@@ -1,12 +1,12 @@
package service package service
import ( import (
"github.com/leanote/leanote/app/info"
"github.com/leanote/leanote/app/db" "github.com/leanote/leanote/app/db"
// . "github.com/leanote/leanote/app/lea" "github.com/leanote/leanote/app/info"
// . "github.com/leanote/leanote/app/lea"
"gopkg.in/mgo.v2/bson" "gopkg.in/mgo.v2/bson"
"time" "time"
// "strings" // "strings"
) )
// 用户组, 用户组用户管理 // 用户组, 用户组用户管理
@@ -16,21 +16,22 @@ type GroupService struct {
// 添加分组 // 添加分组
func (this *GroupService) AddGroup(userId, title string) (bool, info.Group) { func (this *GroupService) AddGroup(userId, title string) (bool, info.Group) {
group := info.Group { group := info.Group{
GroupId: bson.NewObjectId(), GroupId: bson.NewObjectId(),
UserId: bson.ObjectIdHex(userId), UserId: bson.ObjectIdHex(userId),
Title: title, Title: title,
CreatedTime: time.Now(), CreatedTime: time.Now(),
} }
return db.Insert(db.Groups, group), group return db.Insert(db.Groups, group), group
} }
// 删除分组 // 删除分组
// 判断是否有好友 // 判断是否有好友
func (this *GroupService) DeleteGroup(userId, groupId string) (ok bool, msg string) { func (this *GroupService) DeleteGroup(userId, groupId string) (ok bool, msg string) {
/* /*
if db.Has(db.GroupUsers, bson.M{"GroupId": bson.ObjectIdHex(groupId)}) { if db.Has(db.GroupUsers, bson.M{"GroupId": bson.ObjectIdHex(groupId)}) {
return false, "groupHasUsers" return false, "groupHasUsers"
} }
*/ */
if !this.isMyGroup(userId, groupId) { if !this.isMyGroup(userId, groupId) {
return false, "notMyGroup" return false, "notMyGroup"
@@ -38,8 +39,8 @@ func (this *GroupService) DeleteGroup(userId, groupId string) (ok bool, msg stri
// 删除分组后, 需要删除所有用户分享到该组的笔记本, 笔记 // 删除分组后, 需要删除所有用户分享到该组的笔记本, 笔记
shareService.DeleteAllShareNotebookGroup(groupId); shareService.DeleteAllShareNotebookGroup(groupId)
shareService.DeleteAllShareNoteGroup(groupId); shareService.DeleteAllShareNoteGroup(groupId)
db.DeleteAll(db.GroupUsers, bson.M{"GroupId": bson.ObjectIdHex(groupId)}) db.DeleteAll(db.GroupUsers, bson.M{"GroupId": bson.ObjectIdHex(groupId)})
return db.DeleteByIdAndUserId(db.Groups, groupId, userId), "" return db.DeleteByIdAndUserId(db.Groups, groupId, userId), ""
@@ -53,14 +54,14 @@ func (this *GroupService) UpdateGroupTitle(userId, groupId, title string) (ok bo
} }
// 得到用户的所有分组(包括下的所有用户) // 得到用户的所有分组(包括下的所有用户)
func (this *GroupService) GetGroupsAndUsers(userId string) ([]info.Group) { func (this *GroupService) GetGroupsAndUsers(userId string) []info.Group {
/* /*
// 得到我的分组 // 得到我的分组
groups := []info.Group{} groups := []info.Group{}
db.ListByQ(db.Groups, bson.M{"UserId": bson.ObjectIdHex(userId)}, &groups) db.ListByQ(db.Groups, bson.M{"UserId": bson.ObjectIdHex(userId)}, &groups)
*/ */
// 我的分组, 及我所属的分组 // 我的分组, 及我所属的分组
groups := this.GetGroupsContainOf(userId); groups := this.GetGroupsContainOf(userId)
// 得到其下的用户 // 得到其下的用户
for i, group := range groups { for i, group := range groups {
@@ -69,8 +70,9 @@ func (this *GroupService) GetGroupsAndUsers(userId string) ([]info.Group) {
} }
return groups return groups
} }
// 仅仅得到所有分组 // 仅仅得到所有分组
func (this *GroupService) GetGroups(userId string) ([]info.Group) { func (this *GroupService) GetGroups(userId string) []info.Group {
// 得到分组s // 得到分组s
groups := []info.Group{} groups := []info.Group{}
db.ListByQ(db.Groups, bson.M{"UserId": bson.ObjectIdHex(userId)}, &groups) db.ListByQ(db.Groups, bson.M{"UserId": bson.ObjectIdHex(userId)}, &groups)
@@ -78,7 +80,7 @@ func (this *GroupService) GetGroups(userId string) ([]info.Group) {
} }
// 得到我的和我所属组的ids // 得到我的和我所属组的ids
func (this *GroupService) GetMineAndBelongToGroupIds(userId string) ([]bson.ObjectId) { func (this *GroupService) GetMineAndBelongToGroupIds(userId string) []bson.ObjectId {
// 所属组 // 所属组
groupIds := this.GetBelongToGroupIds(userId) groupIds := this.GetBelongToGroupIds(userId)
@@ -126,7 +128,7 @@ func (this *GroupService) GetGroupsContainOf(userId string) []info.Group {
} }
// 得到分组, shareService用 // 得到分组, shareService用
func (this *GroupService) GetGroup(userId, groupId string) (info.Group) { func (this *GroupService) GetGroup(userId, groupId string) info.Group {
// 得到分组s // 得到分组s
group := info.Group{} group := info.Group{}
db.GetByIdAndUserId(db.Groups, groupId, userId, &group) db.GetByIdAndUserId(db.Groups, groupId, userId, &group)
@@ -134,7 +136,7 @@ func (this *GroupService) GetGroup(userId, groupId string) (info.Group) {
} }
// 得到某分组下的用户 // 得到某分组下的用户
func (this *GroupService) GetUsers(groupId string) ([]info.User) { func (this *GroupService) GetUsers(groupId string) []info.User {
// 得到UserIds // 得到UserIds
groupUsers := []info.GroupUser{} groupUsers := []info.GroupUser{}
db.ListByQWithFields(db.GroupUsers, bson.M{"GroupId": bson.ObjectIdHex(groupId)}, []string{"UserId"}, &groupUsers) db.ListByQWithFields(db.GroupUsers, bson.M{"GroupId": bson.ObjectIdHex(groupId)}, []string{"UserId"}, &groupUsers)
@@ -150,7 +152,7 @@ func (this *GroupService) GetUsers(groupId string) ([]info.User) {
} }
// 得到我所属的所有分组ids // 得到我所属的所有分组ids
func (this *GroupService) GetBelongToGroupIds(userId string) ([]bson.ObjectId) { func (this *GroupService) GetBelongToGroupIds(userId string) []bson.ObjectId {
// 得到UserIds // 得到UserIds
groupUsers := []info.GroupUser{} groupUsers := []info.GroupUser{}
db.ListByQWithFields(db.GroupUsers, bson.M{"UserId": bson.ObjectIdHex(userId)}, []string{"GroupId"}, &groupUsers) db.ListByQWithFields(db.GroupUsers, bson.M{"UserId": bson.ObjectIdHex(userId)}, []string{"GroupId"}, &groupUsers)
@@ -182,23 +184,23 @@ func (this *GroupService) IsExistsGroupUser(userId, groupId string) (ok bool) {
func (this *GroupService) AddUser(ownUserId, groupId, userId string) (ok bool, msg string) { func (this *GroupService) AddUser(ownUserId, groupId, userId string) (ok bool, msg string) {
// groupId是否是ownUserId的? // groupId是否是ownUserId的?
/* /*
if !this.IsExistsGroupUser(ownUserId, groupId) { if !this.IsExistsGroupUser(ownUserId, groupId) {
return false, "forbidden" return false, "forbiddenNotMyGroup"
} }
*/ */
if !this.isMyGroup(ownUserId, groupId) { if !this.isMyGroup(ownUserId, groupId) {
return false, "forbidden" return false, "forbiddenNotMyGroup"
} }
// 是否已存在 // 是否已存在
if db.Has(db.GroupUsers, bson.M{"GroupId": bson.ObjectIdHex(groupId), "UserId": bson.ObjectIdHex(userId)}) { if db.Has(db.GroupUsers, bson.M{"GroupId": bson.ObjectIdHex(groupId), "UserId": bson.ObjectIdHex(userId)}) {
return false, "hasUsers" return false, "userExistsInGroup"
} }
return db.Insert(db.GroupUsers, info.GroupUser{ return db.Insert(db.GroupUsers, info.GroupUser{
GroupUserId: bson.NewObjectId(), GroupUserId: bson.NewObjectId(),
GroupId: bson.ObjectIdHex(groupId), GroupId: bson.ObjectIdHex(groupId),
UserId: bson.ObjectIdHex(userId), UserId: bson.ObjectIdHex(userId),
CreatedTime: time.Now(), CreatedTime: time.Now(),
}), "" }), ""
} }
@@ -207,17 +209,17 @@ func (this *GroupService) AddUser(ownUserId, groupId, userId string) (ok bool, m
func (this *GroupService) DeleteUser(ownUserId, groupId, userId string) (ok bool, msg string) { func (this *GroupService) DeleteUser(ownUserId, groupId, userId string) (ok bool, msg string) {
// groupId是否是ownUserId的? // groupId是否是ownUserId的?
/* /*
if !this.IsExistsGroupUser(ownUserId, groupId) { if !this.IsExistsGroupUser(ownUserId, groupId) {
return false, "forbidden" return false, "forbiddenNotMyGroup"
} }
*/ */
if !this.isMyGroup(ownUserId, groupId) { if !this.isMyGroup(ownUserId, groupId) {
return false, "forbidden" return false, "forbiddenNotMyGroup"
} }
// 删除该用户分享到本组的笔记本, 笔记 // 删除该用户分享到本组的笔记本, 笔记
shareService.DeleteShareNotebookGroupWhenDeleteGroupUser(userId, groupId); shareService.DeleteShareNotebookGroupWhenDeleteGroupUser(userId, groupId)
shareService.DeleteShareNoteGroupWhenDeleteGroupUser(userId, groupId); shareService.DeleteShareNoteGroupWhenDeleteGroupUser(userId, groupId)
return db.Delete(db.GroupUsers, bson.M{"GroupId": bson.ObjectIdHex(groupId), "UserId": bson.ObjectIdHex(userId)}), "" return db.Delete(db.GroupUsers, bson.M{"GroupId": bson.ObjectIdHex(groupId), "UserId": bson.ObjectIdHex(userId)}), ""
} }
+5 -5
View File
@@ -1,11 +1,11 @@
package service package service
import ( import (
"github.com/leanote/leanote/app/info"
"github.com/leanote/leanote/app/db" "github.com/leanote/leanote/app/db"
// . "github.com/leanote/leanote/app/lea" "github.com/leanote/leanote/app/info"
// . "github.com/leanote/leanote/app/lea"
"gopkg.in/mgo.v2/bson" "gopkg.in/mgo.v2/bson"
// "time" // "time"
) )
// 历史记录 // 历史记录
@@ -38,7 +38,7 @@ func (this *NoteContentHistoryService) AddHistory(noteId, userId string, eachHis
} }
newHistory := []info.EachHistory{eachHistory} newHistory := []info.EachHistory{eachHistory}
newHistory = append(newHistory, history.Histories...) // 在开头加了, 最近的在最前 newHistory = append(newHistory, history.Histories...) // 在开头加了, 最近的在最前
history.Histories = newHistory history.Histories = newHistory
// 更新之 // 更新之
db.UpdateByIdAndUserId(db.NoteContentHistories, noteId, userId, history) db.UpdateByIdAndUserId(db.NoteContentHistories, noteId, userId, history)
@@ -49,7 +49,7 @@ func (this *NoteContentHistoryService) AddHistory(noteId, userId string, eachHis
// 新建历史 // 新建历史
func (this *NoteContentHistoryService) newHistory(noteId, userId string, eachHistory info.EachHistory) { func (this *NoteContentHistoryService) newHistory(noteId, userId string, eachHistory info.EachHistory) {
history := info.NoteContentHistory{NoteId: bson.ObjectIdHex(noteId), history := info.NoteContentHistory{NoteId: bson.ObjectIdHex(noteId),
UserId: bson.ObjectIdHex(userId), UserId: bson.ObjectIdHex(userId),
Histories: []info.EachHistory{eachHistory}, Histories: []info.EachHistory{eachHistory},
} }
+5 -5
View File
@@ -1,19 +1,19 @@
package service package service
import ( import (
"github.com/leanote/leanote/app/info"
"github.com/leanote/leanote/app/db" "github.com/leanote/leanote/app/db"
"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"
"regexp" "regexp"
// "time" // "time"
) )
type NoteImageService struct { type NoteImageService struct {
} }
// 通过id, userId得到noteIds // 通过id, userId得到noteIds
func (this *NoteImageService) GetNoteIds(imageId string) ([]bson.ObjectId) { func (this *NoteImageService) GetNoteIds(imageId string) []bson.ObjectId {
noteImages := []info.NoteImage{} noteImages := []info.NoteImage{}
db.ListByQWithFields(db.NoteImages, bson.M{"ImageId": bson.ObjectIdHex(imageId)}, []string{"NoteId"}, &noteImages) db.ListByQWithFields(db.NoteImages, bson.M{"ImageId": bson.ObjectIdHex(imageId)}, []string{"NoteId"}, &noteImages)
@@ -123,9 +123,9 @@ func (this *NoteImageService) CopyNoteImages(fromNoteId, fromUserId, newNoteId,
return "getImage?fileId=" + replaceFileId return "getImage?fileId=" + replaceFileId
} }
return each return each
}); })
return content; return content
} }
// //
+317 -84
View File
@@ -1,10 +1,12 @@
package service package service
import ( import (
"github.com/leanote/leanote/app/info"
"github.com/leanote/leanote/app/db" "github.com/leanote/leanote/app/db"
"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"
"regexp"
"strings"
"time" "time"
) )
@@ -17,6 +19,7 @@ func (this *NoteService) GetNote(noteId, userId string) (note info.Note) {
db.GetByIdAndUserId(db.Notes, noteId, userId, &note) db.GetByIdAndUserId(db.Notes, noteId, userId, &note)
return return
} }
// fileService调用 // fileService调用
// 不能是已经删除了的, life bug, 客户端删除后, 竟然还能在web上打开 // 不能是已经删除了的, life bug, 客户端删除后, 竟然还能在web上打开
func (this *NoteService) GetNoteById(noteId string) (note info.Note) { func (this *NoteService) GetNoteById(noteId string) (note info.Note) {
@@ -35,6 +38,7 @@ func (this *NoteService) GetNoteByIdAndUserId(noteId, userId string) (note info.
db.GetByQ(db.Notes, bson.M{"_id": bson.ObjectIdHex(noteId), "UserId": bson.ObjectIdHex(userId), "IsDeleted": false}, &note) db.GetByQ(db.Notes, bson.M{"_id": bson.ObjectIdHex(noteId), "UserId": bson.ObjectIdHex(userId), "IsDeleted": false}, &note)
return return
} }
// 得到blog, blogService用 // 得到blog, blogService用
// 不要传userId, 因为是公开的 // 不要传userId, 因为是公开的
func (this *NoteService) GetBlogNote(noteId string) (note info.Note) { func (this *NoteService) GetBlogNote(noteId string) (note info.Note) {
@@ -43,6 +47,7 @@ func (this *NoteService) GetBlogNote(noteId string) (note info.Note) {
"IsBlog": true, "IsTrash": false, "IsDeleted": false}, &note) "IsBlog": true, "IsTrash": false, "IsDeleted": false}, &note)
return return
} }
// 通过id, userId得到noteContent // 通过id, userId得到noteContent
func (this *NoteService) GetNoteContent(noteContentId, userId string) (noteContent info.NoteContent) { func (this *NoteService) GetNoteContent(noteContentId, userId string) (noteContent info.NoteContent) {
noteContent = info.NoteContent{} noteContent = info.NoteContent{}
@@ -63,8 +68,8 @@ func (this *NoteService) GetSyncNotes(userId string, afterUsn, maxEntry int) []i
notes := []info.Note{} notes := []info.Note{}
q := db.Notes.Find(bson.M{ q := db.Notes.Find(bson.M{
"UserId": bson.ObjectIdHex(userId), "UserId": bson.ObjectIdHex(userId),
"Usn": bson.M{"$gt": afterUsn}, "Usn": bson.M{"$gt": afterUsn},
}); })
q.Sort("Usn").Limit(maxEntry).All(&notes) q.Sort("Usn").Limit(maxEntry).All(&notes)
return this.ToApiNotes(notes) return this.ToApiNotes(notes)
@@ -75,7 +80,7 @@ func (this *NoteService) ToApiNotes(notes []info.Note) []info.ApiNote {
// 2, 得到所有图片, 附件信息 // 2, 得到所有图片, 附件信息
// 查images表, attachs表 // 查images表, attachs表
if len(notes) > 0 { if len(notes) > 0 {
noteIds := make([]bson.ObjectId, len(notes)); noteIds := make([]bson.ObjectId, len(notes))
for i, note := range notes { for i, note := range notes {
noteIds[i] = note.NoteId noteIds[i] = note.NoteId
} }
@@ -92,24 +97,23 @@ func (this *NoteService) ToApiNotes(notes []info.Note) []info.ApiNote {
return []info.ApiNote{} return []info.ApiNote{}
} }
// note与apiNote的转换 // note与apiNote的转换
func (this *NoteService) ToApiNote(note *info.Note, files []info.NoteFile) info.ApiNote { func (this *NoteService) ToApiNote(note *info.Note, files []info.NoteFile) info.ApiNote {
apiNote := info.ApiNote{ apiNote := info.ApiNote{
NoteId: note.NoteId.Hex(), NoteId: note.NoteId.Hex(),
NotebookId: note.NotebookId.Hex(), NotebookId: note.NotebookId.Hex(),
UserId : note.UserId.Hex(), UserId: note.UserId.Hex(),
Title : note.Title, Title: note.Title,
Tags : note.Tags, Tags: note.Tags,
IsMarkdown : note.IsMarkdown, IsMarkdown: note.IsMarkdown,
IsBlog : note.IsBlog, IsBlog: note.IsBlog,
IsTrash : note.IsTrash, IsTrash: note.IsTrash,
IsDeleted : note.IsDeleted, IsDeleted: note.IsDeleted,
Usn : note.Usn, Usn: note.Usn,
CreatedTime : note.CreatedTime, CreatedTime: note.CreatedTime,
UpdatedTime : note.UpdatedTime, UpdatedTime: note.UpdatedTime,
PublicTime : note.PublicTime, PublicTime: note.PublicTime,
Files: files, Files: files,
} }
return apiNote return apiNote
} }
@@ -121,7 +125,7 @@ func (this *NoteService) ToApiNote(note *info.Note, files []info.NoteFile) info.
// 查images表, attachs表 // 查images表, attachs表
// [待测] // [待测]
func (this *NoteService) getFiles(noteIds []bson.ObjectId) map[string][]info.NoteFile { func (this *NoteService) getFiles(noteIds []bson.ObjectId) map[string][]info.NoteFile {
noteImages := noteImageService.getImagesByNoteIds(noteIds); noteImages := noteImageService.getImagesByNoteIds(noteIds)
noteAttachs := attachService.getAttachsByNoteIds(noteIds) noteAttachs := attachService.getAttachsByNoteIds(noteIds)
noteFilesMap := map[string][]info.NoteFile{} noteFilesMap := map[string][]info.NoteFile{}
@@ -134,8 +138,8 @@ func (this *NoteService) getFiles(noteIds []bson.ObjectId) map[string][]info.Not
for _, image := range images { for _, image := range images {
noteFiles = append(noteFiles, info.NoteFile{ noteFiles = append(noteFiles, info.NoteFile{
FileId: image.FileId.Hex(), FileId: image.FileId.Hex(),
Type: image.Type, Type: image.Type,
}); })
} }
} }
@@ -143,11 +147,11 @@ func (this *NoteService) getFiles(noteIds []bson.ObjectId) map[string][]info.Not
if attachs, ok := noteAttachs[noteIdHex]; ok { if attachs, ok := noteAttachs[noteIdHex]; ok {
for _, attach := range attachs { for _, attach := range attachs {
noteFiles = append(noteFiles, info.NoteFile{ noteFiles = append(noteFiles, info.NoteFile{
FileId: attach.AttachId.Hex(), FileId: attach.AttachId.Hex(),
Type: attach.Type, Type: attach.Type,
Title: attach.Title, Title: attach.Title,
IsAttach: true, IsAttach: true,
}); })
} }
} }
@@ -160,7 +164,7 @@ func (this *NoteService) getFiles(noteIds []bson.ObjectId) map[string][]info.Not
// 列出note, 排序规则, 还有分页 // 列出note, 排序规则, 还有分页
// CreatedTime, UpdatedTime, title 来排序 // CreatedTime, UpdatedTime, title 来排序
func (this *NoteService) ListNotes(userId, notebookId string, func (this *NoteService) ListNotes(userId, notebookId string,
isTrash bool, pageNumber, pageSize int, sortField string, isAsc bool, isBlog bool) (count int, notes []info.Note) { isTrash bool, pageNumber, pageSize int, sortField string, isAsc bool, isBlog bool) (count int, notes []info.Note) {
notes = []info.Note{} notes = []info.Note{}
skipNum, sortFieldR := parsePageAndSort(pageNumber, pageSize, sortField, isAsc) skipNum, sortFieldR := parsePageAndSort(pageNumber, pageSize, sortField, isAsc)
@@ -173,7 +177,7 @@ func (this *NoteService) ListNotes(userId, notebookId string,
query["NotebookId"] = bson.ObjectIdHex(notebookId) query["NotebookId"] = bson.ObjectIdHex(notebookId)
} }
q := db.Notes.Find(query); q := db.Notes.Find(query)
// 总记录数 // 总记录数
count, _ = q.Count() count, _ = q.Count()
@@ -188,7 +192,7 @@ func (this *NoteService) ListNotes(userId, notebookId string,
// 通过noteIds来查询 // 通过noteIds来查询
// ShareService调用 // ShareService调用
func (this *NoteService) ListNotesByNoteIdsWithPageSort(noteIds []bson.ObjectId, userId string, func (this *NoteService) ListNotesByNoteIdsWithPageSort(noteIds []bson.ObjectId, userId string,
pageNumber, pageSize int, sortField string, isAsc bool, isBlog bool) (notes []info.Note) { pageNumber, pageSize int, sortField string, isAsc bool, isBlog bool) (notes []info.Note) {
skipNum, sortFieldR := parsePageAndSort(pageNumber, pageSize, sortField, isAsc) skipNum, sortFieldR := parsePageAndSort(pageNumber, pageSize, sortField, isAsc)
notes = []info.Note{} notes = []info.Note{}
@@ -201,6 +205,7 @@ func (this *NoteService) ListNotesByNoteIdsWithPageSort(noteIds []bson.ObjectId,
All(&notes) All(&notes)
return return
} }
// shareService调用 // shareService调用
func (this *NoteService) ListNotesByNoteIds(noteIds []bson.ObjectId) (notes []info.Note) { func (this *NoteService) ListNotesByNoteIds(noteIds []bson.ObjectId) (notes []info.Note) {
notes = []info.Note{} notes = []info.Note{}
@@ -210,6 +215,7 @@ func (this *NoteService) ListNotesByNoteIds(noteIds []bson.ObjectId) (notes []in
All(&notes) All(&notes)
return return
} }
// blog需要 // blog需要
func (this *NoteService) ListNoteContentsByNoteIds(noteIds []bson.ObjectId) (notes []info.NoteContent) { func (this *NoteService) ListNoteContentsByNoteIds(noteIds []bson.ObjectId) (notes []info.NoteContent) {
notes = []info.NoteContent{} notes = []info.NoteContent{}
@@ -219,6 +225,7 @@ func (this *NoteService) ListNoteContentsByNoteIds(noteIds []bson.ObjectId) (not
All(&notes) All(&notes)
return return
} }
// 只得到abstract, 不需要content // 只得到abstract, 不需要content
func (this *NoteService) ListNoteAbstractsByNoteIds(noteIds []bson.ObjectId) (notes []info.NoteContent) { func (this *NoteService) ListNoteAbstractsByNoteIds(noteIds []bson.ObjectId) (notes []info.NoteContent) {
notes = []info.NoteContent{} notes = []info.NoteContent{}
@@ -236,15 +243,18 @@ func (this *NoteService) ListNoteContentByNoteIds(noteIds []bson.ObjectId) (note
// [ok] // [ok]
func (this *NoteService) AddNote(note info.Note, fromApi bool) info.Note { func (this *NoteService) AddNote(note info.Note, fromApi bool) info.Note {
if(note.NoteId.Hex() == "") { if note.NoteId.Hex() == "" {
noteId := bson.NewObjectId(); noteId := bson.NewObjectId()
note.NoteId = noteId; note.NoteId = noteId
} }
note.CreatedTime = time.Now()
note.UpdatedTime = note.CreatedTime // 关于创建时间, 可能是客户端发来, 此时判断时间是否有
note.CreatedTime = FixUrlTime(note.CreatedTime)
note.UpdatedTime = FixUrlTime(note.UpdatedTime)
note.IsTrash = false note.IsTrash = false
note.UpdatedUserId = note.UserId note.UpdatedUserId = note.UserId
note.UrlTitle = GetUrTitle(note.UserId.Hex(), note.Title, "note") note.UrlTitle = GetUrTitle(note.UserId.Hex(), note.Title, "note", note.NoteId.Hex())
note.Usn = userService.IncrUsn(note.UserId.Hex()) note.Usn = userService.IncrUsn(note.UserId.Hex())
notebookId := note.NotebookId.Hex() notebookId := note.NotebookId.Hex()
@@ -254,9 +264,9 @@ func (this *NoteService) AddNote(note info.Note, fromApi bool) info.Note {
// 设为blog // 设为blog
note.IsBlog = notebookService.IsBlog(notebookId) note.IsBlog = notebookService.IsBlog(notebookId)
} }
// if note.IsBlog { // if note.IsBlog {
note.PublicTime = note.UpdatedTime note.PublicTime = note.UpdatedTime
// } // }
db.Insert(db.Notes, note) db.Insert(db.Notes, note)
@@ -279,19 +289,20 @@ func (this *NoteService) AddSharedNote(note info.Note, myUserId bson.ObjectId) i
return info.Note{} return info.Note{}
} }
// 添加笔记本内容 // 添加笔记本内容
// [ok] // [ok]
func (this *NoteService) AddNoteContent(noteContent info.NoteContent) info.NoteContent { func (this *NoteService) AddNoteContent(noteContent info.NoteContent) info.NoteContent {
noteContent.CreatedTime = time.Now()
noteContent.UpdatedTime = noteContent.CreatedTime noteContent.CreatedTime = FixUrlTime(noteContent.CreatedTime)
noteContent.UpdatedTime = FixUrlTime(noteContent.UpdatedTime)
noteContent.UpdatedUserId = noteContent.UserId noteContent.UpdatedUserId = noteContent.UserId
db.Insert(db.NoteContents, noteContent) db.Insert(db.NoteContents, noteContent)
// 更新笔记图片 // 更新笔记图片
noteImageService.UpdateNoteImages(noteContent.UserId.Hex(), noteContent.NoteId.Hex(), "", noteContent.Content) noteImageService.UpdateNoteImages(noteContent.UserId.Hex(), noteContent.NoteId.Hex(), "", noteContent.Content)
return noteContent; return noteContent
} }
// API, abstract, desc需要这里获取 // API, abstract, desc需要这里获取
@@ -348,15 +359,15 @@ func (this *NoteService) AddNoteAndContentForController(note info.Note, noteCont
Log("HAS AUTH -----------") Log("HAS AUTH -----------")
} }
} }
return this.AddNoteAndContent(note, noteContent, bson.ObjectIdHex(updatedUserId)); return this.AddNoteAndContent(note, noteContent, bson.ObjectIdHex(updatedUserId))
} }
func (this *NoteService) AddNoteAndContent(note info.Note, noteContent info.NoteContent, myUserId bson.ObjectId) info.Note { func (this *NoteService) AddNoteAndContent(note info.Note, noteContent info.NoteContent, myUserId bson.ObjectId) info.Note {
if(note.NoteId.Hex() == "") { if note.NoteId.Hex() == "" {
noteId := bson.NewObjectId() noteId := bson.NewObjectId()
note.NoteId = noteId note.NoteId = noteId
} }
noteContent.NoteId = note.NoteId noteContent.NoteId = note.NoteId
if note.UserId != myUserId { if note.UserId != myUserId {
note = this.AddSharedNote(note, myUserId) note = this.AddSharedNote(note, myUserId)
} else { } else {
note = this.AddNote(note, false) note = this.AddNote(note, false)
@@ -368,12 +379,12 @@ func (this *NoteService) AddNoteAndContent(note info.Note, noteContent info.Note
} }
func (this *NoteService) AddNoteAndContentApi(note info.Note, noteContent info.NoteContent, myUserId bson.ObjectId) info.Note { func (this *NoteService) AddNoteAndContentApi(note info.Note, noteContent info.NoteContent, myUserId bson.ObjectId) info.Note {
if(note.NoteId.Hex() == "") { if note.NoteId.Hex() == "" {
noteId := bson.NewObjectId() noteId := bson.NewObjectId()
note.NoteId = noteId note.NoteId = noteId
} }
noteContent.NoteId = note.NoteId noteContent.NoteId = note.NoteId
if note.UserId != myUserId { if note.UserId != myUserId {
note = this.AddSharedNote(note, myUserId) note = this.AddSharedNote(note, myUserId)
} else { } else {
note = this.AddNote(note, true) note = this.AddNote(note, true)
@@ -404,7 +415,7 @@ func (this *NoteService) UpdateNote(updatedUserId, noteId string, needUpdate bso
} }
} }
if usn > 0 && note.Usn != usn { if usn > 0 && note.Usn != usn {
return false, "conflict", 0 return false, "conflict", 0
} }
@@ -414,36 +425,60 @@ func (this *NoteService) UpdateNote(updatedUserId, noteId string, needUpdate bso
delete(needUpdate, "Desc") delete(needUpdate, "Desc")
} }
needUpdate["UpdatedUserId"] = bson.ObjectIdHex(updatedUserId); needUpdate["UpdatedUserId"] = bson.ObjectIdHex(updatedUserId)
needUpdate["UpdatedTime"] = time.Now();
afterUsn := userService.IncrUsn(userId); // 可以将时间传过来
updatedTime, ok := needUpdate["UpdatedTime"].(time.Time)
if ok {
needUpdate["UpdatedTime"] = FixUrlTime(updatedTime)
} else {
needUpdate["UpdatedTime"] = time.Now()
}
afterUsn := userService.IncrUsn(userId)
needUpdate["Usn"] = afterUsn needUpdate["Usn"] = afterUsn
// 添加tag2 needRecountTags := false
// TODO 这个tag去掉, 添加tag另外添加, 不要这个
if tags, ok := needUpdate["Tags"]; ok {
tagService.AddTagsI(userId, tags)
}
// 是否修改了isBlog // 是否修改了isBlog
// 也要修改noteContents的IsBlog // 也要修改noteContents的IsBlog
if isBlog, ok := needUpdate["IsBlog"]; ok { if isBlog, ok := needUpdate["IsBlog"]; ok {
isBlog2 := isBlog.(bool) isBlog2 := isBlog.(bool)
if note.IsBlog != isBlog2 { if note.IsBlog != isBlog2 {
this.UpdateNoteContentIsBlog(noteId, userId, isBlog2); this.UpdateNoteContentIsBlog(noteId, userId, isBlog2)
// 重新发布成博客 // 重新发布成博客
if !note.IsBlog { if !note.IsBlog {
needUpdate["PublicTime"] = needUpdate["UpdatedTime"] needUpdate["PublicTime"] = needUpdate["UpdatedTime"]
} }
needRecountTags = true
} }
} }
ok := db.UpdateByIdAndUserIdMap(db.Notes, noteId, userId, needUpdate) // 添加tag2
// TODO 这个tag去掉, 添加tag另外添加, 不要这个
if tags, ok := needUpdate["Tags"]; ok {
tagService.AddTagsI(userId, tags)
// 如果是博客, 标签改了, 那么重新计算
if note.IsBlog {
needRecountTags = true
}
}
ok = db.UpdateByIdAndUserIdMap(db.Notes, noteId, userId, needUpdate)
if !ok { if !ok {
return ok, "", 0 return ok, "", 0
} }
if needRecountTags {
// 重新计算tags
go (func() {
blogService.ReCountBlogTags(userId)
})()
}
// 重新获取之 // 重新获取之
note = this.GetNoteById(noteId) note = this.GetNoteById(noteId)
@@ -456,14 +491,19 @@ func (this *NoteService) UpdateNote(updatedUserId, noteId string, needUpdate bso
notebookId := notebookIdI.(bson.ObjectId) notebookId := notebookIdI.(bson.ObjectId)
if notebookId != "" { if notebookId != "" {
notebookService.ReCountNotebookNumberNotes(note.NotebookId.Hex()) notebookService.ReCountNotebookNumberNotes(note.NotebookId.Hex())
hasRecount = true
notebookService.ReCountNotebookNumberNotes(notebookId.Hex()) notebookService.ReCountNotebookNumberNotes(notebookId.Hex())
hasRecount = true
} }
} }
// 不要多次更新, isTrash = false, = true都要重新统计 // 不要多次更新, isTrash = false, = true都要重新统计
if !hasRecount { if isTrashI, ok := needUpdate["IsTrash"]; ok {
if _, ok := needUpdate["IsTrash"]; ok { // 如果是垃圾, 则删除之共享
isTrash := isTrashI.(bool)
if isTrash {
shareService.DeleteShareNoteAll(noteId, userId)
}
if !hasRecount {
notebookService.ReCountNotebookNumberNotes(note.NotebookId.Hex()) notebookService.ReCountNotebookNumberNotes(note.NotebookId.Hex())
} }
} }
@@ -503,7 +543,9 @@ func (this *NoteService) UpdateNoteTitle(userId, updatedUserId, noteId, title st
// [ok] TODO perm未测 // [ok] TODO perm未测
// hasBeforeUpdateNote 之前是否更新过note其它信息, 如果有更新, usn不用更新 // hasBeforeUpdateNote 之前是否更新过note其它信息, 如果有更新, usn不用更新
// TODO abstract这里生成 // TODO abstract这里生成
func (this *NoteService) UpdateNoteContent(updatedUserId, noteId, content, abstract string, hasBeforeUpdateNote bool, usn int) (bool, string, int) { func (this *NoteService) UpdateNoteContent(updatedUserId, noteId, content, abstract string,
hasBeforeUpdateNote bool,
usn int, updatedTime time.Time) (bool, string, int) {
// 是否已自定义 // 是否已自定义
note := this.GetNoteById(noteId) note := this.GetNoteById(noteId)
if note.NoteId == "" { if note.NoteId == "" {
@@ -518,11 +560,13 @@ func (this *NoteService) UpdateNoteContent(updatedUserId, noteId, content, abstr
} }
} }
updatedTime = FixUrlTime(updatedTime)
// abstract重置 // abstract重置
data := bson.M{"UpdatedUserId": bson.ObjectIdHex(updatedUserId), data := bson.M{"UpdatedUserId": bson.ObjectIdHex(updatedUserId),
"Content": content, "Content": content,
"Abstract": abstract, "Abstract": abstract,
"UpdatedTime": time.Now()} "UpdatedTime": updatedTime}
if note.IsBlog && note.HasSelfDefined { if note.IsBlog && note.HasSelfDefined {
delete(data, "Abstract") delete(data, "Abstract")
@@ -543,7 +587,7 @@ func (this *NoteService) UpdateNoteContent(updatedUserId, noteId, content, abstr
if db.UpdateByIdAndUserIdMap(db.NoteContents, noteId, userId, data) { if db.UpdateByIdAndUserIdMap(db.NoteContents, noteId, userId, data) {
// 这里, 添加历史记录 // 这里, 添加历史记录
noteContentHistoryService.AddHistory(noteId, userId, info.EachHistory{UpdatedUserId: bson.ObjectIdHex(updatedUserId), noteContentHistoryService.AddHistory(noteId, userId, info.EachHistory{UpdatedUserId: bson.ObjectIdHex(updatedUserId),
Content: content, Content: content,
UpdatedTime: time.Now(), UpdatedTime: time.Now(),
}) })
@@ -589,7 +633,7 @@ func (this *NoteService) ToBlog(userId, noteId string, isBlog, isTop bool) bool
ok := db.UpdateByIdAndUserIdMap(db.Notes, noteId, userId, noteUpdate) ok := db.UpdateByIdAndUserIdMap(db.Notes, noteId, userId, noteUpdate)
// 重新计算tags // 重新计算tags
go (func() { go (func() {
this.UpdateNoteContentIsBlog(noteId, userId, isBlog); this.UpdateNoteContentIsBlog(noteId, userId, isBlog)
blogService.ReCountBlogTags(userId) blogService.ReCountBlogTags(userId)
})() })()
@@ -608,8 +652,8 @@ func (this *NoteService) MoveNote(noteId, notebookId, userId string) info.Note {
re := db.UpdateByIdAndUserId(db.Notes, noteId, userId, re := db.UpdateByIdAndUserId(db.Notes, noteId, userId,
bson.M{"$set": bson.M{"IsTrash": false, bson.M{"$set": bson.M{"IsTrash": false,
"NotebookId": bson.ObjectIdHex(notebookId), "NotebookId": bson.ObjectIdHex(notebookId),
"Usn": userService.IncrUsn(userId), "Usn": userService.IncrUsn(userId),
}}) }})
if re { if re {
// 更新blog状态 // 更新blog状态
@@ -623,7 +667,7 @@ func (this *NoteService) MoveNote(noteId, notebookId, userId string) info.Note {
} }
} }
return this.GetNote(noteId, userId); return this.GetNote(noteId, userId)
} }
return info.Note{} return info.Note{}
} }
@@ -643,10 +687,11 @@ func (this *NoteService) updateToNotebookBlog(noteId, notebookId, userId string)
} }
return false return false
} }
// 判断是否是blog // 判断是否是blog
func (this *NoteService) IsBlog(noteId string) bool { func (this *NoteService) IsBlog(noteId string) bool {
note := info.Note{} note := info.Note{}
db.GetByQWithFields(db.Notes, bson.M{"_id": bson.ObjectIdHex(noteId)}, []string{"IsBlog"}, &note); db.GetByQWithFields(db.Notes, bson.M{"_id": bson.ObjectIdHex(noteId)}, []string{"IsBlog"}, &note)
return note.IsBlog return note.IsBlog
} }
@@ -660,11 +705,11 @@ func (this *NoteService) CopyNote(noteId, notebookId, userId string) info.Note {
noteContent := this.GetNoteContent(noteId, userId) noteContent := this.GetNoteContent(noteId, userId)
// 重新生成noteId // 重新生成noteId
note.NoteId = bson.NewObjectId(); note.NoteId = bson.NewObjectId()
note.NotebookId = bson.ObjectIdHex(notebookId) note.NotebookId = bson.ObjectIdHex(notebookId)
noteContent.NoteId = note.NoteId noteContent.NoteId = note.NoteId
note = this.AddNoteAndContent(note, noteContent, note.UserId); note = this.AddNoteAndContent(note, noteContent, note.UserId)
// 更新blog状态 // 更新blog状态
isBlog := this.updateToNotebookBlog(note.NoteId.Hex(), notebookId, userId) isBlog := this.updateToNotebookBlog(note.NoteId.Hex(), notebookId, userId)
@@ -693,7 +738,7 @@ func (this *NoteService) CopySharedNote(noteId, notebookId, fromUserId, myUserId
noteContent := this.GetNoteContent(noteId, fromUserId) noteContent := this.GetNoteContent(noteId, fromUserId)
// 重新生成noteId // 重新生成noteId
note.NoteId = bson.NewObjectId(); note.NoteId = bson.NewObjectId()
note.NotebookId = bson.ObjectIdHex(notebookId) note.NotebookId = bson.ObjectIdHex(notebookId)
note.UserId = bson.ObjectIdHex(myUserId) note.UserId = bson.ObjectIdHex(myUserId)
note.IsTop = false note.IsTop = false
@@ -712,7 +757,7 @@ func (this *NoteService) CopySharedNote(noteId, notebookId, fromUserId, myUserId
attachService.CopyAttachs(noteId, note.NoteId.Hex(), myUserId) attachService.CopyAttachs(noteId, note.NoteId.Hex(), myUserId)
// 添加之 // 添加之
note = this.AddNoteAndContent(note, noteContent, note.UserId); note = this.AddNoteAndContent(note, noteContent, note.UserId)
// 更新blog状态 // 更新blog状态
isBlog := this.updateToNotebookBlog(note.NoteId.Hex(), notebookId, myUserId) isBlog := this.updateToNotebookBlog(note.NoteId.Hex(), notebookId, myUserId)
@@ -751,14 +796,14 @@ func (this *NoteService) SearchNote(key, userId string, pageNumber, pageSize int
} }
// 不是trash的 // 不是trash的
query := bson.M{"UserId": bson.ObjectIdHex(userId), query := bson.M{"UserId": bson.ObjectIdHex(userId),
"IsTrash": false, "IsTrash": false,
"IsDeleted": false, // 不能搜索已删除了的 "IsDeleted": false, // 不能搜索已删除了的
"$or": orQ, "$or": orQ,
} }
if isBlog { if isBlog {
query["IsBlog"] = true query["IsBlog"] = true
} }
q := db.Notes.Find(query); q := db.Notes.Find(query)
// 总记录数 // 总记录数
count, _ = q.Count() count, _ = q.Count()
@@ -783,7 +828,11 @@ func (this *NoteService) searchNoteFromContent(notes []info.Note, userId, key st
noteIds[i] = note.NoteId noteIds[i] = note.NoteId
} }
noteContents := []info.NoteContent{} noteContents := []info.NoteContent{}
query := bson.M{"_id": bson.M{"$nin": noteIds}, "UserId": bson.ObjectIdHex(userId), "Content": bson.M{"$regex": bson.RegEx{".*?" + key + ".*", "i"}}} query := bson.M{
"_id": bson.M{"$nin": noteIds},
"UserId": bson.ObjectIdHex(userId),
"Content": bson.M{"$regex": bson.RegEx{".*?" + key + ".*", "i"}},
}
if isBlog { if isBlog {
query["IsBlog"] = true query["IsBlog"] = true
} }
@@ -794,7 +843,7 @@ func (this *NoteService) searchNoteFromContent(notes []info.Note, userId, key st
Select(bson.M{"_id": true}). Select(bson.M{"_id": true}).
All(&noteContents) All(&noteContents)
var lenContent = len(noteContents) var lenContent = len(noteContents)
if(lenContent == 0) { if lenContent == 0 {
return notes return notes
} }
@@ -821,9 +870,9 @@ func (this *NoteService) SearchNoteByTags(tags []string, userId string, pageNumb
// 不是trash的 // 不是trash的
query := bson.M{"UserId": bson.ObjectIdHex(userId), query := bson.M{"UserId": bson.ObjectIdHex(userId),
"IsTrash": false, "IsTrash": false,
"Tags": bson.M{"$all": tags}} "Tags": bson.M{"$all": tags}}
q := db.Notes.Find(query); q := db.Notes.Find(query)
// 总记录数 // 总记录数
count, _ = q.Count() count, _ = q.Count()
@@ -858,9 +907,9 @@ func (this *NoteService) CountNoteByTag(userId string, tag string) int {
return 0 return 0
} }
query := bson.M{"UserId": bson.ObjectIdHex(userId), query := bson.M{"UserId": bson.ObjectIdHex(userId),
// "IsTrash": false, // "IsTrash": false,
"IsDeleted": false, "IsDeleted": false,
"Tags": bson.M{"$in": []string{tag}}} "Tags": bson.M{"$in": []string{tag}}}
return db.Count(db.Notes, query) return db.Count(db.Notes, query)
} }
@@ -881,7 +930,7 @@ func (this *NoteService) UpdateNoteToDeleteTag(userId string, targetTag string)
if tag == targetTag { if tag == targetTag {
tags = tags tags = tags
tags = append(tags[:i], tags[i+1:]...) tags = append(tags[:i], tags[i+1:]...)
break; break
} }
} }
usn := userService.IncrUsn(userId) usn := userService.IncrUsn(userId)
@@ -890,3 +939,187 @@ func (this *NoteService) UpdateNoteToDeleteTag(userId string, targetTag string)
} }
return ret return ret
} }
// api
// 得到笔记的内容, 此时将笔记内的链接转成标准的Leanote Url
// 将笔记的图片, 附件链接转换成 site.url/file/getImage?fileId=xxx, site.url/file/getAttach?fileId=xxxx
func (this *NoteService) FixContentBad(content string, isMarkdown bool) string {
baseUrl := configService.GetSiteUrl()
baseUrlPattern := baseUrl
// 避免https的url
if baseUrl[0:8] == "https://" {
baseUrlPattern = strings.Replace(baseUrl, "https://", "https*://", 1)
} else {
baseUrlPattern = strings.Replace(baseUrl, "http://", "https*://", 1)
}
patterns := []map[string]string{
map[string]string{"src": "src", "middle": "/file/outputImage", "param": "fileId", "to": "getImage?fileId="},
map[string]string{"src": "href", "middle": "/attach/download", "param": "attachId", "to": "getAttach?fileId="},
// 该链接已失效, 不再支持
map[string]string{"src": "href", "middle": "/attach/downloadAll", "param": "noteId", "to": "getAllAttachs?noteId="},
}
for _, eachPattern := range patterns {
if !isMarkdown {
// 富文本处理
// <img src="http://leanote.com/file/outputImage?fileId=5503537b38f4111dcb0000d1">
// <a href="http://leanote.com/attach/download?attachId=5504243a38f4111dcb00017d"></a>
var reg *regexp.Regexp
if eachPattern["src"] == "src" {
reg, _ = regexp.Compile("<img(?:[^>]+?)(" + eachPattern["src"] + `=['"]*` + baseUrlPattern + eachPattern["middle"] + `\?` + eachPattern["param"] + `=([a-z0-9A-Z]{24})["']*)[^>]*>`)
} else {
reg, _ = regexp.Compile("<a(?:[^>]+?)(" + eachPattern["src"] + `=['"]*` + baseUrlPattern + eachPattern["middle"] + `\?` + eachPattern["param"] + `=([a-z0-9A-Z]{24})["']*)[^>]*>`)
}
finds := reg.FindAllStringSubmatch(content, -1) // 查找所有的
for _, eachFind := range finds {
if len(eachFind) == 3 {
// 这一行会非常慢!, content是全部的内容, 多次replace导致
content = strings.Replace(content,
eachFind[1],
eachPattern["src"]+"=\""+baseUrl+"/api/file/"+eachPattern["to"]+eachFind[2]+"\"",
1)
}
}
} else {
// markdown处理
// ![](http://leanote.com/file/outputImage?fileId=5503537b38f4111dcb0000d1)
// [selection 2.html](http://leanote.com/attach/download?attachId=5504262638f4111dcb00017f)
// [all.tar.gz](http://leanote.com/attach/downloadAll?noteId=5503b57d59f81b4eb4000000)
pre := "!" // 默认图片
if eachPattern["src"] == "href" { // 是attach
pre = ""
}
regImageMarkdown, _ := regexp.Compile(pre + `\[([^]]*?)\]\(` + baseUrlPattern + eachPattern["middle"] + `\?` + eachPattern["param"] + `=([a-z0-9A-Z]{24})\)`)
findsImageMarkdown := regImageMarkdown.FindAllStringSubmatch(content, -1) // 查找所有的
// [[![](http://leanote.com/file/outputImage?fileId=5503537b38f4111dcb0000d1) 5503537b38f4111dcb0000d1] [![你好啊, 我很好, 为什么?](http://leanote.com/file/outputImage?fileId=5503537b38f4111dcb0000d1) 5503537b38f4111dcb0000d1]]
for _, eachFind := range findsImageMarkdown {
// [![你好啊, 我很好, 为什么?](http://leanote.com/file/outputImage?fileId=5503537b38f4111dcb0000d1) 你好啊, 我很好, 为什么? 5503537b38f4111dcb0000d1]
if len(eachFind) == 3 {
content = strings.Replace(content, eachFind[0], pre+"["+eachFind[1]+"]("+baseUrl+"/api/file/"+eachPattern["to"]+eachFind[2]+")", 1)
}
}
}
}
return content
}
// 性能更好, 5倍的差距
func (this *NoteService) FixContent(content string, isMarkdown bool) string {
baseUrl := configService.GetSiteUrl()
baseUrlPattern := baseUrl
// 避免https的url
if baseUrl[0:8] == "https://" {
baseUrlPattern = strings.Replace(baseUrl, "https://", "https*://", 1)
} else {
baseUrlPattern = strings.Replace(baseUrl, "http://", "https*://", 1)
}
patterns := []map[string]string{
map[string]string{"src": "src", "middle": "/file/outputImage", "param": "fileId", "to": "getImage?fileId="},
map[string]string{"src": "href", "middle": "/attach/download", "param": "attachId", "to": "getAttach?fileId="},
// 该链接已失效, 不再支持
map[string]string{"src": "href", "middle": "/attach/downloadAll", "param": "noteId", "to": "getAllAttachs?noteId="},
}
for _, eachPattern := range patterns {
if !isMarkdown {
// 富文本处理
// <img src="http://leanote.com/file/outputImage?fileId=5503537b38f4111dcb0000d1">
// <a href="http://leanote.com/attach/download?attachId=5504243a38f4111dcb00017d"></a>
var reg *regexp.Regexp
var reg2 *regexp.Regexp
if eachPattern["src"] == "src" {
reg, _ = regexp.Compile("<img(?:[^>]+?)(?:" + eachPattern["src"] + `=['"]*` + baseUrlPattern + eachPattern["middle"] + `\?` + eachPattern["param"] + `=(?:[a-z0-9A-Z]{24})["']*)[^>]*>`)
reg2, _ = regexp.Compile("<img(?:[^>]+?)(" + eachPattern["src"] + `=['"]*` + baseUrlPattern + eachPattern["middle"] + `\?` + eachPattern["param"] + `=([a-z0-9A-Z]{24})["']*)[^>]*>`)
} else {
reg, _ = 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})["']*)[^>]*>`)
}
content = reg.ReplaceAllStringFunc(content, func(str string) string {
// str=这样的
// <img src="http://localhost:9000/file/outputImage?fileId=563d706e99c37b48e0000001" alt="" data-mce-src="http://localhost:9000/file/outputImage?fileId=563d706e99c37b48e0000002">
eachFind := reg2.FindStringSubmatch(str)
str = strings.Replace(str,
eachFind[1],
eachPattern["src"]+"=\""+baseUrl+"/api/file/"+eachPattern["to"]+eachFind[2]+"\"",
1)
// fmt.Println(str)
return str
})
/*
finds := reg.FindAllStringSubmatch(content, -1) // 查找所有的
for _, eachFind := range finds {
if len(eachFind) == 3 {
// 这一行会非常慢!, content是全部的内容, 多次replace导致
content = strings.Replace(content,
eachFind[1],
eachPattern["src"]+"=\""+baseUrl+"/api/file/"+eachPattern["to"]+eachFind[2]+"\"",
1)
}
}
*/
} else {
// markdown处理
// ![](http://leanote.com/file/outputImage?fileId=5503537b38f4111dcb0000d1)
// [selection 2.html](http://leanote.com/attach/download?attachId=5504262638f4111dcb00017f)
// [all.tar.gz](http://leanote.com/attach/downloadAll?noteId=5503b57d59f81b4eb4000000)
pre := "!" // 默认图片
if eachPattern["src"] == "href" { // 是attach
pre = ""
}
regImageMarkdown, _ := regexp.Compile(pre + `\[(?:[^]]*?)\]\(` + baseUrlPattern + eachPattern["middle"] + `\?` + eachPattern["param"] + `=(?:[a-z0-9A-Z]{24})\)`)
regImageMarkdown2, _ := regexp.Compile(pre + `\[([^]]*?)\]\(` + baseUrlPattern + eachPattern["middle"] + `\?` + eachPattern["param"] + `=([a-z0-9A-Z]{24})\)`)
content = regImageMarkdown.ReplaceAllStringFunc(content, func(str string) string {
// str=这样的
// <img src="http://localhost:9000/file/outputImage?fileId=563d706e99c37b48e0000001" alt="" data-mce-src="http://localhost:9000/file/outputImage?fileId=563d706e99c37b48e0000002">
eachFind := regImageMarkdown2.FindStringSubmatch(str)
str = strings.Replace(str, eachFind[0], pre+"["+eachFind[1]+"]("+baseUrl+"/api/file/"+eachPattern["to"]+eachFind[2]+")", 1)
// fmt.Println(str)
return str
})
/*
findsImageMarkdown := regImageMarkdown.FindAllStringSubmatch(content, -1) // 查找所有的
// [[![](http://leanote.com/file/outputImage?fileId=5503537b38f4111dcb0000d1) 5503537b38f4111dcb0000d1] [![你好啊, 我很好, 为什么?](http://leanote.com/file/outputImage?fileId=5503537b38f4111dcb0000d1) 5503537b38f4111dcb0000d1]]
for _, eachFind := range findsImageMarkdown {
// [![你好啊, 我很好, 为什么?](http://leanote.com/file/outputImage?fileId=5503537b38f4111dcb0000d1) 你好啊, 我很好, 为什么? 5503537b38f4111dcb0000d1]
if len(eachFind) == 3 {
content = strings.Replace(content, eachFind[0], pre+"["+eachFind[1]+"]("+baseUrl+"/api/file/"+eachPattern["to"]+eachFind[2]+")", 1)
}
}
*/
}
}
return content
}
+42 -37
View File
@@ -1,15 +1,15 @@
package service package service
import ( import (
// "fmt" // "fmt"
"gopkg.in/mgo.v2/bson"
"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"
"sort" "sort"
"time"
"strings" "strings"
// "html" "time"
// "html"
) )
// 笔记本 // 笔记本
@@ -42,8 +42,8 @@ func ParseAndSortNotebooks(userNotebooks []info.Notebook, noParentDelete, needSo
for _, each := range userNotebooks { for _, each := range userNotebooks {
newNotebooks := info.Notebooks{Subs: info.SubNotebooks{}} newNotebooks := info.Notebooks{Subs: info.SubNotebooks{}}
newNotebooks.NotebookId = each.NotebookId newNotebooks.NotebookId = each.NotebookId
newNotebooks.Title = each.Title; newNotebooks.Title = each.Title
// newNotebooks.Title = html.EscapeString(each.Title) // newNotebooks.Title = html.EscapeString(each.Title)
newNotebooks.Title = strings.Replace(strings.Replace(each.Title, "<script>", "", -1), "</script", "", -1) newNotebooks.Title = strings.Replace(strings.Replace(each.Title, "<script>", "", -1), "</script", "", -1)
newNotebooks.Seq = each.Seq newNotebooks.Seq = each.Seq
newNotebooks.UserId = each.UserId newNotebooks.UserId = each.UserId
@@ -116,9 +116,9 @@ func (this *NotebookService) GetNotebookByUserIdAndUrlTitle(userId, notebookIdOr
} }
// 同步的方法 // 同步的方法
func (this *NotebookService) GeSyncNotebooks(userId string, afterUsn, maxEntry int) ([]info.Notebook) { func (this *NotebookService) GeSyncNotebooks(userId string, afterUsn, maxEntry int) []info.Notebook {
notebooks := []info.Notebook{} notebooks := []info.Notebook{}
q := db.Notebooks.Find(bson.M{"UserId": bson.ObjectIdHex(userId), "Usn": bson.M{"$gt": afterUsn}}); q := db.Notebooks.Find(bson.M{"UserId": bson.ObjectIdHex(userId), "Usn": bson.M{"$gt": afterUsn}})
q.Sort("Usn").Limit(maxEntry).All(&notebooks) q.Sort("Usn").Limit(maxEntry).All(&notebooks)
return notebooks return notebooks
} }
@@ -156,9 +156,13 @@ func (this *NotebookService) GetNotebooksByNotebookIds(notebookIds []bson.Object
} }
// 添加 // 添加
// [ok]
func (this *NotebookService) AddNotebook(notebook info.Notebook) (bool, info.Notebook) { func (this *NotebookService) AddNotebook(notebook info.Notebook) (bool, info.Notebook) {
notebook.UrlTitle = GetUrTitle(notebook.UserId.Hex(), notebook.Title, "notebook")
if notebook.NotebookId == "" {
notebook.NotebookId = bson.NewObjectId()
}
notebook.UrlTitle = GetUrTitle(notebook.UserId.Hex(), notebook.Title, "notebook", notebook.NotebookId.Hex())
notebook.Usn = userService.IncrUsn(notebook.UserId.Hex()) notebook.Usn = userService.IncrUsn(notebook.UserId.Hex())
now := time.Now() now := time.Now()
notebook.CreatedTime = now notebook.CreatedTime = now
@@ -169,6 +173,7 @@ func (this *NotebookService) AddNotebook(notebook info.Notebook) (bool, info.Not
} }
return true, notebook return true, notebook
} }
// 更新笔记, api // 更新笔记, api
func (this *NotebookService) UpdateNotebookApi(userId, notebookId, title, parentNotebookId string, seq, usn int) (bool, string, info.Notebook) { func (this *NotebookService) UpdateNotebookApi(userId, notebookId, title, parentNotebookId string, seq, usn int) (bool, string, info.Notebook) {
if notebookId == "" { if notebookId == "" {
@@ -183,16 +188,16 @@ func (this *NotebookService) UpdateNotebookApi(userId, notebookId, title, parent
} else if notebook.Usn != usn { } else if notebook.Usn != usn {
return false, "conflict", notebook return false, "conflict", notebook
} }
notebook.Usn = userService.IncrUsn(userId); notebook.Usn = userService.IncrUsn(userId)
notebook.Title = title; notebook.Title = title
updates := bson.M{"Title": title, "Usn": notebook.Usn, "Seq": seq, "UpdatedTime": time.Now()}; updates := bson.M{"Title": title, "Usn": notebook.Usn, "Seq": seq, "UpdatedTime": time.Now()}
if(parentNotebookId != "" && bson.IsObjectIdHex(parentNotebookId)) { if parentNotebookId != "" && bson.IsObjectIdHex(parentNotebookId) {
updates["ParentNotebookId"] = bson.ObjectIdHex(parentNotebookId); updates["ParentNotebookId"] = bson.ObjectIdHex(parentNotebookId)
} else { } else {
updates["ParentNotebookId"] = ""; updates["ParentNotebookId"] = ""
} }
ok := db.UpdateByIdAndUserIdMap(db.Notebooks, notebookId, userId, updates); ok := db.UpdateByIdAndUserIdMap(db.Notebooks, notebookId, userId, updates)
if ok { if ok {
return ok, "", this.GetNotebookById(notebookId) return ok, "", this.GetNotebookById(notebookId)
} }
@@ -202,7 +207,7 @@ func (this *NotebookService) UpdateNotebookApi(userId, notebookId, title, parent
// 判断是否是blog // 判断是否是blog
func (this *NotebookService) IsBlog(notebookId string) bool { func (this *NotebookService) IsBlog(notebookId string) bool {
notebook := info.Notebook{} notebook := info.Notebook{}
db.GetByQWithFields(db.Notebooks, bson.M{"_id": bson.ObjectIdHex(notebookId)}, []string{"IsBlog"}, &notebook); db.GetByQWithFields(db.Notebooks, bson.M{"_id": bson.ObjectIdHex(notebookId)}, []string{"IsBlog"}, &notebook)
return notebook.IsBlog return notebook.IsBlog
} }
@@ -228,20 +233,20 @@ func (this *NotebookService) UpdateNotebookTitle(notebookId, userId, title strin
// 更新notebook // 更新notebook
func (this *NotebookService) UpdateNotebook(userId, notebookId string, needUpdate bson.M) bool { func (this *NotebookService) UpdateNotebook(userId, notebookId string, needUpdate bson.M) bool {
needUpdate["UpdatedTime"] = time.Now(); needUpdate["UpdatedTime"] = time.Now()
needUpdate["Usn"] = userService.IncrUsn(userId) needUpdate["Usn"] = userService.IncrUsn(userId)
return db.UpdateByIdAndUserIdMap(db.Notebooks, notebookId, userId, needUpdate) return db.UpdateByIdAndUserIdMap(db.Notebooks, notebookId, userId, needUpdate)
} }
// ToBlog or Not // ToBlog or Not
func (this *NotebookService) ToBlog(userId, notebookId string, isBlog bool) (bool) { func (this *NotebookService) ToBlog(userId, notebookId string, isBlog bool) bool {
updates := bson.M{"IsBlog": isBlog, "Usn": userService.IncrUsn(userId)} updates := bson.M{"IsBlog": isBlog, "Usn": userService.IncrUsn(userId)}
// 笔记本 // 笔记本
db.UpdateByIdAndUserIdMap(db.Notebooks, notebookId, userId, updates) db.UpdateByIdAndUserIdMap(db.Notebooks, notebookId, userId, updates)
// 更新笔记 // 更新笔记
q := bson.M{"UserId": bson.ObjectIdHex(userId), q := bson.M{"UserId": bson.ObjectIdHex(userId),
"NotebookId": bson.ObjectIdHex(notebookId)} "NotebookId": bson.ObjectIdHex(notebookId)}
data := bson.M{"IsBlog": isBlog} data := bson.M{"IsBlog": isBlog}
if isBlog { if isBlog {
data["PublicTime"] = time.Now() data["PublicTime"] = time.Now()
@@ -276,18 +281,18 @@ func (this *NotebookService) ToBlog(userId, notebookId string, isBlog bool) (boo
// 先查看该notebookId下是否有notes, 没有则删除 // 先查看该notebookId下是否有notes, 没有则删除
func (this *NotebookService) DeleteNotebook(userId, notebookId string) (bool, string) { func (this *NotebookService) DeleteNotebook(userId, notebookId string) (bool, string) {
if db.Count(db.Notebooks, bson.M{ if db.Count(db.Notebooks, bson.M{
"ParentNotebookId": bson.ObjectIdHex(notebookId), "ParentNotebookId": bson.ObjectIdHex(notebookId),
"UserId": bson.ObjectIdHex(userId), "UserId": bson.ObjectIdHex(userId),
"IsDeleted": false, "IsDeleted": false,
}) == 0 { // 无 }) == 0 { // 无
if db.Count(db.Notes, bson.M{"NotebookId": bson.ObjectIdHex(notebookId), if db.Count(db.Notes, bson.M{"NotebookId": bson.ObjectIdHex(notebookId),
"UserId": bson.ObjectIdHex(userId), "UserId": bson.ObjectIdHex(userId),
"IsTrash": false, "IsTrash": false,
"IsDeleted": false}) == 0 { // 不包含trash "IsDeleted": false}) == 0 { // 不包含trash
// 不是真删除 1/20, 为了同步笔记本 // 不是真删除 1/20, 为了同步笔记本
ok := db.UpdateByQMap(db.Notebooks, bson.M{"_id": bson.ObjectIdHex(notebookId)}, bson.M{"IsDeleted": true, "Usn": userService.IncrUsn(userId)}) ok := db.UpdateByQMap(db.Notebooks, bson.M{"_id": bson.ObjectIdHex(notebookId)}, bson.M{"IsDeleted": true, "Usn": userService.IncrUsn(userId)})
return ok, "" return ok, ""
// return db.DeleteByIdAndUserId(db.Notebooks, notebookId, userId), "" // return db.DeleteByIdAndUserId(db.Notebooks, notebookId, userId), ""
} }
return false, "笔记本下有笔记" return false, "笔记本下有笔记"
} else { } else {
@@ -329,10 +334,10 @@ func (this *NotebookService) SortNotebooks(userId string, notebookId2Seqs map[st
func (this *NotebookService) DragNotebooks(userId string, curNotebookId string, parentNotebookId string, siblings []string) bool { func (this *NotebookService) DragNotebooks(userId string, curNotebookId string, parentNotebookId string, siblings []string) bool {
ok := false ok := false
// 如果没parentNotebookId, 则parentNotebookId设空 // 如果没parentNotebookId, 则parentNotebookId设空
if(parentNotebookId == "") { if parentNotebookId == "" {
ok = db.UpdateByIdAndUserIdMap(db.Notebooks, curNotebookId, userId, bson.M{"ParentNotebookId": "", "Usn": userService.IncrUsn(userId)}); ok = db.UpdateByIdAndUserIdMap(db.Notebooks, curNotebookId, userId, bson.M{"ParentNotebookId": "", "Usn": userService.IncrUsn(userId)})
} else { } else {
ok = db.UpdateByIdAndUserIdMap(db.Notebooks, curNotebookId, userId, bson.M{"ParentNotebookId": bson.ObjectIdHex(parentNotebookId), "Usn": userService.IncrUsn(userId)}); ok = db.UpdateByIdAndUserIdMap(db.Notebooks, curNotebookId, userId, bson.M{"ParentNotebookId": bson.ObjectIdHex(parentNotebookId), "Usn": userService.IncrUsn(userId)})
} }
if !ok { if !ok {
@@ -362,12 +367,12 @@ func (this *NotebookService) ReCountNotebookNumberNotes(notebookId string) bool
func (this *NotebookService) ReCountAll() { func (this *NotebookService) ReCountAll() {
/* /*
// 得到所有笔记本 // 得到所有笔记本
notebooks := []info.Notebook{} notebooks := []info.Notebook{}
db.ListByQWithFields(db.Notebooks, bson.M{}, []string{"NotebookId"}, &notebooks) db.ListByQWithFields(db.Notebooks, bson.M{}, []string{"NotebookId"}, &notebooks)
for _, each := range notebooks { for _, each := range notebooks {
this.ReCountNotebookNumberNotes(each.NotebookId.Hex()) this.ReCountNotebookNumberNotes(each.NotebookId.Hex())
} }
*/ */
} }
+7 -5
View File
@@ -1,10 +1,10 @@
package service package service
import ( import (
"gopkg.in/mgo.v2/bson"
"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"
) )
// 找回密码 // 找回密码
@@ -34,6 +34,7 @@ func (this *PwdService) FindPwd(email string) (ok bool, msg string) {
return return
} }
// 重置密码时
// 修改密码 // 修改密码
// 先验证 // 先验证
func (this *PwdService) UpdatePwd(token, pwd string) (bool, string) { func (this *PwdService) UpdatePwd(token, pwd string) (bool, string) {
@@ -45,11 +46,12 @@ func (this *PwdService) UpdatePwd(token, pwd string) (bool, string) {
if ok, msg, tokenInfo = tokenService.VerifyToken(token, info.TokenPwd); !ok { if ok, msg, tokenInfo = tokenService.VerifyToken(token, info.TokenPwd); !ok {
return ok, msg return ok, msg
} }
digest, err := GenerateHash(pwd)
if err != nil { passwd := GenPwd(pwd)
return false,"GenerateHash error" if passwd == "" {
return false, "GenerateHash error"
} }
passwd := string(digest)
// 修改密码之 // 修改密码之
ok = db.UpdateByQField(db.Users, bson.M{"_id": tokenInfo.UserId}, "Pwd", passwd) ok = db.UpdateByQField(db.Users, bson.M{"_id": tokenInfo.UserId}, "Pwd", passwd)
+6 -3
View File
@@ -1,12 +1,12 @@
package service package service
import ( import (
"github.com/leanote/leanote/app/info"
"github.com/leanote/leanote/app/db" "github.com/leanote/leanote/app/db"
"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"
) )
// Session存储到mongodb中 // Session存储到mongodb中
@@ -17,6 +17,7 @@ func (this *SessionService) Update(sessionId, key string, value interface{}) boo
return db.UpdateByQMap(db.Sessions, bson.M{"SessionId": sessionId}, return db.UpdateByQMap(db.Sessions, bson.M{"SessionId": sessionId},
bson.M{key: value, "UpdatedTime": time.Now()}) bson.M{key: value, "UpdatedTime": time.Now()})
} }
// 注销时清空session // 注销时清空session
func (this *SessionService) Clear(sessionId string) bool { func (this *SessionService) Clear(sessionId string) bool {
return db.Delete(db.Sessions, bson.M{"SessionId": sessionId}) return db.Delete(db.Sessions, bson.M{"SessionId": sessionId})
@@ -45,14 +46,16 @@ func (this *SessionService) LoginTimesIsOver(sessionId string) bool {
session := this.Get(sessionId) session := this.Get(sessionId)
return session.LoginTimes > 5 return session.LoginTimes > 5
} }
// 登录成功后清空错误次数 // 登录成功后清空错误次数
func (this *SessionService) ClearLoginTimes(sessionId string) bool { func (this *SessionService) ClearLoginTimes(sessionId string) bool {
return this.Update(sessionId, "LoginTimes", 0) return this.Update(sessionId, "LoginTimes", 0)
} }
// 增加错误次数 // 增加错误次数
func (this *SessionService) IncrLoginTimes(sessionId string) bool { func (this *SessionService) IncrLoginTimes(sessionId string) bool {
session := this.Get(sessionId) session := this.Get(sessionId)
return this.Update(sessionId, "LoginTimes", session.LoginTimes + 1) return this.Update(sessionId, "LoginTimes", session.LoginTimes+1)
} }
//---------- //----------
+89 -87
View File
@@ -1,12 +1,12 @@
package service package service
import ( import (
"github.com/leanote/leanote/app/info"
"github.com/leanote/leanote/app/db" "github.com/leanote/leanote/app/db"
. "github.com/leanote/leanote/app/lea" "github.com/leanote/leanote/app/info"
. "github.com/leanote/leanote/app/lea"
"gopkg.in/mgo.v2/bson" "gopkg.in/mgo.v2/bson"
"time"
"sort" "sort"
"time"
) )
// 共享Notebook, Note服务 // 共享Notebook, Note服务
@@ -45,7 +45,7 @@ func (this *ShareService) getOrQ(userId string) bson.M {
// 不是trash的 // 不是trash的
q["$or"] = orQ q["$or"] = orQ
} else { } else {
q["ToUserId"] = bson.ObjectIdHex(userId); q["ToUserId"] = bson.ObjectIdHex(userId)
} }
return q return q
} }
@@ -68,12 +68,12 @@ func (this *ShareService) GetShareNotebooks(userId string) (info.ShareNotebooksB
userIds := append(userIds1, userIds2...) userIds := append(userIds1, userIds2...)
userInfos := userService.GetUserInfosOrderBySeq(userIds); userInfos := userService.GetUserInfosOrderBySeq(userIds)
// 不要我的id // 不要我的id
for i, userInfo := range userInfos { for i, userInfo := range userInfos {
if userInfo.UserId.Hex() == myUserId { if userInfo.UserId.Hex() == myUserId {
userInfos = append(userInfos[:i], userInfos[i+1:]...) userInfos = append(userInfos[:i], userInfos[i+1:]...)
break; break
} }
} }
@@ -109,13 +109,13 @@ func (this *ShareService) GetShareNotebooks(userId string) (info.ShareNotebooksB
subShareNotebooks := this.parseToSubShareNotebooks(&subNotebooks, &shareNotebooksMap) subShareNotebooks := this.parseToSubShareNotebooks(&subNotebooks, &shareNotebooksMap)
// 3 按用户进行分组成ShareNotebooksByUser // 3 按用户进行分组成ShareNotebooksByUser
shareNotebooksByUsersMap := map[bson.ObjectId] []info.ShareNotebooks{} shareNotebooksByUsersMap := map[bson.ObjectId][]info.ShareNotebooks{}
// 先建立userId => [] // 先建立userId => []
for _, eachSub := range subShareNotebooks { for _, eachSub := range subShareNotebooks {
userId := eachSub.Notebook.UserId userId := eachSub.Notebook.UserId
// 我自己的, 算了 // 我自己的, 算了
if userId.Hex() == myUserId { if userId.Hex() == myUserId {
continue; continue
} }
if _, ok := shareNotebooksByUsersMap[userId]; ok { if _, ok := shareNotebooksByUsersMap[userId]; ok {
@@ -124,7 +124,7 @@ func (this *ShareService) GetShareNotebooks(userId string) (info.ShareNotebooksB
shareNotebooksByUsersMap[userId] = []info.ShareNotebooks{eachSub} shareNotebooksByUsersMap[userId] = []info.ShareNotebooks{eachSub}
} }
} }
shareNotebooksByUser := info.ShareNotebooksByUser{}; shareNotebooksByUser := info.ShareNotebooksByUser{}
for userId, eachShareNotebooks := range shareNotebooksByUsersMap { for userId, eachShareNotebooks := range shareNotebooksByUsersMap {
// 4, 按用户排序 // 4, 按用户排序
shareNotebooksByUser[userId.Hex()] = sortSubShareNotebooks(eachShareNotebooks) shareNotebooksByUser[userId.Hex()] = sortSubShareNotebooks(eachShareNotebooks)
@@ -152,7 +152,7 @@ func (this *ShareService) parseToSubShareNotebooks(subNotebooks *info.SubNoteboo
subShareNotebooks := info.SubShareNotebooks{} subShareNotebooks := info.SubShareNotebooks{}
for _, each := range *subNotebooks { for _, each := range *subNotebooks {
shareNotebooks := info.ShareNotebooks{} shareNotebooks := info.ShareNotebooks{}
shareNotebooks.Notebook = each.Notebook // 基本信息有了 shareNotebooks.Notebook = each.Notebook // 基本信息有了
shareNotebooks.ShareNotebook = (*shareNotebooksMap)[each.NotebookId] // perm有了 shareNotebooks.ShareNotebook = (*shareNotebooksMap)[each.NotebookId] // perm有了
// 公用的, 单独赋值 // 公用的, 单独赋值
@@ -173,11 +173,11 @@ func (this *ShareService) parseToSubShareNotebooks(subNotebooks *info.SubNoteboo
// 得到共享笔记本下的notes // 得到共享笔记本下的notes
func (this *ShareService) ListShareNotesByNotebookId(notebookId, myUserId, sharedUserId string, func (this *ShareService) ListShareNotesByNotebookId(notebookId, myUserId, sharedUserId string,
page, pageSize int, sortField string, isAsc bool) ([]info.ShareNoteWithPerm) { page, pageSize int, sortField string, isAsc bool) []info.ShareNoteWithPerm {
// 1 首先判断是否真的sharedUserId 共享了 notebookId 给 myUserId // 1 首先判断是否真的sharedUserId 共享了 notebookId 给 myUserId
q := this.getOrQ(myUserId) q := this.getOrQ(myUserId)
q["NotebookId"] = bson.ObjectIdHex(notebookId); q["NotebookId"] = bson.ObjectIdHex(notebookId)
q["UserId"] = bson.ObjectIdHex(sharedUserId); q["UserId"] = bson.ObjectIdHex(sharedUserId)
shareNotebook := info.ShareNotebook{} shareNotebook := info.ShareNotebook{}
db.GetByQ(db.ShareNotebooks, db.GetByQ(db.ShareNotebooks,
q, q,
@@ -190,7 +190,7 @@ func (this *ShareService) ListShareNotesByNotebookId(notebookId, myUserId, share
perm := shareNotebook.Perm perm := shareNotebook.Perm
// 2 得到该notebook下分页显示所有的notes // 2 得到该notebook下分页显示所有的notes
_, notes := noteService.ListNotes(sharedUserId, notebookId, false, page, pageSize, sortField, isAsc, false); _, notes := noteService.ListNotes(sharedUserId, notebookId, false, page, pageSize, sortField, isAsc, false)
// 3 添加权限信息 // 3 添加权限信息
// 3.1 如果该notebook自己有其它权限信息, 比如1, 那么覆盖notebook的权限信息 // 3.1 如果该notebook自己有其它权限信息, 比如1, 那么覆盖notebook的权限信息
@@ -210,12 +210,12 @@ func (this *ShareService) ListShareNotesByNotebookId(notebookId, myUserId, share
} }
} }
Log("笔记权限") Log("笔记权限")
LogJ(notePerms); LogJ(notePerms)
// 3.2 组合 // 3.2 组合
notesWithPerm := make([]info.ShareNoteWithPerm, len(notes)) notesWithPerm := make([]info.ShareNoteWithPerm, len(notes))
for i, each := range notes { for i, each := range notes {
thisPerm := perm; thisPerm := perm
if selfPerm, ok := notePerms[each.NoteId]; ok { if selfPerm, ok := notePerms[each.NoteId]; ok {
thisPerm = selfPerm thisPerm = selfPerm
} }
@@ -247,13 +247,13 @@ func (this *ShareService) ListShareNotesByNotebookId(notebookId, myUserId, share
// 可以这样! 到时将零散的共享noteId放在用户基本数据中 // 可以这样! 到时将零散的共享noteId放在用户基本数据中
// 这里不好排序 // 这里不好排序
func (this *ShareService) ListShareNotes(myUserId, sharedUserId string, func (this *ShareService) ListShareNotes(myUserId, sharedUserId string,
pageNumber, pageSize int, sortField string, isAsc bool) ([]info.ShareNoteWithPerm) { pageNumber, pageSize int, sortField string, isAsc bool) []info.ShareNoteWithPerm {
skipNum, _ := parsePageAndSort(pageNumber, pageSize, sortField, isAsc) skipNum, _ := parsePageAndSort(pageNumber, pageSize, sortField, isAsc)
shareNotes := []info.ShareNote{} shareNotes := []info.ShareNote{}
q := this.getOrQ(myUserId) q := this.getOrQ(myUserId)
q["UserId"] = bson.ObjectIdHex(sharedUserId); q["UserId"] = bson.ObjectIdHex(sharedUserId)
db.ShareNotes. db.ShareNotes.
Find(q). Find(q).
@@ -297,7 +297,7 @@ func (this *ShareService) notes2NotesWithPerm(notes []info.Note) {
// [ok] // [ok]
func (this *ShareService) AddShareNotebook1(shareNotebook info.ShareNotebook) bool { func (this *ShareService) AddShareNotebook1(shareNotebook info.ShareNotebook) bool {
// 添加一条记录说明两者存在关系 // 添加一条记录说明两者存在关系
this.AddHasShareNote(shareNotebook.UserId.Hex(), shareNotebook.ToUserId.Hex()); this.AddHasShareNote(shareNotebook.UserId.Hex(), shareNotebook.ToUserId.Hex())
shareNotebook.CreatedTime = time.Now() shareNotebook.CreatedTime = time.Now()
return db.Insert(db.ShareNotebooks, shareNotebook) return db.Insert(db.ShareNotebooks, shareNotebook)
@@ -316,18 +316,18 @@ func (this *ShareService) AddShareNotebook(notebookId string, perm int, userId,
// 第三方注册时没有email // 第三方注册时没有email
func (this *ShareService) AddShareNotebookToUserId(notebookId string, perm int, userId, toUserId string) (bool, string, string) { func (this *ShareService) AddShareNotebookToUserId(notebookId string, perm int, userId, toUserId string) (bool, string, string) {
// 添加一条记录说明两者存在关系 // 添加一条记录说明两者存在关系
this.AddHasShareNote(userId, toUserId); this.AddHasShareNote(userId, toUserId)
// 先删除之 // 先删除之
db.Delete(db.ShareNotebooks, bson.M{"NotebookId": bson.ObjectIdHex(notebookId), db.Delete(db.ShareNotebooks, bson.M{"NotebookId": bson.ObjectIdHex(notebookId),
"UserId": bson.ObjectIdHex(userId), "UserId": bson.ObjectIdHex(userId),
"ToUserId": bson.ObjectIdHex(toUserId), "ToUserId": bson.ObjectIdHex(toUserId),
}); })
shareNotebook := info.ShareNotebook{NotebookId: bson.ObjectIdHex(notebookId), shareNotebook := info.ShareNotebook{NotebookId: bson.ObjectIdHex(notebookId),
UserId: bson.ObjectIdHex(userId), UserId: bson.ObjectIdHex(userId),
ToUserId: bson.ObjectIdHex(toUserId), ToUserId: bson.ObjectIdHex(toUserId),
Perm: perm, Perm: perm,
CreatedTime: time.Now(), CreatedTime: time.Now(),
} }
return db.Insert(db.ShareNotebooks, shareNotebook), "", toUserId return db.Insert(db.ShareNotebooks, shareNotebook), "", toUserId
@@ -353,24 +353,23 @@ func (this *ShareService) AddShareNote(noteId string, perm int, userId, email st
// 第三方测试没有userId // 第三方测试没有userId
func (this *ShareService) AddShareNoteToUserId(noteId string, perm int, userId, toUserId string) (bool, string, string) { func (this *ShareService) AddShareNoteToUserId(noteId string, perm int, userId, toUserId string) (bool, string, string) {
// 添加一条记录说明两者存在关系 // 添加一条记录说明两者存在关系
this.AddHasShareNote(userId, toUserId); this.AddHasShareNote(userId, toUserId)
// 先删除之 // 先删除之
db.Delete(db.ShareNotes, bson.M{"NoteId": bson.ObjectIdHex(noteId), db.Delete(db.ShareNotes, bson.M{"NoteId": bson.ObjectIdHex(noteId),
"UserId": bson.ObjectIdHex(userId), "UserId": bson.ObjectIdHex(userId),
"ToUserId": bson.ObjectIdHex(toUserId), "ToUserId": bson.ObjectIdHex(toUserId),
}); })
shareNote := info.ShareNote{NoteId: bson.ObjectIdHex(noteId), shareNote := info.ShareNote{NoteId: bson.ObjectIdHex(noteId),
UserId: bson.ObjectIdHex(userId), UserId: bson.ObjectIdHex(userId),
ToUserId: bson.ObjectIdHex(toUserId), ToUserId: bson.ObjectIdHex(toUserId),
Perm: perm, Perm: perm,
CreatedTime: time.Now(), CreatedTime: time.Now(),
} }
return db.Insert(db.ShareNotes, shareNote), "", toUserId return db.Insert(db.ShareNotes, shareNote), "", toUserId
} }
// updatedUserId是否有查看userId noteId的权限? // updatedUserId是否有查看userId noteId的权限?
// userId是所有者 // userId是所有者
func (this *ShareService) HasReadPerm(userId, updatedUserId, noteId string) bool { func (this *ShareService) HasReadPerm(userId, updatedUserId, noteId string) bool {
@@ -390,9 +389,9 @@ func (this *ShareService) HasReadPerm(userId, updatedUserId, noteId string) bool
// 判断notebook是否被共享 // 判断notebook是否被共享
if !db.Has(db.ShareNotebooks, q) { if !db.Has(db.ShareNotebooks, q) {
return false return false
} else { } else {
return true return true
} }
} else { } else {
return true return true
} }
@@ -443,19 +442,20 @@ func (this *ShareService) HasUpdateNotebookPerm(userId, updatedUserId, notebookI
// 共享note, notebook时使用 // 共享note, notebook时使用
func (this *ShareService) AddHasShareNote(userId, toUserId string) bool { func (this *ShareService) AddHasShareNote(userId, toUserId string) bool {
db.Insert(db.HasShareNotes, info.HasShareNote{UserId: bson.ObjectIdHex(userId), ToUserId: bson.ObjectIdHex(toUserId)}) db.Insert(db.HasShareNotes, info.HasShareNote{UserId: bson.ObjectIdHex(userId), ToUserId: bson.ObjectIdHex(toUserId)})
return true; return true
} }
// userId是否被共享了noteId // userId是否被共享了noteId
func (this *ShareService) HasSharedNote(noteId, myUserId string) bool { func (this *ShareService) HasSharedNote(noteId, myUserId string) bool {
return db.Has(db.ShareNotes, bson.M{"ToUserId": bson.ObjectIdHex(myUserId), "NoteId": bson.ObjectIdHex(noteId)}) return db.Has(db.ShareNotes, bson.M{"ToUserId": bson.ObjectIdHex(myUserId), "NoteId": bson.ObjectIdHex(noteId)})
} }
// noteId的notebook是否共享了给我 // noteId的notebook是否共享了给我
func (this *ShareService) HasSharedNotebook(noteId, myUserId, sharedUserId string) bool { func (this *ShareService) HasSharedNotebook(noteId, myUserId, sharedUserId string) bool {
notebookId := noteService.GetNotebookId(noteId) notebookId := noteService.GetNotebookId(noteId)
if notebookId != "" { if notebookId != "" {
return db.Has(db.ShareNotebooks, bson.M{"NotebookId": notebookId, return db.Has(db.ShareNotebooks, bson.M{"NotebookId": notebookId,
"UserId": bson.ObjectIdHex(sharedUserId), "UserId": bson.ObjectIdHex(sharedUserId),
"ToUserId": bson.ObjectIdHex(myUserId), "ToUserId": bson.ObjectIdHex(myUserId),
}) })
} }
@@ -468,11 +468,12 @@ func (this *ShareService) GetShareNoteContent(noteId, myUserId, sharedUserId str
noteContent = info.NoteContent{} noteContent = info.NoteContent{}
// 是否单独共享了该notebook // 是否单独共享了该notebook
// 或者, 其notebook共享了我 // 或者, 其notebook共享了我
// Log(this.HasSharedNote(noteId, myUserId)) // Log(this.HasSharedNote(noteId, myUserId))
// Log(this.HasSharedNotebook(noteId, myUserId, sharedUserId)) // Log(this.HasSharedNotebook(noteId, myUserId, sharedUserId))
Log(this.HasReadPerm(sharedUserId, myUserId, noteId)) // Log(this.HasReadPerm(sharedUserId, myUserId, noteId))
if this.HasReadPerm(sharedUserId, myUserId, noteId) { if this.HasReadPerm(sharedUserId, myUserId, noteId) {
// if this.HasSharedNote(noteId, myUserId) || this.HasSharedNotebook(noteId, myUserId, sharedUserId) { // if this.HasSharedNote(noteId, myUserId) || this.HasSharedNotebook(noteId, myUserId, sharedUserId) {
db.Get(db.NoteContents, noteId, &noteContent) db.Get(db.NoteContents, noteId, &noteContent)
} else { } else {
} }
@@ -488,13 +489,13 @@ func (this *ShareService) ListNoteShareUserInfo(noteId, userId string) []info.Sh
shareNotes := []info.ShareNote{} shareNotes := []info.ShareNote{}
db.ListByQLimit(db.ShareNotes, db.ListByQLimit(db.ShareNotes,
bson.M{ bson.M{
"NoteId": bson.ObjectIdHex(noteId), "NoteId": bson.ObjectIdHex(noteId),
"UserId": bson.ObjectIdHex(userId), "UserId": bson.ObjectIdHex(userId),
"ToGroupId": bson.M{"$exists": false}, "ToGroupId": bson.M{"$exists": false},
}, &shareNotes, 100) }, &shareNotes, 100)
// Log("<<>>>>") // Log("<<>>>>")
// Log(len(shareNotes)) // Log(len(shareNotes))
if len(shareNotes) == 0 { if len(shareNotes) == 0 {
return nil return nil
@@ -537,10 +538,10 @@ func (this *ShareService) ListNoteShareUserInfo(noteId, userId string) []info.Sh
for i, userInfo := range userInfos { for i, userInfo := range userInfos {
_, hasNotebook := shareNotebooksMap[userInfo.UserId] _, hasNotebook := shareNotebooksMap[userInfo.UserId]
shareUserInfos[i] = info.ShareUserInfo{ToUserId: userInfo.UserId, shareUserInfos[i] = info.ShareUserInfo{ToUserId: userInfo.UserId,
Email: userInfo.Email, Email: userInfo.Email,
Perm: shareNotesMap[userInfo.UserId].Perm, Perm: shareNotesMap[userInfo.UserId].Perm,
NotebookHasShared: hasNotebook, NotebookHasShared: hasNotebook,
} }
} }
return shareUserInfos return shareUserInfos
@@ -555,8 +556,8 @@ func (this *ShareService) ListNotebookShareUserInfo(notebookId, userId string) [
db.ListByQLimit(db.ShareNotebooks, db.ListByQLimit(db.ShareNotebooks,
bson.M{ bson.M{
"NotebookId": bson.ObjectIdHex(notebookId), "NotebookId": bson.ObjectIdHex(notebookId),
"UserId": bson.ObjectIdHex(userId), "UserId": bson.ObjectIdHex(userId),
"ToGroupId": bson.M{"$exists": false}, "ToGroupId": bson.M{"$exists": false},
}, },
&shareNotebooks, 100) &shareNotebooks, 100)
@@ -584,14 +585,13 @@ func (this *ShareService) ListNotebookShareUserInfo(notebookId, userId string) [
for i, userInfo := range userInfos { for i, userInfo := range userInfos {
shareUserInfos[i] = info.ShareUserInfo{ToUserId: userInfo.UserId, shareUserInfos[i] = info.ShareUserInfo{ToUserId: userInfo.UserId,
Email: userInfo.Email, Email: userInfo.Email,
Perm: shareNotebooksMap[userInfo.UserId].Perm, Perm: shareNotebooksMap[userInfo.UserId].Perm,
} }
} }
return shareUserInfos return shareUserInfos
} }
//---------------- //----------------
// 改变note share权限 // 改变note share权限
func (this *ShareService) UpdateShareNotePerm(noteId string, perm int, userId, toUserId string) bool { func (this *ShareService) UpdateShareNotePerm(noteId string, perm int, userId, toUserId string) bool {
@@ -599,7 +599,7 @@ func (this *ShareService) UpdateShareNotePerm(noteId string, perm int, userId, t
bson.M{"NoteId": bson.ObjectIdHex(noteId), "UserId": bson.ObjectIdHex(userId), "ToUserId": bson.ObjectIdHex(toUserId)}, bson.M{"NoteId": bson.ObjectIdHex(noteId), "UserId": bson.ObjectIdHex(userId), "ToUserId": bson.ObjectIdHex(toUserId)},
"Perm", "Perm",
perm, perm,
) )
} }
func (this *ShareService) UpdateShareNotebookPerm(notebookId string, perm int, userId, toUserId string) bool { func (this *ShareService) UpdateShareNotebookPerm(notebookId string, perm int, userId, toUserId string) bool {
@@ -607,7 +607,7 @@ func (this *ShareService) UpdateShareNotebookPerm(notebookId string, perm int, u
bson.M{"NotebookId": bson.ObjectIdHex(notebookId), "UserId": bson.ObjectIdHex(userId), "ToUserId": bson.ObjectIdHex(toUserId)}, bson.M{"NotebookId": bson.ObjectIdHex(notebookId), "UserId": bson.ObjectIdHex(userId), "ToUserId": bson.ObjectIdHex(toUserId)},
"Perm", "Perm",
perm, perm,
) )
} }
//--------------- //---------------
@@ -622,6 +622,7 @@ func (this *ShareService) DeleteShareNoteAll(noteId string, userId string) bool
return db.DeleteAll(db.ShareNotes, return db.DeleteAll(db.ShareNotes,
bson.M{"NoteId": bson.ObjectIdHex(noteId), "UserId": bson.ObjectIdHex(userId)}) bson.M{"NoteId": bson.ObjectIdHex(noteId), "UserId": bson.ObjectIdHex(userId)})
} }
// 删除share notebook // 删除share notebook
func (this *ShareService) DeleteShareNotebook(notebookId string, userId, toUserId string) bool { func (this *ShareService) DeleteShareNotebook(notebookId string, userId, toUserId string) bool {
return db.DeleteAll(db.ShareNotebooks, return db.DeleteAll(db.ShareNotebooks,
@@ -631,9 +632,9 @@ func (this *ShareService) DeleteShareNotebook(notebookId string, userId, toUserI
// 删除userId分享给toUserId的所有 // 删除userId分享给toUserId的所有
func (this *ShareService) DeleteUserShareNoteAndNotebook(userId, toUserId string) bool { func (this *ShareService) DeleteUserShareNoteAndNotebook(userId, toUserId string) bool {
query := bson.M{"UserId": bson.ObjectIdHex(userId), "ToUserId": bson.ObjectIdHex(toUserId)} query := bson.M{"UserId": bson.ObjectIdHex(userId), "ToUserId": bson.ObjectIdHex(toUserId)}
db.DeleteAll(db.ShareNotebooks, query); db.DeleteAll(db.ShareNotebooks, query)
db.DeleteAll(db.ShareNotes, query); db.DeleteAll(db.ShareNotes, query)
db.DeleteAll(db.HasShareNotes, query); db.DeleteAll(db.HasShareNotes, query)
return true return true
} }
@@ -641,10 +642,10 @@ func (this *ShareService) DeleteUserShareNoteAndNotebook(userId, toUserId string
// 用户userId是否有修改noteId的权限 // 用户userId是否有修改noteId的权限
func (this *ShareService) HasUpdateNotePerm(noteId, userId string) bool { func (this *ShareService) HasUpdateNotePerm(noteId, userId string) bool {
if noteId == "" || userId == "" { if noteId == "" || userId == "" {
return false; return false
} }
note := noteService.GetNoteById(noteId) note := noteService.GetNoteById(noteId)
LogJ(note); LogJ(note)
if note.UserId != "" { if note.UserId != "" {
noteUserId := note.UserId.Hex() noteUserId := note.UserId.Hex()
if noteUserId != userId { if noteUserId != userId {
@@ -652,20 +653,20 @@ func (this *ShareService) HasUpdateNotePerm(noteId, userId string) bool {
if this.HasUpdatePerm(noteUserId, userId, noteId) { if this.HasUpdatePerm(noteUserId, userId, noteId) {
return true return true
} else { } else {
return false; return false
} }
} else { } else {
return true return true
} }
} else { } else {
return false; return false
} }
} }
// 用户userId是否有查看noteId的权限 // 用户userId是否有查看noteId的权限
func (this *ShareService) HasReadNotePerm(noteId, userId string) bool { func (this *ShareService) HasReadNotePerm(noteId, userId string) bool {
if noteId == "" || userId == "" { if noteId == "" || userId == "" {
return false; return false
} }
note := noteService.GetNoteById(noteId) note := noteService.GetNoteById(noteId)
if note.UserId != "" { if note.UserId != "" {
@@ -675,13 +676,13 @@ func (this *ShareService) HasReadNotePerm(noteId, userId string) bool {
if this.HasReadPerm(noteUserId, userId, noteId) { if this.HasReadPerm(noteUserId, userId, noteId) {
return true return true
} else { } else {
return false; return false
} }
} else { } else {
return true return true
} }
} else { } else {
return false; return false
} }
} }
@@ -695,7 +696,7 @@ func (this *ShareService) GetNoteShareGroups(noteId, userId string) []info.Share
// 得到有分享的分组 // 得到有分享的分组
shares := []info.ShareNote{} shares := []info.ShareNote{}
db.ListByQ(db.ShareNotes, db.ListByQ(db.ShareNotes,
bson.M{"NoteId": bson.ObjectIdHex(noteId), "UserId": bson.ObjectIdHex(userId), "ToGroupId": bson.M{"$exists":true}}, &shares) bson.M{"NoteId": bson.ObjectIdHex(noteId), "UserId": bson.ObjectIdHex(userId), "ToGroupId": bson.M{"$exists": true}}, &shares)
mapShares := map[bson.ObjectId]info.ShareNote{} mapShares := map[bson.ObjectId]info.ShareNote{}
for _, share := range shares { for _, share := range shares {
mapShares[share.ToGroupId] = share mapShares[share.ToGroupId] = share
@@ -708,7 +709,7 @@ func (this *ShareService) GetNoteShareGroups(noteId, userId string) []info.Share
if !ok { if !ok {
share = info.ShareNote{} share = info.ShareNote{}
} }
share.ToGroup = group; share.ToGroup = group
shares2[i] = share shares2[i] = share
} }
@@ -716,7 +717,7 @@ func (this *ShareService) GetNoteShareGroups(noteId, userId string) []info.Share
} }
// 共享笔记给分组 // 共享笔记给分组
func (this *ShareService) AddShareNoteGroup(userId, noteId, groupId string, perm int) (bool) { func (this *ShareService) AddShareNoteGroup(userId, noteId, groupId string, perm int) bool {
if !groupService.IsExistsGroupUser(userId, groupId) { if !groupService.IsExistsGroupUser(userId, groupId) {
return false return false
} }
@@ -725,9 +726,9 @@ func (this *ShareService) AddShareNoteGroup(userId, noteId, groupId string, perm
this.DeleteShareNoteGroup(userId, noteId, groupId) this.DeleteShareNoteGroup(userId, noteId, groupId)
shareNote := info.ShareNote{NoteId: bson.ObjectIdHex(noteId), shareNote := info.ShareNote{NoteId: bson.ObjectIdHex(noteId),
UserId: bson.ObjectIdHex(userId), // 冗余字段 UserId: bson.ObjectIdHex(userId), // 冗余字段
ToGroupId: bson.ObjectIdHex(groupId), ToGroupId: bson.ObjectIdHex(groupId),
Perm: perm, Perm: perm,
CreatedTime: time.Now(), CreatedTime: time.Now(),
} }
return db.Insert(db.ShareNotes, shareNote) return db.Insert(db.ShareNotes, shareNote)
@@ -736,9 +737,9 @@ func (this *ShareService) AddShareNoteGroup(userId, noteId, groupId string, perm
// 删除 // 删除
func (this *ShareService) DeleteShareNoteGroup(userId, noteId, groupId string) bool { func (this *ShareService) DeleteShareNoteGroup(userId, noteId, groupId string) bool {
return db.Delete(db.ShareNotes, bson.M{"NoteId": bson.ObjectIdHex(noteId), return db.Delete(db.ShareNotes, bson.M{"NoteId": bson.ObjectIdHex(noteId),
"UserId": bson.ObjectIdHex(userId), "UserId": bson.ObjectIdHex(userId),
"ToGroupId": bson.ObjectIdHex(groupId), "ToGroupId": bson.ObjectIdHex(groupId),
}); })
} }
//------- //-------
@@ -750,7 +751,7 @@ func (this *ShareService) GetNotebookShareGroups(notebookId, userId string) []in
// 得到有分享的分组 // 得到有分享的分组
shares := []info.ShareNotebook{} shares := []info.ShareNotebook{}
db.ListByQ(db.ShareNotebooks, db.ListByQ(db.ShareNotebooks,
bson.M{"NotebookId": bson.ObjectIdHex(notebookId), "UserId": bson.ObjectIdHex(userId), "ToGroupId": bson.M{"$exists":true}}, &shares) bson.M{"NotebookId": bson.ObjectIdHex(notebookId), "UserId": bson.ObjectIdHex(userId), "ToGroupId": bson.M{"$exists": true}}, &shares)
mapShares := map[bson.ObjectId]info.ShareNotebook{} mapShares := map[bson.ObjectId]info.ShareNotebook{}
for _, share := range shares { for _, share := range shares {
mapShares[share.ToGroupId] = share mapShares[share.ToGroupId] = share
@@ -764,14 +765,15 @@ func (this *ShareService) GetNotebookShareGroups(notebookId, userId string) []in
if !ok { if !ok {
share = info.ShareNotebook{} share = info.ShareNotebook{}
} }
share.ToGroup = group; share.ToGroup = group
shares2[i] = share shares2[i] = share
} }
return shares2 return shares2
} }
// 共享笔记给分组 // 共享笔记给分组
func (this *ShareService) AddShareNotebookGroup(userId, notebookId, groupId string, perm int) (bool) { func (this *ShareService) AddShareNotebookGroup(userId, notebookId, groupId string, perm int) bool {
if !groupService.IsExistsGroupUser(userId, groupId) { if !groupService.IsExistsGroupUser(userId, groupId) {
return false return false
} }
@@ -780,9 +782,9 @@ func (this *ShareService) AddShareNotebookGroup(userId, notebookId, groupId stri
this.DeleteShareNotebookGroup(userId, notebookId, groupId) this.DeleteShareNotebookGroup(userId, notebookId, groupId)
shareNotebook := info.ShareNotebook{NotebookId: bson.ObjectIdHex(notebookId), shareNotebook := info.ShareNotebook{NotebookId: bson.ObjectIdHex(notebookId),
UserId: bson.ObjectIdHex(userId), // 冗余字段 UserId: bson.ObjectIdHex(userId), // 冗余字段
ToGroupId: bson.ObjectIdHex(groupId), ToGroupId: bson.ObjectIdHex(groupId),
Perm: perm, Perm: perm,
CreatedTime: time.Now(), CreatedTime: time.Now(),
} }
return db.Insert(db.ShareNotebooks, shareNotebook) return db.Insert(db.ShareNotebooks, shareNotebook)
@@ -791,9 +793,9 @@ func (this *ShareService) AddShareNotebookGroup(userId, notebookId, groupId stri
// 删除 // 删除
func (this *ShareService) DeleteShareNotebookGroup(userId, notebookId, groupId string) bool { func (this *ShareService) DeleteShareNotebookGroup(userId, notebookId, groupId string) bool {
return db.Delete(db.ShareNotebooks, bson.M{"NotebookId": bson.ObjectIdHex(notebookId), return db.Delete(db.ShareNotebooks, bson.M{"NotebookId": bson.ObjectIdHex(notebookId),
"UserId": bson.ObjectIdHex(userId), "UserId": bson.ObjectIdHex(userId),
"ToGroupId": bson.ObjectIdHex(groupId), "ToGroupId": bson.ObjectIdHex(groupId),
}); })
} }
//-------------------- //--------------------
@@ -803,12 +805,12 @@ func (this *ShareService) DeleteShareNotebookGroup(userId, notebookId, groupId s
func (this *ShareService) DeleteAllShareNotebookGroup(groupId string) bool { func (this *ShareService) DeleteAllShareNotebookGroup(groupId string) bool {
return db.Delete(db.ShareNotebooks, bson.M{ return db.Delete(db.ShareNotebooks, bson.M{
"ToGroupId": bson.ObjectIdHex(groupId), "ToGroupId": bson.ObjectIdHex(groupId),
}); })
} }
func (this *ShareService) DeleteAllShareNoteGroup(groupId string) bool { func (this *ShareService) DeleteAllShareNoteGroup(groupId string) bool {
return db.Delete(db.ShareNotes, bson.M{ return db.Delete(db.ShareNotes, bson.M{
"ToGroupId": bson.ObjectIdHex(groupId), "ToGroupId": bson.ObjectIdHex(groupId),
}); })
} }
//-------------------- //--------------------
@@ -817,14 +819,14 @@ func (this *ShareService) DeleteAllShareNoteGroup(groupId string) bool {
func (this *ShareService) DeleteShareNotebookGroupWhenDeleteGroupUser(userId, groupId string) bool { func (this *ShareService) DeleteShareNotebookGroupWhenDeleteGroupUser(userId, groupId string) bool {
return db.Delete(db.ShareNotebooks, bson.M{ return db.Delete(db.ShareNotebooks, bson.M{
"UserId": bson.ObjectIdHex(userId), "UserId": bson.ObjectIdHex(userId),
"ToGroupId": bson.ObjectIdHex(groupId), "ToGroupId": bson.ObjectIdHex(groupId),
}); })
} }
func (this *ShareService) DeleteShareNoteGroupWhenDeleteGroupUser(userId, groupId string) bool { func (this *ShareService) DeleteShareNoteGroupWhenDeleteGroupUser(userId, groupId string) bool {
return db.Delete(db.ShareNotes, bson.M{ return db.Delete(db.ShareNotes, bson.M{
"UserId": bson.ObjectIdHex(userId), "UserId": bson.ObjectIdHex(userId),
"ToGroupId": bson.ObjectIdHex(groupId), "ToGroupId": bson.ObjectIdHex(groupId),
}); })
} }
+4 -4
View File
@@ -1,12 +1,12 @@
package service package service
import ( import (
"github.com/leanote/leanote/app/info"
"github.com/leanote/leanote/app/db" "github.com/leanote/leanote/app/db"
// . "github.com/leanote/leanote/app/lea" "github.com/leanote/leanote/app/info"
// . "github.com/leanote/leanote/app/lea"
"gopkg.in/mgo.v2/bson" "gopkg.in/mgo.v2/bson"
// "time" // "time"
// "sort" // "sort"
) )
type SuggestionService struct { type SuggestionService struct {
+8 -8
View File
@@ -1,9 +1,9 @@
package service package service
import ( import (
"github.com/leanote/leanote/app/info"
"github.com/leanote/leanote/app/db" "github.com/leanote/leanote/app/db"
// . "github.com/leanote/leanote/app/lea" "github.com/leanote/leanote/app/info"
// . "github.com/leanote/leanote/app/lea"
"gopkg.in/mgo.v2/bson" "gopkg.in/mgo.v2/bson"
"time" "time"
) )
@@ -60,7 +60,7 @@ func (this *TagService) AddOrUpdateTag(userId string, tag string) info.NoteTag {
count := noteService.CountNoteByTag(userId, tag) count := noteService.CountNoteByTag(userId, tag)
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而已
db.UpdateByIdAndUserId(db.NoteTags, noteTag.TagId.Hex(), userId, noteTag) db.UpdateByIdAndUserId(db.NoteTags, noteTag.TagId.Hex(), userId, noteTag)
return noteTag return noteTag
} }
@@ -83,7 +83,7 @@ func (this *TagService) AddOrUpdateTag(userId string, tag string) info.NoteTag {
func (this *TagService) GetTags(userId string) []info.NoteTag { func (this *TagService) GetTags(userId string) []info.NoteTag {
tags := []info.NoteTag{} tags := []info.NoteTag{}
query := bson.M{"UserId": bson.ObjectIdHex(userId), "IsDeleted": false} query := bson.M{"UserId": bson.ObjectIdHex(userId), "IsDeleted": false}
q := db.NoteTags.Find(query); q := db.NoteTags.Find(query)
sortFieldR := "-UpdatedTime" sortFieldR := "-UpdatedTime"
q.Sort(sortFieldR).All(&tags) q.Sort(sortFieldR).All(&tags)
return tags return tags
@@ -95,7 +95,7 @@ func (this *TagService) GetTags(userId string) []info.NoteTag {
func (this *TagService) DeleteTag(userId string, tag string) map[string]int { func (this *TagService) DeleteTag(userId string, tag string) map[string]int {
usn := userService.IncrUsn(userId) usn := userService.IncrUsn(userId)
if db.UpdateByQMap(db.NoteTags, bson.M{"UserId": bson.ObjectIdHex(userId), "Tag": tag}, bson.M{"Usn": usn, "IsDeleted": true}) { if db.UpdateByQMap(db.NoteTags, bson.M{"UserId": bson.ObjectIdHex(userId), "Tag": tag}, bson.M{"Usn": usn, "IsDeleted": true}) {
return noteService.UpdateNoteToDeleteTag(userId, tag); return noteService.UpdateNoteToDeleteTag(userId, tag)
} }
return map[string]int{} return map[string]int{}
} }
@@ -124,14 +124,14 @@ func (this *TagService) reCountTagCount(userId string, tags []string) {
return return
} }
for _, tag := range tags { for _, tag := range tags {
this.AddOrUpdateTag(userId, tag); this.AddOrUpdateTag(userId, tag)
} }
} }
// 同步用 // 同步用
func (this *TagService) GeSyncTags(userId string, afterUsn, maxEntry int) ([]info.NoteTag) { func (this *TagService) GeSyncTags(userId string, afterUsn, maxEntry int) []info.NoteTag {
noteTags := []info.NoteTag{} noteTags := []info.NoteTag{}
q := db.NoteTags.Find(bson.M{"UserId": bson.ObjectIdHex(userId), "Usn": bson.M{"$gt": afterUsn}}); q := db.NoteTags.Find(bson.M{"UserId": bson.ObjectIdHex(userId), "Usn": bson.M{"$gt": afterUsn}})
q.Sort("Usn").Limit(maxEntry).All(&noteTags) q.Sort("Usn").Limit(maxEntry).All(&noteTags)
return noteTags return noteTags
} }
+94 -73
View File
@@ -1,20 +1,20 @@
package service package service
import ( import (
"github.com/revel/revel" "encoding/json"
"github.com/leanote/leanote/app/info" "fmt"
"github.com/leanote/leanote/app/db" "github.com/leanote/leanote/app/db"
"github.com/leanote/leanote/app/info"
. "github.com/leanote/leanote/app/lea" . "github.com/leanote/leanote/app/lea"
"github.com/leanote/leanote/app/lea/archive" "github.com/leanote/leanote/app/lea/archive"
"github.com/revel/revel"
"gopkg.in/mgo.v2/bson" "gopkg.in/mgo.v2/bson"
"time"
"strings"
"os"
"fmt"
"html/template" "html/template"
"regexp"
"io/ioutil" "io/ioutil"
"encoding/json" "os"
"regexp"
"strings"
"time"
) )
// 主题 // 主题
@@ -29,6 +29,7 @@ var fixedStyle = "blog_left_fixed"
func (this *ThemeService) getDefaultThemeBasePath() string { func (this *ThemeService) getDefaultThemeBasePath() string {
return revel.BasePath + "/public/blog/themes" return revel.BasePath + "/public/blog/themes"
} }
// 默认主题路径 // 默认主题路径
func (this *ThemeService) getDefaultThemePath(style string) string { func (this *ThemeService) getDefaultThemePath(style string) string {
if style == elegantStyle { if style == elegantStyle {
@@ -39,6 +40,7 @@ func (this *ThemeService) getDefaultThemePath(style string) string {
return this.getDefaultThemeBasePath() + "/default" return this.getDefaultThemeBasePath() + "/default"
} }
} }
// blogService用 // blogService用
func (this *ThemeService) GetDefaultThemePath(style string) string { func (this *ThemeService) GetDefaultThemePath(style string) string {
if style == elegantStyle { if style == elegantStyle {
@@ -56,29 +58,29 @@ func (this *ThemeService) getDefaultTheme(style string) info.Theme {
if style == elegantStyle { if style == elegantStyle {
return info.Theme{ return info.Theme{
IsDefault: true, IsDefault: true,
Path: "public/blog/themes/elegant", Path: "public/blog/themes/elegant",
Name: "leanote elegant", Name: "leanote elegant",
Author: "leanote", Author: "leanote",
AuthorUrl: "http://leanote.com", AuthorUrl: "http://leanote.com",
Version: "1.0", Version: "1.0",
} }
} else if style == fixedStyle { } else if style == fixedStyle {
return info.Theme{ return info.Theme{
IsDefault: true, IsDefault: true,
Path: "public/blog/themes/nav_fixed", Path: "public/blog/themes/nav_fixed",
Name: "leanote nav fixed", Name: "leanote nav fixed",
Author: "leanote", Author: "leanote",
AuthorUrl: "http://leanote.com", AuthorUrl: "http://leanote.com",
Version: "1.0", Version: "1.0",
} }
} else { // blog default } else { // blog default
return info.Theme{ return info.Theme{
IsDefault: true, IsDefault: true,
Path: "public/blog/themes/default", Path: "public/blog/themes/default",
Name: "leanote default", Name: "leanote default",
Author: "leanote", Author: "leanote",
AuthorUrl: "http://leanote.com", AuthorUrl: "http://leanote.com",
Version: "1.0", Version: "1.0",
} }
} }
} }
@@ -141,7 +143,7 @@ func (this *ThemeService) NewTheme(userId string) (ok bool, themeId string) {
themeService.NewThemeForFirst(userBlog) themeService.NewThemeForFirst(userBlog)
} }
// 再copy一个默认主题 // 再copy一个默认主题
userBlog.Style = "defaultStyle"; userBlog.Style = "defaultStyle"
ok, themeId = this.CopyDefaultTheme(userBlog) ok, themeId = this.CopyDefaultTheme(userBlog)
return return
} }
@@ -155,29 +157,29 @@ func (this *ThemeService) parseConfig(configStr string) (theme info.Theme, err e
// 转成map // 转成map
config := map[string]interface{}{} config := map[string]interface{}{}
err = json.Unmarshal([]byte(configStr), &config) err = json.Unmarshal([]byte(configStr), &config)
if err != nil { if err != nil {
return return
} }
// 没有错, 则将Name, Version, Author, AuthorUrl // 没有错, 则将Name, Version, Author, AuthorUrl
Name := config["Name"] Name := config["Name"]
if Name != nil { if Name != nil {
theme.Name = Name.(string) theme.Name = Name.(string)
} }
Version := config["Version"] Version := config["Version"]
if Version != nil { if Version != nil {
theme.Version = Version.(string) theme.Version = Version.(string)
} }
Author := config["Author"] Author := config["Author"]
if Author != nil { if Author != nil {
theme.Author = Author.(string) theme.Author = Author.(string)
} }
AuthorUrl := config["AuthorUrl"] AuthorUrl := config["AuthorUrl"]
if AuthorUrl != nil { if AuthorUrl != nil {
theme.AuthorUrl = AuthorUrl.(string) theme.AuthorUrl = AuthorUrl.(string)
} }
theme.Info = config theme.Info = config
return return
} }
// 读取theme.json得到值 // 读取theme.json得到值
@@ -223,11 +225,11 @@ func (this *ThemeService) GetUserThemes(userId string) (theme info.Theme, themes
theme = info.Theme{} theme = info.Theme{}
themes = []info.Theme{} themes = []info.Theme{}
// db.ListByQ(db.Themes, bson.M{"UserId": bson.ObjectIdHex(userId)}, &themes) // db.ListByQ(db.Themes, bson.M{"UserId": bson.ObjectIdHex(userId)}, &themes)
// 创建时间逆序 // 创建时间逆序
query := bson.M{"UserId": bson.ObjectIdHex(userId)} query := bson.M{"UserId": bson.ObjectIdHex(userId)}
q := db.Themes.Find(query); q := db.Themes.Find(query)
q.Sort("-CreatedTime").All(&themes) q.Sort("-CreatedTime").All(&themes)
if len(themes) == 0 { if len(themes) == 0 {
userBlog := blogService.GetUserBlog(userId) userBlog := blogService.GetUserBlog(userId)
@@ -262,8 +264,22 @@ func (this *ThemeService) GetDefaultThemes() (themes []info.Theme) {
return return
} }
func validateFilename(filename string) bool {
// 防止用"../../来获取其它文件"
if (strings.Contains(filename, "..")) {
return false
}
return true
}
// 得到模板内容 // 得到模板内容
func (this *ThemeService) GetTplContent(userId, themeId, filename string) string { func (this *ThemeService) GetTplContent(userId, themeId, filename string) string {
if (!validateFilename(filename)) {
return ""
}
path := this.GetThemeAbsolutePath(userId, themeId) + "/" + filename path := this.GetThemeAbsolutePath(userId, themeId) + "/" + filename
return GetFileStrContent(path) return GetFileStrContent(path)
} }
@@ -285,8 +301,13 @@ func (this *ThemeService) GetThemePath(userId, themeId string) string {
} }
return "" return ""
} }
// 更新模板内容 // 更新模板内容
func (this *ThemeService) UpdateTplContent(userId, themeId, filename, content string) (ok bool, msg string) { func (this *ThemeService) UpdateTplContent(userId, themeId, filename, content string) (ok bool, msg string) {
if (!validateFilename(filename)) {
return
}
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") {
@@ -307,11 +328,11 @@ func (this *ThemeService) UpdateTplContent(userId, themeId, filename, content st
// 正确, 更新theme信息 // 正确, 更新theme信息
ok = db.UpdateByQMap(db.Themes, bson.M{"_id": bson.ObjectIdHex(themeId), "UserId": bson.ObjectIdHex(userId)}, ok = db.UpdateByQMap(db.Themes, bson.M{"_id": bson.ObjectIdHex(themeId), "UserId": bson.ObjectIdHex(userId)},
bson.M{ bson.M{
"Name": theme.Name, "Name": theme.Name,
"Version": theme.Version, "Version": theme.Version,
"Author": theme.Author, "Author": theme.Author,
"AuthorUrl": theme.AuthorUrl, "AuthorUrl": theme.AuthorUrl,
"Info": theme.Info, "Info": theme.Info,
}) })
if ok { if ok {
ok = PutFileStrContent(path, content) ok = PutFileStrContent(path, content)
@@ -323,6 +344,10 @@ func (this *ThemeService) UpdateTplContent(userId, themeId, filename, content st
} }
func (this *ThemeService) DeleteTpl(userId, themeId, filename string) (ok bool) { func (this *ThemeService) DeleteTpl(userId, themeId, filename string) (ok bool) {
if (!validateFilename(filename)) {
return
}
path := this.GetThemeAbsolutePath(userId, themeId) + "/" + filename path := this.GetThemeAbsolutePath(userId, themeId) + "/" + filename
ok = DeleteFile(path) ok = DeleteFile(path)
return return
@@ -361,7 +386,7 @@ func (this *ThemeService) ActiveTheme(userId, themeId string) (ok bool) {
// 删除主题 // 删除主题
func (this *ThemeService) DeleteTheme(userId, themeId string) (ok bool) { func (this *ThemeService) DeleteTheme(userId, themeId string) (ok bool) {
return db.Delete(db.Themes,bson.M{"_id": bson.ObjectIdHex(themeId), "UserId": bson.ObjectIdHex(userId), "IsActive": false}) return db.Delete(db.Themes, bson.M{"_id": bson.ObjectIdHex(themeId), "UserId": bson.ObjectIdHex(userId), "IsActive": false})
} }
// 公开主题, 只有管理员才有权限, 之前没公开的变成公开 // 公开主题, 只有管理员才有权限, 之前没公开的变成公开
@@ -375,7 +400,6 @@ func (this *ThemeService) PublicTheme(userId, themeId string) (ok bool) {
return false return false
} }
// 导出主题 // 导出主题
func (this *ThemeService) ExportTheme(userId, themeId string) (ok bool, path string) { func (this *ThemeService) ExportTheme(userId, themeId string) (ok bool, path string) {
theme := this.GetThemeById(themeId) theme := this.GetThemeById(themeId)
@@ -384,12 +408,12 @@ func (this *ThemeService) ExportTheme(userId, themeId string) (ok bool, path str
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")) ||
strings.Contains(theme.Path, "..") { strings.Contains(theme.Path, "..") {
return return
} }
sourcePath := revel.BasePath + "/" + theme.Path sourcePath := revel.BasePath + "/" + theme.Path
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 {
@@ -406,6 +430,7 @@ func (this *ThemeService) ExportTheme(userId, themeId string) (ok bool, path str
return true, targetName return true, targetName
} }
// 导入主题 // 导入主题
// path == /llllllll/..../public/upload/.../aa.zip, 绝对路径 // path == /llllllll/..../public/upload/.../aa.zip, 绝对路径
func (this *ThemeService) ImportTheme(userId, path string) (ok bool, msg string) { func (this *ThemeService) ImportTheme(userId, path string) (ok bool, msg string) {
@@ -525,7 +550,7 @@ func (this *ThemeService) InstallTheme(userId, themeId string) (ok bool) {
ok = db.Insert(db.Themes, theme) ok = db.Insert(db.Themes, theme)
// 激活之 // 激活之
this.ActiveTheme(userId, themeId); this.ActiveTheme(userId, themeId)
return ok return ok
} }
@@ -538,28 +563,28 @@ func (this *ThemeService) ValidateTheme(path string, filename, newContent string
// 建立一个有向图 // 建立一个有向图
// 将该path下的所有文件提出, 得到文件的引用情况 // 将该path下的所有文件提出, 得到文件的引用情况
files := ListDir(path) files := ListDir(path)
LogJ(files); LogJ(files)
size := len(files) size := len(files)
if(size > 100) { if size > 100 {
ok = false; ok = false
msg = "tooManyFiles" msg = "tooManyFiles"
return return
} }
/* /*
111111111 111111111
111000000 111000000
*/ */
vector := make([][]int, size) vector := make([][]int, size)
for i := 0; i < size; i++ { for i := 0; i < size; i++ {
vector[i] = make([]int, size) vector[i] = make([]int, size)
} }
fileIndexMap := map[string]int{} // fileName => index fileIndexMap := map[string]int{} // fileName => index
fileContent := map[string]string{} // fileName => content fileContent := map[string]string{} // fileName => content
index := 0 index := 0
// 得到文件内容, 和建立索引, 每个文件都有一个index, 对应数组位置 // 得到文件内容, 和建立索引, 每个文件都有一个index, 对应数组位置
for _, t := range files { for _, t := range files {
if !strings.Contains(t, ".html") { if !strings.Contains(t, ".html") {
continue; continue
} }
if t != filename { if t != filename {
fileBytes, err := ioutil.ReadFile(path + "/" + t) fileBytes, err := ioutil.ReadFile(path + "/" + t)
@@ -567,7 +592,7 @@ func (this *ThemeService) ValidateTheme(path string, filename, newContent string
continue continue
} }
fileIndexMap[t] = index; fileIndexMap[t] = index
// html内容 // html内容
fileStr := string(fileBytes) fileStr := string(fileBytes)
fileContent[t] = fileStr fileContent[t] = fileStr
@@ -583,7 +608,7 @@ func (this *ThemeService) ValidateTheme(path string, filename, newContent string
thisIndex := fileIndexMap[filename] thisIndex := fileIndexMap[filename]
finds := reg.FindAllStringSubmatch(content, -1) // 子匹配 finds := reg.FindAllStringSubmatch(content, -1) // 子匹配
LogJ(finds) LogJ(finds)
// Log(content) // Log(content)
if finds != nil && len(finds) > 0 { if finds != nil && len(finds) > 0 {
for _, includes := range finds { for _, includes := range finds {
include := includes[1] include := includes[1]
@@ -607,7 +632,7 @@ func (this *ThemeService) ValidateTheme(path string, filename, newContent string
} else { } else {
ok = true ok = true
} }
return; return
} }
// 检测有向图是否有环, DFS // 检测有向图是否有环, DFS
@@ -615,9 +640,7 @@ func (this *ThemeService) hasRound(vector [][]int, size int) (ok bool) {
for i := 0; i < size; i++ { for i := 0; i < size; i++ {
visited := make([]int, size) visited := make([]int, size)
if this.hasRoundEach(vector, i, size, visited) { if this.hasRoundEach(vector, i, size, visited) {
Log(">>") return true
Log(i);
return true;
} }
} }
return false return false
@@ -626,17 +649,15 @@ func (this *ThemeService) hasRound(vector [][]int, size int) (ok bool) {
// 从每个节点出发, 判断是否有环 // 从每个节点出发, 判断是否有环
func (this *ThemeService) hasRoundEach(vector [][]int, index int, size int, visited []int) (ok bool) { func (this *ThemeService) hasRoundEach(vector [][]int, index int, size int, visited []int) (ok bool) {
if visited[index] > 0 { if visited[index] > 0 {
Log("<")
Log(index)
return true return true
} }
visited[index] = 1; visited[index] = 1
// 遍历它的孩子 // 遍历它的孩子
for i := 0; i < size; i++ { for i := 0; i < size; i++ {
if vector[index][i] > 0 { if vector[index][i] > 0 {
return this.hasRoundEach(vector, i, size, visited); return this.hasRoundEach(vector, i, size, visited)
} }
} }
visited[index] = 0; visited[index] = 0
return false; return false
} }
+1 -1
View File
@@ -1,10 +1,10 @@
package service package service
import ( import (
"gopkg.in/mgo.v2/bson"
"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"
"time" "time"
) )
+18 -8
View File
@@ -1,9 +1,9 @@
package service package service
import ( import (
"gopkg.in/mgo.v2/bson"
"github.com/leanote/leanote/app/db" "github.com/leanote/leanote/app/db"
"github.com/leanote/leanote/app/info" "github.com/leanote/leanote/app/info"
"gopkg.in/mgo.v2/bson"
) )
// 回收站 // 回收站
@@ -25,9 +25,9 @@ type TrashService struct {
// 应该放在回收站里 // 应该放在回收站里
// 有trashService // 有trashService
func (this *TrashService) DeleteNote(noteId, userId string) bool { func (this *TrashService) DeleteNote(noteId, userId string) bool {
note := noteService.GetNote(noteId, userId); note := noteService.GetNote(noteId, userId)
// 如果是垃圾, 则彻底删除 // 如果是垃圾, 则彻底删除
if (note.IsTrash) { if note.IsTrash {
return this.DeleteTrash(noteId, userId) return this.DeleteTrash(noteId, userId)
} }
@@ -61,14 +61,14 @@ func (this *TrashService) DeleteSharedNote(noteId, myUserId string) bool {
func (this *TrashService) recoverNote(noteId, notebookId, userId string) bool { func (this *TrashService) recoverNote(noteId, notebookId, userId string) bool {
re := db.UpdateByIdAndUserId(db.Notes, noteId, userId, re := db.UpdateByIdAndUserId(db.Notes, noteId, userId,
bson.M{"$set": bson.M{"IsTrash": false, bson.M{"$set": bson.M{"IsTrash": false,
"Usn": userService.IncrUsn(userId), "Usn": userService.IncrUsn(userId),
"NotebookId": bson.ObjectIdHex(notebookId)}}) "NotebookId": bson.ObjectIdHex(notebookId)}})
return re; return re
} }
// 删除trash // 删除trash
func (this *TrashService) DeleteTrash(noteId, userId string) bool { func (this *TrashService) DeleteTrash(noteId, userId string) bool {
note := noteService.GetNote(noteId, userId); note := noteService.GetNote(noteId, userId)
if note.NoteId == "" { if note.NoteId == "" {
return false return false
} }
@@ -80,11 +80,14 @@ func (this *TrashService) DeleteTrash(noteId, userId string) bool {
bson.M{"IsDeleted": true, bson.M{"IsDeleted": true,
"Usn": userService.IncrUsn(userId)}) "Usn": userService.IncrUsn(userId)})
// delete note // delete note
// ok = db.DeleteByIdAndUserId(db.Notes, noteId, userId) // ok = db.DeleteByIdAndUserId(db.Notes, noteId, userId)
// delete content // delete content
ok = db.DeleteByIdAndUserId(db.NoteContents, noteId, userId) ok = db.DeleteByIdAndUserId(db.NoteContents, noteId, userId)
// 删除content history
ok = db.DeleteByIdAndUserId(db.NoteContentHistories, noteId, userId)
// 重新统计tag's count // 重新统计tag's count
// TODO 这里会改变tag's Usn // TODO 这里会改变tag's Usn
tagService.reCountTagCount(userId, note.Tags) tagService.reCountTagCount(userId, note.Tags)
@@ -115,13 +118,20 @@ func (this *TrashService) DeleteTrashApi(noteId, userId string, usn int) (bool,
// delete content // delete content
ok = db.DeleteByIdAndUserId(db.NoteContents, noteId, userId) ok = db.DeleteByIdAndUserId(db.NoteContents, noteId, userId)
// 删除content history
ok = db.DeleteByIdAndUserId(db.NoteContentHistories, noteId, userId)
// 一个BUG, iOS删除直接调用这个API, 结果没有重新recount
// recount notebooks' notes number
notebookService.ReCountNotebookNumberNotes(note.NotebookId.Hex())
return ok, "", afterUsn return ok, "", afterUsn
} }
// 列出note, 排序规则, 还有分页 // 列出note, 排序规则, 还有分页
// CreatedTime, UpdatedTime, title 来排序 // CreatedTime, UpdatedTime, title 来排序
func (this *TrashService) ListNotes(userId string, func (this *TrashService) ListNotes(userId string,
pageNumber, pageSize int, sortField string, isAsc bool) (notes []info.Note) { pageNumber, pageSize int, sortField string, isAsc bool) (notes []info.Note) {
_, notes = noteService.ListNotes(userId, "", true, pageNumber, pageSize, sortField, isAsc, false) _, notes = noteService.ListNotes(userId, "", true, pageNumber, pageSize, sortField, isAsc, false)
return return
} }
+15 -16
View File
@@ -1,14 +1,13 @@
package service package service
import ( import (
"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"
"github.com/leanote/leanote/app/db"
"gopkg.in/mgo.v2/bson" "gopkg.in/mgo.v2/bson"
"time" "time"
) )
type UpgradeService struct { type UpgradeService struct {
} }
@@ -66,7 +65,7 @@ func (this *UpgradeService) UpgradeBetaToBeta2(userId string) (ok bool, msg stri
data["RecommendTime"] = note.UpdatedTime data["RecommendTime"] = note.UpdatedTime
Log("Time " + noteId) Log("Time " + noteId)
} }
data["UrlTitle"] = GetUrTitle(note.UserId.Hex(), note.Title, "note") data["UrlTitle"] = GetUrTitle(note.UserId.Hex(), note.Title, "note", noteId)
db.UpdateByIdAndUserIdMap2(db.Notes, note.NoteId, note.UserId, data) db.UpdateByIdAndUserIdMap2(db.Notes, note.NoteId, note.UserId, data)
Log(noteId) Log(noteId)
} }
@@ -78,20 +77,20 @@ func (this *UpgradeService) UpgradeBetaToBeta2(userId string) (ok bool, msg stri
for _, notebook := range notebooks { for _, notebook := range notebooks {
notebookId := notebook.NotebookId.Hex() notebookId := notebook.NotebookId.Hex()
data := bson.M{} data := bson.M{}
data["UrlTitle"] = GetUrTitle(notebook.UserId.Hex(), notebook.Title, "notebook") data["UrlTitle"] = GetUrTitle(notebook.UserId.Hex(), notebook.Title, "notebook", notebookId)
db.UpdateByIdAndUserIdMap2(db.Notebooks, notebook.NotebookId, notebook.UserId, data) db.UpdateByIdAndUserIdMap2(db.Notebooks, notebook.NotebookId, notebook.UserId, data)
Log(notebookId) Log(notebookId)
} }
// 3.3 single // 3.3 single
/* /*
singles := []info.BlogSingle{} singles := []info.BlogSingle{}
db.ListByQ(db.BlogSingles, bson.M{}, &singles) db.ListByQ(db.BlogSingles, bson.M{}, &singles)
for _, single := range singles { for _, single := range singles {
singleId := single.SingleId.Hex() singleId := single.SingleId.Hex()
blogService.UpdateSingleUrlTitle(single.UserId.Hex(), singleId, single.Title) blogService.UpdateSingleUrlTitle(single.UserId.Hex(), singleId, single.Title)
Log(singleId) Log(singleId)
} }
*/ */
// 删除索引 // 删除索引
@@ -134,7 +133,7 @@ func (this *UpgradeService) moveTag() {
func (this *UpgradeService) setNotebookUsn() { func (this *UpgradeService) setNotebookUsn() {
usnI := 1 usnI := 1
notebooks := []info.Notebook{} notebooks := []info.Notebook{}
db.ListByQWithFields(db.Notebooks, bson.M{}, []string{"UserId"}, &notebooks) db.ListByQWithFields(db.Notebooks, bson.M{}, []string{"UserId"}, &notebooks)
for _, notebook := range notebooks { for _, notebook := range notebooks {
db.UpdateByQField(db.Notebooks, bson.M{"_id": notebook.NotebookId}, "Usn", usnI) db.UpdateByQField(db.Notebooks, bson.M{"_id": notebook.NotebookId}, "Usn", usnI)
@@ -145,7 +144,7 @@ func (this *UpgradeService) setNotebookUsn() {
func (this *UpgradeService) setNoteUsn() { func (this *UpgradeService) setNoteUsn() {
usnI := 1 usnI := 1
notes := []info.Note{} notes := []info.Note{}
db.ListByQWithFields(db.Notes, bson.M{}, []string{"UserId"}, &notes) db.ListByQWithFields(db.Notes, bson.M{}, []string{"UserId"}, &notes)
for _, note := range notes { for _, note := range notes {
db.UpdateByQField(db.Notes, bson.M{"_id": note.NoteId}, "Usn", usnI) db.UpdateByQField(db.Notes, bson.M{"_id": note.NoteId}, "Usn", usnI)
@@ -164,17 +163,17 @@ func (this *UpgradeService) Api(userId string) (ok bool, msg string) {
// notebook // notebook
db.UpdateByQField(db.Notebooks, bson.M{}, "IsDeleted", false) db.UpdateByQField(db.Notebooks, bson.M{}, "IsDeleted", false)
this.setNotebookUsn(); this.setNotebookUsn()
// note // note
// 1-N // 1-N
db.UpdateByQField(db.Notes, bson.M{}, "IsDeleted", false) db.UpdateByQField(db.Notes, bson.M{}, "IsDeleted", false)
this.setNoteUsn(); this.setNoteUsn()
// tag // tag
// 1-N // 1-N
/// tag, 要重新插入, 将之前的Tag表迁移到NoteTag中 /// tag, 要重新插入, 将之前的Tag表迁移到NoteTag中
this.moveTag(); this.moveTag()
configService.UpdateGlobalStringConfig(userId, "UpgradeBetaToBeta4", "1") configService.UpdateGlobalStringConfig(userId, "UpgradeBetaToBeta4", "1")
+40 -55
View File
@@ -1,12 +1,12 @@
package service package service
import ( import (
"github.com/leanote/leanote/app/info"
"github.com/leanote/leanote/app/db" "github.com/leanote/leanote/app/db"
"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"
"strings" "strings"
"time"
) )
type UserService struct { type UserService struct {
@@ -23,7 +23,7 @@ func (this *UserService) IncrUsn(userId string) int {
Log("inc Usn") Log("inc Usn")
db.UpdateByQField(db.Users, query, "Usn", usn) db.UpdateByQField(db.Users, query, "Usn", usn)
return usn return usn
// return db.Update(db.Notes, bson.M{"_id": bson.ObjectIdHex(noteId)}, bson.M{"$inc": bson.M{"ReadNum": 1}}) // return db.Update(db.Notes, bson.M{"_id": bson.ObjectIdHex(noteId)}, bson.M{"$inc": bson.M{"ReadNum": 1}})
} }
func (this *UserService) GetUsn(userId string) int { func (this *UserService) GetUsn(userId string) int {
@@ -47,8 +47,8 @@ func (this *UserService) AddUser(user info.User) bool {
go func() { go func() {
emailService.RegisterSendActiveEmail(user, user.Email) emailService.RegisterSendActiveEmail(user, user.Email)
// 发送给我 life@leanote.com // 发送给我 life@leanote.com
emailService.SendEmail("life@leanote.com", "新增用户", "{header}用户名" + user.Email + "{footer}"); // emailService.SendEmail("life@leanote.com", "新增用户", "{header}用户名"+user.Email+"{footer}")
}(); }()
} }
return db.Insert(db.Users, user) return db.Insert(db.Users, user)
@@ -110,7 +110,7 @@ func (this *UserService) setUserLogo(user *info.User) {
} }
if user.Logo != "" && !strings.HasPrefix(user.Logo, "http") { if user.Logo != "" && !strings.HasPrefix(user.Logo, "http") {
user.Logo = strings.Trim(user.Logo, "/") user.Logo = strings.Trim(user.Logo, "/")
user.Logo = configService.GetSiteUrl() + "/" + user.Logo user.Logo = "/" + user.Logo
} }
} }
@@ -129,6 +129,7 @@ func (this *UserService) GetUserInfo(userId string) info.User {
this.setUserLogo(&user) this.setUserLogo(&user)
return user return user
} }
// 得到用户信息 email // 得到用户信息 email
func (this *UserService) GetUserInfoByEmail(email string) info.User { func (this *UserService) GetUserInfoByEmail(email string) info.User {
user := info.User{} user := info.User{}
@@ -137,6 +138,7 @@ func (this *UserService) GetUserInfoByEmail(email string) info.User {
this.setUserLogo(&user) this.setUserLogo(&user)
return user return user
} }
// 得到用户信息 username // 得到用户信息 username
func (this *UserService) GetUserInfoByUsername(username string) info.User { func (this *UserService) GetUserInfoByUsername(username string) info.User {
user := info.User{} user := info.User{}
@@ -163,6 +165,7 @@ func (this *UserService) ListUserInfosByEmails(emails []string) []info.User {
db.ListByQ(db.Users, bson.M{"Email": bson.M{"$in": emails}}, &users) db.ListByQ(db.Users, bson.M{"Email": bson.M{"$in": emails}}, &users)
return users return users
} }
// 用户信息即可 // 用户信息即可
func (this *UserService) MapUserInfoByUserIds(userIds []bson.ObjectId) map[bson.ObjectId]info.User { func (this *UserService) MapUserInfoByUserIds(userIds []bson.ObjectId) map[bson.ObjectId]info.User {
users := []info.User{} users := []info.User{}
@@ -175,6 +178,7 @@ func (this *UserService) MapUserInfoByUserIds(userIds []bson.ObjectId) map[bson.
} }
return userMap return userMap
} }
// 用户信息和博客设置信息 // 用户信息和博客设置信息
func (this *UserService) MapUserInfoAndBlogInfosByUserIds(userIds []bson.ObjectId) map[bson.ObjectId]info.User { func (this *UserService) MapUserInfoAndBlogInfosByUserIds(userIds []bson.ObjectId) map[bson.ObjectId]info.User {
return this.MapUserInfoByUserIds(userIds) return this.MapUserInfoByUserIds(userIds)
@@ -204,13 +208,13 @@ func (this *UserService) MapUserAndBlogByUserIds(userIds []bson.ObjectId) map[st
} }
userAndBlogMap[user.UserId.Hex()] = info.UserAndBlog{ userAndBlogMap[user.UserId.Hex()] = info.UserAndBlog{
UserId: user.UserId, UserId: user.UserId,
Username: user.Username, Username: user.Username,
Email: user.Email, Email: user.Email,
Logo: user.Logo, Logo: user.Logo,
BlogTitle: userBlog.Title, BlogTitle: userBlog.Title,
BlogLogo: userBlog.Logo, BlogLogo: userBlog.Logo,
BlogUrl: blogService.GetUserBlogUrl(&userBlog, user.Username), BlogUrl: blogService.GetUserBlogUrl(&userBlog, user.Username),
} }
} }
return userAndBlogMap return userAndBlogMap
@@ -224,7 +228,7 @@ func (this *UserService) GetUserAndBlogUrl(userId string) info.UserAndBlogUrl {
blogUrls := blogService.GetBlogUrls(&userBlog, &user) blogUrls := blogService.GetBlogUrls(&userBlog, &user)
return info.UserAndBlogUrl{ return info.UserAndBlogUrl{
User: user, User: user,
BlogUrl: blogUrls.IndexUrl, BlogUrl: blogUrls.IndexUrl,
PostUrl: blogUrls.PostUrl, PostUrl: blogUrls.PostUrl,
} }
@@ -249,7 +253,7 @@ func (this *UserService) GetUserAndBlog(userId string) info.UserAndBlog {
// 通过ids得到users, 按id的顺序组织users // 通过ids得到users, 按id的顺序组织users
func (this *UserService) GetUserInfosOrderBySeq(userIds []bson.ObjectId) []info.User { func (this *UserService) GetUserInfosOrderBySeq(userIds []bson.ObjectId) []info.User {
users := []info.User{} users := []info.User{}
db.ListByQ(db.Users, bson.M{"_id": bson.M{"$in": userIds}}, &users); db.ListByQ(db.Users, bson.M{"_id": bson.M{"$in": userIds}}, &users)
usersMap := map[bson.ObjectId]info.User{} usersMap := map[bson.ObjectId]info.User{}
for _, user := range users { for _, user := range users {
@@ -257,7 +261,7 @@ func (this *UserService) GetUserInfosOrderBySeq(userIds []bson.ObjectId) []info.
} }
hasAppend := map[bson.ObjectId]bool{} // 为了防止userIds有重复的 hasAppend := map[bson.ObjectId]bool{} // 为了防止userIds有重复的
users2 := []info.User{}; users2 := []info.User{}
for _, userId := range userIds { for _, userId := range userIds {
if user, ok := usersMap[userId]; ok && !hasAppend[userId] { if user, ok := usersMap[userId]; ok && !hasAppend[userId] {
hasAppend[userId] = true hasAppend[userId] = true
@@ -300,7 +304,7 @@ func (this *UserService) UpdateUsername(userId, username string) (bool, string)
} }
// 修改头像 // 修改头像
func (this *UserService) UpdateAvatar(userId, avatarPath string) (bool) { func (this *UserService) UpdateAvatar(userId, avatarPath string) bool {
userIdO := bson.ObjectIdHex(userId) userIdO := bson.ObjectIdHex(userId)
return db.UpdateByQField(db.Users, bson.M{"_id": userIdO}, "Logo", avatarPath) return db.UpdateByQField(db.Users, bson.M{"_id": userIdO}, "Logo", avatarPath)
} }
@@ -337,7 +341,7 @@ func (this *UserService) ResetPwd(adminUserId, userId, pwd string) (ok bool, msg
} }
// 修改主题 // 修改主题
func (this *UserService) UpdateTheme(userId, theme string) (bool) { func (this *UserService) UpdateTheme(userId, theme string) bool {
ok := db.UpdateByQField(db.Users, bson.M{"_id": bson.ObjectIdHex(userId)}, "Theme", theme) ok := db.UpdateByQField(db.Users, bson.M{"_id": bson.ObjectIdHex(userId)}, "Theme", theme)
return ok return ok
} }
@@ -346,15 +350,15 @@ func (this *UserService) UpdateTheme(userId, theme string) (bool) {
func (this *UserService) UpdateAccount(userId, accountType string, accountStartTime, accountEndTime time.Time, func (this *UserService) UpdateAccount(userId, accountType string, accountStartTime, accountEndTime time.Time,
maxImageNum, maxImageSize, maxAttachNum, maxAttachSize, maxPerAttachSize int) bool { maxImageNum, maxImageSize, maxAttachNum, maxAttachSize, maxPerAttachSize int) bool {
return db.UpdateByQI(db.Users, bson.M{"_id": bson.ObjectIdHex(userId)}, info.UserAccount{ return db.UpdateByQI(db.Users, bson.M{"_id": bson.ObjectIdHex(userId)}, info.UserAccount{
AccountType: accountType, AccountType: accountType,
AccountStartTime: accountStartTime, AccountStartTime: accountStartTime,
AccountEndTime: accountEndTime, AccountEndTime: accountEndTime,
MaxImageNum: maxImageNum, MaxImageNum: maxImageNum,
MaxImageSize: maxImageSize, MaxImageSize: maxImageSize,
MaxAttachNum: maxAttachNum, MaxAttachNum: maxAttachNum,
MaxAttachSize: maxAttachSize, MaxAttachSize: maxAttachSize,
MaxPerAttachSize: maxPerAttachSize, MaxPerAttachSize: maxPerAttachSize,
}) })
} }
//--------------- //---------------
@@ -408,36 +412,17 @@ func (this *UserService) UpdateEmail(token string) (ok bool, msg, email string)
return return
} }
//---------
// 第三方添加账号
func (this *UserService) ThirdAddUser(userId, email, pwd string) (ok bool, msg string) {
// 判断该用户是否已有了帐户
userInfo := this.GetUserInfo(userId)
if userInfo.Email != "" {
msg = "你已有帐户"
return
}
// 判断email是否存在
if this.IsExistsUser(email) {
msg = "该用户已存在"
return
}
ok = db.UpdateByQMap(db.Users, bson.M{"_id": bson.ObjectIdHex(userId)}, bson.M{"Email": email, "Pwd": Md5(pwd)})
return
}
//------------ //------------
// 偏好设置 // 偏好设置
// 宽度 // 宽度
func (this *UserService)UpdateColumnWidth(userId string, notebookWidth, noteListWidth, mdEditorWidth int) bool { func (this *UserService) UpdateColumnWidth(userId string, notebookWidth, noteListWidth, mdEditorWidth int) bool {
return db.UpdateByQMap(db.Users, bson.M{"_id": bson.ObjectIdHex(userId)}, return db.UpdateByQMap(db.Users, bson.M{"_id": bson.ObjectIdHex(userId)},
bson.M{"NotebookWidth": notebookWidth, "NoteListWidth": noteListWidth, "MdEditorWidth": mdEditorWidth}) bson.M{"NotebookWidth": notebookWidth, "NoteListWidth": noteListWidth, "MdEditorWidth": mdEditorWidth})
} }
// 左侧是否隐藏 // 左侧是否隐藏
func (this *UserService)UpdateLeftIsMin(userId string, leftIsMin bool) bool { func (this *UserService) UpdateLeftIsMin(userId string, leftIsMin bool) bool {
return db.UpdateByQMap(db.Users, bson.M{"_id": bson.ObjectIdHex(userId)}, bson.M{"LeftIsMin": leftIsMin}) return db.UpdateByQMap(db.Users, bson.M{"_id": bson.ObjectIdHex(userId)}, bson.M{"LeftIsMin": leftIsMin})
} }
@@ -454,7 +439,7 @@ func (this *UserService) ListUsers(pageNumber, pageSize int, sortField string, i
} }
query["$or"] = orQ query["$or"] = orQ
} }
q := db.Users.Find(query); q := db.Users.Find(query)
// 总记录数 // 总记录数
count, _ := q.Count() count, _ := q.Count()
// 列表 // 列表
@@ -479,9 +464,9 @@ func (this *UserService) GetAllUserByFilter(userFilterEmail, userFilterWhiteList
bson.M{"Username": bson.M{"$regex": bson.RegEx{".*?" + userFilterEmail + ".*", "i"}}}, bson.M{"Username": bson.M{"$regex": bson.RegEx{".*?" + userFilterEmail + ".*", "i"}}},
) )
} }
if(userFilterWhiteList != "") { if userFilterWhiteList != "" {
userFilterWhiteList = strings.Replace(userFilterWhiteList, "\r", "", -1) userFilterWhiteList = strings.Replace(userFilterWhiteList, "\r", "", -1)
emails := strings.Split(userFilterWhiteList, "\n"); emails := strings.Split(userFilterWhiteList, "\n")
orQ = append(orQ, bson.M{"Email": bson.M{"$in": emails}}) orQ = append(orQ, bson.M{"Email": bson.M{"$in": emails}})
} }
if len(orQ) > 0 { if len(orQ) > 0 {
@@ -489,16 +474,16 @@ func (this *UserService) GetAllUserByFilter(userFilterEmail, userFilterWhiteList
} }
emailQ := bson.M{} emailQ := bson.M{}
if(userFilterBlackList != "") { if userFilterBlackList != "" {
userFilterWhiteList = strings.Replace(userFilterBlackList, "\r", "", -1) userFilterWhiteList = strings.Replace(userFilterBlackList, "\r", "", -1)
bEmails := strings.Split(userFilterBlackList, "\n"); bEmails := strings.Split(userFilterBlackList, "\n")
emailQ["$nin"] = bEmails emailQ["$nin"] = bEmails
query["Email"] = emailQ query["Email"] = emailQ
} }
LogJ(query) LogJ(query)
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))
+1 -2
View File
@@ -1,7 +1,6 @@
package service package service
import ( import ()
)
// service 通用方法 // service 通用方法
+24 -7
View File
@@ -1,13 +1,14 @@
package service package service
import ( import (
"regexp"
"strings"
"net/url"
"strconv"
"gopkg.in/mgo.v2"
"github.com/leanote/leanote/app/db" "github.com/leanote/leanote/app/db"
. "github.com/leanote/leanote/app/lea"
"gopkg.in/mgo.v2"
"gopkg.in/mgo.v2/bson" "gopkg.in/mgo.v2/bson"
"net/url"
"regexp"
"strconv"
"strings"
) )
// init service, for share service bettween services // init service, for share service bettween services
@@ -150,12 +151,28 @@ func getUniqueUrlTitle(userId string, urlTitle string, types string, padding int
return urlTitle2 return urlTitle2
} }
// 截取id 24位变成12位
// 先md5, 再取12位
func subIdHalf(id string) string {
idMd5 := Md5(id)
return idMd5[:12]
}
// types == note,notebook,single // types == note,notebook,single
func GetUrTitle(userId string, title string, types string) string { // id noteId, notebookId, singleId 当title没的时候才有用, 用它来替换
func GetUrTitle(userId string, title string, types string, id string) string {
urlTitle := strings.Trim(title, " ") urlTitle := strings.Trim(title, " ")
if urlTitle == "" { if urlTitle == "" {
urlTitle = "Untitled-" + userId if id == "" {
urlTitle = "Untitled-" + userId
} else {
urlTitle = subIdHalf(id)
}
// 不允许title是ObjectId
} else if bson.IsObjectIdHex(title) {
urlTitle = subIdHalf(id)
} }
urlTitle = fixUrlTitle(urlTitle) urlTitle = fixUrlTitle(urlTitle)
return getUniqueUrlTitle(userId, urlTitle, types, 1) return getUniqueUrlTitle(userId, urlTitle, types, 1)
} }
+4 -4
View File
@@ -1,12 +1,12 @@
package tests package tests
import ( import (
"testing"
"github.com/leanote/leanote/app/db" "github.com/leanote/leanote/app/db"
// . "github.com/leanote/leanote/app/lea" "testing"
// . "github.com/leanote/leanote/app/lea"
"github.com/leanote/leanote/app/service" "github.com/leanote/leanote/app/service"
// "gopkg.in/mgo.v2" // "gopkg.in/mgo.v2"
// "fmt" // "fmt"
) )
func init() { func init() {
+6 -6
View File
@@ -1,14 +1,14 @@
package tests package tests
import ( import (
"testing"
"github.com/leanote/leanote/app/db" "github.com/leanote/leanote/app/db"
// . "github.com/leanote/leanote/app/lea" "testing"
// "github.com/leanote/leanote/app/service" // . "github.com/leanote/leanote/app/lea"
// "gopkg.in/mgo.v2" // "github.com/leanote/leanote/app/service"
// "fmt" // "gopkg.in/mgo.v2"
// "fmt"
) )
func TestDBConnect(t *testing.T) { func TestDBConnect(t *testing.T) {
db.Init("mongodb://localhost:27017/leanote", "leanote") db.Init("mongodb://localhost:27017/leanote", "leanote")
} }
+1
View File
@@ -1,3 +1,4 @@
package tests package tests
func a() { func a() {
} }
Loaded 100 of 1184 files, more files were not shown because too many files have changed in this diff. Show more