Add role management
Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
This commit is contained in:
@@ -58,9 +58,9 @@ func NewServer(cfg Config) (*Server, error) {
|
||||
router.Post("/invitations/accept", AcceptInvitationHandler(cfg.Auth, cfg.Authz, cfg.CookieName, cfg.CookieSecret, cfg.CookieSecure))
|
||||
|
||||
router.Get("/api-keys", RequireAuth(cfg.Auth, cfg.Authz, cfg.CookieName, cfg.CookieSecret, cfg.CookieSecure, ListUserAPIKeysHandler(cfg.Auth, cfg.Authz)))
|
||||
router.Post("/api-keys", RequireAuth(cfg.Auth, cfg.Authz, cfg.CookieName, cfg.CookieSecret, cfg.CookieSecure, CreateUserAPIKeyHandler(cfg.Auth)))
|
||||
router.Post("/api-keys", RequireAuth(cfg.Auth, cfg.Authz, cfg.CookieName, cfg.CookieSecret, cfg.CookieSecure, CreateUserAPIKeyHandler(cfg.Auth, cfg.Authz)))
|
||||
router.Get("/api-keys/{id}", RequireAuth(cfg.Auth, cfg.Authz, cfg.CookieName, cfg.CookieSecret, cfg.CookieSecure, GetUserAPIKeyHandler(cfg.Auth)))
|
||||
router.Put("/api-keys", RequireAuth(cfg.Auth, cfg.Authz, cfg.CookieName, cfg.CookieSecret, cfg.CookieSecure, UpdateUserAPIKeyHandler(cfg.Auth)))
|
||||
router.Put("/api-keys", RequireAuth(cfg.Auth, cfg.Authz, cfg.CookieName, cfg.CookieSecret, cfg.CookieSecure, UpdateUserAPIKeyHandler(cfg.Auth, cfg.Authz)))
|
||||
router.Delete("/api-keys", RequireAuth(cfg.Auth, cfg.Authz, cfg.CookieName, cfg.CookieSecret, cfg.CookieSecure, DeleteUserAPIKeyHandler(cfg.Auth)))
|
||||
|
||||
router.Get("/saml/login/{samlConfigID}", SAMLLoginHandler(cfg.SAML, cfg.Auth, cfg.Logger))
|
||||
|
||||
@@ -22,6 +22,7 @@ import (
|
||||
|
||||
"go.gearno.de/kit/httpserver"
|
||||
authsvc "go.probo.inc/probo/pkg/auth"
|
||||
"go.probo.inc/probo/pkg/authz"
|
||||
"go.probo.inc/probo/pkg/coredata"
|
||||
"go.probo.inc/probo/pkg/gid"
|
||||
)
|
||||
@@ -44,7 +45,7 @@ type (
|
||||
}
|
||||
)
|
||||
|
||||
func CreateUserAPIKeyHandler(authSvc *authsvc.Service) http.HandlerFunc {
|
||||
func CreateUserAPIKeyHandler(authSvc *authsvc.Service, authzSvc *authz.Service) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
user := UserFromContext(ctx)
|
||||
@@ -92,6 +93,24 @@ func CreateUserAPIKeyHandler(authSvc *authsvc.Service) http.HandlerFunc {
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// Check if user is an OWNER for this organization
|
||||
tenantAuthzSvc := authzSvc.WithTenant(orgID.TenantID())
|
||||
role, err := tenantAuthzSvc.GetUserRoleInOrganization(ctx, user.ID, orgID)
|
||||
if err != nil {
|
||||
httpserver.RenderJSON(w, http.StatusForbidden, map[string]string{
|
||||
"error": "user does not have access to this organization",
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
if role != coredata.MembershipRoleOwner {
|
||||
httpserver.RenderJSON(w, http.StatusForbidden, map[string]string{
|
||||
"error": "only owners can create API keys for this organization",
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
orgInputs[i] = authsvc.UserAPIKeyOrganizationRequest{
|
||||
OrganizationID: orgID,
|
||||
Role: coredata.APIRole(org.Role),
|
||||
|
||||
@@ -18,11 +18,11 @@ import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"go.gearno.de/kit/httpserver"
|
||||
authsvc "go.probo.inc/probo/pkg/auth"
|
||||
"go.probo.inc/probo/pkg/authz"
|
||||
"go.probo.inc/probo/pkg/coredata"
|
||||
"go.probo.inc/probo/pkg/gid"
|
||||
"go.gearno.de/kit/httpserver"
|
||||
)
|
||||
|
||||
type (
|
||||
@@ -106,9 +106,21 @@ func ListOrganizationsHandler(authSvc *authsvc.Service, authzSvc *authz.Service)
|
||||
user := UserFromContext(ctx)
|
||||
sess := SessionFromContext(ctx)
|
||||
|
||||
organizations, err := authzSvc.GetAllUserOrganizations(ctx, user.ID)
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("cannot list organizations for user: %w", err))
|
||||
var organizations coredata.Organizations
|
||||
var err error
|
||||
|
||||
roleFilter := r.URL.Query().Get("role")
|
||||
if roleFilter != "" {
|
||||
role := coredata.MembershipRole(roleFilter)
|
||||
organizations, err = authzSvc.GetUserOrganizationsWithRole(ctx, user.ID, role)
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("cannot list organizations for user with role: %w", err))
|
||||
}
|
||||
} else {
|
||||
organizations, err = authzSvc.GetAllUserOrganizations(ctx, user.ID)
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("cannot list organizations for user: %w", err))
|
||||
}
|
||||
}
|
||||
|
||||
orgIDs := make([]gid.GID, len(organizations))
|
||||
|
||||
@@ -22,6 +22,7 @@ import (
|
||||
|
||||
"go.gearno.de/kit/httpserver"
|
||||
authsvc "go.probo.inc/probo/pkg/auth"
|
||||
"go.probo.inc/probo/pkg/authz"
|
||||
"go.probo.inc/probo/pkg/coredata"
|
||||
"go.probo.inc/probo/pkg/gid"
|
||||
)
|
||||
@@ -32,7 +33,7 @@ type UpdateUserAPIKeyRequest struct {
|
||||
Organizations []UserAPIKeyOrganizationMembershipRequest `json:"organizations"`
|
||||
}
|
||||
|
||||
func UpdateUserAPIKeyHandler(authSvc *authsvc.Service) http.HandlerFunc {
|
||||
func UpdateUserAPIKeyHandler(authSvc *authsvc.Service, authzSvc *authz.Service) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
user := UserFromContext(ctx)
|
||||
@@ -100,6 +101,22 @@ func UpdateUserAPIKeyHandler(authSvc *authsvc.Service) http.HandlerFunc {
|
||||
return
|
||||
}
|
||||
|
||||
// Check if user is an OWNER for this organization
|
||||
tenantAuthzSvc := authzSvc.WithTenant(orgID.TenantID())
|
||||
role, err := tenantAuthzSvc.GetUserRoleInOrganization(ctx, user.ID, orgID)
|
||||
if err != nil {
|
||||
httpserver.RenderJSON(w, http.StatusForbidden, map[string]string{
|
||||
"error": "user does not have access to this organization",
|
||||
})
|
||||
return
|
||||
}
|
||||
if role != coredata.MembershipRoleOwner {
|
||||
httpserver.RenderJSON(w, http.StatusForbidden, map[string]string{
|
||||
"error": "only owners can update API keys for this organization",
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
orgInputs[i] = authsvc.UserAPIKeyOrganizationRequest{
|
||||
OrganizationID: orgID,
|
||||
Role: coredata.APIRole(org.Role),
|
||||
|
||||
Reference in New Issue
Block a user