Compare commits

...

5 Commits

Author SHA1 Message Date
3308bc9d49 Merge pull request '[FA-misc] Swaps out openvpn container for ExpressVPN' (#70) from feature/FA-misc_VPNSwitch into master
All checks were successful
CI / build-backend (push) Successful in 1m35s
CI / build-frontend (push) Successful in 49s
Build Gateway / build-subgraphs (map[name:novel-service project:FictionArchive.Service.NovelService subgraph:Novel]) (push) Successful in 1m1s
Build Gateway / build-subgraphs (map[name:reporting-service project:FictionArchive.Service.ReportingService subgraph:Reporting]) (push) Successful in 49s
Build Gateway / build-subgraphs (map[name:scheduler-service project:FictionArchive.Service.SchedulerService subgraph:Scheduler]) (push) Successful in 52s
Build Gateway / build-subgraphs (map[name:translation-service project:FictionArchive.Service.TranslationService subgraph:Translation]) (push) Successful in 1m1s
Build Gateway / build-subgraphs (map[name:user-service project:FictionArchive.Service.UserService subgraph:User]) (push) Successful in 56s
Build Gateway / build-subgraphs (map[name:usernoveldata-service project:FictionArchive.Service.UserNovelDataService subgraph:UserNovelData]) (push) Successful in 1m5s
Release / build-and-push (map[dockerfile:FictionArchive.Service.FileService/Dockerfile name:file-service]) (push) Successful in 3m0s
Release / build-and-push (map[dockerfile:FictionArchive.Service.NovelService/Dockerfile name:novel-service]) (push) Successful in 2m9s
Release / build-and-push (map[dockerfile:FictionArchive.Service.ReportingService/Dockerfile name:reporting-service]) (push) Successful in 1m49s
Release / build-and-push (map[dockerfile:FictionArchive.Service.SchedulerService/Dockerfile name:scheduler-service]) (push) Successful in 2m0s
Release / build-and-push (map[dockerfile:FictionArchive.Service.TranslationService/Dockerfile name:translation-service]) (push) Successful in 1m55s
Release / build-and-push (map[dockerfile:FictionArchive.Service.UserNovelDataService/Dockerfile name:usernoveldata-service]) (push) Successful in 1m47s
Release / build-and-push (map[dockerfile:FictionArchive.Service.UserService/Dockerfile name:user-service]) (push) Successful in 1m53s
Release / build-frontend (push) Successful in 1m56s
Build Gateway / build-gateway (push) Successful in 4m10s
Reviewed-on: #70
2026-04-26 20:18:28 +00:00
gamer147
a056ca42ee [FA-misc] Hopefully fix build issues
All checks were successful
CI / build-backend (pull_request) Successful in 1m54s
CI / build-frontend (pull_request) Successful in 54s
2026-04-26 16:11:13 -04:00
gamer147
fe83e0fe27 [FA-misc] Swaps out openvpn container for ExpressVPN
Some checks failed
CI / build-backend (pull_request) Failing after 2m11s
CI / build-frontend (pull_request) Successful in 55s
2026-04-26 15:38:16 -04:00
327c03c098 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
2026-02-02 00:08:37 +00:00
gamer147
5e48f5737f [FA-misc] Delete novel now authorizes based on group
All checks were successful
CI / build-backend (pull_request) Successful in 1m46s
CI / build-frontend (pull_request) Successful in 44s
2026-02-01 19:05:18 -05:00
9 changed files with 35 additions and 24 deletions

View File

@@ -95,6 +95,9 @@ NOVELPIA_USERNAME=your-username
NOVELPIA_PASSWORD=your-password
DEEPL_API_KEY=your-api-key
# ExpressVPN (used by the `vpn` container that tunnels novel-service into Korea)
EXPRESSVPN_ACTIVATION_CODE=your-expressvpn-activation-code
# S3 Storage
S3_ENDPOINT=https://s3.example.com
S3_BUCKET=fictionarchive

View File

@@ -98,6 +98,7 @@ for svc in selected_services:
# Export schema
run([
"dotnet", "run",
"-c", "Release",
"--no-build",
"--no-launch-profile",
"--",

View File

@@ -9,7 +9,7 @@
<ItemGroup>
<PackageReference Include="FluentAssertions" Version="6.12.0" />
<PackageReference Include="MassTransit" Version="8.5.7" />
<PackageReference Include="MassTransit" Version="8.5.9" />
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="9.0.11" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.11.1" />
<PackageReference Include="NodaTime.Testing" Version="3.3.0" />

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

@@ -9,7 +9,7 @@
<ItemGroup>
<PackageReference Include="FluentAssertions" Version="6.12.0" />
<PackageReference Include="MassTransit" Version="8.5.7" />
<PackageReference Include="MassTransit" Version="8.5.9" />
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="9.0.11" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.11.1" />
<PackageReference Include="NodaTime.Testing" Version="3.3.0" />

View File

@@ -43,7 +43,7 @@ services:
# VPN Container
# ===========================================
vpn:
image: dperson/openvpn-client
image: misioslav/expressvpn:latest
networks:
fictionarchive:
ipv4_address: 172.20.0.20
@@ -51,23 +51,25 @@ services:
- novel-service
cap_add:
- NET_ADMIN
- SYS_PTRACE
devices:
- /dev/net/tun
volumes:
- /srv/docker_volumes/korean_vpn:/vpn
dns:
- 192.168.3.1
environment:
- DNS=1.1.1.1,8.8.8.8
CODE: ${EXPRESSVPN_ACTIVATION_CODE}
SERVER: krsi
PROTOCOL: lightwayudp
WHITELIST_DNS: 1.1.1.1,8.8.8.8
CONNECTION_CHECK_INTERVAL: 30
RECONNECT_FAILURE_THRESHOLD: 3
extra_hosts:
- "postgres:172.20.0.10"
- "rabbitmq:172.20.0.11"
healthcheck:
test: ["CMD", "ping", "-c", "1", "-W", "5", "1.1.1.1"]
test: ["CMD-SHELL", "test ! -f /tmp/expressvpn/reconnect-failure.flag && expressvpnctl status | grep -q Connected"]
interval: 30s
timeout: 10s
retries: 3
start_period: 30s
start_period: 60s
restart: unless-stopped
# ===========================================

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;