Files
registry/ts/api/handlers/auth.api.ts
Juergen Kunz ab88ac896f feat: implement account settings and API tokens management
- Added SettingsComponent for user profile management, including display name and password change functionality.
- Introduced TokensComponent for managing API tokens, including creation and revocation.
- Created LayoutComponent for consistent application layout with navigation and user information.
- Established main application structure in index.html and main.ts.
- Integrated Tailwind CSS for styling and responsive design.
- Configured TypeScript settings for strict type checking and module resolution.
2025-11-27 22:15:38 +00:00

185 lines
4.1 KiB
TypeScript

/**
* Auth API handlers
*/
import type { IApiContext, IApiResponse } from '../router.ts';
import { AuthService } from '../../services/auth.service.ts';
export class AuthApi {
private authService: AuthService;
constructor(authService: AuthService) {
this.authService = authService;
}
/**
* POST /api/v1/auth/login
*/
public async login(ctx: IApiContext): Promise<IApiResponse> {
try {
const body = await ctx.request.json();
const { email, password } = body;
if (!email || !password) {
return {
status: 400,
body: { error: 'Email and password are required' },
};
}
const result = await this.authService.login(email, password, {
userAgent: ctx.userAgent,
ipAddress: ctx.ip,
});
if (!result.success) {
return {
status: 401,
body: {
error: result.errorMessage,
code: result.errorCode,
},
};
}
return {
status: 200,
body: {
user: {
id: result.user!.id,
email: result.user!.email,
username: result.user!.username,
displayName: result.user!.displayName,
isSystemAdmin: result.user!.isSystemAdmin,
},
accessToken: result.accessToken,
refreshToken: result.refreshToken,
sessionId: result.sessionId,
},
};
} catch (error) {
console.error('[AuthApi] Login error:', error);
return {
status: 500,
body: { error: 'Login failed' },
};
}
}
/**
* POST /api/v1/auth/refresh
*/
public async refresh(ctx: IApiContext): Promise<IApiResponse> {
try {
const body = await ctx.request.json();
const { refreshToken } = body;
if (!refreshToken) {
return {
status: 400,
body: { error: 'Refresh token is required' },
};
}
const result = await this.authService.refresh(refreshToken);
if (!result.success) {
return {
status: 401,
body: {
error: result.errorMessage,
code: result.errorCode,
},
};
}
return {
status: 200,
body: {
accessToken: result.accessToken,
},
};
} catch (error) {
console.error('[AuthApi] Refresh error:', error);
return {
status: 500,
body: { error: 'Token refresh failed' },
};
}
}
/**
* POST /api/v1/auth/logout
*/
public async logout(ctx: IApiContext): Promise<IApiResponse> {
if (!ctx.actor?.userId) {
return {
status: 401,
body: { error: 'Authentication required' },
};
}
try {
const body = await ctx.request.json().catch(() => ({}));
const { sessionId, all } = body;
if (all) {
const count = await this.authService.logoutAll(ctx.actor.userId, {
ipAddress: ctx.ip,
});
return {
status: 200,
body: { message: `Logged out from ${count} sessions` },
};
}
if (sessionId) {
await this.authService.logout(sessionId, {
userId: ctx.actor.userId,
ipAddress: ctx.ip,
});
}
return {
status: 200,
body: { message: 'Logged out successfully' },
};
} catch (error) {
console.error('[AuthApi] Logout error:', error);
return {
status: 500,
body: { error: 'Logout failed' },
};
}
}
/**
* GET /api/v1/auth/me
*/
public async me(ctx: IApiContext): Promise<IApiResponse> {
if (!ctx.actor?.userId || !ctx.actor.user) {
return {
status: 401,
body: { error: 'Authentication required' },
};
}
const user = ctx.actor.user;
return {
status: 200,
body: {
id: user.id,
email: user.email,
username: user.username,
displayName: user.displayName,
avatarUrl: user.avatarUrl,
isSystemAdmin: user.isSystemAdmin,
isActive: user.isActive,
createdAt: user.createdAt,
lastLoginAt: user.lastLoginAt,
},
};
}
}