Skip to content

Commit

Permalink
docs: add brief description in public func and methods
Browse files Browse the repository at this point in the history
  • Loading branch information
shipperizer committed Mar 15, 2024
1 parent ba8a624 commit e2bc97d
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 14 deletions.
14 changes: 4 additions & 10 deletions pkg/roles/handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ type RoleRequest struct {
ID string `json:"id" validate:"required"`
}

// API is the core HTTP object that implements all the HTTP and business logic for the roles
// HTTP API functionality
type API struct {
service ServiceInterface

Expand All @@ -44,16 +46,7 @@ type API struct {
monitor monitoring.MonitorInterface
}

// GET /roles: list all available roles, not filtered by access permissions
// POST /roles: create a role (name will be ID), allows to attach permissions, groups and users (to evaluate feasibility)
// GET /roles/{id}: details of a specific role, in particular permissions, might expand to associated users and groups
// PATCH /roles/{id}: associate permissions
// DELETE /roles/{id}: remove role
// GET /roles/{id}/entitlements: list of associated permissions to the role, tuple read on each type fga --api-url http://127.0.0.1:8080 --store-id $STORE_ID tuple read --user role:administrator#assignee --object client:
// POST /roles/{id}/entitlements: associate a new permissions to the role
// GET /roles/{id}/entitlements/{e_id}: details about the entitlement
// GET roles/{id}/groups: see groups associated with the role, using read tuple as no direct relationship between role and group, just other way round

// RegisterEndpoints hooks up all the endpoints to the server mux passed via the arg
func (a *API) RegisterEndpoints(mux *chi.Mux) {
mux.Get("/api/v0/roles", a.handleList)
mux.Get("/api/v0/roles/{id}", a.handleDetail)
Expand Down Expand Up @@ -465,6 +458,7 @@ func (a *API) handleRemovePermission(w http.ResponseWriter, r *http.Request) {
)
}

// NewAPI returns an API object responsible for all the roles HTTP handlers
func NewAPI(service ServiceInterface, tracer tracing.TracingInterface, monitor monitoring.MonitorInterface, logger logging.LoggerInterface) *API {
a := new(API)

Expand Down
8 changes: 5 additions & 3 deletions pkg/roles/interfaces.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,19 @@ import (
ofga "github.com/canonical/identity-platform-admin-ui/internal/openfga"
)

// ServiceInterface is the interface that each business logic service needs to implement
type ServiceInterface interface {
ListRoles(context.Context, string) ([]string, error) // list of roles, continuation token, error
ListRoles(context.Context, string) ([]string, error)
GetRole(context.Context, string, string) (string, error)
CreateRole(context.Context, string, string) error
DeleteRole(context.Context, string) error
ListRoleGroups(context.Context, string, string) ([]string, string, error)
ListPermissions(context.Context, string, map[string]string) ([]string, map[string]string, error) // list of permissions, {"type":"continuation tokens"}
AssignPermissions(context.Context, string, ...Permission) error // passing in role id and list of groups
ListPermissions(context.Context, string, map[string]string) ([]string, map[string]string, error)
AssignPermissions(context.Context, string, ...Permission) error
RemovePermissions(context.Context, string, ...Permission) error
}

// OpenFGAClientInterface is the interface used to decouple the OpenFGA store implementation
type OpenFGAClientInterface interface {
ListObjects(context.Context, string, string, string) ([]string, error)
ReadTuples(context.Context, string, string, string, string) (*client.ClientReadResponse, error)
Expand Down
14 changes: 13 additions & 1 deletion pkg/roles/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ const (
ASSIGNEE_RELATION = "assignee"
)

// Service contains the business logic to deal with roles on the Admin UI OpenFGA model
type Service struct {
ofga OpenFGAClientInterface

Expand All @@ -29,6 +30,7 @@ type Service struct {
logger logging.LoggerInterface
}

// ListRoles returns all the roles a specific user can see (using "can_view" OpenFGA relation)
func (s *Service) ListRoles(ctx context.Context, userID string) ([]string, error) {
ctx, span := s.tracer.Start(ctx, "roles.Service.ListRoles")
defer span.End()
Expand All @@ -43,7 +45,8 @@ func (s *Service) ListRoles(ctx context.Context, userID string) ([]string, error
return roles, nil
}

// ListRoleGroups does rely on the /read endpoint which allows for pagination via the token
// ListRoleGroups returns all the groups associated to a specific role
// method relies on the /read endpoint which allows for pagination via the token
// unfortunately we are not able to distinguish between types assigned on the OpenFGA side,
// so we'll have to filter here based on the user, this leads to unrealiable object counts
// TODO @shipperizer a more complex pagination system can be implemented by keeping track of the
Expand Down Expand Up @@ -71,6 +74,7 @@ func (s *Service) ListRoleGroups(ctx context.Context, ID, continuationToken stri
return groups, r.GetContinuationToken(), nil
}

// ListPermissions returns all the permissions associated to a specific role
func (s *Service) ListPermissions(ctx context.Context, ID string, continuationTokens map[string]string) ([]string, map[string]string, error) {
ctx, span := s.tracer.Start(ctx, "roles.Service.ListPermissions")
defer span.End()
Expand Down Expand Up @@ -125,6 +129,8 @@ func (s *Service) ListPermissions(ctx context.Context, ID string, continuationTo
return permissions, tokens, nil
}

// GetRole returns the specified role using the ID argument, userID is used to validate the visibility by the user
// making the call
func (s *Service) GetRole(ctx context.Context, userID, ID string) (string, error) {
ctx, span := s.tracer.Start(ctx, "roles.Service.GetRole")
defer span.End()
Expand All @@ -145,6 +151,8 @@ func (s *Service) GetRole(ctx context.Context, userID, ID string) (string, error
return "", nil
}

// CreateRole creates a role and associates it with the userID passed as argument
// an extra tuple is created to estabilish the "privileged" relatin for admin users
func (s *Service) CreateRole(ctx context.Context, userID, ID string) error {
ctx, span := s.tracer.Start(ctx, "roles.Service.CreateRole")
defer span.End()
Expand All @@ -171,6 +179,7 @@ func (s *Service) CreateRole(ctx context.Context, userID, ID string) error {
return nil
}

// AssignPermissions assigns permissions to a role
// TODO @shipperizer see if it's worth using only one between Permission and ofga.Tuple
func (s *Service) AssignPermissions(ctx context.Context, ID string, permissions ...Permission) error {
ctx, span := s.tracer.Start(ctx, "roles.Service.AssignPermissions")
Expand All @@ -195,6 +204,7 @@ func (s *Service) AssignPermissions(ctx context.Context, ID string, permissions
return nil
}

// RemovePermissions removes permissions from a role
// TODO @shipperizer see if it's worth using only one between Permission and ofga.Tuple
func (s *Service) RemovePermissions(ctx context.Context, ID string, permissions ...Permission) error {
ctx, span := s.tracer.Start(ctx, "roles.Service.RemovePermissions")
Expand All @@ -219,6 +229,7 @@ func (s *Service) RemovePermissions(ctx context.Context, ID string, permissions
return nil
}

// DeleteRole deletes a role and all the related tuples
func (s *Service) DeleteRole(ctx context.Context, ID string) error {
ctx, span := s.tracer.Start(ctx, "roles.Service.DeleteRole")
defer span.End()
Expand Down Expand Up @@ -300,6 +311,7 @@ func (s *Service) permissionTypes() []string {
return []string{"role", "group", "identity", "scheme", "provider", "client"}
}

// NewService returns the implementtation of the business logic for the roles API
func NewService(ofga OpenFGAClientInterface, tracer trace.Tracer, monitor monitoring.MonitorInterface, logger logging.LoggerInterface) *Service {
s := new(Service)

Expand Down

0 comments on commit e2bc97d

Please sign in to comment.