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

Persist space permissions for groups and users

This commit is contained in:
sauls8t 2018-03-03 17:46:29 +00:00
parent 0d39f7251e
commit 7ccb3b4658
16 changed files with 320 additions and 157 deletions

View file

@ -28,8 +28,10 @@ import (
"github.com/documize/community/domain"
"github.com/documize/community/domain/mail"
"github.com/documize/community/model/audit"
"github.com/documize/community/model/group"
"github.com/documize/community/model/permission"
"github.com/documize/community/model/space"
"github.com/documize/community/model/user"
)
// Handler contains the runtime information such as logging and database.
@ -122,52 +124,85 @@ func (h *Handler) SetSpacePermissions(w http.ResponseWriter, r *http.Request) {
hasEveryoneRole := false
roleCount := 0
// Permissions can be assigned to both groups and individual users.
// Pre-fetch users with group membership to help us work out
// if user belongs to a group with permissions.
groupMembers, err := h.Store.Group.GetMembers(ctx)
if err != nil {
ctx.Transaction.Rollback()
response.WriteServerError(w, method, err)
h.Runtime.Log.Error(method, err)
return
}
for _, perm := range model.Permissions {
perm.OrgID = ctx.OrgID
perm.SpaceID = id
isGroup := perm.Who == permission.GroupPermission
groupRecords := []group.Record{}
if isGroup {
// get group records for just this group
groupRecords = group.FilterGroupRecords(groupMembers, perm.WhoID)
}
// Ensure the space owner always has access!
if perm.UserID == ctx.UserID {
if (!isGroup && perm.WhoID == ctx.UserID) ||
(isGroup && group.UserHasGroupMembership(groupMembers, perm.WhoID, ctx.UserID)) {
me = true
}
// Only persist if there is a role!
if permission.HasAnyPermission(perm) {
// identify publically shared spaces
if perm.UserID == "" {
perm.UserID = "0"
if perm.WhoID == "" {
perm.WhoID = user.EveryoneUserID
}
if perm.UserID == "0" {
if perm.WhoID == user.EveryoneUserID {
hasEveryoneRole = true
}
// Encode group/user permission and save to store.
r := permission.EncodeUserPermissions(perm)
roleCount++
for _, p := range r {
err = h.Store.Permission.AddPermission(ctx, p)
if err != nil {
h.Runtime.Log.Error("set permission", err)
ctx.Transaction.Rollback()
response.WriteServerError(w, method, err)
h.Runtime.Log.Error(method, err)
}
}
// We send out space invitation emails to those users
// that have *just* been given permissions.
if _, isExisting := previousRoleUsers[perm.UserID]; !isExisting {
if _, isExisting := previousRoleUsers[perm.WhoID]; !isExisting {
// we skip 'everyone'
if perm.WhoID != user.EveryoneUserID {
whoToEmail := []string{}
// we skip 'everyone' (user id != empty string)
if perm.UserID != "0" && perm.UserID != "" {
existingUser, err := h.Store.User.Get(ctx, perm.UserID)
if err != nil {
response.WriteServerError(w, method, err)
h.Runtime.Log.Error(method, err)
break
if isGroup {
// send email to each group member
for i := range groupRecords {
whoToEmail = append(whoToEmail, groupRecords[i].UserID)
}
} else {
// send email to individual user
whoToEmail = append(whoToEmail, perm.WhoID)
}
mailer := mail.Mailer{Runtime: h.Runtime, Store: h.Store, Context: ctx}
go mailer.ShareSpaceExistingUser(existingUser.Email, inviter.Fullname(), url, sp.Name, model.Message)
h.Runtime.Log.Info(fmt.Sprintf("%s is sharing space %s with existing user %s", inviter.Email, sp.Name, existingUser.Email))
for i := range whoToEmail {
existingUser, err := h.Store.User.Get(ctx, whoToEmail[i])
if err != nil {
h.Runtime.Log.Error(method, err)
continue
}
mailer := mail.Mailer{Runtime: h.Runtime, Store: h.Store, Context: ctx}
go mailer.ShareSpaceExistingUser(existingUser.Email, inviter.Fullname(), url, sp.Name, model.Message)
h.Runtime.Log.Info(fmt.Sprintf("%s is sharing space %s with existing user %s", inviter.Email, sp.Name, existingUser.Email))
}
}
}
}
@ -233,6 +268,7 @@ func (h *Handler) GetSpacePermissions(w http.ResponseWriter, r *http.Request) {
perms, err := h.Store.Permission.GetSpacePermissions(ctx, spaceID)
if err != nil && err != sql.ErrNoRows {
response.WriteServerError(w, method, err)
h.Runtime.Log.Error(method, err)
return
}
@ -246,6 +282,40 @@ func (h *Handler) GetSpacePermissions(w http.ResponseWriter, r *http.Request) {
records = append(records, permission.DecodeUserPermissions(up))
}
// populate user/group name for thing that has permission record
groups, err := h.Store.Group.GetAll(ctx)
if err != nil && err != sql.ErrNoRows {
response.WriteServerError(w, method, err)
h.Runtime.Log.Error(method, err)
return
}
for i := range records {
if records[i].Who == permission.GroupPermission {
for j := range groups {
if records[i].WhoID == groups[j].RefID {
records[i].Name = groups[j].Name
break
}
}
}
if records[i].Who == permission.UserPermission {
if records[i].WhoID == user.EveryoneUserID {
records[i].Name = "Everyone"
} else {
u, err := h.Store.User.Get(ctx, records[i].WhoID)
if err != nil {
h.Runtime.Log.Info(fmt.Sprintf("user not found %s", records[i].WhoID))
h.Runtime.Log.Error(method, err)
continue
}
records[i].Name = u.Fullname()
}
}
}
response.WriteJSON(w, records)
}
@ -261,7 +331,7 @@ func (h *Handler) GetUserSpacePermissions(w http.ResponseWriter, r *http.Request
}
perms, err := h.Store.Permission.GetUserSpacePermissions(ctx, spaceID)
if err != nil && err != sql.ErrNoRows {
if err != nil {
response.WriteServerError(w, method, err)
return
}
@ -464,11 +534,6 @@ func (h *Handler) SetDocumentPermissions(w http.ResponseWriter, r *http.Request)
return
}
// if !HasPermission(ctx, *h.Store, doc.LabelID, permission.SpaceManage, permission.SpaceOwner) {
// response.WriteForbiddenError(w)
// return
// }
defer streamutil.Close(r.Body)
body, err := ioutil.ReadAll(r.Body)
if err != nil {
@ -528,17 +593,38 @@ func (h *Handler) SetDocumentPermissions(w http.ResponseWriter, r *http.Request)
return
}
url := ctx.GetAppURL(fmt.Sprintf("s/%s/%s/d/%s/%s",
sp.RefID, stringutil.MakeSlug(sp.Name), doc.RefID, stringutil.MakeSlug(doc.Title)))
url := ctx.GetAppURL(fmt.Sprintf("s/%s/%s/d/%s/%s", sp.RefID, stringutil.MakeSlug(sp.Name), doc.RefID, stringutil.MakeSlug(doc.Title)))
// Permissions can be assigned to both groups and individual users.
// Pre-fetch users with group membership to help us work out
// if user belongs to a group with permissions.
groupMembers, err := h.Store.Group.GetMembers(ctx)
if err != nil {
ctx.Transaction.Rollback()
response.WriteServerError(w, method, err)
h.Runtime.Log.Error(method, err)
return
}
for _, perm := range model {
perm.OrgID = ctx.OrgID
perm.DocumentID = id
isGroup := perm.Who == permission.GroupPermission
groupRecords := []group.Record{}
if isGroup {
// get group records for just this group
groupRecords = group.FilterGroupRecords(groupMembers, perm.WhoID)
}
// Only persist if there is a role!
if permission.HasAnyDocumentPermission(perm) {
r := permission.EncodeUserDocumentPermissions(perm)
if perm.WhoID == "" {
perm.WhoID = user.EveryoneUserID
}
r := permission.EncodeUserDocumentPermissions(perm)
for _, p := range r {
err = h.Store.Permission.AddPermission(ctx, p)
if err != nil {
@ -547,19 +633,32 @@ func (h *Handler) SetDocumentPermissions(w http.ResponseWriter, r *http.Request)
}
// Send email notification to users who have been given document approver role
if _, isExisting := previousRoleUsers[perm.UserID]; !isExisting {
if _, isExisting := previousRoleUsers[perm.WhoID]; !isExisting {
// we skip 'everyone' as it has no email address!
if perm.WhoID != user.EveryoneUserID && perm.DocumentRoleApprove {
whoToEmail := []string{}
// we skip 'everyone' (user id != empty string)
if perm.UserID != "0" && perm.UserID != "" && perm.DocumentRoleApprove {
existingUser, err := h.Store.User.Get(ctx, perm.UserID)
if err != nil {
response.WriteServerError(w, method, err)
break
if isGroup {
// send email to each group member
for i := range groupRecords {
whoToEmail = append(whoToEmail, groupRecords[i].UserID)
}
} else {
// send email to individual user
whoToEmail = append(whoToEmail, perm.WhoID)
}
mailer := mail.Mailer{Runtime: h.Runtime, Store: h.Store, Context: ctx}
go mailer.DocumentApprover(existingUser.Email, inviter.Fullname(), url, doc.Title)
h.Runtime.Log.Info(fmt.Sprintf("%s has made %s document approver for: %s", inviter.Email, existingUser.Email, doc.Title))
for i := range whoToEmail {
existingUser, err := h.Store.User.Get(ctx, whoToEmail[i])
if err != nil {
h.Runtime.Log.Error(method, err)
continue
}
mailer := mail.Mailer{Runtime: h.Runtime, Store: h.Store, Context: ctx}
go mailer.DocumentApprover(existingUser.Email, inviter.Fullname(), url, doc.Title)
h.Runtime.Log.Info(fmt.Sprintf("%s has made %s document approver for: %s", inviter.Email, existingUser.Email, doc.Title))
}
}
}
}