Skip to content

Commit 1370711

Browse files
committed
feat(global-settings): add login and email registration settings with checks in auth routes
1 parent 9f7359f commit 1370711

File tree

8 files changed

+90
-5
lines changed

8 files changed

+90
-5
lines changed

services/backend/src/global-settings/global.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,22 @@ export const globalSettings: GlobalSettingsModule = {
2424
description: 'Enable or disable email sending functionality',
2525
encrypted: false,
2626
required: false
27+
},
28+
{
29+
key: 'global.enable_login',
30+
defaultValue: true,
31+
type: 'boolean',
32+
description: 'Enable or disable all login functionality (email, GitHub, etc.)',
33+
encrypted: false,
34+
required: false
35+
},
36+
{
37+
key: 'global.enable_email_registration',
38+
defaultValue: true,
39+
type: 'boolean',
40+
description: 'Enable or disable email registration',
41+
encrypted: false,
42+
required: false
2743
}
2844
]
2945
};

services/backend/src/global-settings/index.ts

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -406,14 +406,18 @@ export class GlobalSettingsInitService {
406406
try {
407407
const settings = await Promise.all([
408408
GlobalSettingsService.get('global.page_url'),
409-
GlobalSettingsService.get('global.send_mail')
409+
GlobalSettingsService.get('global.send_mail'),
410+
GlobalSettingsService.get('global.enable_login'),
411+
GlobalSettingsService.get('global.enable_email_registration')
410412
]);
411413

412-
const [pageUrl, sendMail] = settings;
414+
const [pageUrl, sendMail, enableLogin, enableEmailRegistration] = settings;
413415

414416
return {
415417
pageUrl: pageUrl?.value || 'http://localhost:5173',
416-
sendMail: sendMail?.value === 'true'
418+
sendMail: sendMail?.value === 'true',
419+
enableLogin: enableLogin?.value === 'true',
420+
enableEmailRegistration: enableEmailRegistration?.value === 'true'
417421
};
418422
} catch (error) {
419423
console.error('Failed to get Global configuration:', error);
@@ -446,6 +450,32 @@ export class GlobalSettingsInitService {
446450
return 'http://localhost:5173'; // Default fallback
447451
}
448452
}
453+
454+
/**
455+
* Check if login is enabled (all types: email, GitHub, etc.)
456+
*/
457+
static async isLoginEnabled(): Promise<boolean> {
458+
try {
459+
const setting = await GlobalSettingsService.get('global.enable_login');
460+
return setting?.value === 'true';
461+
} catch (error) {
462+
console.error('Failed to check if login is enabled:', error);
463+
return true; // Default to enabled if there's an error
464+
}
465+
}
466+
467+
/**
468+
* Check if email registration is enabled
469+
*/
470+
static async isEmailRegistrationEnabled(): Promise<boolean> {
471+
try {
472+
const setting = await GlobalSettingsService.get('global.enable_email_registration');
473+
return setting?.value === 'true';
474+
} catch (error) {
475+
console.error('Failed to check if email registration is enabled:', error);
476+
return true; // Default to enabled if there's an error
477+
}
478+
}
449479
}
450480

451481
// Export the helper class

