🔒 Check permissions
This commit is contained in:
parent
5961b33ba0
commit
99bce4d1fc
25
store.go
25
store.go
|
@ -56,6 +56,7 @@ type ShareStore interface {
|
||||||
GetShares() ([]Share, error)
|
GetShares() ([]Share, error)
|
||||||
GetShareUsers(share Share) ([]ShareUser, error)
|
GetShareUsers(share Share) ([]ShareUser, error)
|
||||||
GetShareLogins(share Share, username string) ([]Login, error)
|
GetShareLogins(share Share, username string) ([]Login, error)
|
||||||
|
GetShareAccess(share Share, username string) (ShareRole, error)
|
||||||
|
|
||||||
FindShareByLogin(username, loginName string) (LoginShare, error)
|
FindShareByLogin(username, loginName string) (LoginShare, error)
|
||||||
FindSharesByUser(username string) ([]UserShare, error)
|
FindSharesByUser(username string) ([]UserShare, error)
|
||||||
|
@ -384,6 +385,30 @@ func (store *DBStore) AddUserToShare(share Share, username string, role ShareRol
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (store *DBStore) GetShareAccess(share Share, username string) (ShareRole, error) {
|
||||||
|
if strings.Contains(username, ":") {
|
||||||
|
return "", ErrInvalidUsername
|
||||||
|
}
|
||||||
|
|
||||||
|
var shareRole ShareRole
|
||||||
|
|
||||||
|
err := store.db.View(func(tx *buntdb.Tx) error {
|
||||||
|
if _, err := tx.Get(share.key()); err != nil {
|
||||||
|
return ErrShareNotFound
|
||||||
|
}
|
||||||
|
if val, err := tx.Get(share.userKey(username)); err == buntdb.ErrNotFound {
|
||||||
|
return ErrUserNotFound
|
||||||
|
} else if err != nil {
|
||||||
|
return fmt.Errorf("cannot get user: %w", err)
|
||||||
|
} else {
|
||||||
|
shareRole = ShareRole(val)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
|
||||||
|
return shareRole, err
|
||||||
|
}
|
||||||
|
|
||||||
func (store *DBStore) removeUserFromShare(tx *buntdb.Tx, share Share, username string) error {
|
func (store *DBStore) removeUserFromShare(tx *buntdb.Tx, share Share, username string) error {
|
||||||
var logins []string
|
var logins []string
|
||||||
loginsPrefix := share.loginKey(username, "")
|
loginsPrefix := share.loginKey(username, "")
|
||||||
|
|
|
@ -244,6 +244,23 @@ func TestStoreShareHandling(t *testing.T) {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
t.Run("can get share access", func(t *testing.T) {
|
||||||
|
shareRole, err := store.GetShareAccess(share1, user1.Username)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
if shareRole != ShareRoleAdmin {
|
||||||
|
t.Errorf("unexpected role: %s", shareRole)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("cannot get share access if user has none", func(t *testing.T) {
|
||||||
|
_, err := store.GetShareAccess(share2, user1.Username)
|
||||||
|
if err != ErrUserNotFound {
|
||||||
|
t.Errorf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
t.Run("can list users", func(t *testing.T) {
|
t.Run("can list users", func(t *testing.T) {
|
||||||
users, err := store.GetShareUsers(share1)
|
users, err := store.GetShareUsers(share1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
62
webadmin.go
62
webadmin.go
|
@ -57,6 +57,7 @@ type sessionContext struct {
|
||||||
h *webAdminHandler
|
h *webAdminHandler
|
||||||
w http.ResponseWriter
|
w http.ResponseWriter
|
||||||
r *http.Request
|
r *http.Request
|
||||||
|
user User
|
||||||
baseModel map[string]interface{}
|
baseModel map[string]interface{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -181,6 +182,11 @@ func newWebAdminHandler(app *app) *webAdminHandler {
|
||||||
ar.Get("/users", func(w http.ResponseWriter, r *http.Request) {
|
ar.Get("/users", func(w http.ResponseWriter, r *http.Request) {
|
||||||
sessionContext := h.buildSessionContext(w, r)
|
sessionContext := h.buildSessionContext(w, r)
|
||||||
|
|
||||||
|
if sessionContext.user.Role != GlobalRoleAdmin {
|
||||||
|
sessionContext.Unauthorized()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
users, err := app.userStore.GetUsers()
|
users, err := app.userStore.GetUsers()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||||
|
@ -194,6 +200,11 @@ func newWebAdminHandler(app *app) *webAdminHandler {
|
||||||
ar.Get("/shares", func(w http.ResponseWriter, r *http.Request) {
|
ar.Get("/shares", func(w http.ResponseWriter, r *http.Request) {
|
||||||
sessionContext := h.buildSessionContext(w, r)
|
sessionContext := h.buildSessionContext(w, r)
|
||||||
|
|
||||||
|
if sessionContext.user.Role != GlobalRoleAdmin {
|
||||||
|
sessionContext.Unauthorized()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
shares, err := app.shareStore.GetShares()
|
shares, err := app.shareStore.GetShares()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||||
|
@ -224,12 +235,20 @@ func newWebAdminHandler(app *app) *webAdminHandler {
|
||||||
r.Get("/", func(w http.ResponseWriter, r *http.Request) {
|
r.Get("/", func(w http.ResponseWriter, r *http.Request) {
|
||||||
sessionContext := h.buildSessionContext(w, r)
|
sessionContext := h.buildSessionContext(w, r)
|
||||||
|
|
||||||
shareId := r.URL.Query().Get("share")
|
share, err := app.shareStore.GetShare(r.URL.Query().Get("share"))
|
||||||
if shareId == "" {
|
if err != nil {
|
||||||
http.Error(w, "invalid share id", http.StatusBadRequest)
|
sessionContext.RenderError(template.HTML("Internal error: "+err.Error()), "")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if sessionContext.user.Role != GlobalRoleAdmin {
|
||||||
|
shareRole, err := app.shareStore.GetShareAccess(share, sessionContext.user.Username)
|
||||||
|
if err != nil || shareRole != ShareRoleAdmin {
|
||||||
|
sessionContext.Unauthorized()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
users, err := app.userStore.GetUsers()
|
users, err := app.userStore.GetUsers()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||||
|
@ -237,7 +256,7 @@ func newWebAdminHandler(app *app) *webAdminHandler {
|
||||||
}
|
}
|
||||||
|
|
||||||
sessionContext.RenderPage(h.tplShareAddUser, map[string]interface{}{
|
sessionContext.RenderPage(h.tplShareAddUser, map[string]interface{}{
|
||||||
"ShareId": shareId,
|
"ShareId": share.UUID,
|
||||||
"Users": users,
|
"Users": users,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -246,12 +265,19 @@ func newWebAdminHandler(app *app) *webAdminHandler {
|
||||||
|
|
||||||
returnURL := "share-add-user?share=" + r.FormValue("share")
|
returnURL := "share-add-user?share=" + r.FormValue("share")
|
||||||
|
|
||||||
shareId, err := uuid.FromString(r.FormValue("share"))
|
share, err := app.shareStore.GetShare(r.FormValue("share"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
sessionContext.RenderError(template.HTML("Internal error: "+err.Error()), "")
|
sessionContext.RenderError(template.HTML("Internal error: "+err.Error()), "")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
share := Share{UUID: shareId}
|
|
||||||
|
if sessionContext.user.Role != GlobalRoleAdmin {
|
||||||
|
shareRole, err := app.shareStore.GetShareAccess(share, sessionContext.user.Username)
|
||||||
|
if err != nil || shareRole != ShareRoleAdmin {
|
||||||
|
sessionContext.Unauthorized()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
user, err := app.userStore.GetUser(r.FormValue("user"))
|
user, err := app.userStore.GetUser(r.FormValue("user"))
|
||||||
if err == ErrUserNotFound {
|
if err == ErrUserNotFound {
|
||||||
|
@ -276,12 +302,19 @@ func newWebAdminHandler(app *app) *webAdminHandler {
|
||||||
|
|
||||||
returnURL := "shares"
|
returnURL := "shares"
|
||||||
|
|
||||||
shareId, err := uuid.FromString(r.FormValue("share"))
|
share, err := app.shareStore.GetShare(r.FormValue("share"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
sessionContext.RenderError(template.HTML("Internal error: "+err.Error()), "")
|
sessionContext.RenderError(template.HTML("Internal error: "+err.Error()), "")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
share := Share{UUID: shareId}
|
|
||||||
|
if sessionContext.user.Role != GlobalRoleAdmin {
|
||||||
|
shareRole, err := app.shareStore.GetShareAccess(share, sessionContext.user.Username)
|
||||||
|
if err != nil || shareRole != ShareRoleAdmin {
|
||||||
|
sessionContext.Unauthorized()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
err = app.shareStore.RemoveUserFromShare(share, r.FormValue("user"))
|
err = app.shareStore.RemoveUserFromShare(share, r.FormValue("user"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -325,6 +358,14 @@ func newWebAdminHandler(app *app) *webAdminHandler {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if sessionContext.user.Role != GlobalRoleAdmin {
|
||||||
|
shareRole, err := app.shareStore.GetShareAccess(share, sessionContext.user.Username)
|
||||||
|
if err != nil || shareRole != ShareRoleAdmin {
|
||||||
|
sessionContext.Unauthorized()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
message := fmt.Sprintf(`You are about to delete the share %s (%s).<br/>
|
message := fmt.Sprintf(`You are about to delete the share %s (%s).<br/>
|
||||||
This will delete all data permanently.<br/><br/>
|
This will delete all data permanently.<br/><br/>
|
||||||
Are you sure you want to continue?`, share.UUID, share.Name)
|
Are you sure you want to continue?`, share.UUID, share.Name)
|
||||||
|
@ -357,6 +398,7 @@ func (h *webAdminHandler) buildSessionContext(w http.ResponseWriter, r *http.Req
|
||||||
}
|
}
|
||||||
sessionUser := userFromContext(r)
|
sessionUser := userFromContext(r)
|
||||||
if sessionUser != nil {
|
if sessionUser != nil {
|
||||||
|
sessionContext.user = *sessionUser
|
||||||
sessionContext.baseModel["SessionUser"] = sessionUser
|
sessionContext.baseModel["SessionUser"] = sessionUser
|
||||||
}
|
}
|
||||||
return sessionContext
|
return sessionContext
|
||||||
|
@ -387,6 +429,10 @@ func (s *sessionContext) RenderError(msg template.HTML, returnURL string) {
|
||||||
s.RenderPage(s.h.tplError, model)
|
s.RenderPage(s.h.tplError, model)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *sessionContext) Unauthorized() {
|
||||||
|
http.Error(s.w, http.StatusText(http.StatusForbidden), http.StatusForbidden)
|
||||||
|
}
|
||||||
|
|
||||||
func (s *sessionContext) RequestConfirmation(msg template.HTML, returnURL string) int {
|
func (s *sessionContext) RequestConfirmation(msg template.HTML, returnURL string) int {
|
||||||
if s.r.FormValue("_yes") != "" {
|
if s.r.FormValue("_yes") != "" {
|
||||||
return confirmAccepted
|
return confirmAccepted
|
||||||
|
|
Loading…
Reference in New Issue