Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement roles #46

Merged
merged 1 commit into from
Oct 27, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions pkg/onboarding/application/dto/input.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,8 +109,8 @@ type StaffProfileInput struct {
// TODO: the list of facilities to switch between is strictly those that the user is assigned to
DefaultFacilityID *string `json:"defaultFacilityID"`

// // there is nothing special about super-admin; just the set of roles they have
// Roles []domain.RoleType `json:"roles"` // TODO: roles are an enum (controlled list), known to both FE and BE
// there is nothing special about super-admin; just the set of roles they have
Roles []enums.RolesType `json:"roles"` // TODO: roles are an enum (controlled list), known to both FE and BE

Addresses []*AddressesInput `json:"addresses"`
}
Expand Down
82 changes: 82 additions & 0 deletions pkg/onboarding/application/enums/role_type.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package enums

import (
"fmt"
)

// RolesType is a list of all the role types.
type RolesType string

// contacts type constants
const (
RolesTypeCanRegisterStaff RolesType = "CAN_REGISTER_STAFF"
RolesTypeCanInviteStaff RolesType = "CAN_INVITE_STAFF"
RolesTypeCanSuspendStaff RolesType = "CAN_SUSPEND_STAFF"
RolesTypeCanActivateStaff RolesType = "CAN_ACTIVATE_STAFF"
RolesTypeCanDeleteStaff RolesType = "CAN_DELETE_STAFF"
RolesTypeCanInactivateStaff RolesType = "CAN_INACTIVATE_STAFF"

RolesTypeCanRegisterClient RolesType = "CAN_REGISTER_CLIENT"
RolesTypeCanInviteClient RolesType = "CAN_INVITE_CLIENT"
RolesTypeCanSuspendClient RolesType = "CAN_SUSPEND_CLIENT"
RolesTypeCanActivateClient RolesType = "CAN_ACTIVATE_CLIENT"
RolesTypeCanDeleteClient RolesType = "CAN_DELETE_CLIENT"
RolesTypeCanInactivateClient RolesType = "CAN_INACTIVATE_CLIENT"
)

// AllRoles is a set of a valid and known role types.
var AllRoles = []RolesType{
RolesTypeCanRegisterStaff,
RolesTypeCanInviteStaff,
RolesTypeCanSuspendStaff,
RolesTypeCanActivateStaff,
RolesTypeCanDeleteStaff,
RolesTypeCanInactivateStaff,

RolesTypeCanRegisterClient,
RolesTypeCanInviteClient,
RolesTypeCanSuspendClient,
RolesTypeCanActivateClient,
RolesTypeCanDeleteClient,
RolesTypeCanInactivateClient,
}

// IsValid returns true if a role is valid
func (m RolesType) IsValid() bool {
switch m {
case RolesTypeCanRegisterStaff,
RolesTypeCanInviteStaff,
RolesTypeCanSuspendStaff,
RolesTypeCanActivateStaff,
RolesTypeCanDeleteStaff,
RolesTypeCanInactivateStaff,

RolesTypeCanRegisterClient,
RolesTypeCanInviteClient,
RolesTypeCanSuspendClient,
RolesTypeCanActivateClient,
RolesTypeCanDeleteClient,
RolesTypeCanInactivateClient:
return true
}
return false
}

// String converts roles to string.
func (m RolesType) String() string {
return string(m)
}

