Add role management
Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
This commit is contained in:
@@ -77,9 +77,9 @@ func ExtractEmailDomain(email string) (string, error) {
|
||||
return domain, nil
|
||||
}
|
||||
|
||||
func MapSAMLRoleToSystemRole(samlRole string) *coredata.Role {
|
||||
func MapSAMLRoleToSystemRole(samlRole string) *coredata.MembershipRole {
|
||||
if samlRole != "" && isValidRole(samlRole) {
|
||||
role := coredata.Role(samlRole)
|
||||
role := coredata.MembershipRole(samlRole)
|
||||
return &role
|
||||
}
|
||||
|
||||
@@ -88,7 +88,7 @@ func MapSAMLRoleToSystemRole(samlRole string) *coredata.Role {
|
||||
|
||||
func isValidRole(role string) bool {
|
||||
switch role {
|
||||
case "OWNER", "ADMIN", "MEMBER", "VIEWER":
|
||||
case "OWNER", "ADMIN", "VIEWER":
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
|
||||
@@ -407,7 +407,7 @@ func (s *SAMLService) InitiateSAMLLogin(
|
||||
type SAMLUserInfo struct {
|
||||
Email string
|
||||
FullName string
|
||||
Role *coredata.Role
|
||||
Role *coredata.MembershipRole
|
||||
SAMLSubject string
|
||||
OrganizationID gid.GID
|
||||
SAMLConfigID gid.GID
|
||||
|
||||
@@ -46,6 +46,8 @@ type (
|
||||
invitationTokenValidity time.Duration
|
||||
}
|
||||
|
||||
ErrCreateOrganizationDisabled struct{}
|
||||
|
||||
TenantAuthService struct {
|
||||
pg *pg.Client
|
||||
encryptionKey cipher.EncryptionKey
|
||||
@@ -192,6 +194,10 @@ func (e ErrSAMLAutoSignupDisabled) Error() string {
|
||||
return "SAML auto-signup is disabled for this organization"
|
||||
}
|
||||
|
||||
func (e ErrCreateOrganizationDisabled) Error() string {
|
||||
return "organization creation is disabled for users without existing admin or owner membership"
|
||||
}
|
||||
|
||||
func (e ErrSAMLAuthRequired) Error() string {
|
||||
return "SAML authentication required for this organization"
|
||||
}
|
||||
@@ -232,6 +238,28 @@ func (s *Service) WithTenant(tenantID gid.TenantID) *TenantAuthService {
|
||||
}
|
||||
}
|
||||
|
||||
func (s Service) CanCreateOrganization(ctx context.Context, userID gid.GID) error {
|
||||
if !s.disableSignup {
|
||||
return nil
|
||||
}
|
||||
|
||||
var memberships coredata.Memberships
|
||||
err := s.pg.WithConn(ctx, func(conn pg.Conn) error {
|
||||
return memberships.LoadByUserID(ctx, conn, coredata.NewNoScope(), userID)
|
||||
})
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot load user memberships: %w", err)
|
||||
}
|
||||
|
||||
for _, membership := range memberships {
|
||||
if membership.Role == coredata.MembershipRoleOwner || membership.Role == coredata.MembershipRoleAdmin {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
return &ErrCreateOrganizationDisabled{}
|
||||
}
|
||||
|
||||
func (s Service) ForgetPassword(
|
||||
ctx context.Context,
|
||||
email string,
|
||||
@@ -1351,13 +1379,20 @@ func (s *Service) CreateUserAPIKey(
|
||||
|
||||
for _, membership := range memberships {
|
||||
scope := coredata.NewScope(membership.MembershipID.TenantID())
|
||||
|
||||
var m coredata.Membership
|
||||
if err := m.LoadByID(ctx, tx, scope, membership.MembershipID); err != nil {
|
||||
return fmt.Errorf("cannot load membership: %w", err)
|
||||
}
|
||||
|
||||
userAPIKeyMembership := &coredata.UserAPIKeyMembership{
|
||||
ID: gid.New(membership.MembershipID.TenantID(), coredata.UserAPIKeyMembershipEntityType),
|
||||
UserAPIKeyID: userAPIKey.ID,
|
||||
MembershipID: membership.MembershipID,
|
||||
Role: membership.Role,
|
||||
CreatedAt: now,
|
||||
UpdatedAt: now,
|
||||
ID: gid.New(membership.MembershipID.TenantID(), coredata.UserAPIKeyMembershipEntityType),
|
||||
UserAPIKeyID: userAPIKey.ID,
|
||||
MembershipID: membership.MembershipID,
|
||||
Role: membership.Role,
|
||||
OrganizationID: m.OrganizationID,
|
||||
CreatedAt: now,
|
||||
UpdatedAt: now,
|
||||
}
|
||||
|
||||
if err := userAPIKeyMembership.Insert(ctx, tx, scope); err != nil {
|
||||
@@ -1513,13 +1548,20 @@ func (s *Service) UpdateUserAPIKeyMemberships(
|
||||
now := time.Now()
|
||||
for _, membership := range memberships {
|
||||
scope := coredata.NewScope(membership.MembershipID.TenantID())
|
||||
|
||||
var m coredata.Membership
|
||||
if err := m.LoadByID(ctx, tx, scope, membership.MembershipID); err != nil {
|
||||
return fmt.Errorf("cannot load membership: %w", err)
|
||||
}
|
||||
|
||||
userAPIKeyMembership := &coredata.UserAPIKeyMembership{
|
||||
ID: gid.New(membership.MembershipID.TenantID(), coredata.UserAPIKeyMembershipEntityType),
|
||||
UserAPIKeyID: userAPIKey.ID,
|
||||
MembershipID: membership.MembershipID,
|
||||
Role: membership.Role,
|
||||
CreatedAt: now,
|
||||
UpdatedAt: now,
|
||||
ID: gid.New(membership.MembershipID.TenantID(), coredata.UserAPIKeyMembershipEntityType),
|
||||
UserAPIKeyID: userAPIKey.ID,
|
||||
MembershipID: membership.MembershipID,
|
||||
Role: membership.Role,
|
||||
OrganizationID: m.OrganizationID,
|
||||
CreatedAt: now,
|
||||
UpdatedAt: now,
|
||||
}
|
||||
|
||||
if err := userAPIKeyMembership.Insert(ctx, tx, scope); err != nil {
|
||||
|
||||
Reference in New Issue
Block a user