2018-07-30 21:46:30 +00:00
|
|
|
package platform
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"errors"
|
|
|
|
)
|
|
|
|
|
2018-12-28 23:02:19 +00:00
|
|
|
var (
|
|
|
|
// ErrInvalidUserType notes that the provided UserType is invalid
|
|
|
|
ErrInvalidUserType = errors.New("unknown user type")
|
|
|
|
// ErrUserIDRequired notes that the ID was not provided
|
|
|
|
ErrUserIDRequired = errors.New("user id is required")
|
|
|
|
// ErrResourceIDRequired notes that the provided ID was not provided
|
|
|
|
ErrResourceIDRequired = errors.New("resource id is required")
|
|
|
|
)
|
|
|
|
|
|
|
|
// UserType can either be owner or member.
|
2018-07-30 21:46:30 +00:00
|
|
|
type UserType string
|
|
|
|
|
|
|
|
const (
|
2018-12-28 23:02:19 +00:00
|
|
|
// Owner can read and write to a resource
|
|
|
|
Owner UserType = "owner" // 1
|
|
|
|
// Member can read from a resource.
|
|
|
|
Member UserType = "member" // 2
|
2018-07-30 21:46:30 +00:00
|
|
|
)
|
|
|
|
|
2018-12-28 23:02:19 +00:00
|
|
|
// Valid checks if the UserType is a member of the UserType enum
|
|
|
|
func (ut UserType) Valid() (err error) {
|
|
|
|
switch ut {
|
|
|
|
case Owner: // 1
|
|
|
|
case Member: // 2
|
|
|
|
default:
|
|
|
|
err = ErrInvalidUserType
|
|
|
|
}
|
|
|
|
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
// UserResourceMappingService maps the relationships between users and resources.
|
2018-07-30 21:46:30 +00:00
|
|
|
type UserResourceMappingService interface {
|
2018-09-24 17:17:54 +00:00
|
|
|
// FindUserResourceMappings returns a list of UserResourceMappings that match filter and the total count of matching mappings.
|
|
|
|
FindUserResourceMappings(ctx context.Context, filter UserResourceMappingFilter, opt ...FindOptions) ([]*UserResourceMapping, int, error)
|
|
|
|
|
2018-12-28 23:02:19 +00:00
|
|
|
// CreateUserResourceMapping creates a user resource mapping.
|
2018-07-30 21:46:30 +00:00
|
|
|
CreateUserResourceMapping(ctx context.Context, m *UserResourceMapping) error
|
2018-09-24 17:17:54 +00:00
|
|
|
|
2018-12-28 23:02:19 +00:00
|
|
|
// DeleteUserResourceMapping deletes a user resource mapping.
|
2018-07-30 21:46:30 +00:00
|
|
|
DeleteUserResourceMapping(ctx context.Context, resourceID ID, userID ID) error
|
|
|
|
}
|
|
|
|
|
2018-12-28 23:02:19 +00:00
|
|
|
// UserResourceMapping represents a mapping of a resource to its user.
|
2018-07-30 21:46:30 +00:00
|
|
|
type UserResourceMapping struct {
|
2018-12-28 23:02:19 +00:00
|
|
|
UserID ID `json:"userID"`
|
|
|
|
UserType UserType `json:"userType"`
|
|
|
|
Resource Resource `json:"resource"`
|
|
|
|
ResourceID ID `json:"resourceID"`
|
2018-07-30 21:46:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Validate reports any validation errors for the mapping.
|
|
|
|
func (m UserResourceMapping) Validate() error {
|
2018-09-12 11:25:17 +00:00
|
|
|
if !m.ResourceID.Valid() {
|
2018-12-28 23:02:19 +00:00
|
|
|
return ErrResourceIDRequired
|
2018-07-30 21:46:30 +00:00
|
|
|
}
|
2018-12-28 23:02:19 +00:00
|
|
|
|
2018-09-12 11:25:17 +00:00
|
|
|
if !m.UserID.Valid() {
|
2018-12-28 23:02:19 +00:00
|
|
|
return ErrUserIDRequired
|
2018-07-30 21:46:30 +00:00
|
|
|
}
|
2018-12-28 23:02:19 +00:00
|
|
|
|
|
|
|
if err := m.UserType.Valid(); err != nil {
|
|
|
|
return err
|
2018-07-30 21:46:30 +00:00
|
|
|
}
|
2018-12-28 23:02:19 +00:00
|
|
|
|
|
|
|
if err := m.Resource.Valid(); err != nil {
|
|
|
|
return err
|
2018-10-04 21:37:37 +00:00
|
|
|
}
|
2018-12-28 23:02:19 +00:00
|
|
|
|
2018-07-30 21:46:30 +00:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2018-12-28 23:02:19 +00:00
|
|
|
// UserResourceMappingFilter represents a set of filters that restrict the returned results.
|
2018-07-30 21:46:30 +00:00
|
|
|
type UserResourceMappingFilter struct {
|
2018-12-28 23:02:19 +00:00
|
|
|
ResourceID ID
|
|
|
|
Resource Resource
|
|
|
|
UserID ID
|
|
|
|
UserType UserType
|
2018-07-30 21:46:30 +00:00
|
|
|
}
|
2018-11-20 18:56:58 +00:00
|
|
|
|
2018-12-28 23:02:19 +00:00
|
|
|
var ownerActions = []Action{WriteAction, ReadAction}
|
|
|
|
var memberActions = []Action{ReadAction}
|
|
|
|
|
|
|
|
func (m *UserResourceMapping) ownerPerms() ([]Permission, error) {
|
|
|
|
ps := make([]Permission, 0, len(ownerActions))
|
|
|
|
for _, a := range ownerActions {
|
|
|
|
p, err := NewPermissionAtID(m.ResourceID, a, m.Resource)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
2018-11-20 18:56:58 +00:00
|
|
|
}
|
2018-12-28 23:02:19 +00:00
|
|
|
|
|
|
|
ps = append(ps, *p)
|
2019-01-09 15:35:21 +00:00
|
|
|
|
|
|
|
if m.Resource == OrgsResource {
|
|
|
|
ps = append(ps, OrgAdminPermissions(m.ResourceID)...)
|
|
|
|
}
|
|
|
|
|
2018-11-20 18:56:58 +00:00
|
|
|
}
|
|
|
|
|
2018-12-28 23:02:19 +00:00
|
|
|
return ps, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (m *UserResourceMapping) memberPerms() ([]Permission, error) {
|
|
|
|
ps := make([]Permission, 0, len(memberActions))
|
2018-11-20 18:56:58 +00:00
|
|
|
for _, a := range memberActions {
|
2018-12-28 23:02:19 +00:00
|
|
|
p, err := NewPermissionAtID(m.ResourceID, a, m.Resource)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
2018-11-20 18:56:58 +00:00
|
|
|
}
|
2018-12-28 23:02:19 +00:00
|
|
|
|
|
|
|
ps = append(ps, *p)
|
2019-01-09 15:35:21 +00:00
|
|
|
|
|
|
|
if m.Resource == OrgsResource {
|
|
|
|
ps = append(ps, OrgMemberPermissions(m.ResourceID)...)
|
|
|
|
}
|
2018-11-20 18:56:58 +00:00
|
|
|
}
|
|
|
|
|
2018-12-28 23:02:19 +00:00
|
|
|
return ps, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// ToPermissions converts a user resource mapping into a set of permissions.
|
|
|
|
func (m *UserResourceMapping) ToPermissions() ([]Permission, error) {
|
|
|
|
switch m.UserType {
|
|
|
|
case Owner:
|
|
|
|
return m.ownerPerms()
|
|
|
|
case Member:
|
|
|
|
return m.memberPerms()
|
|
|
|
default:
|
|
|
|
return nil, ErrInvalidUserType
|
|
|
|
}
|
2018-11-20 18:56:58 +00:00
|
|
|
}
|