diff --git a/client-code-gen/admin-management-openapi.json b/client-code-gen/admin-management-openapi.json index 40250b6ab..e63816203 100644 --- a/client-code-gen/admin-management-openapi.json +++ b/client-code-gen/admin-management-openapi.json @@ -1 +1 @@ -{"openapi":"3.0.3","info":{"title":"Forest Access Management - FAM - Admin Management API","description":"\nForest Access Management Admin Management API used by the Forest Access Management application\nto define admin access to forest applications.\n","contact":{"name":"Team Heartwood","url":"https://apps.nrs.gov.bc.ca/int/confluence/display/FSAST1/Team+Heartwood","email":"SIBIFSAF@Victoria1.gov.bc.ca"},"license":{"name":"Apache 2.0","url":"https://www.apache.org/licenses/LICENSE-2.0.html"},"version":"0.0.1"},"paths":{"/smoke_test":{"get":{"tags":["Smoke Test"],"summary":"Smoke Test","description":"List of different applications that are administered by FAM","operationId":"smoke_test","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"6jfveou69mgford233or30hmta":[]}]}},"/application_admins":{"get":{"tags":["FAM Application Admin"],"summary":"Get Application Admins","operationId":"get_application_admins","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/FamAppAdminGetResponse"},"type":"array","title":"Response Get Application Admins"}}}}},"security":[{"6jfveou69mgford233or30hmta":[]}]},"post":{"tags":["FAM Application Admin"],"summary":"Create Application Admin","operationId":"create_application_admin","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FamAppAdminCreateRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FamAppAdminGetResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"6jfveou69mgford233or30hmta":[]}]}},"/application_admins/{application_admin_id}":{"delete":{"tags":["FAM Application Admin"],"summary":"Delete Application Admin","operationId":"delete_application_admin","security":[{"6jfveou69mgford233or30hmta":[]}],"parameters":[{"name":"application_admin_id","in":"path","required":true,"schema":{"type":"integer","title":"Application Admin Id"}}],"responses":{"200":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/applications":{"get":{"tags":["FAM Applications"],"summary":"Get Applications","operationId":"get_applications","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/FamApplicationGetResponse"},"type":"array","title":"Response Get Applications"}}}}},"security":[{"6jfveou69mgford233or30hmta":[]}]}},"/access_control_privileges":{"post":{"tags":["FAM Access Control Privileges"],"summary":"Create Access Control Privilege Many","description":"Grant Delegated Admin Privileges","operationId":"create_access_control_privilege_many","security":[{"6jfveou69mgford233or30hmta":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FamAccessControlPrivilegeCreateRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/FamAccessControlPrivilegeCreateResponse"},"title":"Response Create Access Control Privilege Many"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"tags":["FAM Access Control Privileges"],"summary":"Get Access Control Privileges By Application Id","description":"Get Delegated Admin Privileges For an Application","operationId":"get_access_control_privileges_by_application_id","security":[{"6jfveou69mgford233or30hmta":[]}],"parameters":[{"name":"application_id","in":"query","required":true,"schema":{"type":"integer","title":"Application Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/FamAccessControlPrivilegeGetResponse"},"title":"Response Get Access Control Privileges By Application Id"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin-user-accesses":{"get":{"tags":["Admin User Accesses"],"summary":"Admin User Access Privilege","description":"Access privilege for logged on admin user for what applications/roles(scoped) the user can grant.","operationId":"Admin user access privilege","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminUserAccessResponse"}}}}},"security":[{"6jfveou69mgford233or30hmta":[]}]}}},"components":{"schemas":{"AdminRoleAuthGroup":{"type":"string","enum":["FAM_ADMIN","APP_ADMIN","DELEGATED_ADMIN"],"title":"AdminRoleAuthGroup","description":"FAM data model does not explicitly have these role group of admins.\nHowever, business rules do differentiate purpose of admins as:\n (FAM_ADMIN, [APP]_ADMIN, DELEGATED_ADMIN)\n# Referencing to FAM confluence for design:\n https://apps.nrs.gov.bc.ca/int/confluence/display/FSAST1/Delegated+Access+Administration+Design (Auth Function)"},"AdminUserAccessResponse":{"properties":{"access":{"items":{"$ref":"#/components/schemas/FamAuthGrantDto"},"type":"array","title":"Access"}},"type":"object","required":["access"],"title":"AdminUserAccessResponse"},"AppEnv":{"type":"string","enum":["DEV","TEST","PROD"],"title":"AppEnv"},"FamAccessControlPrivilegeCreateRequest":{"properties":{"user_name":{"type":"string","maxLength":20,"minLength":3,"title":"User Name"},"user_type_code":{"$ref":"#/components/schemas/UserType"},"role_id":{"type":"integer","title":"Role Id"},"forest_client_numbers":{"anyOf":[{"items":{"type":"string","maxLength":8,"minLength":1},"type":"array"},{"type":"null"}],"title":"Forest Client Numbers"}},"type":"object","required":["user_name","user_type_code","role_id"],"title":"FamAccessControlPrivilegeCreateRequest","description":"This is used at router level, the data we receive from frontend.\nUse username and user_type_code to get user_id,\nand for concrete role, can use its role_id directly,\nbut for abstract role, need to create/get child role_id based on the forest client number,\nand then use schema FamAccessControlPrivilegeCreateDto to insert into the database"},"FamAccessControlPrivilegeCreateResponse":{"properties":{"status_code":{"type":"integer","title":"Status Code"},"detail":{"$ref":"#/components/schemas/FamAccessControlPrivilegeGetResponse"},"error_message":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error Message"}},"type":"object","required":["status_code","detail"],"title":"FamAccessControlPrivilegeCreateResponse"},"FamAccessControlPrivilegeGetResponse":{"properties":{"access_control_privilege_id":{"type":"integer","title":"Access Control Privilege Id"},"user_id":{"type":"integer","title":"User Id"},"role_id":{"type":"integer","title":"Role Id"},"user":{"$ref":"#/components/schemas/FamUserInfoDto"},"role":{"$ref":"#/components/schemas/FamRoleWithClientDto"}},"type":"object","required":["access_control_privilege_id","user_id","role_id","user","role"],"title":"FamAccessControlPrivilegeGetResponse"},"FamAppAdminCreateRequest":{"properties":{"user_name":{"type":"string","maxLength":20,"minLength":3,"title":"User Name"},"user_type_code":{"$ref":"#/components/schemas/UserType"},"application_id":{"type":"integer","title":"Application Id"}},"type":"object","required":["user_name","user_type_code","application_id"],"title":"FamAppAdminCreateRequest"},"FamAppAdminGetResponse":{"properties":{"application_admin_id":{"type":"integer","title":"Application Admin Id"},"user_id":{"type":"integer","title":"User Id"},"application_id":{"type":"integer","title":"Application Id"},"user":{"$ref":"#/components/schemas/FamUserInfoDto"},"application":{"$ref":"#/components/schemas/FamApplicationBase"}},"type":"object","required":["application_admin_id","user_id","application_id","user","application"],"title":"FamAppAdminGetResponse"},"FamApplicationBase":{"properties":{"application_name":{"type":"string","maxLength":100,"title":"Application Name"},"application_description":{"type":"string","maxLength":200,"title":"Application Description"},"app_environment":{"anyOf":[{"$ref":"#/components/schemas/AppEnv"},{"type":"null"}]}},"type":"object","required":["application_name","application_description"],"title":"FamApplicationBase"},"FamApplicationDto":{"properties":{"id":{"type":"integer","title":"Id"},"name":{"type":"string","maxLength":100,"title":"Name"},"description":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Description"},"env":{"anyOf":[{"$ref":"#/components/schemas/AppEnv"},{"type":"null"}]}},"type":"object","required":["id","name"],"title":"FamApplicationDto"},"FamApplicationGetResponse":{"properties":{"application_name":{"type":"string","maxLength":100,"title":"Application Name"},"application_description":{"type":"string","maxLength":200,"title":"Application Description"},"app_environment":{"anyOf":[{"$ref":"#/components/schemas/AppEnv"},{"type":"null"}]},"application_id":{"type":"integer","title":"Application Id"}},"type":"object","required":["application_name","application_description","application_id"],"title":"FamApplicationGetResponse"},"FamAuthGrantDto":{"properties":{"auth_key":{"$ref":"#/components/schemas/AdminRoleAuthGroup"},"grants":{"items":{"$ref":"#/components/schemas/FamGrantDetailDto"},"type":"array","title":"Grants"}},"type":"object","required":["auth_key","grants"],"title":"FamAuthGrantDto"},"FamForestClientBase":{"properties":{"forest_client_number":{"type":"string","maxLength":8,"title":"Forest Client Number"}},"type":"object","required":["forest_client_number"],"title":"FamForestClientBase"},"FamGrantDetailDto":{"properties":{"application":{"$ref":"#/components/schemas/FamApplicationDto"},"roles":{"anyOf":[{"items":{"$ref":"#/components/schemas/FamRoleDto"},"type":"array"},{"type":"null"}],"title":"Roles"}},"type":"object","required":["application"],"title":"FamGrantDetailDto"},"FamRoleBase":{"properties":{"role_name":{"type":"string","maxLength":100,"title":"Role Name"},"role_type_code":{"$ref":"#/components/schemas/RoleType"}},"type":"object","required":["role_name","role_type_code"],"title":"FamRoleBase"},"FamRoleDto":{"properties":{"id":{"type":"integer","title":"Id"},"name":{"type":"string","maxLength":100,"title":"Name"},"type_code":{"$ref":"#/components/schemas/RoleType"},"forest_clients":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Forest Clients"}},"type":"object","required":["id","name","type_code"],"title":"FamRoleDto"},"FamRoleWithClientDto":{"properties":{"role_id":{"type":"integer","title":"Role Id"},"role_name":{"type":"string","maxLength":100,"title":"Role Name"},"client_number":{"anyOf":[{"$ref":"#/components/schemas/FamForestClientBase"},{"type":"null"}]},"parent_role":{"anyOf":[{"$ref":"#/components/schemas/FamRoleBase"},{"type":"null"}]}},"type":"object","required":["role_id","role_name"],"title":"FamRoleWithClientDto"},"FamUserInfoDto":{"properties":{"user_name":{"type":"string","maxLength":20,"title":"User Name"},"user_type":{"$ref":"#/components/schemas/FamUserTypeDto"}},"type":"object","required":["user_name","user_type"],"title":"FamUserInfoDto"},"FamUserTypeDto":{"properties":{"code":{"$ref":"#/components/schemas/UserType"},"description":{"type":"string","maxLength":35,"title":"Description"}},"type":"object","required":["code","description"],"title":"FamUserTypeDto"},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"RoleType":{"type":"string","enum":["A","C"],"title":"RoleType"},"UserType":{"type":"string","enum":["I","B"],"title":"UserType"},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"}},"securitySchemes":{"6jfveou69mgford233or30hmta":{"type":"oauth2","flows":{"authorizationCode":{"scopes":{},"authorizationUrl":"https://dev-fam-user-pool-domain.auth.ca-central-1.amazoncognito.com/authorize","tokenUrl":"https://dev-fam-user-pool-domain.auth.ca-central-1.amazoncognito.com/token"}}}}}} \ No newline at end of file +{"openapi":"3.0.3","info":{"title":"Forest Access Management - FAM - Admin Management API","description":"\nForest Access Management Admin Management API used by the Forest Access Management application\nto define admin access to forest applications.\n","contact":{"name":"Team Heartwood","url":"https://apps.nrs.gov.bc.ca/int/confluence/display/FSAST1/Team+Heartwood","email":"SIBIFSAF@Victoria1.gov.bc.ca"},"license":{"name":"Apache 2.0","url":"https://www.apache.org/licenses/LICENSE-2.0.html"},"version":"0.0.1"},"paths":{"/smoke_test":{"get":{"tags":["Smoke Test"],"summary":"Smoke Test","description":"List of different applications that are administered by FAM","operationId":"smoke_test","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"6jfveou69mgford233or30hmta":[]}]}},"/application_admins":{"get":{"tags":["FAM Application Admin"],"summary":"Get Application Admins","operationId":"get_application_admins","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/FamAppAdminGetResponse"},"type":"array","title":"Response Get Application Admins"}}}}},"security":[{"6jfveou69mgford233or30hmta":[]}]},"post":{"tags":["FAM Application Admin"],"summary":"Create Application Admin","operationId":"create_application_admin","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FamAppAdminCreateRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FamAppAdminGetResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"6jfveou69mgford233or30hmta":[]}]}},"/application_admins/{application_admin_id}":{"delete":{"tags":["FAM Application Admin"],"summary":"Delete Application Admin","operationId":"delete_application_admin","security":[{"6jfveou69mgford233or30hmta":[]}],"parameters":[{"name":"application_admin_id","in":"path","required":true,"schema":{"type":"integer","title":"Application Admin Id"}}],"responses":{"200":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/applications":{"get":{"tags":["FAM Applications"],"summary":"Get Applications","operationId":"get_applications","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/FamApplicationGetResponse"},"type":"array","title":"Response Get Applications"}}}}},"security":[{"6jfveou69mgford233or30hmta":[]}]}},"/access_control_privileges":{"post":{"tags":["FAM Access Control Privileges"],"summary":"Create Access Control Privilege Many","description":"Grant Delegated Admin Privileges","operationId":"create_access_control_privilege_many","security":[{"6jfveou69mgford233or30hmta":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FamAccessControlPrivilegeCreateRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/FamAccessControlPrivilegeCreateResponse"},"title":"Response Create Access Control Privilege Many"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"tags":["FAM Access Control Privileges"],"summary":"Get Access Control Privileges By Application Id","description":"Get Delegated Admin Privileges For an Application","operationId":"get_access_control_privileges_by_application_id","security":[{"6jfveou69mgford233or30hmta":[]}],"parameters":[{"name":"application_id","in":"query","required":true,"schema":{"type":"integer","title":"Application Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/FamAccessControlPrivilegeGetResponse"},"title":"Response Get Access Control Privileges By Application Id"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/access_control_privileges/{access_control_privilege_id}":{"delete":{"tags":["FAM Access Control Privileges"],"summary":"Delete Access Control Privilege","operationId":"delete_access_control_privilege","security":[{"6jfveou69mgford233or30hmta":[]}],"parameters":[{"name":"access_control_privilege_id","in":"path","required":true,"schema":{"type":"integer","title":"Access Control Privilege Id"}}],"responses":{"200":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin-user-accesses":{"get":{"tags":["Admin User Accesses"],"summary":"Admin User Access Privilege","description":"Access privilege for logged on admin user for what applications/roles(scoped) the user can grant.","operationId":"Admin user access privilege","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminUserAccessResponse"}}}}},"security":[{"6jfveou69mgford233or30hmta":[]}]}}},"components":{"schemas":{"AdminRoleAuthGroup":{"type":"string","enum":["FAM_ADMIN","APP_ADMIN","DELEGATED_ADMIN"],"title":"AdminRoleAuthGroup","description":"FAM data model does not explicitly have these role group of admins.\nHowever, business rules do differentiate purpose of admins as:\n (FAM_ADMIN, [APP]_ADMIN, DELEGATED_ADMIN)\n# Referencing to FAM confluence for design:\n https://apps.nrs.gov.bc.ca/int/confluence/display/FSAST1/Delegated+Access+Administration+Design (Auth Function)"},"AdminUserAccessResponse":{"properties":{"access":{"items":{"$ref":"#/components/schemas/FamAuthGrantDto"},"type":"array","title":"Access"}},"type":"object","required":["access"],"title":"AdminUserAccessResponse"},"AppEnv":{"type":"string","enum":["DEV","TEST","PROD"],"title":"AppEnv"},"FamAccessControlPrivilegeCreateRequest":{"properties":{"user_name":{"type":"string","maxLength":20,"minLength":3,"title":"User Name"},"user_type_code":{"$ref":"#/components/schemas/UserType"},"role_id":{"type":"integer","title":"Role Id"},"forest_client_numbers":{"anyOf":[{"items":{"type":"string","maxLength":8,"minLength":1},"type":"array"},{"type":"null"}],"title":"Forest Client Numbers"}},"type":"object","required":["user_name","user_type_code","role_id"],"title":"FamAccessControlPrivilegeCreateRequest","description":"This is used at router level, the data we receive from frontend.\nUse username and user_type_code to get user_id,\nand for concrete role, can use its role_id directly,\nbut for abstract role, need to create/get child role_id based on the forest client number,\nand then use schema FamAccessControlPrivilegeCreateDto to insert into the database"},"FamAccessControlPrivilegeCreateResponse":{"properties":{"status_code":{"type":"integer","title":"Status Code"},"detail":{"$ref":"#/components/schemas/FamAccessControlPrivilegeGetResponse"},"error_message":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error Message"}},"type":"object","required":["status_code","detail"],"title":"FamAccessControlPrivilegeCreateResponse"},"FamAccessControlPrivilegeGetResponse":{"properties":{"access_control_privilege_id":{"type":"integer","title":"Access Control Privilege Id"},"user_id":{"type":"integer","title":"User Id"},"role_id":{"type":"integer","title":"Role Id"},"user":{"$ref":"#/components/schemas/FamUserInfoDto"},"role":{"$ref":"#/components/schemas/FamRoleWithClientDto"}},"type":"object","required":["access_control_privilege_id","user_id","role_id","user","role"],"title":"FamAccessControlPrivilegeGetResponse"},"FamAppAdminCreateRequest":{"properties":{"user_name":{"type":"string","maxLength":20,"minLength":3,"title":"User Name"},"user_type_code":{"$ref":"#/components/schemas/UserType"},"application_id":{"type":"integer","title":"Application Id"}},"type":"object","required":["user_name","user_type_code","application_id"],"title":"FamAppAdminCreateRequest"},"FamAppAdminGetResponse":{"properties":{"application_admin_id":{"type":"integer","title":"Application Admin Id"},"user_id":{"type":"integer","title":"User Id"},"application_id":{"type":"integer","title":"Application Id"},"user":{"$ref":"#/components/schemas/FamUserInfoDto"},"application":{"$ref":"#/components/schemas/FamApplicationBase"}},"type":"object","required":["application_admin_id","user_id","application_id","user","application"],"title":"FamAppAdminGetResponse"},"FamApplicationBase":{"properties":{"application_name":{"type":"string","maxLength":100,"title":"Application Name"},"application_description":{"type":"string","maxLength":200,"title":"Application Description"},"app_environment":{"anyOf":[{"$ref":"#/components/schemas/AppEnv"},{"type":"null"}]}},"type":"object","required":["application_name","application_description"],"title":"FamApplicationBase"},"FamApplicationDto":{"properties":{"id":{"type":"integer","title":"Id"},"name":{"type":"string","maxLength":100,"title":"Name"},"description":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Description"},"env":{"anyOf":[{"$ref":"#/components/schemas/AppEnv"},{"type":"null"}]}},"type":"object","required":["id","name"],"title":"FamApplicationDto"},"FamApplicationGetResponse":{"properties":{"application_name":{"type":"string","maxLength":100,"title":"Application Name"},"application_description":{"type":"string","maxLength":200,"title":"Application Description"},"app_environment":{"anyOf":[{"$ref":"#/components/schemas/AppEnv"},{"type":"null"}]},"application_id":{"type":"integer","title":"Application Id"}},"type":"object","required":["application_name","application_description","application_id"],"title":"FamApplicationGetResponse"},"FamAuthGrantDto":{"properties":{"auth_key":{"$ref":"#/components/schemas/AdminRoleAuthGroup"},"grants":{"items":{"$ref":"#/components/schemas/FamGrantDetailDto"},"type":"array","title":"Grants"}},"type":"object","required":["auth_key","grants"],"title":"FamAuthGrantDto"},"FamForestClientBase":{"properties":{"forest_client_number":{"type":"string","maxLength":8,"title":"Forest Client Number"}},"type":"object","required":["forest_client_number"],"title":"FamForestClientBase"},"FamGrantDetailDto":{"properties":{"application":{"$ref":"#/components/schemas/FamApplicationDto"},"roles":{"anyOf":[{"items":{"$ref":"#/components/schemas/FamRoleDto"},"type":"array"},{"type":"null"}],"title":"Roles"}},"type":"object","required":["application"],"title":"FamGrantDetailDto"},"FamRoleBase":{"properties":{"role_name":{"type":"string","maxLength":100,"title":"Role Name"},"role_type_code":{"$ref":"#/components/schemas/RoleType"}},"type":"object","required":["role_name","role_type_code"],"title":"FamRoleBase"},"FamRoleDto":{"properties":{"id":{"type":"integer","title":"Id"},"name":{"type":"string","maxLength":100,"title":"Name"},"type_code":{"$ref":"#/components/schemas/RoleType"},"forest_clients":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Forest Clients"}},"type":"object","required":["id","name","type_code"],"title":"FamRoleDto"},"FamRoleWithClientDto":{"properties":{"role_id":{"type":"integer","title":"Role Id"},"role_name":{"type":"string","maxLength":100,"title":"Role Name"},"client_number":{"anyOf":[{"$ref":"#/components/schemas/FamForestClientBase"},{"type":"null"}]},"parent_role":{"anyOf":[{"$ref":"#/components/schemas/FamRoleBase"},{"type":"null"}]}},"type":"object","required":["role_id","role_name"],"title":"FamRoleWithClientDto"},"FamUserInfoDto":{"properties":{"user_name":{"type":"string","maxLength":20,"title":"User Name"},"user_type":{"$ref":"#/components/schemas/FamUserTypeDto"}},"type":"object","required":["user_name","user_type"],"title":"FamUserInfoDto"},"FamUserTypeDto":{"properties":{"code":{"$ref":"#/components/schemas/UserType"},"description":{"type":"string","maxLength":35,"title":"Description"}},"type":"object","required":["code","description"],"title":"FamUserTypeDto"},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"RoleType":{"type":"string","enum":["A","C"],"title":"RoleType"},"UserType":{"type":"string","enum":["I","B"],"title":"UserType"},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"}},"securitySchemes":{"6jfveou69mgford233or30hmta":{"type":"oauth2","flows":{"authorizationCode":{"scopes":{},"authorizationUrl":"https://dev-fam-user-pool-domain.auth.ca-central-1.amazoncognito.com/authorize","tokenUrl":"https://dev-fam-user-pool-domain.auth.ca-central-1.amazoncognito.com/token"}}}}}} \ No newline at end of file diff --git a/client-code-gen/gen/admin-management-api/api/famaccess-control-privileges-api.ts b/client-code-gen/gen/admin-management-api/api/famaccess-control-privileges-api.ts index aa1cbf43b..d9c5701b5 100644 --- a/client-code-gen/gen/admin-management-api/api/famaccess-control-privileges-api.ts +++ b/client-code-gen/gen/admin-management-api/api/famaccess-control-privileges-api.ts @@ -75,6 +75,44 @@ export const FAMAccessControlPrivilegesApiAxiosParamCreator = function (configur options: localVarRequestOptions, }; }, + /** + * + * @summary Delete Access Control Privilege + * @param {number} accessControlPrivilegeId + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + deleteAccessControlPrivilege: async (accessControlPrivilegeId: number, options: AxiosRequestConfig = {}): Promise => { + // verify required parameter 'accessControlPrivilegeId' is not null or undefined + assertParamExists('deleteAccessControlPrivilege', 'accessControlPrivilegeId', accessControlPrivilegeId) + const localVarPath = `/access_control_privileges/{access_control_privilege_id}` + .replace(`{${"access_control_privilege_id"}}`, encodeURIComponent(String(accessControlPrivilegeId))); + // use dummy base URL string because the URL constructor only accepts absolute URLs. + const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); + let baseOptions; + if (configuration) { + baseOptions = configuration.baseOptions; + } + + const localVarRequestOptions = { method: 'DELETE', ...baseOptions, ...options}; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + // authentication 6jfveou69mgford233or30hmta required + // oauth required + await setOAuthToObject(localVarHeaderParameter, "6jfveou69mgford233or30hmta", [], configuration) + + + + setSearchParams(localVarUrlObj, localVarQueryParameter); + let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; + + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, /** * Get Delegated Admin Privileges For an Application * @summary Get Access Control Privileges By Application Id @@ -137,6 +175,17 @@ export const FAMAccessControlPrivilegesApiFp = function(configuration?: Configur const localVarAxiosArgs = await localVarAxiosParamCreator.createAccessControlPrivilegeMany(famAccessControlPrivilegeCreateRequest, options); return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); }, + /** + * + * @summary Delete Access Control Privilege + * @param {number} accessControlPrivilegeId + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async deleteAccessControlPrivilege(accessControlPrivilegeId: number, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.deleteAccessControlPrivilege(accessControlPrivilegeId, options); + return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); + }, /** * Get Delegated Admin Privileges For an Application * @summary Get Access Control Privileges By Application Id @@ -168,6 +217,16 @@ export const FAMAccessControlPrivilegesApiFactory = function (configuration?: Co createAccessControlPrivilegeMany(famAccessControlPrivilegeCreateRequest: FamAccessControlPrivilegeCreateRequest, options?: any): AxiosPromise> { return localVarFp.createAccessControlPrivilegeMany(famAccessControlPrivilegeCreateRequest, options).then((request) => request(axios, basePath)); }, + /** + * + * @summary Delete Access Control Privilege + * @param {number} accessControlPrivilegeId + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + deleteAccessControlPrivilege(accessControlPrivilegeId: number, options?: any): AxiosPromise { + return localVarFp.deleteAccessControlPrivilege(accessControlPrivilegeId, options).then((request) => request(axios, basePath)); + }, /** * Get Delegated Admin Privileges For an Application * @summary Get Access Control Privileges By Application Id @@ -197,6 +256,16 @@ export interface FAMAccessControlPrivilegesApiInterface { */ createAccessControlPrivilegeMany(famAccessControlPrivilegeCreateRequest: FamAccessControlPrivilegeCreateRequest, options?: AxiosRequestConfig): AxiosPromise>; + /** + * + * @summary Delete Access Control Privilege + * @param {number} accessControlPrivilegeId + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof FAMAccessControlPrivilegesApiInterface + */ + deleteAccessControlPrivilege(accessControlPrivilegeId: number, options?: AxiosRequestConfig): AxiosPromise; + /** * Get Delegated Admin Privileges For an Application * @summary Get Access Control Privileges By Application Id @@ -228,6 +297,18 @@ export class FAMAccessControlPrivilegesApi extends BaseAPI implements FAMAccessC return FAMAccessControlPrivilegesApiFp(this.configuration).createAccessControlPrivilegeMany(famAccessControlPrivilegeCreateRequest, options).then((request) => request(this.axios, this.basePath)); } + /** + * + * @summary Delete Access Control Privilege + * @param {number} accessControlPrivilegeId + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof FAMAccessControlPrivilegesApi + */ + public deleteAccessControlPrivilege(accessControlPrivilegeId: number, options?: AxiosRequestConfig) { + return FAMAccessControlPrivilegesApiFp(this.configuration).deleteAccessControlPrivilege(accessControlPrivilegeId, options).then((request) => request(this.axios, this.basePath)); + } + /** * Get Delegated Admin Privileges For an Application * @summary Get Access Control Privileges By Application Id diff --git a/server/admin_management/api/app/repositories/access_control_privilege_repository.py b/server/admin_management/api/app/repositories/access_control_privilege_repository.py index 90365cd9f..851421cf7 100644 --- a/server/admin_management/api/app/repositories/access_control_privilege_repository.py +++ b/server/admin_management/api/app/repositories/access_control_privilege_repository.py @@ -49,6 +49,18 @@ def create_access_control_privilege( self.db.refresh(db_item) return db_item + def delete_access_control_privilege(self, access_control_privilege_id: int): + record = ( + self.db.query(FamAccessControlPrivilege) + .filter( + FamAccessControlPrivilege.access_control_privilege_id + == access_control_privilege_id + ) + .one() + ) + self.db.delete(record) + self.db.flush() + def get_user_delegated_admin_grants(self, user_id: int) -> List[FamRole]: """ Find out from `app_fam.fam_access_control_privilege` the applications' roles @@ -59,11 +71,11 @@ def get_user_delegated_admin_grants(self, user_id: int) -> List[FamRole]: """ return ( self.db.query(FamRole) - .options(joinedload(FamRole.application)) # also loads relationship - .select_from(FamAccessControlPrivilege) - .join(FamAccessControlPrivilege.role) - .join(FamAccessControlPrivilege.user) - .filter(FamAccessControlPrivilege.user_id == user_id) - .order_by(FamRole.application_id, FamRole.role_id) - .all() + .options(joinedload(FamRole.application)) # also loads relationship + .select_from(FamAccessControlPrivilege) + .join(FamAccessControlPrivilege.role) + .join(FamAccessControlPrivilege.user) + .filter(FamAccessControlPrivilege.user_id == user_id) + .order_by(FamRole.application_id, FamRole.role_id) + .all() ) diff --git a/server/admin_management/api/app/routers/router_access_control_privilege.py b/server/admin_management/api/app/routers/router_access_control_privilege.py index 4777ab193..722cbc3a7 100644 --- a/server/admin_management/api/app/routers/router_access_control_privilege.py +++ b/server/admin_management/api/app/routers/router_access_control_privilege.py @@ -8,6 +8,7 @@ authorize_by_application_role, enforce_self_grant_guard, get_current_requester, + validate_param_access_control_privilege_id, ) from api.app.routers.router_utils import ( access_control_privilege_service_instance, @@ -21,7 +22,7 @@ from api.app.services.role_service import RoleService from api.app.services.user_service import UserService from api.app.utils.audit_util import AuditEventLog, AuditEventOutcome, AuditEventType -from fastapi import APIRouter, Depends, Request +from fastapi import APIRouter, Depends, Request, Response LOGGER = logging.getLogger(__name__) @@ -68,7 +69,7 @@ def create_access_control_privilege_many( audit_event_log = AuditEventLog( request=request, event_type=AuditEventType.CREATE_ACCESS_CONTROL_PRIVILIEGE, - forest_client_number=access_control_privilege_request.forest_client_numbers, + forest_client_numbers=access_control_privilege_request.forest_client_numbers, event_outcome=AuditEventOutcome.SUCCESS, ) @@ -120,3 +121,59 @@ def get_access_control_privileges_by_application_id( ), ): return access_control_privilege_service.get_acp_by_application_id(application_id) + + +@router.delete( + "/{access_control_privilege_id}", + response_class=Response, + dependencies=[ + Depends( + validate_param_access_control_privilege_id + ), # validate id first, otherwise authorize_by_application_role cannot find application by role + Depends( + authorize_by_application_role + ), # only app admin can do this, get application by role + Depends(enforce_self_grant_guard), + ], +) +def delete_access_control_privilege( + access_control_privilege_id: int, + request: Request, + user_service: UserService = Depends(user_service_instance), + access_control_privilege_service: AccessControlPrivilegeService = Depends( + access_control_privilege_service_instance + ), + requester: Requester = Depends(get_current_requester), +): + LOGGER.debug( + f"Executing 'delete_access_control_privilege' with request: {access_control_privilege_id}" + ) + + audit_event_log = AuditEventLog( + request=request, + event_type=AuditEventType.REMOVE_ACCESS_CONTROL_PRIVILIEGE, + event_outcome=AuditEventOutcome.SUCCESS, + ) + + try: + audit_event_log.requesting_user = user_service.get_user_by_cognito_user_id( + requester.cognito_user_id + ) + access_control_privilege = access_control_privilege_service.get_acp_by_id( + access_control_privilege_id + ) + audit_event_log.role = access_control_privilege.role + audit_event_log.application = access_control_privilege.role.application + audit_event_log.target_user = access_control_privilege.user + + return access_control_privilege_service.delete_access_control_privilege( + access_control_privilege_id + ) + + except Exception as e: + audit_event_log.event_outcome = AuditEventOutcome.FAIL + audit_event_log.exception = e + raise e + + finally: + audit_event_log.log_event() diff --git a/server/admin_management/api/app/routers/router_guards.py b/server/admin_management/api/app/routers/router_guards.py index de6e095b4..4c3736d4c 100644 --- a/server/admin_management/api/app/routers/router_guards.py +++ b/server/admin_management/api/app/routers/router_guards.py @@ -3,9 +3,7 @@ from http import HTTPStatus from typing import Union from fastapi import Depends, HTTPException, Request -from sqlalchemy.orm import Session -from api.app import database from api.app.jwt_validation import ( ERROR_PERMISSION_REQUIRED, get_access_roles, @@ -22,6 +20,13 @@ from api.app.services.user_service import UserService from api.app.services.role_service import RoleService from api.app.services.application_service import ApplicationService +from api.app.routers.router_utils import ( + access_control_privilege_service_instance, + application_service_instance, + application_admin_service_instance, + user_service_instance, + role_service_instance, +) LOGGER = logging.getLogger(__name__) @@ -33,6 +38,7 @@ ERROR_REQUESTER_NOT_EXISTS = "requester_not_exists" ERROR_EXTERNAL_USER_ACTION_PROHIBITED = "external_user_action_prohibited" ERROR_INVALID_APPLICATION_ADMIN_ID = "invalid_application_admin_id" +ERROR_INVALID_ACCESS_CONTROL_PRIVILEGE_ID = "invalid_access_control_privilege_id" ERROR_NOT_ALLOWED_USER_TYPE = "user_type_not_allowed" @@ -63,9 +69,8 @@ def authorize_by_fam_admin(claims: dict = Depends(validate_token)): async def get_current_requester( request_cognito_user_id: str = Depends(get_request_cognito_user_id), access_roles=Depends(get_access_roles), - db: Session = Depends(database.get_db), + user_service: UserService = Depends(user_service_instance), ): - user_service = UserService(db) fam_user: FamUser = user_service.get_user_by_cognito_user_id( request_cognito_user_id ) @@ -85,16 +90,22 @@ async def get_current_requester( # Specifically: "user_role_xref_id" and "user_name/user_type_code". # Very likely in future might have "cognito_user_id" case. async def get_target_user_from_id( - request: Request, db: Session = Depends(database.get_db) + request: Request, + user_service: UserService = Depends(user_service_instance), + application_admin_service: ApplicationAdminService = Depends( + application_admin_service_instance + ), + access_control_privilege_service: AccessControlPrivilegeService = Depends( + access_control_privilege_service_instance + ), ) -> Union[TargetUser, None]: """ This is used as FastAPI sub-dependency to find target_user for guard purpose. For requester, use "get_current_requester()" above. """ # from path_param - application_admin_id, when remove admin access for a user - user_service = UserService(db) + if "application_admin_id" in request.path_params: - application_admin_service = ApplicationAdminService(db) application_admin = application_admin_service.get_application_admin_by_id( request.path_params["application_admin_id"] ) @@ -103,6 +114,15 @@ async def get_target_user_from_id( if application_admin is not None else None ) + elif "access_control_privilege_id" in request.path_params: + access_control_privilege = access_control_privilege_service.get_acp_by_id( + request.path_params["access_control_privilege_id"] + ) + return ( + TargetUser.model_validate(access_control_privilege.user) + if access_control_privilege is not None + else None + ) else: # from body - {user_name/user_type_code}, when grant admin access try: @@ -146,7 +166,11 @@ async def enforce_self_grant_guard( async def get_request_role_from_id( - request: Request, db: Session = Depends(database.get_db) + request: Request, + access_control_privilege_service: AccessControlPrivilegeService = Depends( + access_control_privilege_service_instance + ), + role_service: RoleService = Depends(role_service_instance), ) -> Union[FamRole, None]: """ To get role from request @@ -158,7 +182,6 @@ async def get_request_role_from_id( access_control_privilege_id = request.path_params["access_control_privilege_id"] if access_control_privilege_id: - access_control_privilege_service = AccessControlPrivilegeService(db) access_control_privilege = access_control_privilege_service.get_acp_by_id( access_control_privilege_id ) @@ -167,7 +190,6 @@ async def get_request_role_from_id( try: rbody = await request.json() role_id = rbody["role_id"] - role_service = RoleService(db) role = role_service.get_role_by_id(role_id) return role # role could be None. @@ -180,8 +202,8 @@ def authorize_by_application_role( # Depends on "get_request_role_from_id()" to figure out # what id to use to get role from endpoint. role: FamRole = Depends(get_request_role_from_id), - db: Session = Depends(database.get_db), claims: dict = Depends(validate_token), + application_service: ApplicationService = Depends(application_service_instance), ): """ This router validation is currently design to validate logged on "admin" @@ -200,16 +222,15 @@ def authorize_by_application_role( headers={"WWW-Authenticate": "Bearer"}, ) - authorize_by_app_id(application_id=role.application_id, db=db, claims=claims) + authorize_by_app_id(role.application_id, claims, application_service) return role def authorize_by_app_id( application_id: int, - db: Session = Depends(database.get_db), claims: dict = Depends(validate_token), + application_service: ApplicationService = Depends(application_service_instance), ): - application_service = ApplicationService(db) application = application_service.get_application(application_id) if not application: raise HTTPException( @@ -236,9 +257,11 @@ def authorize_by_app_id( async def validate_param_application_admin_id( - application_admin_id: int, db: Session = Depends(database.get_db) + application_admin_id: int, + application_admin_service: ApplicationAdminService = Depends( + application_admin_service_instance + ), ): - application_admin_service = ApplicationAdminService(db) application_admin = application_admin_service.get_application_admin_by_id( application_admin_id ) @@ -255,9 +278,8 @@ async def validate_param_application_admin_id( async def validate_param_application_id( application_admin_request: FamAppAdminCreateRequest, - db: Session = Depends(database.get_db), + application_service: ApplicationService = Depends(application_service_instance), ): - application_service = ApplicationService(db) application = application_service.get_application( application_admin_request.application_id ) @@ -285,3 +307,23 @@ async def validate_param_user_type(application_admin_request: FamAppAdminCreateR }, headers={"WWW-Authenticate": "Bearer"}, ) + + +async def validate_param_access_control_privilege_id( + access_control_privilege_id: int, + access_control_privilege_service: AccessControlPrivilegeService = Depends( + access_control_privilege_service_instance + ), +): + access_control_privilege = access_control_privilege_service.get_acp_by_id( + access_control_privilege_id + ) + if not access_control_privilege: + raise HTTPException( + status_code=HTTPStatus.BAD_REQUEST, + detail={ + "code": ERROR_INVALID_ACCESS_CONTROL_PRIVILEGE_ID, + "description": f"Access control privilege ID {access_control_privilege_id} not found", + }, + headers={"WWW-Authenticate": "Bearer"}, + ) diff --git a/server/admin_management/api/app/services/access_control_privilege_service.py b/server/admin_management/api/app/services/access_control_privilege_service.py index 98d9ec96c..a6451dfab 100644 --- a/server/admin_management/api/app/services/access_control_privilege_service.py +++ b/server/admin_management/api/app/services/access_control_privilege_service.py @@ -45,6 +45,11 @@ def get_acp_by_application_id( application_id ) + def delete_access_control_privilege(self, access_control_privilege_id: int): + return self.access_control_privilege_repository.delete_access_control_privilege( + access_control_privilege_id + ) + def create_access_control_privilege_many( self, request: schemas.FamAccessControlPrivilegeCreateRequest, requester: str ) -> List[schemas.FamAccessControlPrivilegeCreateResponse]: diff --git a/server/admin_management/api/app/utils/audit_util.py b/server/admin_management/api/app/utils/audit_util.py index f08417824..dbf3c917b 100644 --- a/server/admin_management/api/app/utils/audit_util.py +++ b/server/admin_management/api/app/utils/audit_util.py @@ -14,6 +14,7 @@ class AuditEventType(str, Enum): CREATE_APPLICATION_ADMIN_ACCESS = "Grant User Application Admin Access" REMOVE_APPLICATION_ADMIN_ACCESS = "Remove User Application Admin Access" CREATE_ACCESS_CONTROL_PRIVILIEGE = "Grant Delegated Admin Privilege" + REMOVE_ACCESS_CONTROL_PRIVILIEGE = "Remove Delegated Admin Privilege" class AuditEventOutcome(str, Enum): @@ -27,7 +28,7 @@ class AuditEventLog: event_outcome: AuditEventOutcome application: models.FamApplication role: models.FamRole - forest_client_number: str + forest_client_numbers: str requesting_user: models.FamUser target_user: models.FamUser exception: Exception @@ -39,7 +40,7 @@ def __init__( event_outcome: AuditEventOutcome = None, application: models.FamApplication = None, role: models.FamRole = None, - forest_client_number: List[str] = None, + forest_client_numbers: List[str] = None, requesting_user: models.FamUser = None, target_user: models.FamUser = None, exception: Exception = None, @@ -49,7 +50,7 @@ def __init__( self.event_outcome = event_outcome self.application = application self.role = role - self.forest_client_number = forest_client_number + self.forest_client_numbers = forest_client_numbers self.requesting_user = requesting_user self.target_user = target_user self.exception = exception @@ -61,53 +62,62 @@ def log_event(self): "roleId": self.role.role_id, "roleName": self.role.role_name, "roleType": self.role.role_type_code, - "forestClientNumber": self.forest_client_number, } } if self.role else {} ) # only return role information when need + log_forest_client_numbers = ( + {"forestClientNumbers": self.forest_client_numbers} + if self.forest_client_numbers + else {} + ) log_item = { "auditEventTypeCode": self.event_type.name if self.event_type else None, - "auditEventResultCode": self.event_outcome.name - if self.event_outcome - else None, + "auditEventResultCode": ( + self.event_outcome.name if self.event_outcome else None + ), "application": { - "applicationId": self.application.application_id - if self.application - else None, - "applicationName": self.application.application_name - if self.application - else None, - "applicationEnv": self.application.app_environment - if self.application - else None, + "applicationId": ( + self.application.application_id if self.application else None + ), + "applicationName": ( + self.application.application_name if self.application else None + ), + "applicationEnv": ( + self.application.app_environment if self.application else None + ), }, **log_role, + **log_forest_client_numbers, "targetUser": { "userGuid": self.target_user.user_guid if self.target_user else None, - "userType": self.target_user.user_type_code - if self.target_user - else None, + "userType": ( + self.target_user.user_type_code if self.target_user else None + ), "idpUserName": self.target_user.user_name if self.target_user else None, - "cognitoUsername": self.target_user.cognito_user_id - if self.target_user - else None, + "cognitoUsername": ( + self.target_user.cognito_user_id if self.target_user else None + ), }, "requestingUser": { - "userGuid": self.requesting_user.user_guid - if self.requesting_user - else None, - "userType": self.requesting_user.user_type_code - if self.requesting_user - else None, - "idpUserName": self.requesting_user.user_name - if self.requesting_user - else None, - "cognitoUsername": self.requesting_user.cognito_user_id - if self.requesting_user - else None, + "userGuid": ( + self.requesting_user.user_guid if self.requesting_user else None + ), + "userType": ( + self.requesting_user.user_type_code + if self.requesting_user + else None + ), + "idpUserName": ( + self.requesting_user.user_name if self.requesting_user else None + ), + "cognitoUsername": ( + self.requesting_user.cognito_user_id + if self.requesting_user + else None + ), }, "requestIP": self.request.client.host if self.request.client else "unknown", } diff --git a/server/admin_management/tests/repositories/test_access_control_privilege_repository.py b/server/admin_management/tests/repositories/test_access_control_privilege_repository.py index f9e8cb710..d1bfdd690 100644 --- a/server/admin_management/tests/repositories/test_access_control_privilege_repository.py +++ b/server/admin_management/tests/repositories/test_access_control_privilege_repository.py @@ -1,23 +1,28 @@ import logging import pytest -from api.app.repositories.access_control_privilege_repository import \ - AccessControlPrivilegeRepository +from api.app.repositories.access_control_privilege_repository import ( + AccessControlPrivilegeRepository, +) from api.app.repositories.user_repository import UserRepository from api.app.schemas import FamAccessControlPrivilegeCreateDto from sqlalchemy.exc import IntegrityError -from tests.constants import (ERROR_VOLIATE_FOREIGN_KEY_CONSTRAINT, - ERROR_VOLIATE_UNIQUE_CONSTRAINT, - TEST_ACCESS_CONTROL_PRIVILEGE_CREATE, - TEST_APPLICATION_ID_FOM_DEV, TEST_CREATOR, - TEST_FOM_DEV_REVIEWER_ROLE_ID, - TEST_FOM_DEV_SUBMITTER_ROLE_ID, - TEST_FOM_TEST_REVIEWER_ROLE_ID, - TEST_NEW_IDIR_USER, - TEST_NON_EXIST_ACCESS_CONTROL_PRIVILEGE_ID, - TEST_NON_EXIST_USER_ID, - TEST_NOT_EXIST_APPLICATION_ID, - TEST_NOT_EXIST_ROLE_ID, TEST_USER_ID) +from tests.constants import ( + ERROR_VOLIATE_FOREIGN_KEY_CONSTRAINT, + ERROR_VOLIATE_UNIQUE_CONSTRAINT, + TEST_ACCESS_CONTROL_PRIVILEGE_CREATE, + TEST_APPLICATION_ID_FOM_DEV, + TEST_CREATOR, + TEST_FOM_DEV_REVIEWER_ROLE_ID, + TEST_FOM_DEV_SUBMITTER_ROLE_ID, + TEST_FOM_TEST_REVIEWER_ROLE_ID, + TEST_NEW_IDIR_USER, + TEST_NON_EXIST_ACCESS_CONTROL_PRIVILEGE_ID, + TEST_NON_EXIST_USER_ID, + TEST_NOT_EXIST_APPLICATION_ID, + TEST_NOT_EXIST_ROLE_ID, + TEST_USER_ID, +) LOGGER = logging.getLogger(__name__) @@ -148,15 +153,50 @@ def test_get_acp_by_application_id( assert len(found_acp) == 0 +def test_delete_access_control_privileg( + access_control_privilege_repo: AccessControlPrivilegeRepository, +): + # create a new access control privilege + new_access_control_privilege = ( + access_control_privilege_repo.create_access_control_privilege( + TEST_ACCESS_CONTROL_PRIVILEGE_CREATE + ) + ) + assert ( + new_access_control_privilege.user_id + == TEST_ACCESS_CONTROL_PRIVILEGE_CREATE.user_id + ) + assert ( + new_access_control_privilege.role_id + == TEST_ACCESS_CONTROL_PRIVILEGE_CREATE.role_id + ) + # verify the new access control privilege is created + access_control_privilege = access_control_privilege_repo.get_acp_by_id( + new_access_control_privilege.access_control_privilege_id + ) + assert access_control_privilege is not None + + # remove the access control privilege + access_control_privilege_repo.delete_access_control_privilege( + new_access_control_privilege.access_control_privilege_id + ) + # verify the access control privilege cannot be found anymore + access_control_privilege = access_control_privilege_repo.get_acp_by_id( + new_access_control_privilege.access_control_privilege_id + ) + assert access_control_privilege is None + + def test_get_user_delegated_admin_grants( access_control_privilege_repo: AccessControlPrivilegeRepository, - user_repo: UserRepository + user_repo: UserRepository, ): new_user = user_repo.create_user(TEST_NEW_IDIR_USER) # user does not have delegated admin privilege initially. - initial_granted_role = access_control_privilege_repo. \ - get_user_delegated_admin_grants(new_user.user_id) + initial_granted_role = ( + access_control_privilege_repo.get_user_delegated_admin_grants(new_user.user_id) + ) assert initial_granted_role == [] # granted new user delegated admin a role @@ -171,8 +211,9 @@ def test_get_user_delegated_admin_grants( fom_dev_reviewer_delegated_request ) - user_grants = access_control_privilege_repo. \ - get_user_delegated_admin_grants(new_user.user_id) + user_grants = access_control_privilege_repo.get_user_delegated_admin_grants( + new_user.user_id + ) assert len(user_grants) == 1 granted_fom_reviewer_role = user_grants[0] assert granted_fom_reviewer_role.role_id == TEST_FOM_DEV_REVIEWER_ROLE_ID @@ -188,9 +229,11 @@ def test_get_user_delegated_admin_grants( access_control_privilege_repo.create_access_control_privilege( fom_test_reviewer_delegated_request ) - user_grants = access_control_privilege_repo. \ - get_user_delegated_admin_grants(new_user.user_id) + user_grants = access_control_privilege_repo.get_user_delegated_admin_grants( + new_user.user_id + ) assert len(user_grants) == 2 granted_role_list = list(map(lambda x: x.role_id, user_grants)) assert set(granted_role_list) == set( - [TEST_FOM_DEV_REVIEWER_ROLE_ID, TEST_FOM_TEST_REVIEWER_ROLE_ID]) \ No newline at end of file + [TEST_FOM_DEV_REVIEWER_ROLE_ID, TEST_FOM_TEST_REVIEWER_ROLE_ID] + ) diff --git a/server/admin_management/tests/routers/test_router_access_control_privilege.py b/server/admin_management/tests/routers/test_router_access_control_privilege.py index e27fe490b..c1ba07346 100644 --- a/server/admin_management/tests/routers/test_router_access_control_privilege.py +++ b/server/admin_management/tests/routers/test_router_access_control_privilege.py @@ -7,6 +7,7 @@ from api.app.routers.router_guards import ( ERROR_INVALID_ROLE_ID, ERROR_INVALID_APPLICATION_ID, + ERROR_INVALID_ACCESS_CONTROL_PRIVILEGE_ID, ) from tests.constants import ( TEST_FOREST_CLIENT_NUMBER, @@ -168,3 +169,48 @@ def test_get_access_control_privileges_by_application_id( ) != -1 ) + + +def test_delete_application_admin( + test_client_fixture: starlette.testclient.TestClient, test_rsa_key +): + # create an access control privilege with abstract role and one forest client number + token = jwt_utils.create_jwt_token(test_rsa_key, [TEST_FOM_DEV_ADMIN_ROLE]) + response = test_client_fixture.post( + f"{endPoint}", + json=TEST_ACCESS_CONTROL_PRIVILEGE_CREATE_REQUEST, + headers=jwt_utils.headers(token), + ) + assert response.status_code == HTTPStatus.OK + assert response.json() is not None + data = response.json()[0]["detail"] + + # test delete with invalid role + token = jwt_utils.create_jwt_token(test_rsa_key) + response = test_client_fixture.delete( + f"{endPoint}/{data.get('access_control_privilege_id')}", + headers=jwt_utils.headers(token), + ) + assert response.status_code == HTTPStatus.FORBIDDEN + assert response.json() is not None + assert str(response.json()["detail"]).find(ERROR_PERMISSION_REQUIRED) != -1 + + # test delete access control privilege + token = jwt_utils.create_jwt_token(test_rsa_key, [TEST_FOM_DEV_ADMIN_ROLE]) + response = test_client_fixture.delete( + f"{endPoint}/{data.get('access_control_privilege_id')}", + headers=jwt_utils.headers(token), + ) + assert response.status_code == HTTPStatus.OK + + # test delete non exists access control privilege + response = test_client_fixture.delete( + f"{endPoint}/{data.get('access_control_privilege_id')}", + headers=jwt_utils.headers(token), + ) + assert response.status_code == HTTPStatus.BAD_REQUEST + assert response.json() is not None + assert ( + str(response.json()["detail"]).find(ERROR_INVALID_ACCESS_CONTROL_PRIVILEGE_ID) + != -1 + )