// UnmarshalGQL converts the supplied value to a role type.
func (m *RolesType) UnmarshalGQL(v interface{}) error {
str, ok := v.(string)
if !ok {
return fmt.Errorf("enums must be strings")
}

*m = RolesType(str)
if !m.IsValid() {
return fmt.Errorf("%s is not a valid RolesType", str)
}
return nil
}
2 changes: 1 addition & 1 deletion pkg/onboarding/domain/models.go
Original file line number Diff line number Diff line change
Expand Up @@ -265,7 +265,7 @@ type StaffProfile struct {
DefaultFacilityID *string

// there is nothing special about super-admin; just the set of roles they have
Roles []string // TODO: roles are an enum (controlled list), known to both FE and BE
Roles []enums.RolesType // TODO: roles are an enum (controlled list), known to both FE and BE

Addresses []*Addresses
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,8 @@ func NewGormMock() *GormMock {
RegisterStaffUserFn: func(ctx context.Context, user *gorm.User, staff *gorm.StaffProfile) (*gorm.StaffUserProfile, error) {
ID := uuid.New().String()
testTime := time.Now()
roles := []string{enums.RolesTypeCanInviteClient.String()}
languages := []string{string(enumutils.LanguageEn)}
return &gorm.StaffUserProfile{
User: &gorm.User{
UserID: &ID,
Expand All @@ -239,6 +241,7 @@ func NewGormMock() *GormMock {
FailedLoginCount: "0",
TermsAccepted: true,
AcceptedTermsID: ID,
Languages: languages,
},
Staff: &gorm.StaffProfile{
StaffProfileID: &ID,
Expand All @@ -256,6 +259,7 @@ func NewGormMock() *GormMock {
Active: true,
},
},
Roles: roles,
},
}, nil
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -187,8 +187,8 @@ type StaffProfile struct {
DefaultFacilityID *string `gorm:"column:default_facility_id"` // TODO: required, FK to facility
Facility Facility `gorm:"foreignKey:default_facility_id;references:facility_id;constraint:OnUpdate:CASCADE,OnDelete:CASCADE;"`

// // there is nothing special about super-admin; just the set of roles they have
// Roles []string `gorm:"type:text[];column:roles"` // TODO: roles are an enum (controlled list), known to both FE and BE
// there is nothing special about super-admin; just the set of roles they have
Roles pq.StringArray `gorm:"type:text[];column:roles"` // TODO: roles are an enum (controlled list), known to both FE and BE

Addresses []*Addresses `gorm:"ForeignKey:StaffProfileID"`
}
Expand Down
11 changes: 9 additions & 2 deletions pkg/onboarding/infrastructure/database/postgres/mappers.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"strconv"

"github.com/savannahghi/enumutils"
"github.com/savannahghi/onboarding-service/pkg/onboarding/application/enums"
"github.com/savannahghi/onboarding-service/pkg/onboarding/domain"
"github.com/savannahghi/onboarding-service/pkg/onboarding/infrastructure/database/postgres/gorm"
)
Expand Down Expand Up @@ -115,14 +116,20 @@ func (d *OnboardingDb) mapRegisterStaffObjectToDomain(userStaffObject *gorm.Staf
addresses = append(addresses, address)
}

roles := []enums.RolesType{}
for _, r := range staffObject.Roles {
roles = append(roles, enums.RolesType(r))

}

staffProfile := &domain.StaffProfile{
ID: staffObject.StaffProfileID,
UserID: userObject.UserID,
StaffNumber: staffObject.StaffNumber,
// Facilities: staffObject.Facilities,
DefaultFacilityID: staffObject.DefaultFacilityID,
// Roles: staffObject.Roles,
Addresses: addresses,
Addresses: addresses,
Roles: roles,
}
return &domain.StaffUserProfile{
User: user,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,8 @@ func NewPostgresMock() *PostgresMock {
RegisterStaffUserFn: func(ctx context.Context, user *dto.UserInput, staff *dto.StaffProfileInput) (*domain.StaffUserProfile, error) {
ID := uuid.New().String()
testTime := time.Now()
roles := []enums.RolesType{enums.RolesTypeCanInviteClient}
languages := []enumutils.Language{enumutils.LanguageEn}
return &domain.StaffUserProfile{
User: &domain.User{
ID: &ID,
Expand All @@ -162,6 +164,7 @@ func NewPostgresMock() *PostgresMock {
FailedLoginCount: "0",
TermsAccepted: true,
AcceptedTermsID: ID,
Languages: languages,
},
Staff: &domain.StaffProfile{
ID: &ID,
Expand All @@ -179,6 +182,7 @@ func NewPostgresMock() *PostgresMock {
Active: true,
},
},
Roles: roles,
},
}, nil
},
Expand Down
10 changes: 10 additions & 0 deletions pkg/onboarding/infrastructure/database/postgres/pg_create.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,10 +114,20 @@ func (d *OnboardingDb) RegisterStaffUser(ctx context.Context, user *dto.UserInpu
}
}

roles := []string{}
for _, r := range staff.Roles {
if !r.IsValid() {
return nil, fmt.Errorf("role %s is not valid", r)
}

roles = append(roles, r.String())
}

staffObject := &gorm.StaffProfile{
StaffNumber: staff.StaffNumber,
DefaultFacilityID: staff.DefaultFacilityID,
Addresses: addresses,
Roles: roles,
}

userStaffProfile, err := d.create.RegisterStaffUser(ctx, userObject, staffObject)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,7 @@ func TestOnboardingDb_RegisterStaffUser(t *testing.T) {
testUserID := uuid.New().String()
testTime := time.Now()
testID := uuid.New().String()
rolesInput := []enums.RolesType{enums.RolesTypeCanInviteClient}

type args struct {
ctx context.Context
Expand Down Expand Up @@ -283,6 +284,7 @@ func TestOnboardingDb_RegisterStaffUser(t *testing.T) {
Active: true,
},
},
Roles: rolesInput,
}
staffNoFacilityIDInput := &dto.StaffProfileInput{
StaffNumber: "s123",
Expand Down Expand Up @@ -375,6 +377,7 @@ func TestOnboardingDb_RegisterStaffUser(t *testing.T) {
Active: true,
},
},
Roles: []string{enums.RolesTypeCanInviteClient.String()},
},
}, nil
}
Expand Down
16 changes: 16 additions & 0 deletions pkg/onboarding/presentation/graph/enums.graphql
Original file line number Diff line number Diff line change
@@ -1,3 +1,19 @@
enum RolesType {
CAN_REGISTER_STAFF
CAN_INVITE_STAFF
CAN_SUSPEND_STAFF
CAN_ACTIVATE_STAFF
CAN_DELETE_STAFF
CAN_INACTIVATE_STAFF

CAN_REGISTER_CLIENT
CAN_INVITE_CLIENT
CAN_SUSPEND_CLIENT
CAN_ACTIVATE_CLIENT
CAN_DELETE_CLIENT
CAN_INACTIVATE_CLIENT
}

enum ClientType {
PMTCT
OVC
Expand Down
Loading