From f1db1eeca3083188594c3a91048b22cb9647a677 Mon Sep 17 00:00:00 2001 From: Ryan Oberlander Date: Tue, 12 Jul 2022 12:35:22 -0500 Subject: [PATCH 01/32] start defining update application role API [#516] --- core/apis.go | 4 ++ core/app_administration.go | 4 ++ core/interfaces.go | 1 + driver/web/adapter.go | 1 + driver/web/apis_admin.go | 35 +++++++++++++++- driver/web/authorization_admin_policy.csv | 1 + driver/web/docs/gen/def.yaml | 41 ++++++++++++++++++- driver/web/docs/gen/gen_types.go | 22 ++++++---- .../resources/admin/application/rolesID.yaml | 39 +++++++++++++++++- driver/web/docs/schemas/index.yaml | 2 +- 10 files changed, 137 insertions(+), 13 deletions(-) diff --git a/core/apis.go b/core/apis.go index 85cbd65e4..a65094dad 100644 --- a/core/apis.go +++ b/core/apis.go @@ -343,6 +343,10 @@ func (s *administrationImpl) AdmDeleteAppOrgRole(ID string, appID string, orgID return s.app.admDeleteAppOrgRole(ID, appID, orgID, assignerPermissions, system, l) } +func (s *administrationImpl) AdmUpdateAppOrgRole(ID string, name string, description string, permissionNames []string, appID string, orgID string, assignerPermissions []string, system bool, l *logs.Log) (*model.AppOrgRole, error) { + return s.app.admUpdateAppOrgRole(ID, name, description, permissionNames, appID, orgID, assignerPermissions, system, l) +} + func (s *administrationImpl) AdmGrantPermissionsToRole(appID string, orgID string, roleID string, permissionNames []string, assignerPermissions []string, system bool, l *logs.Log) error { return s.app.admGrantPermissionsToRole(appID, orgID, roleID, permissionNames, assignerPermissions, system, l) } diff --git a/core/app_administration.go b/core/app_administration.go index cacc477ae..fab8b49fb 100644 --- a/core/app_administration.go +++ b/core/app_administration.go @@ -473,6 +473,10 @@ func (app *application) admGetAppOrgRoles(appID string, orgID string) ([]model.A return getAppOrgRoles, nil } +func (app *application) admUpdateAppOrgRole(ID string, name string, description string, permissionNames []string, appID string, orgID string, assignerPermissions []string, system bool, l *logs.Log) (*model.AppOrgRole, error) { + return nil, errors.New(logutils.Unimplemented) +} + func (app *application) admDeleteAppOrgRole(ID string, appID string, orgID string, assignerPermissions []string, system bool, l *logs.Log) error { //1. get application organization entity appOrg, err := app.storage.FindApplicationOrganization(appID, orgID) diff --git a/core/interfaces.go b/core/interfaces.go index f9b1b2b1a..1992203bd 100644 --- a/core/interfaces.go +++ b/core/interfaces.go @@ -54,6 +54,7 @@ type Administration interface { AdmCreateAppOrgRole(name string, description string, permissionNames []string, appID string, orgID string, assignerPermissions []string, system bool, l *logs.Log) (*model.AppOrgRole, error) AdmGetAppOrgRoles(appID string, orgID string) ([]model.AppOrgRole, error) + AdmUpdateAppOrgRole(ID string, name string, description string, permissionNames []string, appID string, orgID string, assignerPermissions []string, system bool, l *logs.Log) (*model.AppOrgRole, error) AdmGrantPermissionsToRole(appID string, orgID string, roleID string, permissionNames []string, assignerPermissions []string, system bool, l *logs.Log) error AdmDeleteAppOrgRole(ID string, appID string, orgID string, assignerPermissions []string, system bool, l *logs.Log) error diff --git a/driver/web/adapter.go b/driver/web/adapter.go index f580c04ed..fef7c1fab 100644 --- a/driver/web/adapter.go +++ b/driver/web/adapter.go @@ -155,6 +155,7 @@ func (we Adapter) Start() { adminSubrouter.HandleFunc("/application/roles", we.wrapFunc(we.adminApisHandler.getApplicationRoles, we.auth.admin.permissions)).Methods("GET") adminSubrouter.HandleFunc("/application/roles", we.wrapFunc(we.adminApisHandler.createApplicationRole, we.auth.admin.permissions)).Methods("POST") adminSubrouter.HandleFunc("/application/roles/{id}", we.wrapFunc(we.adminApisHandler.deleteApplicationRole, we.auth.admin.permissions)).Methods("DELETE") + adminSubrouter.HandleFunc("/application/roles/{id}", we.wrapFunc(we.adminApisHandler.updateApplicationRole, we.auth.admin.permissions)).Methods("PUT") adminSubrouter.HandleFunc("/application/roles/{id}/permissions", we.wrapFunc(we.adminApisHandler.grantPermissionsToRole, we.auth.admin.permissions)).Methods("PUT") adminSubrouter.HandleFunc("/application/permissions", we.wrapFunc(we.adminApisHandler.getApplicationPermissions, we.auth.admin.permissions)).Methods("GET") diff --git a/driver/web/apis_admin.go b/driver/web/apis_admin.go index 9a10c3ba4..2f3ae74f5 100644 --- a/driver/web/apis_admin.go +++ b/driver/web/apis_admin.go @@ -783,7 +783,7 @@ func (h AdminApisHandler) createApplicationRole(l *logs.Log, r *http.Request, cl return l.HttpResponseErrorAction(logutils.ActionRead, logutils.TypeRequestBody, nil, err, http.StatusBadRequest, false) } - var requestData Def.AdminReqCreateApplicationRole + var requestData Def.AdminReqApplicationRole err = json.Unmarshal(data, &requestData) if err != nil { return l.HttpResponseErrorAction(logutils.ActionUnmarshal, model.TypeAppOrgRole, nil, err, http.StatusBadRequest, true) @@ -804,6 +804,39 @@ func (h AdminApisHandler) createApplicationRole(l *logs.Log, r *http.Request, cl return l.HttpResponseSuccessJSON(response) } +func (h AdminApisHandler) updateApplicationRole(l *logs.Log, r *http.Request, claims *tokenauth.Claims) logs.HttpResponse { + params := mux.Vars(r) + rolesID := params["id"] + if len(rolesID) <= 0 { + return l.HttpResponseErrorData(logutils.StatusMissing, logutils.TypeQueryParam, logutils.StringArgs("id"), nil, http.StatusBadRequest, false) + } + + data, err := ioutil.ReadAll(r.Body) + if err != nil { + return l.HttpResponseErrorAction(logutils.ActionRead, logutils.TypeRequestBody, nil, err, http.StatusBadRequest, false) + } + + var requestData Def.AdminReqApplicationRole + err = json.Unmarshal(data, &requestData) + if err != nil { + return l.HttpResponseErrorAction(logutils.ActionUnmarshal, model.TypeAppOrgRole, nil, err, http.StatusBadRequest, true) + } + + assignerPermissions := strings.Split(claims.Permissions, ",") + role, err := h.coreAPIs.Administration.AdmUpdateAppOrgRole(rolesID, requestData.Name, requestData.Description, requestData.Permissions, claims.AppID, claims.OrgID, assignerPermissions, claims.System, l) + if err != nil || role == nil { + return l.HttpResponseErrorAction(logutils.ActionGet, model.TypeAppOrgRole, nil, err, http.StatusInternalServerError, true) + } + + respRole := appOrgRoleToDef(*role) + response, err := json.Marshal(respRole) + if err != nil { + return l.HttpResponseErrorAction(logutils.ActionMarshal, model.TypeAppOrgRole, nil, err, http.StatusInternalServerError, false) + } + + return l.HttpResponseSuccessJSON(response) +} + func (h AdminApisHandler) deleteApplicationRole(l *logs.Log, r *http.Request, claims *tokenauth.Claims) logs.HttpResponse { params := mux.Vars(r) rolesID := params["id"] diff --git a/driver/web/authorization_admin_policy.csv b/driver/web/authorization_admin_policy.csv index 56f87d8b5..d66bd5850 100644 --- a/driver/web/authorization_admin_policy.csv +++ b/driver/web/authorization_admin_policy.csv @@ -22,6 +22,7 @@ p, all_auth-roles, /core/admin/application/roles/*, (GET)|(POST)|(PUT)|(DELETE) p, all_auth-roles, /core/admin/application/roles/*/permissions, (PUT) p, get_auth-roles, /core/admin/application/roles, (GET) p, update_auth-roles, /core/admin/application/roles, (GET)|(POST)|(PUT) +p, update_auth-roles, /core/admin/application/roles/*, (PUT) p, update_auth-roles, /core/admin/application/roles/*/permissions, (PUT) p, delete_auth-roles, /core/admin/application/roles/*, (DELETE) p, delete_auth-roles, /core/admin/application/roles, (GET) diff --git a/driver/web/docs/gen/def.yaml b/driver/web/docs/gen/def.yaml index 5c67f1263..798aca415 100644 --- a/driver/web/docs/gen/def.yaml +++ b/driver/web/docs/gen/def.yaml @@ -2497,7 +2497,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/_admin_req_create-application_role' + $ref: '#/components/schemas/_admin_req_application_role' required: true responses: '200': @@ -2513,6 +2513,43 @@ paths: '500': description: Internal error '/admin/application/roles/{id}': + put: + tags: + - Admin + summary: Update application role + description: | + Update application role + + **Auth:** Requires admin access token with `update_auth-roles` or `all_auth-roles` permission + security: + - bearerAuth: [] + parameters: + - name: id + in: path + description: The role ID + required: true + schema: + type: string + requestBody: + description: Application role + content: + application/json: + schema: + $ref: '#/components/schemas/_admin_req_application_role' + required: true + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/AppOrgRole' + '400': + description: Bad request + '401': + description: Unauthorized + '500': + description: Internal error delete: tags: - Admin @@ -5964,7 +6001,7 @@ components: properties: token: type: string - _admin_req_create-application_role: + _admin_req_application_role: required: - name - description diff --git a/driver/web/docs/gen/gen_types.go b/driver/web/docs/gen/gen_types.go index 61606de26..2468e9ee7 100644 --- a/driver/web/docs/gen/gen_types.go +++ b/driver/web/docs/gen/gen_types.go @@ -600,6 +600,13 @@ type AdminReqAddAccountsToGroup struct { AccountIds []string `json:"account_ids"` } +// AdminReqApplicationRole defines model for _admin_req_application_role. +type AdminReqApplicationRole struct { + Description string `json:"description"` + Name string `json:"name"` + Permissions []string `json:"permissions"` +} + // AdminReqCreateApplicationGroup defines model for _admin_req_create-application_group. type AdminReqCreateApplicationGroup struct { Name string `json:"name"` @@ -607,13 +614,6 @@ type AdminReqCreateApplicationGroup struct { Roles *[]string `json:"roles,omitempty"` } -// AdminReqCreateApplicationRole defines model for _admin_req_create-application_role. -type AdminReqCreateApplicationRole struct { - Description string `json:"description"` - Name string `json:"name"` - Permissions []string `json:"permissions"` -} - // AdminReqGrantPermissions defines model for _admin_req_grant-permissions. type AdminReqGrantPermissions struct { Permissions []string `json:"permissions"` @@ -1279,7 +1279,10 @@ type GetAdminApplicationLoginSessionsParams struct { } // PostAdminApplicationRolesJSONBody defines parameters for PostAdminApplicationRoles. -type PostAdminApplicationRolesJSONBody AdminReqCreateApplicationRole +type PostAdminApplicationRolesJSONBody AdminReqApplicationRole + +// PutAdminApplicationRolesIdJSONBody defines parameters for PutAdminApplicationRolesId. +type PutAdminApplicationRolesIdJSONBody AdminReqApplicationRole // PutAdminApplicationRolesIdPermissionsJSONBody defines parameters for PutAdminApplicationRolesIdPermissions. type PutAdminApplicationRolesIdPermissionsJSONBody AdminReqGrantPermissionsToRole @@ -1695,6 +1698,9 @@ type PutAdminApplicationGroupsIdAccountsJSONRequestBody PutAdminApplicationGroup // PostAdminApplicationRolesJSONRequestBody defines body for PostAdminApplicationRoles for application/json ContentType. type PostAdminApplicationRolesJSONRequestBody PostAdminApplicationRolesJSONBody +// PutAdminApplicationRolesIdJSONRequestBody defines body for PutAdminApplicationRolesId for application/json ContentType. +type PutAdminApplicationRolesIdJSONRequestBody PutAdminApplicationRolesIdJSONBody + // PutAdminApplicationRolesIdPermissionsJSONRequestBody defines body for PutAdminApplicationRolesIdPermissions for application/json ContentType. type PutAdminApplicationRolesIdPermissionsJSONRequestBody PutAdminApplicationRolesIdPermissionsJSONBody diff --git a/driver/web/docs/resources/admin/application/rolesID.yaml b/driver/web/docs/resources/admin/application/rolesID.yaml index 1e5123349..6eaded077 100644 --- a/driver/web/docs/resources/admin/application/rolesID.yaml +++ b/driver/web/docs/resources/admin/application/rolesID.yaml @@ -1,4 +1,41 @@ - delete: +put: + tags: + - Admin + summary: Update application role + description: | + Update application role + + **Auth:** Requires admin access token with `update_auth-roles` or `all_auth-roles` permission + security: + - bearerAuth: [] + parameters: + - name: id + in: path + description: The role ID + required: true + schema: + type: string + requestBody: + description: Application role + content: + application/json: + schema: + $ref: "../../../schemas/apis/admin/application/roles/request/Request.yaml" + required: true + responses: + 200: + description: Success + content: + application/json: + schema: + $ref: "../../../schemas/application/AppOrgRole.yaml" + 400: + description: Bad request + 401: + description: Unauthorized + 500: + description: Internal error +delete: tags: - Admin summary: Delete application role diff --git a/driver/web/docs/schemas/index.yaml b/driver/web/docs/schemas/index.yaml index 574ea351c..80b389677 100644 --- a/driver/web/docs/schemas/index.yaml +++ b/driver/web/docs/schemas/index.yaml @@ -210,7 +210,7 @@ _admin_res_app-token: $ref: "./apis/admin/app-token/response/Response.yaml" ### admin application_roles API -_admin_req_create-application_role: +_admin_req_application_role: $ref: "./apis/admin/application/roles/request/Request.yaml" ### admin application_groups API From 931a556ad5a1ccd9079d5f272509544a40d87887 Mon Sep 17 00:00:00 2001 From: Ryan Oberlander Date: Tue, 12 Jul 2022 17:42:53 -0500 Subject: [PATCH 02/32] finish implementing update application role API, testing incomplete [#516] --- core/app_administration.go | 44 +++++++++++++++++- core/interfaces.go | 2 +- core/mocks/Storage.go | 10 ++--- driven/storage/adapter.go | 92 ++++++++++++++++++++++++++++++++------ driver/web/apis_admin.go | 2 +- 5 files changed, 129 insertions(+), 21 deletions(-) diff --git a/core/app_administration.go b/core/app_administration.go index fab8b49fb..25b0d7381 100644 --- a/core/app_administration.go +++ b/core/app_administration.go @@ -474,7 +474,49 @@ func (app *application) admGetAppOrgRoles(appID string, orgID string) ([]model.A } func (app *application) admUpdateAppOrgRole(ID string, name string, description string, permissionNames []string, appID string, orgID string, assignerPermissions []string, system bool, l *logs.Log) (*model.AppOrgRole, error) { - return nil, errors.New(logutils.Unimplemented) + var updatedRole *model.AppOrgRole + transaction := func(context storage.TransactionContext) error { + //1. find application organization + appOrg, err := app.storage.FindApplicationOrganization(appID, orgID) + if err != nil || appOrg == nil { + return errors.WrapErrorAction(logutils.ActionGet, model.TypeApplicationOrganization, nil, err) + } + + //2. find role, check if update allowed by system flag + role, err := app.storage.FindAppOrgRole(ID, appOrg.ID) + if err != nil { + return errors.WrapErrorAction(logutils.ActionFind, model.TypeAppOrgRole, nil, err) + } + if role.System && !system { + return errors.ErrorData(logutils.StatusInvalid, logutils.TypeClaim, logutils.StringArgs("system")) + } + + //3. check role permissions + permissions, err := app.auth.CheckPermissions(context, appOrg, permissionNames, assignerPermissions) + if err != nil { + return errors.WrapErrorAction(logutils.ActionValidate, model.TypePermission, nil, err) + } + + //4. update role (also updates all necessary groups and accounts) + now := time.Now().UTC() + role.Name = name + role.Description = description + role.Permissions = permissions + role.DateUpdated = &now + err = app.storage.UpdateAppOrgRole(context, *role) + if err != nil { + return errors.WrapErrorAction(logutils.ActionUpdate, model.TypeAppOrgRole, nil, err) + } + + updatedRole = role + return nil + } + + err := app.storage.PerformTransaction(transaction) + if err != nil { + return nil, err + } + return updatedRole, nil } func (app *application) admDeleteAppOrgRole(ID string, appID string, orgID string, assignerPermissions []string, system bool, l *logs.Log) error { diff --git a/core/interfaces.go b/core/interfaces.go index 1992203bd..0060cf0c5 100644 --- a/core/interfaces.go +++ b/core/interfaces.go @@ -163,7 +163,7 @@ type Storage interface { FindAppOrgRolesByIDs(context storage.TransactionContext, ids []string, appOrgID string) ([]model.AppOrgRole, error) FindAppOrgRole(id string, appOrgID string) (*model.AppOrgRole, error) InsertAppOrgRole(context storage.TransactionContext, item model.AppOrgRole) error - UpdateAppOrgRole(item model.AppOrgRole) error + UpdateAppOrgRole(context storage.TransactionContext, item model.AppOrgRole) error DeleteAppOrgRole(id string) error InsertAppOrgRolePermissions(context storage.TransactionContext, roleID string, permissionNames []model.Permission) error diff --git a/core/mocks/Storage.go b/core/mocks/Storage.go index 56dc9d1fc..9a05093dc 100644 --- a/core/mocks/Storage.go +++ b/core/mocks/Storage.go @@ -1161,13 +1161,13 @@ func (_m *Storage) UpdateAppOrgGroup(item model.AppOrgGroup) error { return r0 } -// UpdateAppOrgRole provides a mock function with given fields: item -func (_m *Storage) UpdateAppOrgRole(item model.AppOrgRole) error { - ret := _m.Called(item) +// UpdateAppOrgRole provides a mock function with given fields: context, item +func (_m *Storage) UpdateAppOrgRole(context storage.TransactionContext, item model.AppOrgRole) error { + ret := _m.Called(context, item) var r0 error - if rf, ok := ret.Get(0).(func(model.AppOrgRole) error); ok { - r0 = rf(item) + if rf, ok := ret.Get(0).(func(storage.TransactionContext, model.AppOrgRole) error); ok { + r0 = rf(context, item) } else { r0 = ret.Error(0) } diff --git a/driven/storage/adapter.go b/driven/storage/adapter.go index bbc438139..bb8c7a734 100644 --- a/driven/storage/adapter.go +++ b/driven/storage/adapter.go @@ -2522,15 +2522,8 @@ func (sa *Adapter) FindAppOrgRole(id string, appOrgID string) (*model.AppOrgRole //InsertAppOrgRole inserts a new application organization role func (sa *Adapter) InsertAppOrgRole(context TransactionContext, item model.AppOrgRole) error { - appOrg, err := sa.getCachedApplicationOrganizationByKey(item.AppOrg.ID) - if err != nil { - return errors.WrapErrorData(logutils.StatusMissing, model.TypeApplicationOrganization, &logutils.FieldArgs{"app_org_id": item.AppOrg.ID}, err) - } - if appOrg == nil { - return errors.ErrorData(logutils.StatusMissing, model.TypeApplicationOrganization, &logutils.FieldArgs{"app_org_id": item.AppOrg.ID}) - } - role := appOrgRoleToStorage(item) + var err error if context != nil { _, err = sa.db.applicationsOrganizationsRoles.InsertOneWithContext(context, role) } else { @@ -2543,11 +2536,84 @@ func (sa *Adapter) InsertAppOrgRole(context TransactionContext, item model.AppOr } //UpdateAppOrgRole updates application organization role -func (sa *Adapter) UpdateAppOrgRole(item model.AppOrgRole) error { - //TODO - //This will be slow operation as we keep a copy of the entity in the users collection without index. - //Maybe we need to up the transaction timeout for this operation because of this. - return errors.New(logutils.Unimplemented) +func (sa *Adapter) UpdateAppOrgRole(context TransactionContext, item model.AppOrgRole) error { + //TODO: when is updating system flag allowed? + filter := bson.D{primitive.E{Key: "_id", Value: item.ID}} + + roleUpdate := bson.D{ + primitive.E{Key: "$set", Value: bson.D{ + primitive.E{Key: "name", Value: item.Name}, + primitive.E{Key: "description", Value: item.Description}, + primitive.E{Key: "permissions", Value: item.Permissions}, + primitive.E{Key: "system", Value: item.System}, + primitive.E{Key: "date_updated", Value: item.DateUpdated}, + }}, + } + + var res *mongo.UpdateResult + var err error + if context != nil { + res, err = sa.db.applicationsOrganizationsRoles.UpdateOneWithContext(context, filter, roleUpdate, nil) + } else { + res, err = sa.db.applicationsOrganizationsRoles.UpdateOne(filter, roleUpdate, nil) + } + if err != nil { + return errors.WrapErrorAction(logutils.ActionUpdate, model.TypeAppOrgRole, &logutils.FieldArgs{"id": item.ID}, err) + } + + if res.ModifiedCount != 1 { + return errors.ErrorAction(logutils.ActionUpdate, model.TypeAppOrgRole, &logutils.FieldArgs{"id": item.ID, "modified": res.ModifiedCount, "expected": 1}) + } + + groupsFilter := bson.D{primitive.E{Key: "roles._id", Value: item.ID}} + groupsUpdate := bson.D{ + primitive.E{Key: "$set", Value: bson.D{ + primitive.E{Key: "roles.$.name", Value: item.Name}, + primitive.E{Key: "roles.$.description", Value: item.Description}, + primitive.E{Key: "roles.$.permissions", Value: item.Permissions}, + primitive.E{Key: "roles.$.system", Value: item.System}, + primitive.E{Key: "roles.$.date_updated", Value: item.DateUpdated}, + }}, + } + + if context != nil { + res, err = sa.db.applicationsOrganizationsGroups.UpdateManyWithContext(context, groupsFilter, groupsUpdate, nil) + } else { + res, err = sa.db.applicationsOrganizationsGroups.UpdateMany(groupsFilter, groupsUpdate, nil) + } + if err != nil { + return errors.WrapErrorAction(logutils.ActionUpdate, model.TypeAppOrgGroup, &logutils.FieldArgs{"roles._id": item.ID}, err) + } + + if res.ModifiedCount != res.MatchedCount { + return errors.ErrorAction(logutils.ActionUpdate, model.TypeAppOrgGroup, &logutils.FieldArgs{"roles._id": item.ID, "modified": res.ModifiedCount, "expected": res.MatchedCount}) + } + + accountsFilter := bson.D{primitive.E{Key: "roles.role._id", Value: item.ID}} + accountsUpdate := bson.D{ + primitive.E{Key: "$set", Value: bson.D{ + primitive.E{Key: "roles.$.role.name", Value: item.Name}, + primitive.E{Key: "roles.$.role.description", Value: item.Description}, + primitive.E{Key: "roles.$.role.permissions", Value: item.Permissions}, + primitive.E{Key: "roles.$.role.system", Value: item.System}, + primitive.E{Key: "roles.$.role.date_updated", Value: item.DateUpdated}, + }}, + } + + if context != nil { + res, err = sa.db.accounts.UpdateManyWithContext(context, accountsFilter, accountsUpdate, nil) + } else { + res, err = sa.db.accounts.UpdateMany(accountsFilter, accountsUpdate, nil) + } + if err != nil { + return errors.WrapErrorAction(logutils.ActionUpdate, model.TypeAccount, &logutils.FieldArgs{"roles.role._id": item.ID}, err) + } + + if res.ModifiedCount != res.MatchedCount { + return errors.ErrorAction(logutils.ActionUpdate, model.TypeAccount, &logutils.FieldArgs{"roles.role._id": item.ID, "modified": res.ModifiedCount, "expected": res.MatchedCount}) + } + + return nil } //DeleteAppOrgRole deletes application organization role diff --git a/driver/web/apis_admin.go b/driver/web/apis_admin.go index 2f3ae74f5..ccdfeb94d 100644 --- a/driver/web/apis_admin.go +++ b/driver/web/apis_admin.go @@ -825,7 +825,7 @@ func (h AdminApisHandler) updateApplicationRole(l *logs.Log, r *http.Request, cl assignerPermissions := strings.Split(claims.Permissions, ",") role, err := h.coreAPIs.Administration.AdmUpdateAppOrgRole(rolesID, requestData.Name, requestData.Description, requestData.Permissions, claims.AppID, claims.OrgID, assignerPermissions, claims.System, l) if err != nil || role == nil { - return l.HttpResponseErrorAction(logutils.ActionGet, model.TypeAppOrgRole, nil, err, http.StatusInternalServerError, true) + return l.HttpResponseErrorAction(logutils.ActionUpdate, model.TypeAppOrgRole, nil, err, http.StatusInternalServerError, true) } respRole := appOrgRoleToDef(*role) From feb704af621df0c4fd9cec332469791d02a10c5b Mon Sep 17 00:00:00 2001 From: Ryan Oberlander Date: Wed, 13 Jul 2022 15:50:43 -0500 Subject: [PATCH 03/32] bug fixes, better code reuse [#516] --- .secrets.baseline | 6 +- core/apis.go | 8 +- core/app_administration.go | 65 ++++++--- core/auth/apis.go | 126 ++++++++---------- core/auth/auth.go | 59 +------- core/auth/interfaces.go | 11 +- core/interfaces.go | 4 +- core/model/application.go | 9 ++ driven/storage/adapter.go | 32 ++--- driver/web/apis_admin.go | 12 +- driver/web/docs/gen/def.yaml | 2 + driver/web/docs/gen/gen_types.go | 1 + .../application/roles/request/Request.yaml | 2 + 13 files changed, 159 insertions(+), 178 deletions(-) diff --git a/.secrets.baseline b/.secrets.baseline index 186f42baf..0c3cb69b9 100644 --- a/.secrets.baseline +++ b/.secrets.baseline @@ -124,7 +124,7 @@ "filename": "core/auth/apis.go", "hashed_secret": "4d55af37dbbb6a42088d917caa1ca25428ec42c9", "is_verified": false, - "line_number": 1918 + "line_number": 1910 } ], "core/auth/auth.go": [ @@ -133,7 +133,7 @@ "filename": "core/auth/auth.go", "hashed_secret": "4d55af37dbbb6a42088d917caa1ca25428ec42c9", "is_verified": false, - "line_number": 2377 + "line_number": 2324 } ], "core/auth/auth_type_email.go": [ @@ -279,5 +279,5 @@ } ] }, - "generated_at": "2022-07-07T03:28:36Z" + "generated_at": "2022-07-13T20:50:37Z" } diff --git a/core/apis.go b/core/apis.go index a65094dad..0699ef51a 100644 --- a/core/apis.go +++ b/core/apis.go @@ -331,8 +331,8 @@ func (s *administrationImpl) AdmRemoveAccountsFromGroup(appID string, orgID stri return s.app.admRemoveAccountsFromGroup(appID, orgID, groupID, accountIDs, assignerPermissions, l) } -func (s *administrationImpl) AdmCreateAppOrgRole(name string, description string, permissionNames []string, appID string, orgID string, assignerPermissions []string, system bool, l *logs.Log) (*model.AppOrgRole, error) { - return s.app.admCreateAppOrgRole(name, description, permissionNames, appID, orgID, assignerPermissions, system, l) +func (s *administrationImpl) AdmCreateAppOrgRole(name string, description string, system bool, permissionNames []string, appID string, orgID string, assignerPermissions []string, systemClaim bool, l *logs.Log) (*model.AppOrgRole, error) { + return s.app.admCreateAppOrgRole(name, description, system, permissionNames, appID, orgID, assignerPermissions, systemClaim, l) } func (s *administrationImpl) AdmGetAppOrgRoles(appID string, orgID string) ([]model.AppOrgRole, error) { @@ -343,8 +343,8 @@ func (s *administrationImpl) AdmDeleteAppOrgRole(ID string, appID string, orgID return s.app.admDeleteAppOrgRole(ID, appID, orgID, assignerPermissions, system, l) } -func (s *administrationImpl) AdmUpdateAppOrgRole(ID string, name string, description string, permissionNames []string, appID string, orgID string, assignerPermissions []string, system bool, l *logs.Log) (*model.AppOrgRole, error) { - return s.app.admUpdateAppOrgRole(ID, name, description, permissionNames, appID, orgID, assignerPermissions, system, l) +func (s *administrationImpl) AdmUpdateAppOrgRole(ID string, name string, description string, system bool, permissionNames []string, appID string, orgID string, assignerPermissions []string, systemClaim bool, l *logs.Log) (*model.AppOrgRole, error) { + return s.app.admUpdateAppOrgRole(ID, name, description, system, permissionNames, appID, orgID, assignerPermissions, systemClaim, l) } func (s *administrationImpl) AdmGrantPermissionsToRole(appID string, orgID string, roleID string, permissionNames []string, assignerPermissions []string, system bool, l *logs.Log) error { diff --git a/core/app_administration.go b/core/app_administration.go index 25b0d7381..ff8128c52 100644 --- a/core/app_administration.go +++ b/core/app_administration.go @@ -208,13 +208,13 @@ func (app *application) admCreateAppOrgGroup(name string, permissionNames []stri } //2. validate permissions - permissions, err := app.auth.CheckPermissions(context, appOrg, permissionNames, assignerPermissions) + permissions, err := app.auth.CheckPermissions(context, appOrg, permissionNames, assignerPermissions, false) if err != nil { return errors.WrapErrorAction(logutils.ActionValidate, model.TypePermission, nil, err) } //3. check roles - roles, err := app.auth.CheckRoles(context, appOrg, rolesIDs, assignerPermissions) + roles, err := app.auth.CheckRoles(context, appOrg, rolesIDs, assignerPermissions, false) if err != nil { return errors.WrapErrorAction(logutils.ActionValidate, model.TypeAppOrgRole, nil, err) } @@ -421,7 +421,7 @@ func (app *application) admRemoveAccountsFromGroup(appID string, orgID string, g return nil } -func (app *application) admCreateAppOrgRole(name string, description string, permissionNames []string, appID string, orgID string, assignerPermissions []string, system bool, l *logs.Log) (*model.AppOrgRole, error) { +func (app *application) admCreateAppOrgRole(name string, description string, system bool, permissionNames []string, appID string, orgID string, assignerPermissions []string, systemClaim bool, l *logs.Log) (*model.AppOrgRole, error) { var newRole *model.AppOrgRole transaction := func(context storage.TransactionContext) error { //1. get application organization entity @@ -431,7 +431,7 @@ func (app *application) admCreateAppOrgRole(name string, description string, per } //2. check role permissions - permissions, err := app.auth.CheckPermissions(context, appOrg, permissionNames, assignerPermissions) + permissions, err := app.auth.CheckPermissions(context, appOrg, permissionNames, assignerPermissions, false) if err != nil { return errors.WrapErrorAction(logutils.ActionValidate, model.TypePermission, nil, err) } @@ -439,7 +439,7 @@ func (app *application) admCreateAppOrgRole(name string, description string, per //3. create and insert role id, _ := uuid.NewUUID() now := time.Now() - role := model.AppOrgRole{ID: id.String(), Name: name, Description: description, System: system, Permissions: permissions, AppOrg: *appOrg, DateCreated: now} + role := model.AppOrgRole{ID: id.String(), Name: name, Description: description, System: systemClaim && system, Permissions: permissions, AppOrg: *appOrg, DateCreated: now} err = app.storage.InsertAppOrgRole(context, role) if err != nil { return errors.WrapErrorAction(logutils.ActionInsert, model.TypeAppOrgRole, nil, err) @@ -473,7 +473,7 @@ func (app *application) admGetAppOrgRoles(appID string, orgID string) ([]model.A return getAppOrgRoles, nil } -func (app *application) admUpdateAppOrgRole(ID string, name string, description string, permissionNames []string, appID string, orgID string, assignerPermissions []string, system bool, l *logs.Log) (*model.AppOrgRole, error) { +func (app *application) admUpdateAppOrgRole(ID string, name string, description string, system bool, permissionNames []string, appID string, orgID string, assignerPermissions []string, systemClaim bool, l *logs.Log) (*model.AppOrgRole, error) { var updatedRole *model.AppOrgRole transaction := func(context storage.TransactionContext) error { //1. find application organization @@ -487,25 +487,54 @@ func (app *application) admUpdateAppOrgRole(ID string, name string, description if err != nil { return errors.WrapErrorAction(logutils.ActionFind, model.TypeAppOrgRole, nil, err) } - if role.System && !system { + if role.System && !systemClaim { return errors.ErrorData(logutils.StatusInvalid, logutils.TypeClaim, logutils.StringArgs("system")) } //3. check role permissions - permissions, err := app.auth.CheckPermissions(context, appOrg, permissionNames, assignerPermissions) - if err != nil { - return errors.WrapErrorAction(logutils.ActionValidate, model.TypePermission, nil, err) + updated := false + newPermissions := []model.Permission{} + added, removed, unchanged := utils.StringListDiff(permissionNames, role.GetAssignedPermissionNames()) + if len(added) > 0 || len(removed) > 0 { + if len(added) > 0 { + addedPermissions, err := app.auth.CheckPermissions(context, appOrg, added, assignerPermissions, false) + if err != nil { + return errors.WrapErrorAction("adding", model.TypePermission, nil, err) + } + newPermissions = append(newPermissions, addedPermissions...) + } + + if len(removed) > 0 { + _, err := app.auth.CheckPermissions(context, appOrg, removed, assignerPermissions, true) + if err != nil { + return errors.WrapErrorAction("revoking", model.TypePermission, nil, err) + } + } + + if len(unchanged) > 0 { + unchangedPermissions, err := app.storage.FindPermissionsByName(context, unchanged) + if err != nil { + return errors.WrapErrorAction(logutils.ActionFind, model.TypePermission, nil, err) + } + newPermissions = append(newPermissions, unchangedPermissions...) + } + + role.Permissions = newPermissions + updated = true } //4. update role (also updates all necessary groups and accounts) - now := time.Now().UTC() - role.Name = name - role.Description = description - role.Permissions = permissions - role.DateUpdated = &now - err = app.storage.UpdateAppOrgRole(context, *role) - if err != nil { - return errors.WrapErrorAction(logutils.ActionUpdate, model.TypeAppOrgRole, nil, err) + updated = updated || (role.Name != name) || (role.Description != description) || (role.System != (systemClaim && system)) + if updated { + now := time.Now().UTC() + role.Name = name + role.Description = description + role.System = systemClaim && system + role.DateUpdated = &now + err = app.storage.UpdateAppOrgRole(context, *role) + if err != nil { + return errors.WrapErrorAction(logutils.ActionUpdate, model.TypeAppOrgRole, nil, err) + } } updatedRole = role diff --git a/core/auth/apis.go b/core/auth/apis.go index 371b6340f..2bbe693cd 100644 --- a/core/auth/apis.go +++ b/core/auth/apis.go @@ -654,7 +654,7 @@ func (a *Auth) UpdateAdminAccount(authenticationType string, appID string, orgID if len(added) > 0 || len(removed) > 0 { newPermissions := []model.Permission{} if len(added) > 0 { - addedPermissions, err := a.CheckPermissions(context, appOrg, added, updaterPermissions) + addedPermissions, err := a.CheckPermissions(context, appOrg, added, updaterPermissions, false) if err != nil { return errors.WrapErrorAction("adding", model.TypePermission, nil, err) } @@ -662,7 +662,7 @@ func (a *Auth) UpdateAdminAccount(authenticationType string, appID string, orgID } if len(removed) > 0 { - err := a.CheckRevokedPermissions(context, appOrg, removed, updaterPermissions) + _, err := a.CheckPermissions(context, appOrg, removed, updaterPermissions, true) if err != nil { return errors.WrapErrorAction("revoking", model.TypePermission, nil, err) } @@ -693,7 +693,7 @@ func (a *Auth) UpdateAdminAccount(authenticationType string, appID string, orgID if len(added) > 0 || len(removed) > 0 { newRoles := []model.AppOrgRole{} if len(added) > 0 { - addedRoles, err := a.CheckRoles(context, appOrg, added, updaterPermissions) + addedRoles, err := a.CheckRoles(context, appOrg, added, updaterPermissions, false) if err != nil { return errors.WrapErrorAction("adding", model.TypeAccountRoles, nil, err) } @@ -701,7 +701,7 @@ func (a *Auth) UpdateAdminAccount(authenticationType string, appID string, orgID } if len(removed) > 0 { - err := a.CheckRevokedRoles(context, appOrg, removed, updaterPermissions) + _, err := a.CheckRoles(context, appOrg, removed, updaterPermissions, true) if err != nil { return errors.WrapErrorAction("revoking", model.TypeAccountRoles, nil, err) } @@ -733,7 +733,7 @@ func (a *Auth) UpdateAdminAccount(authenticationType string, appID string, orgID if len(added) > 0 || len(removed) > 0 { newGroups := []model.AppOrgGroup{} if len(added) > 0 { - addedGroups, err := a.checkGroups(context, *appOrg, added, updaterPermissions) + addedGroups, err := a.CheckGroups(context, appOrg, added, updaterPermissions, false) if err != nil { return errors.WrapErrorAction("adding", model.TypeAccountGroups, nil, err) } @@ -741,7 +741,7 @@ func (a *Auth) UpdateAdminAccount(authenticationType string, appID string, orgID } if len(removed) > 0 { - err := a.checkRevokedGroups(context, *appOrg, removed, updaterPermissions) + _, err := a.CheckGroups(context, appOrg, removed, updaterPermissions, true) if err != nil { return errors.WrapErrorAction("revoking", model.TypeAccountGroups, nil, err) } @@ -1634,7 +1634,7 @@ func (a *Auth) GrantAccountPermissions(context storage.TransactionContext, accou } //check permissions - permissions, err := a.CheckPermissions(context, &account.AppOrg, newPermissions, assignerPermissions) + permissions, err := a.CheckPermissions(context, &account.AppOrg, newPermissions, assignerPermissions, false) if err != nil { return errors.WrapErrorAction(logutils.ActionValidate, model.TypePermission, nil, err) } @@ -1649,8 +1649,8 @@ func (a *Auth) GrantAccountPermissions(context storage.TransactionContext, accou return nil } -//CheckPermissions loads permissions by names from storage and checks that they are assignable and valid for the given appOrg -func (a *Auth) CheckPermissions(context storage.TransactionContext, appOrg *model.ApplicationOrganization, permissionNames []string, assignerPermissions []string) ([]model.Permission, error) { +//CheckPermissions loads permissions by names from storage and checks that they are assignable and valid for the given appOrg or revocable +func (a *Auth) CheckPermissions(context storage.TransactionContext, appOrg *model.ApplicationOrganization, permissionNames []string, assignerPermissions []string, revoke bool) ([]model.Permission, error) { if appOrg == nil { return nil, errors.ErrorData(logutils.StatusInvalid, model.TypeApplicationOrganization, nil) } @@ -1660,7 +1660,8 @@ func (a *Auth) CheckPermissions(context storage.TransactionContext, appOrg *mode if err != nil { return nil, errors.WrapErrorAction(logutils.ActionFind, model.TypePermission, nil, err) } - if len(permissions) != len(permissionNames) { + //Allow revocation of missing permissions + if len(permissions) != len(permissionNames) && !revoke { badNames := make([]string, 0) for _, pName := range permissionNames { bad := true @@ -1680,6 +1681,10 @@ func (a *Auth) CheckPermissions(context storage.TransactionContext, appOrg *mode //check if authorized for _, permission := range permissions { if !utils.Contains(appOrg.ServicesIDs, permission.ServiceID) { + //Allow revocation of permissions for invalid services + if revoke { + continue + } return nil, errors.ErrorData(logutils.StatusInvalid, model.TypePermission, &logutils.FieldArgs{"name": permission.Name, "service_id": permission.ServiceID}) } err = permission.CheckAssigners(assignerPermissions) @@ -1691,34 +1696,6 @@ func (a *Auth) CheckPermissions(context storage.TransactionContext, appOrg *mode return permissions, nil } -//CheckRevokedPermissions loads permissions by names from storage and checks that they are revokable -func (a *Auth) CheckRevokedPermissions(context storage.TransactionContext, appOrg *model.ApplicationOrganization, permissionNames []string, assignerPermissions []string) error { - if appOrg == nil { - return errors.ErrorData(logutils.StatusInvalid, model.TypeApplicationOrganization, nil) - } - - //find permissions - permissions, err := a.storage.FindPermissionsByName(context, permissionNames) - if err != nil { - return errors.WrapErrorAction(logutils.ActionFind, model.TypePermission, nil, err) - } - //Allow revocation of missing permissions - - //check if authorized - for _, permission := range permissions { - //Allow revocation of permissions for invalid services - if !utils.Contains(appOrg.ServicesIDs, permission.ServiceID) { - continue - } - err = permission.CheckAssigners(assignerPermissions) - if err != nil { - return errors.WrapErrorAction(logutils.ActionValidate, "assigner permissions", &logutils.FieldArgs{"name": permission.Name}, err) - } - } - - return nil -} - //GrantAccountRoles grants new roles to an account after validating the assigner has required permissions func (a *Auth) GrantAccountRoles(context storage.TransactionContext, account *model.Account, roleIDs []string, assignerPermissions []string) error { //check if there is data @@ -1739,7 +1716,7 @@ func (a *Auth) GrantAccountRoles(context storage.TransactionContext, account *mo } //check roles - roles, err := a.CheckRoles(context, &account.AppOrg, newRoles, assignerPermissions) + roles, err := a.CheckRoles(context, &account.AppOrg, newRoles, assignerPermissions, false) if err != nil { return errors.WrapErrorAction(logutils.ActionValidate, model.TypeAppOrgRole, nil, err) } @@ -1755,8 +1732,8 @@ func (a *Auth) GrantAccountRoles(context storage.TransactionContext, account *mo return nil } -//CheckRoles loads appOrg roles by IDs from storage and checks that they are assignable -func (a *Auth) CheckRoles(context storage.TransactionContext, appOrg *model.ApplicationOrganization, roleIDs []string, assignerPermissions []string) ([]model.AppOrgRole, error) { +//CheckRoles loads appOrg roles by IDs from storage and checks that they are assignable or revocable +func (a *Auth) CheckRoles(context storage.TransactionContext, appOrg *model.ApplicationOrganization, roleIDs []string, assignerPermissions []string, revoke bool) ([]model.AppOrgRole, error) { if appOrg == nil { return nil, errors.ErrorData(logutils.StatusInvalid, model.TypeApplicationOrganization, nil) } @@ -1766,7 +1743,7 @@ func (a *Auth) CheckRoles(context storage.TransactionContext, appOrg *model.Appl if err != nil { return nil, errors.WrapErrorAction(logutils.ActionFind, model.TypeAppOrgRole, nil, err) } - if len(roles) != len(roleIDs) { + if len(roles) != len(roleIDs) && !revoke { badIDs := make([]string, 0) for _, rID := range roleIDs { bad := true @@ -1794,30 +1771,6 @@ func (a *Auth) CheckRoles(context storage.TransactionContext, appOrg *model.Appl return roles, nil } -//CheckRevokedRoles loads appOrg roles by IDs from storage and checks that they are revocable -func (a *Auth) CheckRevokedRoles(context storage.TransactionContext, appOrg *model.ApplicationOrganization, roleIDs []string, assignerPermissions []string) error { - if appOrg == nil { - return errors.ErrorData(logutils.StatusInvalid, model.TypeApplicationOrganization, nil) - } - - //find roles - roles, err := a.storage.FindAppOrgRolesByIDs(context, roleIDs, appOrg.ID) - if err != nil { - return errors.WrapErrorAction(logutils.ActionFind, model.TypeAppOrgRole, nil, err) - } - //Allow missing roles to be revoked - - //check if authorized - for _, cRole := range roles { - err = cRole.CheckAssigners(assignerPermissions) - if err != nil { - return errors.WrapErrorAction(logutils.ActionValidate, "assigner permissions", &logutils.FieldArgs{"id": cRole.ID}, err) - } - } - - return nil -} - //GrantAccountGroups grants new groups to an account after validating the assigner has required permissions func (a *Auth) GrantAccountGroups(context storage.TransactionContext, account *model.Account, groupIDs []string, assignerPermissions []string) error { //check if there is data @@ -1838,7 +1791,7 @@ func (a *Auth) GrantAccountGroups(context storage.TransactionContext, account *m } //check groups - groups, err := a.checkGroups(context, account.AppOrg, newGroups, assignerPermissions) + groups, err := a.CheckGroups(context, &account.AppOrg, newGroups, assignerPermissions, false) if err != nil { return errors.WrapErrorAction(logutils.ActionValidate, model.TypeAppOrgGroup, nil, err) } @@ -1854,6 +1807,45 @@ func (a *Auth) GrantAccountGroups(context storage.TransactionContext, account *m return nil } +//CheckGroups loads appOrg groups by IDs from storage and checks that they are assignable or revocable +func (a *Auth) CheckGroups(context storage.TransactionContext, appOrg *model.ApplicationOrganization, groupIDs []string, assignerPermissions []string, revoke bool) ([]model.AppOrgGroup, error) { + if appOrg == nil { + return nil, errors.ErrorData(logutils.StatusInvalid, model.TypeApplicationOrganization, nil) + } + + //find groups + groups, err := a.storage.FindAppOrgGroupsByIDs(context, groupIDs, appOrg.ID) + if err != nil { + return nil, errors.WrapErrorAction(logutils.ActionFind, model.TypeAppOrgGroup, nil, err) + } + if len(groups) != len(groupIDs) && !revoke { + badIDs := make([]string, 0) + for _, gID := range groupIDs { + bad := true + for _, g := range groups { + if g.ID == gID { + bad = false + break + } + } + if bad { + badIDs = append(badIDs, gID) + } + } + return nil, errors.ErrorData(logutils.StatusInvalid, model.TypeAppOrgGroup, &logutils.FieldArgs{"ids": badIDs}) + } + + //check assigners + for _, group := range groups { + err = group.CheckAssigners(assignerPermissions) + if err != nil { + return nil, errors.WrapErrorAction(logutils.ActionValidate, "assigner permissions", &logutils.FieldArgs{"id": group.ID}, err) + } + } + + return groups, nil +} + //GetServiceRegistrations retrieves all service registrations func (a *Auth) GetServiceRegistrations(serviceIDs []string) ([]model.ServiceReg, error) { return a.storage.FindServiceRegs(serviceIDs) diff --git a/core/auth/auth.go b/core/auth/auth.go index 9fb0d1c5f..e0d0c5d64 100644 --- a/core/auth/auth.go +++ b/core/auth/auth.go @@ -1404,17 +1404,17 @@ func (a *Auth) constructAccount(context storage.TransactionContext, authType mod var roles []model.AppOrgRole var groups []model.AppOrgGroup if adminSet { - permissions, err = a.CheckPermissions(context, &appOrg, permissionNames, assignerPermissions) + permissions, err = a.CheckPermissions(context, &appOrg, permissionNames, assignerPermissions, false) if err != nil { return nil, errors.WrapErrorAction(logutils.ActionValidate, model.TypePermission, nil, err) } - roles, err = a.CheckRoles(context, &appOrg, roleIDs, assignerPermissions) + roles, err = a.CheckRoles(context, &appOrg, roleIDs, assignerPermissions, false) if err != nil { return nil, errors.WrapErrorAction(logutils.ActionValidate, model.TypeAppOrgRole, nil, err) } - groups, err = a.checkGroups(context, appOrg, groupIDs, assignerPermissions) + groups, err = a.CheckGroups(context, &appOrg, groupIDs, assignerPermissions, false) if err != nil { return nil, errors.WrapErrorAction(logutils.ActionGet, model.TypeAppOrgGroup, nil, err) } @@ -1479,59 +1479,6 @@ func (a *Auth) storeNewAccountInfo(context storage.TransactionContext, account m return nil } -func (a *Auth) checkGroups(context storage.TransactionContext, appOrg model.ApplicationOrganization, groupIDs []string, assignerPermissions []string) ([]model.AppOrgGroup, error) { - //find groups - groups, err := a.storage.FindAppOrgGroupsByIDs(context, groupIDs, appOrg.ID) - if err != nil { - return nil, errors.WrapErrorAction(logutils.ActionFind, model.TypeAppOrgGroup, nil, err) - } - if len(groups) != len(groupIDs) { - badIDs := make([]string, 0) - for _, gID := range groupIDs { - bad := true - for _, g := range groups { - if g.ID == gID { - bad = false - break - } - } - if bad { - badIDs = append(badIDs, gID) - } - } - return nil, errors.ErrorData(logutils.StatusInvalid, model.TypeAppOrgGroup, &logutils.FieldArgs{"ids": badIDs}) - } - - //check assigners - for _, group := range groups { - err = group.CheckAssigners(assignerPermissions) - if err != nil { - return nil, errors.WrapErrorAction(logutils.ActionValidate, "assigner permissions", &logutils.FieldArgs{"id": group.ID}, err) - } - } - - return groups, nil -} - -func (a *Auth) checkRevokedGroups(context storage.TransactionContext, appOrg model.ApplicationOrganization, groupIDs []string, assignerPermissions []string) error { - //find groups - groups, err := a.storage.FindAppOrgGroupsByIDs(context, groupIDs, appOrg.ID) - if err != nil { - return errors.WrapErrorAction(logutils.ActionFind, model.TypeAppOrgGroup, nil, err) - } - //Revoke missing groups - - //check assigners - for _, group := range groups { - err = group.CheckAssigners(assignerPermissions) - if err != nil { - return errors.WrapErrorAction(logutils.ActionValidate, "assigner permissions", &logutils.FieldArgs{"id": group.ID}, err) - } - } - - return nil -} - func (a *Auth) linkAccountAuthType(account model.Account, authType model.AuthType, appOrg model.ApplicationOrganization, creds string, params string, l *logs.Log) (string, *model.AccountAuthType, error) { authImpl, err := a.getAuthTypeImpl(authType) diff --git a/core/auth/interfaces.go b/core/auth/interfaces.go index 496e9d563..b1dd85c75 100644 --- a/core/auth/interfaces.go +++ b/core/auth/interfaces.go @@ -388,18 +388,21 @@ type APIs interface { //GrantAccountPermissions grants new permissions to an account after validating the assigner has required permissions GrantAccountPermissions(context storage.TransactionContext, account *model.Account, permissionNames []string, assignerPermissions []string) error - //CheckPermissions loads permissions by names from storage and checks that they are assignable and valid for the given appOrg - CheckPermissions(context storage.TransactionContext, appOrg *model.ApplicationOrganization, permissionNames []string, assignerPermissions []string) ([]model.Permission, error) + //CheckPermissions loads permissions by names from storage and checks that they are assignable and valid for the given appOrg or revocable + CheckPermissions(context storage.TransactionContext, appOrg *model.ApplicationOrganization, permissionNames []string, assignerPermissions []string, revoke bool) ([]model.Permission, error) //GrantAccountRoles grants new roles to an account after validating the assigner has required permissions GrantAccountRoles(context storage.TransactionContext, account *model.Account, roleIDs []string, assignerPermissions []string) error - //CheckRoles loads appOrg roles by IDs from storage and checks that they are assignable - CheckRoles(context storage.TransactionContext, appOrg *model.ApplicationOrganization, roleIDs []string, assignerPermissions []string) ([]model.AppOrgRole, error) + //CheckRoles loads appOrg roles by IDs from storage and checks that they are assignable or revocable + CheckRoles(context storage.TransactionContext, appOrg *model.ApplicationOrganization, roleIDs []string, assignerPermissions []string, revoke bool) ([]model.AppOrgRole, error) //GrantAccountGroups grants new groups to an account after validating the assigner has required permissions GrantAccountGroups(context storage.TransactionContext, account *model.Account, groupIDs []string, assignerPermissions []string) error + //CheckGroups loads appOrg groups by IDs from storage and checks that they are assignable or revocable + CheckGroups(context storage.TransactionContext, appOrg *model.ApplicationOrganization, groupIDs []string, assignerPermissions []string, revoke bool) ([]model.AppOrgGroup, error) + //DeleteAccount deletes an account for the given id DeleteAccount(id string) error diff --git a/core/interfaces.go b/core/interfaces.go index 0060cf0c5..038f3798a 100644 --- a/core/interfaces.go +++ b/core/interfaces.go @@ -52,9 +52,9 @@ type Administration interface { AdmRemoveAccountsFromGroup(appID string, orgID string, groupID string, accountIDs []string, assignerPermissions []string, l *logs.Log) error AdmDeleteAppOrgGroup(ID string, appID string, orgID string, assignerPermissions []string, system bool, l *logs.Log) error - AdmCreateAppOrgRole(name string, description string, permissionNames []string, appID string, orgID string, assignerPermissions []string, system bool, l *logs.Log) (*model.AppOrgRole, error) + AdmCreateAppOrgRole(name string, description string, system bool, permissionNames []string, appID string, orgID string, assignerPermissions []string, systemClaim bool, l *logs.Log) (*model.AppOrgRole, error) AdmGetAppOrgRoles(appID string, orgID string) ([]model.AppOrgRole, error) - AdmUpdateAppOrgRole(ID string, name string, description string, permissionNames []string, appID string, orgID string, assignerPermissions []string, system bool, l *logs.Log) (*model.AppOrgRole, error) + AdmUpdateAppOrgRole(ID string, name string, description string, system bool, permissionNames []string, appID string, orgID string, assignerPermissions []string, systemClaim bool, l *logs.Log) (*model.AppOrgRole, error) AdmGrantPermissionsToRole(appID string, orgID string, roleID string, permissionNames []string, assignerPermissions []string, system bool, l *logs.Log) error AdmDeleteAppOrgRole(ID string, appID string, orgID string, assignerPermissions []string, system bool, l *logs.Log) error diff --git a/core/model/application.go b/core/model/application.go index e9241fab3..dabae41df 100644 --- a/core/model/application.go +++ b/core/model/application.go @@ -114,6 +114,15 @@ func (c AppOrgRole) GetPermissionNamed(name string) *Permission { return nil } +//GetAssignedPermissionNames returns a list of names of assigned permissions for this role +func (c AppOrgRole) GetAssignedPermissionNames() []string { + names := make([]string, len(c.Permissions)) + for i, permission := range c.Permissions { + names[i] = permission.Name + } + return names +} + //CheckAssigners checks if the passed permissions satisfy the needed assigners for all role permissions func (c AppOrgRole) CheckAssigners(assignerPermissions []string) error { if len(c.Permissions) == 0 { diff --git a/driven/storage/adapter.go b/driven/storage/adapter.go index bb8c7a734..6706a2776 100644 --- a/driven/storage/adapter.go +++ b/driven/storage/adapter.go @@ -2537,9 +2537,12 @@ func (sa *Adapter) InsertAppOrgRole(context TransactionContext, item model.AppOr //UpdateAppOrgRole updates application organization role func (sa *Adapter) UpdateAppOrgRole(context TransactionContext, item model.AppOrgRole) error { - //TODO: when is updating system flag allowed? - filter := bson.D{primitive.E{Key: "_id", Value: item.ID}} + if context == nil { + return errors.ErrorData(logutils.StatusMissing, "transaction context", nil) + } + // update role + roleFilter := bson.D{primitive.E{Key: "_id", Value: item.ID}} roleUpdate := bson.D{ primitive.E{Key: "$set", Value: bson.D{ primitive.E{Key: "name", Value: item.Name}, @@ -2550,21 +2553,15 @@ func (sa *Adapter) UpdateAppOrgRole(context TransactionContext, item model.AppOr }}, } - var res *mongo.UpdateResult - var err error - if context != nil { - res, err = sa.db.applicationsOrganizationsRoles.UpdateOneWithContext(context, filter, roleUpdate, nil) - } else { - res, err = sa.db.applicationsOrganizationsRoles.UpdateOne(filter, roleUpdate, nil) - } + res, err := sa.db.applicationsOrganizationsRoles.UpdateOneWithContext(context, roleFilter, roleUpdate, nil) if err != nil { return errors.WrapErrorAction(logutils.ActionUpdate, model.TypeAppOrgRole, &logutils.FieldArgs{"id": item.ID}, err) } - if res.ModifiedCount != 1 { return errors.ErrorAction(logutils.ActionUpdate, model.TypeAppOrgRole, &logutils.FieldArgs{"id": item.ID, "modified": res.ModifiedCount, "expected": 1}) } + // update all groups that have the role groupsFilter := bson.D{primitive.E{Key: "roles._id", Value: item.ID}} groupsUpdate := bson.D{ primitive.E{Key: "$set", Value: bson.D{ @@ -2576,19 +2573,15 @@ func (sa *Adapter) UpdateAppOrgRole(context TransactionContext, item model.AppOr }}, } - if context != nil { - res, err = sa.db.applicationsOrganizationsGroups.UpdateManyWithContext(context, groupsFilter, groupsUpdate, nil) - } else { - res, err = sa.db.applicationsOrganizationsGroups.UpdateMany(groupsFilter, groupsUpdate, nil) - } + res, err = sa.db.applicationsOrganizationsGroups.UpdateManyWithContext(context, groupsFilter, groupsUpdate, nil) if err != nil { return errors.WrapErrorAction(logutils.ActionUpdate, model.TypeAppOrgGroup, &logutils.FieldArgs{"roles._id": item.ID}, err) } - if res.ModifiedCount != res.MatchedCount { return errors.ErrorAction(logutils.ActionUpdate, model.TypeAppOrgGroup, &logutils.FieldArgs{"roles._id": item.ID, "modified": res.ModifiedCount, "expected": res.MatchedCount}) } + // update all accounts that have the role accountsFilter := bson.D{primitive.E{Key: "roles.role._id", Value: item.ID}} accountsUpdate := bson.D{ primitive.E{Key: "$set", Value: bson.D{ @@ -2600,15 +2593,10 @@ func (sa *Adapter) UpdateAppOrgRole(context TransactionContext, item model.AppOr }}, } - if context != nil { - res, err = sa.db.accounts.UpdateManyWithContext(context, accountsFilter, accountsUpdate, nil) - } else { - res, err = sa.db.accounts.UpdateMany(accountsFilter, accountsUpdate, nil) - } + res, err = sa.db.accounts.UpdateManyWithContext(context, accountsFilter, accountsUpdate, nil) if err != nil { return errors.WrapErrorAction(logutils.ActionUpdate, model.TypeAccount, &logutils.FieldArgs{"roles.role._id": item.ID}, err) } - if res.ModifiedCount != res.MatchedCount { return errors.ErrorAction(logutils.ActionUpdate, model.TypeAccount, &logutils.FieldArgs{"roles.role._id": item.ID, "modified": res.ModifiedCount, "expected": res.MatchedCount}) } diff --git a/driver/web/apis_admin.go b/driver/web/apis_admin.go index ccdfeb94d..81ccd92a7 100644 --- a/driver/web/apis_admin.go +++ b/driver/web/apis_admin.go @@ -789,8 +789,12 @@ func (h AdminApisHandler) createApplicationRole(l *logs.Log, r *http.Request, cl return l.HttpResponseErrorAction(logutils.ActionUnmarshal, model.TypeAppOrgRole, nil, err, http.StatusBadRequest, true) } + system := false + if requestData.System != nil { + system = *requestData.System + } assignerPermissions := strings.Split(claims.Permissions, ",") - role, err := h.coreAPIs.Administration.AdmCreateAppOrgRole(requestData.Name, requestData.Description, requestData.Permissions, claims.AppID, claims.OrgID, assignerPermissions, claims.System, l) + role, err := h.coreAPIs.Administration.AdmCreateAppOrgRole(requestData.Name, requestData.Description, system, requestData.Permissions, claims.AppID, claims.OrgID, assignerPermissions, claims.System, l) if err != nil || role == nil { return l.HttpResponseErrorAction(logutils.ActionGet, model.TypeAppOrgRole, nil, err, http.StatusInternalServerError, true) } @@ -822,8 +826,12 @@ func (h AdminApisHandler) updateApplicationRole(l *logs.Log, r *http.Request, cl return l.HttpResponseErrorAction(logutils.ActionUnmarshal, model.TypeAppOrgRole, nil, err, http.StatusBadRequest, true) } + system := false + if requestData.System != nil { + system = *requestData.System + } assignerPermissions := strings.Split(claims.Permissions, ",") - role, err := h.coreAPIs.Administration.AdmUpdateAppOrgRole(rolesID, requestData.Name, requestData.Description, requestData.Permissions, claims.AppID, claims.OrgID, assignerPermissions, claims.System, l) + role, err := h.coreAPIs.Administration.AdmUpdateAppOrgRole(rolesID, requestData.Name, requestData.Description, system, requestData.Permissions, claims.AppID, claims.OrgID, assignerPermissions, claims.System, l) if err != nil || role == nil { return l.HttpResponseErrorAction(logutils.ActionUpdate, model.TypeAppOrgRole, nil, err, http.StatusInternalServerError, true) } diff --git a/driver/web/docs/gen/def.yaml b/driver/web/docs/gen/def.yaml index 798aca415..4d37c2b4b 100644 --- a/driver/web/docs/gen/def.yaml +++ b/driver/web/docs/gen/def.yaml @@ -6012,6 +6012,8 @@ components: type: string description: type: string + system: + type: boolean permissions: type: array items: diff --git a/driver/web/docs/gen/gen_types.go b/driver/web/docs/gen/gen_types.go index 2468e9ee7..106f1088f 100644 --- a/driver/web/docs/gen/gen_types.go +++ b/driver/web/docs/gen/gen_types.go @@ -605,6 +605,7 @@ type AdminReqApplicationRole struct { Description string `json:"description"` Name string `json:"name"` Permissions []string `json:"permissions"` + System *bool `json:"system,omitempty"` } // AdminReqCreateApplicationGroup defines model for _admin_req_create-application_group. diff --git a/driver/web/docs/schemas/apis/admin/application/roles/request/Request.yaml b/driver/web/docs/schemas/apis/admin/application/roles/request/Request.yaml index f33c258cb..3e87a0e87 100644 --- a/driver/web/docs/schemas/apis/admin/application/roles/request/Request.yaml +++ b/driver/web/docs/schemas/apis/admin/application/roles/request/Request.yaml @@ -8,6 +8,8 @@ properties: type: string description: type: string + system: + type: boolean permissions: type: array items: From afa7af12f81516acab6bef482ebcfad183180fc4 Mon Sep 17 00:00:00 2001 From: Ryan Oberlander Date: Wed, 13 Jul 2022 15:58:54 -0500 Subject: [PATCH 04/32] update changelog, better error checking [#516] --- CHANGELOG.md | 2 ++ core/app_administration.go | 12 ++++++++++-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f7afad470..438ef6dcb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] +### Added +- Update role permissions admin API [#516](https://github.com/rokwire/core-building-block/issues/516) ## [1.24.1] - 2022-07-07 ### Changed diff --git a/core/app_administration.go b/core/app_administration.go index ff8128c52..a574384dd 100644 --- a/core/app_administration.go +++ b/core/app_administration.go @@ -487,6 +487,9 @@ func (app *application) admUpdateAppOrgRole(ID string, name string, description if err != nil { return errors.WrapErrorAction(logutils.ActionFind, model.TypeAppOrgRole, nil, err) } + if role == nil { + return errors.ErrorData(logutils.StatusMissing, model.TypeAppOrgRole, &logutils.FieldArgs{"id": ID}) + } if role.System && !systemClaim { return errors.ErrorData(logutils.StatusInvalid, logutils.TypeClaim, logutils.StringArgs("system")) } @@ -561,7 +564,10 @@ func (app *application) admDeleteAppOrgRole(ID string, appID string, orgID strin return errors.WrapErrorAction(logutils.ActionFind, model.TypeAppOrgRole, nil, err) } if role == nil { - return errors.Newf("there is no role for id %s", ID) + return errors.ErrorData(logutils.StatusMissing, model.TypeAppOrgRole, &logutils.FieldArgs{"id": ID}) + } + if role.System && !system { + return errors.ErrorData(logutils.StatusInvalid, logutils.TypeClaim, logutils.StringArgs("system")) } //3. check assigners field @@ -927,7 +933,9 @@ func (app *application) admGrantPermissionsToRole(appID string, orgID string, ro if err != nil { return errors.Wrap("error finding account on permissions granting", err) } - + if role == nil { + return errors.ErrorData(logutils.StatusMissing, model.TypeAppOrgRole, &logutils.FieldArgs{"id": roleID}) + } if role.System && !system { return errors.ErrorData(logutils.StatusInvalid, logutils.TypeClaim, logutils.StringArgs("system")) } From 9b650d029a15b394d3fca384264dd0135c599985 Mon Sep 17 00:00:00 2001 From: Ryan Oberlander Date: Wed, 20 Jul 2022 14:09:12 -0500 Subject: [PATCH 05/32] added update group admin API [#518] --- .secrets.baseline | 6 +- core/apis.go | 8 +- core/app_administration.go | 119 ++++++++++++++++- core/auth/apis.go | 126 ++++++++---------- core/auth/auth.go | 59 +------- core/auth/interfaces.go | 11 +- core/interfaces.go | 5 +- core/mocks/Storage.go | 12 +- core/model/application.go | 18 +++ driven/storage/adapter.go | 53 +++++++- driver/web/adapter.go | 1 + driver/web/apis_admin.go | 68 +++++++++- driver/web/authorization_admin_policy.csv | 1 + driver/web/docs/gen/def.yaml | 46 ++++++- driver/web/docs/gen/gen_types.go | 14 +- .../resources/admin/application/groupsID.yaml | 37 +++++ .../application/groups/request/Request.yaml | 5 + driver/web/docs/schemas/index.yaml | 2 +- 18 files changed, 433 insertions(+), 158 deletions(-) diff --git a/.secrets.baseline b/.secrets.baseline index 186f42baf..47d073445 100644 --- a/.secrets.baseline +++ b/.secrets.baseline @@ -124,7 +124,7 @@ "filename": "core/auth/apis.go", "hashed_secret": "4d55af37dbbb6a42088d917caa1ca25428ec42c9", "is_verified": false, - "line_number": 1918 + "line_number": 1910 } ], "core/auth/auth.go": [ @@ -133,7 +133,7 @@ "filename": "core/auth/auth.go", "hashed_secret": "4d55af37dbbb6a42088d917caa1ca25428ec42c9", "is_verified": false, - "line_number": 2377 + "line_number": 2324 } ], "core/auth/auth_type_email.go": [ @@ -279,5 +279,5 @@ } ] }, - "generated_at": "2022-07-07T03:28:36Z" + "generated_at": "2022-07-20T19:09:04Z" } diff --git a/core/apis.go b/core/apis.go index 85cbd65e4..caf8a534c 100644 --- a/core/apis.go +++ b/core/apis.go @@ -311,8 +311,12 @@ func (s *administrationImpl) AdmGetApplications(orgID string) ([]model.Applicati return s.app.admGetApplications(orgID) } -func (s *administrationImpl) AdmCreateAppOrgGroup(name string, permissionNames []string, rolesIDs []string, appID string, orgID string, assignerPermissions []string, system bool, l *logs.Log) (*model.AppOrgGroup, error) { - return s.app.admCreateAppOrgGroup(name, permissionNames, rolesIDs, appID, orgID, assignerPermissions, system, l) +func (s *administrationImpl) AdmCreateAppOrgGroup(name string, description string, system bool, permissionNames []string, rolesIDs []string, appID string, orgID string, assignerPermissions []string, systemClaim bool, l *logs.Log) (*model.AppOrgGroup, error) { + return s.app.admCreateAppOrgGroup(name, description, system, permissionNames, rolesIDs, appID, orgID, assignerPermissions, systemClaim, l) +} + +func (s *administrationImpl) AdmUpdateAppOrgGroup(ID string, name string, description string, system bool, permissionNames []string, rolesIDs []string, appID string, orgID string, assignerPermissions []string, systemClaim bool, l *logs.Log) (*model.AppOrgGroup, error) { + return s.app.admUpdateAppOrgGroup(ID, name, description, system, permissionNames, rolesIDs, appID, orgID, assignerPermissions, systemClaim, l) } func (s *administrationImpl) AdmGetAppOrgGroups(appID string, orgID string) ([]model.AppOrgGroup, error) { diff --git a/core/app_administration.go b/core/app_administration.go index cacc477ae..8ea196921 100644 --- a/core/app_administration.go +++ b/core/app_administration.go @@ -198,7 +198,7 @@ func (app *application) admGetApplications(orgID string) ([]model.Application, e return apps, nil } -func (app *application) admCreateAppOrgGroup(name string, permissionNames []string, rolesIDs []string, appID string, orgID string, assignerPermissions []string, system bool, l *logs.Log) (*model.AppOrgGroup, error) { +func (app *application) admCreateAppOrgGroup(name string, description string, system bool, permissionNames []string, rolesIDs []string, appID string, orgID string, assignerPermissions []string, systemClaim bool, l *logs.Log) (*model.AppOrgGroup, error) { var newGroup *model.AppOrgGroup transaction := func(context storage.TransactionContext) error { //1. get application organization entity @@ -208,13 +208,13 @@ func (app *application) admCreateAppOrgGroup(name string, permissionNames []stri } //2. validate permissions - permissions, err := app.auth.CheckPermissions(context, appOrg, permissionNames, assignerPermissions) + permissions, err := app.auth.CheckPermissions(context, appOrg, permissionNames, assignerPermissions, false) if err != nil { return errors.WrapErrorAction(logutils.ActionValidate, model.TypePermission, nil, err) } //3. check roles - roles, err := app.auth.CheckRoles(context, appOrg, rolesIDs, assignerPermissions) + roles, err := app.auth.CheckRoles(context, appOrg, rolesIDs, assignerPermissions, false) if err != nil { return errors.WrapErrorAction(logutils.ActionValidate, model.TypeAppOrgRole, nil, err) } @@ -222,7 +222,7 @@ func (app *application) admCreateAppOrgGroup(name string, permissionNames []stri //4. create and insert group id, _ := uuid.NewUUID() now := time.Now() - group := model.AppOrgGroup{ID: id.String(), Name: name, Roles: roles, Permissions: permissions, AppOrg: *appOrg, System: system, DateCreated: now} + group := model.AppOrgGroup{ID: id.String(), Name: name, Description: description, Roles: roles, Permissions: permissions, AppOrg: *appOrg, System: systemClaim && system, DateCreated: now} err = app.storage.InsertAppOrgGroup(context, group) if err != nil { return err @@ -239,6 +239,115 @@ func (app *application) admCreateAppOrgGroup(name string, permissionNames []stri return newGroup, nil } +func (app *application) admUpdateAppOrgGroup(ID string, name string, description string, system bool, permissionNames []string, rolesIDs []string, appID string, orgID string, assignerPermissions []string, systemClaim bool, l *logs.Log) (*model.AppOrgGroup, error) { + var updatedGroup *model.AppOrgGroup + transaction := func(context storage.TransactionContext) error { + //1. get application organization entity + appOrg, err := app.storage.FindApplicationOrganization(appID, orgID) + if err != nil || appOrg == nil { + return errors.WrapErrorAction(logutils.ActionGet, model.TypeApplicationOrganization, nil, err) + } + + //2. find group, check if update allowed by system flag + group, err := app.storage.FindAppOrgGroup(ID, appOrg.ID) + if err != nil { + return errors.WrapErrorAction(logutils.ActionFind, model.TypeAppOrgGroup, nil, err) + } + if group == nil { + return errors.ErrorData(logutils.StatusMissing, model.TypeAppOrgGroup, &logutils.FieldArgs{"id": ID}) + } + if group.System && !systemClaim { + return errors.ErrorData(logutils.StatusInvalid, logutils.TypeClaim, logutils.StringArgs("system")) + } + + //3. check group permissions + updated := false + newPermissions := []model.Permission{} + added, removed, unchanged := utils.StringListDiff(permissionNames, group.GetAssignedPermissionNames()) + if len(added) > 0 || len(removed) > 0 { + if len(added) > 0 { + addedPermissions, err := app.auth.CheckPermissions(context, appOrg, added, assignerPermissions, false) + if err != nil { + return errors.WrapErrorAction("adding", model.TypePermission, nil, err) + } + newPermissions = append(newPermissions, addedPermissions...) + } + + if len(removed) > 0 { + _, err := app.auth.CheckPermissions(context, appOrg, removed, assignerPermissions, true) + if err != nil { + return errors.WrapErrorAction("revoking", model.TypePermission, nil, err) + } + } + + if len(unchanged) > 0 { + unchangedPermissions, err := app.storage.FindPermissionsByName(context, unchanged) + if err != nil { + return errors.WrapErrorAction(logutils.ActionFind, model.TypePermission, nil, err) + } + newPermissions = append(newPermissions, unchangedPermissions...) + } + + group.Permissions = newPermissions + updated = true + } + + //4. check group roles + newRoles := []model.AppOrgRole{} + added, removed, unchanged = utils.StringListDiff(rolesIDs, group.GetAssignedRoleIDs()) + if len(added) > 0 || len(removed) > 0 { + if len(added) > 0 { + addedRoles, err := app.auth.CheckRoles(context, appOrg, added, assignerPermissions, false) + if err != nil { + return errors.WrapErrorAction("adding", model.TypeAppOrgRole, nil, err) + } + newRoles = append(newRoles, addedRoles...) + } + + if len(removed) > 0 { + _, err := app.auth.CheckRoles(context, appOrg, removed, assignerPermissions, true) + if err != nil { + return errors.WrapErrorAction("revoking", model.TypeAppOrgRole, nil, err) + } + } + + if len(unchanged) > 0 { + unchangedRoles, err := app.storage.FindAppOrgRolesByIDs(context, unchanged, appOrg.ID) + if err != nil { + return errors.WrapErrorAction(logutils.ActionFind, model.TypeAppOrgRole, nil, err) + } + newRoles = append(newRoles, unchangedRoles...) + } + + group.Roles = newRoles + updated = true + } + + //5. update group (also updates all necessary accounts) + updated = updated || (group.Name != name) || (group.Description != description) || (group.System != (systemClaim && system)) + if updated { + now := time.Now().UTC() + group.Name = name + group.Description = description + group.System = systemClaim && system + group.DateUpdated = &now + err = app.storage.UpdateAppOrgGroup(context, *group) + if err != nil { + return errors.WrapErrorAction(logutils.ActionUpdate, model.TypeAppOrgGroup, nil, err) + } + } + + updatedGroup = group + return nil + } + + err := app.storage.PerformTransaction(transaction) + if err != nil { + return nil, err + } + return updatedGroup, nil +} + func (app *application) admGetAppOrgGroups(appID string, orgID string) ([]model.AppOrgGroup, error) { //find application organization getAppOrg, err := app.storage.FindApplicationOrganization(appID, orgID) @@ -431,7 +540,7 @@ func (app *application) admCreateAppOrgRole(name string, description string, per } //2. check role permissions - permissions, err := app.auth.CheckPermissions(context, appOrg, permissionNames, assignerPermissions) + permissions, err := app.auth.CheckPermissions(context, appOrg, permissionNames, assignerPermissions, false) if err != nil { return errors.WrapErrorAction(logutils.ActionValidate, model.TypePermission, nil, err) } diff --git a/core/auth/apis.go b/core/auth/apis.go index 371b6340f..2bbe693cd 100644 --- a/core/auth/apis.go +++ b/core/auth/apis.go @@ -654,7 +654,7 @@ func (a *Auth) UpdateAdminAccount(authenticationType string, appID string, orgID if len(added) > 0 || len(removed) > 0 { newPermissions := []model.Permission{} if len(added) > 0 { - addedPermissions, err := a.CheckPermissions(context, appOrg, added, updaterPermissions) + addedPermissions, err := a.CheckPermissions(context, appOrg, added, updaterPermissions, false) if err != nil { return errors.WrapErrorAction("adding", model.TypePermission, nil, err) } @@ -662,7 +662,7 @@ func (a *Auth) UpdateAdminAccount(authenticationType string, appID string, orgID } if len(removed) > 0 { - err := a.CheckRevokedPermissions(context, appOrg, removed, updaterPermissions) + _, err := a.CheckPermissions(context, appOrg, removed, updaterPermissions, true) if err != nil { return errors.WrapErrorAction("revoking", model.TypePermission, nil, err) } @@ -693,7 +693,7 @@ func (a *Auth) UpdateAdminAccount(authenticationType string, appID string, orgID if len(added) > 0 || len(removed) > 0 { newRoles := []model.AppOrgRole{} if len(added) > 0 { - addedRoles, err := a.CheckRoles(context, appOrg, added, updaterPermissions) + addedRoles, err := a.CheckRoles(context, appOrg, added, updaterPermissions, false) if err != nil { return errors.WrapErrorAction("adding", model.TypeAccountRoles, nil, err) } @@ -701,7 +701,7 @@ func (a *Auth) UpdateAdminAccount(authenticationType string, appID string, orgID } if len(removed) > 0 { - err := a.CheckRevokedRoles(context, appOrg, removed, updaterPermissions) + _, err := a.CheckRoles(context, appOrg, removed, updaterPermissions, true) if err != nil { return errors.WrapErrorAction("revoking", model.TypeAccountRoles, nil, err) } @@ -733,7 +733,7 @@ func (a *Auth) UpdateAdminAccount(authenticationType string, appID string, orgID if len(added) > 0 || len(removed) > 0 { newGroups := []model.AppOrgGroup{} if len(added) > 0 { - addedGroups, err := a.checkGroups(context, *appOrg, added, updaterPermissions) + addedGroups, err := a.CheckGroups(context, appOrg, added, updaterPermissions, false) if err != nil { return errors.WrapErrorAction("adding", model.TypeAccountGroups, nil, err) } @@ -741,7 +741,7 @@ func (a *Auth) UpdateAdminAccount(authenticationType string, appID string, orgID } if len(removed) > 0 { - err := a.checkRevokedGroups(context, *appOrg, removed, updaterPermissions) + _, err := a.CheckGroups(context, appOrg, removed, updaterPermissions, true) if err != nil { return errors.WrapErrorAction("revoking", model.TypeAccountGroups, nil, err) } @@ -1634,7 +1634,7 @@ func (a *Auth) GrantAccountPermissions(context storage.TransactionContext, accou } //check permissions - permissions, err := a.CheckPermissions(context, &account.AppOrg, newPermissions, assignerPermissions) + permissions, err := a.CheckPermissions(context, &account.AppOrg, newPermissions, assignerPermissions, false) if err != nil { return errors.WrapErrorAction(logutils.ActionValidate, model.TypePermission, nil, err) } @@ -1649,8 +1649,8 @@ func (a *Auth) GrantAccountPermissions(context storage.TransactionContext, accou return nil } -//CheckPermissions loads permissions by names from storage and checks that they are assignable and valid for the given appOrg -func (a *Auth) CheckPermissions(context storage.TransactionContext, appOrg *model.ApplicationOrganization, permissionNames []string, assignerPermissions []string) ([]model.Permission, error) { +//CheckPermissions loads permissions by names from storage and checks that they are assignable and valid for the given appOrg or revocable +func (a *Auth) CheckPermissions(context storage.TransactionContext, appOrg *model.ApplicationOrganization, permissionNames []string, assignerPermissions []string, revoke bool) ([]model.Permission, error) { if appOrg == nil { return nil, errors.ErrorData(logutils.StatusInvalid, model.TypeApplicationOrganization, nil) } @@ -1660,7 +1660,8 @@ func (a *Auth) CheckPermissions(context storage.TransactionContext, appOrg *mode if err != nil { return nil, errors.WrapErrorAction(logutils.ActionFind, model.TypePermission, nil, err) } - if len(permissions) != len(permissionNames) { + //Allow revocation of missing permissions + if len(permissions) != len(permissionNames) && !revoke { badNames := make([]string, 0) for _, pName := range permissionNames { bad := true @@ -1680,6 +1681,10 @@ func (a *Auth) CheckPermissions(context storage.TransactionContext, appOrg *mode //check if authorized for _, permission := range permissions { if !utils.Contains(appOrg.ServicesIDs, permission.ServiceID) { + //Allow revocation of permissions for invalid services + if revoke { + continue + } return nil, errors.ErrorData(logutils.StatusInvalid, model.TypePermission, &logutils.FieldArgs{"name": permission.Name, "service_id": permission.ServiceID}) } err = permission.CheckAssigners(assignerPermissions) @@ -1691,34 +1696,6 @@ func (a *Auth) CheckPermissions(context storage.TransactionContext, appOrg *mode return permissions, nil } -//CheckRevokedPermissions loads permissions by names from storage and checks that they are revokable -func (a *Auth) CheckRevokedPermissions(context storage.TransactionContext, appOrg *model.ApplicationOrganization, permissionNames []string, assignerPermissions []string) error { - if appOrg == nil { - return errors.ErrorData(logutils.StatusInvalid, model.TypeApplicationOrganization, nil) - } - - //find permissions - permissions, err := a.storage.FindPermissionsByName(context, permissionNames) - if err != nil { - return errors.WrapErrorAction(logutils.ActionFind, model.TypePermission, nil, err) - } - //Allow revocation of missing permissions - - //check if authorized - for _, permission := range permissions { - //Allow revocation of permissions for invalid services - if !utils.Contains(appOrg.ServicesIDs, permission.ServiceID) { - continue - } - err = permission.CheckAssigners(assignerPermissions) - if err != nil { - return errors.WrapErrorAction(logutils.ActionValidate, "assigner permissions", &logutils.FieldArgs{"name": permission.Name}, err) - } - } - - return nil -} - //GrantAccountRoles grants new roles to an account after validating the assigner has required permissions func (a *Auth) GrantAccountRoles(context storage.TransactionContext, account *model.Account, roleIDs []string, assignerPermissions []string) error { //check if there is data @@ -1739,7 +1716,7 @@ func (a *Auth) GrantAccountRoles(context storage.TransactionContext, account *mo } //check roles - roles, err := a.CheckRoles(context, &account.AppOrg, newRoles, assignerPermissions) + roles, err := a.CheckRoles(context, &account.AppOrg, newRoles, assignerPermissions, false) if err != nil { return errors.WrapErrorAction(logutils.ActionValidate, model.TypeAppOrgRole, nil, err) } @@ -1755,8 +1732,8 @@ func (a *Auth) GrantAccountRoles(context storage.TransactionContext, account *mo return nil } -//CheckRoles loads appOrg roles by IDs from storage and checks that they are assignable -func (a *Auth) CheckRoles(context storage.TransactionContext, appOrg *model.ApplicationOrganization, roleIDs []string, assignerPermissions []string) ([]model.AppOrgRole, error) { +//CheckRoles loads appOrg roles by IDs from storage and checks that they are assignable or revocable +func (a *Auth) CheckRoles(context storage.TransactionContext, appOrg *model.ApplicationOrganization, roleIDs []string, assignerPermissions []string, revoke bool) ([]model.AppOrgRole, error) { if appOrg == nil { return nil, errors.ErrorData(logutils.StatusInvalid, model.TypeApplicationOrganization, nil) } @@ -1766,7 +1743,7 @@ func (a *Auth) CheckRoles(context storage.TransactionContext, appOrg *model.Appl if err != nil { return nil, errors.WrapErrorAction(logutils.ActionFind, model.TypeAppOrgRole, nil, err) } - if len(roles) != len(roleIDs) { + if len(roles) != len(roleIDs) && !revoke { badIDs := make([]string, 0) for _, rID := range roleIDs { bad := true @@ -1794,30 +1771,6 @@ func (a *Auth) CheckRoles(context storage.TransactionContext, appOrg *model.Appl return roles, nil } -//CheckRevokedRoles loads appOrg roles by IDs from storage and checks that they are revocable -func (a *Auth) CheckRevokedRoles(context storage.TransactionContext, appOrg *model.ApplicationOrganization, roleIDs []string, assignerPermissions []string) error { - if appOrg == nil { - return errors.ErrorData(logutils.StatusInvalid, model.TypeApplicationOrganization, nil) - } - - //find roles - roles, err := a.storage.FindAppOrgRolesByIDs(context, roleIDs, appOrg.ID) - if err != nil { - return errors.WrapErrorAction(logutils.ActionFind, model.TypeAppOrgRole, nil, err) - } - //Allow missing roles to be revoked - - //check if authorized - for _, cRole := range roles { - err = cRole.CheckAssigners(assignerPermissions) - if err != nil { - return errors.WrapErrorAction(logutils.ActionValidate, "assigner permissions", &logutils.FieldArgs{"id": cRole.ID}, err) - } - } - - return nil -} - //GrantAccountGroups grants new groups to an account after validating the assigner has required permissions func (a *Auth) GrantAccountGroups(context storage.TransactionContext, account *model.Account, groupIDs []string, assignerPermissions []string) error { //check if there is data @@ -1838,7 +1791,7 @@ func (a *Auth) GrantAccountGroups(context storage.TransactionContext, account *m } //check groups - groups, err := a.checkGroups(context, account.AppOrg, newGroups, assignerPermissions) + groups, err := a.CheckGroups(context, &account.AppOrg, newGroups, assignerPermissions, false) if err != nil { return errors.WrapErrorAction(logutils.ActionValidate, model.TypeAppOrgGroup, nil, err) } @@ -1854,6 +1807,45 @@ func (a *Auth) GrantAccountGroups(context storage.TransactionContext, account *m return nil } +//CheckGroups loads appOrg groups by IDs from storage and checks that they are assignable or revocable +func (a *Auth) CheckGroups(context storage.TransactionContext, appOrg *model.ApplicationOrganization, groupIDs []string, assignerPermissions []string, revoke bool) ([]model.AppOrgGroup, error) { + if appOrg == nil { + return nil, errors.ErrorData(logutils.StatusInvalid, model.TypeApplicationOrganization, nil) + } + + //find groups + groups, err := a.storage.FindAppOrgGroupsByIDs(context, groupIDs, appOrg.ID) + if err != nil { + return nil, errors.WrapErrorAction(logutils.ActionFind, model.TypeAppOrgGroup, nil, err) + } + if len(groups) != len(groupIDs) && !revoke { + badIDs := make([]string, 0) + for _, gID := range groupIDs { + bad := true + for _, g := range groups { + if g.ID == gID { + bad = false + break + } + } + if bad { + badIDs = append(badIDs, gID) + } + } + return nil, errors.ErrorData(logutils.StatusInvalid, model.TypeAppOrgGroup, &logutils.FieldArgs{"ids": badIDs}) + } + + //check assigners + for _, group := range groups { + err = group.CheckAssigners(assignerPermissions) + if err != nil { + return nil, errors.WrapErrorAction(logutils.ActionValidate, "assigner permissions", &logutils.FieldArgs{"id": group.ID}, err) + } + } + + return groups, nil +} + //GetServiceRegistrations retrieves all service registrations func (a *Auth) GetServiceRegistrations(serviceIDs []string) ([]model.ServiceReg, error) { return a.storage.FindServiceRegs(serviceIDs) diff --git a/core/auth/auth.go b/core/auth/auth.go index 9fb0d1c5f..e0d0c5d64 100644 --- a/core/auth/auth.go +++ b/core/auth/auth.go @@ -1404,17 +1404,17 @@ func (a *Auth) constructAccount(context storage.TransactionContext, authType mod var roles []model.AppOrgRole var groups []model.AppOrgGroup if adminSet { - permissions, err = a.CheckPermissions(context, &appOrg, permissionNames, assignerPermissions) + permissions, err = a.CheckPermissions(context, &appOrg, permissionNames, assignerPermissions, false) if err != nil { return nil, errors.WrapErrorAction(logutils.ActionValidate, model.TypePermission, nil, err) } - roles, err = a.CheckRoles(context, &appOrg, roleIDs, assignerPermissions) + roles, err = a.CheckRoles(context, &appOrg, roleIDs, assignerPermissions, false) if err != nil { return nil, errors.WrapErrorAction(logutils.ActionValidate, model.TypeAppOrgRole, nil, err) } - groups, err = a.checkGroups(context, appOrg, groupIDs, assignerPermissions) + groups, err = a.CheckGroups(context, &appOrg, groupIDs, assignerPermissions, false) if err != nil { return nil, errors.WrapErrorAction(logutils.ActionGet, model.TypeAppOrgGroup, nil, err) } @@ -1479,59 +1479,6 @@ func (a *Auth) storeNewAccountInfo(context storage.TransactionContext, account m return nil } -func (a *Auth) checkGroups(context storage.TransactionContext, appOrg model.ApplicationOrganization, groupIDs []string, assignerPermissions []string) ([]model.AppOrgGroup, error) { - //find groups - groups, err := a.storage.FindAppOrgGroupsByIDs(context, groupIDs, appOrg.ID) - if err != nil { - return nil, errors.WrapErrorAction(logutils.ActionFind, model.TypeAppOrgGroup, nil, err) - } - if len(groups) != len(groupIDs) { - badIDs := make([]string, 0) - for _, gID := range groupIDs { - bad := true - for _, g := range groups { - if g.ID == gID { - bad = false - break - } - } - if bad { - badIDs = append(badIDs, gID) - } - } - return nil, errors.ErrorData(logutils.StatusInvalid, model.TypeAppOrgGroup, &logutils.FieldArgs{"ids": badIDs}) - } - - //check assigners - for _, group := range groups { - err = group.CheckAssigners(assignerPermissions) - if err != nil { - return nil, errors.WrapErrorAction(logutils.ActionValidate, "assigner permissions", &logutils.FieldArgs{"id": group.ID}, err) - } - } - - return groups, nil -} - -func (a *Auth) checkRevokedGroups(context storage.TransactionContext, appOrg model.ApplicationOrganization, groupIDs []string, assignerPermissions []string) error { - //find groups - groups, err := a.storage.FindAppOrgGroupsByIDs(context, groupIDs, appOrg.ID) - if err != nil { - return errors.WrapErrorAction(logutils.ActionFind, model.TypeAppOrgGroup, nil, err) - } - //Revoke missing groups - - //check assigners - for _, group := range groups { - err = group.CheckAssigners(assignerPermissions) - if err != nil { - return errors.WrapErrorAction(logutils.ActionValidate, "assigner permissions", &logutils.FieldArgs{"id": group.ID}, err) - } - } - - return nil -} - func (a *Auth) linkAccountAuthType(account model.Account, authType model.AuthType, appOrg model.ApplicationOrganization, creds string, params string, l *logs.Log) (string, *model.AccountAuthType, error) { authImpl, err := a.getAuthTypeImpl(authType) diff --git a/core/auth/interfaces.go b/core/auth/interfaces.go index 496e9d563..b1dd85c75 100644 --- a/core/auth/interfaces.go +++ b/core/auth/interfaces.go @@ -388,18 +388,21 @@ type APIs interface { //GrantAccountPermissions grants new permissions to an account after validating the assigner has required permissions GrantAccountPermissions(context storage.TransactionContext, account *model.Account, permissionNames []string, assignerPermissions []string) error - //CheckPermissions loads permissions by names from storage and checks that they are assignable and valid for the given appOrg - CheckPermissions(context storage.TransactionContext, appOrg *model.ApplicationOrganization, permissionNames []string, assignerPermissions []string) ([]model.Permission, error) + //CheckPermissions loads permissions by names from storage and checks that they are assignable and valid for the given appOrg or revocable + CheckPermissions(context storage.TransactionContext, appOrg *model.ApplicationOrganization, permissionNames []string, assignerPermissions []string, revoke bool) ([]model.Permission, error) //GrantAccountRoles grants new roles to an account after validating the assigner has required permissions GrantAccountRoles(context storage.TransactionContext, account *model.Account, roleIDs []string, assignerPermissions []string) error - //CheckRoles loads appOrg roles by IDs from storage and checks that they are assignable - CheckRoles(context storage.TransactionContext, appOrg *model.ApplicationOrganization, roleIDs []string, assignerPermissions []string) ([]model.AppOrgRole, error) + //CheckRoles loads appOrg roles by IDs from storage and checks that they are assignable or revocable + CheckRoles(context storage.TransactionContext, appOrg *model.ApplicationOrganization, roleIDs []string, assignerPermissions []string, revoke bool) ([]model.AppOrgRole, error) //GrantAccountGroups grants new groups to an account after validating the assigner has required permissions GrantAccountGroups(context storage.TransactionContext, account *model.Account, groupIDs []string, assignerPermissions []string) error + //CheckGroups loads appOrg groups by IDs from storage and checks that they are assignable or revocable + CheckGroups(context storage.TransactionContext, appOrg *model.ApplicationOrganization, groupIDs []string, assignerPermissions []string, revoke bool) ([]model.AppOrgGroup, error) + //DeleteAccount deletes an account for the given id DeleteAccount(id string) error diff --git a/core/interfaces.go b/core/interfaces.go index f9b1b2b1a..c8a12be5f 100644 --- a/core/interfaces.go +++ b/core/interfaces.go @@ -46,7 +46,8 @@ type Administration interface { AdmGetApplications(orgID string) ([]model.Application, error) - AdmCreateAppOrgGroup(name string, permissionNames []string, rolesIDs []string, appID string, orgID string, assignerPermissions []string, system bool, l *logs.Log) (*model.AppOrgGroup, error) + AdmCreateAppOrgGroup(name string, description string, system bool, permissionNames []string, rolesIDs []string, appID string, orgID string, assignerPermissions []string, systemClaim bool, l *logs.Log) (*model.AppOrgGroup, error) + AdmUpdateAppOrgGroup(ID string, name string, description string, system bool, permissionNames []string, rolesIDs []string, appID string, orgID string, assignerPermissions []string, systemClaim bool, l *logs.Log) (*model.AppOrgGroup, error) AdmGetAppOrgGroups(appID string, orgID string) ([]model.AppOrgGroup, error) AdmAddAccountsToGroup(appID string, orgID string, groupID string, accountIDs []string, assignerPermissions []string, l *logs.Log) error AdmRemoveAccountsFromGroup(appID string, orgID string, groupID string, accountIDs []string, assignerPermissions []string, l *logs.Log) error @@ -170,7 +171,7 @@ type Storage interface { FindAppOrgGroupsByIDs(context storage.TransactionContext, ids []string, appOrgID string) ([]model.AppOrgGroup, error) FindAppOrgGroup(id string, appOrgID string) (*model.AppOrgGroup, error) InsertAppOrgGroup(context storage.TransactionContext, item model.AppOrgGroup) error - UpdateAppOrgGroup(item model.AppOrgGroup) error + UpdateAppOrgGroup(context storage.TransactionContext, item model.AppOrgGroup) error DeleteAppOrgGroup(id string) error CountGroupsByRoleID(roleID string) (*int64, error) diff --git a/core/mocks/Storage.go b/core/mocks/Storage.go index 56dc9d1fc..d29db1528 100644 --- a/core/mocks/Storage.go +++ b/core/mocks/Storage.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.13.1. DO NOT EDIT. +// Code generated by mockery v2.14.0. DO NOT EDIT. package mocks @@ -1147,13 +1147,13 @@ func (_m *Storage) UpdateAppConfig(ID string, appType model.ApplicationType, app return r0 } -// UpdateAppOrgGroup provides a mock function with given fields: item -func (_m *Storage) UpdateAppOrgGroup(item model.AppOrgGroup) error { - ret := _m.Called(item) +// UpdateAppOrgGroup provides a mock function with given fields: context, item +func (_m *Storage) UpdateAppOrgGroup(context storage.TransactionContext, item model.AppOrgGroup) error { + ret := _m.Called(context, item) var r0 error - if rf, ok := ret.Get(0).(func(model.AppOrgGroup) error); ok { - r0 = rf(item) + if rf, ok := ret.Get(0).(func(storage.TransactionContext, model.AppOrgGroup) error); ok { + r0 = rf(context, item) } else { r0 = ret.Error(0) } diff --git a/core/model/application.go b/core/model/application.go index e9241fab3..e8542f448 100644 --- a/core/model/application.go +++ b/core/model/application.go @@ -175,6 +175,24 @@ func (cg AppOrgGroup) CheckAssigners(assignerPermissions []string) error { return nil } +//GetAssignedPermissionNames returns a list of names of assigned permissions for this group +func (cg AppOrgGroup) GetAssignedPermissionNames() []string { + names := make([]string, len(cg.Permissions)) + for i, permission := range cg.Permissions { + names[i] = permission.Name + } + return names +} + +//GetAssignedRoleIDs returns a list of ids of assigned roles for this group +func (cg AppOrgGroup) GetAssignedRoleIDs() []string { + ids := make([]string, len(cg.Roles)) + for i, role := range cg.Roles { + ids[i] = role.ID + } + return ids +} + func (cg AppOrgGroup) String() string { return fmt.Sprintf("[ID:%s\nName:%s\nAppOrg:%s]", cg.ID, cg.Name, cg.AppOrg.ID) } diff --git a/driven/storage/adapter.go b/driven/storage/adapter.go index bbc438139..a4bd213cd 100644 --- a/driven/storage/adapter.go +++ b/driven/storage/adapter.go @@ -2680,11 +2680,54 @@ func (sa *Adapter) InsertAppOrgGroup(context TransactionContext, item model.AppO } //UpdateAppOrgGroup updates application organization group -func (sa *Adapter) UpdateAppOrgGroup(item model.AppOrgGroup) error { - //TODO - //This will be slow operation as we keep a copy of the entity in the users collection without index. - //Maybe we need to up the transaction timeout for this operation because of this. - return errors.New(logutils.Unimplemented) +func (sa *Adapter) UpdateAppOrgGroup(context TransactionContext, item model.AppOrgGroup) error { + if context == nil { + return errors.ErrorData(logutils.StatusMissing, "transaction context", nil) + } + + // update group + groupFilter := bson.D{primitive.E{Key: "_id", Value: item.ID}} + groupUpdate := bson.D{ + primitive.E{Key: "$set", Value: bson.D{ + primitive.E{Key: "name", Value: item.Name}, + primitive.E{Key: "description", Value: item.Description}, + primitive.E{Key: "permissions", Value: item.Permissions}, + primitive.E{Key: "roles", Value: item.Roles}, + primitive.E{Key: "system", Value: item.System}, + primitive.E{Key: "date_updated", Value: item.DateUpdated}, + }}, + } + + res, err := sa.db.applicationsOrganizationsGroups.UpdateOneWithContext(context, groupFilter, groupUpdate, nil) + if err != nil { + return errors.WrapErrorAction(logutils.ActionUpdate, model.TypeAppOrgGroup, &logutils.FieldArgs{"id": item.ID}, err) + } + if res.ModifiedCount != 1 { + return errors.ErrorAction(logutils.ActionUpdate, model.TypeAppOrgGroup, &logutils.FieldArgs{"id": item.ID, "modified": res.ModifiedCount, "expected": 1}) + } + + // update all accounts that have the group + accountsFilter := bson.D{primitive.E{Key: "groups.group._id", Value: item.ID}} + accountsUpdate := bson.D{ + primitive.E{Key: "$set", Value: bson.D{ + primitive.E{Key: "groups.$.group.name", Value: item.Name}, + primitive.E{Key: "groups.$.group.description", Value: item.Description}, + primitive.E{Key: "groups.$.group.permissions", Value: item.Permissions}, + primitive.E{Key: "groups.$.group.roles", Value: item.Roles}, + primitive.E{Key: "groups.$.group.system", Value: item.System}, + primitive.E{Key: "groups.$.group.date_updated", Value: item.DateUpdated}, + }}, + } + + res, err = sa.db.accounts.UpdateManyWithContext(context, accountsFilter, accountsUpdate, nil) + if err != nil { + return errors.WrapErrorAction(logutils.ActionUpdate, model.TypeAccount, &logutils.FieldArgs{"groups.group.id": item.ID}, err) + } + if res.ModifiedCount != res.MatchedCount { + return errors.ErrorAction(logutils.ActionUpdate, model.TypeAccount, &logutils.FieldArgs{"groups.group.id": item.ID, "modified": res.ModifiedCount, "expected": res.MatchedCount}) + } + + return nil } //DeleteAppOrgGroup deletes application organization group diff --git a/driver/web/adapter.go b/driver/web/adapter.go index f580c04ed..aa5556e84 100644 --- a/driver/web/adapter.go +++ b/driver/web/adapter.go @@ -147,6 +147,7 @@ func (we Adapter) Start() { adminSubrouter.HandleFunc("/application/groups", we.wrapFunc(we.adminApisHandler.getApplicationGroups, we.auth.admin.permissions)).Methods("GET") adminSubrouter.HandleFunc("/application/groups", we.wrapFunc(we.adminApisHandler.createApplicationGroup, we.auth.admin.permissions)).Methods("POST") + adminSubrouter.HandleFunc("/application/groups/{id}", we.wrapFunc(we.adminApisHandler.updateApplicationGroup, we.auth.admin.permissions)).Methods("PUT") adminSubrouter.HandleFunc("/application/groups/{id}", we.wrapFunc(we.adminApisHandler.deleteApplicationGroup, we.auth.admin.permissions)).Methods("DELETE") adminSubrouter.HandleFunc("/application/groups/{id}/accounts", we.wrapFunc(we.adminApisHandler.addAccountsToGroup, we.auth.admin.permissions)).Methods("PUT") diff --git a/driver/web/apis_admin.go b/driver/web/apis_admin.go index 9a10c3ba4..5dcbf161b 100644 --- a/driver/web/apis_admin.go +++ b/driver/web/apis_admin.go @@ -673,12 +673,72 @@ func (h AdminApisHandler) createApplicationGroup(l *logs.Log, r *http.Request, c if err != nil { return l.HttpResponseErrorAction(logutils.ActionRead, logutils.TypeRequestBody, nil, err, http.StatusBadRequest, false) } - var requestData Def.AdminReqCreateApplicationGroup + var requestData Def.AdminReqApplicationGroup err = json.Unmarshal(data, &requestData) if err != nil { return l.HttpResponseErrorAction(logutils.ActionUnmarshal, model.TypeAppOrgGroup, nil, err, http.StatusBadRequest, true) } + //system flag + system := false + if requestData.System != nil { + system = *requestData.System + } + + //permissions names + var permissionNames []string + if requestData.Permissions != nil { + permissionNames = *requestData.Permissions + } + + //roles ids + var rolesIDs []string + if requestData.Roles != nil { + rolesIDs = *requestData.Roles + } + + if len(permissionNames) == 0 && len(rolesIDs) == 0 { + return l.HttpResponseErrorData(logutils.StatusMissing, "permissions and application organization roles", nil, nil, http.StatusBadRequest, true) + } + + assignerPermissions := strings.Split(claims.Permissions, ",") + group, err := h.coreAPIs.Administration.AdmCreateAppOrgGroup(requestData.Name, requestData.Description, system, permissionNames, rolesIDs, claims.AppID, claims.OrgID, assignerPermissions, claims.System, l) + if err != nil || group == nil { + return l.HttpResponseErrorAction(logutils.ActionGet, model.TypeAppOrgGroup, nil, err, http.StatusInternalServerError, true) + } + + respGroup := appOrgGroupToDef(*group) + response, err := json.Marshal(respGroup) + if err != nil { + return l.HttpResponseErrorAction(logutils.ActionMarshal, model.TypeAppOrgGroup, nil, err, http.StatusInternalServerError, false) + } + return l.HttpResponseSuccessJSON(response) +} + +//updateApplicationGroup updates an application group +func (h AdminApisHandler) updateApplicationGroup(l *logs.Log, r *http.Request, claims *tokenauth.Claims) logs.HttpResponse { + params := mux.Vars(r) + groupID := params["id"] + if len(groupID) <= 0 { + return l.HttpResponseErrorData(logutils.StatusMissing, logutils.TypeQueryParam, logutils.StringArgs("id"), nil, http.StatusBadRequest, false) + } + + data, err := ioutil.ReadAll(r.Body) + if err != nil { + return l.HttpResponseErrorAction(logutils.ActionRead, logutils.TypeRequestBody, nil, err, http.StatusBadRequest, false) + } + var requestData Def.AdminReqApplicationGroup + err = json.Unmarshal(data, &requestData) + if err != nil { + return l.HttpResponseErrorAction(logutils.ActionUnmarshal, model.TypeAppOrgGroup, nil, err, http.StatusBadRequest, true) + } + + //system flag + system := false + if requestData.System != nil { + system = *requestData.System + } + //permissions names var permissionNames []string if requestData.Permissions != nil { @@ -691,8 +751,12 @@ func (h AdminApisHandler) createApplicationGroup(l *logs.Log, r *http.Request, c rolesIDs = *requestData.Roles } + if len(permissionNames) == 0 && len(rolesIDs) == 0 { + return l.HttpResponseErrorData(logutils.StatusMissing, "permissions and application organization roles", nil, nil, http.StatusBadRequest, true) + } + assignerPermissions := strings.Split(claims.Permissions, ",") - group, err := h.coreAPIs.Administration.AdmCreateAppOrgGroup(requestData.Name, permissionNames, rolesIDs, claims.AppID, claims.OrgID, assignerPermissions, claims.System, l) + group, err := h.coreAPIs.Administration.AdmUpdateAppOrgGroup(groupID, requestData.Name, requestData.Description, system, permissionNames, rolesIDs, claims.AppID, claims.OrgID, assignerPermissions, claims.System, l) if err != nil || group == nil { return l.HttpResponseErrorAction(logutils.ActionGet, model.TypeAppOrgGroup, nil, err, http.StatusInternalServerError, true) } diff --git a/driver/web/authorization_admin_policy.csv b/driver/web/authorization_admin_policy.csv index 56f87d8b5..9fc39bd3d 100644 --- a/driver/web/authorization_admin_policy.csv +++ b/driver/web/authorization_admin_policy.csv @@ -15,6 +15,7 @@ p, all_auth-groups, /core/admin/application/groups, (GET)|(POST)|(PUT)|(DELETE) p, all_auth-groups, /core/admin/application/groups/*, (GET)|(POST)|(PUT)|(DELETE) p, get_auth-groups, /core/admin/application/groups, (GET) p, update_auth-groups, /core/admin/application/groups, (GET)|(POST)|(PUT) +p, update_auth-groups, /core/admin/application/groups/*, (GET)|(POST)|(PUT) p, delete_auth-groups, /core/admin/application/groups/*, (GET)|(DELETE) p, all_auth-roles, /core/admin/application/roles, (GET)|(POST)|(PUT)|(DELETE) diff --git a/driver/web/docs/gen/def.yaml b/driver/web/docs/gen/def.yaml index 5c67f1263..e409464a6 100644 --- a/driver/web/docs/gen/def.yaml +++ b/driver/web/docs/gen/def.yaml @@ -2299,7 +2299,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/_admin_req_create-application_group' + $ref: '#/components/schemas/_admin_req_application_group' required: true responses: '200': @@ -2315,6 +2315,43 @@ paths: '500': description: Internal error '/admin/application/groups/{id}': + put: + tags: + - Admin + summary: Update application group + description: | + Updates an existing application group + + **Auth:** Requires admin access token with `update_auth-groups` or `all_auth-groups` permission + security: + - bearerAuth: [] + parameters: + - name: id + in: path + description: The group ID + required: true + schema: + type: string + requestBody: + description: Application group + content: + application/json: + schema: + $ref: '#/components/schemas/_admin_req_application_group' + required: true + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/AppOrgGroup' + '400': + description: Bad request + '401': + description: Unauthorized + '500': + description: Internal error delete: tags: - Admin @@ -5979,13 +6016,18 @@ components: type: array items: type: string - _admin_req_create-application_group: + _admin_req_application_group: required: - name + - description type: object properties: name: type: string + description: + type: string + system: + type: boolean permissions: type: array items: diff --git a/driver/web/docs/gen/gen_types.go b/driver/web/docs/gen/gen_types.go index 61606de26..454b9b81a 100644 --- a/driver/web/docs/gen/gen_types.go +++ b/driver/web/docs/gen/gen_types.go @@ -600,11 +600,13 @@ type AdminReqAddAccountsToGroup struct { AccountIds []string `json:"account_ids"` } -// AdminReqCreateApplicationGroup defines model for _admin_req_create-application_group. -type AdminReqCreateApplicationGroup struct { +// AdminReqApplicationGroup defines model for _admin_req_application_group. +type AdminReqApplicationGroup struct { + Description string `json:"description"` Name string `json:"name"` Permissions *[]string `json:"permissions,omitempty"` Roles *[]string `json:"roles,omitempty"` + System *bool `json:"system,omitempty"` } // AdminReqCreateApplicationRole defines model for _admin_req_create-application_role. @@ -1245,7 +1247,10 @@ type DeleteAdminApplicationAccountsIdRolesJSONBody AdminReqRevokeRolesFromAccoun type PutAdminApplicationAccountsIdRolesJSONBody AdminReqGrantRolesToAccount // PostAdminApplicationGroupsJSONBody defines parameters for PostAdminApplicationGroups. -type PostAdminApplicationGroupsJSONBody AdminReqCreateApplicationGroup +type PostAdminApplicationGroupsJSONBody AdminReqApplicationGroup + +// PutAdminApplicationGroupsIdJSONBody defines parameters for PutAdminApplicationGroupsId. +type PutAdminApplicationGroupsIdJSONBody AdminReqApplicationGroup // DeleteAdminApplicationGroupsIdAccountsJSONBody defines parameters for DeleteAdminApplicationGroupsIdAccounts. type DeleteAdminApplicationGroupsIdAccountsJSONBody AdminReqRemoveAccountFromGroup @@ -1686,6 +1691,9 @@ type PutAdminApplicationAccountsIdRolesJSONRequestBody PutAdminApplicationAccoun // PostAdminApplicationGroupsJSONRequestBody defines body for PostAdminApplicationGroups for application/json ContentType. type PostAdminApplicationGroupsJSONRequestBody PostAdminApplicationGroupsJSONBody +// PutAdminApplicationGroupsIdJSONRequestBody defines body for PutAdminApplicationGroupsId for application/json ContentType. +type PutAdminApplicationGroupsIdJSONRequestBody PutAdminApplicationGroupsIdJSONBody + // DeleteAdminApplicationGroupsIdAccountsJSONRequestBody defines body for DeleteAdminApplicationGroupsIdAccounts for application/json ContentType. type DeleteAdminApplicationGroupsIdAccountsJSONRequestBody DeleteAdminApplicationGroupsIdAccountsJSONBody diff --git a/driver/web/docs/resources/admin/application/groupsID.yaml b/driver/web/docs/resources/admin/application/groupsID.yaml index d28de49d4..7f8000493 100644 --- a/driver/web/docs/resources/admin/application/groupsID.yaml +++ b/driver/web/docs/resources/admin/application/groupsID.yaml @@ -1,3 +1,40 @@ +put: + tags: + - Admin + summary: Update application group + description: | + Updates an existing application group + + **Auth:** Requires admin access token with `update_auth-groups` or `all_auth-groups` permission + security: + - bearerAuth: [] + parameters: + - name: id + in: path + description: The group ID + required: true + schema: + type: string + requestBody: + description: Application group + content: + application/json: + schema: + $ref: "../../../schemas/apis/admin/application/groups/request/Request.yaml" + required: true + responses: + 200: + description: Success + content: + application/json: + schema: + $ref: "../../../schemas/application/AppOrgGroup.yaml" + 400: + description: Bad request + 401: + description: Unauthorized + 500: + description: Internal error delete: tags: - Admin diff --git a/driver/web/docs/schemas/apis/admin/application/groups/request/Request.yaml b/driver/web/docs/schemas/apis/admin/application/groups/request/Request.yaml index 5579db1ca..42dbc1ba0 100644 --- a/driver/web/docs/schemas/apis/admin/application/groups/request/Request.yaml +++ b/driver/web/docs/schemas/apis/admin/application/groups/request/Request.yaml @@ -1,9 +1,14 @@ required: - name + - description type: object properties: name: type: string + description: + type: string + system: + type: boolean permissions: type: array items: diff --git a/driver/web/docs/schemas/index.yaml b/driver/web/docs/schemas/index.yaml index 574ea351c..e3936dcdd 100644 --- a/driver/web/docs/schemas/index.yaml +++ b/driver/web/docs/schemas/index.yaml @@ -214,7 +214,7 @@ _admin_req_create-application_role: $ref: "./apis/admin/application/roles/request/Request.yaml" ### admin application_groups API -_admin_req_create-application_group: +_admin_req_application_group: $ref: "./apis/admin/application/groups/request/Request.yaml" ### admin add-accounts-to-group API From c8a37563ee7bbe9ff4b6d6e4af4aebcebd267eb8 Mon Sep 17 00:00:00 2001 From: Ryan Oberlander Date: Wed, 20 Jul 2022 16:47:21 -0500 Subject: [PATCH 06/32] bug fixes, update changelog [#518] --- CHANGELOG.md | 2 ++ driven/storage/adapter.go | 6 ++++-- driver/web/apis_admin.go | 8 ++++---- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f7afad470..39efa86d7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] +### Added +- Update group admin API [#518](https://github.com/rokwire/core-building-block/issues/518) ## [1.24.1] - 2022-07-07 ### Changed diff --git a/driven/storage/adapter.go b/driven/storage/adapter.go index a4bd213cd..f4f72ec37 100644 --- a/driven/storage/adapter.go +++ b/driven/storage/adapter.go @@ -2685,6 +2685,8 @@ func (sa *Adapter) UpdateAppOrgGroup(context TransactionContext, item model.AppO return errors.ErrorData(logutils.StatusMissing, "transaction context", nil) } + roles := appOrgRolesToStorage(item.Roles) + // update group groupFilter := bson.D{primitive.E{Key: "_id", Value: item.ID}} groupUpdate := bson.D{ @@ -2692,7 +2694,7 @@ func (sa *Adapter) UpdateAppOrgGroup(context TransactionContext, item model.AppO primitive.E{Key: "name", Value: item.Name}, primitive.E{Key: "description", Value: item.Description}, primitive.E{Key: "permissions", Value: item.Permissions}, - primitive.E{Key: "roles", Value: item.Roles}, + primitive.E{Key: "roles", Value: roles}, primitive.E{Key: "system", Value: item.System}, primitive.E{Key: "date_updated", Value: item.DateUpdated}, }}, @@ -2713,7 +2715,7 @@ func (sa *Adapter) UpdateAppOrgGroup(context TransactionContext, item model.AppO primitive.E{Key: "groups.$.group.name", Value: item.Name}, primitive.E{Key: "groups.$.group.description", Value: item.Description}, primitive.E{Key: "groups.$.group.permissions", Value: item.Permissions}, - primitive.E{Key: "groups.$.group.roles", Value: item.Roles}, + primitive.E{Key: "groups.$.group.roles", Value: roles}, primitive.E{Key: "groups.$.group.system", Value: item.System}, primitive.E{Key: "groups.$.group.date_updated", Value: item.DateUpdated}, }}, diff --git a/driver/web/apis_admin.go b/driver/web/apis_admin.go index 5dcbf161b..3becc88d0 100644 --- a/driver/web/apis_admin.go +++ b/driver/web/apis_admin.go @@ -698,13 +698,13 @@ func (h AdminApisHandler) createApplicationGroup(l *logs.Log, r *http.Request, c } if len(permissionNames) == 0 && len(rolesIDs) == 0 { - return l.HttpResponseErrorData(logutils.StatusMissing, "permissions and application organization roles", nil, nil, http.StatusBadRequest, true) + return l.HttpResponseErrorData(logutils.StatusMissing, "permissions and application organization roles", nil, nil, http.StatusBadRequest, false) } assignerPermissions := strings.Split(claims.Permissions, ",") group, err := h.coreAPIs.Administration.AdmCreateAppOrgGroup(requestData.Name, requestData.Description, system, permissionNames, rolesIDs, claims.AppID, claims.OrgID, assignerPermissions, claims.System, l) if err != nil || group == nil { - return l.HttpResponseErrorAction(logutils.ActionGet, model.TypeAppOrgGroup, nil, err, http.StatusInternalServerError, true) + return l.HttpResponseErrorAction(logutils.ActionCreate, model.TypeAppOrgGroup, nil, err, http.StatusInternalServerError, true) } respGroup := appOrgGroupToDef(*group) @@ -752,13 +752,13 @@ func (h AdminApisHandler) updateApplicationGroup(l *logs.Log, r *http.Request, c } if len(permissionNames) == 0 && len(rolesIDs) == 0 { - return l.HttpResponseErrorData(logutils.StatusMissing, "permissions and application organization roles", nil, nil, http.StatusBadRequest, true) + return l.HttpResponseErrorData(logutils.StatusMissing, "permissions and application organization roles", nil, nil, http.StatusBadRequest, false) } assignerPermissions := strings.Split(claims.Permissions, ",") group, err := h.coreAPIs.Administration.AdmUpdateAppOrgGroup(groupID, requestData.Name, requestData.Description, system, permissionNames, rolesIDs, claims.AppID, claims.OrgID, assignerPermissions, claims.System, l) if err != nil || group == nil { - return l.HttpResponseErrorAction(logutils.ActionGet, model.TypeAppOrgGroup, nil, err, http.StatusInternalServerError, true) + return l.HttpResponseErrorAction(logutils.ActionUpdate, model.TypeAppOrgGroup, nil, err, http.StatusInternalServerError, true) } respGroup := appOrgGroupToDef(*group) From cbd6173cce7b0825ce2b852abf4a762a911dc753 Mon Sep 17 00:00:00 2001 From: Ryan Oberlander Date: Thu, 21 Jul 2022 16:45:05 -0500 Subject: [PATCH 07/32] fix update permission storage function [#542] --- core/app_system.go | 57 +++++++++++++++++++++----------- core/interfaces.go | 2 +- core/mocks/Storage.go | 12 +++---- driven/storage/adapter.go | 68 ++++++++++++++++++++++++++++++++------- 4 files changed, 102 insertions(+), 37 deletions(-) diff --git a/core/app_system.go b/core/app_system.go index cbf2b134e..de68bc1bf 100644 --- a/core/app_system.go +++ b/core/app_system.go @@ -185,32 +185,51 @@ func (app *application) sysCreatePermission(name string, description *string, se } func (app *application) sysUpdatePermission(name string, description *string, serviceID *string, assigners *[]string) (*model.Permission, error) { - permissionNames := []string{name} - permissions, err := app.storage.FindPermissionsByName(nil, permissionNames) - if err != nil { - return nil, err - } - if permissions == nil || len(permissions) < 1 { - return nil, errors.WrapErrorAction(logutils.ActionFind, model.TypePermission, nil, err) - } + var updatedPermission *model.Permission + transaction := func(context storage.TransactionContext) error { + //1. + permissionNames := []string{name} + permissions, err := app.storage.FindPermissionsByName(context, permissionNames) + if err != nil { + return err + } + if permissions == nil || len(permissions) < 1 { + return errors.WrapErrorAction(logutils.ActionFind, model.TypePermission, nil, err) + } - permission := permissions[0] - if description != nil { - permission.Description = *description - } - if serviceID != nil { - permission.ServiceID = *serviceID - } - if assigners != nil { - permission.Assigners = *assigners + permission := permissions[0] + updated := false + if description != nil { + permission.Description = *description + updated = true + } + if serviceID != nil { + permission.ServiceID = *serviceID + updated = true + } + if assigners != nil { + permission.Assigners = *assigners + updated = true + } + + if updated { + now := time.Now().UTC() + permission.DateUpdated = &now + err = app.storage.UpdatePermission(context, permission) + if err != nil { + return err + } + } + + return nil } - err = app.storage.UpdatePermission(permission) + err := app.storage.PerformTransaction(transaction) if err != nil { return nil, err } - return &permission, nil + return updatedPermission, nil } func (app *application) sysGetAppConfigs(appTypeID string, orgID *string, versionNumbers *model.VersionNumbers) ([]model.ApplicationConfig, error) { diff --git a/core/interfaces.go b/core/interfaces.go index f9b1b2b1a..477dad15f 100644 --- a/core/interfaces.go +++ b/core/interfaces.go @@ -155,7 +155,7 @@ type Storage interface { FindPermissionsByName(context storage.TransactionContext, names []string) ([]model.Permission, error) FindPermissionsByServiceIDs(serviceIDs []string) ([]model.Permission, error) InsertPermission(context storage.TransactionContext, item model.Permission) error - UpdatePermission(item model.Permission) error + UpdatePermission(context storage.TransactionContext, item model.Permission) error DeletePermission(id string) error FindAppOrgRoles(appOrgID string) ([]model.AppOrgRole, error) diff --git a/core/mocks/Storage.go b/core/mocks/Storage.go index 56dc9d1fc..dbe23097b 100644 --- a/core/mocks/Storage.go +++ b/core/mocks/Storage.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.13.1. DO NOT EDIT. +// Code generated by mockery v2.14.0. DO NOT EDIT. package mocks @@ -1203,13 +1203,13 @@ func (_m *Storage) UpdateOrganization(ID string, name string, requestType string return r0 } -// UpdatePermission provides a mock function with given fields: item -func (_m *Storage) UpdatePermission(item model.Permission) error { - ret := _m.Called(item) +// UpdatePermission provides a mock function with given fields: context, item +func (_m *Storage) UpdatePermission(context storage.TransactionContext, item model.Permission) error { + ret := _m.Called(context, item) var r0 error - if rf, ok := ret.Get(0).(func(model.Permission) error); ok { - r0 = rf(item) + if rf, ok := ret.Get(0).(func(storage.TransactionContext, model.Permission) error); ok { + r0 = rf(context, item) } else { r0 = ret.Error(0) } diff --git a/driven/storage/adapter.go b/driven/storage/adapter.go index bbc438139..96e778d43 100644 --- a/driven/storage/adapter.go +++ b/driven/storage/adapter.go @@ -117,6 +117,7 @@ func (sa *Adapter) RegisterStorageListener(storageListener Listener) { //PerformTransaction performs a transaction func (sa *Adapter) PerformTransaction(transaction func(context TransactionContext) error) error { + //TODO: may want to add timeout arg to PerformTransaction to be able to specify individual timeouts (mainly for slow operations) // transaction err := sa.db.dbClient.UseSession(context.Background(), func(sessionContext mongo.SessionContext) error { err := sessionContext.StartTransaction() @@ -2406,32 +2407,67 @@ func (sa *Adapter) InsertPermission(context TransactionContext, permission model } //UpdatePermission updates permission -func (sa *Adapter) UpdatePermission(item model.Permission) error { +func (sa *Adapter) UpdatePermission(context TransactionContext, item model.Permission) error { //TODO //This will be slow operation as we keep a copy of the entity in the users collection without index. //Maybe we need to up the transaction timeout for this operation because of this. - //TODO - //Update the permission in all collection where there is a copy of it - accounts, application_roles, application_groups, service_accounts - - // Update serviceIDs - filter := bson.D{primitive.E{Key: "name", Value: item.Name}} + if context == nil { + return errors.ErrorData(logutils.StatusMissing, "transaction context", nil) + } - now := time.Now().UTC() + //update permission + permissionFilter := bson.D{primitive.E{Key: "name", Value: item.Name}} permissionUpdate := bson.D{ primitive.E{Key: "$set", Value: bson.D{ + primitive.E{Key: "description", Value: item.Description}, primitive.E{Key: "service_id", Value: item.ServiceID}, primitive.E{Key: "assigners", Value: item.Assigners}, - primitive.E{Key: "date_updated", Value: &now}, + primitive.E{Key: "date_updated", Value: item.DateUpdated}, }}, } - res, err := sa.db.permissions.UpdateOne(filter, permissionUpdate, nil) + res, err := sa.db.permissions.UpdateOneWithContext(context, permissionFilter, permissionUpdate, nil) if err != nil { return errors.WrapErrorAction(logutils.ActionUpdate, model.TypePermission, &logutils.FieldArgs{"name": item.Name}, err) } - if res.ModifiedCount != 1 { - return errors.ErrorAction(logutils.ActionUpdate, model.TypePermission, logutils.StringArgs("unexpected modified count")) + return errors.ErrorAction(logutils.ActionUpdate, model.TypePermission, &logutils.FieldArgs{"name": item.Name, "modified": res.ModifiedCount, "expected": 1}) + } + + //update all roles, groups, accounts, and service accounts that have the permission + dependentsFilter := bson.D{primitive.E{Key: "permissions.name", Value: item.Name}} + dependentsUpdate := bson.D{ + primitive.E{Key: "$set", Value: bson.D{ + primitive.E{Key: "permissions.$.description", Value: item.Description}, + primitive.E{Key: "permissions.$.service_id", Value: item.ServiceID}, + primitive.E{Key: "permissions.$.assigners", Value: item.Assigners}, + primitive.E{Key: "permissions.$.date_updated", Value: item.DateUpdated}, + // primitive.E{Key: "date_updated", Value: item.DateUpdated}, + }}, + } + + //roles + res, err = sa.db.applicationsOrganizationsRoles.UpdateManyWithContext(context, dependentsFilter, dependentsUpdate, nil) + if err = sa.getUpdateManyError(res, err, model.TypeAppOrgRole, "permissions.name", item.Name); err != nil { + return err + } + + //groups + res, err = sa.db.applicationsOrganizationsGroups.UpdateManyWithContext(context, dependentsFilter, dependentsUpdate, nil) + if err = sa.getUpdateManyError(res, err, model.TypeAppOrgGroup, "permissions.name", item.Name); err != nil { + return err + } + + //accounts + res, err = sa.db.accounts.UpdateManyWithContext(context, dependentsFilter, dependentsUpdate, nil) + if err = sa.getUpdateManyError(res, err, model.TypeAccount, "permissions.name", item.Name); err != nil { + return err + } + + //service accounts + res, err = sa.db.serviceAccounts.UpdateManyWithContext(context, dependentsFilter, dependentsUpdate, nil) + if err = sa.getUpdateManyError(res, err, model.TypeServiceAccount, "permissions.name", item.Name); err != nil { + return err } return nil @@ -3540,6 +3576,16 @@ func (sa *Adapter) abortTransaction(sessionContext mongo.SessionContext) { } } +func (sa *Adapter) getUpdateManyError(res *mongo.UpdateResult, err error, dataType logutils.MessageDataType, key string, value string) error { + if err != nil { + return errors.WrapErrorAction(logutils.ActionUpdate, dataType, &logutils.FieldArgs{key: value}, err) + } + if res.ModifiedCount != res.MatchedCount { + return errors.ErrorAction(logutils.ActionUpdate, dataType, &logutils.FieldArgs{key: value, "modified": res.ModifiedCount, "expected": res.MatchedCount}) + } + return nil +} + //NewStorageAdapter creates a new storage adapter instance func NewStorageAdapter(mongoDBAuth string, mongoDBName string, mongoTimeout string, logger *logs.Logger) *Adapter { timeoutInt, err := strconv.Atoi(mongoTimeout) From b70fd54226e8188416402a53b99ff319baabf42a Mon Sep 17 00:00:00 2001 From: Ryan Oberlander Date: Thu, 21 Jul 2022 16:57:45 -0500 Subject: [PATCH 08/32] update create and update permission system API responses, bug fixes [#542] --- core/app_system.go | 14 +++++++++---- driver/web/apis_system.go | 20 +++++++++++++++---- driver/web/docs/gen/def.yaml | 10 ++++------ .../docs/resources/system/permissions.yaml | 10 ++++------ 4 files changed, 34 insertions(+), 20 deletions(-) diff --git a/core/app_system.go b/core/app_system.go index de68bc1bf..2a83f4e70 100644 --- a/core/app_system.go +++ b/core/app_system.go @@ -173,21 +173,24 @@ func (app *application) sysCreatePermission(name string, description *string, se if description != nil { descriptionVal = *description } + assignersVal := make([]string, 0) + if assigners != nil { + assignersVal = *assigners + } - permission := model.Permission{ID: id.String(), Name: name, Description: descriptionVal, DateCreated: now, ServiceID: serviceIDVal, Assigners: *assigners} - + permission := model.Permission{ID: id.String(), Name: name, Description: descriptionVal, DateCreated: now, ServiceID: serviceIDVal, Assigners: assignersVal} err := app.storage.InsertPermission(nil, permission) - if err != nil { return nil, err } + return &permission, nil } func (app *application) sysUpdatePermission(name string, description *string, serviceID *string, assigners *[]string) (*model.Permission, error) { var updatedPermission *model.Permission transaction := func(context storage.TransactionContext) error { - //1. + //1. find permission permissionNames := []string{name} permissions, err := app.storage.FindPermissionsByName(context, permissionNames) if err != nil { @@ -197,6 +200,7 @@ func (app *application) sysUpdatePermission(name string, description *string, se return errors.WrapErrorAction(logutils.ActionFind, model.TypePermission, nil, err) } + //2. update permission data as needed permission := permissions[0] updated := false if description != nil { @@ -212,6 +216,7 @@ func (app *application) sysUpdatePermission(name string, description *string, se updated = true } + //3. if permission data changed, update in storage if updated { now := time.Now().UTC() permission.DateUpdated = &now @@ -221,6 +226,7 @@ func (app *application) sysUpdatePermission(name string, description *string, se } } + updatedPermission = &permission return nil } diff --git a/driver/web/apis_system.go b/driver/web/apis_system.go index d6f31b047..f5a959f04 100644 --- a/driver/web/apis_system.go +++ b/driver/web/apis_system.go @@ -703,12 +703,18 @@ func (h SystemApisHandler) createPermission(l *logs.Log, r *http.Request, claims return l.HttpResponseErrorAction(logutils.ActionUnmarshal, model.TypePermission, nil, err, http.StatusBadRequest, true) } - _, err = h.coreAPIs.System.SysCreatePermission(requestData.Name, requestData.Description, requestData.ServiceId, requestData.Assigners) + permission, err := h.coreAPIs.System.SysCreatePermission(requestData.Name, requestData.Description, requestData.ServiceId, requestData.Assigners) if err != nil { return l.HttpResponseErrorAction(logutils.ActionCreate, model.TypePermission, nil, err, http.StatusInternalServerError, true) } - return l.HttpResponseSuccess() + permissionResp := applicationPermissionToDef(*permission) + data, err = json.Marshal(permissionResp) + if err != nil { + return l.HttpResponseErrorAction(logutils.ActionMarshal, model.TypePermission, nil, err, http.StatusInternalServerError, false) + } + + return l.HttpResponseSuccessJSON(data) } //updatePermission updates an permission @@ -724,12 +730,18 @@ func (h SystemApisHandler) updatePermission(l *logs.Log, r *http.Request, claims return l.HttpResponseErrorAction(logutils.ActionUnmarshal, model.TypePermission, nil, err, http.StatusBadRequest, true) } - _, err = h.coreAPIs.System.SysUpdatePermission(requestData.Name, requestData.Description, requestData.ServiceId, requestData.Assigners) + permission, err := h.coreAPIs.System.SysUpdatePermission(requestData.Name, requestData.Description, requestData.ServiceId, requestData.Assigners) if err != nil { return l.HttpResponseErrorAction(logutils.ActionUpdate, model.TypePermission, nil, err, http.StatusInternalServerError, true) } - return l.HttpResponseSuccess() + permissionResp := applicationPermissionToDef(*permission) + data, err = json.Marshal(permissionResp) + if err != nil { + return l.HttpResponseErrorAction(logutils.ActionMarshal, model.TypePermission, nil, err, http.StatusInternalServerError, false) + } + + return l.HttpResponseSuccessJSON(data) } func (h SystemApisHandler) getApplicationConfigs(l *logs.Log, r *http.Request, claims *tokenauth.Claims) logs.HttpResponse { diff --git a/driver/web/docs/gen/def.yaml b/driver/web/docs/gen/def.yaml index 5c67f1263..c9fd368f4 100644 --- a/driver/web/docs/gen/def.yaml +++ b/driver/web/docs/gen/def.yaml @@ -3920,10 +3920,9 @@ paths: '200': description: Success content: - text/plain: + application/json: schema: - type: string - example: Success + $ref: '#/components/schemas/Permission' '400': description: Bad request '401': @@ -3951,10 +3950,9 @@ paths: '200': description: Success content: - text/plain: + application/json: schema: - type: string - example: Success + $ref: '#/components/schemas/Permission' '400': description: Bad request '401': diff --git a/driver/web/docs/resources/system/permissions.yaml b/driver/web/docs/resources/system/permissions.yaml index 6af9daa2e..9445cac6c 100644 --- a/driver/web/docs/resources/system/permissions.yaml +++ b/driver/web/docs/resources/system/permissions.yaml @@ -19,10 +19,9 @@ post: 200: description: Success content: - text/plain: + application/json: schema: - type: string - example: Success + $ref: "../../schemas/application/Permission.yaml" 400: description: Bad request 401: @@ -50,10 +49,9 @@ put: 200: description: Success content: - text/plain: + application/json: schema: - type: string - example: Success + $ref: "../../schemas/application/Permission.yaml" 400: description: Bad request 401: From dc32acfa4c0adcbd226cc913c60ffb5b7d9bc142 Mon Sep 17 00:00:00 2001 From: Ryan Oberlander Date: Fri, 22 Jul 2022 14:17:43 -0500 Subject: [PATCH 09/32] bug fixes [#542] --- .secrets.baseline | 6 +- core/apis.go | 4 +- core/app_system.go | 74 +++++++++++++------ core/auth/apis.go | 36 ++------- core/auth/auth.go | 18 +---- core/interfaces.go | 4 +- core/model/application.go | 63 ++++++++++++++++ driver/web/docs/gen/def.yaml | 2 + driver/web/docs/gen/gen_types.go | 4 +- .../system/permissions/request/Request.yaml | 2 + 10 files changed, 136 insertions(+), 77 deletions(-) diff --git a/.secrets.baseline b/.secrets.baseline index 186f42baf..690ef257e 100644 --- a/.secrets.baseline +++ b/.secrets.baseline @@ -124,7 +124,7 @@ "filename": "core/auth/apis.go", "hashed_secret": "4d55af37dbbb6a42088d917caa1ca25428ec42c9", "is_verified": false, - "line_number": 1918 + "line_number": 1894 } ], "core/auth/auth.go": [ @@ -133,7 +133,7 @@ "filename": "core/auth/auth.go", "hashed_secret": "4d55af37dbbb6a42088d917caa1ca25428ec42c9", "is_verified": false, - "line_number": 2377 + "line_number": 2365 } ], "core/auth/auth_type_email.go": [ @@ -279,5 +279,5 @@ } ] }, - "generated_at": "2022-07-07T03:28:36Z" + "generated_at": "2022-07-22T19:17:37Z" } diff --git a/core/apis.go b/core/apis.go index 85cbd65e4..a10d54e5b 100644 --- a/core/apis.go +++ b/core/apis.go @@ -461,11 +461,11 @@ func (s *systemImpl) SysGetApplications() ([]model.Application, error) { return s.app.sysGetApplications() } -func (s *systemImpl) SysCreatePermission(name string, description *string, serviceID *string, assigners *[]string) (*model.Permission, error) { +func (s *systemImpl) SysCreatePermission(name string, description string, serviceID string, assigners *[]string) (*model.Permission, error) { return s.app.sysCreatePermission(name, description, serviceID, assigners) } -func (s *systemImpl) SysUpdatePermission(name string, description *string, serviceID *string, assigners *[]string) (*model.Permission, error) { +func (s *systemImpl) SysUpdatePermission(name string, description string, serviceID string, assigners *[]string) (*model.Permission, error) { return s.app.sysUpdatePermission(name, description, serviceID, assigners) } diff --git a/core/app_system.go b/core/app_system.go index 2a83f4e70..e808bb57a 100644 --- a/core/app_system.go +++ b/core/app_system.go @@ -17,6 +17,7 @@ package core import ( "core-building-block/core/model" "core-building-block/driven/storage" + "core-building-block/utils" "time" "github.com/google/uuid" @@ -162,32 +163,44 @@ func (app *application) sysGetApplications() ([]model.Application, error) { return getApplications, nil } -func (app *application) sysCreatePermission(name string, description *string, serviceID *string, assigners *[]string) (*model.Permission, error) { - id, _ := uuid.NewUUID() - now := time.Now() - serviceIDVal := "" - if serviceID != nil { - serviceIDVal = *serviceID - } - descriptionVal := "" - if description != nil { - descriptionVal = *description - } - assignersVal := make([]string, 0) - if assigners != nil { - assignersVal = *assigners +func (app *application) sysCreatePermission(name string, description string, serviceID string, assigners *[]string) (*model.Permission, error) { + var newPermission *model.Permission + transaction := func(context storage.TransactionContext) error { + //1. + id, _ := uuid.NewUUID() + now := time.Now() + assignersVal := make([]string, 0) + if assigners != nil { + assignersVal = *assigners + assignerPermissions, err := app.storage.FindPermissionsByName(context, assignersVal) + if err != nil { + return err + } + _, err = model.GetMissingPermissionNames(assignerPermissions, assignersVal) + if err != nil { + return err + } + } + + permission := model.Permission{ID: id.String(), Name: name, Description: description, DateCreated: now, ServiceID: serviceID, Assigners: assignersVal} + err := app.storage.InsertPermission(context, permission) + if err != nil { + return err + } + + newPermission = &permission + return nil } - permission := model.Permission{ID: id.String(), Name: name, Description: descriptionVal, DateCreated: now, ServiceID: serviceIDVal, Assigners: assignersVal} - err := app.storage.InsertPermission(nil, permission) + err := app.storage.PerformTransaction(transaction) if err != nil { return nil, err } - return &permission, nil + return newPermission, nil } -func (app *application) sysUpdatePermission(name string, description *string, serviceID *string, assigners *[]string) (*model.Permission, error) { +func (app *application) sysUpdatePermission(name string, description string, serviceID string, assigners *[]string) (*model.Permission, error) { var updatedPermission *model.Permission transaction := func(context storage.TransactionContext) error { //1. find permission @@ -203,20 +216,35 @@ func (app *application) sysUpdatePermission(name string, description *string, se //2. update permission data as needed permission := permissions[0] updated := false - if description != nil { - permission.Description = *description + if description != permission.Description { + permission.Description = description updated = true } - if serviceID != nil { - permission.ServiceID = *serviceID + if serviceID != permission.ServiceID { + permission.ServiceID = serviceID updated = true } + + //3. if assigners changed, check that they exist + assignersVal := make([]string, 0) if assigners != nil { + assignersVal = *assigners + } + if !utils.DeepEqual(assignersVal, permission.Assigners) { + assignerPermissions, err := app.storage.FindPermissionsByName(context, assignersVal) + if err != nil { + return err + } + _, err = model.GetMissingPermissionNames(assignerPermissions, assignersVal) + if err != nil { + return err + } + permission.Assigners = *assigners updated = true } - //3. if permission data changed, update in storage + //4. if permission data changed, update in storage if updated { now := time.Now().UTC() permission.DateUpdated = &now diff --git a/core/auth/apis.go b/core/auth/apis.go index 371b6340f..18a1b5083 100644 --- a/core/auth/apis.go +++ b/core/auth/apis.go @@ -1660,21 +1660,9 @@ func (a *Auth) CheckPermissions(context storage.TransactionContext, appOrg *mode if err != nil { return nil, errors.WrapErrorAction(logutils.ActionFind, model.TypePermission, nil, err) } - if len(permissions) != len(permissionNames) { - badNames := make([]string, 0) - for _, pName := range permissionNames { - bad := true - for _, p := range permissions { - if p.Name == pName { - bad = false - break - } - } - if bad { - badNames = append(badNames, pName) - } - } - return nil, errors.ErrorData(logutils.StatusInvalid, model.TypePermission, &logutils.FieldArgs{"names": badNames}) + _, err = model.GetMissingPermissionNames(permissions, permissionNames) + if err != nil { + return nil, err } //check if authorized @@ -1766,21 +1754,9 @@ func (a *Auth) CheckRoles(context storage.TransactionContext, appOrg *model.Appl if err != nil { return nil, errors.WrapErrorAction(logutils.ActionFind, model.TypeAppOrgRole, nil, err) } - if len(roles) != len(roleIDs) { - badIDs := make([]string, 0) - for _, rID := range roleIDs { - bad := true - for _, r := range roles { - if r.ID == rID { - bad = false - break - } - } - if bad { - badIDs = append(badIDs, rID) - } - } - return nil, errors.ErrorData(logutils.StatusInvalid, model.TypeAppOrgRole, &logutils.FieldArgs{"ids": badIDs}) + _, err = model.GetMissingRoleIDs(roles, roleIDs) + if err != nil { + return nil, err } //check if authorized diff --git a/core/auth/auth.go b/core/auth/auth.go index 9fb0d1c5f..3b4759c9d 100644 --- a/core/auth/auth.go +++ b/core/auth/auth.go @@ -1485,21 +1485,9 @@ func (a *Auth) checkGroups(context storage.TransactionContext, appOrg model.Appl if err != nil { return nil, errors.WrapErrorAction(logutils.ActionFind, model.TypeAppOrgGroup, nil, err) } - if len(groups) != len(groupIDs) { - badIDs := make([]string, 0) - for _, gID := range groupIDs { - bad := true - for _, g := range groups { - if g.ID == gID { - bad = false - break - } - } - if bad { - badIDs = append(badIDs, gID) - } - } - return nil, errors.ErrorData(logutils.StatusInvalid, model.TypeAppOrgGroup, &logutils.FieldArgs{"ids": badIDs}) + _, err = model.GetMissingGroupIDs(groups, groupIDs) + if err != nil { + return nil, err } //check assigners diff --git a/core/interfaces.go b/core/interfaces.go index 477dad15f..66411fea3 100644 --- a/core/interfaces.go +++ b/core/interfaces.go @@ -101,8 +101,8 @@ type System interface { SysGetApplication(ID string) (*model.Application, error) SysGetApplications() ([]model.Application, error) - SysCreatePermission(name string, description *string, serviceID *string, assigners *[]string) (*model.Permission, error) - SysUpdatePermission(name string, description *string, serviceID *string, assigners *[]string) (*model.Permission, error) + SysCreatePermission(name string, description string, serviceID string, assigners *[]string) (*model.Permission, error) + SysUpdatePermission(name string, description string, serviceID string, assigners *[]string) (*model.Permission, error) SysGetAppConfigs(appTypeID string, orgID *string, versionNumbers *model.VersionNumbers) ([]model.ApplicationConfig, error) SysGetAppConfig(id string) (*model.ApplicationConfig, error) diff --git a/core/model/application.go b/core/model/application.go index e9241fab3..ceffee00e 100644 --- a/core/model/application.go +++ b/core/model/application.go @@ -428,3 +428,66 @@ func VersionNumbersFromString(version string) *VersionNumbers { return &VersionNumbers{Major: major, Minor: minor, Patch: patch} } + +//GetMissingPermissionNames returns a list of permission names missing from items +func GetMissingPermissionNames(items []Permission, names []string) ([]string, error) { + if len(items) != len(names) { + badNames := make([]string, 0) + for _, name := range names { + bad := true + for _, e := range items { + if e.Name == name { + bad = false + break + } + } + if bad { + badNames = append(badNames, name) + } + } + return nil, errors.ErrorData(logutils.StatusInvalid, TypePermission, &logutils.FieldArgs{"names": badNames}) + } + return nil, nil +} + +//GetMissingRoleIDs returns a list of role IDs missing from items +func GetMissingRoleIDs(items []AppOrgRole, ids []string) ([]string, error) { + if len(items) != len(ids) { + badIDs := make([]string, 0) + for _, id := range ids { + bad := true + for _, e := range items { + if e.ID == id { + bad = false + break + } + } + if bad { + badIDs = append(badIDs, id) + } + } + return nil, errors.ErrorData(logutils.StatusInvalid, TypeAppOrgRole, &logutils.FieldArgs{"ids": badIDs}) + } + return nil, nil +} + +//GetMissingGroupIDs returns a list of group IDs missing from items +func GetMissingGroupIDs(items []AppOrgGroup, ids []string) ([]string, error) { + if len(items) != len(ids) { + badIDs := make([]string, 0) + for _, id := range ids { + bad := true + for _, e := range items { + if e.ID == id { + bad = false + break + } + } + if bad { + badIDs = append(badIDs, id) + } + } + return nil, errors.ErrorData(logutils.StatusInvalid, TypeAppOrgGroup, &logutils.FieldArgs{"ids": badIDs}) + } + return nil, nil +} diff --git a/driver/web/docs/gen/def.yaml b/driver/web/docs/gen/def.yaml index c9fd368f4..cab236064 100644 --- a/driver/web/docs/gen/def.yaml +++ b/driver/web/docs/gen/def.yaml @@ -6279,6 +6279,8 @@ components: _system_req_permissions: required: - name + - description + - service_id type: object properties: name: diff --git a/driver/web/docs/gen/gen_types.go b/driver/web/docs/gen/gen_types.go index 61606de26..7c20c1306 100644 --- a/driver/web/docs/gen/gen_types.go +++ b/driver/web/docs/gen/gen_types.go @@ -1137,9 +1137,9 @@ type SystemReqPermissions struct { // permissions that could assign current permission to accounts Assigners *[]string `json:"assigners,omitempty"` - Description *string `json:"description,omitempty"` + Description string `json:"description"` Name string `json:"name"` - ServiceId *string `json:"service_id,omitempty"` + ServiceId string `json:"service_id"` } // SystemReqUpdateOrganization defines model for _system_req_update_Organization. diff --git a/driver/web/docs/schemas/apis/system/permissions/request/Request.yaml b/driver/web/docs/schemas/apis/system/permissions/request/Request.yaml index ef55255eb..46dbcc949 100644 --- a/driver/web/docs/schemas/apis/system/permissions/request/Request.yaml +++ b/driver/web/docs/schemas/apis/system/permissions/request/Request.yaml @@ -1,5 +1,7 @@ required: - name + - description + - service_id type: object properties: name: From 30c3145bd8a04c75625ed616c95454b07def742a Mon Sep 17 00:00:00 2001 From: Ryan Oberlander Date: Fri, 22 Jul 2022 14:27:34 -0500 Subject: [PATCH 10/32] update changelog [#542] --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f7afad470..b2dc2986b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] +### Fixed +- Update permission should change roles/groups/accounts [#542](https://github.com/rokwire/core-building-block/issues/542) ## [1.24.1] - 2022-07-07 ### Changed From 460d554ec9e6c1ecd3589e39f89e5b34f98b88f2 Mon Sep 17 00:00:00 2001 From: Ryan Oberlander Date: Mon, 1 Aug 2022 14:06:50 -0500 Subject: [PATCH 11/32] update embedded roles in groups in accounts on update role [#516] --- driven/storage/adapter.go | 71 +++++++++++++++++++++------------------ 1 file changed, 38 insertions(+), 33 deletions(-) diff --git a/driven/storage/adapter.go b/driven/storage/adapter.go index 42d8ec93e..5df64777f 100644 --- a/driven/storage/adapter.go +++ b/driven/storage/adapter.go @@ -2561,24 +2561,17 @@ func (sa *Adapter) UpdateAppOrgRole(context TransactionContext, item model.AppOr return errors.ErrorAction(logutils.ActionUpdate, model.TypeAppOrgRole, &logutils.FieldArgs{"id": item.ID, "modified": res.ModifiedCount, "expected": 1}) } - // update all groups that have the role - groupsFilter := bson.D{primitive.E{Key: "roles._id", Value: item.ID}} - groupsUpdate := bson.D{ - primitive.E{Key: "$set", Value: bson.D{ - primitive.E{Key: "roles.$.name", Value: item.Name}, - primitive.E{Key: "roles.$.description", Value: item.Description}, - primitive.E{Key: "roles.$.permissions", Value: item.Permissions}, - primitive.E{Key: "roles.$.system", Value: item.System}, - primitive.E{Key: "roles.$.date_updated", Value: item.DateUpdated}, - }}, - } - - res, err = sa.db.applicationsOrganizationsGroups.UpdateManyWithContext(context, groupsFilter, groupsUpdate, nil) - if err != nil { - return errors.WrapErrorAction(logutils.ActionUpdate, model.TypeAppOrgGroup, &logutils.FieldArgs{"roles._id": item.ID}, err) - } - if res.ModifiedCount != res.MatchedCount { - return errors.ErrorAction(logutils.ActionUpdate, model.TypeAppOrgGroup, &logutils.FieldArgs{"roles._id": item.ID, "modified": res.ModifiedCount, "expected": res.MatchedCount}) + // update all groups that have the role in all collections + key := "roles._id" + groups, err := sa.findAppOrgGroups(context, &key, item.ID, item.AppOrg.ID) + for _, g := range groups { + for ridx, r := range g.Roles { + if r.ID == item.ID { + g.Roles[ridx] = item + err = sa.UpdateAppOrgGroup(context, g) + break + } + } } // update all accounts that have the role @@ -2646,21 +2639,7 @@ func (sa *Adapter) InsertAppOrgRolePermissions(context TransactionContext, roleI //FindAppOrgGroups finds all application organization groups for the provided AppOrg ID func (sa *Adapter) FindAppOrgGroups(appOrgID string) ([]model.AppOrgGroup, error) { - filter := bson.D{primitive.E{Key: "app_org_id", Value: appOrgID}} - var groupsResult []appOrgGroup - err := sa.db.applicationsOrganizationsGroups.Find(filter, &groupsResult, nil) - if err != nil { - return nil, err - } - - appOrg, err := sa.getCachedApplicationOrganizationByKey(appOrgID) - if err != nil { - return nil, errors.WrapErrorData(logutils.StatusMissing, model.TypeOrganization, &logutils.FieldArgs{"app_org_id": appOrg}, err) - } - - result := appOrgGroupsFromStorage(groupsResult, *appOrg) - - return result, nil + return sa.findAppOrgGroups(nil, nil, "", appOrgID) } //FindAppOrgGroupsByIDs finds a set of application organization groups for the provided IDs @@ -2717,6 +2696,32 @@ func (sa *Adapter) FindAppOrgGroup(id string, appOrgID string) (*model.AppOrgGro return &result, nil } +func (sa *Adapter) findAppOrgGroups(context TransactionContext, key *string, id string, appOrgID string) ([]model.AppOrgGroup, error) { + filter := bson.D{primitive.E{Key: "app_org_id", Value: appOrgID}} + if key != nil { + filter = append(filter, primitive.E{Key: *key, Value: id}) + } + var groupsResult []appOrgGroup + var err error + if context != nil { + err = sa.db.applicationsOrganizationsGroups.FindWithContext(context, filter, &groupsResult, nil) + } else { + err = sa.db.applicationsOrganizationsGroups.Find(filter, &groupsResult, nil) + } + if err != nil { + return nil, err + } + + appOrg, err := sa.getCachedApplicationOrganizationByKey(appOrgID) + if err != nil { + return nil, errors.WrapErrorData(logutils.StatusMissing, model.TypeOrganization, &logutils.FieldArgs{"app_org_id": appOrg}, err) + } + + result := appOrgGroupsFromStorage(groupsResult, *appOrg) + + return result, nil +} + //InsertAppOrgGroup inserts a new application organization group func (sa *Adapter) InsertAppOrgGroup(context TransactionContext, item model.AppOrgGroup) error { group := appOrgGroupToStorage(item) From 0e1ebd1f70cf464dab0395b3859e1a8a5141bfa7 Mon Sep 17 00:00:00 2001 From: Ryan Oberlander Date: Mon, 1 Aug 2022 16:05:34 -0500 Subject: [PATCH 12/32] update embedded permissions in roles/groups in accounts [#542] --- driven/storage/adapter.go | 102 ++++++++++++++++++++++++++------------ 1 file changed, 69 insertions(+), 33 deletions(-) diff --git a/driven/storage/adapter.go b/driven/storage/adapter.go index 21bbea93e..f77aeeb37 100644 --- a/driven/storage/adapter.go +++ b/driven/storage/adapter.go @@ -2434,6 +2434,31 @@ func (sa *Adapter) UpdatePermission(context TransactionContext, item model.Permi return errors.ErrorAction(logutils.ActionUpdate, model.TypePermission, &logutils.FieldArgs{"name": item.Name, "modified": res.ModifiedCount, "expected": 1}) } + // update all roles that have the permission + key := "permissions.name" + roles, err := sa.findAppOrgRoles(context, &key, item.Name, "") + for _, r := range roles { + for pidx, p := range r.Permissions { + if p.Name == item.Name { + r.Permissions[pidx] = item + err = sa.UpdateAppOrgRole(context, r) + break + } + } + } + + // update all groups that have the permission + groups, err := sa.findAppOrgGroups(context, &key, item.Name, "") + for _, g := range groups { + for pidx, p := range g.Permissions { + if p.Name == item.Name { + g.Permissions[pidx] = item + err = sa.UpdateAppOrgGroup(context, g) + break + } + } + } + //update all roles, groups, accounts, and service accounts that have the permission dependentsFilter := bson.D{primitive.E{Key: "permissions.name", Value: item.Name}} dependentsUpdate := bson.D{ @@ -2446,18 +2471,6 @@ func (sa *Adapter) UpdatePermission(context TransactionContext, item model.Permi }}, } - //roles - res, err = sa.db.applicationsOrganizationsRoles.UpdateManyWithContext(context, dependentsFilter, dependentsUpdate, nil) - if err = sa.getUpdateManyError(res, err, model.TypeAppOrgRole, "permissions.name", item.Name); err != nil { - return err - } - - //groups - res, err = sa.db.applicationsOrganizationsGroups.UpdateManyWithContext(context, dependentsFilter, dependentsUpdate, nil) - if err = sa.getUpdateManyError(res, err, model.TypeAppOrgGroup, "permissions.name", item.Name); err != nil { - return err - } - //accounts res, err = sa.db.accounts.UpdateManyWithContext(context, dependentsFilter, dependentsUpdate, nil) if err = sa.getUpdateManyError(res, err, model.TypeAccount, "permissions.name", item.Name); err != nil { @@ -2483,22 +2496,7 @@ func (sa *Adapter) DeletePermission(id string) error { //FindAppOrgRoles finds all application organization roles fora given AppOrg ID func (sa *Adapter) FindAppOrgRoles(appOrgID string) ([]model.AppOrgRole, error) { - rolesFilter := bson.D{primitive.E{Key: "app_org_id", Value: appOrgID}} - var rolesResult []appOrgRole - err := sa.db.applicationsOrganizationsRoles.Find(rolesFilter, &rolesResult, nil) - if err != nil { - return nil, err - } - - //get the application organization from the cached ones - appOrg, err := sa.getCachedApplicationOrganizationByKey(appOrgID) - if err != nil { - return nil, errors.WrapErrorData(logutils.StatusMissing, model.TypeOrganization, &logutils.FieldArgs{"app_org_id": appOrg}, err) - } - - result := appOrgRolesFromStorage(rolesResult, *appOrg) - - return result, nil + return sa.findAppOrgRoles(nil, nil, "", appOrgID) } //FindAppOrgRolesByIDs finds a set of application organization roles for the provided IDs @@ -2556,6 +2554,38 @@ func (sa *Adapter) FindAppOrgRole(id string, appOrgID string) (*model.AppOrgRole return &result, nil } +func (sa *Adapter) findAppOrgRoles(context TransactionContext, key *string, id string, appOrgID string) ([]model.AppOrgRole, error) { + filter := bson.D{} + errFields := logutils.FieldArgs{} + if key != nil { + filter = append(filter, primitive.E{Key: *key, Value: id}) + errFields[*key] = id + } + if appOrgID != "" { + filter = append(filter, primitive.E{Key: "app_org_id", Value: appOrgID}) + errFields["app_org_id"] = appOrgID + } + var rolesResult []appOrgRole + var err error + if context != nil { + err = sa.db.applicationsOrganizationsRoles.FindWithContext(context, filter, &rolesResult, nil) + } else { + err = sa.db.applicationsOrganizationsRoles.Find(filter, &rolesResult, nil) + } + if err != nil { + return nil, errors.WrapErrorAction(logutils.ActionFind, model.TypeAppOrgRole, &errFields, err) + } + + appOrg, err := sa.getCachedApplicationOrganizationByKey(appOrgID) + if err != nil || appOrg == nil { + return nil, errors.WrapErrorData(logutils.StatusMissing, model.TypeApplicationOrganization, &logutils.FieldArgs{"app_org_id": appOrg}, err) + } + + result := appOrgRolesFromStorage(rolesResult, *appOrg) + + return result, nil +} + //InsertAppOrgRole inserts a new application organization role func (sa *Adapter) InsertAppOrgRole(context TransactionContext, item model.AppOrgRole) error { role := appOrgRoleToStorage(item) @@ -2597,7 +2627,7 @@ func (sa *Adapter) UpdateAppOrgRole(context TransactionContext, item model.AppOr return errors.ErrorAction(logutils.ActionUpdate, model.TypeAppOrgRole, &logutils.FieldArgs{"id": item.ID, "modified": res.ModifiedCount, "expected": 1}) } - // update all groups that have the role in all collections + // update all groups that have the role key := "roles._id" groups, err := sa.findAppOrgGroups(context, &key, item.ID, item.AppOrg.ID) for _, g := range groups { @@ -2733,9 +2763,15 @@ func (sa *Adapter) FindAppOrgGroup(id string, appOrgID string) (*model.AppOrgGro } func (sa *Adapter) findAppOrgGroups(context TransactionContext, key *string, id string, appOrgID string) ([]model.AppOrgGroup, error) { - filter := bson.D{primitive.E{Key: "app_org_id", Value: appOrgID}} + filter := bson.D{} + errFields := logutils.FieldArgs{} if key != nil { filter = append(filter, primitive.E{Key: *key, Value: id}) + errFields[*key] = id + } + if appOrgID != "" { + filter = append(filter, primitive.E{Key: "app_org_id", Value: appOrgID}) + errFields["app_org_id"] = appOrgID } var groupsResult []appOrgGroup var err error @@ -2745,12 +2781,12 @@ func (sa *Adapter) findAppOrgGroups(context TransactionContext, key *string, id err = sa.db.applicationsOrganizationsGroups.Find(filter, &groupsResult, nil) } if err != nil { - return nil, err + return nil, errors.WrapErrorAction(logutils.ActionFind, model.TypeAppOrgGroup, &errFields, err) } appOrg, err := sa.getCachedApplicationOrganizationByKey(appOrgID) - if err != nil { - return nil, errors.WrapErrorData(logutils.StatusMissing, model.TypeOrganization, &logutils.FieldArgs{"app_org_id": appOrg}, err) + if err != nil || appOrg == nil { + return nil, errors.WrapErrorData(logutils.StatusMissing, model.TypeApplicationOrganization, &logutils.FieldArgs{"app_org_id": appOrg}, err) } result := appOrgGroupsFromStorage(groupsResult, *appOrg) From 6c21035b7da1453e027ff4bc54f2160646d79b9c Mon Sep 17 00:00:00 2001 From: Ryan Oberlander Date: Mon, 1 Aug 2022 17:02:40 -0500 Subject: [PATCH 13/32] fix empty app_org_id bug --- driven/storage/adapter.go | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/driven/storage/adapter.go b/driven/storage/adapter.go index f77aeeb37..becb47c3d 100644 --- a/driven/storage/adapter.go +++ b/driven/storage/adapter.go @@ -2565,6 +2565,7 @@ func (sa *Adapter) findAppOrgRoles(context TransactionContext, key *string, id s filter = append(filter, primitive.E{Key: "app_org_id", Value: appOrgID}) errFields["app_org_id"] = appOrgID } + var rolesResult []appOrgRole var err error if context != nil { @@ -2576,13 +2577,17 @@ func (sa *Adapter) findAppOrgRoles(context TransactionContext, key *string, id s return nil, errors.WrapErrorAction(logutils.ActionFind, model.TypeAppOrgRole, &errFields, err) } - appOrg, err := sa.getCachedApplicationOrganizationByKey(appOrgID) - if err != nil || appOrg == nil { - return nil, errors.WrapErrorData(logutils.StatusMissing, model.TypeApplicationOrganization, &logutils.FieldArgs{"app_org_id": appOrg}, err) + var result []model.AppOrgRole + if len(rolesResult) > 0 { + appOrg, err := sa.getCachedApplicationOrganizationByKey(rolesResult[0].AppOrgID) + if err != nil || appOrg == nil { + return nil, errors.WrapErrorData(logutils.StatusMissing, model.TypeApplicationOrganization, &logutils.FieldArgs{"app_org_id": rolesResult[0].AppOrgID}, err) + } + result = appOrgRolesFromStorage(rolesResult, *appOrg) + } else { + result = make([]model.AppOrgRole, 0) } - result := appOrgRolesFromStorage(rolesResult, *appOrg) - return result, nil } @@ -2773,6 +2778,7 @@ func (sa *Adapter) findAppOrgGroups(context TransactionContext, key *string, id filter = append(filter, primitive.E{Key: "app_org_id", Value: appOrgID}) errFields["app_org_id"] = appOrgID } + var groupsResult []appOrgGroup var err error if context != nil { @@ -2784,13 +2790,17 @@ func (sa *Adapter) findAppOrgGroups(context TransactionContext, key *string, id return nil, errors.WrapErrorAction(logutils.ActionFind, model.TypeAppOrgGroup, &errFields, err) } - appOrg, err := sa.getCachedApplicationOrganizationByKey(appOrgID) - if err != nil || appOrg == nil { - return nil, errors.WrapErrorData(logutils.StatusMissing, model.TypeApplicationOrganization, &logutils.FieldArgs{"app_org_id": appOrg}, err) + var result []model.AppOrgGroup + if len(groupsResult) > 0 { + appOrg, err := sa.getCachedApplicationOrganizationByKey(groupsResult[0].AppOrgID) + if err != nil || appOrg == nil { + return nil, errors.WrapErrorData(logutils.StatusMissing, model.TypeApplicationOrganization, &logutils.FieldArgs{"app_org_id": groupsResult[0].AppOrgID}, err) + } + result = appOrgGroupsFromStorage(groupsResult, *appOrg) + } else { + result = make([]model.AppOrgGroup, 0) } - result := appOrgGroupsFromStorage(groupsResult, *appOrg) - return result, nil } From 79e7ffd1869ba2a251c0dcce6423955874d8ad11 Mon Sep 17 00:00:00 2001 From: Ryan Oberlander Date: Tue, 2 Aug 2022 09:48:25 -0500 Subject: [PATCH 14/32] only use WithContext collection functions --- driven/storage/adapter.go | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/driven/storage/adapter.go b/driven/storage/adapter.go index df16e1422..55a7d2ca2 100644 --- a/driven/storage/adapter.go +++ b/driven/storage/adapter.go @@ -2366,12 +2366,7 @@ func (sa *Adapter) findAppOrgRoles(context TransactionContext, key *string, id s } var rolesResult []appOrgRole - var err error - if context != nil { - err = sa.db.applicationsOrganizationsRoles.FindWithContext(context, filter, &rolesResult, nil) - } else { - err = sa.db.applicationsOrganizationsRoles.Find(filter, &rolesResult, nil) - } + err := sa.db.applicationsOrganizationsRoles.FindWithContext(context, filter, &rolesResult, nil) if err != nil { return nil, errors.WrapErrorAction(logutils.ActionFind, model.TypeAppOrgRole, &errFields, err) } @@ -2569,12 +2564,7 @@ func (sa *Adapter) findAppOrgGroups(context TransactionContext, key *string, id } var groupsResult []appOrgGroup - var err error - if context != nil { - err = sa.db.applicationsOrganizationsGroups.FindWithContext(context, filter, &groupsResult, nil) - } else { - err = sa.db.applicationsOrganizationsGroups.Find(filter, &groupsResult, nil) - } + err := sa.db.applicationsOrganizationsGroups.FindWithContext(context, filter, &groupsResult, nil) if err != nil { return nil, errors.WrapErrorAction(logutils.ActionFind, model.TypeAppOrgGroup, &errFields, err) } From 544994dd687b1e92ed8cd71d886d20f8c715be85 Mon Sep 17 00:00:00 2001 From: Ryan Oberlander Date: Tue, 2 Aug 2022 09:52:10 -0500 Subject: [PATCH 15/32] only use WithContext collection functions --- driven/storage/adapter.go | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/driven/storage/adapter.go b/driven/storage/adapter.go index 054fe6c6d..c70c87048 100644 --- a/driven/storage/adapter.go +++ b/driven/storage/adapter.go @@ -2491,12 +2491,7 @@ func (sa *Adapter) findAppOrgGroups(context TransactionContext, key *string, id filter = append(filter, primitive.E{Key: *key, Value: id}) } var groupsResult []appOrgGroup - var err error - if context != nil { - err = sa.db.applicationsOrganizationsGroups.FindWithContext(context, filter, &groupsResult, nil) - } else { - err = sa.db.applicationsOrganizationsGroups.Find(filter, &groupsResult, nil) - } + err := sa.db.applicationsOrganizationsGroups.FindWithContext(context, filter, &groupsResult, nil) if err != nil { return nil, err } From ab8e863807a26502ec1a5e7a1d28c6944f0c7746 Mon Sep 17 00:00:00 2001 From: Ryan Oberlander Date: Tue, 2 Aug 2022 12:35:01 -0500 Subject: [PATCH 16/32] perform transaction on missing context --- driven/storage/adapter.go | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/driven/storage/adapter.go b/driven/storage/adapter.go index 55a7d2ca2..0af62f2b6 100644 --- a/driven/storage/adapter.go +++ b/driven/storage/adapter.go @@ -2215,6 +2215,17 @@ func (sa *Adapter) UpdatePermission(context TransactionContext, item model.Permi //TODO //This will be slow operation as we keep a copy of the entity in the users collection without index. //Maybe we need to up the transaction timeout for this operation because of this. + if context == nil { + transaction := func(newContext TransactionContext) error { + return sa.updatePermission(newContext, item) + } + return sa.PerformTransaction(transaction) + } + + return sa.updatePermission(context, item) +} + +func (sa *Adapter) updatePermission(context TransactionContext, item model.Permission) error { if context == nil { return errors.ErrorData(logutils.StatusMissing, "transaction context", nil) } @@ -2271,7 +2282,6 @@ func (sa *Adapter) UpdatePermission(context TransactionContext, item model.Permi primitive.E{Key: "permissions.$.service_id", Value: item.ServiceID}, primitive.E{Key: "permissions.$.assigners", Value: item.Assigners}, primitive.E{Key: "permissions.$.date_updated", Value: item.DateUpdated}, - // primitive.E{Key: "date_updated", Value: item.DateUpdated}, }}, } From 9532b29158e738513cf39616a6a0adce754f0e5d Mon Sep 17 00:00:00 2001 From: Ryan Oberlander Date: Tue, 2 Aug 2022 12:43:36 -0500 Subject: [PATCH 17/32] perform transaction on missing context --- driven/storage/adapter.go | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/driven/storage/adapter.go b/driven/storage/adapter.go index c70c87048..b468df2a8 100644 --- a/driven/storage/adapter.go +++ b/driven/storage/adapter.go @@ -2332,9 +2332,16 @@ func (sa *Adapter) InsertAppOrgRole(context TransactionContext, item model.AppOr //UpdateAppOrgRole updates application organization role func (sa *Adapter) UpdateAppOrgRole(context TransactionContext, item model.AppOrgRole) error { if context == nil { - return errors.ErrorData(logutils.StatusMissing, "transaction context", nil) + transaction := func(newContext TransactionContext) error { + return sa.updateAppOrgRole(newContext, item) + } + return sa.PerformTransaction(transaction) } + return sa.updateAppOrgRole(context, item) +} + +func (sa *Adapter) updateAppOrgRole(context TransactionContext, item model.AppOrgRole) error { // update role roleFilter := bson.D{primitive.E{Key: "_id", Value: item.ID}} roleUpdate := bson.D{ @@ -2520,9 +2527,16 @@ func (sa *Adapter) InsertAppOrgGroup(context TransactionContext, item model.AppO //UpdateAppOrgGroup updates application organization group func (sa *Adapter) UpdateAppOrgGroup(context TransactionContext, item model.AppOrgGroup) error { if context == nil { - return errors.ErrorData(logutils.StatusMissing, "transaction context", nil) + transaction := func(newContext TransactionContext) error { + return sa.updateAppOrgGroup(newContext, item) + } + return sa.PerformTransaction(transaction) } + return sa.updateAppOrgGroup(context, item) +} + +func (sa *Adapter) updateAppOrgGroup(context TransactionContext, item model.AppOrgGroup) error { roles := appOrgRolesToStorage(item.Roles) // update group From 137ff240aa821227d02d8d26f1e97e086497e1a1 Mon Sep 17 00:00:00 2001 From: Ryan Oberlander Date: Tue, 2 Aug 2022 12:44:25 -0500 Subject: [PATCH 18/32] remove unnecessary nil context check --- driven/storage/adapter.go | 4 ---- 1 file changed, 4 deletions(-) diff --git a/driven/storage/adapter.go b/driven/storage/adapter.go index 0af62f2b6..f4fca55d2 100644 --- a/driven/storage/adapter.go +++ b/driven/storage/adapter.go @@ -2226,10 +2226,6 @@ func (sa *Adapter) UpdatePermission(context TransactionContext, item model.Permi } func (sa *Adapter) updatePermission(context TransactionContext, item model.Permission) error { - if context == nil { - return errors.ErrorData(logutils.StatusMissing, "transaction context", nil) - } - //update permission permissionFilter := bson.D{primitive.E{Key: "name", Value: item.Name}} permissionUpdate := bson.D{ From f98ed9109e3d2e9831e6c51b1624fc15fc590ff4 Mon Sep 17 00:00:00 2001 From: Ryan Oberlander Date: Tue, 2 Aug 2022 17:13:41 -0500 Subject: [PATCH 19/32] add bbs and tps update permissions APIs, not implemented yet [#475] --- .secrets.baseline | 4 +- core/apis.go | 24 +++++- core/app_bbs.go | 12 +++ core/app_tps.go | 31 ++++++++ core/interfaces.go | 7 ++ core/model/application.go | 1 + driver/web/adapter.go | 5 ++ driver/web/apis_bbs.go | 27 +++++++ driver/web/apis_tps.go | 33 +++++++++ driver/web/conversions_application.go | 21 +++++- driver/web/docs/gen/def.yaml | 74 +++++++++++++++++++ driver/web/docs/gen/gen_types.go | 16 +++- driver/web/docs/index.yaml | 6 ++ .../web/docs/resources/bbs/permissions.yaml | 34 +++++++++ .../web/docs/resources/tps/permissions.yaml | 34 +++++++++ driver/web/docs/resources/tps/test.yaml | 12 +++ .../docs/schemas/application/Permission.yaml | 4 + 17 files changed, 339 insertions(+), 6 deletions(-) create mode 100644 core/app_tps.go create mode 100644 driver/web/docs/resources/bbs/permissions.yaml create mode 100644 driver/web/docs/resources/tps/permissions.yaml create mode 100644 driver/web/docs/resources/tps/test.yaml diff --git a/.secrets.baseline b/.secrets.baseline index cd7a72183..91b921af3 100644 --- a/.secrets.baseline +++ b/.secrets.baseline @@ -115,7 +115,7 @@ "filename": "core/apis.go", "hashed_secret": "f776bc8b6836b3498c27139f23f5d64e4041af0f", "is_verified": false, - "line_number": 169 + "line_number": 170 } ], "core/auth/apis.go": [ @@ -279,5 +279,5 @@ } ] }, - "generated_at": "2022-07-26T15:53:15Z" + "generated_at": "2022-08-02T22:13:33Z" } diff --git a/core/apis.go b/core/apis.go index 85cbd65e4..7f8150dcf 100644 --- a/core/apis.go +++ b/core/apis.go @@ -33,6 +33,7 @@ type APIs struct { Administration Administration //expose to the drivers adapters Encryption Encryption //expose to the drivers adapters BBs BBs //expose to the drivers adapters + TPs TPs //expose to the drivers adapters System System //expose to the drivers adapters Auth auth.APIs //expose to the drivers auth @@ -232,11 +233,12 @@ func NewCoreAPIs(env string, version string, build string, storage Storage, auth administrationImpl := &administrationImpl{app: &application} encryptionImpl := &encryptionImpl{app: &application} bbsImpl := &bbsImpl{app: &application} + tpsImpl := &tpsImpl{app: &application} systemImpl := &systemImpl{app: &application} //+ auth coreAPIs := APIs{Services: servicesImpl, Administration: administrationImpl, Encryption: encryptionImpl, - BBs: bbsImpl, System: systemImpl, Auth: auth, app: &application, systemAppTypeIdentifier: systemInitSettings["app_type_id"], + BBs: bbsImpl, TPs: tpsImpl, System: systemImpl, Auth: auth, app: &application, systemAppTypeIdentifier: systemInitSettings["app_type_id"], systemAppTypeName: systemInitSettings["app_type_name"], systemAPIKey: systemInitSettings["api_key"], systemAccountEmail: systemInitSettings["email"], systemAccountPassword: systemInitSettings["password"], logger: logger} @@ -413,6 +415,26 @@ func (s *bbsImpl) BBsGetTest() string { return s.app.bbsGetTest() } +func (s *bbsImpl) BBsUpdatePermissions(permissions []model.Permission, accountID string) ([]model.Permission, error) { + return s.app.bbsUpdatePermissions(permissions, accountID) +} + +/// + +//tpsImpl + +type tpsImpl struct { + app *application +} + +func (s *tpsImpl) TPsGetTest() string { + return s.app.tpsGetTest() +} + +func (s *tpsImpl) TPsUpdatePermissions(permissions []model.Permission, accountID string) ([]model.Permission, error) { + return s.app.tpsUpdatePermissions(permissions, accountID) +} + /// //systemImpl diff --git a/core/app_bbs.go b/core/app_bbs.go index 2335f7718..533c440e2 100644 --- a/core/app_bbs.go +++ b/core/app_bbs.go @@ -14,6 +14,18 @@ package core +import ( + "core-building-block/core/model" + + "github.com/rokwire/logging-library-go/errors" + "github.com/rokwire/logging-library-go/logutils" +) + func (app *application) bbsGetTest() string { return "BBs - test" } + +func (app *application) bbsUpdatePermissions(permissions []model.Permission, accountID string) ([]model.Permission, error) { + //TODO: implement + return nil, errors.New(logutils.Unimplemented) +} diff --git a/core/app_tps.go b/core/app_tps.go new file mode 100644 index 000000000..fbe48af3d --- /dev/null +++ b/core/app_tps.go @@ -0,0 +1,31 @@ +// Copyright 2022 Board of Trustees of the University of Illinois. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package core + +import ( + "core-building-block/core/model" + + "github.com/rokwire/logging-library-go/errors" + "github.com/rokwire/logging-library-go/logutils" +) + +func (app *application) tpsGetTest() string { + return "TPs - test" +} + +func (app *application) tpsUpdatePermissions(permissions []model.Permission, accountID string) ([]model.Permission, error) { + //TODO: implement + return nil, errors.New(logutils.Unimplemented) +} diff --git a/core/interfaces.go b/core/interfaces.go index f9b1b2b1a..7ea5b8667 100644 --- a/core/interfaces.go +++ b/core/interfaces.go @@ -84,6 +84,13 @@ type Encryption interface { //BBs exposes users related APIs used by the platform building blocks type BBs interface { BBsGetTest() string + BBsUpdatePermissions(permissions []model.Permission, accountID string) ([]model.Permission, error) +} + +//TPs exposes users related APIs used by third-party services +type TPs interface { + TPsGetTest() string + TPsUpdatePermissions(permissions []model.Permission, accountID string) ([]model.Permission, error) } //System exposes system APIs for the driver adapters diff --git a/core/model/application.go b/core/model/application.go index b6da2c45b..6d87711da 100644 --- a/core/model/application.go +++ b/core/model/application.go @@ -63,6 +63,7 @@ type Permission struct { ServiceID string `bson:"service_id"` Assigners []string `bson:"assigners"` + Inactive bool `bson:"inactive"` DateCreated time.Time `bson:"date_created"` DateUpdated *time.Time `bson:"date_updated"` diff --git a/driver/web/adapter.go b/driver/web/adapter.go index 5adeac601..9bcfcbd2f 100644 --- a/driver/web/adapter.go +++ b/driver/web/adapter.go @@ -184,16 +184,21 @@ func (we Adapter) Start() { bbsSubrouter.HandleFunc("/service-account/{id}", we.wrapFunc(we.bbsApisHandler.getServiceAccountParams, nil)).Methods("POST") //Public bbsSubrouter.HandleFunc("/access-token", we.wrapFunc(we.bbsApisHandler.getServiceAccessToken, nil)).Methods("POST") //Public bbsSubrouter.HandleFunc("/access-tokens", we.wrapFunc(we.bbsApisHandler.getServiceAccessTokens, nil)).Methods("POST") //Public + + bbsSubrouter.HandleFunc("/permissions", we.wrapFunc(we.bbsApisHandler.updatePermissions, we.auth.bbs.authenticated)).Methods("PUT") /// ///third-party services /// tpsSubrouter := subRouter.PathPrefix("/tps").Subrouter() tpsSubrouter.HandleFunc("/service-regs", we.wrapFunc(we.tpsApisHandler.getServiceRegistrations, nil)).Methods("GET") //Public + tpsSubrouter.HandleFunc("/test", we.wrapFunc(we.tpsApisHandler.getTest, nil)).Methods("GET") //Public tpsSubrouter.HandleFunc("/auth-keys", we.wrapFunc(we.tpsApisHandler.getAuthKeys, nil)).Methods("GET") //Public tpsSubrouter.HandleFunc("/service-account/{id}", we.wrapFunc(we.tpsApisHandler.getServiceAccountParams, nil)).Methods("POST") //Public tpsSubrouter.HandleFunc("/access-token", we.wrapFunc(we.tpsApisHandler.getServiceAccessToken, nil)).Methods("POST") //Public tpsSubrouter.HandleFunc("/access-tokens", we.wrapFunc(we.tpsApisHandler.getServiceAccessTokens, nil)).Methods("POST") //Public + + tpsSubrouter.HandleFunc("/permissions", we.wrapFunc(we.tpsApisHandler.updatePermissions, we.auth.tps.authenticated)).Methods("PUT") /// ///system /// diff --git a/driver/web/apis_bbs.go b/driver/web/apis_bbs.go index 2b8daf333..89de40fc8 100644 --- a/driver/web/apis_bbs.go +++ b/driver/web/apis_bbs.go @@ -20,6 +20,7 @@ import ( Def "core-building-block/driver/web/docs/gen" "core-building-block/utils" "encoding/json" + "io/ioutil" "net/http" "strings" @@ -162,6 +163,32 @@ func (h BBsApisHandler) getServiceAccessTokens(l *logs.Log, r *http.Request, cla return l.HttpResponseSuccessJSON(respData) } +func (h BBsApisHandler) updatePermissions(l *logs.Log, r *http.Request, claims *tokenauth.Claims) logs.HttpResponse { + data, err := ioutil.ReadAll(r.Body) + if err != nil { + return l.HttpResponseErrorData(logutils.StatusInvalid, logutils.TypeRequestBody, nil, err, http.StatusBadRequest, false) + } + + var requestData []Def.Permission + err = json.Unmarshal(data, &requestData) + if err != nil { + return l.HttpResponseErrorAction(logutils.ActionUnmarshal, model.TypeAPIKey, nil, err, http.StatusBadRequest, true) + } + + permissions := applicationPermissionsFromDef(requestData) + permissions, err = h.coreAPIs.BBs.BBsUpdatePermissions(permissions, claims.Subject) + if err != nil { + return l.HttpResponseErrorAction(logutils.ActionUpdate, model.TypePermission, nil, err, http.StatusInternalServerError, true) + } + + respData, err := json.Marshal(permissions) + if err != nil { + return l.HttpResponseErrorAction(logutils.ActionMarshal, logutils.MessageDataType("service access tokens response"), nil, err, http.StatusInternalServerError, false) + } + + return l.HttpResponseSuccessJSON(respData) +} + //NewBBsApisHandler creates new bbs Handler instance func NewBBsApisHandler(coreAPIs *core.APIs) BBsApisHandler { return BBsApisHandler{coreAPIs: coreAPIs} diff --git a/driver/web/apis_tps.go b/driver/web/apis_tps.go index 237f5fefa..ea8d6da15 100644 --- a/driver/web/apis_tps.go +++ b/driver/web/apis_tps.go @@ -20,6 +20,7 @@ import ( Def "core-building-block/driver/web/docs/gen" "core-building-block/utils" "encoding/json" + "io/ioutil" "net/http" "strings" @@ -36,6 +37,12 @@ type TPSApisHandler struct { coreAPIs *core.APIs } +func (h TPSApisHandler) getTest(l *logs.Log, r *http.Request, claims *tokenauth.Claims) logs.HttpResponse { + res := h.coreAPIs.TPs.TPsGetTest() + + return l.HttpResponseSuccessMessage(res) +} + func (h TPSApisHandler) getServiceRegistrations(l *logs.Log, r *http.Request, claims *tokenauth.Claims) logs.HttpResponse { serviceIDsParam := r.URL.Query().Get("ids") if serviceIDsParam == "" { @@ -171,6 +178,32 @@ func (h TPSApisHandler) getServiceAccessTokens(l *logs.Log, r *http.Request, cla return l.HttpResponseSuccessJSON(respData) } +func (h TPSApisHandler) updatePermissions(l *logs.Log, r *http.Request, claims *tokenauth.Claims) logs.HttpResponse { + data, err := ioutil.ReadAll(r.Body) + if err != nil { + return l.HttpResponseErrorData(logutils.StatusInvalid, logutils.TypeRequestBody, nil, err, http.StatusBadRequest, false) + } + + var requestData []Def.Permission + err = json.Unmarshal(data, &requestData) + if err != nil { + return l.HttpResponseErrorAction(logutils.ActionUnmarshal, model.TypeAPIKey, nil, err, http.StatusBadRequest, true) + } + + permissions := applicationPermissionsFromDef(requestData) + permissions, err = h.coreAPIs.TPs.TPsUpdatePermissions(permissions, claims.Subject) + if err != nil { + return l.HttpResponseErrorAction(logutils.ActionUpdate, model.TypePermission, nil, err, http.StatusInternalServerError, true) + } + + respData, err := json.Marshal(permissions) + if err != nil { + return l.HttpResponseErrorAction(logutils.ActionMarshal, logutils.MessageDataType("service access tokens response"), nil, err, http.StatusInternalServerError, false) + } + + return l.HttpResponseSuccessJSON(respData) +} + //NewTPSApisHandler creates new tps Handler instance func NewTPSApisHandler(coreAPIs *core.APIs) TPSApisHandler { return TPSApisHandler{coreAPIs: coreAPIs} diff --git a/driver/web/conversions_application.go b/driver/web/conversions_application.go index 0d9caa164..6ae00a24a 100644 --- a/driver/web/conversions_application.go +++ b/driver/web/conversions_application.go @@ -89,7 +89,18 @@ func applicationPermissionToDef(item model.Permission) Def.Permission { dateUpdated = &formatted } - return Def.Permission{Id: item.ID, Name: item.Name, Description: &item.Description, ServiceId: &item.ServiceID, Assigners: &assigners, DateCreated: &dateCreated, DateUpdated: dateUpdated} + return Def.Permission{Id: item.ID, Name: item.Name, Description: item.Description, ServiceId: item.ServiceID, Assigners: &assigners, DateCreated: &dateCreated, DateUpdated: dateUpdated} +} + +func applicationPermissionFromDef(item Def.Permission) model.Permission { + assigners := make([]string, 0) + if item.Assigners != nil { + for _, a := range *item.Assigners { + assigners = append(assigners, a) + } + } + + return model.Permission{Name: item.Name, Description: item.Description, Assigners: assigners} } func applicationPermissionsToDef(items []model.Permission) []Def.Permission { @@ -100,6 +111,14 @@ func applicationPermissionsToDef(items []model.Permission) []Def.Permission { return result } +func applicationPermissionsFromDef(items []Def.Permission) []model.Permission { + result := make([]model.Permission, len(items)) + for i, item := range items { + result[i] = applicationPermissionFromDef(item) + } + return result +} + //AppOrgRole func appOrgRoleToDef(item model.AppOrgRole) Def.AppOrgRole { permissions := applicationPermissionsToDef(item.Permissions) diff --git a/driver/web/docs/gen/def.yaml b/driver/web/docs/gen/def.yaml index d28de2232..0acef390d 100644 --- a/driver/web/docs/gen/def.yaml +++ b/driver/web/docs/gen/def.yaml @@ -2814,6 +2814,41 @@ paths: description: Unauthorized '500': description: Internal error + /bbs/permissions: + put: + tags: + - BBs + summary: Updates service permissions + description: | + Updates the permissions used by a service + + **Auth:** Requires service auth token + security: + - bearerAuth: [] + requestBody: + description: Service permission list + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/Permission' + required: true + responses: + '200': + description: Success + content: + application/json: null + schema: + type: array + items: + $ref: '#/components/schemas/Permission' + '400': + description: Bad request + '401': + description: Unauthorized + '500': + description: Internal error /tps/service-regs: get: tags: @@ -3018,6 +3053,41 @@ paths: description: Unauthorized '500': description: Internal error + /tps/permissions: + put: + tags: + - Third-Party Services + summary: Updates service permissions + description: | + Updates the permissions used by a service + + **Auth:** Requires service auth token + security: + - bearerAuth: [] + requestBody: + description: Service permission list + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/Permission' + required: true + responses: + '200': + description: Success + content: + application/json: null + schema: + type: array + items: + $ref: '#/components/schemas/Permission' + '400': + description: Bad request + '401': + description: Unauthorized + '500': + description: Internal error /system/global-config: get: tags: @@ -4561,15 +4631,19 @@ components: required: - id - name + - description + - service_id type: object properties: id: + readOnly: true type: string name: type: string description: type: string service_id: + readOnly: true type: string assigners: type: array diff --git a/driver/web/docs/gen/gen_types.go b/driver/web/docs/gen/gen_types.go index 3e78b2f88..076bec3c9 100644 --- a/driver/web/docs/gen/gen_types.go +++ b/driver/web/docs/gen/gen_types.go @@ -516,10 +516,10 @@ type Permission struct { Assigners *[]string `json:"assigners,omitempty"` DateCreated *string `json:"date_created,omitempty"` DateUpdated *string `json:"date_updated,omitempty"` - Description *string `json:"description,omitempty"` + Description string `json:"description"` Id string `json:"id"` Name string `json:"name"` - ServiceId *string `json:"service_id,omitempty"` + ServiceId string `json:"service_id"` } // Profile defines model for Profile. @@ -1319,6 +1319,9 @@ type PostBbsAccessTokenJSONBody ServicesReqServiceAccountsAccessToken // PostBbsAccessTokensJSONBody defines parameters for PostBbsAccessTokens. type PostBbsAccessTokensJSONBody ServicesReqServiceAccountsAccessTokens +// PutBbsPermissionsJSONBody defines parameters for PutBbsPermissions. +type PutBbsPermissionsJSONBody []Permission + // PostBbsServiceAccountIdJSONBody defines parameters for PostBbsServiceAccountId. type PostBbsServiceAccountIdJSONBody ServicesReqServiceAccountsParams @@ -1635,6 +1638,9 @@ type PostTpsAccessTokenJSONBody ServicesReqServiceAccountsAccessToken // PostTpsAccessTokensJSONBody defines parameters for PostTpsAccessTokens. type PostTpsAccessTokensJSONBody ServicesReqServiceAccountsAccessTokens +// PutTpsPermissionsJSONBody defines parameters for PutTpsPermissions. +type PutTpsPermissionsJSONBody []Permission + // PostTpsServiceAccountIdJSONBody defines parameters for PostTpsServiceAccountId. type PostTpsServiceAccountIdJSONBody ServicesReqServiceAccountsParams @@ -1719,6 +1725,9 @@ type PostBbsAccessTokenJSONRequestBody PostBbsAccessTokenJSONBody // PostBbsAccessTokensJSONRequestBody defines body for PostBbsAccessTokens for application/json ContentType. type PostBbsAccessTokensJSONRequestBody PostBbsAccessTokensJSONBody +// PutBbsPermissionsJSONRequestBody defines body for PutBbsPermissions for application/json ContentType. +type PutBbsPermissionsJSONRequestBody PutBbsPermissionsJSONBody + // PostBbsServiceAccountIdJSONRequestBody defines body for PostBbsServiceAccountId for application/json ContentType. type PostBbsServiceAccountIdJSONRequestBody PostBbsServiceAccountIdJSONBody @@ -1854,6 +1863,9 @@ type PostTpsAccessTokenJSONRequestBody PostTpsAccessTokenJSONBody // PostTpsAccessTokensJSONRequestBody defines body for PostTpsAccessTokens for application/json ContentType. type PostTpsAccessTokensJSONRequestBody PostTpsAccessTokensJSONBody +// PutTpsPermissionsJSONRequestBody defines body for PutTpsPermissions for application/json ContentType. +type PutTpsPermissionsJSONRequestBody PutTpsPermissionsJSONBody + // PostTpsServiceAccountIdJSONRequestBody defines body for PostTpsServiceAccountId for application/json ContentType. type PostTpsServiceAccountIdJSONRequestBody PostTpsServiceAccountIdJSONBody diff --git a/driver/web/docs/index.yaml b/driver/web/docs/index.yaml index e888bf0cd..dd2008d50 100644 --- a/driver/web/docs/index.yaml +++ b/driver/web/docs/index.yaml @@ -141,8 +141,12 @@ paths: $ref: "./resources/bbs/access-token.yaml" /bbs/access-tokens: $ref: "./resources/bbs/access-tokens.yaml" + /bbs/permissions: + $ref: "./resources/bbs/permissions.yaml" #third-party services + /tps/test: + $ref: "./resources/tps/test.yaml" /tps/service-regs: $ref: "./resources/tps/service-regs.yaml" /tps/auth-keys: @@ -153,6 +157,8 @@ paths: $ref: "./resources/tps/access-token.yaml" /tps/access-tokens: $ref: "./resources/tps/access-tokens.yaml" + /tps/permissions: + $ref: "./resources/tps/permissions.yaml" #system /system/global-config: diff --git a/driver/web/docs/resources/bbs/permissions.yaml b/driver/web/docs/resources/bbs/permissions.yaml new file mode 100644 index 000000000..c1e035663 --- /dev/null +++ b/driver/web/docs/resources/bbs/permissions.yaml @@ -0,0 +1,34 @@ +put: + tags: + - BBs + summary: Updates service permissions + description: | + Updates the permissions used by a service + + **Auth:** Requires service auth token + security: + - bearerAuth: [] + requestBody: + description: Service permission list + content: + application/json: + schema: + type: array + items: + $ref: "../../schemas/application/Permission.yaml" + required: true + responses: + 200: + description: Success + content: + application/json: + schema: + type: array + items: + $ref: "../../schemas/application/Permission.yaml" + 400: + description: Bad request + 401: + description: Unauthorized + 500: + description: Internal error \ No newline at end of file diff --git a/driver/web/docs/resources/tps/permissions.yaml b/driver/web/docs/resources/tps/permissions.yaml new file mode 100644 index 000000000..e866eb933 --- /dev/null +++ b/driver/web/docs/resources/tps/permissions.yaml @@ -0,0 +1,34 @@ +put: + tags: + - Third-Party Services + summary: Updates service permissions + description: | + Updates the permissions used by a service + + **Auth:** Requires service auth token + security: + - bearerAuth: [] + requestBody: + description: Service permission list + content: + application/json: + schema: + type: array + items: + $ref: "../../schemas/application/Permission.yaml" + required: true + responses: + 200: + description: Success + content: + application/json: + schema: + type: array + items: + $ref: "../../schemas/application/Permission.yaml" + 400: + description: Bad request + 401: + description: Unauthorized + 500: + description: Internal error \ No newline at end of file diff --git a/driver/web/docs/resources/tps/test.yaml b/driver/web/docs/resources/tps/test.yaml new file mode 100644 index 000000000..5966a1595 --- /dev/null +++ b/driver/web/docs/resources/tps/test.yaml @@ -0,0 +1,12 @@ +get: + tags: + - TPs + summary: Test API.. + responses: + 200: + description: Success + content: + text/plain: + schema: + type: string + example: Echooo \ No newline at end of file diff --git a/driver/web/docs/schemas/application/Permission.yaml b/driver/web/docs/schemas/application/Permission.yaml index 3682f2b97..0028824df 100644 --- a/driver/web/docs/schemas/application/Permission.yaml +++ b/driver/web/docs/schemas/application/Permission.yaml @@ -1,15 +1,19 @@ required: - id - name + - description + - service_id type: object properties: id: + readOnly: true type: string name: type: string description: type: string service_id: + readOnly: true type: string assigners: type: array From d1df9c107034fe165e5ceb49c7557a0b38c2269c Mon Sep 17 00:00:00 2001 From: Ryan Oberlander Date: Tue, 2 Aug 2022 17:14:55 -0500 Subject: [PATCH 20/32] update API docs --- driver/web/docs/gen/def.yaml | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/driver/web/docs/gen/def.yaml b/driver/web/docs/gen/def.yaml index 0acef390d..00d4ec4d0 100644 --- a/driver/web/docs/gen/def.yaml +++ b/driver/web/docs/gen/def.yaml @@ -2849,6 +2849,19 @@ paths: description: Unauthorized '500': description: Internal error + /tps/test: + get: + tags: + - TPs + summary: Test API.. + responses: + '200': + description: Success + content: + text/plain: + schema: + type: string + example: Echooo /tps/service-regs: get: tags: From 2199f1a5787327e87d9652d69a20cd860af50640 Mon Sep 17 00:00:00 2001 From: Ryan Oberlander Date: Wed, 3 Aug 2022 16:42:22 -0500 Subject: [PATCH 21/32] implement update service permissions API, need to handle permission inactive flag [#475] --- .secrets.baseline | 6 +- core/apis.go | 12 +- core/app.go | 6 +- core/app_administration.go | 2 +- core/app_bbs.go | 145 +++++++++- core/app_system.go | 2 +- core/auth/anonymous.go | 4 +- core/auth/apis.go | 152 +++++----- core/auth/auth.go | 34 +-- core/auth/auth_type_email.go | 8 +- core/auth/auth_type_firebase.go | 2 +- core/auth/auth_type_oidc.go | 6 +- core/auth/auth_type_phone.go | 2 +- core/auth/auth_type_saml.go | 2 +- core/auth/auth_type_signature.go | 4 +- core/auth/auth_type_username.go | 2 +- core/auth/interfaces.go | 20 +- core/auth/mfa_email.go | 2 +- core/auth/mfa_phone.go | 2 +- core/auth/mfa_recovery.go | 4 +- core/auth/mfa_totp.go | 4 +- core/auth/service_signature.go | 2 +- core/auth/service_static_token.go | 4 +- core/interfaces.go | 24 +- core/mocks/Storage.go | 49 +++- core/model/application.go | 79 +++-- core/model/auth.go | 46 +-- core/model/config.go | 4 +- core/model/user.go | 74 ++--- driven/emailer/adapter.go | 6 +- driven/profilebb/adapter.go | 6 +- driven/storage/adapter.go | 336 +++++++++++----------- driven/storage/collection.go | 2 +- driven/storage/conversions_application.go | 12 +- driven/storage/conversions_auth.go | 4 +- driven/storage/conversions_user.go | 16 +- driver/web/adapter.go | 8 +- driver/web/apis_admin.go | 26 +- driver/web/apis_bbs.go | 6 +- driver/web/apis_default.go | 8 +- driver/web/apis_enc.go | 6 +- driver/web/apis_services.go | 18 +- driver/web/apis_system.go | 30 +- driver/web/apis_tps.go | 4 +- driver/web/auth.go | 34 +-- driver/web/conversions_application.go | 10 +- driver/web/conversions_auth.go | 4 +- driver/web/conversions_user.go | 12 +- driver/web/utils.go | 2 +- utils/utils.go | 22 +- 50 files changed, 749 insertions(+), 526 deletions(-) diff --git a/.secrets.baseline b/.secrets.baseline index 91b921af3..7c63b409b 100644 --- a/.secrets.baseline +++ b/.secrets.baseline @@ -124,7 +124,7 @@ "filename": "core/auth/apis.go", "hashed_secret": "4d55af37dbbb6a42088d917caa1ca25428ec42c9", "is_verified": false, - "line_number": 1918 + "line_number": 1938 } ], "core/auth/auth.go": [ @@ -133,7 +133,7 @@ "filename": "core/auth/auth.go", "hashed_secret": "4d55af37dbbb6a42088d917caa1ca25428ec42c9", "is_verified": false, - "line_number": 2386 + "line_number": 2388 } ], "core/auth/auth_type_email.go": [ @@ -279,5 +279,5 @@ } ] }, - "generated_at": "2022-08-02T22:13:33Z" + "generated_at": "2022-08-03T21:42:17Z" } diff --git a/core/apis.go b/core/apis.go index 7f8150dcf..eeaa35bec 100644 --- a/core/apis.go +++ b/core/apis.go @@ -27,7 +27,7 @@ import ( "github.com/rokwire/logging-library-go/logutils" ) -//APIs exposes to the drivers adapters access to the core functionality +// APIs exposes to the drivers adapters access to the core functionality type APIs struct { Services Services //expose to the drivers adapters Administration Administration //expose to the drivers adapters @@ -49,7 +49,7 @@ type APIs struct { logger *logs.Logger } -//Start starts the core part of the application +// Start starts the core part of the application func (c *APIs) Start() { c.app.start() c.Auth.Start() @@ -60,12 +60,12 @@ func (c *APIs) Start() { } } -//AddListener adds application listener +// AddListener adds application listener func (c *APIs) AddListener(listener ApplicationListener) { c.app.addListener(listener) } -//GetVersion gives the service version +// GetVersion gives the service version func (c *APIs) GetVersion() string { return c.app.version } @@ -222,7 +222,7 @@ func (c *APIs) storeSystemData() error { return err } -//NewCoreAPIs creates new CoreAPIs +// NewCoreAPIs creates new CoreAPIs func NewCoreAPIs(env string, version string, build string, storage Storage, auth auth.APIs, systemInitSettings map[string]string, logger *logs.Logger) *APIs { //add application instance listeners := []ApplicationListener{} @@ -247,7 +247,7 @@ func NewCoreAPIs(env string, version string, build string, storage Storage, auth /// -//servicesImpl +// servicesImpl type servicesImpl struct { app *application } diff --git a/core/app.go b/core/app.go index cd2b75465..8f3e3e51d 100644 --- a/core/app.go +++ b/core/app.go @@ -22,7 +22,7 @@ import ( "github.com/rokwire/logging-library-go/logutils" ) -//application represents the core application code based on hexagonal architecture +// application represents the core application code based on hexagonal architecture type application struct { env string version string @@ -35,14 +35,14 @@ type application struct { auth auth.APIs } -//start starts the core part of the application +// start starts the core part of the application func (app *application) start() { //set storage listener storageListener := StorageListener{app: app} app.storage.RegisterStorageListener(&storageListener) } -//addListener adds application listener +// addListener adds application listener func (app *application) addListener(listener ApplicationListener) { //TODO //logs.Println("Application -> AddListener") diff --git a/core/app_administration.go b/core/app_administration.go index cacc477ae..03753657b 100644 --- a/core/app_administration.go +++ b/core/app_administration.go @@ -539,7 +539,7 @@ func (app *application) admGetApplicationPermissions(appID string, orgID string, } //2. find permissions by the service ids - permissions, err := app.storage.FindPermissionsByServiceIDs(appOrg.ServicesIDs) + permissions, err := app.storage.FindPermissionsByServiceIDs(nil, appOrg.ServicesIDs) if err != nil { return nil, errors.WrapErrorAction(logutils.ActionGet, model.TypePermission, nil, err) } diff --git a/core/app_bbs.go b/core/app_bbs.go index 533c440e2..c109ad60e 100644 --- a/core/app_bbs.go +++ b/core/app_bbs.go @@ -16,7 +16,11 @@ package core import ( "core-building-block/core/model" + "core-building-block/driven/storage" + "core-building-block/utils" + "time" + "github.com/google/uuid" "github.com/rokwire/logging-library-go/errors" "github.com/rokwire/logging-library-go/logutils" ) @@ -26,6 +30,143 @@ func (app *application) bbsGetTest() string { } func (app *application) bbsUpdatePermissions(permissions []model.Permission, accountID string) ([]model.Permission, error) { - //TODO: implement - return nil, errors.New(logutils.Unimplemented) + //find the service registration record + serviceReg, err := app.storage.FindServiceRegByServiceAccountID(accountID) + if err != nil { + return nil, errors.WrapErrorAction(logutils.ActionFind, model.TypeServiceAccount, nil, err) + } + if serviceReg == nil { + return nil, errors.ErrorData(logutils.StatusMissing, model.TypeServiceReg, &logutils.FieldArgs{"service_account_id": accountID}) + } + + servicePermissions := make([]model.Permission, 0) + transaction := func(context storage.TransactionContext) error { + newNames := make([]string, len(permissions)) + newNamesMap := make(map[string]model.Permission) + allAssigners := make([]string, 0) + for i, p := range permissions { + newNames[i] = p.Name + newNamesMap[p.Name] = p + allAssigners = append(allAssigners, p.Assigners...) + } + + //1. check if any incoming permissions have the same name as another service's permission + invalidNames := make(map[string][]string) + existingPermissions, err := app.storage.FindPermissionsByName(context, newNames) + if err != nil { + return err + } + for _, p := range existingPermissions { + if p.ServiceID != serviceReg.Registration.ServiceID { + if invalidNames[p.ServiceID] == nil { + invalidNames[p.ServiceID] = []string{} + } + invalidNames[p.ServiceID] = append(invalidNames[p.ServiceID], p.Name) + } + } + if len(invalidNames) > 0 { + return errors.ErrorData(logutils.StatusInvalid, model.TypePermission, &logutils.FieldArgs{"names": invalidNames}) + } + + //2. get the list of existing assigner permissions from the incoming permission list + existingAssigners, err := app.storage.FindPermissionsByName(context, allAssigners) + if err != nil { + return err + } + + //3. get current list of service permissions + serviceIDs := []string{serviceReg.Registration.ServiceID} + currentPermissions, err := app.storage.FindPermissionsByServiceIDs(context, serviceIDs) + if err != nil { + return errors.WrapErrorAction(logutils.ActionFind, model.TypePermission, &logutils.FieldArgs{"service_id": serviceReg.Registration.ServiceID}, err) + } + + currentNames := make([]string, len(currentPermissions)) + currentNamesMap := make(map[string]model.Permission) + for i, p := range currentPermissions { + currentNames[i] = p.Name + currentNamesMap[p.Name] = p + } + + now := time.Now().UTC() + added, removed, unchanged := utils.StringListDiff(newNames, currentNames) + + //4. if added, create a new permission + for _, name := range added { + permission := newNamesMap[name] + err = app.validateAssigners(permission.Assigners, existingAssigners, permissions) + if err != nil { + return err + } + + permission.ID = uuid.NewString() + permission.ServiceID = serviceReg.Registration.ServiceID + permission.Inactive = false + permission.DateCreated = now + err = app.storage.InsertPermission(context, permission) + if err != nil { + return errors.WrapErrorAction(logutils.ActionInsert, model.TypePermission, &logutils.FieldArgs{"name": name}, err) + } + + servicePermissions = append(servicePermissions, permission) + } + + //5. if removed, mark existing permission as inactive + for _, name := range removed { + permission := currentNamesMap[name] + if !permission.Inactive { + permission.Inactive = true + permission.DateUpdated = &now + err = app.storage.UpdatePermission(context, permission) + if err != nil { + return errors.WrapErrorAction(logutils.ActionUpdate, model.TypePermission, &logutils.FieldArgs{"name": name}, err) + } + } + } + + //6. if unchanged, update permission data if necessary + for _, name := range unchanged { + currentPermission := currentNamesMap[name] + newPermission := newNamesMap[name] + err = app.validateAssigners(newPermission.Assigners, existingAssigners, permissions) + if err != nil { + return err + } + + updated := currentPermission.Inactive || (newPermission.Description != currentPermission.Description) || !utils.DeepEqual(newPermission.Assigners, currentPermission.Assigners) + if updated { + newPermission.ServiceID = serviceReg.Registration.ServiceID + newPermission.Inactive = false + newPermission.DateUpdated = &now + err = app.storage.UpdatePermission(context, newPermission) + if err != nil { + return err + } + } + + servicePermissions = append(servicePermissions, newPermission) + } + + return nil + } + + err = app.storage.PerformTransaction(transaction) + if err != nil { + return nil, err + } + + return servicePermissions, nil +} + +func (app *application) validateAssigners(assigners []string, existing []model.Permission, incoming []model.Permission) error { + //assigners must already exist or be included in incoming permissions + missing := model.GetMissingPermissionNames(existing, assigners) + if len(missing) > 0 { + missing = model.GetMissingPermissionNames(incoming, missing) + if len(missing) > 0 { + return errors.ErrorData(logutils.StatusInvalid, model.TypePermission, &logutils.FieldArgs{"names": missing}) + } + } + + return nil } diff --git a/core/app_system.go b/core/app_system.go index cbf2b134e..caaad7ebf 100644 --- a/core/app_system.go +++ b/core/app_system.go @@ -205,7 +205,7 @@ func (app *application) sysUpdatePermission(name string, description *string, se permission.Assigners = *assigners } - err = app.storage.UpdatePermission(permission) + err = app.storage.UpdatePermission(nil, permission) if err != nil { return nil, err } diff --git a/core/auth/anonymous.go b/core/auth/anonymous.go index 2d71503ae..a58572c53 100644 --- a/core/auth/anonymous.go +++ b/core/auth/anonymous.go @@ -29,7 +29,7 @@ const ( typeAnonymousCreds logutils.MessageDataType = "anonymous creds" ) -//API Key implementation of authType +// API Key implementation of authType type anonymousAuthImpl struct { auth *Auth authType string @@ -57,7 +57,7 @@ func (a *anonymousAuthImpl) checkCredentials(creds string) (string, map[string]i return anonymousID, params, nil } -//initAnonymousAuth initializes and registers a new API key auth instance +// initAnonymousAuth initializes and registers a new API key auth instance func initAnonymousAuth(auth *Auth) (*anonymousAuthImpl, error) { anonymous := &anonymousAuthImpl{auth: auth, authType: AuthTypeAnonymous} diff --git a/core/auth/apis.go b/core/auth/apis.go index 594685d99..c0198a332 100644 --- a/core/auth/apis.go +++ b/core/auth/apis.go @@ -32,7 +32,7 @@ import ( "github.com/rokwire/logging-library-go/logs" ) -//Start starts the auth service +// Start starts the auth service func (a *Auth) Start() { storageListener := StorageListener{auth: a} a.storage.RegisterStorageListener(&storageListener) @@ -40,13 +40,14 @@ func (a *Auth) Start() { go a.setupDeleteSessionsTimer() } -//GetHost returns the host/issuer of the auth service +// GetHost returns the host/issuer of the auth service func (a *Auth) GetHost() string { return a.host } -//Login logs a user in a specific application using the specified credentials and authentication method. -//The authentication method must be one of the supported for the application. +// Login logs a user in a specific application using the specified credentials and authentication method. +// The authentication method must be one of the supported for the application. +// // Input: // ipAddress (string): Client's IP address // deviceType (string): "mobile" or "web" or "desktop" etc @@ -167,7 +168,8 @@ func (a *Auth) Login(ipAddress string, deviceType string, deviceOS *string, devi return nil, &model.LoginSession{ID: loginSession.ID, Identifier: loginSession.Identifier, Params: responseParams, State: loginSession.State}, mfaTypes, nil } -//Logout logouts an account from app/org +// Logout logouts an account from app/org +// // Input: // allSessions (bool): If to remove the current session only or all sessions for the app/org for the account func (a *Auth) Logout(appID string, orgID string, currentAccountID string, sessionID string, allSessions bool, l *logs.Log) error { @@ -185,8 +187,9 @@ func (a *Auth) Logout(appID string, orgID string, currentAccountID string, sessi return nil } -//AccountExists checks if a user is already registered -//The authentication method must be one of the supported for the application. +// AccountExists checks if a user is already registered +// The authentication method must be one of the supported for the application. +// // Input: // authenticationType (string): Name of the authentication method for provided creds (eg. "email", "username", "illinois_oidc") // userIdentifier (string): User identifier for the specified auth type @@ -204,8 +207,9 @@ func (a *Auth) AccountExists(authenticationType string, userIdentifier string, a return account != nil, nil } -//CanSignIn checks if a user can sign in -//The authentication method must be one of the supported for the application. +// CanSignIn checks if a user can sign in +// The authentication method must be one of the supported for the application. +// // Input: // authenticationType (string): Name of the authentication method for provided creds (eg. "email", "username", "illinois_oidc") // userIdentifier (string): User identifier for the specified auth type @@ -223,8 +227,9 @@ func (a *Auth) CanSignIn(authenticationType string, userIdentifier string, apiKe return a.canSignIn(account, authTypeID, userIdentifier), nil } -//CanLink checks if a user can link a new auth type -//The authentication method must be one of the supported for the application. +// CanLink checks if a user can link a new auth type +// The authentication method must be one of the supported for the application. +// // Input: // authenticationType (string): Name of the authentication method for provided creds (eg. "email", "username", "illinois_oidc") // userIdentifier (string): User identifier for the specified auth type @@ -247,7 +252,8 @@ func (a *Auth) CanLink(authenticationType string, userIdentifier string, apiKey return true, nil } -//Refresh refreshes an access token using a refresh token +// Refresh refreshes an access token using a refresh token +// // Input: // refreshToken (string): Refresh token // apiKey (string): API key to validate the specified app @@ -407,7 +413,8 @@ func (a *Auth) Refresh(refreshToken string, apiKey string, l *logs.Log) (*model. return loginSession, nil } -//GetLoginURL returns a pre-formatted login url for SSO providers +// GetLoginURL returns a pre-formatted login url for SSO providers +// // Input: // authenticationType (string): Name of the authentication method for provided creds (eg. "email", "username", "illinois_oidc") // appTypeIdentifier (string): Identifier of the app type/client that the user is logging in from @@ -446,8 +453,9 @@ func (a *Auth) GetLoginURL(authenticationType string, appTypeIdentifier string, return loginURL, params, nil } -//LoginMFA verifies a code sent by a user as a final login step for enrolled accounts. -//The MFA type must be one of the supported for the application. +// LoginMFA verifies a code sent by a user as a final login step for enrolled accounts. +// The MFA type must be one of the supported for the application. +// // Input: // apiKey (string): API key to validate the specified app // accountID (string): ID of account user is trying to access @@ -550,7 +558,7 @@ func (a *Auth) LoginMFA(apiKey string, accountID string, sessionID string, ident return nil, loginSession, nil } -//CreateAdminAccount creates an account for a new admin user +// CreateAdminAccount creates an account for a new admin user func (a *Auth) CreateAdminAccount(authenticationType string, appID string, orgID string, identifier string, profile model.Profile, permissions []string, roleIDs []string, groupIDs []string, creatorPermissions []string, l *logs.Log) (*model.Account, map[string]interface{}, error) { //TODO: add admin authentication policies that specify which auth types may be used for each app org @@ -611,7 +619,7 @@ func (a *Auth) CreateAdminAccount(authenticationType string, appID string, orgID return newAccount, params, nil } -//UpdateAdminAccount updates an existing user's account with new permissions, roles, and groups +// UpdateAdminAccount updates an existing user's account with new permissions, roles, and groups func (a *Auth) UpdateAdminAccount(authenticationType string, appID string, orgID string, identifier string, permissions []string, roleIDs []string, groupIDs []string, updaterPermissions []string, l *logs.Log) (*model.Account, map[string]interface{}, error) { //TODO: when elevating existing accounts to application level admin, need to enforce any authentication policies set up for the app org @@ -792,7 +800,7 @@ func (a *Auth) UpdateAdminAccount(authenticationType string, appID string, orgID return updatedAccount, params, nil } -//VerifyCredential verifies credential (checks the verification code in the credentials collection) +// VerifyCredential verifies credential (checks the verification code in the credentials collection) func (a *Auth) VerifyCredential(id string, verification string, l *logs.Log) error { credential, err := a.storage.FindCredential(nil, id) if err != nil || credential == nil { @@ -831,14 +839,16 @@ func (a *Auth) VerifyCredential(id string, verification string, l *logs.Log) err return nil } -//UpdateCredential updates the credential object with the new value +// UpdateCredential updates the credential object with the new value +// // Input: // accountID: id of the associated account to reset // accountAuthTypeID (string): id of the AccountAuthType // params: specific params for the different auth types // Returns: // error: if any -//TODO: Clear login sessions using old creds +// +// TODO: Clear login sessions using old creds // Handle refresh tokens when applicable func (a *Auth) UpdateCredential(accountID string, accountAuthTypeID string, params string, l *logs.Log) error { //Get the user credential from account auth type in accounts collection @@ -879,14 +889,16 @@ func (a *Auth) UpdateCredential(accountID string, accountAuthTypeID string, para return nil } -//ResetForgotCredential resets forgot credential +// ResetForgotCredential resets forgot credential +// // Input: // credsID: id of the credential object // resetCode: code from the reset link // params: specific params for the different auth types // Returns: // error: if any -//TODO: Clear login sessions using old creds +// +// TODO: Clear login sessions using old creds // Handle refresh tokens when applicable func (a *Auth) ResetForgotCredential(credsID string, resetCode string, params string, l *logs.Log) error { credential, err := a.storage.FindCredential(nil, credsID) @@ -921,7 +933,8 @@ func (a *Auth) ResetForgotCredential(credsID string, resetCode string, params st return nil } -//ForgotCredential initiate forgot credential process (generates a reset link and sends to the given identifier for email auth type) +// ForgotCredential initiate forgot credential process (generates a reset link and sends to the given identifier for email auth type) +// // Input: // authenticationType (string): Name of the authentication method for provided creds (eg. "email", "username", "illinois_oidc") // identifier: identifier of the account auth type @@ -992,7 +1005,7 @@ func (a *Auth) ForgotCredential(authenticationType string, appTypeIdentifier str return nil } -//SendVerifyCredential sends the verification code to the identifier +// SendVerifyCredential sends the verification code to the identifier func (a *Auth) SendVerifyCredential(authenticationType string, appTypeIdentifier string, orgID string, apiKey string, identifier string, l *logs.Log) error { //validate if the provided auth type is supported by the provided application and organization authType, _, appOrg, err := a.validateAuthType(authenticationType, appTypeIdentifier, orgID) @@ -1037,8 +1050,9 @@ func (a *Auth) SendVerifyCredential(authenticationType string, appTypeIdentifier return nil } -//VerifyMFA verifies a code sent by a user as a final MFA enrollment step. -//The MFA type must be one of the supported for the application. +// VerifyMFA verifies a code sent by a user as a final MFA enrollment step. +// The MFA type must be one of the supported for the application. +// // Input: // accountID (string): ID of account for which user is trying to verify MFA // identifier (string): Email, phone, or TOTP device name @@ -1129,7 +1143,8 @@ func (a *Auth) VerifyMFA(accountID string, identifier string, mfaType string, mf return nil, nil, nil } -//GetMFATypes gets all MFA types set up for an account +// GetMFATypes gets all MFA types set up for an account +// // Input: // accountID (string): Account ID to find MFA types // Returns: @@ -1143,7 +1158,8 @@ func (a *Auth) GetMFATypes(accountID string) ([]model.MFAType, error) { return mfa, nil } -//AddMFAType adds a form of MFA to an account +// AddMFAType adds a form of MFA to an account +// // Input: // accountID (string): Account ID to add MFA // identifier (string): Email, phone, or TOTP device name @@ -1169,7 +1185,8 @@ func (a *Auth) AddMFAType(accountID string, identifier string, mfaType string) ( return newMfa, nil } -//RemoveMFAType removes a form of MFA from an account +// RemoveMFAType removes a form of MFA from an account +// // Input: // accountID (string): Account ID to remove MFA // identifier (string): Email, phone, or TOTP device name @@ -1210,7 +1227,7 @@ func (a *Auth) RemoveMFAType(accountID string, identifier string, mfaType string return nil } -//GetServiceAccountParams returns a list of app, org pairs a service account has access to +// GetServiceAccountParams returns a list of app, org pairs a service account has access to func (a *Auth) GetServiceAccountParams(accountID string, firstParty bool, r *sigauth.Request, l *logs.Log) ([]model.AppOrgPair, error) { accounts, _, err := a.checkServiceAccountCreds(r, &accountID, firstParty, false, l) if err != nil { @@ -1233,7 +1250,7 @@ func (a *Auth) GetServiceAccountParams(accountID string, firstParty bool, r *sig return appOrgPairs, nil } -//GetServiceAccessToken returns an access token for a non-human client +// GetServiceAccessToken returns an access token for a non-human client func (a *Auth) GetServiceAccessToken(firstParty bool, r *sigauth.Request, l *logs.Log) (string, error) { accounts, authType, err := a.checkServiceAccountCreds(r, nil, firstParty, true, l) if err != nil { @@ -1248,7 +1265,7 @@ func (a *Auth) GetServiceAccessToken(firstParty bool, r *sigauth.Request, l *log return accessToken, nil } -//GetAllServiceAccessTokens returns an access token for each app, org pair a service account has access to +// GetAllServiceAccessTokens returns an access token for each app, org pair a service account has access to func (a *Auth) GetAllServiceAccessTokens(firstParty bool, r *sigauth.Request, l *logs.Log) (map[model.AppOrgPair]string, error) { accounts, authType, err := a.checkServiceAccountCreds(r, nil, firstParty, false, l) if err != nil { @@ -1268,7 +1285,7 @@ func (a *Auth) GetAllServiceAccessTokens(firstParty bool, r *sigauth.Request, l return accessTokens, nil } -//GetServiceAccounts gets all service accounts matching a search +// GetServiceAccounts gets all service accounts matching a search func (a *Auth) GetServiceAccounts(params map[string]interface{}) ([]model.ServiceAccount, error) { serviceAccounts, err := a.storage.FindServiceAccounts(params) if err != nil { @@ -1278,7 +1295,7 @@ func (a *Auth) GetServiceAccounts(params map[string]interface{}) ([]model.Servic return serviceAccounts, nil } -//RegisterServiceAccount registers a service account +// RegisterServiceAccount registers a service account func (a *Auth) RegisterServiceAccount(accountID *string, fromAppID *string, fromOrgID *string, name *string, appID string, orgID string, permissions *[]string, firstParty *bool, creds []model.ServiceAccountCredential, assignerPermissions []string, l *logs.Log) (*model.ServiceAccount, error) { var newAccount *model.ServiceAccount @@ -1359,7 +1376,7 @@ func (a *Auth) RegisterServiceAccount(accountID *string, fromAppID *string, from return newAccount, nil } -//DeregisterServiceAccount deregisters a service account +// DeregisterServiceAccount deregisters a service account func (a *Auth) DeregisterServiceAccount(accountID string) error { // delete all service account instances matching accountID err := a.storage.DeleteServiceAccounts(accountID) @@ -1370,7 +1387,7 @@ func (a *Auth) DeregisterServiceAccount(accountID string) error { return nil } -//GetServiceAccountInstance gets a service account instance +// GetServiceAccountInstance gets a service account instance func (a *Auth) GetServiceAccountInstance(accountID string, appID string, orgID string) (*model.ServiceAccount, error) { serviceAccount, err := a.storage.FindServiceAccount(nil, accountID, appID, orgID) if err != nil { @@ -1380,7 +1397,7 @@ func (a *Auth) GetServiceAccountInstance(accountID string, appID string, orgID s return serviceAccount, nil } -//UpdateServiceAccountInstance updates a service account instance +// UpdateServiceAccountInstance updates a service account instance func (a *Auth) UpdateServiceAccountInstance(id string, appID string, orgID string, name string, permissions []string, assignerPermissions []string) (*model.ServiceAccount, error) { updatedAccount, err := a.constructServiceAccount(id, name, appID, orgID, permissions, false, assignerPermissions) if err != nil { @@ -1395,7 +1412,7 @@ func (a *Auth) UpdateServiceAccountInstance(id string, appID string, orgID strin return updatedAccount, nil } -//DeregisterServiceAccountInstance deregisters a service account instance +// DeregisterServiceAccountInstance deregisters a service account instance func (a *Auth) DeregisterServiceAccountInstance(id string, appID string, orgID string) error { err := a.storage.DeleteServiceAccount(id, appID, orgID) if err != nil { @@ -1405,7 +1422,7 @@ func (a *Auth) DeregisterServiceAccountInstance(id string, appID string, orgID s return nil } -//AddServiceAccountCredential adds a credential to a service account +// AddServiceAccountCredential adds a credential to a service account func (a *Auth) AddServiceAccountCredential(accountID string, creds *model.ServiceAccountCredential, l *logs.Log) (*model.ServiceAccountCredential, error) { if creds == nil { return nil, errors.ErrorData(logutils.StatusMissing, model.TypeServiceAccountCredential, nil) @@ -1431,7 +1448,7 @@ func (a *Auth) AddServiceAccountCredential(accountID string, creds *model.Servic return creds, nil } -//RemoveServiceAccountCredential removes a credential from a service account +// RemoveServiceAccountCredential removes a credential from a service account func (a *Auth) RemoveServiceAccountCredential(accountID string, credID string) error { err := a.storage.DeleteServiceAccountCredential(accountID, credID) if err != nil { @@ -1441,7 +1458,8 @@ func (a *Auth) RemoveServiceAccountCredential(accountID string, credID string) e return nil } -//AuthorizeService returns a scoped token for the specified service and the service registration record if authorized or +// AuthorizeService returns a scoped token for the specified service and the service registration record if authorized or +// // the service registration record if not. Passing "approvedScopes" will update the service authorization for this user and // return a scoped access token which reflects this change. // Input: @@ -1489,7 +1507,7 @@ func (a *Auth) AuthorizeService(claims tokenauth.Claims, serviceID string, appro return token, authorization.Scopes, nil, nil } -//GetAdminToken returns an admin token for the specified application +// GetAdminToken returns an admin token for the specified application func (a *Auth) GetAdminToken(claims tokenauth.Claims, appID string, l *logs.Log) (string, error) { //verify that the provided appID is valid for the organization appOrg, err := a.storage.FindApplicationOrganization(appID, claims.OrgID) @@ -1505,8 +1523,9 @@ func (a *Auth) GetAdminToken(claims tokenauth.Claims, appID string, l *logs.Log) return a.buildAccessToken(adminClaims, claims.Permissions, claims.Scope) } -//LinkAccountAuthType links new credentials to an existing account. -//The authentication method must be one of the supported for the application. +// LinkAccountAuthType links new credentials to an existing account. +// The authentication method must be one of the supported for the application. +// // Input: // accountID (string): ID of the account to link the creds to // authenticationType (string): Name of the authentication method for provided creds (eg. "email", "username", "illinois_oidc") @@ -1556,8 +1575,9 @@ func (a *Auth) LinkAccountAuthType(accountID string, authenticationType string, return &message, account, nil } -//UnlinkAccountAuthType unlinks credentials from an existing account. -//The authentication method must be one of the supported for the application. +// UnlinkAccountAuthType unlinks credentials from an existing account. +// The authentication method must be one of the supported for the application. +// // Input: // accountID (string): ID of the account to unlink creds from // authenticationType (string): Name of the authentication method of account auth type to unlink @@ -1570,7 +1590,7 @@ func (a *Auth) UnlinkAccountAuthType(accountID string, authenticationType string return a.unlinkAccountAuthType(accountID, authenticationType, appTypeIdentifier, identifier, l) } -//DeleteAccount deletes an account for the given id +// DeleteAccount deletes an account for the given id func (a *Auth) DeleteAccount(id string) error { transaction := func(context storage.TransactionContext) error { //1. first find the account record @@ -1593,7 +1613,7 @@ func (a *Auth) DeleteAccount(id string) error { return a.storage.PerformTransaction(transaction) } -//InitializeSystemAccount initializes the first system account +// InitializeSystemAccount initializes the first system account func (a *Auth) InitializeSystemAccount(context storage.TransactionContext, authType model.AuthType, appOrg model.ApplicationOrganization, allSystemPermission string, email string, password string, l *logs.Log) (string, error) { //auth type @@ -1614,7 +1634,7 @@ func (a *Auth) InitializeSystemAccount(context storage.TransactionContext, authT return accountAuthType.Account.ID, nil } -//GrantAccountPermissions grants new permissions to an account after validating the assigner has required permissions +// GrantAccountPermissions grants new permissions to an account after validating the assigner has required permissions func (a *Auth) GrantAccountPermissions(context storage.TransactionContext, account *model.Account, permissionNames []string, assignerPermissions []string) error { //check if there is data if account == nil { @@ -1649,7 +1669,7 @@ func (a *Auth) GrantAccountPermissions(context storage.TransactionContext, accou return nil } -//CheckPermissions loads permissions by names from storage and checks that they are assignable and valid for the given appOrg +// CheckPermissions loads permissions by names from storage and checks that they are assignable and valid for the given appOrg func (a *Auth) CheckPermissions(context storage.TransactionContext, appOrg *model.ApplicationOrganization, permissionNames []string, assignerPermissions []string) ([]model.Permission, error) { if appOrg == nil { return nil, errors.ErrorData(logutils.StatusInvalid, model.TypeApplicationOrganization, nil) @@ -1691,7 +1711,7 @@ func (a *Auth) CheckPermissions(context storage.TransactionContext, appOrg *mode return permissions, nil } -//CheckRevokedPermissions loads permissions by names from storage and checks that they are revokable +// CheckRevokedPermissions loads permissions by names from storage and checks that they are revokable func (a *Auth) CheckRevokedPermissions(context storage.TransactionContext, appOrg *model.ApplicationOrganization, permissionNames []string, assignerPermissions []string) error { if appOrg == nil { return errors.ErrorData(logutils.StatusInvalid, model.TypeApplicationOrganization, nil) @@ -1719,7 +1739,7 @@ func (a *Auth) CheckRevokedPermissions(context storage.TransactionContext, appOr return nil } -//GrantAccountRoles grants new roles to an account after validating the assigner has required permissions +// GrantAccountRoles grants new roles to an account after validating the assigner has required permissions func (a *Auth) GrantAccountRoles(context storage.TransactionContext, account *model.Account, roleIDs []string, assignerPermissions []string) error { //check if there is data if account == nil { @@ -1755,7 +1775,7 @@ func (a *Auth) GrantAccountRoles(context storage.TransactionContext, account *mo return nil } -//CheckRoles loads appOrg roles by IDs from storage and checks that they are assignable +// CheckRoles loads appOrg roles by IDs from storage and checks that they are assignable func (a *Auth) CheckRoles(context storage.TransactionContext, appOrg *model.ApplicationOrganization, roleIDs []string, assignerPermissions []string) ([]model.AppOrgRole, error) { if appOrg == nil { return nil, errors.ErrorData(logutils.StatusInvalid, model.TypeApplicationOrganization, nil) @@ -1794,7 +1814,7 @@ func (a *Auth) CheckRoles(context storage.TransactionContext, appOrg *model.Appl return roles, nil } -//CheckRevokedRoles loads appOrg roles by IDs from storage and checks that they are revocable +// CheckRevokedRoles loads appOrg roles by IDs from storage and checks that they are revocable func (a *Auth) CheckRevokedRoles(context storage.TransactionContext, appOrg *model.ApplicationOrganization, roleIDs []string, assignerPermissions []string) error { if appOrg == nil { return errors.ErrorData(logutils.StatusInvalid, model.TypeApplicationOrganization, nil) @@ -1818,7 +1838,7 @@ func (a *Auth) CheckRevokedRoles(context storage.TransactionContext, appOrg *mod return nil } -//GrantAccountGroups grants new groups to an account after validating the assigner has required permissions +// GrantAccountGroups grants new groups to an account after validating the assigner has required permissions func (a *Auth) GrantAccountGroups(context storage.TransactionContext, account *model.Account, groupIDs []string, assignerPermissions []string) error { //check if there is data if account == nil { @@ -1854,12 +1874,12 @@ func (a *Auth) GrantAccountGroups(context storage.TransactionContext, account *m return nil } -//GetServiceRegistrations retrieves all service registrations +// GetServiceRegistrations retrieves all service registrations func (a *Auth) GetServiceRegistrations(serviceIDs []string) ([]model.ServiceReg, error) { return a.storage.FindServiceRegs(serviceIDs) } -//RegisterService creates a new service registration +// RegisterService creates a new service registration func (a *Auth) RegisterService(reg *model.ServiceReg) error { if reg != nil && !reg.FirstParty && strings.Contains(strings.ToUpper(reg.Name), rokwireKeyword) { return errors.Newf("the name of a third-party service may not contain \"%s\"", rokwireKeyword) @@ -1867,7 +1887,7 @@ func (a *Auth) RegisterService(reg *model.ServiceReg) error { return a.storage.InsertServiceReg(reg) } -//UpdateServiceRegistration updates an existing service registration +// UpdateServiceRegistration updates an existing service registration func (a *Auth) UpdateServiceRegistration(reg *model.ServiceReg) error { if reg != nil { if reg.Registration.ServiceID == authServiceID || reg.Registration.ServiceID == a.serviceID { @@ -1880,7 +1900,7 @@ func (a *Auth) UpdateServiceRegistration(reg *model.ServiceReg) error { return a.storage.UpdateServiceReg(reg) } -//DeregisterService deletes an existing service registration +// DeregisterService deletes an existing service registration func (a *Auth) DeregisterService(serviceID string) error { if serviceID == authServiceID || serviceID == a.serviceID { return errors.Newf("deregistering service not allowed for service id %v", serviceID) @@ -1888,7 +1908,7 @@ func (a *Auth) DeregisterService(serviceID string) error { return a.storage.DeleteServiceReg(serviceID) } -//GetAuthKeySet generates a JSON Web Key Set for auth service registration +// GetAuthKeySet generates a JSON Web Key Set for auth service registration func (a *Auth) GetAuthKeySet() (*model.JSONWebKeySet, error) { authReg, err := a.ServiceRegManager.GetServiceReg("auth") if err != nil { @@ -1907,7 +1927,7 @@ func (a *Auth) GetAuthKeySet() (*model.JSONWebKeySet, error) { return &model.JSONWebKeySet{Keys: []model.JSONWebKey{*jwk}}, nil } -//GetApplicationAPIKeys finds and returns the API keys for the provided app +// GetApplicationAPIKeys finds and returns the API keys for the provided app func (a *Auth) GetApplicationAPIKeys(appID string) ([]model.APIKey, error) { cachedAPIKeys, err := a.getCachedAPIKeys() if err != nil { @@ -1924,19 +1944,19 @@ func (a *Auth) GetApplicationAPIKeys(appID string) ([]model.APIKey, error) { return applicationAPIKeys, nil } -//GetAPIKey finds and returns an API key +// GetAPIKey finds and returns an API key func (a *Auth) GetAPIKey(ID string) (*model.APIKey, error) { return a.getCachedAPIKey(ID) } -//CreateAPIKey creates a new API key +// CreateAPIKey creates a new API key func (a *Auth) CreateAPIKey(apiKey model.APIKey) (*model.APIKey, error) { id, _ := uuid.NewUUID() apiKey.ID = id.String() return a.storage.InsertAPIKey(nil, apiKey) } -//UpdateAPIKey updates an existing API key +// UpdateAPIKey updates an existing API key func (a *Auth) UpdateAPIKey(apiKey model.APIKey) error { if len(apiKey.ID) == 0 { return errors.Newf("id cannot be empty") @@ -1944,7 +1964,7 @@ func (a *Auth) UpdateAPIKey(apiKey model.APIKey) error { return a.storage.UpdateAPIKey(apiKey) } -//DeleteAPIKey deletes an API key +// DeleteAPIKey deletes an API key func (a *Auth) DeleteAPIKey(ID string) error { //1. find api key to delete apiKey, err := a.getCachedAPIKey(ID) @@ -1969,7 +1989,7 @@ func (a *Auth) DeleteAPIKey(ID string) error { return nil } -//ValidateAPIKey validates the given API key for the given app ID +// ValidateAPIKey validates the given API key for the given app ID func (a *Auth) ValidateAPIKey(appID string, apiKey string) error { return a.validateAPIKey(apiKey, appID) } diff --git a/core/auth/auth.go b/core/auth/auth.go index 504c3c025..4bf5f5756 100644 --- a/core/auth/auth.go +++ b/core/auth/auth.go @@ -73,7 +73,7 @@ const ( mfaCodeMax int = 1000000 ) -//Auth represents the auth functionality unit +// Auth represents the auth functionality unit type Auth struct { storage Storage emailer Emailer @@ -112,7 +112,7 @@ type Auth struct { timerDone chan bool } -//NewAuth creates a new auth instance +// NewAuth creates a new auth instance func NewAuth(serviceID string, host string, authPrivKey *rsa.PrivateKey, storage Storage, emailer Emailer, minTokenExp *int64, maxTokenExp *int64, twilioAccountSID string, twilioToken string, twilioServiceSID string, profileBB *profilebb.Adapter, smtpHost string, smtpPortNum int, smtpUser string, smtpPassword string, smtpFrom string, logger *logs.Logger) (*Auth, error) { if minTokenExp == nil { @@ -884,7 +884,7 @@ func (a *Auth) hasSharedProfile(app model.Application, authTypeID string, userId return true, profile, credential, nil } -//validateAPIKey checks if the given API key is valid for the given app ID +// validateAPIKey checks if the given API key is valid for the given app ID func (a *Auth) validateAPIKey(apiKey string, appID string) error { validAPIKey, err := a.getCachedAPIKey(apiKey) if err != nil || validAPIKey == nil || validAPIKey.AppID != appID { @@ -903,8 +903,9 @@ func (a *Auth) canSignIn(account *model.Account, authTypeID string, userIdentifi return false } -//isSignUp checks if the operation is sign in or sign up -// first check if the client has set sign_up field +// isSignUp checks if the operation is sign in or sign up +// +// first check if the client has set sign_up field // if sign_up field has not been sent then check if the user exists func (a *Auth) isSignUp(accountExists bool, params string, l *logs.Log) (bool, error) { //check if sign_up field has been passed @@ -1348,7 +1349,8 @@ func (a *Auth) getProfileBBData(authType model.AuthType, identifier string, l *l return profile, preferences, nil } -//registerUser registers account for an organization in an application +// registerUser registers account for an organization in an application +// // Input: // authType (AuthType): The authentication type // userIdentifier (string): The user identifier @@ -2126,7 +2128,7 @@ func (a *Auth) buildRefreshToken() (string, error) { return newToken, nil } -//getScopedAccessToken returns a scoped access token with the requested scopes +// getScopedAccessToken returns a scoped access token with the requested scopes func (a *Auth) getScopedAccessToken(claims tokenauth.Claims, serviceID string, scopes []authorization.Scope) (string, error) { scopeStrings := []string{} services := []string{serviceID} @@ -2287,7 +2289,7 @@ func (a *Auth) updateExternalAccountGroups(account *model.Account, newExternalGr return updated, nil } -//storeReg stores the service registration record +// storeReg stores the service registration record func (a *Auth) storeReg() error { pem, err := authutils.GetPubKeyPem(&a.authPrivKey.PublicKey) if err != nil { @@ -2315,7 +2317,7 @@ func (a *Auth) storeReg() error { return nil } -//cacheIdentityProviders caches the identity providers +// cacheIdentityProviders caches the identity providers func (a *Auth) cacheIdentityProviders() error { a.logger.Info("cacheIdentityProviders..") @@ -2554,13 +2556,13 @@ func (a *Auth) deleteExpiredSessions() { } } -//LocalServiceRegLoaderImpl provides a local implementation for AuthDataLoader +// LocalServiceRegLoaderImpl provides a local implementation for AuthDataLoader type LocalServiceRegLoaderImpl struct { storage Storage *authservice.ServiceRegSubscriptions } -//LoadServices implements ServiceRegLoader interface +// LoadServices implements ServiceRegLoader interface func (l *LocalServiceRegLoaderImpl) LoadServices() ([]authservice.ServiceReg, error) { regs, err := l.storage.FindServiceRegs(l.GetSubscribedServices()) if err != nil { @@ -2577,29 +2579,29 @@ func (l *LocalServiceRegLoaderImpl) LoadServices() ([]authservice.ServiceReg, er return authRegs, nil } -//NewLocalServiceRegLoader creates and configures a new LocalServiceRegLoaderImpl instance +// NewLocalServiceRegLoader creates and configures a new LocalServiceRegLoaderImpl instance func NewLocalServiceRegLoader(storage Storage) *LocalServiceRegLoaderImpl { subscriptions := authservice.NewServiceRegSubscriptions([]string{allServices}) return &LocalServiceRegLoaderImpl{storage: storage, ServiceRegSubscriptions: subscriptions} } -//StorageListener represents storage listener implementation for the auth package +// StorageListener represents storage listener implementation for the auth package type StorageListener struct { auth *Auth storage.DefaultListenerImpl } -//OnIdentityProvidersUpdated notifies that identity providers have been updated +// OnIdentityProvidersUpdated notifies that identity providers have been updated func (al *StorageListener) OnIdentityProvidersUpdated() { al.auth.cacheIdentityProviders() } -//OnAPIKeysUpdated notifies api keys have been updated +// OnAPIKeysUpdated notifies api keys have been updated func (al *StorageListener) OnAPIKeysUpdated() { al.auth.cacheAPIKeys() } -//OnServiceRegsUpdated notifies that a service registration has been updated +// OnServiceRegsUpdated notifies that a service registration has been updated func (al *StorageListener) OnServiceRegsUpdated() { al.auth.ServiceRegManager.LoadServices() } diff --git a/core/auth/auth_type_email.go b/core/auth/auth_type_email.go index db09a1da2..c1cfbbe26 100644 --- a/core/auth/auth_type_email.go +++ b/core/auth/auth_type_email.go @@ -38,7 +38,7 @@ const ( typeEmailParams logutils.MessageDataType = "email params" ) -//enailCreds represents the creds struct for email auth +// enailCreds represents the creds struct for email auth type emailCreds struct { Email string `json:"email" bson:"email" validate:"required"` Password string `json:"password" bson:"password"` @@ -211,7 +211,7 @@ func (a *emailAuthImpl) getVerifyEmail(authType model.AuthType) bool { return verifyEmail } -//Time in seconds to wait before sending another verification email +// Time in seconds to wait before sending another verification email func (a *emailAuthImpl) getVerifyWaitTime(authType model.AuthType) int { //Default is 30 seconds verifyWaitTime := 30 @@ -222,7 +222,7 @@ func (a *emailAuthImpl) getVerifyWaitTime(authType model.AuthType) int { return verifyWaitTime } -//Time in hours before verification code expires +// Time in hours before verification code expires func (a *emailAuthImpl) getVerifyExpiry(authType model.AuthType) int { //Default is 24 hours verifyExpiry := 24 @@ -504,7 +504,7 @@ func mapToEmailCreds(credsMap map[string]interface{}) (*emailCreds, error) { return &creds, nil } -//initEmailAuth initializes and registers a new email auth instance +// initEmailAuth initializes and registers a new email auth instance func initEmailAuth(auth *Auth) (*emailAuthImpl, error) { email := &emailAuthImpl{auth: auth, authType: AuthTypeEmail} diff --git a/core/auth/auth_type_firebase.go b/core/auth/auth_type_firebase.go index 9f9789453..56e047491 100644 --- a/core/auth/auth_type_firebase.go +++ b/core/auth/auth_type_firebase.go @@ -73,7 +73,7 @@ func (a *firebaseAuthImpl) forgotCredential(credential *model.Credential, identi return nil, nil } -//initFirebaseAuth initializes and registers a new Firebase auth instance +// initFirebaseAuth initializes and registers a new Firebase auth instance func initFirebaseAuth(auth *Auth) (*firebaseAuthImpl, error) { firebase := &firebaseAuthImpl{auth: auth, authType: AuthTypeFirebase} diff --git a/core/auth/auth_type_oidc.go b/core/auth/auth_type_oidc.go index 0a3ada6ca..764e0d15b 100644 --- a/core/auth/auth_type_oidc.go +++ b/core/auth/auth_type_oidc.go @@ -135,7 +135,7 @@ func (a *oidcAuthImpl) externalLogin(authType model.AuthType, appType model.Appl return externalUser, parameters, nil } -//refresh must be implemented for OIDC auth +// refresh must be implemented for OIDC auth func (a *oidcAuthImpl) refresh(params map[string]interface{}, authType model.AuthType, appType model.ApplicationType, appOrg model.ApplicationOrganization, l *logs.Log) (*model.ExternalSystemUser, map[string]interface{}, error) { refreshParams, err := oidcRefreshParamsFromMap(params) if err != nil { @@ -497,7 +497,7 @@ func (a *oidcAuthImpl) getOidcAuthConfig(authType model.AuthType, appType model. // --- Helper functions --- -//generatePkceChallenge generates and returns a PKCE code challenge and verifier +// generatePkceChallenge generates and returns a PKCE code challenge and verifier func generatePkceChallenge() (string, string, error) { codeVerifier, err := utils.GenerateRandomString(50) if err != nil { @@ -513,7 +513,7 @@ func generatePkceChallenge() (string, string, error) { return codeChallenge, codeVerifier, nil } -//initOidcAuth initializes and registers a new OIDC auth instance +// initOidcAuth initializes and registers a new OIDC auth instance func initOidcAuth(auth *Auth) (*oidcAuthImpl, error) { oidc := &oidcAuthImpl{auth: auth, authType: AuthTypeOidc} diff --git a/core/auth/auth_type_phone.go b/core/auth/auth_type_phone.go index 2c3f6ae45..c4b2e4c27 100644 --- a/core/auth/auth_type_phone.go +++ b/core/auth/auth_type_phone.go @@ -320,7 +320,7 @@ func (a *twilioPhoneAuthImpl) forgotCredential(credential *model.Credential, ide return nil, nil } -//initPhoneAuth initializes and registers a new phone auth instance +// initPhoneAuth initializes and registers a new phone auth instance func initPhoneAuth(auth *Auth, twilioAccountSID string, twilioToken string, twilioServiceSID string) (*twilioPhoneAuthImpl, error) { phone := &twilioPhoneAuthImpl{auth: auth, authType: AuthTypeTwilioPhone, twilioAccountSID: twilioAccountSID, twilioToken: twilioToken, twilioServiceSID: twilioServiceSID} diff --git a/core/auth/auth_type_saml.go b/core/auth/auth_type_saml.go index de23e7682..dbe587d65 100644 --- a/core/auth/auth_type_saml.go +++ b/core/auth/auth_type_saml.go @@ -45,7 +45,7 @@ func (a *samlAuthImpl) refresh(params map[string]interface{}, authType model.Aut return nil, nil, nil } -//initSamlAuth initializes and registers a new SAML auth instance +// initSamlAuth initializes and registers a new SAML auth instance func initSamlAuth(auth *Auth) (*samlAuthImpl, error) { saml := &samlAuthImpl{auth: auth, authType: AuthTypeSaml} diff --git a/core/auth/auth_type_signature.go b/core/auth/auth_type_signature.go index a2e54006c..fcd3e7a12 100644 --- a/core/auth/auth_type_signature.go +++ b/core/auth/auth_type_signature.go @@ -27,7 +27,7 @@ const ( AuthTypeSignature string = "signature" ) -//Signature implementation of authType +// Signature implementation of authType type signatureAuthImpl struct { auth *Auth authType string @@ -73,7 +73,7 @@ func (a *signatureAuthImpl) forgotCredential(credential *model.Credential, ident return nil, nil } -//initSignatureAuth initializes and registers a new signature auth instance +// initSignatureAuth initializes and registers a new signature auth instance func initSignatureAuth(auth *Auth) (*signatureAuthImpl, error) { signature := &signatureAuthImpl{auth: auth, authType: AuthTypeSignature} diff --git a/core/auth/auth_type_username.go b/core/auth/auth_type_username.go index 37c1e192e..ff84cef34 100644 --- a/core/auth/auth_type_username.go +++ b/core/auth/auth_type_username.go @@ -72,7 +72,7 @@ func (a *usernameAuthImpl) forgotCredential(credential *model.Credential, identi return nil, nil } -//initUsernameAuth initializes and registers a new username auth instance +// initUsernameAuth initializes and registers a new username auth instance func initUsernameAuth(auth *Auth) (*usernameAuthImpl, error) { username := &usernameAuthImpl{auth: auth, authType: authTypeUsername} diff --git a/core/auth/interfaces.go b/core/auth/interfaces.go index b2d97826c..f837187b6 100644 --- a/core/auth/interfaces.go +++ b/core/auth/interfaces.go @@ -25,7 +25,7 @@ import ( "github.com/rokwire/logging-library-go/logs" ) -//authType is the interface for authentication for auth types which are not external for the system(the users do not come from external system) +// authType is the interface for authentication for auth types which are not external for the system(the users do not come from external system) type authType interface { //signUp applies sign up operation // Returns: @@ -73,8 +73,8 @@ type authType interface { checkCredentials(accountAuthType model.AccountAuthType, creds string, l *logs.Log) (string, error) } -//externalAuthType is the interface for authentication for auth types which are external for the system(the users comes from external system). -//these are the different identity providers - illinois_oidc etc +// externalAuthType is the interface for authentication for auth types which are external for the system(the users comes from external system). +// these are the different identity providers - illinois_oidc etc type externalAuthType interface { //getLoginUrl retrieves and pre-formats a login url and params for the SSO provider getLoginURL(authType model.AuthType, appType model.ApplicationType, redirectURI string, l *logs.Log) (string, map[string]interface{}, error) @@ -84,20 +84,20 @@ type externalAuthType interface { refresh(params map[string]interface{}, authType model.AuthType, appType model.ApplicationType, appOrg model.ApplicationOrganization, l *logs.Log) (*model.ExternalSystemUser, map[string]interface{}, error) } -//anonymousAuthType is the interface for authentication for auth types which are anonymous +// anonymousAuthType is the interface for authentication for auth types which are anonymous type anonymousAuthType interface { //checkCredentials checks the credentials for the provided app and organization // Returns anonymous profile identifier checkCredentials(creds string) (string, map[string]interface{}, error) } -//serviceAuthType is the interface for authentication for non-human clients +// serviceAuthType is the interface for authentication for non-human clients type serviceAuthType interface { checkCredentials(r *sigauth.Request, creds interface{}, params map[string]interface{}) ([]model.ServiceAccount, error) addCredentials(creds *model.ServiceAccountCredential) (map[string]interface{}, error) } -//mfaType is the interface for multi-factor authentication +// mfaType is the interface for multi-factor authentication type mfaType interface { //verify verifies the code based on stored mfa params verify(context storage.TransactionContext, mfa *model.MFAType, accountID string, code string) (*string, error) @@ -107,7 +107,7 @@ type mfaType interface { sendCode(identifier string) (string, *time.Time, error) } -//APIs is the interface which defines the APIs provided by the auth package +// APIs is the interface which defines the APIs provided by the auth package type APIs interface { //Start starts the auth service Start() @@ -440,7 +440,7 @@ type APIs interface { ValidateAPIKey(appID string, apiKey string) error } -//Storage interface to communicate with the storage +// Storage interface to communicate with the storage type Storage interface { RegisterStorageListener(storageListener storage.Listener) @@ -571,12 +571,12 @@ type Storage interface { InsertAccountGroups(context storage.TransactionContext, accountID string, appOrgID string, groups []model.AccountGroup) error } -//ProfileBuildingBlock is used by auth to communicate with the profile building block. +// ProfileBuildingBlock is used by auth to communicate with the profile building block. type ProfileBuildingBlock interface { GetProfileBBData(queryParams map[string]string, l *logs.Log) (*model.Profile, map[string]interface{}, error) } -//Emailer is used by core to send emails +// Emailer is used by core to send emails type Emailer interface { Send(toEmail string, subject string, body string, attachmentFilename *string) error } diff --git a/core/auth/mfa_email.go b/core/auth/mfa_email.go index f59722019..bbb03dce6 100644 --- a/core/auth/mfa_email.go +++ b/core/auth/mfa_email.go @@ -97,7 +97,7 @@ func (m *emailMfaImpl) sendCode(identifier string) (string, *time.Time, error) { return code, &expires, errors.New(logutils.Unimplemented) } -//initEmailMfa initializes and registers a new email mfa instance +// initEmailMfa initializes and registers a new email mfa instance func initEmailMfa(auth *Auth) (*emailMfaImpl, error) { email := &emailMfaImpl{auth: auth, mfaType: MfaTypeEmail} diff --git a/core/auth/mfa_phone.go b/core/auth/mfa_phone.go index 15c624ea0..deae323ee 100644 --- a/core/auth/mfa_phone.go +++ b/core/auth/mfa_phone.go @@ -97,7 +97,7 @@ func (m *phoneMfaImpl) sendCode(identifier string) (string, *time.Time, error) { return code, &expires, errors.New(logutils.Unimplemented) } -//initPhoneMfa initializes and registers a new phone mfa instance +// initPhoneMfa initializes and registers a new phone mfa instance func initPhoneMfa(auth *Auth) (*phoneMfaImpl, error) { phone := &phoneMfaImpl{auth: auth, mfaType: MfaTypePhone} diff --git a/core/auth/mfa_recovery.go b/core/auth/mfa_recovery.go index 820da8e7d..03aa76de3 100644 --- a/core/auth/mfa_recovery.go +++ b/core/auth/mfa_recovery.go @@ -97,12 +97,12 @@ func (m *recoveryMfaImpl) enroll(identifier string) (*model.MFAType, error) { return &model.MFAType{ID: id.String(), Type: MfaTypeRecovery, Verified: true, Params: params, DateCreated: time.Now().UTC()}, nil } -//sendCode not used for recovery +// sendCode not used for recovery func (m *recoveryMfaImpl) sendCode(identifier string) (string, *time.Time, error) { return "", nil, errors.New(logutils.Unimplemented) } -//initRecoveryMfa initializes and registers a new recovery mfa instance +// initRecoveryMfa initializes and registers a new recovery mfa instance func initRecoveryMfa(auth *Auth) (*recoveryMfaImpl, error) { recovery := &recoveryMfaImpl{auth: auth, mfaType: MfaTypeRecovery} diff --git a/core/auth/mfa_totp.go b/core/auth/mfa_totp.go index 52f6f1673..5bffca23c 100644 --- a/core/auth/mfa_totp.go +++ b/core/auth/mfa_totp.go @@ -85,12 +85,12 @@ func (m *totpMfaImpl) enroll(identifier string) (*model.MFAType, error) { return &model.MFAType{ID: id.String(), Type: MfaTypeTotp, Verified: false, Params: params, DateCreated: time.Now().UTC()}, nil } -//sendCode not used for TOTP +// sendCode not used for TOTP func (m *totpMfaImpl) sendCode(identifier string) (string, *time.Time, error) { return "", nil, errors.New(logutils.Unimplemented) } -//initTotpMfa initializes and registers a new totp mfa instance +// initTotpMfa initializes and registers a new totp mfa instance func initTotpMfa(auth *Auth) (*totpMfaImpl, error) { totp := &totpMfaImpl{auth: auth, mfaType: MfaTypeTotp} diff --git a/core/auth/service_signature.go b/core/auth/service_signature.go index ace763e21..034e291cf 100644 --- a/core/auth/service_signature.go +++ b/core/auth/service_signature.go @@ -88,7 +88,7 @@ func (s *signatureServiceAuthImpl) addCredentials(creds *model.ServiceAccountCre return creds.Params, nil } -//initSignatureServiceAuth initializes and registers a new signature service auth instance +// initSignatureServiceAuth initializes and registers a new signature service auth instance func initSignatureServiceAuth(auth *Auth) (*signatureServiceAuthImpl, error) { signature := &signatureServiceAuthImpl{auth: auth, serviceAuthType: ServiceAuthTypeSignature} diff --git a/core/auth/service_static_token.go b/core/auth/service_static_token.go index 5fce0c7ea..66c9404d2 100644 --- a/core/auth/service_static_token.go +++ b/core/auth/service_static_token.go @@ -35,7 +35,7 @@ const ( TypeStaticTokenCreds logutils.MessageDataType = "static token creds" ) -//staticTokenCreds represents the creds struct for static token auth +// staticTokenCreds represents the creds struct for static token auth type staticTokenCreds struct { Token string `json:"token" validate:"required"` } @@ -123,7 +123,7 @@ func (s *staticTokenServiceAuthImpl) hashAndEncodeToken(token string) string { return base64.StdEncoding.EncodeToString(hashedToken) } -//initStaticTokenServiceAuth initializes and registers a new static token service auth instance +// initStaticTokenServiceAuth initializes and registers a new static token service auth instance func initStaticTokenServiceAuth(auth *Auth) (*staticTokenServiceAuthImpl, error) { staticToken := &staticTokenServiceAuthImpl{auth: auth, serviceAuthType: ServiceAuthTypeStaticToken} diff --git a/core/interfaces.go b/core/interfaces.go index 7ea5b8667..3de68df10 100644 --- a/core/interfaces.go +++ b/core/interfaces.go @@ -21,7 +21,7 @@ import ( "github.com/rokwire/logging-library-go/logs" ) -//Services exposes APIs for the driver adapters +// Services exposes APIs for the driver adapters type Services interface { SerDeleteAccount(id string) error SerGetAccount(accountID string) (*model.Account, error) @@ -39,7 +39,7 @@ type Services interface { SerGetAppConfig(appTypeIdentifier string, orgID *string, versionNumbers model.VersionNumbers, apiKey *string) (*model.ApplicationConfig, error) } -//Administration exposes administration APIs for the driver adapters +// Administration exposes administration APIs for the driver adapters type Administration interface { AdmGetTest() string AdmGetTestModel() string @@ -76,24 +76,24 @@ type Administration interface { AdmGetApplicationAccountDevices(appID string, orgID string, accountID string, l *logs.Log) ([]model.Device, error) } -//Encryption exposes APIs for the Encryption building block +// Encryption exposes APIs for the Encryption building block type Encryption interface { EncGetTest() string } -//BBs exposes users related APIs used by the platform building blocks +// BBs exposes users related APIs used by the platform building blocks type BBs interface { BBsGetTest() string BBsUpdatePermissions(permissions []model.Permission, accountID string) ([]model.Permission, error) } -//TPs exposes users related APIs used by third-party services +// TPs exposes users related APIs used by third-party services type TPs interface { TPsGetTest() string TPsUpdatePermissions(permissions []model.Permission, accountID string) ([]model.Permission, error) } -//System exposes system APIs for the driver adapters +// System exposes system APIs for the driver adapters type System interface { SysCreateGlobalConfig(setting string) (*model.GlobalConfig, error) SysGetGlobalConfig() (*model.GlobalConfig, error) @@ -122,7 +122,7 @@ type System interface { SysUpdateAuthTypes(ID string, code string, description string, isExternal bool, isAnonymous bool, useCredentials bool, ignoreMFA bool, params map[string]interface{}) error } -//Storage is used by core to storage data - DB storage adapter, file storage adapter etc +// Storage is used by core to storage data - DB storage adapter, file storage adapter etc type Storage interface { RegisterStorageListener(storageListener storage.Listener) @@ -160,9 +160,9 @@ type Storage interface { DeleteGlobalConfig(context storage.TransactionContext) error FindPermissionsByName(context storage.TransactionContext, names []string) ([]model.Permission, error) - FindPermissionsByServiceIDs(serviceIDs []string) ([]model.Permission, error) + FindPermissionsByServiceIDs(context storage.TransactionContext, serviceIDs []string) ([]model.Permission, error) InsertPermission(context storage.TransactionContext, item model.Permission) error - UpdatePermission(item model.Permission) error + UpdatePermission(context storage.TransactionContext, item model.Permission) error DeletePermission(id string) error FindAppOrgRoles(appOrgID string) ([]model.AppOrgRole, error) @@ -209,14 +209,16 @@ type Storage interface { InsertApplicationOrganization(context storage.TransactionContext, applicationOrganization model.ApplicationOrganization) (*model.ApplicationOrganization, error) InsertAPIKey(context storage.TransactionContext, apiKey model.APIKey) (*model.APIKey, error) + + FindServiceRegByServiceAccountID(accountID string) (*model.ServiceReg, error) } -//StorageListener listenes for change data storage events +// StorageListener listenes for change data storage events type StorageListener struct { app *application storage.DefaultListenerImpl } -//ApplicationListener represents application listener +// ApplicationListener represents application listener type ApplicationListener interface { } diff --git a/core/mocks/Storage.go b/core/mocks/Storage.go index 56dc9d1fc..fe5fbe88d 100644 --- a/core/mocks/Storage.go +++ b/core/mocks/Storage.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.13.1. DO NOT EDIT. +// Code generated by mockery v2.14.0. DO NOT EDIT. package mocks @@ -767,13 +767,13 @@ func (_m *Storage) FindPermissionsByName(context storage.TransactionContext, nam return r0, r1 } -// FindPermissionsByServiceIDs provides a mock function with given fields: serviceIDs -func (_m *Storage) FindPermissionsByServiceIDs(serviceIDs []string) ([]model.Permission, error) { - ret := _m.Called(serviceIDs) +// FindPermissionsByServiceIDs provides a mock function with given fields: context, serviceIDs +func (_m *Storage) FindPermissionsByServiceIDs(context storage.TransactionContext, serviceIDs []string) ([]model.Permission, error) { + ret := _m.Called(context, serviceIDs) var r0 []model.Permission - if rf, ok := ret.Get(0).(func([]string) []model.Permission); ok { - r0 = rf(serviceIDs) + if rf, ok := ret.Get(0).(func(storage.TransactionContext, []string) []model.Permission); ok { + r0 = rf(context, serviceIDs) } else { if ret.Get(0) != nil { r0 = ret.Get(0).([]model.Permission) @@ -781,8 +781,31 @@ func (_m *Storage) FindPermissionsByServiceIDs(serviceIDs []string) ([]model.Per } var r1 error - if rf, ok := ret.Get(1).(func([]string) error); ok { - r1 = rf(serviceIDs) + if rf, ok := ret.Get(1).(func(storage.TransactionContext, []string) error); ok { + r1 = rf(context, serviceIDs) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FindServiceRegByServiceAccountID provides a mock function with given fields: accountID +func (_m *Storage) FindServiceRegByServiceAccountID(accountID string) (*model.ServiceReg, error) { + ret := _m.Called(accountID) + + var r0 *model.ServiceReg + if rf, ok := ret.Get(0).(func(string) *model.ServiceReg); ok { + r0 = rf(accountID) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*model.ServiceReg) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(string) error); ok { + r1 = rf(accountID) } else { r1 = ret.Error(1) } @@ -1203,13 +1226,13 @@ func (_m *Storage) UpdateOrganization(ID string, name string, requestType string return r0 } -// UpdatePermission provides a mock function with given fields: item -func (_m *Storage) UpdatePermission(item model.Permission) error { - ret := _m.Called(item) +// UpdatePermission provides a mock function with given fields: context, item +func (_m *Storage) UpdatePermission(context storage.TransactionContext, item model.Permission) error { + ret := _m.Called(context, item) var r0 error - if rf, ok := ret.Get(0).(func(model.Permission) error); ok { - r0 = rf(item) + if rf, ok := ret.Get(0).(func(storage.TransactionContext, model.Permission) error); ok { + r0 = rf(context, item) } else { r0 = ret.Error(0) } diff --git a/core/model/application.go b/core/model/application.go index 6d87711da..97c04d112 100644 --- a/core/model/application.go +++ b/core/model/application.go @@ -55,7 +55,7 @@ const ( PermissionAllSystemCore string = "all_system_core" ) -//Permission represents permission entity +// Permission represents permission entity type Permission struct { ID string `bson:"_id"` Name string `bson:"name"` @@ -69,7 +69,7 @@ type Permission struct { DateUpdated *time.Time `bson:"date_updated"` } -//CheckAssigners checks if the passed permissions satisfy the needed assigners for the permission +// CheckAssigners checks if the passed permissions satisfy the needed assigners for the permission func (p Permission) CheckAssigners(assignerPermissions []string) error { if len(p.Assigners) == 0 { return errors.Newf("not defined assigners for %s permission", p.Name) @@ -89,7 +89,7 @@ func (p Permission) String() string { return fmt.Sprintf("[ID:%s\nName:%s\nServiceID:%s]", p.ID, p.Name, p.ServiceID) } -//AppOrgRole represents application organization role entity. It is a collection of permissions +// AppOrgRole represents application organization role entity. It is a collection of permissions type AppOrgRole struct { ID string Name string @@ -105,7 +105,7 @@ type AppOrgRole struct { DateUpdated *time.Time } -//GetPermissionNamed returns the permission for a name if the role has it +// GetPermissionNamed returns the permission for a name if the role has it func (c AppOrgRole) GetPermissionNamed(name string) *Permission { for _, permission := range c.Permissions { if permission.Name == name { @@ -115,7 +115,7 @@ func (c AppOrgRole) GetPermissionNamed(name string) *Permission { return nil } -//CheckAssigners checks if the passed permissions satisfy the needed assigners for all role permissions +// CheckAssigners checks if the passed permissions satisfy the needed assigners for all role permissions func (c AppOrgRole) CheckAssigners(assignerPermissions []string) error { if len(c.Permissions) == 0 { return nil //no permission @@ -135,7 +135,7 @@ func (c AppOrgRole) String() string { return fmt.Sprintf("[ID:%s\tName:%s\tPermissions:%s\tAppOrg:%s]", c.ID, c.Name, c.Permissions, c.AppOrg.ID) } -//AppOrgGroup represents application organization group entity. It is a collection of users +// AppOrgGroup represents application organization group entity. It is a collection of users type AppOrgGroup struct { ID string Name string @@ -152,7 +152,7 @@ type AppOrgGroup struct { DateUpdated *time.Time } -//CheckAssigners checks if the passed permissions satisfy the needed assigners for the group +// CheckAssigners checks if the passed permissions satisfy the needed assigners for the group func (cg AppOrgGroup) CheckAssigners(assignerPermissions []string) error { //check permission if len(cg.Permissions) > 0 { @@ -180,7 +180,7 @@ func (cg AppOrgGroup) String() string { return fmt.Sprintf("[ID:%s\nName:%s\nAppOrg:%s]", cg.ID, cg.Name, cg.AppOrg.ID) } -//Application represents users application entity - safer community, uuic, etc +// Application represents users application entity - safer community, uuic, etc type Application struct { ID string Name string //safer community, uuic, etc @@ -201,7 +201,7 @@ type Application struct { DateUpdated *time.Time } -//FindApplicationType finds app type +// FindApplicationType finds app type func (a Application) FindApplicationType(id string) *ApplicationType { for _, appType := range a.Types { if appType.Identifier == id || appType.ID == id { @@ -211,7 +211,7 @@ func (a Application) FindApplicationType(id string) *ApplicationType { return nil } -//Organization represents organization entity +// Organization represents organization entity type Organization struct { ID string Name string @@ -231,7 +231,7 @@ func (c Organization) String() string { return fmt.Sprintf("[ID:%s\tName:%s\tType:%s\tConfig:%s]", c.ID, c.Name, c.Type, c.Config) } -//ApplicationOrganization represents application organization entity +// ApplicationOrganization represents application organization entity type ApplicationOrganization struct { ID string @@ -250,7 +250,7 @@ type ApplicationOrganization struct { DateUpdated *time.Time } -//FindIdentityProviderSetting finds the identity provider setting for the application +// FindIdentityProviderSetting finds the identity provider setting for the application func (ao ApplicationOrganization) FindIdentityProviderSetting(identityProviderID string) *IdentityProviderSetting { for _, idPrSetting := range ao.IdentityProvidersSettings { if idPrSetting.IdentityProviderID == identityProviderID { @@ -260,7 +260,7 @@ func (ao ApplicationOrganization) FindIdentityProviderSetting(identityProviderID return nil } -//IsAuthTypeSupported checks if an auth type is supported for application type +// IsAuthTypeSupported checks if an auth type is supported for application type func (ao ApplicationOrganization) IsAuthTypeSupported(appType ApplicationType, authType AuthType) bool { for _, sat := range ao.SupportedAuthTypes { if sat.AppTypeID == appType.ID { @@ -274,15 +274,16 @@ func (ao ApplicationOrganization) IsAuthTypeSupported(appType ApplicationType, a return false } -//IdentityProviderSetting represents identity provider setting for an organization in an application -// User specific fields -// For example: -// UIUC Application has uiucedu_uin specific field for Illinois identity provider +// IdentityProviderSetting represents identity provider setting for an organization in an application // -// Groups mapping: maps an identity provider groups to application groups -// For example: -// for the UIUC application the Illinois group "urn:mace:uiuc.edu:urbana:authman:app-rokwire-service-policy-rokwire groups access" is mapped to an application group called "groups access" -// for the Safer Illinois application the Illinois group "urn:mace:uiuc.edu:urbana:authman:app-rokwire-service-policy-rokwire health test verify" is mapped to an application group called "tests verifiers" +// User specific fields +// For example: +// UIUC Application has uiucedu_uin specific field for Illinois identity provider +// +// Groups mapping: maps an identity provider groups to application groups +// For example: +// for the UIUC application the Illinois group "urn:mace:uiuc.edu:urbana:authman:app-rokwire-service-policy-rokwire groups access" is mapped to an application group called "groups access" +// for the Safer Illinois application the Illinois group "urn:mace:uiuc.edu:urbana:authman:app-rokwire-service-policy-rokwire health test verify" is mapped to an application group called "tests verifiers" type IdentityProviderSetting struct { IdentityProviderID string `bson:"identity_provider_id"` @@ -302,7 +303,7 @@ type IdentityProviderSetting struct { Groups map[string]string `bson:"groups"` //map[identity_provider_group]app_group_id } -//LoginsSessionsSetting represents logins sessions setting for an organization in an application +// LoginsSessionsSetting represents logins sessions setting for an organization in an application type LoginsSessionsSetting struct { MaxConcurrentSessions int `bson:"max_concurrent_sessions"` @@ -311,19 +312,19 @@ type LoginsSessionsSetting struct { YearlyExpirePolicy YearlyExpirePolicy `bson:"yearly_expire_policy"` } -//InactivityExpirePolicy represents expires policy based on inactivity +// InactivityExpirePolicy represents expires policy based on inactivity type InactivityExpirePolicy struct { Active bool `bson:"active"` InactivityPeriod int `bson:"inactivity_period"` //in minutes } -//TSLExpirePolicy represents expires policy based on the time since login +// TSLExpirePolicy represents expires policy based on the time since login type TSLExpirePolicy struct { Active bool `bson:"active"` TimeSinceLoginPeriod int `bson:"time_since_login_period"` //in minutes } -//YearlyExpirePolicy represents expires policy based on fixed date +// YearlyExpirePolicy represents expires policy based on fixed date type YearlyExpirePolicy struct { Active bool `bson:"active"` Day int `bson:"day"` @@ -332,7 +333,7 @@ type YearlyExpirePolicy struct { Min int `bson:"min"` } -//ApplicationType represents users application type entity - safer community android, safer community ios, safer community web, uuic android etc +// ApplicationType represents users application type entity - safer community android, safer community ios, safer community web, uuic android etc type ApplicationType struct { ID string Identifier string //edu.illinois.rokwire etc @@ -342,7 +343,7 @@ type ApplicationType struct { Application Application } -//AuthTypesSupport represents supported auth types for an organization in an application type with configs/params +// AuthTypesSupport represents supported auth types for an organization in an application type with configs/params type AuthTypesSupport struct { AppTypeID string `bson:"app_type_id"` @@ -352,7 +353,7 @@ type AuthTypesSupport struct { } `bson:"supported_auth_types"` } -//ApplicationConfig represents app configs +// ApplicationConfig represents app configs type ApplicationConfig struct { ID string ApplicationType ApplicationType @@ -374,7 +375,7 @@ type Version struct { DateUpdated *time.Time } -//VersionNumbers represents app config version numbers +// VersionNumbers represents app config version numbers type VersionNumbers struct { Major int `json:"major" bson:"major"` Minor int `json:"minor" bson:"minor"` @@ -407,7 +408,7 @@ func (v VersionNumbers) LessThanOrEqualTo(v1 *VersionNumbers) bool { return false } -//VersionNumbersFromString parses a string into a VersionNumbers struct. Returns nil if invalid format. +// VersionNumbersFromString parses a string into a VersionNumbers struct. Returns nil if invalid format. func VersionNumbersFromString(version string) *VersionNumbers { parts := strings.Split(version, ".") if len(parts) != 3 { @@ -429,3 +430,21 @@ func VersionNumbersFromString(version string) *VersionNumbers { return &VersionNumbers{Major: major, Minor: minor, Patch: patch} } + +// GetMissingPermissionNames returns a list of permission names missing from items +func GetMissingPermissionNames(items []Permission, names []string) []string { + badNames := make([]string, 0) + for _, name := range names { + bad := true + for _, e := range items { + if e.Name == name && !e.Inactive { + bad = false + break + } + } + if bad { + badNames = append(badNames, name) + } + } + return badNames +} diff --git a/core/model/auth.go b/core/model/auth.go index b6b669a98..9aeaa99a6 100644 --- a/core/model/auth.go +++ b/core/model/auth.go @@ -79,7 +79,7 @@ const ( TypeIP logutils.MessageDataType = "ip" ) -//LoginSession represents login session entity +// LoginSession represents login session entity type LoginSession struct { ID string @@ -110,7 +110,7 @@ type LoginSession struct { DateCreated time.Time } -//IsExpired says if the sessions is expired +// IsExpired says if the sessions is expired func (ls LoginSession) IsExpired() bool { loginsSessionsSetting := ls.AppOrg.LoginsSessionsSetting @@ -192,7 +192,7 @@ func (ls LoginSession) isYearlyExpired(policy YearlyExpirePolicy) bool { return createdDate.Before(expiresDate) && expiresDate.Before(now) } -//CurrentRefreshToken returns the current refresh token (last element of RefreshTokens) +// CurrentRefreshToken returns the current refresh token (last element of RefreshTokens) func (ls LoginSession) CurrentRefreshToken() string { numTokens := len(ls.RefreshTokens) if numTokens <= 0 { @@ -201,7 +201,7 @@ func (ls LoginSession) CurrentRefreshToken() string { return ls.RefreshTokens[numTokens-1] } -//LogInfo gives the information appropriate to be logged for the session +// LogInfo gives the information appropriate to be logged for the session func (ls LoginSession) LogInfo() string { identifier := utils.GetLogValue(ls.Identifier, 3) accessToken := utils.GetLogValue(ls.AccessToken, 10) @@ -219,14 +219,15 @@ func (ls LoginSession) LogInfo() string { ls.StateExpires, ls.MfaAttempts, ls.DateRefreshed, ls.DateUpdated, ls.DateCreated) } -//APIKey represents an API key entity +// APIKey represents an API key entity type APIKey struct { ID string `json:"id" bson:"_id"` AppID string `json:"app_id" bson:"app_id" validate:"required"` Key string `json:"key" bson:"key"` } -//AuthType represents authentication type entity +// AuthType represents authentication type entity +// // The system supports different authentication types - username, email, phone, identity providers ones etc type AuthType struct { ID string `bson:"_id"` @@ -239,7 +240,8 @@ type AuthType struct { Params map[string]interface{} `bson:"params"` } -//IdentityProvider represents identity provider entity +// IdentityProvider represents identity provider entity +// // The system can integrate different identity providers - facebook, google, illinois etc type IdentityProvider struct { ID string `bson:"_id"` @@ -249,13 +251,13 @@ type IdentityProvider struct { Configs []IdentityProviderConfig `bson:"configs"` } -//IdentityProviderConfig represents identity provider config for an application type +// IdentityProviderConfig represents identity provider config for an application type type IdentityProviderConfig struct { AppTypeID string `bson:"app_type_id"` Config map[string]interface{} `bson:"config"` } -//UserAuth represents user auth entity +// UserAuth represents user auth entity type UserAuth struct { UserID string AccountID string @@ -274,7 +276,7 @@ type UserAuth struct { Anonymous bool } -//AuthCreds represents represents a set of credentials used by auth +// AuthCreds represents represents a set of credentials used by auth type AuthCreds struct { ID string `bson:"_id"` OrgID string `bson:"org_id"` @@ -287,8 +289,8 @@ type AuthCreds struct { DateUpdated *time.Time `bson:"date_updated"` } -//AuthRefresh represents refresh token info used by auth -//TODO remove +// AuthRefresh represents refresh token info used by auth +// TODO remove type AuthRefresh struct { PreviousToken string `bson:"previous_token"` CurrentToken string `bson:"current_token" validate:"required"` @@ -302,7 +304,7 @@ type AuthRefresh struct { DateUpdated *time.Time `bson:"date_updated"` } -//ServiceReg represents a service registration entity +// ServiceReg represents a service registration entity type ServiceReg struct { Registration authservice.ServiceReg `json:"registration" bson:"registration"` Name string `json:"name" bson:"name"` @@ -314,14 +316,14 @@ type ServiceReg struct { FirstParty bool `json:"first_party" bson:"first_party"` } -//ServiceScope represents a scope entity +// ServiceScope represents a scope entity type ServiceScope struct { Scope *authorization.Scope `json:"scope" bson:"scope"` Required bool `json:"required" bson:"required"` Explanation string `json:"explanation,omitempty" bson:"explanation,omitempty"` } -//ServiceAccount represents a service account entity +// ServiceAccount represents a service account entity type ServiceAccount struct { AccountID string Name string @@ -338,7 +340,7 @@ type ServiceAccount struct { DateUpdated *time.Time } -//GetPermissionNames returns all names of permissions granted to this account +// GetPermissionNames returns all names of permissions granted to this account func (s ServiceAccount) GetPermissionNames() []string { permissions := make([]string, len(s.Permissions)) for i, permission := range s.Permissions { @@ -347,13 +349,13 @@ func (s ServiceAccount) GetPermissionNames() []string { return permissions } -//AppOrgPair represents an appID, orgID pair entity +// AppOrgPair represents an appID, orgID pair entity type AppOrgPair struct { AppID string OrgID string } -//ServiceAccountCredential represents a service account credential entity +// ServiceAccountCredential represents a service account credential entity type ServiceAccountCredential struct { ID string `bson:"id"` Name string `bson:"name"` @@ -375,19 +377,19 @@ type ServiceAccountTokenRequest struct { Creds *interface{} `json:"creds,omitempty"` } -//ServiceAuthorization represents service authorization entity +// ServiceAuthorization represents service authorization entity type ServiceAuthorization struct { UserID string `json:"user_id" bson:"user_id"` ServiceID string `json:"service_id" bson:"service_id"` Scopes []authorization.Scope `json:"scopes" bson:"scopes"` } -//JSONWebKeySet represents a JSON Web Key Set (JWKS) entity +// JSONWebKeySet represents a JSON Web Key Set (JWKS) entity type JSONWebKeySet struct { Keys []JSONWebKey `json:"keys" bson:"keys"` } -//JSONWebKey represents a JSON Web Key Set (JWKS) entity +// JSONWebKey represents a JSON Web Key Set (JWKS) entity type JSONWebKey struct { Kty string `json:"kty" bson:"kty"` Use string `json:"use" bson:"use"` @@ -397,7 +399,7 @@ type JSONWebKey struct { E string `json:"e" bson:"e"` } -//JSONWebKeyFromPubKey generates a JSON Web Key from a PubKey +// JSONWebKeyFromPubKey generates a JSON Web Key from a PubKey func JSONWebKeyFromPubKey(key *authservice.PubKey) (*JSONWebKey, error) { if key == nil { return nil, errors.ErrorData(logutils.StatusInvalid, TypePubKey, logutils.StringArgs("nil")) diff --git a/core/model/config.go b/core/model/config.go index 541dc51a8..95a988570 100644 --- a/core/model/config.go +++ b/core/model/config.go @@ -28,7 +28,7 @@ const ( TypeOrganizationConfig logutils.MessageDataType = "org config" ) -//GlobalConfig represents global config for the system +// GlobalConfig represents global config for the system type GlobalConfig struct { Setting string } @@ -37,7 +37,7 @@ func (gc GlobalConfig) String() string { return fmt.Sprintf("[setting:%s]", gc.Setting) } -//OrganizationConfig represents configuration for an organization +// OrganizationConfig represents configuration for an organization type OrganizationConfig struct { ID string `bson:"id"` Setting string `bson:"setting"` diff --git a/core/model/user.go b/core/model/user.go index 6a45d32e9..07a970149 100644 --- a/core/model/user.go +++ b/core/model/user.go @@ -43,7 +43,8 @@ const ( TypeDevice logutils.MessageDataType = "device" ) -//Account represents account entity +// Account represents account entity +// // The account is the user himself or herself. // This is what the person provides to the system so that to use it. // @@ -72,7 +73,7 @@ type Account struct { DateUpdated *time.Time } -//GetAccountAuthTypeByID finds account auth type by id +// GetAccountAuthTypeByID finds account auth type by id func (a Account) GetAccountAuthTypeByID(ID string) *AccountAuthType { for _, aat := range a.AuthTypes { if aat.ID == ID { @@ -83,7 +84,7 @@ func (a Account) GetAccountAuthTypeByID(ID string) *AccountAuthType { return nil } -//GetAccountAuthType finds account auth type +// GetAccountAuthType finds account auth type func (a Account) GetAccountAuthType(authTypeID string, identifier string) *AccountAuthType { for _, aat := range a.AuthTypes { if aat.AuthType.ID == authTypeID && aat.Identifier == identifier { @@ -94,14 +95,14 @@ func (a Account) GetAccountAuthType(authTypeID string, identifier string) *Accou return nil } -//SortAccountAuthTypes sorts account auth types by matching the given uid +// SortAccountAuthTypes sorts account auth types by matching the given uid func (a Account) SortAccountAuthTypes(uid string) { sort.Slice(a.AuthTypes, func(i, _ int) bool { return a.AuthTypes[i].Identifier == uid }) } -//GetPermissions returns all permissions granted to this account +// GetPermissions returns all permissions granted to this account func (a Account) GetPermissions() []Permission { permissionsMap := a.GetPermissionsMap() permissions := make([]Permission, len(permissionsMap)) @@ -113,7 +114,7 @@ func (a Account) GetPermissions() []Permission { return permissions } -//GetPermissionNames returns all names of permissions granted to this account +// GetPermissionNames returns all names of permissions granted to this account func (a Account) GetPermissionNames() []string { permissionsMap := a.GetPermissionsMap() permissions := make([]string, len(permissionsMap)) @@ -125,7 +126,7 @@ func (a Account) GetPermissionNames() []string { return permissions } -//GetPermissionsMap returns a map of all permissions granted to this account +// GetPermissionsMap returns a map of all permissions granted to this account func (a Account) GetPermissionsMap() map[string]Permission { permissionsMap := make(map[string]Permission, len(a.Permissions)) for _, permission := range a.Permissions { @@ -153,7 +154,7 @@ func (a Account) GetPermissionsMap() map[string]Permission { return permissionsMap } -//GetVerifiedMFATypes returns a list of only verified MFA types for this account +// GetVerifiedMFATypes returns a list of only verified MFA types for this account func (a Account) GetVerifiedMFATypes() []MFAType { mfaTypes := make([]MFAType, 0) for _, mfa := range a.MFATypes { @@ -164,7 +165,7 @@ func (a Account) GetVerifiedMFATypes() []MFAType { return mfaTypes } -//GetPermission returns the permission for an ID if the account has it +// GetPermission returns the permission for an ID if the account has it func (a Account) GetPermission(id string) *Permission { for _, permission := range a.Permissions { if permission.ID == id { @@ -174,7 +175,7 @@ func (a Account) GetPermission(id string) *Permission { return nil } -//GetPermissionNamed returns the permission for a name if the account has it +// GetPermissionNamed returns the permission for a name if the account has it func (a Account) GetPermissionNamed(name string) *Permission { for _, permission := range a.Permissions { if permission.Name == name { @@ -184,7 +185,7 @@ func (a Account) GetPermissionNamed(name string) *Permission { return nil } -//GetAssignedPermissionNames returns a list of names of directly assigned permissions for this account +// GetAssignedPermissionNames returns a list of names of directly assigned permissions for this account func (a Account) GetAssignedPermissionNames() []string { names := make([]string, len(a.Permissions)) for i, permission := range a.Permissions { @@ -193,7 +194,7 @@ func (a Account) GetAssignedPermissionNames() []string { return names } -//GetActiveRoles returns all active roles +// GetActiveRoles returns all active roles func (a Account) GetActiveRoles() []AccountRole { roles := []AccountRole{} for _, role := range a.Roles { @@ -204,7 +205,7 @@ func (a Account) GetActiveRoles() []AccountRole { return roles } -//GetRole returns the role for an id if the account has it +// GetRole returns the role for an id if the account has it func (a Account) GetRole(id string) *AccountRole { for _, role := range a.Roles { if role.Role.ID == id { @@ -214,7 +215,7 @@ func (a Account) GetRole(id string) *AccountRole { return nil } -//GetAssignedRoleIDs returns a list of IDs of directly assigned roles for this account +// GetAssignedRoleIDs returns a list of IDs of directly assigned roles for this account func (a Account) GetAssignedRoleIDs() []string { ids := make([]string, len(a.Roles)) for i, role := range a.Roles { @@ -223,7 +224,7 @@ func (a Account) GetAssignedRoleIDs() []string { return ids } -//CheckForRoleChanges checks for changes to account roles given a potential list of new roles +// CheckForRoleChanges checks for changes to account roles given a potential list of new roles func (a Account) CheckForRoleChanges(new []string) bool { unchanged := make([]bool, len(a.Roles)) @@ -249,7 +250,7 @@ func (a Account) CheckForRoleChanges(new []string) bool { return false } -//GetActiveGroups returns all active groups +// GetActiveGroups returns all active groups func (a Account) GetActiveGroups() []AccountGroup { groups := []AccountGroup{} for _, group := range a.Groups { @@ -260,7 +261,7 @@ func (a Account) GetActiveGroups() []AccountGroup { return groups } -//GetGroup returns the group for an id if the account has it +// GetGroup returns the group for an id if the account has it func (a Account) GetGroup(id string) *AccountGroup { for _, group := range a.Groups { if group.Group.ID == id { @@ -270,7 +271,7 @@ func (a Account) GetGroup(id string) *AccountGroup { return nil } -//GetAssignedGroupIDs returns a list of IDs of directly assigned groups for this account +// GetAssignedGroupIDs returns a list of IDs of directly assigned groups for this account func (a Account) GetAssignedGroupIDs() []string { ids := make([]string, len(a.Groups)) for i, group := range a.Groups { @@ -279,7 +280,7 @@ func (a Account) GetAssignedGroupIDs() []string { return ids } -//CheckForGroupChanges checks for changes to account groups given a potential list of new groups +// CheckForGroupChanges checks for changes to account groups given a potential list of new groups func (a Account) CheckForGroupChanges(new []string) bool { unchanged := make([]bool, len(a.Groups)) @@ -305,14 +306,14 @@ func (a Account) CheckForGroupChanges(new []string) bool { return false } -//AccountRole represents a role assigned to an account +// AccountRole represents a role assigned to an account type AccountRole struct { Role AppOrgRole Active bool AdminSet bool } -//AccountRolesFromAppOrgRoles converts AppOrgRoles to AccountRoles +// AccountRolesFromAppOrgRoles converts AppOrgRoles to AccountRoles func AccountRolesFromAppOrgRoles(items []AppOrgRole, active bool, adminSet bool) []AccountRole { accountRoles := make([]AccountRole, len(items)) for i, role := range items { @@ -321,14 +322,14 @@ func AccountRolesFromAppOrgRoles(items []AppOrgRole, active bool, adminSet bool) return accountRoles } -//AccountGroup represents a group assigned to an account +// AccountGroup represents a group assigned to an account type AccountGroup struct { Group AppOrgGroup Active bool AdminSet bool } -//AccountGroupsFromAppOrgGroups converts AppOrgGroups to AccountGroups +// AccountGroupsFromAppOrgGroups converts AppOrgGroups to AccountGroups func AccountGroupsFromAppOrgGroups(items []AppOrgGroup, active bool, adminSet bool) []AccountGroup { accountGroups := make([]AccountGroup, len(items)) for i, group := range items { @@ -337,7 +338,7 @@ func AccountGroupsFromAppOrgGroups(items []AppOrgGroup, active bool, adminSet bo return accountGroups } -//AccountAuthType represents account auth type +// AccountAuthType represents account auth type type AccountAuthType struct { ID string @@ -357,7 +358,7 @@ type AccountAuthType struct { DateUpdated *time.Time } -//SetUnverified sets the Unverified flag to value in the account auth type itself and the appropriate account auth type within the account member +// SetUnverified sets the Unverified flag to value in the account auth type itself and the appropriate account auth type within the account member func (aat *AccountAuthType) SetUnverified(value bool) { if aat == nil { return @@ -371,7 +372,7 @@ func (aat *AccountAuthType) SetUnverified(value bool) { } } -//Credential represents a credential for account auth type/s +// Credential represents a credential for account auth type/s type Credential struct { ID string @@ -384,7 +385,7 @@ type Credential struct { DateUpdated *time.Time } -//MFAType represents a MFA type used by an account +// MFAType represents a MFA type used by an account type MFAType struct { ID string Type string @@ -396,10 +397,11 @@ type MFAType struct { DateUpdated *time.Time } -//Profile represents profile entity -// The profile is an information about the user -// What the person shares with the system/other users/ -// The person should be able to use the system even all profile fields are empty/it is just an information for the user/ +// Profile represents profile entity +// +// The profile is an information about the user +// What the person shares with the system/other users/ +// The person should be able to use the system even all profile fields are empty/it is just an information for the user/ type Profile struct { ID string @@ -420,7 +422,7 @@ type Profile struct { DateUpdated *time.Time } -//GetFullName returns the user's full name +// GetFullName returns the user's full name func (p Profile) GetFullName() string { fullname := p.FirstName if len(fullname) > 0 { @@ -430,7 +432,7 @@ func (p Profile) GetFullName() string { return fullname } -//Device represents user devices entity. +// Device represents user devices entity. type Device struct { ID string @@ -444,7 +446,7 @@ type Device struct { DateUpdated *time.Time } -//ExternalSystemUser represents external system user +// ExternalSystemUser represents external system user type ExternalSystemUser struct { Identifier string `json:"identifier" bson:"identifier"` //this is the identifier used in our system to map the user ExternalIDs map[string]string `json:"external_ids" bson:"external_ids"` @@ -461,7 +463,7 @@ type ExternalSystemUser struct { SystemSpecific map[string]interface{} `json:"system_specific" bson:"system_specific"` } -//Equals checks if two external system users are equals +// Equals checks if two external system users are equals func (esu ExternalSystemUser) Equals(other ExternalSystemUser) bool { if esu.Identifier != other.Identifier { return false @@ -493,7 +495,7 @@ func (esu ExternalSystemUser) Equals(other ExternalSystemUser) bool { return true } -//AccountRelations represents external relations between the application accounts in an organization +// AccountRelations represents external relations between the application accounts in an organization // For example in Safer Illinois application: // - families takes discount for covid tests. // - couples gets discount for the taxes. diff --git a/driven/emailer/adapter.go b/driven/emailer/adapter.go index 09911eae5..f73935b10 100644 --- a/driven/emailer/adapter.go +++ b/driven/emailer/adapter.go @@ -27,7 +27,7 @@ const ( typeMail logutils.MessageDataType = "mail" ) -//Adapter implements the Emailer interface +// Adapter implements the Emailer interface type Adapter struct { smptHost string smtpPortNum int @@ -37,7 +37,7 @@ type Adapter struct { emailDialer *gomail.Dialer } -//Send is used to send verification and password reset emails using Smtp connection +// Send is used to send verification and password reset emails using Smtp connection func (a *Adapter) Send(toEmail string, subject string, body string, attachmentFilename *string) error { if a.emailDialer == nil { return errors.New("email dialer is nil") @@ -63,7 +63,7 @@ func (a *Adapter) Send(toEmail string, subject string, body string, attachmentFi return nil } -//NewEmailerAdapter creates a new emailer adapter instance +// NewEmailerAdapter creates a new emailer adapter instance func NewEmailerAdapter(smtpHost string, smtpPortNum int, smtpUser string, smtpPassword string, smtpFrom string) *Adapter { emailDialer := gomail.NewDialer(smtpHost, smtpPortNum, smtpUser, smtpPassword) diff --git a/driven/profilebb/adapter.go b/driven/profilebb/adapter.go index 42cb97f33..35793273f 100644 --- a/driven/profilebb/adapter.go +++ b/driven/profilebb/adapter.go @@ -27,7 +27,7 @@ import ( "github.com/rokwire/logging-library-go/logutils" ) -//Adapter implements the ProfileBuildingBlock interface +// Adapter implements the ProfileBuildingBlock interface type Adapter struct { migrate bool host string @@ -118,7 +118,7 @@ type interest struct { Subcategories []string `json:"subcategories"` } -//GetProfileBBData gets profile data by queryParams +// GetProfileBBData gets profile data by queryParams func (a *Adapter) GetProfileBBData(queryParams map[string]string, l *logs.Log) (*model.Profile, map[string]interface{}, error) { if !a.migrate { return nil, nil, nil @@ -219,7 +219,7 @@ func parseTime(timeString string) (*time.Time, error) { return &parsedTime, nil } -//NewProfileBBAdapter creates a new profile building block adapter instance +// NewProfileBBAdapter creates a new profile building block adapter instance func NewProfileBBAdapter(migrate bool, profileHost string, apiKey string) *Adapter { return &Adapter{migrate: migrate, host: profileHost, apiKey: apiKey} } diff --git a/driven/storage/adapter.go b/driven/storage/adapter.go index 60f08aa8a..61b5301c4 100644 --- a/driven/storage/adapter.go +++ b/driven/storage/adapter.go @@ -23,6 +23,7 @@ import ( "sync" "time" + "github.com/rokwire/core-auth-library-go/v2/authutils" "github.com/rokwire/logging-library-go/errors" "github.com/rokwire/logging-library-go/logs" "github.com/rokwire/logging-library-go/logutils" @@ -34,7 +35,7 @@ import ( "gopkg.in/go-playground/validator.v9" ) -//Adapter implements the Storage interface +// Adapter implements the Storage interface type Adapter struct { db *database @@ -59,7 +60,7 @@ type Adapter struct { applicationConfigsLock *sync.RWMutex } -//Start starts the storage +// Start starts the storage func (sa *Adapter) Start() error { //start db err := sa.db.start() @@ -110,12 +111,12 @@ func (sa *Adapter) Start() error { return err } -//RegisterStorageListener registers a data change listener with the storage adapter +// RegisterStorageListener registers a data change listener with the storage adapter func (sa *Adapter) RegisterStorageListener(storageListener Listener) { sa.db.listeners = append(sa.db.listeners, storageListener) } -//PerformTransaction performs a transaction +// PerformTransaction performs a transaction func (sa *Adapter) PerformTransaction(transaction func(context TransactionContext) error) error { // transaction err := sa.db.dbClient.UseSession(context.Background(), func(sessionContext mongo.SessionContext) error { @@ -142,7 +143,7 @@ func (sa *Adapter) PerformTransaction(transaction func(context TransactionContex return err } -//cacheServiceRegs caches the service regs from the DB +// cacheServiceRegs caches the service regs from the DB func (sa *Adapter) cacheServiceRegs() error { sa.logger.Info("cacheServiceRegs..") @@ -167,19 +168,20 @@ func (sa *Adapter) setCachedServiceRegs(serviceRegs *[]model.ServiceReg) { err := validate.Struct(serviceReg) if err == nil { sa.cachedServiceRegs.Store(serviceReg.Registration.ServiceID, serviceReg) + sa.cachedServiceRegs.Store(serviceReg.Registration.ServiceAccountID, serviceReg) } else { - sa.logger.Errorf("failed to validate and cache service registration with registration.service_id %s: %s", serviceReg.Registration.ServiceID, err.Error()) + sa.logger.Errorf("failed to validate and cache service registration with registration.service_id %s, registration.service_account_id %s: %s", serviceReg.Registration.ServiceID, serviceReg.Registration.ServiceAccountID, err.Error()) } } } -func (sa *Adapter) getCachedServiceReg(serviceID string) (*model.ServiceReg, error) { +func (sa *Adapter) getCachedServiceReg(key string, value string) (*model.ServiceReg, error) { sa.serviceRegsLock.RLock() defer sa.serviceRegsLock.RUnlock() - errArgs := &logutils.FieldArgs{"registration.service_id": serviceID} + errArgs := &logutils.FieldArgs{key: value} - item, _ := sa.cachedServiceRegs.Load(serviceID) + item, _ := sa.cachedServiceRegs.Load(value) if item != nil { serviceReg, ok := item.(model.ServiceReg) if !ok { @@ -208,12 +210,17 @@ func (sa *Adapter) getCachedServiceRegs(serviceIDs []string) ([]model.ServiceReg } } else { serviceRegList = make([]model.ServiceReg, 0) + serviceIDs = make([]string, 0) sa.cachedServiceRegs.Range(func(key, item interface{}) bool { serviceReg, err := sa.processCachedServiceReg(key, item) if err != nil { return false } - serviceRegList = append(serviceRegList, *serviceReg) + + if !authutils.ContainsString(serviceIDs, serviceReg.Registration.ServiceID) { + serviceRegList = append(serviceRegList, *serviceReg) + serviceIDs = append(serviceIDs, serviceReg.Registration.ServiceID) + } return true }) @@ -236,7 +243,7 @@ func (sa *Adapter) processCachedServiceReg(key, item interface{}) (*model.Servic return &serviceReg, nil } -//cacheOrganizations caches the organizations from the DB +// cacheOrganizations caches the organizations from the DB func (sa *Adapter) cacheOrganizations() error { sa.logger.Info("cacheOrganizations..") @@ -309,7 +316,7 @@ func (sa *Adapter) getCachedOrganizations() ([]model.Organization, error) { return organizationList, err } -//cacheApplications caches the applications +// cacheApplications caches the applications func (sa *Adapter) cacheApplications() error { sa.logger.Info("cacheApplications..") @@ -413,7 +420,7 @@ func (sa *Adapter) getCachedApplicationType(id string) (*model.Application, *mod return nil, nil, errors.ErrorData(logutils.StatusMissing, model.TypeApplicationType, &logutils.FieldArgs{"id": id}) } -//cacheAuthTypes caches the auth types +// cacheAuthTypes caches the auth types func (sa *Adapter) cacheAuthTypes() error { sa.logger.Info("cacheAuthTypes..") @@ -493,7 +500,7 @@ func (sa *Adapter) getCachedAuthTypes() ([]model.AuthType, error) { return authTypeList, err } -//cacheApplicationsOrganizations caches the applications organizations +// cacheApplicationsOrganizations caches the applications organizations func (sa *Adapter) cacheApplicationsOrganizations() error { sa.logger.Info("cacheApplicationsOrganizations..") @@ -700,7 +707,7 @@ func (sa *Adapter) getCachedApplicationConfigByID(id string) (*model.Application return nil, errors.ErrorData(logutils.StatusMissing, model.TypeApplicationConfig, errArgs) } -//loadAuthTypes loads all auth types +// loadAuthTypes loads all auth types func (sa *Adapter) loadAuthTypes() ([]model.AuthType, error) { filter := bson.D{} var result []model.AuthType @@ -715,17 +722,17 @@ func (sa *Adapter) loadAuthTypes() ([]model.AuthType, error) { return result, nil } -//FindAuthType finds auth type by id or code +// FindAuthType finds auth type by id or code func (sa *Adapter) FindAuthType(codeOrID string) (*model.AuthType, error) { return sa.getCachedAuthType(codeOrID) } -//FindAuthTypes finds all auth types +// FindAuthTypes finds all auth types func (sa *Adapter) FindAuthTypes() ([]model.AuthType, error) { return sa.getCachedAuthTypes() } -//InsertLoginSession inserts login session +// InsertLoginSession inserts login session func (sa *Adapter) InsertLoginSession(context TransactionContext, session model.LoginSession) error { storageLoginSession := loginSessionToStorage(session) @@ -737,7 +744,7 @@ func (sa *Adapter) InsertLoginSession(context TransactionContext, session model. return nil } -//FindLoginSessions finds login sessions by identifier and sorts by date created +// FindLoginSessions finds login sessions by identifier and sorts by date created func (sa *Adapter) FindLoginSessions(context TransactionContext, identifier string) ([]model.LoginSession, error) { filter := bson.D{primitive.E{Key: "identifier", Value: identifier}} opts := options.Find() @@ -781,7 +788,7 @@ func (sa *Adapter) FindLoginSessions(context TransactionContext, identifier stri return sessions, nil } -//FindLoginSessionsByParams finds login sessions by params +// FindLoginSessionsByParams finds login sessions by params func (sa *Adapter) FindLoginSessionsByParams(appID string, orgID string, sessionID *string, identifier *string, accountAuthTypeIdentifier *string, appTypeID *string, appTypeIdentifier *string, anonymous *bool, deviceID *string, ipAddress *string) ([]model.LoginSession, error) { filter := bson.D{primitive.E{Key: "app_id", Value: appID}, @@ -845,7 +852,7 @@ func (sa *Adapter) FindLoginSessionsByParams(appID string, orgID string, session return loginSessions, nil } -//FindLoginSession finds a login session +// FindLoginSession finds a login session func (sa *Adapter) FindLoginSession(refreshToken string) (*model.LoginSession, error) { //find loggin session filter := bson.D{primitive.E{Key: "refresh_tokens", Value: refreshToken}} @@ -863,7 +870,7 @@ func (sa *Adapter) FindLoginSession(refreshToken string) (*model.LoginSession, e return sa.buildLoginSession(&loginSession) } -//FindAndUpdateLoginSession finds and updates a login session +// FindAndUpdateLoginSession finds and updates a login session func (sa *Adapter) FindAndUpdateLoginSession(context TransactionContext, id string) (*model.LoginSession, error) { //find loggin session filter := bson.D{primitive.E{Key: "_id", Value: id}} @@ -920,7 +927,7 @@ func (sa *Adapter) buildLoginSession(ls *loginSession) (*model.LoginSession, err return &modelLoginSession, nil } -//UpdateLoginSession updates login session +// UpdateLoginSession updates login session func (sa *Adapter) UpdateLoginSession(context TransactionContext, loginSession model.LoginSession) error { storageLoginSession := loginSessionToStorage(loginSession) @@ -933,7 +940,7 @@ func (sa *Adapter) UpdateLoginSession(context TransactionContext, loginSession m return nil } -//DeleteLoginSession deletes login session +// DeleteLoginSession deletes login session func (sa *Adapter) DeleteLoginSession(context TransactionContext, id string) error { filter := bson.M{"_id": id} @@ -947,7 +954,7 @@ func (sa *Adapter) DeleteLoginSession(context TransactionContext, id string) err return nil } -//DeleteLoginSessionsByIDs deletes login sessions by ids +// DeleteLoginSessionsByIDs deletes login sessions by ids func (sa *Adapter) DeleteLoginSessionsByIDs(transaction TransactionContext, ids []string) error { filter := bson.D{primitive.E{Key: "_id", Value: bson.M{"$in": ids}}} @@ -969,17 +976,17 @@ func (sa *Adapter) DeleteLoginSessionsByIDs(transaction TransactionContext, ids return nil } -//DeleteLoginSessionsByIdentifier deletes all login sessions with the identifier +// DeleteLoginSessionsByIdentifier deletes all login sessions with the identifier func (sa *Adapter) DeleteLoginSessionsByIdentifier(context TransactionContext, identifier string) error { return sa.deleteLoginSessions(context, "identifier", identifier, false) } -//DeleteLoginSessionByID deletes a login session by id +// DeleteLoginSessionByID deletes a login session by id func (sa *Adapter) DeleteLoginSessionByID(context TransactionContext, id string) error { return sa.deleteLoginSessions(context, "_id", id, true) } -//DeleteLoginSessionsByAccountAuthTypeID deletes login sessions by account auth type ID +// DeleteLoginSessionsByAccountAuthTypeID deletes login sessions by account auth type ID func (sa *Adapter) DeleteLoginSessionsByAccountAuthTypeID(context TransactionContext, id string) error { return sa.deleteLoginSessions(context, "account_auth_type_id", id, false) } @@ -997,7 +1004,7 @@ func (sa *Adapter) deleteLoginSessions(context TransactionContext, key string, v return nil } -//DeleteLoginSessionsByAccountAndSessionID deletes all login sessions with the identifier and sessionID +// DeleteLoginSessionsByAccountAndSessionID deletes all login sessions with the identifier and sessionID func (sa *Adapter) DeleteLoginSessionsByAccountAndSessionID(context TransactionContext, identifier string, sessionID string) error { filter := bson.M{"identifier": identifier, "_id": sessionID} result, err := sa.db.loginsSessions.DeleteOne(filter, nil) @@ -1015,7 +1022,7 @@ func (sa *Adapter) DeleteLoginSessionsByAccountAndSessionID(context TransactionC return nil } -//DeleteMFAExpiredSessions deletes MFA expired sessions +// DeleteMFAExpiredSessions deletes MFA expired sessions func (sa *Adapter) DeleteMFAExpiredSessions() error { now := time.Now().UTC() @@ -1029,7 +1036,7 @@ func (sa *Adapter) DeleteMFAExpiredSessions() error { return nil } -//FindSessionsLazy finds all sessions for app/org but lazy filled. +// FindSessionsLazy finds all sessions for app/org but lazy filled. // - lazy means that we make only one request to the logins sessions collection and fill the objects with what we have there. // - i.e. we do not apply any relations // - this partly filled is enough for some cases(expiration policy checks for example) but in the same time it give very good performace @@ -1067,7 +1074,7 @@ func (sa *Adapter) FindSessionsLazy(appID string, orgID string) ([]model.LoginSe return sessions, nil } -//FindAccount finds an account for app, org, auth type and account auth type identifier +// FindAccount finds an account for app, org, auth type and account auth type identifier func (sa *Adapter) FindAccount(context TransactionContext, appOrgID string, authTypeID string, accountAuthTypeIdentifier string) (*model.Account, error) { filter := bson.D{primitive.E{Key: "app_org_id", Value: appOrgID}, primitive.E{Key: "auth_types.auth_type_id", Value: authTypeID}, @@ -1096,7 +1103,7 @@ func (sa *Adapter) FindAccount(context TransactionContext, appOrgID string, auth return &modelAccount, nil } -//FindAccounts finds accounts +// FindAccounts finds accounts func (sa *Adapter) FindAccounts(limit int, offset int, appID string, orgID string, accountID *string, firstName *string, lastName *string, authType *string, authTypeIdentifier *string, hasPermissions *bool, permissions []string, roleIDs []string, groupIDs []string) ([]model.Account, error) { //find app org id @@ -1161,7 +1168,7 @@ func (sa *Adapter) FindAccounts(limit int, offset int, appID string, orgID strin return accounts, nil } -//FindAccountsByAccountID finds accounts +// FindAccountsByAccountID finds accounts func (sa *Adapter) FindAccountsByAccountID(appID string, orgID string, accountIDs []string) ([]model.Account, error) { //find app org id @@ -1180,12 +1187,12 @@ func (sa *Adapter) FindAccountsByAccountID(appID string, orgID string, accountID return accounts, nil } -//FindAccountByID finds an account by id +// FindAccountByID finds an account by id func (sa *Adapter) FindAccountByID(context TransactionContext, id string) (*model.Account, error) { return sa.findAccount(context, "_id", id) } -//FindAccountByAuthTypeID finds an account by auth type id +// FindAccountByAuthTypeID finds an account by auth type id func (sa *Adapter) FindAccountByAuthTypeID(context TransactionContext, id string) (*model.Account, error) { return sa.findAccount(context, "auth_types.id", id) } @@ -1230,7 +1237,7 @@ func (sa *Adapter) findStorageAccount(context TransactionContext, key string, id return &account, nil } -//InsertAccount inserts an account +// InsertAccount inserts an account func (sa *Adapter) InsertAccount(context TransactionContext, account model.Account) (*model.Account, error) { storageAccount := accountToStorage(&account) @@ -1242,7 +1249,7 @@ func (sa *Adapter) InsertAccount(context TransactionContext, account model.Accou return &account, nil } -//SaveAccount saves an existing account +// SaveAccount saves an existing account func (sa *Adapter) SaveAccount(context TransactionContext, account *model.Account) error { if account == nil { return errors.ErrorData(logutils.StatusInvalid, logutils.TypeArg, logutils.StringArgs("account")) @@ -1259,7 +1266,7 @@ func (sa *Adapter) SaveAccount(context TransactionContext, account *model.Accoun return nil } -//DeleteAccount deletes an account +// DeleteAccount deletes an account func (sa *Adapter) DeleteAccount(context TransactionContext, id string) error { //TODO - we have to decide what we do on delete user operation - removing all user relations, (or) mark the user disabled etc @@ -1275,7 +1282,7 @@ func (sa *Adapter) DeleteAccount(context TransactionContext, id string) error { return nil } -//FindServiceAccount finds a service account by accountID, appID, and orgID +// FindServiceAccount finds a service account by accountID, appID, and orgID func (sa *Adapter) FindServiceAccount(context TransactionContext, accountID string, appID string, orgID string) (*model.ServiceAccount, error) { filter := bson.D{primitive.E{Key: "account_id", Value: accountID}, primitive.E{Key: "app_id", Value: appID}, primitive.E{Key: "org_id", Value: orgID}} @@ -1294,7 +1301,7 @@ func (sa *Adapter) FindServiceAccount(context TransactionContext, accountID stri return modelAccount, nil } -//FindServiceAccounts gets all service accounts matching a search +// FindServiceAccounts gets all service accounts matching a search func (sa *Adapter) FindServiceAccounts(params map[string]interface{}) ([]model.ServiceAccount, error) { filter := bson.D{} for k, v := range params { @@ -1317,7 +1324,7 @@ func (sa *Adapter) FindServiceAccounts(params map[string]interface{}) ([]model.S return modelAccounts, nil } -//InsertServiceAccount inserts a service account +// InsertServiceAccount inserts a service account func (sa *Adapter) InsertServiceAccount(account *model.ServiceAccount) error { if account == nil { return errors.ErrorData(logutils.StatusInvalid, model.TypeServiceAccount, nil) @@ -1333,7 +1340,7 @@ func (sa *Adapter) InsertServiceAccount(account *model.ServiceAccount) error { return nil } -//UpdateServiceAccount updates a service account +// UpdateServiceAccount updates a service account func (sa *Adapter) UpdateServiceAccount(account *model.ServiceAccount) (*model.ServiceAccount, error) { if account == nil { return nil, errors.ErrorData(logutils.StatusInvalid, model.TypeServiceAccount, nil) @@ -1368,7 +1375,7 @@ func (sa *Adapter) UpdateServiceAccount(account *model.ServiceAccount) (*model.S return modelAccount, nil } -//DeleteServiceAccount deletes a service account +// DeleteServiceAccount deletes a service account func (sa *Adapter) DeleteServiceAccount(accountID string, appID string, orgID string) error { filter := bson.D{primitive.E{Key: "account_id", Value: accountID}, primitive.E{Key: "app_id", Value: appID}, primitive.E{Key: "org_id", Value: orgID}} @@ -1387,7 +1394,7 @@ func (sa *Adapter) DeleteServiceAccount(accountID string, appID string, orgID st return nil } -//DeleteServiceAccounts deletes service accounts by accountID +// DeleteServiceAccounts deletes service accounts by accountID func (sa *Adapter) DeleteServiceAccounts(accountID string) error { filter := bson.D{primitive.E{Key: "account_id", Value: accountID}} @@ -1402,7 +1409,7 @@ func (sa *Adapter) DeleteServiceAccounts(accountID string) error { return nil } -//InsertServiceAccountCredential inserts a service account credential +// InsertServiceAccountCredential inserts a service account credential func (sa *Adapter) InsertServiceAccountCredential(accountID string, creds *model.ServiceAccountCredential) error { if creds == nil { return errors.ErrorData(logutils.StatusInvalid, logutils.TypeArg, logutils.StringArgs("credentials")) @@ -1432,7 +1439,7 @@ func (sa *Adapter) InsertServiceAccountCredential(accountID string, creds *model return nil } -//DeleteServiceAccountCredential deletes a service account credential +// DeleteServiceAccountCredential deletes a service account credential func (sa *Adapter) DeleteServiceAccountCredential(accountID string, credID string) error { filter := bson.D{primitive.E{Key: "account_id", Value: accountID}} update := bson.D{ @@ -1458,7 +1465,7 @@ func (sa *Adapter) DeleteServiceAccountCredential(accountID string, credID strin return nil } -//UpdateAccountPreferences updates account preferences +// UpdateAccountPreferences updates account preferences func (sa *Adapter) UpdateAccountPreferences(accountID string, preferences map[string]interface{}) error { filter := bson.D{primitive.E{Key: "_id", Value: accountID}} update := bson.D{ @@ -1478,7 +1485,7 @@ func (sa *Adapter) UpdateAccountPreferences(accountID string, preferences map[st return nil } -//InsertAccountPermissions inserts account permissions +// InsertAccountPermissions inserts account permissions func (sa *Adapter) InsertAccountPermissions(context TransactionContext, accountID string, permissions []model.Permission) error { filter := bson.D{primitive.E{Key: "_id", Value: accountID}} update := bson.D{ @@ -1502,7 +1509,7 @@ func (sa *Adapter) InsertAccountPermissions(context TransactionContext, accountI return nil } -//UpdateAccountPermissions updates account permissions +// UpdateAccountPermissions updates account permissions func (sa *Adapter) UpdateAccountPermissions(context TransactionContext, accountID string, hasPermissions bool, permissions []model.Permission) error { filter := bson.D{primitive.E{Key: "_id", Value: accountID}} update := bson.D{ @@ -1524,7 +1531,7 @@ func (sa *Adapter) UpdateAccountPermissions(context TransactionContext, accountI return nil } -//DeleteAccountPermissions deletes permissions from an account +// DeleteAccountPermissions deletes permissions from an account func (sa *Adapter) DeleteAccountPermissions(context TransactionContext, accountID string, hasPermissions bool, permissions []model.Permission) error { //filter filter := bson.D{primitive.E{Key: "_id", Value: accountID}} @@ -1554,7 +1561,7 @@ func (sa *Adapter) DeleteAccountPermissions(context TransactionContext, accountI return nil } -//InsertAccountRoles inserts account roles +// InsertAccountRoles inserts account roles func (sa *Adapter) InsertAccountRoles(context TransactionContext, accountID string, appOrgID string, roles []model.AccountRole) error { stgRoles := accountRolesToStorage(roles) @@ -1581,7 +1588,7 @@ func (sa *Adapter) InsertAccountRoles(context TransactionContext, accountID stri return nil } -//InsertAccountGroups inserts account groups +// InsertAccountGroups inserts account groups func (sa *Adapter) InsertAccountGroups(context TransactionContext, accountID string, appOrgID string, groups []model.AccountGroup) error { stgGroups := accountGroupsToStorage(groups) @@ -1608,7 +1615,7 @@ func (sa *Adapter) InsertAccountGroups(context TransactionContext, accountID str return nil } -//InsertAccountsGroup inserts accounts into a group +// InsertAccountsGroup inserts accounts into a group func (sa *Adapter) InsertAccountsGroup(group model.AccountGroup, accounts []model.Account) error { //prepare filter accountsIDs := make([]string, len(accounts)) @@ -1637,7 +1644,7 @@ func (sa *Adapter) InsertAccountsGroup(group model.AccountGroup, accounts []mode return nil } -//RemoveAccountsGroup removes accounts from a group +// RemoveAccountsGroup removes accounts from a group func (sa *Adapter) RemoveAccountsGroup(groupID string, accounts []model.Account, hasPermissions []bool) error { //split accounts list by admin status standardAccountIDs := make([]string, 0) @@ -1663,7 +1670,7 @@ func (sa *Adapter) RemoveAccountsGroup(groupID string, accounts []model.Account, return nil } -//RemoveAccountsGroup removes accounts from a group +// RemoveAccountsGroup removes accounts from a group func (sa *Adapter) removeAccountsFromGroup(groupID string, accountIDs []string, hasPermissions bool) error { if len(accountIDs) == 0 { return nil @@ -1689,7 +1696,7 @@ func (sa *Adapter) removeAccountsFromGroup(groupID string, accountIDs []string, return nil } -//UpdateAccountRoles updates the account roles +// UpdateAccountRoles updates the account roles func (sa *Adapter) UpdateAccountRoles(context TransactionContext, accountID string, hasPermissions bool, roles []model.AccountRole) error { stgRoles := accountRolesToStorage(roles) @@ -1713,7 +1720,7 @@ func (sa *Adapter) UpdateAccountRoles(context TransactionContext, accountID stri return nil } -//DeleteAccountRoles deletes account roles +// DeleteAccountRoles deletes account roles func (sa *Adapter) DeleteAccountRoles(context TransactionContext, accountID string, hasPermissions bool, roleIDs []string) error { //filter filter := bson.D{primitive.E{Key: "_id", Value: accountID}} @@ -1739,7 +1746,7 @@ func (sa *Adapter) DeleteAccountRoles(context TransactionContext, accountID stri return nil } -//UpdateAccountGroups updates the account groups +// UpdateAccountGroups updates the account groups func (sa *Adapter) UpdateAccountGroups(context TransactionContext, accountID string, hasPermissions bool, groups []model.AccountGroup) error { stgGroups := accountGroupsToStorage(groups) @@ -1763,7 +1770,7 @@ func (sa *Adapter) UpdateAccountGroups(context TransactionContext, accountID str return nil } -//InsertAccountAuthType inserts am account auth type +// InsertAccountAuthType inserts am account auth type func (sa *Adapter) InsertAccountAuthType(item model.AccountAuthType) error { storageItem := accountAuthTypeToStorage(item) @@ -1786,7 +1793,7 @@ func (sa *Adapter) InsertAccountAuthType(item model.AccountAuthType) error { return nil } -//UpdateAccountAuthType updates account auth type +// UpdateAccountAuthType updates account auth type func (sa *Adapter) UpdateAccountAuthType(item model.AccountAuthType) error { // transaction err := sa.db.dbClient.UseSession(context.Background(), func(sessionContext mongo.SessionContext) error { @@ -1852,7 +1859,7 @@ func (sa *Adapter) UpdateAccountAuthType(item model.AccountAuthType) error { return nil } -//DeleteAccountAuthType deletes an account auth type +// DeleteAccountAuthType deletes an account auth type func (sa *Adapter) DeleteAccountAuthType(context TransactionContext, item model.AccountAuthType) error { filter := bson.M{"_id": item.Account.ID} update := bson.D{ @@ -1872,7 +1879,7 @@ func (sa *Adapter) DeleteAccountAuthType(context TransactionContext, item model. return nil } -//UpdateAccountExternalIDs updates account external IDs +// UpdateAccountExternalIDs updates account external IDs func (sa *Adapter) UpdateAccountExternalIDs(accountID string, externalIDs map[string]string) error { filter := bson.D{primitive.E{Key: "_id", Value: accountID}} now := time.Now().UTC() @@ -1894,7 +1901,7 @@ func (sa *Adapter) UpdateAccountExternalIDs(accountID string, externalIDs map[st return nil } -//UpdateLoginSessionExternalIDs updates login session external IDs +// UpdateLoginSessionExternalIDs updates login session external IDs func (sa *Adapter) UpdateLoginSessionExternalIDs(accountID string, externalIDs map[string]string) error { filter := bson.D{primitive.E{Key: "identifier", Value: accountID}} now := time.Now().UTC() @@ -1913,7 +1920,7 @@ func (sa *Adapter) UpdateLoginSessionExternalIDs(accountID string, externalIDs m return nil } -//CountAccountsByRoleID counts how many accounts there are with the passed role id +// CountAccountsByRoleID counts how many accounts there are with the passed role id func (sa *Adapter) CountAccountsByRoleID(roleID string) (*int64, error) { filter := bson.D{primitive.E{Key: "roles._id", Value: roleID}} @@ -1924,7 +1931,7 @@ func (sa *Adapter) CountAccountsByRoleID(roleID string) (*int64, error) { return &count, nil } -//CountAccountsByGroupID counts how many accounts there are with the passed group id +// CountAccountsByGroupID counts how many accounts there are with the passed group id func (sa *Adapter) CountAccountsByGroupID(groupID string) (*int64, error) { filter := bson.D{primitive.E{Key: "groups._id", Value: groupID}} @@ -1935,7 +1942,7 @@ func (sa *Adapter) CountAccountsByGroupID(groupID string) (*int64, error) { return &count, nil } -//FindCredential finds a credential by ID +// FindCredential finds a credential by ID func (sa *Adapter) FindCredential(context TransactionContext, ID string) (*model.Credential, error) { filter := bson.D{primitive.E{Key: "_id", Value: ID}} @@ -1952,7 +1959,7 @@ func (sa *Adapter) FindCredential(context TransactionContext, ID string) (*model return &modelCreds, nil } -//InsertCredential inserts a set of credential +// InsertCredential inserts a set of credential func (sa *Adapter) InsertCredential(context TransactionContext, creds *model.Credential) error { storageCreds := credentialToStorage(creds) @@ -1968,7 +1975,7 @@ func (sa *Adapter) InsertCredential(context TransactionContext, creds *model.Cre return nil } -//UpdateCredential updates a set of credentials +// UpdateCredential updates a set of credentials func (sa *Adapter) UpdateCredential(context TransactionContext, creds *model.Credential) error { storageCreds := credentialToStorage(creds) @@ -1985,7 +1992,7 @@ func (sa *Adapter) UpdateCredential(context TransactionContext, creds *model.Cre return nil } -//UpdateCredentialValue updates the value in credentials collection +// UpdateCredentialValue updates the value in credentials collection func (sa *Adapter) UpdateCredentialValue(ID string, value map[string]interface{}) error { filter := bson.D{primitive.E{Key: "_id", Value: ID}} update := bson.D{ @@ -2005,7 +2012,7 @@ func (sa *Adapter) UpdateCredentialValue(ID string, value map[string]interface{} return nil } -//DeleteCredential deletes a credential +// DeleteCredential deletes a credential func (sa *Adapter) DeleteCredential(context TransactionContext, ID string) error { filter := bson.D{primitive.E{Key: "_id", Value: ID}} @@ -2020,7 +2027,7 @@ func (sa *Adapter) DeleteCredential(context TransactionContext, ID string) error return nil } -//FindMFAType finds one MFA type for an account +// FindMFAType finds one MFA type for an account func (sa *Adapter) FindMFAType(context TransactionContext, accountID string, identifier string, mfaType string) (*model.MFAType, error) { filter := bson.D{ primitive.E{Key: "_id", Value: accountID}, @@ -2044,7 +2051,7 @@ func (sa *Adapter) FindMFAType(context TransactionContext, accountID string, ide return nil, errors.ErrorData(logutils.StatusMissing, model.TypeMFAType, nil) } -//FindMFATypes finds all MFA types for an account +// FindMFATypes finds all MFA types for an account func (sa *Adapter) FindMFATypes(accountID string) ([]model.MFAType, error) { filter := bson.D{primitive.E{Key: "_id", Value: accountID}} @@ -2057,7 +2064,7 @@ func (sa *Adapter) FindMFATypes(accountID string) ([]model.MFAType, error) { return mfaTypesFromStorage(account.MFATypes), nil } -//InsertMFAType inserts a MFA type +// InsertMFAType inserts a MFA type func (sa *Adapter) InsertMFAType(context TransactionContext, mfa *model.MFAType, accountID string) error { if mfa == nil { return errors.ErrorData(logutils.StatusMissing, model.TypeMFAType, nil) @@ -2092,7 +2099,7 @@ func (sa *Adapter) InsertMFAType(context TransactionContext, mfa *model.MFAType, return nil } -//UpdateMFAType updates one MFA type +// UpdateMFAType updates one MFA type func (sa *Adapter) UpdateMFAType(context TransactionContext, mfa *model.MFAType, accountID string) error { if mfa.Params == nil || mfa.Params["identifier"] == nil { return errors.ErrorData(logutils.StatusMissing, "mfa identifier", nil) @@ -2126,7 +2133,7 @@ func (sa *Adapter) UpdateMFAType(context TransactionContext, mfa *model.MFAType, return nil } -//DeleteMFAType deletes a MFA type +// DeleteMFAType deletes a MFA type func (sa *Adapter) DeleteMFAType(context TransactionContext, accountID string, identifier string, mfaType string) error { filter := bson.D{primitive.E{Key: "_id", Value: accountID}} update := bson.D{ @@ -2152,7 +2159,7 @@ func (sa *Adapter) DeleteMFAType(context TransactionContext, accountID string, i return nil } -//FindPermissions finds a set of permissions +// FindPermissions finds a set of permissions func (sa *Adapter) FindPermissions(context TransactionContext, ids []string) ([]model.Permission, error) { if len(ids) == 0 { return []model.Permission{}, nil @@ -2168,15 +2175,15 @@ func (sa *Adapter) FindPermissions(context TransactionContext, ids []string) ([] return permissionsResult, nil } -//FindPermissionsByServiceIDs finds permissions -func (sa *Adapter) FindPermissionsByServiceIDs(serviceIDs []string) ([]model.Permission, error) { +// FindPermissionsByServiceIDs finds permissions +func (sa *Adapter) FindPermissionsByServiceIDs(context TransactionContext, serviceIDs []string) ([]model.Permission, error) { if len(serviceIDs) == 0 { return nil, nil } filter := bson.D{primitive.E{Key: "service_id", Value: bson.M{"$in": serviceIDs}}} var permissionsResult []model.Permission - err := sa.db.permissions.Find(filter, &permissionsResult, nil) + err := sa.db.permissions.FindWithContext(context, filter, &permissionsResult, nil) if err != nil { return nil, err } @@ -2184,7 +2191,7 @@ func (sa *Adapter) FindPermissionsByServiceIDs(serviceIDs []string) ([]model.Per return permissionsResult, nil } -//FindPermissionsByName finds a set of permissions +// FindPermissionsByName finds a set of permissions func (sa *Adapter) FindPermissionsByName(context TransactionContext, names []string) ([]model.Permission, error) { if len(names) == 0 { return []model.Permission{}, nil @@ -2200,7 +2207,7 @@ func (sa *Adapter) FindPermissionsByName(context TransactionContext, names []str return permissionsResult, nil } -//InsertPermission inserts a new permission +// InsertPermission inserts a new permission func (sa *Adapter) InsertPermission(context TransactionContext, permission model.Permission) error { _, err := sa.db.permissions.InsertOneWithContext(context, permission) if err != nil { @@ -2209,8 +2216,8 @@ func (sa *Adapter) InsertPermission(context TransactionContext, permission model return nil } -//UpdatePermission updates permission -func (sa *Adapter) UpdatePermission(item model.Permission) error { +// UpdatePermission updates permission +func (sa *Adapter) UpdatePermission(context TransactionContext, item model.Permission) error { //TODO //This will be slow operation as we keep a copy of the entity in the users collection without index. //Maybe we need to up the transaction timeout for this operation because of this. @@ -2229,7 +2236,7 @@ func (sa *Adapter) UpdatePermission(item model.Permission) error { }}, } - res, err := sa.db.permissions.UpdateOne(filter, permissionUpdate, nil) + res, err := sa.db.permissions.UpdateOneWithContext(context, filter, permissionUpdate, nil) if err != nil { return errors.WrapErrorAction(logutils.ActionUpdate, model.TypePermission, &logutils.FieldArgs{"name": item.Name}, err) } @@ -2241,7 +2248,7 @@ func (sa *Adapter) UpdatePermission(item model.Permission) error { return nil } -//DeletePermission deletes permission +// DeletePermission deletes permission func (sa *Adapter) DeletePermission(id string) error { //TODO //This will be slow operation as we keep a copy of the entity in the users collection without index. @@ -2249,7 +2256,7 @@ func (sa *Adapter) DeletePermission(id string) error { return errors.New(logutils.Unimplemented) } -//FindAppOrgRoles finds all application organization roles fora given AppOrg ID +// FindAppOrgRoles finds all application organization roles fora given AppOrg ID func (sa *Adapter) FindAppOrgRoles(appOrgID string) ([]model.AppOrgRole, error) { rolesFilter := bson.D{primitive.E{Key: "app_org_id", Value: appOrgID}} var rolesResult []appOrgRole @@ -2269,7 +2276,7 @@ func (sa *Adapter) FindAppOrgRoles(appOrgID string) ([]model.AppOrgRole, error) return result, nil } -//FindAppOrgRolesByIDs finds a set of application organization roles for the provided IDs +// FindAppOrgRolesByIDs finds a set of application organization roles for the provided IDs func (sa *Adapter) FindAppOrgRolesByIDs(context TransactionContext, ids []string, appOrgID string) ([]model.AppOrgRole, error) { if len(ids) == 0 { return []model.AppOrgRole{}, nil @@ -2296,7 +2303,7 @@ func (sa *Adapter) FindAppOrgRolesByIDs(context TransactionContext, ids []string return result, nil } -//FindAppOrgRole finds an application organization role +// FindAppOrgRole finds an application organization role func (sa *Adapter) FindAppOrgRole(id string, appOrgID string) (*model.AppOrgRole, error) { filter := bson.D{primitive.E{Key: "_id", Value: id}, primitive.E{Key: "app_org_id", Value: appOrgID}} var rolesResult []appOrgRole @@ -2319,7 +2326,7 @@ func (sa *Adapter) FindAppOrgRole(id string, appOrgID string) (*model.AppOrgRole return &result, nil } -//InsertAppOrgRole inserts a new application organization role +// InsertAppOrgRole inserts a new application organization role func (sa *Adapter) InsertAppOrgRole(context TransactionContext, item model.AppOrgRole) error { appOrg, err := sa.getCachedApplicationOrganizationByKey(item.AppOrg.ID) if err != nil { @@ -2337,7 +2344,7 @@ func (sa *Adapter) InsertAppOrgRole(context TransactionContext, item model.AppOr return nil } -//UpdateAppOrgRole updates application organization role +// UpdateAppOrgRole updates application organization role func (sa *Adapter) UpdateAppOrgRole(item model.AppOrgRole) error { //TODO //This will be slow operation as we keep a copy of the entity in the users collection without index. @@ -2345,9 +2352,9 @@ func (sa *Adapter) UpdateAppOrgRole(item model.AppOrgRole) error { return errors.New(logutils.Unimplemented) } -//DeleteAppOrgRole deletes application organization role -// - make sure to call this function once you have verified that there is no any relations -// in other collections for the role which is supposed to be deleted. +// DeleteAppOrgRole deletes application organization role +// - make sure to call this function once you have verified that there is no any relations +// in other collections for the role which is supposed to be deleted. func (sa *Adapter) DeleteAppOrgRole(id string) error { filter := bson.M{"_id": id} result, err := sa.db.applicationsOrganizationsRoles.DeleteOne(filter, nil) @@ -2364,7 +2371,7 @@ func (sa *Adapter) DeleteAppOrgRole(id string) error { return nil } -//InsertAppOrgRolePermissions inserts permissions to role +// InsertAppOrgRolePermissions inserts permissions to role func (sa *Adapter) InsertAppOrgRolePermissions(context TransactionContext, roleID string, permissions []model.Permission) error { filter := bson.D{primitive.E{Key: "_id", Value: roleID}} @@ -2385,7 +2392,7 @@ func (sa *Adapter) InsertAppOrgRolePermissions(context TransactionContext, roleI return nil } -//FindAppOrgGroups finds all application organization groups for the provided AppOrg ID +// FindAppOrgGroups finds all application organization groups for the provided AppOrg ID func (sa *Adapter) FindAppOrgGroups(appOrgID string) ([]model.AppOrgGroup, error) { filter := bson.D{primitive.E{Key: "app_org_id", Value: appOrgID}} var groupsResult []appOrgGroup @@ -2404,7 +2411,7 @@ func (sa *Adapter) FindAppOrgGroups(appOrgID string) ([]model.AppOrgGroup, error return result, nil } -//FindAppOrgGroupsByIDs finds a set of application organization groups for the provided IDs +// FindAppOrgGroupsByIDs finds a set of application organization groups for the provided IDs func (sa *Adapter) FindAppOrgGroupsByIDs(context TransactionContext, ids []string, appOrgID string) ([]model.AppOrgGroup, error) { if len(ids) == 0 { return []model.AppOrgGroup{}, nil @@ -2430,7 +2437,7 @@ func (sa *Adapter) FindAppOrgGroupsByIDs(context TransactionContext, ids []strin return result, nil } -//FindAppOrgGroup finds a application organization group +// FindAppOrgGroup finds a application organization group func (sa *Adapter) FindAppOrgGroup(id string, appOrgID string) (*model.AppOrgGroup, error) { filter := bson.D{primitive.E{Key: "_id", Value: id}, primitive.E{Key: "app_org_id", Value: appOrgID}} var groupsResult []appOrgGroup @@ -2453,7 +2460,7 @@ func (sa *Adapter) FindAppOrgGroup(id string, appOrgID string) (*model.AppOrgGro return &result, nil } -//InsertAppOrgGroup inserts a new application organization group +// InsertAppOrgGroup inserts a new application organization group func (sa *Adapter) InsertAppOrgGroup(context TransactionContext, item model.AppOrgGroup) error { group := appOrgGroupToStorage(item) @@ -2464,7 +2471,7 @@ func (sa *Adapter) InsertAppOrgGroup(context TransactionContext, item model.AppO return nil } -//UpdateAppOrgGroup updates application organization group +// UpdateAppOrgGroup updates application organization group func (sa *Adapter) UpdateAppOrgGroup(item model.AppOrgGroup) error { //TODO //This will be slow operation as we keep a copy of the entity in the users collection without index. @@ -2472,9 +2479,9 @@ func (sa *Adapter) UpdateAppOrgGroup(item model.AppOrgGroup) error { return errors.New(logutils.Unimplemented) } -//DeleteAppOrgGroup deletes application organization group -// - make sure to call this function once you have verified that there is no any relations -// in other collections for the group which is supposed to be deleted. +// DeleteAppOrgGroup deletes application organization group +// - make sure to call this function once you have verified that there is no any relations +// in other collections for the group which is supposed to be deleted. func (sa *Adapter) DeleteAppOrgGroup(id string) error { filter := bson.M{"_id": id} result, err := sa.db.applicationsOrganizationsGroups.DeleteOne(filter, nil) @@ -2492,7 +2499,7 @@ func (sa *Adapter) DeleteAppOrgGroup(id string) error { return nil } -//CountGroupsByRoleID counts how many groups there are with the passed role id +// CountGroupsByRoleID counts how many groups there are with the passed role id func (sa *Adapter) CountGroupsByRoleID(roleID string) (*int64, error) { filter := bson.D{primitive.E{Key: "roles._id", Value: roleID}} @@ -2503,7 +2510,7 @@ func (sa *Adapter) CountGroupsByRoleID(roleID string) (*int64, error) { return &count, nil } -//LoadAPIKeys finds all api key documents in the DB +// LoadAPIKeys finds all api key documents in the DB func (sa *Adapter) LoadAPIKeys() ([]model.APIKey, error) { filter := bson.D{} var result []model.APIKey @@ -2515,7 +2522,7 @@ func (sa *Adapter) LoadAPIKeys() ([]model.APIKey, error) { return result, nil } -//InsertAPIKey inserts an API key +// InsertAPIKey inserts an API key func (sa *Adapter) InsertAPIKey(context TransactionContext, apiKey model.APIKey) (*model.APIKey, error) { _, err := sa.db.apiKeys.InsertOneWithContext(context, apiKey) if err != nil { @@ -2524,7 +2531,7 @@ func (sa *Adapter) InsertAPIKey(context TransactionContext, apiKey model.APIKey) return &apiKey, nil } -//UpdateAPIKey updates the API key in storage +// UpdateAPIKey updates the API key in storage func (sa *Adapter) UpdateAPIKey(apiKey model.APIKey) error { filter := bson.M{"_id": apiKey.ID} err := sa.db.apiKeys.ReplaceOne(filter, apiKey, nil) @@ -2535,7 +2542,7 @@ func (sa *Adapter) UpdateAPIKey(apiKey model.APIKey) error { return nil } -//DeleteAPIKey deletes the API key from storage +// DeleteAPIKey deletes the API key from storage func (sa *Adapter) DeleteAPIKey(ID string) error { filter := bson.M{"_id": ID} result, err := sa.db.apiKeys.DeleteOne(filter, nil) @@ -2553,7 +2560,7 @@ func (sa *Adapter) DeleteAPIKey(ID string) error { return nil } -//LoadIdentityProviders finds all identity providers documents in the DB +// LoadIdentityProviders finds all identity providers documents in the DB func (sa *Adapter) LoadIdentityProviders() ([]model.IdentityProvider, error) { filter := bson.D{} var result []model.IdentityProvider @@ -2569,7 +2576,7 @@ func (sa *Adapter) LoadIdentityProviders() ([]model.IdentityProvider, error) { } -//UpdateProfile updates a profile +// UpdateProfile updates a profile func (sa *Adapter) UpdateProfile(context TransactionContext, profile model.Profile) error { filter := bson.D{primitive.E{Key: "profile.id", Value: profile.ID}} @@ -2599,7 +2606,7 @@ func (sa *Adapter) UpdateProfile(context TransactionContext, profile model.Profi return nil } -//FindProfiles finds profiles by app id, authtype id and account auth type identifier +// FindProfiles finds profiles by app id, authtype id and account auth type identifier func (sa *Adapter) FindProfiles(appID string, authTypeID string, accountAuthTypeIdentifier string) ([]model.Profile, error) { pipeline := []bson.M{ {"$lookup": bson.M{ @@ -2624,7 +2631,7 @@ func (sa *Adapter) FindProfiles(appID string, authTypeID string, accountAuthType return result, nil } -//CreateGlobalConfig creates global config +// CreateGlobalConfig creates global config func (sa *Adapter) CreateGlobalConfig(context TransactionContext, globalConfig *model.GlobalConfig) error { if globalConfig == nil { return errors.ErrorData(logutils.StatusInvalid, logutils.TypeArg, logutils.StringArgs("global_config")) @@ -2638,7 +2645,7 @@ func (sa *Adapter) CreateGlobalConfig(context TransactionContext, globalConfig * return nil } -//GetGlobalConfig give config +// GetGlobalConfig give config func (sa *Adapter) GetGlobalConfig() (*model.GlobalConfig, error) { filter := bson.D{} var result []model.GlobalConfig @@ -2654,7 +2661,7 @@ func (sa *Adapter) GetGlobalConfig() (*model.GlobalConfig, error) { } -//DeleteGlobalConfig deletes the global configuration from storage +// DeleteGlobalConfig deletes the global configuration from storage func (sa *Adapter) DeleteGlobalConfig(context TransactionContext) error { delFilter := bson.D{} _, err := sa.db.globalConfig.DeleteManyWithContext(context, delFilter, nil) @@ -2665,12 +2672,12 @@ func (sa *Adapter) DeleteGlobalConfig(context TransactionContext) error { return nil } -//FindOrganization finds an organization +// FindOrganization finds an organization func (sa *Adapter) FindOrganization(id string) (*model.Organization, error) { return sa.getCachedOrganization(id) } -//FindSystemOrganization finds the system organization (only one) +// FindSystemOrganization finds the system organization (only one) func (sa *Adapter) FindSystemOrganization() (*model.Organization, error) { organizations, err := sa.getCachedOrganizations() if err != nil { @@ -2686,12 +2693,12 @@ func (sa *Adapter) FindSystemOrganization() (*model.Organization, error) { return nil, nil } -//FindOrganizations finds all organizations +// FindOrganizations finds all organizations func (sa *Adapter) FindOrganizations() ([]model.Organization, error) { return sa.getCachedOrganizations() } -//InsertOrganization inserts an organization +// InsertOrganization inserts an organization func (sa *Adapter) InsertOrganization(context TransactionContext, organization model.Organization) (*model.Organization, error) { org := organizationToStorage(&organization) @@ -2703,7 +2710,7 @@ func (sa *Adapter) InsertOrganization(context TransactionContext, organization m return &organization, nil } -//UpdateOrganization updates an organization +// UpdateOrganization updates an organization func (sa *Adapter) UpdateOrganization(ID string, name string, requestType string, organizationDomains []string) error { now := time.Now() @@ -2730,7 +2737,7 @@ func (sa *Adapter) UpdateOrganization(ID string, name string, requestType string return nil } -//loadOrganizations gets the organizations +// loadOrganizations gets the organizations func (sa *Adapter) loadOrganizations() ([]model.Organization, error) { //no transactions for get operations.. @@ -2751,7 +2758,7 @@ func (sa *Adapter) loadOrganizations() ([]model.Organization, error) { return organizations, nil } -//loadApplications loads all applications +// loadApplications loads all applications func (sa *Adapter) loadApplications() ([]model.Application, error) { filter := bson.D{} var result []application @@ -2769,7 +2776,7 @@ func (sa *Adapter) loadApplications() ([]model.Application, error) { return applications, nil } -//InsertApplication inserts an application +// InsertApplication inserts an application func (sa *Adapter) InsertApplication(context TransactionContext, application model.Application) (*model.Application, error) { app := applicationToStorage(&application) @@ -2781,17 +2788,17 @@ func (sa *Adapter) InsertApplication(context TransactionContext, application mod return &application, nil } -//FindApplication finds application +// FindApplication finds application func (sa *Adapter) FindApplication(ID string) (*model.Application, error) { return sa.getCachedApplication(ID) } -//FindApplications finds applications +// FindApplications finds applications func (sa *Adapter) FindApplications() ([]model.Application, error) { return sa.getCachedApplications() } -//loadAppConfigs loads all application configs +// loadAppConfigs loads all application configs func (sa *Adapter) loadAppConfigs() ([]model.ApplicationConfig, error) { filter := bson.D{} options := options.Find() @@ -2828,12 +2835,12 @@ func (sa *Adapter) loadAppConfigs() ([]model.ApplicationConfig, error) { return result, nil } -//FindAppConfigs finds appconfigs +// FindAppConfigs finds appconfigs func (sa *Adapter) FindAppConfigs(appTypeID string, appOrgID *string, versionNumbers *model.VersionNumbers) ([]model.ApplicationConfig, error) { return sa.getCachedApplicationConfigByAppTypeIDAndVersion(appTypeID, appOrgID, versionNumbers) } -//FindAppConfigByVersion finds the most recent app config for the specified version +// FindAppConfigByVersion finds the most recent app config for the specified version func (sa *Adapter) FindAppConfigByVersion(appTypeID string, appOrgID *string, versionNumbers model.VersionNumbers) (*model.ApplicationConfig, error) { configs, err := sa.getCachedApplicationConfigByAppTypeIDAndVersion(appTypeID, appOrgID, &versionNumbers) if err != nil { @@ -2845,7 +2852,7 @@ func (sa *Adapter) FindAppConfigByVersion(appTypeID string, appOrgID *string, ve return &configs[0], nil } -//FindAppConfigByID finds appconfig by ID +// FindAppConfigByID finds appconfig by ID func (sa *Adapter) FindAppConfigByID(ID string) (*model.ApplicationConfig, error) { return sa.getCachedApplicationConfigByID(ID) } @@ -2912,7 +2919,7 @@ func (sa *Adapter) DeleteAppConfig(ID string) error { return nil } -//FindApplicationType finds an application type by ID or identifier +// FindApplicationType finds an application type by ID or identifier func (sa *Adapter) FindApplicationType(id string) (*model.ApplicationType, error) { app, appType, err := sa.getCachedApplicationType(id) if err != nil { @@ -2924,7 +2931,7 @@ func (sa *Adapter) FindApplicationType(id string) (*model.ApplicationType, error return appType, nil } -//loadApplicationsOrganizations loads all applications organizations +// loadApplicationsOrganizations loads all applications organizations func (sa *Adapter) loadApplicationsOrganizations() ([]model.ApplicationOrganization, error) { filter := bson.D{} var list []applicationOrganization @@ -2961,17 +2968,17 @@ func (sa *Adapter) loadApplicationsOrganizations() ([]model.ApplicationOrganizat } -//FindApplicationOrganization finds application organization +// FindApplicationOrganization finds application organization func (sa *Adapter) FindApplicationOrganization(appID string, orgID string) (*model.ApplicationOrganization, error) { return sa.getCachedApplicationOrganization(appID, orgID) } -//FindApplicationsOrganizations finds application organizations +// FindApplicationsOrganizations finds application organizations func (sa *Adapter) FindApplicationsOrganizations() ([]model.ApplicationOrganization, error) { return sa.getCachedApplicationOrganizations() } -//FindApplicationsOrganizationsByOrgID finds applications organizations by orgID +// FindApplicationsOrganizationsByOrgID finds applications organizations by orgID func (sa *Adapter) FindApplicationsOrganizationsByOrgID(orgID string) ([]model.ApplicationOrganization, error) { cachedAppOrgs, err := sa.getCachedApplicationOrganizations() @@ -3001,7 +3008,7 @@ func (sa *Adapter) InsertApplicationOrganization(context TransactionContext, app return &applicationOrganization, nil } -//FindDevice finds a device by device id and account id +// FindDevice finds a device by device id and account id func (sa *Adapter) FindDevice(context TransactionContext, deviceID string, accountID string) (*model.Device, error) { filter := bson.D{primitive.E{Key: "device_id", Value: deviceID}, primitive.E{Key: "account_id", Value: accountID}} @@ -3021,7 +3028,7 @@ func (sa *Adapter) FindDevice(context TransactionContext, deviceID string, accou return &deviceRes, nil } -//InsertDevice inserts a device +// InsertDevice inserts a device func (sa *Adapter) InsertDevice(context TransactionContext, device model.Device) (*model.Device, error) { //insert in devices storageDevice := deviceToStorage(&device) @@ -3048,7 +3055,7 @@ func (sa *Adapter) InsertDevice(context TransactionContext, device model.Device) return &device, nil } -//InsertAuthType inserts an auth type +// InsertAuthType inserts an auth type func (sa *Adapter) InsertAuthType(context TransactionContext, authType model.AuthType) (*model.AuthType, error) { _, err := sa.db.authTypes.InsertOneWithContext(context, authType) if err != nil { @@ -3058,7 +3065,7 @@ func (sa *Adapter) InsertAuthType(context TransactionContext, authType model.Aut return &authType, nil } -//UpdateAuthTypes updates an auth type +// UpdateAuthTypes updates an auth type func (sa *Adapter) UpdateAuthTypes(ID string, code string, description string, isExternal bool, isAnonymous bool, useCredentials bool, ignoreMFA bool, params map[string]interface{}) error { @@ -3090,7 +3097,7 @@ func (sa *Adapter) UpdateAuthTypes(ID string, code string, description string, i // ============================== ServiceRegs ============================== -//loadServiceRegs fetches all service registration records +// loadServiceRegs fetches all service registration records func (sa *Adapter) loadServiceRegs() ([]model.ServiceReg, error) { filter := bson.M{} var result []model.ServiceReg @@ -3106,17 +3113,22 @@ func (sa *Adapter) loadServiceRegs() ([]model.ServiceReg, error) { return result, nil } -//FindServiceRegs fetches the requested service registration records +// FindServiceRegs fetches the requested service registration records func (sa *Adapter) FindServiceRegs(serviceIDs []string) ([]model.ServiceReg, error) { return sa.getCachedServiceRegs(serviceIDs) } -//FindServiceReg finds the service registration in storage +// FindServiceReg finds the service registration in storage func (sa *Adapter) FindServiceReg(serviceID string) (*model.ServiceReg, error) { - return sa.getCachedServiceReg(serviceID) + return sa.getCachedServiceReg("registration.service_id", serviceID) +} + +// FindServiceRegByServiceAccountID finds a service registration by its service account ID +func (sa *Adapter) FindServiceRegByServiceAccountID(accountID string) (*model.ServiceReg, error) { + return sa.getCachedServiceReg("registration.service_account_id", accountID) } -//InsertServiceReg inserts the service registration to storage +// InsertServiceReg inserts the service registration to storage func (sa *Adapter) InsertServiceReg(reg *model.ServiceReg) error { _, err := sa.db.serviceRegs.InsertOne(reg) if err != nil { @@ -3126,7 +3138,7 @@ func (sa *Adapter) InsertServiceReg(reg *model.ServiceReg) error { return nil } -//UpdateServiceReg updates the service registration in storage +// UpdateServiceReg updates the service registration in storage func (sa *Adapter) UpdateServiceReg(reg *model.ServiceReg) error { filter := bson.M{"registration.service_id": reg.Registration.ServiceID} err := sa.db.serviceRegs.ReplaceOne(filter, reg, nil) @@ -3137,7 +3149,7 @@ func (sa *Adapter) UpdateServiceReg(reg *model.ServiceReg) error { return nil } -//SaveServiceReg saves the service registration to the storage +// SaveServiceReg saves the service registration to the storage func (sa *Adapter) SaveServiceReg(reg *model.ServiceReg) error { filter := bson.M{"registration.service_id": reg.Registration.ServiceID} opts := options.Replace().SetUpsert(true) @@ -3149,7 +3161,7 @@ func (sa *Adapter) SaveServiceReg(reg *model.ServiceReg) error { return nil } -//DeleteServiceReg deletes the service registration from storage +// DeleteServiceReg deletes the service registration from storage func (sa *Adapter) DeleteServiceReg(serviceID string) error { filter := bson.M{"registration.service_id": serviceID} result, err := sa.db.serviceRegs.DeleteOne(filter, nil) @@ -3167,7 +3179,7 @@ func (sa *Adapter) DeleteServiceReg(serviceID string) error { return nil } -//FindServiceAuthorization finds the service authorization in storage +// FindServiceAuthorization finds the service authorization in storage func (sa *Adapter) FindServiceAuthorization(userID string, serviceID string) (*model.ServiceAuthorization, error) { filter := bson.M{"user_id": userID, "service_id": serviceID} var reg *model.ServiceAuthorization @@ -3179,7 +3191,7 @@ func (sa *Adapter) FindServiceAuthorization(userID string, serviceID string) (*m return reg, nil } -//SaveServiceAuthorization saves the service authorization to storage +// SaveServiceAuthorization saves the service authorization to storage func (sa *Adapter) SaveServiceAuthorization(authorization *model.ServiceAuthorization) error { filter := bson.M{"user_id": authorization.UserID, "service_id": authorization.ServiceID} opts := options.Replace().SetUpsert(true) @@ -3191,7 +3203,7 @@ func (sa *Adapter) SaveServiceAuthorization(authorization *model.ServiceAuthoriz return nil } -//DeleteServiceAuthorization deletes the service authorization from storage +// DeleteServiceAuthorization deletes the service authorization from storage func (sa *Adapter) DeleteServiceAuthorization(userID string, serviceID string) error { filter := bson.M{"user_id": userID, "service_id": serviceID} result, err := sa.db.serviceAuthorizations.DeleteOne(filter, nil) @@ -3209,7 +3221,7 @@ func (sa *Adapter) DeleteServiceAuthorization(userID string, serviceID string) e return nil } -//SaveDevice saves device +// SaveDevice saves device func (sa *Adapter) SaveDevice(context TransactionContext, device *model.Device) error { if device == nil { return errors.ErrorData(logutils.StatusInvalid, logutils.TypeArg, logutils.StringArgs("device")) @@ -3227,7 +3239,7 @@ func (sa *Adapter) SaveDevice(context TransactionContext, device *model.Device) return nil } -//DeleteDevice deletes a device +// DeleteDevice deletes a device func (sa *Adapter) DeleteDevice(context TransactionContext, id string) error { filter := bson.M{"_id": id} res, err := sa.db.devices.DeleteOneWithContext(context, filter, nil) @@ -3248,7 +3260,7 @@ func (sa *Adapter) abortTransaction(sessionContext mongo.SessionContext) { } } -//NewStorageAdapter creates a new storage adapter instance +// NewStorageAdapter creates a new storage adapter instance func NewStorageAdapter(mongoDBAuth string, mongoDBName string, mongoTimeout string, logger *logs.Logger) *Adapter { timeoutInt, err := strconv.Atoi(mongoTimeout) if err != nil { @@ -3315,7 +3327,7 @@ func (sl *storageListener) OnApplicationConfigsUpdated() { sl.adapter.cacheApplicationConfigs() } -//Listener represents storage listener +// Listener represents storage listener type Listener interface { OnAPIKeysUpdated() OnAuthTypesUpdated() @@ -3327,34 +3339,34 @@ type Listener interface { OnApplicationConfigsUpdated() } -//DefaultListenerImpl default listener implementation +// DefaultListenerImpl default listener implementation type DefaultListenerImpl struct{} -//OnAPIKeysUpdated notifies api keys have been updated +// OnAPIKeysUpdated notifies api keys have been updated func (d *DefaultListenerImpl) OnAPIKeysUpdated() {} -//OnAuthTypesUpdated notifies auth types have been updated +// OnAuthTypesUpdated notifies auth types have been updated func (d *DefaultListenerImpl) OnAuthTypesUpdated() {} -//OnIdentityProvidersUpdated notifies identity providers have been updated +// OnIdentityProvidersUpdated notifies identity providers have been updated func (d *DefaultListenerImpl) OnIdentityProvidersUpdated() {} -//OnServiceRegsUpdated notifies services regs have been updated +// OnServiceRegsUpdated notifies services regs have been updated func (d *DefaultListenerImpl) OnServiceRegsUpdated() {} -//OnOrganizationsUpdated notifies organizations have been updated +// OnOrganizationsUpdated notifies organizations have been updated func (d *DefaultListenerImpl) OnOrganizationsUpdated() {} -//OnApplicationsUpdated notifies applications have been updated +// OnApplicationsUpdated notifies applications have been updated func (d *DefaultListenerImpl) OnApplicationsUpdated() {} -//OnApplicationsOrganizationsUpdated notifies applications organizations have been updated +// OnApplicationsOrganizationsUpdated notifies applications organizations have been updated func (d *DefaultListenerImpl) OnApplicationsOrganizationsUpdated() {} -//OnApplicationConfigsUpdated notifies application configs have been updated +// OnApplicationConfigsUpdated notifies application configs have been updated func (d *DefaultListenerImpl) OnApplicationConfigsUpdated() {} -//TransactionContext wraps mongo.SessionContext for use by external packages +// TransactionContext wraps mongo.SessionContext for use by external packages type TransactionContext interface { mongo.SessionContext } diff --git a/driven/storage/collection.go b/driven/storage/collection.go index 007899a0e..476e86221 100644 --- a/driven/storage/collection.go +++ b/driven/storage/collection.go @@ -302,7 +302,7 @@ func (collWrapper *collectionWrapper) Watch(pipeline interface{}, l *logs.Logger } } -//Helper function for Watch +// Helper function for Watch func (collWrapper *collectionWrapper) watch(pipeline interface{}, resumeToken bson.Raw, l *logs.Logger) (bson.Raw, error) { if pipeline == nil { pipeline = []bson.M{} diff --git a/driven/storage/conversions_application.go b/driven/storage/conversions_application.go index c1dd08c6d..bae2f185f 100644 --- a/driven/storage/conversions_application.go +++ b/driven/storage/conversions_application.go @@ -18,7 +18,7 @@ import ( "core-building-block/core/model" ) -//Application +// Application func applicationFromStorage(item *application) model.Application { if item == nil { return model.Application{} @@ -42,7 +42,7 @@ func applicationsFromStorage(itemsList []application) []model.Application { return items } -//ApplicationType +// ApplicationType func applicationTypeFromStorage(item *applicationType) model.ApplicationType { if item == nil { return model.ApplicationType{} @@ -67,7 +67,7 @@ func applicationTypesFromStorage(itemsList []applicationType) []model.Applicatio return items } -//AppOrgRole +// AppOrgRole func appOrgRoleFromStorage(item *appOrgRole, appOrg model.ApplicationOrganization) model.AppOrgRole { if item == nil { return model.AppOrgRole{} @@ -177,7 +177,7 @@ func appConfigToStorage(item model.ApplicationConfig) applicationConfig { return appConfig } -//AppOrgGroup +// AppOrgGroup func appOrgGroupFromStorage(item *appOrgGroup, appOrg model.ApplicationOrganization) model.AppOrgGroup { if item == nil { return model.AppOrgGroup{} @@ -218,7 +218,7 @@ func appOrgGroupsToStorage(items []model.AppOrgGroup) []appOrgGroup { return res } -//Organization +// Organization func organizationFromStorage(item *organization) model.Organization { if item == nil { return model.Organization{} @@ -249,7 +249,7 @@ func organizationToStorage(item *model.Organization) *organization { Config: item.Config, DateCreated: item.DateCreated, DateUpdated: item.DateUpdated} } -//ApplicationOrganization +// ApplicationOrganization func applicationOrganizationToStorage(item model.ApplicationOrganization) applicationOrganization { return applicationOrganization{ID: item.ID, AppID: item.Application.ID, OrgID: item.Organization.ID, ServicesIDs: item.ServicesIDs, IdentityProvidersSettings: item.IdentityProvidersSettings, diff --git a/driven/storage/conversions_auth.go b/driven/storage/conversions_auth.go index a4b642277..b3b9f7aff 100644 --- a/driven/storage/conversions_auth.go +++ b/driven/storage/conversions_auth.go @@ -21,7 +21,7 @@ import ( "github.com/rokwire/logging-library-go/logutils" ) -//LoginSession +// LoginSession func loginSessionFromStorage(item loginSession, authType model.AuthType, account *model.Account, appOrg model.ApplicationOrganization) model.LoginSession { id := item.ID @@ -119,7 +119,7 @@ func loginSessionToStorage(item model.LoginSession) *loginSession { DateRefreshed: dateRefreshed, DateUpdated: dateUpdated, DateCreated: dateCreated} } -//ServiceAccount +// ServiceAccount func serviceAccountFromStorage(item serviceAccount, sa *Adapter) (*model.ServiceAccount, error) { var err error var application *model.Application diff --git a/driven/storage/conversions_user.go b/driven/storage/conversions_user.go index 63d436824..083f47de9 100644 --- a/driven/storage/conversions_user.go +++ b/driven/storage/conversions_user.go @@ -18,7 +18,7 @@ import ( "core-building-block/core/model" ) -//Account +// Account func accountFromStorage(item account, appOrg model.ApplicationOrganization) model.Account { id := item.ID permissions := item.Permissions @@ -93,7 +93,7 @@ func accountDeviceToStorage(item model.Device) userDevice { DateCreated: item.DateCreated, DateUpdated: item.DateUpdated} } -//AccountAuthType +// AccountAuthType func accountAuthTypeFromStorage(item accountAuthType) model.AccountAuthType { id := item.ID authType := model.AuthType{ID: item.AuthTypeID, Code: item.AuthTypeCode} @@ -141,7 +141,7 @@ func accountAuthTypesToStorage(items []model.AccountAuthType) []accountAuthType return res } -//AccountRole +// AccountRole func accountRoleFromStorage(item *accountRole, appOrg model.ApplicationOrganization) model.AccountRole { if item == nil { return model.AccountRole{} @@ -180,7 +180,7 @@ func accountRolesToStorage(items []model.AccountRole) []accountRole { return res } -//ApplicationGroup +// ApplicationGroup func accountGroupFromStorage(item *accountGroup, appOrg model.ApplicationOrganization) model.AccountGroup { if item == nil { return model.AccountGroup{} @@ -219,7 +219,7 @@ func accountGroupsToStorage(items []model.AccountGroup) []accountGroup { return res } -//Profile +// Profile func profileFromStorage(item profile) model.Profile { return model.Profile{ID: item.ID, PhotoURL: item.PhotoURL, FirstName: item.FirstName, LastName: item.LastName, Email: item.Email, Phone: item.Phone, BirthYear: item.BirthYear, Address: item.Address, ZipCode: item.ZipCode, @@ -264,7 +264,7 @@ func profileToStorage(item model.Profile) profile { State: item.State, Country: item.Country, DateCreated: item.DateCreated, DateUpdated: item.DateUpdated} } -//Device +// Device func deviceToStorage(item *model.Device) *device { if item == nil { return nil @@ -278,7 +278,7 @@ func deviceFromStorage(item device) model.Device { return model.Device{ID: item.ID, DeviceID: item.DeviceID, Type: item.Type, OS: item.OS, DateUpdated: item.DateUpdated} } -//Credential +// Credential func credentialFromStorage(item credential) model.Credential { accountAuthTypes := make([]model.AccountAuthType, len(item.AccountsAuthTypes)) for i, id := range item.AccountsAuthTypes { @@ -302,7 +302,7 @@ func credentialToStorage(item *model.Credential) *credential { Value: item.Value, DateCreated: item.DateCreated, DateUpdated: item.DateUpdated} } -//MFA +// MFA func mfaTypesFromStorage(items []mfaType) []model.MFAType { res := make([]model.MFAType, len(items)) for i, mfa := range items { diff --git a/driver/web/adapter.go b/driver/web/adapter.go index 9bcfcbd2f..20050dbee 100644 --- a/driver/web/adapter.go +++ b/driver/web/adapter.go @@ -37,7 +37,7 @@ import ( httpSwagger "github.com/swaggo/http-swagger" ) -//Adapter entity +// Adapter entity type Adapter struct { env string serviceID string @@ -62,7 +62,7 @@ type Adapter struct { type handlerFunc = func(*logs.Log, *http.Request, *tokenauth.Claims) logs.HttpResponse -//Start starts the module +// Start starts the module func (we Adapter) Start() { //add listener to the application @@ -426,7 +426,7 @@ func (we Adapter) validateResponse(requestValidationInput *openapi3filter.Reques return nil } -//NewWebAdapter creates new WebAdapter instance +// NewWebAdapter creates new WebAdapter instance func NewWebAdapter(env string, serviceID string, serviceRegManager *authservice.ServiceRegManager, port string, coreAPIs *core.APIs, host string, logger *logs.Logger) Adapter { //openAPI doc loader := &openapi3.Loader{Context: context.Background(), IsExternalRefsAllowed: true} @@ -470,7 +470,7 @@ func NewWebAdapter(env string, serviceID string, serviceRegManager *authservice. encApisHandler: encApisHandler, bbsApisHandler: bbsApisHandler, tpsApisHandler: tpsApisHandler, systemApisHandler: systemApisHandler, coreAPIs: coreAPIs} } -//AppListener implements core.ApplicationListener interface +// AppListener implements core.ApplicationListener interface type AppListener struct { adapter *Adapter } diff --git a/driver/web/apis_admin.go b/driver/web/apis_admin.go index 024008aa1..06e4018c8 100644 --- a/driver/web/apis_admin.go +++ b/driver/web/apis_admin.go @@ -36,19 +36,19 @@ const ( actionGrant logutils.MessageActionType = "granting" ) -//AdminApisHandler handles the admin rest APIs implementation +// AdminApisHandler handles the admin rest APIs implementation type AdminApisHandler struct { coreAPIs *core.APIs } -//getTest TODO get test +// getTest TODO get test func (h AdminApisHandler) getTest(l *logs.Log, r *http.Request, claims *tokenauth.Claims) logs.HttpResponse { res := h.coreAPIs.Administration.AdmGetTest() return l.HttpResponseSuccessMessage(res) } -//getTestModel gives a test model instance +// getTestModel gives a test model instance func (h AdminApisHandler) getTestModel(l *logs.Log, r *http.Request, claims *tokenauth.Claims) logs.HttpResponse { res := h.coreAPIs.Administration.AdmGetTestModel() @@ -667,7 +667,7 @@ func (h AdminApisHandler) getAppToken(l *logs.Log, r *http.Request, claims *toke return l.HttpResponseSuccessJSON(responseJSON) } -//createApplicationGroup creates an application group +// createApplicationGroup creates an application group func (h AdminApisHandler) createApplicationGroup(l *logs.Log, r *http.Request, claims *tokenauth.Claims) logs.HttpResponse { data, err := ioutil.ReadAll(r.Body) if err != nil { @@ -720,7 +720,7 @@ func (h AdminApisHandler) deleteApplicationGroup(l *logs.Log, r *http.Request, c return l.HttpResponseSuccess() } -//addAccountsToGroup adds a group the given account +// addAccountsToGroup adds a group the given account func (h AdminApisHandler) addAccountsToGroup(l *logs.Log, r *http.Request, claims *tokenauth.Claims) logs.HttpResponse { params := mux.Vars(r) groupID := params["id"] @@ -748,7 +748,7 @@ func (h AdminApisHandler) addAccountsToGroup(l *logs.Log, r *http.Request, claim return l.HttpResponseSuccess() } -//removeAccountsFromGroup removes accounts from a given group +// removeAccountsFromGroup removes accounts from a given group func (h AdminApisHandler) removeAccountsFromGroup(l *logs.Log, r *http.Request, claims *tokenauth.Claims) logs.HttpResponse { params := mux.Vars(r) groupID := params["id"] @@ -776,7 +776,7 @@ func (h AdminApisHandler) removeAccountsFromGroup(l *logs.Log, r *http.Request, return l.HttpResponseSuccess() } -//createApplicationRole creates an application role +// createApplicationRole creates an application role func (h AdminApisHandler) createApplicationRole(l *logs.Log, r *http.Request, claims *tokenauth.Claims) logs.HttpResponse { data, err := ioutil.ReadAll(r.Body) if err != nil { @@ -862,7 +862,7 @@ func (h AdminApisHandler) getApplicationAccountDevices(l *logs.Log, r *http.Requ return l.HttpResponseSuccessJSON(data) } -//grantAccountPermissions grants an account the given permissions +// grantAccountPermissions grants an account the given permissions func (h AdminApisHandler) grantAccountPermissions(l *logs.Log, r *http.Request, claims *tokenauth.Claims) logs.HttpResponse { params := mux.Vars(r) accountID := params["id"] @@ -890,7 +890,7 @@ func (h AdminApisHandler) grantAccountPermissions(l *logs.Log, r *http.Request, return l.HttpResponseSuccess() } -//revokeAccountPermissions removes permissions from an account +// revokeAccountPermissions removes permissions from an account func (h AdminApisHandler) revokeAccountPermissions(l *logs.Log, r *http.Request, claims *tokenauth.Claims) logs.HttpResponse { params := mux.Vars(r) accountID := params["id"] @@ -917,7 +917,7 @@ func (h AdminApisHandler) revokeAccountPermissions(l *logs.Log, r *http.Request, return l.HttpResponseSuccess() } -//grantAccountRoles grants an account the given roles +// grantAccountRoles grants an account the given roles func (h AdminApisHandler) grantAccountRoles(l *logs.Log, r *http.Request, claims *tokenauth.Claims) logs.HttpResponse { params := mux.Vars(r) accountID := params["id"] @@ -945,7 +945,7 @@ func (h AdminApisHandler) grantAccountRoles(l *logs.Log, r *http.Request, claims return l.HttpResponseSuccess() } -//revokeAccountRoles removes role from a given account +// revokeAccountRoles removes role from a given account func (h AdminApisHandler) revokeAccountRoles(l *logs.Log, r *http.Request, claims *tokenauth.Claims) logs.HttpResponse { params := mux.Vars(r) accountID := params["id"] @@ -973,7 +973,7 @@ func (h AdminApisHandler) revokeAccountRoles(l *logs.Log, r *http.Request, claim return l.HttpResponseSuccess() } -//grantPermissionsToRole grants a role the given permission +// grantPermissionsToRole grants a role the given permission func (h AdminApisHandler) grantPermissionsToRole(l *logs.Log, r *http.Request, claims *tokenauth.Claims) logs.HttpResponse { params := mux.Vars(r) roleID := params["id"] @@ -1001,7 +1001,7 @@ func (h AdminApisHandler) grantPermissionsToRole(l *logs.Log, r *http.Request, c return l.HttpResponseSuccess() } -//NewAdminApisHandler creates new admin rest Handler instance +// NewAdminApisHandler creates new admin rest Handler instance func NewAdminApisHandler(coreAPIs *core.APIs) AdminApisHandler { return AdminApisHandler{coreAPIs: coreAPIs} } diff --git a/driver/web/apis_bbs.go b/driver/web/apis_bbs.go index 89de40fc8..852a5d50f 100644 --- a/driver/web/apis_bbs.go +++ b/driver/web/apis_bbs.go @@ -32,12 +32,12 @@ import ( "github.com/rokwire/logging-library-go/logutils" ) -//BBsApisHandler handles the APIs implementation used by the platform building blocks +// BBsApisHandler handles the APIs implementation used by the platform building blocks type BBsApisHandler struct { coreAPIs *core.APIs } -//getTest TODO get test +// getTest TODO get test func (h BBsApisHandler) getTest(l *logs.Log, r *http.Request, claims *tokenauth.Claims) logs.HttpResponse { res := h.coreAPIs.BBs.BBsGetTest() @@ -189,7 +189,7 @@ func (h BBsApisHandler) updatePermissions(l *logs.Log, r *http.Request, claims * return l.HttpResponseSuccessJSON(respData) } -//NewBBsApisHandler creates new bbs Handler instance +// NewBBsApisHandler creates new bbs Handler instance func NewBBsApisHandler(coreAPIs *core.APIs) BBsApisHandler { return BBsApisHandler{coreAPIs: coreAPIs} } diff --git a/driver/web/apis_default.go b/driver/web/apis_default.go index eb16c96e3..9e44b40ee 100644 --- a/driver/web/apis_default.go +++ b/driver/web/apis_default.go @@ -25,19 +25,19 @@ import ( "github.com/rokwire/logging-library-go/logutils" ) -//DefaultApisHandler handles default APIs implementation - version etc +// DefaultApisHandler handles default APIs implementation - version etc type DefaultApisHandler struct { coreAPIs *core.APIs } -//getVersion gives the service version +// getVersion gives the service version func (h DefaultApisHandler) getVersion(l *logs.Log, r *http.Request, claims *tokenauth.Claims) logs.HttpResponse { version := h.coreAPIs.GetVersion() return l.HttpResponseSuccessMessage(version) } -//getOpenIDConfiguration gives the OpenID Connect Discovery page +// getOpenIDConfiguration gives the OpenID Connect Discovery page func (h DefaultApisHandler) getOpenIDConfiguration(l *logs.Log, r *http.Request, claims *tokenauth.Claims) logs.HttpResponse { discovery := Def.OIDCDiscovery{Issuer: h.coreAPIs.Auth.GetHost(), JwksUri: h.coreAPIs.Auth.GetHost() + "/tps/auth-keys"} @@ -49,7 +49,7 @@ func (h DefaultApisHandler) getOpenIDConfiguration(l *logs.Log, r *http.Request, return l.HttpResponseSuccessJSON(data) } -//NewDefaultApisHandler creates new rest services Handler instance +// NewDefaultApisHandler creates new rest services Handler instance func NewDefaultApisHandler(coreAPIs *core.APIs) DefaultApisHandler { return DefaultApisHandler{coreAPIs: coreAPIs} } diff --git a/driver/web/apis_enc.go b/driver/web/apis_enc.go index 226b34f57..e176935b3 100644 --- a/driver/web/apis_enc.go +++ b/driver/web/apis_enc.go @@ -22,19 +22,19 @@ import ( "github.com/rokwire/logging-library-go/logs" ) -//EncApisHandler handles the APIs implementation used by the Encryption BB +// EncApisHandler handles the APIs implementation used by the Encryption BB type EncApisHandler struct { coreAPIs *core.APIs } -//getTest TODO get test +// getTest TODO get test func (h EncApisHandler) getTest(l *logs.Log, r *http.Request, claims *tokenauth.Claims) logs.HttpResponse { res := h.coreAPIs.Encryption.EncGetTest() return l.HttpResponseSuccessMessage(res) } -//NewEncApisHandler creates new enc Handler instance +// NewEncApisHandler creates new enc Handler instance func NewEncApisHandler(coreAPIs *core.APIs) EncApisHandler { return EncApisHandler{coreAPIs: coreAPIs} } diff --git a/driver/web/apis_services.go b/driver/web/apis_services.go index 3bd69bc42..dea57fe49 100644 --- a/driver/web/apis_services.go +++ b/driver/web/apis_services.go @@ -31,7 +31,7 @@ import ( "github.com/rokwire/logging-library-go/logutils" ) -//ServicesApisHandler handles the rest APIs implementation +// ServicesApisHandler handles the rest APIs implementation type ServicesApisHandler struct { coreAPIs *core.APIs } @@ -766,14 +766,14 @@ func (h ServicesApisHandler) getAccounts(l *logs.Log, r *http.Request, claims *t return l.HttpResponseSuccessJSON(data) } -//getCommonTest TODO get test +// getCommonTest TODO get test func (h ServicesApisHandler) getTest(l *logs.Log, r *http.Request, claims *tokenauth.Claims) logs.HttpResponse { res := h.coreAPIs.Services.SerGetCommonTest(l) return l.HttpResponseSuccessMessage(res) } -//Handler for verify endpoint +// Handler for verify endpoint func (h ServicesApisHandler) verifyCredential(l *logs.Log, r *http.Request, claims *tokenauth.Claims) logs.HttpResponse { id := r.URL.Query().Get("id") if id == "" { @@ -856,7 +856,7 @@ func (h ServicesApisHandler) getApplicationOrgConfigs(l *logs.Log, r *http.Reque return l.HttpResponseSuccessJSON(response) } -//Handler for reset password endpoint from client application +// Handler for reset password endpoint from client application func (h ServicesApisHandler) updateCredential(l *logs.Log, r *http.Request, claims *tokenauth.Claims) logs.HttpResponse { accountID := claims.Subject data, err := ioutil.ReadAll(r.Body) @@ -883,7 +883,7 @@ func (h ServicesApisHandler) updateCredential(l *logs.Log, r *http.Request, clai return l.HttpResponseSuccessMessage("Reset Password from client successfully") } -//Handler for reset password endpoint from reset link +// Handler for reset password endpoint from reset link func (h ServicesApisHandler) forgotCredentialComplete(l *logs.Log, r *http.Request, claims *tokenauth.Claims) logs.HttpResponse { data, err := ioutil.ReadAll(r.Body) if err != nil { @@ -909,7 +909,7 @@ func (h ServicesApisHandler) forgotCredentialComplete(l *logs.Log, r *http.Reque return l.HttpResponseSuccessMessage("Reset Password from link successfully") } -//Handler for forgot credential endpoint +// Handler for forgot credential endpoint func (h ServicesApisHandler) forgotCredentialInitiate(l *logs.Log, r *http.Request, claims *tokenauth.Claims) logs.HttpResponse { data, err := ioutil.ReadAll(r.Body) if err != nil { @@ -930,7 +930,7 @@ func (h ServicesApisHandler) forgotCredentialInitiate(l *logs.Log, r *http.Reque return l.HttpResponseSuccessMessage("Sent forgot password link successfully") } -//Handler for resending verify code +// Handler for resending verify code func (h ServicesApisHandler) sendVerifyCredential(l *logs.Log, r *http.Request, claims *tokenauth.Claims) logs.HttpResponse { data, err := ioutil.ReadAll(r.Body) if err != nil { @@ -1006,12 +1006,12 @@ func (h ServicesApisHandler) logout(l *logs.Log, r *http.Request, claims *tokena return l.HttpResponseSuccess() } -//NewServicesApisHandler creates new rest services Handler instance +// NewServicesApisHandler creates new rest services Handler instance func NewServicesApisHandler(coreAPIs *core.APIs) ServicesApisHandler { return ServicesApisHandler{coreAPIs: coreAPIs} } -//HTMLResponseTemplate represents html response template +// HTMLResponseTemplate represents html response template type HTMLResponseTemplate struct { Message string } diff --git a/driver/web/apis_system.go b/driver/web/apis_system.go index 29094548c..58509bb7d 100644 --- a/driver/web/apis_system.go +++ b/driver/web/apis_system.go @@ -30,12 +30,12 @@ import ( "github.com/rokwire/logging-library-go/logutils" ) -//SystemApisHandler handles system APIs implementation +// SystemApisHandler handles system APIs implementation type SystemApisHandler struct { coreAPIs *core.APIs } -//createGlobalConfig creates a global config +// createGlobalConfig creates a global config func (h SystemApisHandler) createGlobalConfig(l *logs.Log, r *http.Request, claims *tokenauth.Claims) logs.HttpResponse { data, err := ioutil.ReadAll(r.Body) if err != nil { @@ -56,7 +56,7 @@ func (h SystemApisHandler) createGlobalConfig(l *logs.Log, r *http.Request, clai return l.HttpResponseSuccess() } -//getGlobalConfig gets config +// getGlobalConfig gets config func (h SystemApisHandler) getGlobalConfig(l *logs.Log, r *http.Request, claims *tokenauth.Claims) logs.HttpResponse { config, err := h.coreAPIs.System.SysGetGlobalConfig() if err != nil { @@ -75,7 +75,7 @@ func (h SystemApisHandler) getGlobalConfig(l *logs.Log, r *http.Request, claims return l.HttpResponseSuccessJSON(data) } -//updateGlobalConfig updates global config +// updateGlobalConfig updates global config func (h SystemApisHandler) updateGlobalConfig(l *logs.Log, r *http.Request, claims *tokenauth.Claims) logs.HttpResponse { data, err := ioutil.ReadAll(r.Body) if err != nil { @@ -98,7 +98,7 @@ func (h SystemApisHandler) updateGlobalConfig(l *logs.Log, r *http.Request, clai return l.HttpResponseSuccess() } -//createOrganization creates organization +// createOrganization creates organization func (h SystemApisHandler) createOrganization(l *logs.Log, r *http.Request, claims *tokenauth.Claims) logs.HttpResponse { data, err := ioutil.ReadAll(r.Body) @@ -124,7 +124,7 @@ func (h SystemApisHandler) createOrganization(l *logs.Log, r *http.Request, clai return l.HttpResponseSuccess() } -//updateOrganization updates organization +// updateOrganization updates organization func (h SystemApisHandler) updateOrganization(l *logs.Log, r *http.Request, claims *tokenauth.Claims) logs.HttpResponse { params := mux.Vars(r) ID := params["id"] @@ -154,7 +154,7 @@ func (h SystemApisHandler) updateOrganization(l *logs.Log, r *http.Request, clai return l.HttpResponseSuccess() } -//getOrganization gets organization +// getOrganization gets organization func (h SystemApisHandler) getOrganization(l *logs.Log, r *http.Request, claims *tokenauth.Claims) logs.HttpResponse { params := mux.Vars(r) ID := params["id"] @@ -177,7 +177,7 @@ func (h SystemApisHandler) getOrganization(l *logs.Log, r *http.Request, claims return l.HttpResponseSuccessJSON(data) } -//getOrganizations gets organizations +// getOrganizations gets organizations func (h SystemApisHandler) getOrganizations(l *logs.Log, r *http.Request, claims *tokenauth.Claims) logs.HttpResponse { organizations, err := h.coreAPIs.System.SysGetOrganizations() if err != nil { @@ -647,7 +647,7 @@ func (h SystemApisHandler) getApplication(l *logs.Log, r *http.Request, claims * return l.HttpResponseSuccessJSON(data) } -//createApplication creates an application +// createApplication creates an application func (h SystemApisHandler) createApplication(l *logs.Log, r *http.Request, claims *tokenauth.Claims) logs.HttpResponse { data, err := ioutil.ReadAll(r.Body) if err != nil { @@ -708,7 +708,7 @@ func (h SystemApisHandler) getApplications(l *logs.Log, r *http.Request, claims return l.HttpResponseSuccessJSON(data) } -//createPermission creates an permission +// createPermission creates an permission func (h SystemApisHandler) createPermission(l *logs.Log, r *http.Request, claims *tokenauth.Claims) logs.HttpResponse { data, err := ioutil.ReadAll(r.Body) if err != nil { @@ -729,7 +729,7 @@ func (h SystemApisHandler) createPermission(l *logs.Log, r *http.Request, claims return l.HttpResponseSuccess() } -//updatePermission updates an permission +// updatePermission updates an permission func (h SystemApisHandler) updatePermission(l *logs.Log, r *http.Request, claims *tokenauth.Claims) logs.HttpResponse { data, err := ioutil.ReadAll(r.Body) if err != nil { @@ -886,7 +886,7 @@ func (h SystemApisHandler) deleteApplicationConfig(l *logs.Log, r *http.Request, return l.HttpResponseSuccess() } -//createAuthTypes creates auth-type +// createAuthTypes creates auth-type func (h SystemApisHandler) createAuthTypes(l *logs.Log, r *http.Request, claims *tokenauth.Claims) logs.HttpResponse { data, err := ioutil.ReadAll(r.Body) @@ -916,7 +916,7 @@ func (h SystemApisHandler) createAuthTypes(l *logs.Log, r *http.Request, claims return l.HttpResponseSuccess() } -//getAuthTypes gets auth-types +// getAuthTypes gets auth-types func (h SystemApisHandler) getAuthTypes(l *logs.Log, r *http.Request, claims *tokenauth.Claims) logs.HttpResponse { authTypes, err := h.coreAPIs.System.SysGetAuthTypes() if err != nil { @@ -932,7 +932,7 @@ func (h SystemApisHandler) getAuthTypes(l *logs.Log, r *http.Request, claims *to return l.HttpResponseSuccessJSON(data) } -//updateAuthTypes updates auth type +// updateAuthTypes updates auth type func (h SystemApisHandler) updateAuthTypes(l *logs.Log, r *http.Request, claims *tokenauth.Claims) logs.HttpResponse { rParams := mux.Vars(r) ID := rParams["id"] @@ -966,7 +966,7 @@ func (h SystemApisHandler) updateAuthTypes(l *logs.Log, r *http.Request, claims return l.HttpResponseSuccess() } -//NewSystemApisHandler creates new system Handler instance +// NewSystemApisHandler creates new system Handler instance func NewSystemApisHandler(coreAPIs *core.APIs) SystemApisHandler { return SystemApisHandler{coreAPIs: coreAPIs} } diff --git a/driver/web/apis_tps.go b/driver/web/apis_tps.go index ea8d6da15..7a6c071cd 100644 --- a/driver/web/apis_tps.go +++ b/driver/web/apis_tps.go @@ -32,7 +32,7 @@ import ( "github.com/rokwire/logging-library-go/logutils" ) -//TPSApisHandler handles the APIs implementation used by third-party services +// TPSApisHandler handles the APIs implementation used by third-party services type TPSApisHandler struct { coreAPIs *core.APIs } @@ -204,7 +204,7 @@ func (h TPSApisHandler) updatePermissions(l *logs.Log, r *http.Request, claims * return l.HttpResponseSuccessJSON(respData) } -//NewTPSApisHandler creates new tps Handler instance +// NewTPSApisHandler creates new tps Handler instance func NewTPSApisHandler(coreAPIs *core.APIs) TPSApisHandler { return TPSApisHandler{coreAPIs: coreAPIs} } diff --git a/driver/web/auth.go b/driver/web/auth.go index 4d4725a2c..0f00323d2 100644 --- a/driver/web/auth.go +++ b/driver/web/auth.go @@ -36,7 +36,7 @@ const ( typeCheckServicesAuthRequestToken logutils.MessageActionType = "checking services auth" ) -//Auth handler +// Auth handler type Auth struct { services *TokenAuthHandlers admin *TokenAuthHandlers @@ -48,19 +48,19 @@ type Auth struct { logger *logs.Logger } -//Authorization is an interface for auth types +// Authorization is an interface for auth types type Authorization interface { check(req *http.Request) (int, *tokenauth.Claims, error) start() } -//TokenAuthorization is an interface for auth types +// TokenAuthorization is an interface for auth types type TokenAuthorization interface { Authorization getTokenAuth() *tokenauth.TokenAuth } -//Start starts the auth module +// Start starts the auth module func (auth *Auth) Start() error { auth.logger.Info("Auth -> start") @@ -74,7 +74,7 @@ func (auth *Auth) Start() error { return nil } -//NewAuth creates new auth handler +// NewAuth creates new auth handler func NewAuth(coreAPIs *core.APIs, serviceID string, serviceRegManager *authservice.ServiceRegManager, logger *logs.Logger) (*Auth, error) { servicesAuth, err := newServicesAuth(coreAPIs, serviceRegManager, serviceID, logger) if err != nil { @@ -128,7 +128,7 @@ func NewAuth(coreAPIs *core.APIs, serviceID string, serviceRegManager *authservi return &auth, nil } -//TokenAuthHandlers represents token auth handlers +// TokenAuthHandlers represents token auth handlers type TokenAuthHandlers struct { standard TokenAuthorization permissions *PermissionsAuth @@ -143,7 +143,7 @@ func (auth *TokenAuthHandlers) start() { auth.authenticated.start() } -//newTokenAuthHandlers creates new auth handlers for a +// newTokenAuthHandlers creates new auth handlers for a func newTokenAuthHandlers(auth TokenAuthorization) (*TokenAuthHandlers, error) { permissionsAuth := newPermissionsAuth(auth) userAuth := newUserAuth(auth) @@ -153,7 +153,7 @@ func newTokenAuthHandlers(auth TokenAuthorization) (*TokenAuthHandlers, error) { return &authWrappers, nil } -//ServicesAuth entity +// ServicesAuth entity type ServicesAuth struct { coreAPIs *core.APIs tokenAuth *tokenauth.TokenAuth @@ -203,7 +203,7 @@ func newServicesAuth(coreAPIs *core.APIs, serviceRegManager *authservice.Service return &auth, nil } -//AdminAuth entity +// AdminAuth entity type AdminAuth struct { coreAPIs *core.APIs tokenAuth *tokenauth.TokenAuth @@ -243,7 +243,7 @@ func newAdminAuth(coreAPIs *core.APIs, serviceRegManager *authservice.ServiceReg return &auth, nil } -//EncAuth entity +// EncAuth entity type EncAuth struct { coreAPIs *core.APIs @@ -259,7 +259,7 @@ func newEncAuth(coreAPIs *core.APIs, logger *logs.Logger) *EncAuth { return &auth } -//BBsAuth entity +// BBsAuth entity type BBsAuth struct { coreAPIs *core.APIs tokenAuth *tokenauth.TokenAuth @@ -303,7 +303,7 @@ func newBBsAuth(coreAPIs *core.APIs, serviceRegManager *authservice.ServiceRegMa return &auth, nil } -//TPsAuth entity +// TPsAuth entity type TPsAuth struct { coreAPIs *core.APIs tokenAuth *tokenauth.TokenAuth @@ -347,7 +347,7 @@ func newTPsAuth(coreAPIs *core.APIs, serviceRegManager *authservice.ServiceRegMa return &auth, nil } -//SystemAuth entity +// SystemAuth entity type SystemAuth struct { coreAPIs *core.APIs tokenAuth *tokenauth.TokenAuth @@ -387,8 +387,8 @@ func newSystemAuth(coreAPIs *core.APIs, serviceRegManager *authservice.ServiceRe return &auth, nil } -//PermissionsAuth entity -//This enforces that the user has permissions matching the policy +// PermissionsAuth entity +// This enforces that the user has permissions matching the policy type PermissionsAuth struct { auth TokenAuthorization } @@ -413,7 +413,7 @@ func newPermissionsAuth(auth TokenAuthorization) *PermissionsAuth { return &permissionsAuth } -//UserAuth entity +// UserAuth entity // This enforces that the user is not anonymous type UserAuth struct { auth Authorization @@ -438,7 +438,7 @@ func newUserAuth(auth Authorization) *UserAuth { return &userAuth } -//AuthenticatedAuth entity +// AuthenticatedAuth entity // This enforces that the token was the result of direct user authentication. It should be used to protect sensitive account settings type AuthenticatedAuth struct { userAuth UserAuth diff --git a/driver/web/conversions_application.go b/driver/web/conversions_application.go index 6ae00a24a..ae7d59120 100644 --- a/driver/web/conversions_application.go +++ b/driver/web/conversions_application.go @@ -74,7 +74,7 @@ func applicationsToDef(item []model.Application) []Def.ApplicationFields { return result } -//ApplicationPermission +// ApplicationPermission func applicationPermissionToDef(item model.Permission) Def.Permission { assigners := item.Assigners if assigners == nil { @@ -119,7 +119,7 @@ func applicationPermissionsFromDef(items []Def.Permission) []model.Permission { return result } -//AppOrgRole +// AppOrgRole func appOrgRoleToDef(item model.AppOrgRole) Def.AppOrgRole { permissions := applicationPermissionsToDef(item.Permissions) @@ -142,7 +142,7 @@ func appOrgRolesToDef(items []model.AppOrgRole) []Def.AppOrgRole { return result } -//AppOrgGroup +// AppOrgGroup func appOrgGroupToDef(item model.AppOrgGroup) Def.AppOrgGroup { permissions := applicationPermissionsToDef(item.Permissions) roles := appOrgRolesToDef(item.Roles) @@ -166,7 +166,7 @@ func appOrgGroupsToDef(items []model.AppOrgGroup) []Def.AppOrgGroup { return result } -//Organization +// Organization func organizationToDef(item *model.Organization) *Def.Organization { if item == nil { return nil @@ -203,7 +203,7 @@ func organizationConfigToDef(item *model.OrganizationConfig) *Def.OrganizationCo return &Def.OrganizationConfigFields{Id: id, Domains: domains} } -//App Config +// App Config func appConfigToDef(item model.ApplicationConfig) Def.ApplicationConfig { defConfig := Def.ApplicationConfig{Id: item.ID, AppTypeId: item.ApplicationType.ID, Version: item.Version.VersionNumbers.String(), Data: item.Data} if item.AppOrg != nil { diff --git a/driver/web/conversions_auth.go b/driver/web/conversions_auth.go index 92be778d8..425097a36 100644 --- a/driver/web/conversions_auth.go +++ b/driver/web/conversions_auth.go @@ -25,7 +25,7 @@ import ( "github.com/rokwire/logging-library-go/logutils" ) -//LoginSession +// LoginSession func loginSessionToDef(item model.LoginSession) Def.SharedResLoginSession { var accountAuthTypeID *string var accountAuthTypeIdentifier *string @@ -388,7 +388,7 @@ func jsonWebKeySetDef(items *model.JSONWebKeySet) *Def.JWKS { return &Def.JWKS{Keys: out} } -//AuthType +// AuthType func authTypeToDef(item *model.AuthType) *Def.AuthTypeFields { if item == nil { return nil diff --git a/driver/web/conversions_user.go b/driver/web/conversions_user.go index 135864fb5..6b025d9a4 100644 --- a/driver/web/conversions_user.go +++ b/driver/web/conversions_user.go @@ -20,7 +20,7 @@ import ( "core-building-block/utils" ) -//Account +// Account func accountToDef(item model.Account) *Def.SharedResAccount { //profile profile := profileToDef(&item.Profile) @@ -85,7 +85,7 @@ func partialAccountsToDef(items []model.Account) []Def.PartialAccount { return result } -//AccountAuthType +// AccountAuthType func accountAuthTypeToDef(item model.AccountAuthType) Def.AccountAuthTypeFields { params := &Def.AccountAuthTypeFields_Params{} params.AdditionalProperties = item.Params @@ -101,7 +101,7 @@ func accountAuthTypesToDef(items []model.AccountAuthType) []Def.AccountAuthTypeF return result } -//AccountRole +// AccountRole func accountRoleToDef(item model.AccountRole) Def.AppOrgRole { permissions := applicationPermissionsToDef(item.Role.Permissions) @@ -124,7 +124,7 @@ func accountRolesToDef(items []model.AccountRole) []Def.AppOrgRole { return result } -//AccountGroup +// AccountGroup func accountGroupToDef(item model.AccountGroup) Def.AppOrgGroup { permissions := applicationPermissionsToDef(item.Group.Permissions) roles := appOrgRolesToDef(item.Group.Roles) @@ -148,7 +148,7 @@ func accountGroupsToDef(items []model.AccountGroup) []Def.AppOrgGroup { return result } -//Profile +// Profile func profileFromDef(item *Def.SharedReqProfile) model.Profile { if item == nil { return model.Profile{} @@ -293,7 +293,7 @@ func profileFromDefNullable(item *Def.SharedReqProfileNullable) model.Profile { State: state, Country: country} } -//Device +// Device func deviceFromDef(item *Def.DeviceFields) *model.Device { if item == nil { return nil diff --git a/driver/web/utils.go b/driver/web/utils.go index e597a5dde..9f24cdf1b 100644 --- a/driver/web/utils.go +++ b/driver/web/utils.go @@ -24,7 +24,7 @@ import ( "github.com/rokwire/logging-library-go/logutils" ) -//Helper for authLogin and authLoginMFA +// Helper for authLogin and authLoginMFA func authBuildLoginResponse(l *logs.Log, loginSession *model.LoginSession) logs.HttpResponse { //token accessToken := loginSession.AccessToken diff --git a/utils/utils.go b/utils/utils.go index 6175b56c2..aa98a6a13 100644 --- a/utils/utils.go +++ b/utils/utils.go @@ -110,12 +110,12 @@ func ConvertToJSON(data interface{}) ([]byte, error) { return dataJSON, nil } -//DeepEqual checks whether a and b are ``deeply equal,'' +// DeepEqual checks whether a and b are “deeply equal,” func DeepEqual(a, b interface{}) bool { return reflect.DeepEqual(a, b) } -//SetStringIfEmpty returns b if a is empty, a if not +// SetStringIfEmpty returns b if a is empty, a if not func SetStringIfEmpty(a, b string) string { if a == "" { return b @@ -123,12 +123,12 @@ func SetStringIfEmpty(a, b string) string { return a } -//GetType returns a string representing the type of data +// GetType returns a string representing the type of data func GetType(data interface{}) string { return reflect.TypeOf(data).String() } -//GetIP extracts the IP address from the http request +// GetIP extracts the IP address from the http request func GetIP(l *logs.Log, r *http.Request) string { IPAddress := r.Header.Get("X-Real-Ip") if IPAddress == "" { @@ -140,13 +140,13 @@ func GetIP(l *logs.Log, r *http.Request) string { return IPAddress } -//SHA256Hash computes the SHA256 hash of a byte slice +// SHA256Hash computes the SHA256 hash of a byte slice func SHA256Hash(data []byte) []byte { hash := sha256.Sum256(data) return hash[:] } -//GetLogValue prepares a sensitive data to be logged. +// GetLogValue prepares a sensitive data to be logged. func GetLogValue(value string, n int) string { if len(value) <= n { return "***" @@ -155,7 +155,7 @@ func GetLogValue(value string, n int) string { return fmt.Sprintf("***%s", lastN) } -//FormatTime formats the time value which this pointer points. Gives empty string if the pointer is nil +// FormatTime formats the time value which this pointer points. Gives empty string if the pointer is nil func FormatTime(v *time.Time) string { if v == nil { return "" @@ -163,7 +163,7 @@ func FormatTime(v *time.Time) string { return v.Format("2006-01-02T15:04:05.000Z") } -//Contains checks if list contains value +// Contains checks if list contains value func Contains(list []string, value string) bool { for _, v := range list { if v == value { @@ -173,7 +173,7 @@ func Contains(list []string, value string) bool { return false } -//StringListDiff returns a list of added, removed, unchanged values between a new and old string list +// StringListDiff returns a list of added, removed, unchanged values between a new and old string list func StringListDiff(new []string, old []string) ([]string, []string, []string) { added := []string{} removed := []string{} @@ -193,7 +193,7 @@ func StringListDiff(new []string, old []string) ([]string, []string, []string) { return added, removed, unchanged } -//StringOrNil returns a pointer to the input string, but returns nil if input is empty +// StringOrNil returns a pointer to the input string, but returns nil if input is empty func StringOrNil(v string) *string { if v == "" { return nil @@ -201,7 +201,7 @@ func StringOrNil(v string) *string { return &v } -//GetPrintableString returns the string content of a pointer, and defaultVal if pointer is nil +// GetPrintableString returns the string content of a pointer, and defaultVal if pointer is nil func GetPrintableString(v *string, defaultVal string) string { if v != nil { return *v From 4c9483bfbe28b175907e777898ea4f0ca04daf26 Mon Sep 17 00:00:00 2001 From: Ryan Oberlander Date: Thu, 4 Aug 2022 10:36:10 -0500 Subject: [PATCH 22/32] bug fixes [#475] --- core/app_bbs.go | 19 ++++++----- core/interfaces.go | 1 + core/mocks/Storage.go | 14 ++++++++ driven/storage/adapter.go | 33 ++++++++++++++++++- driver/web/apis_bbs.go | 5 +-- driver/web/docs/gen/def.yaml | 20 +++++------ .../web/docs/resources/bbs/permissions.yaml | 8 ++--- .../web/docs/resources/tps/permissions.yaml | 8 ++--- 8 files changed, 79 insertions(+), 29 deletions(-) diff --git a/core/app_bbs.go b/core/app_bbs.go index c109ad60e..17a8ec906 100644 --- a/core/app_bbs.go +++ b/core/app_bbs.go @@ -103,13 +103,12 @@ func (app *application) bbsUpdatePermissions(permissions []model.Permission, acc permission.ServiceID = serviceReg.Registration.ServiceID permission.Inactive = false permission.DateCreated = now - err = app.storage.InsertPermission(context, permission) - if err != nil { - return errors.WrapErrorAction(logutils.ActionInsert, model.TypePermission, &logutils.FieldArgs{"name": name}, err) - } - servicePermissions = append(servicePermissions, permission) } + err = app.storage.InsertPermissions(context, servicePermissions) + if err != nil { + return errors.WrapErrorAction(logutils.ActionInsert, model.TypePermission, &logutils.FieldArgs{"name": added}, err) + } //5. if removed, mark existing permission as inactive for _, name := range removed { @@ -133,9 +132,13 @@ func (app *application) bbsUpdatePermissions(permissions []model.Permission, acc return err } - updated := currentPermission.Inactive || (newPermission.Description != currentPermission.Description) || !utils.DeepEqual(newPermission.Assigners, currentPermission.Assigners) + description := newPermission.Description + assigners := newPermission.Assigners + updated := currentPermission.Inactive || (description != currentPermission.Description) || !utils.DeepEqual(assigners, currentPermission.Assigners) + newPermission = currentPermission if updated { - newPermission.ServiceID = serviceReg.Registration.ServiceID + newPermission.Description = description + newPermission.Assigners = assigners newPermission.Inactive = false newPermission.DateUpdated = &now err = app.storage.UpdatePermission(context, newPermission) @@ -164,7 +167,7 @@ func (app *application) validateAssigners(assigners []string, existing []model.P if len(missing) > 0 { missing = model.GetMissingPermissionNames(incoming, missing) if len(missing) > 0 { - return errors.ErrorData(logutils.StatusInvalid, model.TypePermission, &logutils.FieldArgs{"names": missing}) + return errors.ErrorData(logutils.StatusInvalid, "assigner permission", &logutils.FieldArgs{"names": missing}) } } diff --git a/core/interfaces.go b/core/interfaces.go index 3de68df10..2212c26e5 100644 --- a/core/interfaces.go +++ b/core/interfaces.go @@ -162,6 +162,7 @@ type Storage interface { FindPermissionsByName(context storage.TransactionContext, names []string) ([]model.Permission, error) FindPermissionsByServiceIDs(context storage.TransactionContext, serviceIDs []string) ([]model.Permission, error) InsertPermission(context storage.TransactionContext, item model.Permission) error + InsertPermissions(context storage.TransactionContext, items []model.Permission) error UpdatePermission(context storage.TransactionContext, item model.Permission) error DeletePermission(id string) error diff --git a/core/mocks/Storage.go b/core/mocks/Storage.go index fe5fbe88d..0f94bc1b3 100644 --- a/core/mocks/Storage.go +++ b/core/mocks/Storage.go @@ -1095,6 +1095,20 @@ func (_m *Storage) InsertPermission(context storage.TransactionContext, item mod return r0 } +// InsertPermissions provides a mock function with given fields: context, items +func (_m *Storage) InsertPermissions(context storage.TransactionContext, items []model.Permission) error { + ret := _m.Called(context, items) + + var r0 error + if rf, ok := ret.Get(0).(func(storage.TransactionContext, []model.Permission) error); ok { + r0 = rf(context, items) + } else { + r0 = ret.Error(0) + } + + return r0 +} + // PerformTransaction provides a mock function with given fields: _a0 func (_m *Storage) PerformTransaction(_a0 func(storage.TransactionContext) error) error { ret := _m.Called(_a0) diff --git a/driven/storage/adapter.go b/driven/storage/adapter.go index 61b5301c4..56c9162c8 100644 --- a/driven/storage/adapter.go +++ b/driven/storage/adapter.go @@ -168,7 +168,9 @@ func (sa *Adapter) setCachedServiceRegs(serviceRegs *[]model.ServiceReg) { err := validate.Struct(serviceReg) if err == nil { sa.cachedServiceRegs.Store(serviceReg.Registration.ServiceID, serviceReg) - sa.cachedServiceRegs.Store(serviceReg.Registration.ServiceAccountID, serviceReg) + if serviceReg.Registration.ServiceAccountID != "" { + sa.cachedServiceRegs.Store(serviceReg.Registration.ServiceAccountID, serviceReg) + } } else { sa.logger.Errorf("failed to validate and cache service registration with registration.service_id %s, registration.service_account_id %s: %s", serviceReg.Registration.ServiceID, serviceReg.Registration.ServiceAccountID, err.Error()) } @@ -2216,6 +2218,35 @@ func (sa *Adapter) InsertPermission(context TransactionContext, permission model return nil } +// InsertPermissions inserts permissions +func (sa *Adapter) InsertPermissions(context TransactionContext, items []model.Permission) error { + if len(items) == 0 { + return nil + } + + stgPermissions := make([]interface{}, len(items)) + for i, p := range items { + stgPermissions[i] = p + } + + var res *mongo.InsertManyResult + var err error + if context != nil { + res, err = sa.db.permissions.InsertManyWithContext(context, stgPermissions, nil) + } else { + res, err = sa.db.permissions.InsertMany(stgPermissions, nil) + } + if err != nil { + return errors.WrapErrorAction(logutils.ActionInsert, model.TypePermission, nil, err) + } + + if len(res.InsertedIDs) != len(items) { + return errors.ErrorAction(logutils.ActionInsert, model.TypePermission, &logutils.FieldArgs{"inserted": len(res.InsertedIDs), "expected": len(items)}) + } + + return nil +} + // UpdatePermission updates permission func (sa *Adapter) UpdatePermission(context TransactionContext, item model.Permission) error { //TODO diff --git a/driver/web/apis_bbs.go b/driver/web/apis_bbs.go index 852a5d50f..4755680b4 100644 --- a/driver/web/apis_bbs.go +++ b/driver/web/apis_bbs.go @@ -181,9 +181,10 @@ func (h BBsApisHandler) updatePermissions(l *logs.Log, r *http.Request, claims * return l.HttpResponseErrorAction(logutils.ActionUpdate, model.TypePermission, nil, err, http.StatusInternalServerError, true) } - respData, err := json.Marshal(permissions) + permissionsResp := applicationPermissionsToDef(permissions) + respData, err := json.Marshal(permissionsResp) if err != nil { - return l.HttpResponseErrorAction(logutils.ActionMarshal, logutils.MessageDataType("service access tokens response"), nil, err, http.StatusInternalServerError, false) + return l.HttpResponseErrorAction(logutils.ActionMarshal, logutils.MessageDataType("permissions response"), nil, err, http.StatusInternalServerError, false) } return l.HttpResponseSuccessJSON(respData) diff --git a/driver/web/docs/gen/def.yaml b/driver/web/docs/gen/def.yaml index 00d4ec4d0..d0019cd00 100644 --- a/driver/web/docs/gen/def.yaml +++ b/driver/web/docs/gen/def.yaml @@ -2838,11 +2838,11 @@ paths: '200': description: Success content: - application/json: null - schema: - type: array - items: - $ref: '#/components/schemas/Permission' + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/Permission' '400': description: Bad request '401': @@ -3090,11 +3090,11 @@ paths: '200': description: Success content: - application/json: null - schema: - type: array - items: - $ref: '#/components/schemas/Permission' + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/Permission' '400': description: Bad request '401': diff --git a/driver/web/docs/resources/bbs/permissions.yaml b/driver/web/docs/resources/bbs/permissions.yaml index c1e035663..8d66a0602 100644 --- a/driver/web/docs/resources/bbs/permissions.yaml +++ b/driver/web/docs/resources/bbs/permissions.yaml @@ -22,10 +22,10 @@ put: description: Success content: application/json: - schema: - type: array - items: - $ref: "../../schemas/application/Permission.yaml" + schema: + type: array + items: + $ref: "../../schemas/application/Permission.yaml" 400: description: Bad request 401: diff --git a/driver/web/docs/resources/tps/permissions.yaml b/driver/web/docs/resources/tps/permissions.yaml index e866eb933..5ad242adc 100644 --- a/driver/web/docs/resources/tps/permissions.yaml +++ b/driver/web/docs/resources/tps/permissions.yaml @@ -22,10 +22,10 @@ put: description: Success content: application/json: - schema: - type: array - items: - $ref: "../../schemas/application/Permission.yaml" + schema: + type: array + items: + $ref: "../../schemas/application/Permission.yaml" 400: description: Bad request 401: From a3d18de92a698ac18432dc64e7cb26c91e5cbbc8 Mon Sep 17 00:00:00 2001 From: Ryan Oberlander Date: Thu, 4 Aug 2022 11:25:27 -0500 Subject: [PATCH 23/32] better error checking --- .secrets.baseline | 4 +- core/app_system.go | 19 +-- core/auth/apis.go | 162 ++++++++++--------- core/model/application.go | 162 +++++++++---------- driven/storage/adapter.go | 322 ++++++++++++++++++++------------------ 5 files changed, 350 insertions(+), 319 deletions(-) diff --git a/.secrets.baseline b/.secrets.baseline index 017db0c39..122d96e12 100644 --- a/.secrets.baseline +++ b/.secrets.baseline @@ -124,7 +124,7 @@ "filename": "core/auth/apis.go", "hashed_secret": "4d55af37dbbb6a42088d917caa1ca25428ec42c9", "is_verified": false, - "line_number": 1885 + "line_number": 1905 } ], "core/auth/auth.go": [ @@ -279,5 +279,5 @@ } ] }, - "generated_at": "2022-08-01T19:22:45Z" + "generated_at": "2022-08-04T16:25:21Z" } diff --git a/core/app_system.go b/core/app_system.go index e808bb57a..77e430603 100644 --- a/core/app_system.go +++ b/core/app_system.go @@ -166,9 +166,7 @@ func (app *application) sysGetApplications() ([]model.Application, error) { func (app *application) sysCreatePermission(name string, description string, serviceID string, assigners *[]string) (*model.Permission, error) { var newPermission *model.Permission transaction := func(context storage.TransactionContext) error { - //1. - id, _ := uuid.NewUUID() - now := time.Now() + //1. make sure all assigners already exist assignersVal := make([]string, 0) if assigners != nil { assignersVal = *assigners @@ -176,12 +174,15 @@ func (app *application) sysCreatePermission(name string, description string, ser if err != nil { return err } - _, err = model.GetMissingPermissionNames(assignerPermissions, assignersVal) - if err != nil { - return err + if len(assignerPermissions) < len(assignersVal) { + missing := model.GetMissingPermissionNames(assignerPermissions, assignersVal) + return errors.ErrorData(logutils.StatusInvalid, "assigner permission", &logutils.FieldArgs{"names": missing}) } } + //2. create permission + id, _ := uuid.NewUUID() + now := time.Now() permission := model.Permission{ID: id.String(), Name: name, Description: description, DateCreated: now, ServiceID: serviceID, Assigners: assignersVal} err := app.storage.InsertPermission(context, permission) if err != nil { @@ -235,9 +236,9 @@ func (app *application) sysUpdatePermission(name string, description string, ser if err != nil { return err } - _, err = model.GetMissingPermissionNames(assignerPermissions, assignersVal) - if err != nil { - return err + if len(assignerPermissions) < len(assignersVal) { + missing := model.GetMissingPermissionNames(assignerPermissions, assignersVal) + return errors.ErrorData(logutils.StatusInvalid, "assigner permission", &logutils.FieldArgs{"names": missing}) } permission.Assigners = *assigners diff --git a/core/auth/apis.go b/core/auth/apis.go index 890abc95c..94a66a36c 100644 --- a/core/auth/apis.go +++ b/core/auth/apis.go @@ -32,7 +32,7 @@ import ( "github.com/rokwire/logging-library-go/logs" ) -//Start starts the auth service +// Start starts the auth service func (a *Auth) Start() { storageListener := StorageListener{auth: a} a.storage.RegisterStorageListener(&storageListener) @@ -40,13 +40,14 @@ func (a *Auth) Start() { go a.setupDeleteSessionsTimer() } -//GetHost returns the host/issuer of the auth service +// GetHost returns the host/issuer of the auth service func (a *Auth) GetHost() string { return a.host } -//Login logs a user in a specific application using the specified credentials and authentication method. -//The authentication method must be one of the supported for the application. +// Login logs a user in a specific application using the specified credentials and authentication method. +// The authentication method must be one of the supported for the application. +// // Input: // ipAddress (string): Client's IP address // deviceType (string): "mobile" or "web" or "desktop" etc @@ -167,7 +168,8 @@ func (a *Auth) Login(ipAddress string, deviceType string, deviceOS *string, devi return nil, &model.LoginSession{ID: loginSession.ID, Identifier: loginSession.Identifier, Params: responseParams, State: loginSession.State}, mfaTypes, nil } -//Logout logouts an account from app/org +// Logout logouts an account from app/org +// // Input: // allSessions (bool): If to remove the current session only or all sessions for the app/org for the account func (a *Auth) Logout(appID string, orgID string, currentAccountID string, sessionID string, allSessions bool, l *logs.Log) error { @@ -185,8 +187,9 @@ func (a *Auth) Logout(appID string, orgID string, currentAccountID string, sessi return nil } -//AccountExists checks if a user is already registered -//The authentication method must be one of the supported for the application. +// AccountExists checks if a user is already registered +// The authentication method must be one of the supported for the application. +// // Input: // authenticationType (string): Name of the authentication method for provided creds (eg. "email", "username", "illinois_oidc") // userIdentifier (string): User identifier for the specified auth type @@ -204,8 +207,9 @@ func (a *Auth) AccountExists(authenticationType string, userIdentifier string, a return account != nil, nil } -//CanSignIn checks if a user can sign in -//The authentication method must be one of the supported for the application. +// CanSignIn checks if a user can sign in +// The authentication method must be one of the supported for the application. +// // Input: // authenticationType (string): Name of the authentication method for provided creds (eg. "email", "username", "illinois_oidc") // userIdentifier (string): User identifier for the specified auth type @@ -223,8 +227,9 @@ func (a *Auth) CanSignIn(authenticationType string, userIdentifier string, apiKe return a.canSignIn(account, authTypeID, userIdentifier), nil } -//CanLink checks if a user can link a new auth type -//The authentication method must be one of the supported for the application. +// CanLink checks if a user can link a new auth type +// The authentication method must be one of the supported for the application. +// // Input: // authenticationType (string): Name of the authentication method for provided creds (eg. "email", "username", "illinois_oidc") // userIdentifier (string): User identifier for the specified auth type @@ -247,7 +252,8 @@ func (a *Auth) CanLink(authenticationType string, userIdentifier string, apiKey return true, nil } -//Refresh refreshes an access token using a refresh token +// Refresh refreshes an access token using a refresh token +// // Input: // refreshToken (string): Refresh token // apiKey (string): API key to validate the specified app @@ -407,7 +413,8 @@ func (a *Auth) Refresh(refreshToken string, apiKey string, l *logs.Log) (*model. return loginSession, nil } -//GetLoginURL returns a pre-formatted login url for SSO providers +// GetLoginURL returns a pre-formatted login url for SSO providers +// // Input: // authenticationType (string): Name of the authentication method for provided creds (eg. "email", "username", "illinois_oidc") // appTypeIdentifier (string): Identifier of the app type/client that the user is logging in from @@ -446,8 +453,9 @@ func (a *Auth) GetLoginURL(authenticationType string, appTypeIdentifier string, return loginURL, params, nil } -//LoginMFA verifies a code sent by a user as a final login step for enrolled accounts. -//The MFA type must be one of the supported for the application. +// LoginMFA verifies a code sent by a user as a final login step for enrolled accounts. +// The MFA type must be one of the supported for the application. +// // Input: // apiKey (string): API key to validate the specified app // accountID (string): ID of account user is trying to access @@ -550,7 +558,7 @@ func (a *Auth) LoginMFA(apiKey string, accountID string, sessionID string, ident return nil, loginSession, nil } -//CreateAdminAccount creates an account for a new admin user +// CreateAdminAccount creates an account for a new admin user func (a *Auth) CreateAdminAccount(authenticationType string, appID string, orgID string, identifier string, profile model.Profile, permissions []string, roleIDs []string, groupIDs []string, creatorPermissions []string, l *logs.Log) (*model.Account, map[string]interface{}, error) { //TODO: add admin authentication policies that specify which auth types may be used for each app org @@ -611,7 +619,7 @@ func (a *Auth) CreateAdminAccount(authenticationType string, appID string, orgID return newAccount, params, nil } -//UpdateAdminAccount updates an existing user's account with new permissions, roles, and groups +// UpdateAdminAccount updates an existing user's account with new permissions, roles, and groups func (a *Auth) UpdateAdminAccount(authenticationType string, appID string, orgID string, identifier string, permissions []string, roleIDs []string, groupIDs []string, updaterPermissions []string, l *logs.Log) (*model.Account, map[string]interface{}, error) { //TODO: when elevating existing accounts to application level admin, need to enforce any authentication policies set up for the app org @@ -792,7 +800,7 @@ func (a *Auth) UpdateAdminAccount(authenticationType string, appID string, orgID return updatedAccount, params, nil } -//VerifyCredential verifies credential (checks the verification code in the credentials collection) +// VerifyCredential verifies credential (checks the verification code in the credentials collection) func (a *Auth) VerifyCredential(id string, verification string, l *logs.Log) error { credential, err := a.storage.FindCredential(nil, id) if err != nil || credential == nil { @@ -831,14 +839,16 @@ func (a *Auth) VerifyCredential(id string, verification string, l *logs.Log) err return nil } -//UpdateCredential updates the credential object with the new value +// UpdateCredential updates the credential object with the new value +// // Input: // accountID: id of the associated account to reset // accountAuthTypeID (string): id of the AccountAuthType // params: specific params for the different auth types // Returns: // error: if any -//TODO: Clear login sessions using old creds +// +// TODO: Clear login sessions using old creds // Handle refresh tokens when applicable func (a *Auth) UpdateCredential(accountID string, accountAuthTypeID string, params string, l *logs.Log) error { //Get the user credential from account auth type in accounts collection @@ -879,14 +889,16 @@ func (a *Auth) UpdateCredential(accountID string, accountAuthTypeID string, para return nil } -//ResetForgotCredential resets forgot credential +// ResetForgotCredential resets forgot credential +// // Input: // credsID: id of the credential object // resetCode: code from the reset link // params: specific params for the different auth types // Returns: // error: if any -//TODO: Clear login sessions using old creds +// +// TODO: Clear login sessions using old creds // Handle refresh tokens when applicable func (a *Auth) ResetForgotCredential(credsID string, resetCode string, params string, l *logs.Log) error { credential, err := a.storage.FindCredential(nil, credsID) @@ -921,7 +933,8 @@ func (a *Auth) ResetForgotCredential(credsID string, resetCode string, params st return nil } -//ForgotCredential initiate forgot credential process (generates a reset link and sends to the given identifier for email auth type) +// ForgotCredential initiate forgot credential process (generates a reset link and sends to the given identifier for email auth type) +// // Input: // authenticationType (string): Name of the authentication method for provided creds (eg. "email", "username", "illinois_oidc") // identifier: identifier of the account auth type @@ -992,7 +1005,7 @@ func (a *Auth) ForgotCredential(authenticationType string, appTypeIdentifier str return nil } -//SendVerifyCredential sends the verification code to the identifier +// SendVerifyCredential sends the verification code to the identifier func (a *Auth) SendVerifyCredential(authenticationType string, appTypeIdentifier string, orgID string, apiKey string, identifier string, l *logs.Log) error { //validate if the provided auth type is supported by the provided application and organization authType, _, appOrg, err := a.validateAuthType(authenticationType, appTypeIdentifier, orgID) @@ -1037,8 +1050,9 @@ func (a *Auth) SendVerifyCredential(authenticationType string, appTypeIdentifier return nil } -//VerifyMFA verifies a code sent by a user as a final MFA enrollment step. -//The MFA type must be one of the supported for the application. +// VerifyMFA verifies a code sent by a user as a final MFA enrollment step. +// The MFA type must be one of the supported for the application. +// // Input: // accountID (string): ID of account for which user is trying to verify MFA // identifier (string): Email, phone, or TOTP device name @@ -1129,7 +1143,8 @@ func (a *Auth) VerifyMFA(accountID string, identifier string, mfaType string, mf return nil, nil, nil } -//GetMFATypes gets all MFA types set up for an account +// GetMFATypes gets all MFA types set up for an account +// // Input: // accountID (string): Account ID to find MFA types // Returns: @@ -1143,7 +1158,8 @@ func (a *Auth) GetMFATypes(accountID string) ([]model.MFAType, error) { return mfa, nil } -//AddMFAType adds a form of MFA to an account +// AddMFAType adds a form of MFA to an account +// // Input: // accountID (string): Account ID to add MFA // identifier (string): Email, phone, or TOTP device name @@ -1169,7 +1185,8 @@ func (a *Auth) AddMFAType(accountID string, identifier string, mfaType string) ( return newMfa, nil } -//RemoveMFAType removes a form of MFA from an account +// RemoveMFAType removes a form of MFA from an account +// // Input: // accountID (string): Account ID to remove MFA // identifier (string): Email, phone, or TOTP device name @@ -1210,7 +1227,7 @@ func (a *Auth) RemoveMFAType(accountID string, identifier string, mfaType string return nil } -//GetServiceAccountParams returns a list of app, org pairs a service account has access to +// GetServiceAccountParams returns a list of app, org pairs a service account has access to func (a *Auth) GetServiceAccountParams(accountID string, firstParty bool, r *sigauth.Request, l *logs.Log) ([]model.AppOrgPair, error) { accounts, _, err := a.checkServiceAccountCreds(r, &accountID, firstParty, false, l) if err != nil { @@ -1233,7 +1250,7 @@ func (a *Auth) GetServiceAccountParams(accountID string, firstParty bool, r *sig return appOrgPairs, nil } -//GetServiceAccessToken returns an access token for a non-human client +// GetServiceAccessToken returns an access token for a non-human client func (a *Auth) GetServiceAccessToken(firstParty bool, r *sigauth.Request, l *logs.Log) (string, error) { accounts, authType, err := a.checkServiceAccountCreds(r, nil, firstParty, true, l) if err != nil { @@ -1248,7 +1265,7 @@ func (a *Auth) GetServiceAccessToken(firstParty bool, r *sigauth.Request, l *log return accessToken, nil } -//GetAllServiceAccessTokens returns an access token for each app, org pair a service account has access to +// GetAllServiceAccessTokens returns an access token for each app, org pair a service account has access to func (a *Auth) GetAllServiceAccessTokens(firstParty bool, r *sigauth.Request, l *logs.Log) (map[model.AppOrgPair]string, error) { accounts, authType, err := a.checkServiceAccountCreds(r, nil, firstParty, false, l) if err != nil { @@ -1268,7 +1285,7 @@ func (a *Auth) GetAllServiceAccessTokens(firstParty bool, r *sigauth.Request, l return accessTokens, nil } -//GetServiceAccounts gets all service accounts matching a search +// GetServiceAccounts gets all service accounts matching a search func (a *Auth) GetServiceAccounts(params map[string]interface{}) ([]model.ServiceAccount, error) { serviceAccounts, err := a.storage.FindServiceAccounts(params) if err != nil { @@ -1278,7 +1295,7 @@ func (a *Auth) GetServiceAccounts(params map[string]interface{}) ([]model.Servic return serviceAccounts, nil } -//RegisterServiceAccount registers a service account +// RegisterServiceAccount registers a service account func (a *Auth) RegisterServiceAccount(accountID *string, fromAppID *string, fromOrgID *string, name *string, appID string, orgID string, permissions *[]string, firstParty *bool, creds []model.ServiceAccountCredential, assignerPermissions []string, l *logs.Log) (*model.ServiceAccount, error) { var newAccount *model.ServiceAccount @@ -1359,7 +1376,7 @@ func (a *Auth) RegisterServiceAccount(accountID *string, fromAppID *string, from return newAccount, nil } -//DeregisterServiceAccount deregisters a service account +// DeregisterServiceAccount deregisters a service account func (a *Auth) DeregisterServiceAccount(accountID string) error { // delete all service account instances matching accountID err := a.storage.DeleteServiceAccounts(accountID) @@ -1370,7 +1387,7 @@ func (a *Auth) DeregisterServiceAccount(accountID string) error { return nil } -//GetServiceAccountInstance gets a service account instance +// GetServiceAccountInstance gets a service account instance func (a *Auth) GetServiceAccountInstance(accountID string, appID string, orgID string) (*model.ServiceAccount, error) { serviceAccount, err := a.storage.FindServiceAccount(nil, accountID, appID, orgID) if err != nil { @@ -1380,7 +1397,7 @@ func (a *Auth) GetServiceAccountInstance(accountID string, appID string, orgID s return serviceAccount, nil } -//UpdateServiceAccountInstance updates a service account instance +// UpdateServiceAccountInstance updates a service account instance func (a *Auth) UpdateServiceAccountInstance(id string, appID string, orgID string, name string, permissions []string, assignerPermissions []string) (*model.ServiceAccount, error) { updatedAccount, err := a.constructServiceAccount(id, name, appID, orgID, permissions, false, assignerPermissions) if err != nil { @@ -1395,7 +1412,7 @@ func (a *Auth) UpdateServiceAccountInstance(id string, appID string, orgID strin return updatedAccount, nil } -//DeregisterServiceAccountInstance deregisters a service account instance +// DeregisterServiceAccountInstance deregisters a service account instance func (a *Auth) DeregisterServiceAccountInstance(id string, appID string, orgID string) error { err := a.storage.DeleteServiceAccount(id, appID, orgID) if err != nil { @@ -1405,7 +1422,7 @@ func (a *Auth) DeregisterServiceAccountInstance(id string, appID string, orgID s return nil } -//AddServiceAccountCredential adds a credential to a service account +// AddServiceAccountCredential adds a credential to a service account func (a *Auth) AddServiceAccountCredential(accountID string, creds *model.ServiceAccountCredential, l *logs.Log) (*model.ServiceAccountCredential, error) { if creds == nil { return nil, errors.ErrorData(logutils.StatusMissing, model.TypeServiceAccountCredential, nil) @@ -1431,7 +1448,7 @@ func (a *Auth) AddServiceAccountCredential(accountID string, creds *model.Servic return creds, nil } -//RemoveServiceAccountCredential removes a credential from a service account +// RemoveServiceAccountCredential removes a credential from a service account func (a *Auth) RemoveServiceAccountCredential(accountID string, credID string) error { err := a.storage.DeleteServiceAccountCredential(accountID, credID) if err != nil { @@ -1441,7 +1458,8 @@ func (a *Auth) RemoveServiceAccountCredential(accountID string, credID string) e return nil } -//AuthorizeService returns a scoped token for the specified service and the service registration record if authorized or +// AuthorizeService returns a scoped token for the specified service and the service registration record if authorized or +// // the service registration record if not. Passing "approvedScopes" will update the service authorization for this user and // return a scoped access token which reflects this change. // Input: @@ -1489,7 +1507,7 @@ func (a *Auth) AuthorizeService(claims tokenauth.Claims, serviceID string, appro return token, authorization.Scopes, nil, nil } -//GetAdminToken returns an admin token for the specified application +// GetAdminToken returns an admin token for the specified application func (a *Auth) GetAdminToken(claims tokenauth.Claims, appID string, l *logs.Log) (string, error) { //verify that the provided appID is valid for the organization appOrg, err := a.storage.FindApplicationOrganization(appID, claims.OrgID) @@ -1505,8 +1523,9 @@ func (a *Auth) GetAdminToken(claims tokenauth.Claims, appID string, l *logs.Log) return a.buildAccessToken(adminClaims, claims.Permissions, claims.Scope) } -//LinkAccountAuthType links new credentials to an existing account. -//The authentication method must be one of the supported for the application. +// LinkAccountAuthType links new credentials to an existing account. +// The authentication method must be one of the supported for the application. +// // Input: // accountID (string): ID of the account to link the creds to // authenticationType (string): Name of the authentication method for provided creds (eg. "email", "username", "illinois_oidc") @@ -1556,8 +1575,9 @@ func (a *Auth) LinkAccountAuthType(accountID string, authenticationType string, return &message, account, nil } -//UnlinkAccountAuthType unlinks credentials from an existing account. -//The authentication method must be one of the supported for the application. +// UnlinkAccountAuthType unlinks credentials from an existing account. +// The authentication method must be one of the supported for the application. +// // Input: // accountID (string): ID of the account to unlink creds from // authenticationType (string): Name of the authentication method of account auth type to unlink @@ -1570,7 +1590,7 @@ func (a *Auth) UnlinkAccountAuthType(accountID string, authenticationType string return a.unlinkAccountAuthType(accountID, authenticationType, appTypeIdentifier, identifier, l) } -//DeleteAccount deletes an account for the given id +// DeleteAccount deletes an account for the given id func (a *Auth) DeleteAccount(id string) error { transaction := func(context storage.TransactionContext) error { //1. first find the account record @@ -1593,7 +1613,7 @@ func (a *Auth) DeleteAccount(id string) error { return a.storage.PerformTransaction(transaction) } -//InitializeSystemAccount initializes the first system account +// InitializeSystemAccount initializes the first system account func (a *Auth) InitializeSystemAccount(context storage.TransactionContext, authType model.AuthType, appOrg model.ApplicationOrganization, allSystemPermission string, email string, password string, l *logs.Log) (string, error) { //auth type @@ -1614,7 +1634,7 @@ func (a *Auth) InitializeSystemAccount(context storage.TransactionContext, authT return accountAuthType.Account.ID, nil } -//GrantAccountPermissions grants new permissions to an account after validating the assigner has required permissions +// GrantAccountPermissions grants new permissions to an account after validating the assigner has required permissions func (a *Auth) GrantAccountPermissions(context storage.TransactionContext, account *model.Account, permissionNames []string, assignerPermissions []string) error { //check if there is data if account == nil { @@ -1649,7 +1669,7 @@ func (a *Auth) GrantAccountPermissions(context storage.TransactionContext, accou return nil } -//CheckPermissions loads permissions by names from storage and checks that they are assignable and valid for the given appOrg or revocable +// CheckPermissions loads permissions by names from storage and checks that they are assignable and valid for the given appOrg or revocable func (a *Auth) CheckPermissions(context storage.TransactionContext, appOrg *model.ApplicationOrganization, permissionNames []string, assignerPermissions []string, revoke bool) ([]model.Permission, error) { if appOrg == nil { return nil, errors.ErrorData(logutils.StatusInvalid, model.TypeApplicationOrganization, nil) @@ -1660,9 +1680,9 @@ func (a *Auth) CheckPermissions(context storage.TransactionContext, appOrg *mode if err != nil { return nil, errors.WrapErrorAction(logutils.ActionFind, model.TypePermission, nil, err) } - _, err = model.GetMissingPermissionNames(permissions, permissionNames) - if err != nil { - return nil, err + if len(permissions) < len(permissionNames) { + missing := model.GetMissingPermissionNames(permissions, permissionNames) + return nil, errors.ErrorData(logutils.StatusInvalid, model.TypePermission, &logutils.FieldArgs{"names": missing}) } //check if authorized @@ -1683,7 +1703,7 @@ func (a *Auth) CheckPermissions(context storage.TransactionContext, appOrg *mode return permissions, nil } -//GrantAccountRoles grants new roles to an account after validating the assigner has required permissions +// GrantAccountRoles grants new roles to an account after validating the assigner has required permissions func (a *Auth) GrantAccountRoles(context storage.TransactionContext, account *model.Account, roleIDs []string, assignerPermissions []string) error { //check if there is data if account == nil { @@ -1719,7 +1739,7 @@ func (a *Auth) GrantAccountRoles(context storage.TransactionContext, account *mo return nil } -//CheckRoles loads appOrg roles by IDs from storage and checks that they are assignable or revocable +// CheckRoles loads appOrg roles by IDs from storage and checks that they are assignable or revocable func (a *Auth) CheckRoles(context storage.TransactionContext, appOrg *model.ApplicationOrganization, roleIDs []string, assignerPermissions []string, revoke bool) ([]model.AppOrgRole, error) { if appOrg == nil { return nil, errors.ErrorData(logutils.StatusInvalid, model.TypeApplicationOrganization, nil) @@ -1730,9 +1750,9 @@ func (a *Auth) CheckRoles(context storage.TransactionContext, appOrg *model.Appl if err != nil { return nil, errors.WrapErrorAction(logutils.ActionFind, model.TypeAppOrgRole, nil, err) } - _, err = model.GetMissingRoleIDs(roles, roleIDs) - if err != nil { - return nil, err + if len(roles) < len(roleIDs) { + missing := model.GetMissingRoleIDs(roles, roleIDs) + return nil, errors.ErrorData(logutils.StatusInvalid, model.TypeAppOrgRole, &logutils.FieldArgs{"ids": missing}) } //check if authorized @@ -1746,7 +1766,7 @@ func (a *Auth) CheckRoles(context storage.TransactionContext, appOrg *model.Appl return roles, nil } -//GrantAccountGroups grants new groups to an account after validating the assigner has required permissions +// GrantAccountGroups grants new groups to an account after validating the assigner has required permissions func (a *Auth) GrantAccountGroups(context storage.TransactionContext, account *model.Account, groupIDs []string, assignerPermissions []string) error { //check if there is data if account == nil { @@ -1782,7 +1802,7 @@ func (a *Auth) GrantAccountGroups(context storage.TransactionContext, account *m return nil } -//CheckGroups loads appOrg groups by IDs from storage and checks that they are assignable or revocable +// CheckGroups loads appOrg groups by IDs from storage and checks that they are assignable or revocable func (a *Auth) CheckGroups(context storage.TransactionContext, appOrg *model.ApplicationOrganization, groupIDs []string, assignerPermissions []string, revoke bool) ([]model.AppOrgGroup, error) { if appOrg == nil { return nil, errors.ErrorData(logutils.StatusInvalid, model.TypeApplicationOrganization, nil) @@ -1821,12 +1841,12 @@ func (a *Auth) CheckGroups(context storage.TransactionContext, appOrg *model.App return groups, nil } -//GetServiceRegistrations retrieves all service registrations +// GetServiceRegistrations retrieves all service registrations func (a *Auth) GetServiceRegistrations(serviceIDs []string) ([]model.ServiceReg, error) { return a.storage.FindServiceRegs(serviceIDs) } -//RegisterService creates a new service registration +// RegisterService creates a new service registration func (a *Auth) RegisterService(reg *model.ServiceReg) error { if reg != nil && !reg.FirstParty && strings.Contains(strings.ToUpper(reg.Name), rokwireKeyword) { return errors.Newf("the name of a third-party service may not contain \"%s\"", rokwireKeyword) @@ -1834,7 +1854,7 @@ func (a *Auth) RegisterService(reg *model.ServiceReg) error { return a.storage.InsertServiceReg(reg) } -//UpdateServiceRegistration updates an existing service registration +// UpdateServiceRegistration updates an existing service registration func (a *Auth) UpdateServiceRegistration(reg *model.ServiceReg) error { if reg != nil { if reg.Registration.ServiceID == authServiceID || reg.Registration.ServiceID == a.serviceID { @@ -1847,7 +1867,7 @@ func (a *Auth) UpdateServiceRegistration(reg *model.ServiceReg) error { return a.storage.UpdateServiceReg(reg) } -//DeregisterService deletes an existing service registration +// DeregisterService deletes an existing service registration func (a *Auth) DeregisterService(serviceID string) error { if serviceID == authServiceID || serviceID == a.serviceID { return errors.Newf("deregistering service not allowed for service id %v", serviceID) @@ -1855,7 +1875,7 @@ func (a *Auth) DeregisterService(serviceID string) error { return a.storage.DeleteServiceReg(serviceID) } -//GetAuthKeySet generates a JSON Web Key Set for auth service registration +// GetAuthKeySet generates a JSON Web Key Set for auth service registration func (a *Auth) GetAuthKeySet() (*model.JSONWebKeySet, error) { authReg, err := a.ServiceRegManager.GetServiceReg("auth") if err != nil { @@ -1874,7 +1894,7 @@ func (a *Auth) GetAuthKeySet() (*model.JSONWebKeySet, error) { return &model.JSONWebKeySet{Keys: []model.JSONWebKey{*jwk}}, nil } -//GetApplicationAPIKeys finds and returns the API keys for the provided app +// GetApplicationAPIKeys finds and returns the API keys for the provided app func (a *Auth) GetApplicationAPIKeys(appID string) ([]model.APIKey, error) { cachedAPIKeys, err := a.getCachedAPIKeys() if err != nil { @@ -1891,19 +1911,19 @@ func (a *Auth) GetApplicationAPIKeys(appID string) ([]model.APIKey, error) { return applicationAPIKeys, nil } -//GetAPIKey finds and returns an API key +// GetAPIKey finds and returns an API key func (a *Auth) GetAPIKey(ID string) (*model.APIKey, error) { return a.getCachedAPIKey(ID) } -//CreateAPIKey creates a new API key +// CreateAPIKey creates a new API key func (a *Auth) CreateAPIKey(apiKey model.APIKey) (*model.APIKey, error) { id, _ := uuid.NewUUID() apiKey.ID = id.String() return a.storage.InsertAPIKey(nil, apiKey) } -//UpdateAPIKey updates an existing API key +// UpdateAPIKey updates an existing API key func (a *Auth) UpdateAPIKey(apiKey model.APIKey) error { if len(apiKey.ID) == 0 { return errors.Newf("id cannot be empty") @@ -1911,7 +1931,7 @@ func (a *Auth) UpdateAPIKey(apiKey model.APIKey) error { return a.storage.UpdateAPIKey(apiKey) } -//DeleteAPIKey deletes an API key +// DeleteAPIKey deletes an API key func (a *Auth) DeleteAPIKey(ID string) error { //1. find api key to delete apiKey, err := a.getCachedAPIKey(ID) @@ -1936,7 +1956,7 @@ func (a *Auth) DeleteAPIKey(ID string) error { return nil } -//ValidateAPIKey validates the given API key for the given app ID +// ValidateAPIKey validates the given API key for the given app ID func (a *Auth) ValidateAPIKey(appID string, apiKey string) error { return a.validateAPIKey(apiKey, appID) } diff --git a/core/model/application.go b/core/model/application.go index 7eabe5a58..3aae86847 100644 --- a/core/model/application.go +++ b/core/model/application.go @@ -55,7 +55,7 @@ const ( PermissionAllSystemCore string = "all_system_core" ) -//Permission represents permission entity +// Permission represents permission entity type Permission struct { ID string `bson:"_id"` Name string `bson:"name"` @@ -68,7 +68,7 @@ type Permission struct { DateUpdated *time.Time `bson:"date_updated"` } -//CheckAssigners checks if the passed permissions satisfy the needed assigners for the permission +// CheckAssigners checks if the passed permissions satisfy the needed assigners for the permission func (p Permission) CheckAssigners(assignerPermissions []string) error { if len(p.Assigners) == 0 { return errors.Newf("not defined assigners for %s permission", p.Name) @@ -88,7 +88,7 @@ func (p Permission) String() string { return fmt.Sprintf("[ID:%s\nName:%s\nServiceID:%s]", p.ID, p.Name, p.ServiceID) } -//AppOrgRole represents application organization role entity. It is a collection of permissions +// AppOrgRole represents application organization role entity. It is a collection of permissions type AppOrgRole struct { ID string Name string @@ -104,7 +104,7 @@ type AppOrgRole struct { DateUpdated *time.Time } -//GetPermissionNamed returns the permission for a name if the role has it +// GetPermissionNamed returns the permission for a name if the role has it func (c AppOrgRole) GetPermissionNamed(name string) *Permission { for _, permission := range c.Permissions { if permission.Name == name { @@ -114,7 +114,7 @@ func (c AppOrgRole) GetPermissionNamed(name string) *Permission { return nil } -//GetAssignedPermissionNames returns a list of names of assigned permissions for this role +// GetAssignedPermissionNames returns a list of names of assigned permissions for this role func (c AppOrgRole) GetAssignedPermissionNames() []string { names := make([]string, len(c.Permissions)) for i, permission := range c.Permissions { @@ -123,7 +123,7 @@ func (c AppOrgRole) GetAssignedPermissionNames() []string { return names } -//CheckAssigners checks if the passed permissions satisfy the needed assigners for all role permissions +// CheckAssigners checks if the passed permissions satisfy the needed assigners for all role permissions func (c AppOrgRole) CheckAssigners(assignerPermissions []string) error { if len(c.Permissions) == 0 { return nil //no permission @@ -143,7 +143,7 @@ func (c AppOrgRole) String() string { return fmt.Sprintf("[ID:%s\tName:%s\tPermissions:%s\tAppOrg:%s]", c.ID, c.Name, c.Permissions, c.AppOrg.ID) } -//AppOrgGroup represents application organization group entity. It is a collection of users +// AppOrgGroup represents application organization group entity. It is a collection of users type AppOrgGroup struct { ID string Name string @@ -160,7 +160,7 @@ type AppOrgGroup struct { DateUpdated *time.Time } -//CheckAssigners checks if the passed permissions satisfy the needed assigners for the group +// CheckAssigners checks if the passed permissions satisfy the needed assigners for the group func (cg AppOrgGroup) CheckAssigners(assignerPermissions []string) error { //check permission if len(cg.Permissions) > 0 { @@ -184,7 +184,7 @@ func (cg AppOrgGroup) CheckAssigners(assignerPermissions []string) error { return nil } -//GetAssignedPermissionNames returns a list of names of assigned permissions for this group +// GetAssignedPermissionNames returns a list of names of assigned permissions for this group func (cg AppOrgGroup) GetAssignedPermissionNames() []string { names := make([]string, len(cg.Permissions)) for i, permission := range cg.Permissions { @@ -193,7 +193,7 @@ func (cg AppOrgGroup) GetAssignedPermissionNames() []string { return names } -//GetAssignedRoleIDs returns a list of ids of assigned roles for this group +// GetAssignedRoleIDs returns a list of ids of assigned roles for this group func (cg AppOrgGroup) GetAssignedRoleIDs() []string { ids := make([]string, len(cg.Roles)) for i, role := range cg.Roles { @@ -206,7 +206,7 @@ func (cg AppOrgGroup) String() string { return fmt.Sprintf("[ID:%s\nName:%s\nAppOrg:%s]", cg.ID, cg.Name, cg.AppOrg.ID) } -//Application represents users application entity - safer community, uuic, etc +// Application represents users application entity - safer community, uuic, etc type Application struct { ID string Name string //safer community, uuic, etc @@ -227,7 +227,7 @@ type Application struct { DateUpdated *time.Time } -//FindApplicationType finds app type +// FindApplicationType finds app type func (a Application) FindApplicationType(id string) *ApplicationType { for _, appType := range a.Types { if appType.Identifier == id || appType.ID == id { @@ -237,7 +237,7 @@ func (a Application) FindApplicationType(id string) *ApplicationType { return nil } -//Organization represents organization entity +// Organization represents organization entity type Organization struct { ID string Name string @@ -257,7 +257,7 @@ func (c Organization) String() string { return fmt.Sprintf("[ID:%s\tName:%s\tType:%s\tConfig:%s]", c.ID, c.Name, c.Type, c.Config) } -//ApplicationOrganization represents application organization entity +// ApplicationOrganization represents application organization entity type ApplicationOrganization struct { ID string @@ -276,7 +276,7 @@ type ApplicationOrganization struct { DateUpdated *time.Time } -//FindIdentityProviderSetting finds the identity provider setting for the application +// FindIdentityProviderSetting finds the identity provider setting for the application func (ao ApplicationOrganization) FindIdentityProviderSetting(identityProviderID string) *IdentityProviderSetting { for _, idPrSetting := range ao.IdentityProvidersSettings { if idPrSetting.IdentityProviderID == identityProviderID { @@ -286,7 +286,7 @@ func (ao ApplicationOrganization) FindIdentityProviderSetting(identityProviderID return nil } -//IsAuthTypeSupported checks if an auth type is supported for application type +// IsAuthTypeSupported checks if an auth type is supported for application type func (ao ApplicationOrganization) IsAuthTypeSupported(appType ApplicationType, authType AuthType) bool { for _, sat := range ao.SupportedAuthTypes { if sat.AppTypeID == appType.ID { @@ -300,15 +300,16 @@ func (ao ApplicationOrganization) IsAuthTypeSupported(appType ApplicationType, a return false } -//IdentityProviderSetting represents identity provider setting for an organization in an application -// User specific fields -// For example: -// UIUC Application has uiucedu_uin specific field for Illinois identity provider +// IdentityProviderSetting represents identity provider setting for an organization in an application // -// Groups mapping: maps an identity provider groups to application groups -// For example: -// for the UIUC application the Illinois group "urn:mace:uiuc.edu:urbana:authman:app-rokwire-service-policy-rokwire groups access" is mapped to an application group called "groups access" -// for the Safer Illinois application the Illinois group "urn:mace:uiuc.edu:urbana:authman:app-rokwire-service-policy-rokwire health test verify" is mapped to an application group called "tests verifiers" +// User specific fields +// For example: +// UIUC Application has uiucedu_uin specific field for Illinois identity provider +// +// Groups mapping: maps an identity provider groups to application groups +// For example: +// for the UIUC application the Illinois group "urn:mace:uiuc.edu:urbana:authman:app-rokwire-service-policy-rokwire groups access" is mapped to an application group called "groups access" +// for the Safer Illinois application the Illinois group "urn:mace:uiuc.edu:urbana:authman:app-rokwire-service-policy-rokwire health test verify" is mapped to an application group called "tests verifiers" type IdentityProviderSetting struct { IdentityProviderID string `bson:"identity_provider_id"` @@ -328,7 +329,7 @@ type IdentityProviderSetting struct { Groups map[string]string `bson:"groups"` //map[identity_provider_group]app_group_id } -//LoginsSessionsSetting represents logins sessions setting for an organization in an application +// LoginsSessionsSetting represents logins sessions setting for an organization in an application type LoginsSessionsSetting struct { MaxConcurrentSessions int `bson:"max_concurrent_sessions"` @@ -337,19 +338,19 @@ type LoginsSessionsSetting struct { YearlyExpirePolicy YearlyExpirePolicy `bson:"yearly_expire_policy"` } -//InactivityExpirePolicy represents expires policy based on inactivity +// InactivityExpirePolicy represents expires policy based on inactivity type InactivityExpirePolicy struct { Active bool `bson:"active"` InactivityPeriod int `bson:"inactivity_period"` //in minutes } -//TSLExpirePolicy represents expires policy based on the time since login +// TSLExpirePolicy represents expires policy based on the time since login type TSLExpirePolicy struct { Active bool `bson:"active"` TimeSinceLoginPeriod int `bson:"time_since_login_period"` //in minutes } -//YearlyExpirePolicy represents expires policy based on fixed date +// YearlyExpirePolicy represents expires policy based on fixed date type YearlyExpirePolicy struct { Active bool `bson:"active"` Day int `bson:"day"` @@ -358,7 +359,7 @@ type YearlyExpirePolicy struct { Min int `bson:"min"` } -//ApplicationType represents users application type entity - safer community android, safer community ios, safer community web, uuic android etc +// ApplicationType represents users application type entity - safer community android, safer community ios, safer community web, uuic android etc type ApplicationType struct { ID string Identifier string //edu.illinois.rokwire etc @@ -368,7 +369,7 @@ type ApplicationType struct { Application Application } -//AuthTypesSupport represents supported auth types for an organization in an application type with configs/params +// AuthTypesSupport represents supported auth types for an organization in an application type with configs/params type AuthTypesSupport struct { AppTypeID string `bson:"app_type_id"` @@ -378,7 +379,7 @@ type AuthTypesSupport struct { } `bson:"supported_auth_types"` } -//ApplicationConfig represents app configs +// ApplicationConfig represents app configs type ApplicationConfig struct { ID string ApplicationType ApplicationType @@ -400,7 +401,7 @@ type Version struct { DateUpdated *time.Time } -//VersionNumbers represents app config version numbers +// VersionNumbers represents app config version numbers type VersionNumbers struct { Major int `json:"major" bson:"major"` Minor int `json:"minor" bson:"minor"` @@ -433,7 +434,7 @@ func (v VersionNumbers) LessThanOrEqualTo(v1 *VersionNumbers) bool { return false } -//VersionNumbersFromString parses a string into a VersionNumbers struct. Returns nil if invalid format. +// VersionNumbersFromString parses a string into a VersionNumbers struct. Returns nil if invalid format. func VersionNumbersFromString(version string) *VersionNumbers { parts := strings.Split(version, ".") if len(parts) != 3 { @@ -456,65 +457,56 @@ func VersionNumbersFromString(version string) *VersionNumbers { return &VersionNumbers{Major: major, Minor: minor, Patch: patch} } -//GetMissingPermissionNames returns a list of permission names missing from items -func GetMissingPermissionNames(items []Permission, names []string) ([]string, error) { - if len(items) != len(names) { - badNames := make([]string, 0) - for _, name := range names { - bad := true - for _, e := range items { - if e.Name == name { - bad = false - break - } - } - if bad { - badNames = append(badNames, name) +// GetMissingPermissionNames returns a list of permission names missing from items +func GetMissingPermissionNames(items []Permission, names []string) []string { + missingNames := make([]string, 0) + for _, name := range names { + missing := true + for _, e := range items { + if e.Name == name { + missing = false + break } } - return nil, errors.ErrorData(logutils.StatusInvalid, TypePermission, &logutils.FieldArgs{"names": badNames}) + if missing { + missingNames = append(missingNames, name) + } } - return nil, nil -} - -//GetMissingRoleIDs returns a list of role IDs missing from items -func GetMissingRoleIDs(items []AppOrgRole, ids []string) ([]string, error) { - if len(items) != len(ids) { - badIDs := make([]string, 0) - for _, id := range ids { - bad := true - for _, e := range items { - if e.ID == id { - bad = false - break - } - } - if bad { - badIDs = append(badIDs, id) + return missingNames +} + +// GetMissingRoleIDs returns a list of role IDs missing from items +func GetMissingRoleIDs(items []AppOrgRole, ids []string) []string { + missingIDs := make([]string, 0) + for _, id := range ids { + missing := true + for _, e := range items { + if e.ID == id { + missing = false + break } } - return nil, errors.ErrorData(logutils.StatusInvalid, TypeAppOrgRole, &logutils.FieldArgs{"ids": badIDs}) + if missing { + missingIDs = append(missingIDs, id) + } } - return nil, nil -} - -//GetMissingGroupIDs returns a list of group IDs missing from items -func GetMissingGroupIDs(items []AppOrgGroup, ids []string) ([]string, error) { - if len(items) != len(ids) { - badIDs := make([]string, 0) - for _, id := range ids { - bad := true - for _, e := range items { - if e.ID == id { - bad = false - break - } - } - if bad { - badIDs = append(badIDs, id) + return missingIDs +} + +// GetMissingGroupIDs returns a list of group IDs missing from items +func GetMissingGroupIDs(items []AppOrgGroup, ids []string) []string { + missingIDs := make([]string, 0) + for _, id := range ids { + missing := true + for _, e := range items { + if e.ID == id { + missing = false + break } } - return nil, errors.ErrorData(logutils.StatusInvalid, TypeAppOrgGroup, &logutils.FieldArgs{"ids": badIDs}) + if missing { + missingIDs = append(missingIDs, id) + } } - return nil, nil + return missingIDs } diff --git a/driven/storage/adapter.go b/driven/storage/adapter.go index 172042a41..050331b8b 100644 --- a/driven/storage/adapter.go +++ b/driven/storage/adapter.go @@ -34,7 +34,7 @@ import ( "gopkg.in/go-playground/validator.v9" ) -//Adapter implements the Storage interface +// Adapter implements the Storage interface type Adapter struct { db *database @@ -59,7 +59,7 @@ type Adapter struct { applicationConfigsLock *sync.RWMutex } -//Start starts the storage +// Start starts the storage func (sa *Adapter) Start() error { //start db err := sa.db.start() @@ -110,12 +110,12 @@ func (sa *Adapter) Start() error { return err } -//RegisterStorageListener registers a data change listener with the storage adapter +// RegisterStorageListener registers a data change listener with the storage adapter func (sa *Adapter) RegisterStorageListener(storageListener Listener) { sa.db.listeners = append(sa.db.listeners, storageListener) } -//PerformTransaction performs a transaction +// PerformTransaction performs a transaction func (sa *Adapter) PerformTransaction(transaction func(context TransactionContext) error) error { //TODO: may want to add timeout arg to PerformTransaction to be able to specify individual timeouts (mainly for slow operations) // transaction @@ -143,7 +143,7 @@ func (sa *Adapter) PerformTransaction(transaction func(context TransactionContex return err } -//cacheServiceRegs caches the service regs from the DB +// cacheServiceRegs caches the service regs from the DB func (sa *Adapter) cacheServiceRegs() error { sa.logger.Info("cacheServiceRegs..") @@ -237,7 +237,7 @@ func (sa *Adapter) processCachedServiceReg(key, item interface{}) (*model.Servic return &serviceReg, nil } -//cacheOrganizations caches the organizations from the DB +// cacheOrganizations caches the organizations from the DB func (sa *Adapter) cacheOrganizations() error { sa.logger.Info("cacheOrganizations..") @@ -310,7 +310,7 @@ func (sa *Adapter) getCachedOrganizations() ([]model.Organization, error) { return organizationList, err } -//cacheApplications caches the applications +// cacheApplications caches the applications func (sa *Adapter) cacheApplications() error { sa.logger.Info("cacheApplications..") @@ -414,7 +414,7 @@ func (sa *Adapter) getCachedApplicationType(id string) (*model.Application, *mod return nil, nil, errors.ErrorData(logutils.StatusMissing, model.TypeApplicationType, &logutils.FieldArgs{"id": id}) } -//cacheAuthTypes caches the auth types +// cacheAuthTypes caches the auth types func (sa *Adapter) cacheAuthTypes() error { sa.logger.Info("cacheAuthTypes..") @@ -494,7 +494,7 @@ func (sa *Adapter) getCachedAuthTypes() ([]model.AuthType, error) { return authTypeList, err } -//cacheApplicationsOrganizations caches the applications organizations +// cacheApplicationsOrganizations caches the applications organizations func (sa *Adapter) cacheApplicationsOrganizations() error { sa.logger.Info("cacheApplicationsOrganizations..") @@ -701,7 +701,7 @@ func (sa *Adapter) getCachedApplicationConfigByID(id string) (*model.Application return nil, errors.ErrorData(logutils.StatusMissing, model.TypeApplicationConfig, errArgs) } -//loadAuthTypes loads all auth types +// loadAuthTypes loads all auth types func (sa *Adapter) loadAuthTypes() ([]model.AuthType, error) { filter := bson.D{} var result []model.AuthType @@ -716,17 +716,17 @@ func (sa *Adapter) loadAuthTypes() ([]model.AuthType, error) { return result, nil } -//FindAuthType finds auth type by id or code +// FindAuthType finds auth type by id or code func (sa *Adapter) FindAuthType(codeOrID string) (*model.AuthType, error) { return sa.getCachedAuthType(codeOrID) } -//FindAuthTypes finds all auth types +// FindAuthTypes finds all auth types func (sa *Adapter) FindAuthTypes() ([]model.AuthType, error) { return sa.getCachedAuthTypes() } -//InsertLoginSession inserts login session +// InsertLoginSession inserts login session func (sa *Adapter) InsertLoginSession(context TransactionContext, session model.LoginSession) error { storageLoginSession := loginSessionToStorage(session) @@ -738,7 +738,7 @@ func (sa *Adapter) InsertLoginSession(context TransactionContext, session model. return nil } -//FindLoginSessions finds login sessions by identifier and sorts by date created +// FindLoginSessions finds login sessions by identifier and sorts by date created func (sa *Adapter) FindLoginSessions(context TransactionContext, identifier string) ([]model.LoginSession, error) { filter := bson.D{primitive.E{Key: "identifier", Value: identifier}} opts := options.Find() @@ -782,7 +782,7 @@ func (sa *Adapter) FindLoginSessions(context TransactionContext, identifier stri return sessions, nil } -//FindLoginSessionsByParams finds login sessions by params +// FindLoginSessionsByParams finds login sessions by params func (sa *Adapter) FindLoginSessionsByParams(appID string, orgID string, sessionID *string, identifier *string, accountAuthTypeIdentifier *string, appTypeID *string, appTypeIdentifier *string, anonymous *bool, deviceID *string, ipAddress *string) ([]model.LoginSession, error) { filter := bson.D{primitive.E{Key: "app_id", Value: appID}, @@ -846,7 +846,7 @@ func (sa *Adapter) FindLoginSessionsByParams(appID string, orgID string, session return loginSessions, nil } -//FindLoginSession finds a login session +// FindLoginSession finds a login session func (sa *Adapter) FindLoginSession(refreshToken string) (*model.LoginSession, error) { //find loggin session filter := bson.D{primitive.E{Key: "refresh_tokens", Value: refreshToken}} @@ -864,7 +864,7 @@ func (sa *Adapter) FindLoginSession(refreshToken string) (*model.LoginSession, e return sa.buildLoginSession(&loginSession) } -//FindAndUpdateLoginSession finds and updates a login session +// FindAndUpdateLoginSession finds and updates a login session func (sa *Adapter) FindAndUpdateLoginSession(context TransactionContext, id string) (*model.LoginSession, error) { //find loggin session filter := bson.D{primitive.E{Key: "_id", Value: id}} @@ -921,7 +921,7 @@ func (sa *Adapter) buildLoginSession(ls *loginSession) (*model.LoginSession, err return &modelLoginSession, nil } -//UpdateLoginSession updates login session +// UpdateLoginSession updates login session func (sa *Adapter) UpdateLoginSession(context TransactionContext, loginSession model.LoginSession) error { storageLoginSession := loginSessionToStorage(loginSession) @@ -934,7 +934,7 @@ func (sa *Adapter) UpdateLoginSession(context TransactionContext, loginSession m return nil } -//DeleteLoginSession deletes login session +// DeleteLoginSession deletes login session func (sa *Adapter) DeleteLoginSession(context TransactionContext, id string) error { filter := bson.M{"_id": id} @@ -948,7 +948,7 @@ func (sa *Adapter) DeleteLoginSession(context TransactionContext, id string) err return nil } -//DeleteLoginSessionsByIDs deletes login sessions by ids +// DeleteLoginSessionsByIDs deletes login sessions by ids func (sa *Adapter) DeleteLoginSessionsByIDs(transaction TransactionContext, ids []string) error { filter := bson.D{primitive.E{Key: "_id", Value: bson.M{"$in": ids}}} @@ -970,17 +970,17 @@ func (sa *Adapter) DeleteLoginSessionsByIDs(transaction TransactionContext, ids return nil } -//DeleteLoginSessionsByIdentifier deletes all login sessions with the identifier +// DeleteLoginSessionsByIdentifier deletes all login sessions with the identifier func (sa *Adapter) DeleteLoginSessionsByIdentifier(context TransactionContext, identifier string) error { return sa.deleteLoginSessions(context, "identifier", identifier, false) } -//DeleteLoginSessionByID deletes a login session by id +// DeleteLoginSessionByID deletes a login session by id func (sa *Adapter) DeleteLoginSessionByID(context TransactionContext, id string) error { return sa.deleteLoginSessions(context, "_id", id, true) } -//DeleteLoginSessionsByAccountAuthTypeID deletes login sessions by account auth type ID +// DeleteLoginSessionsByAccountAuthTypeID deletes login sessions by account auth type ID func (sa *Adapter) DeleteLoginSessionsByAccountAuthTypeID(context TransactionContext, id string) error { return sa.deleteLoginSessions(context, "account_auth_type_id", id, false) } @@ -998,7 +998,7 @@ func (sa *Adapter) deleteLoginSessions(context TransactionContext, key string, v return nil } -//DeleteLoginSessionsByAccountAndSessionID deletes all login sessions with the identifier and sessionID +// DeleteLoginSessionsByAccountAndSessionID deletes all login sessions with the identifier and sessionID func (sa *Adapter) DeleteLoginSessionsByAccountAndSessionID(context TransactionContext, identifier string, sessionID string) error { filter := bson.M{"identifier": identifier, "_id": sessionID} result, err := sa.db.loginsSessions.DeleteOne(filter, nil) @@ -1016,7 +1016,7 @@ func (sa *Adapter) DeleteLoginSessionsByAccountAndSessionID(context TransactionC return nil } -//DeleteMFAExpiredSessions deletes MFA expired sessions +// DeleteMFAExpiredSessions deletes MFA expired sessions func (sa *Adapter) DeleteMFAExpiredSessions() error { now := time.Now().UTC() @@ -1030,7 +1030,7 @@ func (sa *Adapter) DeleteMFAExpiredSessions() error { return nil } -//FindSessionsLazy finds all sessions for app/org but lazy filled. +// FindSessionsLazy finds all sessions for app/org but lazy filled. // - lazy means that we make only one request to the logins sessions collection and fill the objects with what we have there. // - i.e. we do not apply any relations // - this partly filled is enough for some cases(expiration policy checks for example) but in the same time it give very good performace @@ -1068,7 +1068,7 @@ func (sa *Adapter) FindSessionsLazy(appID string, orgID string) ([]model.LoginSe return sessions, nil } -//FindAccount finds an account for app, org, auth type and account auth type identifier +// FindAccount finds an account for app, org, auth type and account auth type identifier func (sa *Adapter) FindAccount(context TransactionContext, appOrgID string, authTypeID string, accountAuthTypeIdentifier string) (*model.Account, error) { filter := bson.D{primitive.E{Key: "app_org_id", Value: appOrgID}, primitive.E{Key: "auth_types.auth_type_id", Value: authTypeID}, @@ -1097,7 +1097,7 @@ func (sa *Adapter) FindAccount(context TransactionContext, appOrgID string, auth return &modelAccount, nil } -//FindAccounts finds accounts +// FindAccounts finds accounts func (sa *Adapter) FindAccounts(limit int, offset int, appID string, orgID string, accountID *string, firstName *string, lastName *string, authType *string, authTypeIdentifier *string, hasPermissions *bool, permissions []string, roleIDs []string, groupIDs []string) ([]model.Account, error) { //find app org id @@ -1162,7 +1162,7 @@ func (sa *Adapter) FindAccounts(limit int, offset int, appID string, orgID strin return accounts, nil } -//FindAccountsByAccountID finds accounts +// FindAccountsByAccountID finds accounts func (sa *Adapter) FindAccountsByAccountID(appID string, orgID string, accountIDs []string) ([]model.Account, error) { //find app org id @@ -1181,12 +1181,12 @@ func (sa *Adapter) FindAccountsByAccountID(appID string, orgID string, accountID return accounts, nil } -//FindAccountByID finds an account by id +// FindAccountByID finds an account by id func (sa *Adapter) FindAccountByID(context TransactionContext, id string) (*model.Account, error) { return sa.findAccount(context, "_id", id) } -//FindAccountByAuthTypeID finds an account by auth type id +// FindAccountByAuthTypeID finds an account by auth type id func (sa *Adapter) FindAccountByAuthTypeID(context TransactionContext, id string) (*model.Account, error) { return sa.findAccount(context, "auth_types.id", id) } @@ -1231,7 +1231,7 @@ func (sa *Adapter) findStorageAccount(context TransactionContext, key string, id return &account, nil } -//InsertAccount inserts an account +// InsertAccount inserts an account func (sa *Adapter) InsertAccount(context TransactionContext, account model.Account) (*model.Account, error) { storageAccount := accountToStorage(&account) @@ -1243,7 +1243,7 @@ func (sa *Adapter) InsertAccount(context TransactionContext, account model.Accou return &account, nil } -//SaveAccount saves an existing account +// SaveAccount saves an existing account func (sa *Adapter) SaveAccount(context TransactionContext, account *model.Account) error { if account == nil { return errors.ErrorData(logutils.StatusInvalid, logutils.TypeArg, logutils.StringArgs("account")) @@ -1260,7 +1260,7 @@ func (sa *Adapter) SaveAccount(context TransactionContext, account *model.Accoun return nil } -//DeleteAccount deletes an account +// DeleteAccount deletes an account func (sa *Adapter) DeleteAccount(context TransactionContext, id string) error { //TODO - we have to decide what we do on delete user operation - removing all user relations, (or) mark the user disabled etc @@ -1276,7 +1276,7 @@ func (sa *Adapter) DeleteAccount(context TransactionContext, id string) error { return nil } -//FindServiceAccount finds a service account by accountID, appID, and orgID +// FindServiceAccount finds a service account by accountID, appID, and orgID func (sa *Adapter) FindServiceAccount(context TransactionContext, accountID string, appID string, orgID string) (*model.ServiceAccount, error) { filter := bson.D{primitive.E{Key: "account_id", Value: accountID}, primitive.E{Key: "app_id", Value: appID}, primitive.E{Key: "org_id", Value: orgID}} @@ -1295,7 +1295,7 @@ func (sa *Adapter) FindServiceAccount(context TransactionContext, accountID stri return modelAccount, nil } -//FindServiceAccounts gets all service accounts matching a search +// FindServiceAccounts gets all service accounts matching a search func (sa *Adapter) FindServiceAccounts(params map[string]interface{}) ([]model.ServiceAccount, error) { filter := bson.D{} for k, v := range params { @@ -1318,7 +1318,7 @@ func (sa *Adapter) FindServiceAccounts(params map[string]interface{}) ([]model.S return modelAccounts, nil } -//InsertServiceAccount inserts a service account +// InsertServiceAccount inserts a service account func (sa *Adapter) InsertServiceAccount(account *model.ServiceAccount) error { if account == nil { return errors.ErrorData(logutils.StatusInvalid, model.TypeServiceAccount, nil) @@ -1334,7 +1334,7 @@ func (sa *Adapter) InsertServiceAccount(account *model.ServiceAccount) error { return nil } -//UpdateServiceAccount updates a service account +// UpdateServiceAccount updates a service account func (sa *Adapter) UpdateServiceAccount(account *model.ServiceAccount) (*model.ServiceAccount, error) { if account == nil { return nil, errors.ErrorData(logutils.StatusInvalid, model.TypeServiceAccount, nil) @@ -1369,7 +1369,7 @@ func (sa *Adapter) UpdateServiceAccount(account *model.ServiceAccount) (*model.S return modelAccount, nil } -//DeleteServiceAccount deletes a service account +// DeleteServiceAccount deletes a service account func (sa *Adapter) DeleteServiceAccount(accountID string, appID string, orgID string) error { filter := bson.D{primitive.E{Key: "account_id", Value: accountID}, primitive.E{Key: "app_id", Value: appID}, primitive.E{Key: "org_id", Value: orgID}} @@ -1388,7 +1388,7 @@ func (sa *Adapter) DeleteServiceAccount(accountID string, appID string, orgID st return nil } -//DeleteServiceAccounts deletes service accounts by accountID +// DeleteServiceAccounts deletes service accounts by accountID func (sa *Adapter) DeleteServiceAccounts(accountID string) error { filter := bson.D{primitive.E{Key: "account_id", Value: accountID}} @@ -1403,7 +1403,7 @@ func (sa *Adapter) DeleteServiceAccounts(accountID string) error { return nil } -//InsertServiceAccountCredential inserts a service account credential +// InsertServiceAccountCredential inserts a service account credential func (sa *Adapter) InsertServiceAccountCredential(accountID string, creds *model.ServiceAccountCredential) error { if creds == nil { return errors.ErrorData(logutils.StatusInvalid, logutils.TypeArg, logutils.StringArgs("credentials")) @@ -1433,7 +1433,7 @@ func (sa *Adapter) InsertServiceAccountCredential(accountID string, creds *model return nil } -//DeleteServiceAccountCredential deletes a service account credential +// DeleteServiceAccountCredential deletes a service account credential func (sa *Adapter) DeleteServiceAccountCredential(accountID string, credID string) error { filter := bson.D{primitive.E{Key: "account_id", Value: accountID}} update := bson.D{ @@ -1459,7 +1459,7 @@ func (sa *Adapter) DeleteServiceAccountCredential(accountID string, credID strin return nil } -//UpdateAccountPreferences updates account preferences +// UpdateAccountPreferences updates account preferences func (sa *Adapter) UpdateAccountPreferences(accountID string, preferences map[string]interface{}) error { filter := bson.D{primitive.E{Key: "_id", Value: accountID}} update := bson.D{ @@ -1479,7 +1479,7 @@ func (sa *Adapter) UpdateAccountPreferences(accountID string, preferences map[st return nil } -//InsertAccountPermissions inserts account permissions +// InsertAccountPermissions inserts account permissions func (sa *Adapter) InsertAccountPermissions(context TransactionContext, accountID string, permissions []model.Permission) error { filter := bson.D{primitive.E{Key: "_id", Value: accountID}} update := bson.D{ @@ -1503,7 +1503,7 @@ func (sa *Adapter) InsertAccountPermissions(context TransactionContext, accountI return nil } -//UpdateAccountPermissions updates account permissions +// UpdateAccountPermissions updates account permissions func (sa *Adapter) UpdateAccountPermissions(context TransactionContext, accountID string, hasPermissions bool, permissions []model.Permission) error { filter := bson.D{primitive.E{Key: "_id", Value: accountID}} update := bson.D{ @@ -1525,7 +1525,7 @@ func (sa *Adapter) UpdateAccountPermissions(context TransactionContext, accountI return nil } -//DeleteAccountPermissions deletes permissions from an account +// DeleteAccountPermissions deletes permissions from an account func (sa *Adapter) DeleteAccountPermissions(context TransactionContext, accountID string, hasPermissions bool, permissions []model.Permission) error { //filter filter := bson.D{primitive.E{Key: "_id", Value: accountID}} @@ -1555,7 +1555,7 @@ func (sa *Adapter) DeleteAccountPermissions(context TransactionContext, accountI return nil } -//InsertAccountRoles inserts account roles +// InsertAccountRoles inserts account roles func (sa *Adapter) InsertAccountRoles(context TransactionContext, accountID string, appOrgID string, roles []model.AccountRole) error { stgRoles := accountRolesToStorage(roles) @@ -1582,7 +1582,7 @@ func (sa *Adapter) InsertAccountRoles(context TransactionContext, accountID stri return nil } -//InsertAccountGroups inserts account groups +// InsertAccountGroups inserts account groups func (sa *Adapter) InsertAccountGroups(context TransactionContext, accountID string, appOrgID string, groups []model.AccountGroup) error { stgGroups := accountGroupsToStorage(groups) @@ -1609,7 +1609,7 @@ func (sa *Adapter) InsertAccountGroups(context TransactionContext, accountID str return nil } -//InsertAccountsGroup inserts accounts into a group +// InsertAccountsGroup inserts accounts into a group func (sa *Adapter) InsertAccountsGroup(group model.AccountGroup, accounts []model.Account) error { //prepare filter accountsIDs := make([]string, len(accounts)) @@ -1638,7 +1638,7 @@ func (sa *Adapter) InsertAccountsGroup(group model.AccountGroup, accounts []mode return nil } -//RemoveAccountsGroup removes accounts from a group +// RemoveAccountsGroup removes accounts from a group func (sa *Adapter) RemoveAccountsGroup(groupID string, accounts []model.Account, hasPermissions []bool) error { //split accounts list by admin status standardAccountIDs := make([]string, 0) @@ -1664,7 +1664,7 @@ func (sa *Adapter) RemoveAccountsGroup(groupID string, accounts []model.Account, return nil } -//RemoveAccountsGroup removes accounts from a group +// RemoveAccountsGroup removes accounts from a group func (sa *Adapter) removeAccountsFromGroup(groupID string, accountIDs []string, hasPermissions bool) error { if len(accountIDs) == 0 { return nil @@ -1690,7 +1690,7 @@ func (sa *Adapter) removeAccountsFromGroup(groupID string, accountIDs []string, return nil } -//UpdateAccountRoles updates the account roles +// UpdateAccountRoles updates the account roles func (sa *Adapter) UpdateAccountRoles(context TransactionContext, accountID string, hasPermissions bool, roles []model.AccountRole) error { stgRoles := accountRolesToStorage(roles) @@ -1714,7 +1714,7 @@ func (sa *Adapter) UpdateAccountRoles(context TransactionContext, accountID stri return nil } -//DeleteAccountRoles deletes account roles +// DeleteAccountRoles deletes account roles func (sa *Adapter) DeleteAccountRoles(context TransactionContext, accountID string, hasPermissions bool, roleIDs []string) error { //filter filter := bson.D{primitive.E{Key: "_id", Value: accountID}} @@ -1740,7 +1740,7 @@ func (sa *Adapter) DeleteAccountRoles(context TransactionContext, accountID stri return nil } -//UpdateAccountGroups updates the account groups +// UpdateAccountGroups updates the account groups func (sa *Adapter) UpdateAccountGroups(context TransactionContext, accountID string, hasPermissions bool, groups []model.AccountGroup) error { stgGroups := accountGroupsToStorage(groups) @@ -1764,7 +1764,7 @@ func (sa *Adapter) UpdateAccountGroups(context TransactionContext, accountID str return nil } -//InsertAccountAuthType inserts am account auth type +// InsertAccountAuthType inserts am account auth type func (sa *Adapter) InsertAccountAuthType(item model.AccountAuthType) error { storageItem := accountAuthTypeToStorage(item) @@ -1787,7 +1787,7 @@ func (sa *Adapter) InsertAccountAuthType(item model.AccountAuthType) error { return nil } -//UpdateAccountAuthType updates account auth type +// UpdateAccountAuthType updates account auth type func (sa *Adapter) UpdateAccountAuthType(item model.AccountAuthType) error { // transaction err := sa.db.dbClient.UseSession(context.Background(), func(sessionContext mongo.SessionContext) error { @@ -1853,7 +1853,7 @@ func (sa *Adapter) UpdateAccountAuthType(item model.AccountAuthType) error { return nil } -//DeleteAccountAuthType deletes an account auth type +// DeleteAccountAuthType deletes an account auth type func (sa *Adapter) DeleteAccountAuthType(context TransactionContext, item model.AccountAuthType) error { filter := bson.M{"_id": item.Account.ID} update := bson.D{ @@ -1873,7 +1873,7 @@ func (sa *Adapter) DeleteAccountAuthType(context TransactionContext, item model. return nil } -//UpdateAccountExternalIDs updates account external IDs +// UpdateAccountExternalIDs updates account external IDs func (sa *Adapter) UpdateAccountExternalIDs(accountID string, externalIDs map[string]string) error { filter := bson.D{primitive.E{Key: "_id", Value: accountID}} now := time.Now().UTC() @@ -1895,7 +1895,7 @@ func (sa *Adapter) UpdateAccountExternalIDs(accountID string, externalIDs map[st return nil } -//UpdateLoginSessionExternalIDs updates login session external IDs +// UpdateLoginSessionExternalIDs updates login session external IDs func (sa *Adapter) UpdateLoginSessionExternalIDs(accountID string, externalIDs map[string]string) error { filter := bson.D{primitive.E{Key: "identifier", Value: accountID}} now := time.Now().UTC() @@ -1914,7 +1914,7 @@ func (sa *Adapter) UpdateLoginSessionExternalIDs(accountID string, externalIDs m return nil } -//CountAccountsByRoleID counts how many accounts there are with the passed role id +// CountAccountsByRoleID counts how many accounts there are with the passed role id func (sa *Adapter) CountAccountsByRoleID(roleID string) (*int64, error) { filter := bson.D{primitive.E{Key: "roles._id", Value: roleID}} @@ -1925,7 +1925,7 @@ func (sa *Adapter) CountAccountsByRoleID(roleID string) (*int64, error) { return &count, nil } -//CountAccountsByGroupID counts how many accounts there are with the passed group id +// CountAccountsByGroupID counts how many accounts there are with the passed group id func (sa *Adapter) CountAccountsByGroupID(groupID string) (*int64, error) { filter := bson.D{primitive.E{Key: "groups._id", Value: groupID}} @@ -1936,7 +1936,7 @@ func (sa *Adapter) CountAccountsByGroupID(groupID string) (*int64, error) { return &count, nil } -//FindCredential finds a credential by ID +// FindCredential finds a credential by ID func (sa *Adapter) FindCredential(context TransactionContext, ID string) (*model.Credential, error) { filter := bson.D{primitive.E{Key: "_id", Value: ID}} @@ -1953,7 +1953,7 @@ func (sa *Adapter) FindCredential(context TransactionContext, ID string) (*model return &modelCreds, nil } -//InsertCredential inserts a set of credential +// InsertCredential inserts a set of credential func (sa *Adapter) InsertCredential(context TransactionContext, creds *model.Credential) error { storageCreds := credentialToStorage(creds) @@ -1969,7 +1969,7 @@ func (sa *Adapter) InsertCredential(context TransactionContext, creds *model.Cre return nil } -//UpdateCredential updates a set of credentials +// UpdateCredential updates a set of credentials func (sa *Adapter) UpdateCredential(context TransactionContext, creds *model.Credential) error { storageCreds := credentialToStorage(creds) @@ -1986,7 +1986,7 @@ func (sa *Adapter) UpdateCredential(context TransactionContext, creds *model.Cre return nil } -//UpdateCredentialValue updates the value in credentials collection +// UpdateCredentialValue updates the value in credentials collection func (sa *Adapter) UpdateCredentialValue(ID string, value map[string]interface{}) error { filter := bson.D{primitive.E{Key: "_id", Value: ID}} update := bson.D{ @@ -2006,7 +2006,7 @@ func (sa *Adapter) UpdateCredentialValue(ID string, value map[string]interface{} return nil } -//DeleteCredential deletes a credential +// DeleteCredential deletes a credential func (sa *Adapter) DeleteCredential(context TransactionContext, ID string) error { filter := bson.D{primitive.E{Key: "_id", Value: ID}} @@ -2021,7 +2021,7 @@ func (sa *Adapter) DeleteCredential(context TransactionContext, ID string) error return nil } -//FindMFAType finds one MFA type for an account +// FindMFAType finds one MFA type for an account func (sa *Adapter) FindMFAType(context TransactionContext, accountID string, identifier string, mfaType string) (*model.MFAType, error) { filter := bson.D{ primitive.E{Key: "_id", Value: accountID}, @@ -2045,7 +2045,7 @@ func (sa *Adapter) FindMFAType(context TransactionContext, accountID string, ide return nil, errors.ErrorData(logutils.StatusMissing, model.TypeMFAType, nil) } -//FindMFATypes finds all MFA types for an account +// FindMFATypes finds all MFA types for an account func (sa *Adapter) FindMFATypes(accountID string) ([]model.MFAType, error) { filter := bson.D{primitive.E{Key: "_id", Value: accountID}} @@ -2058,7 +2058,7 @@ func (sa *Adapter) FindMFATypes(accountID string) ([]model.MFAType, error) { return mfaTypesFromStorage(account.MFATypes), nil } -//InsertMFAType inserts a MFA type +// InsertMFAType inserts a MFA type func (sa *Adapter) InsertMFAType(context TransactionContext, mfa *model.MFAType, accountID string) error { if mfa == nil { return errors.ErrorData(logutils.StatusMissing, model.TypeMFAType, nil) @@ -2093,7 +2093,7 @@ func (sa *Adapter) InsertMFAType(context TransactionContext, mfa *model.MFAType, return nil } -//UpdateMFAType updates one MFA type +// UpdateMFAType updates one MFA type func (sa *Adapter) UpdateMFAType(context TransactionContext, mfa *model.MFAType, accountID string) error { if mfa.Params == nil || mfa.Params["identifier"] == nil { return errors.ErrorData(logutils.StatusMissing, "mfa identifier", nil) @@ -2127,7 +2127,7 @@ func (sa *Adapter) UpdateMFAType(context TransactionContext, mfa *model.MFAType, return nil } -//DeleteMFAType deletes a MFA type +// DeleteMFAType deletes a MFA type func (sa *Adapter) DeleteMFAType(context TransactionContext, accountID string, identifier string, mfaType string) error { filter := bson.D{primitive.E{Key: "_id", Value: accountID}} update := bson.D{ @@ -2153,7 +2153,7 @@ func (sa *Adapter) DeleteMFAType(context TransactionContext, accountID string, i return nil } -//FindPermissions finds a set of permissions +// FindPermissions finds a set of permissions func (sa *Adapter) FindPermissions(context TransactionContext, ids []string) ([]model.Permission, error) { if len(ids) == 0 { return []model.Permission{}, nil @@ -2169,7 +2169,7 @@ func (sa *Adapter) FindPermissions(context TransactionContext, ids []string) ([] return permissionsResult, nil } -//FindPermissionsByServiceIDs finds permissions +// FindPermissionsByServiceIDs finds permissions func (sa *Adapter) FindPermissionsByServiceIDs(serviceIDs []string) ([]model.Permission, error) { if len(serviceIDs) == 0 { return nil, nil @@ -2185,7 +2185,7 @@ func (sa *Adapter) FindPermissionsByServiceIDs(serviceIDs []string) ([]model.Per return permissionsResult, nil } -//FindPermissionsByName finds a set of permissions +// FindPermissionsByName finds a set of permissions func (sa *Adapter) FindPermissionsByName(context TransactionContext, names []string) ([]model.Permission, error) { if len(names) == 0 { return []model.Permission{}, nil @@ -2201,7 +2201,7 @@ func (sa *Adapter) FindPermissionsByName(context TransactionContext, names []str return permissionsResult, nil } -//InsertPermission inserts a new permission +// InsertPermission inserts a new permission func (sa *Adapter) InsertPermission(context TransactionContext, permission model.Permission) error { _, err := sa.db.permissions.InsertOneWithContext(context, permission) if err != nil { @@ -2210,7 +2210,7 @@ func (sa *Adapter) InsertPermission(context TransactionContext, permission model return nil } -//UpdatePermission updates permission +// UpdatePermission updates permission func (sa *Adapter) UpdatePermission(context TransactionContext, item model.Permission) error { //TODO //This will be slow operation as we keep a copy of the entity in the users collection without index. @@ -2248,11 +2248,17 @@ func (sa *Adapter) updatePermission(context TransactionContext, item model.Permi // update all roles that have the permission key := "permissions.name" roles, err := sa.findAppOrgRoles(context, &key, item.Name, "") + if err != nil { + return errors.WrapErrorAction(logutils.ActionFind, model.TypeAppOrgRole, nil, err) + } for _, r := range roles { for pidx, p := range r.Permissions { if p.Name == item.Name { r.Permissions[pidx] = item err = sa.UpdateAppOrgRole(context, r) + if err != nil { + return errors.WrapErrorAction(logutils.ActionUpdate, model.TypeAppOrgRole, nil, err) + } break } } @@ -2260,11 +2266,17 @@ func (sa *Adapter) updatePermission(context TransactionContext, item model.Permi // update all groups that have the permission groups, err := sa.findAppOrgGroups(context, &key, item.Name, "") + if err != nil { + return errors.WrapErrorAction(logutils.ActionFind, model.TypeAppOrgGroup, nil, err) + } for _, g := range groups { for pidx, p := range g.Permissions { if p.Name == item.Name { g.Permissions[pidx] = item err = sa.UpdateAppOrgGroup(context, g) + if err != nil { + return errors.WrapErrorAction(logutils.ActionUpdate, model.TypeAppOrgGroup, nil, err) + } break } } @@ -2296,7 +2308,7 @@ func (sa *Adapter) updatePermission(context TransactionContext, item model.Permi return nil } -//DeletePermission deletes permission +// DeletePermission deletes permission func (sa *Adapter) DeletePermission(id string) error { //TODO //This will be slow operation as we keep a copy of the entity in the users collection without index. @@ -2304,12 +2316,12 @@ func (sa *Adapter) DeletePermission(id string) error { return errors.New(logutils.Unimplemented) } -//FindAppOrgRoles finds all application organization roles fora given AppOrg ID +// FindAppOrgRoles finds all application organization roles fora given AppOrg ID func (sa *Adapter) FindAppOrgRoles(appOrgID string) ([]model.AppOrgRole, error) { return sa.findAppOrgRoles(nil, nil, "", appOrgID) } -//FindAppOrgRolesByIDs finds a set of application organization roles for the provided IDs +// FindAppOrgRolesByIDs finds a set of application organization roles for the provided IDs func (sa *Adapter) FindAppOrgRolesByIDs(context TransactionContext, ids []string, appOrgID string) ([]model.AppOrgRole, error) { if len(ids) == 0 { return []model.AppOrgRole{}, nil @@ -2336,7 +2348,7 @@ func (sa *Adapter) FindAppOrgRolesByIDs(context TransactionContext, ids []string return result, nil } -//FindAppOrgRole finds an application organization role +// FindAppOrgRole finds an application organization role func (sa *Adapter) FindAppOrgRole(id string, appOrgID string) (*model.AppOrgRole, error) { filter := bson.D{primitive.E{Key: "_id", Value: id}, primitive.E{Key: "app_org_id", Value: appOrgID}} var rolesResult []appOrgRole @@ -2391,7 +2403,7 @@ func (sa *Adapter) findAppOrgRoles(context TransactionContext, key *string, id s return result, nil } -//InsertAppOrgRole inserts a new application organization role +// InsertAppOrgRole inserts a new application organization role func (sa *Adapter) InsertAppOrgRole(context TransactionContext, item model.AppOrgRole) error { role := appOrgRoleToStorage(item) _, err := sa.db.applicationsOrganizationsRoles.InsertOneWithContext(context, role) @@ -2401,7 +2413,7 @@ func (sa *Adapter) InsertAppOrgRole(context TransactionContext, item model.AppOr return nil } -//UpdateAppOrgRole updates application organization role +// UpdateAppOrgRole updates application organization role func (sa *Adapter) UpdateAppOrgRole(context TransactionContext, item model.AppOrgRole) error { if context == nil { transaction := func(newContext TransactionContext) error { @@ -2437,11 +2449,17 @@ func (sa *Adapter) updateAppOrgRole(context TransactionContext, item model.AppOr // update all groups that have the role key := "roles._id" groups, err := sa.findAppOrgGroups(context, &key, item.ID, item.AppOrg.ID) + if err != nil { + return errors.WrapErrorAction(logutils.ActionFind, model.TypeAppOrgGroup, nil, err) + } for _, g := range groups { for ridx, r := range g.Roles { if r.ID == item.ID { g.Roles[ridx] = item err = sa.UpdateAppOrgGroup(context, g) + if err != nil { + return errors.WrapErrorAction(logutils.ActionUpdate, model.TypeAppOrgGroup, nil, err) + } break } } @@ -2470,9 +2488,9 @@ func (sa *Adapter) updateAppOrgRole(context TransactionContext, item model.AppOr return nil } -//DeleteAppOrgRole deletes application organization role -// - make sure to call this function once you have verified that there is no any relations -// in other collections for the role which is supposed to be deleted. +// DeleteAppOrgRole deletes application organization role +// - make sure to call this function once you have verified that there is no any relations +// in other collections for the role which is supposed to be deleted. func (sa *Adapter) DeleteAppOrgRole(id string) error { filter := bson.M{"_id": id} result, err := sa.db.applicationsOrganizationsRoles.DeleteOne(filter, nil) @@ -2489,7 +2507,7 @@ func (sa *Adapter) DeleteAppOrgRole(id string) error { return nil } -//InsertAppOrgRolePermissions inserts permissions to role +// InsertAppOrgRolePermissions inserts permissions to role func (sa *Adapter) InsertAppOrgRolePermissions(context TransactionContext, roleID string, permissions []model.Permission) error { filter := bson.D{primitive.E{Key: "_id", Value: roleID}} @@ -2510,12 +2528,12 @@ func (sa *Adapter) InsertAppOrgRolePermissions(context TransactionContext, roleI return nil } -//FindAppOrgGroups finds all application organization groups for the provided AppOrg ID +// FindAppOrgGroups finds all application organization groups for the provided AppOrg ID func (sa *Adapter) FindAppOrgGroups(appOrgID string) ([]model.AppOrgGroup, error) { return sa.findAppOrgGroups(nil, nil, "", appOrgID) } -//FindAppOrgGroupsByIDs finds a set of application organization groups for the provided IDs +// FindAppOrgGroupsByIDs finds a set of application organization groups for the provided IDs func (sa *Adapter) FindAppOrgGroupsByIDs(context TransactionContext, ids []string, appOrgID string) ([]model.AppOrgGroup, error) { if len(ids) == 0 { return []model.AppOrgGroup{}, nil @@ -2541,7 +2559,7 @@ func (sa *Adapter) FindAppOrgGroupsByIDs(context TransactionContext, ids []strin return result, nil } -//FindAppOrgGroup finds a application organization group +// FindAppOrgGroup finds a application organization group func (sa *Adapter) FindAppOrgGroup(id string, appOrgID string) (*model.AppOrgGroup, error) { filter := bson.D{primitive.E{Key: "_id", Value: id}, primitive.E{Key: "app_org_id", Value: appOrgID}} var groupsResult []appOrgGroup @@ -2596,7 +2614,7 @@ func (sa *Adapter) findAppOrgGroups(context TransactionContext, key *string, id return result, nil } -//InsertAppOrgGroup inserts a new application organization group +// InsertAppOrgGroup inserts a new application organization group func (sa *Adapter) InsertAppOrgGroup(context TransactionContext, item model.AppOrgGroup) error { group := appOrgGroupToStorage(item) @@ -2607,7 +2625,7 @@ func (sa *Adapter) InsertAppOrgGroup(context TransactionContext, item model.AppO return nil } -//UpdateAppOrgGroup updates application organization group +// UpdateAppOrgGroup updates application organization group func (sa *Adapter) UpdateAppOrgGroup(context TransactionContext, item model.AppOrgGroup) error { if context == nil { transaction := func(newContext TransactionContext) error { @@ -2667,9 +2685,9 @@ func (sa *Adapter) updateAppOrgGroup(context TransactionContext, item model.AppO return nil } -//DeleteAppOrgGroup deletes application organization group -// - make sure to call this function once you have verified that there is no any relations -// in other collections for the group which is supposed to be deleted. +// DeleteAppOrgGroup deletes application organization group +// - make sure to call this function once you have verified that there is no any relations +// in other collections for the group which is supposed to be deleted. func (sa *Adapter) DeleteAppOrgGroup(id string) error { filter := bson.M{"_id": id} result, err := sa.db.applicationsOrganizationsGroups.DeleteOne(filter, nil) @@ -2687,7 +2705,7 @@ func (sa *Adapter) DeleteAppOrgGroup(id string) error { return nil } -//CountGroupsByRoleID counts how many groups there are with the passed role id +// CountGroupsByRoleID counts how many groups there are with the passed role id func (sa *Adapter) CountGroupsByRoleID(roleID string) (*int64, error) { filter := bson.D{primitive.E{Key: "roles._id", Value: roleID}} @@ -2698,7 +2716,7 @@ func (sa *Adapter) CountGroupsByRoleID(roleID string) (*int64, error) { return &count, nil } -//LoadAPIKeys finds all api key documents in the DB +// LoadAPIKeys finds all api key documents in the DB func (sa *Adapter) LoadAPIKeys() ([]model.APIKey, error) { filter := bson.D{} var result []model.APIKey @@ -2710,7 +2728,7 @@ func (sa *Adapter) LoadAPIKeys() ([]model.APIKey, error) { return result, nil } -//InsertAPIKey inserts an API key +// InsertAPIKey inserts an API key func (sa *Adapter) InsertAPIKey(context TransactionContext, apiKey model.APIKey) (*model.APIKey, error) { _, err := sa.db.apiKeys.InsertOneWithContext(context, apiKey) if err != nil { @@ -2719,7 +2737,7 @@ func (sa *Adapter) InsertAPIKey(context TransactionContext, apiKey model.APIKey) return &apiKey, nil } -//UpdateAPIKey updates the API key in storage +// UpdateAPIKey updates the API key in storage func (sa *Adapter) UpdateAPIKey(apiKey model.APIKey) error { filter := bson.M{"_id": apiKey.ID} err := sa.db.apiKeys.ReplaceOne(filter, apiKey, nil) @@ -2730,7 +2748,7 @@ func (sa *Adapter) UpdateAPIKey(apiKey model.APIKey) error { return nil } -//DeleteAPIKey deletes the API key from storage +// DeleteAPIKey deletes the API key from storage func (sa *Adapter) DeleteAPIKey(ID string) error { filter := bson.M{"_id": ID} result, err := sa.db.apiKeys.DeleteOne(filter, nil) @@ -2748,7 +2766,7 @@ func (sa *Adapter) DeleteAPIKey(ID string) error { return nil } -//LoadIdentityProviders finds all identity providers documents in the DB +// LoadIdentityProviders finds all identity providers documents in the DB func (sa *Adapter) LoadIdentityProviders() ([]model.IdentityProvider, error) { filter := bson.D{} var result []model.IdentityProvider @@ -2764,7 +2782,7 @@ func (sa *Adapter) LoadIdentityProviders() ([]model.IdentityProvider, error) { } -//UpdateProfile updates a profile +// UpdateProfile updates a profile func (sa *Adapter) UpdateProfile(context TransactionContext, profile model.Profile) error { filter := bson.D{primitive.E{Key: "profile.id", Value: profile.ID}} @@ -2794,7 +2812,7 @@ func (sa *Adapter) UpdateProfile(context TransactionContext, profile model.Profi return nil } -//FindProfiles finds profiles by app id, authtype id and account auth type identifier +// FindProfiles finds profiles by app id, authtype id and account auth type identifier func (sa *Adapter) FindProfiles(appID string, authTypeID string, accountAuthTypeIdentifier string) ([]model.Profile, error) { pipeline := []bson.M{ {"$lookup": bson.M{ @@ -2819,7 +2837,7 @@ func (sa *Adapter) FindProfiles(appID string, authTypeID string, accountAuthType return result, nil } -//CreateGlobalConfig creates global config +// CreateGlobalConfig creates global config func (sa *Adapter) CreateGlobalConfig(context TransactionContext, globalConfig *model.GlobalConfig) error { if globalConfig == nil { return errors.ErrorData(logutils.StatusInvalid, logutils.TypeArg, logutils.StringArgs("global_config")) @@ -2833,7 +2851,7 @@ func (sa *Adapter) CreateGlobalConfig(context TransactionContext, globalConfig * return nil } -//GetGlobalConfig give config +// GetGlobalConfig give config func (sa *Adapter) GetGlobalConfig() (*model.GlobalConfig, error) { filter := bson.D{} var result []model.GlobalConfig @@ -2849,7 +2867,7 @@ func (sa *Adapter) GetGlobalConfig() (*model.GlobalConfig, error) { } -//DeleteGlobalConfig deletes the global configuration from storage +// DeleteGlobalConfig deletes the global configuration from storage func (sa *Adapter) DeleteGlobalConfig(context TransactionContext) error { delFilter := bson.D{} _, err := sa.db.globalConfig.DeleteManyWithContext(context, delFilter, nil) @@ -2860,12 +2878,12 @@ func (sa *Adapter) DeleteGlobalConfig(context TransactionContext) error { return nil } -//FindOrganization finds an organization +// FindOrganization finds an organization func (sa *Adapter) FindOrganization(id string) (*model.Organization, error) { return sa.getCachedOrganization(id) } -//FindSystemOrganization finds the system organization (only one) +// FindSystemOrganization finds the system organization (only one) func (sa *Adapter) FindSystemOrganization() (*model.Organization, error) { organizations, err := sa.getCachedOrganizations() if err != nil { @@ -2881,12 +2899,12 @@ func (sa *Adapter) FindSystemOrganization() (*model.Organization, error) { return nil, nil } -//FindOrganizations finds all organizations +// FindOrganizations finds all organizations func (sa *Adapter) FindOrganizations() ([]model.Organization, error) { return sa.getCachedOrganizations() } -//InsertOrganization inserts an organization +// InsertOrganization inserts an organization func (sa *Adapter) InsertOrganization(context TransactionContext, organization model.Organization) (*model.Organization, error) { org := organizationToStorage(&organization) @@ -2898,7 +2916,7 @@ func (sa *Adapter) InsertOrganization(context TransactionContext, organization m return &organization, nil } -//UpdateOrganization updates an organization +// UpdateOrganization updates an organization func (sa *Adapter) UpdateOrganization(ID string, name string, requestType string, organizationDomains []string) error { now := time.Now() @@ -2925,7 +2943,7 @@ func (sa *Adapter) UpdateOrganization(ID string, name string, requestType string return nil } -//loadOrganizations gets the organizations +// loadOrganizations gets the organizations func (sa *Adapter) loadOrganizations() ([]model.Organization, error) { //no transactions for get operations.. @@ -2946,7 +2964,7 @@ func (sa *Adapter) loadOrganizations() ([]model.Organization, error) { return organizations, nil } -//loadApplications loads all applications +// loadApplications loads all applications func (sa *Adapter) loadApplications() ([]model.Application, error) { filter := bson.D{} var result []application @@ -2964,7 +2982,7 @@ func (sa *Adapter) loadApplications() ([]model.Application, error) { return applications, nil } -//InsertApplication inserts an application +// InsertApplication inserts an application func (sa *Adapter) InsertApplication(context TransactionContext, application model.Application) (*model.Application, error) { app := applicationToStorage(&application) @@ -2976,17 +2994,17 @@ func (sa *Adapter) InsertApplication(context TransactionContext, application mod return &application, nil } -//FindApplication finds application +// FindApplication finds application func (sa *Adapter) FindApplication(ID string) (*model.Application, error) { return sa.getCachedApplication(ID) } -//FindApplications finds applications +// FindApplications finds applications func (sa *Adapter) FindApplications() ([]model.Application, error) { return sa.getCachedApplications() } -//loadAppConfigs loads all application configs +// loadAppConfigs loads all application configs func (sa *Adapter) loadAppConfigs() ([]model.ApplicationConfig, error) { filter := bson.D{} options := options.Find() @@ -3023,12 +3041,12 @@ func (sa *Adapter) loadAppConfigs() ([]model.ApplicationConfig, error) { return result, nil } -//FindAppConfigs finds appconfigs +// FindAppConfigs finds appconfigs func (sa *Adapter) FindAppConfigs(appTypeID string, appOrgID *string, versionNumbers *model.VersionNumbers) ([]model.ApplicationConfig, error) { return sa.getCachedApplicationConfigByAppTypeIDAndVersion(appTypeID, appOrgID, versionNumbers) } -//FindAppConfigByVersion finds the most recent app config for the specified version +// FindAppConfigByVersion finds the most recent app config for the specified version func (sa *Adapter) FindAppConfigByVersion(appTypeID string, appOrgID *string, versionNumbers model.VersionNumbers) (*model.ApplicationConfig, error) { configs, err := sa.getCachedApplicationConfigByAppTypeIDAndVersion(appTypeID, appOrgID, &versionNumbers) if err != nil { @@ -3040,7 +3058,7 @@ func (sa *Adapter) FindAppConfigByVersion(appTypeID string, appOrgID *string, ve return &configs[0], nil } -//FindAppConfigByID finds appconfig by ID +// FindAppConfigByID finds appconfig by ID func (sa *Adapter) FindAppConfigByID(ID string) (*model.ApplicationConfig, error) { return sa.getCachedApplicationConfigByID(ID) } @@ -3107,7 +3125,7 @@ func (sa *Adapter) DeleteAppConfig(ID string) error { return nil } -//FindApplicationType finds an application type by ID or identifier +// FindApplicationType finds an application type by ID or identifier func (sa *Adapter) FindApplicationType(id string) (*model.ApplicationType, error) { app, appType, err := sa.getCachedApplicationType(id) if err != nil { @@ -3119,7 +3137,7 @@ func (sa *Adapter) FindApplicationType(id string) (*model.ApplicationType, error return appType, nil } -//loadApplicationsOrganizations loads all applications organizations +// loadApplicationsOrganizations loads all applications organizations func (sa *Adapter) loadApplicationsOrganizations() ([]model.ApplicationOrganization, error) { filter := bson.D{} var list []applicationOrganization @@ -3156,17 +3174,17 @@ func (sa *Adapter) loadApplicationsOrganizations() ([]model.ApplicationOrganizat } -//FindApplicationOrganization finds application organization +// FindApplicationOrganization finds application organization func (sa *Adapter) FindApplicationOrganization(appID string, orgID string) (*model.ApplicationOrganization, error) { return sa.getCachedApplicationOrganization(appID, orgID) } -//FindApplicationsOrganizations finds application organizations +// FindApplicationsOrganizations finds application organizations func (sa *Adapter) FindApplicationsOrganizations() ([]model.ApplicationOrganization, error) { return sa.getCachedApplicationOrganizations() } -//FindApplicationsOrganizationsByOrgID finds applications organizations by orgID +// FindApplicationsOrganizationsByOrgID finds applications organizations by orgID func (sa *Adapter) FindApplicationsOrganizationsByOrgID(orgID string) ([]model.ApplicationOrganization, error) { cachedAppOrgs, err := sa.getCachedApplicationOrganizations() @@ -3196,7 +3214,7 @@ func (sa *Adapter) InsertApplicationOrganization(context TransactionContext, app return &applicationOrganization, nil } -//FindDevice finds a device by device id and account id +// FindDevice finds a device by device id and account id func (sa *Adapter) FindDevice(context TransactionContext, deviceID string, accountID string) (*model.Device, error) { filter := bson.D{primitive.E{Key: "device_id", Value: deviceID}, primitive.E{Key: "account_id", Value: accountID}} @@ -3216,7 +3234,7 @@ func (sa *Adapter) FindDevice(context TransactionContext, deviceID string, accou return &deviceRes, nil } -//InsertDevice inserts a device +// InsertDevice inserts a device func (sa *Adapter) InsertDevice(context TransactionContext, device model.Device) (*model.Device, error) { //insert in devices storageDevice := deviceToStorage(&device) @@ -3243,7 +3261,7 @@ func (sa *Adapter) InsertDevice(context TransactionContext, device model.Device) return &device, nil } -//InsertAuthType inserts an auth type +// InsertAuthType inserts an auth type func (sa *Adapter) InsertAuthType(context TransactionContext, authType model.AuthType) (*model.AuthType, error) { _, err := sa.db.authTypes.InsertOneWithContext(context, authType) if err != nil { @@ -3253,7 +3271,7 @@ func (sa *Adapter) InsertAuthType(context TransactionContext, authType model.Aut return &authType, nil } -//UpdateAuthTypes updates an auth type +// UpdateAuthTypes updates an auth type func (sa *Adapter) UpdateAuthTypes(ID string, code string, description string, isExternal bool, isAnonymous bool, useCredentials bool, ignoreMFA bool, params map[string]interface{}) error { @@ -3285,7 +3303,7 @@ func (sa *Adapter) UpdateAuthTypes(ID string, code string, description string, i // ============================== ServiceRegs ============================== -//loadServiceRegs fetches all service registration records +// loadServiceRegs fetches all service registration records func (sa *Adapter) loadServiceRegs() ([]model.ServiceReg, error) { filter := bson.M{} var result []model.ServiceReg @@ -3301,17 +3319,17 @@ func (sa *Adapter) loadServiceRegs() ([]model.ServiceReg, error) { return result, nil } -//FindServiceRegs fetches the requested service registration records +// FindServiceRegs fetches the requested service registration records func (sa *Adapter) FindServiceRegs(serviceIDs []string) ([]model.ServiceReg, error) { return sa.getCachedServiceRegs(serviceIDs) } -//FindServiceReg finds the service registration in storage +// FindServiceReg finds the service registration in storage func (sa *Adapter) FindServiceReg(serviceID string) (*model.ServiceReg, error) { return sa.getCachedServiceReg(serviceID) } -//InsertServiceReg inserts the service registration to storage +// InsertServiceReg inserts the service registration to storage func (sa *Adapter) InsertServiceReg(reg *model.ServiceReg) error { _, err := sa.db.serviceRegs.InsertOne(reg) if err != nil { @@ -3321,7 +3339,7 @@ func (sa *Adapter) InsertServiceReg(reg *model.ServiceReg) error { return nil } -//UpdateServiceReg updates the service registration in storage +// UpdateServiceReg updates the service registration in storage func (sa *Adapter) UpdateServiceReg(reg *model.ServiceReg) error { filter := bson.M{"registration.service_id": reg.Registration.ServiceID} err := sa.db.serviceRegs.ReplaceOne(filter, reg, nil) @@ -3332,7 +3350,7 @@ func (sa *Adapter) UpdateServiceReg(reg *model.ServiceReg) error { return nil } -//SaveServiceReg saves the service registration to the storage +// SaveServiceReg saves the service registration to the storage func (sa *Adapter) SaveServiceReg(reg *model.ServiceReg) error { filter := bson.M{"registration.service_id": reg.Registration.ServiceID} opts := options.Replace().SetUpsert(true) @@ -3344,7 +3362,7 @@ func (sa *Adapter) SaveServiceReg(reg *model.ServiceReg) error { return nil } -//DeleteServiceReg deletes the service registration from storage +// DeleteServiceReg deletes the service registration from storage func (sa *Adapter) DeleteServiceReg(serviceID string) error { filter := bson.M{"registration.service_id": serviceID} result, err := sa.db.serviceRegs.DeleteOne(filter, nil) @@ -3362,7 +3380,7 @@ func (sa *Adapter) DeleteServiceReg(serviceID string) error { return nil } -//FindServiceAuthorization finds the service authorization in storage +// FindServiceAuthorization finds the service authorization in storage func (sa *Adapter) FindServiceAuthorization(userID string, serviceID string) (*model.ServiceAuthorization, error) { filter := bson.M{"user_id": userID, "service_id": serviceID} var reg *model.ServiceAuthorization @@ -3374,7 +3392,7 @@ func (sa *Adapter) FindServiceAuthorization(userID string, serviceID string) (*m return reg, nil } -//SaveServiceAuthorization saves the service authorization to storage +// SaveServiceAuthorization saves the service authorization to storage func (sa *Adapter) SaveServiceAuthorization(authorization *model.ServiceAuthorization) error { filter := bson.M{"user_id": authorization.UserID, "service_id": authorization.ServiceID} opts := options.Replace().SetUpsert(true) @@ -3386,7 +3404,7 @@ func (sa *Adapter) SaveServiceAuthorization(authorization *model.ServiceAuthoriz return nil } -//DeleteServiceAuthorization deletes the service authorization from storage +// DeleteServiceAuthorization deletes the service authorization from storage func (sa *Adapter) DeleteServiceAuthorization(userID string, serviceID string) error { filter := bson.M{"user_id": userID, "service_id": serviceID} result, err := sa.db.serviceAuthorizations.DeleteOne(filter, nil) @@ -3404,7 +3422,7 @@ func (sa *Adapter) DeleteServiceAuthorization(userID string, serviceID string) e return nil } -//SaveDevice saves device +// SaveDevice saves device func (sa *Adapter) SaveDevice(context TransactionContext, device *model.Device) error { if device == nil { return errors.ErrorData(logutils.StatusInvalid, logutils.TypeArg, logutils.StringArgs("device")) @@ -3422,7 +3440,7 @@ func (sa *Adapter) SaveDevice(context TransactionContext, device *model.Device) return nil } -//DeleteDevice deletes a device +// DeleteDevice deletes a device func (sa *Adapter) DeleteDevice(context TransactionContext, id string) error { filter := bson.M{"_id": id} res, err := sa.db.devices.DeleteOneWithContext(context, filter, nil) @@ -3453,7 +3471,7 @@ func (sa *Adapter) getUpdateManyError(res *mongo.UpdateResult, err error, dataTy return nil } -//NewStorageAdapter creates a new storage adapter instance +// NewStorageAdapter creates a new storage adapter instance func NewStorageAdapter(mongoDBAuth string, mongoDBName string, mongoTimeout string, logger *logs.Logger) *Adapter { timeoutInt, err := strconv.Atoi(mongoTimeout) if err != nil { @@ -3520,7 +3538,7 @@ func (sl *storageListener) OnApplicationConfigsUpdated() { sl.adapter.cacheApplicationConfigs() } -//Listener represents storage listener +// Listener represents storage listener type Listener interface { OnAPIKeysUpdated() OnAuthTypesUpdated() @@ -3532,34 +3550,34 @@ type Listener interface { OnApplicationConfigsUpdated() } -//DefaultListenerImpl default listener implementation +// DefaultListenerImpl default listener implementation type DefaultListenerImpl struct{} -//OnAPIKeysUpdated notifies api keys have been updated +// OnAPIKeysUpdated notifies api keys have been updated func (d *DefaultListenerImpl) OnAPIKeysUpdated() {} -//OnAuthTypesUpdated notifies auth types have been updated +// OnAuthTypesUpdated notifies auth types have been updated func (d *DefaultListenerImpl) OnAuthTypesUpdated() {} -//OnIdentityProvidersUpdated notifies identity providers have been updated +// OnIdentityProvidersUpdated notifies identity providers have been updated func (d *DefaultListenerImpl) OnIdentityProvidersUpdated() {} -//OnServiceRegsUpdated notifies services regs have been updated +// OnServiceRegsUpdated notifies services regs have been updated func (d *DefaultListenerImpl) OnServiceRegsUpdated() {} -//OnOrganizationsUpdated notifies organizations have been updated +// OnOrganizationsUpdated notifies organizations have been updated func (d *DefaultListenerImpl) OnOrganizationsUpdated() {} -//OnApplicationsUpdated notifies applications have been updated +// OnApplicationsUpdated notifies applications have been updated func (d *DefaultListenerImpl) OnApplicationsUpdated() {} -//OnApplicationsOrganizationsUpdated notifies applications organizations have been updated +// OnApplicationsOrganizationsUpdated notifies applications organizations have been updated func (d *DefaultListenerImpl) OnApplicationsOrganizationsUpdated() {} -//OnApplicationConfigsUpdated notifies application configs have been updated +// OnApplicationConfigsUpdated notifies application configs have been updated func (d *DefaultListenerImpl) OnApplicationConfigsUpdated() {} -//TransactionContext wraps mongo.SessionContext for use by external packages +// TransactionContext wraps mongo.SessionContext for use by external packages type TransactionContext interface { mongo.SessionContext } From f2d85c2998fca9a40550cb5ec9d22d05df078478 Mon Sep 17 00:00:00 2001 From: Ryan Oberlander Date: Thu, 4 Aug 2022 13:29:21 -0500 Subject: [PATCH 24/32] update permission inactive flag --- driven/storage/adapter.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/driven/storage/adapter.go b/driven/storage/adapter.go index a30822880..9475230fc 100644 --- a/driven/storage/adapter.go +++ b/driven/storage/adapter.go @@ -2264,6 +2264,7 @@ func (sa *Adapter) updatePermission(context TransactionContext, item model.Permi primitive.E{Key: "description", Value: item.Description}, primitive.E{Key: "service_id", Value: item.ServiceID}, primitive.E{Key: "assigners", Value: item.Assigners}, + primitive.E{Key: "inactive", Value: item.Inactive}, primitive.E{Key: "date_updated", Value: item.DateUpdated}, }}, } @@ -2320,6 +2321,7 @@ func (sa *Adapter) updatePermission(context TransactionContext, item model.Permi primitive.E{Key: "permissions.$.description", Value: item.Description}, primitive.E{Key: "permissions.$.service_id", Value: item.ServiceID}, primitive.E{Key: "permissions.$.assigners", Value: item.Assigners}, + primitive.E{Key: "permissions.$.inactive", Value: item.Inactive}, primitive.E{Key: "permissions.$.date_updated", Value: item.DateUpdated}, }}, } From f27a5a2372b5f5b79cf24db25bb3b0254f74c8f5 Mon Sep 17 00:00:00 2001 From: Ryan Oberlander Date: Thu, 4 Aug 2022 14:08:43 -0500 Subject: [PATCH 25/32] allow system create permission API to create self-assigning permissions --- core/app_system.go | 16 +++++++++++----- core/model/application.go | 13 +++++++++++++ 2 files changed, 24 insertions(+), 5 deletions(-) diff --git a/core/app_system.go b/core/app_system.go index 77e430603..b9f250781 100644 --- a/core/app_system.go +++ b/core/app_system.go @@ -166,6 +166,8 @@ func (app *application) sysGetApplications() ([]model.Application, error) { func (app *application) sysCreatePermission(name string, description string, serviceID string, assigners *[]string) (*model.Permission, error) { var newPermission *model.Permission transaction := func(context storage.TransactionContext) error { + permission := model.Permission{Name: name} + //1. make sure all assigners already exist assignersVal := make([]string, 0) if assigners != nil { @@ -175,15 +177,19 @@ func (app *application) sysCreatePermission(name string, description string, ser return err } if len(assignerPermissions) < len(assignersVal) { - missing := model.GetMissingPermissionNames(assignerPermissions, assignersVal) - return errors.ErrorData(logutils.StatusInvalid, "assigner permission", &logutils.FieldArgs{"names": missing}) + err := model.CheckPermissionsExist(assignersVal, assignerPermissions, []model.Permission{permission}) + if err != nil { + return errors.WrapErrorAction(logutils.ActionValidate, "assigners", nil, err) + } } } //2. create permission - id, _ := uuid.NewUUID() - now := time.Now() - permission := model.Permission{ID: id.String(), Name: name, Description: description, DateCreated: now, ServiceID: serviceID, Assigners: assignersVal} + permission.ID = uuid.NewString() + permission.Description = description + permission.ServiceID = serviceID + permission.Assigners = assignersVal + permission.DateCreated = time.Now() err := app.storage.InsertPermission(context, permission) if err != nil { return err diff --git a/core/model/application.go b/core/model/application.go index 3aae86847..d5d6805f7 100644 --- a/core/model/application.go +++ b/core/model/application.go @@ -475,6 +475,19 @@ func GetMissingPermissionNames(items []Permission, names []string) []string { return missingNames } +// CheckPermissionsExist checks if permissions already exist or are included in list of incoming permissions +func CheckPermissionsExist(names []string, existing []Permission, incoming []Permission) error { + missing := GetMissingPermissionNames(existing, names) + if len(missing) > 0 { + missing = GetMissingPermissionNames(incoming, missing) + if len(missing) > 0 { + return errors.ErrorData(logutils.StatusInvalid, TypePermission, &logutils.FieldArgs{"names": missing}) + } + } + + return nil +} + // GetMissingRoleIDs returns a list of role IDs missing from items func GetMissingRoleIDs(items []AppOrgRole, ids []string) []string { missingIDs := make([]string, 0) From e5276f067e4db131f7f8a4ba1e64da1be0114249 Mon Sep 17 00:00:00 2001 From: Ryan Oberlander Date: Thu, 4 Aug 2022 14:13:13 -0500 Subject: [PATCH 26/32] update assigner existence checks --- core/app_bbs.go | 21 ++++----------------- 1 file changed, 4 insertions(+), 17 deletions(-) diff --git a/core/app_bbs.go b/core/app_bbs.go index 17a8ec906..6afdf69f5 100644 --- a/core/app_bbs.go +++ b/core/app_bbs.go @@ -94,9 +94,9 @@ func (app *application) bbsUpdatePermissions(permissions []model.Permission, acc //4. if added, create a new permission for _, name := range added { permission := newNamesMap[name] - err = app.validateAssigners(permission.Assigners, existingAssigners, permissions) + err = model.CheckPermissionsExist(permission.Assigners, existingAssigners, permissions) if err != nil { - return err + return errors.WrapErrorAction(logutils.ActionValidate, "assigners", nil, err) } permission.ID = uuid.NewString() @@ -127,9 +127,9 @@ func (app *application) bbsUpdatePermissions(permissions []model.Permission, acc for _, name := range unchanged { currentPermission := currentNamesMap[name] newPermission := newNamesMap[name] - err = app.validateAssigners(newPermission.Assigners, existingAssigners, permissions) + err = model.CheckPermissionsExist(newPermission.Assigners, existingAssigners, permissions) if err != nil { - return err + return errors.WrapErrorAction(logutils.ActionValidate, "assigners", nil, err) } description := newPermission.Description @@ -160,16 +160,3 @@ func (app *application) bbsUpdatePermissions(permissions []model.Permission, acc return servicePermissions, nil } - -func (app *application) validateAssigners(assigners []string, existing []model.Permission, incoming []model.Permission) error { - //assigners must already exist or be included in incoming permissions - missing := model.GetMissingPermissionNames(existing, assigners) - if len(missing) > 0 { - missing = model.GetMissingPermissionNames(incoming, missing) - if len(missing) > 0 { - return errors.ErrorData(logutils.StatusInvalid, "assigner permission", &logutils.FieldArgs{"names": missing}) - } - } - - return nil -} From c526d7f7ef3d3ffe273b11802a696eabcd43ca5e Mon Sep 17 00:00:00 2001 From: Ryan Oberlander Date: Thu, 4 Aug 2022 14:27:43 -0500 Subject: [PATCH 27/32] add TPs update permissions handler [#475] --- core/app_tps.go | 135 +++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 133 insertions(+), 2 deletions(-) diff --git a/core/app_tps.go b/core/app_tps.go index fbe48af3d..839e02aa4 100644 --- a/core/app_tps.go +++ b/core/app_tps.go @@ -16,7 +16,11 @@ package core import ( "core-building-block/core/model" + "core-building-block/driven/storage" + "core-building-block/utils" + "time" + "github.com/google/uuid" "github.com/rokwire/logging-library-go/errors" "github.com/rokwire/logging-library-go/logutils" ) @@ -26,6 +30,133 @@ func (app *application) tpsGetTest() string { } func (app *application) tpsUpdatePermissions(permissions []model.Permission, accountID string) ([]model.Permission, error) { - //TODO: implement - return nil, errors.New(logutils.Unimplemented) + //find the service registration record + serviceReg, err := app.storage.FindServiceRegByServiceAccountID(accountID) + if err != nil { + return nil, errors.WrapErrorAction(logutils.ActionFind, model.TypeServiceAccount, nil, err) + } + if serviceReg == nil { + return nil, errors.ErrorData(logutils.StatusMissing, model.TypeServiceReg, &logutils.FieldArgs{"service_account_id": accountID}) + } + + servicePermissions := make([]model.Permission, 0) + transaction := func(context storage.TransactionContext) error { + newNames := make([]string, len(permissions)) + newNamesMap := make(map[string]model.Permission) + allAssigners := make([]string, 0) + for i, p := range permissions { + newNames[i] = p.Name + newNamesMap[p.Name] = p + allAssigners = append(allAssigners, p.Assigners...) + } + + //1. check if any incoming permissions have the same name as another service's permission + invalidNames := make(map[string][]string) + existingPermissions, err := app.storage.FindPermissionsByName(context, newNames) + if err != nil { + return err + } + for _, p := range existingPermissions { + if p.ServiceID != serviceReg.Registration.ServiceID { + if invalidNames[p.ServiceID] == nil { + invalidNames[p.ServiceID] = []string{} + } + invalidNames[p.ServiceID] = append(invalidNames[p.ServiceID], p.Name) + } + } + if len(invalidNames) > 0 { + return errors.ErrorData(logutils.StatusInvalid, model.TypePermission, &logutils.FieldArgs{"names": invalidNames}) + } + + //2. get the list of existing assigner permissions from the incoming permission list + existingAssigners, err := app.storage.FindPermissionsByName(context, allAssigners) + if err != nil { + return err + } + + //3. get current list of service permissions + serviceIDs := []string{serviceReg.Registration.ServiceID} + currentPermissions, err := app.storage.FindPermissionsByServiceIDs(context, serviceIDs) + if err != nil { + return errors.WrapErrorAction(logutils.ActionFind, model.TypePermission, &logutils.FieldArgs{"service_id": serviceReg.Registration.ServiceID}, err) + } + + currentNames := make([]string, len(currentPermissions)) + currentNamesMap := make(map[string]model.Permission) + for i, p := range currentPermissions { + currentNames[i] = p.Name + currentNamesMap[p.Name] = p + } + + now := time.Now().UTC() + added, removed, unchanged := utils.StringListDiff(newNames, currentNames) + + //4. if added, create a new permission + for _, name := range added { + permission := newNamesMap[name] + err = model.CheckPermissionsExist(permission.Assigners, existingAssigners, permissions) + if err != nil { + return errors.WrapErrorAction(logutils.ActionValidate, "assigners", nil, err) + } + + permission.ID = uuid.NewString() + permission.ServiceID = serviceReg.Registration.ServiceID + permission.Inactive = false + permission.DateCreated = now + servicePermissions = append(servicePermissions, permission) + } + err = app.storage.InsertPermissions(context, servicePermissions) + if err != nil { + return errors.WrapErrorAction(logutils.ActionInsert, model.TypePermission, &logutils.FieldArgs{"name": added}, err) + } + + //5. if removed, mark existing permission as inactive + for _, name := range removed { + permission := currentNamesMap[name] + if !permission.Inactive { + permission.Inactive = true + permission.DateUpdated = &now + err = app.storage.UpdatePermission(context, permission) + if err != nil { + return errors.WrapErrorAction(logutils.ActionUpdate, model.TypePermission, &logutils.FieldArgs{"name": name}, err) + } + } + } + + //6. if unchanged, update permission data if necessary + for _, name := range unchanged { + currentPermission := currentNamesMap[name] + newPermission := newNamesMap[name] + err = model.CheckPermissionsExist(newPermission.Assigners, existingAssigners, permissions) + if err != nil { + return errors.WrapErrorAction(logutils.ActionValidate, "assigners", nil, err) + } + + description := newPermission.Description + assigners := newPermission.Assigners + updated := currentPermission.Inactive || (description != currentPermission.Description) || !utils.DeepEqual(assigners, currentPermission.Assigners) + newPermission = currentPermission + if updated { + newPermission.Description = description + newPermission.Assigners = assigners + newPermission.Inactive = false + newPermission.DateUpdated = &now + err = app.storage.UpdatePermission(context, newPermission) + if err != nil { + return err + } + } + + servicePermissions = append(servicePermissions, newPermission) + } + + return nil + } + + err = app.storage.PerformTransaction(transaction) + if err != nil { + return nil, err + } + + return servicePermissions, nil } From c72e4bf03b169f5e3ab107f3ce45f457808e2fea Mon Sep 17 00:00:00 2001 From: Ryan Oberlander Date: Thu, 4 Aug 2022 17:05:31 -0500 Subject: [PATCH 28/32] add admin managed flag, allow system admins to set admin managed and inactive flags [#475] --- core/apis.go | 8 ++++---- core/app_bbs.go | 10 +++++----- core/app_system.go | 20 +++++++++---------- core/app_tps.go | 10 +++++----- core/interfaces.go | 4 ++-- core/model/application.go | 4 +++- driven/storage/adapter.go | 2 ++ driver/web/apis_admin.go | 2 +- driver/web/apis_system.go | 20 +++++++++++++++++-- driver/web/docs/gen/def.yaml | 8 ++++++++ driver/web/docs/gen/gen_types.go | 18 ++++++++++------- .../system/permissions/request/Request.yaml | 6 +++++- .../docs/schemas/application/Permission.yaml | 4 ++++ 13 files changed, 77 insertions(+), 39 deletions(-) diff --git a/core/apis.go b/core/apis.go index 643c93a9c..f0964fc37 100644 --- a/core/apis.go +++ b/core/apis.go @@ -491,12 +491,12 @@ func (s *systemImpl) SysGetApplications() ([]model.Application, error) { return s.app.sysGetApplications() } -func (s *systemImpl) SysCreatePermission(name string, description string, serviceID string, assigners *[]string) (*model.Permission, error) { - return s.app.sysCreatePermission(name, description, serviceID, assigners) +func (s *systemImpl) SysCreatePermission(name string, description string, serviceID string, assigners *[]string, adminManaged bool, inactive bool) (*model.Permission, error) { + return s.app.sysCreatePermission(name, description, serviceID, assigners, adminManaged, inactive) } -func (s *systemImpl) SysUpdatePermission(name string, description string, serviceID string, assigners *[]string) (*model.Permission, error) { - return s.app.sysUpdatePermission(name, description, serviceID, assigners) +func (s *systemImpl) SysUpdatePermission(name string, description string, serviceID string, assigners *[]string, adminManaged bool, inactive bool) (*model.Permission, error) { + return s.app.sysUpdatePermission(name, description, serviceID, assigners, adminManaged, inactive) } func (s *systemImpl) SysGetAppConfigs(appTypeID string, orgID *string, versionNumbers *model.VersionNumbers) ([]model.ApplicationConfig, error) { diff --git a/core/app_bbs.go b/core/app_bbs.go index 6afdf69f5..eb63e60e2 100644 --- a/core/app_bbs.go +++ b/core/app_bbs.go @@ -39,7 +39,7 @@ func (app *application) bbsUpdatePermissions(permissions []model.Permission, acc return nil, errors.ErrorData(logutils.StatusMissing, model.TypeServiceReg, &logutils.FieldArgs{"service_account_id": accountID}) } - servicePermissions := make([]model.Permission, 0) + activePermissions := make([]model.Permission, 0) transaction := func(context storage.TransactionContext) error { newNames := make([]string, len(permissions)) newNamesMap := make(map[string]model.Permission) @@ -103,9 +103,9 @@ func (app *application) bbsUpdatePermissions(permissions []model.Permission, acc permission.ServiceID = serviceReg.Registration.ServiceID permission.Inactive = false permission.DateCreated = now - servicePermissions = append(servicePermissions, permission) + activePermissions = append(activePermissions, permission) } - err = app.storage.InsertPermissions(context, servicePermissions) + err = app.storage.InsertPermissions(context, activePermissions) if err != nil { return errors.WrapErrorAction(logutils.ActionInsert, model.TypePermission, &logutils.FieldArgs{"name": added}, err) } @@ -147,7 +147,7 @@ func (app *application) bbsUpdatePermissions(permissions []model.Permission, acc } } - servicePermissions = append(servicePermissions, newPermission) + activePermissions = append(activePermissions, newPermission) } return nil @@ -158,5 +158,5 @@ func (app *application) bbsUpdatePermissions(permissions []model.Permission, acc return nil, err } - return servicePermissions, nil + return activePermissions, nil } diff --git a/core/app_system.go b/core/app_system.go index b9f250781..33519f94d 100644 --- a/core/app_system.go +++ b/core/app_system.go @@ -163,7 +163,7 @@ func (app *application) sysGetApplications() ([]model.Application, error) { return getApplications, nil } -func (app *application) sysCreatePermission(name string, description string, serviceID string, assigners *[]string) (*model.Permission, error) { +func (app *application) sysCreatePermission(name string, description string, serviceID string, assigners *[]string, adminManaged bool, inactive bool) (*model.Permission, error) { var newPermission *model.Permission transaction := func(context storage.TransactionContext) error { permission := model.Permission{Name: name} @@ -189,6 +189,8 @@ func (app *application) sysCreatePermission(name string, description string, ser permission.Description = description permission.ServiceID = serviceID permission.Assigners = assignersVal + permission.AdminManaged = adminManaged + permission.Inactive = inactive permission.DateCreated = time.Now() err := app.storage.InsertPermission(context, permission) if err != nil { @@ -207,7 +209,7 @@ func (app *application) sysCreatePermission(name string, description string, ser return newPermission, nil } -func (app *application) sysUpdatePermission(name string, description string, serviceID string, assigners *[]string) (*model.Permission, error) { +func (app *application) sysUpdatePermission(name string, description string, serviceID string, assigners *[]string, adminManaged bool, inactive bool) (*model.Permission, error) { var updatedPermission *model.Permission transaction := func(context storage.TransactionContext) error { //1. find permission @@ -222,15 +224,11 @@ func (app *application) sysUpdatePermission(name string, description string, ser //2. update permission data as needed permission := permissions[0] - updated := false - if description != permission.Description { - permission.Description = description - updated = true - } - if serviceID != permission.ServiceID { - permission.ServiceID = serviceID - updated = true - } + updated := (description != permission.Description) || (serviceID != permission.ServiceID) || (adminManaged != permission.AdminManaged) || (inactive != permission.Inactive) + permission.Description = description + permission.ServiceID = serviceID + permission.AdminManaged = adminManaged + permission.Inactive = inactive //3. if assigners changed, check that they exist assignersVal := make([]string, 0) diff --git a/core/app_tps.go b/core/app_tps.go index 839e02aa4..062385144 100644 --- a/core/app_tps.go +++ b/core/app_tps.go @@ -39,7 +39,7 @@ func (app *application) tpsUpdatePermissions(permissions []model.Permission, acc return nil, errors.ErrorData(logutils.StatusMissing, model.TypeServiceReg, &logutils.FieldArgs{"service_account_id": accountID}) } - servicePermissions := make([]model.Permission, 0) + activePermissions := make([]model.Permission, 0) transaction := func(context storage.TransactionContext) error { newNames := make([]string, len(permissions)) newNamesMap := make(map[string]model.Permission) @@ -103,9 +103,9 @@ func (app *application) tpsUpdatePermissions(permissions []model.Permission, acc permission.ServiceID = serviceReg.Registration.ServiceID permission.Inactive = false permission.DateCreated = now - servicePermissions = append(servicePermissions, permission) + activePermissions = append(activePermissions, permission) } - err = app.storage.InsertPermissions(context, servicePermissions) + err = app.storage.InsertPermissions(context, activePermissions) if err != nil { return errors.WrapErrorAction(logutils.ActionInsert, model.TypePermission, &logutils.FieldArgs{"name": added}, err) } @@ -147,7 +147,7 @@ func (app *application) tpsUpdatePermissions(permissions []model.Permission, acc } } - servicePermissions = append(servicePermissions, newPermission) + activePermissions = append(activePermissions, newPermission) } return nil @@ -158,5 +158,5 @@ func (app *application) tpsUpdatePermissions(permissions []model.Permission, acc return nil, err } - return servicePermissions, nil + return activePermissions, nil } diff --git a/core/interfaces.go b/core/interfaces.go index 75d460019..93d6300ff 100644 --- a/core/interfaces.go +++ b/core/interfaces.go @@ -110,8 +110,8 @@ type System interface { SysGetApplication(ID string) (*model.Application, error) SysGetApplications() ([]model.Application, error) - SysCreatePermission(name string, description string, serviceID string, assigners *[]string) (*model.Permission, error) - SysUpdatePermission(name string, description string, serviceID string, assigners *[]string) (*model.Permission, error) + SysCreatePermission(name string, description string, serviceID string, assigners *[]string, adminManaged bool, inactive bool) (*model.Permission, error) + SysUpdatePermission(name string, description string, serviceID string, assigners *[]string, adminManaged bool, inactive bool) (*model.Permission, error) SysGetAppConfigs(appTypeID string, orgID *string, versionNumbers *model.VersionNumbers) ([]model.ApplicationConfig, error) SysGetAppConfig(id string) (*model.ApplicationConfig, error) diff --git a/core/model/application.go b/core/model/application.go index 9e3aaf2c6..ff385842a 100644 --- a/core/model/application.go +++ b/core/model/application.go @@ -63,7 +63,9 @@ type Permission struct { ServiceID string `bson:"service_id"` Assigners []string `bson:"assigners"` - Inactive bool `bson:"inactive"` + + AdminManaged bool `bson:"admin_managed"` + Inactive bool `bson:"inactive"` DateCreated time.Time `bson:"date_created"` DateUpdated *time.Time `bson:"date_updated"` diff --git a/driven/storage/adapter.go b/driven/storage/adapter.go index 9475230fc..754d00edb 100644 --- a/driven/storage/adapter.go +++ b/driven/storage/adapter.go @@ -2264,6 +2264,7 @@ func (sa *Adapter) updatePermission(context TransactionContext, item model.Permi primitive.E{Key: "description", Value: item.Description}, primitive.E{Key: "service_id", Value: item.ServiceID}, primitive.E{Key: "assigners", Value: item.Assigners}, + primitive.E{Key: "admin_managed", Value: item.AdminManaged}, primitive.E{Key: "inactive", Value: item.Inactive}, primitive.E{Key: "date_updated", Value: item.DateUpdated}, }}, @@ -2321,6 +2322,7 @@ func (sa *Adapter) updatePermission(context TransactionContext, item model.Permi primitive.E{Key: "permissions.$.description", Value: item.Description}, primitive.E{Key: "permissions.$.service_id", Value: item.ServiceID}, primitive.E{Key: "permissions.$.assigners", Value: item.Assigners}, + primitive.E{Key: "permissions.$.admin_managed", Value: item.AdminManaged}, primitive.E{Key: "permissions.$.inactive", Value: item.Inactive}, primitive.E{Key: "permissions.$.date_updated", Value: item.DateUpdated}, }}, diff --git a/driver/web/apis_admin.go b/driver/web/apis_admin.go index 55fb0a161..d9e48b45f 100644 --- a/driver/web/apis_admin.go +++ b/driver/web/apis_admin.go @@ -715,7 +715,7 @@ func (h AdminApisHandler) createApplicationGroup(l *logs.Log, r *http.Request, c return l.HttpResponseSuccessJSON(response) } -//updateApplicationGroup updates an application group +// updateApplicationGroup updates an application group func (h AdminApisHandler) updateApplicationGroup(l *logs.Log, r *http.Request, claims *tokenauth.Claims) logs.HttpResponse { params := mux.Vars(r) groupID := params["id"] diff --git a/driver/web/apis_system.go b/driver/web/apis_system.go index eb3029ec8..e4d7668fb 100644 --- a/driver/web/apis_system.go +++ b/driver/web/apis_system.go @@ -721,7 +721,15 @@ func (h SystemApisHandler) createPermission(l *logs.Log, r *http.Request, claims return l.HttpResponseErrorAction(logutils.ActionUnmarshal, model.TypePermission, nil, err, http.StatusBadRequest, true) } - permission, err := h.coreAPIs.System.SysCreatePermission(requestData.Name, requestData.Description, requestData.ServiceId, requestData.Assigners) + adminManaged := false + if requestData.AdminManaged != nil { + adminManaged = *requestData.AdminManaged + } + inactive := false + if requestData.Inactive != nil { + inactive = *requestData.Inactive + } + permission, err := h.coreAPIs.System.SysCreatePermission(requestData.Name, requestData.Description, requestData.ServiceId, requestData.Assigners, adminManaged, inactive) if err != nil { return l.HttpResponseErrorAction(logutils.ActionCreate, model.TypePermission, nil, err, http.StatusInternalServerError, true) } @@ -748,7 +756,15 @@ func (h SystemApisHandler) updatePermission(l *logs.Log, r *http.Request, claims return l.HttpResponseErrorAction(logutils.ActionUnmarshal, model.TypePermission, nil, err, http.StatusBadRequest, true) } - permission, err := h.coreAPIs.System.SysUpdatePermission(requestData.Name, requestData.Description, requestData.ServiceId, requestData.Assigners) + adminManaged := false + if requestData.AdminManaged != nil { + adminManaged = *requestData.AdminManaged + } + inactive := false + if requestData.Inactive != nil { + inactive = *requestData.Inactive + } + permission, err := h.coreAPIs.System.SysUpdatePermission(requestData.Name, requestData.Description, requestData.ServiceId, requestData.Assigners, adminManaged, inactive) if err != nil { return l.HttpResponseErrorAction(logutils.ActionUpdate, model.TypePermission, nil, err, http.StatusInternalServerError, true) } diff --git a/driver/web/docs/gen/def.yaml b/driver/web/docs/gen/def.yaml index 3dfb5a0e8..61af66d91 100644 --- a/driver/web/docs/gen/def.yaml +++ b/driver/web/docs/gen/def.yaml @@ -4734,6 +4734,10 @@ components: type: array items: type: string + admin_managed: + type: boolean + inactive: + type: boolean date_created: type: string date_updated: @@ -6454,6 +6458,10 @@ components: description: permissions that could assign current permission to accounts items: type: string + admin_managed: + type: boolean + inactive: + type: boolean _system_req_create_auth_type: type: object required: diff --git a/driver/web/docs/gen/gen_types.go b/driver/web/docs/gen/gen_types.go index 59ff29adf..96efa56eb 100644 --- a/driver/web/docs/gen/gen_types.go +++ b/driver/web/docs/gen/gen_types.go @@ -513,13 +513,15 @@ type PartialAccount struct { // Permission defines model for Permission. type Permission struct { - Assigners *[]string `json:"assigners,omitempty"` - DateCreated *string `json:"date_created,omitempty"` - DateUpdated *string `json:"date_updated,omitempty"` - Description string `json:"description"` - Id string `json:"id"` - Name string `json:"name"` - ServiceId string `json:"service_id"` + AdminManaged *bool `json:"admin_managed,omitempty"` + Assigners *[]string `json:"assigners,omitempty"` + DateCreated *string `json:"date_created,omitempty"` + DateUpdated *string `json:"date_updated,omitempty"` + Description string `json:"description"` + Id string `json:"id"` + Inactive *bool `json:"inactive,omitempty"` + Name string `json:"name"` + ServiceId string `json:"service_id"` } // Profile defines model for Profile. @@ -1137,10 +1139,12 @@ type SystemReqCreateServiceAccount struct { // SystemReqPermissions defines model for _system_req_permissions. type SystemReqPermissions struct { + AdminManaged *bool `json:"admin_managed,omitempty"` // permissions that could assign current permission to accounts Assigners *[]string `json:"assigners,omitempty"` Description string `json:"description"` + Inactive *bool `json:"inactive,omitempty"` Name string `json:"name"` ServiceId string `json:"service_id"` } diff --git a/driver/web/docs/schemas/apis/system/permissions/request/Request.yaml b/driver/web/docs/schemas/apis/system/permissions/request/Request.yaml index 46dbcc949..36cd2f6a1 100644 --- a/driver/web/docs/schemas/apis/system/permissions/request/Request.yaml +++ b/driver/web/docs/schemas/apis/system/permissions/request/Request.yaml @@ -14,4 +14,8 @@ properties: type: array description: permissions that could assign current permission to accounts items: - type: string \ No newline at end of file + type: string + admin_managed: + type: boolean + inactive: + type: boolean \ No newline at end of file diff --git a/driver/web/docs/schemas/application/Permission.yaml b/driver/web/docs/schemas/application/Permission.yaml index 0028824df..596496fca 100644 --- a/driver/web/docs/schemas/application/Permission.yaml +++ b/driver/web/docs/schemas/application/Permission.yaml @@ -19,6 +19,10 @@ properties: type: array items: type: string + admin_managed: + type: boolean + inactive: + type: boolean date_created: type: string date_updated: From d8312a954f9b609b1ee024fdae1fdd10f2aef041 Mon Sep 17 00:00:00 2001 From: Ryan Oberlander Date: Fri, 5 Aug 2022 12:02:09 -0500 Subject: [PATCH 29/32] change admin managed to service managed [#475] --- core/apis.go | 8 ++--- core/app_bbs.go | 15 ++++++---- core/app_system.go | 10 +++---- core/app_tps.go | 15 ++++++---- core/interfaces.go | 4 +-- core/model/application.go | 4 +-- driven/storage/adapter.go | 4 +-- driver/web/apis_system.go | 16 +++++----- driver/web/conversions_application.go | 10 ++++--- driver/web/docs/gen/def.yaml | 4 +-- driver/web/docs/gen/gen_types.go | 30 +++++++++---------- .../system/permissions/request/Request.yaml | 2 +- .../docs/schemas/application/Permission.yaml | 2 +- 13 files changed, 68 insertions(+), 56 deletions(-) diff --git a/core/apis.go b/core/apis.go index f0964fc37..1e6814b4b 100644 --- a/core/apis.go +++ b/core/apis.go @@ -491,12 +491,12 @@ func (s *systemImpl) SysGetApplications() ([]model.Application, error) { return s.app.sysGetApplications() } -func (s *systemImpl) SysCreatePermission(name string, description string, serviceID string, assigners *[]string, adminManaged bool, inactive bool) (*model.Permission, error) { - return s.app.sysCreatePermission(name, description, serviceID, assigners, adminManaged, inactive) +func (s *systemImpl) SysCreatePermission(name string, description string, serviceID string, assigners *[]string, serviceManaged bool, inactive bool) (*model.Permission, error) { + return s.app.sysCreatePermission(name, description, serviceID, assigners, serviceManaged, inactive) } -func (s *systemImpl) SysUpdatePermission(name string, description string, serviceID string, assigners *[]string, adminManaged bool, inactive bool) (*model.Permission, error) { - return s.app.sysUpdatePermission(name, description, serviceID, assigners, adminManaged, inactive) +func (s *systemImpl) SysUpdatePermission(name string, description string, serviceID string, assigners *[]string, serviceManaged bool, inactive bool) (*model.Permission, error) { + return s.app.sysUpdatePermission(name, description, serviceID, assigners, serviceManaged, inactive) } func (s *systemImpl) SysGetAppConfigs(appTypeID string, orgID *string, versionNumbers *model.VersionNumbers) ([]model.ApplicationConfig, error) { diff --git a/core/app_bbs.go b/core/app_bbs.go index eb63e60e2..2ee4d425f 100644 --- a/core/app_bbs.go +++ b/core/app_bbs.go @@ -101,6 +101,7 @@ func (app *application) bbsUpdatePermissions(permissions []model.Permission, acc permission.ID = uuid.NewString() permission.ServiceID = serviceReg.Registration.ServiceID + permission.ServiceManaged = true permission.Inactive = false permission.DateCreated = now activePermissions = append(activePermissions, permission) @@ -114,11 +115,15 @@ func (app *application) bbsUpdatePermissions(permissions []model.Permission, acc for _, name := range removed { permission := currentNamesMap[name] if !permission.Inactive { - permission.Inactive = true - permission.DateUpdated = &now - err = app.storage.UpdatePermission(context, permission) - if err != nil { - return errors.WrapErrorAction(logutils.ActionUpdate, model.TypePermission, &logutils.FieldArgs{"name": name}, err) + if permission.ServiceManaged { + permission.Inactive = true + permission.DateUpdated = &now + err = app.storage.UpdatePermission(context, permission) + if err != nil { + return errors.WrapErrorAction(logutils.ActionUpdate, model.TypePermission, &logutils.FieldArgs{"name": name}, err) + } + } else { + activePermissions = append(activePermissions, permission) } } } diff --git a/core/app_system.go b/core/app_system.go index 33519f94d..152ae090d 100644 --- a/core/app_system.go +++ b/core/app_system.go @@ -163,7 +163,7 @@ func (app *application) sysGetApplications() ([]model.Application, error) { return getApplications, nil } -func (app *application) sysCreatePermission(name string, description string, serviceID string, assigners *[]string, adminManaged bool, inactive bool) (*model.Permission, error) { +func (app *application) sysCreatePermission(name string, description string, serviceID string, assigners *[]string, serviceManaged bool, inactive bool) (*model.Permission, error) { var newPermission *model.Permission transaction := func(context storage.TransactionContext) error { permission := model.Permission{Name: name} @@ -189,7 +189,7 @@ func (app *application) sysCreatePermission(name string, description string, ser permission.Description = description permission.ServiceID = serviceID permission.Assigners = assignersVal - permission.AdminManaged = adminManaged + permission.ServiceManaged = serviceManaged permission.Inactive = inactive permission.DateCreated = time.Now() err := app.storage.InsertPermission(context, permission) @@ -209,7 +209,7 @@ func (app *application) sysCreatePermission(name string, description string, ser return newPermission, nil } -func (app *application) sysUpdatePermission(name string, description string, serviceID string, assigners *[]string, adminManaged bool, inactive bool) (*model.Permission, error) { +func (app *application) sysUpdatePermission(name string, description string, serviceID string, assigners *[]string, serviceManaged bool, inactive bool) (*model.Permission, error) { var updatedPermission *model.Permission transaction := func(context storage.TransactionContext) error { //1. find permission @@ -224,10 +224,10 @@ func (app *application) sysUpdatePermission(name string, description string, ser //2. update permission data as needed permission := permissions[0] - updated := (description != permission.Description) || (serviceID != permission.ServiceID) || (adminManaged != permission.AdminManaged) || (inactive != permission.Inactive) + updated := (description != permission.Description) || (serviceID != permission.ServiceID) || (serviceManaged != permission.ServiceManaged) || (inactive != permission.Inactive) permission.Description = description permission.ServiceID = serviceID - permission.AdminManaged = adminManaged + permission.ServiceManaged = serviceManaged permission.Inactive = inactive //3. if assigners changed, check that they exist diff --git a/core/app_tps.go b/core/app_tps.go index 062385144..43ab2a68c 100644 --- a/core/app_tps.go +++ b/core/app_tps.go @@ -101,6 +101,7 @@ func (app *application) tpsUpdatePermissions(permissions []model.Permission, acc permission.ID = uuid.NewString() permission.ServiceID = serviceReg.Registration.ServiceID + permission.ServiceManaged = true permission.Inactive = false permission.DateCreated = now activePermissions = append(activePermissions, permission) @@ -114,11 +115,15 @@ func (app *application) tpsUpdatePermissions(permissions []model.Permission, acc for _, name := range removed { permission := currentNamesMap[name] if !permission.Inactive { - permission.Inactive = true - permission.DateUpdated = &now - err = app.storage.UpdatePermission(context, permission) - if err != nil { - return errors.WrapErrorAction(logutils.ActionUpdate, model.TypePermission, &logutils.FieldArgs{"name": name}, err) + if permission.ServiceManaged { + permission.Inactive = true + permission.DateUpdated = &now + err = app.storage.UpdatePermission(context, permission) + if err != nil { + return errors.WrapErrorAction(logutils.ActionUpdate, model.TypePermission, &logutils.FieldArgs{"name": name}, err) + } + } else { + activePermissions = append(activePermissions, permission) } } } diff --git a/core/interfaces.go b/core/interfaces.go index 93d6300ff..712413f5a 100644 --- a/core/interfaces.go +++ b/core/interfaces.go @@ -110,8 +110,8 @@ type System interface { SysGetApplication(ID string) (*model.Application, error) SysGetApplications() ([]model.Application, error) - SysCreatePermission(name string, description string, serviceID string, assigners *[]string, adminManaged bool, inactive bool) (*model.Permission, error) - SysUpdatePermission(name string, description string, serviceID string, assigners *[]string, adminManaged bool, inactive bool) (*model.Permission, error) + SysCreatePermission(name string, description string, serviceID string, assigners *[]string, serviceManaged bool, inactive bool) (*model.Permission, error) + SysUpdatePermission(name string, description string, serviceID string, assigners *[]string, serviceManaged bool, inactive bool) (*model.Permission, error) SysGetAppConfigs(appTypeID string, orgID *string, versionNumbers *model.VersionNumbers) ([]model.ApplicationConfig, error) SysGetAppConfig(id string) (*model.ApplicationConfig, error) diff --git a/core/model/application.go b/core/model/application.go index ff385842a..23fcfda0f 100644 --- a/core/model/application.go +++ b/core/model/application.go @@ -64,8 +64,8 @@ type Permission struct { ServiceID string `bson:"service_id"` Assigners []string `bson:"assigners"` - AdminManaged bool `bson:"admin_managed"` - Inactive bool `bson:"inactive"` + ServiceManaged bool `bson:"service_managed"` + Inactive bool `bson:"inactive"` DateCreated time.Time `bson:"date_created"` DateUpdated *time.Time `bson:"date_updated"` diff --git a/driven/storage/adapter.go b/driven/storage/adapter.go index 754d00edb..8d291a5be 100644 --- a/driven/storage/adapter.go +++ b/driven/storage/adapter.go @@ -2264,7 +2264,7 @@ func (sa *Adapter) updatePermission(context TransactionContext, item model.Permi primitive.E{Key: "description", Value: item.Description}, primitive.E{Key: "service_id", Value: item.ServiceID}, primitive.E{Key: "assigners", Value: item.Assigners}, - primitive.E{Key: "admin_managed", Value: item.AdminManaged}, + primitive.E{Key: "service_managed", Value: item.ServiceManaged}, primitive.E{Key: "inactive", Value: item.Inactive}, primitive.E{Key: "date_updated", Value: item.DateUpdated}, }}, @@ -2322,7 +2322,7 @@ func (sa *Adapter) updatePermission(context TransactionContext, item model.Permi primitive.E{Key: "permissions.$.description", Value: item.Description}, primitive.E{Key: "permissions.$.service_id", Value: item.ServiceID}, primitive.E{Key: "permissions.$.assigners", Value: item.Assigners}, - primitive.E{Key: "permissions.$.admin_managed", Value: item.AdminManaged}, + primitive.E{Key: "permissions.$.service_managed", Value: item.ServiceManaged}, primitive.E{Key: "permissions.$.inactive", Value: item.Inactive}, primitive.E{Key: "permissions.$.date_updated", Value: item.DateUpdated}, }}, diff --git a/driver/web/apis_system.go b/driver/web/apis_system.go index e4d7668fb..d092b8bcc 100644 --- a/driver/web/apis_system.go +++ b/driver/web/apis_system.go @@ -721,15 +721,15 @@ func (h SystemApisHandler) createPermission(l *logs.Log, r *http.Request, claims return l.HttpResponseErrorAction(logutils.ActionUnmarshal, model.TypePermission, nil, err, http.StatusBadRequest, true) } - adminManaged := false - if requestData.AdminManaged != nil { - adminManaged = *requestData.AdminManaged + serviceManaged := false + if requestData.ServiceManaged != nil { + serviceManaged = *requestData.ServiceManaged } inactive := false if requestData.Inactive != nil { inactive = *requestData.Inactive } - permission, err := h.coreAPIs.System.SysCreatePermission(requestData.Name, requestData.Description, requestData.ServiceId, requestData.Assigners, adminManaged, inactive) + permission, err := h.coreAPIs.System.SysCreatePermission(requestData.Name, requestData.Description, requestData.ServiceId, requestData.Assigners, serviceManaged, inactive) if err != nil { return l.HttpResponseErrorAction(logutils.ActionCreate, model.TypePermission, nil, err, http.StatusInternalServerError, true) } @@ -756,15 +756,15 @@ func (h SystemApisHandler) updatePermission(l *logs.Log, r *http.Request, claims return l.HttpResponseErrorAction(logutils.ActionUnmarshal, model.TypePermission, nil, err, http.StatusBadRequest, true) } - adminManaged := false - if requestData.AdminManaged != nil { - adminManaged = *requestData.AdminManaged + serviceManaged := false + if requestData.ServiceManaged != nil { + serviceManaged = *requestData.ServiceManaged } inactive := false if requestData.Inactive != nil { inactive = *requestData.Inactive } - permission, err := h.coreAPIs.System.SysUpdatePermission(requestData.Name, requestData.Description, requestData.ServiceId, requestData.Assigners, adminManaged, inactive) + permission, err := h.coreAPIs.System.SysUpdatePermission(requestData.Name, requestData.Description, requestData.ServiceId, requestData.Assigners, serviceManaged, inactive) if err != nil { return l.HttpResponseErrorAction(logutils.ActionUpdate, model.TypePermission, nil, err, http.StatusInternalServerError, true) } diff --git a/driver/web/conversions_application.go b/driver/web/conversions_application.go index ae7d59120..1c11e1e53 100644 --- a/driver/web/conversions_application.go +++ b/driver/web/conversions_application.go @@ -81,6 +81,9 @@ func applicationPermissionToDef(item model.Permission) Def.Permission { assigners = make([]string, 0) } + serviceManaged := &item.ServiceManaged + inactive := &item.Inactive + //dates var dateUpdated *string dateCreated := utils.FormatTime(&item.DateCreated) @@ -89,15 +92,14 @@ func applicationPermissionToDef(item model.Permission) Def.Permission { dateUpdated = &formatted } - return Def.Permission{Id: item.ID, Name: item.Name, Description: item.Description, ServiceId: item.ServiceID, Assigners: &assigners, DateCreated: &dateCreated, DateUpdated: dateUpdated} + return Def.Permission{Id: item.ID, Name: item.Name, Description: item.Description, ServiceId: item.ServiceID, Assigners: &assigners, + ServiceManaged: serviceManaged, Inactive: inactive, DateCreated: &dateCreated, DateUpdated: dateUpdated} } func applicationPermissionFromDef(item Def.Permission) model.Permission { assigners := make([]string, 0) if item.Assigners != nil { - for _, a := range *item.Assigners { - assigners = append(assigners, a) - } + assigners = append(assigners, *item.Assigners...) } return model.Permission{Name: item.Name, Description: item.Description, Assigners: assigners} diff --git a/driver/web/docs/gen/def.yaml b/driver/web/docs/gen/def.yaml index 61af66d91..d0a0eeb8f 100644 --- a/driver/web/docs/gen/def.yaml +++ b/driver/web/docs/gen/def.yaml @@ -4734,7 +4734,7 @@ components: type: array items: type: string - admin_managed: + service_managed: type: boolean inactive: type: boolean @@ -6458,7 +6458,7 @@ components: description: permissions that could assign current permission to accounts items: type: string - admin_managed: + service_managed: type: boolean inactive: type: boolean diff --git a/driver/web/docs/gen/gen_types.go b/driver/web/docs/gen/gen_types.go index 96efa56eb..643cab97a 100644 --- a/driver/web/docs/gen/gen_types.go +++ b/driver/web/docs/gen/gen_types.go @@ -513,15 +513,15 @@ type PartialAccount struct { // Permission defines model for Permission. type Permission struct { - AdminManaged *bool `json:"admin_managed,omitempty"` - Assigners *[]string `json:"assigners,omitempty"` - DateCreated *string `json:"date_created,omitempty"` - DateUpdated *string `json:"date_updated,omitempty"` - Description string `json:"description"` - Id string `json:"id"` - Inactive *bool `json:"inactive,omitempty"` - Name string `json:"name"` - ServiceId string `json:"service_id"` + Assigners *[]string `json:"assigners,omitempty"` + DateCreated *string `json:"date_created,omitempty"` + DateUpdated *string `json:"date_updated,omitempty"` + Description string `json:"description"` + Id string `json:"id"` + Inactive *bool `json:"inactive,omitempty"` + Name string `json:"name"` + ServiceId string `json:"service_id"` + ServiceManaged *bool `json:"service_managed,omitempty"` } // Profile defines model for Profile. @@ -1139,14 +1139,14 @@ type SystemReqCreateServiceAccount struct { // SystemReqPermissions defines model for _system_req_permissions. type SystemReqPermissions struct { - AdminManaged *bool `json:"admin_managed,omitempty"` // permissions that could assign current permission to accounts - Assigners *[]string `json:"assigners,omitempty"` - Description string `json:"description"` - Inactive *bool `json:"inactive,omitempty"` - Name string `json:"name"` - ServiceId string `json:"service_id"` + Assigners *[]string `json:"assigners,omitempty"` + Description string `json:"description"` + Inactive *bool `json:"inactive,omitempty"` + Name string `json:"name"` + ServiceId string `json:"service_id"` + ServiceManaged *bool `json:"service_managed,omitempty"` } // SystemReqUpdateOrganization defines model for _system_req_update_Organization. diff --git a/driver/web/docs/schemas/apis/system/permissions/request/Request.yaml b/driver/web/docs/schemas/apis/system/permissions/request/Request.yaml index 36cd2f6a1..251f394e9 100644 --- a/driver/web/docs/schemas/apis/system/permissions/request/Request.yaml +++ b/driver/web/docs/schemas/apis/system/permissions/request/Request.yaml @@ -15,7 +15,7 @@ properties: description: permissions that could assign current permission to accounts items: type: string - admin_managed: + service_managed: type: boolean inactive: type: boolean \ No newline at end of file diff --git a/driver/web/docs/schemas/application/Permission.yaml b/driver/web/docs/schemas/application/Permission.yaml index 596496fca..7c7c08e5c 100644 --- a/driver/web/docs/schemas/application/Permission.yaml +++ b/driver/web/docs/schemas/application/Permission.yaml @@ -19,7 +19,7 @@ properties: type: array items: type: string - admin_managed: + service_managed: type: boolean inactive: type: boolean From 8427b3aa75a6c8397aefa062e399a033dffe932d Mon Sep 17 00:00:00 2001 From: Ryan Oberlander Date: Fri, 5 Aug 2022 13:39:16 -0500 Subject: [PATCH 30/32] update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 75ecb15cf..5ced780c1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] ### Added +- Allow services to manage their own permissions [#475](https://github.com/rokwire/core-building-block/issues/475) - Update role permissions admin API [#516](https://github.com/rokwire/core-building-block/issues/516) - Update group admin API [#518](https://github.com/rokwire/core-building-block/issues/518) - Allow passing nil context to WithContext storage functions [#494](https://github.com/rokwire/core-building-block/issues/494) From 4b1c15ad0774c6fff1d676eba794eb9509430828 Mon Sep 17 00:00:00 2001 From: Ryan Oberlander Date: Fri, 5 Aug 2022 14:19:51 -0500 Subject: [PATCH 31/32] fix inactive flag update --- core/app_bbs.go | 4 ++-- core/app_tps.go | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/core/app_bbs.go b/core/app_bbs.go index 2ee4d425f..0c4e160f9 100644 --- a/core/app_bbs.go +++ b/core/app_bbs.go @@ -139,12 +139,12 @@ func (app *application) bbsUpdatePermissions(permissions []model.Permission, acc description := newPermission.Description assigners := newPermission.Assigners - updated := currentPermission.Inactive || (description != currentPermission.Description) || !utils.DeepEqual(assigners, currentPermission.Assigners) + updated := (currentPermission.Inactive && currentPermission.ServiceManaged) || (description != currentPermission.Description) || !utils.DeepEqual(assigners, currentPermission.Assigners) newPermission = currentPermission if updated { newPermission.Description = description newPermission.Assigners = assigners - newPermission.Inactive = false + newPermission.Inactive = newPermission.Inactive && !newPermission.ServiceManaged newPermission.DateUpdated = &now err = app.storage.UpdatePermission(context, newPermission) if err != nil { diff --git a/core/app_tps.go b/core/app_tps.go index 43ab2a68c..9497d453b 100644 --- a/core/app_tps.go +++ b/core/app_tps.go @@ -139,12 +139,12 @@ func (app *application) tpsUpdatePermissions(permissions []model.Permission, acc description := newPermission.Description assigners := newPermission.Assigners - updated := currentPermission.Inactive || (description != currentPermission.Description) || !utils.DeepEqual(assigners, currentPermission.Assigners) + updated := (currentPermission.Inactive && currentPermission.ServiceManaged) || (description != currentPermission.Description) || !utils.DeepEqual(assigners, currentPermission.Assigners) newPermission = currentPermission if updated { newPermission.Description = description newPermission.Assigners = assigners - newPermission.Inactive = false + newPermission.Inactive = newPermission.Inactive && !newPermission.ServiceManaged newPermission.DateUpdated = &now err = app.storage.UpdatePermission(context, newPermission) if err != nil { From 302b483afa524c720702f7e169ad399079cf7e8d Mon Sep 17 00:00:00 2001 From: Ryan Oberlander Date: Mon, 8 Aug 2022 12:33:20 -0500 Subject: [PATCH 32/32] only return success string, don't require description in request, only update assigners list if given [#475] --- core/app_bbs.go | 11 +++++++++-- core/app_tps.go | 11 +++++++++-- driver/web/apis_bbs.go | 14 +++++++------- driver/web/apis_tps.go | 12 ++++++------ driver/web/conversions_application.go | 13 +++++++++---- driver/web/docs/gen/def.yaml | 14 +++++--------- driver/web/docs/gen/gen_types.go | 2 +- driver/web/docs/resources/bbs/permissions.yaml | 6 ++---- driver/web/docs/resources/tps/permissions.yaml | 6 ++---- .../web/docs/schemas/application/Permission.yaml | 2 +- 10 files changed, 51 insertions(+), 40 deletions(-) diff --git a/core/app_bbs.go b/core/app_bbs.go index 0c4e160f9..92fa75e3c 100644 --- a/core/app_bbs.go +++ b/core/app_bbs.go @@ -138,12 +138,19 @@ func (app *application) bbsUpdatePermissions(permissions []model.Permission, acc } description := newPermission.Description + if description == "" { + description = currentPermission.Description + } + assignersGiven := newPermission.Assigners != nil assigners := newPermission.Assigners - updated := (currentPermission.Inactive && currentPermission.ServiceManaged) || (description != currentPermission.Description) || !utils.DeepEqual(assigners, currentPermission.Assigners) + + updated := (currentPermission.Inactive && currentPermission.ServiceManaged) || (description != currentPermission.Description) || (assignersGiven && !utils.DeepEqual(assigners, currentPermission.Assigners)) newPermission = currentPermission if updated { newPermission.Description = description - newPermission.Assigners = assigners + if assignersGiven { + newPermission.Assigners = assigners + } newPermission.Inactive = newPermission.Inactive && !newPermission.ServiceManaged newPermission.DateUpdated = &now err = app.storage.UpdatePermission(context, newPermission) diff --git a/core/app_tps.go b/core/app_tps.go index 9497d453b..1128394b0 100644 --- a/core/app_tps.go +++ b/core/app_tps.go @@ -138,12 +138,19 @@ func (app *application) tpsUpdatePermissions(permissions []model.Permission, acc } description := newPermission.Description + if description == "" { + description = currentPermission.Description + } + assignersGiven := newPermission.Assigners != nil assigners := newPermission.Assigners - updated := (currentPermission.Inactive && currentPermission.ServiceManaged) || (description != currentPermission.Description) || !utils.DeepEqual(assigners, currentPermission.Assigners) + + updated := (currentPermission.Inactive && currentPermission.ServiceManaged) || (description != currentPermission.Description) || (assignersGiven && !utils.DeepEqual(assigners, currentPermission.Assigners)) newPermission = currentPermission if updated { newPermission.Description = description - newPermission.Assigners = assigners + if assignersGiven { + newPermission.Assigners = assigners + } newPermission.Inactive = newPermission.Inactive && !newPermission.ServiceManaged newPermission.DateUpdated = &now err = app.storage.UpdatePermission(context, newPermission) diff --git a/driver/web/apis_bbs.go b/driver/web/apis_bbs.go index 4755680b4..df2fb4877 100644 --- a/driver/web/apis_bbs.go +++ b/driver/web/apis_bbs.go @@ -176,18 +176,18 @@ func (h BBsApisHandler) updatePermissions(l *logs.Log, r *http.Request, claims * } permissions := applicationPermissionsFromDef(requestData) - permissions, err = h.coreAPIs.BBs.BBsUpdatePermissions(permissions, claims.Subject) + _, err = h.coreAPIs.BBs.BBsUpdatePermissions(permissions, claims.Subject) if err != nil { return l.HttpResponseErrorAction(logutils.ActionUpdate, model.TypePermission, nil, err, http.StatusInternalServerError, true) } - permissionsResp := applicationPermissionsToDef(permissions) - respData, err := json.Marshal(permissionsResp) - if err != nil { - return l.HttpResponseErrorAction(logutils.ActionMarshal, logutils.MessageDataType("permissions response"), nil, err, http.StatusInternalServerError, false) - } + // permissionsResp := applicationPermissionsToDef(permissions) + // respData, err := json.Marshal(permissionsResp) + // if err != nil { + // return l.HttpResponseErrorAction(logutils.ActionMarshal, logutils.MessageDataType("permissions response"), nil, err, http.StatusInternalServerError, false) + // } - return l.HttpResponseSuccessJSON(respData) + return l.HttpResponseSuccess() } // NewBBsApisHandler creates new bbs Handler instance diff --git a/driver/web/apis_tps.go b/driver/web/apis_tps.go index 7a6c071cd..07750df8e 100644 --- a/driver/web/apis_tps.go +++ b/driver/web/apis_tps.go @@ -191,17 +191,17 @@ func (h TPSApisHandler) updatePermissions(l *logs.Log, r *http.Request, claims * } permissions := applicationPermissionsFromDef(requestData) - permissions, err = h.coreAPIs.TPs.TPsUpdatePermissions(permissions, claims.Subject) + _, err = h.coreAPIs.TPs.TPsUpdatePermissions(permissions, claims.Subject) if err != nil { return l.HttpResponseErrorAction(logutils.ActionUpdate, model.TypePermission, nil, err, http.StatusInternalServerError, true) } - respData, err := json.Marshal(permissions) - if err != nil { - return l.HttpResponseErrorAction(logutils.ActionMarshal, logutils.MessageDataType("service access tokens response"), nil, err, http.StatusInternalServerError, false) - } + // respData, err := json.Marshal(permissions) + // if err != nil { + // return l.HttpResponseErrorAction(logutils.ActionMarshal, logutils.MessageDataType("service access tokens response"), nil, err, http.StatusInternalServerError, false) + // } - return l.HttpResponseSuccessJSON(respData) + return l.HttpResponseSuccess() } // NewTPSApisHandler creates new tps Handler instance diff --git a/driver/web/conversions_application.go b/driver/web/conversions_application.go index 1c11e1e53..7a79aab82 100644 --- a/driver/web/conversions_application.go +++ b/driver/web/conversions_application.go @@ -81,6 +81,7 @@ func applicationPermissionToDef(item model.Permission) Def.Permission { assigners = make([]string, 0) } + description := &item.Description serviceManaged := &item.ServiceManaged inactive := &item.Inactive @@ -92,17 +93,21 @@ func applicationPermissionToDef(item model.Permission) Def.Permission { dateUpdated = &formatted } - return Def.Permission{Id: item.ID, Name: item.Name, Description: item.Description, ServiceId: item.ServiceID, Assigners: &assigners, + return Def.Permission{Id: item.ID, Name: item.Name, Description: description, ServiceId: item.ServiceID, Assigners: &assigners, ServiceManaged: serviceManaged, Inactive: inactive, DateCreated: &dateCreated, DateUpdated: dateUpdated} } func applicationPermissionFromDef(item Def.Permission) model.Permission { - assigners := make([]string, 0) + description := "" + if item.Description != nil { + description = *item.Description + } + var assigners []string if item.Assigners != nil { - assigners = append(assigners, *item.Assigners...) + assigners = *item.Assigners } - return model.Permission{Name: item.Name, Description: item.Description, Assigners: assigners} + return model.Permission{Name: item.Name, Description: description, Assigners: assigners} } func applicationPermissionsToDef(items []model.Permission) []Def.Permission { diff --git a/driver/web/docs/gen/def.yaml b/driver/web/docs/gen/def.yaml index db3a8fb91..b91c156a8 100644 --- a/driver/web/docs/gen/def.yaml +++ b/driver/web/docs/gen/def.yaml @@ -3011,11 +3011,9 @@ paths: '200': description: Success content: - application/json: + text/plain: schema: - type: array - items: - $ref: '#/components/schemas/Permission' + type: string '400': description: Bad request '401': @@ -3263,11 +3261,9 @@ paths: '200': description: Success content: - application/json: + text/plain: schema: - type: array - items: - $ref: '#/components/schemas/Permission' + type: string '400': description: Bad request '401': @@ -4815,7 +4811,6 @@ components: required: - id - name - - description - service_id type: object properties: @@ -4825,6 +4820,7 @@ components: name: type: string description: + readOnly: true type: string service_id: readOnly: true diff --git a/driver/web/docs/gen/gen_types.go b/driver/web/docs/gen/gen_types.go index 8419513e7..f23eb4076 100644 --- a/driver/web/docs/gen/gen_types.go +++ b/driver/web/docs/gen/gen_types.go @@ -518,7 +518,7 @@ type Permission struct { Assigners *[]string `json:"assigners,omitempty"` DateCreated *string `json:"date_created,omitempty"` DateUpdated *string `json:"date_updated,omitempty"` - Description string `json:"description"` + Description *string `json:"description,omitempty"` Id string `json:"id"` Inactive *bool `json:"inactive,omitempty"` Name string `json:"name"` diff --git a/driver/web/docs/resources/bbs/permissions.yaml b/driver/web/docs/resources/bbs/permissions.yaml index 8d66a0602..cd30d6f19 100644 --- a/driver/web/docs/resources/bbs/permissions.yaml +++ b/driver/web/docs/resources/bbs/permissions.yaml @@ -21,11 +21,9 @@ put: 200: description: Success content: - application/json: + text/plain: schema: - type: array - items: - $ref: "../../schemas/application/Permission.yaml" + type: string 400: description: Bad request 401: diff --git a/driver/web/docs/resources/tps/permissions.yaml b/driver/web/docs/resources/tps/permissions.yaml index 5ad242adc..058083ebf 100644 --- a/driver/web/docs/resources/tps/permissions.yaml +++ b/driver/web/docs/resources/tps/permissions.yaml @@ -21,11 +21,9 @@ put: 200: description: Success content: - application/json: + text/plain: schema: - type: array - items: - $ref: "../../schemas/application/Permission.yaml" + type: string 400: description: Bad request 401: diff --git a/driver/web/docs/schemas/application/Permission.yaml b/driver/web/docs/schemas/application/Permission.yaml index 7c7c08e5c..510bcf0d9 100644 --- a/driver/web/docs/schemas/application/Permission.yaml +++ b/driver/web/docs/schemas/application/Permission.yaml @@ -1,7 +1,6 @@ required: - id - name - - description - service_id type: object properties: @@ -11,6 +10,7 @@ properties: name: type: string description: + readOnly: true type: string service_id: readOnly: true