Md Afiq Iskandar ef5526baf1 Refactor Application Creation and Management Logic
- Simplified the application creation process by consolidating form fields and enhancing validation.
- Updated the create application page to streamline user experience with clearer provider options and improved layout.
- Implemented SweetAlert for success and error notifications during user actions, replacing traditional alerts.
- Enhanced the applications index page with dynamic filtering and improved data fetching from the Authentik API.
- Refactored API endpoints to utilize slugs for application identification, ensuring consistency with Authentik's structure.
- Improved authentication handling by updating the requireAuth utility to support cookie-based authentication.
2025-06-17 11:53:15 +08:00

224 lines
8.7 KiB
JavaScript

import { authentikFetch, clearAuthentikCache } from '../../utils/authentik';
import { requireAuth } from '../../utils/auth';
// Simplified /api/applications endpoint
export default defineEventHandler(async (event) => {
const method = getMethod(event);
switch (method) {
case 'GET':
// Public endpoint for listing applications
try {
const response = await authentikFetch('/core/applications/');
return response;
} catch (error) {
console.error('❌ Failed to fetch applications:', error.message);
throw error;
}
case 'POST':
// TODO: Add authentication later - for now make it public for testing
await requireAuth(event);
try {
const body = await readBody(event);
console.log(`🔨 Creating application: ${body.name} (${body.providerType})`);
// Simplified application creation - just the essentials
// Create application first
const applicationData = {
name: body.name,
slug: body.slug || body.name.toLowerCase().replace(/\s+/g, '-').replace(/[^a-z0-9-]/g, ''),
meta_description: body.meta_description || body.description,
meta_publisher: body.meta_publisher || 'CorradAF RBAC',
meta_launch_url: body.meta_launch_url || body.launchUrl
};
let application;
try {
application = await authentikFetch('/core/applications/', {
method: 'POST',
body: applicationData
});
console.log('✅ Application created successfully');
} catch (appError) {
console.error('❌ Application creation failed:', appError.message);
if (appError.data) {
console.error('Details:', JSON.stringify(appError.data, null, 2));
}
throw appError;
}
// Create provider based on type (simplified presets)
if (body.providerType && application.pk) {
try {
console.log(`🔨 Creating ${body.providerType.toUpperCase()} provider...`);
// Get required flows for all providers
const flows = await authentikFetch('/flows/instances/');
// Find required flows
const authFlows = flows.results.filter(flow => flow.designation === 'authentication');
const invalidationFlows = flows.results.filter(flow => flow.designation === 'invalidation');
const defaultAuthFlow = authFlows.find(flow => flow.slug === 'default-authentication-flow') || authFlows[0];
const defaultInvalidationFlow = invalidationFlows.find(flow => flow.slug === 'default-invalidation-flow') || invalidationFlows[0];
if (!defaultAuthFlow) {
throw new Error('No authentication flow found - required for all providers');
}
let provider = null;
switch (body.providerType) {
case 'oauth2':
// OAuth2/OIDC provider preset
const oauth2Data = {
name: `${body.name} OAuth2`,
client_type: 'confidential',
authorization_flow: defaultAuthFlow.pk,
invalidation_flow: defaultInvalidationFlow?.pk,
redirect_uris: [
{
matching_mode: 'strict',
url: `${body.meta_launch_url || body.launchUrl}/auth/callback`
}
]
};
try {
provider = await authentikFetch('/providers/oauth2/', {
method: 'POST',
body: oauth2Data
});
console.log('✅ OAuth2 provider created');
} catch (oauth2Error) {
console.error('❌ OAuth2 provider failed:', oauth2Error.message);
if (oauth2Error.data) {
console.error('Details:', JSON.stringify(oauth2Error.data, null, 2));
}
throw oauth2Error;
}
break;
case 'saml':
// SAML provider preset
const samlData = {
name: `${body.name} SAML`,
acs_url: `${body.meta_launch_url || body.launchUrl}/saml/acs`,
audience: body.slug,
issuer: `corradaf-${body.slug}`,
sp_binding: 'post',
authorization_flow: defaultAuthFlow.pk,
invalidation_flow: defaultInvalidationFlow?.pk
};
try {
provider = await authentikFetch('/providers/saml/', {
method: 'POST',
body: samlData
});
console.log('✅ SAML provider created');
} catch (samlError) {
console.error('❌ SAML provider failed:', samlError.message);
if (samlError.data) {
console.error('Details:', JSON.stringify(samlError.data, null, 2));
}
throw samlError;
}
break;
case 'ldap':
// LDAP provider preset
const ldapData = {
name: `${body.name} LDAP`,
base_dn: 'dc=ldap,dc=goauthentik,dc=io',
authorization_flow: defaultAuthFlow.pk,
invalidation_flow: defaultInvalidationFlow?.pk
};
try {
provider = await authentikFetch('/providers/ldap/', {
method: 'POST',
body: ldapData
});
console.log('✅ LDAP provider created');
} catch (ldapError) {
console.error('❌ LDAP provider failed:', ldapError.message);
if (ldapError.data) {
console.error('Details:', JSON.stringify(ldapError.data, null, 2));
}
throw ldapError;
}
break;
case 'proxy':
// Proxy provider preset
const proxyData = {
name: `${body.name} Proxy`,
external_host: body.meta_launch_url || body.launchUrl,
internal_host: body.meta_launch_url || body.launchUrl,
authorization_flow: defaultAuthFlow.pk,
invalidation_flow: defaultInvalidationFlow?.pk
};
try {
provider = await authentikFetch('/providers/proxy/', {
method: 'POST',
body: proxyData
});
console.log('✅ Proxy provider created');
} catch (proxyError) {
console.error('❌ Proxy provider failed:', proxyError.message);
if (proxyError.data) {
console.error('Details:', JSON.stringify(proxyError.data, null, 2));
}
throw proxyError;
}
break;
}
// Link provider to application
if (provider && provider.pk) {
await authentikFetch(`/core/applications/${application.slug}/`, {
method: 'PATCH',
body: {
provider: provider.pk
}
});
console.log(`${body.providerType.toUpperCase()} provider linked to application`);
} else {
console.warn('⚠️ Provider was not created properly');
}
} catch (providerError) {
console.warn('⚠️ Provider creation failed, but application was created:', providerError.message);
// Don't fail the entire operation if provider creation fails
}
}
// Clear Authentik cache to ensure changes take effect immediately
try {
await clearAuthentikCache();
console.log('✅ Cache cleared after application creation');
} catch (cacheError) {
console.warn('⚠️ Cache clearing failed but application was created:', cacheError.message);
// Continue even if cache clearing fails
}
return {
...application,
message: 'Application created successfully'
};
} catch (error) {
console.error('❌ Failed to create application:', error.message);
throw error;
}
default:
throw createError({
statusCode: 405,
message: 'Method not allowed'
});
}
});