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.
This commit is contained in:
135
ts/models/session.ts
Normal file
135
ts/models/session.ts
Normal file
@@ -0,0 +1,135 @@
|
||||
/**
|
||||
* Session model for Stack.Gallery Registry
|
||||
*/
|
||||
|
||||
import * as plugins from '../plugins.ts';
|
||||
import type { ISession } from '../interfaces/auth.interfaces.ts';
|
||||
import { getDb } from './db.ts';
|
||||
|
||||
@plugins.smartdata.Collection(() => getDb())
|
||||
export class Session
|
||||
extends plugins.smartdata.SmartDataDbDoc<Session, Session>
|
||||
implements ISession
|
||||
{
|
||||
@plugins.smartdata.unI()
|
||||
public id: string = '';
|
||||
|
||||
@plugins.smartdata.svDb()
|
||||
@plugins.smartdata.index()
|
||||
public userId: string = '';
|
||||
|
||||
@plugins.smartdata.svDb()
|
||||
public userAgent: string = '';
|
||||
|
||||
@plugins.smartdata.svDb()
|
||||
public ipAddress: string = '';
|
||||
|
||||
@plugins.smartdata.svDb()
|
||||
@plugins.smartdata.index()
|
||||
public isValid: boolean = true;
|
||||
|
||||
@plugins.smartdata.svDb()
|
||||
public invalidatedAt?: Date;
|
||||
|
||||
@plugins.smartdata.svDb()
|
||||
public invalidatedReason?: string;
|
||||
|
||||
@plugins.smartdata.svDb()
|
||||
public lastActivityAt: Date = new Date();
|
||||
|
||||
@plugins.smartdata.svDb()
|
||||
@plugins.smartdata.index()
|
||||
public createdAt: Date = new Date();
|
||||
|
||||
/**
|
||||
* Create a new session
|
||||
*/
|
||||
public static async createSession(data: {
|
||||
userId: string;
|
||||
userAgent: string;
|
||||
ipAddress: string;
|
||||
}): Promise<Session> {
|
||||
const session = new Session();
|
||||
session.id = await Session.getNewId();
|
||||
session.userId = data.userId;
|
||||
session.userAgent = data.userAgent;
|
||||
session.ipAddress = data.ipAddress;
|
||||
session.isValid = true;
|
||||
session.lastActivityAt = new Date();
|
||||
session.createdAt = new Date();
|
||||
await session.save();
|
||||
return session;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find valid session by ID
|
||||
*/
|
||||
public static async findValidSession(sessionId: string): Promise<Session | null> {
|
||||
const session = await Session.getInstance({
|
||||
id: sessionId,
|
||||
isValid: true,
|
||||
});
|
||||
|
||||
if (!session) return null;
|
||||
|
||||
// Check if session is expired (7 days)
|
||||
const maxAge = 7 * 24 * 60 * 60 * 1000;
|
||||
if (Date.now() - session.createdAt.getTime() > maxAge) {
|
||||
await session.invalidate('expired');
|
||||
return null;
|
||||
}
|
||||
|
||||
return session;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all valid sessions for a user
|
||||
*/
|
||||
public static async getUserSessions(userId: string): Promise<Session[]> {
|
||||
return await Session.getInstances({
|
||||
userId,
|
||||
isValid: true,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Invalidate all sessions for a user
|
||||
*/
|
||||
public static async invalidateAllUserSessions(
|
||||
userId: string,
|
||||
reason: string = 'logout_all'
|
||||
): Promise<number> {
|
||||
const sessions = await Session.getUserSessions(userId);
|
||||
for (const session of sessions) {
|
||||
await session.invalidate(reason);
|
||||
}
|
||||
return sessions.length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Invalidate this session
|
||||
*/
|
||||
public async invalidate(reason: string): Promise<void> {
|
||||
this.isValid = false;
|
||||
this.invalidatedAt = new Date();
|
||||
this.invalidatedReason = reason;
|
||||
await this.save();
|
||||
}
|
||||
|
||||
/**
|
||||
* Update last activity
|
||||
*/
|
||||
public async touchActivity(): Promise<void> {
|
||||
this.lastActivityAt = new Date();
|
||||
await this.save();
|
||||
}
|
||||
|
||||
/**
|
||||
* Lifecycle hook
|
||||
*/
|
||||
public async beforeSave(): Promise<void> {
|
||||
if (!this.id) {
|
||||
this.id = await Session.getNewId();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user