[web] role deletion confirm, host index page
This commit is contained in:
parent
cddf4820b5
commit
de64f1ed00
|
@ -88,9 +88,22 @@
|
||||||
"role": "Role",
|
"role": "Role",
|
||||||
"lastseen": "Last Seen",
|
"lastseen": "Last Seen",
|
||||||
"actions": "Actions",
|
"actions": "Actions",
|
||||||
"ipaddr": "IP Address"
|
"ipaddr": "IP Address",
|
||||||
|
"edit": "Edit",
|
||||||
|
"enroll": "Enroll",
|
||||||
|
"delete": "Delete",
|
||||||
|
"config": "Configuration"
|
||||||
},
|
},
|
||||||
"roles": {
|
"roles": {
|
||||||
|
"delete": {
|
||||||
|
"title": "Are you sure you want to delete the role {rule}?",
|
||||||
|
"explainer": "This action cannot be undone. This role must be removed from all hosts, lighthouses, and relays prior to deleting it.",
|
||||||
|
"confirm": "I'm sure",
|
||||||
|
"cancel": "Nevermind",
|
||||||
|
"error": {
|
||||||
|
"ERR_DB_ERROR": "Removal failed (role was probably still attached to a host)"
|
||||||
|
}
|
||||||
|
},
|
||||||
"create": "Add",
|
"create": "Add",
|
||||||
"explain": "Roles control how hosts, lighthouses, and relays communicate through firewall rules.",
|
"explain": "Roles control how hosts, lighthouses, and relays communicate through firewall rules.",
|
||||||
"noroles": "You don't have any roles. You'll need to add at least one before you can add any hosts.",
|
"noroles": "You don't have any roles. You'll need to add at least one before you can add any hosts.",
|
||||||
|
@ -129,7 +142,7 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"edit": {
|
"edit": {
|
||||||
"title": "Editing rule {rule}",
|
"title": "Editing role {rule}",
|
||||||
"any": "Any",
|
"any": "Any",
|
||||||
"name": "Role name",
|
"name": "Role name",
|
||||||
"desc": "Role description",
|
"desc": "Role description",
|
||||||
|
@ -141,7 +154,8 @@
|
||||||
"description": "Description",
|
"description": "Description",
|
||||||
"protocol": "Protocol",
|
"protocol": "Protocol",
|
||||||
"portrange": "Port range",
|
"portrange": "Port range",
|
||||||
"allowedrole": "Allowed role"
|
"allowedrole": "Allowed role",
|
||||||
|
"actions": "Actions"
|
||||||
},
|
},
|
||||||
"ruleremove": "Remove rule",
|
"ruleremove": "Remove rule",
|
||||||
"ruleedit": "Edit rule",
|
"ruleedit": "Edit rule",
|
||||||
|
|
|
@ -8,8 +8,10 @@
|
||||||
onMount(async () => {
|
onMount(async () => {
|
||||||
const bootstrap = await import("bootstrap/dist/js/bootstrap.js");
|
const bootstrap = await import("bootstrap/dist/js/bootstrap.js");
|
||||||
|
|
||||||
|
document.onload(() => {
|
||||||
const tooltipTriggerList = document.querySelectorAll('[data-bs-toggle="tooltip"]')
|
const tooltipTriggerList = document.querySelectorAll('[data-bs-toggle="tooltip"]')
|
||||||
const tooltipList = [...tooltipTriggerList].map(tooltipTriggerEl => new bootstrap.Tooltip(tooltipTriggerEl))
|
const tooltipList = [...tooltipTriggerList].map(tooltipTriggerEl => new bootstrap.Tooltip(tooltipTriggerEl))
|
||||||
|
});
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
import {PUBLIC_BASE_URL} from "$env/static/public";
|
import {PUBLIC_BASE_URL} from "$env/static/public";
|
||||||
import {Configuration, HostsApi, NetworksApi, RolesApi} from "$lib/api";
|
import {Configuration, HostsApi, NetworksApi, RolesApi} from "$lib/api";
|
||||||
import type {Host} from "$lib/api/models/Host.ts";
|
import type {Host} from "$lib/api/models/Host.ts";
|
||||||
|
import type {Role} from "$lib/api/models/Role.ts";
|
||||||
import AdminLayout from "$components/AdminLayout.svelte";
|
import AdminLayout from "$components/AdminLayout.svelte";
|
||||||
|
|
||||||
let loading = true;
|
let loading = true;
|
||||||
|
@ -16,6 +17,7 @@
|
||||||
$: currentlyLoading = $isLoading || loading;
|
$: currentlyLoading = $isLoading || loading;
|
||||||
|
|
||||||
let hosts: Host[] = [];
|
let hosts: Host[] = [];
|
||||||
|
let roles: Role[] = [];
|
||||||
|
|
||||||
logSetup();
|
logSetup();
|
||||||
let logger = new Logger("hosts/+page.svelte");
|
let logger = new Logger("hosts/+page.svelte");
|
||||||
|
@ -74,8 +76,20 @@
|
||||||
|
|
||||||
console.log(hosts);
|
console.log(hosts);
|
||||||
|
|
||||||
|
const rolesApi = new RolesApi(configuration);
|
||||||
|
roles = (await rolesApi.rolesList()).data!;
|
||||||
|
|
||||||
loading = false;
|
loading = false;
|
||||||
})
|
});
|
||||||
|
|
||||||
|
function getRoleName(byId: string): string {
|
||||||
|
for (let i = 0; i < roles.length; i++) {
|
||||||
|
if (roles[i].id == byId) {
|
||||||
|
return roles[i].name!;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "Unknown";
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<svelte:head>
|
<svelte:head>
|
||||||
|
@ -103,9 +117,14 @@
|
||||||
<td>{host.name}</td>
|
<td>{host.name}</td>
|
||||||
<td>{host.metadata?.lastSeenAt}</td>
|
<td>{host.metadata?.lastSeenAt}</td>
|
||||||
<td>{host.ipAddress}</td>
|
<td>{host.ipAddress}</td>
|
||||||
<td>{host.roleID}</td>
|
<td><a href="/roles/{host.roleID}/edit">{getRoleName(host.roleID)}</a></td>
|
||||||
<td>
|
<td>
|
||||||
|
<div class="btn-group">
|
||||||
|
<a href="/hosts/{host.id}/enroll" title="{$t('hosts.enroll')}" class="btn btn-success"><i class="fas fa-arrows-rotate fa-fw"></i></a>
|
||||||
|
<a href="/hosts/{host.id}/edit" title="{$t('hosts.edit')}" class="btn btn-primary"><i class="fas fa-pencil fa-fw"></i></a>
|
||||||
|
<a href="/hosts/{host.id}/edit/config" title="{$t('hosts.config')}" class="btn btn-info"><i class="fas fa-gear fa-fw"></i></a>
|
||||||
|
<a href="/hosts/{host.id}/delete" title="{$t('hosts.delete')}" class="btn btn-danger"><i class="fas fa-trash fa-fw"></i></a>
|
||||||
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
|
@ -77,22 +77,6 @@
|
||||||
window.location.href = "/roles/add";
|
window.location.href = "/roles/add";
|
||||||
}
|
}
|
||||||
|
|
||||||
async function roleDelete(id: string) {
|
|
||||||
const configuration = new Configuration({
|
|
||||||
basePath: PUBLIC_BASE_URL,
|
|
||||||
accessToken: window.localStorage.getItem("session") + " " + window.localStorage.getItem("mfa")
|
|
||||||
});
|
|
||||||
|
|
||||||
const rolesApi = new RolesApi(configuration);
|
|
||||||
|
|
||||||
await rolesApi.roleDelete(
|
|
||||||
{
|
|
||||||
roleID: id
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
window.location.reload();
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<svelte:head>
|
<svelte:head>
|
||||||
|
@ -131,8 +115,8 @@
|
||||||
<td>{role.description}</td>
|
<td>{role.description}</td>
|
||||||
<td>
|
<td>
|
||||||
<div class="btn-group">
|
<div class="btn-group">
|
||||||
<button class="btn btn-primary" on:click={() => {window.location.href = `/roles/${role.id}/edit`}}><i class="fas fa-pencil fa-fw"></i></button>
|
<a href="/roles/{role.id}/edit" class="btn btn-primary"><i class="fas fa-pencil fa-fw"></i></a>
|
||||||
<button class="btn btn-danger" on:click={() => {roleDelete(role.id)}}><i class="fas fa-trash fa-fw"></i></button>
|
<a href="/roles/{role.id}/delete" class="btn btn-danger"><i class="fas fa-trash fa-fw"></i></a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</td>
|
</td>
|
||||||
|
|
|
@ -0,0 +1,137 @@
|
||||||
|
<script lang="ts">
|
||||||
|
import {isLoading, t} from "svelte-i18n";
|
||||||
|
import LoadingWrapper from "$components/LoadingWrapper.svelte";
|
||||||
|
import {onMount} from "svelte";
|
||||||
|
import {APIResult, isAuthedMFA, isAuthedSession} from "$lib/auth.ts";
|
||||||
|
import {Logger, logSetup} from "$lib/logger";
|
||||||
|
import type {APIError} from "$lib/auth.ts";
|
||||||
|
import {PUBLIC_BASE_URL} from "$env/static/public";
|
||||||
|
import {Configuration, NetworksApi, RolesApi, FirewallRuleProtocolEnum, ResponseError} from "$lib/api";
|
||||||
|
import type {FirewallRule} from "$lib/api";
|
||||||
|
import AdminBar from "$components/AdminLayout.svelte";
|
||||||
|
import {page} from "$app/stores";
|
||||||
|
import AdminLayout from "$components/AdminLayout.svelte";
|
||||||
|
import {load} from "../../../+layout";
|
||||||
|
|
||||||
|
let loading = true;
|
||||||
|
let fullPageLoading = true;
|
||||||
|
let isError = false;
|
||||||
|
let error = '';
|
||||||
|
$: currentlyLoading = $isLoading || fullPageLoading;
|
||||||
|
|
||||||
|
logSetup();
|
||||||
|
let logger = new Logger("roles/edit/+page.svelte");
|
||||||
|
|
||||||
|
let roles;
|
||||||
|
let role = {
|
||||||
|
data: {
|
||||||
|
name: 'Loading'
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let roleName = '';
|
||||||
|
let roleDescription = '';
|
||||||
|
|
||||||
|
let formErr = '';
|
||||||
|
let hasFormErr = false;
|
||||||
|
|
||||||
|
onMount(async () => {
|
||||||
|
let session_load_info = await isAuthedSession();
|
||||||
|
if (session_load_info[0] == APIResult.Failed) {
|
||||||
|
let err = session_load_info[1] as APIError;
|
||||||
|
logger.error(`session load failed: ${err.code} ${err.message}`);
|
||||||
|
window.location.href = '/login';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mfa_load_info = await isAuthedMFA();
|
||||||
|
if (mfa_load_info[0] == APIResult.Failed) {
|
||||||
|
let err = mfa_load_info[1] as APIError;
|
||||||
|
logger.error(`mfa load failed: ${err.code} ${err.message}`);
|
||||||
|
window.location.href = '/2fa';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// pull networks
|
||||||
|
const configuration = new Configuration({
|
||||||
|
basePath: PUBLIC_BASE_URL,
|
||||||
|
accessToken: window.localStorage.getItem("session") + " " + window.localStorage.getItem("mfa")
|
||||||
|
});
|
||||||
|
|
||||||
|
const networksApi = new NetworksApi(configuration);
|
||||||
|
let networks;
|
||||||
|
try {
|
||||||
|
networks = await networksApi.networksList();
|
||||||
|
} catch (e) {
|
||||||
|
let resp_json = await e.response.json();
|
||||||
|
if (resp_json.errors[0].code == "ERR_NO_ORG") {
|
||||||
|
window.location.href = "/networkcreate";
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
isError = true;
|
||||||
|
error = $t("networkcreate.error.generic", {values:{err:resp_json.errors[0].code}});
|
||||||
|
loading = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
console.log(networks);
|
||||||
|
|
||||||
|
if (networks.data?.length == 0) {
|
||||||
|
window.location.href = '/networkcreate';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const rolesApi = new RolesApi(configuration);
|
||||||
|
roles = await rolesApi.rolesList();
|
||||||
|
|
||||||
|
// pull our role
|
||||||
|
role = await rolesApi.roleGet({
|
||||||
|
roleID: $page.params.role_id
|
||||||
|
});
|
||||||
|
|
||||||
|
fullPageLoading = false;
|
||||||
|
loading = false;
|
||||||
|
});
|
||||||
|
|
||||||
|
async function deleteRole() {
|
||||||
|
loading = true;
|
||||||
|
const configuration = new Configuration({
|
||||||
|
basePath: PUBLIC_BASE_URL,
|
||||||
|
accessToken: window.localStorage.getItem("session") + " " + window.localStorage.getItem("mfa")
|
||||||
|
});
|
||||||
|
const rolesApi = new RolesApi(configuration);
|
||||||
|
try {
|
||||||
|
await rolesApi.roleDelete({roleID: $page.params.role_id});
|
||||||
|
} catch (e) {
|
||||||
|
let body = await (<ResponseError>e).response.json();
|
||||||
|
|
||||||
|
console.log(body);
|
||||||
|
|
||||||
|
formErr = $t("roles.delete.error." + body.errors[0].code);
|
||||||
|
hasFormErr = true;
|
||||||
|
loading = false;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
window.location.href = "/roles";
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<svelte:head>
|
||||||
|
<title>{$t("common.title", {values: {title: $t("common.page.roles")}})}</title>
|
||||||
|
</svelte:head>
|
||||||
|
|
||||||
|
<LoadingWrapper isLoading={currentlyLoading} isError={isError} error={error}>
|
||||||
|
<AdminLayout selected="roles">
|
||||||
|
<h3>{$t("roles.delete.title", {values: {rule: role.data.name}})}</h3>
|
||||||
|
<p>{$t("roles.delete.explainer")}</p>
|
||||||
|
{#if loading}
|
||||||
|
<button disabled class="btn btn-danger"><i class="fas fa-gear fa-spin"></i></button>
|
||||||
|
{:else}
|
||||||
|
<button on:click={deleteRole} class="btn btn-danger">{$t("roles.delete.confirm")}</button>
|
||||||
|
{/if}
|
||||||
|
<button on:click={() => {window.location.href = "/roles"}} class="btn btn-outline-info">{$t("roles.delete.cancel")}</button>
|
||||||
|
{#if hasFormErr}
|
||||||
|
<p class="text-danger">{formErr}</p>
|
||||||
|
{/if}
|
||||||
|
</AdminLayout>
|
||||||
|
</LoadingWrapper>
|
Loading…
Reference in New Issue