style: Fix formatting and spacing in multiple files
Some checks failed
CI / Get Changed Files (pull_request) Successful in 7s
CI / prettier (pull_request) Successful in 22s
CI / Checkstyle Main (pull_request) Successful in 53s
CI / eslint (pull_request) Failing after 1m8s
CI / test-build (pull_request) Successful in 1m35s

This commit is contained in:
Jan K9f 2025-04-02 16:11:53 +02:00
parent fa09a8533f
commit 617654caeb
Signed by: jank
GPG key ID: B9F475106B20F144
5 changed files with 102 additions and 82 deletions

View file

@ -9,7 +9,7 @@ import { OAuthStorage, provideOAuthClient } from 'angular-oauth2-oidc';
import { httpInterceptor } from './shared/interceptor/http.interceptor'; import { httpInterceptor } from './shared/interceptor/http.interceptor';
function storageFactory() { function storageFactory() {
return new class implements OAuthStorage { return new (class implements OAuthStorage {
private data: { [key: string]: string } = {}; private data: { [key: string]: string } = {};
getItem(key: string): string | null { getItem(key: string): string | null {
@ -17,13 +17,13 @@ function storageFactory() {
} }
removeItem(key: string): void { removeItem(key: string): void {
delete this.data[key] delete this.data[key];
} }
setItem(key: string, data: string): void { setItem(key: string, data: string): void {
this.data[key] = data; this.data[key] = data;
} }
} })();
} }
export const appConfig: ApplicationConfig = { export const appConfig: ApplicationConfig = {
@ -37,6 +37,6 @@ export const appConfig: ApplicationConfig = {
{ {
provide: OAuthStorage, provide: OAuthStorage,
useFactory: () => localStorage, useFactory: () => localStorage,
} },
], ],
}; };

View file

