Compare commits

...

5 Commits

Author SHA1 Message Date
GotPPay
9c1ccdcf68 added DELETE rule to authorization_policy 2018-05-04 16:57:19 +02:00
GotPPay
d820d47fcd implement rules checking for orgnz, addr and contact creation and update 2018-05-04 16:36:51 +02:00
GotPPay
ef783567b9 create structure for rules checking 2018-05-03 18:29:24 +02:00
Senad Uka
9da9f7eb78 Upstream sync 2018-05-03 07:57:08 +02:00
Senad Uka
50a6362b67 upstream sync 2018-05-03 07:55:09 +02:00
27 changed files with 838 additions and 182 deletions

View File

@@ -15,6 +15,8 @@ COPY ./dist/${BIN_NAME} /opt/app/${BIN_NAME}
ADD ./dist/docs/ /opt/app/docs/
ADD ./dist/static/ /opt/app/static/
ADD ./dist/config.toml /opt/app/config.toml
ADD ./dist/authorization_model.conf /opt/app/authorization_model.conf
ADD ./dist/authorization_policy.csv /opt/app/authorization_policy.csv
# Sets and executes the app.
WORKDIR /opt/app

View File

@@ -67,6 +67,8 @@ build: clean create-build-container
cp -R static/* ./dist/static/
cp -R docs/swagger/ ./dist/docs/
cp config.${DEPLOY_ENV}.toml ./dist/config.toml
cp authorization_model.conf ./dist/authorization_model.conf
cp authorization_policy.csv ./dist/authorization_policy.csv
#################################################
## Building, based on the current environment. ##

View File

@@ -35,37 +35,42 @@ func (s *organizationService) GetAllTypes() ([]viewmodel.OrganizationType, error
return s.mapEntity.Organization.ToOrganizationTypeModelSlice(result), nil
}
func (s *organizationService) GetByType(organizationTypeKey string) ([]viewmodel.Organization, error) {
result, err := s.svc.Organization.GetByType(organizationTypeKey)
func (s *organizationService) GetByType(organizationTypeKey string, user viewmodel.User) ([]viewmodel.Organization, error) {
userEntity := s.mapEntity.User.ToUserEntity(user)
result, err := s.svc.Organization.GetByType(organizationTypeKey, userEntity)
if err != nil {
return nil, err
}
return s.mapEntity.Organization.ToOrganizationModelSlice(result), nil
}
func (s *organizationService) GetByUUID(organizationUUID string) (viewmodel.Organization, error) {
result, err := s.svc.Organization.GetByUUID(organizationUUID)
func (s *organizationService) GetByUUID(organizationUUID string, user viewmodel.User) (viewmodel.Organization, error) {
userEntity := s.mapEntity.User.ToUserEntity(user)
result, err := s.svc.Organization.GetByUUID(organizationUUID, userEntity)
if err != nil {
return viewmodel.Organization{}, err
}
return s.mapEntity.Organization.ToOrganizationModel(result), nil
}
func (s *organizationService) GetByName(name string, searchType string) ([]viewmodel.Organization, error) {
result, err := s.svc.Organization.GetByName(name, searchType)
func (s *organizationService) GetByName(name string, searchType string, user viewmodel.User) ([]viewmodel.Organization, error) {
userEntity := s.mapEntity.User.ToUserEntity(user)
result, err := s.svc.Organization.GetByName(name, searchType, userEntity)
if err != nil {
return nil, err
}
return s.mapEntity.Organization.ToOrganizationModelSlice(result), nil
}
func (s *organizationService) SetParentOrganization(organizationUUID string, parentOrganizationUUID string) (viewmodel.Organization, error) {
child, err := s.svc.Organization.GetByUUID(organizationUUID)
func (s *organizationService) SetParentOrganization(organizationUUID string, parentOrganizationUUID string, user viewmodel.User) (viewmodel.Organization, error) {
userEntity := s.mapEntity.User.ToUserEntity(user)
child, err := s.svc.Organization.GetByUUID(organizationUUID, userEntity)
if err != nil {
return viewmodel.Organization{}, err
}
parent, err := s.svc.Organization.GetByUUID(parentOrganizationUUID)
parent, err := s.svc.Organization.GetByUUID(parentOrganizationUUID, userEntity)
if err != nil {
return viewmodel.Organization{}, err
}
@@ -74,10 +79,11 @@ func (s *organizationService) SetParentOrganization(organizationUUID string, par
return viewmodel.Organization{}, err
}
return s.GetByUUID(organizationUUID)
return s.GetByUUID(organizationUUID, user)
}
func (s *organizationService) InactivateOrganizationAddress(organizationUUID string, address viewmodel.OrganizationAddress) error {
func (s *organizationService) InactivateOrganizationAddress(organizationUUID string, address viewmodel.OrganizationAddress, userView viewmodel.User) error {
userEntity := s.mapEntity.User.ToUserEntity(userView)
entityAddress := s.mapEntity.Organization.ToOrganizationAddressEntity(address)
entityAddress.Organization = &entity.Organization{
UUID: organizationUUID,
@@ -89,14 +95,15 @@ func (s *organizationService) InactivateOrganizationAddress(organizationUUID str
}
entityAddress.UpdatedUser = user
if err := s.svc.Organization.InactivateOrganizationAddress(entityAddress); err != nil {
if err := s.svc.Organization.InactivateOrganizationAddress(entityAddress, userEntity); err != nil {
return err
} else {
return nil
}
}
func (s *organizationService) SetOrganizationAddress(organizationUUID string, address viewmodel.OrganizationAddress) (viewmodel.OrganizationAddress, error) {
func (s *organizationService) SetOrganizationAddress(organizationUUID string, address viewmodel.OrganizationAddress, userView viewmodel.User) (viewmodel.OrganizationAddress, error) {
userEntity := s.mapEntity.User.ToUserEntity(userView)
entityAddress := s.mapEntity.Organization.ToOrganizationAddressEntity(address)
entityAddress.Organization = &entity.Organization{
UUID: organizationUUID,
@@ -110,7 +117,7 @@ func (s *organizationService) SetOrganizationAddress(organizationUUID string, ad
entityAddress.CreatedUser = user
entityAddress.UpdatedUser = user
entityAddress, err = s.svc.Organization.SetOrganizationAddress(entityAddress)
entityAddress, err = s.svc.Organization.SetOrganizationAddress(entityAddress, userEntity)
if err != nil {
return viewmodel.OrganizationAddress{}, err
}
@@ -118,7 +125,8 @@ func (s *organizationService) SetOrganizationAddress(organizationUUID string, ad
return s.mapEntity.Organization.ToOrganizationAddressModel(entityAddress), nil
}
func (s *organizationService) InactivateOrganizationContact(organizationUUID string, contact viewmodel.OrganizationContact) error {
func (s *organizationService) InactivateOrganizationContact(organizationUUID string, contact viewmodel.OrganizationContact, userView viewmodel.User) error {
userEntity := s.mapEntity.User.ToUserEntity(userView)
entityContact := s.mapEntity.Organization.ToOrganizationContactEntity(contact)
entityContact.Organization = &entity.Organization{
UUID: organizationUUID,
@@ -130,14 +138,15 @@ func (s *organizationService) InactivateOrganizationContact(organizationUUID str
}
entityContact.UpdatedUser = user
if err := s.svc.Organization.InactivateOrganizationContact(entityContact); err != nil {
if err := s.svc.Organization.InactivateOrganizationContact(entityContact, userEntity); err != nil {
return err
} else {
return nil
}
}
func (s *organizationService) SetOrganizationContact(organizationUUID string, contact viewmodel.OrganizationContact) (viewmodel.OrganizationContact, error) {
func (s *organizationService) SetOrganizationContact(organizationUUID string, contact viewmodel.OrganizationContact, userView viewmodel.User) (viewmodel.OrganizationContact, error) {
userEntity := s.mapEntity.User.ToUserEntity(userView)
entityContact := s.mapEntity.Organization.ToOrganizationContactEntity(contact)
entityContact.Organization = &entity.Organization{
UUID: organizationUUID,
@@ -151,7 +160,7 @@ func (s *organizationService) SetOrganizationContact(organizationUUID string, co
entityContact.CreatedUser = user
entityContact.UpdatedUser = user
entityContact, err = s.svc.Organization.SetOrganizationContact(entityContact)
entityContact, err = s.svc.Organization.SetOrganizationContact(entityContact, userEntity)
if err != nil {
return viewmodel.OrganizationContact{}, err
}
@@ -221,10 +230,10 @@ func (s *organizationService) AddOrganization(organization viewmodel.Organizatio
}
}
enOrg, err = s.svc.Organization.AddOrganization(enOrg)
enOrg, err = s.svc.Organization.AddOrganization(enOrg, enUser)
if err != nil {
return viewmodel.Organization{}, nil
}
return s.GetByUUID(enOrg.UUID)
return s.GetByUUID(enOrg.UUID, user)
}

View File

@@ -71,11 +71,12 @@ func (s *userService) Login(email string, pass string) (retVal viewmodel.User, e
return s.mapEntity.User.ToUserModel(user), nil
}
func (s *userService) Create(user viewmodel.User) (retVal viewmodel.User, err error) {
func (s *userService) Create(user viewmodel.User, author viewmodel.User) (retVal viewmodel.User, err error) {
entity := s.mapEntity.User.ToUserEntity(user)
enAuthor := s.mapEntity.User.ToUserEntity(author)
for i, _ := range entity.Organizations {
entity.Organizations[i], err = s.svc.Organization.GetByUUID(entity.Organizations[i].UUID)
entity.Organizations[i], err = s.svc.Organization.GetByUUID(entity.Organizations[i].UUID, enAuthor)
if err != nil {
return retVal, err
}
@@ -89,13 +90,14 @@ func (s *userService) Create(user viewmodel.User) (retVal viewmodel.User, err er
return s.mapEntity.User.ToUserModel(entity), nil
}
func (s *userService) CreateBulk(users []viewmodel.User) (retVal []viewmodel.User, err error) {
func (s *userService) CreateBulk(users []viewmodel.User, author viewmodel.User) (retVal []viewmodel.User, err error) {
entities := s.mapEntity.User.ToUserEntitySlice(users)
enAuthor := s.mapEntity.User.ToUserEntity(author)
organizations := make([]entity.Organization, 0)
for i, _ := range entities {
if i == 0 {
for o, _ := range entities[i].Organizations {
org, err := s.svc.Organization.GetByUUID(entities[i].Organizations[o].UUID)
org, err := s.svc.Organization.GetByUUID(entities[i].Organizations[o].UUID, enAuthor)
if err != nil {
return nil, err
}

11
authorization_model.conf Normal file
View File

@@ -0,0 +1,11 @@
[request_definition]
r = role, objectsRole, orgType, objectsOrgType, orgRelation, objectsRelation, obj, act
[policy_definition]
p = role, objectsRole, orgType, objectsOrgType, orgRelation, objectsRelation, obj, act
[policy_effect]
e = some(where (p.eft == allow)) && !some(where (p.eft == deny))
[matchers]
m = keyMatch(r.role, p.role) && keyMatch(r.objectsRole, p.objectsRole) && keyMatch(r.orgType, p.orgType) && keyMatch(r.objectsOrgType, p.objectsOrgType) && keyMatch(r.objectsRelation, p.objectsRelation) && keyMatch(r.orgRelation, p.orgRelation) && keyMatch(r.obj, p.obj) && (r.act == p.act || p.act == "*")

115
authorization_policy.csv Normal file
View File

@@ -0,0 +1,115 @@
p, AD, *, *, *, *, *, *, *
p, *, *, *, *, *, *, /v1/authenticate/portal, POST
p, *, *, *, *, *, *, /v1/notification/ws, GET
p, *, *, *, *, *, *, /health/, GET
p, *, *, *, *, *, *, /v1/nemt/users/contacttype, GET
p, *, *, *, *, *, [self], /v1/nemt/users/*, GET
p, *, *, *, *, *, [self], /v1/nemt/users/portal/*, DELETE
p, *, *, *, *, *, [self], /v1/nemt/users/portal/*, POST
p, *, *, *, *, *, [self], /v1/nemt/users/portal/*, GET
p, *AD, *, *, *, *, *, /v1/nemt/users/, GET
p, BDCAD, SP, *, *, *, [other], /v1/nemt/users/*/, GET
p, BDCAD, SP, *, *, *, [other], /v1/nemt/users/portal/*, DELETE
p, BDCAD, SP, *, *, *, [other], /v1/nemt/users/portal/*, POST
p, BDCAD, SP, *, *, *, [other], /v1/nemt/users/portal/*, GET
p, BDCAD, SPT, *, *, *, [other], /v1/nemt/users/*/, GET
p, BDCAD, SPT, *, *, *, [other], /v1/nemt/users/portal/*, DELETE
p, BDCAD, SPT, *, *, *, [other], /v1/nemt/users/portal/*, POST
p, BDCAD, SPT, *, *, *, [other], /v1/nemt/users/portal/*, GET
p, BDCAD, US, *, *, *, [other], /v1/nemt/users/*/, GET
p, BDCAD, US, *, *, *, [other], /v1/nemt/users/portal/*, DELETE
p, BDCAD, US, *, *, *, [other], /v1/nemt/users/portal/*, POST
p, BDCAD, US, *, *, *, [other], /v1/nemt/users/portal/*, GET
p, BCBSIAD, SP, *, *, *, [other], /v1/nemt/users/*/, GET
p, BCBSIAD, SP, *, *, *, [other], /v1/nemt/users/portal/*, DELETE
p, BCBSIAD, SP, *, *, *, [other], /v1/nemt/users/portal/*, POST
p, BCBSIAD, SP, *, *, *, [other], /v1/nemt/users/portal/*, GET
p, BCBSIAD, US, *, *, *, [other], /v1/nemt/users/*/, GET
p, BCBSIAD, US, *, *, *, [other], /v1/nemt/users/portal/*, DELETE
p, BCBSIAD, US, *, *, *, [other], /v1/nemt/users/portal/*, POST
p, BCBSIAD, US, *, *, *, [other], /v1/nemt/users/portal/*, GET
p, BCBSIAD, SPT, *, *, *, [other], /v1/nemt/users/*/, GET
p, BCBSIAD, SPT, *, *, *, [other], /v1/nemt/users/portal/*, DELETE
p, BCBSIAD, SPT, *, *, *, [other], /v1/nemt/users/portal/*, POST
p, BCBSIAD, SPT, *, *, *, [other], /v1/nemt/users/portal/*, GET
p, PLANAD, SPT, *, *, [equal], [other], /v1/nemt/users/*/, GET
p, PLANAD, SPT, *, *, [equal], [other], /v1/nemt/users/portal/*, DELETE
p, PLANAD, SPT, *, *, [equal], [other], /v1/nemt/users/portal/*, POST
p, PLANAD, SPT, *, *, [equal], [other], /v1/nemt/users/portal/*, GET
p, PLANAD, US, *, *, [equal], [other], /v1/nemt/users/*/, GET
p, PLANAD, US, *, *, [equal], [other], /v1/nemt/users/portal/*, DELETE
p, PLANAD, US, *, *, [equal], [other], /v1/nemt/users/portal/*, POST
p, PLANAD, US, *, *, [equal], [other], /v1/nemt/users/portal/*, GET
p, PLANAD, SP, *, *, [equal], [other], /v1/nemt/users/*/, GET
p, PLANAD, SP, *, *, [equal], [other], /v1/nemt/users/portal/*, DELETE
p, PLANAD, SP, *, *, [equal], [other], /v1/nemt/users/portal/*, POST
p, PLANAD, SP, *, *, [equal], [other], /v1/nemt/users/portal/*, GET
p, SCHDAD, US, *, *, [parent], [other], /v1/nemt/users/*/, GET
p, SCHDAD, US, *, *, [parent], [other], /v1/nemt/users/portal/*, DELETE
p, SCHDAD, US, *, *, [parent], [other], /v1/nemt/users/portal/*, POST
p, SCHDAD, US, *, *, [parent], [other], /v1/nemt/users/portal/*, GET
p, SCHDAD, SP, *, *, [parent], [other], /v1/nemt/users/*/, GET
p, SCHDAD, SP, *, *, [parent], [other], /v1/nemt/users/portal/*, DELETE
p, SCHDAD, SP, *, *, [parent], [other], /v1/nemt/users/portal/*, POST
p, SCHDAD, SP, *, *, [parent], [other], /v1/nemt/users/portal/*, GET
p, SCHDAD, SPT, *, *, [parent], [other], /v1/nemt/users/*/, GET
p, SCHDAD, SPT, *, *, [parent], [other], /v1/nemt/users/portal/*, DELETE
p, SCHDAD, SPT, *, *, [parent], [other], /v1/nemt/users/portal/*, POST
p, SCHDAD, SPT, *, *, [parent], [other], /v1/nemt/users/portal/*, GET
p, SCHDAD, SP, *, *, [equal*], [other], /v1/nemt/users/*/, GET
p, SCHDAD, SP, *, *, [equal*], [other], /v1/nemt/users/portal/*, DELETE
p, SCHDAD, SP, *, *, [equal*], [other], /v1/nemt/users/portal/*, POST
p, SCHDAD, SP, *, *, [equal*], [other], /v1/nemt/users/portal/*, GET
p, SCHDAD, US, *, *, [equal*], [other], /v1/nemt/users/*/, GET
p, SCHDAD, US, *, *, [equal*], [other], /v1/nemt/users/portal/*, DELETE
p, SCHDAD, US, *, *, [equal*], [other], /v1/nemt/users/portal/*, POST
p, SCHDAD, US, *, *, [equal*], [other], /v1/nemt/users/portal/*, GET
p, SCHDAD, SPT, *, *, [equal*], [other], /v1/nemt/users/*/, GET
p, SCHDAD, SPT, *, *, [equal*], [other], /v1/nemt/users/portal/*, DELETE
p, SCHDAD, SPT, *, *, [equal*], [other], /v1/nemt/users/portal/*, POST
p, SCHDAD, SPT, *, *, [equal*], [other], /v1/nemt/users/portal/*, GET
p, SCHDAD, SCHDAD, *, *, [equal*], [other], /v1/nemt/users/*/, GET
p, SCHDAD, SCHDAD, *, *, [equal*], [other], /v1/nemt/users/portal/*, DELETE
p, SCHDAD, SCHDAD, *, *, [equal*], [other], /v1/nemt/users/portal/*, POST
p, SCHDAD, SCHDAD, *, *, [equal*], [other], /v1/nemt/users/portal/*, GET
p, SPT, *, programsupport, *, *, [other], /v1/nemt/users/, GET
p, SPT, *, programsupport, *, *, [other], /v1/nemt/users/*, GET
p, *, *, *, *, *, *, /v1/nemt/organization/name, GET
p, *, *, *, *, *, *, /v1/nemt/organization/type, GET
p, AD, *, *, *, *, *, /v1/nemt/organization/*, GET
p, AD, *, *, *, *, *, /v1/nemt/organization/*, POST
p, AD, *, *, *, *, *, /v1/nemt/organization/*, PUT
p, AD, *, *, *, *, *, /v1/nemt/organization/*, DELETE
p, SCHDAD, *, *, *, [equal*], *, /v1/nemt/organization/*, GET
p, SCHDAD, *, *, *, [equal*], *, /v1/nemt/organization/*, POST
p, SCHDAD, *, *, *, [equal*], *, /v1/nemt/organization/*, PUT
p, SCHDAD, *, *, *, [equal*], *, /v1/nemt/organization/*, DELETE
p, PLANAD, *, *, *, [equal*], *, /v1/nemt/organization/*, GET
p, PLANAD, *, *, *, [equal*], *, /v1/nemt/organization/*, POST
p, PLANAD, *, *, *, [equal*], *, /v1/nemt/organization/*, PUT
p, PLANAD, *, *, *, [equal*], *, /v1/nemt/organization/*, DELETE
p, BDCAD, *, *, *, *, *, /v1/nemt/organization/*, GET
p, BDCAD, *, *, *, *, *, /v1/nemt/organization/*, POST
p, BDCAD, *, *, *, *, *, /v1/nemt/organization/*, PUT
p, BDCAD, *, *, *, *, *, /v1/nemt/organization/*, DELETE
p, BCBSIAD, *, *, *, *, *, /v1/nemt/organization/*, GET
p, BCBSIAD, *, *, *, *, *, /v1/nemt/organization/*, POST
p, BCBSIAD, *, *, *, *, *, /v1/nemt/organization/*, PUT
p, BCBSIAD, *, *, *, *, *, /v1/nemt/organization/*, DELETE
p, SPT, *, programsupport, *, *, *, /v1/nemt/organization/*, GET
p, SP, *, provider, *, *, *, /v1/nemt/organization, GET
p, SP, *, plan, *, *, *, /v1/nemt/organization, GET
p, SPT, *, programsupport, *, *, *, /v1/nemt/organization, GET
p, SCHDAD, *, provider, *, *, *, /v1/nemt/organization, GET
p, BCBSIAD, *, bcbsi, *, *, *, /v1/nemt/organization, GET
p, BDCAD, *, techsupport, *, *, *, /v1/nemt/organization, GET
p, PLANAD, *, plan, *, *, *, /v1/nemt/organization, GET
p, AD, *, *, *, *, *, /v1/nemt/organization, GET
p, SP, *, provider, *, *, *, /v1/nemt/eligibility, POST
p, SP, *, plan, *, *, *, /v1/nemt/eligibility, POST
p, SPT, *, programsupport, *, *, *, /v1/nemt/eligibility, POST
p, SCHDAD, *, provider, *, *, *, /v1/nemt/eligibility, POST
p, BCBSIAD, *, bcbsi, *, *, *, /v1/nemt/eligibility, POST
p, BDCAD, *, techsupport, *, *, *, /v1/nemt/eligibility, POST
p, PLANAD, *, plan, *, *, *, /v1/nemt/eligibility, POST
p, AD, *, *, *, *, *, /v1/nemt/eligibility, POST
1 p AD * * * * * * *
2 p * * * * * * /v1/authenticate/portal POST
3 p * * * * * * /v1/notification/ws GET
4 p * * * * * * /health/ GET
5 p * * * * * * /v1/nemt/users/contacttype GET
6 p * * * * * [self] /v1/nemt/users/* GET
7 p * * * * * [self] /v1/nemt/users/portal/* DELETE
8 p * * * * * [self] /v1/nemt/users/portal/* POST
9 p * * * * * [self] /v1/nemt/users/portal/* GET
10 p *AD * * * * * /v1/nemt/users/ GET
11 p BDCAD SP * * * [other] /v1/nemt/users/*/ GET
12 p BDCAD SP * * * [other] /v1/nemt/users/portal/* DELETE
13 p BDCAD SP * * * [other] /v1/nemt/users/portal/* POST
14 p BDCAD SP * * * [other] /v1/nemt/users/portal/* GET
15 p BDCAD SPT * * * [other] /v1/nemt/users/*/ GET
16 p BDCAD SPT * * * [other] /v1/nemt/users/portal/* DELETE
17 p BDCAD SPT * * * [other] /v1/nemt/users/portal/* POST
18 p BDCAD SPT * * * [other] /v1/nemt/users/portal/* GET
19 p BDCAD US * * * [other] /v1/nemt/users/*/ GET
20 p BDCAD US * * * [other] /v1/nemt/users/portal/* DELETE
21 p BDCAD US * * * [other] /v1/nemt/users/portal/* POST
22 p BDCAD US * * * [other] /v1/nemt/users/portal/* GET
23 p BCBSIAD SP * * * [other] /v1/nemt/users/*/ GET
24 p BCBSIAD SP * * * [other] /v1/nemt/users/portal/* DELETE
25 p BCBSIAD SP * * * [other] /v1/nemt/users/portal/* POST
26 p BCBSIAD SP * * * [other] /v1/nemt/users/portal/* GET
27 p BCBSIAD US * * * [other] /v1/nemt/users/*/ GET
28 p BCBSIAD US * * * [other] /v1/nemt/users/portal/* DELETE
29 p BCBSIAD US * * * [other] /v1/nemt/users/portal/* POST
30 p BCBSIAD US * * * [other] /v1/nemt/users/portal/* GET
31 p BCBSIAD SPT * * * [other] /v1/nemt/users/*/ GET
32 p BCBSIAD SPT * * * [other] /v1/nemt/users/portal/* DELETE
33 p BCBSIAD SPT * * * [other] /v1/nemt/users/portal/* POST
34 p BCBSIAD SPT * * * [other] /v1/nemt/users/portal/* GET
35 p PLANAD SPT * * [equal] [other] /v1/nemt/users/*/ GET
36 p PLANAD SPT * * [equal] [other] /v1/nemt/users/portal/* DELETE
37 p PLANAD SPT * * [equal] [other] /v1/nemt/users/portal/* POST
38 p PLANAD SPT * * [equal] [other] /v1/nemt/users/portal/* GET
39 p PLANAD US * * [equal] [other] /v1/nemt/users/*/ GET
40 p PLANAD US * * [equal] [other] /v1/nemt/users/portal/* DELETE
41 p PLANAD US * * [equal] [other] /v1/nemt/users/portal/* POST
42 p PLANAD US * * [equal] [other] /v1/nemt/users/portal/* GET
43 p PLANAD SP * * [equal] [other] /v1/nemt/users/*/ GET
44 p PLANAD SP * * [equal] [other] /v1/nemt/users/portal/* DELETE
45 p PLANAD SP * * [equal] [other] /v1/nemt/users/portal/* POST
46 p PLANAD SP * * [equal] [other] /v1/nemt/users/portal/* GET
47 p SCHDAD US * * [parent] [other] /v1/nemt/users/*/ GET
48 p SCHDAD US * * [parent] [other] /v1/nemt/users/portal/* DELETE
49 p SCHDAD US * * [parent] [other] /v1/nemt/users/portal/* POST
50 p SCHDAD US * * [parent] [other] /v1/nemt/users/portal/* GET
51 p SCHDAD SP * * [parent] [other] /v1/nemt/users/*/ GET
52 p SCHDAD SP * * [parent] [other] /v1/nemt/users/portal/* DELETE
53 p SCHDAD SP * * [parent] [other] /v1/nemt/users/portal/* POST
54 p SCHDAD SP * * [parent] [other] /v1/nemt/users/portal/* GET
55 p SCHDAD SPT * * [parent] [other] /v1/nemt/users/*/ GET
56 p SCHDAD SPT * * [parent] [other] /v1/nemt/users/portal/* DELETE
57 p SCHDAD SPT * * [parent] [other] /v1/nemt/users/portal/* POST
58 p SCHDAD SPT * * [parent] [other] /v1/nemt/users/portal/* GET
59 p SCHDAD SP * * [equal*] [other] /v1/nemt/users/*/ GET
60 p SCHDAD SP * * [equal*] [other] /v1/nemt/users/portal/* DELETE
61 p SCHDAD SP * * [equal*] [other] /v1/nemt/users/portal/* POST
62 p SCHDAD SP * * [equal*] [other] /v1/nemt/users/portal/* GET
63 p SCHDAD US * * [equal*] [other] /v1/nemt/users/*/ GET
64 p SCHDAD US * * [equal*] [other] /v1/nemt/users/portal/* DELETE
65 p SCHDAD US * * [equal*] [other] /v1/nemt/users/portal/* POST
66 p SCHDAD US * * [equal*] [other] /v1/nemt/users/portal/* GET
67 p SCHDAD SPT * * [equal*] [other] /v1/nemt/users/*/ GET
68 p SCHDAD SPT * * [equal*] [other] /v1/nemt/users/portal/* DELETE
69 p SCHDAD SPT * * [equal*] [other] /v1/nemt/users/portal/* POST
70 p SCHDAD SPT * * [equal*] [other] /v1/nemt/users/portal/* GET
71 p SCHDAD SCHDAD * * [equal*] [other] /v1/nemt/users/*/ GET
72 p SCHDAD SCHDAD * * [equal*] [other] /v1/nemt/users/portal/* DELETE
73 p SCHDAD SCHDAD * * [equal*] [other] /v1/nemt/users/portal/* POST
74 p SCHDAD SCHDAD * * [equal*] [other] /v1/nemt/users/portal/* GET
75 p SPT * programsupport * * [other] /v1/nemt/users/ GET
76 p SPT * programsupport * * [other] /v1/nemt/users/* GET
77 p * * * * * * /v1/nemt/organization/name GET
78 p * * * * * * /v1/nemt/organization/type GET
79 p AD * * * * * /v1/nemt/organization/* GET
80 p AD * * * * * /v1/nemt/organization/* POST
81 p AD * * * * * /v1/nemt/organization/* PUT
82 p AD * * * * * /v1/nemt/organization/* DELETE
83 p SCHDAD * * * [equal*] * /v1/nemt/organization/* GET
84 p SCHDAD * * * [equal*] * /v1/nemt/organization/* POST
85 p SCHDAD * * * [equal*] * /v1/nemt/organization/* PUT
86 p SCHDAD * * * [equal*] * /v1/nemt/organization/* DELETE
87 p PLANAD * * * [equal*] * /v1/nemt/organization/* GET
88 p PLANAD * * * [equal*] * /v1/nemt/organization/* POST
89 p PLANAD * * * [equal*] * /v1/nemt/organization/* PUT
90 p PLANAD * * * [equal*] * /v1/nemt/organization/* DELETE
91 p BDCAD * * * * * /v1/nemt/organization/* GET
92 p BDCAD * * * * * /v1/nemt/organization/* POST
93 p BDCAD * * * * * /v1/nemt/organization/* PUT
94 p BDCAD * * * * * /v1/nemt/organization/* DELETE
95 p BCBSIAD * * * * * /v1/nemt/organization/* GET
96 p BCBSIAD * * * * * /v1/nemt/organization/* POST
97 p BCBSIAD * * * * * /v1/nemt/organization/* PUT
98 p BCBSIAD * * * * * /v1/nemt/organization/* DELETE
99 p SPT * programsupport * * * /v1/nemt/organization/* GET
100 p SP * provider * * * /v1/nemt/organization GET
101 p SP * plan * * * /v1/nemt/organization GET
102 p SPT * programsupport * * * /v1/nemt/organization GET
103 p SCHDAD * provider * * * /v1/nemt/organization GET
104 p BCBSIAD * bcbsi * * * /v1/nemt/organization GET
105 p BDCAD * techsupport * * * /v1/nemt/organization GET
106 p PLANAD * plan * * * /v1/nemt/organization GET
107 p AD * * * * * /v1/nemt/organization GET
108 p SP * provider * * * /v1/nemt/eligibility POST
109 p SP * plan * * * /v1/nemt/eligibility POST
110 p SPT * programsupport * * * /v1/nemt/eligibility POST
111 p SCHDAD * provider * * * /v1/nemt/eligibility POST
112 p BCBSIAD * bcbsi * * * /v1/nemt/eligibility POST
113 p BDCAD * techsupport * * * /v1/nemt/eligibility POST
114 p PLANAD * plan * * * /v1/nemt/eligibility POST
115 p AD * * * * * /v1/nemt/eligibility POST

View File

@@ -19,6 +19,8 @@ pipelines:
- cp -R static/* ./dist/static/
- cp -R docs/swagger/ ./dist/docs/
- cp config.prd.toml ./dist/config.toml
- cp authorization_model.conf ./dist/authorization_model.conf
- cp authorization_policy.csv ./dist/authorization_policy.csv
- docker build -f Dockerfile.run -t nemt-portal-api-run:prod --force-rm --build-arg BIN_NAME=nemt-portal-api --build-arg APP_NAME=nemt-portal-api .
- apt-get update -y && apt-get upgrade -y && apt-get dist-upgrade -y && apt-get -y autoremove && apt-get clean
- apt-get install python3-pip -y
@@ -46,6 +48,8 @@ pipelines:
- cp -R static/* ./dist/static/
- cp -R docs/swagger/ ./dist/docs/
- cp config.stg.toml ./dist/config.toml
- cp authorization_model.conf ./dist/authorization_model.conf
- cp authorization_policy.csv ./dist/authorization_policy.csv
- docker build -f Dockerfile.run -t nemt-portal-api-run:dev --force-rm --build-arg BIN_NAME=nemt-portal-api --build-arg APP_NAME=nemt-portal-api .
- apt-get update -y && apt-get upgrade -y && apt-get dist-upgrade -y && apt-get -y autoremove && apt-get clean
- apt-get install python3-pip -y

View File

@@ -20,6 +20,63 @@ func newOrganizationRepo(conn executor) *organizationRepo {
}
}
func (c *organizationRepo) getProfileQuery(user entity.User) (query string, where string, err error) {
if len(user.Profiles) > 0 {
for _, p := range user.Profiles {
switch p.Key {
case "AD", "BCBSIAD", "BDCAD", "PLANAD":
switch p.Organization.Type.Key {
case "techsupport", "bcbsi", "bcbsa":
return
case "plan":
query = ` INNER JOIN tab_provider e
ON e.provider_id = a.organization_reference_id
AND b.organization_type_key = 'plan'
LEFT JOIN tab_organization f
ON f.organization_id = a.organization_parent_id `
where = fmt.Sprintf(` AND (a.organization_uuid = '%s' OR f.organization_uuid = '%s') `, p.Organization.UUID, p.Organization.UUID)
case "provider":
query = ` INNER JOIN tab_provider e
ON e.provider_id = a.organization_reference_id
AND b.organization_type_key = 'provider'
LEFT JOIN tab_organization f
ON f.organization_id = a.organization_parent_id `
where = fmt.Sprintf(` AND (a.organization_uuid = '%s' OR f.organization_uuid = '%s') `, p.Organization.UUID, p.Organization.UUID)
return
}
case "SP", "SPT":
switch p.Organization.Type.Key {
case "techsupport", "bcbsi", "bcbsa":
return
case "plan":
query = ` INNER JOIN tab_provider e
ON e.provider_id = a.organization_reference_id
AND b.organization_type_key = 'plan'
LEFT JOIN tab_organization f
ON f.organization_id = a.organization_parent_id `
where = fmt.Sprintf(` AND (a.organization_uuid = '%s' OR f.organization_uuid = '%s') `, p.Organization.UUID, p.Organization.UUID)
case "provider":
query = ` INNER JOIN tab_provider e
ON e.provider_id = a.organization_reference_id
AND b.organization_type_key = 'provider'
LEFT JOIN tab_organization f
ON f.organization_id = a.organization_parent_id `
where = fmt.Sprintf(` AND (a.organization_uuid = '%s' OR f.organization_uuid = '%s') `, p.Organization.UUID, p.Organization.UUID)
return
}
}
}
if query == "" && where == "" {
return "", "", fmt.Errorf("Invalid Query")
} else {
return
}
} else {
return "", "", fmt.Errorf("User has no profile to search")
}
}
func (c *organizationRepo) getQuery() string {
const (
query = `SELECT
@@ -237,42 +294,73 @@ func (c *organizationRepo) GetAllTypes() ([]entity.OrganizationType, error) {
}
func (c *organizationRepo) GetTypeByKey(key string) (entity.OrganizationType, error) {
return c.parseTypeEntity(c.conn.QueryRow(c.getTypeQuery()+" WHERE organization_type_key=?", key))
return c.parseTypeEntity(c.conn.QueryRow(c.getTypeQuery()+" WHERE b.organization_type_key=?", key))
}
func (c *organizationRepo) GetByType(organizationTypeKey string) ([]entity.Organization, error) {
func (c *organizationRepo) GetByType(organizationTypeKey string, user entity.User) ([]entity.Organization, error) {
query, where, err := c.getProfileQuery(user)
if err != nil {
return nil, err
}
if organizationTypeKey == "" {
return c.parseSet(c.conn.Query(c.getQuery()))
return c.parseSet(c.conn.Query(c.getQuery() + query + " WHERE 1 = 1 " + where))
} else {
return c.parseSet(c.conn.Query(c.getQuery()+" WHERE b.organization_type_key = ? ", organizationTypeKey))
return c.parseSet(c.conn.Query(c.getQuery()+query+" WHERE b.organization_type_key = ? "+where, organizationTypeKey))
}
}
func (c *organizationRepo) GetByName(name string, searchType string) ([]entity.Organization, error) {
finalQuery := c.getQuery() + " WHERE a.organization_name LIKE ?"
func (c *organizationRepo) GetByName(name string, searchType string, user entity.User) ([]entity.Organization, error) {
query, where, err := c.getProfileQuery(user)
if err != nil {
return nil, err
}
finalQuery := c.getQuery() + query + " WHERE a.organization_name LIKE ? "
switch searchType {
case "parent":
finalQuery += " AND a.organization_parent_id > 0; "
finalQuery += " AND a.organization_parent_id > 0 "
case "child":
finalQuery += " AND a.organization_parent_id = 0; "
finalQuery += " AND a.organization_parent_id = 0 "
}
name = "%" + name + "%"
fmt.Println(finalQuery)
finalQuery += where
name = "%" + name + "%"
return c.parseSet(c.conn.Query(finalQuery, name))
}
func (c *organizationRepo) GetByUUID(organizationUUID string) (entity.Organization, error) {
return c.parseEntity(c.conn.QueryRow(c.getQuery()+" WHERE a.organization_uuid = ? ", organizationUUID))
func (c *organizationRepo) GetByUUID(organizationUUID string, user entity.User) (entity.Organization, error) {
query, where, err := c.getProfileQuery(user)
if err != nil {
return entity.Organization{}, err
}
query = c.getQuery() + query + " WHERE a.organization_uuid = ? " + where
return c.parseEntity(c.conn.QueryRow(query, organizationUUID))
}
func (c *organizationRepo) GetByID(organizationID int64) (entity.Organization, error) {
return c.parseEntity(c.conn.QueryRow(c.getQuery()+" WHERE a.organization_id = ? ", organizationID))
func (c *organizationRepo) GetByID(organizationID int64, user entity.User) (entity.Organization, error) {
query, where, err := c.getProfileQuery(user)
if err != nil {
return entity.Organization{}, err
}
query = c.getQuery() + query + " WHERE a.organization_id = ? " + where
return c.parseEntity(c.conn.QueryRow(query, organizationID))
}
func (c *organizationRepo) GetChildsByID(organizationID int64) ([]entity.Organization, error) {
return c.parseSet(c.conn.Query(c.getQuery()+" WHERE a.organization_parent_id = ? ", organizationID))
func (c *organizationRepo) GetChildsByID(organizationID int64, user entity.User) ([]entity.Organization, error) {
query, where, err := c.getProfileQuery(user)
if err != nil {
return nil, err
}
query = c.getQuery() + query + " WHERE a.organization_parent_id = ? " + where
return c.parseSet(c.conn.Query(query, organizationID))
}
func (c *organizationRepo) GetContactsByOrganizationUUID(organizationUUID string) ([]entity.OrganizationContact, error) {
@@ -312,7 +400,7 @@ func (c *organizationRepo) SetParentOrganization(organizationID int64, parentOrg
}
}
func (c *organizationRepo) InactivateOrganizationAddress(address entity.OrganizationAddress) error {
func (c *organizationRepo) InactivateOrganizationAddress(address entity.OrganizationAddress, user entity.User) error {
const (
query = "UPDATE tab_organization_address SET active = 0, updated = CURRENT_TIMESTAMP, updated_user_id = ? WHERE organization_id = ? and organization_address_uuid = ?"
)
@@ -321,7 +409,7 @@ func (c *organizationRepo) InactivateOrganizationAddress(address entity.Organiza
return errors.NewNotFoundError()
}
organization, err := c.GetByUUID(address.Organization.UUID)
organization, err := c.GetByUUID(address.Organization.UUID, user)
if err != nil {
return err
}
@@ -334,7 +422,7 @@ func (c *organizationRepo) InactivateOrganizationAddress(address entity.Organiza
}
}
func (c *organizationRepo) SetOrganizationAddress(address entity.OrganizationAddress) (entity.OrganizationAddress, error) {
func (c *organizationRepo) SetOrganizationAddress(address entity.OrganizationAddress, user entity.User) (entity.OrganizationAddress, error) {
const (
query = "INSERT INTO tab_organization_address(organization_address_uuid, organization_id, internal_id, `name`, address, `desc`, lat, `long`, created_user_id, updated_user_id) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?);"
)
@@ -343,7 +431,7 @@ func (c *organizationRepo) SetOrganizationAddress(address entity.OrganizationAdd
return entity.OrganizationAddress{}, errors.NewNotFoundError()
}
organization, err := c.GetByUUID(address.Organization.UUID)
organization, err := c.GetByUUID(address.Organization.UUID, user)
if err != nil {
return entity.OrganizationAddress{}, err
}
@@ -362,7 +450,7 @@ func (c *organizationRepo) SetOrganizationAddress(address entity.OrganizationAdd
return address, nil
}
func (c *organizationRepo) InactivateOrganizationContact(contact entity.OrganizationContact) error {
func (c *organizationRepo) InactivateOrganizationContact(contact entity.OrganizationContact, user entity.User) error {
const (
query = "UPDATE tab_organization_contact SET active = 0, updated = CURRENT_TIMESTAMP, updated_user_id = ? WHERE organization_id = ? and organization_contact_uuid = ?"
)
@@ -371,7 +459,7 @@ func (c *organizationRepo) InactivateOrganizationContact(contact entity.Organiza
return errors.NewNotFoundError()
}
organization, err := c.GetByUUID(contact.Organization.UUID)
organization, err := c.GetByUUID(contact.Organization.UUID, user)
if err != nil {
return err
}
@@ -384,7 +472,7 @@ func (c *organizationRepo) InactivateOrganizationContact(contact entity.Organiza
}
}
func (c *organizationRepo) SetOrganizationContact(contact entity.OrganizationContact) (entity.OrganizationContact, error) {
func (c *organizationRepo) SetOrganizationContact(contact entity.OrganizationContact, user entity.User) (entity.OrganizationContact, error) {
const (
selectQuery = "SELECT a.contact_type_id, a.name, a.key FROM tab_contact_type a WHERE a.key = ?"
query = "INSERT INTO tab_organization_contact(organization_contact_uuid, organization_id, contact_type_id, contact, contact_name, contact_desc, created_user_id, updated_user_id) VALUES(?, ?, ?, ?, ?, ?, ?, ?);"
@@ -394,7 +482,7 @@ func (c *organizationRepo) SetOrganizationContact(contact entity.OrganizationCon
return entity.OrganizationContact{}, errors.NewNotFoundError()
}
organization, err := c.GetByUUID(contact.Organization.UUID)
organization, err := c.GetByUUID(contact.Organization.UUID, user)
if err != nil {
return entity.OrganizationContact{}, err
}
@@ -419,7 +507,7 @@ func (c *organizationRepo) SetOrganizationContact(contact entity.OrganizationCon
return contact, nil
}
func (c *organizationRepo) AddOrganization(organization entity.Organization) (entity.Organization, error) {
func (c *organizationRepo) AddOrganization(organization entity.Organization, user entity.User) (entity.Organization, error) {
const (
queryOrgType = "SELECT a.organization_type_id FROM tab_organization_type a WHERE a.organization_type_key = ?;"
queryParentOrg = "SELECT a.organization_id FROM tab_organization a WHERE a.organization_uuid = ?;"
@@ -457,7 +545,7 @@ func (c *organizationRepo) AddOrganization(organization entity.Organization) (en
if len(organization.Addresses) > 0 {
for i, a := range organization.Addresses {
a.Organization = &organization
address, err := c.SetOrganizationAddress(a)
address, err := c.SetOrganizationAddress(a, user)
if err != nil {
fmt.Println("Error to save addresses")
return entity.Organization{}, err
@@ -469,7 +557,7 @@ func (c *organizationRepo) AddOrganization(organization entity.Organization) (en
if len(organization.Contacts) > 0 {
for i, ct := range organization.Contacts {
ct.Organization = &organization
contact, err := c.SetOrganizationContact(ct)
contact, err := c.SetOrganizationContact(ct, user)
if err != nil {
fmt.Println("Error to save contacts")
return entity.Organization{}, err

View File

@@ -68,23 +68,23 @@ type NotificationRepo interface {
// ProviderRepo defines the data set for Rides
type OrganizationRepo interface {
GetAllTypes() ([]entity.OrganizationType, error)
GetByType(organizationTypeKey string) ([]entity.Organization, error)
GetByUUID(organizationUUID string) (entity.Organization, error)
GetByType(organizationTypeKey string, user entity.User) ([]entity.Organization, error)
GetByUUID(organizationUUID string, user entity.User) (entity.Organization, error)
GetContactsByOrganizationUUID(organizationUUID string) ([]entity.OrganizationContact, error)
GetContactsByOrganizationID(organizationID int64) ([]entity.OrganizationContact, error)
GetContactsByUUID(contactUUID string) (entity.OrganizationContact, error)
GetAddressByOrganizationUUID(organizationUUID string) ([]entity.OrganizationAddress, error)
GetAddressByOrganizationID(organizationID int64) ([]entity.OrganizationAddress, error)
GetAddressByUUID(contactUUID string) (entity.OrganizationAddress, error)
GetByID(organizationID int64) (entity.Organization, error)
GetChildsByID(organizationID int64) ([]entity.Organization, error)
GetByName(name string, searchType string) ([]entity.Organization, error)
GetByID(organizationID int64, user entity.User) (entity.Organization, error)
GetChildsByID(organizationID int64, user entity.User) ([]entity.Organization, error)
GetByName(name string, searchType string, user entity.User) ([]entity.Organization, error)
SetParentOrganization(organizationID int64, parentOrganizationID int64) error
InactivateOrganizationAddress(address entity.OrganizationAddress) error
SetOrganizationAddress(address entity.OrganizationAddress) (entity.OrganizationAddress, error)
InactivateOrganizationContact(contact entity.OrganizationContact) error
SetOrganizationContact(contact entity.OrganizationContact) (entity.OrganizationContact, error)
AddOrganization(organization entity.Organization) (entity.Organization, error)
InactivateOrganizationAddress(address entity.OrganizationAddress, user entity.User) error
SetOrganizationAddress(address entity.OrganizationAddress, user entity.User) (entity.OrganizationAddress, error)
InactivateOrganizationContact(contact entity.OrganizationContact, user entity.User) error
SetOrganizationContact(contact entity.OrganizationContact, user entity.User) (entity.OrganizationContact, error)
AddOrganization(organization entity.Organization, user entity.User) (entity.Organization, error)
GetTypeByKey(key string) (entity.OrganizationType, error)
}

View File

@@ -20,16 +20,16 @@ func (s *organizationService) GetAllTypes() ([]entity.OrganizationType, error) {
return s.svc.db.Organization().GetAllTypes()
}
func (s *organizationService) GetByType(organizationTypeKey string) ([]entity.Organization, error) {
return s.svc.db.Organization().GetByType(organizationTypeKey)
func (s *organizationService) GetByType(organizationTypeKey string, user entity.User) ([]entity.Organization, error) {
return s.svc.db.Organization().GetByType(organizationTypeKey, user)
}
func (s *organizationService) GetByName(name string, searchType string) ([]entity.Organization, error) {
return s.svc.db.Organization().GetByName(name, searchType)
func (s *organizationService) GetByName(name string, searchType string, user entity.User) ([]entity.Organization, error) {
return s.svc.db.Organization().GetByName(name, searchType, user)
}
func (s *organizationService) GetByUUID(organizationUUID string) (entity.Organization, error) {
organization, err := s.svc.db.Organization().GetByUUID(organizationUUID)
func (s *organizationService) GetByUUID(organizationUUID string, user entity.User) (entity.Organization, error) {
organization, err := s.svc.db.Organization().GetByUUID(organizationUUID, user)
if err != nil {
return organization, err
}
@@ -44,13 +44,13 @@ func (s *organizationService) GetByUUID(organizationUUID string) (entity.Organiz
return organization, err
}
organization.ChildOrgs, err = s.svc.db.Organization().GetChildsByID(organization.ID)
organization.ChildOrgs, err = s.svc.db.Organization().GetChildsByID(organization.ID, user)
if err != nil {
return organization, err
}
if organization.ParentID > 0 {
parent, err := s.svc.db.Organization().GetByID(organization.ParentID)
parent, err := s.svc.db.Organization().GetByID(organization.ParentID, user)
if err != nil {
return organization, err
}
@@ -88,24 +88,24 @@ func (s *organizationService) GetAddressByUUID(contactUUID string) (entity.Organ
return s.svc.db.Organization().GetAddressByUUID(contactUUID)
}
func (s *organizationService) InactivateOrganizationAddress(address entity.OrganizationAddress) error {
return s.svc.db.Organization().InactivateOrganizationAddress(address)
func (s *organizationService) InactivateOrganizationAddress(address entity.OrganizationAddress, user entity.User) error {
return s.svc.db.Organization().InactivateOrganizationAddress(address, user)
}
func (s *organizationService) SetOrganizationAddress(address entity.OrganizationAddress) (entity.OrganizationAddress, error) {
return s.svc.db.Organization().SetOrganizationAddress(address)
func (s *organizationService) SetOrganizationAddress(address entity.OrganizationAddress, user entity.User) (entity.OrganizationAddress, error) {
return s.svc.db.Organization().SetOrganizationAddress(address, user)
}
func (s *organizationService) InactivateOrganizationContact(contact entity.OrganizationContact) error {
return s.svc.db.Organization().InactivateOrganizationContact(contact)
func (s *organizationService) InactivateOrganizationContact(contact entity.OrganizationContact, user entity.User) error {
return s.svc.db.Organization().InactivateOrganizationContact(contact, user)
}
func (s *organizationService) SetOrganizationContact(contact entity.OrganizationContact) (entity.OrganizationContact, error) {
return s.svc.db.Organization().SetOrganizationContact(contact)
func (s *organizationService) SetOrganizationContact(contact entity.OrganizationContact, user entity.User) (entity.OrganizationContact, error) {
return s.svc.db.Organization().SetOrganizationContact(contact, user)
}
func (s *organizationService) AddOrganization(organization entity.Organization) (entity.Organization, error) {
return s.svc.db.Organization().AddOrganization(organization)
func (s *organizationService) AddOrganization(organization entity.Organization, user entity.User) (entity.Organization, error) {
return s.svc.db.Organization().AddOrganization(organization, user)
}
func (s *organizationService) GetTypeByKey(key string) (entity.OrganizationType, error) {

View File

@@ -16,17 +16,8 @@
},
"portMappings": [
{
"containerPort": 5100
}
],
"environment": [
{
"name": "SERVICE_5100_NAME",
"value": "portal-api"
},
{
"name": "SERVICE_5100_TAGS",
"value": "api"
"containerPort": 5100,
"hostPort": 5100
}
]
}

View File

@@ -1,7 +1,7 @@
{
"containerDefinitions": [
{
"name": "portal-api-dev",
"name": "portal-api",
"image": "105690980714.dkr.ecr.us-east-2.amazonaws.com/nemt-portal-api:dev",
"cpu": 128,
"memory": 128,
@@ -16,17 +16,8 @@
},
"portMappings": [
{
"containerPort": 5100
}
],
"environment": [
{
"name": "SERVICE_5100_NAME",
"value": "portal-api"
},
{
"name": "SERVICE_5100_TAGS",
"value": "api"
"containerPort": 5100,
"hostPort": 5100
}
]
}

View File

@@ -42,3 +42,7 @@ import:
- package: github.com/ttacon/builder
- package: github.com/casbin/casbin
version: ~1.5.0
- package: github.com/Knetic/govaluate
version: 9aa49832a739dcd78a5542ff189fb82c3e423116
- package: github.com/pkg/errors
version: ^0.8.0

View File

@@ -0,0 +1,15 @@
package authorization
import (
"bitbucket.org/nemt/nemt-portal-api/application/viewmodel"
)
func CanCreateAddress(user viewmodel.User, organization viewmodel.Organization) bool {
//rules are the same for address creation and for organization creation
return CanCreateOrganization(user, organization)
}
func CanUpdateAddress(user viewmodel.User, organization viewmodel.Organization) bool {
return CanCreateAddress(user, organization)
}

View File

@@ -0,0 +1 @@
package authorization

View File

@@ -0,0 +1,15 @@
package authorization
import (
"bitbucket.org/nemt/nemt-portal-api/application/viewmodel"
)
func CanCreateContact(user viewmodel.User, organization viewmodel.Organization) bool {
//rules are the same for contact creation and for organization creation
return CanCreateOrganization(user, organization)
}
func CanUpdateContact(user viewmodel.User, organization viewmodel.Organization) bool {
return CanCreateAddress(user, organization)
}

View File

@@ -0,0 +1,68 @@
package authorization
import (
"fmt"
"bitbucket.org/nemt/nemt-portal-api/application/viewmodel"
)
func isAChildOrganization(potentialParent viewmodel.Organization, potentialChild viewmodel.Organization) bool {
for _, org := range potentialParent.ChildOrgs {
if potentialChild.UUID == org.UUID {
return true
}
}
return false
}
func isSameOrganization(organizationA viewmodel.Organization, organizationB viewmodel.Organization) bool {
return organizationA.UUID == organizationB.UUID
}
func grabOrgFromUser(user viewmodel.User) (viewmodel.Organization, error) {
if len(user.Organizations) < 1 {
return viewmodel.Organization{}, fmt.Errorf("User has no organizations %v", user)
}
return user.Organizations[0], nil
}
func CanCreateOrganization(user viewmodel.User, organization viewmodel.Organization ) bool {
userRole, err := grabProfileFromUser(user)
if err != nil {
return false
}
/*
Admin BCBSI
Admin Technical Support
Super Admin Technical Support
Manage all Organizations*/
if userRole.Key == bcbsiAdmin || userRole.Key == brighterDevAdmin || userRole.Key == superAdmin{
return true
}
userOrg, err := grabOrgFromUser(user)
if err != nil{
return false
}
/*
Admin Provider
Admin Plan
Manage the authenticated Authorized User's Organization and child Organizations */
if userRole.Key == providerAdmin || userRole.Key == planAdmin{
if isSameOrganization(userOrg, organization) || isAChildOrganization(userOrg, organization) {
return true
}
return false
}
return false
}
func CanUpdateOrganization(user viewmodel.User, organization viewmodel.Organization) bool{
return CanCreateOrganization(user, organization)
}

View File

@@ -0,0 +1,62 @@
package authorization
import (
"fmt"
"bitbucket.org/nemt/nemt-portal-api/application/viewmodel"
)
const (
superAdmin = "AD"
scheduler = "SP"
support = "SPT"
member = "US"
brighterDevAdmin = "BDCAD"
bcbsiAdmin = "BCBSIAD"
planAdmin = "PLANAD"
providerAdmin = "SCHDAD"
)
func grabProfileFromUser(user viewmodel.User) (viewmodel.Profile, error) {
if len(user.Profiles) < 1 {
return viewmodel.Profile{}, fmt.Errorf("User has no profiles %v", user)
}
return user.Profiles[0], nil
}
func morePrivileged(who viewmodel.Profile, towardsWhom viewmodel.Profile) bool {
order := []string{superAdmin, brighterDevAdmin, bcbsiAdmin, planAdmin, providerAdmin, support, scheduler, member}
for _, value := range order {
if value == who.Key {
return true
}
if value == towardsWhom.Key {
return false
}
}
// should hapen only in case profile key is empty
// and that's something fishy so let's deny!
return false
}
func equallyOrMorePrivileged(who viewmodel.Profile, towardsWhom viewmodel.Profile) bool {
if who.Key == towardsWhom.Key {
return true
}
return morePrivileged(who, towardsWhom)
}
func lessPrivilegedThanAdmin(who viewmodel.Profile) bool {
switch who.Key {
case member:
return true
case scheduler:
return true
case support:
return true
}
return false
}

View File

@@ -0,0 +1,86 @@
package authorization
import "bitbucket.org/nemt/nemt-portal-api/application/viewmodel"
/*
CanCreateUser returns true if currentUser is allowed to create updatingUser according to
authorization rules
*/
func CanCreateUser(currentUser viewmodel.User, updatingUser viewmodel.User) bool {
if len(currentUser.Profiles) < 1 {
return false
}
if len(updatingUser.Profiles) < 1 {
return false
}
currentUserOrganization, err := grabOrgFromUser(currentUser)
if err != nil {
return false
}
updatingUserOrganization, err := grabOrgFromUser(updatingUser)
if err != nil {
return false
}
currentUserRole, err := grabProfileFromUser(currentUser)
if err != nil {
return false
}
updatingUserRole, err := grabProfileFromUser(updatingUser)
if err != nil {
return false
}
/*
Admin Provider
Manage all Authorized Users of the provider Organization or child organization
The (Provider) Admin can manage Authorized Users of their Parent/ Top-level Org , but not Admins
*/
currentUserHigherOrEqualOrg := isSameOrganization(currentUserOrganization, updatingUserOrganization) || isAChildOrganization(currentUserOrganization, updatingUserOrganization)
currentUserLowerOrg := isAChildOrganization(updatingUserOrganization, currentUserOrganization)
if currentUserRole.Key == providerAdmin && currentUserHigherOrEqualOrg && equallyOrMorePrivileged(currentUserRole, updatingUserRole) {
return true
}
if currentUserRole.Key == providerAdmin && currentUserLowerOrg && lessPrivilegedThanAdmin(updatingUserRole) {
return true
}
/* Admin BCBSI
Manage all Authorized Users except Admins
return false
*/
if currentUserRole.Key == bcbsiAdmin && lessPrivilegedThanAdmin(updatingUserRole) {
return true
}
/* Admin Technical Support Manage all Authorized Users except Admins */
if currentUserRole.Key == brighterDevAdmin && lessPrivilegedThanAdmin(updatingUserRole) {
return true
}
/* Admin Plan Manage all Authorized Users of a single participating Plan except Admins */
if currentUserRole.Key == planAdmin && lessPrivilegedThanAdmin(updatingUserRole) && isSameOrganization(currentUserOrganization, updatingUserOrganization) {
return true
}
/* Super Admin Technical Support
Manage all Members, INCLUDING Admins */
if currentUserRole.Key == superAdmin {
return true
}
return false
}

View File

@@ -10,6 +10,7 @@ import (
"bitbucket.org/nemt/nemt-portal-api/infra/cache"
"bitbucket.org/nemt/nemt-portal-api/infra/config"
"bitbucket.org/nemt/nemt-portal-api/server/router/routeutils"
"bitbucket.org/nemt/nemt-portal-api/server/authorization"
"github.com/labstack/echo"
)
@@ -64,6 +65,11 @@ func (c *controller) handleAddOrganization(ctx echo.Context) error {
if err != nil {
return routeutils.HandleAPIError(ctx, err)
}
if !authorization.CanCreateOrganization(authUser, org) {
return routeutils.ResponseAPIAuthorizationError(ctx)
}
org.Author.ID = authUser.ID
org.LastEditor.ID = authUser.ID
@@ -78,7 +84,12 @@ func (c *controller) handleAddOrganization(ctx echo.Context) error {
func (c *controller) handle(ctx echo.Context) error {
orgType, _ := routeutils.GetAndValidateStringQueryParam(ctx, "type", "Type is mandatory")
resp, err := c.svc.Organization.GetByType(orgType)
authUser, err := auth.GetUserDetail(ctx, c.cfg)
if err != nil {
return routeutils.HandleAPIError(ctx, err)
}
resp, err := c.svc.Organization.GetByType(orgType, authUser)
if err != nil {
return routeutils.HandleAPIError(ctx, err)
}
@@ -92,7 +103,12 @@ func (c *controller) handleDetail(ctx echo.Context) error {
return routeutils.HandleAPIError(ctx, err)
}
resp, err := c.svc.Organization.GetByUUID(orgUUID)
authUser, err := auth.GetUserDetail(ctx, c.cfg)
if err != nil {
return routeutils.HandleAPIError(ctx, err)
}
resp, err := c.svc.Organization.GetByUUID(orgUUID, authUser)
if err != nil {
return routeutils.HandleAPIError(ctx, err)
}
@@ -112,7 +128,21 @@ func (c *controller) handleParent(ctx echo.Context) error {
return routeutils.HandleAPIError(ctx, err)
}
resp, err := c.svc.Organization.SetParentOrganization(orgUUID, parent.UUID)
authUser, err := auth.GetUserDetail(ctx, c.cfg)
if err != nil {
return routeutils.HandleAPIError(ctx, err)
}
organization, err := c.svc.Organization.GetByUUID(orgUUID, authUser)
if err != nil {
return routeutils.HandleAPIError(ctx, err)
}
if !authorization.CanUpdateOrganization(authUser, organization){
return routeutils.ResponseAPIAuthorizationError(ctx)
}
resp, err := c.svc.Organization.SetParentOrganization(orgUUID, parent.UUID, authUser)
if err != nil {
return routeutils.HandleAPIError(ctx, err)
}
@@ -132,12 +162,26 @@ func (c *controller) handleChild(ctx echo.Context) error {
return routeutils.HandleAPIError(ctx, err)
}
_, err = c.svc.Organization.SetParentOrganization(child.UUID, orgUUID)
authUser, err := auth.GetUserDetail(ctx, c.cfg)
if err != nil {
return routeutils.HandleAPIError(ctx, err)
}
resp, err := c.svc.Organization.GetByUUID(orgUUID)
organization, err := c.svc.Organization.GetByUUID(orgUUID, authUser)
if err != nil {
return routeutils.HandleAPIError(ctx, err)
}
if !authorization.CanUpdateOrganization(authUser, organization){
return routeutils.ResponseAPIAuthorizationError(ctx)
}
_, err = c.svc.Organization.SetParentOrganization(child.UUID, orgUUID, authUser)
if err != nil {
return routeutils.HandleAPIError(ctx, err)
}
resp, err := c.svc.Organization.GetByUUID(orgUUID, authUser)
if err != nil {
return routeutils.HandleAPIError(ctx, err)
}
@@ -151,11 +195,16 @@ func (c *controller) handleNameSearch(ctx echo.Context) error {
return routeutils.HandleAPIError(ctx, err)
}
authUser, err := auth.GetUserDetail(ctx, c.cfg)
if err != nil {
return routeutils.HandleAPIError(ctx, err)
}
searchType := ""
searchType, _ = routeutils.GetAndValidateStringQueryParam(ctx, "type", "Type is mandatory")
cache := cache.Instance(c.cfg)
cacheKey := ctx.Request().Method + ctx.Request().URL.RawPath + ctx.Request().URL.RawQuery
cacheKey := ctx.Request().Method + ctx.Request().URL.RawPath + ctx.Request().URL.RawQuery + authUser.ID
resp := []viewmodel.Organization{}
err = cache.GetStruct(cacheKey, &resp)
@@ -163,7 +212,7 @@ func (c *controller) handleNameSearch(ctx echo.Context) error {
if err != domain.ErrCacheMiss {
ctx.Logger().Errorf(domain.LogProblemGettingFromCache, err)
}
resp, err = c.svc.Organization.GetByName(name, searchType)
resp, err = c.svc.Organization.GetByName(name, searchType, authUser)
if err != nil {
return routeutils.HandleAPIError(ctx, err)
}
@@ -180,24 +229,24 @@ func (c *controller) handleRemoveAddress(ctx echo.Context) error {
return routeutils.HandleAPIError(ctx, err)
}
authUser, err := auth.GetUserDetail(ctx, c.cfg)
if err != nil {
return routeutils.HandleAPIError(ctx, err)
}
orgUUID, err := routeutils.GetAndValidateStringParam(ctx, "org_uuid", "Org ID is mandatory")
if err != nil {
return routeutils.HandleAPIError(ctx, err)
}
uInt, err := auth.GetTokenDetail(ctx, c.cfg)
if err != nil {
return routeutils.HandleAPIError(ctx, err)
}
createdUser := uInt.(map[string]interface{})
address.UpdatedUser.ID = createdUser["useruuid"].(string)
address.UpdatedUser.ID = authUser.ID
err = c.svc.Organization.InactivateOrganizationAddress(orgUUID, address)
err = c.svc.Organization.InactivateOrganizationAddress(orgUUID, address, authUser)
if err != nil {
return routeutils.HandleAPIError(ctx, err)
}
resp, err := c.svc.Organization.GetByUUID(orgUUID)
resp, err := c.svc.Organization.GetByUUID(orgUUID, authUser)
if err != nil {
return routeutils.HandleAPIError(ctx, err)
}
@@ -217,20 +266,31 @@ func (c *controller) handleAddAddress(ctx echo.Context) error {
return routeutils.HandleAPIError(ctx, err)
}
uInt, err := auth.GetTokenDetail(ctx, c.cfg)
if err != nil {
return routeutils.HandleAPIError(ctx, err)
}
createdUser := uInt.(map[string]interface{})
address.CreatedUser.ID = createdUser["useruuid"].(string)
address.UpdatedUser.ID = address.CreatedUser.ID
_, err = c.svc.Organization.SetOrganizationAddress(orgUUID, address)
authUser, err := auth.GetUserDetail(ctx, c.cfg)
if err != nil {
return routeutils.HandleAPIError(ctx, err)
}
resp, err := c.svc.Organization.GetByUUID(orgUUID)
organization, err := c.svc.Organization.GetByUUID(orgUUID, authUser)
if err != nil {
return routeutils.HandleAPIError(ctx, err)
}
if !authorization.CanCreateAddress(authUser, organization) {
return routeutils.ResponseAPIAuthorizationError(ctx)
}
return routeutils.ResponseAPIAuthorizationError(ctx)
address.CreatedUser.ID = authUser.ID
address.UpdatedUser.ID = authUser.ID
_, err = c.svc.Organization.SetOrganizationAddress(orgUUID, address, authUser)
if err != nil {
return routeutils.HandleAPIError(ctx, err)
}
resp, err := c.svc.Organization.GetByUUID(orgUUID, authUser)
if err != nil {
return routeutils.HandleAPIError(ctx, err)
}
@@ -250,19 +310,19 @@ func (c *controller) handleRemoveContact(ctx echo.Context) error {
return routeutils.HandleAPIError(ctx, err)
}
uInt, err := auth.GetTokenDetail(ctx, c.cfg)
if err != nil {
return routeutils.HandleAPIError(ctx, err)
}
createdUser := uInt.(map[string]interface{})
contact.UpdatedUser.ID = createdUser["useruuid"].(string)
err = c.svc.Organization.InactivateOrganizationContact(orgUUID, contact)
authUser, err := auth.GetUserDetail(ctx, c.cfg)
if err != nil {
return routeutils.HandleAPIError(ctx, err)
}
resp, err := c.svc.Organization.GetByUUID(orgUUID)
contact.UpdatedUser.ID = authUser.ID
err = c.svc.Organization.InactivateOrganizationContact(orgUUID, contact, authUser)
if err != nil {
return routeutils.HandleAPIError(ctx, err)
}
resp, err := c.svc.Organization.GetByUUID(orgUUID, authUser)
if err != nil {
return routeutils.HandleAPIError(ctx, err)
}
@@ -282,20 +342,29 @@ func (c *controller) handleAddContact(ctx echo.Context) error {
return routeutils.HandleAPIError(ctx, err)
}
uInt, err := auth.GetTokenDetail(ctx, c.cfg)
if err != nil {
return routeutils.HandleAPIError(ctx, err)
}
createdUser := uInt.(map[string]interface{})
contact.CreatedUser.ID = createdUser["useruuid"].(string)
contact.UpdatedUser.ID = contact.CreatedUser.ID
_, err = c.svc.Organization.SetOrganizationContact(orgUUID, contact)
authUser, err := auth.GetUserDetail(ctx, c.cfg)
if err != nil {
return routeutils.HandleAPIError(ctx, err)
}
resp, err := c.svc.Organization.GetByUUID(orgUUID)
organization, err := c.svc.Organization.GetByUUID(orgUUID, authUser)
if err != nil {
return routeutils.HandleAPIError(ctx, err)
}
if !authorization.CanCreateContact(authUser, organization) {
return routeutils.ResponseAPIAuthorizationError(ctx)
}
contact.CreatedUser.ID = authUser.ID
contact.UpdatedUser.ID = authUser.ID
_, err = c.svc.Organization.SetOrganizationContact(orgUUID, contact, authUser)
if err != nil {
return routeutils.HandleAPIError(ctx, err)
}
resp, err := c.svc.Organization.GetByUUID(orgUUID, authUser)
if err != nil {
return routeutils.HandleAPIError(ctx, err)
}

View File

@@ -104,8 +104,8 @@ func (c *controller) handleParticipating(ctx echo.Context) error {
// long = -87.624225
// }
lat = 40.442875
long = -80.003112
lat = 41.819078
long = -87.623129
if len(mukID) > 0 {
query = ""
@@ -152,8 +152,8 @@ func (c *controller) handleList(ctx echo.Context) error {
providerParams := npdmodel.ProviderSearchParams{
Name: name,
SearchBy: searchBy,
Latitude: 40.442875,
Longitude: -80.003112,
Latitude: 41.819078,
Longitude: -87.623129,
Distance: distance,
Limit: limit,
Offset: 0,

View File

@@ -49,6 +49,11 @@ func ResponseAPIAuthError(c echo.Context, message string, redirect bool) error {
return ResponseAPIError(c, http.StatusUnauthorized, message, redirect)
}
// ResponseAPIAuthorizationError returns a standard API auth error to the response
func ResponseAPIAuthorizationError(c echo.Context) error {
return ResponseAPIError(c, http.StatusForbidden, "Forbidden by controller", false)
}
// ResponseAPIServiceError returns a standard API service unavailable error to the response
func ResponseAPIServiceError(c echo.Context, message string) error {
return ResponseAPIError(c, http.StatusServiceUnavailable, message, false)

View File

@@ -13,6 +13,7 @@ import (
"bitbucket.org/nemt/nemt-portal-api/infra/auth"
"bitbucket.org/nemt/nemt-portal-api/infra/cache"
"bitbucket.org/nemt/nemt-portal-api/infra/config"
"bitbucket.org/nemt/nemt-portal-api/server/authorization"
"bitbucket.org/nemt/nemt-portal-api/server/router/routeutils"
"github.com/labstack/echo"
)
@@ -274,6 +275,11 @@ func (c *controller) handleMember(ctx echo.Context) error {
return routeutils.HandleAPIError(ctx, err)
}
authUser, err := auth.GetUserDetail(ctx, c.cfg)
if err != nil {
return routeutils.HandleAPIError(ctx, err)
}
if user.PhoneNumber == nil && user.Email == nil || len(*user.PhoneNumber) == 0 && len(*user.Email) == 0 {
return routeutils.ResponseAPIAuthError(ctx, "phonenumber or email is required", false)
}
@@ -314,7 +320,7 @@ func (c *controller) handleMember(ctx echo.Context) error {
}
user.Profiles = append(user.Profiles, profile)
user, err = c.svc.Users.Create(user)
user, err = c.svc.Users.Create(user, authUser)
if err != nil {
return routeutils.HandleAPIError(ctx, err)
}
@@ -328,6 +334,11 @@ func (c *controller) handleBulkPortal(ctx echo.Context) error {
return routeutils.HandleAPIError(ctx, err)
}
authUser, err := auth.GetUserDetail(ctx, c.cfg)
if err != nil {
return routeutils.HandleAPIError(ctx, err)
}
for i, _ := range users {
if len(users[i].Profiles) == 0 {
return routeutils.ResponseAPIAuthError(ctx, "profile is required", false)
@@ -360,7 +371,7 @@ func (c *controller) handleBulkPortal(ctx echo.Context) error {
}
}
returnUser, err := c.svc.Users.CreateBulk(users)
returnUser, err := c.svc.Users.CreateBulk(users, authUser)
if err != nil {
return routeutils.HandleAPIError(ctx, err)
}
@@ -374,6 +385,15 @@ func (c *controller) handlePortal(ctx echo.Context) error {
return routeutils.HandleAPIError(ctx, err)
}
authUser, err := auth.GetUserDetail(ctx, c.cfg)
if err != nil {
return routeutils.HandleAPIError(ctx, err)
}
if !authorization.CanCreateUser(authUser, user) {
return routeutils.ResponseAPIAuthorizationError(ctx)
}
if len(user.Profiles) == 0 {
return routeutils.ResponseAPIAuthError(ctx, "profile is required", false)
}
@@ -404,7 +424,7 @@ func (c *controller) handlePortal(ctx echo.Context) error {
user.Name = fmt.Sprintf("%s %s", user.First, user.Last)
}
user, err = c.svc.Users.Create(user)
user, err = c.svc.Users.Create(user, authUser)
if err != nil {
return routeutils.HandleAPIError(ctx, err)
}

View File

@@ -52,16 +52,16 @@ func (s *Server) Run() error {
s.srv.Debug = s.cfg.App.Debug
err := serverconfig.SetMiddlewares(s.srv, s.cfg, s.log, s.svc)
if err != nil {
return errors.Wrap(err)
}
entityMapper := entitymapping.New()
notificationService := notificationservice.New(s.svc, entityMapper, s.cfg, s.cache)
appService := applicationservice.New(s.svc, entityMapper, notificationService, s.cfg)
tncService := tncservice.New(s.svc, entityMapper, s.cfg, notificationService)
err := serverconfig.SetMiddlewares(s.srv, s.cfg, s.log, s.svc, appService)
if err != nil {
return errors.Wrap(err)
}
router.Register(s.srv, s.cfg, appService, tncService, notificationService)
err = s.srv.Start(fmt.Sprintf(":%d", s.cfg.HTTP.Port))

View File

@@ -1,6 +1,8 @@
package serverconfig
import (
"fmt"
"bitbucket.org/nemt/nemt-portal-api/application/applicationservice"
"bitbucket.org/nemt/nemt-portal-api/application/viewmodel"
"bitbucket.org/nemt/nemt-portal-api/infra/auth"
@@ -44,6 +46,8 @@ func MiddlewareWithConfig(cfg *config.Config, svc *applicationservice.Service, l
config := &DefaultConfig
config.Enforcer = casbin.NewEnforcer("authorization_model.conf", "authorization_policy.csv")
config.Svc = svc
config.Logger = log
config.Application = cfg
@@ -68,26 +72,128 @@ func setAuthorizationMiddleware(e *echo.Echo, log *logger.Logger, cfg *config.Co
func (a *Config) CheckPermission(c echo.Context) bool {
user, err := auth.GetUserDetail(c, a.Application)
if err != nil {
a.Logger.Warningf("Cannot get user details. %v ", err)
a.Logger.Warningf("Cannot get user details. %v\n", err)
user = viewmodel.User{}
}
method := c.Request().Method
path := c.Request().URL.Path
//objectOrganization := a.organizationGoverningObject(c, user)
return a.Enforcer.Enforce(user, path, method)
objectsRole, objectsOrganization, objectsOrganizationType, object := a.policyObjectAttributes(c, user)
currentUsersOrganization := viewmodel.Organization{}
if len(user.Organizations) > 0 {
currentUsersOrganization = user.Organizations[0]
}
currentUsersRole := viewmodel.Profile{}
if len(user.Profiles) > 0 {
currentUsersRole = user.Profiles[0]
}
currentUsersOrganizationType := ""
if len(user.Profiles) > 0 {
currentUsersOrganizationType = user.Profiles[0].Organization.Type.Key
}
orgRelation := organizationsRelation(currentUsersOrganization, objectsOrganization)
objRelation := a.objectRelation(object, user)
// parameters to Enforce must match the request section of the authorization_model.conf
return a.Enforcer.Enforce(currentUsersRole.Key,
objectsRole.Key,
objectsOrganizationType,
currentUsersOrganizationType,
orgRelation,
objRelation,
path,
method)
}
func (a *Config) organizationGoverningObject(c echo.Context, userDetails viewmodel.User) (result viewmodel.Organization) {
// policyObjectAttributes returns all information about the object being accessed for the policy
// in case object exists and returns users information if it is a new object
func (a *Config) policyObjectAttributes(c echo.Context, userDetails viewmodel.User) (viewmodel.Profile, viewmodel.Organization, string, interface{}) {
existingUser := strings.Contains(c.Request().URL.Path, "/users") && len(c.ParamValues()) > 0
newUser := strings.Contains(c.Request().URL.Path, "/users") && len(c.ParamValues()) <= 0
var object interface{}
const userIDParamName = "user_uuid"
existingUser := strings.Contains(c.Request().URL.Path, "/users/") && c.Param(userIDParamName) != ""
newUser := strings.Contains(c.Request().URL.Path, "/users/") && c.Param(userIDParamName) == ""
const organizationIDParamName = "org_uuid"
existingOrganization := strings.Contains(c.Request().URL.Path, "/organization") && c.Param(organizationIDParamName) != ""
newOrganization := strings.Contains(c.Request().URL.Path, "/organization") && c.Param(organizationIDParamName) == ""
fmt.Println("**********")
fmt.Printf("url %v\n", c.Param(userIDParamName))
fmt.Printf("user %v\n", userDetails.ID)
fmt.Printf("existing %v\n", existingUser)
fmt.Printf("new %v\n", newUser)
fmt.Println("**********")
switch {
case existingUser:
user, _ := a.Svc.Users.GetByUUID(c.ParamValues()[0], "")
result = user.Organizations[0]
case newUser:
result = userDetails.Organizations[0]
object, _ = a.Svc.Users.GetByUUID(c.Param(userIDParamName), "")
case newUser && len(userDetails.Organizations) > 0:
object = userDetails
case existingOrganization:
object, _ = a.Svc.Organization.GetByUUID(c.Param(organizationIDParamName), userDetails)
case newOrganization:
object = viewmodel.Organization{}
}
return
objectsRole := viewmodel.Profile{}
switch obj := object.(type) {
case viewmodel.User:
if len(obj.Profiles) > 0 {
objectsRole = obj.Profiles[0]
}
}
objectsOrganization := viewmodel.Organization{}
switch obj := object.(type) {
case viewmodel.User:
if len(obj.Profiles) > 0 {
objectsOrganization = obj.Profiles[0].Organization
}
case viewmodel.Organization:
objectsOrganization = obj
}
objectsOrganizationType := objectsOrganization.Type.Key
return objectsRole, objectsOrganization, objectsOrganizationType, object
}
func organizationsRelation(requestOrganization, currentUsersOrganization viewmodel.Organization) string {
if requestOrganization.UUID == currentUsersOrganization.UUID {
return "[equal]"
}
for _, childOrg := range currentUsersOrganization.ChildOrgs {
if childOrg.UUID == requestOrganization.UUID {
return "[equal-or-child]"
}
}
for _, childOrg := range requestOrganization.ChildOrgs {
if childOrg.UUID == currentUsersOrganization.UUID {
return "[parent]"
}
}
return "[unrelated]"
}
// organizationGoverningObject returns the role that is the owner of the object that is being accessed
// in case object exists and returns users role if it is a new object
func (a *Config) objectRelation(object interface{}, currentUser viewmodel.User) string {
switch obj := object.(type) {
case viewmodel.User:
if obj.ID == currentUser.ID {
return "[self]"
}
}
return "[other]"
}

View File

@@ -1,11 +0,0 @@
[request_definition]
r = role, obj, act
[policy_definition]
p = role, obj, act
[policy_effect]
e = some(where (p.eft == allow)) && !some(where (p.eft == deny))
[matchers]
m = keymatch(r.role, p.role) && keyMatch(r.obj, p.obj) && (r.act == p.act || p.act == "*")

View File

@@ -1,6 +1,7 @@
package serverconfig
import (
"bitbucket.org/nemt/nemt-portal-api/application/applicationservice"
"bitbucket.org/nemt/nemt-portal-api/domain/service"
"bitbucket.org/nemt/nemt-portal-api/infra/config"
"bitbucket.org/nemt/nemt-portal-api/infra/errors"
@@ -9,7 +10,7 @@ import (
)
// SetMiddlewares attaches middlewares to server
func SetMiddlewares(server *echo.Echo, cfg *config.Config, log *logger.Logger, svc *service.Service) error {
func SetMiddlewares(server *echo.Echo, cfg *config.Config, log *logger.Logger, svc *service.Service, appsvc *applicationservice.Service) error {
setRecoverMiddleware(server)
setGZIPMiddleware(server)
setRequestIDMiddleware(server)
@@ -17,7 +18,7 @@ func SetMiddlewares(server *echo.Echo, cfg *config.Config, log *logger.Logger, s
setCORSMiddleware(server, cfg)
setBodyLimitMiddleware(server)
setRateLimitMiddleware(server)
//setAuthorizationMiddleware(server, log, svc)
setAuthorizationMiddleware(server, log, cfg, appsvc)
err := setJWTMiddleware(server, cfg)
if err != nil {