Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

feat: Add role api keys in UI #3042

Merged
merged 28 commits into from
Feb 16, 2024
Merged
Show file tree
Hide file tree
Changes from 24 commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
270903b
feat: Add roles Api Key in UI
novakzaballa Nov 23, 2023
4ccc068
Add Master APi Key id to response
novakzaballa Nov 23, 2023
97e4db5
create services
novakzaballa Nov 23, 2023
fe5fcba
Update responses, requests
novakzaballa Nov 23, 2023
400cb01
Changes in AdminKeys components
novakzaballa Nov 23, 2023
b78bbcd
Delete Role API Key
novakzaballa Nov 24, 2023
383117e
Add local Roles Api Key
novakzaballa Nov 24, 2023
1ab2818
Add and delete a single Role API Key
novakzaballa Nov 24, 2023
1159d61
Add roles to MasterAPIKeySerializer
novakzaballa Nov 24, 2023
13a6687
Create Roles Api key
novakzaballa Nov 24, 2023
d025ad0
Delete Role api Key when is_admin change from false to true
novakzaballa Nov 27, 2023
5585433
Add optional chaining
novakzaballa Nov 27, 2023
77b9055
Add flag
novakzaballa Nov 29, 2023
89ef27b
move conditional import
novakzaballa Nov 30, 2023
929ece7
Use new RBAC endpoint for get role API keys
novakzaballa Dec 1, 2023
8e34473
Merge branch 'main' into feat/add-role-api-key-in-ui
novakzaballa Dec 22, 2023
1128d28
Delete unnecesary code
novakzaballa Jan 8, 2024
d1c43bb
Merge branch 'main' into feat/add-role-api-key-in-ui
novakzaballa Jan 8, 2024
54646ae
Merge branch 'main' into feat/add-role-api-key-in-ui
novakzaballa Jan 11, 2024
57a3950
Remove unnecesary code, and changes in adimnAPIKey pages
novakzaballa Jan 17, 2024
2e3f439
Correct Delete RTK code
novakzaballa Jan 17, 2024
030a733
Merge branch 'main' into feat/add-role-api-key-in-ui
novakzaballa Jan 18, 2024
b013ff2
change delete url
novakzaballa Jan 23, 2024
4619664
Update Delete endpoint for the Master API key role
novakzaballa Jan 29, 2024
6c761d8
Solve error with the role id
novakzaballa Jan 29, 2024
131615d
Correct RoleMasterApiKey URL
novakzaballa Jan 29, 2024
145592e
Merge branch 'main' into feat/add-role-api-key-in-ui
novakzaballa Feb 14, 2024
bd51477
Update the API key table in the UI
novakzaballa Feb 15, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion api/api_keys/models.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
from django.conf import settings
from django.db import models
from django_lifecycle import BEFORE_UPDATE, LifecycleModelMixin, hook
from rest_framework_api_key.models import AbstractAPIKey, APIKeyManager
from softdelete.models import SoftDeleteManager, SoftDeleteObject

Expand All @@ -9,7 +11,7 @@ class MasterAPIKeyManager(APIKeyManager, SoftDeleteManager):
pass


