mirror of
https://github.com/documize/community.git
synced 2025-07-19 13:19:43 +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
|
@ -34,7 +34,7 @@ func (s Scope) Add(ctx domain.RequestContext, account account.Account) (err erro
|
|||
account.Created = time.Now().UTC()
|
||||
account.Revised = time.Now().UTC()
|
||||
|
||||
stmt, err := ctx.Transaction.Preparex("INSERT INTO account (refid, orgid, userid, admin, editor, users, active, created, revised) VALUES (?, ?, ?, ?, ?, ?, ?, ?)")
|
||||
stmt, err := ctx.Transaction.Preparex("INSERT INTO account (refid, orgid, userid, admin, editor, users, active, created, revised) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)")
|
||||
defer streamutil.Close(stmt)
|
||||
|
||||
if err != nil {
|
||||
|
|
|
@ -15,12 +15,12 @@ import (
|
|||
"database/sql"
|
||||
|
||||
"github.com/documize/community/domain"
|
||||
sp "github.com/documize/community/model/space"
|
||||
)
|
||||
|
||||
// CanViewDocumentInFolder returns if the user has permission to view a document within the specified folder.
|
||||
func CanViewDocumentInFolder(ctx domain.RequestContext, s domain.Store, labelID string) (hasPermission bool) {
|
||||
roles, err := s.Space.GetUserRoles(ctx)
|
||||
|
||||
func CanViewDocumentInFolder(ctx domain.RequestContext, s domain.Store, labelID string) bool {
|
||||
roles, err := s.Space.GetUserPermissions(ctx, labelID)
|
||||
if err == sql.ErrNoRows {
|
||||
err = nil
|
||||
}
|
||||
|
@ -29,7 +29,8 @@ func CanViewDocumentInFolder(ctx domain.RequestContext, s domain.Store, labelID
|
|||
}
|
||||
|
||||
for _, role := range roles {
|
||||
if role.LabelID == labelID && (role.CanView || role.CanEdit) {
|
||||
if role.RefID == labelID && role.Location == "space" && role.Scope == "object" &&
|
||||
sp.HasPermission(role.Action, sp.SpaceView, sp.SpaceManage, sp.SpaceOwner) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
@ -37,10 +38,9 @@ func CanViewDocumentInFolder(ctx domain.RequestContext, s domain.Store, labelID
|
|||
return false
|
||||
}
|
||||
|
||||
// CanViewDocument returns if the clinet has permission to view a given document.
|
||||
func CanViewDocument(ctx domain.RequestContext, s domain.Store, documentID string) (hasPermission bool) {
|
||||
// CanViewDocument returns if the client has permission to view a given document.
|
||||
func CanViewDocument(ctx domain.RequestContext, s domain.Store, documentID string) bool {
|
||||
document, err := s.Document.Get(ctx, documentID)
|
||||
|
||||
if err == sql.ErrNoRows {
|
||||
err = nil
|
||||
}
|
||||
|
@ -48,8 +48,7 @@ func CanViewDocument(ctx domain.RequestContext, s domain.Store, documentID strin
|
|||
return false
|
||||
}
|
||||
|
||||
roles, err := s.Space.GetUserRoles(ctx)
|
||||
|
||||
roles, err := s.Space.GetUserPermissions(ctx, document.LabelID)
|
||||
if err == sql.ErrNoRows {
|
||||
err = nil
|
||||
}
|
||||
|
@ -58,7 +57,8 @@ func CanViewDocument(ctx domain.RequestContext, s domain.Store, documentID strin
|
|||
}
|
||||
|
||||
for _, role := range roles {
|
||||
if role.LabelID == document.LabelID && (role.CanView || role.CanEdit) {
|
||||
if role.RefID == document.LabelID && role.Location == "space" && role.Scope == "object" &&
|
||||
sp.HasPermission(role.Action, sp.SpaceView, sp.SpaceManage, sp.SpaceOwner) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
@ -67,7 +67,7 @@ func CanViewDocument(ctx domain.RequestContext, s domain.Store, documentID strin
|
|||
}
|
||||
|
||||
// CanChangeDocument returns if the clinet has permission to change a given document.
|
||||
func CanChangeDocument(ctx domain.RequestContext, s domain.Store, documentID string) (hasPermission bool) {
|
||||
func CanChangeDocument(ctx domain.RequestContext, s domain.Store, documentID string) bool {
|
||||
document, err := s.Document.Get(ctx, documentID)
|
||||
|
||||
if err == sql.ErrNoRows {
|
||||
|
@ -77,7 +77,7 @@ func CanChangeDocument(ctx domain.RequestContext, s domain.Store, documentID str
|
|||
return false
|
||||
}
|
||||
|
||||
roles, err := s.Space.GetUserRoles(ctx)
|
||||
roles, err := s.Space.GetUserPermissions(ctx, document.LabelID)
|
||||
|
||||
if err == sql.ErrNoRows {
|
||||
err = nil
|
||||
|
@ -87,7 +87,8 @@ func CanChangeDocument(ctx domain.RequestContext, s domain.Store, documentID str
|
|||
}
|
||||
|
||||
for _, role := range roles {
|
||||
if role.LabelID == document.LabelID && role.CanEdit {
|
||||
if role.RefID == document.LabelID && role.Location == "space" && role.Scope == "object" &&
|
||||
sp.HasPermission(role.Action, sp.DocumentEdit) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
@ -95,10 +96,9 @@ func CanChangeDocument(ctx domain.RequestContext, s domain.Store, documentID str
|
|||
return false
|
||||
}
|
||||
|
||||
// CanUploadDocument returns if the client has permission to upload documents to the given folderID.
|
||||
func CanUploadDocument(ctx domain.RequestContext, s domain.Store, folderID string) (hasPermission bool) {
|
||||
roles, err := s.Space.GetUserRoles(ctx)
|
||||
|
||||
// CanUploadDocument returns if the client has permission to upload documents to the given space.
|
||||
func CanUploadDocument(ctx domain.RequestContext, s domain.Store, spaceID string) bool {
|
||||
roles, err := s.Space.GetUserPermissions(ctx, spaceID)
|
||||
if err == sql.ErrNoRows {
|
||||
err = nil
|
||||
}
|
||||
|
@ -107,7 +107,8 @@ func CanUploadDocument(ctx domain.RequestContext, s domain.Store, folderID strin
|
|||
}
|
||||
|
||||
for _, role := range roles {
|
||||
if role.LabelID == folderID && role.CanEdit {
|
||||
if role.RefID == spaceID && role.Location == "space" && role.Scope == "object" &&
|
||||
sp.HasPermission(role.Action, sp.DocumentAdd) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
|
|
@ -168,12 +168,12 @@ func (m *Mailer) PasswordReset(recipient, url string) {
|
|||
}
|
||||
}
|
||||
|
||||
// ShareFolderExistingUser provides an existing user with a link to a newly shared folder.
|
||||
func (m *Mailer) ShareFolderExistingUser(recipient, inviter, url, folder, intro string) {
|
||||
method := "ShareFolderExistingUser"
|
||||
// ShareSpaceExistingUser provides an existing user with a link to a newly shared space.
|
||||
func (m *Mailer) ShareSpaceExistingUser(recipient, inviter, url, folder, intro string) {
|
||||
method := "ShareSpaceExistingUser"
|
||||
m.LoadCredentials()
|
||||
|
||||
file, err := web.ReadFile("mail/share-folder-existing-user.html")
|
||||
file, err := web.ReadFile("mail/share-space-existing-user.html")
|
||||
if err != nil {
|
||||
m.Runtime.Log.Error(fmt.Sprintf("%s - unable to load email template", method), err)
|
||||
return
|
||||
|
@ -218,12 +218,12 @@ func (m *Mailer) ShareFolderExistingUser(recipient, inviter, url, folder, intro
|
|||
}
|
||||
}
|
||||
|
||||
// ShareFolderNewUser invites new user providing Credentials, explaining the product and stating who is inviting them.
|
||||
func (m *Mailer) ShareFolderNewUser(recipient, inviter, url, folder, invitationMessage string) {
|
||||
method := "ShareFolderNewUser"
|
||||
// ShareSpaceNewUser invites new user providing Credentials, explaining the product and stating who is inviting them.
|
||||
func (m *Mailer) ShareSpaceNewUser(recipient, inviter, url, space, invitationMessage string) {
|
||||
method := "ShareSpaceNewUser"
|
||||
m.LoadCredentials()
|
||||
|
||||
file, err := web.ReadFile("mail/share-folder-new-user.html")
|
||||
file, err := web.ReadFile("mail/share-space-new-user.html")
|
||||
if err != nil {
|
||||
m.Runtime.Log.Error(fmt.Sprintf("%s - unable to load email template", method), err)
|
||||
return
|
||||
|
@ -236,7 +236,7 @@ func (m *Mailer) ShareFolderNewUser(recipient, inviter, url, folder, invitationM
|
|||
inviter = "Your colleague"
|
||||
}
|
||||
|
||||
subject := fmt.Sprintf("%s has shared %s with you on Documize", inviter, folder)
|
||||
subject := fmt.Sprintf("%s has shared %s with you on Documize", inviter, space)
|
||||
|
||||
e := NewEmail()
|
||||
e.From = m.Credentials.SMTPsender
|
||||
|
@ -254,7 +254,7 @@ func (m *Mailer) ShareFolderNewUser(recipient, inviter, url, folder, invitationM
|
|||
inviter,
|
||||
url,
|
||||
invitationMessage,
|
||||
folder,
|
||||
space,
|
||||
}
|
||||
|
||||
buffer := new(bytes.Buffer)
|
||||
|
|
|
@ -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()
|
||||
})
|
||||
}
|
||||
|
|
|
@ -56,13 +56,13 @@ type SpaceStorer interface {
|
|||
ChangeOwner(ctx RequestContext, currentOwner, newOwner string) (err error)
|
||||
Viewers(ctx RequestContext) (v []space.Viewer, err error)
|
||||
Delete(ctx RequestContext, id string) (rows int64, err error)
|
||||
AddRole(ctx RequestContext, r space.Role) (err error)
|
||||
GetRoles(ctx RequestContext, labelID string) (r []space.Role, err error)
|
||||
GetUserRoles(ctx RequestContext) (r []space.Role, err error)
|
||||
DeleteRole(ctx RequestContext, roleID string) (rows int64, err error)
|
||||
DeleteSpaceRoles(ctx RequestContext, spaceID string) (rows int64, err error)
|
||||
DeleteUserSpaceRoles(ctx RequestContext, spaceID, userID string) (rows int64, err error)
|
||||
MoveSpaceRoles(ctx RequestContext, previousLabel, newLabel string) (err error)
|
||||
|
||||
AddPermission(ctx RequestContext, r space.Permission) (err error)
|
||||
AddPermissions(ctx RequestContext, r space.Permission, actions ...space.PermissionAction) (err error)
|
||||
GetUserPermissions(ctx RequestContext, spaceID string) (r []space.Permission, err error)
|
||||
GetPermissions(ctx RequestContext, spaceID string) (r []space.Permission, err error)
|
||||
DeleteUserPermissions(ctx RequestContext, spaceID, userID string) (rows int64, err error)
|
||||
DeletePermissions(ctx RequestContext, spaceID string) (rows int64, err error)
|
||||
}
|
||||
|
||||
// UserStorer defines required methods for user management
|
||||
|
|
|
@ -538,31 +538,6 @@ func (h *Handler) ChangePassword(w http.ResponseWriter, r *http.Request) {
|
|||
response.WriteEmpty(w)
|
||||
}
|
||||
|
||||
// UserSpacePermissions returns folder permission for authenticated user.
|
||||
func (h *Handler) UserSpacePermissions(w http.ResponseWriter, r *http.Request) {
|
||||
method := "user.UserSpacePermissions"
|
||||
ctx := domain.GetRequestContext(r)
|
||||
|
||||
userID := request.Param(r, "userID")
|
||||
if userID != ctx.UserID {
|
||||
response.WriteForbiddenError(w)
|
||||
return
|
||||
}
|
||||
|
||||
roles, err := h.Store.Space.GetUserRoles(ctx)
|
||||
if err == sql.ErrNoRows {
|
||||
err = nil
|
||||
roles = []space.Role{}
|
||||
}
|
||||
if err != nil {
|
||||
response.WriteServerError(w, method, err)
|
||||
h.Runtime.Log.Error(method, err)
|
||||
return
|
||||
}
|
||||
|
||||
response.WriteJSON(w, roles)
|
||||
}
|
||||
|
||||
// ForgotPassword initiates the change password procedure.
|
||||
// Generates a reset token and sends email to the user.
|
||||
// User has to click link in email and then provide a new password.
|
||||
|
|
|
@ -48,8 +48,8 @@ export default Ember.Component.extend(NotifierMixin, TooltipMixin, AuthMixin, {
|
|||
this.addTooltip(document.getElementById("delete-documents-button"));
|
||||
} else {
|
||||
if (this.get('isFolderOwner')) {
|
||||
this.addTooltip(document.getElementById("folder-share-button"));
|
||||
this.addTooltip(document.getElementById("folder-settings-button"));
|
||||
this.addTooltip(document.getElementById("space-delete-button"));
|
||||
this.addTooltip(document.getElementById("space-settings-button"));
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
@ -23,7 +23,7 @@ export default Ember.Component.extend(NotifierMixin, {
|
|||
inviteMessage: '',
|
||||
|
||||
getDefaultInvitationMessage() {
|
||||
return "Hey there, I am sharing the " + this.folder.get('name') + " space (in " + this.get("appMeta.title") + ") with you so we can both access the same documents.";
|
||||
return "Hey there, I am sharing the " + this.folder.get('name') + " space (in " + this.get("appMeta.title") + ") with you so we can both collaborate on documents.";
|
||||
},
|
||||
|
||||
willRender() {
|
||||
|
@ -67,7 +67,8 @@ export default Ember.Component.extend(NotifierMixin, {
|
|||
this.set('inviteEmail', '');
|
||||
|
||||
this.get('folderService').share(this.folder.get('id'), result).then(() => {
|
||||
this.showNotification('Shared');
|
||||
this.showNotification('Invietd co-workers');
|
||||
$('#inviteEmail').removeClass('error');
|
||||
});
|
||||
}
|
||||
}
|
|
@ -32,13 +32,22 @@ export default Ember.Component.extend(NotifierMixin, {
|
|||
let isActive = user.get('active');
|
||||
|
||||
let u = {
|
||||
userId: user.get('id'),
|
||||
fullname: user.get('fullname'),
|
||||
orgId: this.get('folder.orgId'),
|
||||
folderId: this.get('folder.id'),
|
||||
canEdit: false,
|
||||
canView: false,
|
||||
canViewPrevious: false
|
||||
who: 'user',
|
||||
whoId: user.get('id'),
|
||||
location: 'space',
|
||||
scope: 'object',
|
||||
refId: this.get('folder.id'),
|
||||
spaceView: false,
|
||||
spaceManage: false,
|
||||
spaceOwner: false,
|
||||
docAdd: false,
|
||||
docEdit: false,
|
||||
docDelete: false,
|
||||
docMove: false,
|
||||
docCopy: false,
|
||||
docTemplate: false,
|
||||
};
|
||||
|
||||
if (isActive) {
|
||||
|
@ -47,13 +56,23 @@ export default Ember.Component.extend(NotifierMixin, {
|
|||
});
|
||||
|
||||
var u = {
|
||||
userId: "",
|
||||
fullname: " Everyone",
|
||||
orgId: this.get('folder.orgId'),
|
||||
folderId: this.get('folder.id'),
|
||||
canEdit: false,
|
||||
canView: false
|
||||
};
|
||||
who: 'user',
|
||||
whoId: '',
|
||||
location: 'space',
|
||||
scope: 'object',
|
||||
refId: this.get('folder.id'),
|
||||
spaceView: false,
|
||||
spaceManage: false,
|
||||
spaceOwner: false,
|
||||
docAdd: false,
|
||||
docEdit: false,
|
||||
docDelete: false,
|
||||
docMove: false,
|
||||
docCopy: false,
|
||||
docTemplate: false,
|
||||
};
|
||||
|
||||
folderPermissions.pushObject(u);
|
||||
|
||||
|
@ -111,6 +130,7 @@ export default Ember.Component.extend(NotifierMixin, {
|
|||
var payload = { Message: message, Roles: data };
|
||||
|
||||
this.get('folderService').savePermissions(folder.get('id'), payload).then(() => {
|
||||
this.showNotification('Saved permissions');
|
||||
});
|
||||
|
||||
var hasEveryone = _.find(data, function (permission) {
|
||||
|
@ -128,7 +148,6 @@ export default Ember.Component.extend(NotifierMixin, {
|
|||
}
|
||||
|
||||
this.get('folderService').save(folder).then(function () {
|
||||
// window.location.href = "/folder/" + folder.get('id') + "/" + folder.get('slug');
|
||||
});
|
||||
}
|
||||
}
|
24
gui/app/models/user-permission.js
Normal file
24
gui/app/models/user-permission.js
Normal file
|
@ -0,0 +1,24 @@
|
|||
// Copyright 2016 Documize Inc. <legal@documize.com>. All rights reserved.
|
||||
//
|
||||
// This software (Documize Community Edition) is licensed under
|
||||
// GNU AGPL v3 http://www.gnu.org/licenses/agpl-3.0.en.html
|
||||
//
|
||||
// You can operate outside the AGPL restrictions by purchasing
|
||||
// Documize Enterprise Edition and obtaining a commercial license
|
||||
// by contacting <sales@documize.com>.
|
||||
//
|
||||
// https://documize.com
|
||||
|
||||
import Model from 'ember-data/model';
|
||||
import attr from 'ember-data/attr';
|
||||
// import { belongsTo, hasMany } from 'ember-data/relationships';
|
||||
|
||||
export default Model.extend({
|
||||
orgId: attr('string'),
|
||||
who: attr('string'),
|
||||
whoId: attr('string'),
|
||||
action: attr('string'),
|
||||
scope: attr('string'),
|
||||
location: attr('string'),
|
||||
refId: attr('string')
|
||||
});
|
|
@ -10,78 +10,6 @@
|
|||
// https://documize.com
|
||||
|
||||
import Ember from 'ember';
|
||||
import NotifierMixin from '../../mixins/notifier';
|
||||
|
||||
export default Ember.Controller.extend(NotifierMixin, {
|
||||
documentService: Ember.inject.service('document'),
|
||||
folderService: Ember.inject.service('folder'),
|
||||
localStorage: Ember.inject.service('localStorage'),
|
||||
selectedDocuments: [],
|
||||
hasSelectedDocuments: Ember.computed.gt('selectedDocuments.length', 0),
|
||||
queryParams: ['tab'],
|
||||
tab: 'index',
|
||||
|
||||
actions: {
|
||||
onMoveDocument(folder) {
|
||||
let self = this;
|
||||
let documents = this.get('selectedDocuments');
|
||||
|
||||
documents.forEach(function (documentId) {
|
||||
self.get('documentService').getDocument(documentId).then(function (doc) {
|
||||
doc.set('folderId', folder);
|
||||
doc.set('selected', !doc.get('selected'));
|
||||
self.get('documentService').save(doc).then(function () {
|
||||
self.get('target._routerMicrolib').refresh();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
this.set('selectedDocuments', []);
|
||||
this.send("showNotification", "Moved");
|
||||
},
|
||||
|
||||
onDeleteDocument() {
|
||||
let documents = this.get('selectedDocuments');
|
||||
let self = this;
|
||||
let promises = [];
|
||||
|
||||
documents.forEach(function (document, index) {
|
||||
promises[index] = self.get('documentService').deleteDocument(document);
|
||||
});
|
||||
|
||||
Ember.RSVP.all(promises).then(() => {
|
||||
let documents = this.get('model.documents');
|
||||
documents.forEach(function (document) {
|
||||
document.set('selected', false);
|
||||
});
|
||||
this.set('model.documents', documents);
|
||||
|
||||
this.set('selectedDocuments', []);
|
||||
this.send("showNotification", "Deleted");
|
||||
this.get('target._routerMicrolib').refresh();
|
||||
});
|
||||
},
|
||||
|
||||
onAddSpace(payload) {
|
||||
let self = this;
|
||||
this.showNotification("Added");
|
||||
|
||||
this.get('folderService').add(payload).then(function (newFolder) {
|
||||
self.get('folderService').setCurrentFolder(newFolder);
|
||||
self.transitionToRoute('folder', newFolder.get('id'), newFolder.get('slug'));
|
||||
});
|
||||
},
|
||||
|
||||
onDeleteSpace() {
|
||||
this.get('folderService').delete(this.get('model.folder.id')).then(() => { /* jshint ignore:line */
|
||||
this.showNotification("Deleted");
|
||||
this.get('localStorage').clearSessionItem('folder');
|
||||
this.transitionToRoute('application');
|
||||
});
|
||||
},
|
||||
|
||||
onImport() {
|
||||
this.get('target._routerMicrolib').refresh();
|
||||
}
|
||||
}
|
||||
export default Ember.Controller.extend({
|
||||
});
|
||||
|
|
87
gui/app/pods/folder/index/controller.js
Normal file
87
gui/app/pods/folder/index/controller.js
Normal file
|
@ -0,0 +1,87 @@
|
|||
// Copyright 2016 Documize Inc. <legal@documize.com>. All rights reserved.
|
||||
//
|
||||
// This software (Documize Community Edition) is licensed under
|
||||
// GNU AGPL v3 http://www.gnu.org/licenses/agpl-3.0.en.html
|
||||
//
|
||||
// You can operate outside the AGPL restrictions by purchasing
|
||||
// Documize Enterprise Edition and obtaining a commercial license
|
||||
// by contacting <sales@documize.com>.
|
||||
//
|
||||
// https://documize.com
|
||||
|
||||
import Ember from 'ember';
|
||||
import NotifierMixin from '../../../mixins/notifier';
|
||||
|
||||
export default Ember.Controller.extend(NotifierMixin, {
|
||||
documentService: Ember.inject.service('document'),
|
||||
folderService: Ember.inject.service('folder'),
|
||||
localStorage: Ember.inject.service('localStorage'),
|
||||
selectedDocuments: [],
|
||||
hasSelectedDocuments: Ember.computed.gt('selectedDocuments.length', 0),
|
||||
queryParams: ['tab'],
|
||||
tab: 'index',
|
||||
|
||||
actions: {
|
||||
onMoveDocument(folder) {
|
||||
let self = this;
|
||||
let documents = this.get('selectedDocuments');
|
||||
|
||||
documents.forEach(function (documentId) {
|
||||
self.get('documentService').getDocument(documentId).then(function (doc) {
|
||||
doc.set('folderId', folder);
|
||||
doc.set('selected', !doc.get('selected'));
|
||||
self.get('documentService').save(doc).then(function () {
|
||||
self.get('target._routerMicrolib').refresh();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
this.set('selectedDocuments', []);
|
||||
this.send("showNotification", "Moved");
|
||||
},
|
||||
|
||||
onDeleteDocument() {
|
||||
let documents = this.get('selectedDocuments');
|
||||
let self = this;
|
||||
let promises = [];
|
||||
|
||||
documents.forEach(function (document, index) {
|
||||
promises[index] = self.get('documentService').deleteDocument(document);
|
||||
});
|
||||
|
||||
Ember.RSVP.all(promises).then(() => {
|
||||
let documents = this.get('model.documents');
|
||||
documents.forEach(function (document) {
|
||||
document.set('selected', false);
|
||||
});
|
||||
this.set('model.documents', documents);
|
||||
|
||||
this.set('selectedDocuments', []);
|
||||
this.send("showNotification", "Deleted");
|
||||
this.get('target._routerMicrolib').refresh();
|
||||
});
|
||||
},
|
||||
|
||||
onAddSpace(payload) {
|
||||
let self = this;
|
||||
this.showNotification("Added");
|
||||
|
||||
this.get('folderService').add(payload).then(function (newFolder) {
|
||||
self.get('folderService').setCurrentFolder(newFolder);
|
||||
self.transitionToRoute('folder', newFolder.get('id'), newFolder.get('slug'));
|
||||
});
|
||||
},
|
||||
|
||||
onDeleteSpace() {
|
||||
this.get('folderService').delete(this.get('model.folder.id')).then(() => { /* jshint ignore:line */
|
||||
this.showNotification("Deleted");
|
||||
this.get('localStorage').clearSessionItem('folder');
|
||||
this.transitionToRoute('application');
|
||||
});
|
||||
},
|
||||
|
||||
onImport() {
|
||||
this.get('target._routerMicrolib').refresh();
|
||||
}
|
||||
}
|
||||
});
|
28
gui/app/pods/folder/index/route.js
Normal file
28
gui/app/pods/folder/index/route.js
Normal file
|
@ -0,0 +1,28 @@
|
|||
// Copyright 2016 Documize Inc. <legal@documize.com>. All rights reserved.
|
||||
//
|
||||
// This software (Documize Community Edition) is licensed under
|
||||
// GNU AGPL v3 http://www.gnu.org/licenses/agpl-3.0.en.html
|
||||
//
|
||||
// You can operate outside the AGPL restrictions by purchasing
|
||||
// Documize Enterprise Edition and obtaining a commercial license
|
||||
// by contacting <sales@documize.com>.
|
||||
//
|
||||
// https://documize.com
|
||||
|
||||
import Ember from 'ember';
|
||||
import AuthenticatedRouteMixin from 'ember-simple-auth/mixins/authenticated-route-mixin';
|
||||
|
||||
export default Ember.Route.extend(AuthenticatedRouteMixin, {
|
||||
model() {
|
||||
this.get('browser').setTitle(this.modelFor('folder').folder.get('name'));
|
||||
|
||||
return Ember.RSVP.hash({
|
||||
folder: this.modelFor('folder').folder,
|
||||
isEditor: this.modelFor('folder').isEditor,
|
||||
isFolderOwner: this.modelFor('folder').isFolderOwner,
|
||||
folders: this.modelFor('folder').folders,
|
||||
documents: this.modelFor('folder').documents,
|
||||
templates: this.modelFor('folder').templates
|
||||
});
|
||||
}
|
||||
});
|
14
gui/app/pods/folder/index/template.hbs
Normal file
14
gui/app/pods/folder/index/template.hbs
Normal file
|
@ -0,0 +1,14 @@
|
|||
{{#layout/zone-container}}
|
||||
{{#layout/zone-sidebar}}
|
||||
{{folder/sidebar-zone folders=model.folders folder=model.folder isFolderOwner=model.isFolderOwner isEditor=model.isEditor tab=tab
|
||||
onAddSpace=(action 'onAddSpace')}}
|
||||
{{/layout/zone-sidebar}}
|
||||
{{#layout/zone-content}}
|
||||
{{folder/folder-heading folder=model.folder isFolderOwner=model.isFolderOwner isEditor=model.isEditor}}
|
||||
{{folder/folder-toolbar folders=model.folders isFolderOwner=model.isFolderOwner folder=model.folder hasSelectedDocuments=hasSelectedDocuments
|
||||
onDeleteDocument=(action 'onDeleteDocument') onMoveDocument=(action 'onMoveDocument')}}
|
||||
{{folder/documents-list documents=model.documents folders=model.folders folder=model.folder templates=model.templates
|
||||
isFolderOwner=model.isFolderOwner isEditor=model.isEditor selectedDocuments=(mut selectedDocuments)
|
||||
onDeleteSpace=(action 'onDeleteSpace') onImport=(action 'onImport')}}
|
||||
{{/layout/zone-content}}
|
||||
{{/layout/zone-container}}
|
|
@ -47,11 +47,6 @@ export default Ember.Route.extend(AuthenticatedRouteMixin, {
|
|||
});
|
||||
},
|
||||
|
||||
setupController(controller, model) {
|
||||
controller.set('model', model);
|
||||
this.browser.setTitle(model.folder.get('name'));
|
||||
},
|
||||
|
||||
actions: {
|
||||
error(error /*, transition*/ ) {
|
||||
console.log(error); // eslint-disable-line no-console
|
||||
|
|
20
gui/app/pods/folder/settings/controller.js
Normal file
20
gui/app/pods/folder/settings/controller.js
Normal file
|
@ -0,0 +1,20 @@
|
|||
// Copyright 2016 Documize Inc. <legal@documize.com>. All rights reserved.
|
||||
//
|
||||
// This software (Documize Community Edition) is licensed under
|
||||
// GNU AGPL v3 http://www.gnu.org/licenses/agpl-3.0.en.html
|
||||
//
|
||||
// You can operate outside the AGPL restrictions by purchasing
|
||||
// Documize Enterprise Edition and obtaining a commercial license
|
||||
// by contacting <sales@documize.com>.
|
||||
//
|
||||
// https://documize.com
|
||||
|
||||
import Ember from 'ember';
|
||||
import NotifierMixin from '../../../mixins/notifier';
|
||||
import AuthProvider from '../../../mixins/auth';
|
||||
|
||||
export default Ember.Controller.extend(AuthProvider, NotifierMixin, {
|
||||
documentService: Ember.inject.service('document'),
|
||||
folderService: Ember.inject.service('folder'),
|
||||
localStorage: Ember.inject.service('localStorage'),
|
||||
});
|
26
gui/app/pods/folder/settings/route.js
Normal file
26
gui/app/pods/folder/settings/route.js
Normal file
|
@ -0,0 +1,26 @@
|
|||
// Copyright 2016 Documize Inc. <legal@documize.com>. All rights reserved.
|
||||
//
|
||||
// This software (Documize Community Edition) is licensed under
|
||||
// GNU AGPL v3 http://www.gnu.org/licenses/agpl-3.0.en.html
|
||||
//
|
||||
// You can operate outside the AGPL restrictions by purchasing
|
||||
// Documize Enterprise Edition and obtaining a commercial license
|
||||
// by contacting <sales@documize.com>.
|
||||
//
|
||||
// https://documize.com
|
||||
|
||||
import Ember from 'ember';
|
||||
import AuthenticatedRouteMixin from 'ember-simple-auth/mixins/authenticated-route-mixin';
|
||||
|
||||
export default Ember.Route.extend(AuthenticatedRouteMixin, {
|
||||
model() {
|
||||
this.get('browser').setTitle(this.modelFor('folder').folder.get('name'));
|
||||
|
||||
return Ember.RSVP.hash({
|
||||
folder: this.modelFor('folder').folder,
|
||||
isEditor: this.modelFor('folder').isEditor,
|
||||
isFolderOwner: this.modelFor('folder').isFolderOwner,
|
||||
folders: this.modelFor('folder').folders
|
||||
});
|
||||
}
|
||||
});
|
36
gui/app/pods/folder/settings/template.hbs
Normal file
36
gui/app/pods/folder/settings/template.hbs
Normal file
|
@ -0,0 +1,36 @@
|
|||
{{#layout/zone-container}}
|
||||
|
||||
{{#layout/zone-sidebar}}
|
||||
<div class="sidebar-toolbar"></div>
|
||||
<div class="sidebar-common">
|
||||
{{layout/sidebar-intro title="Space Settings" message="Invite users and configure space permissions. Set up categories to sub-divide the space."}}
|
||||
</div>
|
||||
<div class="sidebar-wrapper">
|
||||
<div class="sidebar-menu">
|
||||
<ul class="options">
|
||||
<div class="option selected">Users</div>
|
||||
<div class="option ">Categories</div>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
{{/layout/zone-sidebar}}
|
||||
|
||||
{{#layout/zone-content}}
|
||||
<div class="folder-heading">
|
||||
<h1 class="folder-title">{{model.folder.name}}</h1>
|
||||
</div>
|
||||
{{#link-to 'folder' model.folder.id model.folder.slug class="vertical-top"}}
|
||||
<i class="material-icons">arrow_back</i> back to space
|
||||
{{/link-to}}
|
||||
<div class="margin-top-30" />
|
||||
|
||||
{{#if isAuthProviderDocumize}}
|
||||
{{folder/invite-user folders=model.folders folder=model.folder}}
|
||||
<div class="margin-top-50" />
|
||||
{{/if}}
|
||||
|
||||
{{folder/permission-admin folders=model.folders folder=model.folder}}
|
||||
<div class="margin-top-50" />
|
||||
{{/layout/zone-content}}
|
||||
|
||||
{{/layout/zone-container}}
|
|
@ -1,15 +1,2 @@
|
|||
{{layout/zone-navigation}}
|
||||
{{#layout/zone-container}}
|
||||
{{#layout/zone-sidebar}}
|
||||
{{folder/sidebar-zone folders=model.folders folder=model.folder isFolderOwner=model.isFolderOwner isEditor=model.isEditor tab=tab
|
||||
onAddSpace=(action 'onAddSpace')}}
|
||||
{{/layout/zone-sidebar}}
|
||||
{{#layout/zone-content}}
|
||||
{{folder/folder-heading folder=model.folder isFolderOwner=model.isFolderOwner isEditor=model.isEditor}}
|
||||
{{folder/folder-toolbar folders=model.folders folder=model.folder hasSelectedDocuments=hasSelectedDocuments
|
||||
onDeleteDocument=(action 'onDeleteDocument') onMoveDocument=(action 'onMoveDocument')}}
|
||||
{{folder/documents-list documents=model.documents folders=model.folders folder=model.folder templates=model.templates
|
||||
isFolderOwner=model.isFolderOwner isEditor=model.isEditor selectedDocuments=(mut selectedDocuments)
|
||||
onDeleteSpace=(action 'onDeleteSpace') onImport=(action 'onImport')}}
|
||||
{{/layout/zone-content}}
|
||||
{{/layout/zone-container}}
|
||||
{{outlet}}
|
||||
|
|
|
@ -23,6 +23,10 @@ export default Router.map(function () {
|
|||
|
||||
this.route('folder', {
|
||||
path: 's/:folder_id/:folder_slug'
|
||||
}, function() {
|
||||
this.route('settings', {
|
||||
path: 'settings'
|
||||
});
|
||||
});
|
||||
|
||||
this.route('document', {
|
||||
|
|
13
gui/app/serializers/user-permission.js
Normal file
13
gui/app/serializers/user-permission.js
Normal file
|
@ -0,0 +1,13 @@
|
|||
import ApplicationSerializer from './application';
|
||||
|
||||
export default ApplicationSerializer.extend({
|
||||
normalize(modelClass, resourceHash) {
|
||||
return {
|
||||
data: {
|
||||
id: resourceHash.userId ? resourceHash.userId : 0,
|
||||
type: modelClass.modelName,
|
||||
attributes: resourceHash
|
||||
}
|
||||
};
|
||||
}
|
||||
});
|
|
@ -13,7 +13,6 @@ import Ember from 'ember';
|
|||
import BaseService from '../services/base';
|
||||
|
||||
const {
|
||||
get,
|
||||
RSVP,
|
||||
inject: { service }
|
||||
} = Ember;
|
||||
|
@ -30,7 +29,7 @@ export default BaseService.extend({
|
|||
|
||||
// Add a new folder.
|
||||
add(payload) {
|
||||
return this.get('ajax').post(`folders`, {
|
||||
return this.get('ajax').post(`space`, {
|
||||
contentType: 'json',
|
||||
data: JSON.stringify(payload)
|
||||
}).then((folder) => {
|
||||
|
@ -41,7 +40,7 @@ export default BaseService.extend({
|
|||
|
||||
// Returns folder model for specified folder id.
|
||||
getFolder(id) {
|
||||
return this.get('ajax').request(`folders/${id}`, {
|
||||
return this.get('ajax').request(`space/${id}`, {
|
||||
method: 'GET'
|
||||
}).then((folder) => {
|
||||
let data = this.get('store').normalize('folder', folder);
|
||||
|
@ -54,7 +53,7 @@ export default BaseService.extend({
|
|||
|
||||
// Returns all folders that user can see.
|
||||
getAll() {
|
||||
let folders = this.get('folders');
|
||||
let folders = this.get('space');
|
||||
|
||||
if (folders != null) {
|
||||
return new RSVP.resolve(folders);
|
||||
|
@ -67,7 +66,7 @@ export default BaseService.extend({
|
|||
save(folder) {
|
||||
let id = folder.get('id');
|
||||
|
||||
return this.get('ajax').request(`folders/${id}`, {
|
||||
return this.get('ajax').request(`space/${id}`, {
|
||||
method: 'PUT',
|
||||
contentType: 'json',
|
||||
data: JSON.stringify(folder)
|
||||
|
@ -75,7 +74,7 @@ export default BaseService.extend({
|
|||
},
|
||||
|
||||
remove(folderId, moveToId) {
|
||||
let url = `folders/${folderId}/move/${moveToId}`;
|
||||
let url = `space/${folderId}/move/${moveToId}`;
|
||||
|
||||
return this.get('ajax').request(url, {
|
||||
method: 'DELETE'
|
||||
|
@ -83,7 +82,7 @@ export default BaseService.extend({
|
|||
},
|
||||
|
||||
delete(folderId) {
|
||||
return this.get('ajax').request(`folders/${folderId}`, {
|
||||
return this.get('ajax').request(`space/${folderId}`, {
|
||||
method: 'DELETE'
|
||||
});
|
||||
},
|
||||
|
@ -99,7 +98,7 @@ export default BaseService.extend({
|
|||
|
||||
// getProtectedFolderInfo returns non-private folders and who has access to them.
|
||||
getProtectedFolderInfo() {
|
||||
return this.get('ajax').request(`folders?filter=viewers`, {
|
||||
return this.get('ajax').request(`space?filter=viewers`, {
|
||||
method: "GET"
|
||||
}).then((response) => {
|
||||
let data = [];
|
||||
|
@ -116,7 +115,7 @@ export default BaseService.extend({
|
|||
// reloads and caches folders.
|
||||
reload() {
|
||||
|
||||
return this.get('ajax').request(`folders`, {
|
||||
return this.get('ajax').request(`space`, {
|
||||
method: "GET"
|
||||
}).then((response) => {
|
||||
let data = [];
|
||||
|
@ -132,14 +131,13 @@ export default BaseService.extend({
|
|||
|
||||
// so who can see/edit this folder?
|
||||
getPermissions(folderId) {
|
||||
|
||||
return this.get('ajax').request(`folders/${folderId}/permissions`, {
|
||||
return this.get('ajax').request(`space/${folderId}/permissions`, {
|
||||
method: "GET"
|
||||
}).then((response) => {
|
||||
let data = [];
|
||||
|
||||
data = response.map((obj) => {
|
||||
let data = this.get('store').normalize('folder-permission', obj);
|
||||
let data = this.get('store').normalize('user-permission', obj);
|
||||
return this.get('store').push(data);
|
||||
});
|
||||
|
||||
|
@ -149,7 +147,7 @@ export default BaseService.extend({
|
|||
|
||||
// persist folder permissions
|
||||
savePermissions(folderId, payload) {
|
||||
return this.get('ajax').request(`folders/${folderId}/permissions`, {
|
||||
return this.get('ajax').request(`space/${folderId}/permissions`, {
|
||||
method: 'PUT',
|
||||
contentType: 'json',
|
||||
data: JSON.stringify(payload)
|
||||
|
@ -158,7 +156,6 @@ export default BaseService.extend({
|
|||
|
||||
// share this folder with new users!
|
||||
share(folderId, invitation) {
|
||||
|
||||
return this.get('ajax').post(`folders/${folderId}/invitation`, {
|
||||
contentType: 'json',
|
||||
data: JSON.stringify(invitation)
|
||||
|
@ -171,8 +168,9 @@ export default BaseService.extend({
|
|||
return;
|
||||
}
|
||||
|
||||
let folderId = folder.get('id');
|
||||
this.set('currentFolder', folder);
|
||||
this.get('localStorage').storeSessionItem("folder", get(folder, 'id'));
|
||||
this.get('localStorage').storeSessionItem("folder", folderId);
|
||||
this.set('canEditCurrentFolder', false);
|
||||
|
||||
let userId = this.get('sessionService.user.id');
|
||||
|
@ -180,7 +178,7 @@ export default BaseService.extend({
|
|||
userId = "0";
|
||||
}
|
||||
|
||||
let url = `users/${userId}/permissions`;
|
||||
let url = `space/${folderId}/permissions/user`;
|
||||
|
||||
return this.get('ajax').request(url).then((folderPermissions) => {
|
||||
// safety check
|
||||
|
@ -191,7 +189,6 @@ export default BaseService.extend({
|
|||
}
|
||||
|
||||
let result = [];
|
||||
let folderId = folder.get('id');
|
||||
|
||||
folderPermissions.forEach((item) => {
|
||||
if (item.folderId === folderId) {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
@import "document.scss";
|
||||
@import "folder.scss";
|
||||
@import "wizard.scss";
|
||||
@import "sidebar.scss";
|
||||
@import "settings.scss";
|
||||
|
|
42
gui/app/styles/view/folder/settings.scss
Normal file
42
gui/app/styles/view/folder/settings.scss
Normal file
|
@ -0,0 +1,42 @@
|
|||
.space-settings {
|
||||
> .panel {
|
||||
@include content-container();
|
||||
@include ease-in();
|
||||
@extend .transition-all;
|
||||
}
|
||||
|
||||
.permissions-table {
|
||||
padding: 0;
|
||||
margin: 0 0 30px 0;
|
||||
width: 100%;
|
||||
|
||||
> .row {
|
||||
padding: 8px 0;
|
||||
|
||||
> .permission-name-cell {
|
||||
padding: 10px 5px;
|
||||
font-size: 1.1rem;
|
||||
}
|
||||
|
||||
> .permission-roles-cell {
|
||||
background-color: $color-off-white;
|
||||
margin-top: 10px;
|
||||
margin-left: 40px;
|
||||
padding: 10px 10px;
|
||||
display: inline-block;
|
||||
|
||||
> .role-category {
|
||||
color: $color-gray;
|
||||
font-weight: bold;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
> label {
|
||||
color: $color-gray;
|
||||
font-weight: normal;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,57 +0,0 @@
|
|||
.sidebar-folder-share {
|
||||
> .input-control {
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
}
|
||||
|
||||
.sidebar-permissions {
|
||||
> .input-control {
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
> .permissions-table {
|
||||
border: none;
|
||||
padding: 0;
|
||||
margin: 0 0 30px 0;
|
||||
table-layout: fixed;
|
||||
width: 100%;
|
||||
white-space: nowrap;
|
||||
|
||||
> thead {
|
||||
> tr {
|
||||
> th {
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
> th:nth-child(1) {
|
||||
width: 70%;
|
||||
}
|
||||
|
||||
> th:nth-child(2), td:nth-child(3) {
|
||||
width: 20%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
> tbody {
|
||||
width: 300px;
|
||||
|
||||
> tr {
|
||||
> td {
|
||||
padding: 8px 0;
|
||||
@extend .truncate;
|
||||
}
|
||||
|
||||
> td:nth-child(1) {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
> td:nth-child(2), td:nth-child(3) {
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -28,7 +28,19 @@
|
|||
</ul>
|
||||
{{/dropdown-dialog}}
|
||||
{{else}}
|
||||
<div class="margin-top-35"></div>
|
||||
{{#if isFolderOwner}}
|
||||
{{#link-to 'folder.settings' folder.id folder.slug}}{{model.document.name}}
|
||||
<div class="round-button button-gray" id="space-settings-button" data-tooltip="Manage permissions" data-tooltip-position="top center">
|
||||
<i class="material-icons">settings</i>
|
||||
</div>
|
||||
{{/link-to}}
|
||||
<div class="button-gap"></div>
|
||||
<div class="round-button button-gray" id="space-delete-button" data-tooltip="Delete everything" data-tooltip-position="top center">
|
||||
<i class="material-icons">delete</i>
|
||||
</div>
|
||||
{{else}}
|
||||
<div class="margin-top-35"></div>
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
</div>
|
||||
{{/if}}
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
<div class="sidebar-panel">
|
||||
<div class="title">Invite Users</div>
|
||||
<div class="sidebar-folder-share folder-sidebar-form-wrapper">
|
||||
<div class="space-settings">
|
||||
<div class="panel">
|
||||
<div class="form-header">
|
||||
<div class="title">Invite</div>
|
||||
<div class="tip">Share this space with co-workers</div>
|
||||
</div>
|
||||
<div class="input-control">
|
||||
<label>Email</label>
|
||||
<div class="tip">Comma separate multiple email addresses</div>
|
||||
|
@ -8,9 +11,9 @@
|
|||
</div>
|
||||
<div class="input-control">
|
||||
<label>Message</label>
|
||||
<div class="tip">Explain why they are being invited</div>
|
||||
<div class="tip">Explain why they are being invited to this space</div>
|
||||
{{textarea id="explainInvite" value=inviteMessage class="input-transparent" rows="5"}}
|
||||
</div>
|
||||
<div class="regular-button button-blue" {{ action 'onShare' }}>Share</div>
|
||||
<div class="regular-button button-blue" {{ action 'onShare' }}>Invite</div>
|
||||
</div>
|
||||
</div>
|
42
gui/app/templates/components/folder/permission-admin.hbs
Normal file
42
gui/app/templates/components/folder/permission-admin.hbs
Normal file
|
@ -0,0 +1,42 @@
|
|||
<div class="space-settings">
|
||||
<div class="panel">
|
||||
<div class="form-header">
|
||||
<div class="title">Permissions</div>
|
||||
<div class="tip">Define who can do what in this space</div>
|
||||
</div>
|
||||
<div class="input-control">
|
||||
<div class="permissions-table">
|
||||
{{#each permissions key="@index" as |permission|}}
|
||||
<div class="row">
|
||||
<div class="permission-name-cell">{{permission.fullname}}</div>
|
||||
<div class="permission-roles-cell">
|
||||
<span class="role-category">Space: </span>
|
||||
<input type="checkbox" id="space-role-view-{{permission.userId}}" checked={{permission.canView}} />
|
||||
<label for="space-role-view-{{permission.userId}}">view</label>
|
||||
<input type="checkbox" id="space-role-manage-{{permission.userId}}" checked={{permission.canView}} />
|
||||
<label for="space-role-manage-{{permission.userId}}">manage</label>
|
||||
<input type="checkbox" id="space-role-owner-{{permission.userId}}" checked={{permission.canView}} />
|
||||
<label for="space-role-owner-{{permission.userId}}">owner</label>
|
||||
|
||||
<span class="role-category">Document: </span>
|
||||
<input type="checkbox" id="doc-role-add-{{permission.userId}}" checked={{permission.canView}} />
|
||||
<label for="doc-role-add-{{permission.userId}}">create</label>
|
||||
<input type="checkbox" id="doc-role-edit-{{permission.userId}}" checked={{permission.canView}} />
|
||||
<label for="doc-role-edit-{{permission.userId}}">edit</label>
|
||||
<input type="checkbox" id="doc-role-delete-{{permission.userId}}" checked={{permission.canView}} />
|
||||
<label for="doc-role-delete-{{permission.userId}}">delete</label>
|
||||
<input type="checkbox" id="doc-role-move-{{permission.userId}}" checked={{permission.canView}} />
|
||||
<label for="doc-role-move-{{permission.userId}}">move</label>
|
||||
<input type="checkbox" id="doc-role-copy-{{permission.userId}}" checked={{permission.canView}} />
|
||||
<label for="doc-role-copy-{{permission.userId}}">copy</label>
|
||||
<input type="checkbox" id="doc-role-template-{{permission.userId}}" checked={{permission.canView}} />
|
||||
<label for="doc-role-template-{{permission.userId}}">templates</label>
|
||||
</div>
|
||||
</div>
|
||||
{{/each}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="regular-button button-blue" {{action 'setPermissions'}}>GRANT</div>
|
||||
</div>
|
||||
</div>
|
|
@ -1,30 +0,0 @@
|
|||
<div class="sidebar-panel">
|
||||
<div class="title">Space Permissions</div>
|
||||
<div class="sidebar-permissions folder-sidebar-form-wrapper">
|
||||
<table class="permissions-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th> </th>
|
||||
<th>View </th>
|
||||
<th>Edit</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{#each permissions key="@index" as |permission|}}
|
||||
<tr>
|
||||
<td>{{permission.fullname}}</td>
|
||||
<td>
|
||||
<input type="checkbox" id="canView-{{permission.userId}}" checked={{permission.canView}} />
|
||||
<label for="canView-{{permission.userId}}"> </label>
|
||||
</td>
|
||||
<td>
|
||||
<input type="checkbox" id="canEdit-{{permission.userId}}" checked={{permission.canEdit}} />
|
||||
<label for="canEdit-{{permission.userId}}"> </label>
|
||||
</td>
|
||||
</tr>
|
||||
{{/each}}
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="regular-button button-blue" {{action 'setPermissions'}}>Set</div>
|
||||
</div>
|
||||
</div>
|
|
@ -11,7 +11,11 @@
|
|||
|
||||
package space
|
||||
|
||||
import "github.com/documize/community/model"
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/documize/community/model"
|
||||
)
|
||||
|
||||
// Space defines a container for documents.
|
||||
type Space struct {
|
||||
|
@ -51,6 +55,44 @@ func (l *Space) IsRestricted() bool {
|
|||
return l.Type == ScopeRestricted
|
||||
}
|
||||
|
||||
// Permission represents a permission for a space and is persisted to the database.
|
||||
type Permission struct {
|
||||
ID uint64 `json:"id"`
|
||||
OrgID string `json:"-"`
|
||||
Who string `json:"who"` // user, role
|
||||
WhoID string `json:"whoId"` // either a user or role ID
|
||||
Action string `json:"action"` // view, edit, delete
|
||||
Scope string `json:"scope"` // object, table
|
||||
Location string `json:"location"` // table name
|
||||
RefID string `json:"refId"` // id of row in table / blank when scope=table
|
||||
Created time.Time `json:"created"`
|
||||
}
|
||||
|
||||
// PermissionAction details type of action
|
||||
type PermissionAction string
|
||||
|
||||
const (
|
||||
// SpaceView action means you can view a space and documents therein
|
||||
SpaceView PermissionAction = "view"
|
||||
// SpaceManage action means you can add, remove users, set permissions, but not delete that space
|
||||
SpaceManage PermissionAction = "manage"
|
||||
// SpaceOwner action means you can delete a space and do all SpaceManage functions
|
||||
SpaceOwner PermissionAction = "owner"
|
||||
|
||||
// DocumentAdd action means you can create/upload documents to a space
|
||||
DocumentAdd PermissionAction = "doc-add"
|
||||
// DocumentEdit action means you can edit documents in a space
|
||||
DocumentEdit PermissionAction = "doc-edit"
|
||||
// DocumentDelete means you can delete documents in a space
|
||||
DocumentDelete PermissionAction = "doc-delete"
|
||||
// DocumentMove means you can move documents between spaces
|
||||
DocumentMove PermissionAction = "doc-move"
|
||||
// DocumentCopy means you can copy documents within and between spaces
|
||||
DocumentCopy PermissionAction = "doc-copy"
|
||||
// DocumentTemplate means you can create, edit and delete document templates and content blocks
|
||||
DocumentTemplate PermissionAction = "doc-template"
|
||||
)
|
||||
|
||||
// Role determines user permissions for a folder.
|
||||
type Role struct {
|
||||
model.BaseEntityObfuscated
|
||||
|
@ -74,8 +116,8 @@ type Viewer struct {
|
|||
|
||||
// RolesModel details which users have what permissions on a given space.
|
||||
type RolesModel struct {
|
||||
Message string
|
||||
Roles []Role
|
||||
Message string
|
||||
Permissions []Permission
|
||||
}
|
||||
|
||||
// AcceptShareModel is used to setup a user who has accepted a shared space.
|
||||
|
@ -100,3 +142,14 @@ type NewSpaceRequest struct {
|
|||
CopyPermission bool `json:"copyPermission"` // copy uer permissions
|
||||
CopyDocument bool `json:"copyDocument"` // copy all documents!
|
||||
}
|
||||
|
||||
// HasPermission checks if action matches one of the required actions?
|
||||
func HasPermission(action string, actions ...PermissionAction) bool {
|
||||
for _, a := range actions {
|
||||
if action == string(a) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
|
|
@ -111,19 +111,19 @@ func RegisterEndpoints(rt *env.Runtime, s *domain.Store) {
|
|||
Add(rt, RoutePrefixPrivate, "organizations/{orgID}", []string{"GET", "OPTIONS"}, nil, organization.Get)
|
||||
Add(rt, RoutePrefixPrivate, "organizations/{orgID}", []string{"PUT", "OPTIONS"}, nil, organization.Update)
|
||||
|
||||
Add(rt, RoutePrefixPrivate, "folders/{folderID}", []string{"DELETE", "OPTIONS"}, nil, space.Delete)
|
||||
Add(rt, RoutePrefixPrivate, "folders/{folderID}/move/{moveToId}", []string{"DELETE", "OPTIONS"}, nil, space.Remove)
|
||||
Add(rt, RoutePrefixPrivate, "folders/{folderID}/permissions", []string{"PUT", "OPTIONS"}, nil, space.SetPermissions)
|
||||
Add(rt, RoutePrefixPrivate, "folders/{folderID}/permissions", []string{"GET", "OPTIONS"}, nil, space.GetPermissions)
|
||||
Add(rt, RoutePrefixPrivate, "folders/{folderID}/invitation", []string{"POST", "OPTIONS"}, nil, space.Invite)
|
||||
Add(rt, RoutePrefixPrivate, "folders", []string{"GET", "OPTIONS"}, []string{"filter", "viewers"}, space.GetSpaceViewers)
|
||||
Add(rt, RoutePrefixPrivate, "folders", []string{"POST", "OPTIONS"}, nil, space.Add)
|
||||
Add(rt, RoutePrefixPrivate, "folders", []string{"GET", "OPTIONS"}, nil, space.GetAll)
|
||||
Add(rt, RoutePrefixPrivate, "folders/{folderID}", []string{"GET", "OPTIONS"}, nil, space.Get)
|
||||
Add(rt, RoutePrefixPrivate, "folders/{folderID}", []string{"PUT", "OPTIONS"}, nil, space.Update)
|
||||
Add(rt, RoutePrefixPrivate, "space/{spaceID}", []string{"DELETE", "OPTIONS"}, nil, space.Delete)
|
||||
Add(rt, RoutePrefixPrivate, "space/{spaceID}/move/{moveToId}", []string{"DELETE", "OPTIONS"}, nil, space.Remove)
|
||||
Add(rt, RoutePrefixPrivate, "space/{spaceID}/permissions", []string{"PUT", "OPTIONS"}, nil, space.SetPermissions)
|
||||
Add(rt, RoutePrefixPrivate, "space/{spaceID}/permissions/user", []string{"GET", "OPTIONS"}, nil, space.GetUserPermissions)
|
||||
Add(rt, RoutePrefixPrivate, "space/{spaceID}/permissions", []string{"GET", "OPTIONS"}, nil, space.GetPermissions)
|
||||
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", []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{"PUT", "OPTIONS"}, nil, space.Update)
|
||||
|
||||
Add(rt, RoutePrefixPrivate, "users/{userID}/password", []string{"POST", "OPTIONS"}, nil, user.ChangePassword)
|
||||
Add(rt, RoutePrefixPrivate, "users/{userID}/permissions", []string{"GET", "OPTIONS"}, nil, user.UserSpacePermissions)
|
||||
Add(rt, RoutePrefixPrivate, "users", []string{"POST", "OPTIONS"}, nil, user.Add)
|
||||
Add(rt, RoutePrefixPrivate, "users/folder/{folderID}", []string{"GET", "OPTIONS"}, nil, user.GetSpaceUsers)
|
||||
Add(rt, RoutePrefixPrivate, "users", []string{"GET", "OPTIONS"}, nil, user.GetOrganizationUsers)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue