So many things
This commit is contained in:
@@ -8,6 +8,8 @@ export const optima = {
|
||||
credential: (await import("./optima-api/modules/credentials")).credential,
|
||||
credentialType: (await import("./optima-api/modules/credentialTypes"))
|
||||
.credentialType,
|
||||
role: (await import("./optima-api/modules/roles")).role,
|
||||
permission: (await import("./optima-api/modules/permissions")).permission,
|
||||
user,
|
||||
};
|
||||
/**
|
||||
|
||||
@@ -1,8 +1,16 @@
|
||||
import api from "../axios";
|
||||
|
||||
export const company = {
|
||||
async fetch(accessToken: string, id: string) {
|
||||
async fetch(
|
||||
accessToken: string,
|
||||
id: string,
|
||||
options?: { includeAddress?: boolean },
|
||||
) {
|
||||
const params: Record<string, string> = {};
|
||||
if (options?.includeAddress) params.includeAddress = "true";
|
||||
|
||||
const company = await api.get(`/v1/company/companies/${id}`, {
|
||||
params,
|
||||
headers: {
|
||||
Authorization: `Bearer ${accessToken}`,
|
||||
},
|
||||
@@ -27,6 +35,14 @@ export const company = {
|
||||
|
||||
return companies.data;
|
||||
},
|
||||
async count(accessToken: string) {
|
||||
const response = await api.get("/v1/company/count", {
|
||||
headers: {
|
||||
Authorization: `Bearer ${accessToken}`,
|
||||
},
|
||||
});
|
||||
return response.data.data.count;
|
||||
},
|
||||
async fetchConfigurations(accessToken: string, id: string) {
|
||||
const configurations = await api.get(
|
||||
`/v1/company/companies/${id}/configurations`,
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
import api from "../axios";
|
||||
|
||||
export interface PermissionNode {
|
||||
node: string;
|
||||
description: string;
|
||||
usedIn: string[];
|
||||
dependencies?: string[];
|
||||
}
|
||||
|
||||
export interface PermissionCategory {
|
||||
name: string;
|
||||
description: string;
|
||||
permissions: PermissionNode[];
|
||||
}
|
||||
|
||||
export interface PermissionsCategorized {
|
||||
[category: string]: PermissionCategory;
|
||||
}
|
||||
|
||||
export const permission = {
|
||||
async fetchCategorized(accessToken: string) {
|
||||
const response = await api.get("/v1/permissions", {
|
||||
headers: {
|
||||
Authorization: `Bearer ${accessToken}`,
|
||||
},
|
||||
});
|
||||
return response.data;
|
||||
},
|
||||
|
||||
async fetchFlat(accessToken: string) {
|
||||
const response = await api.get("/v1/permissions/nodes", {
|
||||
headers: {
|
||||
Authorization: `Bearer ${accessToken}`,
|
||||
},
|
||||
});
|
||||
return response.data;
|
||||
},
|
||||
|
||||
async fetchByCategory(accessToken: string, category: string) {
|
||||
const response = await api.get(`/v1/permissions/${category}`, {
|
||||
headers: {
|
||||
Authorization: `Bearer ${accessToken}`,
|
||||
},
|
||||
});
|
||||
return response.data;
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,104 @@
|
||||
import api from "../axios";
|
||||
|
||||
export interface Role {
|
||||
id: string;
|
||||
title: string;
|
||||
moniker: string;
|
||||
permissions: string[];
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
}
|
||||
|
||||
export const role = {
|
||||
async fetchMany(accessToken: string) {
|
||||
const response = await api.get("/v1/role", {
|
||||
headers: {
|
||||
Authorization: `Bearer ${accessToken}`,
|
||||
},
|
||||
});
|
||||
return response.data;
|
||||
},
|
||||
|
||||
async fetch(accessToken: string, identifier: string) {
|
||||
const response = await api.get(`/v1/role/${identifier}`, {
|
||||
headers: {
|
||||
Authorization: `Bearer ${accessToken}`,
|
||||
},
|
||||
});
|
||||
return response.data;
|
||||
},
|
||||
|
||||
async create(
|
||||
accessToken: string,
|
||||
data: Omit<Role, "id" | "createdAt" | "updatedAt">,
|
||||
) {
|
||||
const response = await api.post("/v1/role", data, {
|
||||
headers: {
|
||||
Authorization: `Bearer ${accessToken}`,
|
||||
},
|
||||
});
|
||||
return response.data;
|
||||
},
|
||||
|
||||
async update(
|
||||
accessToken: string,
|
||||
identifier: string,
|
||||
updates: Partial<Omit<Role, "id" | "createdAt" | "updatedAt">>,
|
||||
) {
|
||||
const response = await api.patch(`/v1/role/${identifier}`, updates, {
|
||||
headers: {
|
||||
Authorization: `Bearer ${accessToken}`,
|
||||
},
|
||||
});
|
||||
return response.data;
|
||||
},
|
||||
|
||||
async delete(accessToken: string, identifier: string) {
|
||||
const response = await api.delete(`/v1/role/${identifier}`, {
|
||||
headers: {
|
||||
Authorization: `Bearer ${accessToken}`,
|
||||
},
|
||||
});
|
||||
return response.data;
|
||||
},
|
||||
|
||||
async addPermissions(
|
||||
accessToken: string,
|
||||
identifier: string,
|
||||
permissions: string[],
|
||||
) {
|
||||
const response = await api.post(
|
||||
`/v1/role/${identifier}/permissions`,
|
||||
{ permissions },
|
||||
{
|
||||
headers: {
|
||||
Authorization: `Bearer ${accessToken}`,
|
||||
},
|
||||
},
|
||||
);
|
||||
return response.data;
|
||||
},
|
||||
|
||||
async removePermissions(
|
||||
accessToken: string,
|
||||
identifier: string,
|
||||
permissions: string[],
|
||||
) {
|
||||
const response = await api.delete(`/v1/role/${identifier}/permissions`, {
|
||||
headers: {
|
||||
Authorization: `Bearer ${accessToken}`,
|
||||
},
|
||||
data: { permissions },
|
||||
});
|
||||
return response.data;
|
||||
},
|
||||
|
||||
async fetchUsers(accessToken: string, identifier: string) {
|
||||
const response = await api.get(`/v1/role/${identifier}/users`, {
|
||||
headers: {
|
||||
Authorization: `Bearer ${accessToken}`,
|
||||
},
|
||||
});
|
||||
return response.data;
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,51 @@
|
||||
import { optima } from "$lib";
|
||||
|
||||
export type PermissionMap = Record<string, boolean>;
|
||||
|
||||
/**
|
||||
* Check multiple permissions for the current user and return a map of
|
||||
* permission → boolean. Designed to be called from any +page.server.ts
|
||||
* or +layout.server.ts load function.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* const perms = await checkPermissions(accessToken, [
|
||||
* "company.fetch.address",
|
||||
* "credential.create",
|
||||
* ]);
|
||||
* // perms => { "company.fetch.address": true, "credential.create": false }
|
||||
* ```
|
||||
*/
|
||||
export async function checkPermissions(
|
||||
accessToken: string,
|
||||
permissions: string[],
|
||||
): Promise<PermissionMap> {
|
||||
if (!permissions.length) return {};
|
||||
|
||||
try {
|
||||
const result = await optima.user.checkPermissions(accessToken, permissions);
|
||||
|
||||
const results: Array<{ permission: string; hasPermission: boolean }> =
|
||||
result?.data?.results ?? [];
|
||||
|
||||
return results.reduce<PermissionMap>((map, entry) => {
|
||||
map[entry.permission] = entry.hasPermission === true;
|
||||
return map;
|
||||
}, {});
|
||||
} catch (err) {
|
||||
console.error("Permission check failed:", err);
|
||||
// Default every requested permission to false on failure
|
||||
return permissions.reduce<PermissionMap>((map, p) => {
|
||||
map[p] = false;
|
||||
return map;
|
||||
}, {});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience helper — returns true when a specific permission is
|
||||
* granted inside a PermissionMap.
|
||||
*/
|
||||
export function hasPermission(map: PermissionMap, permission: string): boolean {
|
||||
return map[permission] === true;
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
import { writable } from "svelte/store";
|
||||
import { browser } from "$app/environment";
|
||||
|
||||
type Theme = "light" | "dark";
|
||||
|
||||
function createThemeStore() {
|
||||
const initial: Theme = browser
|
||||
? ((localStorage.getItem("theme") as Theme) ?? "dark")
|
||||
: "dark";
|
||||
|
||||
const { subscribe, set, update } = writable<Theme>(initial);
|
||||
|
||||
function applyTheme(theme: Theme) {
|
||||
if (browser) {
|
||||
document.documentElement.setAttribute("data-theme", theme);
|
||||
localStorage.setItem("theme", theme);
|
||||
}
|
||||
}
|
||||
|
||||
// Apply on init
|
||||
if (browser) applyTheme(initial);
|
||||
|
||||
return {
|
||||
subscribe,
|
||||
toggle() {
|
||||
update((current) => {
|
||||
const next = current === "dark" ? "light" : "dark";
|
||||
applyTheme(next);
|
||||
return next;
|
||||
});
|
||||
},
|
||||
set(theme: Theme) {
|
||||
applyTheme(theme);
|
||||
set(theme);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export const theme = createThemeStore();
|
||||
Reference in New Issue
Block a user