add admin admin settings
This commit is contained in:
53
src/lib/components/Input/Badges.svelte
Normal file
53
src/lib/components/Input/Badges.svelte
Normal file
@ -0,0 +1,53 @@
|
||||
<script lang="ts">
|
||||
// eslint-disable-next-line no-undef
|
||||
type T = $$Generic;
|
||||
|
||||
export let id: string | null = null;
|
||||
export let name: string | null = null;
|
||||
export let disabled = true;
|
||||
export let available: string[] | { [key: string]: T } = {};
|
||||
export let value: T[] = [];
|
||||
</script>
|
||||
|
||||
<div class="flex items-center gap-4">
|
||||
<select
|
||||
{id}
|
||||
{name}
|
||||
class="select select-bordered select-xs"
|
||||
disabled={disabled || available.length === 0}
|
||||
on:change={(e) => {
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
value.push(Object.values(available)[Object.keys(available).indexOf(e.target.value)]);
|
||||
value = value;
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
e.target.value = '-';
|
||||
}}
|
||||
>
|
||||
<option selected hidden>-</option>
|
||||
{#each Object.keys(available) as badge}
|
||||
<option
|
||||
hidden={value.find(
|
||||
(v) => v === Object.values(available)[Object.keys(available).indexOf(badge)]
|
||||
) !== undefined}>{badge}</option
|
||||
>
|
||||
{/each}
|
||||
</select>
|
||||
<div class="flex flow flex-wrap gap-2">
|
||||
{#each value as badge, i}
|
||||
{#if Object.values(available).indexOf(badge) !== -1}
|
||||
<div class="badge badge-outline gap-1">
|
||||
<button
|
||||
{disabled}
|
||||
on:click={() => {
|
||||
value.splice(i, 1);
|
||||
value = value;
|
||||
}}>✕</button
|
||||
>
|
||||
{Object.keys(available)[Object.values(available).indexOf(badge)]}
|
||||
</div>
|
||||
{/if}
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
@ -3,10 +3,11 @@
|
||||
<script lang="ts">
|
||||
import { IconSolid } from 'svelte-heros-v2';
|
||||
|
||||
export let id: string;
|
||||
export let id: string | null = null;
|
||||
export let name: string | null = null;
|
||||
export let type: string;
|
||||
export let value: string | null = null;
|
||||
export let placeholder: string | null = null;
|
||||
export let required = false;
|
||||
export let disabled = false;
|
||||
|
||||
@ -18,7 +19,7 @@
|
||||
<!-- the cursor-not-allowed class must be set here because a disabled button does not respect the 'cursor' css property -->
|
||||
<div class={type === 'submit' && disabled ? 'cursor-not-allowed' : ''}>
|
||||
{#if type === 'submit'}
|
||||
<input class="btn" {id} type="submit" {value} {disabled} bind:this={inputElement} />
|
||||
<input class="btn" {id} type="submit" {disabled} bind:value bind:this={inputElement} />
|
||||
{:else}
|
||||
<div>
|
||||
{#if $$slots.label}
|
||||
@ -31,24 +32,29 @@
|
||||
</span>
|
||||
</label>
|
||||
{/if}
|
||||
<div class="flex items-center" class:sm:max-w-[16rem]={type !== 'checkbox'}>
|
||||
<div class="relative flex items-center" class:sm:max-w-[16rem]={type !== 'checkbox'}>
|
||||
<input
|
||||
class:checkbox={type === 'checkbox'}
|
||||
class:input,input-bordered={type !== 'checkbox'}
|
||||
class:w-[100%]={initialType !== 'password' && initialType !== 'checkbox'}
|
||||
class:input,input-bordered,w-[100%]={type !== 'checkbox'}
|
||||
class:pr-11={initialType === 'password'}
|
||||
{id}
|
||||
{name}
|
||||
{type}
|
||||
{value}
|
||||
{placeholder}
|
||||
{required}
|
||||
{disabled}
|
||||
autocomplete="off"
|
||||
bind:this={inputElement}
|
||||
autocomplete="off"
|
||||
on:input={(e) => {
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
value = e.target?.value;
|
||||
}}
|
||||
/>
|
||||
{#if initialType === 'password'}
|
||||
<button
|
||||
class="relative right-9"
|
||||
class="absolute right-3"
|
||||
type="button"
|
||||
on:click={() => {
|
||||
type = type === 'password' ? 'text' : 'password';
|
||||
|
@ -46,7 +46,7 @@
|
||||
<div class="alert alert-error border-none relative text-gray-900 overflow-hidden">
|
||||
<div class="flex gap-2 z-10">
|
||||
<IconOutline name="exclamation-circle-outline" />
|
||||
<span>Nutzername oder Passwort falsch</span>
|
||||
<slot />
|
||||
</div>
|
||||
<progress
|
||||
class="progress progress-error absolute bottom-0 h-[3px] w-full bg-[rgba(0,0,0,0.6)]"
|
||||
|
56
src/lib/permissions.ts
Normal file
56
src/lib/permissions.ts
Normal file
@ -0,0 +1,56 @@
|
||||
export class Permissions {
|
||||
static readonly AdminRead = 2;
|
||||
static readonly AdminWrite = 4;
|
||||
static readonly UserRead = 8;
|
||||
static readonly UserWrite = 16;
|
||||
|
||||
readonly value: number;
|
||||
|
||||
constructor(value: number | number[]) {
|
||||
if (typeof value == 'number') {
|
||||
this.value = value;
|
||||
} else {
|
||||
let finalValue = 0;
|
||||
for (const v of Object.values(value)) {
|
||||
finalValue |= v;
|
||||
}
|
||||
this.value = finalValue;
|
||||
}
|
||||
}
|
||||
|
||||
toJSON() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
static allPermissions(): number[] {
|
||||
return [
|
||||
Permissions.AdminRead,
|
||||
Permissions.AdminWrite,
|
||||
Permissions.UserRead,
|
||||
Permissions.UserWrite
|
||||
];
|
||||
}
|
||||
|
||||
adminRead(): boolean {
|
||||
return (this.value & Permissions.AdminRead) != 0;
|
||||
}
|
||||
adminWrite(): boolean {
|
||||
return (this.value & Permissions.AdminWrite) != 0;
|
||||
}
|
||||
userRead(): boolean {
|
||||
return (this.value & Permissions.UserRead) != 0;
|
||||
}
|
||||
userWrite(): boolean {
|
||||
return (this.value & Permissions.UserWrite) != 0;
|
||||
}
|
||||
|
||||
asArray(): number[] {
|
||||
const array = [];
|
||||
for (const perm of Permissions.allPermissions()) {
|
||||
if ((this.value & perm) != 0) {
|
||||
array.push(perm);
|
||||
}
|
||||
}
|
||||
return array;
|
||||
}
|
||||
}
|
@ -2,7 +2,16 @@ import { DataTypes } from 'sequelize';
|
||||
import { env } from '$env/dynamic/private';
|
||||
import { building, dev } from '$app/environment';
|
||||
import * as bcrypt from 'bcrypt';
|
||||
import { BeforeCreate, BeforeUpdate, Column, Model, Sequelize, Table } from 'sequelize-typescript';
|
||||
import {
|
||||
BeforeCreate,
|
||||
BeforeUpdate,
|
||||
Column,
|
||||
Model,
|
||||
Sequelize,
|
||||
Table,
|
||||
Unique
|
||||
} from 'sequelize-typescript';
|
||||
import { Permissions } from '$lib/permissions';
|
||||
|
||||
@Table({ modelName: 'user' })
|
||||
export class User extends Model {
|
||||
@ -26,18 +35,28 @@ export class User extends Model {
|
||||
|
||||
@Table({ modelName: 'admin' })
|
||||
export class Admin extends Model {
|
||||
@Column({ type: DataTypes.STRING, allowNull: false })
|
||||
@Column({ type: DataTypes.STRING, allowNull: false, unique: true })
|
||||
declare username: string;
|
||||
@Column({ type: DataTypes.STRING, allowNull: false })
|
||||
declare password: string;
|
||||
@Column({ type: DataTypes.BIGINT, allowNull: false })
|
||||
declare permissions: number;
|
||||
@Column({
|
||||
type: DataTypes.BIGINT,
|
||||
allowNull: false,
|
||||
get(this: Admin): Permissions | null {
|
||||
const permissions = this.getDataValue('permissions');
|
||||
return permissions != null ? new Permissions(permissions) : null;
|
||||
},
|
||||
set(this: Admin, value: Permissions) {
|
||||
this.setDataValue('permissions', value.value);
|
||||
}
|
||||
})
|
||||
declare permissions: Permissions;
|
||||
|
||||
@BeforeCreate
|
||||
@BeforeUpdate
|
||||
static hashPassword(instance: Admin) {
|
||||
if (instance.password != null) {
|
||||
instance.username = bcrypt.hashSync(instance.password, 10);
|
||||
instance.password = bcrypt.hashSync(instance.password, 10);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,11 +1,30 @@
|
||||
const sessions: string[] = [];
|
||||
import type { Permissions } from '$lib/permissions';
|
||||
import type { Cookies } from '@sveltejs/kit';
|
||||
|
||||
export function addSession(): string {
|
||||
const sessions: Map<string, Permissions> = new Map();
|
||||
|
||||
export function addSession(permissions: Permissions): string {
|
||||
const session = 'AAA';
|
||||
sessions.push(session);
|
||||
sessions.set(session, permissions);
|
||||
return session;
|
||||
}
|
||||
|
||||
export function hasSession(session: string): boolean {
|
||||
return sessions.find((v) => v == session) != undefined;
|
||||
export function getSession(session: string | Cookies, permissions?: number[]): Permissions | null {
|
||||
let sess: Permissions | null;
|
||||
if (typeof session == 'string') {
|
||||
sess = sessions.get(session) || null;
|
||||
} else {
|
||||
const sessionId = session.get('session');
|
||||
sess = sessionId ? sessions.get(sessionId) || null : null;
|
||||
}
|
||||
|
||||
if (!sess) {
|
||||
return null;
|
||||
}
|
||||
for (const perm of permissions || []) {
|
||||
if ((sess.value & perm) == 0) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return sess;
|
||||
}
|
||||
|
Reference in New Issue
Block a user