diff --git a/Gulpfile.js b/Gulpfile.js index 539986a..8670783 100644 --- a/Gulpfile.js +++ b/Gulpfile.js @@ -21,7 +21,7 @@ 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', // 使用打成的包, 加载速度快 + // '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', @@ -136,6 +136,7 @@ gulp.task('devToProHtml', function() { .pipe(replace(//, '')) // 替换 // .pipe(replace(//, '')) // 替换 .pipe(replace(//, '')) // 替换 + .pipe(replace('/tinymce/tinymce.js', '/tinymce/tinymce.full.min.js')) // 替换 .pipe(replace(//, "var tinyMCEPreInit = {base: '/public/tinymce', suffix: '.min'};")) // 替换 .pipe(replace(/plugins\/main.js/, "plugins/main.min.js")) // 替换 // 连续两个空行换成一个空行 @@ -152,7 +153,6 @@ gulp.task('devToProHtml', function() { .pipe(gulp.dest(noteProBase)); }); -// Get used keys // 只获取需要js i18n的key var path = require('path'); gulp.task('i18n', function() { @@ -230,9 +230,18 @@ gulp.task('i18n', function() { } // msg.zh, msg.js - function genI18nJsFile(fromFilename, keys) { - var msgs = getAllMsgs(leanoteBase + '/messages/' + fromFilename); - var toFilename = fromFilename + '.js'; + function genI18nJsFile(fromFilename, otherNames, keys) { + var msgs = {}; + otherNames.unshift(fromFilename); + // console.log(fromFilename); + // console.log(otherNames); + otherNames.forEach(function (name) { + var tmpMsgs = getAllMsgs(leanoteBase + '/messages/' + name); + for (var i in tmpMsgs) { + msgs[i] = tmpMsgs[i]; + } + }); + var toMsgs = {}; for (var i in msgs) { // 只要需要的 @@ -250,16 +259,23 @@ gulp.task('i18n', function() { '}' + 'return key;' + '}'; + // 写入到文件中 + var toFilename = fromFilename + '.js'; fs.writeFile(base + '/js/i18n/' + toFilename, str); } - genI18nJsFile('msg.zh', keys); - genI18nJsFile('msg.en', keys); - genI18nJsFile('msg.fr', keys); - genI18nJsFile('blog.zh', keys); - genI18nJsFile('blog.en', keys); - genI18nJsFile('blog.fr', keys); + // 必须要的 + // keys.push(); + + genI18nJsFile('blog.zh', [], keys); + genI18nJsFile('blog.en', [], keys); + genI18nJsFile('blog.fr', [], keys); + + genI18nJsFile('msg.fr', ['member.fr'], keys); + genI18nJsFile('msg.zh', ['member.zh'], keys); + genI18nJsFile('msg.en', ['member.en'], keys); + }); // 合并album需要的js diff --git a/app/controllers/AttachController.go b/app/controllers/AttachController.go index 3852fad..e82d142 100644 --- a/app/controllers/AttachController.go +++ b/app/controllers/AttachController.go @@ -67,7 +67,9 @@ func (c Attach) uploadAttach(noteId string) (re info.Re) { } // 生成上传路径 - filePath := "files/" + c.GetUserId() + "/attachs" + // filePath := "files/" + c.GetUserId() + "/attachs" + newGuid := NewGuid() + filePath := "files/" + GetRandomFilePath(c.GetUserId(), newGuid) + "/attachs" dir := revel.BasePath + "/" + filePath err = os.MkdirAll(dir, 0755) if err != nil { @@ -76,7 +78,7 @@ func (c Attach) uploadAttach(noteId string) (re info.Re) { // 生成新的文件名 filename := handel.Filename _, ext := SplitFilename(filename) // .doc - filename = NewGuid() + ext + filename = newGuid + ext toPath := dir + "/" + filename err = ioutil.WriteFile(toPath, data, 0777) if err != nil { @@ -165,10 +167,16 @@ func (c Attach) DownloadAll(noteId string) revel.Result { filename = "all.tar.gz" } + dir := revel.BasePath + "/files/attach_all" + + if !MkdirAll(dir) { + return c.RenderText("error") + } + // file write - fw, err := os.Create(revel.BasePath + "/files/" + filename) + fw, err := os.Create(dir + "/" + filename) if err != nil { - return c.RenderText("") + return c.RenderText("error") } // defer fw.Close() // 不需要关闭, 还要读取给用户下载 diff --git a/app/controllers/AuthController.go b/app/controllers/AuthController.go index ecfe5ed..7463217 100644 --- a/app/controllers/AuthController.go +++ b/app/controllers/AuthController.go @@ -4,6 +4,7 @@ import ( "github.com/leanote/leanote/app/info" . "github.com/leanote/leanote/app/lea" "github.com/revel/revel" + "strings" // "strconv" ) @@ -127,6 +128,8 @@ func (c Auth) DoRegister(email, pwd, iu string) revel.Result { return c.RenderRe(re) } + email = strings.ToLower(email) + // 注册 re.Ok, re.Msg = authService.Register(email, pwd, iu) @@ -141,6 +144,7 @@ func (c Auth) DoRegister(email, pwd, iu string) revel.Result { //-------- // 找回密码 func (c Auth) FindPassword() revel.Result { + c.SetLocale() c.RenderArgs["title"] = c.Message("findPassword") c.RenderArgs["subTitle"] = c.Message("findPassword") return c.RenderTemplate("home/find_password.html") @@ -154,6 +158,7 @@ func (c Auth) DoFindPassword(email string) revel.Result { // 点击链接后, 先验证之 func (c Auth) FindPassword2(token string) revel.Result { + c.SetLocale() c.RenderArgs["title"] = c.Message("findPassword") c.RenderArgs["subTitle"] = c.Message("findPassword") if token == "" { diff --git a/app/controllers/FileController.go b/app/controllers/FileController.go index 0f54e8f..8a1fda8 100644 --- a/app/controllers/FileController.go +++ b/app/controllers/FileController.go @@ -109,7 +109,8 @@ func (c File) uploadImage(from, albumId string) (re info.Re) { if from == "logo" || from == "blogLogo" { fileUrlPath = "public/upload/" + Digest3(userId) + "/" + userId + "/images/logo" } else { - fileUrlPath = "files/" + Digest3(userId) + "/" + userId + "/" + Digest2(newGuid) + "/images" + // fileUrlPath = "files/" + Digest3(userId) + "/" + userId + "/" + Digest2(newGuid) + "/images" + fileUrlPath = "files/" + GetRandomFilePath(userId, newGuid) + "/images" } dir := revel.BasePath + "/" + fileUrlPath @@ -242,7 +243,8 @@ func (c File) CopyHttpImage(src string) revel.Result { // 生成上传路径 newGuid := NewGuid() userId := c.GetUserId() - fileUrlPath := "files/" + Digest3(userId) + "/" + userId + "/" + Digest2(newGuid) + "/images" + // fileUrlPath := "files/" + Digest3(userId) + "/" + userId + "/" + Digest2(newGuid) + "/images" + fileUrlPath := "files/" + GetRandomFilePath(userId, newGuid) + "/images" dir := revel.BasePath + "/" + fileUrlPath err := os.MkdirAll(dir, 0755) if err != nil { diff --git a/app/controllers/NoteController.go b/app/controllers/NoteController.go index 9a911e8..1c34cde 100644 --- a/app/controllers/NoteController.go +++ b/app/controllers/NoteController.go @@ -3,7 +3,6 @@ package controllers import ( "github.com/revel/revel" // "encoding/json" - "fmt" "github.com/leanote/leanote/app/info" . "github.com/leanote/leanote/app/lea" "gopkg.in/mgo.v2/bson" @@ -14,6 +13,7 @@ import ( "time" // "github.com/leanote/leanote/app/types" // "io/ioutil" + "fmt" // "bytes" // "os" ) @@ -248,7 +248,8 @@ func (c Note) UpdateNoteOrContent(noteOrContent NoteOrContent) revel.Result { // 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) + noteOrContent.NoteId, noteOrContent.Content, noteOrContent.Abstract, + needUpdateNote, -1, time.Now()) } Log(afterContentUsn) @@ -334,11 +335,11 @@ func (c Note) ToPdf(noteId, appKey string) revel.Result { // 虽然传了cookie但是这里还是不能得到userId, 所以还是通过appKey来验证之 appKeyTrue, _ := revel.Config.String("app.secret") if appKeyTrue != appKey { - return c.RenderText("error") + return c.RenderText("auth error") } note := noteService.GetNoteById(noteId) if note.NoteId == "" { - return c.RenderText("error") + return c.RenderText("no note") } noteUserId := note.UserId.Hex() @@ -427,13 +428,13 @@ func (c Note) ExportPdf(noteId string) revel.Result { // 是否是有权限协作的 if !note.IsBlog && !shareService.HasReadPerm(noteUserId, userId, noteId) { re.Msg = "No Perm" - return c.RenderText("error") + return c.RenderText("No Perm") } } // path 判断是否需要重新生成之 guid := NewGuid() - fileUrlPath := "files/" + Digest3(noteUserId) + "/" + noteUserId + "/" + Digest2(guid) + "/images/pdf" + fileUrlPath := "files/export_pdf" dir := revel.BasePath + "/" + fileUrlPath if !MkdirAll(dir) { return c.RenderText("error, no dir") @@ -462,9 +463,9 @@ func (c Note) ExportPdf(noteId string) revel.Result { // wkhtmltopdf参数大全 var cc string if note.IsMarkdown { - cc = binPath + " --window-status done \"" + url + "\" \"" + path + "\"" // \"" + cookieDomain + "\" \"" + cookieName + "\" \"" + cookieValue + "\"" + cc = binPath + " --lowquality --window-status done \"" + url + "\" \"" + path + "\"" // \"" + cookieDomain + "\" \"" + cookieName + "\" \"" + cookieValue + "\"" } else { - cc = binPath + " \"" + url + "\" \"" + path + "\"" // \"" + cookieDomain + "\" \"" + cookieName + "\" \"" + cookieValue + "\"" + cc = binPath + " --lowquality \"" + url + "\" \"" + path + "\"" // \"" + cookieDomain + "\" \"" + cookieName + "\" \"" + cookieValue + "\"" } cmd := exec.Command("/bin/sh", "-c", cc) diff --git a/app/controllers/PreviewController.go b/app/controllers/PreviewController.go index 45e7524..0ef55d6 100644 --- a/app/controllers/PreviewController.go +++ b/app/controllers/PreviewController.go @@ -23,7 +23,7 @@ type Preview struct { // 得到要预览的主题绝对路径 func (c Preview) getPreviewThemeAbsolutePath(themeId string) bool { if themeId != "" { - c.Session["themeId"] = themeId // 存到session中, 下次的url就不能带了 + c.Session["themeId"] = themeId // 存到session中, 下次的url就不能带了, 待优化, 有时会取不到 } else { themeId = c.Session["themeId"] // 直接从session中获取 } diff --git a/app/controllers/UserController.go b/app/controllers/UserController.go index e678c8d..44d5f8a 100644 --- a/app/controllers/UserController.go +++ b/app/controllers/UserController.go @@ -93,21 +93,6 @@ func (c User) ReSendActiveEmail() revel.Result { return c.RenderJson(re) } -// 修改Email发送激活邮箱 -func (c User) updateEmailSendActiveEmail(email, pwd string) revel.Result { - re := info.NewRe() - if c.GetUserId() == configService.GetGlobalStringConfig("demoUserId") { - re.Msg = "cannotUpdateDemo" - return c.RenderJson(re) - } - if re.Ok, re.Msg = Vd("email", email); !re.Ok { - return c.RenderRe(re) - } - - re.Ok, re.Msg = emailService.UpdateEmailSendActiveEmail(c.GetUserInfo(), email) - return c.RenderRe(re) -} - // 通过点击链接 // 修改邮箱 func (c User) UpdateEmail(token string) revel.Result { @@ -147,27 +132,6 @@ func (c User) ActiveEmail(token string) revel.Result { return c.RenderTemplate("user/active_email.html") } -//------------ -// 第三方账号添加leanote账号 -func (c User) AddAccount(email, pwd string) revel.Result { - re := info.NewRe() - - if re.Ok, re.Msg = Vd("email", email); !re.Ok { - return c.RenderRe(re) - } - if re.Ok, re.Msg = Vd("password", pwd); !re.Ok { - return c.RenderRe(re) - } - - re.Ok, re.Msg = userService.ThirdAddUser(c.GetUserId(), email, pwd) - - if re.Ok { - c.UpdateSession("Email", email) - } - - return c.RenderRe(re) -} - //----------------- // 用户偏爱 func (c User) UpdateColumnWidth(notebookWidth, noteListWidth, mdEditorWidth int) revel.Result { diff --git a/app/controllers/api/ApiBaseController.go b/app/controllers/api/ApiBaseController.go index 1b975aa..e0b8e34 100644 --- a/app/controllers/api/ApiBaseController.go +++ b/app/controllers/api/ApiBaseController.go @@ -75,7 +75,8 @@ func (c ApiBaseContrller) uploadAttach(name string, noteId string) (ok bool, msg // 生成上传路径 newGuid := NewGuid() - filePath := "files/" + Digest3(userId) + "/" + userId + "/" + Digest2(newGuid) + "/attachs" + // filePath := "files/" + Digest3(userId) + "/" + userId + "/" + Digest2(newGuid) + "/attachs" + filePath := "files/" + GetRandomFilePath(userId, newGuid) + "/attachs" dir := revel.BasePath + "/" + filePath err = os.MkdirAll(dir, 0755) @@ -130,7 +131,8 @@ func (c ApiBaseContrller) upload(name string, noteId string, isAttach bool) (ok newGuid := NewGuid() // 生成上传路径 userId := c.getUserId() - fileUrlPath := "files/" + Digest3(userId) + "/" + userId + "/" + Digest2(newGuid) + "/images" + // fileUrlPath := "files/" + Digest3(userId) + "/" + userId + "/" + Digest2(newGuid) + "/images" + fileUrlPath := "files/" + GetRandomFilePath(userId, newGuid) + "/images" dir := revel.BasePath + "/" + fileUrlPath err = os.MkdirAll(dir, 0755) diff --git a/app/controllers/api/ApiNoteController.go b/app/controllers/api/ApiNoteController.go index 6c97c8c..09439b5 100644 --- a/app/controllers/api/ApiNoteController.go +++ b/app/controllers/api/ApiNoteController.go @@ -8,7 +8,6 @@ import ( "gopkg.in/mgo.v2/bson" "os" "os/exec" - "regexp" "strings" "time" // "github.com/leanote/leanote/app/types" @@ -85,7 +84,6 @@ func (c ApiNote) GetTrashNotes() revel.Result { "Title": "asdfadsf--=", "Desc": "", "Tags": [ - "" ], "Abstract": "", "Content": "", @@ -95,7 +93,7 @@ func (c ApiNote) GetTrashNotes() revel.Result { "Usn": 8, "Files": [ { - "FileId": "551975d599c37b970f000002", + "FileId": "551975d599c37b970f000000", "LocalFileId": "", "Type": "", "Title": "", @@ -103,18 +101,18 @@ func (c ApiNote) GetTrashNotes() revel.Result { "IsAttach": false }, { - "FileId": "551975de99c37b970f000003", + "FileId": "551975de99c37b970f000001", "LocalFileId": "", "Type": "doc", - "Title": "李铁-简历-ali-print-en.doc", + "Title": "李铁-print-en.doc", "HasBody": false, "IsAttach": true }, { - "FileId": "551975de99c37b970f000004", + "FileId": "551975de99c37b970f000002", "LocalFileId": "", "Type": "doc", - "Title": "李铁-简历-ali-print.doc", + "Title": "李铁-print.doc", "HasBody": false, "IsAttach": true } @@ -148,68 +146,10 @@ func (c ApiNote) GetNoteAndContent(noteId string) revel.Result { apiNotes := noteService.ToApiNotes([]info.Note{noteAndContent.Note}) apiNote := apiNotes[0] - apiNote.Content = noteAndContent.Content + apiNote.Content = noteService.FixContent(noteAndContent.Content, noteAndContent.IsMarkdown) 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 @@ -229,12 +169,13 @@ func (c ApiNote) fixPostNotecontent(noteOrContent *info.ApiNote) { } // 得到内容 -// [OK] func (c ApiNote) GetNoteContent(noteId string) revel.Result { + userId := c.getUserId() + note := noteService.GetNote(noteId, userId) // re := info.NewRe() - noteContent := noteService.GetNoteContent(noteId, c.getUserId()) + noteContent := noteService.GetNoteContent(noteId, userId) if noteContent.Content != "" { - noteContent.Content = c.fixContent(noteContent.Content) + noteContent.Content = noteService.FixContent(noteContent.Content, note.IsMarkdown) } apiNoteContent := info.ApiNoteContent{ @@ -243,7 +184,6 @@ func (c ApiNote) GetNoteContent(noteId string) revel.Result { Content: noteContent.Content, } - // re.Item = noteContent return c.RenderJson(apiNoteContent) } @@ -260,7 +200,8 @@ func (c ApiNote) AddNote(noteOrContent info.ApiNote) revel.Result { } */ // Log(noteOrContent.Title) - // LogJ(noteOrContent) + // LogJ(noteOrContent) + /* LogJ(c.Params) for name, _ := range c.Params.Files { @@ -327,15 +268,20 @@ func (c ApiNote) AddNote(noteOrContent info.ApiNote) revel.Result { Tags: noteOrContent.Tags, Desc: noteOrContent.Desc, // ImgSrc: noteOrContent.ImgSrc, - IsBlog: noteOrContent.IsBlog, - IsMarkdown: noteOrContent.IsMarkdown, - AttachNum: attachNum, + IsBlog: noteOrContent.IsBlog, + IsMarkdown: noteOrContent.IsMarkdown, + AttachNum: attachNum, + CreatedTime: noteOrContent.CreatedTime, + UpdatedTime: noteOrContent.UpdatedTime, } noteContent := info.NoteContent{NoteId: note.NoteId, - UserId: userId, - IsBlog: note.IsBlog, - Content: noteOrContent.Content, - Abstract: noteOrContent.Abstract} + UserId: userId, + IsBlog: note.IsBlog, + Content: noteOrContent.Content, + Abstract: noteOrContent.Abstract, + CreatedTime: noteOrContent.CreatedTime, + UpdatedTime: noteOrContent.UpdatedTime, + } // 通过内容得到Desc, abstract if noteOrContent.Abstract == "" { @@ -447,6 +393,7 @@ func (c ApiNote) UpdateNote(noteOrContent info.ApiNote) revel.Result { // Log("after upload") // LogJ(noteOrContent.Files) + } // 移到外面来, 删除最后一个file时也要处理, 不然总删不掉 @@ -509,6 +456,8 @@ func (c ApiNote) UpdateNote(noteOrContent info.ApiNote) revel.Result { } } + noteUpdate["UpdatedTime"] = noteOrContent.UpdatedTime + afterNoteUsn := 0 noteOk := false noteMsg := "" @@ -532,10 +481,16 @@ func (c ApiNote) UpdateNote(noteOrContent info.ApiNote) revel.Result { 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) + noteOrContent.NoteId, + noteOrContent.Content, + noteOrContent.Abstract, + needUpdateNote, + noteOrContent.Usn, + noteOrContent.UpdatedTime) } if needUpdateNote { @@ -585,7 +540,6 @@ func (c ApiNote) GetHistories(noteId string) revel.Result { // 0.2 新增 // 导出成PDF -// test localhost:9000/api/note/exportPdf?noteId=554f07bf05fcd15fa9000000&token=562211dc99c37ba6a7000001 func (c ApiNote) ExportPdf(noteId string) revel.Result { re := info.NewApiRe() userId := c.getUserId() @@ -612,7 +566,7 @@ func (c ApiNote) ExportPdf(noteId string) revel.Result { // path 判断是否需要重新生成之 guid := NewGuid() - fileUrlPath := "files/" + Digest3(noteUserId) + "/" + noteUserId + "/" + Digest2(guid) + "/images/pdf" + fileUrlPath := "files/export_pdf" dir := revel.BasePath + "/" + fileUrlPath if !MkdirAll(dir) { re.Msg = "noDir" @@ -636,9 +590,9 @@ func (c ApiNote) ExportPdf(noteId string) revel.Result { url := configService.GetSiteUrl() + "/note/toPdf?noteId=" + noteId + "&appKey=" + appKey var cc string if note.IsMarkdown { - cc = binPath + " --window-status done \"" + url + "\" \"" + path + "\"" // \"" + cookieDomain + "\" \"" + cookieName + "\" \"" + cookieValue + "\"" + cc = binPath + " --lowquality --window-status done \"" + url + "\" \"" + path + "\"" // \"" + cookieDomain + "\" \"" + cookieName + "\" \"" + cookieValue + "\"" } else { - cc = binPath + " \"" + url + "\" \"" + path + "\"" // \"" + cookieDomain + "\" \"" + cookieName + "\" \"" + cookieValue + "\"" + cc = binPath + " --lowquality \"" + url + "\" \"" + path + "\"" // \"" + cookieDomain + "\" \"" + cookieName + "\" \"" + cookieValue + "\"" } cmd := exec.Command("/bin/sh", "-c", cc) diff --git a/app/controllers/member/MemberBlogController.go b/app/controllers/member/MemberBlogController.go index a546bd2..304a343 100644 --- a/app/controllers/member/MemberBlogController.go +++ b/app/controllers/member/MemberBlogController.go @@ -74,7 +74,7 @@ func (c MemberBlog) Index(sorter, keywords string) revel.Result { userInfo := userService.GetUserInfo(userId) c.RenderArgs["userInfo"] = userInfo - c.RenderArgs["title"] = "Posts" + c.RenderArgs["title"] = c.Message("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) @@ -85,6 +85,8 @@ func (c MemberBlog) Index(sorter, keywords string) revel.Result { userAndBlog := userService.GetUserAndBlog(c.GetUserId()) c.RenderArgs["userAndBlog"] = userAndBlog + c.common() + return c.RenderTemplate("member/blog/list.html") } @@ -97,7 +99,8 @@ func (c MemberBlog) UpdateBlogUrlTitle(noteId, urlTitle string) revel.Result { // 修改笔记的urlTitle func (c MemberBlog) UpdateBlogAbstract(noteId string) revel.Result { - c.RenderArgs["title"] = "Update Post Abstract" + c.common() + c.RenderArgs["title"] = c.Message("Update Post Abstract") note := noteService.GetNoteAndContent(noteId, c.GetUserId()) if !note.Note.IsBlog { return c.E404() @@ -107,7 +110,6 @@ func (c MemberBlog) UpdateBlogAbstract(noteId string) revel.Result { 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) @@ -116,24 +118,24 @@ func (c MemberBlog) DoUpdateBlogAbstract(noteId, imgSrc, desc, abstract string) // 基本信息设置 func (c MemberBlog) Base() revel.Result { c.common() - c.RenderArgs["title"] = "Blog Base Info" + c.RenderArgs["title"] = c.Message("Blog Base Info") return c.RenderTemplate("member/blog/base.html") } func (c MemberBlog) Comment() revel.Result { c.common() - c.RenderArgs["title"] = "Comment" + c.RenderArgs["title"] = c.Message("Comment") return c.RenderTemplate("member/blog/comment.html") } func (c MemberBlog) Paging() revel.Result { c.common() - c.RenderArgs["title"] = "Paging" + c.RenderArgs["title"] = c.Message("Paging") return c.RenderTemplate("member/blog/paging.html") } func (c MemberBlog) Cate() revel.Result { userBlog := c.common() - c.RenderArgs["title"] = "Cate" + c.RenderArgs["title"] = c.Message("Category") notebooks := blogService.ListBlogNotebooks(c.GetUserId()) notebooksMap := map[string]info.Notebook{} @@ -190,10 +192,10 @@ func (c MemberBlog) DoAddOrUpdateSingle(singleId, title, content string) revel.R } func (c MemberBlog) AddOrUpdateSingle(singleId string) revel.Result { c.common() - c.RenderArgs["title"] = "Add Single" + c.RenderArgs["title"] = c.Message("Add Single") c.RenderArgs["singleId"] = singleId if singleId != "" { - c.RenderArgs["title"] = "Update Single" + c.RenderArgs["title"] = c.Message("Update Single") c.RenderArgs["single"] = blogService.GetSingle(singleId) } return c.RenderTemplate("member/blog/add_single.html") @@ -219,7 +221,7 @@ func (c MemberBlog) UpdateSingleUrlTitle(singleId, urlTitle string) revel.Result func (c MemberBlog) Single() revel.Result { c.common() - c.RenderArgs["title"] = "Cate" + c.RenderArgs["title"] = c.Message("Single") c.RenderArgs["singles"] = blogService.GetSingles(c.GetUserId()) return c.RenderTemplate("member/blog/single.html") @@ -234,7 +236,7 @@ func (c MemberBlog) Theme() revel.Result { c.RenderArgs["optionThemes"] = themeService.GetDefaultThemes() - c.RenderArgs["title"] = "Theme" + c.RenderArgs["title"] = c.Message("Theme") return c.RenderTemplate("member/blog/theme.html") } @@ -251,7 +253,7 @@ func (c MemberBlog) UpdateTheme(themeId string, isNew int) revel.Result { } c.common() - c.RenderArgs["title"] = "Upate Theme" + c.RenderArgs["title"] = c.Message("Update Theme") c.RenderArgs["isNew"] = isNew // 先复制之 @@ -443,8 +445,8 @@ func (c MemberBlog) ImportTheme() revel.Result { if err != nil { re.Msg = fmt.Sprintf("%v", err) return c.RenderJson(re) - } + defer file.Close() // 生成上传路径 userId := c.GetUserId() diff --git a/app/controllers/member/MemberGroupController.go b/app/controllers/member/MemberGroupController.go index dc6072a..f5fcf5a 100644 --- a/app/controllers/member/MemberGroupController.go +++ b/app/controllers/member/MemberGroupController.go @@ -14,7 +14,7 @@ type MemberGroup struct { func (c MemberGroup) Index() revel.Result { c.SetUserInfo() c.SetLocale() - c.RenderArgs["title"] = "My Group" + c.RenderArgs["title"] = c.Message("My Group") c.RenderArgs["groups"] = groupService.GetGroupsAndUsers(c.GetUserId()) return c.RenderTemplate("member/group/index.html") } diff --git a/app/controllers/member/MemberIndexController.go b/app/controllers/member/MemberIndexController.go index 50caac6..98b570b 100644 --- a/app/controllers/member/MemberIndexController.go +++ b/app/controllers/member/MemberIndexController.go @@ -13,7 +13,7 @@ type MemberIndex struct { // admin 主页 func (c MemberIndex) Index() revel.Result { c.SetUserInfo() - c.RenderArgs["title"] = "Leanote Member Center" + c.RenderArgs["title"] = c.Message("Leanote Member Center") c.RenderArgs["countNote"] = noteService.CountNote(c.GetUserId()) c.RenderArgs["countBlog"] = noteService.CountBlog(c.GetUserId()) diff --git a/app/controllers/member/MemberUserController.go b/app/controllers/member/MemberUserController.go index 408daf0..4d22301 100644 --- a/app/controllers/member/MemberUserController.go +++ b/app/controllers/member/MemberUserController.go @@ -13,34 +13,28 @@ type MemberUser struct { func (c MemberUser) Username() revel.Result { c.SetUserInfo() c.SetLocale() - c.RenderArgs["title"] = "Username" + c.RenderArgs["title"] = c.Message("Username") return c.RenderTemplate("member/user/username.html") } func (c MemberUser) Email() revel.Result { c.SetUserInfo() c.SetLocale() - c.RenderArgs["title"] = "Email" + c.RenderArgs["title"] = c.Message("Email") return c.RenderTemplate("member/user/email.html") } func (c MemberUser) Password() revel.Result { c.SetUserInfo() c.SetLocale() - c.RenderArgs["title"] = "Password" + c.RenderArgs["title"] = c.Message("Password") return c.RenderTemplate("member/user/password.html") } func (c MemberUser) Avatar() revel.Result { c.SetUserInfo() c.SetLocale() - c.RenderArgs["title"] = "Avatar" + c.RenderArgs["title"] = c.Message("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") -} diff --git a/app/controllers/member/个人中心.md b/app/controllers/member/个人中心.md deleted file mode 100644 index ab0218f..0000000 --- a/app/controllers/member/个人中心.md +++ /dev/null @@ -1,2 +0,0 @@ -包括基本信息设置 -博客设置 diff --git a/app/lea/Util.go b/app/lea/Util.go index 4ff66f7..b2ea077 100644 --- a/app/lea/Util.go +++ b/app/lea/Util.go @@ -394,3 +394,40 @@ func FixFilename(filename string) string { } return filename } + +// 是否是合法的时间 +// 不是, 0001-01-01T00:00:00Z, 且比今天小 +func IsValidTime(t time.Time) bool { + if t.Year() > 20 { + now := time.Now() + Log("------") + Log(t) + Log(now) + if t.Before(now) { + return true + } + } + return false +} + +// url传过来的时间没有时区信息, 转到本地时间 +func ToLocalTime(t time.Time) time.Time { + return time.Date(t.Year(), t.Month(), t.Day(), t.Hour(), t.Minute(), t.Second(), 0, time.Local) +} + +// 修复传过来的时间, 如果比今天大, 则设为现在 +func FixUrlTime(t time.Time) time.Time { + localTime := ToLocalTime(t) + if IsValidTime(localTime) { + return localTime + } + return time.Now() +} + +// 得到用户的随机文件路径 3位/userId/2位 +func GetRandomFilePath(userId, uuid string) string { + if uuid == "" { + uuid = NewGuid() + } + return Digest3(userId) + "/" + userId + "/" + Digest2(uuid) +} diff --git a/app/service/BlogService.go b/app/service/BlogService.go index a4bbe27..89eb979 100644 --- a/app/service/BlogService.go +++ b/app/service/BlogService.go @@ -919,7 +919,7 @@ func (this *BlogService) UpateCateUrlTitle(userId string, cateId, urlTitle strin "UrlTitle": "", }) */ - url = GetUrTitle(userId, urlTitle, "notebook") + url = GetUrTitle(userId, urlTitle, "notebook", cateId) ok = db.UpdateByIdAndUserIdMap(db.Notebooks, cateId, userId, bson.M{ "UrlTitle": url, }) @@ -935,7 +935,7 @@ func (this *BlogService) UpateBlogUrlTitle(userId string, noteId, urlTitle strin ok = db.UpdateByIdAndUserIdMap(db.Notes, noteId, userId, bson.M{ "UrlTitle": "", }) - url = GetUrTitle(userId, urlTitle, "note") + url = GetUrTitle(userId, urlTitle, "note", noteId) ok = db.UpdateByIdAndUserIdMap(db.Notes, noteId, userId, bson.M{ "UrlTitle": url, }) @@ -1036,7 +1036,7 @@ func (this *BlogService) UpdateSingleUrlTitle(userId, singleId, urlTitle string) "UrlTitle": "", }) */ - url = GetUrTitle(userId, urlTitle, "single") + url = GetUrTitle(userId, urlTitle, "single", singleId) ok = db.UpdateByIdAndUserIdMap(db.BlogSingles, singleId, userId, bson.M{ "UrlTitle": url, }) @@ -1070,7 +1070,7 @@ func (this *BlogService) AddOrUpdateSingle(userId, singleId, title, content stri UserId: bson.ObjectIdHex(userId), Title: title, Content: content, - UrlTitle: GetUrTitle(userId, title, "single"), + UrlTitle: GetUrTitle(userId, title, "single", singleId), CreatedTime: time.Now(), } page.UpdatedTime = page.CreatedTime diff --git a/app/service/ConfigService.go b/app/service/ConfigService.go index c1a49d1..806d2ce 100644 --- a/app/service/ConfigService.go +++ b/app/service/ConfigService.go @@ -577,6 +577,14 @@ func (this *ConfigService) GetUploadSize(key string) float64 { f, _ := strconv.ParseFloat(this.GetGlobalStringConfig(key), 64) return f } +func (this *ConfigService) GetInt64(key string) int64 { + f, _ := strconv.ParseInt(this.GetGlobalStringConfig(key), 10, 64) + return f +} +func (this *ConfigService) GetInt32(key string) int32 { + f, _ := strconv.ParseInt(this.GetGlobalStringConfig(key), 10, 32) + return int32(f) +} func (this *ConfigService) GetUploadSizeLimit() map[string]float64 { return map[string]float64{ "uploadImageSize": this.GetUploadSize("uploadImageSize"), diff --git a/app/service/FileService.go b/app/service/FileService.go index 9e3569a..2710ce8 100644 --- a/app/service/FileService.go +++ b/app/service/FileService.go @@ -242,6 +242,7 @@ func (this *FileService) GetFile(userId, fileId string) string { return "" } +// 复制共享的笔记时, 复制其中的图片到我本地 // 复制图片 func (this *FileService) CopyImage(userId, fileId, toUserId string) (bool, string) { // 是否已经复制过了 @@ -252,7 +253,6 @@ func (this *FileService) CopyImage(userId, fileId, toUserId string) (bool, strin } // 复制之 - file := info.File{} db.GetByIdAndUserId(db.Files, fileId, userId, &file) @@ -261,18 +261,20 @@ func (this *FileService) CopyImage(userId, fileId, toUserId string) (bool, strin } _, ext := SplitFilename(file.Name) - newFilename := NewGuid() + ext + guid := NewGuid() + newFilename := guid + ext - dir := "files/" + toUserId + "/images" + // TODO 统一目录格式 + // dir := "files/" + toUserId + "/images" + dir := "files/" + GetRandomFilePath(toUserId, guid) + "/images" filePath := dir + "/" + newFilename - err := os.MkdirAll(dir, 0755) + err := os.MkdirAll(revel.BasePath+dir, 0755) if err != nil { return false, "" } _, err = CopyFile(revel.BasePath+"/"+file.Path, revel.BasePath+"/"+filePath) if err != nil { - Log(err) return false, "" } diff --git a/app/service/GroupService.go b/app/service/GroupService.go index a2cab44..1cb6660 100644 --- a/app/service/GroupService.go +++ b/app/service/GroupService.go @@ -185,16 +185,16 @@ func (this *GroupService) AddUser(ownUserId, groupId, userId string) (ok bool, m // groupId是否是ownUserId的? /* if !this.IsExistsGroupUser(ownUserId, groupId) { - return false, "forbidden" + return false, "forbiddenNotMyGroup" } */ if !this.isMyGroup(ownUserId, groupId) { - return false, "forbidden" + return false, "forbiddenNotMyGroup" } // 是否已存在 if db.Has(db.GroupUsers, bson.M{"GroupId": bson.ObjectIdHex(groupId), "UserId": bson.ObjectIdHex(userId)}) { - return false, "hasUsers" + return false, "userExistsInGroup" } return db.Insert(db.GroupUsers, info.GroupUser{ @@ -210,11 +210,11 @@ func (this *GroupService) DeleteUser(ownUserId, groupId, userId string) (ok bool // groupId是否是ownUserId的? /* if !this.IsExistsGroupUser(ownUserId, groupId) { - return false, "forbidden" + return false, "forbiddenNotMyGroup" } */ if !this.isMyGroup(ownUserId, groupId) { - return false, "forbidden" + return false, "forbiddenNotMyGroup" } // 删除该用户分享到本组的笔记本, 笔记 diff --git a/app/service/NoteService.go b/app/service/NoteService.go index fa3225e..fa06448 100644 --- a/app/service/NoteService.go +++ b/app/service/NoteService.go @@ -5,6 +5,8 @@ import ( "github.com/leanote/leanote/app/info" . "github.com/leanote/leanote/app/lea" "gopkg.in/mgo.v2/bson" + "regexp" + "strings" "time" ) @@ -245,11 +247,14 @@ func (this *NoteService) AddNote(note info.Note, fromApi bool) info.Note { noteId := bson.NewObjectId() note.NoteId = noteId } - note.CreatedTime = time.Now() - note.UpdatedTime = note.CreatedTime + + // 关于创建时间, 可能是客户端发来, 此时判断时间是否有 + note.CreatedTime = FixUrlTime(note.CreatedTime) + note.UpdatedTime = FixUrlTime(note.UpdatedTime) + note.IsTrash = false note.UpdatedUserId = note.UserId - note.UrlTitle = GetUrTitle(note.UserId.Hex(), note.Title, "note") + note.UrlTitle = GetUrTitle(note.UserId.Hex(), note.Title, "note", note.NoteId.Hex()) note.Usn = userService.IncrUsn(note.UserId.Hex()) notebookId := note.NotebookId.Hex() @@ -287,8 +292,10 @@ func (this *NoteService) AddSharedNote(note info.Note, myUserId bson.ObjectId) i // 添加笔记本内容 // [ok] func (this *NoteService) AddNoteContent(noteContent info.NoteContent) info.NoteContent { - noteContent.CreatedTime = time.Now() - noteContent.UpdatedTime = noteContent.CreatedTime + + noteContent.CreatedTime = FixUrlTime(noteContent.CreatedTime) + noteContent.UpdatedTime = FixUrlTime(noteContent.UpdatedTime) + noteContent.UpdatedUserId = noteContent.UserId db.Insert(db.NoteContents, noteContent) @@ -419,7 +426,15 @@ func (this *NoteService) UpdateNote(updatedUserId, noteId string, needUpdate bso } needUpdate["UpdatedUserId"] = bson.ObjectIdHex(updatedUserId) - needUpdate["UpdatedTime"] = time.Now() + + // 可以将时间传过来 + updatedTime, ok := needUpdate["UpdatedTime"].(time.Time) + if ok { + needUpdate["UpdatedTime"] = FixUrlTime(updatedTime) + } else { + needUpdate["UpdatedTime"] = time.Now() + } + afterUsn := userService.IncrUsn(userId) needUpdate["Usn"] = afterUsn @@ -443,7 +458,7 @@ func (this *NoteService) UpdateNote(updatedUserId, noteId string, needUpdate bso } } - ok := db.UpdateByIdAndUserIdMap(db.Notes, noteId, userId, needUpdate) + ok = db.UpdateByIdAndUserIdMap(db.Notes, noteId, userId, needUpdate) if !ok { return ok, "", 0 } @@ -460,14 +475,19 @@ func (this *NoteService) UpdateNote(updatedUserId, noteId string, needUpdate bso notebookId := notebookIdI.(bson.ObjectId) if notebookId != "" { notebookService.ReCountNotebookNumberNotes(note.NotebookId.Hex()) - hasRecount = true notebookService.ReCountNotebookNumberNotes(notebookId.Hex()) + hasRecount = true } } // 不要多次更新, isTrash = false, = true都要重新统计 - if !hasRecount { - if _, ok := needUpdate["IsTrash"]; ok { + if isTrashI, ok := needUpdate["IsTrash"]; ok { + // 如果是垃圾, 则删除之共享 + isTrash := isTrashI.(bool) + if isTrash { + shareService.DeleteShareNoteAll(noteId, userId) + } + if !hasRecount { notebookService.ReCountNotebookNumberNotes(note.NotebookId.Hex()) } } @@ -507,7 +527,9 @@ func (this *NoteService) UpdateNoteTitle(userId, updatedUserId, noteId, title st // [ok] TODO perm未测 // hasBeforeUpdateNote 之前是否更新过note其它信息, 如果有更新, usn不用更新 // TODO abstract这里生成 -func (this *NoteService) UpdateNoteContent(updatedUserId, noteId, content, abstract string, hasBeforeUpdateNote bool, usn int) (bool, string, int) { +func (this *NoteService) UpdateNoteContent(updatedUserId, noteId, content, abstract string, + hasBeforeUpdateNote bool, + usn int, updatedTime time.Time) (bool, string, int) { // 是否已自定义 note := this.GetNoteById(noteId) if note.NoteId == "" { @@ -522,11 +544,13 @@ func (this *NoteService) UpdateNoteContent(updatedUserId, noteId, content, abstr } } + updatedTime = FixUrlTime(updatedTime) + // abstract重置 data := bson.M{"UpdatedUserId": bson.ObjectIdHex(updatedUserId), "Content": content, "Abstract": abstract, - "UpdatedTime": time.Now()} + "UpdatedTime": updatedTime} if note.IsBlog && note.HasSelfDefined { delete(data, "Abstract") @@ -788,7 +812,11 @@ func (this *NoteService) searchNoteFromContent(notes []info.Note, userId, key st noteIds[i] = note.NoteId } noteContents := []info.NoteContent{} - query := bson.M{"_id": bson.M{"$nin": noteIds}, "UserId": bson.ObjectIdHex(userId), "Content": bson.M{"$regex": bson.RegEx{".*?" + key + ".*", "i"}}} + query := bson.M{ + "_id": bson.M{"$nin": noteIds}, + "UserId": bson.ObjectIdHex(userId), + "Content": bson.M{"$regex": bson.RegEx{".*?" + key + ".*", "i"}}, + } if isBlog { query["IsBlog"] = true } @@ -895,3 +923,187 @@ func (this *NoteService) UpdateNoteToDeleteTag(userId string, targetTag string) } return ret } + +// api + +// 得到笔记的内容, 此时将笔记内的链接转成标准的Leanote Url +// 将笔记的图片, 附件链接转换成 site.url/file/getImage?fileId=xxx, site.url/file/getAttach?fileId=xxxx +func (this *NoteService) FixContentBad(content string, isMarkdown bool) string { + baseUrl := configService.GetSiteUrl() + + baseUrlPattern := baseUrl + + // 避免https的url + if baseUrl[0:8] == "https://" { + baseUrlPattern = strings.Replace(baseUrl, "https://", "https*://", 1) + } else { + baseUrlPattern = strings.Replace(baseUrl, "http://", "https*://", 1) + } + + patterns := []map[string]string{ + map[string]string{"src": "src", "middle": "/file/outputImage", "param": "fileId", "to": "getImage?fileId="}, + map[string]string{"src": "href", "middle": "/attach/download", "param": "attachId", "to": "getAttach?fileId="}, + // 该链接已失效, 不再支持 + map[string]string{"src": "href", "middle": "/attach/downloadAll", "param": "noteId", "to": "getAllAttachs?noteId="}, + } + + for _, eachPattern := range patterns { + + if !isMarkdown { + + // 富文本处理 + + // + // + + var reg *regexp.Regexp + if eachPattern["src"] == "src" { + reg, _ = regexp.Compile("]+?)(" + eachPattern["src"] + `=['"]*` + baseUrlPattern + eachPattern["middle"] + `\?` + eachPattern["param"] + `=([a-z0-9A-Z]{24})["']*)[^>]*>`) + } else { + reg, _ = regexp.Compile("]+?)(" + eachPattern["src"] + `=['"]*` + baseUrlPattern + eachPattern["middle"] + `\?` + eachPattern["param"] + `=([a-z0-9A-Z]{24})["']*)[^>]*>`) + } + + finds := reg.FindAllStringSubmatch(content, -1) // 查找所有的 + + for _, eachFind := range finds { + if len(eachFind) == 3 { + // 这一行会非常慢!, content是全部的内容, 多次replace导致 + content = strings.Replace(content, + eachFind[1], + eachPattern["src"]+"=\""+baseUrl+"/api/file/"+eachPattern["to"]+eachFind[2]+"\"", + 1) + } + } + } else { + + // markdown处理 + //  + // [selection 2.html](http://leanote.com/attach/download?attachId=5504262638f4111dcb00017f) + // [all.tar.gz](http://leanote.com/attach/downloadAll?noteId=5503b57d59f81b4eb4000000) + + pre := "!" // 默认图片 + if eachPattern["src"] == "href" { // 是attach + pre = "" + } + + regImageMarkdown, _ := regexp.Compile(pre + `\[([^]]*?)\]\(` + baseUrlPattern + eachPattern["middle"] + `\?` + eachPattern["param"] + `=([a-z0-9A-Z]{24})\)`) + findsImageMarkdown := regImageMarkdown.FindAllStringSubmatch(content, -1) // 查找所有的 + // [[ 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 +} + +// 性能更好, 5倍的差距 +func (this *NoteService) FixContent(content string, isMarkdown bool) string { + baseUrl := configService.GetSiteUrl() + + baseUrlPattern := baseUrl + + // 避免https的url + if baseUrl[0:8] == "https://" { + baseUrlPattern = strings.Replace(baseUrl, "https://", "https*://", 1) + } else { + baseUrlPattern = strings.Replace(baseUrl, "http://", "https*://", 1) + } + + patterns := []map[string]string{ + map[string]string{"src": "src", "middle": "/file/outputImage", "param": "fileId", "to": "getImage?fileId="}, + map[string]string{"src": "href", "middle": "/attach/download", "param": "attachId", "to": "getAttach?fileId="}, + // 该链接已失效, 不再支持 + map[string]string{"src": "href", "middle": "/attach/downloadAll", "param": "noteId", "to": "getAllAttachs?noteId="}, + } + + for _, eachPattern := range patterns { + + if !isMarkdown { + + // 富文本处理 + + // + // + + var reg *regexp.Regexp + var reg2 *regexp.Regexp + if eachPattern["src"] == "src" { + reg, _ = regexp.Compile("]+?)(?:" + eachPattern["src"] + `=['"]*` + baseUrlPattern + eachPattern["middle"] + `\?` + eachPattern["param"] + `=(?:[a-z0-9A-Z]{24})["']*)[^>]*>`) + reg2, _ = regexp.Compile("]+?)(" + eachPattern["src"] + `=['"]*` + baseUrlPattern + eachPattern["middle"] + `\?` + eachPattern["param"] + `=([a-z0-9A-Z]{24})["']*)[^>]*>`) + } else { + reg, _ = regexp.Compile("]+?)(?:" + eachPattern["src"] + `=['"]*` + baseUrlPattern + eachPattern["middle"] + `\?` + eachPattern["param"] + `=(?:[a-z0-9A-Z]{24})["']*)[^>]*>`) + reg2, _ = regexp.Compile("]+?)(" + eachPattern["src"] + `=['"]*` + baseUrlPattern + eachPattern["middle"] + `\?` + eachPattern["param"] + `=([a-z0-9A-Z]{24})["']*)[^>]*>`) + } + + content = reg.ReplaceAllStringFunc(content, func(str string) string { + // str=这样的 + // + + eachFind := reg2.FindStringSubmatch(str) + str = strings.Replace(str, + eachFind[1], + eachPattern["src"]+"=\""+baseUrl+"/api/file/"+eachPattern["to"]+eachFind[2]+"\"", + 1) + + // fmt.Println(str) + return str + }) + /* + finds := reg.FindAllStringSubmatch(content, -1) // 查找所有的 + + for _, eachFind := range finds { + if len(eachFind) == 3 { + // 这一行会非常慢!, content是全部的内容, 多次replace导致 + content = strings.Replace(content, + eachFind[1], + eachPattern["src"]+"=\""+baseUrl+"/api/file/"+eachPattern["to"]+eachFind[2]+"\"", + 1) + } + } + */ + } else { + + // markdown处理 + //  + // [selection 2.html](http://leanote.com/attach/download?attachId=5504262638f4111dcb00017f) + // [all.tar.gz](http://leanote.com/attach/downloadAll?noteId=5503b57d59f81b4eb4000000) + + pre := "!" // 默认图片 + if eachPattern["src"] == "href" { // 是attach + pre = "" + } + + regImageMarkdown, _ := regexp.Compile(pre + `\[(?:[^]]*?)\]\(` + baseUrlPattern + eachPattern["middle"] + `\?` + eachPattern["param"] + `=(?:[a-z0-9A-Z]{24})\)`) + regImageMarkdown2, _ := regexp.Compile(pre + `\[([^]]*?)\]\(` + baseUrlPattern + eachPattern["middle"] + `\?` + eachPattern["param"] + `=([a-z0-9A-Z]{24})\)`) + + content = regImageMarkdown.ReplaceAllStringFunc(content, func(str string) string { + // str=这样的 + // + + eachFind := regImageMarkdown2.FindStringSubmatch(str) + str = strings.Replace(str, eachFind[0], pre+"["+eachFind[1]+"]("+baseUrl+"/api/file/"+eachPattern["to"]+eachFind[2]+")", 1) + + // fmt.Println(str) + return str + }) + + /* + findsImageMarkdown := regImageMarkdown.FindAllStringSubmatch(content, -1) // 查找所有的 + // [[ 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 +} diff --git a/app/service/NotebookService.go b/app/service/NotebookService.go index a437004..4974e36 100644 --- a/app/service/NotebookService.go +++ b/app/service/NotebookService.go @@ -156,9 +156,13 @@ func (this *NotebookService) GetNotebooksByNotebookIds(notebookIds []bson.Object } // 添加 -// [ok] func (this *NotebookService) AddNotebook(notebook info.Notebook) (bool, info.Notebook) { - notebook.UrlTitle = GetUrTitle(notebook.UserId.Hex(), notebook.Title, "notebook") + + if notebook.NotebookId == "" { + notebook.NotebookId = bson.NewObjectId() + } + + notebook.UrlTitle = GetUrTitle(notebook.UserId.Hex(), notebook.Title, "notebook", notebook.NotebookId.Hex()) notebook.Usn = userService.IncrUsn(notebook.UserId.Hex()) now := time.Now() notebook.CreatedTime = now diff --git a/app/service/PwdService.go b/app/service/PwdService.go index 6e7637b..e11c369 100644 --- a/app/service/PwdService.go +++ b/app/service/PwdService.go @@ -34,6 +34,7 @@ func (this *PwdService) FindPwd(email string) (ok bool, msg string) { return } +// 重置密码时 // 修改密码 // 先验证 func (this *PwdService) UpdatePwd(token, pwd string) (bool, string) { @@ -45,11 +46,12 @@ func (this *PwdService) UpdatePwd(token, pwd string) (bool, string) { if ok, msg, tokenInfo = tokenService.VerifyToken(token, info.TokenPwd); !ok { return ok, msg } - digest, err := GenerateHash(pwd) - if err != nil { + + passwd := GenPwd(pwd) + if passwd == "" { return false, "GenerateHash error" } - passwd := string(digest) + // 修改密码之 ok = db.UpdateByQField(db.Users, bson.M{"_id": tokenInfo.UserId}, "Pwd", passwd) diff --git a/app/service/ShareService.go b/app/service/ShareService.go index 6e251fe..45e3c7e 100644 --- a/app/service/ShareService.go +++ b/app/service/ShareService.go @@ -470,7 +470,8 @@ func (this *ShareService) GetShareNoteContent(noteId, myUserId, sharedUserId str // 或者, 其notebook共享了我 // Log(this.HasSharedNote(noteId, myUserId)) // Log(this.HasSharedNotebook(noteId, myUserId, sharedUserId)) - Log(this.HasReadPerm(sharedUserId, myUserId, noteId)) + // Log(this.HasReadPerm(sharedUserId, myUserId, noteId)) + if this.HasReadPerm(sharedUserId, myUserId, noteId) { // if this.HasSharedNote(noteId, myUserId) || this.HasSharedNotebook(noteId, myUserId, sharedUserId) { db.Get(db.NoteContents, noteId, ¬eContent) diff --git a/app/service/ThemeService.go b/app/service/ThemeService.go index e09d7f9..92c693f 100644 --- a/app/service/ThemeService.go +++ b/app/service/ThemeService.go @@ -618,8 +618,6 @@ 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 } } @@ -629,8 +627,6 @@ func (this *ThemeService) hasRound(vector [][]int, size int) (ok bool) { // 从每个节点出发, 判断是否有环 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 diff --git a/app/service/TrashService.go b/app/service/TrashService.go index e5ef218..7f2f6f5 100644 --- a/app/service/TrashService.go +++ b/app/service/TrashService.go @@ -85,6 +85,9 @@ func (this *TrashService) DeleteTrash(noteId, userId string) bool { // delete content ok = db.DeleteByIdAndUserId(db.NoteContents, noteId, userId) + // 删除content history + ok = db.DeleteByIdAndUserId(db.NoteContentHistories, noteId, userId) + // 重新统计tag's count // TODO 这里会改变tag's Usn tagService.reCountTagCount(userId, note.Tags) @@ -115,6 +118,13 @@ func (this *TrashService) DeleteTrashApi(noteId, userId string, usn int) (bool, // delete content ok = db.DeleteByIdAndUserId(db.NoteContents, noteId, userId) + // 删除content history + ok = db.DeleteByIdAndUserId(db.NoteContentHistories, noteId, userId) + + // 一个BUG, iOS删除直接调用这个API, 结果没有重新recount + // recount notebooks' notes number + notebookService.ReCountNotebookNumberNotes(note.NotebookId.Hex()) + return ok, "", afterUsn } diff --git a/app/service/UpgradeService.go b/app/service/UpgradeService.go index f7cfcc3..ddd713f 100644 --- a/app/service/UpgradeService.go +++ b/app/service/UpgradeService.go @@ -65,7 +65,7 @@ func (this *UpgradeService) UpgradeBetaToBeta2(userId string) (ok bool, msg stri data["RecommendTime"] = note.UpdatedTime Log("Time " + noteId) } - data["UrlTitle"] = GetUrTitle(note.UserId.Hex(), note.Title, "note") + data["UrlTitle"] = GetUrTitle(note.UserId.Hex(), note.Title, "note", noteId) db.UpdateByIdAndUserIdMap2(db.Notes, note.NoteId, note.UserId, data) Log(noteId) } @@ -77,7 +77,7 @@ func (this *UpgradeService) UpgradeBetaToBeta2(userId string) (ok bool, msg stri for _, notebook := range notebooks { notebookId := notebook.NotebookId.Hex() data := bson.M{} - data["UrlTitle"] = GetUrTitle(notebook.UserId.Hex(), notebook.Title, "notebook") + data["UrlTitle"] = GetUrTitle(notebook.UserId.Hex(), notebook.Title, "notebook", notebookId) db.UpdateByIdAndUserIdMap2(db.Notebooks, notebook.NotebookId, notebook.UserId, data) Log(notebookId) } diff --git a/app/service/UserService.go b/app/service/UserService.go index dea7841..4fc5224 100644 --- a/app/service/UserService.go +++ b/app/service/UserService.go @@ -47,7 +47,7 @@ func (this *UserService) AddUser(user info.User) bool { go func() { emailService.RegisterSendActiveEmail(user, user.Email) // 发送给我 life@leanote.com - emailService.SendEmail("life@leanote.com", "新增用户", "{header}用户名"+user.Email+"{footer}") + // emailService.SendEmail("life@leanote.com", "新增用户", "{header}用户名"+user.Email+"{footer}") }() } @@ -412,26 +412,6 @@ func (this *UserService) UpdateEmail(token string) (ok bool, msg, email string) return } -//--------- -// 第三方添加账号 -func (this *UserService) ThirdAddUser(userId, email, pwd string) (ok bool, msg string) { - // 判断该用户是否已有了帐户 - userInfo := this.GetUserInfo(userId) - if userInfo.Email != "" { - msg = "你已有帐户" - return - } - - // 判断email是否存在 - if this.IsExistsUser(email) { - msg = "该用户已存在" - return - } - - ok = db.UpdateByQMap(db.Users, bson.M{"_id": bson.ObjectIdHex(userId)}, bson.M{"Email": email, "Pwd": Md5(pwd)}) - return -} - //------------ // 偏好设置 diff --git a/app/service/init.go b/app/service/init.go index 63e8194..a8ed2c6 100644 --- a/app/service/init.go +++ b/app/service/init.go @@ -2,6 +2,7 @@ package service import ( "github.com/leanote/leanote/app/db" + . "github.com/leanote/leanote/app/lea" "gopkg.in/mgo.v2" "gopkg.in/mgo.v2/bson" "net/url" @@ -150,12 +151,28 @@ func getUniqueUrlTitle(userId string, urlTitle string, types string, padding int return urlTitle2 } +// 截取id 24位变成12位 +// 先md5, 再取12位 +func subIdHalf(id string) string { + idMd5 := Md5(id) + return idMd5[:12] +} + // types == note,notebook,single -func GetUrTitle(userId string, title string, types string) string { +// id noteId, notebookId, singleId 当title没的时候才有用, 用它来替换 +func GetUrTitle(userId string, title string, types string, id string) string { urlTitle := strings.Trim(title, " ") if urlTitle == "" { - urlTitle = "Untitled-" + userId + if id == "" { + urlTitle = "Untitled-" + userId + } else { + urlTitle = subIdHalf(id) + } + // 不允许title是ObjectId + } else if bson.IsObjectIdHex(title) { + urlTitle = subIdHalf(id) } + urlTitle = fixUrlTitle(urlTitle) return getUniqueUrlTitle(userId, urlTitle, types, 1) } diff --git a/app/views/home/find_password.html b/app/views/home/find_password.html index 1113cb9..2410c37 100644 --- a/app/views/home/find_password.html +++ b/app/views/home/find_password.html @@ -2,7 +2,7 @@ - leanote + Leanote {{msg . "findPassword"}} @@ -84,4 +84,4 @@ $(function() { });