mirror of
https://github.com/documize/community.git
synced 2025-07-19 13:19:43 +02:00
bug fixes galore
This commit is contained in:
parent
62b7b149c1
commit
557da2847e
13 changed files with 148 additions and 67 deletions
|
@ -92,7 +92,7 @@ func Check(runtime *env.Runtime) bool {
|
|||
}
|
||||
|
||||
{ // check the MySQL character set and collation
|
||||
if charset != "utf8" {
|
||||
if charset != "utf8" && charset != "utf8mb4" {
|
||||
runtime.Log.Error("MySQL character set not utf8:", errors.New(charset))
|
||||
web.SiteInfo.Issue = "MySQL character set not utf8: " + charset
|
||||
runtime.Flags.SiteMode = env.SiteModeBadDB
|
||||
|
|
40
core/database/readme.md
Normal file
40
core/database/readme.md
Normal file
|
@ -0,0 +1,40 @@
|
|||
|
||||
## TODO
|
||||
|
||||
1. Remove audit table
|
||||
2. Remove document.layout field
|
||||
|
||||
|
||||
## MYSQL
|
||||
|
||||
https://stackoverflow.com/questions/37307146/difference-between-utf8mb4-unicode-ci-and-utf8mb4-unicode-520-ci-collations-in-m
|
||||
|
||||
https://mathiasbynens.be/notes/mysql-utf8mb4
|
||||
|
||||
https://medium.com/@adamhooper/in-mysql-never-use-utf8-use-utf8mb4-11761243e434
|
||||
|
||||
ALTER DATABASE documize CHARACTER SET utf8mb4 COLLATE utf8mb4_bin;
|
||||
|
||||
ALTER TABLE account CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_bin;
|
||||
ALTER TABLE attachment CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_bin;
|
||||
ALTER TABLE block CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_bin;
|
||||
ALTER TABLE config CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_bin;
|
||||
ALTER TABLE document CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_bin;
|
||||
ALTER TABLE feedback CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_bin;
|
||||
ALTER TABLE label CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_bin;
|
||||
ALTER TABLE labelrole CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_bin;
|
||||
ALTER TABLE link CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_bin;
|
||||
ALTER TABLE organization CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_bin;
|
||||
ALTER TABLE page CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_bin;
|
||||
ALTER TABLE pagemeta CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_bin;
|
||||
ALTER TABLE participant CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_bin;
|
||||
ALTER TABLE pin CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_bin;
|
||||
ALTER TABLE revision CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_bin;
|
||||
ALTER TABLE search CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_bin;
|
||||
ALTER TABLE share CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_bin;
|
||||
ALTER TABLE user CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_bin;
|
||||
ALTER TABLE useraction CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_bin;
|
||||
ALTER TABLE useractivity CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_bin;
|
||||
ALTER TABLE userconfig CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_bin;
|
||||
ALTER TABLE userevent CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_bin;
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
TODO
|
||||
-----
|
||||
|
||||
1. Remove audit table
|
||||
2. Remove document.layout field
|
|
@ -44,7 +44,6 @@ type RequestContext struct {
|
|||
//GetAppURL returns full HTTP url for the app
|
||||
func (c *RequestContext) GetAppURL(endpoint string) string {
|
||||
scheme := "http://"
|
||||
|
||||
if c.SSL {
|
||||
scheme = "https://"
|
||||
}
|
||||
|
@ -58,17 +57,12 @@ type key string
|
|||
const DocumizeContextKey key = "documize context key"
|
||||
|
||||
// GetRequestContext returns RequestContext from context.Context
|
||||
func GetRequestContext(r *http.Request) RequestContext {
|
||||
return r.Context().Value(DocumizeContextKey).(RequestContext)
|
||||
func GetRequestContext(r *http.Request) (ctx RequestContext) {
|
||||
c := r.Context()
|
||||
if c != nil && c.Value(DocumizeContextKey) != nil {
|
||||
ctx = c.Value(DocumizeContextKey).(RequestContext)
|
||||
return
|
||||
}
|
||||
|
||||
return RequestContext{}
|
||||
}
|
||||
|
||||
// // Scope provides data persistence methods with runtime and request context.
|
||||
// type Scope struct {
|
||||
// Runtime *env.Runtime
|
||||
// Context RequestContext
|
||||
// }
|
||||
|
||||
// // NewScope returns request scoped user context and store context for persistence logic.
|
||||
// func NewScope(rt *env.Runtime, r *http.Request) Scope {
|
||||
// return Scope{Runtime: rt, Context: GetRequestContext(r)}
|
||||
// }
|
||||
|
|
|
@ -278,7 +278,7 @@ func (s Scope) Documents(ctx domain.RequestContext, keywords string) (results []
|
|||
keywords = strings.Replace(keywords, " ", "", -1)
|
||||
}
|
||||
|
||||
keywords = strings.TrimSpace(keywords)
|
||||
keywords = strings.ToLower(strings.TrimSpace(keywords))
|
||||
|
||||
if len(keywords) > 0 {
|
||||
keywordQuery = "AND MATCH(pagetitle,body) AGAINST('" + keywords + "' in boolean mode)"
|
||||
|
|
|
@ -65,15 +65,15 @@ func (h *Handler) Add(w http.ResponseWriter, r *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
var space = space.Space{}
|
||||
err = json.Unmarshal(body, &space)
|
||||
var sp = space.Space{}
|
||||
err = json.Unmarshal(body, &sp)
|
||||
if err != nil {
|
||||
response.WriteServerError(w, method, err)
|
||||
h.Runtime.Log.Error(method, err)
|
||||
return
|
||||
}
|
||||
|
||||
if len(space.Name) == 0 {
|
||||
if len(sp.Name) == 0 {
|
||||
response.WriteMissingDataError(w, method, "name")
|
||||
return
|
||||
}
|
||||
|
@ -85,10 +85,12 @@ func (h *Handler) Add(w http.ResponseWriter, r *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
space.RefID = uniqueid.Generate()
|
||||
space.OrgID = ctx.OrgID
|
||||
sp.RefID = uniqueid.Generate()
|
||||
sp.OrgID = ctx.OrgID
|
||||
sp.Type = space.ScopePrivate
|
||||
sp.UserID = ctx.UserID
|
||||
|
||||
err = h.Store.Space.Add(ctx, space)
|
||||
err = h.Store.Space.Add(ctx, sp)
|
||||
if err != nil {
|
||||
ctx.Transaction.Rollback()
|
||||
response.WriteServerError(w, method, err)
|
||||
|
@ -96,13 +98,29 @@ func (h *Handler) Add(w http.ResponseWriter, r *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
h.Store.Audit.Record(ctx, audit.EventTypeSpaceAdd)
|
||||
role := space.Role{}
|
||||
role.LabelID = sp.RefID
|
||||
role.OrgID = sp.OrgID
|
||||
role.UserID = ctx.UserID
|
||||
role.CanEdit = true
|
||||
role.CanView = true
|
||||
role.RefID = uniqueid.Generate()
|
||||
|
||||
err = h.Store.Space.AddRole(ctx, role)
|
||||
if err != nil {
|
||||
ctx.Transaction.Rollback()
|
||||
response.WriteServerError(w, method, err)
|
||||
h.Runtime.Log.Error(method, err)
|
||||
return
|
||||
}
|
||||
|
||||
ctx.Transaction.Commit()
|
||||
|
||||
space, _ = h.Store.Space.Get(ctx, space.RefID)
|
||||
h.Store.Audit.Record(ctx, audit.EventTypeSpaceAdd)
|
||||
|
||||
response.WriteJSON(w, space)
|
||||
sp, _ = h.Store.Space.Get(ctx, sp.RefID)
|
||||
|
||||
response.WriteJSON(w, sp)
|
||||
}
|
||||
|
||||
// Get returns the requested space.
|
||||
|
|
|
@ -72,7 +72,7 @@ func (s Scope) Get(ctx domain.RequestContext, id string) (sp space.Space, err er
|
|||
return
|
||||
}
|
||||
|
||||
// PublicSpaces returns folders that anyone can see.
|
||||
// PublicSpaces returns spaces that anyone can see.
|
||||
func (s Scope) PublicSpaces(ctx domain.RequestContext, orgID string) (sp []space.Space, err error) {
|
||||
sql := "SELECT id,refid,label as name,orgid,userid,type,created,revised FROM label a where orgid=? AND type=1"
|
||||
|
||||
|
@ -86,18 +86,18 @@ func (s Scope) PublicSpaces(ctx domain.RequestContext, orgID string) (sp []space
|
|||
return
|
||||
}
|
||||
|
||||
// GetAll returns folders that the user can see.
|
||||
// Also handles which folders can be seen by anonymous users.
|
||||
// GetAll returns spaces that the user can see.
|
||||
// Also handles which spaces can be seen by anonymous users.
|
||||
func (s Scope) GetAll(ctx domain.RequestContext) (sp []space.Space, err error) {
|
||||
sql := `
|
||||
(SELECT id,refid,label as name,orgid,userid,type,created,revised from label WHERE orgid=? AND type=2 AND userid=?)
|
||||
UNION ALL
|
||||
(SELECT id,refid,label as name,orgid,userid,type,created,revised FROM label a where orgid=? AND type=1 AND refid in
|
||||
(SELECT id,refid,label as name,orgid,userid,type,created,revised from label WHERE orgid=? AND type=2 AND userid=?)
|
||||
UNION ALL
|
||||
(SELECT id,refid,label as name,orgid,userid,type,created,revised FROM label a where orgid=? AND type=1 AND refid in
|
||||
(SELECT labelid from labelrole WHERE orgid=? AND userid='' AND (canedit=1 OR canview=1)))
|
||||
UNION ALL
|
||||
(SELECT id,refid,label as name,orgid,userid,type,created,revised FROM label a where orgid=? AND type=3 AND refid in
|
||||
UNION ALL
|
||||
(SELECT id,refid,label as name,orgid,userid,type,created,revised FROM label a where orgid=? AND type=3 AND refid in
|
||||
(SELECT labelid from labelrole WHERE orgid=? AND userid=? AND (canedit=1 OR canview=1)))
|
||||
ORDER BY name`
|
||||
ORDER BY name`
|
||||
|
||||
err = s.Runtime.Db.Select(&sp, sql,
|
||||
ctx.OrgID,
|
||||
|
@ -156,22 +156,22 @@ func (s Scope) ChangeOwner(ctx domain.RequestContext, currentOwner, newOwner str
|
|||
return
|
||||
}
|
||||
|
||||
// Viewers returns the list of people who can see shared folders.
|
||||
// Viewers returns the list of people who can see shared spaces.
|
||||
func (s Scope) Viewers(ctx domain.RequestContext) (v []space.Viewer, err error) {
|
||||
sql := `
|
||||
SELECT a.userid,
|
||||
SELECT a.userid,
|
||||
COALESCE(u.firstname, '') as firstname,
|
||||
COALESCE(u.lastname, '') as lastname,
|
||||
COALESCE(u.email, '') as email,
|
||||
a.labelid,
|
||||
b.label as name,
|
||||
b.type
|
||||
FROM labelrole a
|
||||
LEFT JOIN label b ON b.refid=a.labelid
|
||||
LEFT JOIN user u ON u.refid=a.userid
|
||||
WHERE a.orgid=? AND b.type != 2
|
||||
GROUP BY a.labelid,a.userid
|
||||
ORDER BY u.firstname,u.lastname`
|
||||
FROM labelrole a
|
||||
LEFT JOIN label b ON b.refid=a.labelid
|
||||
LEFT JOIN user u ON u.refid=a.userid
|
||||
WHERE a.orgid=? AND b.type != 2
|
||||
GROUP BY a.labelid,a.userid
|
||||
ORDER BY u.firstname,u.lastname`
|
||||
|
||||
err = s.Runtime.Db.Select(&v, sql, ctx.OrgID)
|
||||
|
||||
|
|
|
@ -84,7 +84,7 @@ func InitRuntime(r *env.Runtime, s *domain.Store) bool {
|
|||
}
|
||||
|
||||
var stdParams = map[string]string{
|
||||
"charset": "utf8",
|
||||
"charset": "utf8mb4",
|
||||
"parseTime": "True",
|
||||
"maxAllowedPacket": "4194304", // 4194304 // 16777216 = 16MB
|
||||
}
|
||||
|
|
|
@ -13,8 +13,11 @@
|
|||
package logging
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"runtime"
|
||||
|
||||
"github.com/documize/community/core/env"
|
||||
"github.com/jmoiron/sqlx"
|
||||
|
@ -35,6 +38,14 @@ func (l Logger) Info(message string) {
|
|||
func (l Logger) Error(message string, err error) {
|
||||
l.log.Println(message)
|
||||
l.log.Println(err)
|
||||
|
||||
stack := make([]byte, 4096)
|
||||
runtime.Stack(stack, false)
|
||||
if idx := bytes.IndexByte(stack, 0); idx > 0 && idx < len(stack) {
|
||||
stack = stack[:idx] // remove trailing nulls from stack dump
|
||||
}
|
||||
|
||||
l.log.Println(fmt.Sprintf("%s", stack))
|
||||
}
|
||||
|
||||
// SetDB associates database connection with given logger.
|
||||
|
|
|
@ -82,7 +82,7 @@ export default Ember.Component.extend(NotifierMixin, {
|
|||
},
|
||||
|
||||
getDefaultInvitationMessage() {
|
||||
return "Hey there, I am sharing the " + this.get('folder.name') + " (in " + this.get("appMeta.title") + ") with you so we can both access the same documents.";
|
||||
return "Hey there, I am sharing the " + this.get('folder.name') + " space (in " + this.get("appMeta.title") + ") with you so we can both access the same documents.";
|
||||
},
|
||||
|
||||
actions: {
|
||||
|
|
|
@ -23,7 +23,7 @@ export default Ember.Component.extend(NotifierMixin, {
|
|||
inviteMessage: '',
|
||||
|
||||
getDefaultInvitationMessage() {
|
||||
return "Hey there, I am sharing the " + this.folder.get('name') + " (in " + this.get("appMeta.title") + ") with you so we can both access the same documents.";
|
||||
return "Hey there, I am sharing the " + this.folder.get('name') + " space (in " + this.get("appMeta.title") + ") with you so we can both access the same documents.";
|
||||
},
|
||||
|
||||
willRender() {
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<thead>
|
||||
<tr>
|
||||
<th> </th>
|
||||
<th>View</th>
|
||||
<th>View </th>
|
||||
<th>Edit</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
|
|
@ -68,9 +68,11 @@ func (m *middleware) Authorize(w http.ResponseWriter, r *http.Request, next http
|
|||
method := "middleware.auth"
|
||||
|
||||
// Let certain requests pass straight through
|
||||
authenticated := preAuthorizeStaticAssets(m.Runtime, r)
|
||||
|
||||
if !authenticated {
|
||||
authenticated, ctx := m.preAuthorizeStaticAssets(m.Runtime, r)
|
||||
if authenticated {
|
||||
ctx2 := context.WithValue(r.Context(), domain.DocumizeContextKey, ctx)
|
||||
r = r.WithContext(ctx2)
|
||||
} else {
|
||||
token := auth.FindJWT(r)
|
||||
rc, _, tokenErr := auth.DecodeJWT(m.Runtime, token)
|
||||
|
||||
|
@ -195,7 +197,9 @@ func (m *middleware) Authorize(w http.ResponseWriter, r *http.Request, next http
|
|||
|
||||
// Certain assets/URL do not require authentication.
|
||||
// Just stops the log files being clogged up with failed auth errors.
|
||||
func preAuthorizeStaticAssets(rt *env.Runtime, r *http.Request) bool {
|
||||
func (m *middleware) preAuthorizeStaticAssets(rt *env.Runtime, r *http.Request) (auth bool, ctx domain.RequestContext) {
|
||||
ctx = domain.RequestContext{}
|
||||
|
||||
if strings.ToLower(r.URL.Path) == "/" ||
|
||||
strings.ToLower(r.URL.Path) == "/validate" ||
|
||||
strings.ToLower(r.URL.Path) == "/favicon.ico" ||
|
||||
|
@ -204,8 +208,27 @@ func preAuthorizeStaticAssets(rt *env.Runtime, r *http.Request) bool {
|
|||
strings.HasPrefix(strings.ToLower(r.URL.Path), "/api/public/") ||
|
||||
((rt.Flags.SiteMode == env.SiteModeSetup) && (strings.ToLower(r.URL.Path) == "/api/setup")) {
|
||||
|
||||
return true
|
||||
return true, ctx
|
||||
}
|
||||
|
||||
return false
|
||||
if strings.HasPrefix(strings.ToLower(r.URL.Path), "/api/public/") ||
|
||||
((rt.Flags.SiteMode == env.SiteModeSetup) && (strings.ToLower(r.URL.Path) == "/api/setup")) {
|
||||
|
||||
dom := organization.GetRequestSubdomain(r)
|
||||
dom = m.Store.Organization.CheckDomain(ctx, dom)
|
||||
|
||||
org, _ := m.Store.Organization.GetOrganizationByDomain(dom)
|
||||
ctx.Subdomain = organization.GetSubdomainFromHost(r)
|
||||
ctx.AllowAnonymousAccess = org.AllowAnonymousAccess
|
||||
ctx.OrgName = org.Title
|
||||
ctx.Administrator = false
|
||||
ctx.Editor = false
|
||||
ctx.Global = false
|
||||
ctx.AppURL = r.Host
|
||||
ctx.SSL = r.TLS != nil
|
||||
|
||||
return true, ctx
|
||||
}
|
||||
|
||||
return false, ctx
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue