3 Commits

Author SHA1 Message Date
GotPPay
daf2d31952 fixed sql query error 2018-05-04 16:38:56 +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
26 changed files with 706 additions and 171 deletions

View File

@@ -15,6 +15,8 @@ COPY ./dist/${BIN_NAME} /opt/app/${BIN_NAME}
ADD ./dist/docs/ /opt/app/docs/ ADD ./dist/docs/ /opt/app/docs/
ADD ./dist/static/ /opt/app/static/ ADD ./dist/static/ /opt/app/static/
ADD ./dist/config.toml /opt/app/config.toml 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. # Sets and executes the app.
WORKDIR /opt/app WORKDIR /opt/app

View File

@@ -67,6 +67,8 @@ build: clean create-build-container
cp -R static/* ./dist/static/ cp -R static/* ./dist/static/
cp -R docs/swagger/ ./dist/docs/ cp -R docs/swagger/ ./dist/docs/
cp config.${DEPLOY_ENV}.toml ./dist/config.toml 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. ## ## 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 return s.mapEntity.Organization.ToOrganizationTypeModelSlice(result), nil
} }
func (s *organizationService) GetByType(organizationTypeKey string) ([]viewmodel.Organization, error) { func (s *organizationService) GetByType(organizationTypeKey string, user viewmodel.User) ([]viewmodel.Organization, error) {
result, err := s.svc.Organization.GetByType(organizationTypeKey) userEntity := s.mapEntity.User.ToUserEntity(user)
result, err := s.svc.Organization.GetByType(organizationTypeKey, userEntity)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return s.mapEntity.Organization.ToOrganizationModelSlice(result), nil return s.mapEntity.Organization.ToOrganizationModelSlice(result), nil
} }
func (s *organizationService) GetByUUID(organizationUUID string) (viewmodel.Organization, error) { func (s *organizationService) GetByUUID(organizationUUID string, user viewmodel.User) (viewmodel.Organization, error) {
result, err := s.svc.Organization.GetByUUID(organizationUUID) userEntity := s.mapEntity.User.ToUserEntity(user)
result, err := s.svc.Organization.GetByUUID(organizationUUID, userEntity)
if err != nil { if err != nil {
return viewmodel.Organization{}, err return viewmodel.Organization{}, err
} }
return s.mapEntity.Organization.ToOrganizationModel(result), nil return s.mapEntity.Organization.ToOrganizationModel(result), nil
} }
func (s *organizationService) GetByName(name string, searchType string) ([]viewmodel.Organization, error) { func (s *organizationService) GetByName(name string, searchType string, user viewmodel.User) ([]viewmodel.Organization, error) {
result, err := s.svc.Organization.GetByName(name, searchType) userEntity := s.mapEntity.User.ToUserEntity(user)
result, err := s.svc.Organization.GetByName(name, searchType, userEntity)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return s.mapEntity.Organization.ToOrganizationModelSlice(result), nil return s.mapEntity.Organization.ToOrganizationModelSlice(result), nil
} }
func (s *organizationService) SetParentOrganization(organizationUUID string, parentOrganizationUUID string) (viewmodel.Organization, error) { func (s *organizationService) SetParentOrganization(organizationUUID string, parentOrganizationUUID string, user viewmodel.User) (viewmodel.Organization, error) {
child, err := s.svc.Organization.GetByUUID(organizationUUID) userEntity := s.mapEntity.User.ToUserEntity(user)
child, err := s.svc.Organization.GetByUUID(organizationUUID, userEntity)
if err != nil { if err != nil {
return viewmodel.Organization{}, err return viewmodel.Organization{}, err
} }
parent, err := s.svc.Organization.GetByUUID(parentOrganizationUUID) parent, err := s.svc.Organization.GetByUUID(parentOrganizationUUID, userEntity)
if err != nil { if err != nil {
return viewmodel.Organization{}, err return viewmodel.Organization{}, err
} }
@@ -74,10 +79,11 @@ func (s *organizationService) SetParentOrganization(organizationUUID string, par
return viewmodel.Organization{}, err 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 := s.mapEntity.Organization.ToOrganizationAddressEntity(address)
entityAddress.Organization = &entity.Organization{ entityAddress.Organization = &entity.Organization{
UUID: organizationUUID, UUID: organizationUUID,
@@ -89,14 +95,15 @@ func (s *organizationService) InactivateOrganizationAddress(organizationUUID str
} }
entityAddress.UpdatedUser = user entityAddress.UpdatedUser = user
if err := s.svc.Organization.InactivateOrganizationAddress(entityAddress); err != nil { if err := s.svc.Organization.InactivateOrganizationAddress(entityAddress, userEntity); err != nil {
return err return err
} else { } else {
return nil 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 := s.mapEntity.Organization.ToOrganizationAddressEntity(address)
entityAddress.Organization = &entity.Organization{ entityAddress.Organization = &entity.Organization{
UUID: organizationUUID, UUID: organizationUUID,
@@ -110,7 +117,7 @@ func (s *organizationService) SetOrganizationAddress(organizationUUID string, ad
entityAddress.CreatedUser = user entityAddress.CreatedUser = user
entityAddress.UpdatedUser = user entityAddress.UpdatedUser = user
entityAddress, err = s.svc.Organization.SetOrganizationAddress(entityAddress) entityAddress, err = s.svc.Organization.SetOrganizationAddress(entityAddress, userEntity)
if err != nil { if err != nil {
return viewmodel.OrganizationAddress{}, err return viewmodel.OrganizationAddress{}, err
} }
@@ -118,7 +125,8 @@ func (s *organizationService) SetOrganizationAddress(organizationUUID string, ad
return s.mapEntity.Organization.ToOrganizationAddressModel(entityAddress), nil 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 := s.mapEntity.Organization.ToOrganizationContactEntity(contact)
entityContact.Organization = &entity.Organization{ entityContact.Organization = &entity.Organization{
UUID: organizationUUID, UUID: organizationUUID,
@@ -130,14 +138,15 @@ func (s *organizationService) InactivateOrganizationContact(organizationUUID str
} }
entityContact.UpdatedUser = user entityContact.UpdatedUser = user
if err := s.svc.Organization.InactivateOrganizationContact(entityContact); err != nil { if err := s.svc.Organization.InactivateOrganizationContact(entityContact, userEntity); err != nil {
return err return err
} else { } else {
return nil 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 := s.mapEntity.Organization.ToOrganizationContactEntity(contact)
entityContact.Organization = &entity.Organization{ entityContact.Organization = &entity.Organization{
UUID: organizationUUID, UUID: organizationUUID,
@@ -151,7 +160,7 @@ func (s *organizationService) SetOrganizationContact(organizationUUID string, co
entityContact.CreatedUser = user entityContact.CreatedUser = user
entityContact.UpdatedUser = user entityContact.UpdatedUser = user
entityContact, err = s.svc.Organization.SetOrganizationContact(entityContact) entityContact, err = s.svc.Organization.SetOrganizationContact(entityContact, userEntity)
if err != nil { if err != nil {
return viewmodel.OrganizationContact{}, err 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 { if err != nil {
return viewmodel.Organization{}, 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 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) entity := s.mapEntity.User.ToUserEntity(user)
enAuthor := s.mapEntity.User.ToUserEntity(author)
for i, _ := range entity.Organizations { 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 { if err != nil {
return retVal, err 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 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) entities := s.mapEntity.User.ToUserEntitySlice(users)
enAuthor := s.mapEntity.User.ToUserEntity(author)
organizations := make([]entity.Organization, 0) organizations := make([]entity.Organization, 0)
for i, _ := range entities { for i, _ := range entities {
if i == 0 { if i == 0 {
for o, _ := range entities[i].Organizations { 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 { if err != nil {
return nil, err 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 == "*")

111
authorization_policy.csv Normal file
View File

@@ -0,0 +1,111 @@
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, SCHDAD, *, *, *, [equal*], *, /v1/nemt/organization/*, GET
p, SCHDAD, *, *, *, [equal*], *, /v1/nemt/organization/*, POST
p, SCHDAD, *, *, *, [equal*], *, /v1/nemt/organization/*, PUT
p, PLANAD, *, *, *, [equal*], *, /v1/nemt/organization/*, GET
p, PLANAD, *, *, *, [equal*], *, /v1/nemt/organization/*, POST
p, PLANAD, *, *, *, [equal*], *, /v1/nemt/organization/*, PUT
p, BDCAD, *, *, *, *, *, /v1/nemt/organization/*, GET
p, BDCAD, *, *, *, *, *, /v1/nemt/organization/*, POST
p, BDCAD, *, *, *, *, *, /v1/nemt/organization/*, PUT
p, BCBSIAD, *, *, *, *, *, /v1/nemt/organization/*, GET
p, BCBSIAD, *, *, *, *, *, /v1/nemt/organization/*, POST
p, BCBSIAD, *, *, *, *, *, /v1/nemt/organization/*, PUT
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 SCHDAD * * * [equal*] * /v1/nemt/organization/* GET
83 p SCHDAD * * * [equal*] * /v1/nemt/organization/* POST
84 p SCHDAD * * * [equal*] * /v1/nemt/organization/* PUT
85 p PLANAD * * * [equal*] * /v1/nemt/organization/* GET
86 p PLANAD * * * [equal*] * /v1/nemt/organization/* POST
87 p PLANAD * * * [equal*] * /v1/nemt/organization/* PUT
88 p BDCAD * * * * * /v1/nemt/organization/* GET
89 p BDCAD * * * * * /v1/nemt/organization/* POST
90 p BDCAD * * * * * /v1/nemt/organization/* PUT
91 p BCBSIAD * * * * * /v1/nemt/organization/* GET
92 p BCBSIAD * * * * * /v1/nemt/organization/* POST
93 p BCBSIAD * * * * * /v1/nemt/organization/* PUT
94 p SPT * programsupport * * * /v1/nemt/organization/* GET
95 p SP * provider * * * /v1/nemt/organization GET
96 p SP * plan * * * /v1/nemt/organization GET
97 p SPT * programsupport * * * /v1/nemt/organization GET
98 p SCHDAD * provider * * * /v1/nemt/organization GET
99 p BCBSIAD * bcbsi * * * /v1/nemt/organization GET
100 p BDCAD * techsupport * * * /v1/nemt/organization GET
101 p PLANAD * plan * * * /v1/nemt/organization GET
102 p AD * * * * * /v1/nemt/organization GET
103 p SP * provider * * * /v1/nemt/eligibility POST
104 p SP * plan * * * /v1/nemt/eligibility POST
105 p SPT * programsupport * * * /v1/nemt/eligibility POST
106 p SCHDAD * provider * * * /v1/nemt/eligibility POST
107 p BCBSIAD * bcbsi * * * /v1/nemt/eligibility POST
108 p BDCAD * techsupport * * * /v1/nemt/eligibility POST
109 p PLANAD * plan * * * /v1/nemt/eligibility POST
110 p AD * * * * * /v1/nemt/eligibility POST

View File

@@ -19,6 +19,8 @@ pipelines:
- cp -R static/* ./dist/static/ - cp -R static/* ./dist/static/
- cp -R docs/swagger/ ./dist/docs/ - cp -R docs/swagger/ ./dist/docs/
- cp config.prd.toml ./dist/config.toml - 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 . - 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 update -y && apt-get upgrade -y && apt-get dist-upgrade -y && apt-get -y autoremove && apt-get clean
- apt-get install python3-pip -y - apt-get install python3-pip -y
@@ -46,6 +48,8 @@ pipelines:
- cp -R static/* ./dist/static/ - cp -R static/* ./dist/static/
- cp -R docs/swagger/ ./dist/docs/ - cp -R docs/swagger/ ./dist/docs/
- cp config.stg.toml ./dist/config.toml - 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 . - 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 update -y && apt-get upgrade -y && apt-get dist-upgrade -y && apt-get -y autoremove && apt-get clean
- apt-get install python3-pip -y - 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 { func (c *organizationRepo) getQuery() string {
const ( const (
query = `SELECT query = `SELECT
@@ -237,42 +294,73 @@ func (c *organizationRepo) GetAllTypes() ([]entity.OrganizationType, error) {
} }
func (c *organizationRepo) GetTypeByKey(key string) (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 == "" { if organizationTypeKey == "" {
return c.parseSet(c.conn.Query(c.getQuery())) return c.parseSet(c.conn.Query(c.getQuery() + query + " WHERE 1 = 1 " + where))
} else { } 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) { func (c *organizationRepo) GetByName(name string, searchType string, user entity.User) ([]entity.Organization, error) {
finalQuery := c.getQuery() + " WHERE a.organization_name LIKE ?" query, where, err := c.getProfileQuery(user)
if err != nil {
return nil, err
}
finalQuery := c.getQuery() + query + " WHERE a.organization_name LIKE ? "
switch searchType { switch searchType {
case "parent": case "parent":
finalQuery += " AND a.organization_parent_id > 0; " finalQuery += " AND a.organization_parent_id > 0 "
case "child": 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)) return c.parseSet(c.conn.Query(finalQuery, name))
} }
func (c *organizationRepo) GetByUUID(organizationUUID string) (entity.Organization, error) { func (c *organizationRepo) GetByUUID(organizationUUID string, user entity.User) (entity.Organization, error) {
return c.parseEntity(c.conn.QueryRow(c.getQuery()+" WHERE a.organization_uuid = ? ", organizationUUID)) 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) { func (c *organizationRepo) GetByID(organizationID int64, user entity.User) (entity.Organization, error) {
return c.parseEntity(c.conn.QueryRow(c.getQuery()+" WHERE a.organization_id = ? ", organizationID)) 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) { func (c *organizationRepo) GetChildsByID(organizationID int64, user entity.User) ([]entity.Organization, error) {
return c.parseSet(c.conn.Query(c.getQuery()+" WHERE a.organization_parent_id = ? ", organizationID)) 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) { 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 ( const (
query = "UPDATE tab_organization_address SET active = 0, updated = CURRENT_TIMESTAMP, updated_user_id = ? WHERE organization_id = ? and organization_address_uuid = ?" 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() return errors.NewNotFoundError()
} }
organization, err := c.GetByUUID(address.Organization.UUID) organization, err := c.GetByUUID(address.Organization.UUID, user)
if err != nil { if err != nil {
return err 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 ( 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(?, ?, ?, ?, ?, ?, ?, ?, ?, ?);" 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() return entity.OrganizationAddress{}, errors.NewNotFoundError()
} }
organization, err := c.GetByUUID(address.Organization.UUID) organization, err := c.GetByUUID(address.Organization.UUID, user)
if err != nil { if err != nil {
return entity.OrganizationAddress{}, err return entity.OrganizationAddress{}, err
} }
@@ -362,7 +450,7 @@ func (c *organizationRepo) SetOrganizationAddress(address entity.OrganizationAdd
return address, nil return address, nil
} }
func (c *organizationRepo) InactivateOrganizationContact(contact entity.OrganizationContact) error { func (c *organizationRepo) InactivateOrganizationContact(contact entity.OrganizationContact, user entity.User) error {
const ( const (
query = "UPDATE tab_organization_contact SET active = 0, updated = CURRENT_TIMESTAMP, updated_user_id = ? WHERE organization_id = ? and organization_contact_uuid = ?" 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() return errors.NewNotFoundError()
} }
organization, err := c.GetByUUID(contact.Organization.UUID) organization, err := c.GetByUUID(contact.Organization.UUID, user)
if err != nil { if err != nil {
return err 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 ( const (
selectQuery = "SELECT a.contact_type_id, a.name, a.key FROM tab_contact_type a WHERE a.key = ?" 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(?, ?, ?, ?, ?, ?, ?, ?);" 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() return entity.OrganizationContact{}, errors.NewNotFoundError()
} }
organization, err := c.GetByUUID(contact.Organization.UUID) organization, err := c.GetByUUID(contact.Organization.UUID, user)
if err != nil { if err != nil {
return entity.OrganizationContact{}, err return entity.OrganizationContact{}, err
} }
@@ -419,7 +507,7 @@ func (c *organizationRepo) SetOrganizationContact(contact entity.OrganizationCon
return contact, nil 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 ( const (
queryOrgType = "SELECT a.organization_type_id FROM tab_organization_type a WHERE a.organization_type_key = ?;" 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 = ?;" 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 { if len(organization.Addresses) > 0 {
for i, a := range organization.Addresses { for i, a := range organization.Addresses {
a.Organization = &organization a.Organization = &organization
address, err := c.SetOrganizationAddress(a) address, err := c.SetOrganizationAddress(a, user)
if err != nil { if err != nil {
fmt.Println("Error to save addresses") fmt.Println("Error to save addresses")
return entity.Organization{}, err return entity.Organization{}, err
@@ -469,7 +557,7 @@ func (c *organizationRepo) AddOrganization(organization entity.Organization) (en
if len(organization.Contacts) > 0 { if len(organization.Contacts) > 0 {
for i, ct := range organization.Contacts { for i, ct := range organization.Contacts {
ct.Organization = &organization ct.Organization = &organization
contact, err := c.SetOrganizationContact(ct) contact, err := c.SetOrganizationContact(ct, user)
if err != nil { if err != nil {
fmt.Println("Error to save contacts") fmt.Println("Error to save contacts")
return entity.Organization{}, err return entity.Organization{}, err

View File

@@ -784,7 +784,7 @@ func (c *userRepo) getAddressSecondaryData(address entity.Address) (entity.Addre
// GetAll returns a list of all active cards // GetAll returns a list of all active cards
func (c *userRepo) GetAll() (list []entity.User, err error) { func (c *userRepo) GetAll() (list []entity.User, err error) {
return c.parseSet(c.conn.Query(c.getQuery() + " WHERE a.active = 1 ")) return c.parseSet(c.conn.Query(c.getQuery() + " AND a.active = 1 "))
} }
// GetByID returns a single card data by its ID // GetByID returns a single card data by its ID

View File

@@ -68,23 +68,23 @@ type NotificationRepo interface {
// ProviderRepo defines the data set for Rides // ProviderRepo defines the data set for Rides
type OrganizationRepo interface { type OrganizationRepo interface {
GetAllTypes() ([]entity.OrganizationType, error) GetAllTypes() ([]entity.OrganizationType, error)
GetByType(organizationTypeKey string) ([]entity.Organization, error) GetByType(organizationTypeKey string, user entity.User) ([]entity.Organization, error)
GetByUUID(organizationUUID string) (entity.Organization, error) GetByUUID(organizationUUID string, user entity.User) (entity.Organization, error)
GetContactsByOrganizationUUID(organizationUUID string) ([]entity.OrganizationContact, error) GetContactsByOrganizationUUID(organizationUUID string) ([]entity.OrganizationContact, error)
GetContactsByOrganizationID(organizationID int64) ([]entity.OrganizationContact, error) GetContactsByOrganizationID(organizationID int64) ([]entity.OrganizationContact, error)
GetContactsByUUID(contactUUID string) (entity.OrganizationContact, error) GetContactsByUUID(contactUUID string) (entity.OrganizationContact, error)
GetAddressByOrganizationUUID(organizationUUID string) ([]entity.OrganizationAddress, error) GetAddressByOrganizationUUID(organizationUUID string) ([]entity.OrganizationAddress, error)
GetAddressByOrganizationID(organizationID int64) ([]entity.OrganizationAddress, error) GetAddressByOrganizationID(organizationID int64) ([]entity.OrganizationAddress, error)
GetAddressByUUID(contactUUID string) (entity.OrganizationAddress, error) GetAddressByUUID(contactUUID string) (entity.OrganizationAddress, error)
GetByID(organizationID int64) (entity.Organization, error) GetByID(organizationID int64, user entity.User) (entity.Organization, error)
GetChildsByID(organizationID int64) ([]entity.Organization, error) GetChildsByID(organizationID int64, user entity.User) ([]entity.Organization, error)
GetByName(name string, searchType string) ([]entity.Organization, error) GetByName(name string, searchType string, user entity.User) ([]entity.Organization, error)
SetParentOrganization(organizationID int64, parentOrganizationID int64) error SetParentOrganization(organizationID int64, parentOrganizationID int64) error
InactivateOrganizationAddress(address entity.OrganizationAddress) error InactivateOrganizationAddress(address entity.OrganizationAddress, user entity.User) error
SetOrganizationAddress(address entity.OrganizationAddress) (entity.OrganizationAddress, error) SetOrganizationAddress(address entity.OrganizationAddress, user entity.User) (entity.OrganizationAddress, error)
InactivateOrganizationContact(contact entity.OrganizationContact) error InactivateOrganizationContact(contact entity.OrganizationContact, user entity.User) error
SetOrganizationContact(contact entity.OrganizationContact) (entity.OrganizationContact, error) SetOrganizationContact(contact entity.OrganizationContact, user entity.User) (entity.OrganizationContact, error)
AddOrganization(organization entity.Organization) (entity.Organization, error) AddOrganization(organization entity.Organization, user entity.User) (entity.Organization, error)
GetTypeByKey(key string) (entity.OrganizationType, 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() return s.svc.db.Organization().GetAllTypes()
} }
func (s *organizationService) GetByType(organizationTypeKey string) ([]entity.Organization, error) { func (s *organizationService) GetByType(organizationTypeKey string, user entity.User) ([]entity.Organization, error) {
return s.svc.db.Organization().GetByType(organizationTypeKey) return s.svc.db.Organization().GetByType(organizationTypeKey, user)
} }
func (s *organizationService) GetByName(name string, searchType string) ([]entity.Organization, error) { func (s *organizationService) GetByName(name string, searchType string, user entity.User) ([]entity.Organization, error) {
return s.svc.db.Organization().GetByName(name, searchType) return s.svc.db.Organization().GetByName(name, searchType, user)
} }
func (s *organizationService) GetByUUID(organizationUUID string) (entity.Organization, error) { func (s *organizationService) GetByUUID(organizationUUID string, user entity.User) (entity.Organization, error) {
organization, err := s.svc.db.Organization().GetByUUID(organizationUUID) organization, err := s.svc.db.Organization().GetByUUID(organizationUUID, user)
if err != nil { if err != nil {
return organization, err return organization, err
} }
@@ -44,13 +44,13 @@ func (s *organizationService) GetByUUID(organizationUUID string) (entity.Organiz
return organization, err 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 { if err != nil {
return organization, err return organization, err
} }
if organization.ParentID > 0 { 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 { if err != nil {
return organization, err return organization, err
} }
@@ -88,24 +88,24 @@ func (s *organizationService) GetAddressByUUID(contactUUID string) (entity.Organ
return s.svc.db.Organization().GetAddressByUUID(contactUUID) return s.svc.db.Organization().GetAddressByUUID(contactUUID)
} }
func (s *organizationService) InactivateOrganizationAddress(address entity.OrganizationAddress) error { func (s *organizationService) InactivateOrganizationAddress(address entity.OrganizationAddress, user entity.User) error {
return s.svc.db.Organization().InactivateOrganizationAddress(address) return s.svc.db.Organization().InactivateOrganizationAddress(address, user)
} }
func (s *organizationService) SetOrganizationAddress(address entity.OrganizationAddress) (entity.OrganizationAddress, error) { func (s *organizationService) SetOrganizationAddress(address entity.OrganizationAddress, user entity.User) (entity.OrganizationAddress, error) {
return s.svc.db.Organization().SetOrganizationAddress(address) return s.svc.db.Organization().SetOrganizationAddress(address, user)
} }
func (s *organizationService) InactivateOrganizationContact(contact entity.OrganizationContact) error { func (s *organizationService) InactivateOrganizationContact(contact entity.OrganizationContact, user entity.User) error {
return s.svc.db.Organization().InactivateOrganizationContact(contact) return s.svc.db.Organization().InactivateOrganizationContact(contact, user)
} }
func (s *organizationService) SetOrganizationContact(contact entity.OrganizationContact) (entity.OrganizationContact, error) { func (s *organizationService) SetOrganizationContact(contact entity.OrganizationContact, user entity.User) (entity.OrganizationContact, error) {
return s.svc.db.Organization().SetOrganizationContact(contact) return s.svc.db.Organization().SetOrganizationContact(contact, user)
} }
func (s *organizationService) AddOrganization(organization entity.Organization) (entity.Organization, error) { func (s *organizationService) AddOrganization(organization entity.Organization, user entity.User) (entity.Organization, error) {
return s.svc.db.Organization().AddOrganization(organization) return s.svc.db.Organization().AddOrganization(organization, user)
} }
func (s *organizationService) GetTypeByKey(key string) (entity.OrganizationType, error) { func (s *organizationService) GetTypeByKey(key string) (entity.OrganizationType, error) {

View File

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

View File

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

View File

@@ -42,3 +42,7 @@ import:
- package: github.com/ttacon/builder - package: github.com/ttacon/builder
- package: github.com/casbin/casbin - package: github.com/casbin/casbin
version: ~1.5.0 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 @@
package authorization

View File

@@ -0,0 +1,28 @@
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
}

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

@@ -78,7 +78,12 @@ func (c *controller) handleAddOrganization(ctx echo.Context) error {
func (c *controller) handle(ctx echo.Context) error { func (c *controller) handle(ctx echo.Context) error {
orgType, _ := routeutils.GetAndValidateStringQueryParam(ctx, "type", "Type is mandatory") 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 { if err != nil {
return routeutils.HandleAPIError(ctx, err) return routeutils.HandleAPIError(ctx, err)
} }
@@ -92,7 +97,12 @@ func (c *controller) handleDetail(ctx echo.Context) error {
return routeutils.HandleAPIError(ctx, err) 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 { if err != nil {
return routeutils.HandleAPIError(ctx, err) return routeutils.HandleAPIError(ctx, err)
} }
@@ -112,7 +122,12 @@ func (c *controller) handleParent(ctx echo.Context) error {
return routeutils.HandleAPIError(ctx, err) 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)
}
resp, err := c.svc.Organization.SetParentOrganization(orgUUID, parent.UUID, authUser)
if err != nil { if err != nil {
return routeutils.HandleAPIError(ctx, err) return routeutils.HandleAPIError(ctx, err)
} }
@@ -132,12 +147,17 @@ func (c *controller) handleChild(ctx echo.Context) error {
return routeutils.HandleAPIError(ctx, err) return routeutils.HandleAPIError(ctx, err)
} }
_, err = c.svc.Organization.SetParentOrganization(child.UUID, orgUUID) authUser, err := auth.GetUserDetail(ctx, c.cfg)
if err != nil { if err != nil {
return routeutils.HandleAPIError(ctx, err) return routeutils.HandleAPIError(ctx, err)
} }
resp, err := c.svc.Organization.GetByUUID(orgUUID) _, 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 { if err != nil {
return routeutils.HandleAPIError(ctx, err) return routeutils.HandleAPIError(ctx, err)
} }
@@ -151,11 +171,16 @@ func (c *controller) handleNameSearch(ctx echo.Context) error {
return routeutils.HandleAPIError(ctx, err) return routeutils.HandleAPIError(ctx, err)
} }
authUser, err := auth.GetUserDetail(ctx, c.cfg)
if err != nil {
return routeutils.HandleAPIError(ctx, err)
}
searchType := "" searchType := ""
searchType, _ = routeutils.GetAndValidateStringQueryParam(ctx, "type", "Type is mandatory") searchType, _ = routeutils.GetAndValidateStringQueryParam(ctx, "type", "Type is mandatory")
cache := cache.Instance(c.cfg) 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{} resp := []viewmodel.Organization{}
err = cache.GetStruct(cacheKey, &resp) err = cache.GetStruct(cacheKey, &resp)
@@ -163,7 +188,7 @@ func (c *controller) handleNameSearch(ctx echo.Context) error {
if err != domain.ErrCacheMiss { if err != domain.ErrCacheMiss {
ctx.Logger().Errorf(domain.LogProblemGettingFromCache, err) 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 { if err != nil {
return routeutils.HandleAPIError(ctx, err) return routeutils.HandleAPIError(ctx, err)
} }
@@ -180,24 +205,24 @@ func (c *controller) handleRemoveAddress(ctx echo.Context) error {
return routeutils.HandleAPIError(ctx, err) 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") orgUUID, err := routeutils.GetAndValidateStringParam(ctx, "org_uuid", "Org ID is mandatory")
if err != nil { if err != nil {
return routeutils.HandleAPIError(ctx, err) return routeutils.HandleAPIError(ctx, err)
} }
uInt, err := auth.GetTokenDetail(ctx, c.cfg) address.UpdatedUser.ID = authUser.ID
if err != nil {
return routeutils.HandleAPIError(ctx, err)
}
createdUser := uInt.(map[string]interface{})
address.UpdatedUser.ID = createdUser["useruuid"].(string)
err = c.svc.Organization.InactivateOrganizationAddress(orgUUID, address) err = c.svc.Organization.InactivateOrganizationAddress(orgUUID, address, authUser)
if err != nil { if err != nil {
return routeutils.HandleAPIError(ctx, err) return routeutils.HandleAPIError(ctx, err)
} }
resp, err := c.svc.Organization.GetByUUID(orgUUID) resp, err := c.svc.Organization.GetByUUID(orgUUID, authUser)
if err != nil { if err != nil {
return routeutils.HandleAPIError(ctx, err) return routeutils.HandleAPIError(ctx, err)
} }
@@ -217,20 +242,19 @@ func (c *controller) handleAddAddress(ctx echo.Context) error {
return routeutils.HandleAPIError(ctx, err) return routeutils.HandleAPIError(ctx, err)
} }
uInt, err := auth.GetTokenDetail(ctx, c.cfg) authUser, err := auth.GetUserDetail(ctx, c.cfg)
if err != nil { if err != nil {
return routeutils.HandleAPIError(ctx, err) return routeutils.HandleAPIError(ctx, err)
} }
createdUser := uInt.(map[string]interface{}) address.CreatedUser.ID = authUser.ID
address.CreatedUser.ID = createdUser["useruuid"].(string) address.UpdatedUser.ID = authUser.ID
address.UpdatedUser.ID = address.CreatedUser.ID
_, err = c.svc.Organization.SetOrganizationAddress(orgUUID, address) _, err = c.svc.Organization.SetOrganizationAddress(orgUUID, address, authUser)
if err != nil { if err != nil {
return routeutils.HandleAPIError(ctx, err) return routeutils.HandleAPIError(ctx, err)
} }
resp, err := c.svc.Organization.GetByUUID(orgUUID) resp, err := c.svc.Organization.GetByUUID(orgUUID, authUser)
if err != nil { if err != nil {
return routeutils.HandleAPIError(ctx, err) return routeutils.HandleAPIError(ctx, err)
} }
@@ -250,19 +274,18 @@ func (c *controller) handleRemoveContact(ctx echo.Context) error {
return routeutils.HandleAPIError(ctx, err) return routeutils.HandleAPIError(ctx, err)
} }
uInt, err := auth.GetTokenDetail(ctx, c.cfg) authUser, err := auth.GetUserDetail(ctx, c.cfg)
if err != nil { if err != nil {
return routeutils.HandleAPIError(ctx, err) return routeutils.HandleAPIError(ctx, err)
} }
createdUser := uInt.(map[string]interface{}) contact.UpdatedUser.ID = authUser.ID
contact.UpdatedUser.ID = createdUser["useruuid"].(string)
err = c.svc.Organization.InactivateOrganizationContact(orgUUID, contact) err = c.svc.Organization.InactivateOrganizationContact(orgUUID, contact, authUser)
if err != nil { if err != nil {
return routeutils.HandleAPIError(ctx, err) return routeutils.HandleAPIError(ctx, err)
} }
resp, err := c.svc.Organization.GetByUUID(orgUUID) resp, err := c.svc.Organization.GetByUUID(orgUUID, authUser)
if err != nil { if err != nil {
return routeutils.HandleAPIError(ctx, err) return routeutils.HandleAPIError(ctx, err)
} }
@@ -282,20 +305,19 @@ func (c *controller) handleAddContact(ctx echo.Context) error {
return routeutils.HandleAPIError(ctx, err) return routeutils.HandleAPIError(ctx, err)
} }
uInt, err := auth.GetTokenDetail(ctx, c.cfg) authUser, err := auth.GetUserDetail(ctx, c.cfg)
if err != nil { if err != nil {
return routeutils.HandleAPIError(ctx, err) return routeutils.HandleAPIError(ctx, err)
} }
createdUser := uInt.(map[string]interface{}) contact.CreatedUser.ID = authUser.ID
contact.CreatedUser.ID = createdUser["useruuid"].(string) contact.UpdatedUser.ID = authUser.ID
contact.UpdatedUser.ID = contact.CreatedUser.ID
_, err = c.svc.Organization.SetOrganizationContact(orgUUID, contact) _, err = c.svc.Organization.SetOrganizationContact(orgUUID, contact, authUser)
if err != nil { if err != nil {
return routeutils.HandleAPIError(ctx, err) return routeutils.HandleAPIError(ctx, err)
} }
resp, err := c.svc.Organization.GetByUUID(orgUUID) resp, err := c.svc.Organization.GetByUUID(orgUUID, authUser)
if err != nil { if err != nil {
return routeutils.HandleAPIError(ctx, err) return routeutils.HandleAPIError(ctx, err)
} }

View File

@@ -104,8 +104,8 @@ func (c *controller) handleParticipating(ctx echo.Context) error {
// long = -87.624225 // long = -87.624225
// } // }
lat = 40.442875 lat = 41.819078
long = -80.003112 long = -87.623129
if len(mukID) > 0 { if len(mukID) > 0 {
query = "" query = ""
@@ -152,8 +152,8 @@ func (c *controller) handleList(ctx echo.Context) error {
providerParams := npdmodel.ProviderSearchParams{ providerParams := npdmodel.ProviderSearchParams{
Name: name, Name: name,
SearchBy: searchBy, SearchBy: searchBy,
Latitude: 40.442875, Latitude: 41.819078,
Longitude: -80.003112, Longitude: -87.623129,
Distance: distance, Distance: distance,
Limit: limit, Limit: limit,
Offset: 0, 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) 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 // ResponseAPIServiceError returns a standard API service unavailable error to the response
func ResponseAPIServiceError(c echo.Context, message string) error { func ResponseAPIServiceError(c echo.Context, message string) error {
return ResponseAPIError(c, http.StatusServiceUnavailable, message, false) 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/auth"
"bitbucket.org/nemt/nemt-portal-api/infra/cache" "bitbucket.org/nemt/nemt-portal-api/infra/cache"
"bitbucket.org/nemt/nemt-portal-api/infra/config" "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" "bitbucket.org/nemt/nemt-portal-api/server/router/routeutils"
"github.com/labstack/echo" "github.com/labstack/echo"
) )
@@ -274,6 +275,11 @@ func (c *controller) handleMember(ctx echo.Context) error {
return routeutils.HandleAPIError(ctx, err) 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 { 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) 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.Profiles = append(user.Profiles, profile)
user, err = c.svc.Users.Create(user) user, err = c.svc.Users.Create(user, authUser)
if err != nil { if err != nil {
return routeutils.HandleAPIError(ctx, err) return routeutils.HandleAPIError(ctx, err)
} }
@@ -328,6 +334,11 @@ func (c *controller) handleBulkPortal(ctx echo.Context) error {
return routeutils.HandleAPIError(ctx, err) return routeutils.HandleAPIError(ctx, err)
} }
authUser, err := auth.GetUserDetail(ctx, c.cfg)
if err != nil {
return routeutils.HandleAPIError(ctx, err)
}
for i, _ := range users { for i, _ := range users {
if len(users[i].Profiles) == 0 { if len(users[i].Profiles) == 0 {
return routeutils.ResponseAPIAuthError(ctx, "profile is required", false) 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 { if err != nil {
return routeutils.HandleAPIError(ctx, err) return routeutils.HandleAPIError(ctx, err)
} }
@@ -374,6 +385,15 @@ func (c *controller) handlePortal(ctx echo.Context) error {
return routeutils.HandleAPIError(ctx, err) 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 { if len(user.Profiles) == 0 {
return routeutils.ResponseAPIAuthError(ctx, "profile is required", false) 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.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 { if err != nil {
return routeutils.HandleAPIError(ctx, err) return routeutils.HandleAPIError(ctx, err)
} }

View File

@@ -52,16 +52,16 @@ func (s *Server) Run() error {
s.srv.Debug = s.cfg.App.Debug 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() entityMapper := entitymapping.New()
notificationService := notificationservice.New(s.svc, entityMapper, s.cfg, s.cache) notificationService := notificationservice.New(s.svc, entityMapper, s.cfg, s.cache)
appService := applicationservice.New(s.svc, entityMapper, notificationService, s.cfg) appService := applicationservice.New(s.svc, entityMapper, notificationService, s.cfg)
tncService := tncservice.New(s.svc, entityMapper, s.cfg, notificationService) 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) router.Register(s.srv, s.cfg, appService, tncService, notificationService)
err = s.srv.Start(fmt.Sprintf(":%d", s.cfg.HTTP.Port)) err = s.srv.Start(fmt.Sprintf(":%d", s.cfg.HTTP.Port))

View File

@@ -1,6 +1,8 @@
package serverconfig package serverconfig
import ( import (
"fmt"
"bitbucket.org/nemt/nemt-portal-api/application/applicationservice" "bitbucket.org/nemt/nemt-portal-api/application/applicationservice"
"bitbucket.org/nemt/nemt-portal-api/application/viewmodel" "bitbucket.org/nemt/nemt-portal-api/application/viewmodel"
"bitbucket.org/nemt/nemt-portal-api/infra/auth" "bitbucket.org/nemt/nemt-portal-api/infra/auth"
@@ -44,6 +46,8 @@ func MiddlewareWithConfig(cfg *config.Config, svc *applicationservice.Service, l
config := &DefaultConfig config := &DefaultConfig
config.Enforcer = casbin.NewEnforcer("authorization_model.conf", "authorization_policy.csv")
config.Svc = svc config.Svc = svc
config.Logger = log config.Logger = log
config.Application = cfg 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 { func (a *Config) CheckPermission(c echo.Context) bool {
user, err := auth.GetUserDetail(c, a.Application) user, err := auth.GetUserDetail(c, a.Application)
if err != nil { 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 method := c.Request().Method
path := c.Request().URL.Path 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 var object interface{}
newUser := strings.Contains(c.Request().URL.Path, "/users") && len(c.ParamValues()) <= 0
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 { switch {
case existingUser: case existingUser:
user, _ := a.Svc.Users.GetByUUID(c.ParamValues()[0], "") object, _ = a.Svc.Users.GetByUUID(c.Param(userIDParamName), "")
result = user.Organizations[0] case newUser && len(userDetails.Organizations) > 0:
case newUser: object = userDetails
result = userDetails.Organizations[0] 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 package serverconfig
import ( import (
"bitbucket.org/nemt/nemt-portal-api/application/applicationservice"
"bitbucket.org/nemt/nemt-portal-api/domain/service" "bitbucket.org/nemt/nemt-portal-api/domain/service"
"bitbucket.org/nemt/nemt-portal-api/infra/config" "bitbucket.org/nemt/nemt-portal-api/infra/config"
"bitbucket.org/nemt/nemt-portal-api/infra/errors" "bitbucket.org/nemt/nemt-portal-api/infra/errors"
@@ -9,7 +10,7 @@ import (
) )
// SetMiddlewares attaches middlewares to server // 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) setRecoverMiddleware(server)
setGZIPMiddleware(server) setGZIPMiddleware(server)
setRequestIDMiddleware(server) setRequestIDMiddleware(server)
@@ -17,7 +18,7 @@ func SetMiddlewares(server *echo.Echo, cfg *config.Config, log *logger.Logger, s
setCORSMiddleware(server, cfg) setCORSMiddleware(server, cfg)
setBodyLimitMiddleware(server) setBodyLimitMiddleware(server)
setRateLimitMiddleware(server) setRateLimitMiddleware(server)
//setAuthorizationMiddleware(server, log, svc) setAuthorizationMiddleware(server, log, cfg, appsvc)
err := setJWTMiddleware(server, cfg) err := setJWTMiddleware(server, cfg)
if err != nil { if err != nil {