@blackms/aistack 1.3.0 → 1.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agents/definitions/devops.d.ts +6 -0
- package/dist/agents/definitions/devops.d.ts.map +1 -0
- package/dist/agents/definitions/devops.js +65 -0
- package/dist/agents/definitions/devops.js.map +1 -0
- package/dist/agents/definitions/documentation.d.ts +6 -0
- package/dist/agents/definitions/documentation.d.ts.map +1 -0
- package/dist/agents/definitions/documentation.js +72 -0
- package/dist/agents/definitions/documentation.js.map +1 -0
- package/dist/agents/definitions/index.d.ts +3 -0
- package/dist/agents/definitions/index.d.ts.map +1 -1
- package/dist/agents/definitions/index.js +3 -0
- package/dist/agents/definitions/index.js.map +1 -1
- package/dist/agents/definitions/security-auditor.d.ts +6 -0
- package/dist/agents/definitions/security-auditor.d.ts.map +1 -0
- package/dist/agents/definitions/security-auditor.js +100 -0
- package/dist/agents/definitions/security-auditor.js.map +1 -0
- package/dist/agents/registry.d.ts.map +1 -1
- package/dist/agents/registry.js +4 -1
- package/dist/agents/registry.js.map +1 -1
- package/dist/agents/spawner.d.ts +26 -1
- package/dist/agents/spawner.d.ts.map +1 -1
- package/dist/agents/spawner.js +94 -1
- package/dist/agents/spawner.js.map +1 -1
- package/dist/auth/index.d.ts +6 -0
- package/dist/auth/index.d.ts.map +1 -0
- package/dist/auth/index.js +6 -0
- package/dist/auth/index.js.map +1 -0
- package/dist/auth/service.d.ts +79 -0
- package/dist/auth/service.d.ts.map +1 -0
- package/dist/auth/service.js +383 -0
- package/dist/auth/service.js.map +1 -0
- package/dist/auth/types.d.ts +48 -0
- package/dist/auth/types.d.ts.map +1 -0
- package/dist/auth/types.js +10 -0
- package/dist/auth/types.js.map +1 -0
- package/dist/coordination/review-loop.d.ts +4 -0
- package/dist/coordination/review-loop.d.ts.map +1 -1
- package/dist/coordination/review-loop.js +54 -19
- package/dist/coordination/review-loop.js.map +1 -1
- package/dist/integrations/slack-notifier.d.ts +63 -0
- package/dist/integrations/slack-notifier.d.ts.map +1 -0
- package/dist/integrations/slack-notifier.js +224 -0
- package/dist/integrations/slack-notifier.js.map +1 -0
- package/dist/integrations/slack.d.ts +50 -0
- package/dist/integrations/slack.d.ts.map +1 -0
- package/dist/integrations/slack.js +225 -0
- package/dist/integrations/slack.js.map +1 -0
- package/dist/memory/index.d.ts +75 -0
- package/dist/memory/index.d.ts.map +1 -1
- package/dist/memory/index.js +101 -0
- package/dist/memory/index.js.map +1 -1
- package/dist/memory/sqlite-store.d.ts +85 -1
- package/dist/memory/sqlite-store.d.ts.map +1 -1
- package/dist/memory/sqlite-store.js +647 -15
- package/dist/memory/sqlite-store.js.map +1 -1
- package/dist/monitoring/health.d.ts +68 -0
- package/dist/monitoring/health.d.ts.map +1 -0
- package/dist/monitoring/health.js +220 -0
- package/dist/monitoring/health.js.map +1 -0
- package/dist/monitoring/metrics.d.ts +31 -0
- package/dist/monitoring/metrics.d.ts.map +1 -0
- package/dist/monitoring/metrics.js +230 -0
- package/dist/monitoring/metrics.js.map +1 -0
- package/dist/providers/index.d.ts.map +1 -1
- package/dist/providers/index.js +132 -94
- package/dist/providers/index.js.map +1 -1
- package/dist/types.d.ts +36 -2
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/utils/config.d.ts.map +1 -1
- package/dist/utils/config.js +12 -0
- package/dist/utils/config.js.map +1 -1
- package/dist/utils/index.d.ts +1 -1
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +1 -1
- package/dist/utils/index.js.map +1 -1
- package/dist/utils/logger.d.ts +24 -7
- package/dist/utils/logger.d.ts.map +1 -1
- package/dist/utils/logger.js +128 -20
- package/dist/utils/logger.js.map +1 -1
- package/dist/utils/retry.d.ts +49 -0
- package/dist/utils/retry.d.ts.map +1 -0
- package/dist/utils/retry.js +160 -0
- package/dist/utils/retry.js.map +1 -0
- package/dist/utils/semaphore.d.ts +75 -0
- package/dist/utils/semaphore.d.ts.map +1 -0
- package/dist/utils/semaphore.js +185 -0
- package/dist/utils/semaphore.js.map +1 -0
- package/dist/utils/validation.d.ts +2 -2
- package/dist/web/middleware/auth.d.ts +16 -10
- package/dist/web/middleware/auth.d.ts.map +1 -1
- package/dist/web/middleware/auth.js +152 -12
- package/dist/web/middleware/auth.js.map +1 -1
- package/dist/web/routes/auth.d.ts +50 -0
- package/dist/web/routes/auth.d.ts.map +1 -0
- package/dist/web/routes/auth.js +216 -0
- package/dist/web/routes/auth.js.map +1 -0
- package/dist/web/routes/index.d.ts +2 -0
- package/dist/web/routes/index.d.ts.map +1 -1
- package/dist/web/routes/index.js +2 -0
- package/dist/web/routes/index.js.map +1 -1
- package/dist/web/routes/memory.d.ts.map +1 -1
- package/dist/web/routes/memory.js +188 -0
- package/dist/web/routes/memory.js.map +1 -1
- package/dist/web/routes/review-loops.d.ts +12 -0
- package/dist/web/routes/review-loops.d.ts.map +1 -0
- package/dist/web/routes/review-loops.js +157 -0
- package/dist/web/routes/review-loops.js.map +1 -0
- package/dist/web/routes/sessions.d.ts.map +1 -1
- package/dist/web/routes/sessions.js +14 -0
- package/dist/web/routes/sessions.js.map +1 -1
- package/dist/web/routes/system.d.ts.map +1 -1
- package/dist/web/routes/system.js +34 -23
- package/dist/web/routes/system.js.map +1 -1
- package/dist/web/routes/workflows.d.ts.map +1 -1
- package/dist/web/routes/workflows.js +13 -1
- package/dist/web/routes/workflows.js.map +1 -1
- package/dist/web/server.d.ts +1 -0
- package/dist/web/server.d.ts.map +1 -1
- package/dist/web/server.js +30 -2
- package/dist/web/server.js.map +1 -1
- package/dist/web/utils/request.d.ts +13 -0
- package/dist/web/utils/request.d.ts.map +1 -0
- package/dist/web/utils/request.js +49 -0
- package/dist/web/utils/request.js.map +1 -0
- package/dist/web/websocket/handler.d.ts +4 -0
- package/dist/web/websocket/handler.d.ts.map +1 -1
- package/dist/web/websocket/handler.js +59 -0
- package/dist/web/websocket/handler.js.map +1 -1
- package/dist/workflows/doc-sync.d.ts.map +1 -1
- package/dist/workflows/doc-sync.js +4 -0
- package/dist/workflows/doc-sync.js.map +1 -1
- package/dist/workflows/full-stack-feature.d.ts +74 -0
- package/dist/workflows/full-stack-feature.d.ts.map +1 -0
- package/dist/workflows/full-stack-feature.js +273 -0
- package/dist/workflows/full-stack-feature.js.map +1 -0
- package/dist/workflows/index.d.ts +1 -0
- package/dist/workflows/index.d.ts.map +1 -1
- package/dist/workflows/index.js +2 -0
- package/dist/workflows/index.js.map +1 -1
- package/dist/workflows/runner.js.map +1 -1
- package/dist/workflows/types.d.ts +6 -5
- package/dist/workflows/types.d.ts.map +1 -1
- package/package.json +12 -5
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Authentication service
|
|
3
|
+
*/
|
|
4
|
+
import type Database from 'better-sqlite3';
|
|
5
|
+
import type { User, AuthTokens, JWTPayload, LoginCredentials, RegisterData, UserRole } from './types.js';
|
|
6
|
+
export declare class AuthService {
|
|
7
|
+
private db;
|
|
8
|
+
private jwtSecret;
|
|
9
|
+
private refreshSecret;
|
|
10
|
+
constructor(db: Database.Database, jwtSecret?: string, refreshSecret?: string);
|
|
11
|
+
/**
|
|
12
|
+
* Initialize database schema for authentication
|
|
13
|
+
*/
|
|
14
|
+
private initDatabase;
|
|
15
|
+
/**
|
|
16
|
+
* Create default admin user
|
|
17
|
+
*/
|
|
18
|
+
private createDefaultAdmin;
|
|
19
|
+
/**
|
|
20
|
+
* Generate a secure random secret
|
|
21
|
+
*/
|
|
22
|
+
private generateSecret;
|
|
23
|
+
/**
|
|
24
|
+
* Register a new user
|
|
25
|
+
*/
|
|
26
|
+
register(data: RegisterData, role?: UserRole): Promise<User>;
|
|
27
|
+
/**
|
|
28
|
+
* Authenticate user and generate tokens
|
|
29
|
+
*/
|
|
30
|
+
login(credentials: LoginCredentials): Promise<{
|
|
31
|
+
user: User;
|
|
32
|
+
tokens: AuthTokens;
|
|
33
|
+
}>;
|
|
34
|
+
/**
|
|
35
|
+
* Generate access and refresh tokens
|
|
36
|
+
*/
|
|
37
|
+
private generateTokens;
|
|
38
|
+
/**
|
|
39
|
+
* Store refresh token in database
|
|
40
|
+
*/
|
|
41
|
+
private storeRefreshToken;
|
|
42
|
+
/**
|
|
43
|
+
* Verify access token
|
|
44
|
+
*/
|
|
45
|
+
verifyAccessToken(token: string): JWTPayload;
|
|
46
|
+
/**
|
|
47
|
+
* Refresh access token using refresh token
|
|
48
|
+
*/
|
|
49
|
+
refreshAccessToken(refreshToken: string): Promise<AuthTokens>;
|
|
50
|
+
/**
|
|
51
|
+
* Revoke refresh token (logout)
|
|
52
|
+
*/
|
|
53
|
+
logout(refreshToken: string): Promise<void>;
|
|
54
|
+
/**
|
|
55
|
+
* Get user by ID
|
|
56
|
+
*/
|
|
57
|
+
getUserById(userId: string): User | undefined;
|
|
58
|
+
/**
|
|
59
|
+
* Get user by email
|
|
60
|
+
*/
|
|
61
|
+
getUserByEmail(email: string): User | undefined;
|
|
62
|
+
/**
|
|
63
|
+
* List all users (admin only)
|
|
64
|
+
*/
|
|
65
|
+
listUsers(): Array<Omit<User, 'passwordHash'>>;
|
|
66
|
+
/**
|
|
67
|
+
* Update user role (admin only)
|
|
68
|
+
*/
|
|
69
|
+
updateUserRole(userId: string, role: UserRole): void;
|
|
70
|
+
/**
|
|
71
|
+
* Delete user (admin only)
|
|
72
|
+
*/
|
|
73
|
+
deleteUser(userId: string): void;
|
|
74
|
+
/**
|
|
75
|
+
* Change user password
|
|
76
|
+
*/
|
|
77
|
+
changePassword(userId: string, oldPassword: string, newPassword: string): Promise<void>;
|
|
78
|
+
}
|
|
79
|
+
//# sourceMappingURL=service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../src/auth/service.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAC;AAE3C,OAAO,KAAK,EACV,IAAI,EACJ,UAAU,EACV,UAAU,EACV,gBAAgB,EAChB,YAAY,EACZ,QAAQ,EACT,MAAM,YAAY,CAAC;AAQpB,qBAAa,WAAW;IACtB,OAAO,CAAC,EAAE,CAAoB;IAC9B,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,aAAa,CAAS;gBAG5B,EAAE,EAAE,QAAQ,CAAC,QAAQ,EACrB,SAAS,CAAC,EAAE,MAAM,EAClB,aAAa,CAAC,EAAE,MAAM;IAaxB;;OAEG;IACH,OAAO,CAAC,YAAY;IA6CpB;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAyB1B;;OAEG;IACH,OAAO,CAAC,cAAc;IAItB;;OAEG;IACG,QAAQ,CAAC,IAAI,EAAE,YAAY,EAAE,IAAI,GAAE,QAAkC,GAAG,OAAO,CAAC,IAAI,CAAC;IAsC3F;;OAEG;IACG,KAAK,CAAC,WAAW,EAAE,gBAAgB,GAAG,OAAO,CAAC;QAAE,IAAI,EAAE,IAAI,CAAC;QAAC,MAAM,EAAE,UAAU,CAAA;KAAE,CAAC;IAiDvF;;OAEG;IACH,OAAO,CAAC,cAAc;IAuBtB;;OAEG;YACW,iBAAiB;IAuB/B;;OAEG;IACH,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,UAAU;IAe5C;;OAEG;IACG,kBAAkB,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;IAoDnE;;OAEG;IACG,MAAM,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAejD;;OAEG;IACH,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS;IAmB7C;;OAEG;IACH,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS;IAmB/C;;OAEG;IACH,SAAS,IAAI,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,cAAc,CAAC,CAAC;IAc9C;;OAEG;IACH,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,GAAG,IAAI;IAQpD;;OAEG;IACH,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAKhC;;OAEG;IACG,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAkC9F"}
|
|
@@ -0,0 +1,383 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Authentication service
|
|
3
|
+
*/
|
|
4
|
+
import { randomUUID } from 'node:crypto';
|
|
5
|
+
import jwt from 'jsonwebtoken';
|
|
6
|
+
import bcrypt from 'bcrypt';
|
|
7
|
+
import { logger } from '../utils/logger.js';
|
|
8
|
+
const log = logger.child('auth');
|
|
9
|
+
const SALT_ROUNDS = 10;
|
|
10
|
+
const ACCESS_TOKEN_EXPIRY = '15m'; // 15 minutes
|
|
11
|
+
const REFRESH_TOKEN_EXPIRY = '7d'; // 7 days
|
|
12
|
+
export class AuthService {
|
|
13
|
+
db;
|
|
14
|
+
jwtSecret;
|
|
15
|
+
refreshSecret;
|
|
16
|
+
constructor(db, jwtSecret, refreshSecret) {
|
|
17
|
+
this.db = db;
|
|
18
|
+
this.jwtSecret = jwtSecret || process.env.JWT_SECRET || this.generateSecret();
|
|
19
|
+
this.refreshSecret = refreshSecret || process.env.REFRESH_SECRET || this.generateSecret();
|
|
20
|
+
if (!process.env.JWT_SECRET) {
|
|
21
|
+
log.warn('No JWT_SECRET set, using generated secret (not suitable for production)');
|
|
22
|
+
}
|
|
23
|
+
this.initDatabase();
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Initialize database schema for authentication
|
|
27
|
+
*/
|
|
28
|
+
initDatabase() {
|
|
29
|
+
this.db.exec(`
|
|
30
|
+
CREATE TABLE IF NOT EXISTS users (
|
|
31
|
+
id TEXT PRIMARY KEY,
|
|
32
|
+
email TEXT UNIQUE NOT NULL,
|
|
33
|
+
username TEXT UNIQUE NOT NULL,
|
|
34
|
+
password_hash TEXT NOT NULL,
|
|
35
|
+
role TEXT NOT NULL DEFAULT 'developer',
|
|
36
|
+
created_at TEXT NOT NULL,
|
|
37
|
+
updated_at TEXT NOT NULL,
|
|
38
|
+
last_login_at TEXT
|
|
39
|
+
);
|
|
40
|
+
|
|
41
|
+
CREATE INDEX IF NOT EXISTS idx_users_email ON users(email);
|
|
42
|
+
CREATE INDEX IF NOT EXISTS idx_users_username ON users(username);
|
|
43
|
+
|
|
44
|
+
CREATE TABLE IF NOT EXISTS refresh_tokens (
|
|
45
|
+
id TEXT PRIMARY KEY,
|
|
46
|
+
user_id TEXT NOT NULL,
|
|
47
|
+
token_hash TEXT NOT NULL,
|
|
48
|
+
expires_at TEXT NOT NULL,
|
|
49
|
+
created_at TEXT NOT NULL,
|
|
50
|
+
revoked INTEGER DEFAULT 0,
|
|
51
|
+
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
|
|
52
|
+
);
|
|
53
|
+
|
|
54
|
+
CREATE INDEX IF NOT EXISTS idx_refresh_tokens_user ON refresh_tokens(user_id);
|
|
55
|
+
CREATE INDEX IF NOT EXISTS idx_refresh_tokens_expires ON refresh_tokens(expires_at);
|
|
56
|
+
`);
|
|
57
|
+
// Create default admin user if no users exist
|
|
58
|
+
const userCount = this.db
|
|
59
|
+
.prepare('SELECT COUNT(*) as count FROM users')
|
|
60
|
+
.get();
|
|
61
|
+
if (userCount.count === 0) {
|
|
62
|
+
log.info('Creating default admin user');
|
|
63
|
+
try {
|
|
64
|
+
this.createDefaultAdmin();
|
|
65
|
+
}
|
|
66
|
+
catch (error) {
|
|
67
|
+
log.error('Failed to create default admin user', { error });
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Create default admin user
|
|
73
|
+
*/
|
|
74
|
+
createDefaultAdmin() {
|
|
75
|
+
const defaultPassword = process.env.ADMIN_PASSWORD || 'admin123';
|
|
76
|
+
const passwordHash = bcrypt.hashSync(defaultPassword, SALT_ROUNDS);
|
|
77
|
+
this.db
|
|
78
|
+
.prepare(`INSERT INTO users (id, email, username, password_hash, role, created_at, updated_at)
|
|
79
|
+
VALUES (?, ?, ?, ?, ?, ?, ?)`)
|
|
80
|
+
.run(randomUUID(), 'admin@aistack.local', 'admin', passwordHash, 'admin', new Date().toISOString(), new Date().toISOString());
|
|
81
|
+
log.info('Default admin user created', {
|
|
82
|
+
email: 'admin@aistack.local',
|
|
83
|
+
password: defaultPassword,
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Generate a secure random secret
|
|
88
|
+
*/
|
|
89
|
+
generateSecret() {
|
|
90
|
+
return randomUUID() + randomUUID();
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Register a new user
|
|
94
|
+
*/
|
|
95
|
+
async register(data, role = 'developer') {
|
|
96
|
+
// Validate input
|
|
97
|
+
if (!data.email || !data.username || !data.password) {
|
|
98
|
+
throw new Error('Email, username, and password are required');
|
|
99
|
+
}
|
|
100
|
+
if (data.password.length < 8) {
|
|
101
|
+
throw new Error('Password must be at least 8 characters');
|
|
102
|
+
}
|
|
103
|
+
// Check if user already exists
|
|
104
|
+
const existing = this.db
|
|
105
|
+
.prepare('SELECT id FROM users WHERE email = ? OR username = ?')
|
|
106
|
+
.get(data.email, data.username);
|
|
107
|
+
if (existing) {
|
|
108
|
+
throw new Error('User with this email or username already exists');
|
|
109
|
+
}
|
|
110
|
+
// Hash password
|
|
111
|
+
const passwordHash = await bcrypt.hash(data.password, SALT_ROUNDS);
|
|
112
|
+
// Create user
|
|
113
|
+
const userId = randomUUID();
|
|
114
|
+
const now = new Date().toISOString();
|
|
115
|
+
this.db
|
|
116
|
+
.prepare(`INSERT INTO users (id, email, username, password_hash, role, created_at, updated_at)
|
|
117
|
+
VALUES (?, ?, ?, ?, ?, ?, ?)`)
|
|
118
|
+
.run(userId, data.email, data.username, passwordHash, role, now, now);
|
|
119
|
+
log.info('User registered', { userId, email: data.email, username: data.username });
|
|
120
|
+
return this.getUserById(userId);
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Authenticate user and generate tokens
|
|
124
|
+
*/
|
|
125
|
+
async login(credentials) {
|
|
126
|
+
// Find user
|
|
127
|
+
const user = this.getUserByEmail(credentials.email);
|
|
128
|
+
if (!user) {
|
|
129
|
+
throw new Error('Invalid email or password');
|
|
130
|
+
}
|
|
131
|
+
// Verify password
|
|
132
|
+
const valid = await bcrypt.compare(credentials.password, user.passwordHash);
|
|
133
|
+
if (!valid) {
|
|
134
|
+
throw new Error('Invalid email or password');
|
|
135
|
+
}
|
|
136
|
+
// Generate tokens
|
|
137
|
+
const tokens = this.generateTokens(user);
|
|
138
|
+
// Use transaction to ensure atomic update of last login and token storage
|
|
139
|
+
const now = new Date().toISOString();
|
|
140
|
+
const tokenHash = await bcrypt.hash(tokens.refreshToken, SALT_ROUNDS);
|
|
141
|
+
const expiresAt = new Date(Date.now() + 7 * 24 * 60 * 60 * 1000).toISOString();
|
|
142
|
+
const transaction = this.db.transaction(() => {
|
|
143
|
+
// Update last login
|
|
144
|
+
this.db
|
|
145
|
+
.prepare('UPDATE users SET last_login_at = ? WHERE id = ?')
|
|
146
|
+
.run(now, user.id);
|
|
147
|
+
// Store refresh token
|
|
148
|
+
this.db
|
|
149
|
+
.prepare(`INSERT INTO refresh_tokens (id, user_id, token_hash, expires_at, created_at)
|
|
150
|
+
VALUES (?, ?, ?, ?, ?)`)
|
|
151
|
+
.run(randomUUID(), user.id, tokenHash, expiresAt, now);
|
|
152
|
+
// Clean up expired tokens
|
|
153
|
+
this.db
|
|
154
|
+
.prepare('DELETE FROM refresh_tokens WHERE expires_at < ? OR revoked = 1')
|
|
155
|
+
.run(now);
|
|
156
|
+
});
|
|
157
|
+
transaction();
|
|
158
|
+
log.info('User logged in', { userId: user.id, email: user.email });
|
|
159
|
+
return { user, tokens };
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Generate access and refresh tokens
|
|
163
|
+
*/
|
|
164
|
+
generateTokens(user) {
|
|
165
|
+
const payload = {
|
|
166
|
+
userId: user.id,
|
|
167
|
+
email: user.email,
|
|
168
|
+
username: user.username,
|
|
169
|
+
role: user.role,
|
|
170
|
+
};
|
|
171
|
+
const accessToken = jwt.sign(payload, this.jwtSecret, {
|
|
172
|
+
expiresIn: ACCESS_TOKEN_EXPIRY,
|
|
173
|
+
});
|
|
174
|
+
const refreshToken = jwt.sign({ userId: user.id }, this.refreshSecret, {
|
|
175
|
+
expiresIn: REFRESH_TOKEN_EXPIRY,
|
|
176
|
+
});
|
|
177
|
+
return {
|
|
178
|
+
accessToken,
|
|
179
|
+
refreshToken,
|
|
180
|
+
expiresIn: 15 * 60, // 15 minutes in seconds
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Store refresh token in database
|
|
185
|
+
*/
|
|
186
|
+
async storeRefreshToken(userId, token) {
|
|
187
|
+
const tokenHash = await bcrypt.hash(token, SALT_ROUNDS);
|
|
188
|
+
const expiresAt = new Date(Date.now() + 7 * 24 * 60 * 60 * 1000).toISOString(); // 7 days
|
|
189
|
+
const now = new Date().toISOString();
|
|
190
|
+
// Use transaction to ensure atomic insert and cleanup
|
|
191
|
+
const transaction = this.db.transaction(() => {
|
|
192
|
+
this.db
|
|
193
|
+
.prepare(`INSERT INTO refresh_tokens (id, user_id, token_hash, expires_at, created_at)
|
|
194
|
+
VALUES (?, ?, ?, ?, ?)`)
|
|
195
|
+
.run(randomUUID(), userId, tokenHash, expiresAt, now);
|
|
196
|
+
// Clean up expired tokens
|
|
197
|
+
this.db
|
|
198
|
+
.prepare('DELETE FROM refresh_tokens WHERE expires_at < ? OR revoked = 1')
|
|
199
|
+
.run(now);
|
|
200
|
+
});
|
|
201
|
+
transaction();
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* Verify access token
|
|
205
|
+
*/
|
|
206
|
+
verifyAccessToken(token) {
|
|
207
|
+
try {
|
|
208
|
+
const payload = jwt.verify(token, this.jwtSecret);
|
|
209
|
+
return payload;
|
|
210
|
+
}
|
|
211
|
+
catch (error) {
|
|
212
|
+
if (error instanceof jwt.TokenExpiredError) {
|
|
213
|
+
throw new Error('Token expired');
|
|
214
|
+
}
|
|
215
|
+
if (error instanceof jwt.JsonWebTokenError) {
|
|
216
|
+
throw new Error('Invalid token');
|
|
217
|
+
}
|
|
218
|
+
throw error;
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
/**
|
|
222
|
+
* Refresh access token using refresh token
|
|
223
|
+
*/
|
|
224
|
+
async refreshAccessToken(refreshToken) {
|
|
225
|
+
try {
|
|
226
|
+
// Verify refresh token
|
|
227
|
+
const payload = jwt.verify(refreshToken, this.refreshSecret);
|
|
228
|
+
// Check if token exists and is not revoked
|
|
229
|
+
const storedTokens = this.db
|
|
230
|
+
.prepare(`SELECT * FROM refresh_tokens
|
|
231
|
+
WHERE user_id = ? AND revoked = 0 AND expires_at > ?`)
|
|
232
|
+
.all(payload.userId, new Date().toISOString());
|
|
233
|
+
// Verify at least one stored token matches
|
|
234
|
+
let tokenValid = false;
|
|
235
|
+
for (const stored of storedTokens) {
|
|
236
|
+
if (await bcrypt.compare(refreshToken, stored.token_hash)) {
|
|
237
|
+
tokenValid = true;
|
|
238
|
+
break;
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
if (!tokenValid) {
|
|
242
|
+
throw new Error('Invalid or revoked refresh token');
|
|
243
|
+
}
|
|
244
|
+
// Get user
|
|
245
|
+
const user = this.getUserById(payload.userId);
|
|
246
|
+
if (!user) {
|
|
247
|
+
throw new Error('User not found');
|
|
248
|
+
}
|
|
249
|
+
// Generate new tokens
|
|
250
|
+
const tokens = this.generateTokens(user);
|
|
251
|
+
// Store new refresh token
|
|
252
|
+
await this.storeRefreshToken(user.id, tokens.refreshToken);
|
|
253
|
+
return tokens;
|
|
254
|
+
}
|
|
255
|
+
catch (error) {
|
|
256
|
+
if (error instanceof jwt.TokenExpiredError) {
|
|
257
|
+
throw new Error('Refresh token expired');
|
|
258
|
+
}
|
|
259
|
+
if (error instanceof jwt.JsonWebTokenError) {
|
|
260
|
+
throw new Error('Invalid refresh token');
|
|
261
|
+
}
|
|
262
|
+
throw error;
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
/**
|
|
266
|
+
* Revoke refresh token (logout)
|
|
267
|
+
*/
|
|
268
|
+
async logout(refreshToken) {
|
|
269
|
+
try {
|
|
270
|
+
const payload = jwt.verify(refreshToken, this.refreshSecret);
|
|
271
|
+
// Mark all tokens for this user as revoked
|
|
272
|
+
this.db
|
|
273
|
+
.prepare('UPDATE refresh_tokens SET revoked = 1 WHERE user_id = ?')
|
|
274
|
+
.run(payload.userId);
|
|
275
|
+
log.info('User logged out', { userId: payload.userId });
|
|
276
|
+
}
|
|
277
|
+
catch {
|
|
278
|
+
// Ignore errors - token might be invalid but that's okay for logout
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
/**
|
|
282
|
+
* Get user by ID
|
|
283
|
+
*/
|
|
284
|
+
getUserById(userId) {
|
|
285
|
+
const row = this.db
|
|
286
|
+
.prepare('SELECT * FROM users WHERE id = ?')
|
|
287
|
+
.get(userId);
|
|
288
|
+
if (!row)
|
|
289
|
+
return undefined;
|
|
290
|
+
return {
|
|
291
|
+
id: row.id,
|
|
292
|
+
email: row.email,
|
|
293
|
+
username: row.username,
|
|
294
|
+
passwordHash: row.password_hash,
|
|
295
|
+
role: row.role,
|
|
296
|
+
createdAt: new Date(row.created_at),
|
|
297
|
+
updatedAt: new Date(row.updated_at),
|
|
298
|
+
lastLoginAt: row.last_login_at ? new Date(row.last_login_at) : undefined,
|
|
299
|
+
};
|
|
300
|
+
}
|
|
301
|
+
/**
|
|
302
|
+
* Get user by email
|
|
303
|
+
*/
|
|
304
|
+
getUserByEmail(email) {
|
|
305
|
+
const row = this.db
|
|
306
|
+
.prepare('SELECT * FROM users WHERE email = ?')
|
|
307
|
+
.get(email);
|
|
308
|
+
if (!row)
|
|
309
|
+
return undefined;
|
|
310
|
+
return {
|
|
311
|
+
id: row.id,
|
|
312
|
+
email: row.email,
|
|
313
|
+
username: row.username,
|
|
314
|
+
passwordHash: row.password_hash,
|
|
315
|
+
role: row.role,
|
|
316
|
+
createdAt: new Date(row.created_at),
|
|
317
|
+
updatedAt: new Date(row.updated_at),
|
|
318
|
+
lastLoginAt: row.last_login_at ? new Date(row.last_login_at) : undefined,
|
|
319
|
+
};
|
|
320
|
+
}
|
|
321
|
+
/**
|
|
322
|
+
* List all users (admin only)
|
|
323
|
+
*/
|
|
324
|
+
listUsers() {
|
|
325
|
+
const rows = this.db.prepare('SELECT * FROM users ORDER BY created_at DESC').all();
|
|
326
|
+
return rows.map((row) => ({
|
|
327
|
+
id: row.id,
|
|
328
|
+
email: row.email,
|
|
329
|
+
username: row.username,
|
|
330
|
+
role: row.role,
|
|
331
|
+
createdAt: new Date(row.created_at),
|
|
332
|
+
updatedAt: new Date(row.updated_at),
|
|
333
|
+
lastLoginAt: row.last_login_at ? new Date(row.last_login_at) : undefined,
|
|
334
|
+
}));
|
|
335
|
+
}
|
|
336
|
+
/**
|
|
337
|
+
* Update user role (admin only)
|
|
338
|
+
*/
|
|
339
|
+
updateUserRole(userId, role) {
|
|
340
|
+
this.db
|
|
341
|
+
.prepare('UPDATE users SET role = ?, updated_at = ? WHERE id = ?')
|
|
342
|
+
.run(role, new Date().toISOString(), userId);
|
|
343
|
+
log.info('User role updated', { userId, role });
|
|
344
|
+
}
|
|
345
|
+
/**
|
|
346
|
+
* Delete user (admin only)
|
|
347
|
+
*/
|
|
348
|
+
deleteUser(userId) {
|
|
349
|
+
this.db.prepare('DELETE FROM users WHERE id = ?').run(userId);
|
|
350
|
+
log.info('User deleted', { userId });
|
|
351
|
+
}
|
|
352
|
+
/**
|
|
353
|
+
* Change user password
|
|
354
|
+
*/
|
|
355
|
+
async changePassword(userId, oldPassword, newPassword) {
|
|
356
|
+
const user = this.getUserById(userId);
|
|
357
|
+
if (!user) {
|
|
358
|
+
throw new Error('User not found');
|
|
359
|
+
}
|
|
360
|
+
// Verify old password
|
|
361
|
+
const valid = await bcrypt.compare(oldPassword, user.passwordHash);
|
|
362
|
+
if (!valid) {
|
|
363
|
+
throw new Error('Invalid old password');
|
|
364
|
+
}
|
|
365
|
+
if (newPassword.length < 8) {
|
|
366
|
+
throw new Error('Password must be at least 8 characters');
|
|
367
|
+
}
|
|
368
|
+
// Hash new password
|
|
369
|
+
const passwordHash = await bcrypt.hash(newPassword, SALT_ROUNDS);
|
|
370
|
+
// Use transaction to ensure password update and token revocation are atomic
|
|
371
|
+
const transaction = this.db.transaction(() => {
|
|
372
|
+
// Update password
|
|
373
|
+
this.db
|
|
374
|
+
.prepare('UPDATE users SET password_hash = ?, updated_at = ? WHERE id = ?')
|
|
375
|
+
.run(passwordHash, new Date().toISOString(), userId);
|
|
376
|
+
// Revoke all refresh tokens
|
|
377
|
+
this.db.prepare('UPDATE refresh_tokens SET revoked = 1 WHERE user_id = ?').run(userId);
|
|
378
|
+
});
|
|
379
|
+
transaction();
|
|
380
|
+
log.info('Password changed', { userId });
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
//# sourceMappingURL=service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"service.js","sourceRoot":"","sources":["../../src/auth/service.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,GAAG,MAAM,cAAc,CAAC;AAC/B,OAAO,MAAM,MAAM,QAAQ,CAAC;AAE5B,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAU5C,MAAM,GAAG,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;AAEjC,MAAM,WAAW,GAAG,EAAE,CAAC;AACvB,MAAM,mBAAmB,GAAG,KAAK,CAAC,CAAC,aAAa;AAChD,MAAM,oBAAoB,GAAG,IAAI,CAAC,CAAC,SAAS;AAE5C,MAAM,OAAO,WAAW;IACd,EAAE,CAAoB;IACtB,SAAS,CAAS;IAClB,aAAa,CAAS;IAE9B,YACE,EAAqB,EACrB,SAAkB,EAClB,aAAsB;QAEtB,IAAI,CAAC,EAAE,GAAG,EAAE,CAAC;QACb,IAAI,CAAC,SAAS,GAAG,SAAS,IAAI,OAAO,CAAC,GAAG,CAAC,UAAU,IAAI,IAAI,CAAC,cAAc,EAAE,CAAC;QAC9E,IAAI,CAAC,aAAa,GAAG,aAAa,IAAI,OAAO,CAAC,GAAG,CAAC,cAAc,IAAI,IAAI,CAAC,cAAc,EAAE,CAAC;QAE1F,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,UAAU,EAAE,CAAC;YAC5B,GAAG,CAAC,IAAI,CAAC,yEAAyE,CAAC,CAAC;QACtF,CAAC;QAED,IAAI,CAAC,YAAY,EAAE,CAAC;IACtB,CAAC;IAED;;OAEG;IACK,YAAY;QAClB,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;KA2BZ,CAAC,CAAC;QAEH,8CAA8C;QAC9C,MAAM,SAAS,GAAG,IAAI,CAAC,EAAE;aACtB,OAAO,CAAC,qCAAqC,CAAC;aAC9C,GAAG,EAAuB,CAAC;QAE9B,IAAI,SAAS,CAAC,KAAK,KAAK,CAAC,EAAE,CAAC;YAC1B,GAAG,CAAC,IAAI,CAAC,6BAA6B,CAAC,CAAC;YACxC,IAAI,CAAC;gBACH,IAAI,CAAC,kBAAkB,EAAE,CAAC;YAC5B,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,GAAG,CAAC,KAAK,CAAC,qCAAqC,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;YAC9D,CAAC;QACH,CAAC;IACH,CAAC;IAED;;OAEG;IACK,kBAAkB;QACxB,MAAM,eAAe,GAAG,OAAO,CAAC,GAAG,CAAC,cAAc,IAAI,UAAU,CAAC;QACjE,MAAM,YAAY,GAAG,MAAM,CAAC,QAAQ,CAAC,eAAe,EAAE,WAAW,CAAC,CAAC;QAEnE,IAAI,CAAC,EAAE;aACJ,OAAO,CACN;sCAC8B,CAC/B;aACA,GAAG,CACF,UAAU,EAAE,EACZ,qBAAqB,EACrB,OAAO,EACP,YAAY,EACZ,OAAO,EACP,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,EACxB,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CACzB,CAAC;QAEJ,GAAG,CAAC,IAAI,CAAC,4BAA4B,EAAE;YACrC,KAAK,EAAE,qBAAqB;YAC5B,QAAQ,EAAE,eAAe;SAC1B,CAAC,CAAC;IACL,CAAC;IAED;;OAEG;IACK,cAAc;QACpB,OAAO,UAAU,EAAE,GAAG,UAAU,EAAE,CAAC;IACrC,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,QAAQ,CAAC,IAAkB,EAAE,OAAiB,WAAuB;QACzE,iBAAiB;QACjB,IAAI,CAAC,IAAI,CAAC,KAAK,IAAI,CAAC,IAAI,CAAC,QAAQ,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC;YACpD,MAAM,IAAI,KAAK,CAAC,4CAA4C,CAAC,CAAC;QAChE,CAAC;QAED,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC7B,MAAM,IAAI,KAAK,CAAC,wCAAwC,CAAC,CAAC;QAC5D,CAAC;QAED,+BAA+B;QAC/B,MAAM,QAAQ,GAAG,IAAI,CAAC,EAAE;aACrB,OAAO,CAAC,sDAAsD,CAAC;aAC/D,GAAG,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;QAElC,IAAI,QAAQ,EAAE,CAAC;YACb,MAAM,IAAI,KAAK,CAAC,iDAAiD,CAAC,CAAC;QACrE,CAAC;QAED,gBAAgB;QAChB,MAAM,YAAY,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,WAAW,CAAC,CAAC;QAEnE,cAAc;QACd,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;QAC5B,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;QAErC,IAAI,CAAC,EAAE;aACJ,OAAO,CACN;sCAC8B,CAC/B;aACA,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,QAAQ,EAAE,YAAY,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;QAExE,GAAG,CAAC,IAAI,CAAC,iBAAiB,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC;QAEpF,OAAO,IAAI,CAAC,WAAW,CAAC,MAAM,CAAE,CAAC;IACnC,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,KAAK,CAAC,WAA6B;QACvC,YAAY;QACZ,MAAM,IAAI,GAAG,IAAI,CAAC,cAAc,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;QAEpD,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,MAAM,IAAI,KAAK,CAAC,2BAA2B,CAAC,CAAC;QAC/C,CAAC;QAED,kBAAkB;QAClB,MAAM,KAAK,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,WAAW,CAAC,QAAQ,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC;QAC5E,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,MAAM,IAAI,KAAK,CAAC,2BAA2B,CAAC,CAAC;QAC/C,CAAC;QAED,kBAAkB;QAClB,MAAM,MAAM,GAAG,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC;QAEzC,0EAA0E;QAC1E,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;QACrC,MAAM,SAAS,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,YAAY,EAAE,WAAW,CAAC,CAAC;QACtE,MAAM,SAAS,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC;QAE/E,MAAM,WAAW,GAAG,IAAI,CAAC,EAAE,CAAC,WAAW,CAAC,GAAG,EAAE;YAC3C,oBAAoB;YACpB,IAAI,CAAC,EAAE;iBACJ,OAAO,CAAC,iDAAiD,CAAC;iBAC1D,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC;YAErB,sBAAsB;YACtB,IAAI,CAAC,EAAE;iBACJ,OAAO,CACN;kCACwB,CACzB;iBACA,GAAG,CAAC,UAAU,EAAE,EAAE,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,SAAS,EAAE,GAAG,CAAC,CAAC;YAEzD,0BAA0B;YAC1B,IAAI,CAAC,EAAE;iBACJ,OAAO,CAAC,gEAAgE,CAAC;iBACzE,GAAG,CAAC,GAAG,CAAC,CAAC;QACd,CAAC,CAAC,CAAC;QAEH,WAAW,EAAE,CAAC;QAEd,GAAG,CAAC,IAAI,CAAC,gBAAgB,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC;QAEnE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;IAC1B,CAAC;IAED;;OAEG;IACK,cAAc,CAAC,IAAU;QAC/B,MAAM,OAAO,GAAoC;YAC/C,MAAM,EAAE,IAAI,CAAC,EAAE;YACf,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,IAAI,EAAE,IAAI,CAAC,IAAI;SAChB,CAAC;QAEF,MAAM,WAAW,GAAG,GAAG,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,SAAS,EAAE;YACpD,SAAS,EAAE,mBAAmB;SAC/B,CAAC,CAAC;QAEH,MAAM,YAAY,GAAG,GAAG,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,EAAE,EAAE,IAAI,CAAC,aAAa,EAAE;YACrE,SAAS,EAAE,oBAAoB;SAChC,CAAC,CAAC;QAEH,OAAO;YACL,WAAW;YACX,YAAY;YACZ,SAAS,EAAE,EAAE,GAAG,EAAE,EAAE,wBAAwB;SAC7C,CAAC;IACJ,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,iBAAiB,CAAC,MAAc,EAAE,KAAa;QAC3D,MAAM,SAAS,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,WAAW,CAAC,CAAC;QACxD,MAAM,SAAS,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,SAAS;QACzF,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;QAErC,sDAAsD;QACtD,MAAM,WAAW,GAAG,IAAI,CAAC,EAAE,CAAC,WAAW,CAAC,GAAG,EAAE;YAC3C,IAAI,CAAC,EAAE;iBACJ,OAAO,CACN;kCACwB,CACzB;iBACA,GAAG,CAAC,UAAU,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,GAAG,CAAC,CAAC;YAExD,0BAA0B;YAC1B,IAAI,CAAC,EAAE;iBACJ,OAAO,CAAC,gEAAgE,CAAC;iBACzE,GAAG,CAAC,GAAG,CAAC,CAAC;QACd,CAAC,CAAC,CAAC;QAEH,WAAW,EAAE,CAAC;IAChB,CAAC;IAED;;OAEG;IACH,iBAAiB,CAAC,KAAa;QAC7B,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,GAAG,CAAC,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,SAAS,CAAe,CAAC;YAChE,OAAO,OAAO,CAAC;QACjB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,KAAK,YAAY,GAAG,CAAC,iBAAiB,EAAE,CAAC;gBAC3C,MAAM,IAAI,KAAK,CAAC,eAAe,CAAC,CAAC;YACnC,CAAC;YACD,IAAI,KAAK,YAAY,GAAG,CAAC,iBAAiB,EAAE,CAAC;gBAC3C,MAAM,IAAI,KAAK,CAAC,eAAe,CAAC,CAAC;YACnC,CAAC;YACD,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,kBAAkB,CAAC,YAAoB;QAC3C,IAAI,CAAC;YACH,uBAAuB;YACvB,MAAM,OAAO,GAAG,GAAG,CAAC,MAAM,CAAC,YAAY,EAAE,IAAI,CAAC,aAAa,CAAuB,CAAC;YAEnF,2CAA2C;YAC3C,MAAM,YAAY,GAAG,IAAI,CAAC,EAAE;iBACzB,OAAO,CACN;gEACsD,CACvD;iBACA,GAAG,CAAC,OAAO,CAAC,MAAM,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAE7C,CAAC;YAEH,2CAA2C;YAC3C,IAAI,UAAU,GAAG,KAAK,CAAC;YACvB,KAAK,MAAM,MAAM,IAAI,YAAY,EAAE,CAAC;gBAClC,IAAI,MAAM,MAAM,CAAC,OAAO,CAAC,YAAY,EAAE,MAAM,CAAC,UAAU,CAAC,EAAE,CAAC;oBAC1D,UAAU,GAAG,IAAI,CAAC;oBAClB,MAAM;gBACR,CAAC;YACH,CAAC;YAED,IAAI,CAAC,UAAU,EAAE,CAAC;gBAChB,MAAM,IAAI,KAAK,CAAC,kCAAkC,CAAC,CAAC;YACtD,CAAC;YAED,WAAW;YACX,MAAM,IAAI,GAAG,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;YAC9C,IAAI,CAAC,IAAI,EAAE,CAAC;gBACV,MAAM,IAAI,KAAK,CAAC,gBAAgB,CAAC,CAAC;YACpC,CAAC;YAED,sBAAsB;YACtB,MAAM,MAAM,GAAG,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC;YAEzC,0BAA0B;YAC1B,MAAM,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,EAAE,EAAE,MAAM,CAAC,YAAY,CAAC,CAAC;YAE3D,OAAO,MAAM,CAAC;QAChB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,KAAK,YAAY,GAAG,CAAC,iBAAiB,EAAE,CAAC;gBAC3C,MAAM,IAAI,KAAK,CAAC,uBAAuB,CAAC,CAAC;YAC3C,CAAC;YACD,IAAI,KAAK,YAAY,GAAG,CAAC,iBAAiB,EAAE,CAAC;gBAC3C,MAAM,IAAI,KAAK,CAAC,uBAAuB,CAAC,CAAC;YAC3C,CAAC;YACD,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,MAAM,CAAC,YAAoB;QAC/B,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,GAAG,CAAC,MAAM,CAAC,YAAY,EAAE,IAAI,CAAC,aAAa,CAAuB,CAAC;YAEnF,2CAA2C;YAC3C,IAAI,CAAC,EAAE;iBACJ,OAAO,CAAC,yDAAyD,CAAC;iBAClE,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;YAEvB,GAAG,CAAC,IAAI,CAAC,iBAAiB,EAAE,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;QAC1D,CAAC;QAAC,MAAM,CAAC;YACP,oEAAoE;QACtE,CAAC;IACH,CAAC;IAED;;OAEG;IACH,WAAW,CAAC,MAAc;QACxB,MAAM,GAAG,GAAG,IAAI,CAAC,EAAE;aAChB,OAAO,CAAC,kCAAkC,CAAC;aAC3C,GAAG,CAAC,MAAM,CAAQ,CAAC;QAEtB,IAAI,CAAC,GAAG;YAAE,OAAO,SAAS,CAAC;QAE3B,OAAO;YACL,EAAE,EAAE,GAAG,CAAC,EAAE;YACV,KAAK,EAAE,GAAG,CAAC,KAAK;YAChB,QAAQ,EAAE,GAAG,CAAC,QAAQ;YACtB,YAAY,EAAE,GAAG,CAAC,aAAa;YAC/B,IAAI,EAAE,GAAG,CAAC,IAAI;YACd,SAAS,EAAE,IAAI,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC;YACnC,SAAS,EAAE,IAAI,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC;YACnC,WAAW,EAAE,GAAG,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,SAAS;SACzE,CAAC;IACJ,CAAC;IAED;;OAEG;IACH,cAAc,CAAC,KAAa;QAC1B,MAAM,GAAG,GAAG,IAAI,CAAC,EAAE;aAChB,OAAO,CAAC,qCAAqC,CAAC;aAC9C,GAAG,CAAC,KAAK,CAAQ,CAAC;QAErB,IAAI,CAAC,GAAG;YAAE,OAAO,SAAS,CAAC;QAE3B,OAAO;YACL,EAAE,EAAE,GAAG,CAAC,EAAE;YACV,KAAK,EAAE,GAAG,CAAC,KAAK;YAChB,QAAQ,EAAE,GAAG,CAAC,QAAQ;YACtB,YAAY,EAAE,GAAG,CAAC,aAAa;YAC/B,IAAI,EAAE,GAAG,CAAC,IAAI;YACd,SAAS,EAAE,IAAI,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC;YACnC,SAAS,EAAE,IAAI,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC;YACnC,WAAW,EAAE,GAAG,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,SAAS;SACzE,CAAC;IACJ,CAAC;IAED;;OAEG;IACH,SAAS;QACP,MAAM,IAAI,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,8CAA8C,CAAC,CAAC,GAAG,EAAW,CAAC;QAE5F,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;YACxB,EAAE,EAAE,GAAG,CAAC,EAAE;YACV,KAAK,EAAE,GAAG,CAAC,KAAK;YAChB,QAAQ,EAAE,GAAG,CAAC,QAAQ;YACtB,IAAI,EAAE,GAAG,CAAC,IAAI;YACd,SAAS,EAAE,IAAI,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC;YACnC,SAAS,EAAE,IAAI,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC;YACnC,WAAW,EAAE,GAAG,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,SAAS;SACzE,CAAC,CAAC,CAAC;IACN,CAAC;IAED;;OAEG;IACH,cAAc,CAAC,MAAc,EAAE,IAAc;QAC3C,IAAI,CAAC,EAAE;aACJ,OAAO,CAAC,wDAAwD,CAAC;aACjE,GAAG,CAAC,IAAI,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE,MAAM,CAAC,CAAC;QAE/C,GAAG,CAAC,IAAI,CAAC,mBAAmB,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;IAClD,CAAC;IAED;;OAEG;IACH,UAAU,CAAC,MAAc;QACvB,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,gCAAgC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QAC9D,GAAG,CAAC,IAAI,CAAC,cAAc,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC;IACvC,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,cAAc,CAAC,MAAc,EAAE,WAAmB,EAAE,WAAmB;QAC3E,MAAM,IAAI,GAAG,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;QACtC,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,MAAM,IAAI,KAAK,CAAC,gBAAgB,CAAC,CAAC;QACpC,CAAC;QAED,sBAAsB;QACtB,MAAM,KAAK,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,WAAW,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC;QACnE,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,MAAM,IAAI,KAAK,CAAC,sBAAsB,CAAC,CAAC;QAC1C,CAAC;QAED,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC3B,MAAM,IAAI,KAAK,CAAC,wCAAwC,CAAC,CAAC;QAC5D,CAAC;QAED,oBAAoB;QACpB,MAAM,YAAY,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,WAAW,EAAE,WAAW,CAAC,CAAC;QAEjE,4EAA4E;QAC5E,MAAM,WAAW,GAAG,IAAI,CAAC,EAAE,CAAC,WAAW,CAAC,GAAG,EAAE;YAC3C,kBAAkB;YAClB,IAAI,CAAC,EAAE;iBACJ,OAAO,CAAC,iEAAiE,CAAC;iBAC1E,GAAG,CAAC,YAAY,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE,MAAM,CAAC,CAAC;YAEvD,4BAA4B;YAC5B,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,yDAAyD,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QACzF,CAAC,CAAC,CAAC;QAEH,WAAW,EAAE,CAAC;QAEd,GAAG,CAAC,IAAI,CAAC,kBAAkB,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC;IAC3C,CAAC;CACF"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Authentication types
|
|
3
|
+
*/
|
|
4
|
+
export interface User {
|
|
5
|
+
id: string;
|
|
6
|
+
email: string;
|
|
7
|
+
username: string;
|
|
8
|
+
passwordHash: string;
|
|
9
|
+
role: UserRole;
|
|
10
|
+
createdAt: Date;
|
|
11
|
+
updatedAt: Date;
|
|
12
|
+
lastLoginAt?: Date;
|
|
13
|
+
}
|
|
14
|
+
export declare enum UserRole {
|
|
15
|
+
ADMIN = "admin",
|
|
16
|
+
DEVELOPER = "developer",
|
|
17
|
+
VIEWER = "viewer"
|
|
18
|
+
}
|
|
19
|
+
export interface AuthTokens {
|
|
20
|
+
accessToken: string;
|
|
21
|
+
refreshToken: string;
|
|
22
|
+
expiresIn: number;
|
|
23
|
+
}
|
|
24
|
+
export interface JWTPayload {
|
|
25
|
+
userId: string;
|
|
26
|
+
email: string;
|
|
27
|
+
username: string;
|
|
28
|
+
role: UserRole;
|
|
29
|
+
iat: number;
|
|
30
|
+
exp: number;
|
|
31
|
+
}
|
|
32
|
+
export interface LoginCredentials {
|
|
33
|
+
email: string;
|
|
34
|
+
password: string;
|
|
35
|
+
}
|
|
36
|
+
export interface RegisterData {
|
|
37
|
+
email: string;
|
|
38
|
+
username: string;
|
|
39
|
+
password: string;
|
|
40
|
+
}
|
|
41
|
+
export interface AuthContext {
|
|
42
|
+
authenticated: boolean;
|
|
43
|
+
user?: Omit<User, 'passwordHash'>;
|
|
44
|
+
userId?: string;
|
|
45
|
+
role?: UserRole;
|
|
46
|
+
permissions?: string[];
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/auth/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,WAAW,IAAI;IACnB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,IAAI,EAAE,QAAQ,CAAC;IACf,SAAS,EAAE,IAAI,CAAC;IAChB,SAAS,EAAE,IAAI,CAAC;IAChB,WAAW,CAAC,EAAE,IAAI,CAAC;CACpB;AAED,oBAAY,QAAQ;IAClB,KAAK,UAAU;IACf,SAAS,cAAc;IACvB,MAAM,WAAW;CAClB;AAED,MAAM,WAAW,UAAU;IACzB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,QAAQ,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,WAAW;IAC1B,aAAa,EAAE,OAAO,CAAC;IACvB,IAAI,CAAC,EAAE,IAAI,CAAC,IAAI,EAAE,cAAc,CAAC,CAAC;IAClC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,QAAQ,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;CACxB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/auth/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAaH,MAAM,CAAN,IAAY,QAIX;AAJD,WAAY,QAAQ;IAClB,2BAAe,CAAA;IACf,mCAAuB,CAAA;IACvB,6BAAiB,CAAA;AACnB,CAAC,EAJW,QAAQ,KAAR,QAAQ,QAInB"}
|
|
@@ -25,6 +25,10 @@ export declare class ReviewLoopCoordinator extends EventEmitter {
|
|
|
25
25
|
private state;
|
|
26
26
|
private config;
|
|
27
27
|
constructor(codeInput: string, config: AgentStackConfig, options?: ReviewLoopOptions);
|
|
28
|
+
/**
|
|
29
|
+
* Persist state to database
|
|
30
|
+
*/
|
|
31
|
+
private persistState;
|
|
28
32
|
/**
|
|
29
33
|
* Get current state
|
|
30
34
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"review-loop.d.ts","sourceRoot":"","sources":["../../src/coordination/review-loop.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C,OAAO,KAAK,EACV,gBAAgB,EAChB,eAAe,EACf,YAAY,EACZ,WAAW,EAGZ,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"review-loop.d.ts","sourceRoot":"","sources":["../../src/coordination/review-loop.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C,OAAO,KAAK,EACV,gBAAgB,EAChB,eAAe,EACf,YAAY,EACZ,WAAW,EAGZ,MAAM,aAAa,CAAC;AAYrB,MAAM,WAAW,iBAAiB;IAChC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,gBAAgB;IAC/B,YAAY,EAAE,CAAC,KAAK,EAAE,eAAe,KAAK,IAAI,CAAC;IAC/C,gBAAgB,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,eAAe,KAAK,IAAI,CAAC;IACtE,aAAa,EAAE,CAAC,MAAM,EAAE,YAAY,EAAE,KAAK,EAAE,eAAe,KAAK,IAAI,CAAC;IACtE,UAAU,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,EAAE,KAAK,EAAE,eAAe,KAAK,IAAI,CAAC;IACvF,eAAe,EAAE,CAAC,KAAK,EAAE,eAAe,KAAK,IAAI,CAAC;IAClD,eAAe,EAAE,CAAC,KAAK,EAAE,eAAe,KAAK,IAAI,CAAC;IAClD,YAAY,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,eAAe,KAAK,IAAI,CAAC;CAC9D;AAKD;;GAEG;AACH,qBAAa,qBAAsB,SAAQ,YAAY;IACrD,OAAO,CAAC,KAAK,CAAkB;IAC/B,OAAO,CAAC,MAAM,CAAmB;gBAErB,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,gBAAgB,EAAE,OAAO,GAAE,iBAAsB;IA2CxF;;OAEG;IACH,OAAO,CAAC,YAAY;IAYpB;;OAEG;IACH,QAAQ,IAAI,eAAe;IAI3B;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,eAAe,CAAC;IA2BvC;;OAEG;YACW,mBAAmB;IAejC;;OAEG;YACW,OAAO;IAkDrB;;OAEG;YACW,aAAa;IA0B3B;;OAEG;IACH,OAAO,CAAC,iBAAiB;IA8DzB;;OAEG;YACW,OAAO;IAgCrB;;OAEG;IACH,KAAK,IAAI,IAAI;IAeb;;OAEG;IACH,OAAO,IAAI,IAAI;CAMhB;AAED;;GAEG;AACH,wBAAsB,gBAAgB,CACpC,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,gBAAgB,EACxB,OAAO,GAAE,iBAAsB,GAC9B,OAAO,CAAC,eAAe,CAAC,CAI1B;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,EAAE,EAAE,MAAM,GAAG,qBAAqB,GAAG,IAAI,CAEtE;AAED;;GAEG;AACH,wBAAgB,eAAe,IAAI,eAAe,EAAE,CAEnD;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAKnD;AAED;;GAEG;AACH,wBAAgB,gBAAgB,IAAI,IAAI,CAKvC"}
|