-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add roles authorization page and subpages.
- Loading branch information
Showing
24 changed files
with
987 additions
and
23 deletions.
There are no files selected for viewing
54 changes: 54 additions & 0 deletions
54
src/lib/components/admin/authorization/PrivilegeForm.svelte
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
<script lang="ts"> | ||
import type { Privilege } from '$lib/models/Privileges'; | ||
export let privilege: Privilege | undefined = undefined; | ||
export let applicationList: string[][]; | ||
export let onSave = () => {}; | ||
let name; | ||
let description; | ||
let application; | ||
</script> | ||
|
||
<label class="label"> | ||
<span>Name:</span> | ||
<input type="text" bind:this={name} value={privilege ? privilege.name : ''} class="input" /> | ||
</label> | ||
|
||
<label class="label"> | ||
<span>Description:</span> | ||
<input | ||
type="text" | ||
bind:this={description} | ||
value={privilege ? privilege.description : ''} | ||
class="input" | ||
/> | ||
</label> | ||
|
||
<label class="label"> | ||
<span>Application:</span> | ||
<select class="select" bind:this={application}> | ||
<option selected={!privilege || !privilege.application} value>none</option> | ||
{#each applicationList as [name, uuid]} | ||
<option value={uuid} selected={privilege && privilege.application === uuid}>{name}</option> | ||
{/each} | ||
</select> | ||
</label> | ||
|
||
<button | ||
type="submit" | ||
class="btn variant-ghost-primary hover:variant-filled-primary" | ||
aria-label="You are on the save button" | ||
on:click={onSave} | ||
> | ||
Save | ||
</button> | ||
<a href="/admin/authorization" class="btn variant-ghost-secondary hover:variant-filled-secondary"> | ||
Cancel | ||
</a> | ||
|
||
<style> | ||
label { | ||
margin: 0.5em 0; | ||
} | ||
</style> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
<script lang="ts"> | ||
import type { Role } from '$lib/models/Role'; | ||
export let role: Role | undefined = undefined; | ||
export let privilegeList: string[][]; | ||
export let onSave = () => {}; | ||
let name; | ||
let description; | ||
let privileges: HTMLElement[] = []; | ||
</script> | ||
|
||
<label class="label"> | ||
<span>Name:</span> | ||
<input type="text" bind:this={name} value={role ? role.name : ''} class="input" /> | ||
</label> | ||
|
||
<label class="label"> | ||
<span>Description:</span> | ||
<input type="text" bind:this={description} value={role ? role.description : ''} class="input" /> | ||
</label> | ||
|
||
<fieldset data-testid="privilege-checkboxes"> | ||
<legend>Privileges:</legend> | ||
{#each privilegeList as [name, uuid], index} | ||
<label class="flex items-center space-x-2"> | ||
<input | ||
class="checkbox" | ||
type="checkbox" | ||
bind:this={privileges[index]} | ||
value={uuid} | ||
checked={role && role.privileges.includes(uuid)} | ||
/> | ||
<p>{name}</p> | ||
</label> | ||
{/each} | ||
</fieldset> | ||
|
||
<button | ||
type="submit" | ||
class="btn variant-ghost-primary hover:variant-filled-primary" | ||
aria-label="You are on the save button" | ||
on:click={onSave} | ||
> | ||
Save | ||
</button> | ||
<a href="/admin/authorization" class="btn variant-ghost-secondary hover:variant-filled-secondary"> | ||
Cancel | ||
</a> | ||
|
||
<style> | ||
label, | ||
fieldset { | ||
margin: 0.5em 0; | ||
} | ||
fieldset label { | ||
margin: 0; | ||
} | ||
</style> |
8 changes: 8 additions & 0 deletions
8
src/lib/components/admin/authorization/cell/Application.svelte
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
<script lang="ts"> | ||
import ApplicationStore from '$lib/stores/Application'; | ||
const { getApplication } = ApplicationStore; | ||
export let data: { cell: '' }; | ||
</script> | ||
|
||
{data.cell ? getApplication(data.cell).name : 'none'} |
47 changes: 47 additions & 0 deletions
47
src/lib/components/admin/authorization/cell/PrivilegeActions.svelte
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
<script lang="ts"> | ||
import { getModalStore } from '@skeletonlabs/skeleton'; | ||
const modalStore = getModalStore(); | ||
export let data = { cell: '', row: { name: '' } }; | ||
function deleteModal() { | ||
modalStore.trigger({ | ||
type: 'confirm', | ||
title: 'Delete Privilege?', | ||
body: `Are you sure you want to delete privilege '${data.row.name}'?`, | ||
buttonTextConfirm: 'Yes', | ||
buttonTextCancel: 'No', | ||
response: (confirm: boolean) => { | ||
if (!confirm) return; | ||
// TODO: add delete logic using data.cell | ||
}, | ||
}); | ||
} | ||
</script> | ||
|
||
<a | ||
data-testid={`privilege-view-btn-${data.cell}`} | ||
href={`/admin/authorization/privilege/${data.cell}`} | ||
class="text-secondary-600 hover:text-primary-600" | ||
> | ||
<i class="fa-solid fa-circle-info fa-xl"></i> | ||
<span class="sr-only">View Privilege</span> | ||
</a> | ||
<a | ||
data-testid={`privilege-edit-btn-${data.cell}`} | ||
href={`/admin/authorization/privilege/${data.cell}/edit`} | ||
class="text-secondary-600 hover:text-primary-600" | ||
> | ||
<i class="fa-solid fa-pen-to-square fa-xl"></i> | ||
<span class="sr-only">Edit</span> | ||
</a> | ||
<button | ||
data-testid={`privilege-delete-btn-${data.cell}`} | ||
type="button" | ||
title="Delete" | ||
class="bg-initial text-secondary-600 hover:text-primary-600" | ||
on:click={deleteModal} | ||
> | ||
<i class="fa-solid fa-trash fa-xl"></i> | ||
<span class="sr-only">Delete</span> | ||
</button> |
47 changes: 47 additions & 0 deletions
47
src/lib/components/admin/authorization/cell/RoleActions.svelte
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
<script lang="ts"> | ||
import { getModalStore } from '@skeletonlabs/skeleton'; | ||
const modalStore = getModalStore(); | ||
export let data = { cell: '', row: { name: '' } }; | ||
function deleteModal() { | ||
modalStore.trigger({ | ||
type: 'confirm', | ||
title: 'Delete Role?', | ||
body: `Are you sure you want to delete role '${data.row.name}'?`, | ||
buttonTextConfirm: 'Yes', | ||
buttonTextCancel: 'No', | ||
response: (confirm: boolean) => { | ||
if (!confirm) return; | ||
// TODO: add delete logic using data.cell | ||
}, | ||
}); | ||
} | ||
</script> | ||
|
||
<a | ||
data-testid={`role-view-btn-${data.cell}`} | ||
href={`/admin/authorization/role/${data.cell}`} | ||
class="text-secondary-600 hover:text-primary-600" | ||
> | ||
<i class="fa-solid fa-circle-info fa-xl"></i> | ||
<span class="sr-only">View Role</span> | ||
</a> | ||
<a | ||
data-testid={`role-edit-btn-${data.cell}`} | ||
href={`/admin/authorization/role/${data.cell}/edit`} | ||
class="text-secondary-600 hover:text-primary-600" | ||
> | ||
<i class="fa-solid fa-pen-to-square fa-xl"></i> | ||
<span class="sr-only">Edit</span> | ||
</a> | ||
<button | ||
data-testid={`role-delete-btn-${data.cell}`} | ||
type="button" | ||
title="Delete" | ||
class="bg-initial text-secondary-600 hover:text-primary-600" | ||
on:click={deleteModal} | ||
> | ||
<i class="fa-solid fa-trash fa-xl"></i> | ||
<span class="sr-only">Delete</span> | ||
</button> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
export interface Application { | ||
uuid: string; | ||
name: string; | ||
description: string; | ||
token: string; | ||
url: string; | ||
enable: boolean; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
export interface Privilege { | ||
uuid: string; | ||
name: string; | ||
description: string; | ||
queryScope: string; | ||
application: string; | ||
} | ||
|
||
// TODO: Replace any type | ||
/* eslint-disable @typescript-eslint/no-explicit-any */ | ||
export function mapPrivilege(data: any) { | ||
return { | ||
...data, | ||
application: data.application?.uuid || '', | ||
}; | ||
} | ||
/* eslint-enable @typescript-eslint/no-explicit-any */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,14 +1,16 @@ | ||
export interface Privilege { | ||
export interface Role { | ||
uuid: string; | ||
name: string; | ||
description: string; | ||
queryScope: string; | ||
application?: object; | ||
privileges: string[]; | ||
} | ||
|
||
export interface Role { | ||
uuid: string; | ||
name: string; | ||
description: string; | ||
privileges: Privilege[]; | ||
// TODO: Replace any type | ||
/* eslint-disable @typescript-eslint/no-explicit-any */ | ||
export function mapRole(data: any) { | ||
return { | ||
...data, | ||
privileges: data.privileges.map((p: any) => p.uuid) || [], | ||
}; | ||
} | ||
/* eslint-enable @typescript-eslint/no-explicit-any */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
import { get, derived, writable, type Writable } from 'svelte/store'; | ||
import { type Application } from '$lib/models/Applications'; | ||
|
||
import { applications as mockApps } from './mock/data'; | ||
|
||
/* eslint-disable @typescript-eslint/no-unused-vars */ | ||
const APP_URL = 'psama/application'; | ||
/* eslint-enable @typescript-eslint/no-unused-vars */ | ||
|
||
const applications: Writable<Application[]> = writable([]); | ||
const applicationList = derived(applications, ($a) => $a.map((a) => [a.name, a.uuid])); | ||
|
||
// TODO: Add api integration | ||
async function loadApplications() { | ||
applications.set(mockApps); | ||
} | ||
|
||
function getApplication(uuid: string) { | ||
const store: Application[] = get(applications); | ||
const appIndex: number = store.findIndex((a) => a.uuid === uuid); | ||
return store[appIndex]; | ||
} | ||
|
||
export default { | ||
subscribe: applications.subscribe, | ||
applications, | ||
applicationList, | ||
loadApplications, | ||
getApplication, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
import { get, derived, writable, type Writable } from 'svelte/store'; | ||
import { type Privilege, mapPrivilege } from '$lib/models/Privileges'; | ||
|
||
import { privileges as mockPrivileges } from './mock/data'; | ||
|
||
/* eslint-disable @typescript-eslint/no-unused-vars */ | ||
const PRIV_PATH = 'psama/privilege'; | ||
/* eslint-enable @typescript-eslint/no-unused-vars */ | ||
|
||
const privileges: Writable<Privilege[]> = writable([]); | ||
const privilegeList = derived(privileges, ($p) => $p.map((p) => [p.name, p.uuid])); | ||
|
||
// TODO: Add api integration | ||
async function loadPrivileges() { | ||
privileges.set(mockPrivileges.map(mapPrivilege)); | ||
} | ||
|
||
async function getPrivilege(uuid: string) { | ||
const store: Privilege[] = get(privileges); | ||
const privIndex: number = store.findIndex((p) => p.uuid === uuid); | ||
return store[privIndex]; | ||
} | ||
|
||
export default { | ||
subscribe: privileges.subscribe, | ||
privileges, | ||
privilegeList, | ||
loadPrivileges, | ||
getPrivilege, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
import { get, writable, type Writable } from 'svelte/store'; | ||
import { type Role, mapRole } from '$lib/models/Role'; | ||
|
||
import { roles as mockRoles } from './mock/data'; | ||
|
||
/* eslint-disable @typescript-eslint/no-unused-vars */ | ||
const ROLE_PATH = '/psama/role'; | ||
/* eslint-enable @typescript-eslint/no-unused-vars */ | ||
|
||
const roles: Writable<Role[]> = writable([]); | ||
|
||
// TODO: Add api integration | ||
async function loadRoles() { | ||
roles.set(mockRoles.map(mapRole)); | ||
} | ||
|
||
async function getRole(uuid: string) { | ||
const store: Role[] = get(roles); | ||
const roleIndex: number = store.findIndex((r) => r.uuid === uuid); | ||
return store[roleIndex]; | ||
} | ||
|
||
export default { | ||
subscribe: roles.subscribe, | ||
roles, | ||
loadRoles, | ||
getRole, | ||
}; |
Oops, something went wrong.