@ -6,7 +6,6 @@ import { Router } from '@angular/router';
import { environment } from '../../environments/environment'; import { environment } from '../../environments/environment';
import { catchError, from, of, tap } from 'rxjs'; import { catchError, from, of, tap } from 'rxjs';
@Injectable({ @Injectable({
providedIn: 'root', providedIn: 'root',
}) })
@ -42,12 +41,13 @@ export class AuthService {
console.log('Auth service initializing'); console.log('Auth service initializing');
this.oauthService.configure(this.authConfig); this.oauthService.configure(this.authConfig);
this.setupEventHandling(); this.setupEventHandling();
// Check if we're on the callback page // Check if we're on the callback page
const hasAuthParams = window.location.search.includes('code=') || const hasAuthParams =
window.location.search.includes('token=') || window.location.search.includes('code=') ||
window.location.search.includes('id_token='); window.location.search.includes('token=') ||
window.location.search.includes('id_token=');
if (hasAuthParams) { if (hasAuthParams) {
console.log('Auth parameters detected in URL, processing code flow'); console.log('Auth parameters detected in URL, processing code flow');
// We're in the OAuth callback // We're in the OAuth callback
@ -58,37 +58,42 @@ export class AuthService {
this.checkExistingSession(); this.checkExistingSession();
} }
} }
private processCodeFlow() { private processCodeFlow() {
// Try to exchange the authorization code for tokens // Try to exchange the authorization code for tokens
this.oauthService.tryLogin({ this.oauthService
onTokenReceived: context => { .tryLogin({
console.log('Token received in code flow:', context); onTokenReceived: (context) => {
// Manually create a token_received event console.log('Token received in code flow:', context);
this.handleSuccessfulLogin(); // Manually create a token_received event
} this.handleSuccessfulLogin();
}).catch(err => { },
console.error('Error processing code flow:', err); })
}); .catch((err) => {
console.error('Error processing code flow:', err);
});
} }
private checkExistingSession() { private checkExistingSession() {
// Try login on startup // Try login on startup
this.oauthService.loadDiscoveryDocumentAndTryLogin().then((isLoggedIn) => { this.oauthService
console.log('Initial login attempt result:', isLoggedIn); .loadDiscoveryDocumentAndTryLogin()
.then((isLoggedIn) => {
if (isLoggedIn && !this.user) { console.log('Initial login attempt result:', isLoggedIn);
this.handleSuccessfulLogin();
} if (isLoggedIn && !this.user) {
}).catch(err => { this.handleSuccessfulLogin();
console.error('Error during initial login attempt:', err); }
}); })
.catch((err) => {
console.error('Error during initial login attempt:', err);
});
} }
private setupEventHandling() { private setupEventHandling() {
this.oauthService.events.subscribe((event: OAuthEvent) => { this.oauthService.events.subscribe((event: OAuthEvent) => {
console.log('Auth event:', event); console.log('Auth event:', event);
if (event.type === 'token_received') { if (event.type === 'token_received') {
this.handleSuccessfulLogin(); this.handleSuccessfulLogin();
} else if (event.type === 'token_refresh_error' || event.type === 'token_expires') { } else if (event.type === 'token_refresh_error' || event.type === 'token_expires') {
@ -102,44 +107,46 @@ export class AuthService {
console.log('Token valid:', this.oauthService.hasValidAccessToken()); console.log('Token valid:', this.oauthService.hasValidAccessToken());
console.log('ID token valid:', this.oauthService.hasValidIdToken()); console.log('ID token valid:', this.oauthService.hasValidIdToken());
console.log('Access token:', this.oauthService.getAccessToken()); console.log('Access token:', this.oauthService.getAccessToken());
// Extract claims from id token if available // Extract claims from id token if available
let claims = this.oauthService.getIdentityClaims(); let claims = this.oauthService.getIdentityClaims();
console.log('ID token claims:', claims); console.log('ID token claims:', claims);
// If we have claims, use that as profile // If we have claims, use that as profile
if (claims && (claims['sub'] || claims['email'])) { if (claims && (claims['sub'] || claims['email'])) {
console.log('Using ID token claims as profile'); console.log('Using ID token claims as profile');
this.processUserProfile(claims); this.processUserProfile(claims);
return; return;
} }
// Otherwise try to load user profile // Otherwise try to load user profile
try { try {
from(this.oauthService.loadUserProfile()).pipe( from(this.oauthService.loadUserProfile())
tap(profile => console.log('User profile loaded:', profile)), .pipe(
catchError(error => { tap((profile) => console.log('User profile loaded:', profile)),
console.error('Error loading user profile:', error); catchError((error) => {
// If we can't load the profile but have a token, create a minimal profile console.error('Error loading user profile:', error);
if (this.oauthService.hasValidAccessToken()) { // If we can't load the profile but have a token, create a minimal profile
const token = this.oauthService.getAccessToken(); if (this.oauthService.hasValidAccessToken()) {
// Create a basic profile from the token const token = this.oauthService.getAccessToken();
const minimalProfile = { // Create a basic profile from the token
sub: 'user-' + Math.random().toString(36).substring(2, 10), const minimalProfile = {
preferred_username: 'user' + Date.now() sub: 'user-' + Math.random().toString(36).substring(2, 10),
}; preferred_username: 'user' + Date.now(),
return of({ info: minimalProfile }); };
return of({ info: minimalProfile });
}
return of(null);
})
)
.subscribe((profile) => {
if (profile) {
this.processUserProfile(profile);
} else {
console.error('Could not load or create user profile');
this.router.navigate(['/']);
} }
return of(null); });
})
).subscribe(profile => {
if (profile) {
this.processUserProfile(profile);
} else {
console.error('Could not load or create user profile');
this.router.navigate(['/']);
}
});
} catch (err) { } catch (err) {
console.error('Exception in handleSuccessfulLogin:', err); console.error('Exception in handleSuccessfulLogin:', err);
// Try to navigate to home if we have a token anyway // Try to navigate to home if we have a token anyway
@ -150,7 +157,7 @@ export class AuthService {
} }
} }
} }
private processUserProfile(profile: any) { private processUserProfile(profile: any) {
this.fromUserProfile(profile).subscribe({ this.fromUserProfile(profile).subscribe({
next: (user) => { next: (user) => {
@ -166,7 +173,7 @@ export class AuthService {
} else { } else {
this.router.navigate(['/']); this.router.navigate(['/']);
} }
} },
}); });
} }
@ -174,14 +181,17 @@ export class AuthService {
console.log('Initiating login flow'); console.log('Initiating login flow');
try { try {
// First ensure discovery document is loaded // First ensure discovery document is loaded
this.oauthService.loadDiscoveryDocument().then(() => { this.oauthService
console.log('Discovery document loaded, starting login flow'); .loadDiscoveryDocument()
this.oauthService.initLoginFlow(); .then(() => {
}).catch(err => { console.log('Discovery document loaded, starting login flow');
console.error('Error loading discovery document:', err); this.oauthService.initLoginFlow();
// Try login anyway with configured endpoints })
this.oauthService.initLoginFlow(); .catch((err) => {
}); console.error('Error loading discovery document:', err);
// Try login anyway with configured endpoints
this.oauthService.initLoginFlow();
});
} catch (err) { } catch (err) {
console.error('Exception in login:', err); console.error('Exception in login:', err);
// Try direct login as a fallback // Try direct login as a fallback
@ -222,7 +232,7 @@ export class AuthService {
getAccessToken() { getAccessToken() {
return this.oauthService.getAccessToken(); return this.oauthService.getAccessToken();
} }
getUser() { getUser() {
return this.user; return this.user;
} }

View file

@ -35,10 +35,12 @@ export class UserService {
} }
public createUser(id: string, username: string): Observable<User> { public createUser(id: string, username: string): Observable<User> {
return this.http.post<User>('/backend/user', { return this.http
authentikId: id, .post<User>('/backend/user', {
username: username, authentikId: id,
}).pipe(tap((user) => this.currentUserSubject.next(user))); username: username,
})
.pipe(tap((user) => this.currentUserSubject.next(user)));
} }
public getOrCreateUser(profile: any): Observable<User> { public getOrCreateUser(profile: any): Observable<User> {
@ -46,7 +48,11 @@ export class UserService {
// Authentik format might differ from Keycloak // Authentik format might differ from Keycloak
// Check different possible locations for the ID and username // Check different possible locations for the ID and username
const id = profile.info?.sub || profile['sub']; const id = profile.info?.sub || profile['sub'];
const username = profile.info?.preferred_username || profile['preferred_username'] || profile['email'] || profile['name']; const username =
profile.info?.preferred_username ||
profile['preferred_username'] ||
profile['email'] ||
profile['name'];
if (!id || !username) { if (!id || !username) {
console.error('Could not extract user ID or username from profile', profile); console.error('Could not extract user ID or username from profile', profile);

View file

@ -6,13 +6,15 @@ export const httpInterceptor: HttpInterceptorFn = (req, next) => {
const oauthStorage = inject(OAuthStorage); const oauthStorage = inject(OAuthStorage);
if (oauthStorage.getItem('access_token')) { if (oauthStorage.getItem('access_token')) {
return next(req.clone({ return next(
setHeaders: { req.clone({
'Authorization': 'Bearer ' + oauthStorage.getItem('access_token'), setHeaders: {
'Access-Control-Allow-Origin': '*', Authorization: 'Bearer ' + oauthStorage.getItem('access_token'),
'Referrer-Policy': 'no-referrer', 'Access-Control-Allow-Origin': '*',
} 'Referrer-Policy': 'no-referrer',
})); },
})
);
} else { } else {
return next(req); return next(req);
} }

View file

@ -1,5 +1,7 @@
export const environment = { export const environment = {
STRIPE_KEY: 'pk_test_51QrePYIvCfqz7ANgMizBorPpVjJ8S6gcaL4yvcMQnVaKyReqcQ6jqaQEF7aDZbDu8rNVsTZrw8ABek4ToxQX7KZe00jpGh8naG', STRIPE_KEY:
'pk_test_51QrePYIvCfqz7ANgMizBorPpVjJ8S6gcaL4yvcMQnVaKyReqcQ6jqaQEF7aDZbDu8rNVsTZrw8ABek4ToxQX7KZe00jpGh8naG',
OAUTH_CLIENT_ID: 'MDqjm1kcWKuZfqHJXjxwAV20i44aT7m4VhhTL3Nm', OAUTH_CLIENT_ID: 'MDqjm1kcWKuZfqHJXjxwAV20i44aT7m4VhhTL3Nm',
OAUTH_CLIENT_SECRET: 'GY2F8te6iAVYt1TNAUVLzWZEXb6JoMNp6chbjqaXNq4gS5xTDL54HqBiAlV1jFKarN28LQ7FUsYX4SbwjfEhZhgeoKuBnZKjR9eiu7RawnGgxIK9ffvUfMkjRxnmiGI5' OAUTH_CLIENT_SECRET:
'GY2F8te6iAVYt1TNAUVLzWZEXb6JoMNp6chbjqaXNq4gS5xTDL54HqBiAlV1jFKarN28LQ7FUsYX4SbwjfEhZhgeoKuBnZKjR9eiu7RawnGgxIK9ffvUfMkjRxnmiGI5',
}; };