From 54dd404e0182b8ebbb68664550183f16d407e261 Mon Sep 17 00:00:00 2001 From: Simon <9295182+grimsi@users.noreply.github.com> Date: Sat, 26 Jul 2025 15:51:13 +0200 Subject: [PATCH 01/10] Add image with Ubuntu base (#661) --- .github/actions/docker-build-push/action.yml | 21 ++++++++++- docker/Dockerfile.ubuntu | 39 ++++++++++++++++++++ docker/entrypoint.ubuntu.sh | 12 ++++++ 3 files changed, 71 insertions(+), 1 deletion(-) create mode 100644 docker/Dockerfile.ubuntu create mode 100644 docker/entrypoint.ubuntu.sh diff --git a/.github/actions/docker-build-push/action.yml b/.github/actions/docker-build-push/action.yml index 7c90618..2170b2c 100644 --- a/.github/actions/docker-build-push/action.yml +++ b/.github/actions/docker-build-push/action.yml @@ -19,7 +19,15 @@ runs: username: ${{ inputs.ghcr_username }} password: ${{ inputs.ghcr_token }} - - name: Build and push Docker image + - name: Prepare Ubuntu tags + id: ubuntu_tags + shell: bash + run: | + TAGS="${{ inputs.tags }}" + UBUNTU_TAGS=$(echo "$TAGS" | awk -F, '{for(i=1;i<=NF;i++){split($i,a,":"); printf "%s:%s-ubuntu", a[1], a[2]; if(i> $GITHUB_OUTPUT + + - name: Build and push Docker image (Alpine) uses: docker/build-push-action@v5 with: context: ${{ inputs.context }} @@ -30,6 +38,17 @@ runs: cache-from: type=gha cache-to: type=gha + - name: Build and push Docker image (Ubuntu) + uses: docker/build-push-action@v5 + with: + context: ${{ inputs.context }} + file: docker/Dockerfile.ubuntu + platforms: ${{ inputs.platforms }} + push: true + tags: ${{ steps.ubuntu_tags.outputs.ubuntu_tags }} + cache-from: type=gha + cache-to: type=gha + inputs: dockerhub_username: required: true diff --git a/docker/Dockerfile.ubuntu b/docker/Dockerfile.ubuntu new file mode 100644 index 0000000..12d71b0 --- /dev/null +++ b/docker/Dockerfile.ubuntu @@ -0,0 +1,39 @@ +# syntax=docker/dockerfile:1.4 +FROM eclipse-temurin:21-jre + +MAINTAINER grimsi + +# Install necessary packages +RUN apt-get update && \ + apt-get install -y tini gosu && \ + rm -rf /var/lib/apt/lists/* + +ENV USER=gameyfin + +RUN groupadd gameyfin && \ + useradd -M -g gameyfin gameyfin + +WORKDIR /opt/gameyfin + +# Create necessary directories with appropriate permissions +RUN mkdir -p plugins db data logs && \ + chown -R gameyfin:gameyfin . + +# Copy entrypoint script and set permissions +COPY --chown=gameyfin:gameyfin ./docker/entrypoint.ubuntu.sh /entrypoint.sh +RUN chmod +x /entrypoint.sh + +# Copy application jar (not ending with -plain.jar) +COPY --chown=gameyfin:gameyfin ./app/build/libs/ /tmp/app-libs/ +RUN find /tmp/app-libs -type f -name "*.jar" ! -name "*-plain.jar" -exec cp {} gameyfin.jar \; && \ + rm -rf /tmp/app-libs + +# Copy all plugin jars +COPY --chown=gameyfin:gameyfin ./plugins/ /tmp/plugins/ +RUN find /tmp/plugins -type f -path "*/build/libs/*.jar" -exec cp {} plugins/ \; && \ + rm -rf /tmp/plugins + +EXPOSE 8080 + +ENTRYPOINT ["/usr/bin/tini", "--", "/entrypoint.sh"] + diff --git a/docker/entrypoint.ubuntu.sh b/docker/entrypoint.ubuntu.sh new file mode 100644 index 0000000..6ace8d9 --- /dev/null +++ b/docker/entrypoint.ubuntu.sh @@ -0,0 +1,12 @@ +#!/bin/bash +set -e + +if [ -n "$PUID" ] && [ -n "$PGID" ]; then + groupmod -o -g "$PGID" gameyfin + usermod -o -u "$PUID" gameyfin + chown -R gameyfin:gameyfin /opt/gameyfin + exec gosu gameyfin:gameyfin java -jar gameyfin.jar +else + exec gosu gameyfin:gameyfin java -jar gameyfin.jar +fi + From 3070a0c93161168d1c9412380a6d9d7e4aa87c23 Mon Sep 17 00:00:00 2001 From: Simon <9295182+grimsi@users.noreply.github.com> Date: Sat, 26 Jul 2025 17:13:38 +0200 Subject: [PATCH 02/10] Fix UI display bug when user email is very long (#664) Fixes #662 --- .../general/cards/UserManagementCard.tsx | 45 ++++++++++--------- 1 file changed, 24 insertions(+), 21 deletions(-) diff --git a/app/src/main/frontend/components/general/cards/UserManagementCard.tsx b/app/src/main/frontend/components/general/cards/UserManagementCard.tsx index 5521e35..3bdc20e 100644 --- a/app/src/main/frontend/components/general/cards/UserManagementCard.tsx +++ b/app/src/main/frontend/components/general/cards/UserManagementCard.tsx @@ -1,6 +1,6 @@ -import {Card, Dropdown, DropdownItem, DropdownMenu, DropdownTrigger, useDisclosure} from "@heroui/react"; +import {Button, Card, Dropdown, DropdownItem, DropdownMenu, DropdownTrigger, useDisclosure} from "@heroui/react"; import {DotsThreeVertical} from "@phosphor-icons/react"; -import {useEffect, useState} from "react"; +import React, {useEffect, useState} from "react"; import {MessageEndpoint, PasswordResetEndpoint, UserEndpoint} from "Frontend/generated/endpoints"; import {AvatarEndpoint} from "Frontend/endpoints/endpoints"; import Avatar from "Frontend/components/general/Avatar"; @@ -108,6 +108,27 @@ export function UserManagementCard({user}: { user: UserInfoDto }) { <> +
+ + + + + + {(item) => ( + + {item.label} + + )} + + +

{user.username}

-

{user.email}

+

{user.email}

{user.roles?.map((role) => ( ))}
- - - - - - - {(item) => ( - - {item.label} - - )} - -
Date: Wed, 13 Aug 2025 08:05:33 +0200 Subject: [PATCH 03/10] Bump actions/download-artifact from 4 to 5 (#677) Bumps [actions/download-artifact](https://github.com/actions/download-artifact) from 4 to 5. - [Release notes](https://github.com/actions/download-artifact/releases) - [Commits](https://github.com/actions/download-artifact/compare/v4...v5) --- updated-dependencies: - dependency-name: actions/download-artifact dependency-version: '5' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/release.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index cc5e05f..d36835e 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -69,7 +69,7 @@ jobs: fetch-depth: 0 - name: Download modified files - uses: actions/download-artifact@v4 + uses: actions/download-artifact@v5 with: name: modified-files @@ -124,7 +124,7 @@ jobs: fetch-depth: 0 - name: Download modified files - uses: actions/download-artifact@v4 + uses: actions/download-artifact@v5 with: name: modified-files @@ -155,7 +155,7 @@ jobs: fetch-depth: 0 - name: Download modified files - uses: actions/download-artifact@v4 + uses: actions/download-artifact@v5 with: name: modified-files From 20c9bf47dae3d27edb2fa9bb0b5eaf27493324f4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 13 Aug 2025 08:05:48 +0200 Subject: [PATCH 04/10] Bump actions/checkout from 4 to 5 (#676) Bumps [actions/checkout](https://github.com/actions/checkout) from 4 to 5. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v4...v5) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: '5' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/docker-develop.yml | 2 +- .github/workflows/docker-fix.yml | 2 +- .github/workflows/release.yml | 8 ++++---- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/docker-develop.yml b/.github/workflows/docker-develop.yml index 87d5776..d102feb 100644 --- a/.github/workflows/docker-develop.yml +++ b/.github/workflows/docker-develop.yml @@ -18,7 +18,7 @@ jobs: packages: write steps: - name: Checkout code - uses: actions/checkout@v4 + uses: actions/checkout@v5 - name: Set up JDK 21 uses: actions/setup-java@v4 diff --git a/.github/workflows/docker-fix.yml b/.github/workflows/docker-fix.yml index a759bc2..4ef82fc 100644 --- a/.github/workflows/docker-fix.yml +++ b/.github/workflows/docker-fix.yml @@ -12,7 +12,7 @@ jobs: packages: write steps: - name: Checkout code - uses: actions/checkout@v4 + uses: actions/checkout@v5 - name: Set up JDK 21 uses: actions/setup-java@v4 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index d36835e..77aace5 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -23,7 +23,7 @@ jobs: release_version: ${{ steps.get_version.outputs.release_version }} steps: - name: Checkout code - uses: actions/checkout@v4 + uses: actions/checkout@v5 with: fetch-depth: 0 @@ -64,7 +64,7 @@ jobs: packages: write steps: - name: Checkout code - uses: actions/checkout@v4 + uses: actions/checkout@v5 with: fetch-depth: 0 @@ -119,7 +119,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout code - uses: actions/checkout@v4 + uses: actions/checkout@v5 with: fetch-depth: 0 @@ -150,7 +150,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout code - uses: actions/checkout@v4 + uses: actions/checkout@v5 with: fetch-depth: 0 From 021d165fb1932058cc81e932a5193002e2243cf3 Mon Sep 17 00:00:00 2001 From: Simon <9295182+grimsi@users.noreply.github.com> Date: Fri, 29 Aug 2025 19:20:43 +0200 Subject: [PATCH 05/10] Fix #663 (#679) Implement clean-up of image files --- app/package.json | 2 +- .../app/games/entities/GameEntityListener.kt | 12 ++-- .../org/gameyfin/app/games/entities/Image.kt | 6 +- .../app/games/entities/ImageEntityListener.kt | 27 ++++++++ .../app/libraries/LibraryScanService.kt | 63 ++++++++++++------- 5 files changed, 77 insertions(+), 33 deletions(-) create mode 100644 app/src/main/kotlin/org/gameyfin/app/games/entities/ImageEntityListener.kt diff --git a/app/package.json b/app/package.json index 4d7345d..59d3828 100644 --- a/app/package.json +++ b/app/package.json @@ -265,4 +265,4 @@ "disableUsageStatistics": true, "hash": "962eccc3fa0735d5234901be4f9e384096113c45bec22564a53688096d62aef4" } -} +} \ No newline at end of file diff --git a/app/src/main/kotlin/org/gameyfin/app/games/entities/GameEntityListener.kt b/app/src/main/kotlin/org/gameyfin/app/games/entities/GameEntityListener.kt index efe500b..9a04b3e 100644 --- a/app/src/main/kotlin/org/gameyfin/app/games/entities/GameEntityListener.kt +++ b/app/src/main/kotlin/org/gameyfin/app/games/entities/GameEntityListener.kt @@ -12,19 +12,19 @@ import org.gameyfin.app.games.extensions.toUserDto class GameEntityListener { @PostPersist fun created(game: Game) { - GameService.Companion.emitUser(GameUserEvent.Created(game.toUserDto())) - GameService.Companion.emitAdmin(GameAdminEvent.Created(game.toAdminDto())) + GameService.emitUser(GameUserEvent.Created(game.toUserDto())) + GameService.emitAdmin(GameAdminEvent.Created(game.toAdminDto())) } @PostUpdate fun updated(game: Game) { - GameService.Companion.emitUser(GameUserEvent.Updated(game.toUserDto())) - GameService.Companion.emitAdmin(GameAdminEvent.Updated(game.toAdminDto())) + GameService.emitUser(GameUserEvent.Updated(game.toUserDto())) + GameService.emitAdmin(GameAdminEvent.Updated(game.toAdminDto())) } @PostRemove fun deleted(game: Game) { - GameService.Companion.emitUser(GameUserEvent.Deleted(game.id!!)) - GameService.Companion.emitAdmin(GameAdminEvent.Deleted(game.id!!)) + GameService.emitUser(GameUserEvent.Deleted(game.id!!)) + GameService.emitAdmin(GameAdminEvent.Deleted(game.id!!)) } } \ No newline at end of file diff --git a/app/src/main/kotlin/org/gameyfin/app/games/entities/Image.kt b/app/src/main/kotlin/org/gameyfin/app/games/entities/Image.kt index 4a1dc05..3bc44cf 100644 --- a/app/src/main/kotlin/org/gameyfin/app/games/entities/Image.kt +++ b/app/src/main/kotlin/org/gameyfin/app/games/entities/Image.kt @@ -1,15 +1,13 @@ package org.gameyfin.app.games.entities -import jakarta.persistence.Entity -import jakarta.persistence.GeneratedValue -import jakarta.persistence.GenerationType -import jakarta.persistence.Id +import jakarta.persistence.* import org.springframework.content.commons.annotations.ContentId import org.springframework.content.commons.annotations.ContentLength import org.springframework.content.commons.annotations.MimeType import java.net.URL @Entity +@EntityListeners(ImageEntityListener::class) class Image( @Id @GeneratedValue(strategy = GenerationType.AUTO) diff --git a/app/src/main/kotlin/org/gameyfin/app/games/entities/ImageEntityListener.kt b/app/src/main/kotlin/org/gameyfin/app/games/entities/ImageEntityListener.kt new file mode 100644 index 0000000..0486bfc --- /dev/null +++ b/app/src/main/kotlin/org/gameyfin/app/games/entities/ImageEntityListener.kt @@ -0,0 +1,27 @@ +package org.gameyfin.app.games.entities + +import jakarta.persistence.PostRemove +import org.gameyfin.app.media.ImageService +import org.springframework.context.ApplicationContext +import org.springframework.context.ApplicationContextAware +import org.springframework.stereotype.Component + +@Component +class ImageEntityListener : ApplicationContextAware { + companion object { + private lateinit var applicationContext: ApplicationContext + } + + override fun setApplicationContext(context: ApplicationContext) { + applicationContext = context + } + + private fun getImageService(): ImageService { + return applicationContext.getBean(ImageService::class.java) + } + + @PostRemove + fun deleted(image: Image) { + getImageService().deleteFile(image) + } +} \ No newline at end of file diff --git a/app/src/main/kotlin/org/gameyfin/app/libraries/LibraryScanService.kt b/app/src/main/kotlin/org/gameyfin/app/libraries/LibraryScanService.kt index e66d23e..bbc28e9 100644 --- a/app/src/main/kotlin/org/gameyfin/app/libraries/LibraryScanService.kt +++ b/app/src/main/kotlin/org/gameyfin/app/libraries/LibraryScanService.kt @@ -4,6 +4,7 @@ import io.github.oshai.kotlinlogging.KotlinLogging import org.gameyfin.app.core.filesystem.FilesystemService import org.gameyfin.app.games.GameService import org.gameyfin.app.games.entities.Game +import org.gameyfin.app.games.entities.Image import org.gameyfin.app.libraries.dto.LibraryScanProgress import org.gameyfin.app.libraries.dto.LibraryScanStatus import org.gameyfin.app.libraries.dto.LibraryScanStep @@ -13,6 +14,7 @@ import org.gameyfin.app.media.ImageService import org.springframework.stereotype.Service import reactor.core.publisher.Flux import reactor.core.publisher.Sinks +import java.net.URL import java.nio.file.Path import java.time.Instant import java.util.concurrent.Callable @@ -331,39 +333,56 @@ class LibraryScanService( private fun downloadImages(games: List, progress: LibraryScanProgress): DownloadImagesResult { val completedImageDownload = AtomicInteger(0) - val imageDownloadTasks = games.map { game -> - Callable { + // Collect all images from all games in the batch + val allImages = games.flatMap { game -> + val images = mutableListOf() + game.coverImage?.let { images.add(it) } + game.headerImage?.let { images.add(it) } + images.addAll(game.images) + images + } + + // Deduplicate by originalUrl + val uniqueImages = allImages + .filter { it.originalUrl != null } + .distinctBy { it.originalUrl } + + // Map to track which Image entity was used for download per originalUrl + val downloadedImageMap = ConcurrentHashMap() + + // Download each unique image in parallel + val imageDownloadTasks = uniqueImages.map { image -> + Callable { try { - game.coverImage?.let { - imageService.downloadIfNew(it) - completedImageDownload.andIncrement + imageService.downloadIfNew(image) + image.originalUrl?.let { url -> + downloadedImageMap[url] = image } - - game.headerImage?.let { - imageService.downloadIfNew(it) - completedImageDownload.andIncrement - } - - game.images.map { - imageService.downloadIfNew(it) - completedImageDownload.andIncrement - } - - game } catch (e: Exception) { - log.error { "Error downloading images for game '${game.title}' (${game.id}): ${e.message}" } + log.error { "Error downloading image '${image.originalUrl}': ${e.message}" } log.debug(e) {} - null } finally { - progress.currentStep.current = completedImageDownload.get() + progress.currentStep.current = completedImageDownload.incrementAndGet() emit(progress) } } } + executor.invokeAll(imageDownloadTasks) - val gamesWithImages = executor.invokeAll(imageDownloadTasks).mapNotNull { it.get() } + // After downloads, associate the contentId with all other Image entities in the batch with the same originalUrl + for ((url, downloadedImage) in downloadedImageMap) { + val contentId = downloadedImage.contentId + if (contentId != null) { + allImages.filter { it.originalUrl.toString() == url.toString() && it !== downloadedImage } + .forEach { image -> + imageService.downloadIfNew(image) + progress.currentStep.current = completedImageDownload.incrementAndGet() + emit(progress) + } + } + } - return DownloadImagesResult(gamesWithImages = gamesWithImages) + return DownloadImagesResult(gamesWithImages = games) } private fun calculateFileSizes(games: List, progress: LibraryScanProgress): CalculateFilesizesResult { From 10c83fc436775f642c0467b4e3abd0c6823a85e4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 30 Aug 2025 18:14:24 +0200 Subject: [PATCH 06/10] Bump actions/setup-java from 4 to 5 (#687) Bumps [actions/setup-java](https://github.com/actions/setup-java) from 4 to 5. - [Release notes](https://github.com/actions/setup-java/releases) - [Commits](https://github.com/actions/setup-java/compare/v4...v5) --- updated-dependencies: - dependency-name: actions/setup-java dependency-version: '5' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/docker-develop.yml | 2 +- .github/workflows/docker-fix.yml | 2 +- .github/workflows/release.yml | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/docker-develop.yml b/.github/workflows/docker-develop.yml index d102feb..2e0c221 100644 --- a/.github/workflows/docker-develop.yml +++ b/.github/workflows/docker-develop.yml @@ -21,7 +21,7 @@ jobs: uses: actions/checkout@v5 - name: Set up JDK 21 - uses: actions/setup-java@v4 + uses: actions/setup-java@v5 with: distribution: 'temurin' java-version: '21' diff --git a/.github/workflows/docker-fix.yml b/.github/workflows/docker-fix.yml index 4ef82fc..87b2b5f 100644 --- a/.github/workflows/docker-fix.yml +++ b/.github/workflows/docker-fix.yml @@ -15,7 +15,7 @@ jobs: uses: actions/checkout@v5 - name: Set up JDK 21 - uses: actions/setup-java@v4 + uses: actions/setup-java@v5 with: distribution: 'temurin' java-version: '21' diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 77aace5..eaf81a3 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -74,7 +74,7 @@ jobs: name: modified-files - name: Set up JDK 21 - uses: actions/setup-java@v4 + uses: actions/setup-java@v5 with: distribution: 'temurin' java-version: '21' @@ -129,7 +129,7 @@ jobs: name: modified-files - name: Set up JDK 21 - uses: actions/setup-java@v4 + uses: actions/setup-java@v5 with: distribution: 'temurin' java-version: '21' From 345bd6cd1e32ad3643184e147a6acebabd3235f2 Mon Sep 17 00:00:00 2001 From: Simon <9295182+grimsi@users.noreply.github.com> Date: Sat, 30 Aug 2025 19:16:22 +0200 Subject: [PATCH 07/10] Fix download providers not updating on view navigation event --- app/src/main/frontend/views/GameView.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/frontend/views/GameView.tsx b/app/src/main/frontend/views/GameView.tsx index 4ef6d24..44ac19e 100644 --- a/app/src/main/frontend/views/GameView.tsx +++ b/app/src/main/frontend/views/GameView.tsx @@ -46,7 +46,7 @@ export default function GameView() { }, {} as Record); setDownloadOptions(options); }); - }, []); + }, [gameId]); useEffect(() => { if (state.isLoaded && (!gameId || !state.state[parseInt(gameId)])) { From a2abac06986c0268bee7b398f044d83e33241816 Mon Sep 17 00:00:00 2001 From: Simon <9295182+grimsi@users.noreply.github.com> Date: Mon, 1 Sep 2025 13:50:28 +0200 Subject: [PATCH 08/10] Make OAuth request scopes & roles claim configurable (#689) * Request OAuth scope "roles" by default * Make OAuth request scopes configurable * Make roles claim configurable --- .../components/administration/SsoManagement.tsx | 9 ++++++++- .../org/gameyfin/app/config/ConfigProperties.kt | 14 ++++++++++++++ .../gameyfin/app/core/security/SecurityConfig.kt | 2 +- .../kotlin/org/gameyfin/app/users/RoleService.kt | 8 ++++++-- 4 files changed, 29 insertions(+), 4 deletions(-) diff --git a/app/src/main/frontend/components/administration/SsoManagement.tsx b/app/src/main/frontend/components/administration/SsoManagement.tsx index 7db75e9..f873d8b 100644 --- a/app/src/main/frontend/components/administration/SsoManagement.tsx +++ b/app/src/main/frontend/components/administration/SsoManagement.tsx @@ -49,7 +49,7 @@ function SsoManagementLayout({getConfig, formik, setSaveMessage}: any) {
-
+
@@ -70,6 +70,13 @@ function SsoManagementLayout({getConfig, formik, setSaveMessage}: any) { !formik.values.sso.oidc["auto-register-new-users"]}/>
+
+ + +
+
diff --git a/app/src/main/kotlin/org/gameyfin/app/config/ConfigProperties.kt b/app/src/main/kotlin/org/gameyfin/app/config/ConfigProperties.kt index 23e928e..a65cf0a 100644 --- a/app/src/main/kotlin/org/gameyfin/app/config/ConfigProperties.kt +++ b/app/src/main/kotlin/org/gameyfin/app/config/ConfigProperties.kt @@ -147,6 +147,20 @@ sealed class ConfigProperties( true ) + data object RolesClaim : ConfigProperties( + String::class, + "sso.oidc.roles-claim", + "JWT claim to extract roles from", + "roles" + ) + + data object OAuthScopes : ConfigProperties>( + Array::class, + "sso.oidc.oauth-scopes", + "OAuth2 scopes to request", + arrayOf("openid", "profile", "email", "roles") + ) + data object ClientId : ConfigProperties( String::class, "sso.oidc.client-id", diff --git a/app/src/main/kotlin/org/gameyfin/app/core/security/SecurityConfig.kt b/app/src/main/kotlin/org/gameyfin/app/core/security/SecurityConfig.kt index 08df09c..3caaa62 100644 --- a/app/src/main/kotlin/org/gameyfin/app/core/security/SecurityConfig.kt +++ b/app/src/main/kotlin/org/gameyfin/app/core/security/SecurityConfig.kt @@ -98,7 +98,7 @@ class SecurityConfig( val clientRegistration = ClientRegistration.withRegistrationId(SSO_PROVIDER_KEY) .clientId(config.get(ConfigProperties.SSO.OIDC.ClientId)) .clientSecret(config.get(ConfigProperties.SSO.OIDC.ClientSecret)) - .scope("openid", "profile", "email") + .scope(config.get(ConfigProperties.SSO.OIDC.OAuthScopes)?.toList()) .userNameAttributeName("preferred_username") .authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE) .issuerUri(config.get(ConfigProperties.SSO.OIDC.IssuerUrl)) diff --git a/app/src/main/kotlin/org/gameyfin/app/users/RoleService.kt b/app/src/main/kotlin/org/gameyfin/app/users/RoleService.kt index d5feeef..c729574 100644 --- a/app/src/main/kotlin/org/gameyfin/app/users/RoleService.kt +++ b/app/src/main/kotlin/org/gameyfin/app/users/RoleService.kt @@ -1,5 +1,7 @@ package org.gameyfin.app.users +import org.gameyfin.app.config.ConfigProperties +import org.gameyfin.app.config.ConfigService import org.gameyfin.app.core.Role import org.gameyfin.app.users.entities.User import org.gameyfin.app.users.persistence.UserRepository @@ -11,7 +13,8 @@ import org.springframework.stereotype.Service @Service class RoleService( - private val userRepository: UserRepository + private val userRepository: UserRepository, + private val configService: ConfigService ) { companion object { @@ -66,7 +69,8 @@ class RoleService( .filterIsInstance() .flatMap { oidcUserAuthority -> val userInfo = oidcUserAuthority.userInfo - val roles = userInfo.getClaim>("roles") ?: return@flatMap emptySequence() + val rolesClaim = configService.get(ConfigProperties.SSO.OIDC.RolesClaim) + val roles = userInfo.getClaim>(rolesClaim) ?: return@flatMap emptySequence() roles.asSequence().mapNotNull { if (it.startsWith(SSO_ROLE_PREFIX)) SimpleGrantedAuthority( it.replace(SSO_ROLE_PREFIX, INTERNAL_ROLE_PREFIX) From 7a4ad961347971baae0d899c8c213a262f5baef9 Mon Sep 17 00:00:00 2001 From: Simon <9295182+grimsi@users.noreply.github.com> Date: Mon, 1 Sep 2025 14:00:09 +0200 Subject: [PATCH 09/10] Use .getHostName() instead of .getCanonicalHostname() to avoid reverse DNS lookups (#672) --- .../gameyfin/plugins/download/torrent/TorrentDownloadPlugin.kt | 2 +- plugins/torrentdownload/src/main/resources/MANIFEST.MF | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/torrentdownload/src/main/kotlin/org/gameyfin/plugins/download/torrent/TorrentDownloadPlugin.kt b/plugins/torrentdownload/src/main/kotlin/org/gameyfin/plugins/download/torrent/TorrentDownloadPlugin.kt index d3cc38d..d65eb46 100644 --- a/plugins/torrentdownload/src/main/kotlin/org/gameyfin/plugins/download/torrent/TorrentDownloadPlugin.kt +++ b/plugins/torrentdownload/src/main/kotlin/org/gameyfin/plugins/download/torrent/TorrentDownloadPlugin.kt @@ -150,7 +150,7 @@ class TorrentDownloadPlugin(wrapper: PluginWrapper) : ConfigurableGameyfinPlugin private fun getTrackerUri(): URI { val protocol = "http" // No SSL support in ttorrent: https://github.com/mpetazzoni/ttorrent/issues/4 - val host = getHostname().getCanonicalHostName() + val host = getHostname().getHostName() val port = config("trackerPort") val path = "announce" diff --git a/plugins/torrentdownload/src/main/resources/MANIFEST.MF b/plugins/torrentdownload/src/main/resources/MANIFEST.MF index ee430df..c947776 100644 --- a/plugins/torrentdownload/src/main/resources/MANIFEST.MF +++ b/plugins/torrentdownload/src/main/resources/MANIFEST.MF @@ -1,4 +1,4 @@ -Plugin-Version: 1.0.0 +Plugin-Version: 1.0.1 Plugin-Class: org.gameyfin.plugins.download.torrent.TorrentDownloadPlugin Plugin-Id: org.gameyfin.plugins.download.torrent Plugin-Name: Torrent Download From ee67f98431891030c90436fb2c61bdf48bd81689 Mon Sep 17 00:00:00 2001 From: grimsi <9295182+grimsi@users.noreply.github.com> Date: Mon, 1 Sep 2025 15:42:46 +0000 Subject: [PATCH 10/10] chore: release v2.0.1 --- app/package.json | 4 ++-- build.gradle.kts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/package.json b/app/package.json index 59d3828..51b9f15 100644 --- a/app/package.json +++ b/app/package.json @@ -1,6 +1,6 @@ { "name": "gameyfin", - "version": "2.0.0", + "version": "2.0.1", "type": "module", "dependencies": { "@heroui/react": "2.7.9", @@ -265,4 +265,4 @@ "disableUsageStatistics": true, "hash": "962eccc3fa0735d5234901be4f9e384096113c45bec22564a53688096d62aef4" } -} \ No newline at end of file +} diff --git a/build.gradle.kts b/build.gradle.kts index 0fec534..fd5349d 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -6,7 +6,7 @@ import org.jetbrains.kotlin.gradle.tasks.KotlinJvmCompile import java.nio.file.Files group = "org.gameyfin" -version = "2.0.0" +version = "2.0.1" allprojects { repositories {