Skip to content

Commit 3c50653

Browse files
Merge pull request #159 from documize/search-data-limits
Search data limits
2 parents ae50b88 + dc091fe commit 3c50653

File tree

9 files changed

+763
-677
lines changed

9 files changed

+763
-677
lines changed

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,9 +58,9 @@ Space view.
5858

5959
## Latest version
6060

61-
[Community edition: v1.65.3](https://github.com/documize/community/releases)
61+
[Community edition: v1.65.4](https://github.com/documize/community/releases)
6262

63-
[Enterprise edition: v1.67.3](https://documize.com/downloads)
63+
[Enterprise edition: v1.67.4](https://documize.com/downloads)
6464

6565
## OS support
6666

domain/category/mysql/store.go

Lines changed: 46 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,8 +77,8 @@ func (s Scope) GetAllBySpace(ctx domain.RequestContext, spaceID string) (c []cat
7777
WHERE orgid=? AND labelid=?
7878
AND labelid IN (SELECT refid FROM permission WHERE orgid=? AND location='space' AND refid IN (
7979
SELECT refid from permission WHERE orgid=? AND who='user' AND (whoid=? OR whoid='0') AND location='space' AND action='view' UNION ALL
80-
SELECT p.refid from permission p LEFT JOIN rolemember r ON p.whoid=r.roleid WHERE p.orgid=? AND p.who='role' AND p.location='space'
81-
AND p.action='view' AND (r.userid=? OR r.userid='0')
80+
SELECT p.refid from permission p LEFT JOIN rolemember r ON p.whoid=r.roleid
81+
WHERE p.orgid=? AND p.who='role' AND p.location='space' AND p.action='view' AND (r.userid=? OR r.userid='0')
8282
))
8383
ORDER BY category`, ctx.OrgID, spaceID, ctx.OrgID, ctx.OrgID, ctx.UserID, ctx.OrgID, ctx.UserID)
8484

@@ -92,6 +92,28 @@ func (s Scope) GetAllBySpace(ctx domain.RequestContext, spaceID string) (c []cat
9292
return
9393
}
9494

95+
// GetByOrg returns all categories accessible by user for their org.
96+
func (s Scope) GetByOrg(ctx domain.RequestContext, userID string) (c []category.Category, err error) {
97+
err = s.Runtime.Db.Select(&c, `
98+
SELECT id, refid, orgid, labelid, category, created, revised FROM category
99+
WHERE orgid=?
100+
AND refid IN (SELECT refid FROM permission WHERE orgid=? AND location='category' AND refid IN (
101+
SELECT refid from permission WHERE orgid=? AND who='user' AND (whoid=? OR whoid='0') AND location='category' UNION ALL
102+
SELECT p.refid from permission p LEFT JOIN rolemember r ON p.whoid=r.roleid
103+
WHERE p.orgid=? AND p.who='role' AND p.location='category' AND (r.userid=? OR r.userid='0')
104+
))
105+
ORDER BY category`, ctx.OrgID, ctx.OrgID, ctx.OrgID, userID, ctx.OrgID, userID)
106+
107+
if err == sql.ErrNoRows {
108+
err = nil
109+
}
110+
if err != nil {
111+
err = errors.Wrap(err, fmt.Sprintf("unable to execute select categories for org %s", ctx.OrgID))
112+
}
113+
114+
return
115+
}
116+
95117
// Update saves category name change.
96118
func (s Scope) Update(ctx domain.RequestContext, c category.Category) (err error) {
97119
c.Revised = time.Now().UTC()
@@ -255,3 +277,25 @@ func (s Scope) GetSpaceCategoryMembership(ctx domain.RequestContext, spaceID str
255277

256278
return
257279
}
280+
281+
// GetOrgCategoryMembership returns category/document associations within organization.
282+
func (s Scope) GetOrgCategoryMembership(ctx domain.RequestContext, userID string) (c []category.Member, err error) {
283+
err = s.Runtime.Db.Select(&c, `
284+
SELECT id, refid, orgid, labelid, categoryid, documentid, created, revised FROM categorymember
285+
WHERE orgid=?
286+
AND labelid IN (SELECT refid FROM permission WHERE orgid=? AND location='space' AND refid IN (
287+
SELECT refid from permission WHERE orgid=? AND who='user' AND (whoid=? OR whoid='0') AND location='space' AND action='view' UNION ALL
288+
SELECT p.refid from permission p LEFT JOIN rolemember r ON p.whoid=r.roleid WHERE p.orgid=? AND p.who='role' AND p.location='space'
289+
AND p.action='view' AND (r.userid=? OR r.userid='0')
290+
))
291+
ORDER BY documentid`, ctx.OrgID, ctx.OrgID, ctx.OrgID, userID, ctx.OrgID, userID)
292+
293+
if err == sql.ErrNoRows {
294+
err = nil
295+
}
296+
if err != nil {
297+
err = errors.Wrap(err, fmt.Sprintf("select all category/document membership for organization %s", ctx.OrgID))
298+
}
299+
300+
return
301+
}

domain/document/endpoint.go

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -418,31 +418,38 @@ func (h *Handler) SearchDocuments(w http.ResponseWriter, r *http.Request) {
418418
return
419419
}
420420

421+
// Get search criteria.
421422
options := search.QueryOptions{}
422423
err = json.Unmarshal(body, &options)
423424
if err != nil {
424425
response.WriteBadRequestError(w, method, err.Error())
425426
h.Runtime.Log.Error(method, err)
426427
return
427428
}
428-
429429
options.Keywords = strings.TrimSpace(options.Keywords)
430430

431+
// Get documents for search criteria.
431432
results, err := h.Store.Search.Documents(ctx, options)
432433
if err != nil {
433434
h.Runtime.Log.Error(method, err)
434435
}
435436

436-
// Put in slugs for easy UI display of search URL
437+
// Generate slugs for search URL.
437438
for key, result := range results {
438439
results[key].DocumentSlug = stringutil.MakeSlug(result.Document)
439440
results[key].SpaceSlug = stringutil.MakeSlug(result.Space)
440441
}
441442

442-
// Record user search history
443+
// Remove documents that cannot be seen due to lack of
444+
// category view/access permission.
445+
cats, err := h.Store.Category.GetByOrg(ctx, ctx.UserID)
446+
members, err := h.Store.Category.GetOrgCategoryMembership(ctx, ctx.UserID)
447+
filtered := indexer.FilterCategoryProtected(results, cats, members)
448+
449+
// Record user search history.
443450
if !options.SkipLog {
444-
if len(results) > 0 {
445-
go h.recordSearchActivity(ctx, results, options.Keywords)
451+
if len(filtered) > 0 {
452+
go h.recordSearchActivity(ctx, filtered, options.Keywords)
446453
} else {
447454
ctx.Transaction, err = h.Runtime.Db.Beginx()
448455
if err != nil {
@@ -468,7 +475,7 @@ func (h *Handler) SearchDocuments(w http.ResponseWriter, r *http.Request) {
468475

469476
h.Store.Audit.Record(ctx, audit.EventTypeSearch)
470477

471-
response.WriteJSON(w, results)
478+
response.WriteJSON(w, filtered)
472479
}
473480

474481
// Record search request once per document.

domain/search/mysql/store.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ func (s Scope) DeleteContent(ctx domain.RequestContext, pageID string) (err erro
151151
}
152152

153153
// Documents searches the documents that the client is allowed to see, using the keywords search string, then audits that search.
154-
// Visible documents include both those in the client's own organisation and those that are public, or whose visibility includes the client.
154+
// Visible documents include both those in the client's own organization and those that are public, or whose visibility includes the client.
155155
func (s Scope) Documents(ctx domain.RequestContext, q search.QueryOptions) (results []search.QueryResult, err error) {
156156
q.Keywords = strings.TrimSpace(q.Keywords)
157157
if len(q.Keywords) == 0 {

domain/search/search.go

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,10 @@ package search
1414
import (
1515
"github.com/documize/community/domain"
1616
"github.com/documize/community/model/attachment"
17+
"github.com/documize/community/model/category"
1718
"github.com/documize/community/model/doc"
1819
"github.com/documize/community/model/page"
20+
sm "github.com/documize/community/model/search"
1921
)
2022

2123
// IndexDocument adds search indesd entries for document inserting title, tags and attachments as
@@ -103,3 +105,34 @@ func (m *Indexer) DeleteContent(ctx domain.RequestContext, pageID string) {
103105

104106
ctx.Transaction.Commit()
105107
}
108+
109+
// FilterCategoryProtected removes search results that cannot be seen by user
110+
// due to document cateogory viewing permissions.
111+
func FilterCategoryProtected(results []sm.QueryResult, cats []category.Category, members []category.Member) (filtered []sm.QueryResult) {
112+
filtered = []sm.QueryResult{}
113+
114+
for _, result := range results {
115+
hasCategory := false
116+
canSeeCategory := false
117+
118+
OUTER:
119+
120+
for _, m := range members {
121+
if m.DocumentID == result.DocumentID {
122+
hasCategory = true
123+
for _, cat := range cats {
124+
if cat.RefID == m.CategoryID {
125+
canSeeCategory = true
126+
continue OUTER
127+
}
128+
}
129+
}
130+
}
131+
132+
if !hasCategory || canSeeCategory {
133+
filtered = append(filtered, result)
134+
}
135+
}
136+
137+
return
138+
}

domain/storer.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,8 @@ type CategoryStorer interface {
8181
GetSpaceCategoryMembership(ctx RequestContext, spaceID string) (c []category.Member, err error)
8282
RemoveDocumentCategories(ctx RequestContext, documentID string) (rows int64, err error)
8383
RemoveSpaceCategoryMemberships(ctx RequestContext, spaceID string) (rows int64, err error)
84+
GetByOrg(ctx RequestContext, userID string) (c []category.Category, err error)
85+
GetOrgCategoryMembership(ctx RequestContext, userID string) (c []category.Member, err error)
8486
}
8587

8688
// PermissionStorer defines required methods for space/document permission management

edition/community.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ func main() {
4242
rt.Product = env.ProdInfo{}
4343
rt.Product.Major = "1"
4444
rt.Product.Minor = "65"
45-
rt.Product.Patch = "3"
45+
rt.Product.Patch = "4"
4646
rt.Product.Version = fmt.Sprintf("%s.%s.%s", rt.Product.Major, rt.Product.Minor, rt.Product.Patch)
4747
rt.Product.Edition = "Community"
4848
rt.Product.Title = fmt.Sprintf("%s Edition", rt.Product.Edition)

0 commit comments

Comments
 (0)