mirror of https://github.com/mindoc-org/mindoc.git
bugfix: 1. 修复私有问题访问bug;2. 重构私有文档访问逻辑代码;3. shell生成zip包中,删除go文件。 resolves mindoc-org/mindoc#751, resolves mindoc-org/mindoc#801
parent
b4b7528e3f
commit
0b83a53b56
|
@ -14,7 +14,7 @@ go build -v -o mindoc_linux_amd64 -ldflags="-linkmode external -extldflags '-sta
|
||||||
mkdir ../mindoc_linux_amd64
|
mkdir ../mindoc_linux_amd64
|
||||||
cp -r * ../mindoc_linux_amd64
|
cp -r * ../mindoc_linux_amd64
|
||||||
cd ../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
|
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
|
zip -r mindoc_linux_amd64.zip conf static uploads views lib mindoc_linux_amd64 favicon.ico LICENSE.md
|
||||||
mv ./mindoc_linux_amd64.zip ../
|
mv ./mindoc_linux_amd64.zip ../
|
||||||
|
|
|
@ -14,7 +14,7 @@ go build -v -o mindoc_linux_musl_amd64 -ldflags="-linkmode external -extldflags
|
||||||
mkdir ../mindoc_linux_musl_amd64
|
mkdir ../mindoc_linux_musl_amd64
|
||||||
cp -r * ../mindoc_linux_musl_amd64
|
cp -r * ../mindoc_linux_musl_amd64
|
||||||
cd ../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
|
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
|
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 ../
|
mv ./mindoc_linux_musl_amd64.zip ../
|
||||||
|
|
|
@ -190,8 +190,9 @@ func (c *BaseController) ShowErrorPage(errCode int, errMsg string) {
|
||||||
c.Data["ErrorCode"] = errCode
|
c.Data["ErrorCode"] = errCode
|
||||||
|
|
||||||
var buf bytes.Buffer
|
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")
|
c.Abort("500")
|
||||||
}
|
}
|
||||||
if errCode >= 200 && errCode <= 510 {
|
if errCode >= 200 && errCode <= 510 {
|
||||||
|
|
|
@ -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() {
|
func (c *DocumentController) Read() {
|
||||||
c.Prepare()
|
c.Prepare()
|
||||||
|
@ -1258,47 +1293,57 @@ func (c *DocumentController) isReadable(identify, token string) *models.BookResu
|
||||||
bookResult.RoleId = roleId
|
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) {
|
* token设置情况
|
||||||
c.SetSession(identify, token)
|
* 已设置:可以通过token访问
|
||||||
} else if token, ok := c.GetSession(identify).(string); !ok || !strings.EqualFold(token, book.PrivateToken) {
|
* 未设置:不可以通过token访问
|
||||||
logs.Info("尝试访问文档但权限不足 ->", identify, token)
|
* password设置情况
|
||||||
c.ShowErrorPage(403, i18n.Tr(c.Lang, "message.no_permission"))
|
* 已设置:可以通过password访问
|
||||||
}
|
* 未设置:不可以通过password访问
|
||||||
} else if password := c.GetString("bPassword", ""); !isOk && book.BookPassword != "" && 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
|
||||||
|
}
|
||||||
|
|
||||||
//如果设置了密码,则判断密码是否正确
|
// Use session in preference.
|
||||||
if book.BookPassword != password {
|
if tokenOrPassword, ok := c.GetSession(identify).(string); ok {
|
||||||
c.JsonResult(5001, i18n.Tr(c.Lang, "message.wrong_password"))
|
if strings.EqualFold(book.PrivateToken, tokenOrPassword) || strings.EqualFold(book.BookPassword, tokenOrPassword) {
|
||||||
} else {
|
return bookResult
|
||||||
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"))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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
|
return bookResult
|
||||||
|
|
|
@ -11,6 +11,7 @@ import (
|
||||||
"github.com/beego/beego/v2/core/logs"
|
"github.com/beego/beego/v2/core/logs"
|
||||||
"github.com/beego/beego/v2/server/web"
|
"github.com/beego/beego/v2/server/web"
|
||||||
"github.com/beego/beego/v2/server/web/context"
|
"github.com/beego/beego/v2/server/web/context"
|
||||||
|
|
||||||
// "github.com/mindoc-org/mindoc/conf"
|
// "github.com/mindoc-org/mindoc/conf"
|
||||||
"github.com/mindoc-org/mindoc/controllers"
|
"github.com/mindoc-org/mindoc/controllers"
|
||||||
)
|
)
|
||||||
|
@ -243,6 +244,7 @@ func init() {
|
||||||
web.Router("/history/restore", &controllers.DocumentController{}, "*:RestoreHistory")
|
web.Router("/history/restore", &controllers.DocumentController{}, "*:RestoreHistory")
|
||||||
|
|
||||||
web.Router("/docs/:key", &controllers.DocumentController{}, "*:Index")
|
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/:id", &controllers.DocumentController{}, "*:Read")
|
||||||
web.Router("/docs/:key/search", &controllers.DocumentController{}, "post:Search")
|
web.Router("/docs/:key/search", &controllers.DocumentController{}, "post:Search")
|
||||||
web.Router("/export/:key", &controllers.DocumentController{}, "*:Export")
|
web.Router("/export/:key", &controllers.DocumentController{}, "*:Export")
|
||||||
|
|
|
@ -100,7 +100,7 @@
|
||||||
<body>
|
<body>
|
||||||
<div class="auth_form">
|
<div class="auth_form">
|
||||||
<div class="shell">
|
<div class="shell">
|
||||||
<form action="{{urlfor "DocumentController.Index" ":key" .Identify}}" method="post" id="auth_form">
|
<form action="{{urlfor "DocumentController.CheckPassword" ":key" .Identify}}" method="post" id="auth_form">
|
||||||
<div class="tit">{{i18n .Lang "doc.input_pwd"}}</div>
|
<div class="tit">{{i18n .Lang "doc.input_pwd"}}</div>
|
||||||
<div style="margin-top: 10px;">
|
<div style="margin-top: 10px;">
|
||||||
<input type="password" name="bPassword" placeholder="{{i18n .Lang "doc.read_pwd"}}" class="inp"/>
|
<input type="password" name="bPassword" placeholder="{{i18n .Lang "doc.read_pwd"}}" class="inp"/>
|
||||||
|
|
Loading…
Reference in New Issue