Cleanup and some edge case fixes

This commit is contained in:
Amelia 2025-07-06 16:42:21 +02:00
parent b6bfc65bc4
commit 6e72c74fde
17 changed files with 172 additions and 148 deletions

View file

@ -6,7 +6,7 @@ export interface User {
username: string;
// This is set by the oidc service, will always take precedence over the Kavita generated token
// When set, the refresh logic for the Kavita token will not run
oidcToken: string;
oidcToken?: string;
token: string;
refreshToken: string;
roles: string[];

View file

@ -92,10 +92,6 @@ export class AccountService {
});
}
oidcEnabled() {
return this.httpClient.get<boolean>(this.baseUrl + "oidc/enabled");
}
canInvokeAction(user: User, action: Action) {
const isAdmin = this.hasAdminRole(user);
const canDownload = this.hasDownloadRole(user);

View file

@ -10,6 +10,7 @@ import {take} from "rxjs/operators";
import {ToastrService} from "ngx-toastr";
import {translate} from "@jsverse/transloco";
import {APP_BASE_HREF} from "@angular/common";
import {MessageHubService} from "./message-hub.service";
@Injectable({
providedIn: 'root'
@ -21,6 +22,7 @@ export class OidcService {
private readonly accountService = inject(AccountService);
private readonly destroyRef = inject(DestroyRef);
private readonly toastR = inject(ToastrService);
private readonly messageHub = inject(MessageHubService);
protected readonly baseUrl = inject(APP_BASE_HREF);
apiBaseUrl = environment.apiUrl;
@ -33,7 +35,7 @@ export class OidcService {
public readonly loaded$ = toObservable(this.loaded);
/**
* OIDC discovery document has been loaded, and login tried and OIDC has been set up
* OIDC discovery document has been loaded, login tried and OIDC has been set up
*/
private readonly _ready = signal(false);
public readonly ready = this._ready.asReadonly();
@ -62,12 +64,15 @@ export class OidcService {
this.accountService.currentUser$.pipe(take(1)).subscribe(user => {
if (!user) return; // Don't update tokens when we're not logged in. But what's going on?
// TODO: Do we need to refresh the SignalR connection here?
user.oidcToken = this.token;
this.messageHub.stopHubConnection();
this.messageHub.createHubConnection(user);
});
});
this.config().subscribe(oidcSetting => {
this.getPublicOidcConfig().subscribe(oidcSetting => {
this._settings.set(oidcSetting);
if (!oidcSetting.authority) {
this._loaded.set(true);
return
@ -86,7 +91,6 @@ export class OidcService {
// Not all OIDC providers follow this nicely
strictDiscoveryDocumentValidation: false,
});
this._settings.set(oidcSetting);
this.oauth2.setupAutomaticSilentRefresh();
from(this.oauth2.loadDiscoveryDocumentAndTryLogin()).subscribe({
@ -113,7 +117,7 @@ export class OidcService {
}
}
config() {
getPublicOidcConfig() {
return this.httpClient.get<OidcPublicConfig>(this.apiBaseUrl + "oidc/config");
}

View file

@ -1,20 +1,5 @@
import {AgeRating} from "../../_models/metadata/age-rating";
export interface OidcConfig {
authority: string;
clientId: string;
provisionAccounts: boolean;
requireVerifiedEmail: boolean;
syncUserSettings: boolean;
autoLogin: boolean;
disablePasswordAuthentication: boolean;
providerName: string;
defaultRoles: string[];
defaultLibraries: number[];
defaultAgeRating: AgeRating;
defaultIncludeUnknowns: boolean;
}
export interface OidcPublicConfig {
authority: string;
clientId: string;
@ -22,3 +7,14 @@ export interface OidcPublicConfig {
disablePasswordAuthentication: boolean;
providerName: string;
}
export interface OidcConfig extends OidcPublicConfig {
provisionAccounts: boolean;
requireVerifiedEmail: boolean;
syncUserSettings: boolean;
defaultRoles: string[];
defaultLibraries: number[];
defaultAgeRating: AgeRating;
defaultIncludeUnknowns: boolean;
}

View file

@ -3,10 +3,9 @@ import {
ChangeDetectorRef,
Component,
computed,
DestroyRef, effect,
DestroyRef,
inject,
input,
Input, model,
model,
OnInit
} from '@angular/core';
import {FormControl, FormGroup, ReactiveFormsModule, Validators} from '@angular/forms';
@ -27,8 +26,6 @@ import {takeUntilDestroyed} from "@angular/core/rxjs-interop";
import {ServerSettings} from "../_models/server-settings";
import {UserOwner, UserOwners} from "../../_models/user";
import {UserOwnerPipe} from "../../_pipes/user-owner.pipe";
import {SettingItemComponent} from "../../settings/_components/setting-item/setting-item.component";
import {OwnerIconComponent} from "../../shared/_components/owner-icon/owner-icon.component";
const AllowedUsernameCharacters = /^[\sa-zA-Z0-9\-._@+/\s]*$/;
const EmailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
@ -37,7 +34,7 @@ const EmailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
selector: 'app-edit-user',
templateUrl: './edit-user.component.html',
styleUrls: ['./edit-user.component.scss'],
imports: [ReactiveFormsModule, RoleSelectorComponent, LibrarySelectorComponent, RestrictionSelectorComponent, SentenceCasePipe, TranslocoDirective, AsyncPipe, UserOwnerPipe, SettingItemComponent, OwnerIconComponent],
imports: [ReactiveFormsModule, RoleSelectorComponent, LibrarySelectorComponent, RestrictionSelectorComponent, SentenceCasePipe, TranslocoDirective, AsyncPipe, UserOwnerPipe],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class EditUserComponent implements OnInit {
@ -80,8 +77,6 @@ export class EditUserComponent implements OnInit {
this.userForm.addControl('username', new FormControl(this.member().username, [Validators.required, Validators.pattern(AllowedUsernameCharacters)]));
this.userForm.addControl('owner', new FormControl(this.member().owner, [Validators.required]));
// TODO: Rework, bad hack
// Work around isLocked so we're able to downgrade users
this.userForm.get('owner')!.valueChanges.pipe(
tap(value => {
const newOwner = parseInt(value, 10) as UserOwner;

View file

@ -17,7 +17,7 @@
<ngx-extended-pdf-viewer
#pdfViewer
[src]="readerService.downloadPdf(this.chapterId)"
[authorization]="'Bearer ' + user.token"
[authorization]="'Bearer ' + user.oidcToken ?? user.token"
height="100vh"
[(page)]="currentPage"
[textLayer]="true"

View file

@ -80,7 +80,7 @@
"notice": "Warning!",
"out-of-sync": "This user was created via OIDC, if the SynUsers setting is turned on changes made may be lost",
"oidc-managed": "This user is managed via OIDC, contact your OIDC administrator if they require changes.",
"owner": "User type",
"owner": "Ownership",
"owner-tooltip": "Native users will never be synced with OIDC"
},