class MasterAPIKey(AbstractAPIKey, SoftDeleteObject):
class MasterAPIKey(AbstractAPIKey, LifecycleModelMixin, SoftDeleteObject):
organisation = models.ForeignKey(
Organisation,
on_delete=models.CASCADE,
Expand All @@ -18,3 +20,12 @@ class MasterAPIKey(AbstractAPIKey, SoftDeleteObject):

objects = MasterAPIKeyManager()
is_admin = models.BooleanField(default=True)

@hook(BEFORE_UPDATE, when="is_admin", was=False, is_now=True)
def delete_role_api_keys(
self,
):
if settings.IS_RBAC_INSTALLED:
from rbac.models import MasterAPIKeyRole

MasterAPIKeyRole.objects.filter(master_api_key=self.id).delete()
1 change: 1 addition & 0 deletions api/api_keys/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ class MasterAPIKeySerializer(serializers.ModelSerializer):
class Meta:
model = MasterAPIKey
fields = (
"id",
"prefix",
"created",
"name",
Expand Down
5 changes: 4 additions & 1 deletion frontend/common/services/useGroupWithRole.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,10 @@ export const groupWithRoleService = service
Res['groupWithRole'],
Req['deleteGroupWithRole']
>({
invalidatesTags: [{ type: 'GroupWithRole' }, { type: 'RolePermissionGroup' }],
invalidatesTags: [
{ type: 'GroupWithRole' },
{ type: 'RolePermissionGroup' },
],
query: (query: Req['deleteGroupWithRole']) => ({
body: query,
method: 'DELETE',
Expand Down
102 changes: 102 additions & 0 deletions frontend/common/services/useMasterAPIKeyWithMasterAPIKeyRole.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
import { Res } from 'common/types/responses'
import { Req } from 'common/types/requests'
import { service } from 'common/service'

export const masterAPIKeyWithMasterAPIKeyRoleService = service
.enhanceEndpoints({ addTagTypes: ['MasterAPIKeyWithMasterAPIKeyRole'] })
.injectEndpoints({
endpoints: (builder) => ({
deleteMasterAPIKeyWithMasterAPIKeyRoles: builder.mutation<
Res['masterAPIKeyWithMasterAPIKeyRoles'],
Req['deleteMasterAPIKeyWithMasterAPIKeyRoles']
>({
invalidatesTags: ['MasterAPIKeyWithMasterAPIKeyRole'],
query: (query: Req['deleteMasterAPIKeyWithMasterAPIKeyRoles']) => ({
method: 'DELETE',
url: `organisations/${query.org_id}/master-api-keys/${query.prefix}/roles/${query.role_id}/detach-roles-from-master-api-key/`,
}),
}),
getMasterAPIKeyWithMasterAPIKeyRoles: builder.query<
Res['masterAPIKeyWithMasterAPIKeyRoles'],
Req['getMasterAPIKeyWithMasterAPIKeyRoles']
>({
providesTags: (res) => [
{ id: res?.id, type: 'MasterAPIKeyWithMasterAPIKeyRole' },
],
query: (query: Req['getMasterAPIKeyWithMasterAPIKeyRoles']) => ({
url: `organisations/${query.org_id}/master-api-keys/${query.prefix}/`,
}),
}),
getRolesMasterAPIKeyWithMasterAPIKeyRoles: builder.query<
Res['masterAPIKeyWithMasterAPIKeyRoles'],
Req['getMasterAPIKeyWithMasterAPIKeyRoles']
>({
providesTags: (res) => [
{ id: res?.id, type: 'MasterAPIKeyWithMasterAPIKeyRole' },
],
query: (query: Req['getMasterAPIKeyWithMasterAPIKeyRoles']) => ({
url: `organisations/${query.org_id}/master-api-keys/${query.prefix}/roles/`,
}),
}),
// END OF ENDPOINTS
}),
})

export async function getMasterAPIKeyWithMasterAPIKeyRoles(
store: any,
data: Req['getMasterAPIKeyWithMasterAPIKeyRoles'],
options?: Parameters<
typeof masterAPIKeyWithMasterAPIKeyRoleService.endpoints.getMasterAPIKeyWithMasterAPIKeyRoles.initiate
>[1],
) {
return store.dispatch(
masterAPIKeyWithMasterAPIKeyRoleService.endpoints.getMasterAPIKeyWithMasterAPIKeyRoles.initiate(
data,
options,
),
)
}

export async function getRolesMasterAPIKeyWithMasterAPIKeyRoles(
store: any,
data: Req['getMasterAPIKeyWithMasterAPIKeyRoles'],
options?: Parameters<
typeof masterAPIKeyWithMasterAPIKeyRoleService.endpoints.getRolesMasterAPIKeyWithMasterAPIKeyRoles.initiate
>[1],
) {
return store.dispatch(
masterAPIKeyWithMasterAPIKeyRoleService.endpoints.getRolesMasterAPIKeyWithMasterAPIKeyRoles.initiate(
data,
options,
),
)
}

export async function deleteMasterAPIKeyWithMasterAPIKeyRoles(
store: any,
data: Req['getMasterAPIKeyWithMasterAPIKeyRoles'],
options?: Parameters<
typeof masterAPIKeyWithMasterAPIKeyRoleService.endpoints.deleteMasterAPIKeyWithMasterAPIKeyRoles.initiate
>[1],
) {
return store.dispatch(
masterAPIKeyWithMasterAPIKeyRoleService.endpoints.deleteMasterAPIKeyWithMasterAPIKeyRoles.initiate(
data,
options,
),
)
}
// END OF FUNCTION_EXPORTS

export const {
useDeletexMasterAPIKeyWithMasterAPIKeyRolesMutation,
useGetMasterAPIKeyWithMasterAPIKeyRolesQuery,
useGetRolesMasterAPIKeyWithMasterAPIKeyRolesQuery,
// END OF EXPORTS
} = masterAPIKeyWithMasterAPIKeyRoleService

/* Usage examples:
const { data, isLoading } = useGetMasterAPIKeyWithMasterAPIKeyRolesQuery({ id: 2 }, {}) //get hook
const [createMasterAPIKeyWithMasterAPIKeyRoles, { isLoading, data, isSuccess }] = useCreateMasterAPIKeyWithMasterAPIKeyRolesMutation() //create hook
masterAPIKeyWithMasterAPIKeyRoleService.endpoints.getMasterAPIKeyWithMasterAPIKeyRoles.select({id: 2})(store.getState()) //access data from any function
*/
135 changes: 135 additions & 0 deletions frontend/common/services/useRoleMasterApiKey.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
import { Res } from 'common/types/responses'
import { Req } from 'common/types/requests'
import { service } from 'common/service'

export const roleMasterApiKeyService = service
.enhanceEndpoints({
addTagTypes: ['RoleMasterApiKey'],
})
.injectEndpoints({
endpoints: (builder) => ({
createRoleMasterApiKey: builder.mutation<
Res['roleMasterApiKey'],
Req['createRoleMasterApiKey']
>({
invalidatesTags: [
{ id: 'LIST', type: 'RoleMasterApiKey' },
'MasterAPIKeyWithMasterAPIKeyRole',
],
query: (query: Req['createRoleMasterApiKey']) => ({
body: query.body,
method: 'POST',
url: `organisations/${query.org_id}/roles/${query.role_id}/master-api-keys/`,
}),
}),
deleteRoleMasterApiKey: builder.mutation<
Res['roleMasterApiKey'],
Req['deleteRoleMasterApiKey']
>({
invalidatesTags: [
{ id: 'LIST', type: 'RoleMasterApiKey' },
'MasterAPIKeyWithMasterAPIKeyRole',
],
query: (query: Req['deleteRoleMasterApiKey']) => ({
method: 'DELETE',
url: `organisations/${query.org_id}/roles/${query.role_id}/master-api-keys/${query.id}`,
}),
}),
getRoleMasterApiKey: builder.query<
Res['roleMasterApiKey'],
Req['getRoleMasterApiKey']
>({
providesTags: (res) => [{ id: res?.id, type: 'RoleMasterApiKey' }],
query: (query: Req['getRoleMasterApiKey']) => ({
url: `organisations/${query.org_id}/roles/${query.role_id}/master-api-keys/${id}`,
}),
}),
updateRoleMasterApiKey: builder.mutation<
Res['roleMasterApiKey'],
Req['updateRoleMasterApiKey']
>({
invalidatesTags: (res) => [
{ id: 'LIST', type: 'RoleMasterApiKey' },
{ id: res?.id, type: 'RoleMasterApiKey' },
],
query: (query: Req['updateRoleMasterApiKey']) => ({
body: query,
method: 'PUT',
url: `organisations/${query.org_id}/roles/${query.role_id}/master-api-keys/${id}`,
}),
}),
// END OF ENDPOINTS
}),
})

export async function createRoleMasterApiKey(
store: any,
data: Req['createRoleMasterApiKey'],
options?: Parameters<
typeof roleMasterApiKeyService.endpoints.createRoleMasterApiKey.initiate
>[1],
) {
return store.dispatch(
roleMasterApiKeyService.endpoints.createRoleMasterApiKey.initiate(
data,
options,
),
)
}
export async function deleteRoleMasterApiKey(
store: any,
data: Req['deleteRoleMasterApiKey'],
options?: Parameters<
typeof roleMasterApiKeyService.endpoints.deleteRoleMasterApiKey.initiate
>[1],
) {
return store.dispatch(
roleMasterApiKeyService.endpoints.deleteRoleMasterApiKey.initiate(
data,
options,
),
)
}
export async function getRoleMasterApiKey(
store: any,
data: Req['getRoleMasterApiKey'],
options?: Parameters<
typeof roleMasterApiKeyService.endpoints.getRoleMasterApiKey.initiate
>[1],
) {
return store.dispatch(
roleMasterApiKeyService.endpoints.getRoleMasterApiKey.initiate(
data,
options,
),
)
}
export async function updateRoleMasterApiKey(
store: any,
data: Req['updateRoleMasterApiKey'],
options?: Parameters<
typeof roleMasterApiKeyService.endpoints.updateRoleMasterApiKey.initiate
>[1],
) {
return store.dispatch(
roleMasterApiKeyService.endpoints.updateRoleMasterApiKey.initiate(
data,
options,
),
)
}
// END OF FUNCTION_EXPORTS

export const {
useCreateRoleMasterApiKeyMutation,
useDeleteRoleMasterApiKeyMutation,
useGetRoleMasterApiKeyQuery,
useUpdateRoleMasterApiKeyMutation,
// END OF EXPORTS
} = roleMasterApiKeyService

/* Usage examples:
const { data, isLoading } = useGetRoleMasterApiKeyQuery({ id: 2 }, {}) //get hook
const [createRoleMasterApiKey, { isLoading, data, isSuccess }] = useCreateRoleMasterApiKeyMutation() //create hook
roleMasterApiKeyService.endpoints.getRoleMasterApiKey.select({id: 2})(store.getState()) //access data from any function
*/
5 changes: 1 addition & 4 deletions frontend/common/services/useRolesUser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,7 @@ export const rolesUserService = service
Res['rolesUsers'],
Req['deleteRolesPermissionUsers']
>({
invalidatesTags: [
{ type: 'User-role' },
{ type: 'RolesUser' },
],
invalidatesTags: [{ type: 'User-role' }, { type: 'RolesUser' }],
query: (query: Req['deleteRolesPermissionUsers']) => ({
body: query,
method: 'DELETE',
Expand Down
11 changes: 11 additions & 0 deletions frontend/common/types/requests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,17 @@ export type Req = {
getGetSubscriptionMetadata: { id: string }
getEnvironment: { id: string }
getSubscriptionMetadata: { id: string }
getRoleMasterApiKey: { org_id: number; role_id: number; id: string }
updateRoleMasterApiKey: { org_id: number; role_id: number; id: string }
deleteRoleMasterApiKey: { org_id: number; role_id: number; id: string }
createRoleMasterApiKey: { org_id: number; role_id: number }
getMasterAPIKeyWithMasterAPIKeyRoles: { org_id: number; prefix: string }
deleteMasterAPIKeyWithMasterAPIKeyRoles: {
org_id: number
prefix: string
role_id: number
}
getRolesMasterAPIKeyWithMasterAPIKeyRoles: { org_id: number; prefix: string }
createLaunchDarklyProjectImport: {
project_id: string
body: {
Expand Down
7 changes: 7 additions & 0 deletions frontend/common/types/responses.ts
Original file line number Diff line number Diff line change
Expand Up @@ -320,6 +320,7 @@ export type RolePermissionUser = {
user: number
role: number
id: number
role_name: string
}

export type Res = {
Expand Down Expand Up @@ -393,6 +394,12 @@ export type Res = {
environment: Environment
launchDarklyProjectImport: LaunchDarklyProjectImport
launchDarklyProjectsImport: LaunchDarklyProjectImport[]
roleMasterApiKey: { id: number; master_api_key: string; role: number }
masterAPIKeyWithMasterAPIKeyRoles: {
id: string
prefix: string
roles: RolePermissionUser[]
}
userWithRoles: PagedResponse<Roles>
groupWithRole: PagedResponse<Roles>
changeRequests: PagedResponse<ChangeRequestSummary>
Expand Down
Loading
Loading