Преглед на файлове

bugfix: 1. 修复私有问题访问bug;2. 重构私有文档访问逻辑代码;3. shell生成zip包中,删除go文件。 resolves mindoc-org/mindoc#751, resolves mindoc-org/mindoc#801

Go-Go-Farther преди 3 години
родител
ревизия
0b83a53b56
променени са 6 файла, в които са добавени 90 реда и са изтрити 42 реда
  1. 1 1
      build_amd64.sh
  2. 1 1
      build_musl_amd64.sh
  3. 2 1
      controllers/BaseController.go
  4. 83 38
      controllers/DocumentController.go
  5. 2 0
      routers/router.go
  6. 1 1
      views/document/document_password.tpl

+ 1 - 1
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 ../

+ 1 - 1
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 ../

+ 2 - 1
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 {

+ 83 - 38
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,46 +1293,56 @@ 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 != "" {
-
-				//如果设置了密码,则判断密码是否正确
-				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"))
-				}
+	/* 	私有项目:
+	 *   管理员可以直接访问
+	 *   参与者可以直接访问
+	 *   其他用户(支持匿名访问)
+	 *   	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
+		}
+
+		// 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"))
 		}
 	}
 

+ 2 - 0
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")

+ 1 - 1
views/document/document_password.tpl

@@ -100,7 +100,7 @@
 <body>
 <div class="auth_form">
 <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 style="margin-top: 10px;">
                 <input type="password" name="bPassword" placeholder="{{i18n .Lang "doc.read_pwd"}}" class="inp"/>