Compare commits
1
Commits
1.0.1
..
feature-api
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c26d25deab |
No files matched your search
+4
-3
@@ -2,12 +2,14 @@
|
|||||||
pkg
|
pkg
|
||||||
bin2
|
bin2
|
||||||
bin/i18n
|
bin/i18n
|
||||||
bin/leanote*
|
bin/leanote-linux
|
||||||
|
bin/leanote-mac
|
||||||
bin/release
|
bin/release
|
||||||
bin/test.sh
|
|
||||||
bin/tmp
|
bin/tmp
|
||||||
bin/test
|
bin/test
|
||||||
bin/src
|
bin/src
|
||||||
|
conf/app.conf
|
||||||
|
conf/routes
|
||||||
public/upload
|
public/upload
|
||||||
app/routes/routes.go
|
app/routes/routes.go
|
||||||
app/tmp/main.go
|
app/tmp/main.go
|
||||||
@@ -16,4 +18,3 @@ app/tmp/main.go
|
|||||||
.project
|
.project
|
||||||
public/config.codekit
|
public/config.codekit
|
||||||
files
|
files
|
||||||
/node_modules
|
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<projectDescription>
|
<projectDescription>
|
||||||
<name>leanote-public</name>
|
<name>leanote2</name>
|
||||||
<comment>leanote, your own cloud note!</comment>
|
<comment>leanote, your own cloud note!</comment>
|
||||||
<projects>
|
<projects>
|
||||||
</projects>
|
</projects>
|
||||||
|
|||||||
-19
@@ -1,19 +0,0 @@
|
|||||||
language: go
|
|
||||||
go: 1.3
|
|
||||||
|
|
||||||
services:
|
|
||||||
- mongodb # 2.4.12
|
|
||||||
|
|
||||||
install:
|
|
||||||
- export PATH=$PATH:$HOME/gopath/bin
|
|
||||||
- go get -v github.com/leanote/leanote/app
|
|
||||||
# - go get github.com/revel/cmd/revel
|
|
||||||
# - go install github.com/revel/cmd/revel
|
|
||||||
|
|
||||||
script:
|
|
||||||
- mongo --version
|
|
||||||
- mongorestore -h localhost -d leanote --directoryperdb ./mongodb_backup/leanote_install_data/
|
|
||||||
- go test github.com/leanote/leanote/app/tests
|
|
||||||
- go build -ldflags -X github.com/leanote/leanote/app
|
|
||||||
# - revel build github.com/leanote/leanote tmp
|
|
||||||
# OK
|
|
||||||
-138
@@ -1,138 +0,0 @@
|
|||||||
var gulp = require('gulp');
|
|
||||||
var clean = require('gulp-clean');
|
|
||||||
var uglify = require('gulp-uglify');
|
|
||||||
var rename = require('gulp-rename');
|
|
||||||
var minifyHtml = require("gulp-minify-html");
|
|
||||||
var concat = require('gulp-concat');
|
|
||||||
var replace = require('gulp-replace');
|
|
||||||
var inject = require('gulp-inject');
|
|
||||||
var gulpSequence = require('gulp-sequence');
|
|
||||||
|
|
||||||
var fs = require('fs');
|
|
||||||
|
|
||||||
var leanoteBase = './';
|
|
||||||
var base = leanoteBase + '/public'; // public base
|
|
||||||
var noteDev = leanoteBase + '/app/views/note/note-dev.html';
|
|
||||||
var noteProBase = leanoteBase + '/app/views/note';
|
|
||||||
|
|
||||||
// 合并Js, 这些js都是不怎么修改, 且是依赖
|
|
||||||
// 840kb, 非常耗时!!
|
|
||||||
gulp.task('concatDepJs', function() {
|
|
||||||
var jss = [
|
|
||||||
'js/jquery-1.9.0.min.js',
|
|
||||||
'js/jquery.ztree.all-3.5-min.js',
|
|
||||||
'tinymce/tinymce.full.min.js', // 使用打成的包, 加载速度快
|
|
||||||
// 'libs/ace/ace.js',
|
|
||||||
'js/jQuery-slimScroll-1.3.0/jquery.slimscroll-min.js',
|
|
||||||
'js/contextmenu/jquery.contextmenu-min.js',
|
|
||||||
'js/bootstrap-min.js',
|
|
||||||
'js/object_id-min.js',
|
|
||||||
];
|
|
||||||
|
|
||||||
for(var i in jss) {
|
|
||||||
jss[i] = base + '/' + jss[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
return gulp
|
|
||||||
.src(jss)
|
|
||||||
// .pipe(uglify()) // 压缩
|
|
||||||
.pipe(concat('dep.min.js'))
|
|
||||||
.pipe(gulp.dest(base + '/js'));
|
|
||||||
});
|
|
||||||
|
|
||||||
// 合并app js 这些js会经常变化 90kb
|
|
||||||
gulp.task('concatAppJs', function() {
|
|
||||||
var jss = [
|
|
||||||
'js/common.js',
|
|
||||||
'js/app/note.js',
|
|
||||||
'js/app/page.js', // 写作模式下, page依赖note
|
|
||||||
'js/app/tag.js',
|
|
||||||
'js/app/notebook.js',
|
|
||||||
'js/app/share.js',
|
|
||||||
];
|
|
||||||
|
|
||||||
for(var i in jss) {
|
|
||||||
jss[i] = base + '/' + jss[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
return gulp
|
|
||||||
.src(jss)
|
|
||||||
.pipe(uglify()) // 压缩
|
|
||||||
.pipe(concat('app.min.js'))
|
|
||||||
.pipe(gulp.dest(base + '/js'));
|
|
||||||
});
|
|
||||||
|
|
||||||
// 合并requirejs和markdown为一个文件
|
|
||||||
gulp.task('concatMarkdownJs', function() {
|
|
||||||
var jss = [
|
|
||||||
'js/require.js',
|
|
||||||
'dist/main.min.js',
|
|
||||||
];
|
|
||||||
|
|
||||||
for(var i in jss) {
|
|
||||||
jss[i] = base + '/' + jss[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
return gulp
|
|
||||||
.src(jss)
|
|
||||||
.pipe(uglify()) // 压缩
|
|
||||||
.pipe(concat('markdown.min.js'))
|
|
||||||
.pipe(gulp.dest(base + '/js'));
|
|
||||||
});
|
|
||||||
|
|
||||||
// note-dev.html -> note.html, 替换css, js
|
|
||||||
// TODO 加?t=2323232, 强制浏览器更新, 一般只需要把app.min.js上加
|
|
||||||
gulp.task('devToProHtml', function() {
|
|
||||||
return gulp
|
|
||||||
.src(noteDev)
|
|
||||||
.pipe(replace(/<!-- dev -->[.\s\S]+?<!-- \/dev -->/g, '')) // 把dev 去掉
|
|
||||||
.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_markdown_js -->/, '<script src="/js/markdown.min.js"></script>')) // 替换
|
|
||||||
.pipe(replace(/<!-- pro_tinymce_init_js -->/, "var tinyMCEPreInit = {base: '/public/tinymce', suffix: '.min'};")) // 替换
|
|
||||||
// 连续两个空行换成一个空行, 没用
|
|
||||||
.pipe(replace(/\n\n/g, '\n'))
|
|
||||||
.pipe(replace(/\n\n/g, '\n'))
|
|
||||||
.pipe(replace('console.log(o);', ''))
|
|
||||||
// .pipe(minifyHtml()) // 不行, 压缩后golang报错
|
|
||||||
.pipe(rename('note.html'))
|
|
||||||
.pipe(gulp.dest(noteProBase));
|
|
||||||
});
|
|
||||||
|
|
||||||
// tinymce
|
|
||||||
|
|
||||||
var tinymceBase = base + '/tinymce_4.1.9';
|
|
||||||
gulp.task('tinymce', function() {
|
|
||||||
// 先清理
|
|
||||||
fs.unlink(tinymceBase + '/js/tinymce/tinymce.dev.js');
|
|
||||||
fs.unlink(tinymceBase + '/js/tinymce/tinymce.jquery.dev.js');
|
|
||||||
fs.unlink(tinymceBase + '/js/tinymce/tinymce.full.js');
|
|
||||||
fs.unlink(tinymceBase + '/js/tinymce/tinymce.full.min.js');
|
|
||||||
|
|
||||||
var cp = require('child_process');
|
|
||||||
|
|
||||||
var bundleCmd = 'grunt bundle --themes leanote --plugins autolink,link,leaui_image,leaui_mind,lists,hr,paste,searchreplace,leanote_nav,leanote_code,tabfocus,table,directionality,textcolor';
|
|
||||||
// build
|
|
||||||
cp.exec('grunt minify', {cwd: tinymceBase}, function(err, stdout, stderr) {
|
|
||||||
console.log('stdout: ' + stdout);
|
|
||||||
console.log('stderr: ' + stderr);
|
|
||||||
|
|
||||||
// 将所有都合并成一起
|
|
||||||
cp.exec(bundleCmd, {cwd: tinymceBase}, function(err, stdout, stderr) {
|
|
||||||
console.log('stdout: ' + stdout);
|
|
||||||
console.log('stderr: ' + stderr);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// 合并css, 无用
|
|
||||||
gulp.task('concatCss', function() {
|
|
||||||
return gulp
|
|
||||||
.src([markdownRaw + '/css/default.css', markdownRaw + '/css/md.css'])
|
|
||||||
.pipe(concat('all.css'))
|
|
||||||
.pipe(gulp.dest(markdownMin));
|
|
||||||
});
|
|
||||||
|
|
||||||
gulp.task('concat', ['concatDepJs', 'concatAppJs', 'concatMarkdownJs']);
|
|
||||||
gulp.task('html', ['devToProHtml']);
|
|
||||||
gulp.task('default', ['concat', 'html']);
|
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
LEANOTE - NOT JUST A NOTEPAD!
|
leanote - you own cloud note!
|
||||||
|
|
||||||
Copyright 2014-2015 by the contributors
|
Copyright 2014 by the contributors
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
This program is free software; you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
@@ -12,7 +12,7 @@ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
GNU General Public License for more details.
|
GNU General Public License for more details.
|
||||||
|
|
||||||
Leanote is licensed under the GPL v2.
|
leanote is licensed under the GPL v2.
|
||||||
|
|
||||||
life(life@leanote.com, lifephp@gmail.com)
|
life(life@leanote.com, lifephp@gmail.com)
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,8 @@
|
|||||||
|
[中文](https://github.com/leanote/leanote#1-介绍)
|
||||||
|
|
||||||
# Leanote
|
|
||||||
[](https://gitter.im/leanote/leanote?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
|
|
||||||
[](https://travis-ci.org/leanote/leanote)
|
|
||||||
## 1. Introduction
|
## 1. Introduction
|
||||||
|
|
||||||
Leanote, not just a notepad!
|
Leanote, note just a notebook!
|
||||||

|
|
||||||
|
|
||||||
**Some Features**
|
**Some Features**
|
||||||
|
|
||||||
@@ -23,52 +20,175 @@ To be honest, our inspiration comes from Evernote. We use Evernote to manage our
|
|||||||
|
|
||||||
## 3. How to install leanote
|
## 3. How to install leanote
|
||||||
|
|
||||||
More information about how to install leanote please see:
|
### 3.1. Download leanote
|
||||||
* [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)
|
Leanote V1.0-beta has been released. Binaries:
|
||||||
|
|
||||||
|
* Linux: [leanote-linux-x86_64.v1.0-beta.bin.tar.gz](https://github.com/leanote/leanote/releases/download/1.0-beta/leanote-linux-x86_64.v1.0-beta.bin.tar.gz)
|
||||||
|
* MacOS X: [leanote-mac-x86_64.v1.0-beta.bin.tar.gz](https://github.com/leanote/leanote/releases/download/1.0-beta/leanote-mac-x86_64.v1.0-beta.bin.tar.gz)
|
||||||
|
|
||||||
|
### 3.2. Install MongoDB
|
||||||
|
|
||||||
|
Leanote is written in go using [revel](https://revel.github.io/) and [MongoDB](https://www.mongodb.org). Thus, you need to first install MongoDB.
|
||||||
|
|
||||||
|
For more tips please have a look at [our wiki](https://github.com/leanote/leanote/wiki/Install-Mongodb)
|
||||||
|
|
||||||
|
### 3.3. Import initial MongoDB data
|
||||||
|
|
||||||
|
The mongodb data is in `[PATH_TO_LEANOTE]/mongodb_backup/leanote_install_data`
|
||||||
|
|
||||||
|
```
|
||||||
|
$> mongorestore -h localhost -d leanote --directoryperdb PATH_TO_LEANOTE/mongodb_backup/leanote_install_data
|
||||||
|
```
|
||||||
|
|
||||||
|
The initial database contains two users:
|
||||||
|
|
||||||
|
```
|
||||||
|
user2 username: admin, password: abc123 (administrator)
|
||||||
|
user3 username: demo, password: demo@leanote.com (this user is for demo)
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3.4. Configuration
|
||||||
|
|
||||||
|
Modify `[PATH_TO_LEANOTE]/conf/app.conf`. Available configuration options are:
|
||||||
|
|
||||||
|
``mongodb`` **required**
|
||||||
|
|
||||||
|
```Shell
|
||||||
|
db.host=localhost
|
||||||
|
db.port=27017
|
||||||
|
db.dbname=leanote
|
||||||
|
db.username=
|
||||||
|
db.password=
|
||||||
|
```
|
||||||
|
|
||||||
|
``app.secret`` **required** **important**
|
||||||
|
The secret key used for cryptographic operations (revel.Sign).
|
||||||
|
|
||||||
|
FOR SECURITY, YOU MUST CHANGE IT!!
|
||||||
|
|
||||||
|
For more infomation please see `app/app.conf` and the [revel manuals](https://revel.github.io/)
|
||||||
|
|
||||||
|
### 3.5. Run leanote
|
||||||
|
|
||||||
|
```
|
||||||
|
$> cd PATH_TO_LEANOTE/bin
|
||||||
|
$> sudo sh run.sh
|
||||||
|
```
|
||||||
|
|
||||||
## 4. How to develop leanote
|
## 4. How to develop leanote
|
||||||
|
|
||||||
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 [How-to-develop-leanote](https://github.com/leanote/leanote/wiki/How-to-develop-leanote-%E5%A6%82%E4%BD%95%E5%BC%80%E5%8F%91leanote)
|
||||||
|
|
||||||
|
|
||||||
## 5. Docs
|
## 5. Contributors
|
||||||
* [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)
|
|
||||||
* [leanote blog theme api](https://github.com/leanote/leanote/wiki/leanote-blog-theme-api_en)
|
|
||||||
|
|
||||||
More docs please see [wiki](https://github.com/leanote/leanote/wiki).
|
|
||||||
|
|
||||||
## 6. Contributors
|
|
||||||
Thank you to all the [contributors](https://github.com/leanote/leanote/graphs/contributors) on
|
Thank you to all the [contributors](https://github.com/leanote/leanote/graphs/contributors) on
|
||||||
this project. Your help is much appreciated.
|
this project. Your help is much appreciated.
|
||||||
|
|
||||||
## 7.Join us
|
## 6. Contributing
|
||||||
|
|
||||||
Please fork this repository and contribute back using [pull requests](https://github.com/leanote/leanote/pulls).
|
Please fork this repository and contribute back using [pull requests](https://github.com/leanote/leanote/pulls).
|
||||||
|
|
||||||
If you find some problems or has some good ideas, please submit [issues](https://github.com/leanote/leanote/issues).
|
## Discussion
|
||||||
|
* [leanote bbs](http://bbs.leanote.com)
|
||||||
You are always welcomed!
|
* [leanote google group](https://groups.google.com/forum/#!forum/leanote)
|
||||||
|
* QQ Group: 158716820
|
||||||
## 8. Donation
|
|
||||||
Support us, [donate us](http://leanote.org/#donate). And thanks [donators](http://leanote.leanote.com/post/leanote-donation-list).
|
|
||||||
|
|
||||||
## 9. Related projects
|
|
||||||
* [Leanote Desktop App](https://github.com/leanote/desktop-app), [Download](http://app.leanote.com)
|
|
||||||
* [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/Dminter/leanote-android-client), development phase
|
|
||||||
|
|
||||||
And also, you are welcome to join us.
|
|
||||||
|
|
||||||
## 9. Support & Join us
|
|
||||||
|
|
||||||
* Email: leanote@leanote.com
|
|
||||||
* [Leanote BBS](http://bbs.leanote.com)
|
|
||||||
* [Leanote Google Group](https://groups.google.com/forum/#!forum/leanote)
|
|
||||||
* QQ Group: 158716820, 256076853
|
|
||||||
|
|
||||||
|
|
||||||
-----------------------------------------------------------------------
|
-----------------------------------------------------------------------
|
||||||
[中文](README_zh.md)
|
|
||||||
|
|
||||||
|
## 1. 介绍
|
||||||
|
|
||||||
|
Leanote, 不只是笔记!
|
||||||
|
|
||||||
|
**特性**
|
||||||
|
|
||||||
|
* 知识管理: 通过leanote来管理知识, leanote有易操作的界面, 包含两款编辑器tinymce和markdown. 在leanote, 你可以尽情享受写作.
|
||||||
|
* 分享: 你也可以通过分享知识给好友, 让好友拥有你的知识.
|
||||||
|
* 协作: 在分享的同时也可以与好友一起协作知识.
|
||||||
|
* 博客: leanote也可以作为你的博客, 将知识公开成博客, 让leanote把你的知识传播的更远!
|
||||||
|
|
||||||
|
## 2. 为什么我们要创建leanote?
|
||||||
|
说实话, 我们曾是evernote的忠实粉丝, 但是我们也发现evernote的不足:
|
||||||
|
* evernote的编辑器不能满足我们的需求, 不能贴代码(格式会乱掉, 作为程序员, 代码是我们的基本需求啊), 图片不能缩放.
|
||||||
|
* 我们是markdown的爱好者, 可是evernote竟然没有.
|
||||||
|
* 我们也想将知识公开, 所以我们有自己的博客, 如wordpress, 但为什么这两者不能合二为一呢?
|
||||||
|
* 还有...
|
||||||
|
|
||||||
|
## 3.安装leanote
|
||||||
|
leanote是一款私有云笔记, 你可以下载它安装在自己的服务器上, 当然也可以在 http://leanote.com 上注册.
|
||||||
|
|
||||||
|
这里详细整理了leanote二进版和leanote开发版的安装教程, 请移步至:
|
||||||
|
* [leanote二进制详细安装教程](https://github.com/leanote/leanote/wiki/leanote%E4%BA%8C%E8%BF%9B%E5%88%B6%E7%89%88%E8%AF%A6%E7%BB%86%E5%AE%89%E8%A3%85%E6%95%99%E7%A8%8B)
|
||||||
|
* [leanote开发版详细安装教程](https://github.com/leanote/leanote/wiki/leanote%E5%BC%80%E5%8F%91%E7%89%88%E8%AF%A6%E7%BB%86%E5%AE%89%E8%A3%85%E6%95%99%E7%A8%8B)
|
||||||
|
|
||||||
|
### 3.1. 下载leanote
|
||||||
|
|
||||||
|
Leanote V1.0-beta 已发布, 二进制文件(暂时没有windows版的):
|
||||||
|
|
||||||
|
* Linux: [leanote-linux-x86_64.v1.0-beta.bin.tar.gz](https://github.com/leanote/leanote/releases/download/1.0-beta/leanote-linux-x86_64.v1.0-beta.bin.tar.gz)
|
||||||
|
* MacOS X: [leanote-mac-x86_64.v1.0-beta.bin.tar.gz](https://github.com/leanote/leanote/releases/download/1.0-beta/leanote-mac-x86_64.v1.0-beta.bin.tar.gz)
|
||||||
|
|
||||||
|
### 3.2. 安装 MongodbDB
|
||||||
|
|
||||||
|
Leanote是由golang(使用[revel](https://revel.github.io/)框架 和 [MongoDB](https://www.mongodb.org)数据库), 你需要先安装Mongodb.
|
||||||
|
|
||||||
|
安装MongodbDB, 导入数据更多细节请查看: [wiki](https://github.com/leanote/leanote/wiki/Install-Mongodb)
|
||||||
|
|
||||||
|
### 3.3. 导入初始数据
|
||||||
|
|
||||||
|
MongodbDB初始数据在 `[PATH_TO_LEANOTE]/mongodb_backup/leanote_install_data`
|
||||||
|
|
||||||
|
```
|
||||||
|
$> mongorestore -h localhost -d leanote --directoryperdb PATH_TO_LEANOTE/mongodb_backup/leanote_install_data
|
||||||
|
```
|
||||||
|
|
||||||
|
初始数据包含两个用户:
|
||||||
|
|
||||||
|
```
|
||||||
|
user2 username: admin, password: abc123 (管理员, 重要!)
|
||||||
|
user3 username: demo@leanote.com, password: demo@leanote.com (为体验使用)
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3.4. 配置
|
||||||
|
|
||||||
|
修改 `[PATH_TO_LEANOTE]/conf/app.conf`. 有以下选项:
|
||||||
|
|
||||||
|
``mongodb`` **必须配置!**
|
||||||
|
|
||||||
|
```Shell
|
||||||
|
db.host=localhost
|
||||||
|
db.port=27017
|
||||||
|
db.dbname=leanote
|
||||||
|
db.username=
|
||||||
|
db.password=
|
||||||
|
```
|
||||||
|
|
||||||
|
``app.secret`` **重要**
|
||||||
|
请随意修改一个, app的密钥, 不能使用默认的, 不然会有安全问题
|
||||||
|
|
||||||
|
更多配置请查看 `app/app.conf` 和 [revel 手册](https://revel.github.io/)
|
||||||
|
|
||||||
|
### 3.5. 运行leanote
|
||||||
|
|
||||||
|
```
|
||||||
|
$> cd PATH_TO_LEANOTE/bin
|
||||||
|
$> sudo sh run.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
## 4. 如何对leanote进行二次开发
|
||||||
|
|
||||||
|
请查看 [How-to-develop-leanote](https://github.com/leanote/leanote/wiki/How-to-develop-leanote-%E5%A6%82%E4%BD%95%E5%BC%80%E5%8F%91leanote)
|
||||||
|
|
||||||
|
## 5. 贡献者
|
||||||
|
多谢 [贡献者](https://github.com/leanote/leanote/graphs/contributors) 的贡献, leanote因有你们而更完美!
|
||||||
|
|
||||||
|
## 6. 加入我们
|
||||||
|
|
||||||
|
欢迎提交[pull requests](https://github.com/leanote/leanote/pulls) 到leanote.
|
||||||
|
|
||||||
|
leanote还有很多问题, 如果你喜欢它, 欢迎加入我们一起完善leanote.
|
||||||
|
|
||||||
|
## 讨论
|
||||||
|
* [leanote 社区](http://bbs.leanote.com)
|
||||||
|
* QQ群: 158716820
|
||||||
|
* [leanote google group](https://groups.google.com/forum/#!forum/leanote)
|
||||||
@@ -1,73 +0,0 @@
|
|||||||
# Leanote
|
|
||||||
|
|
||||||
[](https://gitter.im/leanote/leanote?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
|
|
||||||
[](https://travis-ci.org/leanote/leanote)
|
|
||||||
## 1. 介绍
|
|
||||||
|
|
||||||
Leanote, 不只是笔记!
|
|
||||||

|
|
||||||
|
|
||||||
**特性**
|
|
||||||
|
|
||||||
* 知识管理: 通过leanote来管理知识, leanote有易操作的界面, 包含两款编辑器tinymce和markdown. 在leanote, 你可以尽情享受写作.
|
|
||||||
* 分享: 你也可以通过分享知识给好友, 让好友拥有你的知识.
|
|
||||||
* 协作: 在分享的同时也可以与好友一起协作知识.
|
|
||||||
* 博客: leanote也可以作为你的博客, 将知识公开成博客, 让leanote把你的知识传播的更远!
|
|
||||||
|
|
||||||
## 2. 为什么我们要创建leanote?
|
|
||||||
说实话, 我们曾是evernote的忠实粉丝, 但是我们也发现evernote的不足:
|
|
||||||
* evernote的编辑器不能满足我们的需求, 不能贴代码(格式会乱掉, 作为程序员, 代码是我们的基本需求啊), 图片不能缩放.
|
|
||||||
* 我们是markdown的爱好者, 可是evernote竟然没有.
|
|
||||||
* 我们也想将知识公开, 所以我们有自己的博客, 如wordpress, 但为什么这两者不能合二为一呢?
|
|
||||||
* 还有...
|
|
||||||
|
|
||||||
## 3.安装leanote
|
|
||||||
leanote是一款私有云笔记, 你可以下载它安装在自己的服务器上, 当然也可以在 http://leanote.com 上注册.
|
|
||||||
|
|
||||||
这里详细整理了leanote二进版和leanote开发版的安装教程, 请移步至:
|
|
||||||
|
|
||||||
* [leanote二进制详细安装教程](https://github.com/leanote/leanote/wiki/leanote%E4%BA%8C%E8%BF%9B%E5%88%B6%E7%89%88%E8%AF%A6%E7%BB%86%E5%AE%89%E8%A3%85%E6%95%99%E7%A8%8B)
|
|
||||||
* [leanote开发版详细安装教程](https://github.com/leanote/leanote/wiki/leanote%E5%BC%80%E5%8F%91%E7%89%88%E8%AF%A6%E7%BB%86%E5%AE%89%E8%A3%85%E6%95%99%E7%A8%8B)
|
|
||||||
|
|
||||||
## 4. 如何对leanote进行二次开发
|
|
||||||
|
|
||||||
请查看 [How-to-develop-leanote](https://github.com/leanote/leanote/wiki/How-to-develop-leanote-%E5%A6%82%E4%BD%95%E5%BC%80%E5%8F%91leanote)
|
|
||||||
|
|
||||||
## 5 相关文档
|
|
||||||
* [leanote二进制版详细安装教程](https://github.com/leanote/leanote/wiki/leanote%E4%BA%8C%E8%BF%9B%E5%88%B6%E7%89%88%E8%AF%A6%E7%BB%86%E5%AE%89%E8%A3%85%E6%95%99%E7%A8%8B)
|
|
||||||
* [leanote开发版详细安装教程](https://github.com/leanote/leanote/wiki/leanote%E5%BC%80%E5%8F%91%E7%89%88%E8%AF%A6%E7%BB%86%E5%AE%89%E8%A3%85%E6%95%99%E7%A8%8B)
|
|
||||||
* [Leanote source leanote源码导读](https://github.com/leanote/leanote/wiki/Leanote-source-leanote源码导读)
|
|
||||||
* [leanote blog theme api(中文版)](https://github.com/leanote/leanote/wiki/leanote-blog-theme-api)
|
|
||||||
* [How to develop leanote 如何开发leanote](https://github.com/leanote/leanote/wiki/How-to-develop-leanote-如何开发leanote)
|
|
||||||
|
|
||||||
更多文档请查看 [wiki](https://github.com/leanote/leanote/wiki).
|
|
||||||
|
|
||||||
## 6. 贡献者
|
|
||||||
多谢 [贡献者](https://github.com/leanote/leanote/graphs/contributors) 的贡献, leanote因有你们而更完美!
|
|
||||||
|
|
||||||
## 7. 加入我们
|
|
||||||
|
|
||||||
欢迎提交[pull requests](https://github.com/leanote/leanote/pulls) 到leanote.
|
|
||||||
|
|
||||||
有任何问题或建议, 欢迎提交[issue](https://github.com/leanote/leanote/issues).
|
|
||||||
|
|
||||||
Leanote还有很多问题, 如果你喜欢它, 欢迎加入我们一起完善leanote.
|
|
||||||
|
|
||||||
## 8. 捐赠
|
|
||||||
支持我们, [捐赠Leanote](http://leanote.org/#donate). 感谢[捐赠者](http://leanote.leanote.com/post/leanote-donation-list), 谢谢你们的鼓励, Leanote会一直坚持!
|
|
||||||
|
|
||||||
## 9. 其它相关项目
|
|
||||||
* [Leanote Desktop App](https://github.com/leanote/desktop-app), [下载地址](http://app.leanote.com)
|
|
||||||
* [Leanote IOS](https://github.com/leanote/leanote-ios), [从App Store下载](https://itunes.apple.com/zn/app/leanote/id1022302858?mt=8)
|
|
||||||
* [Leanote Android](https://github.com/Dminter/leanote-android-client), 开发阶段
|
|
||||||
|
|
||||||
欢迎加入我们!
|
|
||||||
|
|
||||||
## 联系&加入我们
|
|
||||||
* Email: leanote@leanote.com
|
|
||||||
* [leanote 社区](http://bbs.leanote.com)
|
|
||||||
* QQ群: 158716820, 256076853
|
|
||||||
* [Leanote Google Group](https://groups.google.com/forum/#!forum/leanote)
|
|
||||||
|
|
||||||
----------------------------------------------------------------
|
|
||||||
[English](README.md)
|
|
||||||
@@ -11,7 +11,6 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
"io"
|
"io"
|
||||||
"fmt"
|
|
||||||
"archive/tar"
|
"archive/tar"
|
||||||
"compress/gzip"
|
"compress/gzip"
|
||||||
)
|
)
|
||||||
@@ -57,12 +56,8 @@ func (c Attach) uploadAttach(noteId string) (re info.Re) {
|
|||||||
return re
|
return re
|
||||||
}
|
}
|
||||||
// > 5M?
|
// > 5M?
|
||||||
maxFileSize := configService.GetUploadSize("uploadAttachSize");
|
if(len(data) > 5 * 1024 * 1024) {
|
||||||
if maxFileSize <= 0 {
|
resultMsg = "File is bigger than 5M"
|
||||||
maxFileSize = 1000
|
|
||||||
}
|
|
||||||
if(float64(len(data)) > maxFileSize * float64(1024*1024)) {
|
|
||||||
resultMsg = fmt.Sprintf("The file's size is bigger than %vM", maxFileSize)
|
|
||||||
return re
|
return re
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -100,15 +95,11 @@ func (c Attach) uploadAttach(noteId string) (re info.Re) {
|
|||||||
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 = attachService.AddAttach(fileInfo)
|
||||||
if resultMsg != "" {
|
|
||||||
resultMsg = c.Message(resultMsg)
|
|
||||||
}
|
|
||||||
|
|
||||||
fileInfo.Path = ""; // 不要返回
|
fileInfo.Path = ""; // 不要返回
|
||||||
if Ok {
|
resultMsg = "success"
|
||||||
resultMsg = "success"
|
|
||||||
}
|
|
||||||
return re
|
return re
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -216,4 +207,4 @@ func (c Attach) DownloadAll(noteId string) revel.Result {
|
|||||||
// 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
|
||||||
}
|
}
|
||||||
@@ -40,16 +40,16 @@ func (c Auth) Login(email, from string) revel.Result {
|
|||||||
func (c Auth) doLogin(email, pwd string) revel.Result {
|
func (c Auth) doLogin(email, pwd string) revel.Result {
|
||||||
sessionId := c.Session.Id()
|
sessionId := c.Session.Id()
|
||||||
var msg = ""
|
var msg = ""
|
||||||
|
|
||||||
userInfo, err := authService.Login(email, pwd)
|
userInfo := authService.Login(email, pwd)
|
||||||
if err != nil {
|
if userInfo.Email != "" {
|
||||||
// 登录错误, 则错误次数++
|
|
||||||
msg = "wrongUsernameOrPassword"
|
|
||||||
} 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})
|
||||||
}
|
} else {
|
||||||
|
// 登录错误, 则错误次数++
|
||||||
|
msg = "wrongUsernameOrPassword"
|
||||||
|
}
|
||||||
|
|
||||||
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)})
|
||||||
}
|
}
|
||||||
@@ -61,16 +61,16 @@ func (c Auth) DoLogin(email, pwd string, captcha string) revel.Result {
|
|||||||
if sessionService.LoginTimesIsOver(sessionId) && sessionService.GetCaptcha(sessionId) != captcha {
|
if sessionService.LoginTimesIsOver(sessionId) && sessionService.GetCaptcha(sessionId) != captcha {
|
||||||
msg = "captchaError"
|
msg = "captchaError"
|
||||||
} else {
|
} else {
|
||||||
userInfo, err := authService.Login(email, pwd)
|
userInfo := authService.Login(email, pwd)
|
||||||
if err != nil {
|
if userInfo.Email != "" {
|
||||||
// 登录错误, 则错误次数++
|
|
||||||
msg = "wrongUsernameOrPassword"
|
|
||||||
sessionService.IncrLoginTimes(sessionId)
|
|
||||||
} 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})
|
||||||
}
|
} else {
|
||||||
|
// 登录错误, 则错误次数++
|
||||||
|
msg = "wrongUsernameOrPassword"
|
||||||
|
sessionService.IncrLoginTimes(sessionId)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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)})
|
||||||
@@ -85,33 +85,24 @@ func (c Auth) Logout() revel.Result {
|
|||||||
|
|
||||||
// 体验一下
|
// 体验一下
|
||||||
func (c Auth) Demo() revel.Result {
|
func (c Auth) Demo() revel.Result {
|
||||||
email := configService.GetGlobalStringConfig("demoUsername")
|
c.doLogin(configService.GetGlobalStringConfig("demoUsername"), configService.GetGlobalStringConfig("demoPassword"))
|
||||||
pwd := configService.GetGlobalStringConfig("demoPassword");
|
return c.Redirect("/note")
|
||||||
userInfo, err := authService.Login(email, pwd)
|
|
||||||
if err != nil {
|
|
||||||
return c.RenderJson(info.Re{Ok: false})
|
|
||||||
} else {
|
|
||||||
c.SetSession(userInfo)
|
|
||||||
return c.Redirect("/note")
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------
|
//--------
|
||||||
// 注册
|
// 注册
|
||||||
func (c Auth) Register(from, iu string) revel.Result {
|
func (c Auth) Register(from string) revel.Result {
|
||||||
if !configService.IsOpenRegister() {
|
if !configService.IsOpenRegister() {
|
||||||
return c.Redirect("/index")
|
return c.Redirect("/index")
|
||||||
}
|
}
|
||||||
c.SetLocale()
|
c.SetLocale()
|
||||||
c.RenderArgs["from"] = from
|
c.RenderArgs["from"] = from
|
||||||
c.RenderArgs["iu"] = iu
|
|
||||||
|
|
||||||
c.RenderArgs["title"] = c.Message("register")
|
c.RenderArgs["title"] = c.Message("register")
|
||||||
c.RenderArgs["subTitle"] = c.Message("register")
|
c.RenderArgs["subTitle"] = c.Message("register")
|
||||||
return c.RenderTemplate("home/register.html")
|
return c.RenderTemplate("home/register.html")
|
||||||
}
|
}
|
||||||
func (c Auth) DoRegister(email, pwd, iu string) revel.Result {
|
func (c Auth) DoRegister(email, pwd string) revel.Result {
|
||||||
if !configService.IsOpenRegister() {
|
if !configService.IsOpenRegister() {
|
||||||
return c.Redirect("/index")
|
return c.Redirect("/index")
|
||||||
}
|
}
|
||||||
@@ -126,7 +117,7 @@ func (c Auth) DoRegister(email, pwd, iu string) revel.Result {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 注册
|
// 注册
|
||||||
re.Ok, re.Msg = authService.Register(email, pwd, iu)
|
re.Ok, re.Msg = authService.Register(email, pwd)
|
||||||
|
|
||||||
// 注册成功, 则立即登录之
|
// 注册成功, 则立即登录之
|
||||||
if re.Ok {
|
if re.Ok {
|
||||||
|
|||||||
@@ -183,7 +183,7 @@ func (c BaseController) SetLocale() string {
|
|||||||
lang = "en";
|
lang = "en";
|
||||||
}
|
}
|
||||||
c.RenderArgs["locale"] = lang;
|
c.RenderArgs["locale"] = lang;
|
||||||
c.RenderArgs["siteUrl"] = configService.GetSiteUrl();
|
c.RenderArgs["siteUrl"] = siteUrl;
|
||||||
|
|
||||||
c.RenderArgs["blogUrl"] = configService.GetBlogUrl()
|
c.RenderArgs["blogUrl"] = configService.GetBlogUrl()
|
||||||
c.RenderArgs["leaUrl"] = configService.GetLeaUrl()
|
c.RenderArgs["leaUrl"] = configService.GetLeaUrl()
|
||||||
@@ -193,13 +193,9 @@ func (c BaseController) SetLocale() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 设置userInfo
|
// 设置userInfo
|
||||||
func (c BaseController) SetUserInfo() info.User {
|
func (c BaseController) SetUserInfo() {
|
||||||
userInfo := c.GetUserInfo()
|
userInfo := c.GetUserInfo()
|
||||||
c.RenderArgs["userInfo"] = userInfo
|
c.RenderArgs["userInfo"] = userInfo
|
||||||
if(userInfo.Username == configService.GetAdminUsername()) {
|
|
||||||
c.RenderArgs["isAdmin"] = true
|
|
||||||
}
|
|
||||||
return userInfo
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// life
|
// life
|
||||||
@@ -225,7 +221,6 @@ func (c BaseController) RenderTemplateStr(templatePath string) string {
|
|||||||
// 为了msg
|
// 为了msg
|
||||||
// msg-v1-v2-v3
|
// msg-v1-v2-v3
|
||||||
func (c BaseController) RenderRe(re info.Re) revel.Result {
|
func (c BaseController) RenderRe(re info.Re) revel.Result {
|
||||||
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, "-")
|
||||||
@@ -243,8 +238,5 @@ func (c BaseController) RenderRe(re info.Re) revel.Result {
|
|||||||
re.Msg = c.Message(re.Msg)
|
re.Msg = c.Message(re.Msg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if strings.HasPrefix(re.Msg, "???") {
|
|
||||||
re.Msg = oldMsg
|
|
||||||
}
|
|
||||||
return c.RenderJson(re)
|
return c.RenderJson(re)
|
||||||
}
|
}
|
||||||
+341
-741
File diff suppressed because it is too large.
Load diff
@@ -9,8 +9,7 @@ import (
|
|||||||
"github.com/leanote/leanote/app/info"
|
"github.com/leanote/leanote/app/info"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"fmt"
|
"strconv"
|
||||||
// "strconv"
|
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -22,7 +21,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("logo", "");
|
||||||
|
|
||||||
c.RenderArgs["fileUrlPath"] = re.Id
|
c.RenderArgs["fileUrlPath"] = re.Id
|
||||||
c.RenderArgs["resultCode"] = re.Code
|
c.RenderArgs["resultCode"] = re.Code
|
||||||
@@ -85,7 +84,7 @@ func (c File) uploadImage(from, albumId string) (re info.Re) {
|
|||||||
var fileUrlPath = ""
|
var fileUrlPath = ""
|
||||||
var fileId = ""
|
var fileId = ""
|
||||||
var resultCode = 0 // 1表示正常
|
var resultCode = 0 // 1表示正常
|
||||||
var resultMsg = "error" // 错误信息
|
var resultMsg = "内部错误" // 错误信息
|
||||||
var Ok = false
|
var Ok = false
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
@@ -101,7 +100,7 @@ func (c File) uploadImage(from, albumId string) (re info.Re) {
|
|||||||
}
|
}
|
||||||
defer file.Close()
|
defer file.Close()
|
||||||
// 生成上传路径
|
// 生成上传路径
|
||||||
if(from == "logo" || from == "blogLogo") {
|
if(from == "logo") {
|
||||||
fileUrlPath = "public/upload/" + c.GetUserId() + "/images/logo"
|
fileUrlPath = "public/upload/" + c.GetUserId() + "/images/logo"
|
||||||
} else {
|
} else {
|
||||||
fileUrlPath = "files/" + c.GetUserId() + "/images"
|
fileUrlPath = "files/" + c.GetUserId() + "/images"
|
||||||
@@ -120,7 +119,7 @@ func (c File) uploadImage(from, albumId string) (re info.Re) {
|
|||||||
} else {
|
} else {
|
||||||
_, 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") {
|
||||||
resultMsg = "Please upload image"
|
resultMsg = "不是图片"
|
||||||
return re
|
return re
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -132,22 +131,10 @@ func (c File) uploadImage(from, albumId string) (re info.Re) {
|
|||||||
return re
|
return re
|
||||||
}
|
}
|
||||||
|
|
||||||
var maxFileSize float64
|
|
||||||
if(from == "logo") {
|
|
||||||
maxFileSize = configService.GetUploadSize("uploadAvatarSize");
|
|
||||||
} else if from == "blogLogo" {
|
|
||||||
maxFileSize = configService.GetUploadSize("uploadBlogLogoSize");
|
|
||||||
} else {
|
|
||||||
maxFileSize = configService.GetUploadSize("uploadImageSize");
|
|
||||||
}
|
|
||||||
if maxFileSize <= 0 {
|
|
||||||
maxFileSize = 1000
|
|
||||||
}
|
|
||||||
|
|
||||||
// > 2M?
|
// > 2M?
|
||||||
if(float64(len(data)) > maxFileSize * float64(1024*1024)) {
|
if(len(data) > 5 * 1024 * 1024) {
|
||||||
resultCode = 0
|
resultCode = 0
|
||||||
resultMsg = fmt.Sprintf("The file Size is bigger than %vM", maxFileSize)
|
resultMsg = "图片大于2M"
|
||||||
return re
|
return re
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -163,7 +150,7 @@ func (c File) uploadImage(from, albumId string) (re info.Re) {
|
|||||||
filesize := GetFilesize(toPathGif)
|
filesize := GetFilesize(toPathGif)
|
||||||
fileUrlPath += "/" + filename
|
fileUrlPath += "/" + filename
|
||||||
resultCode = 1
|
resultCode = 1
|
||||||
resultMsg = "Upload Success!"
|
resultMsg = "上传成功!"
|
||||||
|
|
||||||
// File
|
// File
|
||||||
fileInfo := info.File{Name: filename,
|
fileInfo := info.File{Name: filename,
|
||||||
@@ -174,12 +161,11 @@ func (c File) uploadImage(from, albumId string) (re info.Re) {
|
|||||||
id := bson.NewObjectId();
|
id := bson.NewObjectId();
|
||||||
fileInfo.FileId = id
|
fileInfo.FileId = id
|
||||||
fileId = id.Hex()
|
fileId = id.Hex()
|
||||||
if(from == "logo" || from == "blogLogo") {
|
if(from == "logo") {
|
||||||
fileId = "public/upload/" + c.GetUserId() + "/images/logo/" + filename
|
fileId = "public/upload/" + c.GetUserId() + "/images/logo/" + filename
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok, resultMsg = fileService.AddImage(fileInfo, albumId, c.GetUserId(), from == "" || from == "pasteImage")
|
Ok = fileService.AddImage(fileInfo, albumId, c.GetUserId())
|
||||||
resultMsg = c.Message(resultMsg)
|
|
||||||
|
|
||||||
fileInfo.Path = ""; // 不要返回
|
fileInfo.Path = ""; // 不要返回
|
||||||
re.Item = fileInfo
|
re.Item = fileInfo
|
||||||
@@ -204,6 +190,55 @@ func (c File) DeleteImage(fileId string) revel.Result {
|
|||||||
re.Ok, re.Msg = fileService.DeleteImage(c.GetUserId(), fileId)
|
re.Ok, re.Msg = fileService.DeleteImage(c.GetUserId(), fileId)
|
||||||
return c.RenderJson(re)
|
return c.RenderJson(re)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// update image uploader to leaui image,
|
||||||
|
// scan all user's images and insert into db
|
||||||
|
func (c File) UpgradeLeauiImage() revel.Result {
|
||||||
|
re := info.NewRe()
|
||||||
|
|
||||||
|
if ok, _ := revel.Config.Bool("upgradeLeauiImage"); !ok {
|
||||||
|
re.Msg = "Not allowed"
|
||||||
|
return c.RenderJson(re)
|
||||||
|
}
|
||||||
|
|
||||||
|
uploadPath := revel.BasePath + "/public/upload";
|
||||||
|
userIds := ListDir(uploadPath)
|
||||||
|
if userIds == nil {
|
||||||
|
re.Msg = "no user"
|
||||||
|
return c.RenderJson(re)
|
||||||
|
}
|
||||||
|
|
||||||
|
msg := "";
|
||||||
|
|
||||||
|
for _, userId := range userIds {
|
||||||
|
dirPath := uploadPath + "/" + userId + "/images"
|
||||||
|
images := ListDir(dirPath)
|
||||||
|
if images == nil {
|
||||||
|
msg += userId + " no images "
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
hadImages := fileService.GetAllImageNamesMap(userId)
|
||||||
|
|
||||||
|
i := 0
|
||||||
|
for _, filename := range images {
|
||||||
|
if _, ok := hadImages[filename]; !ok {
|
||||||
|
fileUrlPath := "/upload/" + userId + "/images/" + filename
|
||||||
|
fileInfo := info.File{Name: filename,
|
||||||
|
Title: filename,
|
||||||
|
Path: fileUrlPath,
|
||||||
|
Size: GetFilesize(dirPath + "/" + filename)}
|
||||||
|
fileService.AddImage(fileInfo, "", userId)
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
msg += userId + ": " + strconv.Itoa(len(images)) + " -- " + strconv.Itoa(i) + " images "
|
||||||
|
}
|
||||||
|
|
||||||
|
re.Msg = msg
|
||||||
|
return c.RenderJson(re)
|
||||||
|
}
|
||||||
|
|
||||||
//-----------
|
//-----------
|
||||||
|
|
||||||
// 输出image
|
// 输出image
|
||||||
@@ -219,15 +254,15 @@ func (c File) OutputImage(noteId, fileId string) revel.Result {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 协作时复制图片到owner
|
// 协作时复制图片到owner
|
||||||
// 需要计算对方大小
|
|
||||||
func (c File) CopyImage(userId, fileId, toUserId string) revel.Result {
|
func (c File) CopyImage(userId, fileId, toUserId string) revel.Result {
|
||||||
re := info.NewRe()
|
re := info.NewRe()
|
||||||
|
|
||||||
re.Ok, re.Id = fileService.CopyImage(userId, fileId, toUserId)
|
re.Ok, re.Id = fileService.CopyImage(userId, fileId, toUserId)
|
||||||
|
|
||||||
return c.RenderJson(re)
|
return c.RenderJson(re)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 复制外网的图片, 成公共图片 放在/upload下
|
// 复制外网的图片, 成公共图片 放在/upload下
|
||||||
// 都要好好的计算大小
|
|
||||||
func (c File) CopyHttpImage(src string) revel.Result {
|
func (c File) CopyHttpImage(src string) revel.Result {
|
||||||
re := info.NewRe()
|
re := info.NewRe()
|
||||||
fileUrlPath := "upload/" + c.GetUserId() + "/images"
|
fileUrlPath := "upload/" + c.GetUserId() + "/images"
|
||||||
@@ -254,7 +289,29 @@ func (c File) CopyHttpImage(src string) revel.Result {
|
|||||||
|
|
||||||
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 = fileService.AddImage(fileInfo, "", c.GetUserId())
|
||||||
|
|
||||||
|
return c.RenderJson(re)
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------
|
||||||
|
// 过时 已弃用!
|
||||||
|
func (c File) UploadImage(renderHtml string) revel.Result {
|
||||||
|
if renderHtml == "" {
|
||||||
|
renderHtml = "file/image.html"
|
||||||
|
}
|
||||||
|
|
||||||
|
re := c.uploadImage("", "");
|
||||||
|
|
||||||
|
c.RenderArgs["fileUrlPath"] = siteUrl + re.Id
|
||||||
|
c.RenderArgs["resultCode"] = re.Code
|
||||||
|
c.RenderArgs["resultMsg"] = re.Msg
|
||||||
|
|
||||||
|
return c.RenderTemplate(renderHtml)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 已弃用
|
||||||
|
func (c File) UploadImageJson(from, noteId string) revel.Result {
|
||||||
|
re := c.uploadImage(from, "");
|
||||||
return c.RenderJson(re)
|
return c.RenderJson(re)
|
||||||
}
|
}
|
||||||
@@ -12,16 +12,8 @@ type Index struct {
|
|||||||
BaseController
|
BaseController
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c Index) Default() revel.Result {
|
|
||||||
if configService.HomePageIsAdminsBlog(){
|
|
||||||
blog := Blog{c.BaseController}
|
|
||||||
return blog.Index(configService.GetAdminUsername());
|
|
||||||
}
|
|
||||||
return c.Index()
|
|
||||||
}
|
|
||||||
// leanote展示页, 没有登录的, 或已登录明确要进该页的
|
// leanote展示页, 没有登录的, 或已登录明确要进该页的
|
||||||
func (c Index) Index() revel.Result {
|
func (c Index) Index() revel.Result {
|
||||||
|
|
||||||
c.SetUserInfo()
|
c.SetUserInfo()
|
||||||
c.RenderArgs["title"] = "leanote"
|
c.RenderArgs["title"] = "leanote"
|
||||||
c.RenderArgs["openRegister"] = configService.GlobalStringConfigs["openRegister"]
|
c.RenderArgs["openRegister"] = configService.GlobalStringConfigs["openRegister"]
|
||||||
|
|||||||
@@ -0,0 +1,44 @@
|
|||||||
|
package controllers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/revel/revel"
|
||||||
|
// "github.com/leanote/leanote/app/info"
|
||||||
|
)
|
||||||
|
|
||||||
|
// 首页
|
||||||
|
type Mobile struct {
|
||||||
|
BaseController
|
||||||
|
}
|
||||||
|
|
||||||
|
// leanote展示页, 没有登录的, 或已登录明确要进该页的
|
||||||
|
func (c Mobile) Index() revel.Result {
|
||||||
|
c.SetLocale()
|
||||||
|
|
||||||
|
userInfo := c.GetUserInfo()
|
||||||
|
userId := userInfo.UserId.Hex()
|
||||||
|
|
||||||
|
// 没有登录
|
||||||
|
if userId == "" {
|
||||||
|
return c.RenderTemplate("mobile/login.html")
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
// 已登录了, 那么得到所有信息
|
||||||
|
notebooks := notebookService.GetNotebooks(userId)
|
||||||
|
shareNotebooks, sharedUserInfos := shareService.GetShareNotebooks(userId)
|
||||||
|
|
||||||
|
c.RenderArgs["userInfo"] = userInfo
|
||||||
|
c.RenderArgs["userInfoJson"] = c.Json(userInfo)
|
||||||
|
c.RenderArgs["notebooks"] = c.Json(notebooks)
|
||||||
|
c.RenderArgs["shareNotebooks"] = c.Json(shareNotebooks)
|
||||||
|
c.RenderArgs["sharedUserInfos"] = c.Json(sharedUserInfos)
|
||||||
|
c.RenderArgs["tagsJson"] = c.Json(tagService.GetTags(c.GetUserId()))
|
||||||
|
*/
|
||||||
|
|
||||||
|
return c.RenderTemplate("mobile/angular.html");
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c Mobile) Logout() revel.Result {
|
||||||
|
c.ClearSession()
|
||||||
|
return c.RenderTemplate("mobile/login.html");
|
||||||
|
}
|
||||||
+156
-103
@@ -6,8 +6,7 @@ import (
|
|||||||
"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"
|
||||||
"strings"
|
"os/exec"
|
||||||
// "time"
|
|
||||||
// "github.com/leanote/leanote/app/types"
|
// "github.com/leanote/leanote/app/types"
|
||||||
// "io/ioutil"
|
// "io/ioutil"
|
||||||
// "fmt"
|
// "fmt"
|
||||||
@@ -22,8 +21,9 @@ type Note struct {
|
|||||||
// 笔记首页, 判断是否已登录
|
// 笔记首页, 判断是否已登录
|
||||||
// 已登录, 得到用户基本信息(notebook, shareNotebook), 跳转到index.html中
|
// 已登录, 得到用户基本信息(notebook, shareNotebook), 跳转到index.html中
|
||||||
// 否则, 转向登录页面
|
// 否则, 转向登录页面
|
||||||
func (c Note) Index(noteId string) revel.Result {
|
func (c Note) Index() revel.Result {
|
||||||
c.SetLocale()
|
c.SetLocale()
|
||||||
|
|
||||||
userInfo := c.GetUserInfo()
|
userInfo := c.GetUserInfo()
|
||||||
|
|
||||||
userId := userInfo.UserId.Hex()
|
userId := userInfo.UserId.Hex()
|
||||||
@@ -34,7 +34,7 @@ func (c Note) Index(noteId string) revel.Result {
|
|||||||
}
|
}
|
||||||
|
|
||||||
c.RenderArgs["openRegister"] = configService.IsOpenRegister()
|
c.RenderArgs["openRegister"] = configService.IsOpenRegister()
|
||||||
|
|
||||||
// 已登录了, 那么得到所有信息
|
// 已登录了, 那么得到所有信息
|
||||||
notebooks := notebookService.GetNotebooks(userId)
|
notebooks := notebookService.GetNotebooks(userId)
|
||||||
shareNotebooks, sharedUserInfos := shareService.GetShareNotebooks(userId)
|
shareNotebooks, sharedUserInfos := shareService.GetShareNotebooks(userId)
|
||||||
@@ -42,91 +42,30 @@ func (c Note) Index(noteId string) revel.Result {
|
|||||||
// 还需要按时间排序(DESC)得到notes
|
// 还需要按时间排序(DESC)得到notes
|
||||||
notes := []info.Note{}
|
notes := []info.Note{}
|
||||||
noteContent := info.NoteContent{}
|
noteContent := info.NoteContent{}
|
||||||
|
|
||||||
if len(notebooks) > 0 {
|
if len(notebooks) > 0 {
|
||||||
// noteId是否存在
|
// _, notes = noteService.ListNotes(c.GetUserId(), "", false, c.GetPage(), pageSize, defaultSortField, false, false);
|
||||||
// 是否传入了正确的noteId
|
// 变成最新
|
||||||
hasRightNoteId := false
|
_, notes = noteService.ListNotes(c.GetUserId(), "", false, c.GetPage(), 50, defaultSortField, false, false);
|
||||||
if IsObjectId(noteId) {
|
if len(notes) > 0 {
|
||||||
note := noteService.GetNoteById(noteId)
|
noteContent = noteService.GetNoteContent(notes[0].NoteId.Hex(), userId)
|
||||||
|
|
||||||
if note.NoteId != "" {
|
|
||||||
var noteOwner = note.UserId.Hex()
|
|
||||||
noteContent = noteService.GetNoteContent(noteId, noteOwner)
|
|
||||||
|
|
||||||
hasRightNoteId = true
|
|
||||||
c.RenderArgs["curNoteId"] = noteId
|
|
||||||
c.RenderArgs["curNotebookId"] = note.NotebookId.Hex()
|
|
||||||
|
|
||||||
// 打开的是共享的笔记, 那么判断是否是共享给我的默认笔记
|
|
||||||
if noteOwner != c.GetUserId() {
|
|
||||||
if shareService.HasReadPerm(noteOwner, c.GetUserId(), noteId) {
|
|
||||||
// 不要获取notebook下的笔记
|
|
||||||
// 在前端下发请求
|
|
||||||
c.RenderArgs["curSharedNoteNotebookId"] = note.NotebookId.Hex()
|
|
||||||
c.RenderArgs["curSharedUserId"] = noteOwner;
|
|
||||||
// 没有读写权限
|
|
||||||
} else {
|
|
||||||
hasRightNoteId = false
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
_, notes = noteService.ListNotes(c.GetUserId(), note.NotebookId.Hex(), false, c.GetPage(), 50, defaultSortField, false, false);
|
|
||||||
|
|
||||||
// 如果指定了某笔记, 则该笔记放在首位
|
|
||||||
lenNotes := len(notes)
|
|
||||||
if lenNotes > 1 {
|
|
||||||
notes2 := make([]info.Note, len(notes))
|
|
||||||
notes2[0] = note
|
|
||||||
i := 1
|
|
||||||
for _, note := range notes {
|
|
||||||
if note.NoteId.Hex() != noteId {
|
|
||||||
if i == lenNotes { // 防止越界
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
notes2[i] = note
|
|
||||||
i++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
notes = notes2
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 得到最近的笔记
|
|
||||||
_, latestNotes := noteService.ListNotes(c.GetUserId(), "", false, c.GetPage(), 50, defaultSortField, false, false);
|
|
||||||
c.RenderArgs["latestNotes"] = latestNotes
|
|
||||||
}
|
|
||||||
|
|
||||||
// 没有传入笔记
|
|
||||||
// 那么得到最新笔记
|
|
||||||
if !hasRightNoteId {
|
|
||||||
_, notes = noteService.ListNotes(c.GetUserId(), "", false, c.GetPage(), 50, defaultSortField, false, false);
|
|
||||||
if len(notes) > 0 {
|
|
||||||
noteContent = noteService.GetNoteContent(notes[0].NoteId.Hex(), userId)
|
|
||||||
c.RenderArgs["curNoteId"] = notes[0].NoteId.Hex()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 当然, 还需要得到第一个notes的content
|
// 当然, 还需要得到第一个notes的content
|
||||||
//...
|
//...
|
||||||
c.RenderArgs["isAdmin"] = configService.GetAdminUsername() == userInfo.Username
|
|
||||||
|
|
||||||
|
c.RenderArgs["isAdmin"] = leanoteUserId == userInfo.Username
|
||||||
c.RenderArgs["userInfo"] = userInfo
|
c.RenderArgs["userInfo"] = userInfo
|
||||||
c.RenderArgs["notebooks"] = notebooks
|
c.RenderArgs["userInfoJson"] = c.Json(userInfo)
|
||||||
c.RenderArgs["shareNotebooks"] = shareNotebooks // note信息在notes列表中
|
c.RenderArgs["notebooks"] = c.Json(notebooks)
|
||||||
c.RenderArgs["sharedUserInfos"] = sharedUserInfos
|
c.RenderArgs["shareNotebooks"] = c.Json(shareNotebooks)
|
||||||
|
c.RenderArgs["sharedUserInfos"] = c.Json(sharedUserInfos)
|
||||||
|
|
||||||
c.RenderArgs["notes"] = notes
|
c.RenderArgs["notes"] = c.Json(notes)
|
||||||
c.RenderArgs["noteContentJson"] = noteContent
|
c.RenderArgs["noteContentJson"] = c.Json(noteContent)
|
||||||
c.RenderArgs["noteContent"] = noteContent.Content
|
c.RenderArgs["noteContent"] = noteContent.Content
|
||||||
|
|
||||||
c.RenderArgs["tags"] = tagService.GetTags(c.GetUserId())
|
c.RenderArgs["tagsJson"] = c.Json(tagService.GetTags(c.GetUserId()))
|
||||||
|
|
||||||
c.RenderArgs["globalConfigs"] = configService.GetGlobalConfigForUser()
|
|
||||||
|
|
||||||
// return c.RenderTemplate("note/note.html")
|
|
||||||
|
|
||||||
if isDev, _ := revel.Config.Bool("mode.dev"); isDev {
|
if isDev, _ := revel.Config.Bool("mode.dev"); isDev {
|
||||||
return c.RenderTemplate("note/note-dev.html")
|
return c.RenderTemplate("note/note-dev.html")
|
||||||
} else {
|
} else {
|
||||||
@@ -169,7 +108,7 @@ type NoteOrContent struct {
|
|||||||
Title string
|
Title string
|
||||||
Desc string
|
Desc string
|
||||||
ImgSrc string
|
ImgSrc string
|
||||||
Tags string
|
Tags []string
|
||||||
Content string
|
Content string
|
||||||
Abstract string
|
Abstract string
|
||||||
IsNew bool
|
IsNew bool
|
||||||
@@ -182,7 +121,7 @@ func (c Note) UpdateNoteOrContent(noteOrContent 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)
|
||||||
@@ -192,7 +131,7 @@ func (c Note) UpdateNoteOrContent(noteOrContent NoteOrContent) revel.Result {
|
|||||||
NoteId: bson.ObjectIdHex(noteOrContent.NoteId),
|
NoteId: bson.ObjectIdHex(noteOrContent.NoteId),
|
||||||
NotebookId: bson.ObjectIdHex(noteOrContent.NotebookId),
|
NotebookId: bson.ObjectIdHex(noteOrContent.NotebookId),
|
||||||
Title: noteOrContent.Title,
|
Title: noteOrContent.Title,
|
||||||
Tags: strings.Split(noteOrContent.Tags, ","),
|
Tags: noteOrContent.Tags,
|
||||||
Desc: noteOrContent.Desc,
|
Desc: noteOrContent.Desc,
|
||||||
ImgSrc: noteOrContent.ImgSrc,
|
ImgSrc: noteOrContent.ImgSrc,
|
||||||
IsBlog: noteOrContent.IsBlog,
|
IsBlog: noteOrContent.IsBlog,
|
||||||
@@ -204,7 +143,7 @@ func (c Note) UpdateNoteOrContent(noteOrContent NoteOrContent) revel.Result {
|
|||||||
Content: noteOrContent.Content,
|
Content: noteOrContent.Content,
|
||||||
Abstract: noteOrContent.Abstract};
|
Abstract: noteOrContent.Abstract};
|
||||||
|
|
||||||
note = noteService.AddNoteAndContentForController(note, noteContent, c.GetUserId())
|
note = noteService.AddNoteAndContent(note, noteContent, myUserId)
|
||||||
return c.RenderJson(note)
|
return c.RenderJson(note)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -225,31 +164,22 @@ func (c Note) UpdateNoteOrContent(noteOrContent NoteOrContent) revel.Result {
|
|||||||
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"] = noteOrContent.Tags;
|
||||||
}
|
}
|
||||||
|
|
||||||
// web端不控制
|
|
||||||
if needUpdateNote {
|
if needUpdateNote {
|
||||||
noteService.UpdateNote(c.GetUserId(),
|
noteService.UpdateNote(noteOrContent.UserId, c.GetUserId(),
|
||||||
noteOrContent.NoteId, noteUpdate, -1)
|
noteOrContent.NoteId, noteUpdate)
|
||||||
}
|
}
|
||||||
|
|
||||||
//-------------
|
//-------------
|
||||||
afterContentUsn := 0
|
|
||||||
contentOk := false
|
|
||||||
contentMsg := ""
|
|
||||||
if c.Has("Content") {
|
|
||||||
// noteService.UpdateNoteContent(noteOrContent.UserId, c.GetUserId(),
|
|
||||||
// noteOrContent.NoteId, noteOrContent.Content, noteOrContent.Abstract)
|
|
||||||
contentOk, contentMsg, afterContentUsn = noteService.UpdateNoteContent(c.GetUserId(),
|
|
||||||
noteOrContent.NoteId, noteOrContent.Content, noteOrContent.Abstract, needUpdateNote, -1)
|
|
||||||
}
|
|
||||||
|
|
||||||
Log(afterContentUsn)
|
if c.Has("Content") {
|
||||||
Log(contentOk)
|
noteService.UpdateNoteContent(noteOrContent.UserId, c.GetUserId(),
|
||||||
Log(contentMsg)
|
noteOrContent.NoteId, noteOrContent.Content, noteOrContent.Abstract)
|
||||||
|
}
|
||||||
|
|
||||||
return c.RenderJson(true)
|
return c.RenderJson(true)
|
||||||
}
|
}
|
||||||
@@ -293,8 +223,131 @@ func (c Note) SearchNoteByTags(tags []string) revel.Result {
|
|||||||
return c.RenderJson(blogs)
|
return c.RenderJson(blogs)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 设置/取消Blog; 置顶
|
//------------------
|
||||||
func (c Note) SetNote2Blog(noteId string, isBlog, isTop bool) revel.Result {
|
// html2image
|
||||||
re := noteService.ToBlog(c.GetUserId(), noteId, isBlog, isTop)
|
// 判断是否有权限生成
|
||||||
return c.RenderJson(re)
|
// 博客也可以调用
|
||||||
|
// 这是脚本调用, 没有cookie, 不执行权限控制, 通过传来的appKey判断
|
||||||
|
func (c Note) ToImage(noteId, appKey string) revel.Result {
|
||||||
|
// 虽然传了cookie但是这里还是不能得到userId, 所以还是通过appKey来验证之
|
||||||
|
appKeyTrue, _ := revel.Config.String("app.secret")
|
||||||
|
if appKeyTrue != appKey {
|
||||||
|
return c.RenderText("")
|
||||||
|
}
|
||||||
|
note := noteService.GetNoteById(noteId)
|
||||||
|
if note.NoteId == "" {
|
||||||
|
return c.RenderText("")
|
||||||
|
}
|
||||||
|
|
||||||
|
c.SetLocale()
|
||||||
|
|
||||||
|
noteUserId := note.UserId.Hex()
|
||||||
|
content := noteService.GetNoteContent(noteId, noteUserId)
|
||||||
|
userInfo := userService.GetUserInfo(noteUserId);
|
||||||
|
|
||||||
|
c.RenderArgs["blog"] = note
|
||||||
|
c.RenderArgs["content"] = content.Content
|
||||||
|
c.RenderArgs["userInfo"] = userInfo
|
||||||
|
userBlog := blogService.GetUserBlog(noteUserId)
|
||||||
|
c.RenderArgs["userBlog"] = userBlog
|
||||||
|
|
||||||
|
return c.RenderTemplate("html2Image/index.html")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c Note) Html2Image(noteId string) revel.Result {
|
||||||
|
re := info.NewRe()
|
||||||
|
userId := c.GetUserId()
|
||||||
|
note := noteService.GetNoteById(noteId)
|
||||||
|
if note.NoteId == "" {
|
||||||
|
re.Msg = "No Note"
|
||||||
|
return c.RenderJson(re)
|
||||||
|
}
|
||||||
|
|
||||||
|
noteUserId := note.UserId.Hex()
|
||||||
|
// 是否有权限
|
||||||
|
if noteUserId != userId {
|
||||||
|
// 是否是有权限协作的
|
||||||
|
if !note.IsBlog && !shareService.HasReadPerm(noteUserId, userId, noteId) {
|
||||||
|
re.Msg = "No Perm"
|
||||||
|
return c.RenderJson(re)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// path 判断是否需要重新生成之
|
||||||
|
fileUrlPath := "/upload/" + noteUserId + "/images/weibo"
|
||||||
|
dir := revel.BasePath + "/public/" + fileUrlPath
|
||||||
|
if !ClearDir(dir) {
|
||||||
|
re.Msg = "No Dir"
|
||||||
|
return c.RenderJson(re)
|
||||||
|
}
|
||||||
|
|
||||||
|
filename := note.NoteId.Hex() + ".png";
|
||||||
|
path := dir + "/" + filename
|
||||||
|
|
||||||
|
// cookie
|
||||||
|
cookieName := revel.CookiePrefix + "_SESSION"
|
||||||
|
cookie, err := c.Request.Cookie(cookieName)
|
||||||
|
cookieStr := cookie.String()
|
||||||
|
cookieValue := ""
|
||||||
|
if err == nil && len(cookieStr) > len(cookieName) {
|
||||||
|
cookieValue = cookieStr[len(cookieName)+1:]
|
||||||
|
}
|
||||||
|
|
||||||
|
appKey, _ := revel.Config.String("app.secret")
|
||||||
|
cookieDomain, _ := revel.Config.String("cookie.domain")
|
||||||
|
// 生成之
|
||||||
|
url := siteUrl + "/note/toImage?noteId=" + noteId + "&appKey=" + appKey;
|
||||||
|
// /Users/life/Documents/bin/phantomjs/bin/phantomjs /Users/life/Desktop/test/b.js
|
||||||
|
binPath := configService.GetGlobalStringConfig("toImageBinPath")
|
||||||
|
if binPath == "" {
|
||||||
|
return c.RenderJson(re);
|
||||||
|
}
|
||||||
|
cc := binPath + " \"" + url + "\" \"" + path + "\" \"" + cookieDomain + "\" \"" + cookieName + "\" \"" + cookieValue + "\""
|
||||||
|
cmd := exec.Command("/bin/sh", "-c", cc)
|
||||||
|
Log(cc);
|
||||||
|
b, err := cmd.Output()
|
||||||
|
if err == nil {
|
||||||
|
re.Ok = true
|
||||||
|
re.Id = fileUrlPath + "/" + filename
|
||||||
|
} else {
|
||||||
|
re.Msg = string(b)
|
||||||
|
Log("error:......")
|
||||||
|
Log(string(b))
|
||||||
|
}
|
||||||
|
|
||||||
|
return c.RenderJson(re)
|
||||||
|
|
||||||
|
/*
|
||||||
|
// 这里速度慢, 生成不完全(图片和内容都不全)
|
||||||
|
content := noteService.GetNoteContent(noteId, noteUserId)
|
||||||
|
userInfo := userService.GetUserInfo(noteUserId);
|
||||||
|
|
||||||
|
c.SetLocale()
|
||||||
|
|
||||||
|
c.RenderArgs["blog"] = note
|
||||||
|
c.RenderArgs["content"] = content.Content
|
||||||
|
c.RenderArgs["userInfo"] = userInfo
|
||||||
|
userBlog := blogService.GetUserBlog(noteUserId)
|
||||||
|
c.RenderArgs["userBlog"] = userBlog
|
||||||
|
|
||||||
|
html := c.RenderTemplateStr("html2Image/index.html") // Result类型的
|
||||||
|
contentFile := dir + "/html";
|
||||||
|
fout, err := os.Create(contentFile)
|
||||||
|
if err != nil {
|
||||||
|
return c.RenderJson(re)
|
||||||
|
}
|
||||||
|
fout.WriteString(html);
|
||||||
|
fout.Close()
|
||||||
|
|
||||||
|
cc := "/Users/life/Documents/bin/phantomjs/bin/phantomjs /Users/life/Desktop/test/c.js \"" + contentFile + "\" \"" + path + "\""
|
||||||
|
cmd := exec.Command("/bin/sh", "-c", cc)
|
||||||
|
b, err := cmd.Output()
|
||||||
|
if err == nil {
|
||||||
|
re.Ok = true
|
||||||
|
re.Id = fileUrlPath + "/" + filename
|
||||||
|
} else {
|
||||||
|
Log(string(b))
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
}
|
||||||
@@ -37,8 +37,7 @@ func (c Notebook) AddNotebook(notebookId, title, parentNotebookId string) revel.
|
|||||||
if(parentNotebookId != "") {
|
if(parentNotebookId != "") {
|
||||||
notebook.ParentNotebookId = bson.ObjectIdHex(parentNotebookId)
|
notebook.ParentNotebookId = bson.ObjectIdHex(parentNotebookId)
|
||||||
}
|
}
|
||||||
|
re := notebookService.AddNotebook(notebook)
|
||||||
re, notebook := notebookService.AddNotebook(notebook)
|
|
||||||
|
|
||||||
if(re) {
|
if(re) {
|
||||||
return c.RenderJson(notebook)
|
return c.RenderJson(notebook)
|
||||||
@@ -69,10 +68,4 @@ func (c Notebook) DragNotebooks(data string) revel.Result {
|
|||||||
json.Unmarshal([]byte(data), &info)
|
json.Unmarshal([]byte(data), &info)
|
||||||
|
|
||||||
return c.RenderJson(notebookService.DragNotebooks(c.GetUserId(), info.CurNotebookId, info.ParentNotebookId, info.Siblings))
|
return c.RenderJson(notebookService.DragNotebooks(c.GetUserId(), info.CurNotebookId, info.ParentNotebookId, info.Siblings))
|
||||||
}
|
}
|
||||||
|
|
||||||
// 设置notebook <-> blog
|
|
||||||
func (c Notebook) SetNotebook2Blog(notebookId string, isBlog bool) revel.Result {
|
|
||||||
re := notebookService.ToBlog(c.GetUserId(), notebookId, isBlog)
|
|
||||||
return c.RenderJson(re)
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,70 @@
|
|||||||
|
package controllers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"code.google.com/p/goauth2/oauth"
|
||||||
|
"github.com/revel/revel"
|
||||||
|
"github.com/leanote/leanote/app/lea/netutil"
|
||||||
|
. "github.com/leanote/leanote/app/lea"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Oauth struct {
|
||||||
|
BaseController
|
||||||
|
}
|
||||||
|
|
||||||
|
var oauthCfg = &oauth.Config{
|
||||||
|
ClientId: "3790fbf1fc14bc6c5d85",
|
||||||
|
ClientSecret: "e9dadfe601c7caa6df9b33db3e7539945c60dfa2",
|
||||||
|
AuthURL: "https://github.com/login/oauth/authorize",
|
||||||
|
TokenURL: "https://github.com/login/oauth/access_token",
|
||||||
|
RedirectURL: "http://leanote.com/oauth/githubCallback",
|
||||||
|
Scope: "user",
|
||||||
|
}
|
||||||
|
|
||||||
|
// 用户允许后, github返回到leanote
|
||||||
|
// 通过code得到token
|
||||||
|
// https://github.com/login/oauth/authorize?access_type=&approval_prompt=&client_id=3790fbf1fc14bc6c5d85&redirect_uri=http%3A%2F%2F127.0.0.1%3A8080%2Foauth2callback&response_type=code&scope=user&state=
|
||||||
|
func (c Oauth) GithubCallback(code string) revel.Result {
|
||||||
|
t := &oauth.Transport{Config: oauthCfg}
|
||||||
|
|
||||||
|
// Exchange the received code for a token
|
||||||
|
tok, err := t.Exchange(code)
|
||||||
|
token := tok.AccessToken
|
||||||
|
if err != nil || token == "" {
|
||||||
|
c.RenderArgs["title"] = "error"
|
||||||
|
return c.RenderTemplate("oauth/oauth_callback_error.html")
|
||||||
|
}
|
||||||
|
|
||||||
|
// 得到用户信息
|
||||||
|
profileInfoURL := "https://api.github.com/user"
|
||||||
|
url := fmt.Sprintf("%s?access_token=%s", profileInfoURL, token)
|
||||||
|
content, err2 := netutil.GetContent(url)
|
||||||
|
if err2 != nil {
|
||||||
|
c.RenderArgs["title"] = "error"
|
||||||
|
return c.RenderTemplate("oauth/oauth_callback_error.html")
|
||||||
|
}
|
||||||
|
// 转成map
|
||||||
|
profileInfo := map[string]interface{}{}
|
||||||
|
Log(string(content))
|
||||||
|
err2 = json.Unmarshal(content, &profileInfo)
|
||||||
|
if err2 != nil {
|
||||||
|
c.RenderArgs["title"] = "error"
|
||||||
|
return c.RenderTemplate("oauth/oauth_callback_error.html")
|
||||||
|
}
|
||||||
|
|
||||||
|
usernameI := profileInfo["login"]
|
||||||
|
|
||||||
|
username, _ := usernameI.(string)
|
||||||
|
userId := username
|
||||||
|
|
||||||
|
// 注册
|
||||||
|
isExists, userInfo := authService.ThirdRegister("github", userId, username)
|
||||||
|
c.RenderArgs["isExists"] = isExists
|
||||||
|
c.RenderArgs["userInfo"] = userInfo
|
||||||
|
|
||||||
|
// 登录之
|
||||||
|
c.SetSession(userInfo)
|
||||||
|
|
||||||
|
return c.Redirect("/note")
|
||||||
|
}
|
||||||
@@ -1,103 +0,0 @@
|
|||||||
package controllers
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/revel/revel"
|
|
||||||
// "strings"
|
|
||||||
// "time"
|
|
||||||
// "encoding/json"
|
|
||||||
// "github.com/leanote/leanote/app/info"
|
|
||||||
// . "github.com/leanote/leanote/app/lea"
|
|
||||||
// "github.com/leanote/leanote/app/lea/blog"
|
|
||||||
// "gopkg.in/mgo.v2/bson"
|
|
||||||
// "github.com/leanote/leanote/app/types"
|
|
||||||
// "io/ioutil"
|
|
||||||
// "math"
|
|
||||||
// "os"
|
|
||||||
// "path"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Preview struct {
|
|
||||||
Blog
|
|
||||||
}
|
|
||||||
|
|
||||||
// 得到要预览的主题绝对路径
|
|
||||||
func (c Preview) getPreviewThemeAbsolutePath(themeId string) bool {
|
|
||||||
if themeId != "" {
|
|
||||||
c.Session["themeId"] = themeId // 存到session中, 下次的url就不能带了
|
|
||||||
} else {
|
|
||||||
themeId = c.Session["themeId"] // 直接从session中获取
|
|
||||||
}
|
|
||||||
if themeId == "" {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
theme := themeService.GetTheme(c.GetUserId(), themeId)
|
|
||||||
|
|
||||||
c.RenderArgs["isPreview"] = true
|
|
||||||
c.RenderArgs["themeId"] = themeId
|
|
||||||
c.RenderArgs["themeInfoPreview"] = theme.Info
|
|
||||||
c.RenderArgs["themePath"] = theme.Path
|
|
||||||
if theme.Path == "" {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c Preview) Index(userIdOrEmail string, themeId string) revel.Result {
|
|
||||||
if !c.getPreviewThemeAbsolutePath(themeId) {
|
|
||||||
return c.E404()
|
|
||||||
}
|
|
||||||
return c.Blog.Index(c.GetUserId())
|
|
||||||
// return blog.RenderTemplate("index.html", c.RenderArgs, c.getPreviewThemeAbsolutePath(themeId))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c Preview) Tag(userIdOrEmail, tag string) revel.Result {
|
|
||||||
if !c.getPreviewThemeAbsolutePath("") {
|
|
||||||
return c.E404()
|
|
||||||
}
|
|
||||||
return c.Blog.Tag(c.GetUserId(), tag)
|
|
||||||
}
|
|
||||||
func (c Preview) Tags(userIdOrEmail string) revel.Result {
|
|
||||||
if !c.getPreviewThemeAbsolutePath("") {
|
|
||||||
return c.E404()
|
|
||||||
}
|
|
||||||
return c.Blog.Tags(c.GetUserId())
|
|
||||||
// if tag == "" {
|
|
||||||
// return blog.RenderTemplate("tags.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 {
|
|
||||||
if !c.getPreviewThemeAbsolutePath("") {
|
|
||||||
return c.E404()
|
|
||||||
}
|
|
||||||
return c.Blog.Archives(c.GetUserId(), notebookId, year, month)
|
|
||||||
// return blog.RenderTemplate("archive.html", c.RenderArgs, c.getPreviewThemeAbsolutePath(""))
|
|
||||||
}
|
|
||||||
func (c Preview) Cate(userIdOrEmail, notebookId string) revel.Result {
|
|
||||||
if !c.getPreviewThemeAbsolutePath("") {
|
|
||||||
return c.E404()
|
|
||||||
}
|
|
||||||
return c.Blog.Cate(userIdOrEmail, notebookId)
|
|
||||||
// return blog.RenderTemplate("cate.html", c.RenderArgs, c.getPreviewThemeAbsolutePath(""))
|
|
||||||
}
|
|
||||||
func (c Preview) Post(userIdOrEmail, noteId string) revel.Result {
|
|
||||||
if !c.getPreviewThemeAbsolutePath("") {
|
|
||||||
return c.E404()
|
|
||||||
}
|
|
||||||
return c.Blog.Post(userIdOrEmail, noteId)
|
|
||||||
// return blog.RenderTemplate("view.html", c.RenderArgs, c.getPreviewThemeAbsolutePath(""))
|
|
||||||
}
|
|
||||||
func (c Preview) Single(userIdOrEmail, singleId string) revel.Result {
|
|
||||||
if !c.getPreviewThemeAbsolutePath("") {
|
|
||||||
return c.E404()
|
|
||||||
}
|
|
||||||
return c.Blog.Single(userIdOrEmail, singleId)
|
|
||||||
// return blog.RenderTemplate("single.html", c.RenderArgs, c.getPreviewThemeAbsolutePath(""))
|
|
||||||
}
|
|
||||||
func (c Preview) Search(userIdOrEmail, keywords string) revel.Result {
|
|
||||||
if !c.getPreviewThemeAbsolutePath("") {
|
|
||||||
return c.E404()
|
|
||||||
}
|
|
||||||
return c.Blog.Search(c.GetUserId(), keywords)
|
|
||||||
// return blog.RenderTemplate("search.html", c.RenderArgs, c.getPreviewThemeAbsolutePath(""))
|
|
||||||
}
|
|
||||||
@@ -4,7 +4,7 @@ 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"
|
||||||
// "github.com/leanote/leanote/app/types"
|
// "github.com/leanote/leanote/app/types"
|
||||||
// "io/ioutil"
|
// "io/ioutil"
|
||||||
@@ -87,8 +87,6 @@ func (c Share) ListNoteShareUserInfo(noteId string) revel.Result {
|
|||||||
noteShareUserInfos := shareService.ListNoteShareUserInfo(noteId, c.GetUserId())
|
noteShareUserInfos := shareService.ListNoteShareUserInfo(noteId, c.GetUserId())
|
||||||
c.RenderArgs["noteOrNotebookShareUserInfos"] = noteShareUserInfos
|
c.RenderArgs["noteOrNotebookShareUserInfos"] = noteShareUserInfos
|
||||||
|
|
||||||
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
|
||||||
@@ -101,9 +99,6 @@ func (c Share) ListNotebookShareUserInfo(notebookId string) revel.Result {
|
|||||||
notebookShareUserInfos := shareService.ListNotebookShareUserInfo(notebookId, c.GetUserId())
|
notebookShareUserInfos := shareService.ListNotebookShareUserInfo(notebookId, c.GetUserId())
|
||||||
c.RenderArgs["noteOrNotebookShareUserInfos"] = notebookShareUserInfos
|
c.RenderArgs["noteOrNotebookShareUserInfos"] = notebookShareUserInfos
|
||||||
|
|
||||||
c.RenderArgs["noteOrNotebookShareGroupInfos"] = shareService.GetNotebookShareGroups(notebookId, c.GetUserId())
|
|
||||||
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
|
||||||
@@ -144,45 +139,4 @@ func (c Share) DeleteShareNotebookBySharedUser(notebookId string, fromUserId str
|
|||||||
// 删除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 {
|
|
||||||
re := info.NewRe()
|
|
||||||
re.Ok = shareService.AddShareNoteGroup(c.GetUserId(), noteId, groupId, perm);
|
|
||||||
return c.RenderJson(re);
|
|
||||||
}
|
|
||||||
// 删除
|
|
||||||
func (c Share) DeleteShareNoteGroup(noteId, groupId string) revel.Result {
|
|
||||||
re := info.NewRe()
|
|
||||||
re.Ok = shareService.DeleteShareNoteGroup(c.GetUserId(), noteId, groupId);
|
|
||||||
return c.RenderJson(re);
|
|
||||||
}
|
|
||||||
// 更新, 也是一样, 先删后加
|
|
||||||
func (c Share) UpdateShareNoteGroupPerm(noteId, groupId string, perm int) revel.Result {
|
|
||||||
return c.AddShareNoteGroup(noteId, groupId, perm)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//------
|
|
||||||
|
|
||||||
// 将笔记分享给分组
|
|
||||||
func (c Share) AddShareNotebookGroup(notebookId, groupId string, perm int) revel.Result {
|
|
||||||
re := info.NewRe()
|
|
||||||
re.Ok = shareService.AddShareNotebookGroup(c.GetUserId(), notebookId, groupId, perm);
|
|
||||||
return c.RenderJson(re);
|
|
||||||
}
|
|
||||||
// 删除
|
|
||||||
func (c Share) DeleteShareNotebookGroup(notebookId, groupId string) revel.Result {
|
|
||||||
re := info.NewRe()
|
|
||||||
re.Ok = shareService.DeleteShareNotebookGroup(c.GetUserId(), notebookId, groupId);
|
|
||||||
return c.RenderJson(re);
|
|
||||||
}
|
|
||||||
// 更新, 也是一样, 先删后加
|
|
||||||
func (c Share) UpdateShareNotebookGroupPerm(notebookId, groupId string, perm int) revel.Result {
|
|
||||||
return c.AddShareNotebookGroup(notebookId, groupId, perm)
|
|
||||||
}
|
}
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
package controllers
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/revel/revel"
|
|
||||||
// "encoding/json"
|
|
||||||
// "gopkg.in/mgo.v2/bson"
|
|
||||||
// . "github.com/leanote/leanote/app/lea"
|
|
||||||
"github.com/leanote/leanote/app/info"
|
|
||||||
// "os/exec"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Tag struct {
|
|
||||||
BaseController
|
|
||||||
}
|
|
||||||
|
|
||||||
// 更新Tag
|
|
||||||
func (c Tag) UpdateTag(tag string) revel.Result {
|
|
||||||
ret := info.NewRe()
|
|
||||||
ret.Ok = true
|
|
||||||
ret.Item = tagService.AddOrUpdateTag(c.GetUserId(), tag)
|
|
||||||
return c.RenderJson(ret)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 删除标签
|
|
||||||
func (c Tag) DeleteTag(tag string) revel.Result {
|
|
||||||
ret := info.Re{}
|
|
||||||
ret.Ok = true
|
|
||||||
ret.Item = tagService.DeleteTag(c.GetUserId(), tag)
|
|
||||||
return c.RenderJson(ret)
|
|
||||||
}
|
|
||||||
@@ -16,7 +16,7 @@ type AdminBlog struct {
|
|||||||
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
|
||||||
@@ -27,4 +27,4 @@ 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)
|
||||||
}
|
}
|
||||||
@@ -18,8 +18,8 @@ func (c Admin) Index() revel.Result {
|
|||||||
c.SetLocale()
|
c.SetLocale()
|
||||||
|
|
||||||
c.RenderArgs["countUser"] = userService.CountUser()
|
c.RenderArgs["countUser"] = userService.CountUser()
|
||||||
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");
|
||||||
}
|
}
|
||||||
@@ -30,7 +30,6 @@ func (c Admin) T(t string) revel.Result {
|
|||||||
c.RenderArgs["arr"] = configService.GlobalArrayConfigs
|
c.RenderArgs["arr"] = configService.GlobalArrayConfigs
|
||||||
c.RenderArgs["map"] = configService.GlobalMapConfigs
|
c.RenderArgs["map"] = configService.GlobalMapConfigs
|
||||||
c.RenderArgs["arrMap"] = configService.GlobalArrMapConfigs
|
c.RenderArgs["arrMap"] = configService.GlobalArrMapConfigs
|
||||||
c.RenderArgs["version"] = configService.GetVersion()
|
|
||||||
return c.RenderTemplate("admin/" + t + ".html")
|
return c.RenderTemplate("admin/" + t + ".html")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -46,10 +46,7 @@ func (c AdminEmail) Demo() revel.Result {
|
|||||||
func (c AdminEmail) DoDemo(demoUsername, demoPassword string) revel.Result {
|
func (c AdminEmail) DoDemo(demoUsername, demoPassword string) revel.Result {
|
||||||
re := info.NewRe()
|
re := info.NewRe()
|
||||||
|
|
||||||
userInfo, err := authService.Login(demoUsername, demoPassword)
|
userInfo := authService.Login(demoUsername, demoPassword)
|
||||||
if err != nil {
|
|
||||||
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)
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ import (
|
|||||||
// . "github.com/leanote/leanote/app/lea"
|
// . "github.com/leanote/leanote/app/lea"
|
||||||
"github.com/leanote/leanote/app/info"
|
"github.com/leanote/leanote/app/info"
|
||||||
"strings"
|
"strings"
|
||||||
"fmt"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// admin 首页
|
// admin 首页
|
||||||
@@ -56,11 +55,7 @@ func (c AdminSetting) Demo() revel.Result {
|
|||||||
func (c AdminSetting) DoDemo(demoUsername, demoPassword string) revel.Result {
|
func (c AdminSetting) DoDemo(demoUsername, demoPassword string) revel.Result {
|
||||||
re := info.NewRe()
|
re := info.NewRe()
|
||||||
|
|
||||||
userInfo, err := authService.Login(demoUsername, demoPassword)
|
userInfo := authService.Login(demoUsername, demoPassword)
|
||||||
if err != nil {
|
|
||||||
fmt.Println(err)
|
|
||||||
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)
|
||||||
@@ -115,28 +110,10 @@ func (c AdminSetting) OpenRegister(openRegister string) revel.Result {
|
|||||||
return c.RenderJson(re)
|
return c.RenderJson(re)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c AdminSetting) HomePage(homePage string) revel.Result {
|
|
||||||
re := info.NewRe()
|
|
||||||
if homePage == "0" {
|
|
||||||
homePage = ""
|
|
||||||
}
|
|
||||||
re.Ok = configService.UpdateGlobalStringConfig(c.GetUserId(), "homePage", homePage)
|
|
||||||
return c.RenderJson(re)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c AdminSetting) Mongodb(mongodumpPath, mongorestorePath string) revel.Result {
|
func (c AdminSetting) Mongodb(mongodumpPath, mongorestorePath string) revel.Result {
|
||||||
re := info.NewRe()
|
re := info.NewRe()
|
||||||
re.Ok = configService.UpdateGlobalStringConfig(c.GetUserId(), "mongodumpPath", mongodumpPath)
|
re.Ok = configService.UpdateGlobalStringConfig(c.GetUserId(), "mongodumpPath", mongodumpPath)
|
||||||
re.Ok = configService.UpdateGlobalStringConfig(c.GetUserId(), "mongorestorePath", mongorestorePath)
|
re.Ok = configService.UpdateGlobalStringConfig(c.GetUserId(), "mongorestorePath", mongorestorePath)
|
||||||
|
|
||||||
return c.RenderJson(re)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c AdminSetting) UploadSize(uploadImageSize, uploadAvatarSize, uploadBlogLogoSize, uploadAttachSize float64) revel.Result {
|
|
||||||
re := info.NewRe()
|
|
||||||
re.Ok = configService.UpdateGlobalStringConfig(c.GetUserId(), "uploadImageSize", fmt.Sprintf("%v", uploadImageSize))
|
|
||||||
re.Ok = configService.UpdateGlobalStringConfig(c.GetUserId(), "uploadAvatarSize", fmt.Sprintf("%v", uploadAvatarSize))
|
|
||||||
re.Ok = configService.UpdateGlobalStringConfig(c.GetUserId(), "uploadBlogLogoSize", fmt.Sprintf("%v", uploadBlogLogoSize))
|
|
||||||
re.Ok = configService.UpdateGlobalStringConfig(c.GetUserId(), "uploadAttachSize", fmt.Sprintf("%v", uploadAttachSize))
|
|
||||||
return c.RenderJson(re)
|
return c.RenderJson(re)
|
||||||
}
|
}
|
||||||
@@ -3,7 +3,7 @@ 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/lea"
|
||||||
// "io/ioutil"
|
// "io/ioutil"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -15,16 +15,4 @@ 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 {
|
|
||||||
re := info.NewRe()
|
|
||||||
re.Ok, re.Msg = upgradeService.UpgradeBetaToBeta2(c.GetUserId())
|
|
||||||
return c.RenderJson(re)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c AdminUpgrade) UpgradeBeta3ToBeta4() revel.Result {
|
|
||||||
re := info.NewRe()
|
|
||||||
re.Ok, re.Msg = upgradeService.Api(c.GetUserId())
|
|
||||||
return c.RenderJson(re)
|
|
||||||
}
|
}
|
||||||
@@ -2,9 +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"
|
||||||
// "time"
|
|
||||||
"github.com/leanote/leanote/app/info"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// admin 首页
|
// admin 首页
|
||||||
@@ -15,13 +13,10 @@ 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) revel.Result {
|
||||||
pageNumber := c.GetPage()
|
pageNumber := c.GetPage()
|
||||||
if userPageSize == 0 {
|
sorterField, isAsc := c.getSorter("CreatedTime", false, []string{"email", "username", "verified", "createdTime"});
|
||||||
pageSize = userPageSize
|
pageInfo, users := userService.ListUsers(pageNumber, userPageSize, sorterField, isAsc, keywords);
|
||||||
}
|
|
||||||
sorterField, isAsc := c.getSorter("CreatedTime", false, []string{"email", "username", "verified", "createdTime", "accountType"});
|
|
||||||
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
|
||||||
@@ -31,36 +26,3 @@ func (c AdminUser) Index(sorter, keywords string, pageSize int) revel.Result {
|
|||||||
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 {
|
|
||||||
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 = authService.Register(email, pwd, "")
|
|
||||||
|
|
||||||
return c.RenderRe(re)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 修改帐户
|
|
||||||
func (c AdminUser) ResetPwd(userId string) revel.Result {
|
|
||||||
userInfo := userService.GetUserInfo(userId)
|
|
||||||
c.RenderArgs["userInfo"] = userInfo
|
|
||||||
return c.RenderTemplate("admin/user/reset_pwd.html");
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c AdminUser) DoResetPwd(userId, pwd string) revel.Result {
|
|
||||||
re := info.NewRe();
|
|
||||||
if re.Ok, re.Msg = Vd("password", pwd); !re.Ok {
|
|
||||||
return c.RenderRe(re);
|
|
||||||
}
|
|
||||||
re.Ok, re.Msg = userService.ResetPwd(c.GetUserId(), userId, pwd)
|
|
||||||
return c.RenderRe(re)
|
|
||||||
}
|
|
||||||
@@ -28,6 +28,7 @@ var configService *service.ConfigService
|
|||||||
var emailService *service.EmailService
|
var emailService *service.EmailService
|
||||||
var upgradeService *service.UpgradeService
|
var upgradeService *service.UpgradeService
|
||||||
|
|
||||||
|
var adminUsername = "admin"
|
||||||
// 拦截器
|
// 拦截器
|
||||||
// 不需要拦截的url
|
// 不需要拦截的url
|
||||||
// Index 除了Note之外都不需要
|
// Index 除了Note之外都不需要
|
||||||
@@ -82,7 +83,7 @@ func AuthInterceptor(c *revel.Controller) revel.Result {
|
|||||||
|
|
||||||
// 验证是否已登录
|
// 验证是否已登录
|
||||||
// 必须是管理员
|
// 必须是管理员
|
||||||
if username, ok := c.Session["Username"]; ok && username == configService.GetAdminUsername() {
|
if username, ok := c.Session["Username"]; ok && username == adminUsername {
|
||||||
return nil // 已登录
|
return nil // 已登录
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -128,4 +129,4 @@ func init() {
|
|||||||
revel.InterceptFunc(AuthInterceptor, revel.BEFORE, &AdminEmail{})
|
revel.InterceptFunc(AuthInterceptor, revel.BEFORE, &AdminEmail{})
|
||||||
revel.InterceptFunc(AuthInterceptor, revel.BEFORE, &AdminUpgrade{})
|
revel.InterceptFunc(AuthInterceptor, revel.BEFORE, &AdminUpgrade{})
|
||||||
revel.InterceptFunc(AuthInterceptor, revel.BEFORE, &AdminData{})
|
revel.InterceptFunc(AuthInterceptor, revel.BEFORE, &AdminData{})
|
||||||
}
|
}
|
||||||
@@ -1,465 +0,0 @@
|
|||||||
# API 列表
|
|
||||||
|
|
||||||
## 前言
|
|
||||||
|
|
||||||
### api url
|
|
||||||
|
|
||||||
所有api的url前面带/api/, 如:
|
|
||||||
|
|
||||||
`/api/user/info?userId=xxxx&token=xxxx`
|
|
||||||
|
|
||||||
除了/auth/login, /auth/register外其它的都需要另外带参数token=xxxx
|
|
||||||
|
|
||||||
### 文件目录结构
|
|
||||||
* 所有API的Controller都在app/api文件夹下
|
|
||||||
* 文件命名: Api功能Controller.go, 如ApiUserController.go
|
|
||||||
* 结构体命名为 Api功能, 如ApiUser
|
|
||||||
* API公用Controller: ApiBaseController
|
|
||||||
* init.go 注入service和定义拦截器
|
|
||||||
|
|
||||||
### 流程
|
|
||||||
用户登录后返回一个token, 以后所有的请求都携带该token.
|
|
||||||
在init.go中的拦截器会得到token并调用sessionService判断是否登录了
|
|
||||||
|
|
||||||
## 返回值结构
|
|
||||||
* 全部返回JSON, JSON, 除二进制文件(图片, 附件外), 如果返回其它非JSON格式的值, 肯定是出错了
|
|
||||||
* 错误信息全部返回 {Ok: false, Msg: "相应的错误信息"}
|
|
||||||
* 正确信息返回分两种:
|
|
||||||
1. 一些操作型的api, 比如updateUsername, updateLogo之类的, 成功后返回 {Ok: true, Msg:""}
|
|
||||||
2. 一些获取型api, 如getNote, 全部返回真实的返回数据, 如返回笔记:
|
|
||||||
```
|
|
||||||
{
|
|
||||||
"NoteId": "54bdc7e305fcd13ea3000000",
|
|
||||||
"NotebookId": "54bdc65599c37b0da9000003",
|
|
||||||
"UserId": "54bdc65599c37b0da9000002",
|
|
||||||
"Title": "笔记标题",
|
|
||||||
"Desc": "",
|
|
||||||
"Tags": null,
|
|
||||||
"Abstract": "",
|
|
||||||
"Content": "",
|
|
||||||
"IsMarkdown": false,
|
|
||||||
"IsBlog": false,
|
|
||||||
"IsTrash": true,
|
|
||||||
"IsDeleted": false,
|
|
||||||
"Usn": 15,
|
|
||||||
"Files": [],
|
|
||||||
"CreatedTime": "2015-01-20T11:13:41.34+08:00",
|
|
||||||
"UpdatedTime": "2015-01-20T11:13:41.34+08:00",
|
|
||||||
"PublicTime": "0001-01-01T00:00:00Z"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
* 时间类型全是返回如 "2015-01-20T11:13:41.34+08:00" 的格式, (因为golang的time转成Json就是这样, 历史原因)
|
|
||||||
|
|
||||||
-----------------
|
|
||||||
|
|
||||||
## Auth 登录与注册
|
|
||||||
|
|
||||||
### /auth/login 登录
|
|
||||||
|
|
||||||
```
|
|
||||||
参数: email, pwd
|
|
||||||
Method: GET
|
|
||||||
返回:
|
|
||||||
错误: {"Ok":false, "Msg":"用户名或密码有误"}
|
|
||||||
正确: 比如:
|
|
||||||
{
|
|
||||||
"Ok":true,
|
|
||||||
"Token":"5500830738f41138e90003232",
|
|
||||||
"UserId":"52d26b4e99c37b609a000001",
|
|
||||||
"Email":"leanote@leanote.com",
|
|
||||||
"Username":"leanote"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
登录成功后将使用token作为之后的请求
|
|
||||||
|
|
||||||
### /auth/logout 注销
|
|
||||||
```
|
|
||||||
参数: token
|
|
||||||
Method: GET
|
|
||||||
返回:
|
|
||||||
错误: {Ok: false, Msg: ""}
|
|
||||||
成功: {Ok: true, Msg: ""}
|
|
||||||
```
|
|
||||||
|
|
||||||
### /auth/register 注册
|
|
||||||
```
|
|
||||||
参数: email, pwd
|
|
||||||
Method: POST
|
|
||||||
返回:
|
|
||||||
错误: {Ok: false, Msg: ""}
|
|
||||||
成功: {Ok: true, Msg: ""}
|
|
||||||
```
|
|
||||||
|
|
||||||
## User 用户
|
|
||||||
### /user/info 获取用户信息
|
|
||||||
```
|
|
||||||
参数: userId
|
|
||||||
Method: GET
|
|
||||||
返回:
|
|
||||||
错误: {Ok: false, Msg: ""}
|
|
||||||
成功: type.User
|
|
||||||
```
|
|
||||||
|
|
||||||
### /user/updateUsername 修改用户名
|
|
||||||
```
|
|
||||||
参数: username(新用户名)
|
|
||||||
Method: POST
|
|
||||||
返回:
|
|
||||||
错误: {Ok: false, Msg: ""}
|
|
||||||
成功: {Ok: true, Msg: ""}
|
|
||||||
```
|
|
||||||
|
|
||||||
### /user/updatePwd 修改密码
|
|
||||||
```
|
|
||||||
参数: oldPwd(旧密码), pwd(新密码)
|
|
||||||
Method: POST
|
|
||||||
返回:
|
|
||||||
错误: {Ok: false, Msg: ""}
|
|
||||||
成功: {Ok: true, Msg: ""}
|
|
||||||
```
|
|
||||||
|
|
||||||
### /user/updateLogo 修改头像
|
|
||||||
```
|
|
||||||
参数: file(文件)
|
|
||||||
Method: POST
|
|
||||||
返回:
|
|
||||||
错误: {Ok: false, Msg: ""}
|
|
||||||
成功: {Ok: true, Msg: ""}
|
|
||||||
```
|
|
||||||
|
|
||||||
### /user/getSyncState 获取最新同步状态
|
|
||||||
```
|
|
||||||
参数: 无
|
|
||||||
Method: POST
|
|
||||||
返回:
|
|
||||||
错误: {Ok: false, Msg: ""}
|
|
||||||
成功: {LastSyncUsn: 3232, LastSyncTime: "上次同步时间"(暂时无用)}
|
|
||||||
```
|
|
||||||
|
|
||||||
-----
|
|
||||||
|
|
||||||
## Notebook 笔记本
|
|
||||||
|
|
||||||
### /notebook/getSyncNotebooks 得到需要同步的笔记本
|
|
||||||
```
|
|
||||||
参数: afterUsn(int, 在此usn后的笔记本是需要同步的), maxEntry(int, 最大要同步的量)
|
|
||||||
Method: GET
|
|
||||||
返回:
|
|
||||||
错误: {Ok: false, Msg: ""}
|
|
||||||
成功: [type.Notebook] 数组
|
|
||||||
```
|
|
||||||
|
|
||||||
### /notebook/getNotebooks 得到所有笔记本
|
|
||||||
```
|
|
||||||
无参数
|
|
||||||
Method: GET
|
|
||||||
返回:
|
|
||||||
错误: {Ok: false, Msg: ""}
|
|
||||||
成功: [type.Notebook] 数组
|
|
||||||
```
|
|
||||||
|
|
||||||
### /notebook/addNotebook 添加笔记本
|
|
||||||
```
|
|
||||||
参数: title(string), parentNotebookId(string, 父notebookId, 可空), seq(int) 排列
|
|
||||||
Method: POST
|
|
||||||
返回:
|
|
||||||
错误: {Ok: false, Msg:""}
|
|
||||||
成功: type.Notebook
|
|
||||||
```
|
|
||||||
|
|
||||||
### /notebook/updateNotebook 修改笔记本
|
|
||||||
```
|
|
||||||
参数: notebookId, title, parentNotebookId, seq(int), usn(int)
|
|
||||||
Method: POST
|
|
||||||
返回:
|
|
||||||
错误: {Ok: false, msg: ""} msg == "conflict" 表示冲突
|
|
||||||
成功: type.Notebook
|
|
||||||
```
|
|
||||||
|
|
||||||
### /notebook/deleteNotebook 删除笔记本
|
|
||||||
```
|
|
||||||
参数: notebookId, usn(int)
|
|
||||||
Method: GET
|
|
||||||
返回:
|
|
||||||
错误: {Ok: false, msg: ""} msg == "conflict" 表示冲突
|
|
||||||
成功: {Ok: true}
|
|
||||||
```
|
|
||||||
|
|
||||||
----
|
|
||||||
|
|
||||||
## Note 笔记
|
|
||||||
|
|
||||||
|
|
||||||
### /note/getSyncNotes 获取需要同步的笔记
|
|
||||||
```
|
|
||||||
参数: afterUsn(int, 在此usn后的笔记是需要同步的), maxEntry(int, 最大要同步的量)
|
|
||||||
Method: GET
|
|
||||||
返回:
|
|
||||||
错误: {Ok: false, Msg: ""}
|
|
||||||
成功: [type.Note] 数组, 笔记不包含Abstract和Content
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
### /note/getNotes 获得某笔记本下的笔记(无内容)
|
|
||||||
```
|
|
||||||
参数: notebookId
|
|
||||||
Method: GET
|
|
||||||
返回:
|
|
||||||
错误: {Ok: false, Msg: ""}
|
|
||||||
成功: [type.Note] 数组, 笔记不包含Abstract和Content
|
|
||||||
```
|
|
||||||
|
|
||||||
### /note/getNoteAndContent 获得笔记与内容
|
|
||||||
```
|
|
||||||
参数: noteId
|
|
||||||
Method: GET
|
|
||||||
返回:
|
|
||||||
错误: {Ok: false, Msg: ""}
|
|
||||||
成功: type.Note
|
|
||||||
```
|
|
||||||
|
|
||||||
### /note/getNoteContent 获得笔记内容
|
|
||||||
```
|
|
||||||
参数: noteId
|
|
||||||
Method: GET
|
|
||||||
返回:
|
|
||||||
错误: {Ok: false, Msg: ""}
|
|
||||||
成功: type.NoteContent
|
|
||||||
```
|
|
||||||
|
|
||||||
### /note/addNote 添加笔记
|
|
||||||
```
|
|
||||||
参数: (注意首字大写)
|
|
||||||
NotebookId string 必传
|
|
||||||
Title string 必传
|
|
||||||
Tags []string 可选
|
|
||||||
Content string 必传
|
|
||||||
Abstract string 可选, 当是markdown笔记时必须传
|
|
||||||
IsMarkdown bool 可选
|
|
||||||
Files []type.NoteFiles 数组 可选
|
|
||||||
Method: POST
|
|
||||||
返回:
|
|
||||||
错误: {Ok: false, Msg: ""}
|
|
||||||
成功: type.Note, 不包含Abstract, Content
|
|
||||||
```
|
|
||||||
|
|
||||||
** 关于笔记中的图片/附件**
|
|
||||||
客户端应该添加一个"图片/附件表"来存元数据, 图片应该要缓存到本地, 附件可在需要的时候再调用相应api获取.
|
|
||||||
|
|
||||||
Content中的数据, 图片,附件在Leanote的链接是, 所以, 不管你在本地的笔记中是以什么形式来保存图片,附件的链接的,请addNote和updateNote时务必将链接修改成leanote服务器上的链接.
|
|
||||||
http://leanote.com/api/file/getImage?fileId=xx
|
|
||||||
单个附件:
|
|
||||||
http://leanote.com/api/file/getAttach?fileId=xx
|
|
||||||
所有附件:
|
|
||||||
http://leanote.com/api/file/getAllAttachs?noteId=xxx
|
|
||||||
|
|
||||||
**注意:**
|
|
||||||
addNote时必须要把Files, 和相关的图片/附件一起传到服务器中
|
|
||||||
其中Files(文件的元数据)和其它字段以POST方式传出, 而真正数据则以http的multipart传入, 每个文件的name为"FileDatas[LocalFileId]"
|
|
||||||
|
|
||||||
图片在笔记内的链接必须为: http://leanote.com/api/file/getImage?fileId=LocalFileId或FileId
|
|
||||||
附件如果插入到了笔记内容内, 其链接必须为: http://leanote.com/api/file/getAttach?fileId=LocalFileId或FileId
|
|
||||||
其中, fileId为文件在本地的LocalFileId或服务器上的FileId
|
|
||||||
|
|
||||||
服务器端会生成FileId传给Client. Client在本地必须要建立LocalFileId与FileId的关联.
|
|
||||||
|
|
||||||
如果笔记内容传了, 且笔记内有图片, 则必须要传Files 文件元数据, 因为Server端还要对内容内的图片, 附件链接进行修改, 可能你传过去的是LocalFileId, 服务器端会将LocalFileId替换成FileId存到数据库中.
|
|
||||||
|
|
||||||
同样适用于 updateNote
|
|
||||||
|
|
||||||
http://leanote.com 不绝对, 因为用户可以自建服务, 所以在开发时需要可配置
|
|
||||||
|
|
||||||
### /note/updateNote 更新笔记
|
|
||||||
|
|
||||||
当更新了笔记某个属性时, 只要传某个属性就行, 其它不用传, 比如把笔记拉入了trash, 那么就传IsTrash: true
|
|
||||||
|
|
||||||
```
|
|
||||||
参数: (注意首字大写)
|
|
||||||
NoteId string 必传
|
|
||||||
Usn int 必传
|
|
||||||
NotebookId string 可选
|
|
||||||
Title string 可选
|
|
||||||
Tags []string 可选
|
|
||||||
Content string 可选
|
|
||||||
Abstract string 可选, 当是markdown笔记时必须传
|
|
||||||
IsMarkdown bool 可选
|
|
||||||
IsTrash bool 是否是trash 可选
|
|
||||||
Files []type.NoteFiles 数组 可选
|
|
||||||
Method: POST
|
|
||||||
返回:
|
|
||||||
错误: {Ok: false, msg: ''} msg == 'conflict' 表示冲突
|
|
||||||
成功: type.Note, 不包含Abstract和Content
|
|
||||||
```
|
|
||||||
|
|
||||||
### /note/deleteTrash 彻底删除笔记
|
|
||||||
```
|
|
||||||
参数: noteId, usn
|
|
||||||
Method: GET
|
|
||||||
返回:
|
|
||||||
错误: {Ok: false, msg: ''} msg == 'conflict' 表示冲突
|
|
||||||
成功: type.UpdateRet
|
|
||||||
```
|
|
||||||
|
|
||||||
-------
|
|
||||||
|
|
||||||
## Tag 标签
|
|
||||||
|
|
||||||
### /tag/getSyncTags 获取需要同步的标签
|
|
||||||
```
|
|
||||||
参数: afterUsn(int, 在此usn后的标签是需要同步的), maxEntry(int, 最大要同步的量)
|
|
||||||
Method: GET
|
|
||||||
返回:
|
|
||||||
错误: {Ok: false, Msg: ""}
|
|
||||||
成功: [type.Tag] 数组
|
|
||||||
```
|
|
||||||
|
|
||||||
### /tag/addTag 添加标签
|
|
||||||
```
|
|
||||||
参数: tag(string)
|
|
||||||
Method: POST
|
|
||||||
返回:
|
|
||||||
错误: {Ok: false, Msg: ""}
|
|
||||||
成功: type.Tag
|
|
||||||
```
|
|
||||||
|
|
||||||
### /tag/deleteTag 删除标签
|
|
||||||
```
|
|
||||||
参数: tag(string)
|
|
||||||
Method: POST
|
|
||||||
返回:
|
|
||||||
错误: {Ok: false, Msg: ""}
|
|
||||||
成功: type.UpdateRet
|
|
||||||
```
|
|
||||||
|
|
||||||
### File 文件(获取图片, 附件)
|
|
||||||
|
|
||||||
### /file/getImage 获取图片
|
|
||||||
```
|
|
||||||
参数: fileId
|
|
||||||
Method: GET
|
|
||||||
返回:
|
|
||||||
错误: 非二进制文件数据
|
|
||||||
成功: 二进制文件
|
|
||||||
```
|
|
||||||
|
|
||||||
### /file/getAttach 获取附件
|
|
||||||
```
|
|
||||||
参数: fileId
|
|
||||||
Method: GET
|
|
||||||
返回:
|
|
||||||
错误: 非二进制文件数据
|
|
||||||
成功: 二进制文件
|
|
||||||
```
|
|
||||||
|
|
||||||
### /file/getAllAttachs 获取所有附件
|
|
||||||
```
|
|
||||||
参数: noteId
|
|
||||||
Method: GET
|
|
||||||
返回:
|
|
||||||
错误: 非二进制文件数据
|
|
||||||
成功: 二进制文件
|
|
||||||
```
|
|
||||||
|
|
||||||
--------
|
|
||||||
|
|
||||||
## 数据类型
|
|
||||||
|
|
||||||
### type.User 用户信息
|
|
||||||
|
|
||||||
```
|
|
||||||
User {
|
|
||||||
UserId string
|
|
||||||
Username string
|
|
||||||
Email string
|
|
||||||
Verified bool
|
|
||||||
Logo string
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### type.Notebook 笔记本
|
|
||||||
|
|
||||||
```
|
|
||||||
Notebook {
|
|
||||||
NotebookId
|
|
||||||
UserId
|
|
||||||
ParentNotebookId // 上级
|
|
||||||
Seq int // 排序
|
|
||||||
Title string
|
|
||||||
IsBlog bool
|
|
||||||
IsDeleted bool
|
|
||||||
CreatedTime time.Time
|
|
||||||
UpdatedTime time.Time
|
|
||||||
|
|
||||||
// 更新序号
|
|
||||||
Usn int // UpdateSequenceNum
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### type.Note 笔记
|
|
||||||
```
|
|
||||||
Note {
|
|
||||||
NoteId string
|
|
||||||
NotebookId string
|
|
||||||
UserId string
|
|
||||||
Title string
|
|
||||||
Tags []string
|
|
||||||
Content string
|
|
||||||
IsMarkdown bool
|
|
||||||
IsBlog bool
|
|
||||||
IsTrash bool
|
|
||||||
Files []NoteFile // 图片, 附件
|
|
||||||
CreatedTime time.Time
|
|
||||||
UpdatedTime time.Time
|
|
||||||
PublicTime time.Time
|
|
||||||
|
|
||||||
// 更新序号
|
|
||||||
Usn int
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### type.NoteContent 笔记内容
|
|
||||||
```
|
|
||||||
NoteContent {
|
|
||||||
NoteId string
|
|
||||||
UserId string
|
|
||||||
Content string
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### type.NoteFile 笔记文件(图片,附件)
|
|
||||||
```
|
|
||||||
NoteFile {
|
|
||||||
FileId string // 服务器端Id
|
|
||||||
LocalFileId string // 客户端Id
|
|
||||||
Type string // images/png, doc, xls, 根据fileName确定
|
|
||||||
Title string
|
|
||||||
HasBody bool // 传过来的值是否要更新内容, 如果有true, 则必须传文件
|
|
||||||
IsAttach bool // 是否是附件, 不是附件就是图片
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### type.Tag 标签
|
|
||||||
```
|
|
||||||
Tag {
|
|
||||||
TagId string
|
|
||||||
UserId string
|
|
||||||
Tag string
|
|
||||||
CreatedTime
|
|
||||||
UpdatedTime
|
|
||||||
IsDeleted bool // 删除位
|
|
||||||
// 更新序号
|
|
||||||
Usn
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### type.UpdateRe 更新后返回的值, 包含Usn
|
|
||||||
```
|
|
||||||
ReUpdate {
|
|
||||||
Ok bool
|
|
||||||
Msg string
|
|
||||||
|
|
||||||
// 更新序号
|
|
||||||
Usn int
|
|
||||||
}
|
|
||||||
```
|
|
||||||
@@ -1,47 +0,0 @@
|
|||||||
# API设计
|
|
||||||
|
|
||||||
By life (life@leanote.com)
|
|
||||||
|
|
||||||
## api url
|
|
||||||
|
|
||||||
所有api的url前面带/api/, 如:
|
|
||||||
|
|
||||||
`/api/user/info?userId=xxxx&token=xxxx`
|
|
||||||
|
|
||||||
## 文件目录结构
|
|
||||||
* 所有API的Controller都在app/api文件夹下
|
|
||||||
* 文件命名: Api功能Controller.go, 如ApiUserController.go
|
|
||||||
* 结构体命名为 Api功能, 如ApiUser
|
|
||||||
* API公用Controller: ApiBaseController
|
|
||||||
* init.go 注入service和定义拦截器
|
|
||||||
|
|
||||||
## 流程
|
|
||||||
用户登录后返回一个token, 以后所有的请求都携带该token.
|
|
||||||
在init.go中的拦截器会得到token并调用sessionService判断是否登录了
|
|
||||||
|
|
||||||
## 返回值结构
|
|
||||||
* 全部返回JSON, JSON, 除二进制文件(图片, 附件外), 如果返回其它非JSON格式的值, 肯定是出错了
|
|
||||||
* 错误信息全部返回 {Ok: false, Msg: ""}
|
|
||||||
* 正确信息全部返回真实的返回数据, 如返回笔记:
|
|
||||||
```
|
|
||||||
{
|
|
||||||
"NoteId": "54bdc7e305fcd13ea3000000",
|
|
||||||
"NotebookId": "54bdc65599c37b0da9000003",
|
|
||||||
"UserId": "54bdc65599c37b0da9000002",
|
|
||||||
"Title": "asdfads",
|
|
||||||
"Desc": "",
|
|
||||||
"Tags": null,
|
|
||||||
"Abstract": "",
|
|
||||||
"Content": "",
|
|
||||||
"IsMarkdown": false,
|
|
||||||
"IsBlog": false,
|
|
||||||
"IsTrash": true,
|
|
||||||
"IsDeleted": false,
|
|
||||||
"Usn": 15,
|
|
||||||
"Files": [],
|
|
||||||
"CreatedTime": "2015-01-20T11:13:41.34+08:00",
|
|
||||||
"UpdatedTime": "2015-01-20T11:13:41.34+08:00",
|
|
||||||
"PublicTime": "0001-01-01T00:00:00Z"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
* 时间类型全是返回如 "2015-01-20T11:13:41.34+08:00" 的格式, (因为golang的time转成Json就是这样, 历史原因)
|
|
||||||
@@ -1,11 +1,10 @@
|
|||||||
package api
|
package api
|
||||||
|
|
||||||
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"
|
||||||
"github.com/revel/revel"
|
// "strconv"
|
||||||
"gopkg.in/mgo.v2/bson"
|
|
||||||
// "strconv"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// 用户登录后生成一个token, 将这个token保存到session中
|
// 用户登录后生成一个token, 将这个token保存到session中
|
||||||
@@ -17,53 +16,140 @@ type ApiAuth struct {
|
|||||||
ApiBaseContrller
|
ApiBaseContrller
|
||||||
}
|
}
|
||||||
|
|
||||||
// 登录
|
// 为了demo和register
|
||||||
// [ok]
|
func (c ApiAuth) doLogin(email, pwd string) revel.Result {
|
||||||
// 成功返回 {Ok: true, Item: token }
|
sessionId := c.Session.Id()
|
||||||
// 失败返回 {Ok: false, Msg: ""}
|
|
||||||
func (c ApiAuth) Login(email, pwd string) revel.Result {
|
|
||||||
var msg = ""
|
var msg = ""
|
||||||
|
|
||||||
userInfo, err := authService.Login(email, pwd)
|
userInfo := authService.Login(email, pwd)
|
||||||
if err != nil {
|
if userInfo.Email != "" {
|
||||||
|
c.SetSession(userInfo)
|
||||||
|
sessionService.ClearLoginTimes(sessionId)
|
||||||
|
return c.RenderJson(info.Re{Ok: true})
|
||||||
|
} else {
|
||||||
// 登录错误, 则错误次数++
|
// 登录错误, 则错误次数++
|
||||||
msg = "wrongUsernameOrPassword"
|
msg = "wrongUsernameOrPassword"
|
||||||
|
}
|
||||||
|
|
||||||
|
return c.RenderJson(info.Re{Ok: false, Item: sessionService.LoginTimesIsOver(sessionId) , Msg: c.Message(msg)})
|
||||||
|
}
|
||||||
|
func (c ApiAuth) Login(email, pwd string, captcha string) revel.Result {
|
||||||
|
sessionId := c.Session.Id()
|
||||||
|
var msg = ""
|
||||||
|
|
||||||
|
// > 5次需要验证码, 直到登录成功
|
||||||
|
if sessionService.LoginTimesIsOver(sessionId) && sessionService.GetCaptcha(sessionId) != captcha {
|
||||||
|
msg = "captchaError"
|
||||||
} else {
|
} else {
|
||||||
token := bson.NewObjectId().Hex()
|
userInfo := authService.Login(email, pwd)
|
||||||
sessionService.SetUserId(token, userInfo.UserId.Hex())
|
if userInfo.Email != "" {
|
||||||
return c.RenderJson(info.AuthOk{Ok: true, Token: token, UserId: userInfo.UserId, Email: userInfo.Email, Username: userInfo.Username})
|
c.SetSession(userInfo)
|
||||||
}
|
sessionService.ClearLoginTimes(sessionId)
|
||||||
return c.RenderJson(info.ApiRe{Ok: false, Msg: c.Message(msg)})
|
return c.RenderJson(info.Re{Ok: true})
|
||||||
|
} else {
|
||||||
|
// 登录错误, 则错误次数++
|
||||||
|
msg = "wrongUsernameOrPassword"
|
||||||
|
sessionService.IncrLoginTimes(sessionId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return c.RenderJson(info.Re{Ok: false, Item: sessionService.LoginTimesIsOver(sessionId) , Msg: c.Message(msg)})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 注销
|
// 注销
|
||||||
// [Ok]
|
|
||||||
func (c ApiAuth) Logout() revel.Result {
|
func (c ApiAuth) Logout() revel.Result {
|
||||||
token := c.getToken()
|
sessionId := c.Session.Id()
|
||||||
sessionService.Clear(token)
|
sessionService.Clear(sessionId)
|
||||||
re := info.NewApiRe()
|
c.ClearSession()
|
||||||
|
re := info.NewRe()
|
||||||
re.Ok = true
|
re.Ok = true
|
||||||
return c.RenderJson(re)
|
return c.RenderJson(re)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 注册
|
// 体验一下
|
||||||
// [Ok]
|
func (c ApiAuth) Demo() revel.Result {
|
||||||
// 成功后并不返回用户ID, 需要用户重新登录
|
c.doLogin(configService.GetGlobalStringConfig("demoUsername"), configService.GetGlobalStringConfig("demoPassword"))
|
||||||
func (c ApiAuth) Register(email, pwd string) revel.Result {
|
return c.Redirect("/note")
|
||||||
re := info.NewApiRe()
|
}
|
||||||
if !configService.IsOpenRegister() {
|
|
||||||
re.Msg = "notOpenRegister" // 未开放注册
|
|
||||||
return c.RenderJson(re)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
//--------
|
||||||
|
// 注册
|
||||||
|
func (c ApiAuth) Register(from string) revel.Result {
|
||||||
|
if !configService.IsOpenRegister() {
|
||||||
|
return c.Redirect("/index")
|
||||||
|
}
|
||||||
|
c.SetLocale()
|
||||||
|
c.RenderArgs["from"] = from
|
||||||
|
|
||||||
|
c.RenderArgs["title"] = c.Message("register")
|
||||||
|
c.RenderArgs["subTitle"] = c.Message("register")
|
||||||
|
return c.RenderTemplate("home/register.html")
|
||||||
|
}
|
||||||
|
func (c ApiAuth) DoRegister(email, pwd string) revel.Result {
|
||||||
|
if !configService.IsOpenRegister() {
|
||||||
|
return c.Redirect("/index")
|
||||||
|
}
|
||||||
|
|
||||||
|
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.RenderJson(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.RenderJson(re)
|
return c.RenderRe(re);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 注册
|
||||||
|
re.Ok, re.Msg = authService.Register(email, pwd)
|
||||||
|
|
||||||
|
// 注册成功, 则立即登录之
|
||||||
|
if re.Ok {
|
||||||
|
c.doLogin(email, pwd)
|
||||||
|
}
|
||||||
|
|
||||||
|
return c.RenderRe(re)
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------
|
||||||
|
// 找回密码
|
||||||
|
func (c ApiAuth) FindPassword() revel.Result {
|
||||||
|
c.RenderArgs["title"] = c.Message("findPassword")
|
||||||
|
c.RenderArgs["subTitle"] = c.Message("findPassword")
|
||||||
|
return c.RenderTemplate("home/find_password.html")
|
||||||
|
}
|
||||||
|
func (c ApiAuth) DoFindPassword(email string) revel.Result {
|
||||||
|
pwdService.FindPwd(email)
|
||||||
|
re := info.NewRe()
|
||||||
|
re.Ok = true
|
||||||
|
return c.RenderJson(re)
|
||||||
|
}
|
||||||
|
// 点击链接后, 先验证之
|
||||||
|
func (c ApiAuth) FindPassword2(token string) revel.Result {
|
||||||
|
c.RenderArgs["title"] = c.Message("findPassword")
|
||||||
|
c.RenderArgs["subTitle"] = c.Message("findPassword")
|
||||||
|
if token == "" {
|
||||||
|
return c.RenderTemplate("find_password2_timeout.html")
|
||||||
|
}
|
||||||
|
ok, _, findPwd := tokenService.VerifyToken(token, info.TokenPwd);
|
||||||
|
if !ok {
|
||||||
|
return c.RenderTemplate("home/find_password2_timeout.html")
|
||||||
|
}
|
||||||
|
c.RenderArgs["findPwd"] = findPwd
|
||||||
|
|
||||||
|
c.RenderArgs["title"] = c.Message("updatePassword")
|
||||||
|
c.RenderArgs["subTitle"] = c.Message("updatePassword")
|
||||||
|
|
||||||
|
return c.RenderTemplate("home/find_password2.html")
|
||||||
|
}
|
||||||
|
// 找回密码修改密码
|
||||||
|
func (c ApiAuth) FindPasswordUpdate(token, pwd string) revel.Result {
|
||||||
|
re := info.NewRe();
|
||||||
|
|
||||||
|
if re.Ok, re.Msg = Vd("password", pwd); !re.Ok {
|
||||||
|
return c.RenderRe(re);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 注册
|
// 修改之
|
||||||
re.Ok, re.Msg = authService.Register(email, pwd, "")
|
re.Ok, re.Msg = pwdService.UpdatePwd(token, pwd)
|
||||||
return c.RenderJson(re)
|
return c.RenderRe(re)
|
||||||
}
|
}
|
||||||
@@ -1,181 +1,19 @@
|
|||||||
package api
|
package api
|
||||||
|
|
||||||
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/lea"
|
||||||
"github.com/leanote/leanote/app/controllers"
|
"github.com/leanote/leanote/app/controllers"
|
||||||
"github.com/leanote/leanote/app/info"
|
// "io/ioutil"
|
||||||
"os"
|
|
||||||
// "fmt"
|
// "fmt"
|
||||||
"io/ioutil"
|
// "math"
|
||||||
// "fmt"
|
// "strconv"
|
||||||
// "math"
|
// "strings"
|
||||||
// "strconv"
|
|
||||||
"strings"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// 公用Controller, 其它Controller继承它
|
// 公用Controller, 其它Controller继承它
|
||||||
type ApiBaseContrller struct {
|
type ApiBaseContrller struct {
|
||||||
controllers.BaseController // 不能用*BaseController
|
controllers.BaseController // 不能用*BaseController
|
||||||
}
|
}
|
||||||
|
|
||||||
// 得到token, 这个token是在AuthInterceptor设到Session中的
|
|
||||||
func (c ApiBaseContrller) getToken() string {
|
|
||||||
return c.Session["_token"]
|
|
||||||
}
|
|
||||||
|
|
||||||
// userId
|
|
||||||
// _userId是在AuthInterceptor设置的
|
|
||||||
func (c ApiBaseContrller) getUserId() string {
|
|
||||||
return c.Session["_userId"]
|
|
||||||
}
|
|
||||||
|
|
||||||
// 得到用户信息
|
|
||||||
func (c ApiBaseContrller) getUserInfo() info.User {
|
|
||||||
userId := c.Session["_userId"]
|
|
||||||
if userId == "" {
|
|
||||||
return info.User{}
|
|
||||||
}
|
|
||||||
return userService.GetUserInfo(userId)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 上传附件
|
|
||||||
func (c ApiBaseContrller) uploadAttach(name string, noteId string) (ok bool, msg string, id string) {
|
|
||||||
userId := c.getUserId();
|
|
||||||
|
|
||||||
// 判断是否有权限为笔记添加附件
|
|
||||||
// 如果笔记还没有添加是不是会有问题
|
|
||||||
/*
|
|
||||||
if !shareService.HasUpdateNotePerm(noteId, userId) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
file, handel, err := c.Request.FormFile(name)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
defer file.Close()
|
|
||||||
|
|
||||||
data, err := ioutil.ReadAll(file)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// > 5M?
|
|
||||||
maxFileSize := configService.GetUploadSize("uploadAttachSize");
|
|
||||||
if maxFileSize <= 0 {
|
|
||||||
maxFileSize = 1000
|
|
||||||
}
|
|
||||||
if(float64(len(data)) > maxFileSize * float64(1024*1024)) {
|
|
||||||
msg = "fileIsTooLarge"
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 生成上传路径
|
|
||||||
filePath := "files/" + userId + "/attachs"
|
|
||||||
dir := revel.BasePath + "/" + filePath
|
|
||||||
err = os.MkdirAll(dir, 0755)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// 生成新的文件名
|
|
||||||
filename := handel.Filename
|
|
||||||
_, ext := SplitFilename(filename) // .doc
|
|
||||||
filename = NewGuid() + ext
|
|
||||||
toPath := dir + "/" + filename;
|
|
||||||
err = ioutil.WriteFile(toPath, data, 0777)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// add File to db
|
|
||||||
fileType := ""
|
|
||||||
if ext != "" {
|
|
||||||
fileType = strings.ToLower(ext[1:])
|
|
||||||
}
|
|
||||||
filesize := GetFilesize(toPath)
|
|
||||||
fileInfo := info.Attach{AttachId: bson.NewObjectId(),
|
|
||||||
Name: filename,
|
|
||||||
Title: handel.Filename,
|
|
||||||
NoteId: bson.ObjectIdHex(noteId),
|
|
||||||
UploadUserId: bson.ObjectIdHex(userId),
|
|
||||||
Path: filePath + "/" + filename,
|
|
||||||
Type: fileType,
|
|
||||||
Size: filesize}
|
|
||||||
|
|
||||||
ok, msg = attachService.AddAttach(fileInfo, true)
|
|
||||||
if !ok {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
id = fileInfo.AttachId.Hex()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 上传图片
|
|
||||||
func (c ApiBaseContrller) upload(name string, noteId string, isAttach bool) (ok bool, msg string, id string) {
|
|
||||||
if isAttach {
|
|
||||||
return c.uploadAttach(name, noteId)
|
|
||||||
}
|
|
||||||
file, handel, err := c.Request.FormFile(name)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
defer file.Close()
|
|
||||||
// 生成上传路径
|
|
||||||
fileUrlPath := "files/" + c.getUserId() + "/images"
|
|
||||||
dir := revel.BasePath + "/" + fileUrlPath
|
|
||||||
err = os.MkdirAll(dir, 0755)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// 生成新的文件名
|
|
||||||
filename := handel.Filename
|
|
||||||
_, ext := SplitFilename(filename)
|
|
||||||
if(ext != ".gif" && ext != ".jpg" && ext != ".png" && ext != ".bmp" && ext != ".jpeg") {
|
|
||||||
msg = "notImage"
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
filename = NewGuid() + ext
|
|
||||||
data, err := ioutil.ReadAll(file)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
maxFileSize := configService.GetUploadSize("uploadImageSize");
|
|
||||||
if maxFileSize <= 0 {
|
|
||||||
maxFileSize = 1000
|
|
||||||
}
|
|
||||||
|
|
||||||
// > 2M?
|
|
||||||
if(float64(len(data)) > maxFileSize * float64(1024*1024)) {
|
|
||||||
msg = "fileIsTooLarge"
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
toPath := dir + "/" + filename;
|
|
||||||
err = ioutil.WriteFile(toPath, data, 0777)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// 改变成gif图片
|
|
||||||
_, toPathGif := TransToGif(toPath, 0, true)
|
|
||||||
filename = GetFilename(toPathGif)
|
|
||||||
filesize := GetFilesize(toPathGif)
|
|
||||||
fileUrlPath += "/" + filename
|
|
||||||
|
|
||||||
// File
|
|
||||||
fileInfo := info.File{FileId: bson.NewObjectId(),
|
|
||||||
Name: filename,
|
|
||||||
Title: handel.Filename,
|
|
||||||
Path: fileUrlPath,
|
|
||||||
Size: filesize}
|
|
||||||
ok, msg = fileService.AddImage(fileInfo, "", c.getUserId(), true)
|
|
||||||
if ok {
|
|
||||||
id = fileInfo.FileId.Hex()
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
@@ -1,164 +0,0 @@
|
|||||||
package api
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/revel/revel"
|
|
||||||
// "encoding/json"
|
|
||||||
// . "github.com/leanote/leanote/app/lea"
|
|
||||||
// "gopkg.in/mgo.v2/bson"
|
|
||||||
// "github.com/leanote/leanote/app/lea/netutil"
|
|
||||||
// "github.com/leanote/leanote/app/info"
|
|
||||||
// "io/ioutil"
|
|
||||||
"os"
|
|
||||||
// "strconv"
|
|
||||||
"io"
|
|
||||||
"time"
|
|
||||||
"strings"
|
|
||||||
"archive/tar"
|
|
||||||
"compress/gzip"
|
|
||||||
)
|
|
||||||
|
|
||||||
// 文件操作, 图片, 头像上传, 输出
|
|
||||||
|
|
||||||
type ApiFile struct {
|
|
||||||
ApiBaseContrller
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
// 协作时复制图片到owner
|
|
||||||
func (c ApiFile) CopyImage(userId, fileId, toUserId string) revel.Result {
|
|
||||||
re := info.NewRe()
|
|
||||||
|
|
||||||
re.Ok, re.Id = fileService.CopyImage(userId, fileId, toUserId)
|
|
||||||
|
|
||||||
return c.RenderJson(re)
|
|
||||||
}
|
|
||||||
|
|
||||||
// get all images by userId with page
|
|
||||||
func (c ApiFile) GetImages(albumId, key string, page int) revel.Result {
|
|
||||||
imagesPage := fileService.ListImagesWithPage(c.getUserId(), albumId, key, page, 12)
|
|
||||||
re := info.NewRe()
|
|
||||||
re.Ok = true
|
|
||||||
re.Item = imagesPage
|
|
||||||
return c.RenderJson(re)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c ApiFile) UpdateImageTitle(fileId, title string) revel.Result {
|
|
||||||
re := info.NewRe()
|
|
||||||
re.Ok = fileService.UpdateImageTitle(c.getUserId(), fileId, title)
|
|
||||||
return c.RenderJson(re)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c ApiFile) DeleteImage(fileId string) revel.Result {
|
|
||||||
re := info.NewRe()
|
|
||||||
re.Ok, re.Msg = fileService.DeleteImage(c.getUserId(), fileId)
|
|
||||||
return c.RenderJson(re)
|
|
||||||
}
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
//-----------
|
|
||||||
|
|
||||||
// 输出image
|
|
||||||
// [OK]
|
|
||||||
func (c ApiFile) GetImage(fileId string) revel.Result {
|
|
||||||
path := fileService.GetFile(c.getUserId(), fileId) // 得到路径
|
|
||||||
if path == "" {
|
|
||||||
return c.RenderText("")
|
|
||||||
}
|
|
||||||
fn := revel.BasePath + "/" + strings.TrimLeft(path, "/")
|
|
||||||
file, _ := os.Open(fn)
|
|
||||||
return c.RenderFile(file, revel.Inline) // revel.Attachment
|
|
||||||
}
|
|
||||||
|
|
||||||
// 下载附件
|
|
||||||
// [OK]
|
|
||||||
func (c ApiFile) GetAttach(fileId string) revel.Result {
|
|
||||||
attach := attachService.GetAttach(fileId, c.getUserId()); // 得到路径
|
|
||||||
path := attach.Path
|
|
||||||
if path == "" {
|
|
||||||
return c.RenderText("No Such File")
|
|
||||||
}
|
|
||||||
fn := revel.BasePath + "/" + strings.TrimLeft(path, "/")
|
|
||||||
file, _ := os.Open(fn)
|
|
||||||
return c.RenderBinary(file, attach.Title, revel.Attachment, time.Now()) // revel.Attachment
|
|
||||||
}
|
|
||||||
|
|
||||||
// 下载所有附件
|
|
||||||
// [OK]
|
|
||||||
func (c ApiFile) GetAllAttachs(noteId string) revel.Result {
|
|
||||||
note := noteService.GetNoteById(noteId)
|
|
||||||
if note.NoteId == "" {
|
|
||||||
return c.RenderText("")
|
|
||||||
}
|
|
||||||
// 得到文件列表
|
|
||||||
attachs := attachService.ListAttachs(noteId, c.getUserId())
|
|
||||||
if attachs == nil || len(attachs) == 0 {
|
|
||||||
return c.RenderText("")
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
dir := revel.BasePath + "/files/tmp"
|
|
||||||
err := os.MkdirAll(dir, 0755)
|
|
||||||
if err != nil {
|
|
||||||
return c.RenderText("")
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
filename := note.Title + ".tar.gz"
|
|
||||||
if note.Title == "" {
|
|
||||||
filename = "all.tar.gz"
|
|
||||||
}
|
|
||||||
|
|
||||||
// file write
|
|
||||||
fw, err := os.Create(revel.BasePath + "/files/" + filename)
|
|
||||||
if err != nil {
|
|
||||||
return c.RenderText("")
|
|
||||||
}
|
|
||||||
// defer fw.Close() // 不需要关闭, 还要读取给用户下载
|
|
||||||
|
|
||||||
// gzip write
|
|
||||||
gw := gzip.NewWriter(fw)
|
|
||||||
defer gw.Close()
|
|
||||||
|
|
||||||
// tar write
|
|
||||||
tw := tar.NewWriter(gw)
|
|
||||||
defer tw.Close()
|
|
||||||
|
|
||||||
// 遍历文件列表
|
|
||||||
for _, attach := range attachs {
|
|
||||||
fn := revel.BasePath + "/" + strings.TrimLeft(attach.Path, "/")
|
|
||||||
fr, err := os.Open(fn)
|
|
||||||
fileInfo, _ := fr.Stat()
|
|
||||||
if err != nil {
|
|
||||||
return c.RenderText("")
|
|
||||||
}
|
|
||||||
defer fr.Close()
|
|
||||||
|
|
||||||
// 信息头
|
|
||||||
h := new(tar.Header)
|
|
||||||
h.Name = attach.Title
|
|
||||||
h.Size = fileInfo.Size()
|
|
||||||
h.Mode = int64(fileInfo.Mode())
|
|
||||||
h.ModTime = fileInfo.ModTime()
|
|
||||||
|
|
||||||
// 写信息头
|
|
||||||
err = tw.WriteHeader(h)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 写文件
|
|
||||||
_, err = io.Copy(tw, fr)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
} // for
|
|
||||||
|
|
||||||
// tw.Close()
|
|
||||||
// gw.Close()
|
|
||||||
// fw.Close()
|
|
||||||
// file, _ := os.Open(dir + "/" + filename)
|
|
||||||
// fw.Seek(0, 0)
|
|
||||||
return c.RenderBinary(fw, filename, revel.Attachment, time.Now()) // revel.Attachment
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,581 +0,0 @@
|
|||||||
package api
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/revel/revel"
|
|
||||||
// "encoding/json"
|
|
||||||
"github.com/leanote/leanote/app/info"
|
|
||||||
. "github.com/leanote/leanote/app/lea"
|
|
||||||
"gopkg.in/mgo.v2/bson"
|
|
||||||
"regexp"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
// "github.com/leanote/leanote/app/types"
|
|
||||||
// "io/ioutil"
|
|
||||||
// "fmt"
|
|
||||||
// "bytes"
|
|
||||||
// "os"
|
|
||||||
)
|
|
||||||
|
|
||||||
// 笔记API
|
|
||||||
|
|
||||||
type ApiNote struct {
|
|
||||||
ApiBaseContrller
|
|
||||||
}
|
|
||||||
|
|
||||||
// 获取同步的笔记
|
|
||||||
// > afterUsn的笔记
|
|
||||||
// 无Desc, Abstract, 有Files
|
|
||||||
/*
|
|
||||||
{
|
|
||||||
"NoteId": "55195fa199c37b79be000005",
|
|
||||||
"NotebookId": "55195fa199c37b79be000002",
|
|
||||||
"UserId": "55195fa199c37b79be000001",
|
|
||||||
"Title": "Leanote语法Leanote语法Leanote语法Leanote语法Leanote语法",
|
|
||||||
"Desc": "",
|
|
||||||
"Tags": null,
|
|
||||||
"Abstract": "",
|
|
||||||
"Content": "",
|
|
||||||
"IsMarkdown": true,
|
|
||||||
"IsBlog": false,
|
|
||||||
"IsTrash": false,
|
|
||||||
"Usn": 5,
|
|
||||||
"Files": [],
|
|
||||||
"CreatedTime": "2015-03-30T22:37:21.695+08:00",
|
|
||||||
"UpdatedTime": "2015-03-30T22:37:21.724+08:00",
|
|
||||||
"PublicTime": "2015-03-30T22:37:21.695+08:00"
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
func (c ApiNote) GetSyncNotes(afterUsn, maxEntry int) revel.Result {
|
|
||||||
if maxEntry == 0 {
|
|
||||||
maxEntry = 100
|
|
||||||
}
|
|
||||||
notes := noteService.GetSyncNotes(c.getUserId(), afterUsn, maxEntry)
|
|
||||||
return c.RenderJson(notes)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 得到笔记本下的笔记
|
|
||||||
// [OK]
|
|
||||||
func (c ApiNote) GetNotes(notebookId string) revel.Result {
|
|
||||||
if notebookId != "" && !bson.IsObjectIdHex(notebookId) {
|
|
||||||
re := info.NewApiRe()
|
|
||||||
re.Msg = "notebookIdInvalid"
|
|
||||||
return c.RenderJson(re)
|
|
||||||
}
|
|
||||||
_, notes := noteService.ListNotes(c.getUserId(), notebookId, false, c.GetPage(), pageSize, defaultSortField, false, false)
|
|
||||||
return c.RenderJson(noteService.ToApiNotes(notes))
|
|
||||||
}
|
|
||||||
|
|
||||||
// 得到trash
|
|
||||||
// [OK]
|
|
||||||
func (c ApiNote) GetTrashNotes() revel.Result {
|
|
||||||
_, notes := noteService.ListNotes(c.getUserId(), "", true, c.GetPage(), pageSize, defaultSortField, false, false)
|
|
||||||
return c.RenderJson(noteService.ToApiNotes(notes))
|
|
||||||
}
|
|
||||||
|
|
||||||
// get Note
|
|
||||||
// [OK]
|
|
||||||
/*
|
|
||||||
{
|
|
||||||
"NoteId": "550c0bee2ec82a2eb5000000",
|
|
||||||
"NotebookId": "54a1676399c37b1c77000004",
|
|
||||||
"UserId": "54a1676399c37b1c77000002",
|
|
||||||
"Title": "asdfadsf--=",
|
|
||||||
"Desc": "",
|
|
||||||
"Tags": [
|
|
||||||
""
|
|
||||||
],
|
|
||||||
"Abstract": "",
|
|
||||||
"Content": "",
|
|
||||||
"IsMarkdown": false,
|
|
||||||
"IsBlog": false,
|
|
||||||
"IsTrash": false,
|
|
||||||
"Usn": 8,
|
|
||||||
"Files": [
|
|
||||||
{
|
|
||||||
"FileId": "551975d599c37b970f000002",
|
|
||||||
"LocalFileId": "",
|
|
||||||
"Type": "",
|
|
||||||
"Title": "",
|
|
||||||
"HasBody": false,
|
|
||||||
"IsAttach": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"FileId": "551975de99c37b970f000003",
|
|
||||||
"LocalFileId": "",
|
|
||||||
"Type": "doc",
|
|
||||||
"Title": "李铁-简历-ali-print-en.doc",
|
|
||||||
"HasBody": false,
|
|
||||||
"IsAttach": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"FileId": "551975de99c37b970f000004",
|
|
||||||
"LocalFileId": "",
|
|
||||||
"Type": "doc",
|
|
||||||
"Title": "李铁-简历-ali-print.doc",
|
|
||||||
"HasBody": false,
|
|
||||||
"IsAttach": true
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"CreatedTime": "2015-03-20T20:00:52.463+08:00",
|
|
||||||
"UpdatedTime": "2015-03-31T00:12:44.967+08:00",
|
|
||||||
"PublicTime": "2015-03-20T20:00:52.463+08:00"
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
func (c ApiNote) GetNote(noteId string) revel.Result {
|
|
||||||
if !bson.IsObjectIdHex(noteId) {
|
|
||||||
re := info.NewApiRe()
|
|
||||||
re.Msg = "noteIdInvalid"
|
|
||||||
return c.RenderJson(re)
|
|
||||||
}
|
|
||||||
|
|
||||||
note := noteService.GetNote(noteId, c.getUserId())
|
|
||||||
if note.NoteId == "" {
|
|
||||||
re := info.NewApiRe()
|
|
||||||
re.Msg = "notExists"
|
|
||||||
return c.RenderJson(re)
|
|
||||||
}
|
|
||||||
apiNotes := noteService.ToApiNotes([]info.Note{note})
|
|
||||||
return c.RenderJson(apiNotes[0])
|
|
||||||
}
|
|
||||||
|
|
||||||
// 得到note和内容
|
|
||||||
// [OK]
|
|
||||||
func (c ApiNote) GetNoteAndContent(noteId string) revel.Result {
|
|
||||||
noteAndContent := noteService.GetNoteAndContent(noteId, c.getUserId())
|
|
||||||
|
|
||||||
apiNotes := noteService.ToApiNotes([]info.Note{noteAndContent.Note})
|
|
||||||
apiNote := apiNotes[0]
|
|
||||||
apiNote.Content = noteAndContent.Content
|
|
||||||
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处理
|
|
||||||
// 
|
|
||||||
// [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) // 查找所有的
|
|
||||||
// [[ 5503537b38f4111dcb0000d1] [ 5503537b38f4111dcb0000d1]]
|
|
||||||
for _, eachFind := range findsImageMarkdown {
|
|
||||||
// [ 你好啊, 我很好, 为什么? 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链接是
|
|
||||||
// https://leanote.com/api/file/getImage?fileId=xx
|
|
||||||
// https://leanote.com/api/file/getAttach?fileId=xx
|
|
||||||
// 将fileId=映射成ServerFileId, 这里的fileId可能是本地的FileId
|
|
||||||
func (c ApiNote) fixPostNotecontent(noteOrContent *info.ApiNote) {
|
|
||||||
if noteOrContent.Content == "" {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
files := noteOrContent.Files
|
|
||||||
if files != nil && len(files) > 0 {
|
|
||||||
for _, file := range files {
|
|
||||||
if file.LocalFileId != "" {
|
|
||||||
noteOrContent.Content = strings.Replace(noteOrContent.Content, "fileId=" + file.LocalFileId, "fileId=" + file.FileId, -1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 得到内容
|
|
||||||
// [OK]
|
|
||||||
func (c ApiNote) GetNoteContent(noteId string) revel.Result {
|
|
||||||
// re := info.NewRe()
|
|
||||||
noteContent := noteService.GetNoteContent(noteId, c.getUserId())
|
|
||||||
if noteContent.Content != "" {
|
|
||||||
noteContent.Content = c.fixContent(noteContent.Content)
|
|
||||||
}
|
|
||||||
|
|
||||||
apiNoteContent := info.ApiNoteContent{
|
|
||||||
NoteId: noteContent.NoteId,
|
|
||||||
UserId: noteContent.UserId,
|
|
||||||
Content: noteContent.Content,
|
|
||||||
}
|
|
||||||
|
|
||||||
// re.Item = noteContent
|
|
||||||
return c.RenderJson(apiNoteContent)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 添加笔记
|
|
||||||
// [OK]
|
|
||||||
func (c ApiNote) AddNote(noteOrContent info.ApiNote) revel.Result {
|
|
||||||
userId := bson.ObjectIdHex(c.getUserId())
|
|
||||||
re := info.NewRe()
|
|
||||||
myUserId := userId
|
|
||||||
// 为共享新建?
|
|
||||||
/*
|
|
||||||
if noteOrContent.FromUserId != "" {
|
|
||||||
userId = bson.ObjectIdHex(noteOrContent.FromUserId)
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
// Log(noteOrContent.Title)
|
|
||||||
// LogJ(noteOrContent)
|
|
||||||
/*
|
|
||||||
LogJ(c.Params)
|
|
||||||
for name, _ := range c.Params.Files {
|
|
||||||
Log(name)
|
|
||||||
file, _, _ := c.Request.FormFile(name)
|
|
||||||
LogJ(file)
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
// return c.RenderJson(re)
|
|
||||||
if noteOrContent.NotebookId == "" || !bson.IsObjectIdHex(noteOrContent.NotebookId) {
|
|
||||||
re.Msg = "notebookIdNotExists"
|
|
||||||
return c.RenderJson(re)
|
|
||||||
}
|
|
||||||
|
|
||||||
noteId := bson.NewObjectId()
|
|
||||||
// TODO 先上传图片/附件, 如果不成功, 则返回false
|
|
||||||
//
|
|
||||||
attachNum := 0
|
|
||||||
if noteOrContent.Files != nil && len(noteOrContent.Files) > 0 {
|
|
||||||
for i, file := range noteOrContent.Files {
|
|
||||||
if file.HasBody {
|
|
||||||
if file.LocalFileId != "" {
|
|
||||||
// FileDatas[54c7ae27d98d0329dd000000]
|
|
||||||
ok, msg, fileId := c.upload("FileDatas["+file.LocalFileId+"]", noteId.Hex(), file.IsAttach)
|
|
||||||
|
|
||||||
if !ok {
|
|
||||||
re.Ok = false
|
|
||||||
if msg != "" {
|
|
||||||
Log(msg)
|
|
||||||
Log(file.LocalFileId)
|
|
||||||
re.Msg = "fileUploadError"
|
|
||||||
}
|
|
||||||
// 报不是图片的错误没关系, 证明客户端传来非图片的数据
|
|
||||||
if msg != "notImage" {
|
|
||||||
return c.RenderJson(re)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// 建立映射
|
|
||||||
file.FileId = fileId
|
|
||||||
noteOrContent.Files[i] = file
|
|
||||||
|
|
||||||
if file.IsAttach {
|
|
||||||
attachNum++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return c.RenderJson(re)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
c.fixPostNotecontent(¬eOrContent)
|
|
||||||
|
|
||||||
// Log("Add")
|
|
||||||
// LogJ(noteOrContent)
|
|
||||||
|
|
||||||
// return c.RenderJson(re)
|
|
||||||
|
|
||||||
note := info.Note{UserId: userId,
|
|
||||||
NoteId: noteId,
|
|
||||||
NotebookId: bson.ObjectIdHex(noteOrContent.NotebookId),
|
|
||||||
Title: noteOrContent.Title,
|
|
||||||
Tags: noteOrContent.Tags,
|
|
||||||
Desc: noteOrContent.Desc,
|
|
||||||
// ImgSrc: noteOrContent.ImgSrc,
|
|
||||||
IsBlog: noteOrContent.IsBlog,
|
|
||||||
IsMarkdown: noteOrContent.IsMarkdown,
|
|
||||||
AttachNum: attachNum,
|
|
||||||
}
|
|
||||||
noteContent := info.NoteContent{NoteId: note.NoteId,
|
|
||||||
UserId: userId,
|
|
||||||
IsBlog: note.IsBlog,
|
|
||||||
Content: noteOrContent.Content,
|
|
||||||
Abstract: noteOrContent.Abstract}
|
|
||||||
|
|
||||||
// 通过内容得到Desc, abstract
|
|
||||||
if noteOrContent.Abstract == "" {
|
|
||||||
note.Desc = SubStringHTMLToRaw(noteContent.Content, 200)
|
|
||||||
noteContent.Abstract = SubStringHTML(noteContent.Content, 200, "")
|
|
||||||
} else {
|
|
||||||
note.Desc = SubStringHTMLToRaw(noteContent.Abstract, 200)
|
|
||||||
}
|
|
||||||
|
|
||||||
note = noteService.AddNoteAndContentApi(note, noteContent, myUserId)
|
|
||||||
|
|
||||||
if note.NoteId == "" {
|
|
||||||
re.Ok = false
|
|
||||||
return c.RenderJson(re)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 添加需要返回的
|
|
||||||
noteOrContent.NoteId = note.NoteId.Hex()
|
|
||||||
noteOrContent.Usn = note.Usn
|
|
||||||
noteOrContent.CreatedTime = note.CreatedTime
|
|
||||||
noteOrContent.UpdatedTime = note.UpdatedTime
|
|
||||||
noteOrContent.UserId = c.getUserId()
|
|
||||||
noteOrContent.IsMarkdown = note.IsMarkdown
|
|
||||||
// 删除一些不要返回的, 删除Desc?
|
|
||||||
noteOrContent.Content = ""
|
|
||||||
noteOrContent.Abstract = ""
|
|
||||||
// apiNote := info.NoteToApiNote(note, noteOrContent.Files)
|
|
||||||
return c.RenderJson(noteOrContent)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 更新笔记
|
|
||||||
// [OK]
|
|
||||||
func (c ApiNote) UpdateNote(noteOrContent info.ApiNote) revel.Result {
|
|
||||||
re := info.NewReUpdate()
|
|
||||||
|
|
||||||
noteUpdate := bson.M{}
|
|
||||||
needUpdateNote := false
|
|
||||||
|
|
||||||
noteId := noteOrContent.NoteId
|
|
||||||
|
|
||||||
if noteOrContent.NoteId == "" {
|
|
||||||
re.Msg = "noteIdNotExists"
|
|
||||||
return c.RenderJson(re)
|
|
||||||
}
|
|
||||||
|
|
||||||
if noteOrContent.Usn <= 0 {
|
|
||||||
re.Msg = "usnNotExists"
|
|
||||||
return c.RenderJson(re)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Log("_____________")
|
|
||||||
// LogJ(noteOrContent)
|
|
||||||
/*
|
|
||||||
LogJ(c.Params.Files)
|
|
||||||
LogJ(c.Request.Header)
|
|
||||||
LogJ(c.Params.Values)
|
|
||||||
*/
|
|
||||||
|
|
||||||
// 先判断USN的问题, 因为很可能添加完附件后, 会有USN冲突, 这时附件就添错了
|
|
||||||
userId := c.getUserId()
|
|
||||||
note := noteService.GetNote(noteId, userId)
|
|
||||||
if note.NoteId == "" {
|
|
||||||
re.Msg = "notExists"
|
|
||||||
return c.RenderJson(re)
|
|
||||||
}
|
|
||||||
if note.Usn != noteOrContent.Usn {
|
|
||||||
re.Msg = "conflict"
|
|
||||||
Log("conflict")
|
|
||||||
return c.RenderJson(re)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 如果传了files
|
|
||||||
// TODO 测试
|
|
||||||
/*
|
|
||||||
for key, v := range c.Params.Values {
|
|
||||||
Log(key)
|
|
||||||
Log(v)
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
// Log(c.Has("Files[0]"))
|
|
||||||
if c.Has("Files[0][LocalFileId]") {
|
|
||||||
// LogJ(c.Params.Files)
|
|
||||||
if noteOrContent.Files != nil && len(noteOrContent.Files) > 0 {
|
|
||||||
for i, file := range noteOrContent.Files {
|
|
||||||
if file.HasBody {
|
|
||||||
if file.LocalFileId != "" {
|
|
||||||
// FileDatas[54c7ae27d98d0329dd000000]
|
|
||||||
ok, msg, fileId := c.upload("FileDatas["+file.LocalFileId+"]", noteId, file.IsAttach)
|
|
||||||
if !ok {
|
|
||||||
Log("upload file error")
|
|
||||||
re.Ok = false
|
|
||||||
if msg == "" {
|
|
||||||
re.Msg = "fileUploadError"
|
|
||||||
} else {
|
|
||||||
re.Msg = msg
|
|
||||||
}
|
|
||||||
return c.RenderJson(re)
|
|
||||||
} else {
|
|
||||||
// 建立映射
|
|
||||||
file.FileId = fileId
|
|
||||||
noteOrContent.Files[i] = file
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return c.RenderJson(re)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Log("after upload")
|
|
||||||
// LogJ(noteOrContent.Files)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 移到外面来, 删除最后一个file时也要处理, 不然总删不掉
|
|
||||||
// 附件问题, 根据Files, 有些要删除的, 只留下这些
|
|
||||||
attachService.UpdateOrDeleteAttachApi(noteId, userId, noteOrContent.Files)
|
|
||||||
|
|
||||||
// Desc前台传来
|
|
||||||
if c.Has("Desc") {
|
|
||||||
needUpdateNote = true
|
|
||||||
noteUpdate["Desc"] = noteOrContent.Desc
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
if c.Has("ImgSrc") {
|
|
||||||
needUpdateNote = true
|
|
||||||
noteUpdate["ImgSrc"] = noteOrContent.ImgSrc
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
if c.Has("Title") {
|
|
||||||
needUpdateNote = true
|
|
||||||
noteUpdate["Title"] = noteOrContent.Title
|
|
||||||
}
|
|
||||||
if c.Has("IsTrash") {
|
|
||||||
needUpdateNote = true
|
|
||||||
noteUpdate["IsTrash"] = noteOrContent.IsTrash
|
|
||||||
}
|
|
||||||
|
|
||||||
// 是否是博客
|
|
||||||
if c.Has("IsBlog") {
|
|
||||||
needUpdateNote = true
|
|
||||||
noteUpdate["IsBlog"] = noteOrContent.IsBlog
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
Log(c.Has("tags[0]"))
|
|
||||||
Log(c.Has("Tags[]"))
|
|
||||||
for key, v := range c.Params.Values {
|
|
||||||
Log(key)
|
|
||||||
Log(v)
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
if c.Has("Tags[0]") {
|
|
||||||
needUpdateNote = true
|
|
||||||
noteUpdate["Tags"] = noteOrContent.Tags
|
|
||||||
}
|
|
||||||
|
|
||||||
if c.Has("NotebookId") {
|
|
||||||
if bson.IsObjectIdHex(noteOrContent.NotebookId) {
|
|
||||||
needUpdateNote = true
|
|
||||||
noteUpdate["NotebookId"] = bson.ObjectIdHex(noteOrContent.NotebookId)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if c.Has("Content") {
|
|
||||||
// 通过内容得到Desc, 如果有Abstract, 则用Abstract生成Desc
|
|
||||||
if noteOrContent.Abstract == "" {
|
|
||||||
noteUpdate["Desc"] = SubStringHTMLToRaw(noteOrContent.Content, 200)
|
|
||||||
} else {
|
|
||||||
noteUpdate["Desc"] = SubStringHTMLToRaw(noteOrContent.Abstract, 200)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
afterNoteUsn := 0
|
|
||||||
noteOk := false
|
|
||||||
noteMsg := ""
|
|
||||||
if needUpdateNote {
|
|
||||||
noteOk, noteMsg, afterNoteUsn = noteService.UpdateNote(c.getUserId(), noteOrContent.NoteId, noteUpdate, noteOrContent.Usn)
|
|
||||||
if !noteOk {
|
|
||||||
re.Ok = false
|
|
||||||
re.Msg = noteMsg
|
|
||||||
return c.RenderJson(re)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//-------------
|
|
||||||
afterContentUsn := 0
|
|
||||||
contentOk := false
|
|
||||||
contentMsg := ""
|
|
||||||
if c.Has("Content") {
|
|
||||||
// 把fileId替换下
|
|
||||||
c.fixPostNotecontent(¬eOrContent)
|
|
||||||
// 如果传了Abstract就用之
|
|
||||||
if noteOrContent.Abstract == "" {
|
|
||||||
noteOrContent.Abstract = SubStringHTML(noteOrContent.Content, 200, "")
|
|
||||||
}
|
|
||||||
// Log("--------> afte fixed")
|
|
||||||
// Log(noteOrContent.Content)
|
|
||||||
contentOk, contentMsg, afterContentUsn = noteService.UpdateNoteContent(c.getUserId(),
|
|
||||||
noteOrContent.NoteId, noteOrContent.Content, noteOrContent.Abstract, needUpdateNote, noteOrContent.Usn)
|
|
||||||
}
|
|
||||||
|
|
||||||
if needUpdateNote {
|
|
||||||
re.Ok = noteOk
|
|
||||||
re.Msg = noteMsg
|
|
||||||
re.Usn = afterNoteUsn
|
|
||||||
} else {
|
|
||||||
re.Ok = contentOk
|
|
||||||
re.Msg = contentMsg
|
|
||||||
re.Usn = afterContentUsn
|
|
||||||
}
|
|
||||||
|
|
||||||
if !re.Ok {
|
|
||||||
return c.RenderJson(re)
|
|
||||||
}
|
|
||||||
|
|
||||||
noteOrContent.Content = ""
|
|
||||||
noteOrContent.Usn = re.Usn
|
|
||||||
noteOrContent.UpdatedTime = time.Now()
|
|
||||||
|
|
||||||
// Log("after upload")
|
|
||||||
// LogJ(noteOrContent.Files)
|
|
||||||
noteOrContent.UserId = c.getUserId()
|
|
||||||
|
|
||||||
return c.RenderJson(noteOrContent)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 删除trash
|
|
||||||
func (c ApiNote) DeleteTrash(noteId string, usn int) revel.Result {
|
|
||||||
re := info.NewReUpdate()
|
|
||||||
re.Ok, re.Msg, re.Usn = trashService.DeleteTrashApi(noteId, c.getUserId(), usn)
|
|
||||||
return c.RenderJson(re)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 得到历史列表
|
|
||||||
/*
|
|
||||||
func (c ApiNote) GetHistories(noteId string) revel.Result {
|
|
||||||
re := info.NewRe()
|
|
||||||
histories := noteContentHistoryService.ListHistories(noteId, c.getUserId())
|
|
||||||
if len(histories) > 0 {
|
|
||||||
re.Ok = true
|
|
||||||
re.Item = histories
|
|
||||||
}
|
|
||||||
return c.RenderJson(re)
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
@@ -1,106 +0,0 @@
|
|||||||
package api
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/leanote/leanote/app/info"
|
|
||||||
"github.com/revel/revel"
|
|
||||||
"gopkg.in/mgo.v2/bson"
|
|
||||||
. "github.com/leanote/leanote/app/lea"
|
|
||||||
// "io/ioutil"
|
|
||||||
)
|
|
||||||
|
|
||||||
// 笔记本API
|
|
||||||
|
|
||||||
type ApiNotebook struct {
|
|
||||||
ApiBaseContrller
|
|
||||||
}
|
|
||||||
|
|
||||||
// 从Notebook -> ApiNotebook
|
|
||||||
func (c ApiNotebook) fixNotebooks(notebooks []info.Notebook) []info.ApiNotebook {
|
|
||||||
if notebooks == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
apiNotebooks := make([]info.ApiNotebook, len(notebooks))
|
|
||||||
for i, notebook := range notebooks {
|
|
||||||
apiNotebooks[i] = c.fixNotebook(¬ebook)
|
|
||||||
}
|
|
||||||
return apiNotebooks
|
|
||||||
}
|
|
||||||
func (c ApiNotebook) fixNotebook(notebook *info.Notebook) info.ApiNotebook {
|
|
||||||
if notebook == nil {
|
|
||||||
return info.ApiNotebook{}
|
|
||||||
}
|
|
||||||
return info.ApiNotebook{
|
|
||||||
NotebookId : notebook.NotebookId,
|
|
||||||
UserId : notebook.UserId,
|
|
||||||
ParentNotebookId : notebook.ParentNotebookId,
|
|
||||||
Seq : notebook.Seq,
|
|
||||||
Title : notebook.Title,
|
|
||||||
UrlTitle : notebook.UrlTitle,
|
|
||||||
IsBlog : notebook.IsBlog,
|
|
||||||
CreatedTime : notebook.CreatedTime,
|
|
||||||
UpdatedTime : notebook.UpdatedTime,
|
|
||||||
Usn: notebook.Usn,
|
|
||||||
IsDeleted: notebook.IsDeleted,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 获取同步的笔记本
|
|
||||||
// [OK]
|
|
||||||
// > afterUsn的笔记
|
|
||||||
// 返回 {ChunkHighUsn: 本下最大的usn, 借此可以知道是否还有, Notebooks: []}
|
|
||||||
func (c ApiNotebook) GetSyncNotebooks(afterUsn, maxEntry int) revel.Result {
|
|
||||||
if maxEntry == 0 {
|
|
||||||
maxEntry = 100
|
|
||||||
}
|
|
||||||
notebooks := notebookService.GeSyncNotebooks(c.getUserId(), afterUsn, maxEntry)
|
|
||||||
return c.RenderJson(c.fixNotebooks(notebooks))
|
|
||||||
}
|
|
||||||
|
|
||||||
// 得到用户的所有笔记本
|
|
||||||
// [OK]
|
|
||||||
// info.SubNotebooks
|
|
||||||
func (c ApiNotebook) GetNotebooks() revel.Result {
|
|
||||||
notebooks := notebookService.GeSyncNotebooks(c.getUserId(), 0, 99999)
|
|
||||||
return c.RenderJson(c.fixNotebooks(notebooks))
|
|
||||||
}
|
|
||||||
|
|
||||||
// 添加notebook
|
|
||||||
// [OK]
|
|
||||||
func (c ApiNotebook) AddNotebook(title, parentNotebookId string, seq int) revel.Result {
|
|
||||||
notebook := info.Notebook{NotebookId: bson.NewObjectId(),
|
|
||||||
Title: title,
|
|
||||||
Seq: seq,
|
|
||||||
UserId: bson.ObjectIdHex(c.getUserId())}
|
|
||||||
if parentNotebookId != "" && bson.IsObjectIdHex(parentNotebookId) {
|
|
||||||
notebook.ParentNotebookId = bson.ObjectIdHex(parentNotebookId)
|
|
||||||
}
|
|
||||||
re := info.NewRe()
|
|
||||||
re.Ok, notebook = notebookService.AddNotebook(notebook)
|
|
||||||
if !re.Ok {
|
|
||||||
return c.RenderJson(re)
|
|
||||||
}
|
|
||||||
return c.RenderJson(c.fixNotebook(¬ebook))
|
|
||||||
}
|
|
||||||
|
|
||||||
// 修改笔记
|
|
||||||
// [OK]
|
|
||||||
func (c ApiNotebook) UpdateNotebook(notebookId, title, parentNotebookId string, seq, usn int) revel.Result {
|
|
||||||
re := info.NewApiRe()
|
|
||||||
|
|
||||||
ok, msg, notebook := notebookService.UpdateNotebookApi(c.getUserId(), notebookId, title, parentNotebookId, seq, usn)
|
|
||||||
if !ok {
|
|
||||||
re.Ok = false
|
|
||||||
re.Msg = msg
|
|
||||||
return c.RenderJson(re)
|
|
||||||
}
|
|
||||||
LogJ(notebook)
|
|
||||||
return c.RenderJson(c.fixNotebook(¬ebook))
|
|
||||||
}
|
|
||||||
|
|
||||||
// 删除笔记本
|
|
||||||
// [OK]
|
|
||||||
func (c ApiNotebook) DeleteNotebook(notebookId string, usn int) revel.Result {
|
|
||||||
re := info.NewApiRe()
|
|
||||||
re.Ok, re.Msg = notebookService.DeleteNotebookForce(c.getUserId(), notebookId, usn)
|
|
||||||
return c.RenderJson(re)
|
|
||||||
}
|
|
||||||
@@ -1,56 +0,0 @@
|
|||||||
package api
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/leanote/leanote/app/info"
|
|
||||||
"github.com/revel/revel"
|
|
||||||
// "gopkg.in/mgo.v2/bson"
|
|
||||||
// . "github.com/leanote/leanote/app/lea"
|
|
||||||
// "io/ioutil"
|
|
||||||
)
|
|
||||||
|
|
||||||
// 标签API
|
|
||||||
|
|
||||||
type ApiTag struct {
|
|
||||||
ApiBaseContrller
|
|
||||||
}
|
|
||||||
|
|
||||||
// 获取同步的标签
|
|
||||||
// [OK]
|
|
||||||
// > afterUsn的笔记
|
|
||||||
// 返回 {ChunkHighUsn: 本下最大的usn, 借此可以知道是否还有, Notebooks: []}
|
|
||||||
func (c ApiTag) GetSyncTags(afterUsn, maxEntry int) revel.Result {
|
|
||||||
if maxEntry == 0 {
|
|
||||||
maxEntry = 100
|
|
||||||
}
|
|
||||||
tags := tagService.GeSyncTags(c.getUserId(), afterUsn, maxEntry)
|
|
||||||
return c.RenderJson(tags)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 添加Tag
|
|
||||||
// [OK]
|
|
||||||
// 不会产生冲突, 即使里面有
|
|
||||||
// 返回
|
|
||||||
/*
|
|
||||||
{
|
|
||||||
"TagId": "551978dd99c37b9bc5000001",
|
|
||||||
"UserId": "54a1676399c37b1c77000002",
|
|
||||||
"Tag": "32",
|
|
||||||
"Usn": 25,
|
|
||||||
"Count": 1,
|
|
||||||
"CreatedTime": "2015-03-31T00:25:01.149312407+08:00",
|
|
||||||
"UpdatedTime": "2015-03-31T00:25:01.149312407+08:00",
|
|
||||||
"IsDeleted": false
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
func (c ApiTag) AddTag(tag string) revel.Result {
|
|
||||||
ret := tagService.AddOrUpdateTag(c.getUserId(), tag)
|
|
||||||
return c.RenderJson(ret)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 删除标签
|
|
||||||
// [OK]
|
|
||||||
func (c ApiTag) DeleteTag(tag string, usn int) revel.Result {
|
|
||||||
re := info.NewReUpdate()
|
|
||||||
re.Ok, re.Msg, re.Usn = tagService.DeleteTagApi(c.getUserId(), tag, usn)
|
|
||||||
return c.RenderJson(re)
|
|
||||||
}
|
|
||||||
@@ -2,154 +2,27 @@ package api
|
|||||||
|
|
||||||
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/info"
|
|
||||||
. "github.com/leanote/leanote/app/lea"
|
. "github.com/leanote/leanote/app/lea"
|
||||||
"time"
|
// "github.com/leanote/leanote/app/info"
|
||||||
// "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"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ApiUser struct {
|
type ApiUser struct {
|
||||||
ApiBaseContrller
|
ApiBaseContrller
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取用户信息
|
// 修改用户名, 需要重置session
|
||||||
// [OK]
|
|
||||||
func (c ApiUser) Info() revel.Result {
|
func (c ApiUser) Info() revel.Result {
|
||||||
re := info.NewApiRe()
|
Log("APIUser");
|
||||||
|
return c.RenderTemplate("home/index.html");
|
||||||
userInfo := c.getUserInfo()
|
// return nil;
|
||||||
if userInfo.UserId == "" {
|
}
|
||||||
return c.RenderJson(re)
|
|
||||||
}
|
|
||||||
apiUser := info.ApiUser{
|
|
||||||
UserId: userInfo.UserId.Hex(),
|
|
||||||
Username: userInfo.Username,
|
|
||||||
Email: userInfo.Email,
|
|
||||||
Logo: userInfo.Logo,
|
|
||||||
Verified: userInfo.Verified,
|
|
||||||
}
|
|
||||||
return c.RenderJson(apiUser)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 修改用户名
|
|
||||||
// [OK]
|
|
||||||
func (c ApiUser) UpdateUsername(username string) revel.Result {
|
|
||||||
re := info.NewApiRe()
|
|
||||||
if c.GetUsername() == "demo" {
|
|
||||||
re.Msg = "cannotUpdateDemo"
|
|
||||||
return c.RenderJson(re)
|
|
||||||
}
|
|
||||||
|
|
||||||
if re.Ok, re.Msg = Vd("username", username); !re.Ok {
|
|
||||||
return c.RenderJson(re)
|
|
||||||
}
|
|
||||||
|
|
||||||
re.Ok, re.Msg = userService.UpdateUsername(c.getUserId(), username)
|
|
||||||
return c.RenderJson(re)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 修改密码
|
|
||||||
// [OK]
|
|
||||||
func (c ApiUser) UpdatePwd(oldPwd, pwd string) revel.Result {
|
|
||||||
re := info.NewApiRe()
|
|
||||||
if c.GetUsername() == "demo" {
|
|
||||||
re.Msg = "cannotUpdateDemo"
|
|
||||||
return c.RenderJson(re)
|
|
||||||
}
|
|
||||||
if re.Ok, re.Msg = Vd("password", oldPwd); !re.Ok {
|
|
||||||
return c.RenderJson(re)
|
|
||||||
}
|
|
||||||
if re.Ok, re.Msg = Vd("password", pwd); !re.Ok {
|
|
||||||
return c.RenderJson(re)
|
|
||||||
}
|
|
||||||
re.Ok, re.Msg = userService.UpdatePwd(c.getUserId(), oldPwd, pwd)
|
|
||||||
return c.RenderJson(re)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 获得同步状态
|
|
||||||
// [OK]
|
|
||||||
func (c ApiUser) GetSyncState() revel.Result {
|
|
||||||
ret := bson.M{"LastSyncUsn": userService.GetUsn(c.getUserId()), "LastSyncTime": time.Now().Unix()}
|
|
||||||
return c.RenderJson(ret)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// 头像设置
|
|
||||||
// 参数file=文件
|
|
||||||
// 成功返回{Logo: url} 头像新url
|
|
||||||
// [OK]
|
|
||||||
func (c ApiUser) UpdateLogo() revel.Result {
|
|
||||||
ok, msg, url := c.uploadImage()
|
|
||||||
|
|
||||||
if ok {
|
|
||||||
ok = userService.UpdateAvatar(c.getUserId(), url)
|
|
||||||
return c.RenderJson(map[string]string{"Logo": url})
|
|
||||||
} else {
|
|
||||||
re := info.NewApiRe()
|
|
||||||
re.Msg = msg
|
|
||||||
return c.RenderJson(re)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 上传图片
|
|
||||||
func (c ApiUser) uploadImage() (ok bool, msg, url string) {
|
|
||||||
var fileUrlPath = ""
|
|
||||||
ok = false
|
|
||||||
|
|
||||||
file, handel, err := c.Request.FormFile("file")
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
defer file.Close()
|
|
||||||
// 生成上传路径
|
|
||||||
fileUrlPath = "public/upload/" + c.getUserId() + "/images/logo"
|
|
||||||
|
|
||||||
dir := revel.BasePath + "/" + fileUrlPath
|
|
||||||
err = os.MkdirAll(dir, 0755)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// 生成新的文件名
|
|
||||||
filename := handel.Filename
|
|
||||||
|
|
||||||
var ext string
|
|
||||||
|
|
||||||
_, ext = SplitFilename(filename)
|
|
||||||
if ext != ".gif" && ext != ".jpg" && ext != ".png" && ext != ".bmp" && ext != ".jpeg" {
|
|
||||||
msg = "notImage"
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
filename = NewGuid() + ext
|
|
||||||
data, err := ioutil.ReadAll(file)
|
|
||||||
if err != nil {
|
|
||||||
LogJ(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// > 5M?
|
|
||||||
if len(data) > 5*1024*1024 {
|
|
||||||
msg = "fileIsTooLarge"
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
toPath := dir + "/" + filename
|
|
||||||
err = ioutil.WriteFile(toPath, data, 0777)
|
|
||||||
if err != nil {
|
|
||||||
LogJ(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
ok = true
|
|
||||||
url = configService.GetSiteUrl() + "/" + fileUrlPath + "/" + filename
|
|
||||||
return
|
|
||||||
}
|
|
||||||
+58
-63
@@ -1,9 +1,9 @@
|
|||||||
package api
|
package api
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"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/info"
|
||||||
|
// . "github.com/leanote/leanote/app/lea"
|
||||||
"github.com/revel/revel"
|
"github.com/revel/revel"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
@@ -19,9 +19,9 @@ var blogService *service.BlogService
|
|||||||
var tagService *service.TagService
|
var tagService *service.TagService
|
||||||
var pwdService *service.PwdService
|
var pwdService *service.PwdService
|
||||||
var tokenService *service.TokenService
|
var tokenService *service.TokenService
|
||||||
var suggestionService *service.SuggestionService
|
var suggestionService *service.SuggestionService
|
||||||
var albumService *service.AlbumService
|
var albumService *service.AlbumService
|
||||||
var noteImageService *service.NoteImageService
|
var noteImageService *service.NoteImageService
|
||||||
var fileService *service.FileService
|
var fileService *service.FileService
|
||||||
var attachService *service.AttachService
|
var attachService *service.AttachService
|
||||||
var configService *service.ConfigService
|
var configService *service.ConfigService
|
||||||
@@ -31,29 +31,41 @@ var sessionService *service.SessionService
|
|||||||
var pageSize = 1000
|
var pageSize = 1000
|
||||||
var defaultSortField = "UpdatedTime"
|
var defaultSortField = "UpdatedTime"
|
||||||
var leanoteUserId = "admin" // 不能更改
|
var leanoteUserId = "admin" // 不能更改
|
||||||
|
var siteUrl = "http://leanote.com"
|
||||||
// 状态
|
|
||||||
const (
|
|
||||||
S_DEFAULT = iota // 0
|
|
||||||
S_NOT_LOGIN // 1
|
|
||||||
S_WRONG_USERNAME_PASSWORD // 2
|
|
||||||
S_WRONG_CAPTCHA // 3
|
|
||||||
S_NEED_CAPTCHA // 4
|
|
||||||
S_NOT_OPEN_REGISTER // 4
|
|
||||||
)
|
|
||||||
|
|
||||||
// 拦截器
|
// 拦截器
|
||||||
// 不需要拦截的url
|
// 不需要拦截的url
|
||||||
var commonUrl = map[string]map[string]bool{"ApiAuth": map[string]bool{"Login": true,
|
// Index 除了Note之外都不需要
|
||||||
"Register": true,
|
var commonUrl = map[string]map[string]bool{"Index": map[string]bool{"Index": true,
|
||||||
},
|
"Login": true,
|
||||||
// 文件的操作也不用登录, userId会从session中获取
|
"DoLogin": true,
|
||||||
"ApiFile": map[string]bool{"GetImage": true,
|
"Logout": true,
|
||||||
"GetAttach": true,
|
"Register": true,
|
||||||
"GetAllAttachs": true,
|
"DoRegister": true,
|
||||||
|
"FindPasswword": true,
|
||||||
|
"DoFindPassword": true,
|
||||||
|
"FindPassword2": true,
|
||||||
|
"FindPasswordUpdate": true,
|
||||||
|
"Suggestion": true,
|
||||||
},
|
},
|
||||||
|
"Note": map[string]bool{"ToImage": true},
|
||||||
|
"Blog": map[string]bool{"Index": true,
|
||||||
|
"View": true,
|
||||||
|
"AboutMe": true,
|
||||||
|
"Cate": true,
|
||||||
|
"Search": true,
|
||||||
|
"GetLikeAndComments": true,
|
||||||
|
"IncReadNum": true,
|
||||||
|
"ListComments": true,
|
||||||
|
},
|
||||||
|
// 用户的激活与修改邮箱都不需要登录, 通过链接地址
|
||||||
|
"User": map[string]bool{"UpdateEmail": true,
|
||||||
|
"ActiveEmail":true,
|
||||||
|
},
|
||||||
|
"Oauth": map[string]bool{"GithubCallback": true},
|
||||||
|
"File": map[string]bool{"OutputImage": true, "OutputFile": 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 {
|
||||||
@@ -64,59 +76,32 @@ func needValidate(controller, method string) bool {
|
|||||||
return true
|
return true
|
||||||
} else {
|
} else {
|
||||||
// controller不在这里的, 肯定要验证
|
// controller不在这里的, 肯定要验证
|
||||||
return true
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 这里得到token, 若不是login, logout等公用操作, 必须验证是否已登录
|
|
||||||
func AuthInterceptor(c *revel.Controller) revel.Result {
|
func AuthInterceptor(c *revel.Controller) revel.Result {
|
||||||
// 得到token /api/user/info?userId=xxx&token=xxxxx
|
|
||||||
token := c.Params.Values.Get("token")
|
|
||||||
noToken := false
|
|
||||||
if token == "" {
|
|
||||||
// 若无, 则取sessionId
|
|
||||||
token = c.Session.Id()
|
|
||||||
noToken = true
|
|
||||||
}
|
|
||||||
c.Session["_token"] = token
|
|
||||||
|
|
||||||
// 全部变成首字大写
|
// 全部变成首字大写
|
||||||
var controller = strings.Title(c.Name)
|
var controller = strings.Title(c.Name)
|
||||||
var method = strings.Title(c.MethodName)
|
var method = strings.Title(c.MethodName)
|
||||||
|
|
||||||
// 验证是否已登录
|
|
||||||
// 通过sessionService判断该token下是否有userId, 并返回userId
|
|
||||||
userId := sessionService.GetUserId(token)
|
|
||||||
if noToken && userId == "" {
|
|
||||||
// 从session中获取, api/file/getImage, api/file/getAttach, api/file/getAllAttach
|
|
||||||
// 客户端
|
|
||||||
userId, _ = c.Session["UserId"];
|
|
||||||
}
|
|
||||||
c.Session["_userId"] = userId
|
|
||||||
|
|
||||||
// 是否需要验证?
|
// 是否需要验证?
|
||||||
if !needValidate(controller, method) {
|
if !needValidate(controller, method) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if userId != "" {
|
// 验证是否已登录
|
||||||
|
if userId, ok := c.Session["UserId"]; ok && userId != "" {
|
||||||
return nil // 已登录
|
return nil // 已登录
|
||||||
}
|
}
|
||||||
|
|
||||||
// 没有登录, 返回错误的信息, 需要登录
|
// 没有登录, 判断是否是ajax操作
|
||||||
re := info.NewApiRe()
|
if c.Request.Header.Get("X-Requested-With") == "XMLHttpRequest" {
|
||||||
re.Msg = "NOTLOGIN"
|
re := info.NewRe()
|
||||||
return c.RenderJson(re)
|
re.Msg = "NOTLOGIN"
|
||||||
}
|
return c.RenderJson(re)
|
||||||
|
}
|
||||||
func init() {
|
|
||||||
// interceptors
|
return c.Redirect("/login")
|
||||||
revel.InterceptFunc(AuthInterceptor, revel.BEFORE, &ApiAuth{})
|
|
||||||
revel.InterceptFunc(AuthInterceptor, revel.BEFORE, &ApiUser{})
|
|
||||||
revel.InterceptFunc(AuthInterceptor, revel.BEFORE, &ApiFile{})
|
|
||||||
revel.InterceptFunc(AuthInterceptor, revel.BEFORE, &ApiNote{})
|
|
||||||
revel.InterceptFunc(AuthInterceptor, revel.BEFORE, &ApiTag{})
|
|
||||||
revel.InterceptFunc(AuthInterceptor, revel.BEFORE, &ApiNotebook{})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 最外层init.go调用
|
// 最外层init.go调用
|
||||||
@@ -133,7 +118,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
|
||||||
@@ -142,3 +127,13 @@ func InitService() {
|
|||||||
emailService = service.EmailS
|
emailService = service.EmailS
|
||||||
sessionService = service.SessionS
|
sessionService = service.SessionS
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
// interceptors
|
||||||
|
revel.InterceptFunc(AuthInterceptor, revel.BEFORE, &ApiAuth{})
|
||||||
|
revel.InterceptFunc(AuthInterceptor, revel.BEFORE, &ApiUser{})
|
||||||
|
|
||||||
|
revel.OnAppStart(func() {
|
||||||
|
siteUrl, _ = revel.Config.String("site.url")
|
||||||
|
})
|
||||||
|
}
|
||||||
+38
-50
@@ -3,7 +3,6 @@ package controllers
|
|||||||
import (
|
import (
|
||||||
"github.com/leanote/leanote/app/service"
|
"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"
|
// . "github.com/leanote/leanote/app/lea"
|
||||||
"github.com/revel/revel"
|
"github.com/revel/revel"
|
||||||
"strings"
|
"strings"
|
||||||
@@ -20,57 +19,53 @@ var blogService *service.BlogService
|
|||||||
var tagService *service.TagService
|
var tagService *service.TagService
|
||||||
var pwdService *service.PwdService
|
var pwdService *service.PwdService
|
||||||
var tokenService *service.TokenService
|
var tokenService *service.TokenService
|
||||||
var suggestionService *service.SuggestionService
|
var suggestionService *service.SuggestionService
|
||||||
var albumService *service.AlbumService
|
var albumService *service.AlbumService
|
||||||
var noteImageService *service.NoteImageService
|
var noteImageService *service.NoteImageService
|
||||||
var fileService *service.FileService
|
var fileService *service.FileService
|
||||||
var attachService *service.AttachService
|
var attachService *service.AttachService
|
||||||
var configService *service.ConfigService
|
var configService *service.ConfigService
|
||||||
var emailService *service.EmailService
|
var emailService *service.EmailService
|
||||||
var sessionService *service.SessionService
|
var sessionService *service.SessionService
|
||||||
var themeService *service.ThemeService
|
|
||||||
|
|
||||||
var pageSize = 1000
|
var pageSize = 1000
|
||||||
var defaultSortField = "UpdatedTime"
|
var defaultSortField = "UpdatedTime"
|
||||||
|
var leanoteUserId = "admin" // 不能更改
|
||||||
|
var siteUrl = "http://leanote.com"
|
||||||
|
|
||||||
// 拦截器
|
// 拦截器
|
||||||
// 不需要拦截的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,
|
||||||
},
|
},
|
||||||
"Note": map[string]bool{"ToImage": true},
|
"Note": map[string]bool{"ToImage": true},
|
||||||
"Blog": map[string]bool{"Index": true,
|
"Blog": map[string]bool{"Index": true,
|
||||||
"View": true,
|
"View": true,
|
||||||
"AboutMe": true,
|
"AboutMe": true,
|
||||||
"Cate": true,
|
"Cate": true,
|
||||||
"ListCateLatest": true,
|
"Search": true,
|
||||||
"Search": true,
|
|
||||||
"GetLikeAndComments": true,
|
"GetLikeAndComments": true,
|
||||||
"IncReadNum": true,
|
"IncReadNum": true,
|
||||||
"ListComments": true,
|
"ListComments": true,
|
||||||
"Single": true,
|
},
|
||||||
"Archive": true,
|
|
||||||
"Tags": 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 {
|
||||||
@@ -81,31 +76,31 @@ 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
|
||||||
}
|
}
|
||||||
|
|
||||||
// 验证是否已登录
|
// 验证是否已登录
|
||||||
if userId, ok := c.Session["UserId"]; ok && userId != "" {
|
if userId, ok := c.Session["UserId"]; ok && userId != "" {
|
||||||
return nil // 已登录
|
return nil // 已登录
|
||||||
}
|
}
|
||||||
|
|
||||||
// 没有登录, 判断是否是ajax操作
|
// 没有登录, 判断是否是ajax操作
|
||||||
if c.Request.Header.Get("X-Requested-With") == "XMLHttpRequest" {
|
if c.Request.Header.Get("X-Requested-With") == "XMLHttpRequest" {
|
||||||
re := info.NewRe()
|
re := info.NewRe()
|
||||||
re.Msg = "NOTLOGIN"
|
re.Msg = "NOTLOGIN"
|
||||||
return c.RenderJson(re)
|
return c.RenderJson(re)
|
||||||
}
|
}
|
||||||
|
|
||||||
return c.Redirect("/login")
|
return c.Redirect("/login")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -123,7 +118,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
|
||||||
@@ -131,12 +126,6 @@ func InitService() {
|
|||||||
configService = service.ConfigS
|
configService = service.ConfigS
|
||||||
emailService = service.EmailS
|
emailService = service.EmailS
|
||||||
sessionService = service.SessionS
|
sessionService = service.SessionS
|
||||||
themeService = service.ThemeS
|
|
||||||
}
|
|
||||||
|
|
||||||
// 初始化博客模板
|
|
||||||
// 博客模板不由revel的
|
|
||||||
func initBlogTemplate() {
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
@@ -148,11 +137,10 @@ func init() {
|
|||||||
revel.InterceptFunc(AuthInterceptor, revel.BEFORE, &User{})
|
revel.InterceptFunc(AuthInterceptor, revel.BEFORE, &User{})
|
||||||
revel.InterceptFunc(AuthInterceptor, revel.BEFORE, &File{})
|
revel.InterceptFunc(AuthInterceptor, revel.BEFORE, &File{})
|
||||||
revel.InterceptFunc(AuthInterceptor, revel.BEFORE, &Attach{})
|
revel.InterceptFunc(AuthInterceptor, revel.BEFORE, &Attach{})
|
||||||
// revel.InterceptFunc(AuthInterceptor, revel.BEFORE, &Blog{})
|
revel.InterceptFunc(AuthInterceptor, revel.BEFORE, &Blog{})
|
||||||
revel.InterceptFunc(AuthInterceptor, revel.BEFORE, &NoteContentHistory{})
|
revel.InterceptFunc(AuthInterceptor, revel.BEFORE, &NoteContentHistory{})
|
||||||
|
|
||||||
revel.OnAppStart(func() {
|
revel.OnAppStart(func() {
|
||||||
// 博客初始化模板
|
siteUrl, _ = revel.Config.String("site.url")
|
||||||
blog.Init()
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -1,59 +0,0 @@
|
|||||||
package member
|
|
||||||
|
|
||||||
import (
|
|
||||||
// "github.com/revel/revel"
|
|
||||||
// "gopkg.in/mgo.v2/bson"
|
|
||||||
// "encoding/json"
|
|
||||||
. "github.com/leanote/leanote/app/lea"
|
|
||||||
"github.com/leanote/leanote/app/controllers"
|
|
||||||
// "io/ioutil"
|
|
||||||
// "fmt"
|
|
||||||
// "math"
|
|
||||||
// "strconv"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
// 公用Controller, 其它Controller继承它
|
|
||||||
type MemberBaseController struct {
|
|
||||||
controllers.BaseController // 不能用*BaseController
|
|
||||||
}
|
|
||||||
|
|
||||||
// 得到sorterField 和 isAsc
|
|
||||||
// okSorter = ['email', 'username']
|
|
||||||
func (c MemberBaseController) getSorter(sorterField string, isAsc bool, okSorter []string) (string, bool){
|
|
||||||
sorter := ""
|
|
||||||
c.Params.Bind(&sorter, "sorter")
|
|
||||||
if sorter == "" {
|
|
||||||
return sorterField, isAsc;
|
|
||||||
}
|
|
||||||
|
|
||||||
// sorter形式 email-up, email-down
|
|
||||||
s2 := strings.Split(sorter, "-")
|
|
||||||
if len(s2) != 2 {
|
|
||||||
return sorterField, isAsc;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 必须是可用的sorter
|
|
||||||
if okSorter != nil && len(okSorter) > 0 {
|
|
||||||
if !InArray(okSorter, s2[0]) {
|
|
||||||
return sorterField, isAsc;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sorterField = strings.Title(s2[0])
|
|
||||||
if s2[1] == "up" {
|
|
||||||
isAsc = true
|
|
||||||
} else {
|
|
||||||
isAsc = false
|
|
||||||
}
|
|
||||||
c.RenderArgs["sorter"] = sorter
|
|
||||||
return sorterField, isAsc;
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c MemberBaseController) updateConfig(keys []string) {
|
|
||||||
userId := c.GetUserId()
|
|
||||||
for _, key := range keys {
|
|
||||||
v := c.Params.Values.Get(key)
|
|
||||||
configService.UpdateGlobalStringConfig(userId, key, v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,526 +0,0 @@
|
|||||||
package member
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"github.com/leanote/leanote/app/info"
|
|
||||||
. "github.com/leanote/leanote/app/lea"
|
|
||||||
"github.com/revel/revel"
|
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
// "github.com/leanote/leanote/app/lea/blog"
|
|
||||||
)
|
|
||||||
|
|
||||||
// 博客管理
|
|
||||||
|
|
||||||
type MemberBlog struct {
|
|
||||||
MemberBaseController
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c MemberBlog) common() info.UserBlog {
|
|
||||||
userId := c.GetUserId()
|
|
||||||
userInfo := userService.GetUserInfo(userId)
|
|
||||||
c.RenderArgs["userInfo"] = userInfo
|
|
||||||
|
|
||||||
// 得到博客设置信息
|
|
||||||
c.RenderArgs["allowCustomDomain"] = configService.GetGlobalStringConfig("allowCustomDomain")
|
|
||||||
|
|
||||||
userBlog := blogService.GetUserBlog(userId)
|
|
||||||
c.RenderArgs["userBlog"] = userBlog
|
|
||||||
|
|
||||||
c.SetUserInfo()
|
|
||||||
c.SetLocale()
|
|
||||||
return userBlog
|
|
||||||
}
|
|
||||||
|
|
||||||
// 得到sorterField 和 isAsc
|
|
||||||
// okSorter = ['email', 'username']
|
|
||||||
func (c MemberBlog) getSorter(sorterField string, isAsc bool, okSorter []string) (string, bool) {
|
|
||||||
sorter := ""
|
|
||||||
c.Params.Bind(&sorter, "sorter")
|
|
||||||
if sorter == "" {
|
|
||||||
return sorterField, isAsc
|
|
||||||
}
|
|
||||||
|
|
||||||
// sorter形式 email-up, email-down
|
|
||||||
s2 := strings.Split(sorter, "-")
|
|
||||||
if len(s2) != 2 {
|
|
||||||
return sorterField, isAsc
|
|
||||||
}
|
|
||||||
|
|
||||||
// 必须是可用的sorter
|
|
||||||
if okSorter != nil && len(okSorter) > 0 {
|
|
||||||
if !InArray(okSorter, s2[0]) {
|
|
||||||
return sorterField, isAsc
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sorterField = strings.Title(s2[0])
|
|
||||||
if s2[1] == "up" {
|
|
||||||
isAsc = true
|
|
||||||
} else {
|
|
||||||
isAsc = false
|
|
||||||
}
|
|
||||||
c.RenderArgs["sorter"] = sorter
|
|
||||||
return sorterField, isAsc
|
|
||||||
}
|
|
||||||
|
|
||||||
// 博客列表
|
|
||||||
var userPageSize = 15
|
|
||||||
|
|
||||||
func (c MemberBlog) Index(sorter, keywords string) revel.Result {
|
|
||||||
userId := c.GetUserId()
|
|
||||||
userInfo := userService.GetUserInfo(userId)
|
|
||||||
c.RenderArgs["userInfo"] = userInfo
|
|
||||||
|
|
||||||
c.RenderArgs["title"] = "Posts"
|
|
||||||
pageNumber := c.GetPage()
|
|
||||||
sorterField, isAsc := c.getSorter("CreatedTime", false, []string{"title", "urlTitle", "updatedTime", "publicTime", "createdTime"})
|
|
||||||
pageInfo, blogs := blogService.ListAllBlogs(c.GetUserId(), "", keywords, false, pageNumber, userPageSize, sorterField, isAsc)
|
|
||||||
c.RenderArgs["pageInfo"] = pageInfo
|
|
||||||
c.RenderArgs["blogs"] = blogs
|
|
||||||
c.RenderArgs["keywords"] = keywords
|
|
||||||
|
|
||||||
userAndBlog := userService.GetUserAndBlog(c.GetUserId())
|
|
||||||
c.RenderArgs["userAndBlog"] = userAndBlog
|
|
||||||
|
|
||||||
return c.RenderTemplate("member/blog/list.html")
|
|
||||||
}
|
|
||||||
|
|
||||||
// 修改笔记的urlTitle
|
|
||||||
func (c MemberBlog) UpdateBlogUrlTitle(noteId, urlTitle string) revel.Result {
|
|
||||||
re := info.NewRe()
|
|
||||||
re.Ok, re.Item = blogService.UpateBlogUrlTitle(c.GetUserId(), noteId, urlTitle)
|
|
||||||
return c.RenderJson(re)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 修改笔记的urlTitle
|
|
||||||
func (c MemberBlog) UpdateBlogAbstract(noteId string) revel.Result {
|
|
||||||
c.RenderArgs["title"] = "Update Post Abstract"
|
|
||||||
note := noteService.GetNoteAndContent(noteId, c.GetUserId())
|
|
||||||
if !note.Note.IsBlog {
|
|
||||||
return c.E404()
|
|
||||||
}
|
|
||||||
c.RenderArgs["note"] = note
|
|
||||||
c.RenderArgs["noteId"] = noteId
|
|
||||||
return c.RenderTemplate("member/blog/update_abstract.html")
|
|
||||||
}
|
|
||||||
func (c MemberBlog) DoUpdateBlogAbstract(noteId, imgSrc, desc, abstract string) revel.Result {
|
|
||||||
|
|
||||||
re := info.NewRe()
|
|
||||||
re.Ok = blogService.UpateBlogAbstract(c.GetUserId(), noteId, imgSrc, desc, abstract)
|
|
||||||
return c.RenderJson(re)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 基本信息设置
|
|
||||||
func (c MemberBlog) Base() revel.Result {
|
|
||||||
c.common()
|
|
||||||
c.RenderArgs["title"] = "Blog Base Info"
|
|
||||||
return c.RenderTemplate("member/blog/base.html")
|
|
||||||
}
|
|
||||||
func (c MemberBlog) Comment() revel.Result {
|
|
||||||
c.common()
|
|
||||||
c.RenderArgs["title"] = "Comment"
|
|
||||||
return c.RenderTemplate("member/blog/comment.html")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c MemberBlog) Paging() revel.Result {
|
|
||||||
c.common()
|
|
||||||
c.RenderArgs["title"] = "Paging"
|
|
||||||
return c.RenderTemplate("member/blog/paging.html")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c MemberBlog) Cate() revel.Result {
|
|
||||||
userBlog := c.common()
|
|
||||||
c.RenderArgs["title"] = "Cate"
|
|
||||||
|
|
||||||
notebooks := blogService.ListBlogNotebooks(c.GetUserId())
|
|
||||||
notebooksMap := map[string]info.Notebook{}
|
|
||||||
for _, each := range notebooks {
|
|
||||||
notebooksMap[each.NotebookId.Hex()] = each
|
|
||||||
}
|
|
||||||
|
|
||||||
var i = 0
|
|
||||||
notebooks2 := make([]info.Notebook, len(notebooks))
|
|
||||||
|
|
||||||
// 先要保证已有的是正确的排序
|
|
||||||
cateIds := userBlog.CateIds
|
|
||||||
has := map[string]bool{} // cateIds中有的
|
|
||||||
if cateIds != nil && len(cateIds) > 0 {
|
|
||||||
for _, cateId := range cateIds {
|
|
||||||
if n, ok := notebooksMap[cateId]; ok {
|
|
||||||
notebooks2[i] = n
|
|
||||||
i++
|
|
||||||
has[cateId] = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// 之后
|
|
||||||
for _, each := range notebooks {
|
|
||||||
id := each.NotebookId.Hex()
|
|
||||||
if !has[id] {
|
|
||||||
notebooks2[i] = each
|
|
||||||
i++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
c.RenderArgs["notebooks"] = notebooks2
|
|
||||||
|
|
||||||
return c.RenderTemplate("member/blog/cate.html")
|
|
||||||
}
|
|
||||||
|
|
||||||
// 修改分类排序
|
|
||||||
func (c MemberBlog) UpateCateIds(cateIds []string) revel.Result {
|
|
||||||
re := info.NewRe()
|
|
||||||
re.Ok = blogService.UpateCateIds(c.GetUserId(), cateIds)
|
|
||||||
return c.RenderJson(re)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c MemberBlog) UpdateCateUrlTitle(cateId, urlTitle string) revel.Result {
|
|
||||||
re := info.NewRe()
|
|
||||||
re.Ok, re.Item = blogService.UpateCateUrlTitle(c.GetUserId(), cateId, urlTitle)
|
|
||||||
return c.RenderJson(re)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 保存之, 包含增加与保存
|
|
||||||
func (c MemberBlog) DoAddOrUpdateSingle(singleId, title, content string) revel.Result {
|
|
||||||
re := info.NewRe()
|
|
||||||
re.Ok = blogService.AddOrUpdateSingle(c.GetUserId(), singleId, title, content)
|
|
||||||
return c.RenderJson(re)
|
|
||||||
}
|
|
||||||
func (c MemberBlog) AddOrUpdateSingle(singleId string) revel.Result {
|
|
||||||
c.common()
|
|
||||||
c.RenderArgs["title"] = "Add Single"
|
|
||||||
c.RenderArgs["singleId"] = singleId
|
|
||||||
if singleId != "" {
|
|
||||||
c.RenderArgs["title"] = "Update Single"
|
|
||||||
c.RenderArgs["single"] = blogService.GetSingle(singleId)
|
|
||||||
}
|
|
||||||
return c.RenderTemplate("member/blog/add_single.html")
|
|
||||||
}
|
|
||||||
func (c MemberBlog) SortSingles(singleIds []string) revel.Result {
|
|
||||||
re := info.NewRe()
|
|
||||||
re.Ok = blogService.SortSingles(c.GetUserId(), singleIds)
|
|
||||||
return c.RenderJson(re)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c MemberBlog) DeleteSingle(singleId string) revel.Result {
|
|
||||||
re := info.NewRe()
|
|
||||||
re.Ok = blogService.DeleteSingle(c.GetUserId(), singleId)
|
|
||||||
return c.RenderJson(re)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 修改页面标题
|
|
||||||
func (c MemberBlog) UpdateSingleUrlTitle(singleId, urlTitle string) revel.Result {
|
|
||||||
re := info.NewRe()
|
|
||||||
re.Ok, re.Item = blogService.UpdateSingleUrlTitle(c.GetUserId(), singleId, urlTitle)
|
|
||||||
return c.RenderJson(re)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c MemberBlog) Single() revel.Result {
|
|
||||||
c.common()
|
|
||||||
c.RenderArgs["title"] = "Cate"
|
|
||||||
c.RenderArgs["singles"] = blogService.GetSingles(c.GetUserId())
|
|
||||||
|
|
||||||
return c.RenderTemplate("member/blog/single.html")
|
|
||||||
}
|
|
||||||
|
|
||||||
// 主题
|
|
||||||
func (c MemberBlog) Theme() revel.Result {
|
|
||||||
c.common()
|
|
||||||
activeTheme, otherThemes := themeService.GetUserThemes(c.GetUserId())
|
|
||||||
c.RenderArgs["activeTheme"] = activeTheme
|
|
||||||
c.RenderArgs["otherThemes"] = otherThemes
|
|
||||||
|
|
||||||
c.RenderArgs["optionThemes"] = themeService.GetDefaultThemes()
|
|
||||||
|
|
||||||
c.RenderArgs["title"] = "Theme"
|
|
||||||
return c.RenderTemplate("member/blog/theme.html")
|
|
||||||
}
|
|
||||||
|
|
||||||
// 编辑主题
|
|
||||||
var baseTpls = []string{"header.html", "footer.html", "index.html", "cate.html", "search.html", "post.html", "single.html", "tags.html", "tag_posts.html", "archive.html", "share_comment.html", "404.html", "theme.json", "style.css", "blog.js"}
|
|
||||||
|
|
||||||
func (c MemberBlog) UpdateTheme(themeId string, isNew int) revel.Result {
|
|
||||||
// 查看用户是否有该theme, 若没有则复制default之
|
|
||||||
// 得到主题的文件列表
|
|
||||||
userBlog := blogService.GetUserBlog(c.GetUserId())
|
|
||||||
if themeId == "" {
|
|
||||||
_, themeId = themeService.NewThemeForFirst(userBlog)
|
|
||||||
return c.Redirect("/member/blog/updateTheme?themeId=" + themeId)
|
|
||||||
}
|
|
||||||
|
|
||||||
c.common()
|
|
||||||
c.RenderArgs["title"] = "Upate Theme"
|
|
||||||
c.RenderArgs["isNew"] = isNew
|
|
||||||
|
|
||||||
// 先复制之
|
|
||||||
c.RenderArgs["themeId"] = themeId
|
|
||||||
|
|
||||||
// 得到脚本目录
|
|
||||||
userId := c.GetUserId()
|
|
||||||
|
|
||||||
theme := themeService.GetTheme(userId, themeId)
|
|
||||||
if theme.ThemeId == "" {
|
|
||||||
return c.E404()
|
|
||||||
}
|
|
||||||
c.RenderArgs["theme"] = theme
|
|
||||||
|
|
||||||
path := revel.BasePath + "/" + theme.Path
|
|
||||||
|
|
||||||
tpls := ListDir(path)
|
|
||||||
myTpls := make([]string, len(baseTpls))
|
|
||||||
tplMap := map[string]bool{}
|
|
||||||
for i, t := range baseTpls {
|
|
||||||
myTpls[i] = t
|
|
||||||
tplMap[t] = true
|
|
||||||
}
|
|
||||||
// 得到没有的tpls
|
|
||||||
for _, t := range tpls {
|
|
||||||
if t == "images" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if !tplMap[t] {
|
|
||||||
myTpls = append(myTpls, t)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
c.RenderArgs["myTpls"] = myTpls
|
|
||||||
|
|
||||||
return c.RenderTemplate("member/blog/update_theme.html")
|
|
||||||
}
|
|
||||||
|
|
||||||
// 得到文件内容
|
|
||||||
func (c MemberBlog) GetTplContent(themeId string, filename string) revel.Result {
|
|
||||||
re := info.NewRe()
|
|
||||||
re.Ok = true
|
|
||||||
re.Item = themeService.GetTplContent(c.GetUserId(), themeId, filename)
|
|
||||||
|
|
||||||
return c.RenderJson(re)
|
|
||||||
}
|
|
||||||
func (c MemberBlog) UpdateTplContent(themeId, filename, content string) revel.Result {
|
|
||||||
re := info.NewRe()
|
|
||||||
re.Ok, re.Msg = themeService.UpdateTplContent(c.GetUserId(), themeId, filename, content)
|
|
||||||
return c.RenderRe(re)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c MemberBlog) DeleteTpl(themeId, filename string) revel.Result {
|
|
||||||
re := info.NewRe()
|
|
||||||
re.Ok = themeService.DeleteTpl(c.GetUserId(), themeId, filename)
|
|
||||||
return c.RenderJson(re)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c MemberBlog) ListThemeImages(themeId string) revel.Result {
|
|
||||||
re := info.NewRe()
|
|
||||||
userId := c.GetUserId()
|
|
||||||
path := themeService.GetThemeAbsolutePath(userId, themeId) + "/images"
|
|
||||||
os.MkdirAll(path, 0755)
|
|
||||||
images := ListDir(path)
|
|
||||||
re.List = images
|
|
||||||
re.Ok = true
|
|
||||||
return c.RenderJson(re)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c MemberBlog) DeleteThemeImage(themeId, filename string) revel.Result {
|
|
||||||
re := info.NewRe()
|
|
||||||
path := themeService.GetThemeAbsolutePath(c.GetUserId(), themeId) + "/images/" + filename
|
|
||||||
re.Ok = DeleteFile(path)
|
|
||||||
return c.RenderJson(re)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 上传主题图片
|
|
||||||
func (c MemberBlog) UploadThemeImage(themeId string) revel.Result {
|
|
||||||
re := c.uploadImage(themeId)
|
|
||||||
c.RenderArgs["fileUrlPath"] = re.Id
|
|
||||||
c.RenderArgs["resultCode"] = re.Code
|
|
||||||
c.RenderArgs["resultMsg"] = re.Msg
|
|
||||||
return c.RenderTemplate("file/blog_logo.html")
|
|
||||||
}
|
|
||||||
func (c MemberBlog) uploadImage(themeId string) (re info.Re) {
|
|
||||||
var fileId = ""
|
|
||||||
var resultCode = 0 // 1表示正常
|
|
||||||
var resultMsg = "内部错误" // 错误信息
|
|
||||||
var Ok = false
|
|
||||||
|
|
||||||
defer func() {
|
|
||||||
re.Id = fileId // 只是id, 没有其它信息
|
|
||||||
re.Code = resultCode
|
|
||||||
re.Msg = resultMsg
|
|
||||||
re.Ok = Ok
|
|
||||||
}()
|
|
||||||
|
|
||||||
file, handel, err := c.Request.FormFile("file")
|
|
||||||
if err != nil {
|
|
||||||
return re
|
|
||||||
}
|
|
||||||
defer file.Close()
|
|
||||||
// 生成上传路径
|
|
||||||
dir := themeService.GetThemeAbsolutePath(c.GetUserId(), themeId) + "/images"
|
|
||||||
err = os.MkdirAll(dir, 0755)
|
|
||||||
if err != nil {
|
|
||||||
return re
|
|
||||||
}
|
|
||||||
// 生成新的文件名
|
|
||||||
filename := handel.Filename
|
|
||||||
|
|
||||||
var ext string
|
|
||||||
|
|
||||||
_, ext = SplitFilename(filename)
|
|
||||||
if ext != ".gif" && ext != ".jpg" && ext != ".png" && ext != ".bmp" && ext != ".jpeg" {
|
|
||||||
resultMsg = "不是图片"
|
|
||||||
return re
|
|
||||||
}
|
|
||||||
|
|
||||||
filename = filename
|
|
||||||
data, err := ioutil.ReadAll(file)
|
|
||||||
if err != nil {
|
|
||||||
LogJ(err)
|
|
||||||
return re
|
|
||||||
}
|
|
||||||
|
|
||||||
// > 2M?
|
|
||||||
if len(data) > 5*1024*1024 {
|
|
||||||
resultCode = 0
|
|
||||||
resultMsg = "图片大于2M"
|
|
||||||
return re
|
|
||||||
}
|
|
||||||
|
|
||||||
toPath := dir + "/" + filename
|
|
||||||
err = ioutil.WriteFile(toPath, data, 0777)
|
|
||||||
if err != nil {
|
|
||||||
LogJ(err)
|
|
||||||
return re
|
|
||||||
}
|
|
||||||
TransToGif(toPath, 0, true)
|
|
||||||
resultCode = 1
|
|
||||||
resultMsg = "上传成功!"
|
|
||||||
|
|
||||||
return re
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// 使用主题
|
|
||||||
func (c MemberBlog) ActiveTheme(themeId string) revel.Result {
|
|
||||||
re := info.NewRe()
|
|
||||||
re.Ok = themeService.ActiveTheme(c.GetUserId(), themeId)
|
|
||||||
return c.RenderJson(re)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 删除主题
|
|
||||||
func (c MemberBlog) DeleteTheme(themeId string) revel.Result {
|
|
||||||
re := info.NewRe()
|
|
||||||
re.Ok = themeService.DeleteTheme(c.GetUserId(), themeId)
|
|
||||||
return c.RenderJson(re)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 管理员公开主题
|
|
||||||
func (c MemberBlog) PublicTheme(themeId string) revel.Result {
|
|
||||||
re := info.NewRe()
|
|
||||||
re.Ok = themeService.PublicTheme(c.GetUserId(), themeId)
|
|
||||||
return c.RenderJson(re)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 导出
|
|
||||||
func (c MemberBlog) ExportTheme(themeId string) revel.Result {
|
|
||||||
re := info.NewRe()
|
|
||||||
var path string
|
|
||||||
re.Ok, path = themeService.ExportTheme(c.GetUserId(), themeId)
|
|
||||||
if !re.Ok {
|
|
||||||
return c.RenderText("error...")
|
|
||||||
}
|
|
||||||
fw, err := os.Open(path)
|
|
||||||
if err != nil {
|
|
||||||
return c.RenderText("error")
|
|
||||||
}
|
|
||||||
return c.RenderBinary(fw, GetFilename(path), revel.Attachment, time.Now()) // revel.Attachment
|
|
||||||
}
|
|
||||||
|
|
||||||
// 导入主题
|
|
||||||
func (c MemberBlog) ImportTheme() revel.Result {
|
|
||||||
re := info.NewRe()
|
|
||||||
|
|
||||||
file, handel, err := c.Request.FormFile("file")
|
|
||||||
if err != nil {
|
|
||||||
re.Msg = fmt.Sprintf("%v", err)
|
|
||||||
return c.RenderJson(re)
|
|
||||||
|
|
||||||
}
|
|
||||||
defer file.Close()
|
|
||||||
// 生成上传路径
|
|
||||||
userId := c.GetUserId()
|
|
||||||
dir := revel.BasePath + "/public/upload/" + userId + "/tmp"
|
|
||||||
err = os.MkdirAll(dir, 0755)
|
|
||||||
if err != nil {
|
|
||||||
re.Msg = fmt.Sprintf("%v", err)
|
|
||||||
return c.RenderJson(re)
|
|
||||||
}
|
|
||||||
// 生成新的文件名
|
|
||||||
filename := handel.Filename
|
|
||||||
|
|
||||||
var ext string
|
|
||||||
_, ext = SplitFilename(filename)
|
|
||||||
if ext != ".zip" {
|
|
||||||
re.Msg = "Please upload zip file"
|
|
||||||
return c.RenderJson(re)
|
|
||||||
}
|
|
||||||
|
|
||||||
filename = filename
|
|
||||||
data, err := ioutil.ReadAll(file)
|
|
||||||
if err != nil {
|
|
||||||
return c.RenderJson(re)
|
|
||||||
}
|
|
||||||
|
|
||||||
// > 10M?
|
|
||||||
if len(data) > 10*1024*1024 {
|
|
||||||
re.Msg = "File is big than 10M"
|
|
||||||
return c.RenderJson(re)
|
|
||||||
}
|
|
||||||
|
|
||||||
toPath := dir + "/" + filename
|
|
||||||
err = ioutil.WriteFile(toPath, data, 0777)
|
|
||||||
if err != nil {
|
|
||||||
re.Msg = fmt.Sprintf("%v", err)
|
|
||||||
return c.RenderJson(re)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 上传好后, 增加之
|
|
||||||
re.Ok, re.Msg = themeService.ImportTheme(c.GetUserId(), toPath)
|
|
||||||
return c.RenderRe(re)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 安装
|
|
||||||
func (c MemberBlog) InstallTheme(themeId string) revel.Result {
|
|
||||||
re := info.NewRe()
|
|
||||||
re.Ok = themeService.InstallTheme(c.GetUserId(), themeId)
|
|
||||||
return c.RenderJson(re)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 新建主题
|
|
||||||
func (c MemberBlog) NewTheme() revel.Result {
|
|
||||||
_, themeId := themeService.NewTheme(c.GetUserId())
|
|
||||||
return c.Redirect("/member/blog/updateTheme?isNew=1&themeId=" + themeId)
|
|
||||||
}
|
|
||||||
|
|
||||||
//-----------
|
|
||||||
//
|
|
||||||
func (c MemberBlog) SetUserBlogBase(userBlog info.UserBlogBase) revel.Result {
|
|
||||||
re := info.NewRe()
|
|
||||||
re.Ok = blogService.UpdateUserBlogBase(c.GetUserId(), userBlog)
|
|
||||||
return c.RenderJson(re)
|
|
||||||
}
|
|
||||||
func (c MemberBlog) SetUserBlogComment(userBlog info.UserBlogComment) revel.Result {
|
|
||||||
re := info.NewRe()
|
|
||||||
re.Ok = blogService.UpdateUserBlogComment(c.GetUserId(), userBlog)
|
|
||||||
return c.RenderJson(re)
|
|
||||||
}
|
|
||||||
func (c MemberBlog) SetUserBlogStyle(userBlog info.UserBlogStyle) revel.Result {
|
|
||||||
re := info.NewRe()
|
|
||||||
re.Ok = blogService.UpdateUserBlogStyle(c.GetUserId(), userBlog)
|
|
||||||
return c.RenderJson(re)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c MemberBlog) SetUserBlogPaging(perPageSize int, sortField string, isAsc bool) revel.Result {
|
|
||||||
re := info.NewRe()
|
|
||||||
re.Ok, re.Msg = blogService.UpdateUserBlogPaging(c.GetUserId(), perPageSize, sortField, isAsc)
|
|
||||||
return c.RenderRe(re)
|
|
||||||
}
|
|
||||||
@@ -1,58 +0,0 @@
|
|||||||
package member
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/revel/revel"
|
|
||||||
"github.com/leanote/leanote/app/info"
|
|
||||||
)
|
|
||||||
|
|
||||||
// 分组管理
|
|
||||||
type MemberGroup struct {
|
|
||||||
MemberBaseController
|
|
||||||
}
|
|
||||||
|
|
||||||
// 首页, 显示所有分组和用户
|
|
||||||
func (c MemberGroup) Index() revel.Result {
|
|
||||||
c.SetUserInfo()
|
|
||||||
c.SetLocale()
|
|
||||||
c.RenderArgs["title"] = "My Group"
|
|
||||||
c.RenderArgs["groups"] = groupService.GetGroupsAndUsers(c.GetUserId())
|
|
||||||
return c.RenderTemplate("member/group/index.html");
|
|
||||||
}
|
|
||||||
|
|
||||||
// 添加分组
|
|
||||||
func (c MemberGroup) AddGroup(title string) revel.Result {
|
|
||||||
re := info.NewRe()
|
|
||||||
re.Ok, re.Item = groupService.AddGroup(c.GetUserId(), title)
|
|
||||||
return c.RenderJson(re)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c MemberGroup) UpdateGroupTitle(groupId, title string) revel.Result {
|
|
||||||
re := info.NewRe()
|
|
||||||
re.Ok = groupService.UpdateGroupTitle(c.GetUserId(), groupId, title)
|
|
||||||
return c.RenderJson(re)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c MemberGroup) DeleteGroup(groupId string) revel.Result {
|
|
||||||
re := info.NewRe()
|
|
||||||
re.Ok, re.Msg = groupService.DeleteGroup(c.GetUserId(), groupId)
|
|
||||||
return c.RenderRe(re)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 添加用户
|
|
||||||
func (c MemberGroup) AddUser(groupId, email string) revel.Result {
|
|
||||||
re := info.NewRe()
|
|
||||||
userInfo := userService.GetUserInfoByAny(email)
|
|
||||||
if userInfo.UserId == "" {
|
|
||||||
re.Msg = "userNotExists"
|
|
||||||
} else {
|
|
||||||
re.Ok, re.Msg = groupService.AddUser(c.GetUserId(), groupId, userInfo.UserId.Hex())
|
|
||||||
re.Item = userInfo
|
|
||||||
}
|
|
||||||
return c.RenderRe(re)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c MemberGroup) DeleteUser(groupId, userId string) revel.Result {
|
|
||||||
re := info.NewRe()
|
|
||||||
re.Ok, re.Msg = groupService.DeleteUser(c.GetUserId(), groupId, userId)
|
|
||||||
return c.RenderRe(re)
|
|
||||||
}
|
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
package member
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/revel/revel"
|
|
||||||
)
|
|
||||||
|
|
||||||
// admin 首页
|
|
||||||
|
|
||||||
type MemberIndex struct {
|
|
||||||
MemberBaseController
|
|
||||||
}
|
|
||||||
|
|
||||||
// admin 主页
|
|
||||||
func (c MemberIndex) Index() revel.Result {
|
|
||||||
c.SetUserInfo()
|
|
||||||
c.RenderArgs["title"] = "Leanote Member Center"
|
|
||||||
|
|
||||||
c.RenderArgs["countNote"] = noteService.CountNote(c.GetUserId())
|
|
||||||
c.RenderArgs["countBlog"] = noteService.CountBlog(c.GetUserId())
|
|
||||||
|
|
||||||
c.SetLocale()
|
|
||||||
|
|
||||||
return c.RenderTemplate("member/index.html");
|
|
||||||
}
|
|
||||||
|
|
||||||
// 模板
|
|
||||||
func (c MemberIndex) T(t string) revel.Result {
|
|
||||||
c.RenderArgs["str"] = configService.GlobalStringConfigs
|
|
||||||
c.RenderArgs["arr"] = configService.GlobalArrayConfigs
|
|
||||||
c.RenderArgs["map"] = configService.GlobalMapConfigs
|
|
||||||
c.RenderArgs["arrMap"] = configService.GlobalArrMapConfigs
|
|
||||||
return c.RenderTemplate("admin/" + t + ".html")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c MemberIndex) GetView(view string) revel.Result {
|
|
||||||
return c.RenderTemplate("admin/" + view);
|
|
||||||
}
|
|
||||||
@@ -1,46 +0,0 @@
|
|||||||
package member
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/revel/revel"
|
|
||||||
)
|
|
||||||
|
|
||||||
// 帐户信息
|
|
||||||
|
|
||||||
type MemberUser struct {
|
|
||||||
MemberBaseController
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c MemberUser) Username() revel.Result {
|
|
||||||
c.SetUserInfo()
|
|
||||||
c.SetLocale()
|
|
||||||
c.RenderArgs["title"] = "Username"
|
|
||||||
return c.RenderTemplate("member/user/username.html");
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c MemberUser) Email() revel.Result {
|
|
||||||
c.SetUserInfo()
|
|
||||||
c.SetLocale()
|
|
||||||
c.RenderArgs["title"] = "Email"
|
|
||||||
return c.RenderTemplate("member/user/email.html");
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c MemberUser) Password() revel.Result {
|
|
||||||
c.SetUserInfo()
|
|
||||||
c.SetLocale()
|
|
||||||
c.RenderArgs["title"] = "Password"
|
|
||||||
return c.RenderTemplate("member/user/password.html");
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c MemberUser) Avatar() revel.Result {
|
|
||||||
c.SetUserInfo()
|
|
||||||
c.SetLocale()
|
|
||||||
c.RenderArgs["title"] = "Avatar"
|
|
||||||
c.RenderArgs["globalConfigs"] = configService.GetGlobalConfigForUser()
|
|
||||||
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");
|
|
||||||
}
|
|
||||||
@@ -1,134 +0,0 @@
|
|||||||
package member
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/leanote/leanote/app/service"
|
|
||||||
"github.com/leanote/leanote/app/info"
|
|
||||||
// . "github.com/leanote/leanote/app/lea"
|
|
||||||
"github.com/revel/revel"
|
|
||||||
// "strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
var userService *service.UserService
|
|
||||||
var groupService *service.GroupService
|
|
||||||
var noteService *service.NoteService
|
|
||||||
var trashService *service.TrashService
|
|
||||||
var notebookService *service.NotebookService
|
|
||||||
var noteContentHistoryService *service.NoteContentHistoryService
|
|
||||||
var authService *service.AuthService
|
|
||||||
var shareService *service.ShareService
|
|
||||||
var blogService *service.BlogService
|
|
||||||
var tagService *service.TagService
|
|
||||||
var pwdService *service.PwdService
|
|
||||||
var tokenService *service.TokenService
|
|
||||||
var suggestionService *service.SuggestionService
|
|
||||||
var albumService *service.AlbumService
|
|
||||||
var noteImageService *service.NoteImageService
|
|
||||||
var fileService *service.FileService
|
|
||||||
var attachService *service.AttachService
|
|
||||||
var configService *service.ConfigService
|
|
||||||
var emailService *service.EmailService
|
|
||||||
var upgradeService *service.UpgradeService
|
|
||||||
var themeService *service.ThemeService
|
|
||||||
|
|
||||||
// 拦截器
|
|
||||||
// 不需要拦截的url
|
|
||||||
// Index 除了Note之外都不需要
|
|
||||||
var commonUrl = map[string]map[string]bool{"Index": map[string]bool{"Index": true,
|
|
||||||
"Login": true,
|
|
||||||
"DoLogin": true,
|
|
||||||
"Logout": true,
|
|
||||||
"Register": true,
|
|
||||||
"DoRegister": true,
|
|
||||||
"FindPasswword": true,
|
|
||||||
"DoFindPassword": true,
|
|
||||||
"FindPassword2": true,
|
|
||||||
"FindPasswordUpdate": true,
|
|
||||||
"Suggestion": true,
|
|
||||||
},
|
|
||||||
"Blog": map[string]bool{"Index": true,
|
|
||||||
"View": true,
|
|
||||||
"AboutMe": true,
|
|
||||||
"SearchBlog": true,
|
|
||||||
},
|
|
||||||
// 用户的激活与修改邮箱都不需要登录, 通过链接地址
|
|
||||||
"User": map[string]bool{"UpdateEmail": true,
|
|
||||||
"ActiveEmail":true,
|
|
||||||
},
|
|
||||||
"Oauth": map[string]bool{"GithubCallback": true},
|
|
||||||
"File": map[string]bool{"OutputImage": true, "OutputFile": true},
|
|
||||||
"Attach": map[string]bool{"Download": true, "DownloadAll": true},
|
|
||||||
}
|
|
||||||
func needValidate(controller, method string) bool {
|
|
||||||
// 在里面
|
|
||||||
if v, ok := commonUrl[controller]; ok {
|
|
||||||
// 在commonUrl里
|
|
||||||
if _, ok2 := v[method]; ok2 {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
} else {
|
|
||||||
// controller不在这里的, 肯定要验证
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
func AuthInterceptor(c *revel.Controller) revel.Result {
|
|
||||||
// 全部变成首字大写
|
|
||||||
/*
|
|
||||||
var controller = strings.Title(c.Name)
|
|
||||||
var method = strings.Title(c.MethodName)
|
|
||||||
// 是否需要验证?
|
|
||||||
if !needValidate(controller, method) {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
// 验证是否已登录
|
|
||||||
// 必须是管理员
|
|
||||||
if _, ok := c.Session["Username"]; ok {
|
|
||||||
return nil // 已登录
|
|
||||||
}
|
|
||||||
|
|
||||||
// 没有登录, 判断是否是ajax操作
|
|
||||||
if c.Request.Header.Get("X-Requested-With") == "XMLHttpRequest" {
|
|
||||||
re := info.NewRe()
|
|
||||||
re.Msg = "NOTLOGIN"
|
|
||||||
return c.RenderJson(re)
|
|
||||||
}
|
|
||||||
|
|
||||||
return c.Redirect("/login")
|
|
||||||
}
|
|
||||||
|
|
||||||
// 最外层init.go调用
|
|
||||||
// 获取service, 单例
|
|
||||||
func InitService() {
|
|
||||||
notebookService = service.NotebookS
|
|
||||||
noteService = service.NoteS
|
|
||||||
noteContentHistoryService = service.NoteContentHistoryS
|
|
||||||
trashService = service.TrashS
|
|
||||||
shareService = service.ShareS
|
|
||||||
userService = service.UserS
|
|
||||||
groupService = service.GroupS
|
|
||||||
tagService = service.TagS
|
|
||||||
blogService = service.BlogS
|
|
||||||
tokenService = service.TokenS
|
|
||||||
noteImageService = service.NoteImageS
|
|
||||||
fileService = service.FileS
|
|
||||||
albumService= service.AlbumS
|
|
||||||
attachService = service.AttachS
|
|
||||||
pwdService = service.PwdS
|
|
||||||
suggestionService = service.SuggestionS
|
|
||||||
authService = service.AuthS
|
|
||||||
configService = service.ConfigS
|
|
||||||
emailService = service.EmailS
|
|
||||||
upgradeService = service.UpgradeS
|
|
||||||
themeService = service.ThemeS
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
revel.InterceptFunc(AuthInterceptor, revel.BEFORE, &MemberIndex{})
|
|
||||||
revel.InterceptFunc(AuthInterceptor, revel.BEFORE, &MemberUser{})
|
|
||||||
revel.InterceptFunc(AuthInterceptor, revel.BEFORE, &MemberBlog{})
|
|
||||||
revel.InterceptFunc(AuthInterceptor, revel.BEFORE, &MemberGroup{})
|
|
||||||
revel.OnAppStart(func() {
|
|
||||||
})
|
|
||||||
}
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
包括基本信息设置
|
|
||||||
博客设置
|
|
||||||
+31
-69
@@ -2,11 +2,9 @@ package db
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/revel/revel"
|
|
||||||
. "github.com/leanote/leanote/app/lea"
|
|
||||||
"gopkg.in/mgo.v2"
|
"gopkg.in/mgo.v2"
|
||||||
"gopkg.in/mgo.v2/bson"
|
"gopkg.in/mgo.v2/bson"
|
||||||
"strings"
|
"github.com/revel/revel"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Init mgo and the common DAO
|
// Init mgo and the common DAO
|
||||||
@@ -25,12 +23,9 @@ var ShareNotebooks *mgo.Collection
|
|||||||
var HasShareNotes *mgo.Collection
|
var HasShareNotes *mgo.Collection
|
||||||
var Blogs *mgo.Collection
|
var Blogs *mgo.Collection
|
||||||
var Users *mgo.Collection
|
var Users *mgo.Collection
|
||||||
var Groups *mgo.Collection
|
|
||||||
var GroupUsers *mgo.Collection
|
|
||||||
|
|
||||||
var Tags *mgo.Collection
|
var Tags *mgo.Collection
|
||||||
var NoteTags *mgo.Collection
|
var TagNotes *mgo.Collection
|
||||||
var TagCounts *mgo.Collection
|
|
||||||
|
|
||||||
var UserBlogs *mgo.Collection
|
var UserBlogs *mgo.Collection
|
||||||
|
|
||||||
@@ -51,30 +46,17 @@ var EmailLogs *mgo.Collection
|
|||||||
var BlogLikes *mgo.Collection
|
var BlogLikes *mgo.Collection
|
||||||
var BlogComments *mgo.Collection
|
var BlogComments *mgo.Collection
|
||||||
var Reports *mgo.Collection
|
var Reports *mgo.Collection
|
||||||
var BlogSingles *mgo.Collection
|
|
||||||
var Themes *mgo.Collection
|
|
||||||
|
|
||||||
// session
|
// session
|
||||||
var Sessions *mgo.Collection
|
var Sessions *mgo.Collection
|
||||||
|
|
||||||
// 初始化时连接数据库
|
// 初始化时连接数据库
|
||||||
func Init(url, dbname string) {
|
func Init() {
|
||||||
ok := true
|
var url string
|
||||||
config := revel.Config
|
var ok bool
|
||||||
if url == "" {
|
config := revel.Config;
|
||||||
url, ok = config.String("db.url")
|
url, ok = config.String("db.url")
|
||||||
if !ok {
|
dbname, _ := config.String("db.dbname")
|
||||||
url, ok = config.String("db.urlEnv")
|
|
||||||
}
|
|
||||||
if ok {
|
|
||||||
// get dbname from url
|
|
||||||
urls := strings.Split(url, "/")
|
|
||||||
dbname = urls[len(urls)-1]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if dbname == "" {
|
|
||||||
dbname, _ = config.String("db.dbname")
|
|
||||||
}
|
|
||||||
if !ok {
|
if !ok {
|
||||||
host, _ := revel.Config.String("db.host")
|
host, _ := revel.Config.String("db.host")
|
||||||
port, _ := revel.Config.String("db.port")
|
port, _ := revel.Config.String("db.port")
|
||||||
@@ -84,10 +66,9 @@ func Init(url, dbname string) {
|
|||||||
if username == "" || password == "" {
|
if username == "" || password == "" {
|
||||||
usernameAndPassword = ""
|
usernameAndPassword = ""
|
||||||
}
|
}
|
||||||
url = "mongodb://" + usernameAndPassword + host + ":" + port + "/" + dbname
|
url = "mongodb://" + usernameAndPassword + host + ":" + port + "/" + dbname
|
||||||
}
|
}
|
||||||
Log(url)
|
|
||||||
|
|
||||||
// [mongodb://][user:pass@]host1[:port1][,host2[:port2],...][/database][?options]
|
// [mongodb://][user:pass@]host1[:port1][,host2[:port2],...][/database][?options]
|
||||||
// mongodb://myuser:mypass@localhost:40001,otherhost:40001/mydb
|
// mongodb://myuser:mypass@localhost:40001,otherhost:40001/mydb
|
||||||
var err error
|
var err error
|
||||||
@@ -101,61 +82,55 @@ func Init(url, dbname string) {
|
|||||||
|
|
||||||
// notebook
|
// notebook
|
||||||
Notebooks = Session.DB(dbname).C("notebooks")
|
Notebooks = Session.DB(dbname).C("notebooks")
|
||||||
|
|
||||||
// notes
|
// notes
|
||||||
Notes = Session.DB(dbname).C("notes")
|
Notes = Session.DB(dbname).C("notes")
|
||||||
|
|
||||||
// noteContents
|
// noteContents
|
||||||
NoteContents = Session.DB(dbname).C("note_contents")
|
NoteContents = Session.DB(dbname).C("note_contents")
|
||||||
NoteContentHistories = Session.DB(dbname).C("note_content_histories")
|
NoteContentHistories = Session.DB(dbname).C("note_content_histories")
|
||||||
|
|
||||||
// share
|
// share
|
||||||
ShareNotes = Session.DB(dbname).C("share_notes")
|
ShareNotes = Session.DB(dbname).C("share_notes")
|
||||||
ShareNotebooks = Session.DB(dbname).C("share_notebooks")
|
ShareNotebooks = Session.DB(dbname).C("share_notebooks")
|
||||||
HasShareNotes = Session.DB(dbname).C("has_share_notes")
|
HasShareNotes = Session.DB(dbname).C("has_share_notes")
|
||||||
|
|
||||||
// user
|
// user
|
||||||
Users = Session.DB(dbname).C("users")
|
Users = Session.DB(dbname).C("users")
|
||||||
// group
|
|
||||||
Groups = Session.DB(dbname).C("groups")
|
|
||||||
GroupUsers = Session.DB(dbname).C("group_users")
|
|
||||||
|
|
||||||
// blog
|
// blog
|
||||||
Blogs = Session.DB(dbname).C("blogs")
|
Blogs = Session.DB(dbname).C("blogs")
|
||||||
|
|
||||||
// tag
|
// tag
|
||||||
Tags = Session.DB(dbname).C("tags")
|
Tags = Session.DB(dbname).C("tags")
|
||||||
NoteTags = Session.DB(dbname).C("note_tags")
|
TagNotes = Session.DB(dbname).C("tag_notes")
|
||||||
TagCounts = Session.DB(dbname).C("tag_count")
|
|
||||||
|
|
||||||
// blog
|
// blog
|
||||||
UserBlogs = Session.DB(dbname).C("user_blogs")
|
UserBlogs = Session.DB(dbname).C("user_blogs")
|
||||||
BlogSingles = Session.DB(dbname).C("blog_singles")
|
|
||||||
Themes = Session.DB(dbname).C("themes")
|
|
||||||
|
|
||||||
// find password
|
// find password
|
||||||
Tokens = Session.DB(dbname).C("tokens")
|
Tokens = Session.DB(dbname).C("tokens")
|
||||||
|
|
||||||
// Suggestion
|
// Suggestion
|
||||||
Suggestions = Session.DB(dbname).C("suggestions")
|
Suggestions = Session.DB(dbname).C("suggestions")
|
||||||
|
|
||||||
// Album & file
|
// Album & file
|
||||||
Albums = Session.DB(dbname).C("albums")
|
Albums = Session.DB(dbname).C("albums")
|
||||||
Files = Session.DB(dbname).C("files")
|
Files = Session.DB(dbname).C("files")
|
||||||
Attachs = Session.DB(dbname).C("attachs")
|
Attachs = Session.DB(dbname).C("attachs")
|
||||||
|
|
||||||
NoteImages = Session.DB(dbname).C("note_images")
|
NoteImages = Session.DB(dbname).C("note_images")
|
||||||
|
|
||||||
Configs = Session.DB(dbname).C("configs")
|
Configs = Session.DB(dbname).C("configs")
|
||||||
EmailLogs = Session.DB(dbname).C("email_logs")
|
EmailLogs = Session.DB(dbname).C("email_logs")
|
||||||
|
|
||||||
// 社交
|
// 社交
|
||||||
BlogLikes = Session.DB(dbname).C("blog_likes")
|
BlogLikes = Session.DB(dbname).C("blog_likes")
|
||||||
BlogComments = Session.DB(dbname).C("blog_comments")
|
BlogComments = Session.DB(dbname).C("blog_comments")
|
||||||
|
|
||||||
// 举报
|
// 举报
|
||||||
Reports = Session.DB(dbname).C("reports")
|
Reports = Session.DB(dbname).C("reports")
|
||||||
|
|
||||||
// session
|
// session
|
||||||
Sessions = Session.DB(dbname).C("sessions")
|
Sessions = Session.DB(dbname).C("sessions")
|
||||||
}
|
}
|
||||||
@@ -199,29 +174,22 @@ func UpdateByIdAndUserId2(collection *mgo.Collection, id, userId bson.ObjectId,
|
|||||||
return Err(err)
|
return Err(err)
|
||||||
}
|
}
|
||||||
func UpdateByIdAndUserIdField(collection *mgo.Collection, id, userId, field string, value interface{}) bool {
|
func UpdateByIdAndUserIdField(collection *mgo.Collection, id, userId, field string, value interface{}) bool {
|
||||||
return UpdateByIdAndUserId(collection, id, userId, bson.M{"$set": bson.M{field: value}})
|
return UpdateByIdAndUserId(collection, id, userId, bson.M{"$set": bson.M{field:value}})
|
||||||
}
|
}
|
||||||
func UpdateByIdAndUserIdMap(collection *mgo.Collection, id, userId string, v bson.M) bool {
|
func UpdateByIdAndUserIdMap(collection *mgo.Collection, id, userId string, v bson.M) bool {
|
||||||
return UpdateByIdAndUserId(collection, id, userId, bson.M{"$set": v})
|
return UpdateByIdAndUserId(collection, id, userId, bson.M{"$set": v})
|
||||||
}
|
}
|
||||||
|
|
||||||
func UpdateByIdAndUserIdField2(collection *mgo.Collection, id, userId bson.ObjectId, field string, value interface{}) bool {
|
func UpdateByIdAndUserIdField2(collection *mgo.Collection, id, userId bson.ObjectId, field string, value interface{}) bool {
|
||||||
return UpdateByIdAndUserId2(collection, id, userId, bson.M{"$set": bson.M{field: value}})
|
return UpdateByIdAndUserId2(collection, id, userId, bson.M{"$set": bson.M{field:value}})
|
||||||
}
|
}
|
||||||
func UpdateByIdAndUserIdMap2(collection *mgo.Collection, id, userId bson.ObjectId, v bson.M) bool {
|
func UpdateByIdAndUserIdMap2(collection *mgo.Collection, id, userId bson.ObjectId, v bson.M) bool {
|
||||||
return UpdateByIdAndUserId2(collection, id, userId, bson.M{"$set": v})
|
return UpdateByIdAndUserId2(collection, id, userId, bson.M{"$set": v})
|
||||||
}
|
}
|
||||||
|
//
|
||||||
//
|
|
||||||
func UpdateByQField(collection *mgo.Collection, q interface{}, field string, value interface{}) bool {
|
func UpdateByQField(collection *mgo.Collection, q interface{}, field string, value interface{}) bool {
|
||||||
_, err := collection.UpdateAll(q, bson.M{"$set": bson.M{field: value}})
|
_, err := collection.UpdateAll(q, bson.M{"$set": bson.M{field: value}})
|
||||||
return Err(err)
|
return Err(err)
|
||||||
}
|
}
|
||||||
func UpdateByQI(collection *mgo.Collection, q interface{}, v interface{}) bool {
|
|
||||||
_, err := collection.UpdateAll(q, bson.M{"$set": v})
|
|
||||||
return Err(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 查询条件和值
|
// 查询条件和值
|
||||||
func UpdateByQMap(collection *mgo.Collection, q interface{}, v interface{}) bool {
|
func UpdateByQMap(collection *mgo.Collection, q interface{}, v interface{}) bool {
|
||||||
_, err := collection.UpdateAll(q, bson.M{"$set": v})
|
_, err := collection.UpdateAll(q, bson.M{"$set": v})
|
||||||
@@ -287,7 +255,6 @@ func GetByQWithFields(collection *mgo.Collection, q bson.M, fields []string, i i
|
|||||||
}
|
}
|
||||||
collection.Find(q).Select(selector).One(i)
|
collection.Find(q).Select(selector).One(i)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 查询某些字段, q是查询条件, fields是字段名列表
|
// 查询某些字段, q是查询条件, fields是字段名列表
|
||||||
func ListByQWithFields(collection *mgo.Collection, q bson.M, fields []string, i interface{}) {
|
func ListByQWithFields(collection *mgo.Collection, q bson.M, fields []string, i interface{}) {
|
||||||
selector := make(bson.M, len(fields))
|
selector := make(bson.M, len(fields))
|
||||||
@@ -303,11 +270,6 @@ func GetByIdAndUserId2(collection *mgo.Collection, id, userId bson.ObjectId, i i
|
|||||||
collection.Find(GetIdAndUserIdBsonQ(id, userId)).One(i)
|
collection.Find(GetIdAndUserIdBsonQ(id, userId)).One(i)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 按field去重
|
|
||||||
func Distinct(collection *mgo.Collection, q bson.M, field string, i interface{}) {
|
|
||||||
collection.Find(q).Distinct(field, i)
|
|
||||||
}
|
|
||||||
|
|
||||||
//----------------------
|
//----------------------
|
||||||
|
|
||||||
func Count(collection *mgo.Collection, q interface{}) int {
|
func Count(collection *mgo.Collection, q interface{}) int {
|
||||||
@@ -341,9 +303,9 @@ func Err(err error) bool {
|
|||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
// 删除时, 查找
|
// 删除时, 查找
|
||||||
if err.Error() == "not found" {
|
if err.Error() == "not found" {
|
||||||
return true
|
return true;
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
+2
-4
@@ -10,8 +10,8 @@ import (
|
|||||||
|
|
||||||
// convert revel msg to js msg
|
// convert revel msg to js msg
|
||||||
|
|
||||||
var msgBasePath = "/Users/life/Documents/Go/package2/src/github.com/leanote/leanote/messages/"
|
var msgBasePath = "/Users/life/Documents/Go/package1/src/github.com/leanote/leanote/messages/"
|
||||||
var targetBasePath = "/Users/life/Documents/Go/package2/src/github.com/leanote/leanote/public/js/i18n/"
|
var targetBasePath = "/Users/life/Documents/Go/package1/src/github.com/leanote/leanote/public/js/i18n/"
|
||||||
func parse(filename string) {
|
func parse(filename string) {
|
||||||
file, err := os.Open(msgBasePath + filename)
|
file, err := os.Open(msgBasePath + filename)
|
||||||
reader := bufio.NewReader(file)
|
reader := bufio.NewReader(file)
|
||||||
@@ -84,8 +84,6 @@ function getMsg(key, data) {
|
|||||||
func main() {
|
func main() {
|
||||||
parse("msg.en")
|
parse("msg.en")
|
||||||
parse("msg.zh")
|
parse("msg.zh")
|
||||||
parse("msg.fr")
|
|
||||||
parse("blog.zh")
|
parse("blog.zh")
|
||||||
parse("blog.en")
|
parse("blog.en")
|
||||||
parse("blog.fr")
|
|
||||||
}
|
}
|
||||||
-119
@@ -1,119 +0,0 @@
|
|||||||
package info
|
|
||||||
|
|
||||||
import (
|
|
||||||
"time"
|
|
||||||
"gopkg.in/mgo.v2/bson"
|
|
||||||
)
|
|
||||||
|
|
||||||
//---------
|
|
||||||
// 数据结构
|
|
||||||
//---------
|
|
||||||
type NoteFile struct {
|
|
||||||
FileId string // 服务器端Id
|
|
||||||
LocalFileId string // 客户端Id
|
|
||||||
Type string // images/png, doc, xls, 根据fileName确定
|
|
||||||
Title string
|
|
||||||
HasBody bool // 传过来的值是否要更新内容
|
|
||||||
IsAttach bool // 是否是附件, 不是附件就是图片
|
|
||||||
}
|
|
||||||
type ApiNote struct {
|
|
||||||
NoteId string
|
|
||||||
NotebookId string
|
|
||||||
UserId string
|
|
||||||
Title string
|
|
||||||
Desc string
|
|
||||||
// ImgSrc string
|
|
||||||
Tags []string
|
|
||||||
Abstract string
|
|
||||||
Content string
|
|
||||||
IsMarkdown bool
|
|
||||||
// FromUserId string // 为共享而新建
|
|
||||||
IsBlog bool // 是否是blog, 更新note不需要修改, 添加note时才有可能用到, 此时需要判断notebook是否设为Blog
|
|
||||||
IsTrash bool
|
|
||||||
IsDeleted bool
|
|
||||||
Usn int
|
|
||||||
Files []NoteFile
|
|
||||||
CreatedTime time.Time
|
|
||||||
UpdatedTime time.Time
|
|
||||||
PublicTime time.Time
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// 内容
|
|
||||||
type ApiNoteContent struct {
|
|
||||||
NoteId bson.ObjectId `bson:"_id,omitempty"`
|
|
||||||
UserId bson.ObjectId `bson:"UserId"`
|
|
||||||
|
|
||||||
Content string `Content`
|
|
||||||
|
|
||||||
// CreatedTime time.Time `CreatedTime`
|
|
||||||
// UpdatedTime time.Time `UpdatedTime`
|
|
||||||
}
|
|
||||||
|
|
||||||
// 转换
|
|
||||||
func NoteToApiNote(note Note, files []NoteFile) ApiNote {
|
|
||||||
apiNote := ApiNote{}
|
|
||||||
return apiNote
|
|
||||||
}
|
|
||||||
|
|
||||||
//----------
|
|
||||||
// 用户信息
|
|
||||||
//----------
|
|
||||||
|
|
||||||
type ApiUser struct {
|
|
||||||
UserId string
|
|
||||||
Username string
|
|
||||||
Email string
|
|
||||||
Verified bool
|
|
||||||
Logo string
|
|
||||||
}
|
|
||||||
|
|
||||||
//----------
|
|
||||||
// Notebook
|
|
||||||
//----------
|
|
||||||
type ApiNotebook struct {
|
|
||||||
NotebookId bson.ObjectId `bson:"_id,omitempty"` // 必须要设置bson:"_id" 不然mgo不会认为是主键
|
|
||||||
UserId bson.ObjectId `bson:"UserId"`
|
|
||||||
ParentNotebookId bson.ObjectId `bson:"ParentNotebookId,omitempty"` // 上级
|
|
||||||
Seq int `Seq` // 排序
|
|
||||||
Title string `Title` // 标题
|
|
||||||
UrlTitle string `UrlTitle` // Url标题 2014/11.11加
|
|
||||||
IsBlog bool `IsBlog,omitempty` // 是否是Blog 2013/12/29 新加
|
|
||||||
CreatedTime time.Time `CreatedTime,omitempty`
|
|
||||||
UpdatedTime time.Time `UpdatedTime,omitempty`
|
|
||||||
Usn int `Usn` // UpdateSequenceNum
|
|
||||||
IsDeleted bool `IsDeleted`
|
|
||||||
}
|
|
||||||
|
|
||||||
//---------
|
|
||||||
// api 返回
|
|
||||||
//---------
|
|
||||||
|
|
||||||
// 一般返回
|
|
||||||
type ApiRe struct {
|
|
||||||
Ok bool
|
|
||||||
Msg string
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewApiRe() ApiRe {
|
|
||||||
return ApiRe{Ok: false}
|
|
||||||
}
|
|
||||||
|
|
||||||
// auth
|
|
||||||
type AuthOk struct {
|
|
||||||
Ok bool
|
|
||||||
Token string
|
|
||||||
UserId bson.ObjectId
|
|
||||||
Email string
|
|
||||||
Username string
|
|
||||||
}
|
|
||||||
|
|
||||||
// 供notebook, note, tag更新的返回数据用
|
|
||||||
type ReUpdate struct {
|
|
||||||
Ok bool
|
|
||||||
Msg string
|
|
||||||
Usn int
|
|
||||||
}
|
|
||||||
func NewReUpdate() ReUpdate {
|
|
||||||
return ReUpdate{Ok: false}
|
|
||||||
}
|
|
||||||
@@ -1,57 +0,0 @@
|
|||||||
package info
|
|
||||||
|
|
||||||
import (
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
// 仅仅为了博客的主题
|
|
||||||
|
|
||||||
type BlogInfoCustom struct {
|
|
||||||
UserId string
|
|
||||||
Username string
|
|
||||||
UserLogo string
|
|
||||||
Title string
|
|
||||||
SubTitle string
|
|
||||||
Logo string
|
|
||||||
OpenComment bool
|
|
||||||
CommentType string
|
|
||||||
ThemeId string
|
|
||||||
SubDomain string
|
|
||||||
Domain string
|
|
||||||
}
|
|
||||||
|
|
||||||
type Post struct {
|
|
||||||
NoteId string
|
|
||||||
Title string
|
|
||||||
UrlTitle string
|
|
||||||
ImgSrc string
|
|
||||||
CreatedTime time.Time
|
|
||||||
UpdatedTime time.Time
|
|
||||||
PublicTime time.Time
|
|
||||||
Desc string
|
|
||||||
Abstract string
|
|
||||||
Content string
|
|
||||||
Tags []string
|
|
||||||
CommentNum int
|
|
||||||
ReadNum int
|
|
||||||
LikeNum int
|
|
||||||
IsMarkdown bool
|
|
||||||
}
|
|
||||||
// 归档
|
|
||||||
type ArchiveMonth struct {
|
|
||||||
Month int
|
|
||||||
Posts []*Post
|
|
||||||
}
|
|
||||||
type Archive struct {
|
|
||||||
Year int
|
|
||||||
MonthAchives []ArchiveMonth
|
|
||||||
Posts []*Post
|
|
||||||
}
|
|
||||||
|
|
||||||
type Cate struct {
|
|
||||||
CateId string
|
|
||||||
ParentCateId string
|
|
||||||
Title string
|
|
||||||
UrlTitle string
|
|
||||||
Children []*Cate
|
|
||||||
}
|
|
||||||
+9
-51
@@ -9,7 +9,6 @@ import (
|
|||||||
|
|
||||||
type BlogItem struct {
|
type BlogItem struct {
|
||||||
Note
|
Note
|
||||||
Abstract string
|
|
||||||
Content string // 可能是content的一部分, 截取. 点击more后就是整个信息了
|
Content string // 可能是content的一部分, 截取. 点击more后就是整个信息了
|
||||||
HasMore bool // 是否是否还有
|
HasMore bool // 是否是否还有
|
||||||
User User // 用户信息
|
User User // 用户信息
|
||||||
@@ -19,13 +18,13 @@ 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 {
|
||||||
CanComment bool `CanComment` // 是否可以评论
|
CanComment bool `CanComment` // 是否可以评论
|
||||||
CommentType string `CommentType` // default 或 disqus
|
CommentType string `CommentType` // default 或 disqus
|
||||||
DisqusId string `DisqusId`
|
DisqusId string `DisqusId`
|
||||||
}
|
}
|
||||||
|
|
||||||
type UserBlogStyle struct {
|
type UserBlogStyle struct {
|
||||||
@@ -39,48 +38,18 @@ type UserBlog 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` // 关于我
|
||||||
|
|
||||||
CanComment bool `CanComment` // 是否可以评论
|
|
||||||
|
|
||||||
|
CanComment bool `CanComment` // 是否可以评论
|
||||||
|
|
||||||
CommentType string `CommentType` // default 或 disqus
|
CommentType string `CommentType` // default 或 disqus
|
||||||
DisqusId string `DisqusId`
|
DisqusId string `DisqusId`
|
||||||
|
|
||||||
Style string `Style` // 风格
|
Style string `Style` // 风格
|
||||||
Css string `Css` // 自定义css
|
Css string `Css` // 自定义css
|
||||||
|
|
||||||
ThemeId bson.ObjectId `ThemeId,omitempty` // 主题Id
|
|
||||||
ThemePath string `bson:"ThemePath" json:"-"` // 不存值, 从Theme中获取, 相对路径 public/
|
|
||||||
|
|
||||||
CateIds []string `CateIds,omitempty` // 分类Id, 排序好的
|
|
||||||
Singles []map[string]string `Singles,omitempty` // 单页, 排序好的, map包含: ["Title"], ["SingleId"]
|
|
||||||
|
|
||||||
PerPageSize int `PerPageSize,omitempty`
|
|
||||||
SortField string `SortField` // 排序字段
|
|
||||||
IsAsc bool `IsAsc,omitempty` // 排序类型, 降序, 升序, 默认是false, 表示降序
|
|
||||||
|
|
||||||
SubDomain string `SubDomain` // 二级域名
|
SubDomain string `SubDomain` // 二级域名
|
||||||
Domain string `Domain` // 自定义域名
|
Domain string `Domain` // 自定义域名
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// 博客统计信息
|
|
||||||
type BlogStat struct {
|
|
||||||
NoteId bson.ObjectId `bson:"_id,omitempty"`
|
|
||||||
ReadNum int `ReadNum,omitempty` // 阅读次数 2014/9/28
|
|
||||||
LikeNum int `LikeNum,omitempty` // 点赞次数 2014/9/28
|
|
||||||
CommentNum int `CommentNum,omitempty` // 评论次数 2014/9/28
|
|
||||||
}
|
|
||||||
|
|
||||||
// 单页
|
|
||||||
type BlogSingle struct {
|
|
||||||
SingleId bson.ObjectId `bson:"_id,omitempty"`
|
|
||||||
UserId bson.ObjectId `UserId`
|
|
||||||
Title string `Title`
|
|
||||||
UrlTitle string `UrlTitle` // 2014/11/11
|
|
||||||
Content string `Content`
|
|
||||||
UpdatedTime time.Time `UpdatedTime`
|
|
||||||
CreatedTime time.Time `CreatedTime`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------
|
//------------------------
|
||||||
@@ -88,7 +57,7 @@ type BlogSingle struct {
|
|||||||
|
|
||||||
// 点赞记录
|
// 点赞记录
|
||||||
type BlogLike struct {
|
type BlogLike struct {
|
||||||
LikeId bson.ObjectId `bson:"_id,omitempty"`
|
LikeId bson.ObjectId `bson:"_id"`
|
||||||
NoteId bson.ObjectId `NoteId`
|
NoteId bson.ObjectId `NoteId`
|
||||||
UserId bson.ObjectId `UserId`
|
UserId bson.ObjectId `UserId`
|
||||||
CreatedTime time.Time `CreatedTime`
|
CreatedTime time.Time `CreatedTime`
|
||||||
@@ -96,7 +65,7 @@ type BlogLike struct {
|
|||||||
|
|
||||||
// 评论
|
// 评论
|
||||||
type BlogComment struct {
|
type BlogComment struct {
|
||||||
CommentId bson.ObjectId `bson:"_id,omitempty"`
|
CommentId bson.ObjectId `bson:"_id"`
|
||||||
NoteId bson.ObjectId `NoteId`
|
NoteId bson.ObjectId `NoteId`
|
||||||
|
|
||||||
UserId bson.ObjectId `UserId` // UserId回复ToUserId
|
UserId bson.ObjectId `UserId` // UserId回复ToUserId
|
||||||
@@ -115,14 +84,3 @@ type BlogCommentPublic struct {
|
|||||||
BlogComment
|
BlogComment
|
||||||
IsILikeIt bool
|
IsILikeIt bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type BlogUrls struct {
|
|
||||||
IndexUrl string
|
|
||||||
CateUrl string
|
|
||||||
SearchUrl string
|
|
||||||
SingleUrl string
|
|
||||||
PostUrl string
|
|
||||||
ArchiveUrl string
|
|
||||||
TagsUrl string
|
|
||||||
TagPostsUrl string
|
|
||||||
}
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
package info
|
|
||||||
|
|
||||||
import (
|
|
||||||
"gopkg.in/mgo.v2/bson"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
// 分组
|
|
||||||
type Group struct {
|
|
||||||
GroupId bson.ObjectId `bson:"_id"` // 谁的
|
|
||||||
UserId bson.ObjectId `UserId` // 所有者Id
|
|
||||||
Title string `Title` // 标题
|
|
||||||
UserCount int `UserCount` // 用户数
|
|
||||||
CreatedTime time.Time `CreatedTime`
|
|
||||||
|
|
||||||
Users []User `Users,omitempty` // 分组下的用户, 不保存, 仅查看
|
|
||||||
}
|
|
||||||
|
|
||||||
// 分组好友
|
|
||||||
type GroupUser struct {
|
|
||||||
GroupUserId bson.ObjectId `bson:"_id"` // 谁的
|
|
||||||
GroupId bson.ObjectId `GroupId` // 分组
|
|
||||||
UserId bson.ObjectId `UserId` // 用户
|
|
||||||
CreatedTime time.Time `CreatedTime`
|
|
||||||
}
|
|
||||||
+7
-14
@@ -20,11 +20,9 @@ type Note struct {
|
|||||||
|
|
||||||
IsTrash bool `IsTrash` // 是否是trash, 默认是false
|
IsTrash bool `IsTrash` // 是否是trash, 默认是false
|
||||||
|
|
||||||
IsBlog bool `IsBlog,omitempty` // 是否设置成了blog 2013/12/29 新加
|
IsBlog bool `IsBlog,omitempty` // 是否设置成了blog 2013/12/29 新加
|
||||||
UrlTitle string `UrlTitle,omitempty` // 博客的url标题, 为了更友好的url, 在UserId, UrlName下唯一
|
IsRecommend bool `IsRecommend,omitempty` // 是否为推荐博客 2014/9/24新加
|
||||||
IsRecommend bool `IsRecommend,omitempty` // 是否为推荐博客 2014/9/24新加
|
IsTop bool `IsTop,omitempty` // blog是否置顶
|
||||||
IsTop bool `IsTop,omitempty` // blog是否置顶
|
|
||||||
HasSelfDefined bool `HasSelfDefined` // 是否已经自定义博客图片, desc, abstract
|
|
||||||
|
|
||||||
// 2014/9/28 添加评论社交功能
|
// 2014/9/28 添加评论社交功能
|
||||||
ReadNum int `ReadNum,omitempty` // 阅读次数 2014/9/28
|
ReadNum int `ReadNum,omitempty` // 阅读次数 2014/9/28
|
||||||
@@ -34,17 +32,12 @@ type Note struct {
|
|||||||
IsMarkdown bool `IsMarkdown` // 是否是markdown笔记, 默认是false
|
IsMarkdown bool `IsMarkdown` // 是否是markdown笔记, 默认是false
|
||||||
|
|
||||||
AttachNum int `AttachNum` // 2014/9/21, attachments num
|
AttachNum int `AttachNum` // 2014/9/21, attachments num
|
||||||
|
|
||||||
CreatedTime time.Time `CreatedTime`
|
CreatedTime time.Time `CreatedTime`
|
||||||
UpdatedTime time.Time `UpdatedTime`
|
UpdatedTime time.Time `UpdatedTime`
|
||||||
RecommendTime time.Time `RecommendTime,omitempty` // 推荐时间
|
RecommendTime time.Time `RecommendTime,omitempty` // 推荐时间
|
||||||
PublicTime time.Time `PublicTime,omitempty` // 发表时间, 公开为博客则设置
|
PublicTime time.Time `PublicTime,omitempty` // 发表时间, 公开为博客则设置
|
||||||
UpdatedUserId bson.ObjectId `bson:"UpdatedUserId"` // 如果共享了, 并可写, 那么可能是其它他修改了
|
UpdatedUserId bson.ObjectId `bson:"UpdatedUserId"` // 如果共享了, 并可写, 那么可能是其它他修改了
|
||||||
|
|
||||||
// 2015/1/15, 更新序号
|
|
||||||
Usn int `Usn` // UpdateSequenceNum
|
|
||||||
|
|
||||||
IsDeleted bool `IsDeleted` // 删除位
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 内容
|
// 内容
|
||||||
|
|||||||
@@ -13,16 +13,11 @@ type Notebook struct {
|
|||||||
ParentNotebookId bson.ObjectId `bson:"ParentNotebookId,omitempty"` // 上级
|
ParentNotebookId bson.ObjectId `bson:"ParentNotebookId,omitempty"` // 上级
|
||||||
Seq int `Seq` // 排序
|
Seq int `Seq` // 排序
|
||||||
Title string `Title` // 标题
|
Title string `Title` // 标题
|
||||||
UrlTitle string `UrlTitle` // Url标题 2014/11.11加
|
|
||||||
NumberNotes int `NumberNotes` // 笔记数
|
NumberNotes int `NumberNotes` // 笔记数
|
||||||
IsTrash bool `IsTrash,omitempty` // 是否是trash, 默认是false
|
IsTrash bool `IsTrash,omitempty` // 是否是trash, 默认是false
|
||||||
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`
|
||||||
|
|
||||||
// 2015/1/15, 更新序号
|
|
||||||
Usn int `Usn` // UpdateSequenceNum
|
|
||||||
IsDeleted bool `IsDeleted`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 仅仅是为了返回前台
|
// 仅仅是为了返回前台
|
||||||
|
|||||||
@@ -13,8 +13,6 @@ type Session struct {
|
|||||||
|
|
||||||
LoginTimes int `LoginTimes` // 登录错误时间
|
LoginTimes int `LoginTimes` // 登录错误时间
|
||||||
Captcha string `Captcha` // 验证码
|
Captcha string `Captcha` // 验证码
|
||||||
|
|
||||||
UserId string `UserId` // API时有值UserId
|
|
||||||
|
|
||||||
CreatedTime time.Time `CreatedTime`
|
CreatedTime time.Time `CreatedTime`
|
||||||
UpdatedTime time.Time `UpdatedTime` // 更新时间, expire这个时间会自动清空
|
UpdatedTime time.Time `UpdatedTime` // 更新时间, expire这个时间会自动清空
|
||||||
|
|||||||
@@ -76,9 +76,7 @@ type SharingNotebookAndNotes struct {
|
|||||||
type ShareNotebook struct {
|
type ShareNotebook struct {
|
||||||
ShareNotebookId bson.ObjectId `bson:"_id,omitempty"` // 必须要设置bson:"_id" 不然mgo不会认为是主键
|
ShareNotebookId bson.ObjectId `bson:"_id,omitempty"` // 必须要设置bson:"_id" 不然mgo不会认为是主键
|
||||||
UserId bson.ObjectId `bson:"UserId"`
|
UserId bson.ObjectId `bson:"UserId"`
|
||||||
ToUserId bson.ObjectId `bson:"ToUserId,omitempty"`
|
ToUserId bson.ObjectId `bson:"ToUserId"`
|
||||||
ToGroupId bson.ObjectId `bson:"ToGroupId,omitempty"` // 分享给的用户组
|
|
||||||
ToGroup Group `ToGroup,omitempty` // 仅仅为了显示, 不存储, 分组信息
|
|
||||||
NotebookId bson.ObjectId `bson:"NotebookId"`
|
NotebookId bson.ObjectId `bson:"NotebookId"`
|
||||||
Seq int `bson:"Seq"` // 排序
|
Seq int `bson:"Seq"` // 排序
|
||||||
Perm int `bson:"Perm"` // 权限, 其下所有notes 0只读, 1可修改
|
Perm int `bson:"Perm"` // 权限, 其下所有notes 0只读, 1可修改
|
||||||
@@ -136,9 +134,7 @@ type ShareNotebooksByUser struct {
|
|||||||
type ShareNote struct {
|
type ShareNote struct {
|
||||||
ShareNoteId bson.ObjectId `bson:"_id,omitempty"` // 必须要设置bson:"_id" 不然mgo不会认为是主键
|
ShareNoteId bson.ObjectId `bson:"_id,omitempty"` // 必须要设置bson:"_id" 不然mgo不会认为是主键
|
||||||
UserId bson.ObjectId `bson:"UserId"`
|
UserId bson.ObjectId `bson:"UserId"`
|
||||||
ToUserId bson.ObjectId `bson:"ToUserId,omitempty"`
|
ToUserId bson.ObjectId `bson:"ToUserId"`
|
||||||
ToGroupId bson.ObjectId `bson:"ToGroupId,omitempty"` // 分享给的用户组
|
|
||||||
ToGroup Group `ToGroup,omitempty` // 仅仅为了显示, 不存储, 分组信息
|
|
||||||
NoteId bson.ObjectId `bson:"NoteId"`
|
NoteId bson.ObjectId `bson:"NoteId"`
|
||||||
Perm int `bson:"Perm"` // 权限, 0只读, 1可修改
|
Perm int `bson:"Perm"` // 权限, 0只读, 1可修改
|
||||||
CreatedTime time.Time `CreatedTime`
|
CreatedTime time.Time `CreatedTime`
|
||||||
|
|||||||
+1
-38
@@ -2,55 +2,18 @@ package info
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"gopkg.in/mgo.v2/bson"
|
"gopkg.in/mgo.v2/bson"
|
||||||
"time"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// 这里主要是为了统计每个tag的note数目
|
// 这里主要是为了统计每个tag的note数目
|
||||||
// 暂时没用
|
|
||||||
/*
|
|
||||||
type TagNote struct {
|
type TagNote struct {
|
||||||
TagId bson.ObjectId `bson:"_id,omitempty"` // 必须要设置bson:"_id" 不然mgo不会认为是主键
|
TagId bson.ObjectId `bson:"_id,omitempty"` // 必须要设置bson:"_id" 不然mgo不会认为是主键
|
||||||
UserId bson.ObjectId `bson:"UserId"`
|
UserId bson.ObjectId `bson:"UserId"`
|
||||||
Tag string `Title` // 标题
|
Tag string `Title` // 标题
|
||||||
NoteNum int `NoteNum` // note数目
|
NoteNum int `NoteNum` // note数目
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
// 每个用户一条记录, 存储用户的所有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 版标签
|
|
||||||
type NoteTag struct {
|
|
||||||
TagId bson.ObjectId `bson:"_id"`
|
|
||||||
UserId bson.ObjectId `UserId` // 谁的
|
|
||||||
Tag string `Tag` // UserId, Tag是唯一索引
|
|
||||||
Usn int `Usn` // Update Sequence Number
|
|
||||||
Count int `Count` // 笔记数
|
|
||||||
CreatedTime time.Time `CreatedTime`
|
|
||||||
UpdatedTime time.Time `UpdatedTime`
|
|
||||||
IsDeleted bool `IsDeleted` // 删除位
|
|
||||||
}
|
|
||||||
|
|
||||||
type TagCount struct {
|
|
||||||
TagCountId bson.ObjectId `bson:"_id,omitempty"`
|
|
||||||
UserId bson.ObjectId `UserId` // 谁的
|
|
||||||
Tag string `Tag`
|
|
||||||
IsBlog bool `IsBlog` // 是否是博客的tag统计
|
|
||||||
Count int `Count` // 统计数量
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
type TagsCounts []TagCount
|
|
||||||
func (this TagsCounts) Len() int {
|
|
||||||
return len(this)
|
|
||||||
}
|
|
||||||
func (this TagsCounts) Less(i, j int) bool {
|
|
||||||
return this[i].Count > this[j].Count
|
|
||||||
}
|
|
||||||
func (this TagsCounts) Swap(i, j int) {
|
|
||||||
this[i], this[j] = this[j], this[i]
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
package info
|
|
||||||
|
|
||||||
import (
|
|
||||||
"gopkg.in/mgo.v2/bson"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
// 主题, 每个用户有多个主题, 这里面有主题的配置信息
|
|
||||||
// 模板, css, js, images, 都在路径Path下
|
|
||||||
type Theme struct {
|
|
||||||
ThemeId bson.ObjectId `bson:"_id,omitempty"` // 必须要设置bson:"_id" 不然mgo不会认为是主键
|
|
||||||
UserId bson.ObjectId `UserId`
|
|
||||||
Name string `Name`
|
|
||||||
Version string `Version`
|
|
||||||
Author string `Author`
|
|
||||||
AuthorUrl string `AuthorUrl`
|
|
||||||
Path string `Path` // 文件夹路径, public/upload/54d7620d99c37b030600002c/themes/54d867c799c37b533e000001
|
|
||||||
Info map[string]interface{} `Info` // 所有信息
|
|
||||||
IsActive bool `IsActive` // 是否在用
|
|
||||||
|
|
||||||
IsDefault bool `IsDefault` // leanote默认主题, 如果用户修改了默认主题, 则先copy之. 也是admin用户的主题
|
|
||||||
Style string `Style,omitempty` // 之前的, 只有default的用户才有blog_default, blog_daqi, blog_left_fixed
|
|
||||||
|
|
||||||
CreatedTime time.Time `CreatedTime`
|
|
||||||
UpdatedTime time.Time `UpdatedTime`
|
|
||||||
}
|
|
||||||
@@ -34,51 +34,4 @@ type User struct {
|
|||||||
ThirdUserId string `ThirdUserId` // 用户Id, 在第三方中唯一可识别
|
ThirdUserId string `ThirdUserId` // 用户Id, 在第三方中唯一可识别
|
||||||
ThirdUsername string `ThirdUsername` // 第三方中username, 为了显示
|
ThirdUsername string `ThirdUsername` // 第三方中username, 为了显示
|
||||||
ThirdType int `ThirdType` // 第三方类型
|
ThirdType int `ThirdType` // 第三方类型
|
||||||
|
|
||||||
// 用户的帐户类型
|
|
||||||
|
|
||||||
ImageNum int `bson:"ImageNum" json:"-"` // 图片数量
|
|
||||||
ImageSize int `bson:"ImageSize" json:"-"` // 图片大小
|
|
||||||
AttachNum int `bson:"AttachNum" json:"-"` // 附件数量
|
|
||||||
AttachSize int `bson:"AttachSize" json:"-"` // 附件大小
|
|
||||||
FromUserId bson.ObjectId `FromUserId,omitempty` // 邀请的用户
|
|
||||||
|
|
||||||
AccountType string `bson:"AccountType" json:"-"` // normal(为空), premium
|
|
||||||
AccountStartTime time.Time `bson:"AccountStartTime" json:"-"` // 开始日期
|
|
||||||
AccountEndTime time.Time `bson:"AccountEndTime" json:"-"` // 结束日期
|
|
||||||
// 阈值
|
|
||||||
MaxImageNum int `bson:"MaxImageNums" json:"-"` // 图片数量
|
|
||||||
MaxImageSize int `bson:"MaxImageSize" json:"-"` // 图片大小
|
|
||||||
MaxAttachNum int `bson:"MaxAttachNum" json:"-"` // 图片数量
|
|
||||||
MaxAttachSize int `bson:"MaxAttachSize" json:"-"` // 图片大小
|
|
||||||
MaxPerAttachSize int `bson:"MaxPerAttachSize" json:"-"` // 单个附件大小
|
|
||||||
|
|
||||||
// 2015/1/15, 更新序号
|
|
||||||
Usn int `Usn` // UpdateSequenceNum , 全局的
|
|
||||||
FullSyncBefore time.Time `bson:"FullSyncBefore"` // 需要全量同步的时间, 如果 > 客户端的LastSyncTime, 则需要全量更新
|
|
||||||
}
|
|
||||||
|
|
||||||
type UserAccount struct {
|
|
||||||
AccountType string `bson:"AccountType" json:"-"` // normal(为空), premium
|
|
||||||
AccountStartTime time.Time `bson:"AccountStartTime" json:"-"` // 开始日期
|
|
||||||
AccountEndTime time.Time `bson:"AccountEndTime" json:"-"` // 结束日期
|
|
||||||
// 阈值
|
|
||||||
MaxImageNum int `bson:"MaxImageNums" json:"-"` // 图片数量
|
|
||||||
MaxImageSize int `bson:"MaxImageSize" json:"-"` // 图片大小
|
|
||||||
MaxAttachNum int `bson:"MaxAttachNum" json:"-"` // 图片数量
|
|
||||||
MaxAttachSize int `bson:"MaxAttachSize" json:"-"` // 图片大小
|
|
||||||
MaxPerAttachSize int `bson:"MaxPerAttachSize" json:"-"` // 单个附件大小
|
|
||||||
}
|
|
||||||
|
|
||||||
// 用户与博客信息结合, 公开
|
|
||||||
type UserAndBlog struct {
|
|
||||||
UserId bson.ObjectId `bson:"_id,omitempty"` // 必须要设置bson:"_id" 不然mgo不会认为是主键
|
|
||||||
Email string `Email` // 全是小写
|
|
||||||
Username string `Username` // 不区分大小写, 全是小写
|
|
||||||
Logo string `Logo`
|
|
||||||
BlogTitle string `BlogTitle` // 博客标题
|
|
||||||
BlogLogo string `BlogLogo` // 博客Logo
|
|
||||||
BlogUrl string `BlogUrl` // 博客链接, 主页
|
|
||||||
|
|
||||||
BlogUrls // 各个页面
|
|
||||||
}
|
}
|
||||||
+2
-3
@@ -9,7 +9,6 @@ import (
|
|||||||
type Page struct {
|
type Page struct {
|
||||||
CurPage int // 当前页码
|
CurPage int // 当前页码
|
||||||
TotalPage int // 总页
|
TotalPage int // 总页
|
||||||
PerPageSize int
|
|
||||||
Count int // 总记录数
|
Count int // 总记录数
|
||||||
List interface{}
|
List interface{}
|
||||||
}
|
}
|
||||||
@@ -19,5 +18,5 @@ func NewPage(page, perPageSize, count int, list interface{}) Page {
|
|||||||
if count > 0 {
|
if count > 0 {
|
||||||
totalPage = int(math.Ceil(float64(count) / float64(perPageSize)))
|
totalPage = int(math.Ceil(float64(count) / float64(perPageSize)))
|
||||||
}
|
}
|
||||||
return Page{page, totalPage, perPageSize, count, list}
|
return Page{page, totalPage, count, list}
|
||||||
}
|
}
|
||||||
+11
-122
@@ -6,12 +6,10 @@ import (
|
|||||||
"github.com/leanote/leanote/app/service"
|
"github.com/leanote/leanote/app/service"
|
||||||
"github.com/leanote/leanote/app/db"
|
"github.com/leanote/leanote/app/db"
|
||||||
"github.com/leanote/leanote/app/controllers"
|
"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/admin"
|
||||||
"github.com/leanote/leanote/app/controllers/member"
|
|
||||||
_ "github.com/leanote/leanote/app/lea/binder"
|
_ "github.com/leanote/leanote/app/lea/binder"
|
||||||
// "github.com/leanote/leanote/app/lea/session"
|
"github.com/leanote/leanote/app/lea/session"
|
||||||
// "github.com/leanote/leanote/app/lea/memcache"
|
"github.com/leanote/leanote/app/lea/memcache"
|
||||||
"github.com/leanote/leanote/app/lea/route"
|
"github.com/leanote/leanote/app/lea/route"
|
||||||
"reflect"
|
"reflect"
|
||||||
"fmt"
|
"fmt"
|
||||||
@@ -21,7 +19,6 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"net/url"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
@@ -33,11 +30,11 @@ func init() {
|
|||||||
// AuthFilter, // Invoke the action.
|
// AuthFilter, // Invoke the action.
|
||||||
revel.FilterConfiguringFilter, // A hook for adding or removing per-Action filters.
|
revel.FilterConfiguringFilter, // A hook for adding or removing per-Action filters.
|
||||||
revel.ParamsFilter, // Parse parameters into Controller.Params.
|
revel.ParamsFilter, // Parse parameters into Controller.Params.
|
||||||
revel.SessionFilter, // Restore and write the session cookie.
|
// revel.SessionFilter, // Restore and write the session cookie.
|
||||||
|
|
||||||
// 使用SessionFilter标准版从cookie中得到sessionID, 然后通过MssessionFilter从Memcache中得到
|
// 使用SessionFilter标准版从cookie中得到sessionID, 然后通过MssessionFilter从Memcache中得到
|
||||||
// session, 之后MSessionFilter将session只存sessionID然后返回给SessionFilter返回到web
|
// session, 之后MSessionFilter将session只存sessionID然后返回给SessionFilter返回到web
|
||||||
// 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.
|
||||||
@@ -51,18 +48,6 @@ func init() {
|
|||||||
revel.TemplateFuncs["raw"] = func(str string) template.HTML {
|
revel.TemplateFuncs["raw"] = func(str string) template.HTML {
|
||||||
return template.HTML(str)
|
return template.HTML(str)
|
||||||
}
|
}
|
||||||
revel.TemplateFuncs["trim"] = func(str string) string {
|
|
||||||
str = strings.Trim(str, " ")
|
|
||||||
str = strings.Trim(str, " ")
|
|
||||||
|
|
||||||
str = strings.Trim(str, "\n")
|
|
||||||
str = strings.Trim(str, " ")
|
|
||||||
|
|
||||||
// 以下两个空格不一样
|
|
||||||
str = strings.Trim(str, " ")
|
|
||||||
str = strings.Trim(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)
|
||||||
@@ -71,11 +56,6 @@ func init() {
|
|||||||
i = i - 1;
|
i = i - 1;
|
||||||
return i
|
return i
|
||||||
}
|
}
|
||||||
// 增加或减少
|
|
||||||
revel.TemplateFuncs["incr"] = func(n, i int) int {
|
|
||||||
n = n + i;
|
|
||||||
return n
|
|
||||||
}
|
|
||||||
revel.TemplateFuncs["join"] = func(arr []string) template.HTML {
|
revel.TemplateFuncs["join"] = func(arr []string) template.HTML {
|
||||||
if arr == nil {
|
if arr == nil {
|
||||||
return template.HTML("")
|
return template.HTML("")
|
||||||
@@ -92,24 +72,13 @@ func init() {
|
|||||||
}
|
}
|
||||||
return str
|
return str
|
||||||
}
|
}
|
||||||
revel.TemplateFuncs["decodeUrlValue"] = func(i string) string {
|
|
||||||
v, _ := url.ParseQuery("a=" + i)
|
|
||||||
return v.Get("a")
|
|
||||||
}
|
|
||||||
revel.TemplateFuncs["json"] = func(i interface{}) string {
|
revel.TemplateFuncs["json"] = func(i interface{}) string {
|
||||||
b, _ := json.Marshal(i)
|
b, _ := json.Marshal(i)
|
||||||
return string(b)
|
return string(b)
|
||||||
}
|
}
|
||||||
revel.TemplateFuncs["jsonJs"] = func(i interface{}) template.JS {
|
|
||||||
b, _ := json.Marshal(i)
|
|
||||||
return template.JS(string(b))
|
|
||||||
}
|
|
||||||
revel.TemplateFuncs["datetime"] = func(t time.Time) template.HTML {
|
revel.TemplateFuncs["datetime"] = func(t time.Time) template.HTML {
|
||||||
return template.HTML(t.Format("2006-01-02 15:04:05"))
|
return template.HTML(t.Format("2006-01-02 15:04:05"))
|
||||||
}
|
}
|
||||||
revel.TemplateFuncs["dateFormat"] = func(t time.Time, format string) template.HTML {
|
|
||||||
return template.HTML(t.Format(format))
|
|
||||||
}
|
|
||||||
revel.TemplateFuncs["unixDatetime"] = func(unixSec string) template.HTML {
|
revel.TemplateFuncs["unixDatetime"] = func(unixSec string) template.HTML {
|
||||||
sec, _ := strconv.Atoi(unixSec)
|
sec, _ := strconv.Atoi(unixSec)
|
||||||
t := time.Unix(int64(sec), 0)
|
t := time.Unix(int64(sec), 0)
|
||||||
@@ -124,7 +93,6 @@ func init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// tags
|
// tags
|
||||||
// 2014/12/30 标签添加链接
|
|
||||||
revel.TemplateFuncs["blogTags"] = func(renderArgs map[string]interface{}, tags []string) template.HTML {
|
revel.TemplateFuncs["blogTags"] = func(renderArgs map[string]interface{}, tags []string) template.HTML {
|
||||||
if tags == nil || len(tags) == 0 {
|
if tags == nil || len(tags) == 0 {
|
||||||
return ""
|
return ""
|
||||||
@@ -132,95 +100,18 @@ func init() {
|
|||||||
locale, _ := renderArgs[revel.CurrentLocaleRenderArg].(string)
|
locale, _ := renderArgs[revel.CurrentLocaleRenderArg].(string)
|
||||||
tagStr := ""
|
tagStr := ""
|
||||||
lenTags := len(tags)
|
lenTags := len(tags)
|
||||||
|
|
||||||
tagPostUrl, _ := renderArgs["tagPostsUrl"].(string)
|
|
||||||
|
|
||||||
for i, tag := range tags {
|
for i, tag := range tags {
|
||||||
str := revel.Message(locale, tag)
|
str := revel.Message(locale, tag)
|
||||||
var classes = "label"
|
|
||||||
if strings.HasPrefix(str, "???") {
|
if strings.HasPrefix(str, "???") {
|
||||||
str = tag
|
str = tag
|
||||||
}
|
}
|
||||||
if InArray([]string{"red", "blue", "yellow", "green"}, tag) {
|
tagStr += str
|
||||||
classes += " label-" + tag
|
|
||||||
} else {
|
|
||||||
classes += " label-default"
|
|
||||||
}
|
|
||||||
|
|
||||||
classes += " label-post"
|
|
||||||
var url = tagPostUrl + "/" + url.QueryEscape(tag)
|
|
||||||
tagStr += "<a class=\"" + classes + "\" href=\"" + url + "\">" + str + "</a>";
|
|
||||||
if i != lenTags - 1 {
|
if i != lenTags - 1 {
|
||||||
tagStr += " "
|
tagStr += ","
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return template.HTML(tagStr)
|
return template.HTML(tagStr)
|
||||||
}
|
}
|
||||||
|
|
||||||
revel.TemplateFuncs["blogTagsForExport"] = func(renderArgs map[string]interface{}, tags []string) template.HTML {
|
|
||||||
if tags == nil || len(tags) == 0 {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
tagStr := ""
|
|
||||||
lenTags := len(tags)
|
|
||||||
|
|
||||||
for i, tag := range tags {
|
|
||||||
str := tag
|
|
||||||
var classes = "label"
|
|
||||||
if InArray([]string{"red", "blue", "yellow", "green"}, tag) {
|
|
||||||
classes += " label-" + tag
|
|
||||||
} else {
|
|
||||||
classes += " label-default"
|
|
||||||
}
|
|
||||||
|
|
||||||
classes += " label-post"
|
|
||||||
tagStr += "<span class=\"" + classes + "\" >" + str + "</span>";
|
|
||||||
if i != lenTags - 1 {
|
|
||||||
tagStr += " "
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return template.HTML(tagStr)
|
|
||||||
}
|
|
||||||
|
|
||||||
// lea++
|
|
||||||
revel.TemplateFuncs["blogTagsLea"] = func(renderArgs map[string]interface{}, tags []string, typeStr string) template.HTML {
|
|
||||||
if tags == nil || len(tags) == 0 {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
locale, _ := renderArgs[revel.CurrentLocaleRenderArg].(string)
|
|
||||||
tagStr := ""
|
|
||||||
lenTags := len(tags)
|
|
||||||
|
|
||||||
tagPostUrl := "http://lea.leanote.com/"
|
|
||||||
if typeStr == "recommend" {
|
|
||||||
tagPostUrl += "?tag=";
|
|
||||||
} else if typeStr == "latest" {
|
|
||||||
tagPostUrl += "latest?tag=";
|
|
||||||
} else {
|
|
||||||
tagPostUrl += "subscription?tag=";
|
|
||||||
}
|
|
||||||
|
|
||||||
for i, tag := range tags {
|
|
||||||
str := revel.Message(locale, tag)
|
|
||||||
var classes = "label"
|
|
||||||
if strings.HasPrefix(str, "???") {
|
|
||||||
str = tag
|
|
||||||
}
|
|
||||||
if InArray([]string{"red", "blue", "yellow", "green"}, tag) {
|
|
||||||
classes += " label-" + tag
|
|
||||||
} else {
|
|
||||||
classes += " label-default"
|
|
||||||
}
|
|
||||||
classes += " label-post"
|
|
||||||
var url = tagPostUrl + url.QueryEscape(tag)
|
|
||||||
tagStr += "<a class=\"" + classes + "\" href=\"" + url + "\">" + str + "</a>";
|
|
||||||
if i != lenTags - 1 {
|
|
||||||
tagStr += " "
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return template.HTML(tagStr)
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
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 {
|
||||||
@@ -244,6 +135,8 @@ func init() {
|
|||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
revel.TemplateFuncs["li"] = func(a string) string {
|
revel.TemplateFuncs["li"] = func(a string) string {
|
||||||
|
Log(a)
|
||||||
|
Log("life==")
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
// str连接
|
// str连接
|
||||||
@@ -355,7 +248,6 @@ func init() {
|
|||||||
// https://groups.google.com/forum/#!topic/golang-nuts/OEdSDgEC7js
|
// https://groups.google.com/forum/#!topic/golang-nuts/OEdSDgEC7js
|
||||||
// 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:
|
case string:
|
||||||
@@ -381,7 +273,6 @@ func init() {
|
|||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
{{range $i := N 1 10}}
|
{{range $i := N 1 10}}
|
||||||
@@ -402,17 +293,15 @@ func init() {
|
|||||||
// init Email
|
// init Email
|
||||||
revel.OnAppStart(func() {
|
revel.OnAppStart(func() {
|
||||||
// 数据库
|
// 数据库
|
||||||
db.Init("", "")
|
db.Init()
|
||||||
// email配置
|
// email配置
|
||||||
InitEmail()
|
InitEmail()
|
||||||
InitVd()
|
InitVd()
|
||||||
// memcache.InitMemcache() // session服务
|
memcache.InitMemcache() // session服务
|
||||||
// 其它service
|
// 其它service
|
||||||
service.InitService()
|
service.InitService()
|
||||||
controllers.InitService()
|
controllers.InitService()
|
||||||
admin.InitService()
|
admin.InitService()
|
||||||
member.InitService()
|
|
||||||
service.ConfigS.InitGlobalConfigs()
|
service.ConfigS.InitGlobalConfigs()
|
||||||
api.InitService()
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
+1
-12
@@ -3,7 +3,6 @@ package lea
|
|||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"github.com/revel/revel"
|
"github.com/revel/revel"
|
||||||
"fmt"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func Log(i interface{}) {
|
func Log(i interface{}) {
|
||||||
@@ -13,14 +12,4 @@ func Log(i interface{}) {
|
|||||||
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用
|
|
||||||
func L(i interface{}) {
|
|
||||||
fmt.Println(i)
|
|
||||||
}
|
|
||||||
|
|
||||||
func LJ(i interface{}) {
|
|
||||||
b, _ := json.MarshalIndent(i, "", " ")
|
|
||||||
fmt.Println(string(b))
|
|
||||||
}
|
|
||||||
+15
-115
@@ -1,11 +1,10 @@
|
|||||||
package lea
|
package lea
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"io"
|
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
"strings"
|
"strings"
|
||||||
|
"path/filepath"
|
||||||
|
"os"
|
||||||
|
"io"
|
||||||
)
|
)
|
||||||
|
|
||||||
// 分离文件名与扩展名(包含.)
|
// 分离文件名与扩展名(包含.)
|
||||||
@@ -15,14 +14,14 @@ func SplitFilename(filename string) (baseName, ext string) {
|
|||||||
ext = SubstringByte(filename, strings.LastIndex(filename, "."))
|
ext = SubstringByte(filename, strings.LastIndex(filename, "."))
|
||||||
baseName = strings.TrimRight(filename, ext)
|
baseName = strings.TrimRight(filename, ext)
|
||||||
ext = strings.ToLower(ext)
|
ext = strings.ToLower(ext)
|
||||||
return
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 转换文件的格式
|
// 转换文件的格式
|
||||||
// toExt包含.
|
// toExt包含.
|
||||||
func TransferExt(path string, toExt string) string {
|
func TransferExt(path string, toExt string) string {
|
||||||
dir := filepath.Dir(path) + "/" // 文件路径
|
dir := filepath.Dir(path) + "/" // 文件路径
|
||||||
name := filepath.Base(path) // 文件名 a.jpg
|
name := filepath.Base(path) // 文件名 a.jpg
|
||||||
// 获取文件名与路径
|
// 获取文件名与路径
|
||||||
baseName, _ := SplitFilename(name)
|
baseName, _ := SplitFilename(name)
|
||||||
return dir + baseName + toExt
|
return dir + baseName + toExt
|
||||||
@@ -39,7 +38,7 @@ func GetFilesize(path string) int64 {
|
|||||||
if err == nil {
|
if err == nil {
|
||||||
return fileinfo.Size()
|
return fileinfo.Size()
|
||||||
}
|
}
|
||||||
return 0
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 清空dir下所有的文件和文件夹
|
// 清空dir下所有的文件和文件夹
|
||||||
@@ -56,14 +55,6 @@ func ClearDir(dir string) bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func MkdirAll(dir string) bool {
|
|
||||||
err := os.MkdirAll(dir, 0777)
|
|
||||||
if err != nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// list dir's all file, return filenames
|
// list dir's all file, return filenames
|
||||||
func ListDir(dir string) []string {
|
func ListDir(dir string) []string {
|
||||||
f, err := os.Open(dir)
|
f, err := os.Open(dir)
|
||||||
@@ -88,103 +79,12 @@ func CopyFile(srcName, dstName string) (written int64, err error) {
|
|||||||
return io.Copy(dst, src)
|
return io.Copy(dst, src)
|
||||||
}
|
}
|
||||||
|
|
||||||
func CopyDir(source string, dest string) (err error) {
|
|
||||||
// get properties of source dir
|
|
||||||
sourceinfo, err := os.Stat(source)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// create dest dir
|
|
||||||
|
|
||||||
err = os.MkdirAll(dest, sourceinfo.Mode())
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
directory, _ := os.Open(source)
|
|
||||||
|
|
||||||
objects, err := directory.Readdir(-1)
|
|
||||||
|
|
||||||
for _, obj := range objects {
|
|
||||||
|
|
||||||
sourcefilepointer := source + "/" + obj.Name()
|
|
||||||
|
|
||||||
destinationfilepointer := dest + "/" + obj.Name()
|
|
||||||
|
|
||||||
if obj.IsDir() {
|
|
||||||
// create sub-directories - recursively
|
|
||||||
err = CopyDir(sourcefilepointer, destinationfilepointer)
|
|
||||||
if err != nil {
|
|
||||||
// fmt.Println(err)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// perform copy
|
|
||||||
_, err = CopyFile(sourcefilepointer, destinationfilepointer)
|
|
||||||
if err != nil {
|
|
||||||
// fmt.Println(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func DeleteFile(path string) bool {
|
|
||||||
err := os.Remove(path)
|
|
||||||
if err != nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
func IsDirExists(path string) bool {
|
func IsDirExists(path string) bool {
|
||||||
fi, err := os.Stat(path)
|
fi, err := os.Stat(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return os.IsExist(err)
|
return os.IsExist(err)
|
||||||
} else {
|
}else{
|
||||||
return fi.IsDir()
|
return fi.IsDir()
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获得文件str内容
|
|
||||||
func GetFileStrContent(path string) string {
|
|
||||||
fileBytes, err := ioutil.ReadFile(path)
|
|
||||||
if err != nil {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
return string(fileBytes)
|
|
||||||
}
|
|
||||||
|
|
||||||
func IsFileExist(filename string) bool {
|
|
||||||
var exist = true
|
|
||||||
if _, err := os.Stat(filename); os.IsNotExist(err) {
|
|
||||||
exist = false
|
|
||||||
}
|
|
||||||
return exist
|
|
||||||
}
|
|
||||||
|
|
||||||
// 写入string内容
|
|
||||||
func PutFileStrContent(path, content string) bool {
|
|
||||||
var f *os.File
|
|
||||||
var err1 error
|
|
||||||
defer (func() {
|
|
||||||
if f != nil {
|
|
||||||
f.Close()
|
|
||||||
}
|
|
||||||
})()
|
|
||||||
f, err1 = os.OpenFile(path, os.O_RDWR|os.O_TRUNC|os.O_CREATE, 0666) //打开文件
|
|
||||||
// Log(err1)
|
|
||||||
// var n int
|
|
||||||
_, err1 = io.WriteString(f, content) //写入文件(字符串)
|
|
||||||
// Log(content)
|
|
||||||
// Log(err1)
|
|
||||||
// Log(n)
|
|
||||||
// Log(path)
|
|
||||||
|
|
||||||
if err1 != nil {
|
|
||||||
Log(err1)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
package lea
|
|
||||||
|
|
||||||
// 对比密码是否一致
|
|
||||||
// 因为之前密码是用md5加密的, 所以通过密码长度来判断
|
|
||||||
// rawPwd 原始, 用户输入的密码
|
|
||||||
func ComparePwd(rawPwd, dbPwd string) bool {
|
|
||||||
if len(dbPwd) == 32 {
|
|
||||||
return Md5(rawPwd) == dbPwd
|
|
||||||
}
|
|
||||||
|
|
||||||
hex := []byte(dbPwd)
|
|
||||||
return CompareHash(hex, rawPwd)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 加密
|
|
||||||
func GenPwd(rawPwd string) string {
|
|
||||||
digest, err := GenerateHash(rawPwd)
|
|
||||||
if err != nil {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
return string(digest)
|
|
||||||
}
|
|
||||||
+3
-60
@@ -10,7 +10,6 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"gopkg.in/mgo.v2/bson"
|
"gopkg.in/mgo.v2/bson"
|
||||||
"time"
|
"time"
|
||||||
"strings"
|
|
||||||
math_rand "math/rand"
|
math_rand "math/rand"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -123,44 +122,9 @@ func ReplaceAll(oldStr, pattern, newStr string) string {
|
|||||||
return string(s)
|
return string(s)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取纯文本
|
|
||||||
func SubStringHTMLToRaw(param string, length int) (result string) {
|
|
||||||
if param == "" {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
result = ""
|
|
||||||
n := 0
|
|
||||||
var temp rune // 中文问题, 用rune来解决
|
|
||||||
rStr := []rune(param)
|
|
||||||
isCode := false
|
|
||||||
for i := 0; i < len(rStr); i++ {
|
|
||||||
temp = rStr[i]
|
|
||||||
if temp == '<' {
|
|
||||||
isCode = true
|
|
||||||
continue
|
|
||||||
} else if temp == '>' {
|
|
||||||
isCode = false
|
|
||||||
result += " "; // 空格
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if !isCode {
|
|
||||||
result += string(temp)
|
|
||||||
n++
|
|
||||||
if n >= length {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 获取摘要, HTML
|
|
||||||
func SubStringHTML(param string, length int, end string) string {
|
func SubStringHTML(param string, length int, end string) string {
|
||||||
if param == "" {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
// 先取出<pre></pre>占位..
|
// 先取出<pre></pre>占位..
|
||||||
|
|
||||||
result := ""
|
result := ""
|
||||||
|
|
||||||
// 1
|
// 1
|
||||||
@@ -232,7 +196,6 @@ func SubStringHTML(param string, length int, end string) string {
|
|||||||
|
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
// 是否是合格的密码
|
// 是否是合格的密码
|
||||||
func IsGoodPwd(pwd string) (bool, string) {
|
func IsGoodPwd(pwd string) (bool, string) {
|
||||||
if pwd == "" {
|
if pwd == "" {
|
||||||
@@ -249,7 +212,7 @@ 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,3}$`, email)
|
ok, _ := regexp.MatchString(`^([a-zA-Z0-9]+[_|\_|\.]?)*[a-zA-Z0-9]+@([a-zA-Z0-9]+[_|\_|\.]?)*[a-zA-Z0-9]+\.[0-9a-zA-Z]{2,3}$`, email)
|
||||||
return ok
|
return ok
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -315,24 +278,4 @@ func InArray(arr []string, str string) bool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// 将名称的特殊字符去掉
|
|
||||||
func FixFilename(filename string) string {
|
|
||||||
if filename != "" {
|
|
||||||
// 把特殊字段给替换掉
|
|
||||||
// str := `life "%&()+,/:;<>=?@\|`
|
|
||||||
// . == \\.
|
|
||||||
// $ === \\$
|
|
||||||
reg, _ := regexp.Compile("\\.|/|#|\\$|!|\\^|\\*|'| |\"|%|&|\\(|\\)|\\+|\\,|/|:|;|<|>|=|\\?|@|\\||\\\\")
|
|
||||||
filename = reg.ReplaceAllString(filename, "-")
|
|
||||||
filename = strings.Trim(filename, "-") // 左右单独的-去掉
|
|
||||||
// 把空格替换成-
|
|
||||||
// filename = strings.Replace(filename, " ", "-", -1)
|
|
||||||
for strings.Index(filename, "--") >= 0 { // 防止出现连续的--
|
|
||||||
filename = strings.Replace(filename, "--", "-", -1)
|
|
||||||
}
|
|
||||||
return filename
|
|
||||||
}
|
|
||||||
return filename
|
|
||||||
}
|
|
||||||
@@ -27,12 +27,6 @@ var rulesStr = `{
|
|||||||
],
|
],
|
||||||
"domain": [
|
"domain": [
|
||||||
{"rule": "domain", "msg": "errorDomain"}
|
{"rule": "domain", "msg": "errorDomain"}
|
||||||
],
|
|
||||||
"perPageSize": [
|
|
||||||
{"rule": "min", "data": "1", "msg": "errorPerPageSize"}
|
|
||||||
],
|
|
||||||
"sortField": [
|
|
||||||
{"rule": "sortField", "msg": "errorSortField"}
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
@@ -55,25 +49,6 @@ 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) {
|
|
||||||
if value == "" {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
data := rule["data"]
|
|
||||||
dataI, _ := strconv.Atoi(data)
|
|
||||||
vI, _ := strconv.Atoi(value)
|
|
||||||
ok = vI >= dataI
|
|
||||||
return
|
|
||||||
},
|
|
||||||
|
|
||||||
"sortField": func(value string, rule map[string]string)(ok bool, msg string) {
|
|
||||||
if value == "" {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
sortFields := []string{"PublicTime", "CreatedTime", "UpdatedTime", "Title"}
|
|
||||||
ok = InArray(sortFields, value)
|
|
||||||
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 == "" {
|
||||||
|
|||||||
@@ -1,230 +0,0 @@
|
|||||||
package archive
|
|
||||||
|
|
||||||
import (
|
|
||||||
"archive/tar"
|
|
||||||
"compress/gzip"
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"os"
|
|
||||||
"path"
|
|
||||||
)
|
|
||||||
|
|
||||||
// main functions shows how to TarGz a directory/file and
|
|
||||||
// UnTarGz a file
|
|
||||||
// Gzip and tar from source directory or file to destination file
|
|
||||||
// you need check file exist before you call this function
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
/*
|
|
||||||
os.Mkdir("/home/ty4z2008/tar", 0777)
|
|
||||||
w, err := CopyFile("/home/ty4z2008/tar/1.pdf", "/home/ty4z2008/src/1.pdf")
|
|
||||||
//targetfile,sourcefile
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println(err.Error())
|
|
||||||
}
|
|
||||||
fmt.Println(w)
|
|
||||||
|
|
||||||
TarGz("/home/ty4z2008/tar/1.pdf", "/home/ty4z2008/test.tar.gz") //压缩
|
|
||||||
//UnTarGz("/home/ty4z2008/1.tar.gz", "/home/ty4z2008") //解压
|
|
||||||
os.RemoveAll("/home/ty4z2008/tar")
|
|
||||||
*/
|
|
||||||
// TaZip("/Users/life/Desktop/j", "/Users/life/Desktop/aaa.tar.gz")
|
|
||||||
Zip("/Users/life/Desktop/j", "/Users/life/Desktop/aaa.zip")
|
|
||||||
fmt.Println("ok")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TarGz(srcDirPath string, destFilePath string) (ok bool) {
|
|
||||||
defer func() { //必须要先声明defer,否则不能捕获到panic异常
|
|
||||||
if err := recover(); err != nil {
|
|
||||||
ok = false
|
|
||||||
}
|
|
||||||
|
|
||||||
}()
|
|
||||||
|
|
||||||
fw, err := os.Create(destFilePath)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
defer fw.Close()
|
|
||||||
|
|
||||||
// Gzip writer
|
|
||||||
gw := gzip.NewWriter(fw)
|
|
||||||
defer gw.Close()
|
|
||||||
|
|
||||||
// Tar writer
|
|
||||||
tw := tar.NewWriter(gw)
|
|
||||||
defer tw.Close()
|
|
||||||
|
|
||||||
// Check if it's a file or a directory
|
|
||||||
f, err := os.Open(srcDirPath)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
fi, err := f.Stat()
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
if fi.IsDir() {
|
|
||||||
// handle source directory
|
|
||||||
// fmt.Println("Cerating tar.gz from directory...")
|
|
||||||
tarGzDir(srcDirPath, path.Base(srcDirPath), tw)
|
|
||||||
} else {
|
|
||||||
// handle file directly
|
|
||||||
// fmt.Println("Cerating tar.gz from " + fi.Name() + "...")
|
|
||||||
tarGzFile(srcDirPath, fi.Name(), tw, fi)
|
|
||||||
}
|
|
||||||
ok = true
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Deal with directories
|
|
||||||
// if find files, handle them with tarGzFile
|
|
||||||
// Every recurrence append the base path to the recPath
|
|
||||||
// recPath is the path inside of tar.gz
|
|
||||||
func tarGzDir(srcDirPath string, recPath string, tw *tar.Writer) {
|
|
||||||
// Open source diretory
|
|
||||||
dir, err := os.Open(srcDirPath)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
defer dir.Close()
|
|
||||||
|
|
||||||
// Get file info slice
|
|
||||||
fis, err := dir.Readdir(0)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
for _, fi := range fis {
|
|
||||||
// Append path
|
|
||||||
curPath := srcDirPath + "/" + fi.Name()
|
|
||||||
// Check it is directory or file
|
|
||||||
if fi.IsDir() {
|
|
||||||
// Directory
|
|
||||||
// (Directory won't add unitl all subfiles are added)
|
|
||||||
// fmt.Printf("Adding path...%s\n", curPath)
|
|
||||||
tarGzDir(curPath, recPath+"/"+fi.Name(), tw)
|
|
||||||
} else {
|
|
||||||
// File
|
|
||||||
// fmt.Printf("Adding file...%s\n", curPath)
|
|
||||||
}
|
|
||||||
|
|
||||||
tarGzFile(curPath, recPath+"/"+fi.Name(), tw, fi)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Deal with files
|
|
||||||
func tarGzFile(srcFile string, recPath string, tw *tar.Writer, fi os.FileInfo) {
|
|
||||||
if fi.IsDir() {
|
|
||||||
// fmt.Println("??")
|
|
||||||
// Create tar header
|
|
||||||
hdr := new(tar.Header)
|
|
||||||
// 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
|
|
||||||
hdr.Name = recPath // + "/"
|
|
||||||
// fmt.Println(hdr.Name)
|
|
||||||
hdr.Typeflag = tar.TypeDir
|
|
||||||
// hdr.Size = 0
|
|
||||||
//hdr.Mode = 0755 | c_ISDIR
|
|
||||||
// hdr.Mode = int64(fi.Mode()) // 加这个会有错误!!!
|
|
||||||
// hdr.ModTime = fi.ModTime() // 加这个会有错误!!
|
|
||||||
|
|
||||||
// Write hander
|
|
||||||
err := tw.WriteHeader(hdr)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// File reader
|
|
||||||
fr, err := os.Open(srcFile)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
defer fr.Close()
|
|
||||||
|
|
||||||
// Create tar header
|
|
||||||
hdr := new(tar.Header)
|
|
||||||
hdr.Name = recPath
|
|
||||||
// fmt.Println(hdr.Name)
|
|
||||||
hdr.Size = fi.Size()
|
|
||||||
hdr.Mode = int64(fi.Mode())
|
|
||||||
hdr.ModTime = fi.ModTime()
|
|
||||||
|
|
||||||
// Write hander
|
|
||||||
err = tw.WriteHeader(hdr)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Write file data
|
|
||||||
_, err = io.Copy(tw, fr)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ungzip and untar from source file to destination directory
|
|
||||||
// you need check file exist before you call this function
|
|
||||||
func UnTarGz(srcFilePath string, destDirPath string) {
|
|
||||||
// fmt.Println("UnTarGzing " + srcFilePath + "...")
|
|
||||||
// Create destination directory
|
|
||||||
os.Mkdir(destDirPath, os.ModePerm)
|
|
||||||
|
|
||||||
fr, err := os.Open(srcFilePath)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
defer fr.Close()
|
|
||||||
|
|
||||||
// Gzip reader
|
|
||||||
gr, err := gzip.NewReader(fr)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
defer gr.Close()
|
|
||||||
|
|
||||||
// Tar reader
|
|
||||||
tr := tar.NewReader(gr)
|
|
||||||
|
|
||||||
for {
|
|
||||||
hdr, err := tr.Next()
|
|
||||||
if err == io.EOF {
|
|
||||||
// End of tar archive
|
|
||||||
break
|
|
||||||
}
|
|
||||||
//handleError(err)
|
|
||||||
// fmt.Println("UnTarGzing file..." + hdr.Name)
|
|
||||||
// Check if it is diretory or file
|
|
||||||
if hdr.Typeflag != tar.TypeDir {
|
|
||||||
// Get files from archive
|
|
||||||
// Create diretory before create file
|
|
||||||
os.MkdirAll(destDirPath+"/"+path.Dir(hdr.Name), os.ModePerm)
|
|
||||||
// Write data to file
|
|
||||||
fw, _ := os.Create(destDirPath + "/" + hdr.Name)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
_, err = io.Copy(fw, tr)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// fmt.Println("Well done!")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Copyfile
|
|
||||||
func CopyFile(dstName, srcName string) (written int64, err error) {
|
|
||||||
src, err := os.Open(srcName)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
defer src.Close()
|
|
||||||
dst, err := os.OpenFile(dstName, os.O_WRONLY|os.O_CREATE, 0644)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
defer dst.Close()
|
|
||||||
return io.Copy(dst, src)
|
|
||||||
}
|
|
||||||
@@ -1,192 +0,0 @@
|
|||||||
package archive
|
|
||||||
|
|
||||||
import (
|
|
||||||
"archive/zip"
|
|
||||||
"fmt"
|
|
||||||
"strings"
|
|
||||||
"io"
|
|
||||||
"os"
|
|
||||||
"path"
|
|
||||||
)
|
|
||||||
|
|
||||||
// main functions shows how to TarGz a directory/file and
|
|
||||||
// UnTarGz a file
|
|
||||||
// Gzip and tar from source directory or file to destination file
|
|
||||||
// you need check file exist before you call this function
|
|
||||||
|
|
||||||
func Zip(srcDirPath string, destFilePath string) (ok bool) {
|
|
||||||
defer func() { //必须要先声明defer,否则不能捕获到panic异常
|
|
||||||
if err := recover(); err != nil {
|
|
||||||
ok = false
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
fw, err := os.Create(destFilePath)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
defer fw.Close()
|
|
||||||
|
|
||||||
// Tar writer
|
|
||||||
tw := zip.NewWriter(fw)
|
|
||||||
defer tw.Close()
|
|
||||||
|
|
||||||
// Check if it's a file or a directory
|
|
||||||
f, err := os.Open(srcDirPath)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
fi, err := f.Stat()
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
if fi.IsDir() {
|
|
||||||
// handle source directory
|
|
||||||
// fmt.Println("Cerating tar.gz from directory...")
|
|
||||||
zipDir(srcDirPath, path.Base(srcDirPath), tw)
|
|
||||||
} else {
|
|
||||||
// handle file directly
|
|
||||||
// fmt.Println("Cerating tar.gz from " + fi.Name() + "...")
|
|
||||||
zipFile(srcDirPath, fi.Name(), tw, fi)
|
|
||||||
}
|
|
||||||
ok = true
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Deal with directories
|
|
||||||
// if find files, handle them with zipFile
|
|
||||||
// Every recurrence append the base path to the recPath
|
|
||||||
// recPath is the path inside of tar.gz
|
|
||||||
func zipDir(srcDirPath string, recPath string, tw *zip.Writer) {
|
|
||||||
// Open source diretory
|
|
||||||
dir, err := os.Open(srcDirPath)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
defer dir.Close()
|
|
||||||
|
|
||||||
// Get file info slice
|
|
||||||
fis, err := dir.Readdir(0)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
for _, fi := range fis {
|
|
||||||
// Append path
|
|
||||||
curPath := srcDirPath + "/" + fi.Name()
|
|
||||||
// Check it is directory or file
|
|
||||||
if fi.IsDir() {
|
|
||||||
// Directory
|
|
||||||
// (Directory won't add unitl all subfiles are added)
|
|
||||||
// fmt.Printf("Adding path...%s\n", curPath)
|
|
||||||
zipDir(curPath, recPath+"/"+fi.Name(), tw)
|
|
||||||
} else {
|
|
||||||
// File
|
|
||||||
// fmt.Printf("Adding file...%s\n", curPath)
|
|
||||||
}
|
|
||||||
|
|
||||||
zipFile(curPath, recPath+"/"+fi.Name(), tw, fi)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Deal with files
|
|
||||||
func zipFile(srcFile string, recPath string, tw *zip.Writer, fi os.FileInfo) {
|
|
||||||
if fi.IsDir() {
|
|
||||||
// fmt.Println("??")
|
|
||||||
// Create tar header
|
|
||||||
/*
|
|
||||||
fh, err := zip.FileInfoHeader(fi)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
fh.Name = recPath // + "/"
|
|
||||||
err = tw.WriteHeader(hdr)
|
|
||||||
tw.Create(recPath)
|
|
||||||
*/
|
|
||||||
} else {
|
|
||||||
// File reader
|
|
||||||
fr, err := os.Open(srcFile)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
defer fr.Close()
|
|
||||||
|
|
||||||
// Write hander
|
|
||||||
w, err2 := tw.Create(recPath)
|
|
||||||
if err2 != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
// Write file data
|
|
||||||
_, err = io.Copy(w, fr)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ungzip and untar from source file to destination directory
|
|
||||||
// you need check file exist before you call this function
|
|
||||||
func Unzip(srcFilePath string, destDirPath string) (ok bool, msg string) {
|
|
||||||
ok = false
|
|
||||||
msg = ""
|
|
||||||
|
|
||||||
defer func() { //必须要先声明defer,否则不能捕获到panic异常
|
|
||||||
if err := recover(); err != nil {
|
|
||||||
msg = fmt.Sprintf("%v", err)
|
|
||||||
ok = false
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
os.Mkdir(destDirPath, os.ModePerm)
|
|
||||||
r, err := zip.OpenReader(srcFilePath);
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
defer r.Close();
|
|
||||||
for _, f := range r.File {
|
|
||||||
// fmt.Println("FileName : ", f.Name); // j/aaa.zip
|
|
||||||
rc, err := f.Open();
|
|
||||||
if err!=nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 把首文件夹去掉, 即j去掉, 分离出文件夹和文件名
|
|
||||||
paths := strings.Split(f.Name, "/")
|
|
||||||
prePath := ""
|
|
||||||
filename := ""
|
|
||||||
l := len(paths)
|
|
||||||
// fmt.Println(l)
|
|
||||||
if l > 1 {
|
|
||||||
// 去掉第1个文件夹
|
|
||||||
if l == 2 {
|
|
||||||
filename = paths[1]
|
|
||||||
} else {
|
|
||||||
filename = paths[l-1]
|
|
||||||
prePath = strings.Join(paths[1:l-1], "/")
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
filename = f.Name
|
|
||||||
}
|
|
||||||
// fmt.Println(prePath)
|
|
||||||
|
|
||||||
// 相对于目标文件件下的路径
|
|
||||||
destPath := destDirPath + "/" + filename
|
|
||||||
if prePath != "" {
|
|
||||||
os.MkdirAll(destDirPath + "/" + prePath, os.ModePerm)
|
|
||||||
destPath = destDirPath + "/" + prePath + "/" + filename
|
|
||||||
}
|
|
||||||
// Write data to file
|
|
||||||
// fmt.Println(destPath)
|
|
||||||
fw, _ := os.Create(destPath)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
_, err = io.Copy(fw, rc)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ok = true
|
|
||||||
return
|
|
||||||
}
|
|
||||||
@@ -4,7 +4,6 @@ import (
|
|||||||
"github.com/revel/revel"
|
"github.com/revel/revel"
|
||||||
"github.com/leanote/leanote/app/info"
|
"github.com/leanote/leanote/app/info"
|
||||||
"github.com/leanote/leanote/app/controllers"
|
"github.com/leanote/leanote/app/controllers"
|
||||||
// "github.com/leanote/leanote/app/controllers/api"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"reflect"
|
"reflect"
|
||||||
"strings"
|
"strings"
|
||||||
@@ -55,34 +54,15 @@ func nextKey(key string) string {
|
|||||||
return key[:fieldLen]
|
return key[:fieldLen]
|
||||||
}
|
}
|
||||||
var leanoteStructBinder = revel.Binder{
|
var leanoteStructBinder = revel.Binder{
|
||||||
// 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()
|
||||||
fieldValues := make(map[string]reflect.Value)
|
fieldValues := make(map[string]reflect.Value)
|
||||||
// fmt.Println(name)
|
for key, _ := range params.Values {
|
||||||
// fmt.Println(typ) // api.NoteFiles
|
|
||||||
// name = files[0], files[1], noteContent
|
|
||||||
// fmt.Println(params.Values)
|
|
||||||
/*
|
|
||||||
map[Title:[test1] METHOD:[POST] NotebookId:[54c4f51705fcd14031000002]
|
|
||||||
files[1][FileId]:[]
|
|
||||||
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[0][HasBody]:[true]]
|
|
||||||
*/
|
|
||||||
nameIsSlice := strings.Contains(name, "[")
|
|
||||||
// fmt.Println(params.Values["files[1]"])
|
|
||||||
// fmt.Println(params.Values["Title"])
|
|
||||||
for key, _ := range params.Values {// Title, Content, Files
|
|
||||||
// 这里, 如果没有点, 默认就是a.
|
// 这里, 如果没有点, 默认就是a.
|
||||||
// life
|
// life
|
||||||
// fmt.Println("key:" + key); // 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 !strings.HasPrefix(key, name + ".") {
|
||||||
suffix = key[len(name)+1:len(key)-1] // files[0][LocalFileId] 去掉 => LocalFileId
|
|
||||||
} else if !strings.HasPrefix(key, name + ".") {
|
|
||||||
noPrefix = true
|
noPrefix = true
|
||||||
suffix = key
|
suffix = key
|
||||||
// continue
|
// continue
|
||||||
@@ -91,18 +71,13 @@ files[0][HasBody]:[true]]
|
|||||||
// 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);
|
|
||||||
|
|
||||||
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);
|
|
||||||
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
|
|
||||||
// fmt.Println("xx: " + fieldName)
|
|
||||||
fieldValue := result.FieldByName(fieldName)
|
fieldValue := result.FieldByName(fieldName)
|
||||||
// fmt.Println(fieldValue)
|
|
||||||
if !fieldValue.IsValid() {
|
if !fieldValue.IsValid() {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@@ -112,16 +87,8 @@ files[0][HasBody]:[true]]
|
|||||||
var boundVal reflect.Value
|
var boundVal reflect.Value
|
||||||
// 没有name前缀
|
// 没有name前缀
|
||||||
if(noPrefix) {
|
if(noPrefix) {
|
||||||
// life
|
|
||||||
// fmt.Println("<<")
|
|
||||||
// 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(key[:len(name)+1+fieldLen]) // files[0][HasBody
|
|
||||||
if nameIsSlice {
|
|
||||||
fieldLen += 1
|
|
||||||
}
|
|
||||||
boundVal = revel.Bind(params, key[:len(name)+1+fieldLen], fieldValue.Type())
|
boundVal = revel.Bind(params, key[:len(name)+1+fieldLen], fieldValue.Type())
|
||||||
}
|
}
|
||||||
fieldValue.Set(boundVal)
|
fieldValue.Set(boundVal)
|
||||||
@@ -149,8 +116,5 @@ func init() {
|
|||||||
revel.TypeBinders[reflect.TypeOf(info.UserBlogComment{})] = leanoteStructBinder
|
revel.TypeBinders[reflect.TypeOf(info.UserBlogComment{})] = leanoteStructBinder
|
||||||
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(controllers.NoteOrContent{})] = leanoteStructBinder
|
revel.TypeBinders[reflect.TypeOf(controllers.NoteOrContent{})] = leanoteStructBinder
|
||||||
revel.TypeBinders[reflect.TypeOf(info.ApiNote{})] = leanoteStructBinder
|
|
||||||
revel.TypeBinders[reflect.TypeOf(info.NoteFile{})] = leanoteStructBinder
|
|
||||||
}
|
}
|
||||||
@@ -1,300 +0,0 @@
|
|||||||
package blog
|
|
||||||
|
|
||||||
import (
|
|
||||||
. "github.com/leanote/leanote/app/lea"
|
|
||||||
"github.com/revel/revel"
|
|
||||||
"html/template"
|
|
||||||
"io/ioutil"
|
|
||||||
// "os"
|
|
||||||
"fmt"
|
|
||||||
"bytes"
|
|
||||||
"io"
|
|
||||||
"net/http"
|
|
||||||
"regexp"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
//--------------------
|
|
||||||
// leanote 自定义主题
|
|
||||||
// 不使用revel的模板机制
|
|
||||||
// By life
|
|
||||||
//--------------------
|
|
||||||
|
|
||||||
var ts = []string{"header.html", "footer.html", "highlight.html", "comment.html", "view.html", "404.html"}
|
|
||||||
var selfTs = []string{"header.html", "footer.html", "index.html", "about_me.html"} // 用户自定义的文件列表
|
|
||||||
|
|
||||||
type BlogTpl struct {
|
|
||||||
Template *template.Template
|
|
||||||
PathContent map[string]string // path => content
|
|
||||||
}
|
|
||||||
|
|
||||||
func (this *BlogTpl) Content(name string) string {
|
|
||||||
return this.PathContent[name]
|
|
||||||
}
|
|
||||||
|
|
||||||
var BlogTplObject *BlogTpl
|
|
||||||
var CloneTemplate *template.Template
|
|
||||||
|
|
||||||
type RenderTemplateResult struct {
|
|
||||||
Template *template.Template
|
|
||||||
PathContent map[string]string
|
|
||||||
RenderArgs map[string]interface{}
|
|
||||||
|
|
||||||
IsPreview bool // 是否是预览
|
|
||||||
CurBlogTpl *BlogTpl
|
|
||||||
}
|
|
||||||
|
|
||||||
func parseTemplateError(err error) (templateName string, line int, description string) {
|
|
||||||
description = err.Error()
|
|
||||||
i := regexp.MustCompile(`:\d+:`).FindStringIndex(description)
|
|
||||||
if i != nil {
|
|
||||||
line, err = strconv.Atoi(description[i[0]+1 : i[1]-1])
|
|
||||||
if err != nil {
|
|
||||||
}
|
|
||||||
templateName = description[:i[0]]
|
|
||||||
if colon := strings.Index(templateName, ":"); colon != -1 {
|
|
||||||
templateName = templateName[colon+1:]
|
|
||||||
}
|
|
||||||
templateName = strings.TrimSpace(templateName)
|
|
||||||
description = description[i[1]+1:]
|
|
||||||
}
|
|
||||||
return templateName, line, description
|
|
||||||
}
|
|
||||||
func (r *RenderTemplateResult) render(req *revel.Request, resp *revel.Response, wr io.Writer) {
|
|
||||||
err := r.Template.Execute(wr, r.RenderArgs)
|
|
||||||
if err == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
var templateContent []string
|
|
||||||
templateName, line, description := parseTemplateError(err)
|
|
||||||
var content = ""
|
|
||||||
if templateName == "" {
|
|
||||||
templateName = r.Template.Name()
|
|
||||||
content = r.PathContent[templateName]
|
|
||||||
} else {
|
|
||||||
content = r.PathContent[templateName]
|
|
||||||
}
|
|
||||||
if content != "" {
|
|
||||||
templateContent = strings.Split(content, "\n")
|
|
||||||
}
|
|
||||||
|
|
||||||
compileError := &revel.Error{
|
|
||||||
Title: "Template Execution Error",
|
|
||||||
Path: templateName,
|
|
||||||
Description: description,
|
|
||||||
Line: line,
|
|
||||||
SourceLines: templateContent,
|
|
||||||
}
|
|
||||||
|
|
||||||
// 这里, 错误!!
|
|
||||||
// 这里应该导向到本主题的错误页面
|
|
||||||
resp.Status = 500
|
|
||||||
ErrorResult{r.RenderArgs, compileError, r.IsPreview, r.CurBlogTpl}.Apply(req, resp)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *RenderTemplateResult) Apply(req *revel.Request, resp *revel.Response) {
|
|
||||||
// Handle panics when rendering templates.
|
|
||||||
defer func() {
|
|
||||||
if err := recover(); err != nil {
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
chunked := revel.Config.BoolDefault("results.chunked", false)
|
|
||||||
|
|
||||||
// If it's a HEAD request, throw away the bytes.
|
|
||||||
out := io.Writer(resp.Out)
|
|
||||||
if req.Method == "HEAD" {
|
|
||||||
out = ioutil.Discard
|
|
||||||
}
|
|
||||||
|
|
||||||
// In a prod mode, write the status, render, and hope for the best.
|
|
||||||
// (In a dev mode, always render to a temporary buffer first to avoid having
|
|
||||||
// error pages distorted by HTML already written)
|
|
||||||
if chunked && !revel.DevMode {
|
|
||||||
resp.WriteHeader(http.StatusOK, "text/html; charset=utf-8")
|
|
||||||
r.render(req, resp, out) // 这里!!!
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Render the template into a temporary buffer, to see if there was an error
|
|
||||||
// rendering the template. If not, then copy it into the response buffer.
|
|
||||||
// Otherwise, template render errors may result in unpredictable HTML (and
|
|
||||||
// would carry a 200 status code)
|
|
||||||
var b bytes.Buffer
|
|
||||||
r.render(req, resp, &b)
|
|
||||||
if !chunked {
|
|
||||||
resp.Out.Header().Set("Content-Length", strconv.Itoa(b.Len()))
|
|
||||||
}
|
|
||||||
resp.WriteHeader(http.StatusOK, "text/html; charset=utf-8")
|
|
||||||
b.WriteTo(out)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 博客模板
|
|
||||||
func Init() {
|
|
||||||
BlogTplObject = &BlogTpl{PathContent: map[string]string{}}
|
|
||||||
BlogTplObject.Template = template.New("blog").Funcs(revel.TemplateFuncs)
|
|
||||||
for _, path := range ts {
|
|
||||||
fileBytes, _ := ioutil.ReadFile(revel.ViewsPath + "/Blog/" + path)
|
|
||||||
fileStr := string(fileBytes)
|
|
||||||
path := "blog/" + path
|
|
||||||
// path := path
|
|
||||||
BlogTplObject.PathContent[path] = fileStr
|
|
||||||
BlogTplObject.Template.New(path).Parse(fileStr) // 以blog为根
|
|
||||||
}
|
|
||||||
// 复制一份
|
|
||||||
CloneTemplate, _ = BlogTplObject.Template.Clone()
|
|
||||||
}
|
|
||||||
|
|
||||||
// name = index.html, search.html, cate.html, page.html
|
|
||||||
// basePath 表未用户主题的基路径, 如/xxx/public/upload/32323232/themes/theme1, 如果没有, 则表示用自带的
|
|
||||||
// isPreview 如果是, 错误提示则显示系统的 500 错误详情信息, 供debug
|
|
||||||
//
|
|
||||||
func RenderTemplate(name string, args map[string]interface{}, basePath string, isPreview bool) revel.Result {
|
|
||||||
var r *RenderTemplateResult
|
|
||||||
// 传来的主题路径为空, 则用系统的
|
|
||||||
// 都不会为空的
|
|
||||||
if basePath == "" {
|
|
||||||
path := "blog/" + name
|
|
||||||
// path := name
|
|
||||||
t := BlogTplObject.Template.Lookup(path)
|
|
||||||
r = &RenderTemplateResult{
|
|
||||||
Template: t,
|
|
||||||
PathContent: BlogTplObject.PathContent, // 为了显示错误
|
|
||||||
RenderArgs: args, // 把args给它
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// 复制一份
|
|
||||||
newBlogTplObject := &BlogTpl{}
|
|
||||||
var err error
|
|
||||||
newBlogTplObject.Template, err = CloneTemplate.Clone() // 复制一份, 为防止多用户出现问题, 因为newBlogTplObject是全局的
|
|
||||||
if err != nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
newBlogTplObject.PathContent = map[string]string{}
|
|
||||||
for k, v := range BlogTplObject.PathContent {
|
|
||||||
newBlogTplObject.PathContent[k] = v
|
|
||||||
}
|
|
||||||
|
|
||||||
// 将该basePath下的所有文件提出
|
|
||||||
files := ListDir(basePath)
|
|
||||||
for _, t := range files {
|
|
||||||
if !strings.Contains(t, ".html") {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
fileBytes, err := ioutil.ReadFile(basePath + "/" + t)
|
|
||||||
if err != nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
fileStr := string(fileBytes)
|
|
||||||
newBlogTplObject.PathContent[t] = fileStr
|
|
||||||
newBlogTplObject.Template.New(t).Parse(fileStr)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 如果本主题下没有, 则用系统的
|
|
||||||
t := newBlogTplObject.Template.Lookup(name)
|
|
||||||
|
|
||||||
if t == nil {
|
|
||||||
path := "blog/" + name
|
|
||||||
t = BlogTplObject.Template.Lookup(path)
|
|
||||||
}
|
|
||||||
r = &RenderTemplateResult{
|
|
||||||
Template: t,
|
|
||||||
PathContent: newBlogTplObject.PathContent, // 为了显示错误
|
|
||||||
RenderArgs: args,
|
|
||||||
CurBlogTpl: newBlogTplObject,
|
|
||||||
IsPreview: isPreview,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return r
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////
|
|
||||||
//
|
|
||||||
|
|
||||||
|
|
||||||
type ErrorResult struct {
|
|
||||||
RenderArgs map[string]interface{}
|
|
||||||
Error error
|
|
||||||
IsPreview bool
|
|
||||||
CurBlogTpl *BlogTpl
|
|
||||||
}
|
|
||||||
|
|
||||||
// 错误显示出
|
|
||||||
func (r ErrorResult) Apply(req *revel.Request, resp *revel.Response) {
|
|
||||||
format := req.Format
|
|
||||||
status := resp.Status
|
|
||||||
if status == 0 {
|
|
||||||
status = http.StatusInternalServerError
|
|
||||||
}
|
|
||||||
|
|
||||||
contentType := revel.ContentTypeByFilename("xxx." + format)
|
|
||||||
if contentType == revel.DefaultFileContentType {
|
|
||||||
contentType = "text/plain"
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the error template.
|
|
||||||
var err error
|
|
||||||
templatePath := fmt.Sprintf("errors/%d.%s", status, format)
|
|
||||||
err = nil
|
|
||||||
// tmpl, err := revel.MainTemplateLoader.Template("index.html") // 这里找到错误页面主题
|
|
||||||
|
|
||||||
// This func shows a plaintext error message, in case the template rendering
|
|
||||||
// doesn't work.
|
|
||||||
showPlaintext := func(err error) {
|
|
||||||
revel.PlaintextErrorResult{fmt.Errorf("Server Error:\n%s\n\n"+
|
|
||||||
"Additionally, an error occurred when rendering the error page:\n%s",
|
|
||||||
r.Error, err)}.Apply(req, resp)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 根据是否是preview来得到404模板
|
|
||||||
// 是, 则显示系统的错误信息, blog-500.html
|
|
||||||
var tmpl *template.Template
|
|
||||||
if r.IsPreview {
|
|
||||||
tmpl = r.CurBlogTpl.Template.Lookup("blog/404.html")
|
|
||||||
} else {
|
|
||||||
tmpl = r.CurBlogTpl.Template.Lookup("404.html")
|
|
||||||
}
|
|
||||||
if tmpl == nil {
|
|
||||||
if err == nil {
|
|
||||||
err = fmt.Errorf("Couldn't find template %s", templatePath)
|
|
||||||
}
|
|
||||||
showPlaintext(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// If it's not a revel error, wrap it in one.
|
|
||||||
var revelError *revel.Error
|
|
||||||
switch e := r.Error.(type) {
|
|
||||||
case *revel.Error:
|
|
||||||
revelError = e
|
|
||||||
case error:
|
|
||||||
revelError = &revel.Error{
|
|
||||||
Title: "Server Error",
|
|
||||||
Description: e.Error(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if revelError == nil {
|
|
||||||
panic("no error provided")
|
|
||||||
}
|
|
||||||
|
|
||||||
if r.RenderArgs == nil {
|
|
||||||
r.RenderArgs = make(map[string]interface{})
|
|
||||||
}
|
|
||||||
r.RenderArgs["Error"] = revelError
|
|
||||||
r.RenderArgs["Router"] = revel.MainRouter
|
|
||||||
|
|
||||||
// 不是preview就不要显示错误了
|
|
||||||
if r.IsPreview {
|
|
||||||
var b bytes.Buffer
|
|
||||||
out := io.Writer(resp.Out)
|
|
||||||
// out = ioutil.Discard
|
|
||||||
err = tmpl.Execute(&b, r.RenderArgs)
|
|
||||||
resp.WriteHeader(http.StatusOK, "text/html; charset=utf-8")
|
|
||||||
b.WriteTo(out)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
// contains two cryptographic functions for both storing and comparing passwords.
|
|
||||||
package lea
|
|
||||||
|
|
||||||
import (
|
|
||||||
"golang.org/x/crypto/bcrypt"
|
|
||||||
)
|
|
||||||
|
|
||||||
// GenerateHash generates bcrypt hash from plaintext password
|
|
||||||
func GenerateHash(password string) ([]byte, error) {
|
|
||||||
hex := []byte(password)
|
|
||||||
hashedPassword, err := bcrypt.GenerateFromPassword(hex, 10)
|
|
||||||
if err != nil {
|
|
||||||
return hashedPassword, err
|
|
||||||
}
|
|
||||||
return hashedPassword, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// CompareHash compares bcrypt password with a plaintext one. Returns true if passwords match
|
|
||||||
// and false if they do not.
|
|
||||||
func CompareHash(digest []byte, password string) bool {
|
|
||||||
hex := []byte(password)
|
|
||||||
if err := bcrypt.CompareHashAndPassword(digest, hex); err == nil {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
@@ -3,7 +3,6 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"os"
|
"os"
|
||||||
// "path/filepath"
|
// "path/filepath"
|
||||||
"net"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
. "github.com/leanote/leanote/app/lea"
|
. "github.com/leanote/leanote/app/lea"
|
||||||
@@ -90,13 +89,4 @@ func trimQueryParams(url string) string {
|
|||||||
url = Substr(url, 0, pos);
|
url = Substr(url, 0, pos);
|
||||||
}
|
}
|
||||||
return url;
|
return url;
|
||||||
}
|
|
||||||
|
|
||||||
// 通过domain得到ip
|
|
||||||
func GetIpFromDomain(domain string) string {
|
|
||||||
ip, _ := net.LookupIP(domain)
|
|
||||||
if ip != nil && len(ip) > 0 {
|
|
||||||
return ip[0].String()
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
}
|
||||||
@@ -44,12 +44,8 @@ func RouterFilter(c *revel.Controller, fc []revel.Filter) {
|
|||||||
if route.ControllerName != "Static" {
|
if route.ControllerName != "Static" {
|
||||||
// api设置
|
// api设置
|
||||||
// leanote.com/api/user/get => ApiUser::Get
|
// leanote.com/api/user/get => ApiUser::Get
|
||||||
//* /api/login ApiAuth.Login, 这里的设置, 其实已经转成了ApiAuth了
|
if strings.HasPrefix(path, "/api/") || strings.HasPrefix(path, "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") {
|
|
||||||
// member设置
|
|
||||||
route.ControllerName = "Member" + route.ControllerName
|
|
||||||
}
|
}
|
||||||
// end
|
// end
|
||||||
}
|
}
|
||||||
|
|||||||
+22
-34
@@ -6,9 +6,7 @@ import (
|
|||||||
"os/exec"
|
"os/exec"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"strings"
|
"strings"
|
||||||
// "time"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
用golang exec 总是说找不到uglifyjs命令, 需要全部路径
|
用golang exec 总是说找不到uglifyjs命令, 需要全部路径
|
||||||
而且node, npm要在/usr/bin下, 已建ln
|
而且node, npm要在/usr/bin下, 已建ln
|
||||||
@@ -54,7 +52,7 @@ 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);
|
|
||||||
cmdError(err)
|
cmdError(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -82,17 +80,14 @@ func combineJs() {
|
|||||||
// 改note-dev->note
|
// 改note-dev->note
|
||||||
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{"note.js": "note-min.js",
|
||||||
"tinymce.js": "tinymce.min.js",
|
|
||||||
"jquery.ztree.all-3.5.js": "jquery.ztree.all-3.5-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",
|
"main.js": "main-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",
|
||||||
@@ -107,13 +102,6 @@ func dev() {
|
|||||||
for key, value := range m {
|
for key, value := range m {
|
||||||
content = strings.Replace(content, key, value, -1)
|
content = strings.Replace(content, key, value, -1)
|
||||||
}
|
}
|
||||||
|
|
||||||
// var time = time.Now().Unix() % 1000
|
|
||||||
|
|
||||||
// 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, "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)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -121,31 +109,29 @@ func dev() {
|
|||||||
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("/Users/life/Documents/eclipse-workspace/go/leanote_release/tinymce-master/node_modules/jake/bin/cli.js", "minify")
|
||||||
cmd.Dir = base + "/tinymce_4.1.9"
|
cmd.Dir = "/Users/life/Documents/eclipse-workspace/go/leanote_release/tinymce-master"
|
||||||
|
c, err := cmd.CombinedOutput()
|
||||||
fmt.Println("正在build tinymce");
|
|
||||||
|
|
||||||
// 必须要先删除
|
|
||||||
cmd2 := exec.Command("/bin/sh", "-c", "rm " + cmd.Dir + "/js/tinymce/tinymce.dev.js")
|
|
||||||
cmd2.CombinedOutput()
|
|
||||||
cmd2 = exec.Command("/bin/sh", "-c", "rm " + cmd.Dir + "/js/tinymce/tinymce.jquery.dev.js")
|
|
||||||
c, _ := cmd2.CombinedOutput()
|
|
||||||
fmt.Println(string(c))
|
|
||||||
|
|
||||||
c, _ = cmd.CombinedOutput()
|
|
||||||
fmt.Println(string(c))
|
fmt.Println(string(c))
|
||||||
|
cmdError(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
// 压缩tinymce
|
|
||||||
// tinymce()
|
|
||||||
|
|
||||||
dev();
|
dev();
|
||||||
|
|
||||||
// 其它零散的需要压缩的js
|
// 其它零散的需要压缩的js
|
||||||
otherJss := []string{"js/main", "js/app/page", "js/contextmenu/jquery.contextmenu",
|
otherJss := []string{"tinymce/tinymce", "js/main", "js/app/page", "js/contextmenu/jquery.contextmenu",
|
||||||
"js/jquery.ztree.all-3.5",
|
"mdeditor/editor/scrollLink",
|
||||||
|
"mdeditor/editor/editor",
|
||||||
|
"mdeditor/editor/jquery.waitforimages",
|
||||||
|
"mdeditor/editor/pagedown/local/Markdown.local.zh",
|
||||||
|
"mdeditor/editor/pagedown/local/Markdown.local.en",
|
||||||
|
"mdeditor/editor/pagedown/Markdown.Editor",
|
||||||
|
"mdeditor/editor/pagedown/Markdown.Sanitizer",
|
||||||
|
"mdeditor/editor/pagedown/Markdown.Converter",
|
||||||
|
"mdeditor/editor/Markdown.Extra",
|
||||||
|
"mdeditor/editor/underscore",
|
||||||
|
"mdeditor/editor/mathJax",
|
||||||
"js/jQuery-slimScroll-1.3.0/jquery.slimscroll",
|
"js/jQuery-slimScroll-1.3.0/jquery.slimscroll",
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -155,5 +141,7 @@ func main() {
|
|||||||
|
|
||||||
// 先压缩后合并
|
// 先压缩后合并
|
||||||
combineJs()
|
combineJs()
|
||||||
|
|
||||||
|
// 压缩tinymce
|
||||||
|
tinymce()
|
||||||
}
|
}
|
||||||
@@ -1,47 +1,30 @@
|
|||||||
package service
|
package service
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"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/revel/revel"
|
"github.com/revel/revel"
|
||||||
|
"github.com/leanote/leanote/app/info"
|
||||||
|
"github.com/leanote/leanote/app/db"
|
||||||
"gopkg.in/mgo.v2/bson"
|
"gopkg.in/mgo.v2/bson"
|
||||||
|
"time"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type AttachService struct {
|
type AttachService struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// add attach
|
// add attach
|
||||||
// api调用时, 添加attach之前是没有note的
|
func (this *AttachService) AddAttach(attach info.Attach) bool {
|
||||||
// fromApi表示是api添加的, updateNote传过来的, 此时不要incNote's usn, 因为updateNote会inc的
|
|
||||||
func (this *AttachService) AddAttach(attach info.Attach, fromApi bool) (ok bool, msg string) {
|
|
||||||
attach.CreatedTime = time.Now()
|
attach.CreatedTime = time.Now()
|
||||||
ok = db.Insert(db.Attachs, attach)
|
ok := db.Insert(db.Attachs, attach)
|
||||||
|
|
||||||
note := noteService.GetNoteById(attach.NoteId.Hex())
|
|
||||||
|
|
||||||
// api调用时, 添加attach之前是没有note的
|
|
||||||
var userId string
|
|
||||||
if note.NoteId != "" {
|
|
||||||
userId = note.UserId.Hex()
|
|
||||||
} else {
|
|
||||||
userId = attach.UploadUserId.Hex()
|
|
||||||
}
|
|
||||||
|
|
||||||
if ok {
|
if ok {
|
||||||
// 更新笔记的attachs num
|
// 更新笔记的attachs num
|
||||||
this.updateNoteAttachNum(attach.NoteId, 1)
|
this.updateNoteAttachNum(attach.NoteId, 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !fromApi {
|
return ok
|
||||||
// 增长note's usn
|
|
||||||
noteService.IncrNoteUsn(attach.NoteId.Hex(), userId)
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 更新笔记的附件个数
|
// 更新笔记的附件个数
|
||||||
@@ -67,32 +50,17 @@ func (this *AttachService) ListAttachs(noteId, userId string) []info.Attach {
|
|||||||
if !shareService.HasUpdateNotePerm(noteId, userId) {
|
if !shareService.HasUpdateNotePerm(noteId, userId) {
|
||||||
return attachs
|
return attachs
|
||||||
}
|
}
|
||||||
|
|
||||||
db.ListByQ(db.Attachs, bson.M{"NoteId": bson.ObjectIdHex(noteId)}, &attachs)
|
db.ListByQ(db.Attachs, bson.M{"NoteId": bson.ObjectIdHex(noteId)}, &attachs)
|
||||||
|
|
||||||
return attachs
|
return attachs
|
||||||
}
|
}
|
||||||
|
|
||||||
// api调用, 通过noteIds得到note's attachs, 通过noteId归类返回
|
|
||||||
func (this *AttachService) getAttachsByNoteIds(noteIds []bson.ObjectId) map[string][]info.Attach {
|
|
||||||
attachs := []info.Attach{}
|
|
||||||
db.ListByQ(db.Attachs, bson.M{"NoteId": bson.M{"$in": noteIds}}, &attachs)
|
|
||||||
noteAttchs := make(map[string][]info.Attach)
|
|
||||||
for _, attach := range attachs {
|
|
||||||
noteId := attach.NoteId.Hex()
|
|
||||||
if itAttachs, ok := noteAttchs[noteId]; ok {
|
|
||||||
noteAttchs[noteId] = append(itAttachs, attach)
|
|
||||||
} else {
|
|
||||||
noteAttchs[noteId] = []info.Attach{attach}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return noteAttchs
|
|
||||||
}
|
|
||||||
|
|
||||||
func (this *AttachService) UpdateImageTitle(userId, fileId, title string) bool {
|
func (this *AttachService) UpdateImageTitle(userId, fileId, title string) bool {
|
||||||
return db.UpdateByIdAndUserIdField(db.Files, fileId, userId, "Title", title)
|
return db.UpdateByIdAndUserIdField(db.Files, fileId, userId, "Title", title)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Delete note to delete attas firstly
|
// Delete note to delete attas firstly
|
||||||
func (this *AttachService) DeleteAllAttachs(noteId, userId string) bool {
|
func (this *AttachService) DeleteAllAttachs(noteId, userId string) bool {
|
||||||
note := noteService.GetNoteById(noteId)
|
note := noteService.GetNoteById(noteId)
|
||||||
@@ -105,7 +73,7 @@ func (this *AttachService) DeleteAllAttachs(noteId, userId string) bool {
|
|||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -125,11 +93,7 @@ func (this *AttachService) DeleteAttach(attachId, userId string) (bool, string)
|
|||||||
attach.Path = strings.TrimLeft(attach.Path, "/")
|
attach.Path = strings.TrimLeft(attach.Path, "/")
|
||||||
err := os.Remove(revel.BasePath + "/" + attach.Path)
|
err := os.Remove(revel.BasePath + "/" + attach.Path)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
// userService.UpdateAttachSize(note.UserId.Hex(), -attach.Size)
|
return true, "delete file error"
|
||||||
// 修改note Usn
|
|
||||||
noteService.IncrNoteUsn(attach.NoteId.Hex(), userId)
|
|
||||||
|
|
||||||
return true, "delete file success"
|
|
||||||
}
|
}
|
||||||
return false, "delete file error"
|
return false, "delete file error"
|
||||||
}
|
}
|
||||||
@@ -143,37 +107,37 @@ func (this *AttachService) DeleteAttach(attachId, userId string) (bool, string)
|
|||||||
// userId是否具有attach的访问权限
|
// userId是否具有attach的访问权限
|
||||||
func (this *AttachService) GetAttach(attachId, userId string) (attach info.Attach) {
|
func (this *AttachService) GetAttach(attachId, userId string) (attach info.Attach) {
|
||||||
if attachId == "" {
|
if attachId == "" {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
attach = info.Attach{}
|
attach = info.Attach{}
|
||||||
db.Get(db.Attachs, attachId, &attach)
|
db.Get(db.Attachs, attachId, &attach)
|
||||||
path := attach.Path
|
path := attach.Path
|
||||||
if path == "" {
|
if path == "" {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
note := noteService.GetNoteById(attach.NoteId.Hex())
|
note := noteService.GetNoteById(attach.NoteId.Hex())
|
||||||
|
|
||||||
// 判断权限
|
// 判断权限
|
||||||
|
|
||||||
// 笔记是否是公开的
|
// 笔记是否是公开的
|
||||||
if note.IsBlog {
|
if note.IsBlog {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// 笔记是否是我的
|
// 笔记是否是我的
|
||||||
if note.UserId.Hex() == userId {
|
if note.UserId.Hex() == userId {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// 我是否有权限查看或协作
|
// 我是否有权限查看或协作
|
||||||
if shareService.HasReadNotePerm(attach.NoteId.Hex(), userId) {
|
if shareService.HasReadNotePerm(attach.NoteId.Hex(), userId) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
attach = info.Attach{}
|
attach = info.Attach{}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// 复制笔记时需要复制附件
|
// 复制笔记时需要复制附件
|
||||||
@@ -181,58 +145,31 @@ func (this *AttachService) GetAttach(attachId, userId string) (attach info.Attac
|
|||||||
func (this *AttachService) CopyAttachs(noteId, toNoteId, toUserId string) bool {
|
func (this *AttachService) CopyAttachs(noteId, toNoteId, toUserId string) bool {
|
||||||
attachs := []info.Attach{}
|
attachs := []info.Attach{}
|
||||||
db.ListByQ(db.Attachs, bson.M{"NoteId": bson.ObjectIdHex(noteId)}, &attachs)
|
db.ListByQ(db.Attachs, bson.M{"NoteId": bson.ObjectIdHex(noteId)}, &attachs)
|
||||||
|
|
||||||
// 复制之
|
// 复制之
|
||||||
toNoteIdO := bson.ObjectIdHex(toNoteId)
|
toNoteIdO := bson.ObjectIdHex(toNoteId)
|
||||||
for _, attach := range attachs {
|
for _, attach := range attachs {
|
||||||
attach.AttachId = ""
|
attach.AttachId = ""
|
||||||
attach.NoteId = toNoteIdO
|
attach.NoteId = toNoteIdO
|
||||||
|
|
||||||
// 文件复制一份
|
// 文件复制一份
|
||||||
_, ext := SplitFilename(attach.Name)
|
_, ext := SplitFilename(attach.Name)
|
||||||
newFilename := NewGuid() + ext
|
newFilename := NewGuid() + ext
|
||||||
dir := "files/" + toUserId + "/attachs"
|
dir := "files/" + toUserId + "/attachs"
|
||||||
filePath := dir + "/" + newFilename
|
filePath := dir + "/" + newFilename
|
||||||
err := os.MkdirAll(revel.BasePath+"/"+dir, 0755)
|
err := os.MkdirAll(revel.BasePath + "/" + dir, 0755)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
_, err = CopyFile(revel.BasePath+"/"+attach.Path, revel.BasePath+"/"+filePath)
|
_, err = CopyFile(revel.BasePath + "/" + attach.Path, revel.BasePath + "/" + filePath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
attach.Name = newFilename
|
attach.Name = newFilename
|
||||||
attach.Path = filePath
|
attach.Path = filePath
|
||||||
|
|
||||||
this.AddAttach(attach, false)
|
this.AddAttach(attach)
|
||||||
}
|
}
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// 只留下files的数据, 其它的都删除
|
|
||||||
func (this *AttachService) UpdateOrDeleteAttachApi(noteId, userId string, files []info.NoteFile) bool {
|
|
||||||
// 现在数据库内的
|
|
||||||
attachs := this.ListAttachs(noteId, userId)
|
|
||||||
|
|
||||||
nowAttachs := map[string]bool{}
|
|
||||||
if files != nil {
|
|
||||||
for _, file := range files {
|
|
||||||
if file.IsAttach && file.FileId != "" {
|
|
||||||
nowAttachs[file.FileId] = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, attach := range attachs {
|
|
||||||
fileId := attach.AttachId.Hex()
|
|
||||||
if !nowAttachs[fileId] {
|
|
||||||
// 需要删除的
|
|
||||||
// TODO 权限验证去掉
|
|
||||||
this.DeleteAttach(fileId, userId)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
|
|
||||||
}
|
|
||||||
+38
-58
@@ -2,31 +2,23 @@ package service
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"gopkg.in/mgo.v2/bson"
|
"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/revel/revel"
|
// "github.com/revel/revel"
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
. "github.com/leanote/leanote/app/lea"
|
. "github.com/leanote/leanote/app/lea"
|
||||||
|
"fmt"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// 登录与权限 Login & Register
|
// 登录与权限
|
||||||
|
|
||||||
type AuthService struct {
|
type AuthService struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// 使用bcrypt认证或者Md5认证
|
// pwd已md5了
|
||||||
// Use bcrypt (Md5 depreciated)
|
func (this *AuthService) Login(emailOrUsername, pwd string) info.User {
|
||||||
func (this *AuthService) Login(emailOrUsername, pwd string) (info.User, error) {
|
userInfo := userService.LoginGetUserInfo(emailOrUsername, Md5(pwd))
|
||||||
emailOrUsername = strings.Trim(emailOrUsername, " ")
|
return userInfo
|
||||||
// pwd = strings.Trim(pwd, " ")
|
|
||||||
userInfo := userService.GetUserInfoByName(emailOrUsername)
|
|
||||||
if userInfo.UserId == "" || !ComparePwd(pwd, userInfo.Pwd) {
|
|
||||||
return userInfo, errors.New("wrong username or password")
|
|
||||||
}
|
|
||||||
return userInfo, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 注册
|
// 注册
|
||||||
@@ -40,79 +32,67 @@ func (this *AuthService) Login(emailOrUsername, pwd string) (info.User, error) {
|
|||||||
// 1. 添加用户
|
// 1. 添加用户
|
||||||
// 2. 将leanote共享给我
|
// 2. 将leanote共享给我
|
||||||
// [ok]
|
// [ok]
|
||||||
func (this *AuthService) Register(email, pwd, fromUserId string) (bool, string) {
|
func (this *AuthService) Register(email, pwd string) (bool, string) {
|
||||||
// 用户是否已存在
|
// 用户是否已存在
|
||||||
if userService.IsExistsUser(email) {
|
if userService.IsExistsUser(email) {
|
||||||
return false, "userHasBeenRegistered-" + email
|
return false, email + " 已被注册"
|
||||||
}
|
|
||||||
passwd := GenPwd(pwd)
|
|
||||||
if passwd == "" {
|
|
||||||
return false, "GenerateHash error"
|
|
||||||
}
|
|
||||||
user := info.User{UserId: bson.NewObjectId(), Email: email, Username: email, Pwd: passwd}
|
|
||||||
if fromUserId != "" && IsObjectId(fromUserId) {
|
|
||||||
user.FromUserId = bson.ObjectIdHex(fromUserId)
|
|
||||||
}
|
}
|
||||||
|
user := info.User{UserId: bson.NewObjectId(), Email: email, Username: email, Pwd: Md5(pwd)}
|
||||||
return this.register(user)
|
return this.register(user)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (this *AuthService) register(user info.User) (bool, string) {
|
func (this *AuthService) register(user info.User) (bool, string) {
|
||||||
if userService.AddUser(user) {
|
if userService.AddUser(user) {
|
||||||
// 添加笔记本, 生活, 学习, 工作
|
// 添加笔记本, 生活, 学习, 工作
|
||||||
userId := user.UserId.Hex()
|
|
||||||
notebook := info.Notebook{
|
notebook := info.Notebook{
|
||||||
Seq: -1,
|
Seq: -1,
|
||||||
UserId: user.UserId}
|
UserId: user.UserId}
|
||||||
title2Id := map[string]bson.ObjectId{"life": bson.NewObjectId(), "study": bson.NewObjectId(), "work": bson.NewObjectId()}
|
title2Id := map[string]bson.ObjectId{"life": bson.NewObjectId(), "study": bson.NewObjectId(), "work": bson.NewObjectId()}
|
||||||
for title, objectId := range title2Id {
|
for title, objectId := range title2Id {
|
||||||
notebook.Title = title
|
notebook.Title = title
|
||||||
notebook.NotebookId = objectId
|
notebook.NotebookId = objectId
|
||||||
notebook.UserId = user.UserId
|
notebook.UserId = user.UserId
|
||||||
notebookService.AddNotebook(notebook)
|
notebookService.AddNotebook(notebook);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
email := user.Email
|
||||||
|
|
||||||
// 添加leanote -> 该用户的共享
|
// 添加leanote -> 该用户的共享
|
||||||
registerSharedUserId := configService.GetGlobalStringConfig("registerSharedUserId")
|
registerSharedUserId := configService.GetGlobalStringConfig("registerSharedUserId")
|
||||||
if registerSharedUserId != "" {
|
if(registerSharedUserId != "") {
|
||||||
registerSharedNotebooks := configService.GetGlobalArrMapConfig("registerSharedNotebooks")
|
registerSharedNotebooks := configService.GetGlobalArrMapConfig("registerSharedNotebooks")
|
||||||
registerSharedNotes := configService.GetGlobalArrMapConfig("registerSharedNotes")
|
registerSharedNotes := configService.GetGlobalArrMapConfig("registerSharedNotes")
|
||||||
registerCopyNoteIds := configService.GetGlobalArrayConfig("registerCopyNoteIds")
|
registerCopyNoteIds := configService.GetGlobalArrayConfig("registerCopyNoteIds")
|
||||||
|
|
||||||
// 添加共享笔记本
|
// 添加共享笔记本
|
||||||
for _, notebook := range registerSharedNotebooks {
|
for _, notebook := range registerSharedNotebooks {
|
||||||
perm, _ := strconv.Atoi(notebook["perm"])
|
perm, _ := strconv.Atoi(notebook["perm"])
|
||||||
shareService.AddShareNotebookToUserId(notebook["notebookId"], perm, registerSharedUserId, userId)
|
shareService.AddShareNotebook(notebook["notebookId"], perm, registerSharedUserId, email);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 添加共享笔记
|
// 添加共享笔记
|
||||||
for _, note := range registerSharedNotes {
|
for _, note := range registerSharedNotes {
|
||||||
perm, _ := strconv.Atoi(note["perm"])
|
perm, _ := strconv.Atoi(note["perm"])
|
||||||
shareService.AddShareNoteToUserId(note["noteId"], perm, registerSharedUserId, userId)
|
shareService.AddShareNote(note["noteId"], perm, registerSharedUserId, email);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 复制笔记
|
// 复制笔记
|
||||||
for _, noteId := range registerCopyNoteIds {
|
for _, noteId := range registerCopyNoteIds {
|
||||||
note := noteService.CopySharedNote(noteId, title2Id["life"].Hex(), registerSharedUserId, user.UserId.Hex())
|
note := noteService.CopySharedNote(noteId, title2Id["life"].Hex(), registerSharedUserId, user.UserId.Hex());
|
||||||
// Log(noteId)
|
noteUpdate := bson.M{"IsBlog": true}
|
||||||
// Log("Copy")
|
noteService.UpdateNote(user.UserId.Hex(), user.UserId.Hex(), note.NoteId.Hex(), noteUpdate)
|
||||||
// LogJ(note)
|
|
||||||
noteUpdate := bson.M{"IsBlog": false} // 不要是博客
|
|
||||||
noteService.UpdateNote(user.UserId.Hex(), note.NoteId.Hex(), noteUpdate, -1)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------
|
//---------------
|
||||||
// 添加一条userBlog
|
// 添加一条userBlog
|
||||||
blogService.UpdateUserBlog(info.UserBlog{UserId: user.UserId,
|
blogService.UpdateUserBlog(info.UserBlog{UserId: user.UserId,
|
||||||
Title: user.Username + " 's Blog",
|
Title: user.Username + " 's Blog",
|
||||||
SubTitle: "Love Leanote!",
|
SubTitle: "love leanote!",
|
||||||
AboutMe: "Hello, I am (^_^)",
|
AboutMe: "Hello, I am (^_^)",
|
||||||
CanComment: true,
|
})
|
||||||
})
|
|
||||||
// 添加一个单页面
|
|
||||||
blogService.AddOrUpdateSingle(user.UserId.Hex(), "", "About Me", "Hello, I am (^_^)")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true, ""
|
return true, ""
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -123,7 +103,7 @@ func (this *AuthService) register(user info.User) (bool, string) {
|
|||||||
func (this *AuthService) getUsername(thirdType, thirdUsername string) (username string) {
|
func (this *AuthService) getUsername(thirdType, thirdUsername string) (username string) {
|
||||||
username = thirdType + "-" + thirdUsername
|
username = thirdType + "-" + thirdUsername
|
||||||
i := 1
|
i := 1
|
||||||
for {
|
for ;; {
|
||||||
if !userService.IsExistsUserByUsername(username) {
|
if !userService.IsExistsUserByUsername(username) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -139,11 +119,11 @@ func (this *AuthService) ThirdRegister(thirdType, thirdUserId, thirdUsername str
|
|||||||
}
|
}
|
||||||
|
|
||||||
username := this.getUsername(thirdType, thirdUsername)
|
username := this.getUsername(thirdType, thirdUsername)
|
||||||
userInfo = info.User{UserId: bson.NewObjectId(),
|
userInfo = info.User{UserId: bson.NewObjectId(),
|
||||||
Username: username,
|
Username: username,
|
||||||
ThirdUserId: thirdUserId,
|
ThirdUserId: thirdUserId,
|
||||||
ThirdUsername: thirdUsername,
|
ThirdUsername: thirdUsername,
|
||||||
}
|
}
|
||||||
_, _ = this.register(userInfo)
|
_, _ = this.register(userInfo)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
+158
-817
File diff suppressed because it is too large.
Load diff
@@ -17,9 +17,6 @@ import (
|
|||||||
// 配置服务
|
// 配置服务
|
||||||
// 只是全局的, 用户的配置没有
|
// 只是全局的, 用户的配置没有
|
||||||
type ConfigService struct {
|
type ConfigService struct {
|
||||||
adminUserId string
|
|
||||||
siteUrl string
|
|
||||||
adminUsername string
|
|
||||||
// 全局的
|
// 全局的
|
||||||
GlobalAllConfigs map[string]interface{}
|
GlobalAllConfigs map[string]interface{}
|
||||||
GlobalStringConfigs map[string]string
|
GlobalStringConfigs map[string]string
|
||||||
@@ -27,6 +24,9 @@ type ConfigService struct {
|
|||||||
GlobalMapConfigs map[string]map[string]string
|
GlobalMapConfigs map[string]map[string]string
|
||||||
GlobalArrMapConfigs map[string][]map[string]string
|
GlobalArrMapConfigs map[string][]map[string]string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var adminUserId = ""
|
||||||
|
|
||||||
// appStart时 将全局的配置从数据库中得到作为全局
|
// appStart时 将全局的配置从数据库中得到作为全局
|
||||||
func (this *ConfigService) InitGlobalConfigs() bool {
|
func (this *ConfigService) InitGlobalConfigs() bool {
|
||||||
this.GlobalAllConfigs = map[string]interface{}{}
|
this.GlobalAllConfigs = map[string]interface{}{}
|
||||||
@@ -35,17 +35,16 @@ func (this *ConfigService) InitGlobalConfigs() bool {
|
|||||||
this.GlobalMapConfigs = map[string]map[string]string{}
|
this.GlobalMapConfigs = map[string]map[string]string{}
|
||||||
this.GlobalArrMapConfigs = map[string][]map[string]string{}
|
this.GlobalArrMapConfigs = map[string][]map[string]string{}
|
||||||
|
|
||||||
this.adminUsername, _ = revel.Config.String("adminUsername")
|
adminUsername, _ := revel.Config.String("adminUsername")
|
||||||
if this.adminUsername == "" {
|
if adminUsername == "" {
|
||||||
this.adminUsername = "admin"
|
adminUsername = "admin"
|
||||||
}
|
}
|
||||||
this.siteUrl, _ = revel.Config.String("site.url")
|
|
||||||
|
|
||||||
userInfo := userService.GetUserInfoByAny(this.adminUsername)
|
userInfo := userService.GetUserInfoByAny(adminUsername)
|
||||||
if userInfo.UserId == "" {
|
if userInfo.UserId == "" {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
this.adminUserId = userInfo.UserId.Hex()
|
adminUserId = userInfo.UserId.Hex()
|
||||||
|
|
||||||
configs := []info.Config{}
|
configs := []info.Config{}
|
||||||
db.ListByQ(db.Configs, bson.M{"UserId": userInfo.UserId}, &configs)
|
db.ListByQ(db.Configs, bson.M{"UserId": userInfo.UserId}, &configs)
|
||||||
@@ -69,16 +68,6 @@ func (this *ConfigService) InitGlobalConfigs() bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (this *ConfigService) GetSiteUrl() string {
|
|
||||||
return this.siteUrl;
|
|
||||||
}
|
|
||||||
func (this *ConfigService) GetAdminUsername() string {
|
|
||||||
return this.adminUsername
|
|
||||||
}
|
|
||||||
func (this *ConfigService) GetAdminUserId() string {
|
|
||||||
return this.adminUserId
|
|
||||||
}
|
|
||||||
|
|
||||||
// 通用方法
|
// 通用方法
|
||||||
func (this *ConfigService) updateGlobalConfig(userId, key string, value interface{}, isArr, isMap, isArrMap bool) bool {
|
func (this *ConfigService) updateGlobalConfig(userId, key string, value interface{}, isArr, isMap, isArrMap bool) bool {
|
||||||
// 判断是否存在
|
// 判断是否存在
|
||||||
@@ -194,7 +183,7 @@ func (this *ConfigService) UpdateShareNoteConfig(registerSharedUserId string,
|
|||||||
if registerSharedUserId == "" {
|
if registerSharedUserId == "" {
|
||||||
ok = true
|
ok = true
|
||||||
msg = "share userId is blank, So it share nothing to register"
|
msg = "share userId is blank, So it share nothing to register"
|
||||||
this.UpdateGlobalStringConfig(this.adminUserId, "registerSharedUserId", "")
|
this.UpdateGlobalStringConfig(adminUserId, "registerSharedUserId", "")
|
||||||
return
|
return
|
||||||
} else {
|
} else {
|
||||||
user := userService.GetUserInfo(registerSharedUserId)
|
user := userService.GetUserInfo(registerSharedUserId)
|
||||||
@@ -203,7 +192,7 @@ func (this *ConfigService) UpdateShareNoteConfig(registerSharedUserId string,
|
|||||||
msg = "no such user: " + registerSharedUserId
|
msg = "no such user: " + registerSharedUserId
|
||||||
return
|
return
|
||||||
} else {
|
} else {
|
||||||
this.UpdateGlobalStringConfig(this.adminUserId, "registerSharedUserId", registerSharedUserId)
|
this.UpdateGlobalStringConfig(adminUserId, "registerSharedUserId", registerSharedUserId)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -230,7 +219,7 @@ func (this *ConfigService) UpdateShareNoteConfig(registerSharedUserId string,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.UpdateGlobalArrMapConfig(this.adminUserId, "registerSharedNotebooks", notebooks)
|
this.UpdateGlobalArrMapConfig(adminUserId, "registerSharedNotebooks", notebooks)
|
||||||
|
|
||||||
notes := []map[string]string{}
|
notes := []map[string]string{}
|
||||||
// 共享笔记
|
// 共享笔记
|
||||||
@@ -255,7 +244,7 @@ func (this *ConfigService) UpdateShareNoteConfig(registerSharedUserId string,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.UpdateGlobalArrMapConfig(this.adminUserId, "registerSharedNotes", notes)
|
this.UpdateGlobalArrMapConfig(adminUserId, "registerSharedNotes", notes)
|
||||||
|
|
||||||
// 复制
|
// 复制
|
||||||
noteIds := []string{}
|
noteIds := []string{}
|
||||||
@@ -276,7 +265,7 @@ func (this *ConfigService) UpdateShareNoteConfig(registerSharedUserId string,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.UpdateGlobalArrayConfig(this.adminUserId, "registerCopyNoteIds", noteIds)
|
this.UpdateGlobalArrayConfig(adminUserId, "registerCopyNoteIds", noteIds)
|
||||||
|
|
||||||
ok = true
|
ok = true
|
||||||
return
|
return
|
||||||
@@ -288,7 +277,7 @@ func (this *ConfigService) AddBackup(path, remark string) bool {
|
|||||||
n := time.Now().Unix()
|
n := time.Now().Unix()
|
||||||
nstr := fmt.Sprintf("%v", n)
|
nstr := fmt.Sprintf("%v", n)
|
||||||
backups = append(backups, map[string]string{"createdTime": nstr, "path": path, "remark": remark})
|
backups = append(backups, map[string]string{"createdTime": nstr, "path": path, "remark": remark})
|
||||||
return this.UpdateGlobalArrMapConfig(this.adminUserId, "backups", backups)
|
return this.UpdateGlobalArrMapConfig(adminUserId, "backups", backups)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (this *ConfigService) getBackupDirname() string {
|
func (this *ConfigService) getBackupDirname() string {
|
||||||
@@ -304,8 +293,8 @@ func (this *ConfigService) Backup(remark string) (ok bool, msg string) {
|
|||||||
port, _ := revel.Config.String("db.port")
|
port, _ := revel.Config.String("db.port")
|
||||||
username, _ := revel.Config.String("db.username")
|
username, _ := revel.Config.String("db.username")
|
||||||
password, _ := revel.Config.String("db.password")
|
password, _ := revel.Config.String("db.password")
|
||||||
// mongodump -h localhost -d leanote -o /root/mongodb_backup/leanote-9-22/ -u leanote -p nKFAkxKnWkEQy8Vv2LlM
|
// mongodump -h localhost -d leanote -o /root/mongodb_backup/leanote-10-25/ -u leanote -p xx
|
||||||
binPath = binPath + " -h " + host + " -d " + dbname + " --port " + port
|
binPath = binPath + " -h " + host + " -d " + dbname + " -port " + port
|
||||||
if username != "" {
|
if username != "" {
|
||||||
binPath += " -u " + username + " -p " + password
|
binPath += " -u " + username + " -p " + password
|
||||||
}
|
}
|
||||||
@@ -361,7 +350,7 @@ func (this *ConfigService) Restore(createdTime string) (ok bool, msg string) {
|
|||||||
username, _ := revel.Config.String("db.username")
|
username, _ := revel.Config.String("db.username")
|
||||||
password, _ := revel.Config.String("db.password")
|
password, _ := revel.Config.String("db.password")
|
||||||
// mongorestore -h localhost -d leanote -o /root/mongodb_backup/leanote-9-22/ -u leanote -p nKFAkxKnWkEQy8Vv2LlM
|
// mongorestore -h localhost -d leanote -o /root/mongodb_backup/leanote-9-22/ -u leanote -p nKFAkxKnWkEQy8Vv2LlM
|
||||||
binPath = binPath + " --drop -h " + host + " -d " + dbname + " --port " + port
|
binPath = binPath + " --drop -h " + host + " -d " + dbname + " -port " + port
|
||||||
if username != "" {
|
if username != "" {
|
||||||
binPath += " -u " + username + " -p " + password
|
binPath += " -u " + username + " -p " + password
|
||||||
}
|
}
|
||||||
@@ -372,7 +361,7 @@ func (this *ConfigService) Restore(createdTime string) (ok bool, msg string) {
|
|||||||
return false, path + " Is Not Exists"
|
return false, path + " Is Not Exists"
|
||||||
}
|
}
|
||||||
|
|
||||||
binPath += " " + path
|
binPath += " --directoryperdb " + path
|
||||||
|
|
||||||
cmd := exec.Command("/bin/sh", "-c", binPath)
|
cmd := exec.Command("/bin/sh", "-c", binPath)
|
||||||
Log(binPath);
|
Log(binPath);
|
||||||
@@ -409,7 +398,7 @@ func (this *ConfigService) DeleteBackup(createdTime string) (bool, string) {
|
|||||||
// 删除之
|
// 删除之
|
||||||
backups = append(backups[0:i], backups[i+1:]...)
|
backups = append(backups[0:i], backups[i+1:]...)
|
||||||
|
|
||||||
ok := this.UpdateGlobalArrMapConfig(this.adminUserId, "backups", backups)
|
ok := this.UpdateGlobalArrMapConfig(adminUserId, "backups", backups)
|
||||||
return ok, ""
|
return ok, ""
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -427,7 +416,7 @@ func (this *ConfigService) UpdateBackupRemark(createdTime, remark string) (bool,
|
|||||||
}
|
}
|
||||||
backup["remark"] = remark;
|
backup["remark"] = remark;
|
||||||
|
|
||||||
ok := this.UpdateGlobalArrMapConfig(this.adminUserId, "backups", backups)
|
ok := this.UpdateGlobalArrMapConfig(adminUserId, "backups", backups)
|
||||||
return ok, ""
|
return ok, ""
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -455,37 +444,24 @@ var port string
|
|||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
revel.OnAppStart(func() {
|
revel.OnAppStart(func() {
|
||||||
/*
|
|
||||||
不用配置的, 因为最终通过命令可以改, 而且有的使用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
|
||||||
if strings.HasPrefix(siteUrl, "http://") {
|
if strings.HasPrefix(siteUrl, "http://") {
|
||||||
defaultDomain = siteUrl[len("http://"):]
|
defaultDomain = siteUrl[len("http://"):]
|
||||||
} else if strings.HasPrefix(siteUrl, "https://") {
|
} else if strings.HasPrefix(siteUrl, "https://") {
|
||||||
defaultDomain = siteUrl[len("https://"):]
|
defaultDomain = siteUrl[len("https://"):]
|
||||||
schema = "https://"
|
schema = "https://"
|
||||||
}
|
}
|
||||||
|
|
||||||
// port localhost:9000
|
|
||||||
ports := strings.Split(defaultDomain, ":")
|
|
||||||
if len(ports) == 2 {
|
|
||||||
port = ports[1]
|
|
||||||
}
|
|
||||||
if port == "80" {
|
|
||||||
port = ""
|
|
||||||
} else {
|
|
||||||
port = ":" + port
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func (this *ConfigService) GetSchema() string {
|
func (this *ConfigService) GetSchema() string {
|
||||||
return schema;
|
return schema;
|
||||||
}
|
}
|
||||||
@@ -563,36 +539,3 @@ func (this *ConfigService) IsGoodSubDomain(domain string) bool {
|
|||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// 上传大小
|
|
||||||
func (this *ConfigService) GetUploadSize(key string) float64 {
|
|
||||||
f, _ := strconv.ParseFloat(this.GetGlobalStringConfig(key), 64)
|
|
||||||
return f;
|
|
||||||
}
|
|
||||||
func (this *ConfigService) GetUploadSizeLimit() map[string]float64 {
|
|
||||||
return map[string]float64{
|
|
||||||
"uploadImageSize": this.GetUploadSize("uploadImageSize"),
|
|
||||||
"uploadBlogLogoSize":this.GetUploadSize("uploadBlogLogoSize"),
|
|
||||||
"uploadAttachSize":this.GetUploadSize("uploadAttachSize"),
|
|
||||||
"uploadAvatarSize":this.GetUploadSize("uploadAvatarSize"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// 为用户得到全局的配置
|
|
||||||
// NoteController调用
|
|
||||||
func (this *ConfigService) GetGlobalConfigForUser() map[string]interface{} {
|
|
||||||
uploadSizeConfigs := this.GetUploadSizeLimit();
|
|
||||||
config := map[string]interface{}{}
|
|
||||||
for k, v := range uploadSizeConfigs {
|
|
||||||
config[k] = v
|
|
||||||
}
|
|
||||||
return config
|
|
||||||
}
|
|
||||||
|
|
||||||
// 主页是否是管理员的博客页
|
|
||||||
func (this *ConfigService) HomePageIsAdminsBlog() bool {
|
|
||||||
return this.GetGlobalStringConfig("homePage") == ""
|
|
||||||
}
|
|
||||||
|
|
||||||
func (this *ConfigService) GetVersion() string {
|
|
||||||
return "1.0-beta.4"
|
|
||||||
}
|
|
||||||
+10
-10
@@ -82,9 +82,9 @@ func (this *EmailService) RegisterSendActiveEmail(userInfo info.User, email stri
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
tokenUrl := configService.GetSiteUrl() + "/user/activeEmail?token=" + token
|
tokenUrl := siteUrl + "/user/activeEmail?token=" + token
|
||||||
// {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": siteUrl, "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,
|
||||||
@@ -122,9 +122,9 @@ func (this *EmailService) UpdateEmailSendActiveEmail(userInfo info.User, email s
|
|||||||
tpl := configService.GetGlobalStringConfig("emailTemplateUpdateEmail");
|
tpl := configService.GetGlobalStringConfig("emailTemplateUpdateEmail");
|
||||||
|
|
||||||
// 发送邮件
|
// 发送邮件
|
||||||
tokenUrl := configService.GetSiteUrl() + "/user/updateEmail?token=" + token
|
tokenUrl := siteUrl + "/user/updateEmail?token=" + token
|
||||||
// {siteUrl} {tokenUrl} {token} {tokenTimeout} {user.userId} {user.email} {user.username}
|
// {siteUrl} {tokenUrl} {token} {tokenTimeout} {user.userId} {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": siteUrl, "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(),
|
||||||
@@ -148,9 +148,9 @@ func (this *EmailService) FindPwdSendEmail(token, email string) (ok bool, msg st
|
|||||||
tpl := configService.GetGlobalStringConfig("emailTemplateFindPassword");
|
tpl := configService.GetGlobalStringConfig("emailTemplateFindPassword");
|
||||||
|
|
||||||
// 发送邮件
|
// 发送邮件
|
||||||
tokenUrl := configService.GetSiteUrl() + "/findPassword/" + token
|
tokenUrl := siteUrl + "/findPassword/" + token
|
||||||
// {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,
|
token2Value := map[string]interface{}{"siteUrl": siteUrl, "tokenUrl": tokenUrl,
|
||||||
"token": token, "tokenTimeout": strconv.Itoa(int(tokenService.GetOverHours(info.TokenActiveEmail)))}
|
"token": token, "tokenTimeout": strconv.Itoa(int(tokenService.GetOverHours(info.TokenActiveEmail)))}
|
||||||
|
|
||||||
ok, msg, subject, tpl = this.renderEmail(subject, tpl, token2Value)
|
ok, msg, subject, tpl = this.renderEmail(subject, tpl, token2Value)
|
||||||
@@ -167,8 +167,8 @@ func (this *EmailService) SendInviteEmail(userInfo info.User, email, content str
|
|||||||
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": siteUrl,
|
||||||
"registerUrl": configService.GetSiteUrl() + "/register?from=" + userInfo.Username,
|
"registerUrl": siteUrl + "/register?from=" + userInfo.Username,
|
||||||
"content": content,
|
"content": content,
|
||||||
"user": map[string]interface{}{
|
"user": map[string]interface{}{
|
||||||
"username": userInfo.Username,
|
"username": userInfo.Username,
|
||||||
@@ -225,7 +225,7 @@ func (this *EmailService) SendCommentEmail(note info.Note, comment info.BlogComm
|
|||||||
// {blog.id} {blog.title} {blog.url}
|
// {blog.id} {blog.title} {blog.url}
|
||||||
// {commentUser.userId} {commentUser.username} {commentUser.email}
|
// {commentUser.userId} {commentUser.username} {commentUser.email}
|
||||||
// {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": siteUrl, "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,
|
||||||
@@ -316,7 +316,7 @@ func (this *EmailService) renderEmail(subject, body string, values map[string]in
|
|||||||
|
|
||||||
var tpl *template.Template
|
var tpl *template.Template
|
||||||
|
|
||||||
values["siteUrl"] = configService.GetSiteUrl();
|
values["siteUrl"] = siteUrl;
|
||||||
|
|
||||||
// subject
|
// subject
|
||||||
if subject != "" {
|
if subject != "" {
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ type FileService struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// add Image
|
// add Image
|
||||||
func (this *FileService) AddImage(image info.File, albumId, userId string, needCheckSize bool) (ok bool, msg string) {
|
func (this *FileService) AddImage(image info.File, albumId, userId string) bool {
|
||||||
image.CreatedTime = time.Now()
|
image.CreatedTime = time.Now()
|
||||||
if albumId != "" {
|
if albumId != "" {
|
||||||
image.AlbumId = bson.ObjectIdHex(albumId)
|
image.AlbumId = bson.ObjectIdHex(albumId)
|
||||||
@@ -27,8 +27,7 @@ func (this *FileService) AddImage(image info.File, albumId, userId string, needC
|
|||||||
}
|
}
|
||||||
image.UserId = bson.ObjectIdHex(userId)
|
image.UserId = bson.ObjectIdHex(userId)
|
||||||
|
|
||||||
ok = db.Insert(db.Files, image)
|
return db.Insert(db.Files, image)
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// list images
|
// list images
|
||||||
@@ -148,16 +147,7 @@ func (this *FileService) GetFile(userId, fileId string) string {
|
|||||||
return path
|
return path
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2014/12/28 修复, 如果是分享给用户组, 那就不行, 这里可以实现
|
|
||||||
for _, noteId := range noteIds {
|
|
||||||
note := noteService.GetNoteById(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}}) {
|
if db.Has(db.ShareNotes, bson.M{"ToUserId": bson.ObjectIdHex(userId), "NoteId": bson.M{"$in": noteIds}}) {
|
||||||
return path
|
return path
|
||||||
}
|
}
|
||||||
@@ -176,7 +166,6 @@ func (this *FileService) GetFile(userId, fileId string) string {
|
|||||||
return path
|
return path
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 可能是刚复制到owner上, 但内容又没有保存, 所以没有note->imageId的映射, 此时看是否有fromFileId
|
// 可能是刚复制到owner上, 但内容又没有保存, 所以没有note->imageId的映射, 此时看是否有fromFileId
|
||||||
@@ -233,7 +222,7 @@ func (this *FileService) CopyImage(userId, fileId, toUserId string) (bool, strin
|
|||||||
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)
|
||||||
|
|
||||||
if Ok {
|
if Ok {
|
||||||
return Ok, id.Hex()
|
return Ok, id.Hex()
|
||||||
@@ -243,9 +232,5 @@ 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
|
|
||||||
if !bson.IsObjectIdHex(fileId) || !bson.IsObjectIdHex(userId) {
|
|
||||||
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)})
|
||||||
}
|
}
|
||||||
@@ -1,223 +0,0 @@
|
|||||||
package service
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/leanote/leanote/app/info"
|
|
||||||
"github.com/leanote/leanote/app/db"
|
|
||||||
// . "github.com/leanote/leanote/app/lea"
|
|
||||||
"gopkg.in/mgo.v2/bson"
|
|
||||||
"time"
|
|
||||||
// "strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
// 用户组, 用户组用户管理
|
|
||||||
|
|
||||||
type GroupService struct {
|
|
||||||
}
|
|
||||||
|
|
||||||
// 添加分组
|
|
||||||
func (this *GroupService) AddGroup(userId, title string) (bool, info.Group) {
|
|
||||||
group := info.Group {
|
|
||||||
GroupId: bson.NewObjectId(),
|
|
||||||
UserId: bson.ObjectIdHex(userId),
|
|
||||||
Title: title,
|
|
||||||
CreatedTime: time.Now(),
|
|
||||||
}
|
|
||||||
return db.Insert(db.Groups, group), group
|
|
||||||
}
|
|
||||||
// 删除分组
|
|
||||||
// 判断是否有好友
|
|
||||||
func (this *GroupService) DeleteGroup(userId, groupId string) (ok bool, msg string) {
|
|
||||||
/*
|
|
||||||
if db.Has(db.GroupUsers, bson.M{"GroupId": bson.ObjectIdHex(groupId)}) {
|
|
||||||
return false, "groupHasUsers"
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
if !this.isMyGroup(userId, groupId) {
|
|
||||||
return false, "notMyGroup"
|
|
||||||
}
|
|
||||||
|
|
||||||
// 删除分组后, 需要删除所有用户分享到该组的笔记本, 笔记
|
|
||||||
|
|
||||||
shareService.DeleteAllShareNotebookGroup(groupId);
|
|
||||||
shareService.DeleteAllShareNoteGroup(groupId);
|
|
||||||
|
|
||||||
db.DeleteAll(db.GroupUsers, bson.M{"GroupId": bson.ObjectIdHex(groupId)})
|
|
||||||
return db.DeleteByIdAndUserId(db.Groups, groupId, userId), ""
|
|
||||||
|
|
||||||
// TODO 删除分组后, 在shareNote, shareNotebook中也要删除
|
|
||||||
}
|
|
||||||
|
|
||||||
// 修改group标题
|
|
||||||
func (this *GroupService) UpdateGroupTitle(userId, groupId, title string) (ok bool) {
|
|
||||||
return db.UpdateByIdAndUserIdField(db.Groups, groupId, userId, "Title", title)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 得到用户的所有分组(包括下的所有用户)
|
|
||||||
func (this *GroupService) GetGroupsAndUsers(userId string) ([]info.Group) {
|
|
||||||
/*
|
|
||||||
// 得到我的分组
|
|
||||||
groups := []info.Group{}
|
|
||||||
db.ListByQ(db.Groups, bson.M{"UserId": bson.ObjectIdHex(userId)}, &groups)
|
|
||||||
*/
|
|
||||||
// 我的分组, 及我所属的分组
|
|
||||||
groups := this.GetGroupsContainOf(userId);
|
|
||||||
|
|
||||||
// 得到其下的用户
|
|
||||||
for i, group := range groups {
|
|
||||||
group.Users = this.GetUsers(group.GroupId.Hex())
|
|
||||||
groups[i] = group
|
|
||||||
}
|
|
||||||
return groups
|
|
||||||
}
|
|
||||||
// 仅仅得到所有分组
|
|
||||||
func (this *GroupService) GetGroups(userId string) ([]info.Group) {
|
|
||||||
// 得到分组s
|
|
||||||
groups := []info.Group{}
|
|
||||||
db.ListByQ(db.Groups, bson.M{"UserId": bson.ObjectIdHex(userId)}, &groups)
|
|
||||||
return groups
|
|
||||||
}
|
|
||||||
|
|
||||||
// 得到我的和我所属组的ids
|
|
||||||
func (this *GroupService) GetMineAndBelongToGroupIds(userId string) ([]bson.ObjectId) {
|
|
||||||
// 所属组
|
|
||||||
groupIds := this.GetBelongToGroupIds(userId)
|
|
||||||
|
|
||||||
m := map[bson.ObjectId]bool{}
|
|
||||||
for _, groupId := range groupIds {
|
|
||||||
m[groupId] = true
|
|
||||||
}
|
|
||||||
|
|
||||||
// 我的组
|
|
||||||
myGroups := this.GetGroups(userId)
|
|
||||||
|
|
||||||
for _, group := range myGroups {
|
|
||||||
if !m[group.GroupId] {
|
|
||||||
groupIds = append(groupIds, group.GroupId)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return groupIds
|
|
||||||
}
|
|
||||||
|
|
||||||
// 获取包含此用户的组对象数组
|
|
||||||
// 获取该用户所属组, 和我的组
|
|
||||||
func (this *GroupService) GetGroupsContainOf(userId string) []info.Group {
|
|
||||||
// 我的组
|
|
||||||
myGroups := this.GetGroups(userId)
|
|
||||||
myGroupMap := map[bson.ObjectId]bool{}
|
|
||||||
|
|
||||||
for _, group := range myGroups {
|
|
||||||
myGroupMap[group.GroupId] = true
|
|
||||||
}
|
|
||||||
|
|
||||||
// 所属组
|
|
||||||
groupIds := this.GetBelongToGroupIds(userId)
|
|
||||||
|
|
||||||
groups := []info.Group{}
|
|
||||||
db.ListByQ(db.Groups, bson.M{"_id": bson.M{"$in": groupIds}}, &groups)
|
|
||||||
|
|
||||||
for _, group := range groups {
|
|
||||||
if !myGroupMap[group.GroupId] {
|
|
||||||
myGroups = append(myGroups, group)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return myGroups
|
|
||||||
}
|
|
||||||
|
|
||||||
// 得到分组, shareService用
|
|
||||||
func (this *GroupService) GetGroup(userId, groupId string) (info.Group) {
|
|
||||||
// 得到分组s
|
|
||||||
group := info.Group{}
|
|
||||||
db.GetByIdAndUserId(db.Groups, groupId, userId, &group)
|
|
||||||
return group
|
|
||||||
}
|
|
||||||
|
|
||||||
// 得到某分组下的用户
|
|
||||||
func (this *GroupService) GetUsers(groupId string) ([]info.User) {
|
|
||||||
// 得到UserIds
|
|
||||||
groupUsers := []info.GroupUser{}
|
|
||||||
db.ListByQWithFields(db.GroupUsers, bson.M{"GroupId": bson.ObjectIdHex(groupId)}, []string{"UserId"}, &groupUsers)
|
|
||||||
if len(groupUsers) == 0 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
userIds := make([]bson.ObjectId, len(groupUsers))
|
|
||||||
for i, each := range groupUsers {
|
|
||||||
userIds[i] = each.UserId
|
|
||||||
}
|
|
||||||
// 得到userInfos
|
|
||||||
return userService.ListUserInfosByUserIds(userIds)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 得到我所属的所有分组ids
|
|
||||||
func (this *GroupService) GetBelongToGroupIds(userId string) ([]bson.ObjectId) {
|
|
||||||
// 得到UserIds
|
|
||||||
groupUsers := []info.GroupUser{}
|
|
||||||
db.ListByQWithFields(db.GroupUsers, bson.M{"UserId": bson.ObjectIdHex(userId)}, []string{"GroupId"}, &groupUsers)
|
|
||||||
if len(groupUsers) == 0 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
groupIds := make([]bson.ObjectId, len(groupUsers))
|
|
||||||
for i, each := range groupUsers {
|
|
||||||
groupIds[i] = each.GroupId
|
|
||||||
}
|
|
||||||
return groupIds
|
|
||||||
}
|
|
||||||
|
|
||||||
func (this *GroupService) isMyGroup(ownUserId, groupId string) (ok bool) {
|
|
||||||
return db.Has(db.Groups, bson.M{"_id": bson.ObjectIdHex(groupId), "UserId": bson.ObjectIdHex(ownUserId)})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 判断组中是否包含指定用户
|
|
||||||
func (this *GroupService) IsExistsGroupUser(userId, groupId string) (ok bool) {
|
|
||||||
// 如果我拥有这个组, 那也行
|
|
||||||
if this.isMyGroup(userId, groupId) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return db.Has(db.GroupUsers, bson.M{"UserId": bson.ObjectIdHex(userId), "GroupId": bson.ObjectIdHex(groupId)})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 为group添加用户
|
|
||||||
// 用户是否已存在?
|
|
||||||
func (this *GroupService) AddUser(ownUserId, groupId, userId string) (ok bool, msg string) {
|
|
||||||
// groupId是否是ownUserId的?
|
|
||||||
/*
|
|
||||||
if !this.IsExistsGroupUser(ownUserId, groupId) {
|
|
||||||
return false, "forbidden"
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
if !this.isMyGroup(ownUserId, groupId) {
|
|
||||||
return false, "forbidden"
|
|
||||||
}
|
|
||||||
|
|
||||||
// 是否已存在
|
|
||||||
if db.Has(db.GroupUsers, bson.M{"GroupId": bson.ObjectIdHex(groupId), "UserId": bson.ObjectIdHex(userId)}) {
|
|
||||||
return false, "hasUsers"
|
|
||||||
}
|
|
||||||
|
|
||||||
return db.Insert(db.GroupUsers, info.GroupUser{
|
|
||||||
GroupUserId: bson.NewObjectId(),
|
|
||||||
GroupId: bson.ObjectIdHex(groupId),
|
|
||||||
UserId: bson.ObjectIdHex(userId),
|
|
||||||
CreatedTime: time.Now(),
|
|
||||||
}), ""
|
|
||||||
}
|
|
||||||
|
|
||||||
// 删除用户
|
|
||||||
func (this *GroupService) DeleteUser(ownUserId, groupId, userId string) (ok bool, msg string) {
|
|
||||||
// groupId是否是ownUserId的?
|
|
||||||
/*
|
|
||||||
if !this.IsExistsGroupUser(ownUserId, groupId) {
|
|
||||||
return false, "forbidden"
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
if !this.isMyGroup(ownUserId, groupId) {
|
|
||||||
return false, "forbidden"
|
|
||||||
}
|
|
||||||
|
|
||||||
// 删除该用户分享到本组的笔记本, 笔记
|
|
||||||
shareService.DeleteShareNotebookGroupWhenDeleteGroupUser(userId, groupId);
|
|
||||||
shareService.DeleteShareNoteGroupWhenDeleteGroupUser(userId, groupId);
|
|
||||||
|
|
||||||
return db.Delete(db.GroupUsers, bson.M{"GroupId": bson.ObjectIdHex(groupId), "UserId": bson.ObjectIdHex(userId)}), ""
|
|
||||||
}
|
|
||||||
@@ -33,8 +33,7 @@ func (this *NoteContentHistoryService) AddHistory(noteId, userId string, eachHis
|
|||||||
// TODO
|
// TODO
|
||||||
l := len(history.Histories)
|
l := len(history.Histories)
|
||||||
if l >= maxSize {
|
if l >= maxSize {
|
||||||
// history.Histories = history.Histories[l-maxSize:] // BUG, 致使都是以前的
|
history.Histories = history.Histories[l-maxSize:]
|
||||||
history.Histories = history.Histories[:maxSize]
|
|
||||||
}
|
}
|
||||||
newHistory := []info.EachHistory{eachHistory}
|
newHistory := []info.EachHistory{eachHistory}
|
||||||
newHistory = append(newHistory, history.Histories...) // 在开头加了, 最近的在最前
|
newHistory = append(newHistory, history.Histories...) // 在开头加了, 最近的在最前
|
||||||
@@ -62,4 +61,4 @@ func (this *NoteContentHistoryService) ListHistories(noteId, userId string) []in
|
|||||||
histories := info.NoteContentHistory{}
|
histories := info.NoteContentHistory{}
|
||||||
db.GetByIdAndUserId(db.NoteContentHistories, noteId, userId, &histories)
|
db.GetByIdAndUserId(db.NoteContentHistories, noteId, userId, &histories)
|
||||||
return histories.Histories
|
return histories.Histories
|
||||||
}
|
}
|
||||||
@@ -29,31 +29,24 @@ func (this *NoteImageService) GetNoteIds(imageId string) ([]bson.ObjectId) {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO 这个web可以用, 但api会传来, 不用用了
|
|
||||||
// 解析内容中的图片, 建立图片与note的关系
|
// 解析内容中的图片, 建立图片与note的关系
|
||||||
// <img src="/file/outputImage?fileId=12323232" />
|
// <img src="/file/outputImage?fileId=12323232" />
|
||||||
// 图片必须是我的, 不然不添加
|
// 图片必须是我的, 不然不添加
|
||||||
// imgSrc 防止博客修改了, 但内容删除了
|
func (this *NoteImageService) UpdateNoteImages(userId, noteId, content string) bool {
|
||||||
func (this *NoteImageService) UpdateNoteImages(userId, noteId, imgSrc, content string) bool {
|
reg, _ := regexp.Compile("outputImage\\?fileId=([a-z0-9A-Z]{24})")
|
||||||
// 让主图成为内容的一员
|
|
||||||
if imgSrc != "" {
|
|
||||||
content = "<img src=\"" + imgSrc + "\" >" + content
|
|
||||||
}
|
|
||||||
// life 添加getImage
|
|
||||||
reg, _ := regexp.Compile("(outputImage|getImage)\\?fileId=([a-z0-9A-Z]{24})")
|
|
||||||
find := reg.FindAllStringSubmatch(content, -1) // 查找所有的
|
find := reg.FindAllStringSubmatch(content, -1) // 查找所有的
|
||||||
|
|
||||||
// 删除旧的
|
// 删除旧的
|
||||||
db.DeleteAll(db.NoteImages, bson.M{"NoteId": bson.ObjectIdHex(noteId)})
|
db.DeleteAll(db.NoteImages, bson.M{"NoteId": bson.ObjectIdHex(noteId)})
|
||||||
|
|
||||||
// 添加新的
|
// 添加新的
|
||||||
var fileId string
|
var fileId string
|
||||||
noteImage := info.NoteImage{NoteId: bson.ObjectIdHex(noteId)}
|
noteImage := info.NoteImage{NoteId: bson.ObjectIdHex(noteId)}
|
||||||
hasAdded := make(map[string]bool)
|
hasAdded := make(map[string]bool)
|
||||||
if find != nil && len(find) > 0 {
|
if find != nil && len(find) > 0 {
|
||||||
for _, each := range find {
|
for _, each := range find {
|
||||||
if each != nil && len(each) == 3 {
|
if each != nil && len(each) == 2 {
|
||||||
fileId = each[2] // 现在有两个子表达式了
|
fileId = each[1]
|
||||||
// 之前没能添加过的
|
// 之前没能添加过的
|
||||||
if _, ok := hasAdded[fileId]; !ok {
|
if _, ok := hasAdded[fileId]; !ok {
|
||||||
Log(fileId)
|
Log(fileId)
|
||||||
@@ -107,48 +100,3 @@ func (this *NoteImageService) CopyNoteImages(fromNoteId, fromUserId, newNoteId,
|
|||||||
|
|
||||||
return content;
|
return content;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
|
||||||
func (this *NoteImageService) getImagesByNoteIds(noteIds []bson.ObjectId) map[string][]info.File {
|
|
||||||
noteNoteImages := []info.NoteImage{}
|
|
||||||
db.ListByQ(db.NoteImages, bson.M{"NoteId": bson.M{"$in": noteIds}}, ¬eNoteImages)
|
|
||||||
|
|
||||||
// 得到imageId, 再去files表查所有的Files
|
|
||||||
imageIds := []bson.ObjectId{}
|
|
||||||
|
|
||||||
// 图片1 => N notes
|
|
||||||
imageIdNotes := map[string][]string{} // imageId => [noteId1, noteId2, ...]
|
|
||||||
for _, noteImage := range noteNoteImages {
|
|
||||||
imageId := noteImage.ImageId
|
|
||||||
imageIds = append(imageIds, imageId)
|
|
||||||
|
|
||||||
imageIdHex := imageId.Hex()
|
|
||||||
noteId := noteImage.NoteId.Hex()
|
|
||||||
if notes, ok := imageIdNotes[imageIdHex]; ok {
|
|
||||||
imageIdNotes[imageIdHex] = append(notes, noteId)
|
|
||||||
} else {
|
|
||||||
imageIdNotes[imageIdHex] = []string{noteId}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 得到所有files
|
|
||||||
files := []info.File{}
|
|
||||||
db.ListByQ(db.Files, bson.M{"_id": bson.M{"$in": imageIds}}, &files)
|
|
||||||
|
|
||||||
// 建立note->file关联
|
|
||||||
noteImages := make(map[string][]info.File)
|
|
||||||
for _, file := range files {
|
|
||||||
fileIdHex := file.FileId.Hex() // == imageId
|
|
||||||
// 这个fileIdHex有哪些notes呢?
|
|
||||||
if notes, ok := imageIdNotes[fileIdHex]; ok {
|
|
||||||
for _, noteId := range notes {
|
|
||||||
if files, ok2 := noteImages[noteId]; ok2 {
|
|
||||||
noteImages[noteId] = append(files, file)
|
|
||||||
} else {
|
|
||||||
noteImages[noteId] = []info.File{file}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return noteImages
|
|
||||||
}
|
|
||||||
+36
-390
@@ -18,10 +18,9 @@ func (this *NoteService) GetNote(noteId, userId string) (note info.Note) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
// fileService调用
|
// fileService调用
|
||||||
// 不能是已经删除了的, life bug, 客户端删除后, 竟然还能在web上打开
|
|
||||||
func (this *NoteService) GetNoteById(noteId string) (note info.Note) {
|
func (this *NoteService) GetNoteById(noteId string) (note info.Note) {
|
||||||
note = info.Note{}
|
note = info.Note{}
|
||||||
db.GetByQ(db.Notes, bson.M{"_id": bson.ObjectIdHex(noteId), "IsDeleted": false}, ¬e)
|
db.Get(db.Notes, noteId, ¬e)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// 得到blog, blogService用
|
// 得到blog, blogService用
|
||||||
@@ -45,115 +44,14 @@ func (this *NoteService) GetNoteAndContent(noteId, userId string) (noteAndConten
|
|||||||
return info.NoteAndContent{note, noteContent}
|
return info.NoteAndContent{note, noteContent}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取同步的笔记
|
|
||||||
// > afterUsn的笔记
|
|
||||||
func (this *NoteService) GetSyncNotes(userId string, afterUsn, maxEntry int) []info.ApiNote {
|
|
||||||
notes := []info.Note{}
|
|
||||||
q := db.Notes.Find(bson.M{
|
|
||||||
"UserId": bson.ObjectIdHex(userId),
|
|
||||||
"Usn": bson.M{"$gt": afterUsn},
|
|
||||||
});
|
|
||||||
q.Sort("Usn").Limit(maxEntry).All(¬es)
|
|
||||||
|
|
||||||
return this.ToApiNotes(notes)
|
|
||||||
}
|
|
||||||
|
|
||||||
// note与apiNote的转换
|
|
||||||
func (this *NoteService) ToApiNotes(notes []info.Note) []info.ApiNote {
|
|
||||||
// 2, 得到所有图片, 附件信息
|
|
||||||
// 查images表, attachs表
|
|
||||||
if len(notes) > 0 {
|
|
||||||
noteIds := make([]bson.ObjectId, len(notes));
|
|
||||||
for i, note := range notes {
|
|
||||||
noteIds[i] = note.NoteId
|
|
||||||
}
|
|
||||||
noteFilesMap := this.getFiles(noteIds)
|
|
||||||
// 生成info.ApiNote
|
|
||||||
apiNotes := make([]info.ApiNote, len(notes))
|
|
||||||
for i, note := range notes {
|
|
||||||
noteId := note.NoteId.Hex()
|
|
||||||
apiNotes[i] = this.ToApiNote(¬e, noteFilesMap[noteId])
|
|
||||||
}
|
|
||||||
return apiNotes
|
|
||||||
}
|
|
||||||
// 返回空的
|
|
||||||
return []info.ApiNote{}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// note与apiNote的转换
|
|
||||||
func (this *NoteService) ToApiNote(note *info.Note, files []info.NoteFile) info.ApiNote {
|
|
||||||
apiNote := info.ApiNote{
|
|
||||||
NoteId: note.NoteId.Hex(),
|
|
||||||
NotebookId: note.NotebookId.Hex(),
|
|
||||||
UserId : note.UserId.Hex(),
|
|
||||||
Title : note.Title,
|
|
||||||
Tags : note.Tags,
|
|
||||||
IsMarkdown : note.IsMarkdown,
|
|
||||||
IsBlog : note.IsBlog,
|
|
||||||
IsTrash : note.IsTrash,
|
|
||||||
IsDeleted : note.IsDeleted,
|
|
||||||
Usn : note.Usn,
|
|
||||||
CreatedTime : note.CreatedTime,
|
|
||||||
UpdatedTime : note.UpdatedTime,
|
|
||||||
PublicTime : note.PublicTime,
|
|
||||||
Files: files,
|
|
||||||
}
|
|
||||||
return apiNote
|
|
||||||
}
|
|
||||||
|
|
||||||
// getDirtyNotes, 把note的图片, 附件信息都发送给客户端
|
|
||||||
// 客户端保存到本地, 再获取图片, 附件
|
|
||||||
|
|
||||||
// 得到所有图片, 附件信息
|
|
||||||
// 查images表, attachs表
|
|
||||||
// [待测]
|
|
||||||
func (this *NoteService) getFiles(noteIds []bson.ObjectId) map[string][]info.NoteFile {
|
|
||||||
noteImages := noteImageService.getImagesByNoteIds(noteIds);
|
|
||||||
noteAttachs := attachService.getAttachsByNoteIds(noteIds)
|
|
||||||
|
|
||||||
noteFilesMap := map[string][]info.NoteFile{}
|
|
||||||
|
|
||||||
for _, noteId := range noteIds {
|
|
||||||
noteIdHex := noteId.Hex()
|
|
||||||
noteFiles := []info.NoteFile{}
|
|
||||||
// images
|
|
||||||
if images, ok := noteImages[noteIdHex]; ok {
|
|
||||||
for _, image := range images {
|
|
||||||
noteFiles = append(noteFiles, info.NoteFile{
|
|
||||||
FileId: image.FileId.Hex(),
|
|
||||||
Type: image.Type,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// attach
|
|
||||||
if attachs, ok := noteAttachs[noteIdHex]; ok {
|
|
||||||
for _, attach := range attachs {
|
|
||||||
noteFiles = append(noteFiles, info.NoteFile{
|
|
||||||
FileId: attach.AttachId.Hex(),
|
|
||||||
Type: attach.Type,
|
|
||||||
Title: attach.Title,
|
|
||||||
IsAttach: true,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
noteFilesMap[noteIdHex] = noteFiles
|
|
||||||
}
|
|
||||||
|
|
||||||
return noteFilesMap
|
|
||||||
}
|
|
||||||
|
|
||||||
// 列出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)
|
||||||
|
|
||||||
// 不是trash的
|
// 不是trash的
|
||||||
query := bson.M{"UserId": bson.ObjectIdHex(userId), "IsTrash": isTrash, "IsDeleted": false}
|
query := bson.M{"UserId": bson.ObjectIdHex(userId), "IsTrash": isTrash}
|
||||||
if isBlog {
|
if isBlog {
|
||||||
query["IsBlog"] = true
|
query["IsBlog"] = true
|
||||||
}
|
}
|
||||||
@@ -213,17 +111,11 @@ func (this *NoteService) ListNoteAbstractsByNoteIds(noteIds []bson.ObjectId) (no
|
|||||||
db.ListByQWithFields(db.NoteContents, bson.M{"_id": bson.M{"$in": noteIds}}, []string{"_id", "Abstract"}, ¬es)
|
db.ListByQWithFields(db.NoteContents, bson.M{"_id": bson.M{"$in": noteIds}}, []string{"_id", "Abstract"}, ¬es)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
func (this *NoteService) ListNoteContentByNoteIds(noteIds []bson.ObjectId) (notes []info.NoteContent) {
|
|
||||||
notes = []info.NoteContent{}
|
|
||||||
db.ListByQWithFields(db.NoteContents, bson.M{"_id": bson.M{"$in": noteIds}}, []string{"_id", "Abstract", "Content"}, ¬es)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 添加笔记
|
// 添加笔记
|
||||||
// 首先要判断Notebook是否是Blog, 是的话设为blog
|
// 首先要判断Notebook是否是Blog, 是的话设为blog
|
||||||
// [ok]
|
// [ok]
|
||||||
|
func (this *NoteService) AddNote(note info.Note) 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;
|
||||||
@@ -232,19 +124,14 @@ func (this *NoteService) AddNote(note info.Note, fromApi bool) info.Note {
|
|||||||
note.UpdatedTime = note.CreatedTime
|
note.UpdatedTime = note.CreatedTime
|
||||||
note.IsTrash = false
|
note.IsTrash = false
|
||||||
note.UpdatedUserId = note.UserId
|
note.UpdatedUserId = note.UserId
|
||||||
note.UrlTitle = GetUrTitle(note.UserId.Hex(), note.Title, "note")
|
|
||||||
note.Usn = userService.IncrUsn(note.UserId.Hex())
|
|
||||||
|
|
||||||
|
// 设为blog
|
||||||
notebookId := note.NotebookId.Hex()
|
notebookId := note.NotebookId.Hex()
|
||||||
|
note.IsBlog = notebookService.IsBlog(notebookId)
|
||||||
|
|
||||||
// api会传IsBlog, web不会传
|
if note.IsBlog {
|
||||||
if !fromApi {
|
note.PublicTime = note.UpdatedTime
|
||||||
// 设为blog
|
|
||||||
note.IsBlog = notebookService.IsBlog(notebookId)
|
|
||||||
}
|
}
|
||||||
// if note.IsBlog {
|
|
||||||
note.PublicTime = note.UpdatedTime
|
|
||||||
// }
|
|
||||||
|
|
||||||
db.Insert(db.Notes, note)
|
db.Insert(db.Notes, note)
|
||||||
|
|
||||||
@@ -262,7 +149,7 @@ func (this *NoteService) AddSharedNote(note info.Note, myUserId bson.ObjectId) i
|
|||||||
// 判断我是否有权限添加
|
// 判断我是否有权限添加
|
||||||
if shareService.HasUpdateNotebookPerm(note.UserId.Hex(), myUserId.Hex(), note.NotebookId.Hex()) {
|
if shareService.HasUpdateNotebookPerm(note.UserId.Hex(), myUserId.Hex(), note.NotebookId.Hex()) {
|
||||||
note.CreatedUserId = myUserId // 是我给共享我的人创建的
|
note.CreatedUserId = myUserId // 是我给共享我的人创建的
|
||||||
return this.AddNote(note, false)
|
return this.AddNote(note)
|
||||||
}
|
}
|
||||||
return info.Note{}
|
return info.Note{}
|
||||||
}
|
}
|
||||||
@@ -277,67 +164,13 @@ func (this *NoteService) AddNoteContent(noteContent info.NoteContent) info.NoteC
|
|||||||
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需要这里获取
|
|
||||||
// 不需要
|
|
||||||
/*
|
|
||||||
func (this *NoteService) AddNoteAndContentApi(note info.Note, noteContent info.NoteContent, myUserId bson.ObjectId) info.Note {
|
|
||||||
if(note.NoteId.Hex() == "") {
|
|
||||||
noteId := bson.NewObjectId();
|
|
||||||
note.NoteId = noteId;
|
|
||||||
}
|
|
||||||
note.CreatedTime = time.Now()
|
|
||||||
note.UpdatedTime = note.CreatedTime
|
|
||||||
note.IsTrash = false
|
|
||||||
note.UpdatedUserId = note.UserId
|
|
||||||
note.UrlTitle = GetUrTitle(note.UserId.Hex(), note.Title, "note")
|
|
||||||
note.Usn = userService.IncrUsn(note.UserId.Hex())
|
|
||||||
|
|
||||||
// desc这里获取
|
|
||||||
desc := SubStringHTMLToRaw(noteContent.Content, 50)
|
|
||||||
note.Desc = desc;
|
|
||||||
|
|
||||||
// 设为blog
|
|
||||||
notebookId := note.NotebookId.Hex()
|
|
||||||
note.IsBlog = notebookService.IsBlog(notebookId)
|
|
||||||
|
|
||||||
if note.IsBlog {
|
|
||||||
note.PublicTime = note.UpdatedTime
|
|
||||||
}
|
|
||||||
|
|
||||||
db.Insert(db.Notes, note)
|
|
||||||
|
|
||||||
// tag1, 不需要了
|
|
||||||
// tagService.AddTags(note.UserId.Hex(), note.Tags)
|
|
||||||
|
|
||||||
// recount notebooks' notes number
|
|
||||||
notebookService.ReCountNotebookNumberNotes(notebookId)
|
|
||||||
|
|
||||||
// 这里, 添加到内容中
|
|
||||||
abstract := SubStringHTML(noteContent.Content, 200, "")
|
|
||||||
noteContent.Abstract = abstract
|
|
||||||
this.AddNoteContent(noteContent)
|
|
||||||
|
|
||||||
return note
|
|
||||||
}*/
|
|
||||||
|
|
||||||
// 添加笔记和内容
|
// 添加笔记和内容
|
||||||
// 这里使用 info.NoteAndContent 接收?
|
// 这里使用 info.NoteAndContent 接收?
|
||||||
func (this *NoteService) AddNoteAndContentForController(note info.Note, noteContent info.NoteContent, updatedUserId string) info.Note {
|
|
||||||
if note.UserId.Hex() != updatedUserId {
|
|
||||||
if !shareService.HasUpdateNotebookPerm(note.UserId.Hex(), updatedUserId, note.NotebookId.Hex()) {
|
|
||||||
Log("NO AUTH11")
|
|
||||||
return info.Note{}
|
|
||||||
} else {
|
|
||||||
Log("HAS AUTH -----------")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
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()
|
||||||
@@ -347,24 +180,7 @@ func (this *NoteService) AddNoteAndContent(note info.Note, noteContent info.Note
|
|||||||
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)
|
||||||
}
|
|
||||||
if note.NoteId != "" {
|
|
||||||
this.AddNoteContent(noteContent)
|
|
||||||
}
|
|
||||||
return note
|
|
||||||
}
|
|
||||||
|
|
||||||
func (this *NoteService) AddNoteAndContentApi(note info.Note, noteContent info.NoteContent, myUserId bson.ObjectId) info.Note {
|
|
||||||
if(note.NoteId.Hex() == "") {
|
|
||||||
noteId := bson.NewObjectId()
|
|
||||||
note.NoteId = noteId
|
|
||||||
}
|
|
||||||
noteContent.NoteId = note.NoteId
|
|
||||||
if note.UserId != myUserId {
|
|
||||||
note = this.AddSharedNote(note, myUserId)
|
|
||||||
} else {
|
|
||||||
note = this.AddNote(note, true)
|
|
||||||
}
|
}
|
||||||
if note.NoteId != "" {
|
if note.NoteId != "" {
|
||||||
this.AddNoteContent(noteContent)
|
this.AddNoteContent(noteContent)
|
||||||
@@ -373,42 +189,22 @@ func (this *NoteService) AddNoteAndContentApi(note info.Note, noteContent info.N
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 修改笔记
|
// 修改笔记
|
||||||
// 这里没有判断usn
|
// [ok] TODO perm还没测
|
||||||
func (this *NoteService) UpdateNote(updatedUserId, noteId string, needUpdate bson.M, usn int) (bool, string, int) {
|
func (this *NoteService) UpdateNote(userId, updatedUserId, noteId string, needUpdate bson.M) bool {
|
||||||
// 是否存在
|
|
||||||
note := this.GetNoteById(noteId)
|
|
||||||
if note.NoteId == "" {
|
|
||||||
return false, "notExists", 0
|
|
||||||
}
|
|
||||||
|
|
||||||
userId := note.UserId.Hex()
|
|
||||||
// updatedUserId 要修改userId的note, 此时需要判断是否有修改权限
|
// updatedUserId 要修改userId的note, 此时需要判断是否有修改权限
|
||||||
if userId != updatedUserId {
|
if userId != updatedUserId {
|
||||||
if !shareService.HasUpdatePerm(userId, updatedUserId, noteId) {
|
if !shareService.HasUpdatePerm(userId, updatedUserId, noteId) {
|
||||||
Log("NO AUTH2")
|
Log("NO AUTH")
|
||||||
return false, "noAuth", 0
|
return false
|
||||||
} else {
|
} else {
|
||||||
Log("HAS AUTH -----------")
|
Log("HAS AUTH -----------")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if usn > 0 && note.Usn != usn {
|
|
||||||
return false, "conflict", 0
|
|
||||||
}
|
|
||||||
|
|
||||||
// 是否已自定义
|
|
||||||
if note.IsBlog && note.HasSelfDefined {
|
|
||||||
delete(needUpdate, "ImgSrc")
|
|
||||||
delete(needUpdate, "Desc")
|
|
||||||
}
|
|
||||||
|
|
||||||
needUpdate["UpdatedUserId"] = bson.ObjectIdHex(updatedUserId);
|
needUpdate["UpdatedUserId"] = bson.ObjectIdHex(updatedUserId);
|
||||||
needUpdate["UpdatedTime"] = time.Now();
|
needUpdate["UpdatedTime"] = time.Now();
|
||||||
afterUsn := userService.IncrUsn(userId);
|
|
||||||
needUpdate["Usn"] = afterUsn
|
|
||||||
|
|
||||||
// 添加tag2
|
// 添加tag2
|
||||||
// TODO 这个tag去掉, 添加tag另外添加, 不要这个
|
|
||||||
if tags, ok := needUpdate["Tags"]; ok {
|
if tags, ok := needUpdate["Tags"]; ok {
|
||||||
tagService.AddTagsI(userId, tags)
|
tagService.AddTagsI(userId, tags)
|
||||||
}
|
}
|
||||||
@@ -416,55 +212,10 @@ func (this *NoteService) UpdateNote(updatedUserId, noteId string, needUpdate bso
|
|||||||
// 是否修改了isBlog
|
// 是否修改了isBlog
|
||||||
// 也要修改noteContents的IsBlog
|
// 也要修改noteContents的IsBlog
|
||||||
if isBlog, ok := needUpdate["IsBlog"]; ok {
|
if isBlog, ok := needUpdate["IsBlog"]; ok {
|
||||||
isBlog2 := isBlog.(bool)
|
db.UpdateByIdAndUserIdMap(db.NoteContents, noteId, userId, bson.M{"IsBlog": isBlog})
|
||||||
if note.IsBlog != isBlog2 {
|
|
||||||
db.UpdateByIdAndUserIdMap(db.NoteContents, noteId, userId, bson.M{"IsBlog": isBlog2})
|
|
||||||
|
|
||||||
// 重新发布成博客
|
|
||||||
if !note.IsBlog {
|
|
||||||
needUpdate["PublicTime"] = needUpdate["UpdatedTime"]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ok := db.UpdateByIdAndUserIdMap(db.Notes, noteId, userId, needUpdate)
|
return db.UpdateByIdAndUserIdMap(db.Notes, noteId, userId, needUpdate)
|
||||||
if !ok {
|
|
||||||
return ok, "", 0
|
|
||||||
}
|
|
||||||
|
|
||||||
// 重新获取之
|
|
||||||
note = this.GetNoteById(noteId)
|
|
||||||
|
|
||||||
hasRecount := false
|
|
||||||
|
|
||||||
// 如果修改了notebookId, 则更新notebookId'count
|
|
||||||
// 两方的notebook也要修改
|
|
||||||
notebookIdI := needUpdate["NotebookId"]
|
|
||||||
if notebookIdI != nil {
|
|
||||||
notebookId := notebookIdI.(bson.ObjectId)
|
|
||||||
if notebookId != "" {
|
|
||||||
notebookService.ReCountNotebookNumberNotes(note.NotebookId.Hex())
|
|
||||||
hasRecount = true
|
|
||||||
notebookService.ReCountNotebookNumberNotes(notebookId.Hex())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 不要多次更新, isTrash = false, = true都要重新统计
|
|
||||||
if !hasRecount {
|
|
||||||
if _, ok := needUpdate["IsTrash"]; ok {
|
|
||||||
notebookService.ReCountNotebookNumberNotes(note.NotebookId.Hex())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true, "", afterUsn
|
|
||||||
}
|
|
||||||
|
|
||||||
// 附件修改, 增加noteIncr
|
|
||||||
func (this *NoteService) IncrNoteUsn(noteId, userId string) int {
|
|
||||||
afterUsn := userService.IncrUsn(userId)
|
|
||||||
db.UpdateByIdAndUserIdMap(db.Notes, noteId, userId,
|
|
||||||
bson.M{"UpdatedTime": time.Now(), "Usn": afterUsn})
|
|
||||||
return afterUsn
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 这里要判断权限, 如果userId != updatedUserId, 那么需要判断权限
|
// 这里要判断权限, 如果userId != updatedUserId, 那么需要判断权限
|
||||||
@@ -479,51 +230,26 @@ func (this *NoteService) UpdateNoteTitle(userId, updatedUserId, noteId, title st
|
|||||||
}
|
}
|
||||||
|
|
||||||
return db.UpdateByIdAndUserIdMap(db.Notes, noteId, userId,
|
return db.UpdateByIdAndUserIdMap(db.Notes, noteId, userId,
|
||||||
bson.M{"UpdatedUserId": bson.ObjectIdHex(updatedUserId), "Title": title, "UpdatedTime": time.Now(), "Usn": userService.IncrUsn(userId)})
|
bson.M{"UpdatedUserId": bson.ObjectIdHex(updatedUserId), "Title": title, "UpdatedTime": time.Now()})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 修改笔记本内容
|
// 修改笔记本内容
|
||||||
// [ok] TODO perm未测
|
// [ok] TODO perm未测
|
||||||
// hasBeforeUpdateNote 之前是否更新过note其它信息, 如果有更新, usn不用更新
|
func (this *NoteService) UpdateNoteContent(userId, updatedUserId, noteId, content, abstract string) bool {
|
||||||
// TODO abstract这里生成
|
|
||||||
func (this *NoteService) UpdateNoteContent(updatedUserId, noteId, content, abstract string, hasBeforeUpdateNote bool, usn int) (bool, string, int) {
|
|
||||||
// 是否已自定义
|
|
||||||
note := this.GetNoteById(noteId)
|
|
||||||
if note.NoteId == "" {
|
|
||||||
return false, "notExists", 0
|
|
||||||
}
|
|
||||||
userId := note.UserId.Hex()
|
|
||||||
// updatedUserId 要修改userId的note, 此时需要判断是否有修改权限
|
// updatedUserId 要修改userId的note, 此时需要判断是否有修改权限
|
||||||
if userId != updatedUserId {
|
if userId != updatedUserId {
|
||||||
if !shareService.HasUpdatePerm(userId, updatedUserId, noteId) {
|
if !shareService.HasUpdatePerm(userId, updatedUserId, noteId) {
|
||||||
Log("NO AUTH")
|
Log("NO AUTH")
|
||||||
return false, "noAuth", 0
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// abstract重置
|
if db.UpdateByIdAndUserIdMap(db.NoteContents, noteId, userId,
|
||||||
data := bson.M{"UpdatedUserId": bson.ObjectIdHex(updatedUserId),
|
bson.M{"UpdatedUserId": bson.ObjectIdHex(updatedUserId),
|
||||||
"Content": content,
|
"Content": content,
|
||||||
"Abstract": abstract,
|
"Abstract": abstract,
|
||||||
"UpdatedTime": time.Now()}
|
"UpdatedTime": time.Now()}) {
|
||||||
|
|
||||||
if note.IsBlog && note.HasSelfDefined {
|
|
||||||
delete(data, "Abstract")
|
|
||||||
}
|
|
||||||
|
|
||||||
// usn, 修改笔记不可能单独修改内容
|
|
||||||
afterUsn := 0
|
|
||||||
// 如果之前没有修改note其它信息, 那么usn++
|
|
||||||
if !hasBeforeUpdateNote {
|
|
||||||
// 需要验证
|
|
||||||
if usn >= 0 && note.Usn != usn {
|
|
||||||
return false, "conflict", 0
|
|
||||||
}
|
|
||||||
afterUsn = userService.IncrUsn(userId)
|
|
||||||
db.UpdateByIdAndUserIdField(db.Notes, noteId, userId, "Usn", usn)
|
|
||||||
}
|
|
||||||
|
|
||||||
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,
|
||||||
@@ -531,11 +257,11 @@ func (this *NoteService) UpdateNoteContent(updatedUserId, noteId, content, abstr
|
|||||||
})
|
})
|
||||||
|
|
||||||
// 更新笔记图片
|
// 更新笔记图片
|
||||||
noteImageService.UpdateNoteImages(userId, noteId, note.ImgSrc, content)
|
noteImageService.UpdateNoteImages(userId, noteId, content)
|
||||||
|
|
||||||
return true, "", afterUsn
|
return true
|
||||||
}
|
}
|
||||||
return false, "", 0
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// ?????
|
// ?????
|
||||||
@@ -549,32 +275,7 @@ func (this *NoteService) updateNoteImages(noteId string, content string) bool {
|
|||||||
// 更新tags
|
// 更新tags
|
||||||
// [ok] [del]
|
// [ok] [del]
|
||||||
func (this *NoteService) UpdateTags(noteId string, userId string, tags []string) bool {
|
func (this *NoteService) UpdateTags(noteId string, userId string, tags []string) bool {
|
||||||
return db.UpdateByIdAndUserIdMap(db.Notes, noteId, userId, bson.M{"Tags": tags, "Usn": userService.IncrUsn(userId)})
|
return db.UpdateByIdAndUserIdField(db.Notes, noteId, userId, "Tags", tags)
|
||||||
}
|
|
||||||
|
|
||||||
func (this *NoteService) ToBlog(userId, noteId string, isBlog, isTop bool) bool {
|
|
||||||
noteUpdate := bson.M{}
|
|
||||||
if isTop {
|
|
||||||
isBlog = true
|
|
||||||
}
|
|
||||||
if !isBlog {
|
|
||||||
isTop = false
|
|
||||||
}
|
|
||||||
noteUpdate["IsBlog"] = isBlog
|
|
||||||
noteUpdate["IsTop"] = isTop
|
|
||||||
if isBlog {
|
|
||||||
noteUpdate["PublicTime"] = time.Now()
|
|
||||||
} else {
|
|
||||||
noteUpdate["HasSelfDefined"] = false
|
|
||||||
}
|
|
||||||
noteUpdate["Usn"] = userService.IncrUsn(userId)
|
|
||||||
|
|
||||||
ok := db.UpdateByIdAndUserIdMap(db.Notes, noteId, userId, noteUpdate)
|
|
||||||
// 重新计算tags
|
|
||||||
go (func() {
|
|
||||||
blogService.ReCountBlogTags(userId)
|
|
||||||
})()
|
|
||||||
return ok
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 移动note
|
// 移动note
|
||||||
@@ -588,9 +289,7 @@ 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),
|
|
||||||
}})
|
|
||||||
|
|
||||||
if re {
|
if re {
|
||||||
// 更新blog状态
|
// 更新blog状态
|
||||||
@@ -612,14 +311,13 @@ func (this *NoteService) MoveNote(noteId, notebookId, userId string) info.Note {
|
|||||||
// 如果自己的blog状态是true, 不用改变,
|
// 如果自己的blog状态是true, 不用改变,
|
||||||
// 否则, 如果notebookId的blog是true, 则改为true之
|
// 否则, 如果notebookId的blog是true, 则改为true之
|
||||||
// 返回blog状态
|
// 返回blog状态
|
||||||
// move, copy时用
|
|
||||||
func (this *NoteService) updateToNotebookBlog(noteId, notebookId, userId string) bool {
|
func (this *NoteService) updateToNotebookBlog(noteId, notebookId, userId string) bool {
|
||||||
if this.IsBlog(noteId) {
|
if this.IsBlog(noteId) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
if notebookService.IsBlog(notebookId) {
|
if notebookService.IsBlog(notebookId) {
|
||||||
db.UpdateByIdAndUserId(db.Notes, noteId, userId,
|
db.UpdateByIdAndUserId(db.Notes, noteId, userId,
|
||||||
bson.M{"$set": bson.M{"IsBlog": true, "PublicTime": time.Now()}}) // life
|
bson.M{"$set": bson.M{"IsBlog": true}})
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
@@ -721,20 +419,15 @@ func (this *NoteService) GetNotebookId(noteId string) bson.ObjectId {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//------------------
|
//------------------
|
||||||
// 搜索Note, 博客使用了
|
// 搜索Note
|
||||||
func (this *NoteService) SearchNote(key, userId string, pageNumber, pageSize int, sortField string, isAsc, isBlog bool) (count int, notes []info.Note) {
|
func (this *NoteService) SearchNote(key, userId string, pageNumber, pageSize int, sortField string, isAsc, 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)
|
||||||
|
|
||||||
// 利用标题和desc, 不用content
|
|
||||||
orQ := []bson.M{
|
|
||||||
bson.M{"Title": bson.M{"$regex": bson.RegEx{".*?" + key + ".*", "i"}}},
|
|
||||||
bson.M{"Desc": bson.M{"$regex": bson.RegEx{".*?" + key + ".*", "i"}}},
|
|
||||||
}
|
|
||||||
// 不是trash的
|
// 不是trash的
|
||||||
query := bson.M{"UserId": bson.ObjectIdHex(userId),
|
query := bson.M{"UserId": bson.ObjectIdHex(userId),
|
||||||
"IsTrash": false,
|
"IsTrash": false,
|
||||||
"$or": orQ,
|
"Title": bson.M{"$regex": bson.RegEx{".*?" + key + ".*", "i"}},
|
||||||
}
|
}
|
||||||
if isBlog {
|
if isBlog {
|
||||||
query["IsBlog"] = true
|
query["IsBlog"] = true
|
||||||
@@ -818,56 +511,9 @@ func (this *NoteService) SearchNoteByTags(tags []string, userId string, pageNumb
|
|||||||
|
|
||||||
//------------
|
//------------
|
||||||
// 统计
|
// 统计
|
||||||
func (this *NoteService) CountNote(userId string) int {
|
func (this *NoteService) CountNote() int {
|
||||||
q := bson.M{"IsTrash": false}
|
return db.Count(db.Notes, bson.M{"IsTrash": false})
|
||||||
if userId != "" {
|
|
||||||
q["UserId"] = bson.ObjectIdHex(userId)
|
|
||||||
}
|
|
||||||
return db.Count(db.Notes, q)
|
|
||||||
}
|
|
||||||
func (this *NoteService) CountBlog(userId string) int {
|
|
||||||
q := bson.M{"IsBlog": true, "IsTrash": false}
|
|
||||||
if userId != "" {
|
|
||||||
q["UserId"] = bson.ObjectIdHex(userId)
|
|
||||||
}
|
|
||||||
return db.Count(db.Notes, q)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 通过标签来查询
|
|
||||||
func (this *NoteService) CountNoteByTag(userId string, tag string) int {
|
|
||||||
if tag == "" {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
query := bson.M{"UserId": bson.ObjectIdHex(userId),
|
|
||||||
// "IsTrash": false,
|
|
||||||
"IsDeleted": false,
|
|
||||||
"Tags": bson.M{"$in": []string{tag}}}
|
|
||||||
return db.Count(db.Notes, query)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 删除tag
|
|
||||||
// 返回所有note的Usn
|
|
||||||
func (this *NoteService) UpdateNoteToDeleteTag(userId string, targetTag string) map[string]int {
|
|
||||||
query := bson.M{"UserId": bson.ObjectIdHex(userId),
|
|
||||||
"Tags": bson.M{"$in": []string{targetTag}}}
|
|
||||||
notes := []info.Note{}
|
|
||||||
db.ListByQ(db.Notes, query, ¬es)
|
|
||||||
ret := map[string]int{}
|
|
||||||
for _, note := range notes {
|
|
||||||
tags := note.Tags
|
|
||||||
if tags == nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
for i, tag := range tags {
|
|
||||||
if tag == targetTag {
|
|
||||||
tags = tags
|
|
||||||
tags = append(tags[:i], tags[i+1:]...)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
usn := userService.IncrUsn(userId)
|
|
||||||
db.UpdateByQMap(db.Notes, bson.M{"_id": note.NoteId}, bson.M{"Usn": usn, "Tags": tags})
|
|
||||||
ret[note.NoteId.Hex()] = usn
|
|
||||||
}
|
|
||||||
return ret
|
|
||||||
}
|
}
|
||||||
|
func (this *NoteService) CountBlog() int {
|
||||||
|
return db.Count(db.Notes, bson.M{"IsBlog": true, "IsTrash": false})
|
||||||
|
}
|
||||||
+40
-130
@@ -8,8 +8,6 @@ import (
|
|||||||
. "github.com/leanote/leanote/app/lea"
|
. "github.com/leanote/leanote/app/lea"
|
||||||
"sort"
|
"sort"
|
||||||
"time"
|
"time"
|
||||||
"strings"
|
|
||||||
// "html"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// 笔记本
|
// 笔记本
|
||||||
@@ -42,9 +40,7 @@ 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 = 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
|
||||||
newNotebooks.ParentNotebookId = each.ParentNotebookId
|
newNotebooks.ParentNotebookId = each.ParentNotebookId
|
||||||
@@ -105,34 +101,13 @@ func (this *NotebookService) GetNotebookById(notebookId string) info.Notebook {
|
|||||||
db.Get(db.Notebooks, notebookId, ¬ebook)
|
db.Get(db.Notebooks, notebookId, ¬ebook)
|
||||||
return notebook
|
return notebook
|
||||||
}
|
}
|
||||||
func (this *NotebookService) GetNotebookByUserIdAndUrlTitle(userId, notebookIdOrUrlTitle string) info.Notebook {
|
|
||||||
notebook := info.Notebook{}
|
|
||||||
if IsObjectId(notebookIdOrUrlTitle) {
|
|
||||||
db.Get(db.Notebooks, notebookIdOrUrlTitle, ¬ebook)
|
|
||||||
} else {
|
|
||||||
db.GetByQ(db.Notebooks, bson.M{"UserId": bson.ObjectIdHex(userId), "UrlTitle": encodeValue(notebookIdOrUrlTitle)}, ¬ebook)
|
|
||||||
}
|
|
||||||
return notebook
|
|
||||||
}
|
|
||||||
|
|
||||||
// 同步的方法
|
|
||||||
func (this *NotebookService) GeSyncNotebooks(userId string, afterUsn, maxEntry int) ([]info.Notebook) {
|
|
||||||
notebooks := []info.Notebook{}
|
|
||||||
q := db.Notebooks.Find(bson.M{"UserId": bson.ObjectIdHex(userId), "Usn": bson.M{"$gt": afterUsn}});
|
|
||||||
q.Sort("Usn").Limit(maxEntry).All(¬ebooks)
|
|
||||||
return notebooks
|
|
||||||
}
|
|
||||||
|
|
||||||
// 得到用户下所有的notebook
|
// 得到用户下所有的notebook
|
||||||
// 排序好之后返回
|
// 排序好之后返回
|
||||||
// [ok]
|
// [ok]
|
||||||
func (this *NotebookService) GetNotebooks(userId string) info.SubNotebooks {
|
func (this *NotebookService) GetNotebooks(userId string) info.SubNotebooks {
|
||||||
userNotebooks := []info.Notebook{}
|
userNotebooks := []info.Notebook{}
|
||||||
orQ := []bson.M{
|
db.Notebooks.Find(bson.M{"UserId": bson.ObjectIdHex(userId)}).All(&userNotebooks)
|
||||||
bson.M{"IsDeleted": false},
|
|
||||||
bson.M{"IsDeleted": bson.M{"$exists": false}},
|
|
||||||
}
|
|
||||||
db.Notebooks.Find(bson.M{"UserId": bson.ObjectIdHex(userId), "$or": orQ}).All(&userNotebooks)
|
|
||||||
|
|
||||||
if len(userNotebooks) == 0 {
|
if len(userNotebooks) == 0 {
|
||||||
return nil
|
return nil
|
||||||
@@ -157,46 +132,13 @@ func (this *NotebookService) GetNotebooksByNotebookIds(notebookIds []bson.Object
|
|||||||
|
|
||||||
// 添加
|
// 添加
|
||||||
// [ok]
|
// [ok]
|
||||||
func (this *NotebookService) AddNotebook(notebook info.Notebook) (bool, info.Notebook) {
|
func (this *NotebookService) AddNotebook(notebook info.Notebook) bool {
|
||||||
notebook.UrlTitle = GetUrTitle(notebook.UserId.Hex(), notebook.Title, "notebook")
|
|
||||||
notebook.Usn = userService.IncrUsn(notebook.UserId.Hex())
|
|
||||||
now := time.Now()
|
|
||||||
notebook.CreatedTime = now
|
|
||||||
notebook.UpdatedTime = now
|
|
||||||
err := db.Notebooks.Insert(notebook)
|
err := db.Notebooks.Insert(notebook)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, notebook
|
panic(err)
|
||||||
}
|
|
||||||
return true, notebook
|
|
||||||
}
|
|
||||||
// 更新笔记, api
|
|
||||||
func (this *NotebookService) UpdateNotebookApi(userId, notebookId, title, parentNotebookId string, seq, usn int) (bool, string, info.Notebook) {
|
|
||||||
if notebookId == "" {
|
|
||||||
return false, "notebookIdNotExists", info.Notebook{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 先判断usn是否和数据库的一样, 如果不一样, 则冲突, 不保存
|
|
||||||
notebook := this.GetNotebookById(notebookId)
|
|
||||||
// 不存在
|
|
||||||
if notebook.NotebookId == "" {
|
|
||||||
return false, "notExists", notebook
|
|
||||||
} else if notebook.Usn != usn {
|
|
||||||
return false, "conflict", notebook
|
|
||||||
}
|
|
||||||
notebook.Usn = userService.IncrUsn(userId);
|
|
||||||
notebook.Title = title;
|
|
||||||
|
|
||||||
updates := bson.M{"Title": title, "Usn": notebook.Usn, "Seq": seq, "UpdatedTime": time.Now()};
|
|
||||||
if(parentNotebookId != "" && bson.IsObjectIdHex(parentNotebookId)) {
|
|
||||||
updates["ParentNotebookId"] = bson.ObjectIdHex(parentNotebookId);
|
|
||||||
} else {
|
} else {
|
||||||
updates["ParentNotebookId"] = "";
|
|
||||||
}
|
}
|
||||||
ok := db.UpdateByIdAndUserIdMap(db.Notebooks, notebookId, userId, updates);
|
return true
|
||||||
if ok {
|
|
||||||
return ok, "", this.GetNotebookById(notebookId)
|
|
||||||
}
|
|
||||||
return false, "", notebook
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 判断是否是blog
|
// 判断是否是blog
|
||||||
@@ -222,72 +164,51 @@ func (this *NotebookService) UpdateNotebook(notebook info.Notebook) bool {
|
|||||||
// 更新笔记本标题
|
// 更新笔记本标题
|
||||||
// [ok]
|
// [ok]
|
||||||
func (this *NotebookService) UpdateNotebookTitle(notebookId, userId, title string) bool {
|
func (this *NotebookService) UpdateNotebookTitle(notebookId, userId, title string) bool {
|
||||||
usn := userService.IncrUsn(userId)
|
return db.UpdateByIdAndUserIdField(db.Notebooks, notebookId, userId, "Title", title)
|
||||||
return db.UpdateByIdAndUserIdMap(db.Notebooks, notebookId, userId, bson.M{"Title": title, "Usn": usn})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 更新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)
|
|
||||||
return db.UpdateByIdAndUserIdMap(db.Notebooks, notebookId, userId, needUpdate)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ToBlog or Not
|
|
||||||
func (this *NotebookService) ToBlog(userId, notebookId string, isBlog bool) (bool) {
|
|
||||||
updates := bson.M{"IsBlog": isBlog, "Usn": userService.IncrUsn(userId)}
|
|
||||||
// 笔记本
|
|
||||||
db.UpdateByIdAndUserIdMap(db.Notebooks, notebookId, userId, updates)
|
|
||||||
|
|
||||||
// 更新笔记
|
// 如果有IsBlog之类的, 需要特殊处理
|
||||||
q := bson.M{"UserId": bson.ObjectIdHex(userId),
|
if isBlog, ok := needUpdate["IsBlog"]; ok {
|
||||||
|
// 设为blog/取消, 把它下面所有的note都设为isBlog
|
||||||
|
if is, ok2 := isBlog.(bool); ok2 {
|
||||||
|
q := bson.M{"UserId": bson.ObjectIdHex(userId),
|
||||||
"NotebookId": bson.ObjectIdHex(notebookId)}
|
"NotebookId": bson.ObjectIdHex(notebookId)}
|
||||||
data := bson.M{"IsBlog": isBlog}
|
data := bson.M{"IsBlog": is}
|
||||||
if isBlog {
|
if is {
|
||||||
data["PublicTime"] = time.Now()
|
data["PublicTime"] = time.Now()
|
||||||
} else {
|
}
|
||||||
data["HasSelfDefined"] = false
|
db.UpdateByQMap(db.Notes, q, data)
|
||||||
}
|
|
||||||
// usn
|
// noteContents也更新, 这个就麻烦了, noteContents表没有NotebookId
|
||||||
data["Usn"] = userService.IncrUsn(userId)
|
// 先查该notebook下所有notes, 得到id
|
||||||
db.UpdateByQMap(db.Notes, q, data)
|
notes := []info.Note{}
|
||||||
|
db.ListByQWithFields(db.Notes, q, []string{"_id"}, ¬es)
|
||||||
// noteContents也更新, 这个就麻烦了, noteContents表没有NotebookId
|
if len(notes) > 0 {
|
||||||
// 先查该notebook下所有notes, 得到id
|
noteIds := make([]bson.ObjectId, len(notes))
|
||||||
notes := []info.Note{}
|
for i, each := range notes {
|
||||||
db.ListByQWithFields(db.Notes, q, []string{"_id"}, ¬es)
|
noteIds[i] = each.NoteId
|
||||||
if len(notes) > 0 {
|
}
|
||||||
noteIds := make([]bson.ObjectId, len(notes))
|
db.UpdateByQMap(db.NoteContents, bson.M{"_id": bson.M{"$in": noteIds}}, bson.M{"IsBlog": isBlog})
|
||||||
for i, each := range notes {
|
}
|
||||||
noteIds[i] = each.NoteId
|
|
||||||
}
|
}
|
||||||
db.UpdateByQMap(db.NoteContents, bson.M{"_id": bson.M{"$in": noteIds}}, bson.M{"IsBlog": isBlog})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 重新计算tags
|
return db.UpdateByIdAndUserIdMap(db.Notebooks, notebookId, userId, needUpdate)
|
||||||
go (func() {
|
|
||||||
blogService.ReCountBlogTags(userId)
|
|
||||||
})()
|
|
||||||
|
|
||||||
return true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 查看是否有子notebook
|
// 查看是否有子notebook
|
||||||
// 先查看该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)}) == 0 { // 无
|
||||||
"UserId": bson.ObjectIdHex(userId),
|
|
||||||
"IsDeleted": false,
|
|
||||||
}) == 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}) == 0 { // 不包含trash
|
||||||
"IsDeleted": false}) == 0 { // 不包含trash
|
return db.DeleteByIdAndUserId(db.Notebooks, notebookId, userId), ""
|
||||||
// 不是真删除 1/20, 为了同步笔记本
|
|
||||||
ok := db.UpdateByQMap(db.Notebooks, bson.M{"_id": bson.ObjectIdHex(notebookId)}, bson.M{"IsDeleted": true, "Usn": userService.IncrUsn(userId)})
|
|
||||||
return ok, ""
|
|
||||||
// return db.DeleteByIdAndUserId(db.Notebooks, notebookId, userId), ""
|
|
||||||
}
|
}
|
||||||
return false, "笔记本下有笔记"
|
return false, "笔记本下有笔记"
|
||||||
} else {
|
} else {
|
||||||
@@ -295,18 +216,6 @@ func (this *NotebookService) DeleteNotebook(userId, notebookId string) (bool, st
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// API调用, 删除笔记本, 不作笔记控制
|
|
||||||
func (this *NotebookService) DeleteNotebookForce(userId, notebookId string, usn int) (bool, string) {
|
|
||||||
notebook := this.GetNotebookById(notebookId)
|
|
||||||
// 不存在
|
|
||||||
if notebook.NotebookId == "" {
|
|
||||||
return false, "notExists"
|
|
||||||
} else if notebook.Usn != usn {
|
|
||||||
return false, "conflict"
|
|
||||||
}
|
|
||||||
return db.DeleteByIdAndUserId(db.Notebooks, notebookId, userId), ""
|
|
||||||
}
|
|
||||||
|
|
||||||
// 排序
|
// 排序
|
||||||
// 传入 notebookId => Seq
|
// 传入 notebookId => Seq
|
||||||
// 为什么要传入userId, 防止修改其它用户的信息 (恶意)
|
// 为什么要传入userId, 防止修改其它用户的信息 (恶意)
|
||||||
@@ -317,7 +226,7 @@ func (this *NotebookService) SortNotebooks(userId string, notebookId2Seqs map[st
|
|||||||
}
|
}
|
||||||
|
|
||||||
for notebookId, seq := range notebookId2Seqs {
|
for notebookId, seq := range notebookId2Seqs {
|
||||||
if !db.UpdateByIdAndUserIdMap(db.Notebooks, notebookId, userId, bson.M{"Seq": seq, "Usn": userService.IncrUsn(userId)}) {
|
if !db.UpdateByIdAndUserIdField2(db.Notebooks, bson.ObjectIdHex(notebookId), bson.ObjectIdHex(userId), "Seq", seq) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -325,14 +234,15 @@ func (this *NotebookService) SortNotebooks(userId string, notebookId2Seqs map[st
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// 排序和设置父
|
|
||||||
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 {
|
||||||
|
userIdO := bson.ObjectIdHex(userId)
|
||||||
|
|
||||||
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.UpdateByIdAndUserIdField2(db.Notebooks, bson.ObjectIdHex(curNotebookId), userIdO, "ParentNotebookId", "");
|
||||||
} else {
|
} else {
|
||||||
ok = db.UpdateByIdAndUserIdMap(db.Notebooks, curNotebookId, userId, bson.M{"ParentNotebookId": bson.ObjectIdHex(parentNotebookId), "Usn": userService.IncrUsn(userId)});
|
ok = db.UpdateByIdAndUserIdField2(db.Notebooks, bson.ObjectIdHex(curNotebookId), userIdO, "ParentNotebookId", bson.ObjectIdHex(parentNotebookId));
|
||||||
}
|
}
|
||||||
|
|
||||||
if !ok {
|
if !ok {
|
||||||
@@ -341,7 +251,7 @@ func (this *NotebookService) DragNotebooks(userId string, curNotebookId string,
|
|||||||
|
|
||||||
// 排序
|
// 排序
|
||||||
for seq, notebookId := range siblings {
|
for seq, notebookId := range siblings {
|
||||||
if !db.UpdateByIdAndUserIdMap(db.Notebooks, notebookId, userId, bson.M{"Seq": seq, "Usn": userService.IncrUsn(userId)}) {
|
if !db.UpdateByIdAndUserIdField2(db.Notebooks, bson.ObjectIdHex(notebookId), userIdO, "Seq", seq) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -354,7 +264,7 @@ func (this *NotebookService) DragNotebooks(userId string, curNotebookId string,
|
|||||||
// trashService: DeleteNote (recove不用, 都统一在MoveNote里了)
|
// trashService: DeleteNote (recove不用, 都统一在MoveNote里了)
|
||||||
func (this *NotebookService) ReCountNotebookNumberNotes(notebookId string) bool {
|
func (this *NotebookService) ReCountNotebookNumberNotes(notebookId string) bool {
|
||||||
notebookIdO := bson.ObjectIdHex(notebookId)
|
notebookIdO := bson.ObjectIdHex(notebookId)
|
||||||
count := db.Count(db.Notes, bson.M{"NotebookId": notebookIdO, "IsTrash": false, "IsDeleted": false})
|
count := db.Count(db.Notes, bson.M{"NotebookId": notebookIdO, "IsTrash": false})
|
||||||
Log(count)
|
Log(count)
|
||||||
Log(notebookId)
|
Log(notebookId)
|
||||||
return db.UpdateByQField(db.Notebooks, bson.M{"_id": notebookIdO}, "NumberNotes", count)
|
return db.UpdateByQField(db.Notebooks, bson.M{"_id": notebookIdO}, "NumberNotes", count)
|
||||||
|
|||||||
@@ -45,13 +45,9 @@ 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 {
|
|
||||||
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", Md5(pwd))
|
||||||
|
|
||||||
// 删除token
|
// 删除token
|
||||||
tokenService.DeleteToken(tokenInfo.UserId.Hex(), info.TokenPwd)
|
tokenService.DeleteToken(tokenInfo.UserId.Hex(), info.TokenPwd)
|
||||||
|
|||||||
@@ -69,20 +69,3 @@ func (this *SessionService) SetCaptcha(sessionId, captcha string) bool {
|
|||||||
Log(ok)
|
Log(ok)
|
||||||
return ok
|
return ok
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------
|
|
||||||
// API
|
|
||||||
func (this *SessionService) GetUserId(sessionId string) string {
|
|
||||||
session := this.Get(sessionId)
|
|
||||||
// 更新updateTime, 避免过期
|
|
||||||
db.UpdateByQMap(db.Sessions, bson.M{"SessionId": sessionId},
|
|
||||||
bson.M{"UpdatedTime": time.Now()})
|
|
||||||
return session.UserId
|
|
||||||
}
|
|
||||||
|
|
||||||
// 登录成功后设置userId
|
|
||||||
func (this *SessionService) SetUserId(sessionId, userId string) bool {
|
|
||||||
this.Get(sessionId)
|
|
||||||
ok := this.Update(sessionId, "UserId", userId)
|
|
||||||
return ok
|
|
||||||
}
|
|
||||||
+78
-329
@@ -13,10 +13,7 @@ import (
|
|||||||
type ShareService struct {
|
type ShareService struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------
|
//-----------------
|
||||||
// 返回shareNotebooks, sharedUserInfos
|
|
||||||
// info.ShareNotebooksByUser, []info.User
|
|
||||||
|
|
||||||
// 总体来说, 这个方法比较麻烦, 速度未知. 以后按以下方案来缓存用户基础数据
|
// 总体来说, 这个方法比较麻烦, 速度未知. 以后按以下方案来缓存用户基础数据
|
||||||
|
|
||||||
// 以后建个用户的基本数据表, 放所有notebook, sharedNotebook的缓存!!
|
// 以后建个用户的基本数据表, 放所有notebook, sharedNotebook的缓存!!
|
||||||
@@ -30,60 +27,23 @@ type ShareService struct {
|
|||||||
// 3 每个层按seq进行排序
|
// 3 每个层按seq进行排序
|
||||||
// 4 按用户分组
|
// 4 按用户分组
|
||||||
// [ok]
|
// [ok]
|
||||||
|
|
||||||
// 谁共享给了我的Query
|
|
||||||
func (this *ShareService) getOrQ(userId string) bson.M {
|
|
||||||
// 得到我和和我参与的组织
|
|
||||||
groupIds := groupService.GetMineAndBelongToGroupIds(userId)
|
|
||||||
|
|
||||||
q := bson.M{}
|
|
||||||
if len(groupIds) > 0 {
|
|
||||||
orQ := []bson.M{
|
|
||||||
bson.M{"ToUserId": bson.ObjectIdHex(userId)},
|
|
||||||
bson.M{"ToGroupId": bson.M{"$in": groupIds}},
|
|
||||||
}
|
|
||||||
// 不是trash的
|
|
||||||
q["$or"] = orQ
|
|
||||||
} else {
|
|
||||||
q["ToUserId"] = bson.ObjectIdHex(userId);
|
|
||||||
}
|
|
||||||
return q
|
|
||||||
}
|
|
||||||
|
|
||||||
// 得到共享给我的笔记本和用户(谁共享给了我)
|
|
||||||
func (this *ShareService) GetShareNotebooks(userId string) (info.ShareNotebooksByUser, []info.User) {
|
func (this *ShareService) GetShareNotebooks(userId string) (info.ShareNotebooksByUser, []info.User) {
|
||||||
myUserId := userId
|
//-------------
|
||||||
|
// 查询HasShareNote表得到所有其它用户信息
|
||||||
|
hasShareNotes := []info.HasShareNote{}
|
||||||
|
db.ListByQ(db.HasShareNotes, bson.M{"ToUserId": bson.ObjectIdHex(userId)}, &hasShareNotes);
|
||||||
|
|
||||||
// 得到共享给我的用户s信息
|
userIds := make([]bson.ObjectId, len(hasShareNotes))
|
||||||
// 得到我参与的组织
|
for i, each := range hasShareNotes {
|
||||||
q := this.getOrQ(userId)
|
userIds[i] = each.UserId
|
||||||
|
|
||||||
// 不查hasShareNotes
|
|
||||||
// 直接查shareNotes, shareNotebooks表得到userId
|
|
||||||
userIds1 := []bson.ObjectId{}
|
|
||||||
db.Distinct(db.ShareNotes, q, "UserId", &userIds1)
|
|
||||||
|
|
||||||
userIds2 := []bson.ObjectId{}
|
|
||||||
db.Distinct(db.ShareNotebooks, q, "UserId", &userIds2) // BUG之前是userId1, 2014/12/29
|
|
||||||
|
|
||||||
userIds := append(userIds1, userIds2...)
|
|
||||||
|
|
||||||
userInfos := userService.GetUserInfosOrderBySeq(userIds);
|
|
||||||
// 不要我的id
|
|
||||||
for i, userInfo := range userInfos {
|
|
||||||
if userInfo.UserId.Hex() == myUserId {
|
|
||||||
userInfos = append(userInfos[:i], userInfos[i+1:]...)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
userInfos := userService.GetUserInfosOrderBySeq(userIds);
|
||||||
|
|
||||||
//--------------------
|
//--------------------
|
||||||
// 得到他们共享给我的notebooks
|
// 得到他们共享给我的notebooks
|
||||||
|
|
||||||
// 这里可能会得到重复的记录
|
|
||||||
// 权限: 笔记本分享给个人 > 笔记本分享给组织
|
|
||||||
shareNotebooks := []info.ShareNotebook{}
|
shareNotebooks := []info.ShareNotebook{}
|
||||||
db.ShareNotebooks.Find(q).Sort("-ToUserId").All(&shareNotebooks) // 按ToUserId降序排序, 那么有ToUserId的在前面
|
db.ShareNotebooks.Find(bson.M{"ToUserId": bson.ObjectIdHex(userId)}).All(&shareNotebooks)
|
||||||
|
|
||||||
if len(shareNotebooks) == 0 {
|
if len(shareNotebooks) == 0 {
|
||||||
return nil, userInfos
|
return nil, userInfos
|
||||||
@@ -92,15 +52,12 @@ func (this *ShareService) GetShareNotebooks(userId string) (info.ShareNotebooksB
|
|||||||
shareNotebooksLen := len(shareNotebooks)
|
shareNotebooksLen := len(shareNotebooks)
|
||||||
|
|
||||||
// 找到了所有的notbookId, 那么找notebook表得到其详细信息
|
// 找到了所有的notbookId, 那么找notebook表得到其详细信息
|
||||||
notebookIds := []bson.ObjectId{}
|
notebookIds := make([]bson.ObjectId, shareNotebooksLen)
|
||||||
shareNotebooksMap := make(map[bson.ObjectId]info.ShareNotebook, shareNotebooksLen)
|
shareNotebooksMap := make(map[bson.ObjectId]info.ShareNotebook, shareNotebooksLen)
|
||||||
for _, each := range shareNotebooks {
|
for i, each := range shareNotebooks {
|
||||||
// 之后的就不要了, 只留权限高的
|
// 默认的是没有notebookId的
|
||||||
if _, ok := shareNotebooksMap[each.NotebookId]; !ok {
|
notebookIds[i] = each.NotebookId
|
||||||
// 默认的是没有notebookId的
|
shareNotebooksMap[each.NotebookId] = each
|
||||||
notebookIds = append(notebookIds, each.NotebookId)
|
|
||||||
shareNotebooksMap[each.NotebookId] = each
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 1, 2
|
// 1, 2
|
||||||
@@ -113,11 +70,6 @@ func (this *ShareService) GetShareNotebooks(userId string) (info.ShareNotebooksB
|
|||||||
// 先建立userId => []
|
// 先建立userId => []
|
||||||
for _, eachSub := range subShareNotebooks {
|
for _, eachSub := range subShareNotebooks {
|
||||||
userId := eachSub.Notebook.UserId
|
userId := eachSub.Notebook.UserId
|
||||||
// 我自己的, 算了
|
|
||||||
if userId.Hex() == myUserId {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, ok := shareNotebooksByUsersMap[userId]; ok {
|
if _, ok := shareNotebooksByUsersMap[userId]; ok {
|
||||||
shareNotebooksByUsersMap[userId] = append(shareNotebooksByUsersMap[userId], eachSub)
|
shareNotebooksByUsersMap[userId] = append(shareNotebooksByUsersMap[userId], eachSub)
|
||||||
} else {
|
} else {
|
||||||
@@ -175,13 +127,9 @@ func (this *ShareService) parseToSubShareNotebooks(subNotebooks *info.SubNoteboo
|
|||||||
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["NotebookId"] = bson.ObjectIdHex(notebookId);
|
|
||||||
q["UserId"] = bson.ObjectIdHex(sharedUserId);
|
|
||||||
shareNotebook := info.ShareNotebook{}
|
shareNotebook := info.ShareNotebook{}
|
||||||
db.GetByQ(db.ShareNotebooks,
|
db.GetByQ(db.ShareNotebooks, bson.M{"NotebookId": bson.ObjectIdHex(notebookId),
|
||||||
q,
|
"UserId": bson.ObjectIdHex(sharedUserId), "ToUserId": bson.ObjectIdHex(myUserId)}, &shareNotebook)
|
||||||
&shareNotebook)
|
|
||||||
|
|
||||||
if shareNotebook.NotebookId == "" {
|
if shareNotebook.NotebookId == "" {
|
||||||
return nil
|
return nil
|
||||||
@@ -198,19 +146,7 @@ func (this *ShareService) ListShareNotesByNotebookId(notebookId, myUserId, share
|
|||||||
for i, note := range notes {
|
for i, note := range notes {
|
||||||
noteIds[i] = note.NoteId
|
noteIds[i] = note.NoteId
|
||||||
}
|
}
|
||||||
// 笔记的权限
|
notePerms := this.getNotesPerm(noteIds, myUserId, sharedUserId);
|
||||||
shareNotes := []info.ShareNote{}
|
|
||||||
delete(q, "NotebookId")
|
|
||||||
q["NoteId"] = bson.M{"$in": noteIds}
|
|
||||||
db.ShareNotes.Find(q).Sort("-ToUserId").All(&shareNotes) // 给个的权限>给组织的权限
|
|
||||||
notePerms := map[bson.ObjectId]int{}
|
|
||||||
for _, each := range shareNotes {
|
|
||||||
if _, ok := notePerms[each.NoteId]; !ok {
|
|
||||||
notePerms[each.NoteId] = each.Perm
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Log("笔记权限")
|
|
||||||
LogJ(notePerms);
|
|
||||||
|
|
||||||
// 3.2 组合
|
// 3.2 组合
|
||||||
notesWithPerm := make([]info.ShareNoteWithPerm, len(notes))
|
notesWithPerm := make([]info.ShareNoteWithPerm, len(notes))
|
||||||
@@ -226,21 +162,17 @@ func (this *ShareService) ListShareNotesByNotebookId(notebookId, myUserId, share
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 得到note的perm信息
|
// 得到note的perm信息
|
||||||
//func (this *ShareService) getNotesPerm(noteIds []bson.ObjectId, myUserId, sharedUserId string) map[bson.ObjectId]int {
|
func (this *ShareService) getNotesPerm(noteIds []bson.ObjectId, myUserId, sharedUserId string) map[bson.ObjectId]int {
|
||||||
// shareNotes := []info.ShareNote{}
|
shareNotes := []info.ShareNote{}
|
||||||
// db.ListByQ(db.ShareNotes,
|
db.ListByQ(db.ShareNotes, bson.M{"NoteId": bson.M{"$in": noteIds}, "UserId": bson.ObjectIdHex(sharedUserId), "ToUserId": bson.ObjectIdHex(myUserId)}, &shareNotes)
|
||||||
// bson.M{
|
|
||||||
// "NoteId": bson.M{"$in": noteIds},
|
notesPerm := make(map[bson.ObjectId]int, len(shareNotes))
|
||||||
// "UserId": bson.ObjectIdHex(sharedUserId),
|
for _, each := range shareNotes {
|
||||||
// "ToUserId": bson.ObjectIdHex(myUserId)}, &shareNotes)
|
notesPerm[each.NoteId] = each.Perm
|
||||||
//
|
}
|
||||||
// notesPerm := make(map[bson.ObjectId]int, len(shareNotes))
|
|
||||||
// for _, each := range shareNotes {
|
return notesPerm
|
||||||
// notesPerm[each.NoteId] = each.Perm
|
}
|
||||||
// }
|
|
||||||
//
|
|
||||||
// return notesPerm
|
|
||||||
//}
|
|
||||||
|
|
||||||
// 得到默认的单个的notes 共享集
|
// 得到默认的单个的notes 共享集
|
||||||
// 如果真要支持排序, 这里得到所有共享的notes, 到noteService方再sort和limit
|
// 如果真要支持排序, 这里得到所有共享的notes, 到noteService方再sort和limit
|
||||||
@@ -252,12 +184,9 @@ func (this *ShareService) ListShareNotes(myUserId, sharedUserId string,
|
|||||||
skipNum, _ := parsePageAndSort(pageNumber, pageSize, sortField, isAsc)
|
skipNum, _ := parsePageAndSort(pageNumber, pageSize, sortField, isAsc)
|
||||||
shareNotes := []info.ShareNote{}
|
shareNotes := []info.ShareNote{}
|
||||||
|
|
||||||
q := this.getOrQ(myUserId)
|
|
||||||
q["UserId"] = bson.ObjectIdHex(sharedUserId);
|
|
||||||
|
|
||||||
db.ShareNotes.
|
db.ShareNotes.
|
||||||
Find(q).
|
Find(bson.M{"UserId": bson.ObjectIdHex(sharedUserId), "ToUserId": bson.ObjectIdHex(myUserId)}).
|
||||||
Sort("-ToUserId"). // 给个人的权限 > 给组织的权限
|
// Sort(sortFieldR).
|
||||||
Skip(skipNum).
|
Skip(skipNum).
|
||||||
Limit(pageSize).
|
Limit(pageSize).
|
||||||
All(&shareNotes)
|
All(&shareNotes)
|
||||||
@@ -271,20 +200,15 @@ func (this *ShareService) ListShareNotes(myUserId, sharedUserId string,
|
|||||||
noteIds[i] = each.NoteId
|
noteIds[i] = each.NoteId
|
||||||
}
|
}
|
||||||
notes := noteService.ListNotesByNoteIds(noteIds)
|
notes := noteService.ListNotesByNoteIds(noteIds)
|
||||||
notesMap := map[bson.ObjectId]info.Note{}
|
notesMap := make(map[bson.ObjectId]info.Note, len(notes))
|
||||||
for _, each := range notes {
|
for _, each := range notes {
|
||||||
notesMap[each.NoteId] = each
|
notesMap[each.NoteId] = each
|
||||||
}
|
}
|
||||||
|
|
||||||
// 将shareNotes与notes结合起来
|
// 将shareNotes与notes结合起来
|
||||||
notesWithPerm := []info.ShareNoteWithPerm{}
|
notesWithPerm := make([]info.ShareNoteWithPerm, len(shareNotes))
|
||||||
hasAdded := map[bson.ObjectId]bool{} // 防止重复, 只要前面权限高的
|
for i, each := range shareNotes {
|
||||||
for _, each := range shareNotes {
|
notesWithPerm[i] = info.ShareNoteWithPerm{notesMap[each.NoteId], each.Perm}
|
||||||
if !hasAdded[each.NoteId] {
|
|
||||||
// 待优化
|
|
||||||
notesWithPerm = append(notesWithPerm, info.ShareNoteWithPerm{notesMap[each.NoteId], each.Perm})
|
|
||||||
hasAdded[each.NoteId] = true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return notesWithPerm
|
return notesWithPerm
|
||||||
}
|
}
|
||||||
@@ -310,11 +234,7 @@ func (this *ShareService) AddShareNotebook(notebookId string, perm int, userId,
|
|||||||
if toUserId == "" {
|
if toUserId == "" {
|
||||||
return false, "无该用户", ""
|
return false, "无该用户", ""
|
||||||
}
|
}
|
||||||
return this.AddShareNotebookToUserId(notebookId, perm, userId, toUserId)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 第三方注册时没有email
|
|
||||||
func (this *ShareService) AddShareNotebookToUserId(notebookId string, perm int, userId, toUserId string) (bool, string, string) {
|
|
||||||
// 添加一条记录说明两者存在关系
|
// 添加一条记录说明两者存在关系
|
||||||
this.AddHasShareNote(userId, toUserId);
|
this.AddHasShareNote(userId, toUserId);
|
||||||
|
|
||||||
@@ -347,11 +267,7 @@ func (this *ShareService) AddShareNote(noteId string, perm int, userId, email st
|
|||||||
if toUserId == "" {
|
if toUserId == "" {
|
||||||
return false, "无该用户", ""
|
return false, "无该用户", ""
|
||||||
}
|
}
|
||||||
return this.AddShareNoteToUserId(noteId, perm, userId, toUserId)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 第三方测试没有userId
|
|
||||||
func (this *ShareService) AddShareNoteToUserId(noteId string, perm int, userId, toUserId string) (bool, string, string) {
|
|
||||||
// 添加一条记录说明两者存在关系
|
// 添加一条记录说明两者存在关系
|
||||||
this.AddHasShareNote(userId, toUserId);
|
this.AddHasShareNote(userId, toUserId);
|
||||||
|
|
||||||
@@ -370,25 +286,19 @@ func (this *ShareService) AddShareNoteToUserId(noteId string, perm int, userId,
|
|||||||
return db.Insert(db.ShareNotes, shareNote), "", toUserId
|
return db.Insert(db.ShareNotes, shareNote), "", toUserId
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// updatedUserId是否有查看userId noteId的权限?
|
// updatedUserId是否有查看userId noteId的权限?
|
||||||
// userId是所有者
|
|
||||||
func (this *ShareService) HasReadPerm(userId, updatedUserId, noteId string) bool {
|
func (this *ShareService) HasReadPerm(userId, updatedUserId, noteId string) bool {
|
||||||
q := this.getOrQ(updatedUserId) // (toUserId == "xxx" || ToGroupId in (1, 2,3))
|
if !db.Has(db.ShareNotes,
|
||||||
q["UserId"] = bson.ObjectIdHex(userId)
|
bson.M{"UserId": bson.ObjectIdHex(userId), "ToUserId": bson.ObjectIdHex(updatedUserId), "NoteId": bson.ObjectIdHex(noteId)}) {
|
||||||
q["NoteId"] = bson.ObjectIdHex(noteId)
|
|
||||||
if !db.Has(db.ShareNotes, q) {
|
|
||||||
// noteId的notebookId是否被共享了?
|
// noteId的notebookId是否被共享了?
|
||||||
notebookId := noteService.GetNotebookId(noteId)
|
notebookId := noteService.GetNotebookId(noteId)
|
||||||
if notebookId.Hex() == "" {
|
if notebookId.Hex() == "" {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
delete(q, "NoteId")
|
|
||||||
q["NotebookId"] = notebookId
|
|
||||||
|
|
||||||
// 判断notebook是否被共享
|
// 判断notebook是否被共享
|
||||||
if !db.Has(db.ShareNotebooks, q) {
|
if !db.Has(db.ShareNotebooks,
|
||||||
|
bson.M{"UserId": bson.ObjectIdHex(userId), "ToUserId": bson.ObjectIdHex(updatedUserId), "NotebookId": notebookId}) {
|
||||||
return false
|
return false
|
||||||
} else {
|
} else {
|
||||||
return true
|
return true
|
||||||
@@ -400,44 +310,43 @@ func (this *ShareService) HasReadPerm(userId, updatedUserId, noteId string) bool
|
|||||||
|
|
||||||
// updatedUserId是否有修改userId noteId的权限?
|
// updatedUserId是否有修改userId noteId的权限?
|
||||||
func (this *ShareService) HasUpdatePerm(userId, updatedUserId, noteId string) bool {
|
func (this *ShareService) HasUpdatePerm(userId, updatedUserId, noteId string) bool {
|
||||||
q := this.getOrQ(updatedUserId) // (toUserId == "xxx" || ToGroupId in (1, 2,3))
|
// 1. noteId是否被共享了?
|
||||||
q["UserId"] = bson.ObjectIdHex(userId)
|
// 得到该note share的信息
|
||||||
q["NoteId"] = bson.ObjectIdHex(noteId)
|
/*
|
||||||
|
UserId bson.ObjectId `bson:"UserId"`
|
||||||
// note的权限
|
ToUserId bson.ObjectId `bson:"ToUserId"`
|
||||||
shares := []info.ShareNote{}
|
NoteId bson.ObjectId `bson:"NoteId"`
|
||||||
db.ShareNotes.Find(q).Sort("-ToUserId").All(&shares) // 个人 > 组织
|
Perm int `bson:"Perm"` // 权限, 0只读, 1可修改
|
||||||
for _, share := range shares {
|
*/
|
||||||
return share.Perm == 1 // 第1个权限最大
|
if !db.Has(db.ShareNotes,
|
||||||
|
bson.M{"UserId": bson.ObjectIdHex(userId), "ToUserId": bson.ObjectIdHex(updatedUserId), "NoteId": bson.ObjectIdHex(noteId), "Perm": 1}) {
|
||||||
|
// noteId的notebookId是否被共享了?
|
||||||
|
notebookId := noteService.GetNotebookId(noteId)
|
||||||
|
if notebookId.Hex() == "" {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// 判断notebook是否被共享
|
||||||
|
if !db.Has(db.ShareNotebooks,
|
||||||
|
bson.M{"UserId": bson.ObjectIdHex(userId), "ToUserId": bson.ObjectIdHex(updatedUserId), "NotebookId": notebookId, "Perm": 1}) {
|
||||||
|
return false
|
||||||
|
} else {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// notebook的权限
|
|
||||||
notebookId := noteService.GetNotebookId(noteId)
|
|
||||||
if notebookId.Hex() == "" {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
delete(q, "NoteId")
|
|
||||||
q["NotebookId"] = notebookId
|
|
||||||
shares2 := []info.ShareNotebook{}
|
|
||||||
db.ShareNotebooks.Find(q).Sort("-ToUserId").All(&shares2) // 个人 > 组织
|
|
||||||
for _, share := range shares2 {
|
|
||||||
return share.Perm == 1 // 第1个权限最大
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// updatedUserId是否有修改userId notebookId的权限?
|
// updatedUserId是否有修改userId notebookId的权限?
|
||||||
func (this *ShareService) HasUpdateNotebookPerm(userId, updatedUserId, notebookId string) bool {
|
func (this *ShareService) HasUpdateNotebookPerm(userId, updatedUserId, notebookId string) bool {
|
||||||
q := this.getOrQ(updatedUserId) // (toUserId == "xxx" || ToGroupId in (1, 2,3))
|
// 判断notebook是否被共享
|
||||||
q["UserId"] = bson.ObjectIdHex(userId)
|
if !db.Has(db.ShareNotebooks,
|
||||||
q["NotebookId"] = bson.ObjectIdHex(notebookId)
|
bson.M{"UserId": bson.ObjectIdHex(userId), "ToUserId": bson.ObjectIdHex(updatedUserId), "NotebookId": bson.ObjectIdHex(notebookId), "Perm": 1}) {
|
||||||
shares2 := []info.ShareNotebook{}
|
return false
|
||||||
db.ShareNotebooks.Find(q).Sort("-ToUserId").All(&shares2) // 个人 > 组织
|
} else {
|
||||||
for _, share := range shares2 {
|
return true
|
||||||
return share.Perm == 1 // 第1个权限最大
|
}
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 共享note, notebook时使用
|
// 共享note, notebook时使用
|
||||||
@@ -463,16 +372,12 @@ func (this *ShareService) HasSharedNotebook(noteId, myUserId, sharedUserId strin
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 得到共享的笔记内容
|
// 得到共享的笔记内容
|
||||||
// 并返回笔记的权限!!!
|
// 首先要判断这个note是否我被共享了
|
||||||
func (this *ShareService) GetShareNoteContent(noteId, myUserId, sharedUserId string) (noteContent info.NoteContent) {
|
func (this *ShareService) GetShareNoteContent(noteId, myUserId, sharedUserId string) (noteContent info.NoteContent) {
|
||||||
noteContent = info.NoteContent{}
|
noteContent = info.NoteContent{}
|
||||||
// 是否单独共享了该notebook
|
// 是否单独共享了该notebook
|
||||||
// 或者, 其notebook共享了我
|
// 或者, 其notebook共享了我
|
||||||
// Log(this.HasSharedNote(noteId, myUserId))
|
if this.HasSharedNote(noteId, myUserId) || this.HasSharedNotebook(noteId, myUserId, sharedUserId) {
|
||||||
// Log(this.HasSharedNotebook(noteId, myUserId, sharedUserId))
|
|
||||||
Log(this.HasReadPerm(sharedUserId, myUserId, noteId))
|
|
||||||
if this.HasReadPerm(sharedUserId, myUserId, noteId) {
|
|
||||||
// if this.HasSharedNote(noteId, myUserId) || this.HasSharedNotebook(noteId, myUserId, sharedUserId) {
|
|
||||||
db.Get(db.NoteContents, noteId, ¬eContent)
|
db.Get(db.NoteContents, noteId, ¬eContent)
|
||||||
} else {
|
} else {
|
||||||
}
|
}
|
||||||
@@ -486,15 +391,7 @@ func (this *ShareService) GetShareNoteContent(noteId, myUserId, sharedUserId str
|
|||||||
func (this *ShareService) ListNoteShareUserInfo(noteId, userId string) []info.ShareUserInfo {
|
func (this *ShareService) ListNoteShareUserInfo(noteId, userId string) []info.ShareUserInfo {
|
||||||
// 得到shareNote信息, 得到所有的ToUserId
|
// 得到shareNote信息, 得到所有的ToUserId
|
||||||
shareNotes := []info.ShareNote{}
|
shareNotes := []info.ShareNote{}
|
||||||
db.ListByQLimit(db.ShareNotes,
|
db.ListByQLimit(db.ShareNotes, bson.M{"NoteId": bson.ObjectIdHex(noteId), "UserId": bson.ObjectIdHex(userId)}, &shareNotes, 100)
|
||||||
bson.M{
|
|
||||||
"NoteId": bson.ObjectIdHex(noteId),
|
|
||||||
"UserId": bson.ObjectIdHex(userId),
|
|
||||||
"ToGroupId": bson.M{"$exists": false},
|
|
||||||
}, &shareNotes, 100)
|
|
||||||
|
|
||||||
// Log("<<>>>>")
|
|
||||||
// Log(len(shareNotes))
|
|
||||||
|
|
||||||
if len(shareNotes) == 0 {
|
if len(shareNotes) == 0 {
|
||||||
return nil
|
return nil
|
||||||
@@ -553,11 +450,7 @@ func (this *ShareService) ListNotebookShareUserInfo(notebookId, userId string) [
|
|||||||
shareNotebooks := []info.ShareNotebook{}
|
shareNotebooks := []info.ShareNotebook{}
|
||||||
|
|
||||||
db.ListByQLimit(db.ShareNotebooks,
|
db.ListByQLimit(db.ShareNotebooks,
|
||||||
bson.M{
|
bson.M{"NotebookId": bson.ObjectIdHex(notebookId), "UserId": bson.ObjectIdHex(userId)},
|
||||||
"NotebookId": bson.ObjectIdHex(notebookId),
|
|
||||||
"UserId": bson.ObjectIdHex(userId),
|
|
||||||
"ToGroupId": bson.M{"$exists": false},
|
|
||||||
},
|
|
||||||
&shareNotebooks, 100)
|
&shareNotebooks, 100)
|
||||||
|
|
||||||
if len(shareNotebooks) == 0 {
|
if len(shareNotebooks) == 0 {
|
||||||
@@ -662,7 +555,7 @@ func (this *ShareService) HasUpdateNotePerm(noteId, userId string) bool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 用户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;
|
||||||
@@ -683,148 +576,4 @@ func (this *ShareService) HasReadNotePerm(noteId, userId string) bool {
|
|||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------
|
|
||||||
// 用户分组
|
|
||||||
|
|
||||||
// 得到笔记分享给的groups
|
|
||||||
func (this *ShareService) GetNoteShareGroups(noteId, userId string) []info.ShareNote {
|
|
||||||
groups := groupService.GetGroupsContainOf(userId)
|
|
||||||
|
|
||||||
// 得到有分享的分组
|
|
||||||
shares := []info.ShareNote{}
|
|
||||||
db.ListByQ(db.ShareNotes,
|
|
||||||
bson.M{"NoteId": bson.ObjectIdHex(noteId), "UserId": bson.ObjectIdHex(userId), "ToGroupId": bson.M{"$exists":true}}, &shares)
|
|
||||||
mapShares := map[bson.ObjectId]info.ShareNote{}
|
|
||||||
for _, share := range shares {
|
|
||||||
mapShares[share.ToGroupId] = share
|
|
||||||
}
|
|
||||||
|
|
||||||
// 所有的groups都有share, 但没有share的group没有shareId
|
|
||||||
shares2 := make([]info.ShareNote, len(groups))
|
|
||||||
for i, group := range groups {
|
|
||||||
share, ok := mapShares[group.GroupId]
|
|
||||||
if !ok {
|
|
||||||
share = info.ShareNote{}
|
|
||||||
}
|
|
||||||
share.ToGroup = group;
|
|
||||||
shares2[i] = share
|
|
||||||
}
|
|
||||||
|
|
||||||
return shares2
|
|
||||||
}
|
|
||||||
|
|
||||||
// 共享笔记给分组
|
|
||||||
func (this *ShareService) AddShareNoteGroup(userId, noteId, groupId string, perm int) (bool) {
|
|
||||||
if !groupService.IsExistsGroupUser(userId, groupId) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// 先删除之
|
|
||||||
this.DeleteShareNoteGroup(userId, noteId, groupId)
|
|
||||||
|
|
||||||
shareNote := info.ShareNote{NoteId: bson.ObjectIdHex(noteId),
|
|
||||||
UserId: bson.ObjectIdHex(userId), // 冗余字段
|
|
||||||
ToGroupId: bson.ObjectIdHex(groupId),
|
|
||||||
Perm: perm,
|
|
||||||
CreatedTime: time.Now(),
|
|
||||||
}
|
|
||||||
return db.Insert(db.ShareNotes, shareNote)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 删除
|
|
||||||
func (this *ShareService) DeleteShareNoteGroup(userId, noteId, groupId string) bool {
|
|
||||||
return db.Delete(db.ShareNotes, bson.M{"NoteId": bson.ObjectIdHex(noteId),
|
|
||||||
"UserId": bson.ObjectIdHex(userId),
|
|
||||||
"ToGroupId": bson.ObjectIdHex(groupId),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
//-------
|
|
||||||
|
|
||||||
// 得到笔记本分享给的groups
|
|
||||||
func (this *ShareService) GetNotebookShareGroups(notebookId, userId string) []info.ShareNotebook {
|
|
||||||
groups := groupService.GetGroupsContainOf(userId)
|
|
||||||
|
|
||||||
// 得到有分享的分组
|
|
||||||
shares := []info.ShareNotebook{}
|
|
||||||
db.ListByQ(db.ShareNotebooks,
|
|
||||||
bson.M{"NotebookId": bson.ObjectIdHex(notebookId), "UserId": bson.ObjectIdHex(userId), "ToGroupId": bson.M{"$exists":true}}, &shares)
|
|
||||||
mapShares := map[bson.ObjectId]info.ShareNotebook{}
|
|
||||||
for _, share := range shares {
|
|
||||||
mapShares[share.ToGroupId] = share
|
|
||||||
}
|
|
||||||
LogJ(shares)
|
|
||||||
|
|
||||||
// 所有的groups都有share, 但没有share的group没有shareId
|
|
||||||
shares2 := make([]info.ShareNotebook, len(groups))
|
|
||||||
for i, group := range groups {
|
|
||||||
share, ok := mapShares[group.GroupId]
|
|
||||||
if !ok {
|
|
||||||
share = info.ShareNotebook{}
|
|
||||||
}
|
|
||||||
share.ToGroup = group;
|
|
||||||
shares2[i] = share
|
|
||||||
}
|
|
||||||
|
|
||||||
return shares2
|
|
||||||
}
|
|
||||||
// 共享笔记给分组
|
|
||||||
func (this *ShareService) AddShareNotebookGroup(userId, notebookId, groupId string, perm int) (bool) {
|
|
||||||
if !groupService.IsExistsGroupUser(userId, groupId) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// 先删除之
|
|
||||||
this.DeleteShareNotebookGroup(userId, notebookId, groupId)
|
|
||||||
|
|
||||||
shareNotebook := info.ShareNotebook{NotebookId: bson.ObjectIdHex(notebookId),
|
|
||||||
UserId: bson.ObjectIdHex(userId), // 冗余字段
|
|
||||||
ToGroupId: bson.ObjectIdHex(groupId),
|
|
||||||
Perm: perm,
|
|
||||||
CreatedTime: time.Now(),
|
|
||||||
}
|
|
||||||
return db.Insert(db.ShareNotebooks, shareNotebook)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 删除
|
|
||||||
func (this *ShareService) DeleteShareNotebookGroup(userId, notebookId, groupId string) bool {
|
|
||||||
return db.Delete(db.ShareNotebooks, bson.M{"NotebookId": bson.ObjectIdHex(notebookId),
|
|
||||||
"UserId": bson.ObjectIdHex(userId),
|
|
||||||
"ToGroupId": bson.ObjectIdHex(groupId),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
//--------------------
|
|
||||||
// 删除组时, 删除所有的
|
|
||||||
//--------------------
|
|
||||||
|
|
||||||
func (this *ShareService) DeleteAllShareNotebookGroup(groupId string) bool {
|
|
||||||
return db.Delete(db.ShareNotebooks, bson.M{
|
|
||||||
"ToGroupId": bson.ObjectIdHex(groupId),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
func (this *ShareService) DeleteAllShareNoteGroup(groupId string) bool {
|
|
||||||
return db.Delete(db.ShareNotes, bson.M{
|
|
||||||
"ToGroupId": bson.ObjectIdHex(groupId),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
//--------------------
|
|
||||||
// 删除组内用户时, 删除其分享的
|
|
||||||
//--------------------
|
|
||||||
|
|
||||||
func (this *ShareService) DeleteShareNotebookGroupWhenDeleteGroupUser(userId, groupId string) bool {
|
|
||||||
return db.Delete(db.ShareNotebooks, bson.M{
|
|
||||||
"UserId": bson.ObjectIdHex(userId),
|
|
||||||
"ToGroupId": bson.ObjectIdHex(groupId),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
func (this *ShareService) DeleteShareNoteGroupWhenDeleteGroupUser(userId, groupId string) bool {
|
|
||||||
return db.Delete(db.ShareNotes, bson.M{
|
|
||||||
"UserId": bson.ObjectIdHex(userId),
|
|
||||||
"ToGroupId": bson.ObjectIdHex(groupId),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
+3
-101
@@ -3,9 +3,9 @@ package service
|
|||||||
import (
|
import (
|
||||||
"github.com/leanote/leanote/app/info"
|
"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/lea"
|
||||||
"gopkg.in/mgo.v2/bson"
|
"gopkg.in/mgo.v2/bson"
|
||||||
"time"
|
// "time"
|
||||||
)
|
)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -14,14 +14,12 @@ import (
|
|||||||
type TagService struct {
|
type TagService struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
func (this *TagService) GetTags(userId string) []string {
|
func (this *TagService) GetTags(userId string) []string {
|
||||||
tag := info.Tag{}
|
tag := info.Tag{}
|
||||||
db.Get(db.Tags, userId, &tag)
|
db.Get(db.Tags, userId, &tag)
|
||||||
LogJ(tag)
|
LogJ(tag)
|
||||||
return tag.Tags
|
return tag.Tags
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
func (this *TagService) AddTagsI(userId string, tags interface{}) bool {
|
func (this *TagService) AddTagsI(userId string, tags interface{}) bool {
|
||||||
if ts, ok2 := tags.([]string); ok2 {
|
if ts, ok2 := tags.([]string); ok2 {
|
||||||
@@ -38,100 +36,4 @@ func (this *TagService) AddTags(userId string, tags []string) bool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------
|
|
||||||
// v2
|
|
||||||
// 第二版标签, 单独一张表, 每一个tag一条记录
|
|
||||||
|
|
||||||
// 添加或更新标签, 先查下是否存在, 不存在则添加, 存在则更新
|
|
||||||
// 都要统计下tag的note数
|
|
||||||
// 什么时候调用? 笔记添加Tag, 删除Tag时
|
|
||||||
// 删除note时, 都可以调用
|
|
||||||
// 万能
|
|
||||||
func (this *TagService) AddOrUpdateTag(userId string, tag string) info.NoteTag {
|
|
||||||
userIdO := bson.ObjectIdHex(userId)
|
|
||||||
noteTag := info.NoteTag{}
|
|
||||||
db.GetByQ(db.NoteTags, bson.M{"UserId": userIdO, "Tag": tag}, ¬eTag)
|
|
||||||
|
|
||||||
// 存在, 则更新之
|
|
||||||
if noteTag.TagId != "" {
|
|
||||||
// 统计note数
|
|
||||||
count := noteService.CountNoteByTag(userId, tag)
|
|
||||||
noteTag.Count = count
|
|
||||||
noteTag.UpdatedTime = time.Now()
|
|
||||||
// noteTag.Usn = userService.IncrUsn(userId), 更新count而已
|
|
||||||
db.UpdateByIdAndUserId(db.NoteTags, noteTag.TagId.Hex(), userId, noteTag)
|
|
||||||
return noteTag
|
|
||||||
}
|
|
||||||
|
|
||||||
// 不存在, 则创建之
|
|
||||||
noteTag.TagId = bson.NewObjectId()
|
|
||||||
noteTag.Count = 1
|
|
||||||
noteTag.Tag = tag
|
|
||||||
noteTag.UserId = bson.ObjectIdHex(userId)
|
|
||||||
noteTag.CreatedTime = time.Now()
|
|
||||||
noteTag.UpdatedTime = noteTag.CreatedTime
|
|
||||||
noteTag.Usn = userService.IncrUsn(userId)
|
|
||||||
noteTag.IsDeleted = false
|
|
||||||
db.Insert(db.NoteTags, noteTag)
|
|
||||||
|
|
||||||
return noteTag
|
|
||||||
}
|
|
||||||
|
|
||||||
// 得到标签, 按更新时间来排序
|
|
||||||
func (this *TagService) GetTags(userId string) []info.NoteTag {
|
|
||||||
tags := []info.NoteTag{}
|
|
||||||
query := bson.M{"UserId": bson.ObjectIdHex(userId), "IsDeleted": false}
|
|
||||||
q := db.NoteTags.Find(query);
|
|
||||||
sortFieldR := "-UpdatedTime"
|
|
||||||
q.Sort(sortFieldR).All(&tags)
|
|
||||||
return tags
|
|
||||||
}
|
|
||||||
|
|
||||||
// 删除标签
|
|
||||||
// 也删除所有的笔记含该标签的
|
|
||||||
// 返回noteId => usn
|
|
||||||
func (this *TagService) DeleteTag(userId string, tag string) map[string]int {
|
|
||||||
usn := userService.IncrUsn(userId)
|
|
||||||
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 map[string]int{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 删除标签, 供API调用
|
|
||||||
func (this *TagService) DeleteTagApi(userId string, tag string, usn int) (ok bool, msg string, toUsn int) {
|
|
||||||
noteTag := info.NoteTag{}
|
|
||||||
db.GetByQ(db.NoteTags, bson.M{"UserId": bson.ObjectIdHex(userId), "Tag": tag}, ¬eTag)
|
|
||||||
|
|
||||||
if noteTag.TagId == "" {
|
|
||||||
return false, "notExists", 0
|
|
||||||
}
|
|
||||||
if noteTag.Usn > usn {
|
|
||||||
return false, "conflict", 0
|
|
||||||
}
|
|
||||||
toUsn = userService.IncrUsn(userId)
|
|
||||||
if db.UpdateByQMap(db.NoteTags, bson.M{"UserId": bson.ObjectIdHex(userId), "Tag": tag}, bson.M{"Usn": usn, "IsDeleted": true}) {
|
|
||||||
return true, "", toUsn
|
|
||||||
}
|
|
||||||
return false, "", 0
|
|
||||||
}
|
|
||||||
|
|
||||||
// 重新统计标签的count
|
|
||||||
func (this *TagService) reCountTagCount(userId string, tags []string) {
|
|
||||||
if tags == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
for _, tag := range tags {
|
|
||||||
this.AddOrUpdateTag(userId, tag);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 同步用
|
|
||||||
func (this *TagService) GeSyncTags(userId string, afterUsn, maxEntry int) ([]info.NoteTag) {
|
|
||||||
noteTags := []info.NoteTag{}
|
|
||||||
q := db.NoteTags.Find(bson.M{"UserId": bson.ObjectIdHex(userId), "Usn": bson.M{"$gt": afterUsn}});
|
|
||||||
q.Sort("Usn").Limit(maxEntry).All(¬eTags)
|
|
||||||
return noteTags
|
|
||||||
}
|
|
||||||
@@ -1,634 +0,0 @@
|
|||||||
package service
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/revel/revel"
|
|
||||||
"github.com/leanote/leanote/app/info"
|
|
||||||
"github.com/leanote/leanote/app/db"
|
|
||||||
. "github.com/leanote/leanote/app/lea"
|
|
||||||
"github.com/leanote/leanote/app/lea/archive"
|
|
||||||
"gopkg.in/mgo.v2/bson"
|
|
||||||
"time"
|
|
||||||
"strings"
|
|
||||||
"os"
|
|
||||||
"fmt"
|
|
||||||
"html/template"
|
|
||||||
"regexp"
|
|
||||||
"io/ioutil"
|
|
||||||
"encoding/json"
|
|
||||||
)
|
|
||||||
|
|
||||||
// 主题
|
|
||||||
type ThemeService struct {
|
|
||||||
}
|
|
||||||
|
|
||||||
var defaultStyle = "blog_default"
|
|
||||||
var elegantStyle = "blog_daqi"
|
|
||||||
var fixedStyle = "blog_left_fixed"
|
|
||||||
|
|
||||||
// admin用户的主题基路径
|
|
||||||
func (this *ThemeService) getDefaultThemeBasePath() string {
|
|
||||||
return revel.BasePath + "/public/blog/themes"
|
|
||||||
}
|
|
||||||
// 默认主题路径
|
|
||||||
func (this *ThemeService) getDefaultThemePath(style string) string {
|
|
||||||
if style == elegantStyle {
|
|
||||||
return this.getDefaultThemeBasePath() + "/elegant"
|
|
||||||
} else if style == fixedStyle {
|
|
||||||
return this.getDefaultThemeBasePath() + "/nav_fixed"
|
|
||||||
} else {
|
|
||||||
return this.getDefaultThemeBasePath() + "/default"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// blogService用
|
|
||||||
func (this *ThemeService) GetDefaultThemePath(style string) string {
|
|
||||||
if style == elegantStyle {
|
|
||||||
return "public/blog/themes/elegant"
|
|
||||||
} else if style == fixedStyle {
|
|
||||||
return "public/blog/themes/nav_fixed"
|
|
||||||
} else {
|
|
||||||
return "public/blog/themes/default"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 得到默认主题
|
|
||||||
// style是之前的值, 有3个值 blog_default, blog_daqi, blog_left_fixed
|
|
||||||
func (this *ThemeService) getDefaultTheme(style string) info.Theme {
|
|
||||||
if style == elegantStyle {
|
|
||||||
return info.Theme{
|
|
||||||
IsDefault: true,
|
|
||||||
Path: "public/blog/themes/elegant",
|
|
||||||
Name: "leanote elegant",
|
|
||||||
Author: "leanote",
|
|
||||||
AuthorUrl: "http://leanote.com",
|
|
||||||
Version: "1.0",
|
|
||||||
}
|
|
||||||
} else if style == fixedStyle {
|
|
||||||
return info.Theme{
|
|
||||||
IsDefault: true,
|
|
||||||
Path: "public/blog/themes/nav_fixed",
|
|
||||||
Name: "leanote nav fixed",
|
|
||||||
Author: "leanote",
|
|
||||||
AuthorUrl: "http://leanote.com",
|
|
||||||
Version: "1.0",
|
|
||||||
}
|
|
||||||
} else { // blog default
|
|
||||||
return info.Theme{
|
|
||||||
IsDefault: true,
|
|
||||||
Path: "public/blog/themes/default",
|
|
||||||
Name: "leanote default",
|
|
||||||
Author: "leanote",
|
|
||||||
AuthorUrl: "http://leanote.com",
|
|
||||||
Version: "1.0",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 用户的主题路径设置
|
|
||||||
func (this *ThemeService) getUserThemeBasePath(userId string) string {
|
|
||||||
return revel.BasePath + "/public/upload/" + userId + "/themes"
|
|
||||||
}
|
|
||||||
func (this *ThemeService) getUserThemePath(userId, themeId string) string {
|
|
||||||
return this.getUserThemeBasePath(userId) + "/" + themeId
|
|
||||||
}
|
|
||||||
func (this *ThemeService) getUserThemePath2(userId, themeId string) string {
|
|
||||||
return "public/upload/" + userId + "/themes/" + themeId
|
|
||||||
}
|
|
||||||
|
|
||||||
// 新建主题
|
|
||||||
// 复制默认主题到文件夹下
|
|
||||||
func (this *ThemeService) CopyDefaultTheme(userBlog info.UserBlog) (ok bool, themeId string) {
|
|
||||||
newThemeId := bson.NewObjectId()
|
|
||||||
themeId = newThemeId.Hex()
|
|
||||||
userId := userBlog.UserId.Hex()
|
|
||||||
themePath := this.getUserThemePath(userId, themeId)
|
|
||||||
err := os.MkdirAll(themePath, 0755)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// 复制默认主题
|
|
||||||
defaultThemePath := this.getDefaultThemePath(userBlog.Style)
|
|
||||||
err = CopyDir(defaultThemePath, themePath)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 保存到数据库中
|
|
||||||
theme, _ := this.getThemeConfig(themePath)
|
|
||||||
theme.ThemeId = newThemeId
|
|
||||||
theme.Path = this.getUserThemePath2(userId, themeId)
|
|
||||||
theme.CreatedTime = time.Now()
|
|
||||||
theme.UpdatedTime = theme.CreatedTime
|
|
||||||
theme.UserId = bson.ObjectIdHex(userId)
|
|
||||||
|
|
||||||
ok = db.Insert(db.Themes, theme)
|
|
||||||
return ok, themeId
|
|
||||||
}
|
|
||||||
|
|
||||||
// 第一次新建主题
|
|
||||||
// 设为active true
|
|
||||||
func (this *ThemeService) NewThemeForFirst(userBlog info.UserBlog) (ok bool, themeId string) {
|
|
||||||
ok, themeId = this.CopyDefaultTheme(userBlog)
|
|
||||||
this.ActiveTheme(userBlog.UserId.Hex(), themeId)
|
|
||||||
// db.UpdateByQField(db.Themes, bson.M{"_id": bson.ObjectIdHex(themeId)}, "IsActive", true)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 新建主题, 判断是否有主题了
|
|
||||||
func (this *ThemeService) NewTheme(userId string) (ok bool, themeId string) {
|
|
||||||
userBlog := blogService.GetUserBlog(userId)
|
|
||||||
// 如果还没有主题, 那先复制旧的主题
|
|
||||||
if userBlog.ThemeId == "" {
|
|
||||||
themeService.NewThemeForFirst(userBlog)
|
|
||||||
}
|
|
||||||
// 再copy一个默认主题
|
|
||||||
userBlog.Style = "defaultStyle";
|
|
||||||
ok, themeId = this.CopyDefaultTheme(userBlog)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 将字符串转成Theme配置
|
|
||||||
func (this *ThemeService) parseConfig(configStr string) (theme info.Theme, err error) {
|
|
||||||
theme = info.Theme{}
|
|
||||||
// 除去/**/注释
|
|
||||||
reg, _ := regexp.Compile("/\\*[\\s\\S]*?\\*/")
|
|
||||||
configStr = reg.ReplaceAllString(configStr, "")
|
|
||||||
// 转成map
|
|
||||||
config := map[string]interface{}{}
|
|
||||||
err = json.Unmarshal([]byte(configStr), &config)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// 没有错, 则将Name, Version, Author, AuthorUrl
|
|
||||||
Name := config["Name"]
|
|
||||||
if Name != nil {
|
|
||||||
theme.Name = Name.(string)
|
|
||||||
}
|
|
||||||
Version := config["Version"]
|
|
||||||
if Version != nil {
|
|
||||||
theme.Version = Version.(string)
|
|
||||||
}
|
|
||||||
Author := config["Author"]
|
|
||||||
if Author != nil {
|
|
||||||
theme.Author = Author.(string)
|
|
||||||
}
|
|
||||||
AuthorUrl := config["AuthorUrl"]
|
|
||||||
if AuthorUrl != nil {
|
|
||||||
theme.AuthorUrl = AuthorUrl.(string)
|
|
||||||
}
|
|
||||||
theme.Info = config
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 读取theme.json得到值
|
|
||||||
func (this *ThemeService) getThemeConfig(themePath string) (theme info.Theme, err error) {
|
|
||||||
theme = info.Theme{}
|
|
||||||
configStr := GetFileStrContent(themePath + "/theme.json")
|
|
||||||
theme, err = this.parseConfig(configStr)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (this *ThemeService) GetTheme(userId, themeId string) info.Theme {
|
|
||||||
theme := info.Theme{}
|
|
||||||
db.GetByQ(db.Themes, bson.M{"_id": bson.ObjectIdHex(themeId), "UserId": bson.ObjectIdHex(userId)}, &theme)
|
|
||||||
return theme
|
|
||||||
}
|
|
||||||
func (this *ThemeService) GetThemeById(themeId string) info.Theme {
|
|
||||||
theme := info.Theme{}
|
|
||||||
db.GetByQ(db.Themes, bson.M{"_id": bson.ObjectIdHex(themeId)}, &theme)
|
|
||||||
return theme
|
|
||||||
}
|
|
||||||
|
|
||||||
// 得到主题信息, 为了给博客用
|
|
||||||
func (this *ThemeService) GetThemeInfo(themeId, style string) map[string]interface{} {
|
|
||||||
q := bson.M{}
|
|
||||||
if themeId == "" {
|
|
||||||
if style == "" {
|
|
||||||
style = defaultStyle
|
|
||||||
}
|
|
||||||
q["Style"] = style
|
|
||||||
q["IsDefault"] = true
|
|
||||||
} else {
|
|
||||||
q["_id"] = bson.ObjectIdHex(themeId)
|
|
||||||
}
|
|
||||||
theme := info.Theme{}
|
|
||||||
db.GetByQ(db.Themes, q, &theme)
|
|
||||||
return theme.Info
|
|
||||||
}
|
|
||||||
|
|
||||||
// 得到用户的主题
|
|
||||||
// 若用户没有主题, 则至少有一个默认主题
|
|
||||||
// 第一个返回值是当前active
|
|
||||||
func (this *ThemeService) GetUserThemes(userId string) (theme info.Theme, themes []info.Theme) {
|
|
||||||
theme = info.Theme{}
|
|
||||||
themes = []info.Theme{}
|
|
||||||
|
|
||||||
// db.ListByQ(db.Themes, bson.M{"UserId": bson.ObjectIdHex(userId)}, &themes)
|
|
||||||
|
|
||||||
// 创建时间逆序
|
|
||||||
query := bson.M{"UserId": bson.ObjectIdHex(userId)}
|
|
||||||
q := db.Themes.Find(query);
|
|
||||||
q.Sort("-CreatedTime").All(&themes)
|
|
||||||
if len(themes) == 0 {
|
|
||||||
userBlog := blogService.GetUserBlog(userId)
|
|
||||||
theme = this.getDefaultTheme(userBlog.Style)
|
|
||||||
} else {
|
|
||||||
var has = false
|
|
||||||
// 第一个是active的主题
|
|
||||||
themes2 := make([]info.Theme, len(themes))
|
|
||||||
i := 0
|
|
||||||
for _, t := range themes {
|
|
||||||
if t.IsActive {
|
|
||||||
theme = t
|
|
||||||
} else {
|
|
||||||
has = true
|
|
||||||
themes2[i] = t
|
|
||||||
i++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if has {
|
|
||||||
themes = themes2
|
|
||||||
} else {
|
|
||||||
themes = nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 得到默认主题供选择
|
|
||||||
func (this *ThemeService) GetDefaultThemes() (themes []info.Theme) {
|
|
||||||
themes = []info.Theme{}
|
|
||||||
db.ListByQ(db.Themes, bson.M{"IsDefault": true}, &themes)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 得到模板内容
|
|
||||||
func (this *ThemeService) GetTplContent(userId, themeId, filename string) string {
|
|
||||||
path := this.GetThemeAbsolutePath(userId, themeId) + "/" + filename
|
|
||||||
return GetFileStrContent(path)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 得到主题的绝对路径
|
|
||||||
func (this *ThemeService) GetThemeAbsolutePath(userId, themeId string) string {
|
|
||||||
theme := info.Theme{}
|
|
||||||
db.GetByQWithFields(db.Themes, bson.M{"_id": bson.ObjectIdHex(themeId), "UserId": bson.ObjectIdHex(userId)}, []string{"Path"}, &theme)
|
|
||||||
if theme.Path != "" {
|
|
||||||
return revel.BasePath + "/" + theme.Path
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
func (this *ThemeService) GetThemePath(userId, themeId string) string {
|
|
||||||
theme := info.Theme{}
|
|
||||||
db.GetByQWithFields(db.Themes, bson.M{"_id": bson.ObjectIdHex(themeId), "UserId": bson.ObjectIdHex(userId)}, []string{"Path"}, &theme)
|
|
||||||
if theme.Path != "" {
|
|
||||||
return theme.Path
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
// 更新模板内容
|
|
||||||
func (this *ThemeService) UpdateTplContent(userId, themeId, filename, content string) (ok bool, msg string) {
|
|
||||||
basePath := this.GetThemeAbsolutePath(userId, themeId)
|
|
||||||
path := basePath + "/" + filename
|
|
||||||
if strings.Contains(filename, ".html") {
|
|
||||||
Log(">>")
|
|
||||||
if ok, msg = this.ValidateTheme(basePath, filename, content); ok {
|
|
||||||
// 模板
|
|
||||||
if ok, msg = this.mustTpl(filename, content); ok {
|
|
||||||
ok = PutFileStrContent(path, content)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return
|
|
||||||
} else if filename == "theme.json" {
|
|
||||||
// 主题配置, 判断是否是正确的json
|
|
||||||
theme, err := this.parseConfig(content)
|
|
||||||
if err != nil {
|
|
||||||
return false, fmt.Sprintf("%v", err)
|
|
||||||
}
|
|
||||||
// 正确, 更新theme信息
|
|
||||||
ok = db.UpdateByQMap(db.Themes, bson.M{"_id": bson.ObjectIdHex(themeId), "UserId": bson.ObjectIdHex(userId)},
|
|
||||||
bson.M{
|
|
||||||
"Name": theme.Name,
|
|
||||||
"Version": theme.Version,
|
|
||||||
"Author": theme.Author,
|
|
||||||
"AuthorUrl": theme.AuthorUrl,
|
|
||||||
"Info": theme.Info,
|
|
||||||
})
|
|
||||||
if ok {
|
|
||||||
ok = PutFileStrContent(path, content)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
ok = PutFileStrContent(path, content)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (this *ThemeService) DeleteTpl(userId, themeId, filename string) (ok bool) {
|
|
||||||
path := this.GetThemeAbsolutePath(userId, themeId) + "/" + filename
|
|
||||||
ok = DeleteFile(path)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 判断是否有语法错误
|
|
||||||
func (this *ThemeService) mustTpl(filename, content string) (ok bool, msg string) {
|
|
||||||
ok = true
|
|
||||||
defer func() {
|
|
||||||
if err := recover(); err != nil {
|
|
||||||
ok = false
|
|
||||||
Log(err)
|
|
||||||
msg = fmt.Sprintf("%v", err)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
template.Must(template.New(filename).Funcs(revel.TemplateFuncs).Parse(content))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
/////////
|
|
||||||
|
|
||||||
// 使用主题
|
|
||||||
func (this *ThemeService) ActiveTheme(userId, themeId string) (ok bool) {
|
|
||||||
if db.Has(db.Themes, bson.M{"_id": bson.ObjectIdHex(themeId), "UserId": bson.ObjectIdHex(userId)}) {
|
|
||||||
// 之前的设为false
|
|
||||||
db.UpdateByQField(db.Themes, bson.M{"UserId": bson.ObjectIdHex(userId), "IsActive": true}, "IsActive", false)
|
|
||||||
// 现在的设为true
|
|
||||||
db.UpdateByQField(db.Themes, bson.M{"_id": bson.ObjectIdHex(themeId)}, "IsActive", true)
|
|
||||||
|
|
||||||
// UserBlog ThemeId
|
|
||||||
db.UpdateByQField(db.UserBlogs, bson.M{"_id": bson.ObjectIdHex(userId)}, "ThemeId", bson.ObjectIdHex(themeId))
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// 删除主题
|
|
||||||
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})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 公开主题, 只有管理员才有权限, 之前没公开的变成公开
|
|
||||||
func (this *ThemeService) PublicTheme(userId, themeId string) (ok bool) {
|
|
||||||
// 是否是管理员?
|
|
||||||
userInfo := userService.GetUserInfo(userId)
|
|
||||||
if userInfo.Username == configService.GetAdminUsername() {
|
|
||||||
theme := this.GetThemeById(themeId)
|
|
||||||
return db.UpdateByQField(db.Themes, bson.M{"UserId": bson.ObjectIdHex(userId), "_id": bson.ObjectIdHex(themeId)}, "IsDefault", !theme.IsDefault)
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// 导出主题
|
|
||||||
func (this *ThemeService) ExportTheme(userId, themeId string) (ok bool, path string) {
|
|
||||||
theme := this.GetThemeById(themeId)
|
|
||||||
// 打包
|
|
||||||
// 验证路径, 别把整个项目打包了
|
|
||||||
Log(theme.Path)
|
|
||||||
if theme.Path == "" ||
|
|
||||||
(!strings.HasPrefix(theme.Path, "public/upload") &&
|
|
||||||
!strings.HasPrefix(theme.Path, "public/blog/themes")) ||
|
|
||||||
strings.Contains(theme.Path, "..") {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
sourcePath := revel.BasePath + "/" + theme.Path
|
|
||||||
targetPath := revel.BasePath + "/public/upload/" + userId + "/tmp"
|
|
||||||
err := os.MkdirAll(targetPath, 0755)
|
|
||||||
if err != nil {
|
|
||||||
Log(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
targetName := targetPath + "/" + theme.Name + ".zip"
|
|
||||||
Log(sourcePath)
|
|
||||||
Log(targetName)
|
|
||||||
ok = archive.Zip(sourcePath, targetName)
|
|
||||||
if !ok {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
return true, targetName
|
|
||||||
}
|
|
||||||
// 导入主题
|
|
||||||
// path == /llllllll/..../public/upload/.../aa.zip, 绝对路径
|
|
||||||
func (this *ThemeService) ImportTheme(userId, path string) (ok bool, msg string) {
|
|
||||||
themeIdO := bson.NewObjectId()
|
|
||||||
themeId := themeIdO.Hex()
|
|
||||||
targetPath := this.getUserThemePath(userId, themeId) // revel.BasePath + "/public/upload/" + userId + "/themes/" + themeId
|
|
||||||
if ok, msg = archive.Unzip(path, targetPath); !ok {
|
|
||||||
DeleteFile(targetPath)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// 主题验证
|
|
||||||
if ok, msg = this.ValidateTheme(targetPath, "", ""); !ok {
|
|
||||||
DeleteFile(targetPath)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// 解压成功, 那么新建之
|
|
||||||
// 保存到数据库中
|
|
||||||
theme, _ := this.getThemeConfig(targetPath)
|
|
||||||
if theme.Name == "" {
|
|
||||||
ok = false
|
|
||||||
DeleteFile(targetPath)
|
|
||||||
msg = "解析错误"
|
|
||||||
return
|
|
||||||
}
|
|
||||||
theme.ThemeId = themeIdO
|
|
||||||
theme.Path = this.getUserThemePath2(userId, themeId)
|
|
||||||
theme.CreatedTime = time.Now()
|
|
||||||
theme.UpdatedTime = theme.CreatedTime
|
|
||||||
theme.UserId = bson.ObjectIdHex(userId)
|
|
||||||
|
|
||||||
ok = db.Insert(db.Themes, theme)
|
|
||||||
if !ok {
|
|
||||||
DeleteFile(targetPath)
|
|
||||||
}
|
|
||||||
DeleteFile(path)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 升级用
|
|
||||||
// public/
|
|
||||||
|
|
||||||
func (this *ThemeService) UpgradeThemeBeta2() (ok bool) {
|
|
||||||
adminUserId := configService.GetAdminUserId()
|
|
||||||
this.upgradeThemeBeta2(adminUserId, defaultStyle, true)
|
|
||||||
this.upgradeThemeBeta2(adminUserId, elegantStyle, false)
|
|
||||||
this.upgradeThemeBeta2(adminUserId, fixedStyle, false)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
func (this *ThemeService) upgradeThemeBeta2(userId, style string, isActive bool) (ok bool) {
|
|
||||||
// 解压成功, 那么新建之
|
|
||||||
// 保存到数据库中
|
|
||||||
targetPath := this.GetDefaultThemePath(style)
|
|
||||||
theme, _ := this.getThemeConfig(revel.BasePath + "/" + targetPath)
|
|
||||||
if theme.Name == "" {
|
|
||||||
ok = false
|
|
||||||
return
|
|
||||||
}
|
|
||||||
themeIdO := bson.NewObjectId()
|
|
||||||
theme.ThemeId = themeIdO
|
|
||||||
theme.Path = targetPath // public
|
|
||||||
theme.CreatedTime = time.Now()
|
|
||||||
theme.UpdatedTime = theme.CreatedTime
|
|
||||||
theme.UserId = bson.ObjectIdHex(userId)
|
|
||||||
theme.IsActive = isActive
|
|
||||||
theme.IsDefault = true
|
|
||||||
theme.Style = style
|
|
||||||
ok = db.Insert(db.Themes, theme)
|
|
||||||
return ok
|
|
||||||
}
|
|
||||||
|
|
||||||
// 安装主题
|
|
||||||
// 得到该主题路径
|
|
||||||
func (this *ThemeService) InstallTheme(userId, themeId string) (ok bool) {
|
|
||||||
theme := this.GetThemeById(themeId)
|
|
||||||
// 不是默认主题, 即不是admin用户的主题, 不能乱安装
|
|
||||||
if !theme.IsDefault {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// 用户之前是否有主题?
|
|
||||||
userBlog := blogService.GetUserBlog(userId)
|
|
||||||
if userBlog.ThemeId == "" {
|
|
||||||
this.NewThemeForFirst(userBlog)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 生成新主题
|
|
||||||
newThemeId := bson.NewObjectId()
|
|
||||||
themeId = newThemeId.Hex()
|
|
||||||
themePath := this.getUserThemePath(userId, themeId)
|
|
||||||
err := os.MkdirAll(themePath, 0755)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// 复制默认主题
|
|
||||||
sourceThemePath := revel.BasePath + "/" + theme.Path
|
|
||||||
err = CopyDir(sourceThemePath, themePath)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 保存到数据库中
|
|
||||||
theme, _ = this.getThemeConfig(themePath)
|
|
||||||
theme.ThemeId = newThemeId
|
|
||||||
theme.Path = this.getUserThemePath2(userId, themeId)
|
|
||||||
theme.CreatedTime = time.Now()
|
|
||||||
theme.UpdatedTime = theme.CreatedTime
|
|
||||||
theme.UserId = bson.ObjectIdHex(userId)
|
|
||||||
|
|
||||||
ok = db.Insert(db.Themes, theme)
|
|
||||||
|
|
||||||
// 激活之
|
|
||||||
this.ActiveTheme(userId, themeId);
|
|
||||||
|
|
||||||
return ok
|
|
||||||
}
|
|
||||||
|
|
||||||
// 验证主题是否全法, 存在循环引用?
|
|
||||||
// filename, newContent 表示在修改模板时要判断模板修改时是否有错误
|
|
||||||
func (this *ThemeService) ValidateTheme(path string, filename, newContent string) (ok bool, msg string) {
|
|
||||||
Log("theme Path")
|
|
||||||
Log(path)
|
|
||||||
// 建立一个有向图
|
|
||||||
// 将该path下的所有文件提出, 得到文件的引用情况
|
|
||||||
files := ListDir(path)
|
|
||||||
LogJ(files);
|
|
||||||
size := len(files)
|
|
||||||
if(size > 100) {
|
|
||||||
ok = false;
|
|
||||||
msg = "tooManyFiles"
|
|
||||||
return
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
111111111
|
|
||||||
111000000
|
|
||||||
*/
|
|
||||||
vector := make([][]int, size)
|
|
||||||
for i := 0; i < size; i++ {
|
|
||||||
vector[i] = make([]int, size)
|
|
||||||
}
|
|
||||||
fileIndexMap := map[string]int{} // fileName => index
|
|
||||||
fileContent := map[string]string{} // fileName => content
|
|
||||||
index := 0
|
|
||||||
// 得到文件内容, 和建立索引, 每个文件都有一个index, 对应数组位置
|
|
||||||
for _, t := range files {
|
|
||||||
if !strings.Contains(t, ".html") {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if t != filename {
|
|
||||||
fileBytes, err := ioutil.ReadFile(path + "/" + t)
|
|
||||||
if err != nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
fileIndexMap[t] = index;
|
|
||||||
// html内容
|
|
||||||
fileStr := string(fileBytes)
|
|
||||||
fileContent[t] = fileStr
|
|
||||||
} else {
|
|
||||||
fileIndexMap[t] = index
|
|
||||||
fileContent[t] = newContent
|
|
||||||
}
|
|
||||||
index++
|
|
||||||
}
|
|
||||||
// 分析文件内容, 建立有向图
|
|
||||||
reg, _ := regexp.Compile("{{ *template \"(.+?\\.html)\".*}}")
|
|
||||||
for filename, content := range fileContent {
|
|
||||||
thisIndex := fileIndexMap[filename]
|
|
||||||
finds := reg.FindAllStringSubmatch(content, -1) // 子匹配
|
|
||||||
LogJ(finds)
|
|
||||||
// Log(content)
|
|
||||||
if finds != nil && len(finds) > 0 {
|
|
||||||
for _, includes := range finds {
|
|
||||||
include := includes[1]
|
|
||||||
includeIndex, has := fileIndexMap[include]
|
|
||||||
Log(includeIndex)
|
|
||||||
Log("??")
|
|
||||||
Log(has)
|
|
||||||
if has {
|
|
||||||
vector[thisIndex][includeIndex] = 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
LogJ(vector)
|
|
||||||
LogJ(fileIndexMap)
|
|
||||||
// 建立图后, 判断是否有环
|
|
||||||
if this.hasRound(vector, index) {
|
|
||||||
ok = false
|
|
||||||
msg = "themeValidHasRoundInclude"
|
|
||||||
} else {
|
|
||||||
ok = true
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 检测有向图是否有环, DFS
|
|
||||||
func (this *ThemeService) hasRound(vector [][]int, size int) (ok bool) {
|
|
||||||
for i := 0; i < size; i++ {
|
|
||||||
visited := make([]int, size)
|
|
||||||
if this.hasRoundEach(vector, i, size, visited) {
|
|
||||||
Log(">>")
|
|
||||||
Log(i);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// 从每个节点出发, 判断是否有环
|
|
||||||
func (this *ThemeService) hasRoundEach(vector [][]int, index int, size int, visited []int) (ok bool) {
|
|
||||||
if visited[index] > 0 {
|
|
||||||
Log("<")
|
|
||||||
Log(index)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
visited[index] = 1;
|
|
||||||
// 遍历它的孩子
|
|
||||||
for i := 0; i < size; i++ {
|
|
||||||
if vector[index][i] > 0 {
|
|
||||||
return this.hasRoundEach(vector, i, size, visited);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
visited[index] = 0;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
@@ -28,7 +28,7 @@ func (this *TrashService) DeleteNote(noteId, userId string) bool {
|
|||||||
// 首先删除其共享
|
// 首先删除其共享
|
||||||
if shareService.DeleteShareNoteAll(noteId, userId) {
|
if shareService.DeleteShareNoteAll(noteId, userId) {
|
||||||
// 更新note isTrash = true
|
// 更新note isTrash = true
|
||||||
if db.UpdateByIdAndUserId(db.Notes, noteId, userId, bson.M{"$set": bson.M{"IsTrash": true, "Usn": userService.IncrUsn(userId)}}) {
|
if db.UpdateByIdAndUserId(db.Notes, noteId, userId, bson.M{"$set": bson.M{"IsTrash": true}}) {
|
||||||
// recount notebooks' notes number
|
// recount notebooks' notes number
|
||||||
notebookIdO := noteService.GetNotebookId(noteId)
|
notebookIdO := noteService.GetNotebookId(noteId)
|
||||||
notebookId := notebookIdO.Hex()
|
notebookId := notebookIdO.Hex()
|
||||||
@@ -44,7 +44,7 @@ func (this *TrashService) DeleteNote(noteId, userId string) bool {
|
|||||||
func (this *TrashService) DeleteSharedNote(noteId, userId, myUserId string) bool {
|
func (this *TrashService) DeleteSharedNote(noteId, userId, myUserId string) bool {
|
||||||
note := noteService.GetNote(noteId, userId)
|
note := noteService.GetNote(noteId, userId)
|
||||||
if shareService.HasUpdatePerm(userId, myUserId, noteId) && note.CreatedUserId.Hex() == myUserId {
|
if shareService.HasUpdatePerm(userId, myUserId, noteId) && note.CreatedUserId.Hex() == myUserId {
|
||||||
return db.UpdateByIdAndUserId(db.Notes, noteId, userId, bson.M{"$set": bson.M{"IsTrash": true, "Usn": userService.IncrUsn(userId)}})
|
return db.UpdateByIdAndUserId(db.Notes, noteId, userId, bson.M{"$set": bson.M{"IsTrash": true}})
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@@ -53,63 +53,23 @@ func (this *TrashService) DeleteSharedNote(noteId, userId, 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),
|
|
||||||
"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);
|
|
||||||
if note.NoteId == "" {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
// delete note's attachs
|
// delete note's attachs
|
||||||
ok := attachService.DeleteAllAttachs(noteId, userId)
|
ok := attachService.DeleteAllAttachs(noteId, userId)
|
||||||
|
|
||||||
// 设置删除位
|
|
||||||
ok = db.UpdateByIdAndUserIdMap(db.Notes, noteId, userId,
|
|
||||||
bson.M{"IsDeleted": true,
|
|
||||||
"Usn": userService.IncrUsn(userId)})
|
|
||||||
// delete note
|
|
||||||
// ok = db.DeleteByIdAndUserId(db.Notes, noteId, userId)
|
|
||||||
|
|
||||||
|
// delete note
|
||||||
|
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)
|
||||||
|
|
||||||
// 重新统计tag's count
|
|
||||||
// TODO 这里会改变tag's Usn
|
|
||||||
tagService.reCountTagCount(userId, note.Tags)
|
|
||||||
|
|
||||||
return ok
|
return ok
|
||||||
}
|
}
|
||||||
|
|
||||||
func (this *TrashService) DeleteTrashApi(noteId, userId string, usn int) (bool, string, int) {
|
|
||||||
note := noteService.GetNote(noteId, userId)
|
|
||||||
|
|
||||||
if note.NoteId == "" || note.IsDeleted {
|
|
||||||
return false, "notExists", 0
|
|
||||||
}
|
|
||||||
|
|
||||||
if note.Usn != usn {
|
|
||||||
return false, "conflict", 0
|
|
||||||
}
|
|
||||||
|
|
||||||
// delete note's attachs
|
|
||||||
ok := attachService.DeleteAllAttachs(noteId, userId)
|
|
||||||
|
|
||||||
// 设置删除位
|
|
||||||
afterUsn := userService.IncrUsn(userId)
|
|
||||||
ok = db.UpdateByIdAndUserIdMap(db.Notes, noteId, userId,
|
|
||||||
bson.M{"IsDeleted": true,
|
|
||||||
"Usn": afterUsn})
|
|
||||||
|
|
||||||
// delete content
|
|
||||||
ok = db.DeleteByIdAndUserId(db.NoteContents, noteId, userId)
|
|
||||||
|
|
||||||
return ok, "", afterUsn
|
|
||||||
}
|
|
||||||
|
|
||||||
// 列出note, 排序规则, 还有分页
|
// 列出note, 排序规则, 还有分页
|
||||||
// CreatedTime, UpdatedTime, title 来排序
|
// CreatedTime, UpdatedTime, title 来排序
|
||||||
func (this *TrashService) ListNotes(userId string,
|
func (this *TrashService) ListNotes(userId string,
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import (
|
|||||||
. "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"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -19,164 +19,9 @@ func (this *UpgradeService) UpgradeBlog() bool {
|
|||||||
|
|
||||||
// PublicTime, RecommendTime = UpdatedTime
|
// PublicTime, RecommendTime = UpdatedTime
|
||||||
for _, note := range notes {
|
for _, note := range notes {
|
||||||
if note.IsBlog && note.PublicTime.Year() < 100 {
|
db.UpdateByIdAndUserIdMap2(db.Notes, note.NoteId, note.UserId, bson.M{"PublicTime": note.UpdatedTime, "RecommendTime": note.UpdatedTime})
|
||||||
db.UpdateByIdAndUserIdMap2(db.Notes, note.NoteId, note.UserId, bson.M{"PublicTime": note.UpdatedTime, "RecommendTime": note.UpdatedTime})
|
Log(note.NoteId.Hex())
|
||||||
Log(note.NoteId.Hex())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// 11-5自定义博客升级, 将aboutMe移至pages
|
|
||||||
/*
|
|
||||||
<li>Migrate "About me" to single(a single post)</li>
|
|
||||||
<li>Add some default themes to administrator</li>
|
|
||||||
<li>Generate "UrlTitle" for all notes. "UrlTitle" is a friendly url for post</li>
|
|
||||||
<li>Generate "UrlTitle" for all notebooks</li>
|
|
||||||
<li>Generate "UrlTitle" for all singles</li>
|
|
||||||
*/
|
|
||||||
func (this *UpgradeService) UpgradeBetaToBeta2(userId string) (ok bool, msg string) {
|
|
||||||
if configService.GetGlobalStringConfig("UpgradeBetaToBeta2") != "" {
|
|
||||||
return false, "Leanote have been upgraded"
|
|
||||||
}
|
|
||||||
|
|
||||||
// 1. aboutMe -> page
|
|
||||||
userBlogs := []info.UserBlog{}
|
|
||||||
db.ListByQ(db.UserBlogs, bson.M{}, &userBlogs)
|
|
||||||
|
|
||||||
for _, userBlog := range userBlogs {
|
|
||||||
blogService.AddOrUpdateSingle(userBlog.UserId.Hex(), "", "About Me", userBlog.AboutMe)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2. 默认主题, 给admin用户
|
|
||||||
themeService.UpgradeThemeBeta2()
|
|
||||||
|
|
||||||
// 3. UrlTitles
|
|
||||||
|
|
||||||
// 3.1 note
|
|
||||||
notes := []info.Note{}
|
|
||||||
db.ListByQ(db.Notes, bson.M{}, ¬es)
|
|
||||||
for _, note := range notes {
|
|
||||||
data := bson.M{}
|
|
||||||
noteId := note.NoteId.Hex()
|
|
||||||
// PublicTime, RecommendTime = UpdatedTime
|
|
||||||
if note.IsBlog && note.PublicTime.Year() < 100 {
|
|
||||||
data["PublicTime"] = note.UpdatedTime
|
|
||||||
data["RecommendTime"] = note.UpdatedTime
|
|
||||||
Log("Time " + noteId)
|
|
||||||
}
|
|
||||||
data["UrlTitle"] = GetUrTitle(note.UserId.Hex(), note.Title, "note")
|
|
||||||
db.UpdateByIdAndUserIdMap2(db.Notes, note.NoteId, note.UserId, data)
|
|
||||||
Log(noteId)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 3.2
|
|
||||||
Log("notebook")
|
|
||||||
notebooks := []info.Notebook{}
|
|
||||||
db.ListByQ(db.Notebooks, bson.M{}, ¬ebooks)
|
|
||||||
for _, notebook := range notebooks {
|
|
||||||
notebookId := notebook.NotebookId.Hex()
|
|
||||||
data := bson.M{}
|
|
||||||
data["UrlTitle"] = GetUrTitle(notebook.UserId.Hex(), notebook.Title, "notebook")
|
|
||||||
db.UpdateByIdAndUserIdMap2(db.Notebooks, notebook.NotebookId, notebook.UserId, data)
|
|
||||||
Log(notebookId)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 3.3 single
|
|
||||||
/*
|
|
||||||
singles := []info.BlogSingle{}
|
|
||||||
db.ListByQ(db.BlogSingles, bson.M{}, &singles)
|
|
||||||
for _, single := range singles {
|
|
||||||
singleId := single.SingleId.Hex()
|
|
||||||
blogService.UpdateSingleUrlTitle(single.UserId.Hex(), singleId, single.Title)
|
|
||||||
Log(singleId)
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
// 删除索引
|
|
||||||
db.ShareNotes.DropIndex("UserId", "ToUserId", "NoteId")
|
|
||||||
ok = true
|
|
||||||
msg = "success"
|
|
||||||
configService.UpdateGlobalStringConfig(userId, "UpgradeBetaToBeta2", "1")
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Usn设置
|
|
||||||
// 客户端 api
|
|
||||||
|
|
||||||
func (this *UpgradeService) moveTag() {
|
|
||||||
usnI := 1
|
|
||||||
tags := []info.Tag{}
|
|
||||||
db.ListByQ(db.Tags, bson.M{}, &tags)
|
|
||||||
for _, eachTag := range tags {
|
|
||||||
tagTitles := eachTag.Tags
|
|
||||||
now := time.Now()
|
|
||||||
if tagTitles != nil && len(tagTitles) > 0 {
|
|
||||||
for _, tagTitle := range tagTitles {
|
|
||||||
noteTag := info.NoteTag{}
|
|
||||||
noteTag.TagId = bson.NewObjectId()
|
|
||||||
noteTag.Count = 1
|
|
||||||
noteTag.Tag = tagTitle
|
|
||||||
noteTag.UserId = eachTag.UserId
|
|
||||||
noteTag.CreatedTime = now
|
|
||||||
noteTag.UpdatedTime = now
|
|
||||||
noteTag.Usn = usnI
|
|
||||||
noteTag.IsDeleted = false
|
|
||||||
db.Insert(db.NoteTags, noteTag)
|
|
||||||
usnI++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (this *UpgradeService) setNotebookUsn() {
|
|
||||||
usnI := 1
|
|
||||||
notebooks := []info.Notebook{}
|
|
||||||
db.ListByQWithFields(db.Notebooks, bson.M{}, []string{"UserId"}, ¬ebooks)
|
|
||||||
|
|
||||||
for _, notebook := range notebooks {
|
|
||||||
db.UpdateByQField(db.Notebooks, bson.M{"_id": notebook.NotebookId}, "Usn", usnI)
|
|
||||||
usnI++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (this *UpgradeService) setNoteUsn() {
|
|
||||||
usnI := 1
|
|
||||||
notes := []info.Note{}
|
|
||||||
db.ListByQWithFields(db.Notes, bson.M{}, []string{"UserId"}, ¬es)
|
|
||||||
|
|
||||||
for _, note := range notes {
|
|
||||||
db.UpdateByQField(db.Notes, bson.M{"_id": note.NoteId}, "Usn", usnI)
|
|
||||||
usnI++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 升级为Api, beta.4
|
|
||||||
func (this *UpgradeService) Api(userId string) (ok bool, msg string) {
|
|
||||||
if configService.GetGlobalStringConfig("UpgradeBetaToBeta4") != "" {
|
|
||||||
return false, "Leanote have been upgraded"
|
|
||||||
}
|
|
||||||
|
|
||||||
// user
|
|
||||||
db.UpdateByQField(db.Users, bson.M{}, "Usn", 200000)
|
|
||||||
|
|
||||||
// notebook
|
|
||||||
db.UpdateByQField(db.Notebooks, bson.M{}, "IsDeleted", false)
|
|
||||||
this.setNotebookUsn();
|
|
||||||
|
|
||||||
// note
|
|
||||||
// 1-N
|
|
||||||
db.UpdateByQField(db.Notes, bson.M{}, "IsDeleted", false)
|
|
||||||
this.setNoteUsn();
|
|
||||||
|
|
||||||
// tag
|
|
||||||
// 1-N
|
|
||||||
/// tag, 要重新插入, 将之前的Tag表迁移到NoteTag中
|
|
||||||
this.moveTag();
|
|
||||||
|
|
||||||
configService.UpdateGlobalStringConfig(userId, "UpgradeBetaToBeta4", "1")
|
|
||||||
|
|
||||||
return true, ""
|
|
||||||
}
|
|
||||||
+15
-148
@@ -12,27 +12,6 @@ import (
|
|||||||
type UserService struct {
|
type UserService struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// 自增Usn
|
|
||||||
// 每次notebook,note添加, 修改, 删除, 都要修改
|
|
||||||
func (this *UserService) IncrUsn(userId string) int {
|
|
||||||
user := info.User{}
|
|
||||||
query := bson.M{"_id": bson.ObjectIdHex(userId)}
|
|
||||||
db.GetByQWithFields(db.Users, query, []string{"Usn"}, &user)
|
|
||||||
usn := user.Usn
|
|
||||||
usn += 1
|
|
||||||
Log("inc Usn")
|
|
||||||
db.UpdateByQField(db.Users, query, "Usn", usn)
|
|
||||||
return usn
|
|
||||||
// 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 {
|
|
||||||
user := info.User{}
|
|
||||||
query := bson.M{"_id": bson.ObjectIdHex(userId)}
|
|
||||||
db.GetByQWithFields(db.Users, query, []string{"Usn"}, &user)
|
|
||||||
return user.Usn
|
|
||||||
}
|
|
||||||
|
|
||||||
// 添加用户
|
// 添加用户
|
||||||
func (this *UserService) AddUser(user info.User) bool {
|
func (this *UserService) AddUser(user info.User) bool {
|
||||||
if user.UserId == "" {
|
if user.UserId == "" {
|
||||||
@@ -47,7 +26,7 @@ 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}");
|
||||||
}();
|
}();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -62,13 +41,6 @@ func (this *UserService) GetUserId(email string) string {
|
|||||||
return user.UserId.Hex()
|
return user.UserId.Hex()
|
||||||
}
|
}
|
||||||
|
|
||||||
// 得到用户名
|
|
||||||
func (this *UserService) GetUsername(userId string) string {
|
|
||||||
user := info.User{}
|
|
||||||
db.GetByQWithFields(db.Users, bson.M{"_id": bson.ObjectIdHex(userId)}, []string{"Username"}, &user)
|
|
||||||
return user.Username
|
|
||||||
}
|
|
||||||
|
|
||||||
// 是否存在该用户 email
|
// 是否存在该用户 email
|
||||||
func (this *UserService) IsExistsUser(email string) bool {
|
func (this *UserService) IsExistsUser(email string) bool {
|
||||||
if this.GetUserId(email) == "" {
|
if this.GetUserId(email) == "" {
|
||||||
@@ -103,7 +75,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 = siteUrl + "/" + user.Logo
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -119,8 +91,6 @@ func (this *UserService) GetUserInfo(userId string) info.User {
|
|||||||
func (this *UserService) GetUserInfoByEmail(email string) info.User {
|
func (this *UserService) GetUserInfoByEmail(email string) info.User {
|
||||||
user := info.User{}
|
user := info.User{}
|
||||||
db.GetByQ(db.Users, bson.M{"Email": email}, &user)
|
db.GetByQ(db.Users, bson.M{"Email": email}, &user)
|
||||||
// Logo路径问题, 有些有http: 有些没有
|
|
||||||
this.setUserLogo(&user)
|
|
||||||
return user
|
return user
|
||||||
}
|
}
|
||||||
// 得到用户信息 username
|
// 得到用户信息 username
|
||||||
@@ -128,15 +98,12 @@ func (this *UserService) GetUserInfoByUsername(username string) info.User {
|
|||||||
user := info.User{}
|
user := info.User{}
|
||||||
username = strings.ToLower(username)
|
username = strings.ToLower(username)
|
||||||
db.GetByQ(db.Users, bson.M{"Username": username}, &user)
|
db.GetByQ(db.Users, bson.M{"Username": username}, &user)
|
||||||
// Logo路径问题, 有些有http: 有些没有
|
|
||||||
this.setUserLogo(&user)
|
|
||||||
return user
|
return user
|
||||||
}
|
}
|
||||||
|
|
||||||
func (this *UserService) GetUserInfoByThirdUserId(thirdUserId string) info.User {
|
func (this *UserService) GetUserInfoByThirdUserId(thirdUserId string) info.User {
|
||||||
user := info.User{}
|
user := info.User{}
|
||||||
db.GetByQ(db.Users, bson.M{"ThirdUserId": thirdUserId}, &user)
|
db.GetByQ(db.Users, bson.M{"ThirdUserId": thirdUserId}, &user)
|
||||||
this.setUserLogo(&user)
|
|
||||||
return user
|
return user
|
||||||
}
|
}
|
||||||
func (this *UserService) ListUserInfosByUserIds(userIds []bson.ObjectId) []info.User {
|
func (this *UserService) ListUserInfosByUserIds(userIds []bson.ObjectId) []info.User {
|
||||||
@@ -166,58 +133,6 @@ func (this *UserService) MapUserInfoAndBlogInfosByUserIds(userIds []bson.ObjectI
|
|||||||
return this.MapUserInfoByUserIds(userIds)
|
return this.MapUserInfoByUserIds(userIds)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 返回info.UserAndBlog
|
|
||||||
func (this *UserService) MapUserAndBlogByUserIds(userIds []bson.ObjectId) map[string]info.UserAndBlog {
|
|
||||||
users := []info.User{}
|
|
||||||
db.ListByQ(db.Users, bson.M{"_id": bson.M{"$in": userIds}}, &users)
|
|
||||||
|
|
||||||
userBlogs := []info.UserBlog{}
|
|
||||||
db.ListByQ(db.UserBlogs, bson.M{"_id": bson.M{"$in": userIds}}, &userBlogs)
|
|
||||||
|
|
||||||
userBlogMap := make(map[bson.ObjectId]info.UserBlog, len(userBlogs))
|
|
||||||
for _, user := range userBlogs {
|
|
||||||
userBlogMap[user.UserId] = user
|
|
||||||
}
|
|
||||||
|
|
||||||
userAndBlogMap := make(map[string]info.UserAndBlog, len(users))
|
|
||||||
|
|
||||||
for _, user := range users {
|
|
||||||
this.setUserLogo(&user)
|
|
||||||
|
|
||||||
userBlog, ok := userBlogMap[user.UserId]
|
|
||||||
if !ok {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
userAndBlogMap[user.UserId.Hex()] = info.UserAndBlog{
|
|
||||||
UserId: user.UserId,
|
|
||||||
Username: user.Username,
|
|
||||||
Email: user.Email,
|
|
||||||
Logo: user.Logo,
|
|
||||||
BlogTitle: userBlog.Title,
|
|
||||||
BlogLogo: userBlog.Logo,
|
|
||||||
BlogUrl: blogService.GetUserBlogUrl(&userBlog, user.Username),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return userAndBlogMap
|
|
||||||
}
|
|
||||||
|
|
||||||
// 得到userAndBlog公开信息
|
|
||||||
func (this *UserService) GetUserAndBlog(userId string) info.UserAndBlog {
|
|
||||||
user := this.GetUserInfo(userId)
|
|
||||||
userBlog := blogService.GetUserBlog(userId)
|
|
||||||
return info.UserAndBlog{
|
|
||||||
UserId: user.UserId,
|
|
||||||
Username: user.Username,
|
|
||||||
Email: user.Email,
|
|
||||||
Logo: user.Logo,
|
|
||||||
BlogTitle: userBlog.Title,
|
|
||||||
BlogLogo: userBlog.Logo,
|
|
||||||
BlogUrl: blogService.GetUserBlogUrl(&userBlog, user.Username),
|
|
||||||
BlogUrls: blogService.GetBlogUrls(&userBlog, &user),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 通过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{}
|
||||||
@@ -228,35 +143,33 @@ func (this *UserService) GetUserInfosOrderBySeq(userIds []bson.ObjectId) []info.
|
|||||||
usersMap[user.UserId] = user
|
usersMap[user.UserId] = user
|
||||||
}
|
}
|
||||||
|
|
||||||
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] = true
|
|
||||||
users2 = append(users2, user)
|
users2 = append(users2, user)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return users2
|
return users2
|
||||||
}
|
}
|
||||||
|
|
||||||
// 使用email(username), 得到用户信息
|
// 使用email(username), pwd得到用户信息
|
||||||
func (this *UserService) GetUserInfoByName(emailOrUsername string) info.User {
|
func (this *UserService) LoginGetUserInfo(emailOrUsername, md5Pwd string) info.User {
|
||||||
emailOrUsername = strings.ToLower(emailOrUsername)
|
emailOrUsername = strings.ToLower(emailOrUsername)
|
||||||
|
|
||||||
user := info.User{}
|
user := info.User{}
|
||||||
if strings.Contains(emailOrUsername, "@") {
|
if strings.Contains(emailOrUsername, "@") {
|
||||||
db.GetByQ(db.Users, bson.M{"Email": emailOrUsername}, &user)
|
db.GetByQ(db.Users, bson.M{"Email": emailOrUsername, "Pwd": md5Pwd}, &user)
|
||||||
} else {
|
} else {
|
||||||
db.GetByQ(db.Users, bson.M{"Username": emailOrUsername}, &user)
|
db.GetByQ(db.Users, bson.M{"Username": emailOrUsername, "Pwd": md5Pwd}, &user)
|
||||||
}
|
}
|
||||||
this.setUserLogo(&user)
|
|
||||||
return user
|
return user
|
||||||
}
|
}
|
||||||
|
|
||||||
// 更新username
|
// 更新username
|
||||||
func (this *UserService) UpdateUsername(userId, username string) (bool, string) {
|
func (this *UserService) UpdateUsername(userId, username string) (bool, string) {
|
||||||
if userId == "" || username == "" || username == "admin" { // admin用户是内置的, 不能设置
|
if userId == "" || username == "" || username == "admin" { // admin用户是内置的, 不能设置
|
||||||
return false, "usernameIsExisted"
|
return false, "用户已存在"
|
||||||
}
|
}
|
||||||
usernameRaw := username // 原先的, 可能是同一个, 但有大小写
|
usernameRaw := username // 原先的, 可能是同一个, 但有大小写
|
||||||
username = strings.ToLower(username)
|
username = strings.ToLower(username)
|
||||||
@@ -264,7 +177,7 @@ func (this *UserService) UpdateUsername(userId, username string) (bool, string)
|
|||||||
// 先判断是否存在
|
// 先判断是否存在
|
||||||
userIdO := bson.ObjectIdHex(userId)
|
userIdO := bson.ObjectIdHex(userId)
|
||||||
if db.Has(db.Users, bson.M{"Username": username, "_id": bson.M{"$ne": userIdO}}) {
|
if db.Has(db.Users, bson.M{"Username": username, "_id": bson.M{"$ne": userIdO}}) {
|
||||||
return false, "usernameIsExisted"
|
return false, "用户已存在"
|
||||||
}
|
}
|
||||||
|
|
||||||
ok := db.UpdateByQMap(db.Users, bson.M{"_id": userIdO}, bson.M{"Username": username, "UsernameRaw": usernameRaw})
|
ok := db.UpdateByQMap(db.Users, bson.M{"_id": userIdO}, bson.M{"Username": username, "UsernameRaw": usernameRaw})
|
||||||
@@ -281,54 +194,19 @@ func (this *UserService) UpdateAvatar(userId, avatarPath string) (bool) {
|
|||||||
// 已经登录了的用户修改密码
|
// 已经登录了的用户修改密码
|
||||||
func (this *UserService) UpdatePwd(userId, oldPwd, pwd string) (bool, string) {
|
func (this *UserService) UpdatePwd(userId, oldPwd, pwd string) (bool, string) {
|
||||||
userInfo := this.GetUserInfo(userId)
|
userInfo := this.GetUserInfo(userId)
|
||||||
if !ComparePwd(oldPwd, userInfo.Pwd) {
|
if userInfo.Pwd != Md5(oldPwd) {
|
||||||
return false, "oldPasswordError"
|
return false, "旧密码错误"
|
||||||
}
|
}
|
||||||
|
ok := db.UpdateByQField(db.Users, bson.M{"_id": bson.ObjectIdHex(userId)}, "Pwd", Md5(pwd))
|
||||||
passwd := GenPwd(pwd)
|
|
||||||
if passwd == "" {
|
|
||||||
return false, "GenerateHash error"
|
|
||||||
}
|
|
||||||
|
|
||||||
ok := db.UpdateByQField(db.Users, bson.M{"_id": bson.ObjectIdHex(userId)}, "Pwd", passwd)
|
|
||||||
return ok, ""
|
return ok, ""
|
||||||
}
|
}
|
||||||
|
|
||||||
// 管理员重置密码
|
|
||||||
func (this *UserService) ResetPwd(adminUserId, userId, pwd string) (ok bool, msg string) {
|
|
||||||
if configService.GetAdminUserId() != adminUserId {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
passwd := GenPwd(pwd)
|
|
||||||
if passwd == "" {
|
|
||||||
return false, "GenerateHash error"
|
|
||||||
}
|
|
||||||
ok = db.UpdateByQField(db.Users, bson.M{"_id": bson.ObjectIdHex(userId)}, "Pwd", passwd)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 修改主题
|
// 修改主题
|
||||||
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
|
||||||
}
|
}
|
||||||
|
|
||||||
// 帐户类型设置
|
|
||||||
func (this *UserService) UpdateAccount(userId, accountType string, accountStartTime, accountEndTime time.Time,
|
|
||||||
maxImageNum, maxImageSize, maxAttachNum, maxAttachSize, maxPerAttachSize int) bool {
|
|
||||||
return db.UpdateByQI(db.Users, bson.M{"_id": bson.ObjectIdHex(userId)}, info.UserAccount{
|
|
||||||
AccountType: accountType,
|
|
||||||
AccountStartTime: accountStartTime,
|
|
||||||
AccountEndTime: accountEndTime,
|
|
||||||
MaxImageNum: maxImageNum,
|
|
||||||
MaxImageSize: maxImageSize,
|
|
||||||
MaxAttachNum: maxAttachNum,
|
|
||||||
MaxAttachSize: maxAttachSize,
|
|
||||||
MaxPerAttachSize: maxPerAttachSize,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
//---------------
|
//---------------
|
||||||
// 修改email
|
// 修改email
|
||||||
|
|
||||||
@@ -383,13 +261,6 @@ func (this *UserService) UpdateEmail(token string) (ok bool, msg, email string)
|
|||||||
//---------
|
//---------
|
||||||
// 第三方添加账号
|
// 第三方添加账号
|
||||||
func (this *UserService) ThirdAddUser(userId, email, pwd string) (ok bool, msg string) {
|
func (this *UserService) ThirdAddUser(userId, email, pwd string) (ok bool, msg string) {
|
||||||
// 判断该用户是否已有了帐户
|
|
||||||
userInfo := this.GetUserInfo(userId)
|
|
||||||
if userInfo.Email != "" {
|
|
||||||
msg = "你已有帐户"
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 判断email是否存在
|
// 判断email是否存在
|
||||||
if this.IsExistsUser(email) {
|
if this.IsExistsUser(email) {
|
||||||
msg = "该用户已存在"
|
msg = "该用户已存在"
|
||||||
@@ -406,7 +277,7 @@ func (this *UserService) ThirdAddUser(userId, email, pwd string) (ok bool, msg s
|
|||||||
// 宽度
|
// 宽度
|
||||||
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 {
|
||||||
@@ -420,11 +291,7 @@ func (this *UserService) ListUsers(pageNumber, pageSize int, sortField string, i
|
|||||||
skipNum, sortFieldR := parsePageAndSort(pageNumber, pageSize, sortField, isAsc)
|
skipNum, sortFieldR := parsePageAndSort(pageNumber, pageSize, sortField, isAsc)
|
||||||
query := bson.M{}
|
query := bson.M{}
|
||||||
if email != "" {
|
if email != "" {
|
||||||
orQ := []bson.M{
|
query["Email"] = bson.M{"$regex": bson.RegEx{".*?" + email + ".*", "i"}}
|
||||||
bson.M{"Email": bson.M{"$regex": bson.RegEx{".*?" + email + ".*", "i"}}},
|
|
||||||
bson.M{"Username": bson.M{"$regex": bson.RegEx{".*?" + email + ".*", "i"}}},
|
|
||||||
}
|
|
||||||
query["$or"] = orQ
|
|
||||||
}
|
}
|
||||||
q := db.Users.Find(query);
|
q := db.Users.Find(query);
|
||||||
// 总记录数
|
// 总记录数
|
||||||
|
|||||||
+6
-80
@@ -1,13 +1,7 @@
|
|||||||
package service
|
package service
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"regexp"
|
"github.com/revel/revel"
|
||||||
"strings"
|
|
||||||
"net/url"
|
|
||||||
"strconv"
|
|
||||||
"gopkg.in/mgo.v2"
|
|
||||||
"github.com/leanote/leanote/app/db"
|
|
||||||
"gopkg.in/mgo.v2/bson"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// init service, for share service bettween services
|
// init service, for share service bettween services
|
||||||
@@ -20,7 +14,6 @@ var noteContentHistoryService, NoteContentHistoryS *NoteContentHistoryService
|
|||||||
var trashService, TrashS *TrashService
|
var trashService, TrashS *TrashService
|
||||||
var shareService, ShareS *ShareService
|
var shareService, ShareS *ShareService
|
||||||
var userService, UserS *UserService
|
var userService, UserS *UserService
|
||||||
var groupService, GroupS *GroupService
|
|
||||||
var tagService, TagS *TagService
|
var tagService, TagS *TagService
|
||||||
var blogService, BlogS *BlogService
|
var blogService, BlogS *BlogService
|
||||||
var tokenService, TokenS *TokenService
|
var tokenService, TokenS *TokenService
|
||||||
@@ -35,7 +28,8 @@ var emailService, EmailS *EmailService
|
|||||||
var AuthS *AuthService
|
var AuthS *AuthService
|
||||||
var UpgradeS *UpgradeService
|
var UpgradeS *UpgradeService
|
||||||
var SessionS, sessionService *SessionService
|
var SessionS, sessionService *SessionService
|
||||||
var ThemeS, themeService *ThemeService
|
|
||||||
|
var siteUrl string
|
||||||
|
|
||||||
// onAppStart调用
|
// onAppStart调用
|
||||||
func InitService() {
|
func InitService() {
|
||||||
@@ -45,7 +39,6 @@ func InitService() {
|
|||||||
TrashS = &TrashService{}
|
TrashS = &TrashService{}
|
||||||
ShareS = &ShareService{}
|
ShareS = &ShareService{}
|
||||||
UserS = &UserService{}
|
UserS = &UserService{}
|
||||||
GroupS = &GroupService{}
|
|
||||||
TagS = &TagService{}
|
TagS = &TagService{}
|
||||||
BlogS = &BlogService{}
|
BlogS = &BlogService{}
|
||||||
TokenS = &TokenService{}
|
TokenS = &TokenService{}
|
||||||
@@ -60,7 +53,6 @@ func InitService() {
|
|||||||
EmailS = NewEmailService()
|
EmailS = NewEmailService()
|
||||||
UpgradeS = &UpgradeService{}
|
UpgradeS = &UpgradeService{}
|
||||||
SessionS = &SessionService{}
|
SessionS = &SessionService{}
|
||||||
ThemeS = &ThemeService{}
|
|
||||||
|
|
||||||
notebookService = NotebookS
|
notebookService = NotebookS
|
||||||
noteService = NoteS
|
noteService = NoteS
|
||||||
@@ -68,7 +60,6 @@ func InitService() {
|
|||||||
trashService = TrashS
|
trashService = TrashS
|
||||||
shareService = ShareS
|
shareService = ShareS
|
||||||
userService = UserS
|
userService = UserS
|
||||||
groupService = GroupS
|
|
||||||
tagService = TagS
|
tagService = TagS
|
||||||
blogService = BlogS
|
blogService = BlogS
|
||||||
tokenService = TokenS
|
tokenService = TokenS
|
||||||
@@ -79,72 +70,7 @@ func InitService() {
|
|||||||
configService = ConfigS
|
configService = ConfigS
|
||||||
emailService = EmailS
|
emailService = EmailS
|
||||||
sessionService = SessionS
|
sessionService = SessionS
|
||||||
themeService = ThemeS
|
|
||||||
}
|
|
||||||
|
|
||||||
//----------------
|
|
||||||
// service 公用方法
|
|
||||||
|
|
||||||
// 将name=val的val进行encoding
|
|
||||||
func decodeValue(val string) string {
|
|
||||||
v, _ := url.ParseQuery("a=" + val)
|
|
||||||
return v.Get("a")
|
|
||||||
}
|
|
||||||
|
|
||||||
func encodeValue(val string) string {
|
|
||||||
if val == "" {
|
|
||||||
return val
|
|
||||||
}
|
|
||||||
v := url.Values{}
|
|
||||||
v.Set("", val)
|
|
||||||
return v.Encode()[1:]
|
|
||||||
}
|
|
||||||
// 添加笔记时通过title得到urlTitle
|
|
||||||
func fixUrlTitle(urlTitle string) string {
|
|
||||||
if urlTitle != "" {
|
|
||||||
// 把特殊字段给替换掉
|
|
||||||
// str := `life "%&()+,/:;<>=?@\|`
|
|
||||||
reg, _ := regexp.Compile("/|#|\\$|!|\\^|\\*|'| |\"|%|&|\\(|\\)|\\+|\\,|/|:|;|<|>|=|\\?|@|\\||\\\\")
|
|
||||||
urlTitle = reg.ReplaceAllString(urlTitle, "-")
|
|
||||||
urlTitle = strings.Trim(urlTitle, "-") // 左右单独的-去掉
|
|
||||||
// 把空格替换成-
|
|
||||||
// urlTitle = strings.Replace(urlTitle, " ", "-", -1)
|
|
||||||
for strings.Index(urlTitle, "--") >= 0 { // 防止出现连续的--
|
|
||||||
urlTitle = strings.Replace(urlTitle, "--", "-", -1)
|
|
||||||
}
|
|
||||||
return encodeValue(urlTitle)
|
|
||||||
}
|
|
||||||
return urlTitle
|
|
||||||
}
|
|
||||||
|
|
||||||
func getUniqueUrlTitle(userId string, urlTitle string, types string, padding int) string {
|
|
||||||
urlTitle2 := urlTitle
|
|
||||||
if padding > 1 {
|
|
||||||
urlTitle2 = urlTitle + "-" + strconv.Itoa(padding)
|
|
||||||
}
|
|
||||||
userIdO := bson.ObjectIdHex(userId)
|
|
||||||
|
|
||||||
var collection *mgo.Collection
|
//
|
||||||
if types == "note" {
|
siteUrl, _ = revel.Config.String("site.url")
|
||||||
collection = db.Notes
|
}
|
||||||
} else if types == "notebook" {
|
|
||||||
collection = db.Notebooks
|
|
||||||
} else if types == "single" {
|
|
||||||
collection = db.BlogSingles
|
|
||||||
}
|
|
||||||
for db.Has(collection, bson.M{"UserId": userIdO, "UrlTitle": urlTitle2}) { // 用户下唯一
|
|
||||||
padding++
|
|
||||||
urlTitle2 = urlTitle + "-" + strconv.Itoa(padding)
|
|
||||||
}
|
|
||||||
|
|
||||||
return urlTitle2
|
|
||||||
}
|
|
||||||
// types == note,notebook,single
|
|
||||||
func GetUrTitle(userId string, title string, types string) string {
|
|
||||||
urlTitle := strings.Trim(title, " ")
|
|
||||||
if urlTitle == "" {
|
|
||||||
urlTitle = "Untitled-" + userId
|
|
||||||
}
|
|
||||||
urlTitle = fixUrlTitle(urlTitle)
|
|
||||||
return getUniqueUrlTitle(userId, urlTitle, types, 1)
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,237 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/robfig/revel"
|
||||||
|
|
||||||
|
"github.com/leanote/leanote/app/service"
|
||||||
|
"github.com/leanote/leanote/app/info"
|
||||||
|
. "github.com/leanote/leanote/app/lea"
|
||||||
|
// "github.com/leanote/leanote/app/lea/memcache"
|
||||||
|
// "github.com/leanote/leanote/app/lea/netutil"
|
||||||
|
"github.com/leanote/leanote/app/lea/html2image"
|
||||||
|
"time"
|
||||||
|
"fmt"
|
||||||
|
"gopkg.in/mgo.v2/bson"
|
||||||
|
// "gopkg.in/mgo.v2"
|
||||||
|
// "encoding/json"
|
||||||
|
// "strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
var userId = "5295d4c95b1dd58edb4a7f4f"
|
||||||
|
var userIdO = bson.ObjectIdHex(userId)
|
||||||
|
|
||||||
|
var userId3 = "52b43ae4cfeeae33ef073b2b"
|
||||||
|
var userId3O = bson.ObjectIdHex(userId3)
|
||||||
|
|
||||||
|
var toUserId = "52b4376bcfeeae33ef073b21"
|
||||||
|
var toUserIdO = bson.ObjectIdHex(toUserId)
|
||||||
|
|
||||||
|
var notebookId = "52b2d051ea3ba3d3fb35910c"
|
||||||
|
var notebookIdO = bson.ObjectIdHex(notebookId)
|
||||||
|
var notebookId2O = bson.ObjectIdHex("52b2d051ea3ba3d3fb35910b")
|
||||||
|
|
||||||
|
var noteId = "52b2dd34ea3ba3d3fb35910d"
|
||||||
|
var noteIdO = bson.ObjectIdHex(noteId)
|
||||||
|
|
||||||
|
func testNoteService() {
|
||||||
|
println("testNoteService")
|
||||||
|
noteService := &service.NoteService{}
|
||||||
|
note := noteService.GetBlogNote("535f9e6b19807a4c8d000000")
|
||||||
|
LogJ(note)
|
||||||
|
/*
|
||||||
|
_, notes := noteService.SearchNote("go", "52d3e8ac99c37b7f0d000001", 1, 30, "", false, true);
|
||||||
|
LogJ(notes)
|
||||||
|
*/
|
||||||
|
return;
|
||||||
|
|
||||||
|
/*
|
||||||
|
noteService.AddNote(info.Note{UserId: userIdO,
|
||||||
|
NotebookId: notebookIdO,
|
||||||
|
Title: "life you", Tags: []string{"red", "yellow"}})
|
||||||
|
*/
|
||||||
|
|
||||||
|
noteService.AddNoteContent(info.NoteContent{UserId: userIdO,
|
||||||
|
NoteId: bson.ObjectIdHex("52b4531dcfeeae33ef073b33"),
|
||||||
|
Content:"xxxxxxxxxxxxxxxxxxxxlifeyou can m<div><p></p></div>"})
|
||||||
|
|
||||||
|
// noteService.UpdateNoteContent(userId, userId, "52b2dd34ea3ba3d3fb35910d", "life2---------")
|
||||||
|
|
||||||
|
// noteService.AddNote(info.Note{Title: "life", Tags: []string{"life", "life2"}})
|
||||||
|
|
||||||
|
// println(bson.IsObjectIdHex(id))
|
||||||
|
|
||||||
|
// note := noteService.Get(id)
|
||||||
|
// fmt.Println(note)
|
||||||
|
|
||||||
|
// noteService.UpdateTags(id, []string{"lifedd", "life2"});
|
||||||
|
}
|
||||||
|
|
||||||
|
func testNotebookService() {
|
||||||
|
service := &service.NotebookService{}
|
||||||
|
Log(service.IsBlog("52ccb959bcbf21610d000001"))
|
||||||
|
|
||||||
|
return;
|
||||||
|
|
||||||
|
notebooks := service.GetNotebooks(userId3)
|
||||||
|
LogJ(notebooks)
|
||||||
|
|
||||||
|
// b, _ := json.MarshalIndent(notebooks, "", " ")
|
||||||
|
// fmt.Println(string(b))
|
||||||
|
|
||||||
|
// service.UpdateNotebookTitle("52b2cf9eea3ba3d3fb359108", userId, "JS")
|
||||||
|
|
||||||
|
// service.SortNotebooks(userId, map[string]int{"52b2d051ea3ba3d3fb35910c": 4, "52b2d051ea3ba3d3fb35910b": 3})
|
||||||
|
|
||||||
|
/*
|
||||||
|
service.AddNotebook(info.Notebook{UserId: userId3O,
|
||||||
|
ParentNotebookId: bson.ObjectIdHex("52b43c1fcfeeae33ef073b2e"),
|
||||||
|
Title: "Mac-life",
|
||||||
|
Seq: 0})
|
||||||
|
*/
|
||||||
|
|
||||||
|
println("xxx")
|
||||||
|
}
|
||||||
|
|
||||||
|
func testShareService() {
|
||||||
|
service := &service.ShareService{}
|
||||||
|
|
||||||
|
// service.AddShareNote("52bd127dbcbf216d0b000000", 1, "5295d4c95b1dd58edb4a7f4f", "c@a.com")
|
||||||
|
LogJ(service.ListNoteShareUserInfo("52cd11a1bcbf215680000000", "5295d4c95b1dd58edb4a7f4f"))
|
||||||
|
return;
|
||||||
|
|
||||||
|
/*
|
||||||
|
service.AddShareNotebook(info.ShareNotebook{UserId: userId3O, ToUserId: userIdO,
|
||||||
|
NotebookId: bson.ObjectIdHex("52b43c38cfeeae33ef073b30")})
|
||||||
|
*/
|
||||||
|
|
||||||
|
notebooks,_ := service.GetShareNotebooks(userId)
|
||||||
|
LogJ(notebooks)
|
||||||
|
|
||||||
|
// noteService.AddNoteContent(info.NoteContent{UserId: userIdO,
|
||||||
|
// NoteId: bson.ObjectIdHex("52b2dd34ea3ba3d3fb35910d"), Content:"xxxxxxxxxxxxxxxxxxxxlifeyou can m<div><p></p></div>"})
|
||||||
|
|
||||||
|
|
||||||
|
// noteService.AddNote(info.Note{Title: "life", Tags: []string{"life", "life2"}})
|
||||||
|
|
||||||
|
// println(bson.IsObjectIdHex(id))
|
||||||
|
|
||||||
|
// note := noteService.Get(id)
|
||||||
|
// fmt.Println(note)
|
||||||
|
|
||||||
|
// noteService.UpdateTags(id, []string{"lifedd", "life2"});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
func testAuthService() {
|
||||||
|
userService := &service.UserService{}
|
||||||
|
LogJ(userService.GetUserInfo("52d26b4e99c37b609a000001"))
|
||||||
|
// userService.AddUser(info.User{UserId: bson.ObjectIdHex("52d26b4e99c37b609a000001"), Email: "leanote@leanote.com", Pwd:"abc"})
|
||||||
|
return;
|
||||||
|
|
||||||
|
authService := &service.AuthService{}
|
||||||
|
authService.Register("f@a.com", "abc")
|
||||||
|
|
||||||
|
// fmt.Println(authService.LogonGetUserInfo("a@a.com", "abc"))
|
||||||
|
|
||||||
|
// noteService.AddNoteContent(info.NoteContent{UserId: userIdO,
|
||||||
|
// NoteId: bson.ObjectIdHex("52b2dd34ea3ba3d3fb35910d"), Content:"xxxxxxxxxxxxxxxxxxxxlifeyou can m<div><p></p></div>"})
|
||||||
|
|
||||||
|
// noteService.AddNote(info.Note{Title: "life", Tags: []string{"life", "life2"}})
|
||||||
|
|
||||||
|
// println(bson.IsObjectIdHex(id))
|
||||||
|
|
||||||
|
// note := noteService.Get(id)
|
||||||
|
// fmt.Println(note)
|
||||||
|
|
||||||
|
// noteService.UpdateTags(id, []string{"lifedd", "life2"});
|
||||||
|
}
|
||||||
|
|
||||||
|
func testTagService() {
|
||||||
|
service := &service.TagService{}
|
||||||
|
// service.AddTags("5295d4c95b1dd58edb4a7f4f", []string{"life", "blue", "yellow"})
|
||||||
|
// service.AddTags("5295d4c95b1dd58edb4a7f4f", []string{"what", "can", "make"})
|
||||||
|
LogJ(service.GetTags("5295d4c95b1dd58edb4a7f4f"))
|
||||||
|
}
|
||||||
|
|
||||||
|
func testHtml2Image() {
|
||||||
|
start := time.Now()
|
||||||
|
Log("start...")
|
||||||
|
// TestFillString()
|
||||||
|
|
||||||
|
|
||||||
|
html2image.ToImage("uid", "username", "noteId", "开发一款属于自己的编程语言,开发一款属于自己的编程语言听起来是不是很酷?", `
|
||||||
|
<div class="each-post">
|
||||||
|
<p>
|
||||||
|
一个合格的 Techspace 需要有足够专业的器材、场地和资源,你可以和你的团队在里面进行激光切割、快速贴片甚至加工木材等操作,在相对独立的空间内又能同周围的同道友人互相激发切磋。国内现有的 Techspace 没几家,不久前我去深圳特地拜访了当地的 Techspace,很喜欢那里的氛围,希望国内其他地方也能有更多这类空间供创客发挥。
|
||||||
|
假如你有一个比较成型的想法,想在硬件领域做点事情,核心团队也基本组好,硬件软件交互基本都有专人了。</p>
|
||||||
|
<p><a>这时候你的首要目标</a>,就是找个地方,按照你的计划,尽早做出一个可用的原型。Techspace可能是一个合适的地方。
|
||||||
|
一个合格的 Techspace 需要有足够专业的器材、场地和资源,你可以和你的团队在里面进行激光切割、快速贴片甚至加工木材等操作,在相对独立的空间内又能同周围的同道友人互相激发切磋。国内现有的 Techspace 没几家,不久前我去深圳特地拜访了当地的 Techspace,很喜欢那里的氛围,希望国内其他地方也能有更多这类空间供创客发挥。
|
||||||
|
深圳 Techspace 位于工业区,园区内有奥迪、BMW 等企业的厂房,在大门口我停下来问保安,M10 栋在哪里?保安答,去 Techspace?最里面靠右手那栋。惊叹于保安的机智,我也在想,莫非有许多朋友都慕名来到这巨大园区寻访 Techspace?
|
||||||
|
穿过一片工业区里的高楼和各种建筑材料
|
||||||
|
</p>
|
||||||
|
<!--
|
||||||
|
<pre class="">cd jpeg-9a/<br>./configure --enable-shared --enable-static
|
||||||
|
make<br>make --- install</pre>
|
||||||
|
<p>
|
||||||
|
life you can, !!@kk
|
||||||
|
</p>
|
||||||
|
|
||||||
|
-->
|
||||||
|
</div>
|
||||||
|
`, "/Users/life/Desktop/a.png")
|
||||||
|
fmt.Printf("time cost %v\n", time.Now().Sub(start))
|
||||||
|
}
|
||||||
|
|
||||||
|
func testLea() {
|
||||||
|
names := ListDir("/Users/life/Documents/Go/package/src/leanote")
|
||||||
|
fmt.Println(names);
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
revel.BasePath = "/Users/life/Documents/Go/package/src/leanote"
|
||||||
|
// testLea();
|
||||||
|
|
||||||
|
// a, b := SplitFilename("http://ab/c/a.gif#??")
|
||||||
|
// println(a)
|
||||||
|
// println(b)
|
||||||
|
|
||||||
|
// path, ok := netutil.WriteUrl("http://a.36krcnd.com/photo/2014/9bd1a07c0973d79ca05ad13c3c2e16b8.png!slider", "/tmp")
|
||||||
|
// println(path)
|
||||||
|
// testHtml2Image();
|
||||||
|
|
||||||
|
// println(IsObjectId("52d26b4e99c37b609a000001"))
|
||||||
|
|
||||||
|
// b := `请点击链接验证邮箱: <a href="">http://leanote.com/user/activeEmail?token=d8ca086cce5550a6227f9dc84dbac09d</a>. 48小时后过期.`
|
||||||
|
// SendEmail("lifephp@gmail.com", "leanote-验证邮箱", "验证邮", b)
|
||||||
|
|
||||||
|
//_, err := mgo.Dial("mongodb://leanote:nKFAkxKnWkEQy8Vv2LlM@115.28.133.226:27017/leanote")
|
||||||
|
|
||||||
|
// testNotebookService();
|
||||||
|
// testNoteService();
|
||||||
|
// testShareService()
|
||||||
|
// testAuthService()
|
||||||
|
|
||||||
|
// testTagService();
|
||||||
|
/*
|
||||||
|
filename := "你好59.26.png"
|
||||||
|
ext := SubstringByte(filename, strings.LastIndex(filename, "."))
|
||||||
|
ext = strings.ToLower(ext)
|
||||||
|
print(ext)
|
||||||
|
52d26ab199c37b5f80000001
|
||||||
|
|
||||||
|
Log(bson.NewObjectId())
|
||||||
|
Log(bson.NewObjectId())
|
||||||
|
Log(bson.NewObjectId())
|
||||||
|
|
||||||
|
*/
|
||||||
|
// Log(TransferExt("/你好a/b/a.gif", ".jpg"))
|
||||||
|
// TransToGif("/Users/life/Desktop/a2.png", 0, false)
|
||||||
|
|
||||||
|
// Log(IsUsername("xx**x"))
|
||||||
|
|
||||||
|
/*
|
||||||
|
memcache.Set("xx", map[string]string{"A":"you"}, 0)
|
||||||
|
a := memcache.Get("xx")
|
||||||
|
Log(a)
|
||||||
|
*/
|
||||||
|
}
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
package tests
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
"github.com/leanote/leanote/app/db"
|
|
||||||
// . "github.com/leanote/leanote/app/lea"
|
|
||||||
"github.com/leanote/leanote/app/service"
|
|
||||||
// "gopkg.in/mgo.v2"
|
|
||||||
// "fmt"
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
db.Init("mongodb://localhost:27017/leanote", "leanote")
|
|
||||||
service.InitService()
|
|
||||||
}
|
|
||||||
|
|
||||||
// 测试登录
|
|
||||||
func TestAuth(t *testing.T) {
|
|
||||||
_, err := service.AuthS.Login("admin", "abc123")
|
|
||||||
if err != nil {
|
|
||||||
t.Error("Admin User Auth Error")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
package tests
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
"github.com/leanote/leanote/app/db"
|
|
||||||
// . "github.com/leanote/leanote/app/lea"
|
|
||||||
// "github.com/leanote/leanote/app/service"
|
|
||||||
// "gopkg.in/mgo.v2"
|
|
||||||
// "fmt"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestDBConnect(t *testing.T) {
|
|
||||||
db.Init("mongodb://localhost:27017/leanote", "leanote")
|
|
||||||
}
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
package tests
|
|
||||||
func a() {
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,130 @@
|
|||||||
|
{{template "admin/top.html" .}}
|
||||||
|
<div class="m-b-md"> <h3 class="m-b-none">Blog</h3></div>
|
||||||
|
|
||||||
|
<section class="panel panel-default">
|
||||||
|
<div class="row wrapper">
|
||||||
|
<div class="col-sm-5 m-b-xs">
|
||||||
|
<button class="btn btn-sm btn-default">
|
||||||
|
Action1
|
||||||
|
</button>
|
||||||
|
<button class="btn btn-sm btn-default">
|
||||||
|
Action2
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-4 m-b-xs">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-3">
|
||||||
|
<div class="input-group search-group">
|
||||||
|
<input type="text" class="input-sm form-control" placeholder="Title" id="keywords" value="{{.keywords}}" />
|
||||||
|
<span class="input-group-btn">
|
||||||
|
<button class="btn btn-sm btn-default" type="button" data-url="/adminBlog/index">Search</button>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="table-responsive">
|
||||||
|
<table class="table table-striped b-t b-light">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th width="20">
|
||||||
|
<input type="checkbox">
|
||||||
|
</th>
|
||||||
|
{{$url := urlConcat "/adminBlog/index" "keywords" .keywords}}
|
||||||
|
<th
|
||||||
|
{{sorterTh $url "title" .sorter}}
|
||||||
|
>
|
||||||
|
Title
|
||||||
|
<span class="th-sort">
|
||||||
|
<i class="fa fa-sort-down"></i>
|
||||||
|
<i class="fa fa-sort-up"></i>
|
||||||
|
<i class="fa fa-sort"></i>
|
||||||
|
</span>
|
||||||
|
</th>
|
||||||
|
<th
|
||||||
|
{{sorterTh $url "userId" .sorter}}
|
||||||
|
>
|
||||||
|
Username
|
||||||
|
<span class="th-sort">
|
||||||
|
<i class="fa fa-sort-down"></i>
|
||||||
|
<i class="fa fa-sort-up"></i>
|
||||||
|
<i class="fa fa-sort"></i>
|
||||||
|
</span>
|
||||||
|
</th>
|
||||||
|
|
||||||
|
<th
|
||||||
|
{{sorterTh $url "createdTime" .sorter}}
|
||||||
|
>
|
||||||
|
Create Date
|
||||||
|
<span class="th-sort">
|
||||||
|
<i class="fa fa-sort-down"></i>
|
||||||
|
<i class="fa fa-sort-up"></i>
|
||||||
|
<i class="fa fa-sort"></i>
|
||||||
|
</span>
|
||||||
|
</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{{range .blogs}}
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<input type="checkbox" name="post[]" value="2">
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<a href="/blog/view/{{.NoteId.Hex}}" target="_blank">{{.Title|raw}}</a>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<a href="/blog/{{.UserId.Hex}}" target="_blank">
|
||||||
|
{{.User.Username}}
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{{.CreatedTime|datetime}}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{{end}}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<footer class="panel-footer">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-sm-4 hidden-xs">
|
||||||
|
<button class="btn btn-sm btn-default">
|
||||||
|
Action1
|
||||||
|
</button>
|
||||||
|
<button class="btn btn-sm btn-default">
|
||||||
|
Action2
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-4 text-center">
|
||||||
|
<small class="text-muted inline m-t-sm m-b-sm">
|
||||||
|
showing 20-30 of 50 items
|
||||||
|
</small>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-4 text-right text-center-xs">
|
||||||
|
{{set . "url" (urlConcat "/adminBlog/index" "sorter" .sorter "keywords" .keywords)}}
|
||||||
|
{{template "admin/user/page.html" .}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</footer>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{{template "admin/footer.html" .}}
|
||||||
|
|
||||||
|
<script>
|
||||||
|
$(function() {
|
||||||
|
$(".change-recommend").click(function() {
|
||||||
|
var isRecommend = +$(this).data("recommend");
|
||||||
|
var noteId = $(this).data("id");
|
||||||
|
var t = this;
|
||||||
|
$(t).button("loading");
|
||||||
|
ajaxGet("/adminBlog/setRecommend", {noteId: noteId, recommend: !isRecommend}, function() {
|
||||||
|
$(t).button("reset");
|
||||||
|
$(t).text(isRecommend ? "N" : "Y");
|
||||||
|
$(t).data("recommend", !isRecommend);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{{template "admin/end.html" .}}
|
||||||
File renamed without changes.
File renamed without changes.
Loaded 100 of 2687 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user