services/backend/src/global-settings/types.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,8 @@ export interface GitHubOAuthConfig {
8181
export interface GlobalConfig {
8282
pageUrl: string;
8383
sendMail: boolean;
84+
enableLogin: boolean;
85+
enableEmailRegistration: boolean;
8486
}
8587

8688
export interface InitializationResult {

services/backend/src/routes/auth/github.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { getDb, getSchema } from '../../db';
66
import { eq } from 'drizzle-orm';
77
import { generateId } from 'lucia';
88
import { generateState } from 'arctic';
9+
import { GlobalSettingsInitService } from '../../global-settings';
910

1011
// Define types for requests with specific query parameters
1112
const GITHUB_SCOPES = ['user:email']; // Request access to user's email
@@ -15,6 +16,14 @@ export default async function githubAuthRoutes(fastify: FastifyInstance) {
1516
fastify.get(
1617
'/login',
1718
async (_request, reply: FastifyReply) => { // _request type can be FastifyRequest if no specific generics needed here
19+
// Check if login is enabled
20+
const isLoginEnabled = await GlobalSettingsInitService.isLoginEnabled();
21+
if (!isLoginEnabled) {
22+
return reply.status(403).send({
23+
error: 'Login is currently disabled by administrator.'
24+
});
25+
}
26+
1827
const state = generateState();
1928
// PKCE is recommended for OAuth 2.0 public clients, but for confidential clients (server-side),
2029
// state alone is often sufficient for CSRF. Lucia's GitHub provider handles PKCE if code_verifier is passed.
@@ -44,6 +53,14 @@ export default async function githubAuthRoutes(fastify: FastifyInstance) {
4453
fastify.get<{ Querystring: GithubCallbackInput }>(
4554
'/callback',
4655
async (request, reply: FastifyReply) => { // request.query will be typed as GithubCallbackInput by Fastify
56+
// Check if login is enabled
57+
const isLoginEnabled = await GlobalSettingsInitService.isLoginEnabled();
58+
if (!isLoginEnabled) {
59+
return reply.status(403).send({
60+
error: 'Login is currently disabled by administrator.'
61+
});
62+
}
63+
4764
const storedState = request.cookies?.oauth_state; // Access cookies safely, ensure @fastify/cookie is registered
4865
// const storedCodeVerifier = request.cookies?.oauth_code_verifier; // if using PKCE
4966

services/backend/src/routes/auth/loginEmail.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,21 @@ import { getLucia } from '../../lib/lucia'; // Corrected import
44
import { verify } from '@node-rs/argon2';
55
import { getDb, getSchema } from '../../db';
66
import { eq, or } from 'drizzle-orm';
7+
import { GlobalSettingsInitService } from '../../global-settings';
78

89
export default async function loginEmailRoute(fastify: FastifyInstance) {
910
fastify.post(
1011
'/login',
1112
async (request, reply: FastifyReply) => {
13+
// Check if login is enabled
14+
const isLoginEnabled = await GlobalSettingsInitService.isLoginEnabled();
15+
if (!isLoginEnabled) {
16+
return reply.status(403).send({
17+
success: false,
18+
error: 'Login is currently disabled by administrator.'
19+
});
20+
}
21+
1222
// eslint-disable-next-line @typescript-eslint/no-explicit-any
1323
const { login, email, password } = request.body as any;
1424

services/backend/src/routes/auth/registerEmail.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,21 @@ import { eq, or } from 'drizzle-orm';
77
import { generateId } from 'lucia'; // Lucia's utility for generating IDs
88
import { hash } from '@node-rs/argon2';
99
import { TeamService } from '../../services/teamService';
10+
import { GlobalSettingsInitService } from '../../global-settings';
1011

1112
export default async function registerEmailRoute(fastify: FastifyInstance) {
1213
fastify.post<{ Body: RegisterEmailInput }>( // Use Fastify's generic type for request body
1314
'/register',
1415
async (request, reply: FastifyReply) => { // request type will be inferred by Fastify
16+
// Check if email registration is enabled
17+
const isEmailRegistrationEnabled = await GlobalSettingsInitService.isEmailRegistrationEnabled();
18+
if (!isEmailRegistrationEnabled) {
19+
return reply.status(403).send({
20+
success: false,
21+
error: 'Email registration is currently disabled by administrator.'
22+
});
23+
}
24+
1525
const { username, email, password, first_name, last_name } = request.body; // request.body should now be typed as RegisterEmailInput
1626

1727
const db = getDb();

services/frontend/src/assets/index.css

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ input {
120120
}
121121

122122
.bg-card {
123-
background-color: var(--color-muted);
123+
background-color: oklch(96.8% 0.007 247.896)
124124
}
125125

126126
/* Global cursor pointer for buttons and interactive elements */

services/frontend/src/router/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ const routes = [
7676
children: [
7777
{
7878
path: 'settings',
79-
redirect: '/admin/settings/smtp'
79+
redirect: '/admin/settings/global'
8080
},
8181
{
8282
path: 'settings/:groupId',

0 commit comments

Comments
 (0)