update user login baru dan hakakses

This commit is contained in:
Fanrouver
2025-12-18 15:11:41 +07:00
parent dfcd59481c
commit c95da96017
20 changed files with 2564 additions and 404 deletions

No files matched your search

+133
View File
@@ -35,6 +35,31 @@ export default defineEventHandler(async (event) => {
const db = new Database(dbPath);
// Ensure schema is up to date
try {
const tableInfo = db.prepare("PRAGMA table_info(users)").all() as any[];
const columnNames = tableInfo.map(col => col.name);
if (!columnNames.includes('lastLogin')) {
db.exec(`ALTER TABLE users ADD COLUMN lastLogin INTEGER`);
console.log('✅ Added column: lastLogin');
}
if (!columnNames.includes('realmRoles')) {
db.exec(`ALTER TABLE users ADD COLUMN realmRoles TEXT DEFAULT '[]'`);
console.log('✅ Added column: realmRoles');
}
if (!columnNames.includes('accountRoles')) {
db.exec(`ALTER TABLE users ADD COLUMN accountRoles TEXT DEFAULT '[]'`);
console.log('✅ Added column: accountRoles');
}
if (!columnNames.includes('resourceRoles')) {
db.exec(`ALTER TABLE users ADD COLUMN resourceRoles TEXT DEFAULT '[]'`);
console.log('✅ Added column: resourceRoles');
}
} catch (e: any) {
console.warn('Migration note:', e.message);
}
// Check if user exists
const existingUser = db.prepare('SELECT * FROM users WHERE id = ?').get(userId) as any;
@@ -46,6 +71,114 @@ export default defineEventHandler(async (event) => {
});
}
// Handle password update to Keycloak if password is provided
if (body.password && body.password.trim() !== '') {
try {
const config = useRuntimeConfig();
// Get access token from current user session
let accessToken: string | null = null;
try {
const sessionCookie = getCookie(event, "user_session");
if (sessionCookie) {
const session = JSON.parse(sessionCookie);
const isExpired = Date.now() > session.expiresAt;
if (!isExpired && session.accessToken) {
accessToken = session.accessToken;
}
}
} catch (e) {
console.warn("⚠️ No valid session found for password update");
}
if (!accessToken) {
db.close();
throw createError({
statusCode: 401,
statusMessage: "Authentication required to update password",
});
}
// Extract realm from issuer
const issuerUrl = new URL(config.keycloakIssuer);
const realm = issuerUrl.pathname.split('/').filter(Boolean).pop() || 'master';
const keycloakBaseUrl = config.keycloakIssuer.replace('/realms/' + realm, '');
const passwordUpdateUrl = `${keycloakBaseUrl}/admin/realms/${realm}/users/${userId}/reset-password`;
console.log(`🔐 Updating password for user ${userId} in Keycloak`);
console.log(`🔗 Password update URL: ${passwordUpdateUrl}`);
// Create abort controller for timeout
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), 30000); // 30 second timeout
// Update password in Keycloak
let passwordResponse;
try {
passwordResponse = await fetch(passwordUpdateUrl, {
method: 'PUT',
headers: {
'Authorization': `Bearer ${accessToken}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
type: 'password',
value: body.password,
temporary: false, // Set to true if you want to force password change on next login
}),
signal: controller.signal,
});
clearTimeout(timeoutId);
} catch (fetchError: any) {
clearTimeout(timeoutId);
console.error('❌ Fetch error during password update:');
console.error(' - Error type:', fetchError.name);
console.error(' - Error message:', fetchError.message);
console.error(' - URL attempted:', passwordUpdateUrl);
db.close();
let errorMsg = 'Failed to connect to Keycloak server to update password.';
if (fetchError.name === 'AbortError' || fetchError.message.includes('timeout')) {
errorMsg = 'Keycloak server timeout. Please try again.';
} else if (fetchError.message.includes('ENOTFOUND') || fetchError.message.includes('getaddrinfo')) {
errorMsg = 'Cannot reach Keycloak server. Please check network connection.';
} else if (fetchError.message.includes('ECONNREFUSED')) {
errorMsg = 'Keycloak server refused connection. Server may be down.';
} else if (fetchError.message.includes('certificate') || fetchError.message.includes('SSL')) {
errorMsg = 'SSL certificate error. Please contact administrator.';
}
throw createError({
statusCode: 500,
statusMessage: errorMsg,
});
}
if (!passwordResponse.ok) {
const errorText = await passwordResponse.text();
console.error('❌ Keycloak password update failed:', errorText);
db.close();
throw createError({
statusCode: passwordResponse.status,
statusMessage: `Failed to update password in Keycloak: ${errorText}`,
});
}
console.log(`✅ Password updated successfully in Keycloak for user ${userId}`);
} catch (passwordError: any) {
console.error('❌ Error updating password in Keycloak:', passwordError);
db.close();
// Re-throw if it's already a createError
if (passwordError.statusCode) {
throw passwordError;
}
throw createError({
statusCode: 500,
statusMessage: `Failed to update password: ${passwordError.message}`,
});
}
}
// Prepare update fields
const updateFields: string[] = [];
const updateValues: any[] = [];