Merge pull request '[FA-misc] Delete novel now authorizes based on group' (#65) from feature/FA-misc_GroupBasedAuth into master
All checks were successful
CI / build-backend (push) Successful in 1m9s
CI / build-frontend (push) Successful in 42s
Build Gateway / build-subgraphs (map[name:novel-service project:FictionArchive.Service.NovelService subgraph:Novel]) (push) Successful in 51s
Build Gateway / build-subgraphs (map[name:reporting-service project:FictionArchive.Service.ReportingService subgraph:Reporting]) (push) Successful in 45s
Build Gateway / build-subgraphs (map[name:scheduler-service project:FictionArchive.Service.SchedulerService subgraph:Scheduler]) (push) Successful in 44s
Build Gateway / build-subgraphs (map[name:translation-service project:FictionArchive.Service.TranslationService subgraph:Translation]) (push) Successful in 46s
Build Gateway / build-subgraphs (map[name:user-service project:FictionArchive.Service.UserService subgraph:User]) (push) Successful in 46s
Build Gateway / build-subgraphs (map[name:usernoveldata-service project:FictionArchive.Service.UserNovelDataService subgraph:UserNovelData]) (push) Successful in 45s
Release / build-and-push (map[dockerfile:FictionArchive.Service.FileService/Dockerfile name:file-service]) (push) Successful in 2m5s
Release / build-and-push (map[dockerfile:FictionArchive.Service.NovelService/Dockerfile name:novel-service]) (push) Successful in 2m1s
Release / build-and-push (map[dockerfile:FictionArchive.Service.ReportingService/Dockerfile name:reporting-service]) (push) Successful in 1m44s
Release / build-and-push (map[dockerfile:FictionArchive.Service.SchedulerService/Dockerfile name:scheduler-service]) (push) Successful in 1m53s
Release / build-and-push (map[dockerfile:FictionArchive.Service.TranslationService/Dockerfile name:translation-service]) (push) Successful in 1m46s
Release / build-and-push (map[dockerfile:FictionArchive.Service.UserNovelDataService/Dockerfile name:usernoveldata-service]) (push) Successful in 1m43s
Release / build-and-push (map[dockerfile:FictionArchive.Service.UserService/Dockerfile name:user-service]) (push) Successful in 1m39s
Release / build-frontend (push) Successful in 1m43s
Build Gateway / build-gateway (push) Successful in 3m33s

Reviewed-on: #65
This commit was merged in pull request #65.
This commit is contained in:
2026-02-02 00:08:37 +00:00
4 changed files with 19 additions and 14 deletions

View File

@@ -5,6 +5,7 @@ using FictionArchive.Service.NovelService.Models.Novels;
using FictionArchive.Service.NovelService.Models.SourceAdapters;
using FictionArchive.Service.NovelService.Services;
using FictionArchive.Service.NovelService.Services.SourceAdapters;
using FictionArchive.Service.Shared.Constants;
using FictionArchive.Service.Shared.Contracts.Events;
using HotChocolate.Authorization;
using HotChocolate.Types;
@@ -21,19 +22,8 @@ public class Mutation
return await service.QueueNovelImport(novelUrl);
}
[Authorize]
public async Task<ChapterPullRequested> FetchChapterContents(
Guid importId,
uint novelId,
uint volumeId,
uint chapterOrder,
NovelUpdateService service)
{
return await service.QueueChapterPull(importId, novelId, volumeId, chapterOrder);
}
[Error<KeyNotFoundException>]
[Authorize]
[Authorize(Roles = [AuthorizationConstants.Roles.Admin])]
public async Task<bool> DeleteNovel(uint novelId, NovelUpdateService service)
{
await service.DeleteNovel(novelId);

View File

@@ -1,4 +1,4 @@
import { writable, derived } from 'svelte/store';
import { writable, derived, get } from 'svelte/store';
import type { User } from 'oidc-client-ts';
import { userManager, isOidcConfigured } from './oidcConfig';
@@ -8,6 +8,15 @@ export const isLoading = writable(true);
export const isAuthenticated = derived(user, ($user) => $user !== null);
export const isConfigured = isOidcConfigured;
export const userGroups = derived(user, ($user) => {
const groups = $user?.profile?.groups;
return Array.isArray(groups) ? (groups as string[]) : [];
});
export function hasGroup(groupName: string): boolean {
return get(userGroups).includes(groupName);
}
// Cookie management
function setCookieFromUser(u: User) {
if (!u?.access_token) return;

View File

@@ -35,7 +35,8 @@
import { onMount } from 'svelte';
import { client } from '$lib/graphql/client';
import { NovelDocument, ImportNovelDocument, DeleteNovelDocument, GetBookmarksDocument } from '$lib/graphql/__generated__/graphql';
import { isAuthenticated } from '$lib/auth/authStore';
import { isAuthenticated, hasGroup } from '$lib/auth/authStore';
import { Groups } from '$lib/constants/groups';
import { Card, CardContent, CardHeader } from '$lib/components/ui/card';
import { Badge } from '$lib/components/ui/badge';
import { Button } from '$lib/components/ui/button';
@@ -483,6 +484,7 @@
{/if}
</Tooltip>
</TooltipProvider>
{#if hasGroup(Groups.Admin)}
<Button
variant="destructive"
size="sm"
@@ -492,6 +494,7 @@
<Trash2 class="h-3 w-3" />
Delete
</Button>
{/if}
<AddToReadingListButton novelId={novel.id} />
{/if}
{#if refreshSuccess}

View File

@@ -0,0 +1,3 @@
export const Groups = {
Admin: 'admin'
} as const;