feat: Add public endpoint to get registration configuration
Some checks failed
ParentFlow CI/CD Pipeline / Backend Tests (push) Has been cancelled
ParentFlow CI/CD Pipeline / Frontend Tests (push) Has been cancelled
ParentFlow CI/CD Pipeline / Security Scanning (push) Has been cancelled
ParentFlow CI/CD Pipeline / Build Docker Images (map[context:maternal-app/maternal-app-backend dockerfile:Dockerfile.production name:backend]) (push) Has been cancelled
ParentFlow CI/CD Pipeline / Build Docker Images (map[context:maternal-web dockerfile:Dockerfile.production name:frontend]) (push) Has been cancelled
ParentFlow CI/CD Pipeline / Deploy to Development (push) Has been cancelled
ParentFlow CI/CD Pipeline / Deploy to Production (push) Has been cancelled
CI/CD Pipeline / Lint and Test (push) Has been cancelled
CI/CD Pipeline / E2E Tests (push) Has been cancelled
CI/CD Pipeline / Build Application (push) Has been cancelled
Some checks failed
ParentFlow CI/CD Pipeline / Backend Tests (push) Has been cancelled
ParentFlow CI/CD Pipeline / Frontend Tests (push) Has been cancelled
ParentFlow CI/CD Pipeline / Security Scanning (push) Has been cancelled
ParentFlow CI/CD Pipeline / Build Docker Images (map[context:maternal-app/maternal-app-backend dockerfile:Dockerfile.production name:backend]) (push) Has been cancelled
ParentFlow CI/CD Pipeline / Build Docker Images (map[context:maternal-web dockerfile:Dockerfile.production name:frontend]) (push) Has been cancelled
ParentFlow CI/CD Pipeline / Deploy to Development (push) Has been cancelled
ParentFlow CI/CD Pipeline / Deploy to Production (push) Has been cancelled
CI/CD Pipeline / Lint and Test (push) Has been cancelled
CI/CD Pipeline / E2E Tests (push) Has been cancelled
CI/CD Pipeline / Build Application (push) Has been cancelled
Backend Changes: - Added GET /api/v1/auth/registration/config public endpoint - Returns registrationMode and requireInviteCode settings - No authentication required - accessible before registration - Injected ConfigService into AuthController This allows the frontend to dynamically show/hide the invite code field based on the current registration mode setting. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -14,6 +14,7 @@ import {
|
|||||||
Param,
|
Param,
|
||||||
Req,
|
Req,
|
||||||
} from '@nestjs/common';
|
} from '@nestjs/common';
|
||||||
|
import { ConfigService } from '@nestjs/config';
|
||||||
import { AuthService } from './auth.service';
|
import { AuthService } from './auth.service';
|
||||||
import { PasswordResetService } from './password-reset.service';
|
import { PasswordResetService } from './password-reset.service';
|
||||||
import { MFAService } from './mfa.service';
|
import { MFAService } from './mfa.service';
|
||||||
@@ -44,8 +45,25 @@ export class AuthController {
|
|||||||
private readonly sessionService: SessionService,
|
private readonly sessionService: SessionService,
|
||||||
private readonly deviceTrustService: DeviceTrustService,
|
private readonly deviceTrustService: DeviceTrustService,
|
||||||
private readonly biometricAuthService: BiometricAuthService,
|
private readonly biometricAuthService: BiometricAuthService,
|
||||||
|
private readonly configService: ConfigService,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
|
@Public()
|
||||||
|
@Get('registration/config')
|
||||||
|
@HttpCode(HttpStatus.OK)
|
||||||
|
async getRegistrationConfig() {
|
||||||
|
const registrationMode = this.configService.get<string>('REGISTRATION_MODE', 'invite_only');
|
||||||
|
const requireInviteCode = registrationMode === 'invite_only';
|
||||||
|
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
data: {
|
||||||
|
registrationMode,
|
||||||
|
requireInviteCode,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
@Public()
|
@Public()
|
||||||
@Post('register')
|
@Post('register')
|
||||||
@HttpCode(HttpStatus.CREATED)
|
@HttpCode(HttpStatus.CREATED)
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ import * as z from 'zod';
|
|||||||
import { useAuth } from '@/lib/auth/AuthContext';
|
import { useAuth } from '@/lib/auth/AuthContext';
|
||||||
import Link from 'next/link';
|
import Link from 'next/link';
|
||||||
import { useTheme } from '@mui/material/styles';
|
import { useTheme } from '@mui/material/styles';
|
||||||
|
import apiClient from '@/lib/api/client';
|
||||||
|
|
||||||
const registerSchema = z.object({
|
const registerSchema = z.object({
|
||||||
name: z.string().min(2, 'Name must be at least 2 characters'),
|
name: z.string().min(2, 'Name must be at least 2 characters'),
|
||||||
@@ -79,6 +80,8 @@ export default function RegisterPage() {
|
|||||||
const [isLoading, setIsLoading] = useState(false);
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
const [userAge, setUserAge] = useState<number | null>(null);
|
const [userAge, setUserAge] = useState<number | null>(null);
|
||||||
const [requiresParentalConsent, setRequiresParentalConsent] = useState(false);
|
const [requiresParentalConsent, setRequiresParentalConsent] = useState(false);
|
||||||
|
const [requireInviteCode, setRequireInviteCode] = useState(false);
|
||||||
|
const [loadingConfig, setLoadingConfig] = useState(true);
|
||||||
const { register: registerUser } = useAuth();
|
const { register: registerUser } = useAuth();
|
||||||
|
|
||||||
const {
|
const {
|
||||||
@@ -95,6 +98,26 @@ export default function RegisterPage() {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Fetch registration configuration on mount
|
||||||
|
useEffect(() => {
|
||||||
|
const fetchRegistrationConfig = async () => {
|
||||||
|
try {
|
||||||
|
const response = await apiClient.get('/api/v1/auth/registration/config');
|
||||||
|
if (response.data?.success && response.data?.data) {
|
||||||
|
setRequireInviteCode(response.data.data.requireInviteCode);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Failed to fetch registration config:', error);
|
||||||
|
// Default to not requiring invite code if fetch fails
|
||||||
|
setRequireInviteCode(false);
|
||||||
|
} finally {
|
||||||
|
setLoadingConfig(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
fetchRegistrationConfig();
|
||||||
|
}, []);
|
||||||
|
|
||||||
// Watch date of birth to calculate age and show parental consent if needed
|
// Watch date of birth to calculate age and show parental consent if needed
|
||||||
const dateOfBirth = watch('dateOfBirth');
|
const dateOfBirth = watch('dateOfBirth');
|
||||||
|
|
||||||
@@ -244,26 +267,30 @@ export default function RegisterPage() {
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<TextField
|
{requireInviteCode && (
|
||||||
fullWidth
|
<TextField
|
||||||
label="Invite Code (Optional)"
|
fullWidth
|
||||||
margin="normal"
|
label="Invite Code"
|
||||||
error={!!errors.inviteCode}
|
margin="normal"
|
||||||
helperText={errors.inviteCode?.message || 'Leave blank if registration is open'}
|
error={!!errors.inviteCode}
|
||||||
{...register('inviteCode')}
|
helperText={errors.inviteCode?.message || 'Enter your invite code to register'}
|
||||||
disabled={isLoading}
|
{...register('inviteCode')}
|
||||||
inputProps={{
|
disabled={isLoading}
|
||||||
'aria-invalid': !!errors.inviteCode,
|
required
|
||||||
'aria-describedby': errors.inviteCode ? 'invite-code-error' : 'invite-code-helper',
|
inputProps={{
|
||||||
}}
|
'aria-required': 'true',
|
||||||
InputProps={{
|
'aria-invalid': !!errors.inviteCode,
|
||||||
sx: { borderRadius: 3 },
|
'aria-describedby': errors.inviteCode ? 'invite-code-error' : 'invite-code-helper',
|
||||||
}}
|
}}
|
||||||
FormHelperTextProps={{
|
InputProps={{
|
||||||
id: errors.inviteCode ? 'invite-code-error' : 'invite-code-helper',
|
sx: { borderRadius: 3 },
|
||||||
role: errors.inviteCode ? 'alert' : undefined,
|
}}
|
||||||
}}
|
FormHelperTextProps={{
|
||||||
/>
|
id: errors.inviteCode ? 'invite-code-error' : 'invite-code-helper',
|
||||||
|
role: errors.inviteCode ? 'alert' : undefined,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
|
||||||
<TextField
|
<TextField
|
||||||
fullWidth
|
fullWidth
|
||||||
|
|||||||
Reference in New Issue
Block a user