AI Implementation feature(859): Admin Area General Settings and Categories (#21)
This commit was merged in pull request #21.
This commit is contained in:
@@ -0,0 +1,100 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
import { ConfigService } from '@nestjs/config';
|
||||
import { SettingsService } from '../settings/settings.module';
|
||||
import { ThemeLoaderService } from '../../common/utils/theme-loader.service';
|
||||
import { SseHubService } from '../../common/services/sse-hub.service';
|
||||
import { SETTINGS_KEYS } from '../../config/env.schema';
|
||||
import { GeneralSettingsPayload } from './dto/general.dto';
|
||||
|
||||
export interface GeneralSettingsView {
|
||||
pageTitle: string;
|
||||
logo: string;
|
||||
welcomeMarkdown: string;
|
||||
themeKey: string;
|
||||
eventStartUtc: string;
|
||||
eventEndUtc: string;
|
||||
defaultChallengeIp: string;
|
||||
registrationsEnabled: boolean;
|
||||
}
|
||||
|
||||
export interface ThemeView {
|
||||
id: string;
|
||||
key: string;
|
||||
name: string;
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
export class AdminGeneralService {
|
||||
constructor(
|
||||
private readonly settings: SettingsService,
|
||||
private readonly themes: ThemeLoaderService,
|
||||
private readonly hub: SseHubService,
|
||||
private readonly config: ConfigService,
|
||||
) {}
|
||||
|
||||
async getSettings(): Promise<GeneralSettingsView> {
|
||||
const [pageTitle, logo, welcomeMarkdown, themeKey, eventStartUtc, eventEndUtc, defaultChallengeIp, registrationsEnabled] =
|
||||
await Promise.all([
|
||||
this.settings.get(SETTINGS_KEYS.PAGE_TITLE, 'HIPCTF'),
|
||||
this.settings.get(SETTINGS_KEYS.LOGO, ''),
|
||||
this.settings.get(SETTINGS_KEYS.WELCOME_MARKDOWN, ''),
|
||||
this.settings.get(SETTINGS_KEYS.THEME_KEY, 'classic'),
|
||||
this.settings.get(SETTINGS_KEYS.EVENT_START_UTC, ''),
|
||||
this.settings.get(SETTINGS_KEYS.EVENT_END_UTC, ''),
|
||||
this.settings.get(SETTINGS_KEYS.DEFAULT_CHALLENGE_IP, '127.0.0.1'),
|
||||
this.settings.get(SETTINGS_KEYS.REGISTRATIONS_ENABLED, 'false'),
|
||||
]);
|
||||
return {
|
||||
pageTitle,
|
||||
logo,
|
||||
welcomeMarkdown,
|
||||
themeKey,
|
||||
eventStartUtc,
|
||||
eventEndUtc,
|
||||
defaultChallengeIp,
|
||||
registrationsEnabled: registrationsEnabled === 'true',
|
||||
};
|
||||
}
|
||||
|
||||
async updateSettings(payload: GeneralSettingsPayload): Promise<GeneralSettingsView> {
|
||||
await Promise.all([
|
||||
this.settings.set(SETTINGS_KEYS.PAGE_TITLE, payload.pageTitle),
|
||||
this.settings.set(SETTINGS_KEYS.LOGO, payload.logo),
|
||||
this.settings.set(SETTINGS_KEYS.WELCOME_MARKDOWN, payload.welcomeMarkdown),
|
||||
this.settings.set(SETTINGS_KEYS.THEME_KEY, payload.themeKey),
|
||||
this.settings.set(SETTINGS_KEYS.EVENT_START_UTC, payload.eventStartUtc),
|
||||
this.settings.set(SETTINGS_KEYS.EVENT_END_UTC, payload.eventEndUtc),
|
||||
this.settings.set(SETTINGS_KEYS.DEFAULT_CHALLENGE_IP, payload.defaultChallengeIp),
|
||||
this.settings.set(SETTINGS_KEYS.REGISTRATIONS_ENABLED, payload.registrationsEnabled ? 'true' : 'false'),
|
||||
]);
|
||||
this.hub.emitEvent({ topic: 'general', themeKey: payload.themeKey });
|
||||
return this.getSettings();
|
||||
}
|
||||
|
||||
listThemes(): ThemeView[] {
|
||||
const themesDir = path.resolve(this.config.get<string>('THEMES_DIR', './themes'));
|
||||
let present = new Set<string>();
|
||||
try {
|
||||
if (fs.existsSync(themesDir)) {
|
||||
for (const f of fs.readdirSync(themesDir)) {
|
||||
if (!f.endsWith('.json')) continue;
|
||||
try {
|
||||
const raw = fs.readFileSync(path.join(themesDir, f), 'utf-8');
|
||||
const parsed = JSON.parse(raw) as { id?: string };
|
||||
if (parsed?.id) present.add(parsed.id);
|
||||
} catch {
|
||||
/* skip unreadable */
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
/* swallow */
|
||||
}
|
||||
return this.themes
|
||||
.listThemes()
|
||||
.filter((t) => present.has(t.id))
|
||||
.map((t) => ({ id: t.id, key: t.id, name: t.name }));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user