feat(permissions): Adds server permissions

This commit is contained in:
Michel Fedde 2025-06-24 20:58:46 +02:00
parent d46bbd84c5
commit cf9c88a2d6
24 changed files with 415 additions and 69 deletions

View file

@ -7,6 +7,17 @@ import deepmerge from "deepmerge";
import {isPlainObject} from "is-plain-object";
import {Nullable} from "../types/Nullable";
import {ConfigurationTransformer, TransformerResults} from "./ConfigurationTransformer";
import _ from "lodash";
export enum PathConfigurationFrom {
Database,
Default
}
export type PathConfiguration = {
value: TransformerResults,
from: PathConfigurationFrom
}
export class ConfigurationHandler<
TProviderModel extends ConfigurationModel = ConfigurationModel,
@ -48,22 +59,27 @@ export class ConfigurationHandler<
)
}
public getConfigurationByPath(path: string): Nullable<TransformerResults> {
public getConfigurationByPath(path: string): PathConfiguration {
const configuration = this.provider.get(path);
if (!configuration) {
return;
return {
value: _.get(this.provider.defaults, path, null),
from: PathConfigurationFrom.Default
};
}
return this.transformer.getValue(configuration);
return {
value: this.transformer.getValue(configuration),
from: PathConfigurationFrom.Database
};
}
private getCompleteDatabaseConfig(): Partial<TRuntimeConfiguration> {
const values = this.provider.getAll();
const configuration: Partial<TRuntimeConfiguration> = {};
values.forEach((configValue) => {
const value = this.transformer.getValue(configValue);
setPath(configuration, configValue.key, value);
_.set(configuration, configValue.key, value);
})
return configuration;

View file

@ -29,9 +29,6 @@ export type CalendarRuntimeGroupConfiguration = {
location: null | string
}
export type GroupConfigurationResult =
ChannelId | Intl.Locale | boolean | string | null
export class GroupConfigurationProvider implements ConfigurationProvider<
GroupConfigurationModel,
RuntimeGroupConfiguration
@ -66,9 +63,13 @@ export class GroupConfigurationProvider implements ConfigurationProvider<
if (value.id) {
// @ts-expect-error id is set, due to the check on line above
this.repository.update(value);
return
}
this.repository.create(value);
this.repository.create({
...value,
group: this.group
});
}
getTransformer(): ConfigurationTransformer {
return new ConfigurationTransformer(

View file

@ -1,8 +1,10 @@
import {ConfigurationHandler} from "./ConfigurationHandler";
import {ConfigurationHandler, PathConfigurationFrom} from "./ConfigurationHandler";
import {
AnyMenuItem,
CollectionMenuItem,
FieldMenuItem, FieldMenuItemContext, FieldMenuItemSaveValue,
FieldMenuItem,
FieldMenuItemContext,
FieldMenuItemSaveValue,
MenuItem,
MenuItemType,
PromptMenuItem
@ -12,11 +14,11 @@ import {
channelMention,
ChannelSelectMenuBuilder,
ChannelType,
inlineCode,
italic,
StringSelectMenuBuilder, TextInputBuilder, TextInputStyle
StringSelectMenuBuilder,
TextInputBuilder,
TextInputStyle
} from "discord.js";
import {ChannelId} from "../types/DiscordTypes";
import {MessageActionRowComponentBuilder} from "@discordjs/builders";
import {TransformerType} from "./ConfigurationTransformer";
@ -101,14 +103,14 @@ export class MenuHandler {
private getChannelValue(context: FieldMenuItemContext): string {
const value = this.config.getConfigurationByPath(context.path.join('.'));
if (value === undefined) {
return italic("None");
const isDefault = value.from === PathConfigurationFrom.Default;
const display = !value ? "None" : channelMention(<string>value.value);
if (isDefault) {
return italic(`Default (${display})`)
}
if (!value) {
return inlineCode("None");
}
return channelMention(<ChannelId>value);
return display;
}
private getChannelMenuBuilder(): MessageActionRowComponentBuilder {
@ -119,11 +121,14 @@ export class MenuHandler {
private getPermissionBooleanValue(context: FieldMenuItemContext) {
const value = this.config.getConfigurationByPath(context.path.join('.'));
if (value === undefined) {
return italic("None");
}
return value ? 'Allowed' : "Disallowed";
const isDefault = value.from === PathConfigurationFrom.Default;
const display = value.value === null ? "None" : value.value == true ? "Allowed" : "Disallowed";
if (isDefault) {
return italic(`Default (${display})`)
}
return display;
}
private getPermissionBooleanBuilder() {
@ -144,15 +149,8 @@ export class MenuHandler {
private getStringValue(context: FieldMenuItemContext): string {
const value = this.config.getConfigurationByPath(context.path.join('.'));
if (!value) {
return "";
}
if (typeof value !== 'string') {
throw new TypeError(`Value of type ${typeof value} can't be used for a string value!`)
}
return value;
return value.value === null ? "" : <string>value.value;
}
private getStringBuilder(): TextInputBuilder {

View file

@ -0,0 +1,70 @@
import {ConfigurationProvider} from "../ConfigurationProvider";
import {ServerConfigurationModel} from "../../Database/Models/ServerConfigurationModel";
import {ServerConfigurationRepository} from "../../Database/Repositories/ServerConfigurationRepository";
import {Snowflake} from "discord.js";
import { ConfigurationModel } from "../../Database/Models/ConfigurationModel";
import { Model } from "../../Database/Models/Model";
import { Nullable } from "../../types/Nullable";
import {ConfigurationTransformer, TransformerType} from "../ConfigurationTransformer";
export type RuntimeServerConfiguration = {
permissions: PermissionRuntimeServerConfiguration
}
export type PermissionRuntimeServerConfiguration = {
groupCreation: GroupCreatePermissionRuntimeServerConfiguration
}
export type GroupCreatePermissionRuntimeServerConfiguration = {
allowEveryone: boolean
}
export class ServerConfigurationProvider implements ConfigurationProvider<
ServerConfigurationModel,
RuntimeServerConfiguration
> {
constructor(
private readonly repository: ServerConfigurationRepository,
private readonly serverid: Snowflake
) {
}
get defaults(): RuntimeServerConfiguration {
return {
permissions: {
groupCreation: {
allowEveryone: false
}
}
}
}
get(path: string): Nullable<ServerConfigurationModel> {
return this.repository.findConfigurationByPath(this.serverid, path);
}
getAll(): ServerConfigurationModel[] {
return this.repository.findServerConfigurations(this.serverid);
}
save(value: Omit<ConfigurationModel, "id"> & Partial<Model>): void {
if (value.id) {
// @ts-expect-error id is set, due to the check on line above
this.repository.update(value);
return
}
this.repository.create({
...value,
serverid: this.serverid
});
}
getTransformer(): ConfigurationTransformer {
return new ConfigurationTransformer(
[
{
path: ['permissions', 'groupCreation', 'allowEveryone'],
type: TransformerType.PermissionBoolean
}
]
)
}
}