mirror of
https://github.com/documize/community.git
synced 2025-08-05 05:25:27 +02:00
re-working space permissions -- WIP
This commit is contained in:
parent
c51ba65b1d
commit
ae05cacf3f
37 changed files with 735 additions and 601 deletions
|
@ -106,15 +106,16 @@ func (h *Handler) Add(w http.ResponseWriter, r *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
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()
|
||||
perm := space.Permission{}
|
||||
perm.OrgID = sp.OrgID
|
||||
perm.Who = "user"
|
||||
perm.WhoID = ctx.UserID
|
||||
perm.Scope = "object"
|
||||
perm.Location = "space"
|
||||
perm.RefID = sp.RefID
|
||||
perm.Action = "" // we send array for actions below
|
||||
|
||||
err = h.Store.Space.AddRole(ctx, role)
|
||||
err = h.Store.Space.AddPermissions(ctx, perm, space.SpaceOwner, space.SpaceManage, space.SpaceView)
|
||||
if err != nil {
|
||||
ctx.Transaction.Rollback()
|
||||
response.WriteServerError(w, method, err)
|
||||
|
@ -138,7 +139,7 @@ func (h *Handler) Add(w http.ResponseWriter, r *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
spCloneRoles, err := h.Store.Space.GetRoles(ctx, model.CloneID)
|
||||
spCloneRoles, err := h.Store.Space.GetPermissions(ctx, model.CloneID)
|
||||
if err != nil {
|
||||
response.WriteServerError(w, method, err)
|
||||
h.Runtime.Log.Error(method, err)
|
||||
|
@ -147,10 +148,9 @@ func (h *Handler) Add(w http.ResponseWriter, r *http.Request) {
|
|||
|
||||
if model.CopyPermission {
|
||||
for _, r := range spCloneRoles {
|
||||
r.RefID = uniqueid.Generate()
|
||||
r.LabelID = sp.RefID
|
||||
r.RefID = sp.RefID
|
||||
|
||||
err = h.Store.Space.AddRole(ctx, r)
|
||||
err = h.Store.Space.AddPermission(ctx, r)
|
||||
if err != nil {
|
||||
ctx.Transaction.Rollback()
|
||||
response.WriteServerError(w, method, err)
|
||||
|
@ -279,9 +279,9 @@ func (h *Handler) Get(w http.ResponseWriter, r *http.Request) {
|
|||
method := "Get"
|
||||
ctx := domain.GetRequestContext(r)
|
||||
|
||||
id := request.Param(r, "folderID")
|
||||
id := request.Param(r, "spaceID")
|
||||
if len(id) == 0 {
|
||||
response.WriteMissingDataError(w, method, "folderID")
|
||||
response.WriteMissingDataError(w, method, "spaceID")
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -349,9 +349,9 @@ func (h *Handler) Update(w http.ResponseWriter, r *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
folderID := request.Param(r, "folderID")
|
||||
if len(folderID) == 0 {
|
||||
response.WriteMissingDataError(w, method, "folderID")
|
||||
spaceID := request.Param(r, "spaceID")
|
||||
if len(spaceID) == 0 {
|
||||
response.WriteMissingDataError(w, method, "spaceID")
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -377,7 +377,7 @@ func (h *Handler) Update(w http.ResponseWriter, r *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
sp.RefID = folderID
|
||||
sp.RefID = spaceID
|
||||
|
||||
ctx.Transaction, err = h.Runtime.Db.Beginx()
|
||||
if err != nil {
|
||||
|
@ -401,7 +401,7 @@ func (h *Handler) Update(w http.ResponseWriter, r *http.Request) {
|
|||
response.WriteJSON(w, sp)
|
||||
}
|
||||
|
||||
// Remove moves documents to another folder before deleting it
|
||||
// Remove moves documents to another space before deleting it
|
||||
func (h *Handler) Remove(w http.ResponseWriter, r *http.Request) {
|
||||
method := "space.Remove"
|
||||
ctx := domain.GetRequestContext(r)
|
||||
|
@ -416,9 +416,9 @@ func (h *Handler) Remove(w http.ResponseWriter, r *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
id := request.Param(r, "folderID")
|
||||
id := request.Param(r, "spaceID")
|
||||
if len(id) == 0 {
|
||||
response.WriteMissingDataError(w, method, "folderID")
|
||||
response.WriteMissingDataError(w, method, "spaceID")
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -436,14 +436,6 @@ func (h *Handler) Remove(w http.ResponseWriter, r *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
_, err = h.Store.Space.Delete(ctx, id)
|
||||
if err != nil {
|
||||
ctx.Transaction.Rollback()
|
||||
response.WriteServerError(w, method, err)
|
||||
h.Runtime.Log.Error(method, err)
|
||||
return
|
||||
}
|
||||
|
||||
err = h.Store.Document.MoveDocumentSpace(ctx, id, move)
|
||||
if err != nil {
|
||||
ctx.Transaction.Rollback()
|
||||
|
@ -452,7 +444,15 @@ func (h *Handler) Remove(w http.ResponseWriter, r *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
err = h.Store.Space.MoveSpaceRoles(ctx, id, move)
|
||||
_, err = h.Store.Space.Delete(ctx, id)
|
||||
if err != nil {
|
||||
ctx.Transaction.Rollback()
|
||||
response.WriteServerError(w, method, err)
|
||||
h.Runtime.Log.Error(method, err)
|
||||
return
|
||||
}
|
||||
|
||||
_, err = h.Store.Space.DeletePermissions(ctx, id)
|
||||
if err != nil {
|
||||
ctx.Transaction.Rollback()
|
||||
response.WriteServerError(w, method, err)
|
||||
|
@ -490,9 +490,9 @@ func (h *Handler) Delete(w http.ResponseWriter, r *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
id := request.Param(r, "folderID")
|
||||
id := request.Param(r, "spaceID")
|
||||
if len(id) == 0 {
|
||||
response.WriteMissingDataError(w, method, "folderID")
|
||||
response.WriteMissingDataError(w, method, "spaceID")
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -512,7 +512,7 @@ func (h *Handler) Delete(w http.ResponseWriter, r *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
_, err = h.Store.Space.DeleteSpaceRoles(ctx, id)
|
||||
_, err = h.Store.Space.DeletePermissions(ctx, id)
|
||||
if err != nil {
|
||||
ctx.Transaction.Rollback()
|
||||
response.WriteServerError(w, method, err)
|
||||
|
@ -545,9 +545,9 @@ func (h *Handler) SetPermissions(w http.ResponseWriter, r *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
id := request.Param(r, "folderID")
|
||||
id := request.Param(r, "spaceID")
|
||||
if len(id) == 0 {
|
||||
response.WriteMissingDataError(w, method, "folderID")
|
||||
response.WriteMissingDataError(w, method, "spaceID")
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -586,8 +586,8 @@ func (h *Handler) SetPermissions(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
|
||||
// We compare new permisions to what we had before.
|
||||
// Why? So we can send out folder invitation emails.
|
||||
previousRoles, err := h.Store.Space.GetRoles(ctx, id)
|
||||
// Why? So we can send out space invitation emails.
|
||||
previousRoles, err := h.Store.Space.GetPermissions(ctx, id)
|
||||
if err != nil {
|
||||
ctx.Transaction.Rollback()
|
||||
response.WriteServerError(w, method, err)
|
||||
|
@ -599,10 +599,10 @@ func (h *Handler) SetPermissions(w http.ResponseWriter, r *http.Request) {
|
|||
previousRoleUsers := make(map[string]bool)
|
||||
|
||||
for _, v := range previousRoles {
|
||||
previousRoleUsers[v.UserID] = true
|
||||
previousRoleUsers[v.WhoID] = true
|
||||
}
|
||||
|
||||
// Who is sharing this folder?
|
||||
// Who is sharing this space?
|
||||
inviter, err := h.Store.User.Get(ctx, ctx.UserID)
|
||||
if err != nil {
|
||||
ctx.Transaction.Rollback()
|
||||
|
@ -611,8 +611,8 @@ func (h *Handler) SetPermissions(w http.ResponseWriter, r *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
// Nuke all previous permissions for this folder
|
||||
_, err = h.Store.Space.DeleteSpaceRoles(ctx, id)
|
||||
// Nuke all previous permissions for this space
|
||||
_, err = h.Store.Space.DeletePermissions(ctx, id)
|
||||
if err != nil {
|
||||
ctx.Transaction.Rollback()
|
||||
response.WriteServerError(w, method, err)
|
||||
|
@ -626,44 +626,40 @@ func (h *Handler) SetPermissions(w http.ResponseWriter, r *http.Request) {
|
|||
|
||||
url := ctx.GetAppURL(fmt.Sprintf("s/%s/%s", sp.RefID, stringutil.MakeSlug(sp.Name)))
|
||||
|
||||
for _, role := range model.Roles {
|
||||
role.OrgID = ctx.OrgID
|
||||
role.LabelID = id
|
||||
for _, perm := range model.Permissions {
|
||||
perm.OrgID = ctx.OrgID
|
||||
perm.RefID = id
|
||||
|
||||
// Ensure the folder owner always has access!
|
||||
if role.UserID == ctx.UserID {
|
||||
// Ensure the space owner always has access!
|
||||
if perm.WhoID == ctx.UserID {
|
||||
me = true
|
||||
role.CanView = true
|
||||
role.CanEdit = true
|
||||
}
|
||||
|
||||
if len(role.UserID) == 0 && (role.CanView || role.CanEdit) {
|
||||
if len(perm.WhoID) == 0 {
|
||||
hasEveryoneRole = true
|
||||
}
|
||||
|
||||
// Only persist if there is a role!
|
||||
if role.CanView || role.CanEdit {
|
||||
roleID := uniqueid.Generate()
|
||||
role.RefID = roleID
|
||||
err = h.Store.Space.AddRole(ctx, role)
|
||||
if perm.Action == "TBC" {
|
||||
err = h.Store.Space.AddPermission(ctx, perm)
|
||||
if err != nil {
|
||||
h.Runtime.Log.Error("add role", err)
|
||||
}
|
||||
|
||||
roleCount++
|
||||
|
||||
// We send out folder invitation emails to those users
|
||||
// We send out space invitation emails to those users
|
||||
// that have *just* been given permissions.
|
||||
if _, isExisting := previousRoleUsers[role.UserID]; !isExisting {
|
||||
if _, isExisting := previousRoleUsers[perm.WhoID]; !isExisting {
|
||||
|
||||
// we skip 'everyone' (user id != empty string)
|
||||
if len(role.UserID) > 0 {
|
||||
if len(perm.WhoID) > 0 {
|
||||
var existingUser user.User
|
||||
existingUser, err = h.Store.User.Get(ctx, role.UserID)
|
||||
existingUser, err = h.Store.User.Get(ctx, perm.WhoID)
|
||||
|
||||
if err == nil {
|
||||
mailer := mail.Mailer{Runtime: h.Runtime, Store: h.Store, Context: ctx}
|
||||
go mailer.ShareFolderExistingUser(existingUser.Email, inviter.Fullname(), url, sp.Name, model.Message)
|
||||
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))
|
||||
} else {
|
||||
response.WriteServerError(w, method, err)
|
||||
|
@ -675,16 +671,16 @@ func (h *Handler) SetPermissions(w http.ResponseWriter, r *http.Request) {
|
|||
|
||||
// Do we need to ensure permissions for space owner when shared?
|
||||
if !me {
|
||||
role := space.Role{}
|
||||
role.LabelID = id
|
||||
role.OrgID = ctx.OrgID
|
||||
role.UserID = ctx.UserID
|
||||
role.CanEdit = true
|
||||
role.CanView = true
|
||||
roleID := uniqueid.Generate()
|
||||
role.RefID = roleID
|
||||
perm := space.Permission{}
|
||||
perm.OrgID = ctx.OrgID
|
||||
perm.Who = "user"
|
||||
perm.WhoID = ctx.UserID
|
||||
perm.Scope = "object"
|
||||
perm.Location = "space"
|
||||
perm.RefID = id
|
||||
perm.Action = "" // we send array for actions below
|
||||
|
||||
err = h.Store.Space.AddRole(ctx, role)
|
||||
err = h.Store.Space.AddPermission(ctx, perm)
|
||||
if err != nil {
|
||||
ctx.Transaction.Rollback()
|
||||
response.WriteServerError(w, method, err)
|
||||
|
@ -692,7 +688,7 @@ func (h *Handler) SetPermissions(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
}
|
||||
|
||||
// Mark up folder type as either public, private or restricted access.
|
||||
// Mark up space type as either public, private or restricted access.
|
||||
if hasEveryoneRole {
|
||||
sp.Type = space.ScopePublic
|
||||
} else {
|
||||
|
@ -718,28 +714,52 @@ func (h *Handler) SetPermissions(w http.ResponseWriter, r *http.Request) {
|
|||
response.WriteEmpty(w)
|
||||
}
|
||||
|
||||
// GetPermissions returns user permissions for the requested folder.
|
||||
// GetPermissions returns permissions for the requested space, for all users.
|
||||
func (h *Handler) GetPermissions(w http.ResponseWriter, r *http.Request) {
|
||||
method := "space.GetPermissions"
|
||||
ctx := domain.GetRequestContext(r)
|
||||
|
||||
folderID := request.Param(r, "folderID")
|
||||
if len(folderID) == 0 {
|
||||
response.WriteMissingDataError(w, method, "folderID")
|
||||
spaceID := request.Param(r, "spaceID")
|
||||
if len(spaceID) == 0 {
|
||||
response.WriteMissingDataError(w, method, "spaceID")
|
||||
return
|
||||
}
|
||||
|
||||
roles, err := h.Store.Space.GetRoles(ctx, folderID)
|
||||
perms, err := h.Store.Space.GetPermissions(ctx, spaceID)
|
||||
if err != nil && err != sql.ErrNoRows {
|
||||
response.WriteServerError(w, method, err)
|
||||
return
|
||||
}
|
||||
|
||||
if len(roles) == 0 {
|
||||
roles = []space.Role{}
|
||||
if len(perms) == 0 {
|
||||
perms = []space.Permission{}
|
||||
}
|
||||
|
||||
response.WriteJSON(w, roles)
|
||||
response.WriteJSON(w, perms)
|
||||
}
|
||||
|
||||
// GetUserPermissions returns permissions for the requested space, for current user.
|
||||
func (h *Handler) GetUserPermissions(w http.ResponseWriter, r *http.Request) {
|
||||
method := "space.GetUserPermissions"
|
||||
ctx := domain.GetRequestContext(r)
|
||||
|
||||
spaceID := request.Param(r, "spaceID")
|
||||
if len(spaceID) == 0 {
|
||||
response.WriteMissingDataError(w, method, "spaceID")
|
||||
return
|
||||
}
|
||||
|
||||
perms, err := h.Store.Space.GetUserPermissions(ctx, spaceID)
|
||||
if err != nil && err != sql.ErrNoRows {
|
||||
response.WriteServerError(w, method, err)
|
||||
return
|
||||
}
|
||||
|
||||
if len(perms) == 0 {
|
||||
perms = []space.Permission{}
|
||||
}
|
||||
|
||||
response.WriteJSON(w, perms)
|
||||
}
|
||||
|
||||
// AcceptInvitation records the fact that a user has completed space onboard process.
|
||||
|
@ -747,10 +767,10 @@ func (h *Handler) AcceptInvitation(w http.ResponseWriter, r *http.Request) {
|
|||
method := "space.AcceptInvitation"
|
||||
ctx := domain.GetRequestContext(r)
|
||||
ctx.Subdomain = organization.GetSubdomainFromHost(r)
|
||||
|
||||
folderID := request.Param(r, "folderID")
|
||||
if len(folderID) == 0 {
|
||||
response.WriteMissingDataError(w, method, "folderID")
|
||||
|
||||
spaceID := request.Param(r, "spaceID")
|
||||
if len(spaceID) == 0 {
|
||||
response.WriteMissingDataError(w, method, "spaceID")
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -831,14 +851,14 @@ func (h *Handler) AcceptInvitation(w http.ResponseWriter, r *http.Request) {
|
|||
response.WriteJSON(w, u)
|
||||
}
|
||||
|
||||
// Invite sends users folder invitation emails.
|
||||
// Invite sends users space invitation emails.
|
||||
func (h *Handler) Invite(w http.ResponseWriter, r *http.Request) {
|
||||
method := "space.Invite"
|
||||
ctx := domain.GetRequestContext(r)
|
||||
|
||||
id := request.Param(r, "folderID")
|
||||
id := request.Param(r, "spaceID")
|
||||
if len(id) == 0 {
|
||||
response.WriteMissingDataError(w, method, "folderID")
|
||||
response.WriteMissingDataError(w, method, "spaceID")
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -917,6 +937,7 @@ func (h *Handler) Invite(w http.ResponseWriter, r *http.Request) {
|
|||
a.OrgID = ctx.OrgID
|
||||
a.Admin = false
|
||||
a.Editor = false
|
||||
a.Users = false
|
||||
a.Active = true
|
||||
accountID := uniqueid.Generate()
|
||||
a.RefID = accountID
|
||||
|
@ -931,18 +952,18 @@ func (h *Handler) Invite(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
|
||||
// Ensure they have space roles
|
||||
h.Store.Space.DeleteUserSpaceRoles(ctx, sp.RefID, u.RefID)
|
||||
h.Store.Space.DeleteUserPermissions(ctx, sp.RefID, u.RefID)
|
||||
|
||||
role := space.Role{}
|
||||
role.LabelID = sp.RefID
|
||||
role.OrgID = ctx.OrgID
|
||||
role.UserID = u.RefID
|
||||
role.CanEdit = false
|
||||
role.CanView = true
|
||||
roleID := uniqueid.Generate()
|
||||
role.RefID = roleID
|
||||
perm := space.Permission{}
|
||||
perm.OrgID = sp.OrgID
|
||||
perm.Who = "user"
|
||||
perm.WhoID = u.RefID
|
||||
perm.Scope = "object"
|
||||
perm.Location = "space"
|
||||
perm.RefID = sp.RefID
|
||||
perm.Action = "" // we send array for actions below
|
||||
|
||||
err = h.Store.Space.AddRole(ctx, role)
|
||||
err = h.Store.Space.AddPermissions(ctx, perm, space.SpaceView)
|
||||
if err != nil {
|
||||
ctx.Transaction.Rollback()
|
||||
response.WriteServerError(w, method, err)
|
||||
|
@ -952,7 +973,7 @@ func (h *Handler) Invite(w http.ResponseWriter, r *http.Request) {
|
|||
|
||||
url := ctx.GetAppURL(fmt.Sprintf("s/%s/%s", sp.RefID, stringutil.MakeSlug(sp.Name)))
|
||||
mailer := mail.Mailer{Runtime: h.Runtime, Store: h.Store, Context: ctx}
|
||||
go mailer.ShareFolderExistingUser(email, inviter.Fullname(), url, sp.Name, model.Message)
|
||||
go mailer.ShareSpaceExistingUser(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, email))
|
||||
} else {
|
||||
|
@ -973,7 +994,7 @@ func (h *Handler) Invite(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
}
|
||||
|
||||
// We ensure that the folder is marked as restricted as a minimum!
|
||||
// We ensure that the space is marked as restricted as a minimum!
|
||||
if len(model.Recipients) > 0 && sp.Type == space.ScopePrivate {
|
||||
sp.Type = space.ScopeRestricted
|
||||
|
||||
|
|
|
@ -184,109 +184,98 @@ func (s Scope) Delete(ctx domain.RequestContext, id string) (rows int64, err err
|
|||
return b.DeleteConstrained(ctx.Transaction, "label", ctx.OrgID, id)
|
||||
}
|
||||
|
||||
// AddRole inserts the given record into the labelrole database table.
|
||||
func (s Scope) AddRole(ctx domain.RequestContext, r space.Role) (err error) {
|
||||
// AddPermission inserts the given record into the labelrole database table.
|
||||
func (s Scope) AddPermission(ctx domain.RequestContext, r space.Permission) (err error) {
|
||||
r.Created = time.Now().UTC()
|
||||
r.Revised = time.Now().UTC()
|
||||
|
||||
stmt, err := ctx.Transaction.Preparex("INSERT INTO labelrole (refid, labelid, orgid, userid, canview, canedit, created, revised) VALUES (?, ?, ?, ?, ?, ?, ?, ?)")
|
||||
stmt, err := ctx.Transaction.Preparex("INSERT INTO labelrole (orgid, who, whoid, action, scope, location, refid, created) VALUES (?, ?, ?, ?, ?, ?, ?, ?)")
|
||||
defer streamutil.Close(stmt)
|
||||
|
||||
if err != nil {
|
||||
err = errors.Wrap(err, "unable to prepare insert for space role")
|
||||
err = errors.Wrap(err, "unable to prepare insert for space permission")
|
||||
return
|
||||
}
|
||||
|
||||
_, err = stmt.Exec(r.RefID, r.LabelID, r.OrgID, r.UserID, r.CanView, r.CanEdit, r.Created, r.Revised)
|
||||
_, err = stmt.Exec(r.OrgID, r.Who, r.WhoID, r.Action, r.Scope, r.Location, r.RefID, r.Created)
|
||||
if err != nil {
|
||||
err = errors.Wrap(err, "unable to execute insert for space role")
|
||||
err = errors.Wrap(err, "unable to execute insert for space permission")
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// GetRoles returns a slice of labelrole records, for the given labelID in the client's organization, grouped by user.
|
||||
func (s Scope) GetRoles(ctx domain.RequestContext, labelID string) (r []space.Role, err error) {
|
||||
query := `SELECT id, refid, labelid, orgid, userid, canview, canedit, created, revised FROM labelrole WHERE orgid=? AND labelid=?` // was + "GROUP BY userid"
|
||||
|
||||
err = s.Runtime.Db.Select(&r, query, ctx.OrgID, labelID)
|
||||
|
||||
if err == sql.ErrNoRows {
|
||||
err = nil
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
err = errors.Wrap(err, fmt.Sprintf("unable to execute select for space roles %s", labelID))
|
||||
return
|
||||
// AddPermissions inserts records into permission database table, one per action.
|
||||
func (s Scope) AddPermissions(ctx domain.RequestContext, r space.Permission, actions ...space.PermissionAction) (err error) {
|
||||
for _, a := range actions {
|
||||
r.Action = string(a)
|
||||
s.AddPermission(ctx, r)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// GetUserRoles returns a slice of role records, for both the client's user and organization, and
|
||||
// those space roles that exist for all users in the client's organization.
|
||||
func (s Scope) GetUserRoles(ctx domain.RequestContext) (r []space.Role, err error) {
|
||||
// GetUserPermissions returns space permissions for user.
|
||||
// Context is used to for user ID.
|
||||
func (s Scope) GetUserPermissions(ctx domain.RequestContext, spaceID string) (r []space.Permission, err error) {
|
||||
err = s.Runtime.Db.Select(&r, `
|
||||
SELECT id, refid, labelid, orgid, userid, canview, canedit, created, revised FROM labelrole WHERE orgid=? and userid=?
|
||||
SELECT id, orgid, who, whoid, action, scope, location, refid
|
||||
FROM permission WHERE orgid=? AND location='space' AND refid=? AND who='user' AND (whoid=? OR whoid='')
|
||||
UNION ALL
|
||||
SELECT id, refid, labelid, orgid, userid, canview, canedit, created, revised FROM labelrole WHERE orgid=? AND userid=''`,
|
||||
ctx.OrgID, ctx.UserID, ctx.OrgID)
|
||||
SELECT p.id, p.orgid, p.who, p.whoid, p.action, p.scope, p.location, p.refid
|
||||
FROM permission p LEFT JOIN rolemember r ON p.whoid=r.roleid WHERE p.orgid=? AND p.location='space' AND refid=?
|
||||
AND p.who='role' AND (r.userid=? OR r.userid='')`,
|
||||
ctx.OrgID, spaceID, ctx.UserID, ctx.OrgID, spaceID, ctx.OrgID)
|
||||
|
||||
if err == sql.ErrNoRows {
|
||||
err = nil
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
err = errors.Wrap(err, fmt.Sprintf("unable to execute select for user space roles %s", ctx.UserID))
|
||||
err = errors.Wrap(err, fmt.Sprintf("unable to execute select user permissions %s", ctx.UserID))
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// DeleteRole deletes the labelRoleID record from the labelrole table.
|
||||
func (s Scope) DeleteRole(ctx domain.RequestContext, roleID string) (rows int64, err error) {
|
||||
// GetPermissions returns space permissions for all users.
|
||||
func (s Scope) GetPermissions(ctx domain.RequestContext, spaceID string) (r []space.Permission, err error) {
|
||||
err = s.Runtime.Db.Select(&r, `
|
||||
SELECT id, orgid, who, whoid, action, scope, location, refid
|
||||
FROM permission WHERE orgid=? AND location='space' AND refid=? AND who='user' AND (whoid=? OR whoid='')
|
||||
UNION ALL
|
||||
SELECT p.id, p.orgid, p.who, p.whoid, p.action, p.scope, p.location, p.refid
|
||||
FROM permission p LEFT JOIN rolemember r ON p.whoid=r.roleid WHERE p.orgid=? AND p.location='space' AND p.refid=?
|
||||
AND p.who='role' AND (r.userid=? OR r.userid='')`,
|
||||
ctx.OrgID, spaceID, ctx.UserID, ctx.OrgID, spaceID, ctx.OrgID)
|
||||
|
||||
if err == sql.ErrNoRows {
|
||||
err = nil
|
||||
}
|
||||
if err != nil {
|
||||
err = errors.Wrap(err, fmt.Sprintf("unable to execute select space permissions %s", ctx.UserID))
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// DeletePermissions removes records from permissions table for given space ID.
|
||||
func (s Scope) DeletePermissions(ctx domain.RequestContext, spaceID string) (rows int64, err error) {
|
||||
b := mysql.BaseQuery{}
|
||||
|
||||
sql := fmt.Sprintf("DELETE FROM labelrole WHERE orgid='%s' AND refid='%s'", ctx.OrgID, roleID)
|
||||
sql := fmt.Sprintf("DELETE FROM permission WHERE orgid='%s' AND location='space' AND refid='%s'",
|
||||
ctx.OrgID, spaceID)
|
||||
|
||||
return b.DeleteWhere(ctx.Transaction, sql)
|
||||
}
|
||||
|
||||
// DeleteSpaceRoles deletes records from the labelrole table which have the given space ID.
|
||||
func (s Scope) DeleteSpaceRoles(ctx domain.RequestContext, spaceID string) (rows int64, err error) {
|
||||
// DeleteUserPermissions removes all roles for the specified user, for the specified space.
|
||||
func (s Scope) DeleteUserPermissions(ctx domain.RequestContext, spaceID, userID string) (rows int64, err error) {
|
||||
b := mysql.BaseQuery{}
|
||||
|
||||
sql := fmt.Sprintf("DELETE FROM labelrole WHERE orgid='%s' AND labelid='%s'", ctx.OrgID, spaceID)
|
||||
|
||||
return b.DeleteWhere(ctx.Transaction, sql)
|
||||
}
|
||||
|
||||
// DeleteUserSpaceRoles removes all roles for the specified user, for the specified space.
|
||||
func (s Scope) DeleteUserSpaceRoles(ctx domain.RequestContext, spaceID, userID string) (rows int64, err error) {
|
||||
b := mysql.BaseQuery{}
|
||||
|
||||
sql := fmt.Sprintf("DELETE FROM labelrole WHERE orgid='%s' AND labelid='%s' AND userid='%s'",
|
||||
sql := fmt.Sprintf("DELETE FROM permission WHERE orgid='%s' AND location='space' AND refid='%s' who='user' AND whoid='%s'",
|
||||
ctx.OrgID, spaceID, userID)
|
||||
|
||||
return b.DeleteWhere(ctx.Transaction, sql)
|
||||
}
|
||||
|
||||
// MoveSpaceRoles changes the space ID for space role records from previousLabel to newLabel.
|
||||
func (s Scope) MoveSpaceRoles(ctx domain.RequestContext, previousLabel, newLabel string) (err error) {
|
||||
stmt, err := ctx.Transaction.Preparex("UPDATE labelrole SET labelid=? WHERE labelid=? AND orgid=?")
|
||||
defer streamutil.Close(stmt)
|
||||
|
||||
if err != nil {
|
||||
err = errors.Wrap(err, fmt.Sprintf("unable to prepare move space roles for label %s", previousLabel))
|
||||
return
|
||||
}
|
||||
|
||||
_, err = stmt.Exec(newLabel, previousLabel, ctx.OrgID)
|
||||
if err != nil {
|
||||
err = errors.Wrap(err, fmt.Sprintf("unable to execute move space roles for label %s", previousLabel))
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
|
|
@ -17,11 +17,12 @@ import (
|
|||
"database/sql"
|
||||
|
||||
"github.com/documize/community/domain"
|
||||
"github.com/documize/community/model/space"
|
||||
)
|
||||
|
||||
// CanViewSpace returns if the user has permission to view the given spaceID.
|
||||
func CanViewSpace(ctx domain.RequestContext, s domain.Store, spaceID string) (hasPermission bool) {
|
||||
roles, err := s.Space.GetRoles(ctx, spaceID)
|
||||
func CanViewSpace(ctx domain.RequestContext, s domain.Store, spaceID string) bool {
|
||||
roles, err := s.Space.GetUserPermissions(ctx, spaceID)
|
||||
if err == sql.ErrNoRows {
|
||||
err = nil
|
||||
}
|
||||
|
@ -30,27 +31,8 @@ func CanViewSpace(ctx domain.RequestContext, s domain.Store, spaceID string) (ha
|
|||
}
|
||||
|
||||
for _, role := range roles {
|
||||
if role.LabelID == spaceID && (role.CanView || role.CanEdit) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// CanViewSpaceDocuments returns if the user has permission to view a document within the specified space.
|
||||
func CanViewSpaceDocuments(ctx domain.RequestContext, s domain.Store, spaceID string) (hasPermission bool) {
|
||||
roles, err := s.Space.GetRoles(ctx, spaceID)
|
||||
if err == sql.ErrNoRows {
|
||||
err = nil
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
for _, role := range roles {
|
||||
if role.LabelID == spaceID && (role.CanView || role.CanEdit) {
|
||||
if role.RefID == spaceID && role.Location == "space" && role.Scope == "object" &&
|
||||
space.HasPermission(role.Action, space.SpaceView, space.SpaceManage, space.SpaceOwner) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,33 +24,10 @@ import (
|
|||
"github.com/documize/community/model/user"
|
||||
)
|
||||
|
||||
// addSpace prepares and creates space record.
|
||||
func addSpace(ctx domain.RequestContext, s *domain.Store, sp space.Space) (err error) {
|
||||
sp.Type = space.ScopePrivate
|
||||
sp.UserID = ctx.UserID
|
||||
|
||||
err = s.Space.Add(ctx, sp)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
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 = s.Space.AddRole(ctx, role)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// Invite new user to a folder that someone has shared with them.
|
||||
// Invite new user to a space that someone has shared with them.
|
||||
// We create the user account with default values and then take them
|
||||
// through a welcome process designed to capture profile data.
|
||||
// We add them to the organization and grant them view-only folder access.
|
||||
// We add them to the organization and grant them view-only space access.
|
||||
func inviteNewUserToSharedSpace(ctx domain.RequestContext, rt *env.Runtime, s *domain.Store, email string, invitedBy user.User,
|
||||
baseURL string, sp space.Space, invitationMessage string) (err error) {
|
||||
|
||||
|
@ -75,25 +52,25 @@ func inviteNewUserToSharedSpace(ctx domain.RequestContext, rt *env.Runtime, s *d
|
|||
a.OrgID = ctx.OrgID
|
||||
a.Admin = false
|
||||
a.Editor = false
|
||||
a.Users = false
|
||||
a.Active = true
|
||||
accountID := uniqueid.Generate()
|
||||
a.RefID = accountID
|
||||
a.RefID = uniqueid.Generate()
|
||||
|
||||
err = s.Account.Add(ctx, a)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
role := space.Role{}
|
||||
role.LabelID = sp.RefID
|
||||
role.OrgID = ctx.OrgID
|
||||
role.UserID = userID
|
||||
role.CanEdit = false
|
||||
role.CanView = true
|
||||
roleID := uniqueid.Generate()
|
||||
role.RefID = roleID
|
||||
perm := space.Permission{}
|
||||
perm.OrgID = sp.OrgID
|
||||
perm.Who = "user"
|
||||
perm.WhoID = userID
|
||||
perm.Scope = "object"
|
||||
perm.Location = "space"
|
||||
perm.RefID = sp.RefID
|
||||
perm.Action = "" // we send array for actions below
|
||||
|
||||
err = s.Space.AddRole(ctx, role)
|
||||
err = s.Space.AddPermissions(ctx, perm, space.SpaceView)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
@ -101,7 +78,7 @@ func inviteNewUserToSharedSpace(ctx domain.RequestContext, rt *env.Runtime, s *d
|
|||
mailer := mail.Mailer{Runtime: rt, Store: s, Context: ctx}
|
||||
|
||||
url := fmt.Sprintf("%s/%s", baseURL, u.Salt)
|
||||
go mailer.ShareFolderNewUser(u.Email, invitedBy.Fullname(), url, sp.Name, invitationMessage)
|
||||
go mailer.ShareSpaceNewUser(u.Email, invitedBy.Fullname(), url, sp.Name, invitationMessage)
|
||||
|
||||
return
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package space
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"testing"
|
||||
|
||||
"github.com/documize/community/core/uniqueid"
|
||||
|
@ -39,17 +38,19 @@ func TestSpace(t *testing.T) {
|
|||
t.Error("failed to add sp space")
|
||||
}
|
||||
|
||||
r.RefID = uniqueid.Generate()
|
||||
r.LabelID = spaceID
|
||||
r.OrgID = ctx.OrgID
|
||||
r.UserID = "testAddSpace"
|
||||
r.CanView = true
|
||||
r.CanEdit = true
|
||||
perm := space.Permission{}
|
||||
perm.OrgID = ctx.OrgID
|
||||
perm.Who = "user"
|
||||
perm.WhoID = ctx.UserID
|
||||
perm.Scope = "object"
|
||||
perm.Location = "space"
|
||||
perm.RefID = spaceID
|
||||
perm.Action = "" // we send array for actions below
|
||||
|
||||
err = s.Space.AddRole(ctx, r)
|
||||
err = s.Space.AddPermissions(ctx, perm, space.SpaceOwner, space.SpaceManage, space.SpaceView)
|
||||
if err != nil {
|
||||
ctx.Transaction.Rollback()
|
||||
t.Error("failed to add role r")
|
||||
t.Error("failed to add permission")
|
||||
}
|
||||
|
||||
ctx.Transaction.Commit()
|
||||
|
@ -104,17 +105,19 @@ func TestSpace(t *testing.T) {
|
|||
t.Error("failed to add sp2")
|
||||
}
|
||||
|
||||
r2.RefID = uniqueid.Generate()
|
||||
r2.LabelID = spaceID2
|
||||
r2.OrgID = ctx.OrgID
|
||||
r2.UserID = ctx.UserID
|
||||
r2.CanView = true
|
||||
r2.CanEdit = true
|
||||
perm := space.Permission{}
|
||||
perm.OrgID = ctx.OrgID
|
||||
perm.Who = "user"
|
||||
perm.WhoID = ctx.UserID
|
||||
perm.Scope = "object"
|
||||
perm.Location = "space"
|
||||
perm.RefID = spaceID2
|
||||
perm.Action = "" // we send array for actions below
|
||||
|
||||
err = s.Space.AddRole(ctx, r2)
|
||||
err = s.Space.AddPermissions(ctx, perm, space.SpaceOwner, space.SpaceManage, space.SpaceView)
|
||||
if err != nil {
|
||||
ctx.Transaction.Rollback()
|
||||
t.Error("failed to add role")
|
||||
t.Error("failed to add permission")
|
||||
}
|
||||
|
||||
ctx.Transaction.Commit()
|
||||
|
@ -171,22 +174,24 @@ func TestSpace(t *testing.T) {
|
|||
t.Run("Add Role", func(t *testing.T) {
|
||||
ctx.Transaction, err = rt.Db.Beginx()
|
||||
|
||||
r3.CanView = true
|
||||
r3.CanEdit = true
|
||||
r3.RefID = uniqueid.Generate()
|
||||
r3.LabelID = spaceID
|
||||
r3.OrgID = ctx.OrgID
|
||||
r3.UserID = "testAddRole"
|
||||
perm := space.Permission{}
|
||||
perm.OrgID = ctx.OrgID
|
||||
perm.Who = "user"
|
||||
perm.WhoID = ctx.UserID
|
||||
perm.Scope = "object"
|
||||
perm.Location = "space"
|
||||
perm.RefID = spaceID
|
||||
perm.Action = "" // we send array for actions below
|
||||
|
||||
err = s.Space.AddRole(ctx, r3)
|
||||
err = s.Space.AddPermissions(ctx, perm, space.DocumentAdd, space.DocumentDelete, space.DocumentMove)
|
||||
if err != nil {
|
||||
ctx.Transaction.Rollback()
|
||||
t.Error("failed to add role")
|
||||
return
|
||||
t.Error("failed to add permission")
|
||||
}
|
||||
|
||||
ctx.Transaction.Commit()
|
||||
|
||||
roles, err := s.Space.GetRoles(ctx, spaceID)
|
||||
roles, err := s.Space.GetUserPermissions(ctx, spaceID)
|
||||
if err != nil || roles == nil {
|
||||
t.Error("Could not get any roles")
|
||||
return
|
||||
|
@ -194,61 +199,16 @@ func TestSpace(t *testing.T) {
|
|||
// TODO: could we Verify the role was added with the if r3.UserID == Returned.UserID?
|
||||
})
|
||||
|
||||
t.Run("Get User Roles", func(t *testing.T) {
|
||||
userRoles, err := s.Space.GetUserRoles(ctx)
|
||||
t.Run("Get User Permissions", func(t *testing.T) {
|
||||
userRoles, err := s.Space.GetUserPermissions(ctx, spaceID)
|
||||
if err != nil || userRoles == nil {
|
||||
t.Error("failed to get user roles")
|
||||
return
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("Move space Roles", func(t *testing.T) {
|
||||
ctx.Transaction, err = rt.Db.Beginx()
|
||||
err := s.Space.MoveSpaceRoles(ctx, spaceID, spaceID2)
|
||||
if err != nil {
|
||||
ctx.Transaction.Rollback()
|
||||
t.Error("failed to move space roles")
|
||||
return
|
||||
}
|
||||
ctx.Transaction.Commit()
|
||||
})
|
||||
|
||||
t.Run("Delete Role", func(t *testing.T) {
|
||||
ctx.Transaction, err = rt.Db.Beginx()
|
||||
rowsDeleted, err := s.Space.DeleteRole(ctx, r3.RefID)
|
||||
if err != nil || rowsDeleted == 0 {
|
||||
ctx.Transaction.Rollback()
|
||||
t.Error("failed to delete roles")
|
||||
return
|
||||
}
|
||||
ctx.Transaction.Commit()
|
||||
})
|
||||
|
||||
t.Run("Delete space Roles", func(t *testing.T) {
|
||||
ctx.Transaction, err = rt.Db.Beginx()
|
||||
_, err := s.Space.DeleteSpaceRoles(ctx, spaceID)
|
||||
if err != nil && err != sql.ErrNoRows {
|
||||
ctx.Transaction.Rollback()
|
||||
t.Error("failed to delete space roles")
|
||||
return
|
||||
}
|
||||
ctx.Transaction.Commit()
|
||||
})
|
||||
|
||||
t.Run("Delete user space Roles", func(t *testing.T) {
|
||||
ctx.Transaction, err = rt.Db.Beginx()
|
||||
_, err := s.Space.DeleteUserSpaceRoles(ctx, spaceID2, ctx.UserID)
|
||||
if err != nil && err != sql.ErrNoRows {
|
||||
ctx.Transaction.Rollback()
|
||||
t.Error("failed to delete user space roles")
|
||||
return
|
||||
}
|
||||
ctx.Transaction.Commit()
|
||||
})
|
||||
|
||||
//Delete spaces last, otherwise tests may fail
|
||||
|
||||
t.Run("Delete Space", func(t *testing.T) {
|
||||
// teardown
|
||||
t.Run("Delete space", func(t *testing.T) {
|
||||
ctx.Transaction, err = rt.Db.Beginx()
|
||||
|
||||
_, err = s.Space.Delete(ctx, spaceID)
|
||||
|
@ -261,11 +221,7 @@ func TestSpace(t *testing.T) {
|
|||
ctx.Transaction.Commit()
|
||||
})
|
||||
|
||||
//
|
||||
// teardown code goes here
|
||||
//
|
||||
|
||||
t.Run("Delete sp2 Space", func(t *testing.T) {
|
||||
t.Run("Delete space 2", func(t *testing.T) {
|
||||
ctx.Transaction, err = rt.Db.Beginx()
|
||||
|
||||
_, err = s.Space.Delete(ctx, spaceID2)
|
||||
|
@ -277,15 +233,4 @@ func TestSpace(t *testing.T) {
|
|||
|
||||
ctx.Transaction.Commit()
|
||||
})
|
||||
|
||||
t.Run("Delete r Role", func(t *testing.T) {
|
||||
ctx.Transaction, err = rt.Db.Beginx()
|
||||
rowsDeleted, err := s.Space.DeleteRole(ctx, r.RefID)
|
||||
if err != nil || rowsDeleted == 0 {
|
||||
ctx.Transaction.Rollback()
|
||||
t.Error("failed to delete role r in teardown")
|
||||
return
|
||||
}
|
||||
ctx.Transaction.Commit()
|
||||
})
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue