diff --git a/app/controllers/AuthController.go b/app/controllers/AuthController.go
index d49f2e3..c12dc08 100644
--- a/app/controllers/AuthController.go
+++ b/app/controllers/AuthController.go
@@ -4,6 +4,7 @@ import (
"github.com/revel/revel"
"github.com/leanote/leanote/app/info"
. "github.com/leanote/leanote/app/lea"
+// "strconv"
)
// 用户登录/注销/找回密码
@@ -14,48 +15,88 @@ type Auth struct {
//--------
// 登录
-func (c Auth) Login(email string) revel.Result {
+func (c Auth) Login(email, from string) revel.Result {
c.RenderArgs["title"] = c.Message("login")
c.RenderArgs["subTitle"] = c.Message("login")
c.RenderArgs["email"] = email
+ c.RenderArgs["from"] = from
c.RenderArgs["openRegister"] = openRegister
+ sessionId := c.Session.Id()
+ if sessionService.LoginTimesIsOver(sessionId) {
+ c.RenderArgs["needCaptcha"] = true
+ }
+
+ c.SetLocale()
+
if c.Has("demo") {
c.RenderArgs["demo"] = true
c.RenderArgs["email"] = "demo@leanote.com"
}
return c.RenderTemplate("home/login.html")
}
-func (c Auth) DoLogin(email, pwd string) revel.Result {
+
+// 为了demo和register
+func (c Auth) doLogin(email, pwd string) revel.Result {
+ sessionId := c.Session.Id()
+ var msg = ""
+
userInfo := authService.Login(email, pwd)
if userInfo.Email != "" {
c.SetSession(userInfo)
- // 必须要redirect, 不然用户刷新会重复提交登录信息
-// return c.Redirect("/")
- configService.InitUserConfigs(userInfo.UserId.Hex())
+ sessionService.ClearLoginTimes(sessionId)
return c.RenderJson(info.Re{Ok: true})
+ } else {
+ // 登录错误, 则错误次数++
+ msg = "wrongUsernameOrPassword"
}
-// return c.RenderTemplate("login.html")
- return c.RenderJson(info.Re{Ok: false, Msg: c.Message("wrongUsernameOrPassword")})
+
+ return c.RenderJson(info.Re{Ok: false, Item: sessionService.LoginTimesIsOver(sessionId) , Msg: c.Message(msg)})
+}
+func (c Auth) DoLogin(email, pwd string, captcha string) revel.Result {
+ sessionId := c.Session.Id()
+ var msg = ""
+
+ // > 5次需要验证码, 直到登录成功
+ if sessionService.LoginTimesIsOver(sessionId) && sessionService.GetCaptcha(sessionId) != captcha {
+ msg = "captchaError"
+ } else {
+ userInfo := authService.Login(email, pwd)
+ if userInfo.Email != "" {
+ c.SetSession(userInfo)
+ sessionService.ClearLoginTimes(sessionId)
+ 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)})
}
// 注销
func (c Auth) Logout() revel.Result {
+ sessionId := c.Session.Id()
+ sessionService.Clear(sessionId)
c.ClearSession()
return c.Redirect("/login")
}
// 体验一下
func (c Auth) Demo() revel.Result {
- c.DoLogin("demo@leanote.com", "demo@leanote.com")
+ c.doLogin(configService.GetGlobalStringConfig("demoUsername"), configService.GetGlobalStringConfig("demoPassword"))
return c.Redirect("/note")
}
//--------
// 注册
-func (c Auth) Register() revel.Result {
+func (c Auth) Register(from string) revel.Result {
if !openRegister {
return c.Redirect("/index")
}
+ c.SetLocale()
+ c.RenderArgs["from"] = from
c.RenderArgs["title"] = c.Message("register")
c.RenderArgs["subTitle"] = c.Message("register")
@@ -68,21 +109,11 @@ func (c Auth) DoRegister(email, pwd string) revel.Result {
re := info.NewRe();
- if email == "" {
- re.Msg = c.Message("inputEmail")
- return c.RenderJson(re)
- } else if !IsEmail(email) {
- re.Msg = c.Message("wrongEmail")
- return c.RenderJson(re)
+ if re.Ok, re.Msg = Vd("email", email); !re.Ok {
+ return c.RenderRe(re);
}
-
- // 密码
- if pwd == "" {
- re.Msg = c.Message("inputPassword")
- return c.RenderJson(re)
- } else if len(pwd) < 6 {
- re.Msg = c.Message("wrongPassword")
- return c.RenderJson(re)
+ if re.Ok, re.Msg = Vd("password", pwd); !re.Ok {
+ return c.RenderRe(re);
}
// 注册
@@ -90,10 +121,10 @@ func (c Auth) DoRegister(email, pwd string) revel.Result {
// 注册成功, 则立即登录之
if re.Ok {
- c.DoLogin(email, pwd)
+ c.doLogin(email, pwd)
}
- return c.RenderJson(re)
+ return c.RenderRe(re)
}
//--------
@@ -130,13 +161,12 @@ func (c Auth) FindPassword2(token string) revel.Result {
// 找回密码修改密码
func (c Auth) FindPasswordUpdate(token, pwd string) revel.Result {
re := info.NewRe();
-
- re.Ok, re.Msg = IsGoodPwd(pwd)
- if !re.Ok {
- return c.RenderJson(re)
+
+ if re.Ok, re.Msg = Vd("password", pwd); !re.Ok {
+ return c.RenderRe(re);
}
// 修改之
re.Ok, re.Msg = pwdService.UpdatePwd(token, pwd)
- return c.RenderJson(re)
+ return c.RenderRe(re)
}
diff --git a/app/controllers/BaseController.go b/app/controllers/BaseController.go
index 34e0862..d86a99e 100644
--- a/app/controllers/BaseController.go
+++ b/app/controllers/BaseController.go
@@ -5,11 +5,13 @@ import (
"gopkg.in/mgo.v2/bson"
"encoding/json"
"github.com/leanote/leanote/app/info"
+// . "github.com/leanote/leanote/app/lea"
// "io/ioutil"
// "fmt"
"math"
"strconv"
"strings"
+ "bytes"
)
// 公用Controller, 其它Controller继承它
@@ -54,15 +56,21 @@ func (c BaseController) GetUsername() string {
// 得到用户信息
func (c BaseController) GetUserInfo() info.User {
if userId, ok := c.Session["UserId"]; ok && userId != "" {
+ return userService.GetUserInfo(userId);
+ /*
notebookWidth, _ := strconv.Atoi(c.Session["NotebookWidth"])
noteListWidth, _ := strconv.Atoi(c.Session["NoteListWidth"])
+ mdEditorWidth, _ := strconv.Atoi(c.Session["MdEditorWidth"])
+ LogJ(c.Session)
user := info.User{UserId: bson.ObjectIdHex(userId),
Email: c.Session["Email"],
+ Logo: c.Session["Logo"],
Username: c.Session["Username"],
UsernameRaw: c.Session["UsernameRaw"],
Theme: c.Session["Theme"],
NotebookWidth: notebookWidth,
NoteListWidth: noteListWidth,
+ MdEditorWidth: mdEditorWidth,
}
if c.Session["Verified"] == "1" {
user.Verified = true
@@ -71,10 +79,19 @@ func (c BaseController) GetUserInfo() info.User {
user.LeftIsMin = true
}
return user
+ */
}
return info.User{}
}
+// 这里的session都是cookie中的, 与数据库session无关
+func (c BaseController) GetSession(key string) string {
+ v, ok := c.Session[key]
+ if !ok {
+ v = ""
+ }
+ return v
+}
func (c BaseController) SetSession(userInfo info.User) {
if userInfo.UserId.Hex() != "" {
c.Session["UserId"] = userInfo.UserId.Hex()
@@ -82,6 +99,7 @@ func (c BaseController) SetSession(userInfo info.User) {
c.Session["Username"] = userInfo.Username
c.Session["UsernameRaw"] = userInfo.UsernameRaw
c.Session["Theme"] = userInfo.Theme
+ c.Session["Logo"] = userInfo.Logo
c.Session["NotebookWidth"] = strconv.Itoa(userInfo.NotebookWidth)
c.Session["NoteListWidth"] = strconv.Itoa(userInfo.NoteListWidth)
@@ -165,6 +183,12 @@ func (c BaseController) SetLocale() string {
lang = "en";
}
c.RenderArgs["locale"] = lang;
+ c.RenderArgs["siteUrl"] = siteUrl;
+
+ c.RenderArgs["blogUrl"] = configService.GetBlogUrl()
+ c.RenderArgs["leaUrl"] = configService.GetLeaUrl()
+ c.RenderArgs["noteUrl"] = configService.GetNoteUrl()
+
return lang
}
@@ -172,4 +196,47 @@ func (c BaseController) SetLocale() string {
func (c BaseController) SetUserInfo() {
userInfo := c.GetUserInfo()
c.RenderArgs["userInfo"] = userInfo
+}
+
+// life
+// 返回解析后的字符串, 只是为了解析模板得到字符串
+func (c BaseController) RenderTemplateStr(templatePath string) string {
+ // Get the Template.
+ // 返回 GoTemplate{tmpl, loader}
+ template, err := revel.MainTemplateLoader.Template(templatePath)
+ if err != nil {
+ }
+
+ tpl := &revel.RenderTemplateResult{
+ Template: template,
+ RenderArgs: c.RenderArgs, // 把args给它
+ }
+
+ var buffer bytes.Buffer
+ tpl.Template.Render(&buffer, c.RenderArgs)
+ return buffer.String();
+}
+
+// json, result
+// 为了msg
+// msg-v1-v2-v3
+func (c BaseController) RenderRe(re info.Re) revel.Result {
+ if re.Msg != "" {
+ if(strings.Contains(re.Msg, "-")) {
+ msgAndValues := strings.Split(re.Msg, "-")
+ if len(msgAndValues) == 2 {
+ re.Msg = c.Message(msgAndValues[0], msgAndValues[1])
+ } else {
+ others := msgAndValues[0:]
+ a := make([]interface{}, len(others))
+ for i, v := range others {
+ a[i] = v
+ }
+ re.Msg = c.Message(msgAndValues[0], a...)
+ }
+ } else {
+ re.Msg = c.Message(re.Msg)
+ }
+ }
+ return c.RenderJson(re)
}
\ No newline at end of file
diff --git a/app/controllers/BlogController.go b/app/controllers/BlogController.go
index 98062b2..7c9fde2 100644
--- a/app/controllers/BlogController.go
+++ b/app/controllers/BlogController.go
@@ -1,6 +1,8 @@
package controllers
import (
+ "strings"
+ "time"
"github.com/revel/revel"
// "encoding/json"
"gopkg.in/mgo.v2/bson"
@@ -17,142 +19,283 @@ type Blog struct {
BaseController
}
-//---------------------------
-// 后台 note<->blog
-
-// 设置/取消Blog; 置顶
-func (c Blog) SetNote2Blog(noteId string, isBlog, isTop bool) revel.Result {
- if isTop {
- isBlog = true
- }
- if !isBlog {
- isTop = false
- }
- noteUpdate := bson.M{"IsBlog": isBlog, "IsTop": isTop}
- re := noteService.UpdateNote(c.GetUserId(), c.GetUserId(),
- noteId, noteUpdate)
- return c.RenderJson(re)
-}
-
-// 设置notebook <-> blog
-func (c Blog) SetNotebook2Blog(notebookId string, isBlog bool) revel.Result {
- noteUpdate := bson.M{"IsBlog": isBlog}
- re := notebookService.UpdateNotebook(c.GetUserId(),
- notebookId, noteUpdate)
- return c.RenderJson(re)
-}
-
//-----------------------------
// 前台
+// 域名, 没用
+func (c Blog) domain() (ok bool, userBlog info.UserBlog) {
+ return
+}
+
+// 各种地址设置
+func (c Blog) setUrl(userBlog info.UserBlog, userInfo info.User) {
+ // 主页 http://leanote.com/blog/life or http://blog.leanote.com/life or http:// xxxx.leanote.com or aa.com
+ var indexUrl, viewUrl, searchUrl, cateUrl, aboutMeUrl, staticUrl string
+ host := c.Request.Request.Host
+ staticUrl = configService.GetUserUrl(strings.Split(host, ":")[0])
+ // staticUrl == host, 为保证同源!!! 只有host, http://leanote.com, http://blog/leanote.com
+ // life.leanote.com, lealife.com
+ if userBlog.Domain != "" && configService.AllowCustomDomain() {
+ // ok
+ indexUrl = configService.GetUserUrl(userBlog.Domain)
+ cateUrl = indexUrl + "/cate" // /xxxxx
+ viewUrl = indexUrl + "/view" // /xxxxx
+ searchUrl = indexUrl + "/search" // /xxxxx
+ aboutMeUrl = indexUrl + "/aboutMe"
+ } else if userBlog.SubDomain != "" {
+ indexUrl = configService.GetUserSubUrl(userBlog.SubDomain)
+ cateUrl = indexUrl + "/cate" // /xxxxx
+ viewUrl = indexUrl + "/view" // /xxxxx
+ searchUrl = indexUrl + "/search" // /xxxxx
+ aboutMeUrl = indexUrl + "/aboutMe"
+ } else {
+ // ok
+ blogUrl := configService.GetBlogUrl()
+ userIdOrEmail := ""
+ if userInfo.Username != "" {
+ userIdOrEmail = userInfo.Username
+ } else if userInfo.Email != "" {
+ userIdOrEmail = userInfo.Email
+ } else {
+ userIdOrEmail = userInfo.UserId.Hex()
+ }
+ indexUrl = blogUrl + "/" + userIdOrEmail
+ cateUrl = blogUrl + "/cate" // /notebookId
+ viewUrl = blogUrl + "/view" // /xxxxx
+ searchUrl = blogUrl + "/search/" + userIdOrEmail // /xxxxx
+ aboutMeUrl = blogUrl + "/aboutMe/" + userIdOrEmail
+ }
+
+ // 分类
+ // 搜索
+ // 查看
+ c.RenderArgs["indexUrl"] = indexUrl
+ c.RenderArgs["cateUrl"] = cateUrl
+ c.RenderArgs["viewUrl"] = viewUrl
+ c.RenderArgs["searchUrl"] = searchUrl
+ c.RenderArgs["aboutMeUrl"] = aboutMeUrl
+ c.RenderArgs["staticUrl"] = staticUrl
+}
+
+// 公共
+func (c Blog) blogCommon(userId string, userBlog info.UserBlog, userInfo info.User) (ok bool) {
+ if userInfo.UserId == "" {
+ userInfo = userService.GetUserInfoByAny(userId)
+ if userInfo.UserId == "" {
+ return
+ }
+ }
+ c.RenderArgs["userInfo"] = userInfo
+
+ // 分类导航
+ c.RenderArgs["notebooks"] = blogService.ListBlogNotebooks(userId)
+ // 最新笔记
+ c.getRecentBlogs(userId)
+ // 语言, url地址
+ c.SetLocale();
+ c.RenderArgs["isMe"] = userId == c.GetUserId()
+
+ // 得到博客设置信息
+ if userBlog.UserId == "" {
+ userBlog = blogService.GetUserBlog(userId)
+ }
+ c.RenderArgs["userBlog"] = userBlog
+
+ c.setUrl(userBlog, userInfo)
+
+ return true
+}
+
+// 跨域判断是否是我的博客
+func (c Blog) IsMe(userId string) revel.Result {
+ var js = ""
+ if c.GetUserId() == userId {
+ js = "$('.is-me').removeClass('hide');"
+ }
+ return c.RenderText(js);
+}
// 进入某个用户的博客
var blogPageSize = 5
var searchBlogPageSize = 30
-func (c Blog) Index(userId string, notebookId string) revel.Result {
- // 用户id为空, 转至博客平台
- if userId == "" {
- userId = leanoteUserId;
+
+// 分类 /cate/xxxxxxxx?notebookId=1212
+func (c Blog) Cate(notebookId string) revel.Result {
+ if notebookId == "" {
+ return c.E404()
+ }
+ // 自定义域名
+ hasDomain, userBlog := c.domain()
+ userId := ""
+ if hasDomain {
+ userId = userBlog.UserId.Hex()
}
- // userId可能是 username, email
- userInfo := userService.GetUserInfoByAny(userId)
- if userInfo.UserId == "" {
+ var notebook info.Notebook
+ notebook = notebookService.GetNotebookById(notebookId)
+ if !notebook.IsBlog {
+ return c.E404()
+ }
+ if userId != "" && userId != notebook.UserId.Hex() {
+ return c.E404()
+ }
+ userId = notebook.UserId.Hex()
+
+ if !c.blogCommon(userId, userBlog, info.User{}) {
return c.E404()
}
- userId = userInfo.UserId.Hex()
- c.isMe(userId)
-
- c.RenderArgs["userInfo"] = userInfo
-
- // 得到博客设置信息
- userBlog := blogService.GetUserBlog(userId)
- c.RenderArgs["userBlog"] = userBlog
-
- var notebook info.Notebook
- if notebookId != "" {
- notebook = notebookService.GetNotebook(notebookId, userId)
- if !notebook.IsBlog {
- return c.E404()
- }
-
- c.RenderArgs["title"] = userBlog.Title + " - 分类: " + notebook.Title
- } else {
- c.RenderArgs["title"] = userBlog.Title
- }
// 分页的话, 需要分页信息, totalPage, curPage
page := c.GetPage()
- count, blogs := blogService.ListBlogs(userId, notebookId, page, blogPageSize, "UpdatedTime", false)
+ count, blogs := blogService.ListBlogs(userId, notebookId, page, blogPageSize, "PublicTime", false)
+
+ c.RenderArgs["notebookId"] = notebookId
+ c.RenderArgs["notebook"] = notebook
+ c.RenderArgs["title"] = c.Message("blogClass") + " - " + notebook.Title
+ c.RenderArgs["blogs"] = blogs
+ c.RenderArgs["page"] = page
+ c.RenderArgs["pageSize"] = blogPageSize
+ c.RenderArgs["count"] = count
+
+ return c.RenderTemplate("blog/index.html")
+}
+
+// 显示分类的最近博客, json
+func (c Blog) ListCateLatest(notebookId string) revel.Result {
+ if notebookId == "" {
+ return c.E404()
+ }
+ // 自定义域名
+ hasDomain, userBlog := c.domain()
+ userId := ""
+ if hasDomain {
+ userId = userBlog.UserId.Hex()
+ }
+
+ var notebook info.Notebook
+ notebook = notebookService.GetNotebookById(notebookId)
+ if !notebook.IsBlog {
+ return c.E404()
+ }
+ if userId != "" && userId != notebook.UserId.Hex() {
+ return c.E404()
+ }
+ userId = notebook.UserId.Hex()
+
+ if !c.blogCommon(userId, userBlog, info.User{}) {
+ return c.E404()
+ }
+
+ // 分页的话, 需要分页信息, totalPage, curPage
+ page := 1
+ _, blogs := blogService.ListBlogs(userId, notebookId, page, 5, "PublicTime", false)
+ re := info.NewRe()
+ re.Ok = true
+ re.List = blogs
+ return c.RenderJson(re)
+}
+
+func (c Blog) Index(userIdOrEmail string) revel.Result {
+ // 自定义域名
+ hasDomain, userBlog := c.domain()
+ userId := ""
+ if hasDomain {
+ userId = userBlog.UserId.Hex()
+ }
+
+ // 用户id为空, 转至博客平台
+ if userIdOrEmail == "" {
+ userIdOrEmail = leanoteUserId;
+ }
+ var userInfo info.User
+ if userId != "" {
+ userInfo = userService.GetUserInfoByAny(userId)
+ } else {
+ userInfo = userService.GetUserInfoByAny(userIdOrEmail)
+ }
+ userId = userInfo.UserId.Hex()
+
+ if !c.blogCommon(userId, userBlog, userInfo) {
+ return c.E404()
+ }
+
+ // 分页的话, 需要分页信息, totalPage, curPage
+ page := c.GetPage()
+ count, blogs := blogService.ListBlogs(userId, "", page, blogPageSize, "PublicTime", false)
c.RenderArgs["blogs"] = blogs
c.RenderArgs["page"] = page
c.RenderArgs["pageSize"] = blogPageSize
c.RenderArgs["count"] = count
-
- // 当前notebook
- c.RenderArgs["notebookId"] = notebookId
- c.RenderArgs["notebook"] = notebook
-
- c.RenderArgs["notebooks"] = blogService.ListBlogNotebooks(userId)
-
-
- if notebookId == "" {
- c.RenderArgs["index"] = true
- }
-
- c.getRecentBlogs(userId)
+ c.RenderArgs["index"] = true
+ c.RenderArgs["notebookId"] = ""
+ c.RenderArgs["title"] = userBlog.Title
return c.RenderTemplate("blog/index.html")
}
// 详情
func (c Blog) View(noteId string) revel.Result {
+ // 自定义域名
+ hasDomain, userBlog := c.domain()
+ userId := ""
+ if hasDomain {
+ userId = userBlog.UserId.Hex()
+ }
+
blog := blogService.GetBlog(noteId)
- c.RenderArgs["blog"] = blog
-
userInfo := userService.GetUserInfo(blog.UserId.Hex())
+ if userId != "" && userInfo.UserId.Hex() != userId {
+ return c.E404()
+ }
+ c.RenderArgs["blog"] = blog
c.RenderArgs["userInfo"] = userInfo
+ c.RenderArgs["title"] = blog.Title + " - " + userInfo.Username
- c.RenderArgs["title"] = blog.Title + " - " + userInfo.Email
+ userId = userInfo.UserId.Hex()
+ c.blogCommon(userId, userBlog, info.User{})
- userId := userInfo.UserId.Hex()
- c.isMe(userId)
-
- c.RenderArgs["notebooks"] = blogService.ListBlogNotebooks(userId)
-
- // 得到博客设置信息
- c.RenderArgs["userBlog"] = blogService.GetUserBlog(userId)
-
- c.getRecentBlogs(userId)
+ // 得到访问者id
+ visitUserId := c.GetUserId()
+ if(visitUserId != "") {
+ visitUserInfo := userService.GetUserInfo(visitUserId)
+ c.RenderArgs["visitUserInfoJson"] = c.Json(visitUserInfo)
+ c.RenderArgs["visitUserInfo"] = visitUserInfo
+ } else {
+ c.RenderArgs["visitUserInfoJson"] = "{}";
+ }
return c.RenderTemplate("blog/view.html")
}
// 搜索
-func (c Blog) SearchBlog(userId, key string) revel.Result {
- c.RenderArgs["title"] = "搜索 " + key
+func (c Blog) Search(userIdOrEmail, key string) revel.Result {
+ // 自定义域名
+ hasDomain, userBlog := c.domain()
+ userId := ""
+ if hasDomain {
+ userId = userBlog.UserId.Hex()
+ }
+
+ c.RenderArgs["title"] = c.Message("search") + " - " + key
c.RenderArgs["key"] = key
- userInfo := userService.GetUserInfoByAny(userId)
+ var userInfo info.User
+ if userId != "" {
+ userInfo = userService.GetUserInfoByAny(userId)
+ } else {
+ userInfo = userService.GetUserInfoByAny(userIdOrEmail)
+ }
c.RenderArgs["userInfo"] = userInfo
-
userId = userInfo.UserId.Hex()
+ c.blogCommon(userId, userBlog, userInfo)
page := c.GetPage()
- _, blogs := blogService.SearchBlog(key, userId, page, searchBlogPageSize, "UpdatedTime", false)
+ _, blogs := blogService.SearchBlog(key, userId, page, searchBlogPageSize, "PublicTime", false)
c.RenderArgs["blogs"] = blogs
c.RenderArgs["key"] = key
- c.RenderArgs["notebooks"] = blogService.ListBlogNotebooks(userId)
- // 得到博客设置信息
- c.RenderArgs["userBlog"] = blogService.GetUserBlog(userId)
-
- c.getRecentBlogs(userId)
-
- c.isMe(userId)
-
return c.RenderTemplate("blog/search.html")
}
@@ -162,17 +305,15 @@ func (c Blog) Set() revel.Result {
userInfo := userService.GetUserInfo(userId)
c.RenderArgs["userInfo"] = userInfo
- c.RenderArgs["notebooks"] = blogService.ListBlogNotebooks(userId)
-
// 得到博客设置信息
- c.RenderArgs["userBlog"] = blogService.GetUserBlog(userId)
- c.RenderArgs["title"] = "博客设置"
+ c.RenderArgs["title"] = c.Message("blogSet")
c.RenderArgs["isMe"] = true
c.RenderArgs["set"] = true
- c.getRecentBlogs(userId)
+ c.RenderArgs["allowCustomDomain"] = configService.GetGlobalStringConfig("allowCustomDomain")
- c.SetLocale();
+ userBlog := blogService.GetUserBlog(userId)
+ c.blogCommon(userId, userBlog, info.User{})
return c.RenderTemplate("blog/set.html")
}
@@ -194,37 +335,38 @@ func (c Blog) SetUserBlogStyle(userBlog info.UserBlogStyle) revel.Result {
}
// userId可能是其它的
-func (c Blog) AboutMe(userId string) revel.Result {
- userInfo := userService.GetUserInfoByAny(userId)
+func (c Blog) AboutMe(userIdOrEmail string) revel.Result {
+ // 自定义域名
+ hasDomain, userBlog := c.domain()
+ userId := ""
+ if hasDomain {
+ userId = userBlog.UserId.Hex()
+ }
+
+ var userInfo info.User
+ if userId != "" {
+ userInfo = userService.GetUserInfoByAny(userId)
+ } else {
+ userInfo = userService.GetUserInfoByAny(userIdOrEmail)
+ }
+
if userInfo.UserId == "" {
return c.E404()
}
userId = userInfo.UserId.Hex()
c.RenderArgs["userInfo"] = userInfo
-
- c.RenderArgs["notebooks"] = blogService.ListBlogNotebooks(userId)
-
- c.RenderArgs["userBlog"] = blogService.GetUserBlog(userId)
c.RenderArgs["aboutMe"] = true
-
- c.RenderArgs["title"] = "关于我"
-
- c.isMe(userId)
-
- c.getRecentBlogs(userId)
+
+ c.RenderArgs["title"] = c.Message("aboutMe")
+ c.blogCommon(userId, userBlog, info.User{})
return c.RenderTemplate("blog/about_me.html")
}
-// 当前的博客是否是我的
-func (c Blog) isMe(userId string) {
- c.RenderArgs["isMe"] = userId == c.GetUserId()
-}
-
// 优化, 这里不要得到count
func (c Blog) getRecentBlogs(userId string) {
- _, c.RenderArgs["recentBlogs"] = blogService.ListBlogs(userId, "", 1, 5, "UpdatedTime", false)
+ _, c.RenderArgs["recentBlogs"] = blogService.ListBlogs(userId, "", 1, 5, "PublicTime", false)
}
// 可以不要, 因为注册的时候已经把username设为email了
@@ -233,4 +375,130 @@ func (c Blog) setRenderUserInfo(userInfo info.User) {
userInfo.Username = userInfo.Email
}
c.RenderArgs["userInfo"] = userInfo
+}
+
+//---------------------------
+// 后台 note<->blog
+
+// 设置/取消Blog; 置顶
+func (c Blog) SetNote2Blog(noteId string, isBlog, isTop bool) revel.Result {
+ noteUpdate := bson.M{}
+ if isTop {
+ isBlog = true
+ }
+ if !isBlog {
+ isTop = false
+ }
+ noteUpdate["IsBlog"] = isBlog
+ noteUpdate["IsTop"] = isTop
+ if isBlog {
+ noteUpdate["PublicTime"] = time.Now()
+ }
+ re := noteService.UpdateNote(c.GetUserId(), c.GetUserId(),
+ noteId, noteUpdate)
+ return c.RenderJson(re)
+}
+
+// 设置notebook <-> blog
+func (c Blog) SetNotebook2Blog(notebookId string, isBlog bool) revel.Result {
+ noteUpdate := bson.M{"IsBlog": isBlog}
+ re := notebookService.UpdateNotebook(c.GetUserId(),
+ notebookId, noteUpdate)
+ return c.RenderJson(re)
+}
+
+//----------------
+// 社交, 点赞, 评论
+
+// 我是否点过赞?
+// 所有点赞的用户列表
+// 各个评论中是否我也点过赞?
+func (c Blog) GetLike(noteId string) revel.Result {
+ userId := c.GetUserId()
+
+ // 我也点过?
+ isILikeIt := blogService.IsILikeIt(noteId, userId)
+ // 点赞用户列表
+ likedUsers, hasMoreLikedUser := blogService.ListLikedUsers(noteId, false)
+
+ result := map[string]interface{}{}
+ result["isILikeIt"] = isILikeIt
+ result["likedUsers"] = likedUsers
+ result["hasMoreLikedUser"] = hasMoreLikedUser
+
+ return c.RenderJson(result)
+}
+func (c Blog) GetLikeAndComments(noteId string) revel.Result {
+ userId := c.GetUserId()
+
+ // 我也点过?
+ isILikeIt := blogService.IsILikeIt(noteId, userId)
+ // 点赞用户列表
+ likedUsers, hasMoreLikedUser := blogService.ListLikedUsers(noteId, false)
+ // 评论
+ page := c.GetPage()
+ pageInfo, comments, commentUserInfo := blogService.ListComments(userId, noteId, page, 15)
+
+ result := map[string]interface{}{}
+ result["isILikeIt"] = isILikeIt
+ result["likedUsers"] = likedUsers
+ result["hasMoreLikedUser"] = hasMoreLikedUser
+ result["pageInfo"] = pageInfo
+ result["comments"] = comments
+ result["commentUserInfo"] = commentUserInfo
+
+ return c.RenderJson(result)
+}
+
+func (c Blog) IncReadNum(noteId string) revel.Result {
+ blogService.IncReadNum(noteId)
+ return nil
+}
+// 点赞
+func (c Blog) LikeBlog(noteId string) revel.Result {
+ userId := c.GetUserId()
+ re := info.NewRe()
+ re.Ok, re.Item = blogService.LikeBlog(noteId, userId)
+
+ return c.RenderJson(re)
+}
+func (c Blog) ListLikes(noteId string) revel.Result {
+ return nil
+}
+
+func (c Blog) ListComments(noteId string) revel.Result {
+ // 评论
+ userId := c.GetUserId()
+ page := c.GetPage()
+ pageInfo, comments, commentUserInfo := blogService.ListComments(userId, noteId, page, 15)
+
+ result := map[string]interface{}{}
+ result["pageInfo"] = pageInfo
+ result["comments"] = comments
+ result["commentUserInfo"] = commentUserInfo
+
+ return c.RenderJson(result)
+}
+func (c Blog) DeleteComment(noteId, commentId string) revel.Result {
+ re := info.NewRe()
+ re.Ok = blogService.DeleteComment(noteId, commentId, c.GetUserId())
+ return c.RenderJson(re)
+}
+func (c Blog) Comment(noteId, content, toCommentId string) revel.Result {
+ re := info.NewRe()
+ re.Ok, re.Item = blogService.Comment(noteId, toCommentId, c.GetUserId(), content);
+ return c.RenderJson(re)
+}
+func (c Blog) LikeComment(commentId string) revel.Result {
+ re := info.NewRe()
+ ok, isILikeIt, num := blogService.LikeComment(commentId, c.GetUserId())
+ re.Ok = ok
+ re.Item = bson.M{"IsILikeIt": isILikeIt, "Num": num}
+ return c.RenderJson(re)
+}
+
+func (c Blog) Report(noteId, commentId, reason string) revel.Result {
+ re := info.NewRe()
+ re.Ok = blogService.Report(noteId, commentId, reason, c.GetUserId());
+ return c.RenderJson(re)
}
\ No newline at end of file
diff --git a/app/controllers/CaptchaController.go b/app/controllers/CaptchaController.go
new file mode 100644
index 0000000..a4dd621
--- /dev/null
+++ b/app/controllers/CaptchaController.go
@@ -0,0 +1,43 @@
+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/lea/captcha"
+// "github.com/leanote/leanote/app/types"
+// "io/ioutil"
+// "fmt"
+// "math"
+// "os"
+// "path"
+// "strconv"
+ "net/http"
+)
+
+// 验证码服务
+type Captcha struct {
+ BaseController
+}
+
+type Ca string
+func (r Ca) Apply(req *revel.Request, resp *revel.Response) {
+ resp.WriteHeader(http.StatusOK, "image/png")
+}
+
+func (c Captcha) Get() revel.Result {
+ c.Response.ContentType = "image/png"
+ image, str := captcha.Fetch()
+ image.WriteTo(c.Response.Out)
+
+ sessionId := c.Session["_ID"]
+// LogJ(c.Session)
+// Log("------")
+// Log(str)
+// Log(sessionId)
+Log("..")
+ sessionService.SetCaptcha(sessionId, str)
+
+ return c.Render()
+}
\ No newline at end of file
diff --git a/app/controllers/FileController.go b/app/controllers/FileController.go
index dd5cebe..e8609bd 100644
--- a/app/controllers/FileController.go
+++ b/app/controllers/FileController.go
@@ -5,6 +5,7 @@ import (
// "encoding/json"
"gopkg.in/mgo.v2/bson"
. "github.com/leanote/leanote/app/lea"
+ "github.com/leanote/leanote/app/lea/netutil"
"github.com/leanote/leanote/app/info"
"io/ioutil"
"os"
@@ -22,7 +23,7 @@ type File struct {
func (c File) UploadBlogLogo() revel.Result {
re := c.uploadImage("logo", "");
- c.RenderArgs["fileUrlPath"] = siteUrl + "/" + re.Id
+ c.RenderArgs["fileUrlPath"] = re.Id
c.RenderArgs["resultCode"] = re.Code
c.RenderArgs["resultMsg"] = re.Msg
@@ -53,6 +54,24 @@ func (c File) PasteImage(noteId string) revel.Result {
return c.RenderJson(re)
}
+// 头像设置
+func (c File) UploadAvatar() revel.Result {
+ re := c.uploadImage("logo", "");
+
+ c.RenderArgs["fileUrlPath"] = re.Id
+ c.RenderArgs["resultCode"] = re.Code
+ c.RenderArgs["resultMsg"] = re.Msg
+
+ if re.Ok {
+ re.Ok = userService.UpdateAvatar(c.GetUserId(), re.Id)
+ if re.Ok {
+ c.UpdateSession("Logo", re.Id);
+ }
+ }
+
+ return c.RenderJson(re)
+}
+
// leaui image plugin upload image
func (c File) UploadImageLeaui(albumId string) revel.Result {
re := c.uploadImage("", albumId);
@@ -243,6 +262,38 @@ func (c File) CopyImage(userId, fileId, toUserId string) revel.Result {
return c.RenderJson(re)
}
+// 复制外网的图片, 成公共图片 放在/upload下
+func (c File) CopyHttpImage(src string) revel.Result {
+ re := info.NewRe()
+ fileUrlPath := "upload/" + c.GetUserId() + "/images"
+ dir := revel.BasePath + "/public/" + fileUrlPath
+ err := os.MkdirAll(dir, 0755)
+ if err != nil {
+ return c.RenderJson(re)
+ }
+ filesize, filename, _, ok := netutil.WriteUrl(src, dir)
+
+ if !ok {
+ re.Msg = "copy error"
+ return c.RenderJson(re)
+ }
+
+ // File
+ fileInfo := info.File{Name: filename,
+ Title: filename,
+ Path: fileUrlPath + "/" + filename,
+ Size: filesize}
+
+ id := bson.NewObjectId();
+ fileInfo.FileId = id
+
+ re.Id = id.Hex()
+ re.Item = fileInfo.Path
+ re.Ok = fileService.AddImage(fileInfo, "", c.GetUserId())
+
+ return c.RenderJson(re)
+}
+
//------------
// 过时 已弃用!
func (c File) UploadImage(renderHtml string) revel.Result {
diff --git a/app/controllers/IndexController.go b/app/controllers/IndexController.go
index 9f39cf0..c357f66 100644
--- a/app/controllers/IndexController.go
+++ b/app/controllers/IndexController.go
@@ -3,7 +3,7 @@ package controllers
import (
"github.com/revel/revel"
"github.com/leanote/leanote/app/info"
- . "github.com/leanote/leanote/app/lea"
+// . "github.com/leanote/leanote/app/lea"
)
// 首页
@@ -29,7 +29,7 @@ func (c Index) Suggestion(addr, suggestion string) revel.Result {
// 发给我
go func() {
- SendToLeanote("建议", "建议", "UserId: " + c.GetUserId() + "
Suggestions: " + suggestion)
+ emailService.SendEmail("leanote@leanote.com", "建议", "UserId: " + c.GetUserId() + "
Suggestions: " + suggestion)
}();
return c.RenderJson(re)
diff --git a/app/controllers/NoteController.go b/app/controllers/NoteController.go
index 17b48c5..aca4420 100644
--- a/app/controllers/NoteController.go
+++ b/app/controllers/NoteController.go
@@ -5,12 +5,13 @@ import (
// "encoding/json"
"gopkg.in/mgo.v2/bson"
. "github.com/leanote/leanote/app/lea"
- "github.com/leanote/leanote/app/lea/html2image"
"github.com/leanote/leanote/app/info"
-// "os"
+ "os/exec"
// "github.com/leanote/leanote/app/types"
// "io/ioutil"
// "fmt"
+// "bytes"
+// "os"
)
type Note struct {
@@ -52,6 +53,8 @@ func (c Note) Index() revel.Result {
// 当然, 还需要得到第一个notes的content
//...
+ adminUsername, _ := revel.Config.String("adminUsername")
+ c.RenderArgs["isAdmin"] = adminUsername == userInfo.Username
c.RenderArgs["userInfo"] = userInfo
c.RenderArgs["userInfoJson"] = c.Json(userInfo)
c.RenderArgs["notebooks"] = c.Json(notebooks)
@@ -221,31 +224,131 @@ func (c Note) SearchNoteByTags(tags []string) revel.Result {
return c.RenderJson(blogs)
}
-//-----------------
+//------------------
// html2image
+// 判断是否有权限生成
+// 博客也可以调用
+// 这是脚本调用, 没有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.GetNote(noteId, userId)
+ note := noteService.GetNoteById(noteId)
if note.NoteId == "" {
+ re.Msg = "No Note"
return c.RenderJson(re)
}
- content := noteService.GetNoteContent(noteId, userId)
+ 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/" + userId + "/images/weibo"
+ 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
- // 生成之
- html2image.ToImage(userId, c.GetUsername(), noteId, note.Title, content.Content, path)
+ // 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:]
+ }
- re.Ok = true
- re.Id = fileUrlPath + "/" + filename
+ 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))
+ }
+ */
+
}
\ No newline at end of file
diff --git a/app/controllers/UserController.go b/app/controllers/UserController.go
index 8abe42a..c2b74b8 100644
--- a/app/controllers/UserController.go
+++ b/app/controllers/UserController.go
@@ -8,7 +8,7 @@ import (
"github.com/leanote/leanote/app/info"
// "github.com/leanote/leanote/app/types"
// "io/ioutil"
- "fmt"
+// "fmt"
// "math"
// "os"
// "path"
@@ -19,43 +19,48 @@ type User struct {
BaseController
}
+func (c User) Account(tab int) revel.Result {
+ userInfo := c.GetUserInfo()
+ c.RenderArgs["userInfo"] = userInfo
+ c.RenderArgs["tab"] = tab
+ c.SetLocale()
+ return c.RenderTemplate("user/account.html")
+}
+
// 修改用户名, 需要重置session
func (c User) UpdateUsername(username string) revel.Result {
re := info.NewRe();
- // 判断是否满足最基本的, 4位, 不含特殊字符, 大小写无关. email大小写无关
- if len(username) < 4 {
- re.Ok = false
- re.Msg = "至少4位"
- return c.RenderJson(re);
+ if(c.GetUsername() == "demo") {
+ re.Msg = "cannotUpdateDemo"
+ return c.RenderRe(re);
}
- if !IsUsername(username) {
- re.Ok = false
- re.Msg = "不能包含特殊字符"
- return c.RenderJson(re);
+
+ if re.Ok, re.Msg = Vd("username", username); !re.Ok {
+ return c.RenderRe(re);
}
re.Ok, re.Msg = userService.UpdateUsername(c.GetUserId(), username)
if(re.Ok) {
c.UpdateSession("Username", username)
}
- return c.RenderJson(re);
+ return c.RenderRe(re);
}
// 修改密码
func (c User) UpdatePwd(oldPwd, pwd string) revel.Result {
re := info.NewRe();
- if oldPwd == "" {
- re.Msg = "旧密码错误"
- return c.RenderJson(re);
+ if(c.GetUsername() == "demo") {
+ re.Msg = "cannotUpdateDemo"
+ return c.RenderRe(re);
}
-
- re.Ok, re.Msg = IsGoodPwd(pwd)
- if !re.Ok {
- return c.RenderJson(re);
+ if re.Ok, re.Msg = Vd("password", oldPwd); !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.UpdatePwd(c.GetUserId(), oldPwd, pwd)
- return c.RenderJson(re);
+ return c.RenderRe(re);
}
// 更新主题
@@ -75,14 +80,7 @@ func (c User) SendRegisterEmail(content, toEmail string) revel.Result {
return c.RenderJson(re);
}
- // 发送邮件
- var userInfo = c.GetUserInfo();
- siteUrl, _ := revel.Config.String("site.url")
- url := siteUrl + "/register?from=" + userInfo.Username
- body := fmt.Sprintf("点击链接注册leanote: %v. ", url, url);
- body = content + "
" + body
- re.Ok = SendEmail(toEmail, userInfo.Username + "邀请您注册leanote", "邀请注册", body)
-
+ re.Ok = emailService.SendInviteEmail(c.GetUserInfo(), toEmail, content)
return c.RenderJson(re);
}
@@ -91,15 +89,23 @@ func (c User) SendRegisterEmail(content, toEmail string) revel.Result {
// 重新发送激活邮件
func (c User) ReSendActiveEmail() revel.Result {
re := info.NewRe()
- re.Ok = userService.RegisterSendActiveEmail(c.GetUserId(), c.GetEmail())
+ re.Ok = emailService.RegisterSendActiveEmail(c.GetUserInfo(), c.GetEmail())
return c.RenderJson(re)
}
// 修改Email发送激活邮箱
func (c User) UpdateEmailSendActiveEmail(email string) revel.Result {
re := info.NewRe()
- re.Ok, re.Msg = userService.UpdateEmailSendActiveEmail(c.GetUserId(), email)
- return c.RenderJson(re)
+ if(c.GetUsername() == "demo") {
+ 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)
}
// 通过点击链接
@@ -145,22 +151,12 @@ func (c User) ActiveEmail(token string) revel.Result {
// 第三方账号添加leanote账号
func (c User) AddAccount(email, pwd string) revel.Result {
re := info.NewRe()
-
- if email == "" {
- re.Msg = "请输入邮箱"
- return c.RenderJson(re)
- } else if !IsEmail(email) {
- re.Msg = "请输入正确的邮箱"
- return c.RenderJson(re)
- }
- // 密码
- if pwd == "" {
- re.Msg = "请输入密码"
- return c.RenderJson(re)
- } else if len(pwd) < 6 {
- re.Msg = "密码长度至少6位"
- return c.RenderJson(re)
+ 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)
@@ -169,17 +165,20 @@ func (c User) AddAccount(email, pwd string) revel.Result {
c.UpdateSession("Email", email);
}
- return c.RenderJson(re)
+ return c.RenderRe(re)
}
//-----------------
// 用户偏爱
-func (c User) UpdateColumnWidth(notebookWidth, noteListWidth int) revel.Result {
+func (c User) UpdateColumnWidth(notebookWidth, noteListWidth, mdEditorWidth int) revel.Result {
re := info.NewRe()
- re.Ok = userService.UpdateColumnWidth(c.GetUserId(), notebookWidth, noteListWidth)
+ re.Ok = userService.UpdateColumnWidth(c.GetUserId(), notebookWidth, noteListWidth, mdEditorWidth)
if re.Ok {
c.UpdateSession("NotebookWidth", strconv.Itoa(notebookWidth));
- c.UpdateSession("NoteListWidth", strconv.Itoa(noteListWidth));
+ c.UpdateSession("NoteListWidth", strconv.Itoa(noteListWidth));
+ c.UpdateSession("MdEditorWidth", strconv.Itoa(mdEditorWidth));
+
+ LogJ(c.Session)
}
return c.RenderJson(re)
}
diff --git a/app/controllers/admin/AdminBaseController.go b/app/controllers/admin/AdminBaseController.go
index 296cf88..6b3ab18 100644
--- a/app/controllers/admin/AdminBaseController.go
+++ b/app/controllers/admin/AdminBaseController.go
@@ -48,4 +48,12 @@ func (c AdminBaseController) getSorter(sorterField string, isAsc bool, okSorter
}
c.RenderArgs["sorter"] = sorter
return sorterField, isAsc;
+}
+
+func (c AdminBaseController) updateConfig(keys []string) {
+ userId := c.GetUserId()
+ for _, key := range keys {
+ v := c.Params.Values.Get(key)
+ configService.UpdateGlobalStringConfig(userId, key, v)
+ }
}
\ No newline at end of file
diff --git a/app/controllers/admin/AdminController.go b/app/controllers/admin/AdminController.go
index d4ec713..5bdc5e8 100644
--- a/app/controllers/admin/AdminController.go
+++ b/app/controllers/admin/AdminController.go
@@ -17,9 +17,22 @@ func (c Admin) Index() revel.Result {
c.RenderArgs["title"] = "leanote"
c.SetLocale()
+ c.RenderArgs["countUser"] = userService.CountUser()
+ c.RenderArgs["countNote"] = noteService.CountNote()
+ c.RenderArgs["countBlog"] = noteService.CountBlog()
+
return c.RenderTemplate("admin/index.html");
}
+// 模板
+func (c Admin) 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 Admin) GetView(view string) revel.Result {
return c.RenderTemplate("admin/" + view);
}
\ No newline at end of file
diff --git a/app/controllers/admin/AdminData.go b/app/controllers/admin/AdminData.go
new file mode 100644
index 0000000..8304c79
--- /dev/null
+++ b/app/controllers/admin/AdminData.go
@@ -0,0 +1,114 @@
+package admin
+
+import (
+ "github.com/revel/revel"
+ . "github.com/leanote/leanote/app/lea"
+ "github.com/leanote/leanote/app/info"
+ "archive/tar"
+ "compress/gzip"
+ "os"
+ "io"
+ "time"
+)
+
+// 数据管理, 备份和恢复
+
+type AdminData struct {
+ AdminBaseController
+}
+
+func (c AdminData) Index() revel.Result {
+ backups := configService.GetGlobalArrMapConfig("backups")
+ // 逆序之
+ backups2 := make([]map[string]string, len(backups))
+ j := 0
+ for i := len(backups)-1; i >= 0; i-- {
+ backups2[j] = backups[i]
+ j++
+ }
+ c.RenderArgs["backups"] = backups2
+ return c.RenderTemplate("admin/data/index.html");
+}
+
+func (c AdminData) Backup() revel.Result {
+ re := info.NewRe()
+ re.Ok, re.Msg = configService.Backup("")
+ return c.RenderJson(re)
+}
+
+// 还原
+func (c AdminData) Restore(createdTime string) revel.Result {
+ re := info.Re{}
+ re.Ok, re.Msg = configService.Restore(createdTime)
+ return c.RenderJson(re)
+}
+
+func (c AdminData) Delete(createdTime string) revel.Result {
+ re := info.Re{}
+ re.Ok, re.Msg = configService.DeleteBackup(createdTime)
+ return c.RenderJson(re)
+}
+func (c AdminData) UpdateRemark(createdTime, remark string) revel.Result {
+ re := info.Re{}
+ re.Ok, re.Msg = configService.UpdateBackupRemark(createdTime, remark)
+
+ return c.RenderJson(re)
+}
+func (c AdminData) Download(createdTime string) revel.Result {
+ backup, ok := configService.GetBackup(createdTime)
+ if !ok {
+ return c.RenderText("")
+ }
+
+ dbname, _ := revel.Config.String("db.dbname")
+ path := backup["path"] + "/" + dbname
+ allFiles := ListDir(path)
+
+ filename := "backup_" + dbname + "_" + backup["createdTime"] + ".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 _, file := range allFiles {
+ fn := path + "/" + file
+ fr, err := os.Open(fn)
+ fileInfo, _ := fr.Stat()
+ if err != nil {
+ return c.RenderText("")
+ }
+ defer fr.Close()
+
+ // 信息头
+ h := new(tar.Header)
+ h.Name = file
+ 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
+
+ return c.RenderBinary(fw, filename, revel.Attachment, time.Now()) // revel.Attachm
+}
diff --git a/app/controllers/admin/AdminEmailController.go b/app/controllers/admin/AdminEmailController.go
new file mode 100644
index 0000000..b12494f
--- /dev/null
+++ b/app/controllers/admin/AdminEmailController.go
@@ -0,0 +1,233 @@
+package admin
+
+import (
+ "github.com/revel/revel"
+ . "github.com/leanote/leanote/app/lea"
+ "github.com/leanote/leanote/app/info"
+ "strings"
+ "strconv"
+)
+
+// admin 首页
+
+type AdminEmail struct {
+ AdminBaseController
+}
+
+// email配置
+func (c AdminEmail) Email() revel.Result {
+ return nil
+}
+
+// blog标签设置
+func (c AdminEmail) Blog() revel.Result {
+ recommendTags := configService.GetGlobalArrayConfig("recommendTags")
+ newTags := configService.GetGlobalArrayConfig("newTags")
+ c.RenderArgs["recommendTags"] = strings.Join(recommendTags, ",")
+ c.RenderArgs["newTags"] = strings.Join(newTags, ",")
+ return c.RenderTemplate("admin/setting/blog.html");
+}
+func (c AdminEmail) DoBlogTag(recommendTags, newTags string) revel.Result {
+ re := info.NewRe()
+
+ re.Ok = configService.UpdateGlobalArrayConfig(c.GetUserId(), "recommendTags", strings.Split(recommendTags, ","))
+ re.Ok = configService.UpdateGlobalArrayConfig(c.GetUserId(), "newTags", strings.Split(newTags, ","))
+
+ return c.RenderJson(re)
+}
+
+// demo
+// blog标签设置
+func (c AdminEmail) Demo() revel.Result {
+ c.RenderArgs["demoUsername"] = configService.GetGlobalStringConfig("demoUsername")
+ c.RenderArgs["demoPassword"] = configService.GetGlobalStringConfig("demoPassword")
+ return c.RenderTemplate("admin/setting/demo.html");
+}
+func (c AdminEmail) DoDemo(demoUsername, demoPassword string) revel.Result {
+ re := info.NewRe()
+
+ userInfo := authService.Login(demoUsername, demoPassword)
+ if userInfo.UserId == "" {
+ re.Msg = "The User is Not Exists";
+ return c.RenderJson(re)
+ }
+
+ re.Ok = configService.UpdateGlobalStringConfig(c.GetUserId(), "demoUserId", userInfo.UserId.Hex())
+ re.Ok = configService.UpdateGlobalStringConfig(c.GetUserId(), "demoUsername", demoUsername)
+ re.Ok = configService.UpdateGlobalStringConfig(c.GetUserId(), "demoPassword", demoPassword)
+
+ return c.RenderJson(re)
+}
+
+// ToImage
+// 长微博的bin路径phantomJs
+func (c AdminEmail) ToImage() revel.Result {
+ c.RenderArgs["toImageBinPath"] = configService.GetGlobalStringConfig("toImageBinPath")
+ return c.RenderTemplate("admin/setting/toImage.html");
+}
+func (c AdminEmail) DoToImage(toImageBinPath string) revel.Result {
+ re := info.NewRe()
+ re.Ok = configService.UpdateGlobalStringConfig(c.GetUserId(), "toImageBinPath", toImageBinPath)
+ return c.RenderJson(re)
+}
+
+func (c AdminEmail) Set(emailHost, emailPort, emailUsername, emailPassword string) revel.Result {
+ re := info.NewRe()
+ re.Ok = configService.UpdateGlobalStringConfig(c.GetUserId(), "emailHost", emailHost)
+ re.Ok = configService.UpdateGlobalStringConfig(c.GetUserId(), "emailPort", emailPort)
+ re.Ok = configService.UpdateGlobalStringConfig(c.GetUserId(), "emailUsername", emailUsername)
+ re.Ok = configService.UpdateGlobalStringConfig(c.GetUserId(), "emailPassword", emailPassword)
+
+ return c.RenderJson(re)
+}
+func (c AdminEmail) Template() revel.Result {
+ re := info.NewRe()
+
+ keys := []string{"emailTemplateHeader", "emailTemplateFooter",
+ "emailTemplateRegisterSubject",
+ "emailTemplateRegister",
+ "emailTemplateFindPasswordSubject",
+ "emailTemplateFindPassword",
+ "emailTemplateUpdateEmailSubject",
+ "emailTemplateUpdateEmail",
+ "emailTemplateInviteSubject",
+ "emailTemplateInvite",
+ "emailTemplateCommentSubject",
+ "emailTemplateComment",
+ }
+
+ userId := c.GetUserId()
+ for _, key := range keys {
+ v := c.Params.Values.Get(key)
+ if v != "" {
+ ok, msg := emailService.ValidTpl(v)
+ if !ok {
+ re.Ok = false
+ re.Msg = "Error key: " + key + "
" + msg
+ return c.RenderJson(re)
+ } else {
+ configService.UpdateGlobalStringConfig(userId, key, v)
+ }
+ }
+ }
+
+ re.Ok = true
+ return c.RenderJson(re)
+}
+
+// 发送Email
+func (c AdminEmail) SendEmailToEmails(sendEmails, latestEmailSubject, latestEmailBody string, verified, saveAsOldEmail bool) revel.Result {
+ re := info.NewRe()
+
+ c.updateConfig([]string{"sendEmails", "latestEmailSubject", "latestEmailBody"})
+
+ if latestEmailSubject == "" || latestEmailBody == "" {
+ re.Msg = "subject or body is blank"
+ return c.RenderJson(re)
+ }
+
+ if saveAsOldEmail {
+ oldEmails := configService.GetGlobalMapConfig("oldEmails")
+ oldEmails[latestEmailSubject] = latestEmailBody
+ configService.UpdateGlobalMapConfig(c.GetUserId(), "oldEmails", oldEmails);
+ }
+
+ sendEmails = strings.Replace(sendEmails, "\r", "", -1)
+ emails := strings.Split(sendEmails, "\n")
+
+ re.Ok, re.Msg = emailService.SendEmailToEmails(emails, latestEmailSubject, latestEmailBody);
+ return c.RenderJson(re)
+}
+
+// 发送Email
+func (c AdminEmail) SendToUsers2(emails, latestEmailSubject, latestEmailBody string, verified, saveAsOldEmail bool) revel.Result {
+ re := info.NewRe()
+
+ c.updateConfig([]string{"sendEmails", "latestEmailSubject", "latestEmailBody"})
+
+ if latestEmailSubject == "" || latestEmailBody == "" {
+ re.Msg = "subject or body is blank"
+ return c.RenderJson(re)
+ }
+
+ if saveAsOldEmail {
+ oldEmails := configService.GetGlobalMapConfig("oldEmails")
+ oldEmails[latestEmailSubject] = latestEmailBody
+ configService.UpdateGlobalMapConfig(c.GetUserId(), "oldEmails", oldEmails);
+ }
+
+ emails = strings.Replace(emails, "\r", "", -1)
+ emailsArr := strings.Split(emails, "\n")
+
+ users := userService.ListUserInfosByEmails(emailsArr)
+ LogJ(emailsArr)
+
+
+ re.Ok, re.Msg = emailService.SendEmailToUsers(users, latestEmailSubject, latestEmailBody);
+
+ return c.RenderJson(re)
+}
+
+// send Email dialog
+func (c AdminEmail) SendEmailDialog(emails string) revel.Result{
+ emailsArr := strings.Split(emails, ",")
+ emailsNl := strings.Join(emailsArr, "\n")
+
+ c.RenderArgs["emailsNl"] = emailsNl
+ c.RenderArgs["str"] = configService.GlobalStringConfigs
+ c.RenderArgs["map"] = configService.GlobalMapConfigs
+
+ return c.RenderTemplate("admin/email/emailDialog.html");
+}
+
+func (c AdminEmail) SendToUsers(userFilterEmail, userFilterWhiteList, userFilterBlackList, latestEmailSubject, latestEmailBody string, verified, saveAsOldEmail bool) revel.Result {
+ re := info.NewRe()
+
+ c.updateConfig([]string{"userFilterEmail", "userFilterWhiteList", "userFilterBlackList", "latestEmailSubject", "latestEmailBody"})
+
+ if latestEmailSubject == "" || latestEmailBody == "" {
+ re.Msg = "subject or body is blank"
+ return c.RenderJson(re)
+ }
+
+ if saveAsOldEmail {
+ oldEmails := configService.GetGlobalMapConfig("oldEmails")
+ oldEmails[latestEmailSubject] = latestEmailBody
+ configService.UpdateGlobalMapConfig(c.GetUserId(), "oldEmails", oldEmails);
+ }
+
+ users := userService.GetAllUserByFilter(userFilterEmail, userFilterWhiteList, userFilterBlackList, verified)
+
+ if(users == nil || len(users) == 0) {
+ re.Ok = false
+ re.Msg = "no users"
+ return c.RenderJson(re)
+ }
+
+ re.Ok, re.Msg = emailService.SendEmailToUsers(users, latestEmailSubject, latestEmailBody);
+ if(!re.Ok) {
+ return c.RenderJson(re)
+ }
+
+ re.Ok = true
+ re.Msg = "users:" + strconv.Itoa(len(users))
+
+ return c.RenderJson(re)
+}
+
+// 删除emails
+func (c AdminEmail) DeleteEmails(ids string) revel.Result {
+ re := info.NewRe()
+ re.Ok = emailService.DeleteEmails(strings.Split(ids, ","))
+ return c.RenderJson(re)
+}
+
+func (c AdminEmail) List(sorter, keywords string) revel.Result {
+ pageNumber := c.GetPage()
+ sorterField, isAsc := c.getSorter("CreatedTime", false, []string{"email", "ok", "subject", "createdTime"});
+ pageInfo, emails := emailService.ListEmailLogs(pageNumber, userPageSize, sorterField, isAsc, keywords);
+ c.RenderArgs["pageInfo"] = pageInfo
+ c.RenderArgs["emails"] = emails
+ c.RenderArgs["keywords"] = keywords
+ return c.RenderTemplate("admin/email/list.html");
+}
\ No newline at end of file
diff --git a/app/controllers/admin/AdminSettingController.go b/app/controllers/admin/AdminSettingController.go
index 630b2a2..41d92ac 100644
--- a/app/controllers/admin/AdminSettingController.go
+++ b/app/controllers/admin/AdminSettingController.go
@@ -29,12 +29,22 @@ func (c AdminSetting) Blog() revel.Result {
func (c AdminSetting) DoBlogTag(recommendTags, newTags string) revel.Result {
re := info.NewRe()
- re.Ok = configService.UpdateUserArrayConfig(c.GetUserId(), "recommendTags", strings.Split(recommendTags, ","))
- re.Ok = configService.UpdateUserArrayConfig(c.GetUserId(), "newTags", strings.Split(newTags, ","))
+ re.Ok = configService.UpdateGlobalArrayConfig(c.GetUserId(), "recommendTags", strings.Split(recommendTags, ","))
+ re.Ok = configService.UpdateGlobalArrayConfig(c.GetUserId(), "newTags", strings.Split(newTags, ","))
return c.RenderJson(re)
}
+// 共享设置
+func (c AdminSetting) ShareNote(registerSharedUserId string,
+ registerSharedNotebookPerms, registerSharedNotePerms []int,
+ registerSharedNotebookIds, registerSharedNoteIds, registerCopyNoteIds []string) revel.Result {
+
+ re := info.NewRe()
+ re.Ok, re.Msg = configService.UpdateShareNoteConfig(registerSharedUserId, registerSharedNotebookPerms, registerSharedNotePerms, registerSharedNotebookIds, registerSharedNoteIds, registerCopyNoteIds);
+ return c.RenderJson(re)
+}
+
// demo
// blog标签设置
func (c AdminSetting) Demo() revel.Result {
@@ -51,12 +61,53 @@ func (c AdminSetting) DoDemo(demoUsername, demoPassword string) revel.Result {
return c.RenderJson(re)
}
- re.Ok = configService.UpdateUserStringConfig(c.GetUserId(), "demoUserId", userInfo.UserId.Hex())
- re.Ok = configService.UpdateUserStringConfig(c.GetUserId(), "demoUsername", demoUsername)
- re.Ok = configService.UpdateUserStringConfig(c.GetUserId(), "demoPassword", demoPassword)
+ re.Ok = configService.UpdateGlobalStringConfig(c.GetUserId(), "demoUserId", userInfo.UserId.Hex())
+ re.Ok = configService.UpdateGlobalStringConfig(c.GetUserId(), "demoUsername", demoUsername)
+ re.Ok = configService.UpdateGlobalStringConfig(c.GetUserId(), "demoPassword", demoPassword)
return c.RenderJson(re)
}
+// ToImage
+// 长微博的bin路径phantomJs
+func (c AdminSetting) ToImage() revel.Result {
+ c.RenderArgs["toImageBinPath"] = configService.GetGlobalStringConfig("toImageBinPath")
+ return c.RenderTemplate("admin/setting/toImage.html");
+}
+func (c AdminSetting) DoToImage(toImageBinPath string) revel.Result {
+ re := info.NewRe()
+ re.Ok = configService.UpdateGlobalStringConfig(c.GetUserId(), "toImageBinPath", toImageBinPath)
+ return c.RenderJson(re)
+}
+// SubDomain
+func (c AdminSetting) SubDomain() revel.Result {
+ c.RenderArgs["str"] = configService.GlobalStringConfigs
+ c.RenderArgs["arr"] = configService.GlobalArrayConfigs
+
+ c.RenderArgs["noteSubDomain"] = configService.GetGlobalStringConfig("noteSubDomain")
+ c.RenderArgs["blogSubDomain"] = configService.GetGlobalStringConfig("blogSubDomain")
+ c.RenderArgs["leaSubDomain"] = configService.GetGlobalStringConfig("leaSubDomain")
+
+ return c.RenderTemplate("admin/setting/subDomain.html");
+}
+func (c AdminSetting) DoSubDomain(noteSubDomain, blogSubDomain, leaSubDomain, blackSubDomains, allowCustomDomain, blackCustomDomains string) revel.Result {
+ re := info.NewRe()
+ re.Ok = configService.UpdateGlobalStringConfig(c.GetUserId(), "noteSubDomain", noteSubDomain)
+ re.Ok = configService.UpdateGlobalStringConfig(c.GetUserId(), "blogSubDomain", blogSubDomain)
+ re.Ok = configService.UpdateGlobalStringConfig(c.GetUserId(), "leaSubDomain", leaSubDomain)
+
+ re.Ok = configService.UpdateGlobalStringConfig(c.GetUserId(), "allowCustomDomain", allowCustomDomain)
+ re.Ok = configService.UpdateGlobalArrayConfig(c.GetUserId(), "blackSubDomains", strings.Split(blackSubDomains, ","))
+ re.Ok = configService.UpdateGlobalArrayConfig(c.GetUserId(), "blackCustomDomains", strings.Split(blackCustomDomains, ","))
+
+ return c.RenderJson(re)
+}
+func (c AdminSetting) Mongodb(mongodumpPath, mongorestorePath string) revel.Result {
+ re := info.NewRe()
+ re.Ok = configService.UpdateGlobalStringConfig(c.GetUserId(), "mongodumpPath", mongodumpPath)
+ re.Ok = configService.UpdateGlobalStringConfig(c.GetUserId(), "mongorestorePath", mongorestorePath)
+
+ return c.RenderJson(re)
+}
\ No newline at end of file
diff --git a/app/controllers/admin/AdminUpgradeController.go b/app/controllers/admin/AdminUpgradeController.go
new file mode 100644
index 0000000..c8dc206
--- /dev/null
+++ b/app/controllers/admin/AdminUpgradeController.go
@@ -0,0 +1,18 @@
+package admin
+
+import (
+ "github.com/revel/revel"
+// "encoding/json"
+// . "github.com/leanote/leanote/app/lea"
+// "io/ioutil"
+)
+
+// Upgrade controller
+type AdminUpgrade struct {
+ AdminBaseController
+}
+
+func (c AdminUpgrade) UpgradeBlog() revel.Result {
+ upgradeService.UpgradeBlog()
+ return nil;
+}
\ No newline at end of file
diff --git a/app/controllers/admin/init.go b/app/controllers/admin/init.go
index 8907670..f725029 100644
--- a/app/controllers/admin/init.go
+++ b/app/controllers/admin/init.go
@@ -25,6 +25,8 @@ 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 adminUsername = "admin"
// 拦截器
@@ -115,12 +117,18 @@ func InitService() {
suggestionService = service.SuggestionS
authService = service.AuthS
configService = service.ConfigS
+ emailService = service.EmailS
+ upgradeService = service.UpgradeS
}
func init() {
revel.InterceptFunc(AuthInterceptor, revel.BEFORE, &Admin{})
revel.InterceptFunc(AuthInterceptor, revel.BEFORE, &AdminSetting{})
revel.InterceptFunc(AuthInterceptor, revel.BEFORE, &AdminUser{})
+ revel.InterceptFunc(AuthInterceptor, revel.BEFORE, &AdminBlog{})
+ revel.InterceptFunc(AuthInterceptor, revel.BEFORE, &AdminEmail{})
+ revel.InterceptFunc(AuthInterceptor, revel.BEFORE, &AdminUpgrade{})
+ revel.InterceptFunc(AuthInterceptor, revel.BEFORE, &AdminData{})
revel.OnAppStart(func() {
adminUsername, _ = revel.Config.String("adminUsername")
})
diff --git a/app/controllers/init.go b/app/controllers/init.go
index 4f47a40..cc257ed 100644
--- a/app/controllers/init.go
+++ b/app/controllers/init.go
@@ -25,6 +25,8 @@ var noteImageService *service.NoteImageService
var fileService *service.FileService
var attachService *service.AttachService
var configService *service.ConfigService
+var emailService *service.EmailService
+var sessionService *service.SessionService
var pageSize = 1000
var defaultSortField = "UpdatedTime"
@@ -47,10 +49,15 @@ var commonUrl = map[string]map[string]bool{"Index": map[string]bool{"Index": tru
"FindPasswordUpdate": true,
"Suggestion": true,
},
+ "Note": map[string]bool{"ToImage": true},
"Blog": map[string]bool{"Index": true,
"View": true,
"AboutMe": true,
- "SearchBlog": true,
+ "Cate": true,
+ "Search": true,
+ "GetLikeAndComments": true,
+ "IncReadNum": true,
+ "ListComments": true,
},
// 用户的激活与修改邮箱都不需要登录, 通过链接地址
"User": map[string]bool{"UpdateEmail": true,
@@ -118,6 +125,8 @@ func InitService() {
suggestionService = service.SuggestionS
authService = service.AuthS
configService = service.ConfigS
+ emailService = service.EmailS
+ sessionService = service.SessionS
}
func init() {
diff --git a/app/db/Mgo.go b/app/db/Mgo.go
index 66b0c7a..55c2326 100644
--- a/app/db/Mgo.go
+++ b/app/db/Mgo.go
@@ -40,6 +40,15 @@ var Attachs *mgo.Collection
var NoteImages *mgo.Collection
var Configs *mgo.Collection
+var EmailLogs *mgo.Collection
+
+// blog
+var BlogLikes *mgo.Collection
+var BlogComments *mgo.Collection
+var Reports *mgo.Collection
+
+// session
+var Sessions *mgo.Collection
// 初始化时连接数据库
func Init() {
@@ -113,12 +122,17 @@ func Init() {
NoteImages = Session.DB(dbname).C("note_images")
Configs = Session.DB(dbname).C("configs")
-}
-
-func init() {
- revel.OnAppStart(func() {
- Init()
- })
+ EmailLogs = Session.DB(dbname).C("email_logs")
+
+ // 社交
+ BlogLikes = Session.DB(dbname).C("blog_likes")
+ BlogComments = Session.DB(dbname).C("blog_comments")
+
+ // 举报
+ Reports = Session.DB(dbname).C("reports")
+
+ // session
+ Sessions = Session.DB(dbname).C("sessions")
}
func close() {
diff --git a/app/i18n/i18n.go b/app/i18n/i18n.go
index 02d8b56..8c0f77b 100644
--- a/app/i18n/i18n.go
+++ b/app/i18n/i18n.go
@@ -10,8 +10,8 @@ import (
// convert revel msg to js msg
-var msgBasePath = "/Users/life/Documents/Go/package/src/github.com/leanote/leanote/messages/"
-var targetBasePath = "/Users/life/Documents/Go/package/src/github.com/leanote/leanote/public/js/i18n/"
+var msgBasePath = "/Users/life/Documents/Go/package1/src/github.com/leanote/leanote/messages/"
+var targetBasePath = "/Users/life/Documents/Go/package1/src/github.com/leanote/leanote/public/js/i18n/"
func parse(filename string) {
file, err := os.Open(msgBasePath + filename)
reader := bufio.NewReader(file)
@@ -62,11 +62,28 @@ func parse(filename string) {
if err2 != nil {
file2, err2 = os.Create(targetName)
}
- file2.WriteString("var MSG = " + str + ";")
+ file2.WriteString("var MSG = " + str + ";" + `
+function getMsg(key, data) {
+ var msg = MSG[key]
+ if(msg) {
+ if(data) {
+ if(!isArray(data)) {
+ data = [data];
+ }
+ for(var i = 0; i < data.length; ++i) {
+ msg = msg.replace("%s", data[i]);
+ }
+ }
+ return msg;
+ }
+ return key;
+}`)
}
// 生成js的i18n文件
func main() {
parse("msg.en")
parse("msg.zh")
+ parse("blog.zh")
+ parse("blog.en")
}
diff --git a/app/info/BlogInfo.go b/app/info/BlogInfo.go
index fe5af1d..976c24f 100644
--- a/app/info/BlogInfo.go
+++ b/app/info/BlogInfo.go
@@ -2,6 +2,7 @@ package info
import (
"gopkg.in/mgo.v2/bson"
+ "time"
)
// 只为blog, 不为note
@@ -10,35 +11,76 @@ type BlogItem struct {
Note
Content string // 可能是content的一部分, 截取. 点击more后就是整个信息了
HasMore bool // 是否是否还有
- User User // 用户信息
+ User User // 用户信息
}
type UserBlogBase struct {
- Logo string `Logo`
- Title string `Title` // 标题
- SubTitle string `SubTitle` // 副标题
- AboutMe string `AboutMe` // 关于我
+ Logo string `Logo`
+ Title string `Title` // 标题
+ SubTitle string `SubTitle` // 副标题
+ AboutMe string `AboutMe` // 关于我
}
type UserBlogComment struct {
- CanComment bool `CanComment` // 是否可以评论
- DisqusId string `DisqusId`
+ CanComment bool `CanComment` // 是否可以评论
+ CommentType string `CommentType` // default 或 disqus
+ DisqusId string `DisqusId`
}
type UserBlogStyle struct {
- Style string `Style` // 风格
+ Style string `Style` // 风格
+ Css string `Css` // 自定义css
}
// 每个用户一份博客设置信息
type UserBlog struct {
- UserId bson.ObjectId `bson:"_id"` // 谁的
- Logo string `Logo`
- Title string `Title` // 标题
- SubTitle string `SubTitle` // 副标题
- AboutMe string `AboutMe` // 关于我
+ UserId bson.ObjectId `bson:"_id"` // 谁的
+ Logo string `Logo`
+ Title string `Title` // 标题
+ SubTitle string `SubTitle` // 副标题
+ AboutMe string `AboutMe` // 关于我
+
+ CanComment bool `CanComment` // 是否可以评论
- CanComment bool `CanComment` // 是否可以评论
- DisqusId string `DisqusId`
-
- Style string `Style` // 风格
-}
\ No newline at end of file
+ CommentType string `CommentType` // default 或 disqus
+ DisqusId string `DisqusId`
+
+ Style string `Style` // 风格
+ Css string `Css` // 自定义css
+
+ SubDomain string `SubDomain` // 二级域名
+ Domain string `Domain` // 自定义域名
+}
+
+//------------------------
+// 社交功能, 点赞, 分享, 评论
+
+// 点赞记录
+type BlogLike struct {
+ LikeId bson.ObjectId `bson:"_id"`
+ NoteId bson.ObjectId `NoteId`
+ UserId bson.ObjectId `UserId`
+ CreatedTime time.Time `CreatedTime`
+}
+
+// 评论
+type BlogComment struct {
+ CommentId bson.ObjectId `bson:"_id"`
+ NoteId bson.ObjectId `NoteId`
+
+ UserId bson.ObjectId `UserId` // UserId回复ToUserId
+ Content string `Content` // 评论内容
+
+ ToCommentId bson.ObjectId `ToCommendId,omitempty` // 对某条评论进行回复
+ ToUserId bson.ObjectId `ToUserId,omitempty` // 为空表示直接评论, 不回空表示回复某人
+
+ LikeNum int `LikeNum` // 点赞次数, 评论也可以点赞
+ LikeUserIds []string `LikeUserIds` // 点赞的用户ids
+
+ CreatedTime time.Time `CreatedTime`
+}
+
+type BlogCommentPublic struct {
+ BlogComment
+ IsILikeIt bool
+}
diff --git a/app/info/Configinfo.go b/app/info/Configinfo.go
index c318e13..1fbecd5 100644
--- a/app/info/Configinfo.go
+++ b/app/info/Configinfo.go
@@ -5,11 +5,21 @@ import (
"time"
)
-// 配置
-// 用户配置高于全局配置
+// 配置, 每一个配置一行记录
type Config struct {
- UserId bson.ObjectId `bson:"_id"`
- StringConfigs map[string]string `StringConfigs` // key => value
- ArrayConfigs map[string][]string `ArrayConfigs` // key => []value
- UpdatedTime time.Time `UpdatedTime`
+ ConfigId bson.ObjectId `bson:"_id"`
+ UserId bson.ObjectId `UserId`
+ Key string `Key`
+ ValueStr string `ValueStr,omitempty` // "1"
+ ValueArr []string `ValueArr,omitempty` // ["1","b","c"]
+ ValueMap map[string]string `ValueMap,omitempty` // {"a":"bb", "CC":"xx"}
+ ValueArrMap []map[string]string `ValueArrMap,omitempty` // [{"a":"B"}, {}, {}]
+ IsArr bool `IsArr` // 是否是数组
+ IsMap bool `IsMap` // 是否是Map
+ IsArrMap bool `IsArrMap` // 是否是数组Map
+
+ // StringConfigs map[string]string `StringConfigs` // key => value
+ // ArrayConfigs map[string][]string `ArrayConfigs` // key => []value
+
+ UpdatedTime time.Time `UpdatedTime`
}
diff --git a/app/info/EmailLogInfo.go b/app/info/EmailLogInfo.go
new file mode 100644
index 0000000..e0e98dd
--- /dev/null
+++ b/app/info/EmailLogInfo.go
@@ -0,0 +1,19 @@
+package info
+
+import (
+ "gopkg.in/mgo.v2/bson"
+ "time"
+)
+
+// 发送邮件
+type EmailLog struct {
+ LogId bson.ObjectId `bson:"_id"`
+
+ Email string `Email` // 发送者
+ Subject string `Subject` // 主题
+ Body string `Body` // 内容
+ Msg string `Msg` // 发送失败信息
+ Ok bool `Ok` // 发送是否成功
+
+ CreatedTime time.Time `CreatedTime`
+}
diff --git a/app/info/NoteInfo.go b/app/info/NoteInfo.go
index e342cc1..e8560e0 100644
--- a/app/info/NoteInfo.go
+++ b/app/info/NoteInfo.go
@@ -15,21 +15,28 @@ type Note struct {
Title string `Title` // 标题
Desc string `Desc` // 描述, 非html
- ImgSrc string `ImgSrc` // 图片, 第一张缩略图地址
- Tags []string `Tags,omitempty`
-
- IsTrash bool `IsTrash` // 是否是trash, 默认是false
+ ImgSrc string `ImgSrc` // 图片, 第一张缩略图地址
+ Tags []string `Tags,omitempty`
- IsBlog bool `IsBlog,omitempty` // 是否设置成了blog 2013/12/29 新加
+ IsTrash bool `IsTrash` // 是否是trash, 默认是false
+
+ IsBlog bool `IsBlog,omitempty` // 是否设置成了blog 2013/12/29 新加
IsRecommend bool `IsRecommend,omitempty` // 是否为推荐博客 2014/9/24新加
- IsTop bool `IsTop,omitempty` // blog是否置顶
+ IsTop bool `IsTop,omitempty` // blog是否置顶
+
+ // 2014/9/28 添加评论社交功能
+ ReadNum int `ReadNum,omitempty` // 阅读次数 2014/9/28
+ LikeNum int `LikeNum,omitempty` // 点赞次数 2014/9/28
+ CommentNum int `CommentNum,omitempty` // 评论次数 2014/9/28
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`
UpdatedTime time.Time `UpdatedTime`
+ RecommendTime time.Time `RecommendTime,omitempty` // 推荐时间
+ PublicTime time.Time `PublicTime,omitempty` // 发表时间, 公开为博客则设置
UpdatedUserId bson.ObjectId `bson:"UpdatedUserId"` // 如果共享了, 并可写, 那么可能是其它他修改了
}
diff --git a/app/info/ReportInfo.go b/app/info/ReportInfo.go
new file mode 100644
index 0000000..c1e738f
--- /dev/null
+++ b/app/info/ReportInfo.go
@@ -0,0 +1,19 @@
+package info
+
+import (
+ "gopkg.in/mgo.v2/bson"
+ "time"
+)
+
+// 举报
+type Report struct {
+ ReportId bson.ObjectId `bson:"_id"`
+ NoteId bson.ObjectId `NoteId`
+
+ UserId bson.ObjectId `UserId` // UserId回复ToUserId
+ Reason string `Reason` // 评论内容
+
+ CommentId bson.ObjectId `CommendId,omitempty` // 对某条评论进行回复
+
+ CreatedTime time.Time `CreatedTime`
+}
diff --git a/app/info/SessionInfo.go b/app/info/SessionInfo.go
new file mode 100644
index 0000000..a724626
--- /dev/null
+++ b/app/info/SessionInfo.go
@@ -0,0 +1,19 @@
+package info
+
+import (
+ "gopkg.in/mgo.v2/bson"
+ "time"
+)
+
+// http://docs.mongodb.org/manual/tutorial/expire-data/
+type Session struct {
+ Id bson.ObjectId `bson:"_id,omitempty"` // 没有意义
+
+ SessionId string `bson:"SessionId"` // SessionId
+
+ LoginTimes int `LoginTimes` // 登录错误时间
+ Captcha string `Captcha` // 验证码
+
+ CreatedTime time.Time `CreatedTime`
+ UpdatedTime time.Time `UpdatedTime` // 更新时间, expire这个时间会自动清空
+}
diff --git a/app/info/UserInfo.go b/app/info/UserInfo.go
index bf7ffb9..104069e 100644
--- a/app/info/UserInfo.go
+++ b/app/info/UserInfo.go
@@ -27,6 +27,7 @@ type User struct {
// 用户配置
NotebookWidth int `NotebookWidth` // 笔记本宽度
NoteListWidth int `NoteListWidth` // 笔记列表宽度
+ MdEditorWidth int `MdEditorWidth` // markdown 左侧编辑器宽度
LeftIsMin bool `LeftIsMin` // 左侧是否是隐藏的, 默认是打开的
// 这里 第三方登录
diff --git a/app/init.go b/app/init.go
index 92125ab..10e94f9 100644
--- a/app/init.go
+++ b/app/init.go
@@ -4,9 +4,13 @@ import (
"github.com/revel/revel"
. "github.com/leanote/leanote/app/lea"
"github.com/leanote/leanote/app/service"
+ "github.com/leanote/leanote/app/db"
"github.com/leanote/leanote/app/controllers"
"github.com/leanote/leanote/app/controllers/admin"
_ "github.com/leanote/leanote/app/lea/binder"
+ "github.com/leanote/leanote/app/lea/session"
+ "github.com/leanote/leanote/app/lea/memcache"
+ "github.com/leanote/leanote/app/lea/route"
"reflect"
"fmt"
"html/template"
@@ -14,20 +18,24 @@ import (
"strings"
"strconv"
"time"
+ "encoding/json"
)
func init() {
// Filters is the default set of global filters.
revel.Filters = []revel.Filter{
revel.PanicFilter, // Recover from panics and display an error page instead.
- RouterFilter,
+ route.RouterFilter,
// revel.RouterFilter, // Use the routing table to select the right Action
// AuthFilter, // Invoke the action.
revel.FilterConfiguringFilter, // A hook for adding or removing per-Action filters.
revel.ParamsFilter, // Parse parameters into Controller.Params.
- revel.SessionFilter, // Restore and write the session cookie.
+ // revel.SessionFilter, // Restore and write the session cookie.
-// session.SessionFilter, // leanote memcache session life
+ // 使用SessionFilter标准版从cookie中得到sessionID, 然后通过MssessionFilter从Memcache中得到
+ // session, 之后MSessionFilter将session只存sessionID然后返回给SessionFilter返回到web
+ session.SessionFilter, // leanote session
+ // session.MSessionFilter, // leanote memcache session
revel.FlashFilter, // Restore and write the flash cookie.
revel.ValidationFilter, // Restore kept validation errors and save new ones from cookie.
@@ -48,12 +56,34 @@ func init() {
i = i - 1;
return i
}
+ revel.TemplateFuncs["join"] = func(arr []string) template.HTML {
+ if arr == nil {
+ return template.HTML("")
+ }
+ return template.HTML(strings.Join(arr, ","))
+ }
revel.TemplateFuncs["concat"] = func(s1, s2 string) template.HTML {
return template.HTML(s1 + s2)
}
+ revel.TemplateFuncs["concatStr"] = func(strs ...string) string {
+ str := ""
+ for _, s := range strs {
+ str += s
+ }
+ return str
+ }
+ revel.TemplateFuncs["json"] = func(i interface{}) string {
+ b, _ := json.Marshal(i)
+ return string(b)
+ }
revel.TemplateFuncs["datetime"] = func(t time.Time) template.HTML {
return template.HTML(t.Format("2006-01-02 15:04:05"))
}
+ revel.TemplateFuncs["unixDatetime"] = func(unixSec string) template.HTML {
+ sec, _ := strconv.Atoi(unixSec)
+ t := time.Unix(int64(sec), 0)
+ return template.HTML(t.Format("2006-01-02 15:04:05"))
+ }
// interface是否有该字段
revel.TemplateFuncs["has"] = func(i interface{}, key string) bool {
@@ -63,6 +93,26 @@ func init() {
}
// tags
+ revel.TemplateFuncs["blogTags"] = func(renderArgs map[string]interface{}, tags []string) template.HTML {
+ if tags == nil || len(tags) == 0 {
+ return ""
+ }
+ locale, _ := renderArgs[revel.CurrentLocaleRenderArg].(string)
+ tagStr := ""
+ lenTags := len(tags)
+ for i, tag := range tags {
+ str := revel.Message(locale, tag)
+ if strings.HasPrefix(str, "???") {
+ str = tag
+ }
+ tagStr += str
+ if i != lenTags - 1 {
+ tagStr += ","
+ }
+ }
+ return template.HTML(tagStr)
+ }
+ /*
revel.TemplateFuncs["blogTags"] = func(tags []string) template.HTML {
if tags == nil || len(tags) == 0 {
return ""
@@ -83,7 +133,7 @@ func init() {
}
return template.HTML(tagStr)
}
-
+ */
revel.TemplateFuncs["li"] = func(a string) string {
Log(a)
Log("life==")
@@ -130,6 +180,15 @@ func init() {
return ""
}
+ // http://stackoverflow.com/questions/14226416/go-lang-templates-always-quotes-a-string-and-removes-comments
+ revel.TemplateFuncs["rawMsg"] = func(renderArgs map[string]interface{}, message string, args ...interface{}) template.JS {
+ str, ok := renderArgs[revel.CurrentLocaleRenderArg].(string)
+ if !ok {
+ return ""
+ }
+ return template.JS(revel.Message(str, message, args...))
+ }
+
// 为后台管理sorter th使用
// 必须要返回HTMLAttr, 返回html, golang 会执行安全检查返回ZgotmplZ
// sorterI 可能是nil, 所以用interfalce{}来接收
@@ -155,7 +214,7 @@ func init() {
}
// pagination
- revel.TemplateFuncs["page"] = func(userId, notebookId string, page, pageSize, count int) template.HTML {
+ revel.TemplateFuncs["page"] = func(urlBase string, page, pageSize, count int) template.HTML {
if count == 0 {
return "";
}
@@ -170,11 +229,6 @@ func init() {
nextPage := page + 1
var preUrl, nextUrl string
- urlBase := "/blog/" + userId
- if notebookId != "" {
- urlBase += "/" + notebookId
- }
-
preUrl = urlBase + "?page=" + strconv.Itoa(prePage)
nextUrl = urlBase + "?page=" + strconv.Itoa(nextPage)
@@ -238,8 +292,13 @@ func init() {
// init Email
revel.OnAppStart(func() {
+ // 数据库
+ db.Init()
+ // email配置
InitEmail()
-
+ InitVd()
+ memcache.InitMemcache() // session服务
+ // 其它service
service.InitService()
controllers.InitService()
admin.InitService()
diff --git a/app/lea/Email.go b/app/lea/Email.go
index 26cf001..7f5812c 100644
--- a/app/lea/Email.go
+++ b/app/lea/Email.go
@@ -22,7 +22,7 @@ func InitEmail() {
var bodyTpl = `
" + content + ""; + href := "http://"+ configService.GetBlogDomain() + "/view/" + note.NoteId.Hex() + body += "