mirror of
https://github.com/documize/community.git
synced 2025-07-19 13:19:43 +02:00
refined category permission checks
This commit is contained in:
parent
4d989e2497
commit
3a9675eb14
11 changed files with 149 additions and 22 deletions
|
@ -278,6 +278,37 @@ func (h *Handler) Delete(w http.ResponseWriter, r *http.Request) {
|
||||||
response.WriteEmpty(w)
|
response.WriteEmpty(w)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetSummary returns number of documents and users for space categories.
|
||||||
|
func (h *Handler) GetSummary(w http.ResponseWriter, r *http.Request) {
|
||||||
|
method := "category.GetSummary"
|
||||||
|
ctx := domain.GetRequestContext(r)
|
||||||
|
|
||||||
|
spaceID := request.Param(r, "spaceID")
|
||||||
|
if len(spaceID) == 0 {
|
||||||
|
response.WriteMissingDataError(w, method, "spaceID")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
ok := permission.HasPermission(ctx, *h.Store, spaceID, pm.SpaceManage, pm.SpaceOwner)
|
||||||
|
if !ok || !ctx.Authenticated {
|
||||||
|
response.WriteForbiddenError(w)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
s, err := h.Store.Category.GetSpaceCategorySummary(ctx, spaceID)
|
||||||
|
if err != nil {
|
||||||
|
h.Runtime.Log.Error("get space category summary failed", err)
|
||||||
|
response.WriteServerError(w, method, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(s) == 0 {
|
||||||
|
s = []category.SummaryModel{}
|
||||||
|
}
|
||||||
|
|
||||||
|
response.WriteJSON(w, s)
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
- category view permission handling
|
- category view permission handling
|
||||||
- filter users using new permission
|
- filter users using new permission
|
||||||
|
|
|
@ -199,3 +199,29 @@ func (s Scope) DeleteBySpace(ctx domain.RequestContext, spaceID string) (rows in
|
||||||
s2 := fmt.Sprintf("DELETE FROM category WHERE orgid='%s' AND labelid='%s'", ctx.OrgID, spaceID)
|
s2 := fmt.Sprintf("DELETE FROM category WHERE orgid='%s' AND labelid='%s'", ctx.OrgID, spaceID)
|
||||||
return b.DeleteWhere(ctx.Transaction, s2)
|
return b.DeleteWhere(ctx.Transaction, s2)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetSpaceCategorySummary returns number of documents and users for space categories.
|
||||||
|
func (s Scope) GetSpaceCategorySummary(ctx domain.RequestContext, spaceID string) (c []category.SummaryModel, err error) {
|
||||||
|
err = s.Runtime.Db.Select(&c, `
|
||||||
|
SELECT 'documents' as type, categoryid, COUNT(*) as count FROM categorymember WHERE orgid=? AND labelid=? GROUP BY categoryid, type
|
||||||
|
UNION ALL
|
||||||
|
SELECT 'users' as type, refid AS categoryid, count(*) AS count FROM permission WHERE orgid=? AND who='user' AND location='category'
|
||||||
|
AND refid IN (SELECT refid FROM category WHERE orgid=? AND labelid=?)
|
||||||
|
GROUP BY refid, type
|
||||||
|
UNION ALL
|
||||||
|
SELECT 'users' as type, p.refid AS categoryid, count(*) AS count FROM rolemember r LEFT JOIN permission p ON p.whoid=r.roleid
|
||||||
|
WHERE p.orgid=? AND p.who='role' AND p.location='category'
|
||||||
|
AND p.refid IN (SELECT refid FROM category WHERE orgid=? AND labelid=?)
|
||||||
|
GROUP BY p.refid, type`,
|
||||||
|
ctx.OrgID, spaceID, ctx.OrgID, ctx.OrgID, spaceID, ctx.OrgID, ctx.OrgID, spaceID)
|
||||||
|
|
||||||
|
if err == sql.ErrNoRows {
|
||||||
|
err = nil
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
err = errors.Wrap(err, fmt.Sprintf("unable to execute select category summary for space %s", spaceID))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
|
@ -273,9 +273,9 @@ func (h *Handler) GetUserSpacePermissions(w http.ResponseWriter, r *http.Request
|
||||||
response.WriteJSON(w, record)
|
response.WriteJSON(w, record)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetCategoryPermissions returns user permissions for given category.
|
// GetCategoryViewers returns user permissions for given category.
|
||||||
func (h *Handler) GetCategoryPermissions(w http.ResponseWriter, r *http.Request) {
|
func (h *Handler) GetCategoryViewers(w http.ResponseWriter, r *http.Request) {
|
||||||
method := "space.GetCategoryPermissions"
|
method := "space.GetCategoryViewers"
|
||||||
ctx := domain.GetRequestContext(r)
|
ctx := domain.GetRequestContext(r)
|
||||||
|
|
||||||
categoryID := request.Param(r, "categoryID")
|
categoryID := request.Param(r, "categoryID")
|
||||||
|
@ -296,6 +296,29 @@ func (h *Handler) GetCategoryPermissions(w http.ResponseWriter, r *http.Request)
|
||||||
response.WriteJSON(w, u)
|
response.WriteJSON(w, u)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetCategoryPermissions returns user permissions for given category.
|
||||||
|
func (h *Handler) GetCategoryPermissions(w http.ResponseWriter, r *http.Request) {
|
||||||
|
method := "space.GetCategoryPermissions"
|
||||||
|
ctx := domain.GetRequestContext(r)
|
||||||
|
|
||||||
|
categoryID := request.Param(r, "categoryID")
|
||||||
|
if len(categoryID) == 0 {
|
||||||
|
response.WriteMissingDataError(w, method, "categoryID")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
u, err := h.Store.Permission.GetCategoryPermissions(ctx, categoryID)
|
||||||
|
if err != nil && err != sql.ErrNoRows {
|
||||||
|
response.WriteServerError(w, method, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if len(u) == 0 {
|
||||||
|
u = []permission.Permission{}
|
||||||
|
}
|
||||||
|
|
||||||
|
response.WriteJSON(w, u)
|
||||||
|
}
|
||||||
|
|
||||||
// SetCategoryPermissions persists specified category permissions
|
// SetCategoryPermissions persists specified category permissions
|
||||||
func (h *Handler) SetCategoryPermissions(w http.ResponseWriter, r *http.Request) {
|
func (h *Handler) SetCategoryPermissions(w http.ResponseWriter, r *http.Request) {
|
||||||
method := "permission.SetCategoryPermissions"
|
method := "permission.SetCategoryPermissions"
|
||||||
|
|
|
@ -182,9 +182,9 @@ func (s Scope) GetCategoryPermissions(ctx domain.RequestContext, catID string) (
|
||||||
// GetCategoryUsers returns space permissions for all users.
|
// GetCategoryUsers returns space permissions for all users.
|
||||||
func (s Scope) GetCategoryUsers(ctx domain.RequestContext, catID string) (u []user.User, err error) {
|
func (s Scope) GetCategoryUsers(ctx domain.RequestContext, catID string) (u []user.User, err error) {
|
||||||
err = s.Runtime.Db.Select(&u, `
|
err = s.Runtime.Db.Select(&u, `
|
||||||
SELECT u.id, u.refid, u.firstname, u.lastname, u.email, u.initials, u.password, u.salt, u.reset, u.created, u.revised
|
SELECT u.id, IFNULL(u.refid, '') AS refid, IFNULL(u.firstname, '') AS firstname, IFNULL(u.lastname, '') as lastname, u.email, u.initials, u.password, u.salt, u.reset, u.created, u.revised
|
||||||
FROM user u, account a
|
FROM user u LEFT JOIN account a ON u.refid = a.userid
|
||||||
WHERE a.orgid=? AND u.refid = a.userid AND a.active=1 AND u.refid IN (
|
WHERE a.orgid=? AND a.active=1 AND u.refid IN (
|
||||||
SELECT whoid from permission WHERE orgid=? AND who='user' AND location='category' AND refid=? UNION ALL
|
SELECT whoid from permission WHERE orgid=? AND who='user' AND location='category' AND refid=? UNION ALL
|
||||||
SELECT r.userid from rolemember r LEFT JOIN permission p ON p.whoid=r.roleid WHERE p.orgid=? AND p.who='role'
|
SELECT r.userid from rolemember r LEFT JOIN permission p ON p.whoid=r.roleid WHERE p.orgid=? AND p.who='role'
|
||||||
AND p.location='category' AND p.refid=?
|
AND p.location='category' AND p.refid=?
|
||||||
|
@ -197,7 +197,7 @@ func (s Scope) GetCategoryUsers(ctx domain.RequestContext, catID string) (u []us
|
||||||
err = nil
|
err = nil
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = errors.Wrap(err, fmt.Sprintf("unable to execute select category user %s", catID))
|
err = errors.Wrap(err, fmt.Sprintf("unable to execute select users for category %s", catID))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -68,6 +68,7 @@ type CategoryStorer interface {
|
||||||
Get(ctx RequestContext, id string) (c category.Category, err error)
|
Get(ctx RequestContext, id string) (c category.Category, err error)
|
||||||
GetBySpace(ctx RequestContext, spaceID string) (c []category.Category, err error)
|
GetBySpace(ctx RequestContext, spaceID string) (c []category.Category, err error)
|
||||||
GetAllBySpace(ctx RequestContext, spaceID string) (c []category.Category, err error)
|
GetAllBySpace(ctx RequestContext, spaceID string) (c []category.Category, err error)
|
||||||
|
GetSpaceCategorySummary(ctx RequestContext, spaceID string) (c []category.SummaryModel, err error)
|
||||||
Delete(ctx RequestContext, id string) (rows int64, err error)
|
Delete(ctx RequestContext, id string) (rows int64, err error)
|
||||||
AssociateDocument(ctx RequestContext, m category.Member) (err error)
|
AssociateDocument(ctx RequestContext, m category.Member) (err error)
|
||||||
DisassociateDocument(ctx RequestContext, categoryID, documentID string) (rows int64, err error)
|
DisassociateDocument(ctx RequestContext, categoryID, documentID string) (rows int64, err error)
|
||||||
|
|
|
@ -44,6 +44,20 @@ export default Ember.Component.extend(NotifierMixin, TooltipMixin, DropdownMixin
|
||||||
this.get('categoryService').getAll(this.get('folder.id')).then((c) => {
|
this.get('categoryService').getAll(this.get('folder.id')).then((c) => {
|
||||||
this.set('category', c);
|
this.set('category', c);
|
||||||
|
|
||||||
|
// get summary of documents and users for each category in space
|
||||||
|
this.get('categoryService').getSummary(this.get('folder.id')).then((s) => {
|
||||||
|
c.forEach((cat) => {
|
||||||
|
let docs = _.findWhere(s, {categoryId: cat.get('id'), type: 'documents'});
|
||||||
|
let docCount = is.not.undefined(docs) ? docs.count : 0;
|
||||||
|
|
||||||
|
let users = _.findWhere(s, {categoryId: cat.get('id'), type: 'users'});
|
||||||
|
let userCount = is.not.undefined(users) ? users.count : 0;
|
||||||
|
|
||||||
|
cat.set('documents', docCount);
|
||||||
|
cat.set('users', userCount);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
// get users that this space admin user can see
|
// get users that this space admin user can see
|
||||||
this.get('userService').getAll().then((users) => {
|
this.get('userService').getAll().then((users) => {
|
||||||
// set up Everyone user
|
// set up Everyone user
|
||||||
|
@ -132,12 +146,12 @@ export default Ember.Component.extend(NotifierMixin, TooltipMixin, DropdownMixin
|
||||||
let users = this.get('users');
|
let users = this.get('users');
|
||||||
let category = this.get('category').findBy('id', catId);
|
let category = this.get('category').findBy('id', catId);
|
||||||
|
|
||||||
this.get('categoryService').getViewers(category.get('id')).then((viewers) => {
|
this.get('categoryService').getPermissions(category.get('id')).then((viewers) => {
|
||||||
// mark those users as selected that have already been given permission
|
// mark those users as selected that have already been given permission
|
||||||
// to see the current category;
|
// to see the current category;
|
||||||
|
|
||||||
users.forEach((user) => {
|
users.forEach((user) => {
|
||||||
let selected = viewers.isAny('id', user.get('id'));
|
let userId = user.get('id') === '0' ? '' : user.get('id');
|
||||||
|
let selected = viewers.isAny('whoId', userId);
|
||||||
user.set('selected', selected);
|
user.set('selected', selected);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -173,17 +187,22 @@ export default Ember.Component.extend(NotifierMixin, TooltipMixin, DropdownMixin
|
||||||
let viewers = [];
|
let viewers = [];
|
||||||
|
|
||||||
users.forEach((user) => {
|
users.forEach((user) => {
|
||||||
|
let userId = user.get('id');
|
||||||
|
if (userId === "0") userId = '';
|
||||||
|
|
||||||
let v = {
|
let v = {
|
||||||
orgId: this.get('folder.orgId'),
|
orgId: this.get('folder.orgId'),
|
||||||
folderId: this.get('folder.id'),
|
folderId: this.get('folder.id'),
|
||||||
categoryId: category.get('id'),
|
categoryId: category.get('id'),
|
||||||
userId: user.get('id')
|
userId: userId
|
||||||
};
|
};
|
||||||
|
|
||||||
viewers.push(v);
|
viewers.push(v);
|
||||||
});
|
});
|
||||||
|
|
||||||
this.get('categoryService').setViewers(category.get('id'), viewers).then( () => {});
|
this.get('categoryService').setViewers(category.get('id'), viewers).then(() => {
|
||||||
|
this.load();
|
||||||
|
});
|
||||||
|
|
||||||
this.closeDropdown();
|
this.closeDropdown();
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,5 +17,9 @@ export default Model.extend({
|
||||||
folderId: attr('string'),
|
folderId: attr('string'),
|
||||||
category: attr('string'),
|
category: attr('string'),
|
||||||
created: attr(),
|
created: attr(),
|
||||||
revised: attr()
|
revised: attr(),
|
||||||
|
|
||||||
|
// fields used by UI only
|
||||||
|
documents: attr(),
|
||||||
|
users: attr(),
|
||||||
});
|
});
|
||||||
|
|
|
@ -85,10 +85,19 @@ export default BaseService.extend({
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
// Get list of users who can see given category
|
// Get viewer permission records for given category
|
||||||
getViewers(categoryId) {
|
getPermissions(categoryId) {
|
||||||
return this.get('ajax').request(`category/${categoryId}/permission`, {
|
return this.get('ajax').request(`category/${categoryId}/permission`, {
|
||||||
method: 'GET'
|
method: 'GET'
|
||||||
|
}).then((response) => {
|
||||||
|
return response;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
// Get list of users who can see given category
|
||||||
|
getUsers(categoryId) {
|
||||||
|
return this.get('ajax').request(`category/${categoryId}/user`, {
|
||||||
|
method: 'GET'
|
||||||
}).then((response) => {
|
}).then((response) => {
|
||||||
let data = [];
|
let data = [];
|
||||||
|
|
||||||
|
@ -109,4 +118,13 @@ export default BaseService.extend({
|
||||||
data: JSON.stringify(viewers)
|
data: JSON.stringify(viewers)
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// Get count of documents and users associated with each category in given space.
|
||||||
|
getSummary(spaceId) {
|
||||||
|
return this.get('ajax').request(`category/space/${spaceId}/summary`, {
|
||||||
|
method: 'GET'
|
||||||
|
}).then((response) => {
|
||||||
|
return response;
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
{{else}}
|
{{else}}
|
||||||
<div class="category">
|
<div class="category">
|
||||||
<div class="name">{{cat.category}}</div>
|
<div class="name">{{cat.category}}</div>
|
||||||
<div class="info">7 documents, 14 people</div>
|
<div class="info">{{cat.documents}} documents, {{cat.users}} people</div>
|
||||||
</div>
|
</div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
<div class="pull-right buttons">
|
<div class="pull-right buttons">
|
||||||
|
@ -66,12 +66,8 @@
|
||||||
{{ui/ui-list-picker items=categoryUsers nameField='fullname'}}
|
{{ui/ui-list-picker items=categoryUsers nameField='fullname'}}
|
||||||
</div>
|
</div>
|
||||||
<div class="actions">
|
<div class="actions">
|
||||||
<div class="flat-button" {{action 'onGrantCancel'}}>
|
<div class="flat-button" {{action 'onGrantCancel'}}>cancel</div>
|
||||||
cancel
|
<div class="flat-button flat-blue" {{action 'onGrantAccess'}}>grant access</div>
|
||||||
</div>
|
|
||||||
<div class="flat-button flat-blue" {{action 'onGrantAccess'}}>
|
|
||||||
grant access
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="clearfix"></div>
|
<div class="clearfix"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -29,3 +29,10 @@ type Member struct {
|
||||||
LabelID string `json:"folderId"`
|
LabelID string `json:"folderId"`
|
||||||
DocumentID string `json:"documentId"`
|
DocumentID string `json:"documentId"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SummaryModel holds number of documents and users for space categories.
|
||||||
|
type SummaryModel struct {
|
||||||
|
Type string `json:"type"` // documents or users
|
||||||
|
CategoryID string `json:"categoryId"`
|
||||||
|
Count int64 `json:"count"`
|
||||||
|
}
|
||||||
|
|
|
@ -132,8 +132,10 @@ func RegisterEndpoints(rt *env.Runtime, s *domain.Store) {
|
||||||
Add(rt, RoutePrefixPrivate, "category", []string{"POST", "OPTIONS"}, nil, category.Add)
|
Add(rt, RoutePrefixPrivate, "category", []string{"POST", "OPTIONS"}, nil, category.Add)
|
||||||
Add(rt, RoutePrefixPrivate, "category/{categoryID}", []string{"PUT", "OPTIONS"}, nil, category.Update)
|
Add(rt, RoutePrefixPrivate, "category/{categoryID}", []string{"PUT", "OPTIONS"}, nil, category.Update)
|
||||||
Add(rt, RoutePrefixPrivate, "category/{categoryID}", []string{"DELETE", "OPTIONS"}, nil, category.Delete)
|
Add(rt, RoutePrefixPrivate, "category/{categoryID}", []string{"DELETE", "OPTIONS"}, nil, category.Delete)
|
||||||
|
Add(rt, RoutePrefixPrivate, "category/space/{spaceID}/summary", []string{"GET", "OPTIONS"}, nil, category.GetSummary)
|
||||||
Add(rt, RoutePrefixPrivate, "category/{categoryID}/permission", []string{"PUT", "OPTIONS"}, nil, permission.SetCategoryPermissions)
|
Add(rt, RoutePrefixPrivate, "category/{categoryID}/permission", []string{"PUT", "OPTIONS"}, nil, permission.SetCategoryPermissions)
|
||||||
Add(rt, RoutePrefixPrivate, "category/{categoryID}/permission", []string{"GET", "OPTIONS"}, nil, permission.GetCategoryPermissions)
|
Add(rt, RoutePrefixPrivate, "category/{categoryID}/permission", []string{"GET", "OPTIONS"}, nil, permission.GetCategoryPermissions)
|
||||||
|
Add(rt, RoutePrefixPrivate, "category/{categoryID}/user", []string{"GET", "OPTIONS"}, nil, permission.GetCategoryViewers)
|
||||||
|
|
||||||
Add(rt, RoutePrefixPrivate, "users/{userID}/password", []string{"POST", "OPTIONS"}, nil, user.ChangePassword)
|
Add(rt, RoutePrefixPrivate, "users/{userID}/password", []string{"POST", "OPTIONS"}, nil, user.ChangePassword)
|
||||||
Add(rt, RoutePrefixPrivate, "users", []string{"POST", "OPTIONS"}, nil, user.Add)
|
Add(rt, RoutePrefixPrivate, "users", []string{"POST", "OPTIONS"}, nil, user.Add)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue