1
0
Fork 0
mirror of https://github.com/documize/community.git synced 2025-07-19 21:29:42 +02:00

delete space, mov doc edge cases

This commit is contained in:
Harvey Kandola 2017-09-26 20:13:44 +01:00
parent 5481de4e1c
commit 8d761da939
11 changed files with 117 additions and 125 deletions

View file

@ -155,6 +155,26 @@ func (s Scope) RemoveCategoryMembership(ctx domain.RequestContext, categoryID st
return b.DeleteWhere(ctx.Transaction, sql) return b.DeleteWhere(ctx.Transaction, sql)
} }
// RemoveSpaceCategoryMemberships removes all category associations from the store for the space.
func (s Scope) RemoveSpaceCategoryMemberships(ctx domain.RequestContext, spaceID string) (rows int64, err error) {
b := mysql.BaseQuery{}
sql := fmt.Sprintf("DELETE FROM categorymember WHERE orgid='%s' AND labelid='%s'",
ctx.OrgID, spaceID)
return b.DeleteWhere(ctx.Transaction, sql)
}
// RemoveDocumentCategories removes all document category associations from the store.
func (s Scope) RemoveDocumentCategories(ctx domain.RequestContext, documentID string) (rows int64, err error) {
b := mysql.BaseQuery{}
sql := fmt.Sprintf("DELETE FROM categorymember WHERE orgid='%s' AND documentid='%s'",
ctx.OrgID, documentID)
return b.DeleteWhere(ctx.Transaction, sql)
}
// DeleteBySpace removes all category and category associations for given space. // DeleteBySpace removes all category and category associations for given space.
func (s Scope) DeleteBySpace(ctx domain.RequestContext, spaceID string) (rows int64, err error) { func (s Scope) DeleteBySpace(ctx domain.RequestContext, spaceID string) (rows int64, err error) {
b := mysql.BaseQuery{} b := mysql.BaseQuery{}

View file

@ -206,11 +206,6 @@ func (h *Handler) Update(w http.ResponseWriter, r *http.Request) {
return return
} }
// if !ctx.Editor {
// response.WriteForbiddenError(w)
// return
// }
if !permission.CanChangeDocument(ctx, *h.Store, documentID) { if !permission.CanChangeDocument(ctx, *h.Store, documentID) {
response.WriteForbiddenError(w) response.WriteForbiddenError(w)
return return
@ -241,6 +236,18 @@ func (h *Handler) Update(w http.ResponseWriter, r *http.Request) {
return return
} }
// if space changed for document, remove document categories
oldDoc, err := h.Store.Document.Get(ctx, documentID)
if err != nil {
response.WriteServerError(w, method, err)
h.Runtime.Log.Error(method, err)
return
}
if oldDoc.LabelID != d.LabelID {
h.Store.Category.RemoveDocumentCategories(ctx, d.RefID)
}
err = h.Store.Document.Update(ctx, d) err = h.Store.Document.Update(ctx, d)
if err != nil { if err != nil {
ctx.Transaction.Rollback() ctx.Transaction.Rollback()

View file

@ -301,11 +301,11 @@ func (h *Handler) Get(w http.ResponseWriter, r *http.Request) {
} }
// GetAll returns spaces the user can see. // GetAll returns spaces the user can see.
func (h *Handler) GetAll(w http.ResponseWriter, r *http.Request) { func (h *Handler) GetViewable(w http.ResponseWriter, r *http.Request) {
method := "space.getAll" method := "space.GetViewable"
ctx := domain.GetRequestContext(r) ctx := domain.GetRequestContext(r)
sp, err := h.Store.Space.GetAll(ctx) sp, err := h.Store.Space.GetViewable(ctx)
if err != nil && err != sql.ErrNoRows { if err != nil && err != sql.ErrNoRows {
response.WriteServerError(w, method, err) response.WriteServerError(w, method, err)
@ -320,23 +320,31 @@ func (h *Handler) GetAll(w http.ResponseWriter, r *http.Request) {
response.WriteJSON(w, sp) response.WriteJSON(w, sp)
} }
// GetSpaceViewers returns the users that can see the shared spaces.
func (h *Handler) GetSpaceViewers(w http.ResponseWriter, r *http.Request) { // GetAll returns every space for documize admin users to manage
method := "space.viewers" func (h *Handler) GetAll(w http.ResponseWriter, r *http.Request) {
method := "space.getAll"
ctx := domain.GetRequestContext(r) ctx := domain.GetRequestContext(r)
v, err := h.Store.Space.Viewers(ctx) if !ctx.Administrator {
response.WriteForbiddenError(w)
h.Runtime.Log.Info("rejected non-admin user request for all spaces")
return
}
sp, err := h.Store.Space.GetAll(ctx)
if err != nil && err != sql.ErrNoRows { if err != nil && err != sql.ErrNoRows {
response.WriteServerError(w, method, err) response.WriteServerError(w, method, err)
h.Runtime.Log.Error(method, err) h.Runtime.Log.Error(method, err)
return return
} }
if len(v) == 0 { if len(sp) == 0 {
v = []space.Viewer{} sp = []space.Space{}
} }
response.WriteJSON(w, v) response.WriteJSON(w, sp)
} }
// Update processes request to save space object to the database // Update processes request to save space object to the database
@ -444,6 +452,14 @@ func (h *Handler) Remove(w http.ResponseWriter, r *http.Request) {
return return
} }
_, err = h.Store.Category.RemoveSpaceCategoryMemberships(ctx, id)
if err != nil {
ctx.Transaction.Rollback()
response.WriteServerError(w, method, err)
h.Runtime.Log.Error(method, err)
return
}
_, err = h.Store.Space.Delete(ctx, id) _, err = h.Store.Space.Delete(ctx, id)
if err != nil { if err != nil {
ctx.Transaction.Rollback() ctx.Transaction.Rollback()
@ -811,4 +827,4 @@ func (h *Handler) Invite(w http.ResponseWriter, r *http.Request) {
ctx.Transaction.Commit() ctx.Transaction.Commit()
response.WriteEmpty(w) response.WriteEmpty(w)
} }

View file

@ -69,9 +69,9 @@ func (s Scope) PublicSpaces(ctx domain.RequestContext, orgID string) (sp []space
return return
} }
// GetAll returns spaces that the user can see. // GetViewable returns spaces that the user can see.
// Also handles which spaces can be seen by anonymous users. // Also handles which spaces can be seen by anonymous users.
func (s Scope) GetAll(ctx domain.RequestContext) (sp []space.Space, err error) { func (s Scope) GetViewable(ctx domain.RequestContext) (sp []space.Space, err error) {
sql := ` sql := `
SELECT id,refid,label as name,orgid,userid,type,created,revised FROM label SELECT id,refid,label as name,orgid,userid,type,created,revised FROM label
WHERE orgid=? WHERE orgid=?
@ -90,6 +90,22 @@ func (s Scope) GetAll(ctx domain.RequestContext) (sp []space.Space, err error) {
ctx.OrgID, ctx.OrgID,
ctx.UserID) ctx.UserID)
if err != nil {
err = errors.Wrap(err, fmt.Sprintf("failed space.GetViewable org %s", ctx.OrgID))
}
return
}
// GetAll for admin 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=?
ORDER BY name`
err = s.Runtime.Db.Select(&sp, sql, ctx.OrgID)
if err != nil { if err != nil {
err = errors.Wrap(err, fmt.Sprintf("failed space.GetAll org %s", ctx.OrgID)) err = errors.Wrap(err, fmt.Sprintf("failed space.GetAll org %s", ctx.OrgID))
} }
@ -110,28 +126,6 @@ func (s Scope) Update(ctx domain.RequestContext, sp space.Space) (err error) {
return return
} }
// 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,
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`
err = s.Runtime.Db.Select(&v, sql, ctx.OrgID)
return
}
// Delete removes space from the store. // Delete removes space from the store.
func (s Scope) Delete(ctx domain.RequestContext, id string) (rows int64, err error) { func (s Scope) Delete(ctx domain.RequestContext, id string) (rows int64, err error) {
b := mysql.BaseQuery{} b := mysql.BaseQuery{}

View file

@ -163,14 +163,6 @@ func TestSpace(t *testing.T) {
} }
}) })
t.Run("Viewers", func(t *testing.T) {
viewers, err := s.Space.Viewers(ctx)
if err != nil || viewers == nil {
t.Error("failed to get viewers")
return
}
})
t.Run("Add Role", func(t *testing.T) { t.Run("Add Role", func(t *testing.T) {
ctx.Transaction, err = rt.Db.Beginx() ctx.Transaction, err = rt.Db.Beginx()

View file

@ -55,9 +55,9 @@ type SpaceStorer interface {
Add(ctx RequestContext, sp space.Space) (err error) Add(ctx RequestContext, sp space.Space) (err error)
Get(ctx RequestContext, id string) (sp space.Space, err error) Get(ctx RequestContext, id string) (sp space.Space, err error)
PublicSpaces(ctx RequestContext, orgID string) (sp []space.Space, err error) PublicSpaces(ctx RequestContext, orgID string) (sp []space.Space, err error)
GetViewable(ctx RequestContext) (sp []space.Space, err error)
GetAll(ctx RequestContext) (sp []space.Space, err error) GetAll(ctx RequestContext) (sp []space.Space, err error)
Update(ctx RequestContext, sp space.Space) (err error) Update(ctx RequestContext, sp space.Space) (err error)
Viewers(ctx RequestContext) (v []space.Viewer, err error)
Delete(ctx RequestContext, id string) (rows int64, err error) Delete(ctx RequestContext, id string) (rows int64, err error)
} }
@ -76,6 +76,8 @@ type CategoryStorer interface {
DeleteBySpace(ctx RequestContext, spaceID string) (rows int64, err error) DeleteBySpace(ctx RequestContext, spaceID string) (rows int64, err error)
GetDocumentCategoryMembership(ctx RequestContext, documentID string) (c []category.Category, err error) GetDocumentCategoryMembership(ctx RequestContext, documentID string) (c []category.Category, err error)
GetSpaceCategoryMembership(ctx RequestContext, spaceID string) (c []category.Member, err error) GetSpaceCategoryMembership(ctx RequestContext, spaceID string) (c []category.Member, err error)
RemoveDocumentCategories(ctx RequestContext, documentID string) (rows int64, err error)
RemoveSpaceCategoryMemberships(ctx RequestContext, spaceID string) (rows int64, err error)
} }
// PermissionStorer defines required methods for space/document permission management // PermissionStorer defines required methods for space/document permission management

View file

@ -22,7 +22,7 @@ export default Ember.Route.extend(AuthenticatedRouteMixin, {
}, },
model() { model() {
return this.get('folderService').getAll(); return this.get('folderService').adminList();
}, },
setupController(controller, model) { setupController(controller, model) {
@ -30,33 +30,12 @@ export default Ember.Route.extend(AuthenticatedRouteMixin, {
if (is.empty(nonPrivateFolders) || is.null(model) || is.undefined(model)) { if (is.empty(nonPrivateFolders) || is.null(model) || is.undefined(model)) {
nonPrivateFolders = []; nonPrivateFolders = [];
} }
controller.set('folders', nonPrivateFolders); controller.set('folders', nonPrivateFolders);
this.get('folderService').getProtectedFolderInfo().then((people) => {
people.forEach((person) => {
person.set('isEveryone', person.get('userId') === '');
person.set('isOwner', false);
});
nonPrivateFolders.forEach(function (folder) {
let shared = people.filterBy('folderId', folder.get('id'));
let person = shared.findBy('userId', folder.get('userId'));
if (is.not.undefined(person)) {
person.set('isOwner', true);
}
folder.set('sharedWith', shared);
});
});
}, },
activate() { activate() {
document.title = "Spaces | Documize"; document.title = "Spaces | Documize";
},
actions: {
onChangeOwner() {
this.refresh();
}
} }
}); });

View file

@ -4,40 +4,16 @@
<div class="title">{{folders.length}} shared {{label}}</div> <div class="title">{{folders.length}} shared {{label}}</div>
<div class="tip">View and change shared space ownership</div> <div class="tip">View and change shared space ownership</div>
</div> </div>
<div class="input-control"> <div class="input-control manage-space-list">
<table class="basic-table"> {{#each folders as |folder|}}
<thead> <div class="space pull-left width-80">
<tr> {{#link-to 'folder' folder.id folder.slug class="alt"}}{{folder.name}}{{/link-to}}
<th class="bordered">Space</th> </div>
<th class="bordered">Participants</th> <div class="pull-right">
</tr> &nbsp;
</thead> </div>
<tbody> <div class="clearfix" />
{{#each folders as |folder|}} {{/each}}
<tr>
<td class="bordered">
{{#link-to 'folder' folder.id folder.slug class="alt"}}{{folder.name}}{{/link-to}}
</td>
<td class="bordered">
{{#each folder.sharedWith as |person|}}
{{#if person.isEveryone}}
Everyone
{{else}}
{{#if person.isOwner}}
<span class="bold">{{person.firstname}} {{person.lastname}} (owner)</span>
{{else}}
{{person.firstname}} {{person.lastname}}
<a class="action-link" {{action "changeOwner" folder.id person.userId}}>make owner</a>
{{/if}}
{{/if}}
<br/>
{{/each}}
</td>
</tr>
{{/each}}
</tbody>
</table>
</div> </div>
</div> </div>
{{else}} {{else}}

View file

@ -96,22 +96,6 @@ export default BaseService.extend({
}); });
}, },
// getProtectedFolderInfo returns non-private folders and who has access to them.
getProtectedFolderInfo() {
return this.get('ajax').request(`space?filter=viewers`, {
method: "GET"
}).then((response) => {
let data = [];
data = response.map((obj) => {
let data = this.get('store').normalize('protected-folder-participant', obj);
return this.get('store').push(data);
});
return data;
});
},
// reloads and caches folders. // reloads and caches folders.
reload() { reload() {
return this.get('ajax').request(`space`, { return this.get('ajax').request(`space`, {
@ -185,4 +169,20 @@ export default BaseService.extend({
return data2; return data2;
}); });
}, },
// returns all spaces -- for use by documize admin user
adminList() {
return this.get('ajax').request(`space/manage`, {
method: "GET"
}).then((response) => {
let data = [];
data = response.map((obj) => {
let data = this.get('store').normalize('folder', obj);
return this.get('store').push(data);
});
return data;
});
}
}); });

View file

@ -89,4 +89,10 @@
.edit-user-dialog, .delete-user-dialog { .edit-user-dialog, .delete-user-dialog {
display: none; display: none;
} }
.manage-space-list {
> .space {
margin: 10px 0;
}
}
} }

View file

@ -119,11 +119,11 @@ func RegisterEndpoints(rt *env.Runtime, s *domain.Store) {
Add(rt, RoutePrefixPrivate, "space/{spaceID}/permissions/user", []string{"GET", "OPTIONS"}, nil, permission.GetUserSpacePermissions) Add(rt, RoutePrefixPrivate, "space/{spaceID}/permissions/user", []string{"GET", "OPTIONS"}, nil, permission.GetUserSpacePermissions)
Add(rt, RoutePrefixPrivate, "space/{spaceID}/permissions", []string{"GET", "OPTIONS"}, nil, permission.GetSpacePermissions) Add(rt, RoutePrefixPrivate, "space/{spaceID}/permissions", []string{"GET", "OPTIONS"}, nil, permission.GetSpacePermissions)
Add(rt, RoutePrefixPrivate, "space/{spaceID}/invitation", []string{"POST", "OPTIONS"}, nil, space.Invite) Add(rt, RoutePrefixPrivate, "space/{spaceID}/invitation", []string{"POST", "OPTIONS"}, nil, space.Invite)
Add(rt, RoutePrefixPrivate, "space", []string{"GET", "OPTIONS"}, []string{"filter", "viewers"}, space.GetSpaceViewers) Add(rt, RoutePrefixPrivate, "space/manage", []string{"GET", "OPTIONS"}, nil, space.GetAll)
Add(rt, RoutePrefixPrivate, "space", []string{"POST", "OPTIONS"}, nil, space.Add)
Add(rt, RoutePrefixPrivate, "space", []string{"GET", "OPTIONS"}, nil, space.GetAll)
Add(rt, RoutePrefixPrivate, "space/{spaceID}", []string{"GET", "OPTIONS"}, nil, space.Get) Add(rt, RoutePrefixPrivate, "space/{spaceID}", []string{"GET", "OPTIONS"}, nil, space.Get)
Add(rt, RoutePrefixPrivate, "space", []string{"GET", "OPTIONS"}, nil, space.GetViewable)
Add(rt, RoutePrefixPrivate, "space/{spaceID}", []string{"PUT", "OPTIONS"}, nil, space.Update) Add(rt, RoutePrefixPrivate, "space/{spaceID}", []string{"PUT", "OPTIONS"}, nil, space.Update)
Add(rt, RoutePrefixPrivate, "space", []string{"POST", "OPTIONS"}, nil, space.Add)
Add(rt, RoutePrefixPrivate, "category/document/{documentID}", []string{"GET", "OPTIONS"}, nil, category.GetDocumentCategoryMembership) Add(rt, RoutePrefixPrivate, "category/document/{documentID}", []string{"GET", "OPTIONS"}, nil, category.GetDocumentCategoryMembership)
Add(rt, RoutePrefixPrivate, "category/space/{spaceID}", []string{"GET", "OPTIONS"}, []string{"filter", "all"}, category.GetAll) Add(rt, RoutePrefixPrivate, "category/space/{spaceID}", []string{"GET", "OPTIONS"}, []string{"filter", "all"}, category.GetAll)