diff --git a/build_amd64.sh b/build_amd64.sh index 6d2f6239..eaf64a5b 100644 --- a/build_amd64.sh +++ b/build_amd64.sh @@ -14,7 +14,7 @@ go build -v -o mindoc_linux_amd64 -ldflags="-linkmode external -extldflags '-sta mkdir ../mindoc_linux_amd64 cp -r * ../mindoc_linux_amd64 cd ../mindoc_linux_amd64 -rm -rf cache commands controllers converter .git .github graphics mail models routers utils runtime +rm -rf cache commands controllers converter .git .github graphics mail models routers utils runtime conf/*.go rm appveyor.yml docker-compose.yml Dockerfile .travis.yml .gitattributes .gitignore go.mod go.sum main.go README.md simsun.ttc start.sh sync_host.sh build_amd64.sh build_musl_amd64.sh zip -r mindoc_linux_amd64.zip conf static uploads views lib mindoc_linux_amd64 favicon.ico LICENSE.md mv ./mindoc_linux_amd64.zip ../ diff --git a/build_musl_amd64.sh b/build_musl_amd64.sh index c7f9441e..51c8ca93 100644 --- a/build_musl_amd64.sh +++ b/build_musl_amd64.sh @@ -14,7 +14,7 @@ go build -v -o mindoc_linux_musl_amd64 -ldflags="-linkmode external -extldflags mkdir ../mindoc_linux_musl_amd64 cp -r * ../mindoc_linux_musl_amd64 cd ../mindoc_linux_musl_amd64 -rm -rf cache commands controllers converter .git .github graphics mail models routers utils runtime +rm -rf cache commands controllers converter .git .github graphics mail models routers utils runtime conf/*.go rm appveyor.yml docker-compose.yml Dockerfile .travis.yml .gitattributes .gitignore go.mod go.sum main.go README.md simsun.ttc start.sh sync_host.sh build_amd64.sh build_musl_amd64.sh zip -r mindoc_linux_musl_amd64.zip conf static uploads views lib mindoc_linux_musl_amd64 favicon.ico LICENSE.md mv ./mindoc_linux_musl_amd64.zip ../ diff --git a/controllers/BaseController.go b/controllers/BaseController.go index 7e2a5571..4d7d27dc 100644 --- a/controllers/BaseController.go +++ b/controllers/BaseController.go @@ -190,8 +190,9 @@ func (c *BaseController) ShowErrorPage(errCode int, errMsg string) { c.Data["ErrorCode"] = errCode var buf bytes.Buffer + exeData := map[string]interface{}{"ErrorMessage": errMsg, "ErrorCode": errCode, "BaseUrl": conf.BaseUrl, "Lang": c.Lang} - if err := web.ExecuteViewPathTemplate(&buf, "errors/error.tpl", web.BConfig.WebConfig.ViewsPath, map[string]interface{}{"ErrorMessage": errMsg, "ErrorCode": errCode, "BaseUrl": conf.BaseUrl}); err != nil { + if err := web.ExecuteViewPathTemplate(&buf, "errors/error.tpl", web.BConfig.WebConfig.ViewsPath, exeData); err != nil { c.Abort("500") } if errCode >= 200 && errCode <= 510 { diff --git a/controllers/DocumentController.go b/controllers/DocumentController.go index c9e341a0..7a99a833 100644 --- a/controllers/DocumentController.go +++ b/controllers/DocumentController.go @@ -96,6 +96,41 @@ func (c *DocumentController) Index() { } +// CheckPassword : Handles password verification for private documents, +// and front-end requests are made through Ajax. +func (c *DocumentController) CheckPassword() { + c.Prepare() + + identify := c.Ctx.Input.Param(":key") + password := c.GetString("bPassword") + + if identify == "" || password == "" { + c.JsonResult(http.StatusBadRequest, i18n.Tr(c.Lang, "message.param_error")) + } + + // You have not logged in and need to log in again. + if !c.EnableAnonymous && !c.isUserLoggedIn() { + logs.Info("You have not logged in and need to log in again(SessionId: %s).", + c.CruSession.SessionID(context.TODO())) + c.JsonResult(6000, i18n.Tr(c.Lang, "message.need_relogin")) + return + } + + book, err := models.NewBook().FindByFieldFirst("identify", identify) + + if err != nil { + logs.Error(err) + c.JsonResult(500, i18n.Tr(c.Lang, "message.item_not_exist")) + } + + if book.BookPassword != password { + c.JsonResult(5001, i18n.Tr(c.Lang, "message.wrong_password")) + } else { + c.SetSession(identify, password) + c.JsonResult(0, "OK") + } +} + // 阅读文档 func (c *DocumentController) Read() { c.Prepare() @@ -1258,47 +1293,57 @@ func (c *DocumentController) isReadable(identify, token string) *models.BookResu bookResult.RoleId = roleId } } - // 如果文档是私有的 - if book.PrivatelyOwned == 1 && (!c.isUserLoggedIn() || !c.Member.IsAdministrator()) { - if s, ok := c.GetSession(identify).(string); !ok || (!strings.EqualFold(s, book.PrivateToken) && !strings.EqualFold(s, book.BookPassword)) { - if book.PrivateToken != "" && !isOk && token != "" { - // 如果有访问的 Token,并且该项目设置了访问 Token,并且和用户提供的相匹配,则记录到 Session 中。 - // 如果用户未提供 Token 且用户登录了,则判断用户是否参与了该项目。 - // 如果用户未登录,则从 Session 中读取 Token。 - if token != "" && strings.EqualFold(token, book.PrivateToken) { - c.SetSession(identify, token) - } else if token, ok := c.GetSession(identify).(string); !ok || !strings.EqualFold(token, book.PrivateToken) { - logs.Info("尝试访问文档但权限不足 ->", identify, token) - c.ShowErrorPage(403, i18n.Tr(c.Lang, "message.no_permission")) - } - } else if password := c.GetString("bPassword", ""); !isOk && book.BookPassword != "" && password != "" { + /* 私有项目: + * 管理员可以直接访问 + * 参与者可以直接访问 + * 其他用户(支持匿名访问) + * token设置情况 + * 已设置:可以通过token访问 + * 未设置:不可以通过token访问 + * password设置情况 + * 已设置:可以通过password访问 + * 未设置:不可以通过password访问 + * 注意: + * 1. 第一次访问需要存session + * 2. 有session优先使用session中的token或者password,再使用携带的token或者password + * 3. 私有项目如果token和password都没有设置,则除管理员和参与者的其他用户不可以访问 + * 4. 使用token访问如果不通过,则提示输入密码 + */ + if book.PrivatelyOwned == 1 { + if c.isUserLoggedIn() && c.Member.IsAdministrator() { + return bookResult + } + if isOk { // Project participant. + return bookResult + } - //如果设置了密码,则判断密码是否正确 - if book.BookPassword != password { - c.JsonResult(5001, i18n.Tr(c.Lang, "message.wrong_password")) - } else { - c.SetSession(identify, password) - c.JsonResult(0, "OK") - } - - } else if !isOk { - //如果设置了密码,则显示密码输入页面 - if book.BookPassword != "" { - //判断已存在的密码是否正确 - if password, ok := c.GetSession(identify).(string); !ok || !strings.EqualFold(password, book.BookPassword) { - body, err := c.ExecuteViewPathTemplate("document/document_password.tpl", map[string]string{"Identify": book.Identify}) - if err != nil { - logs.Error("显示密码页面失败 ->", err) - } - c.CustomAbort(200, body) - } - } else { - logs.Info("尝试访问文档但权限不足 ->", identify, token) - c.ShowErrorPage(403, i18n.Tr(c.Lang, "message.no_permission")) - } + // Use session in preference. + if tokenOrPassword, ok := c.GetSession(identify).(string); ok { + if strings.EqualFold(book.PrivateToken, tokenOrPassword) || strings.EqualFold(book.BookPassword, tokenOrPassword) { + return bookResult } } + + // Next: Session not exist or not correct. + if book.PrivateToken != "" && book.PrivateToken == token { + c.SetSession(identify, token) + return bookResult + } else if book.BookPassword != "" { + // Send a page for inputting password. + // For verification, see function DocumentController.CheckPassword + body, err := c.ExecuteViewPathTemplate("document/document_password.tpl", + map[string]string{"Identify": book.Identify, "Lang": c.Lang}) + if err != nil { + logs.Error("显示密码页面失败 ->", err) + c.ShowErrorPage(500, i18n.Tr(c.Lang, "message.system_error")) + } + c.CustomAbort(200, body) + } else { + // No permission to access this book. + logs.Info("尝试访问文档但权限不足 ->", identify, token) + c.ShowErrorPage(403, i18n.Tr(c.Lang, "message.no_permission")) + } } return bookResult diff --git a/routers/router.go b/routers/router.go index c0e9d5a4..f30c8593 100644 --- a/routers/router.go +++ b/routers/router.go @@ -11,6 +11,7 @@ import ( "github.com/beego/beego/v2/core/logs" "github.com/beego/beego/v2/server/web" "github.com/beego/beego/v2/server/web/context" + // "github.com/mindoc-org/mindoc/conf" "github.com/mindoc-org/mindoc/controllers" ) @@ -243,6 +244,7 @@ func init() { web.Router("/history/restore", &controllers.DocumentController{}, "*:RestoreHistory") web.Router("/docs/:key", &controllers.DocumentController{}, "*:Index") + web.Router("/docs/:key/check-password", &controllers.DocumentController{}, "post:CheckPassword") web.Router("/docs/:key/:id", &controllers.DocumentController{}, "*:Read") web.Router("/docs/:key/search", &controllers.DocumentController{}, "post:Search") web.Router("/export/:key", &controllers.DocumentController{}, "*:Export") diff --git a/views/document/document_password.tpl b/views/document/document_password.tpl index efa698dd..e46d4af4 100644 --- a/views/document/document_password.tpl +++ b/views/document/document_password.tpl @@ -100,7 +100,7 @@
-
+
{{i18n .Lang "doc.input_pwd"}}