mirror of
https://github.com/imgfloat/server.git
synced 2026-02-05 03:39:26 +00:00
Use environment for download link
This commit is contained in:
4
Makefile
4
Makefile
@@ -4,12 +4,16 @@
|
|||||||
.DEFAULT_GOAL := build
|
.DEFAULT_GOAL := build
|
||||||
|
|
||||||
IMGFLOAT_DB_PATH ?= ./imgfloat.db
|
IMGFLOAT_DB_PATH ?= ./imgfloat.db
|
||||||
|
IMGFLOAT_GITHUB_OWNER ?= Kruhlmann
|
||||||
|
IMGFLOAT_GITHUB_REPO ?= imgfloat-j
|
||||||
IMGFLOAT_ASSETS_PATH ?= ./assets
|
IMGFLOAT_ASSETS_PATH ?= ./assets
|
||||||
IMGFLOAT_PREVIEWS_PATH ?= ./previews
|
IMGFLOAT_PREVIEWS_PATH ?= ./previews
|
||||||
SPRING_SERVLET_MULTIPART_MAX_REQUEST_SIZE ?= 10MB
|
SPRING_SERVLET_MULTIPART_MAX_REQUEST_SIZE ?= 10MB
|
||||||
SPRING_SERVLET_MULTIPART_MAX_FILE_SIZE ?= 10MB
|
SPRING_SERVLET_MULTIPART_MAX_FILE_SIZE ?= 10MB
|
||||||
RUNTIME_ENV = IMGFLOAT_ASSETS_PATH=$(IMGFLOAT_ASSETS_PATH) \
|
RUNTIME_ENV = IMGFLOAT_ASSETS_PATH=$(IMGFLOAT_ASSETS_PATH) \
|
||||||
IMGFLOAT_PREVIEWS_PATH=$(IMGFLOAT_PREVIEWS_PATH) \
|
IMGFLOAT_PREVIEWS_PATH=$(IMGFLOAT_PREVIEWS_PATH) \
|
||||||
|
IMGFLOAT_GITHUB_OWNER=$(IMGFLOAT_GITHUB_OWNER) \
|
||||||
|
IMGFLOAT_GITHUB_REPO=$(IMGFLOAT_GITHUB_REPO) \
|
||||||
IMGFLOAT_DB_PATH=$(IMGFLOAT_DB_PATH) \
|
IMGFLOAT_DB_PATH=$(IMGFLOAT_DB_PATH) \
|
||||||
SPRING_SERVLET_MULTIPART_MAX_FILE_SIZE=$(SPRING_SERVLET_MULTIPART_MAX_FILE_SIZE) \
|
SPRING_SERVLET_MULTIPART_MAX_FILE_SIZE=$(SPRING_SERVLET_MULTIPART_MAX_FILE_SIZE) \
|
||||||
SPRING_SERVLET_MULTIPART_MAX_REQUEST_SIZE=$(SPRING_SERVLET_MULTIPART_MAX_REQUEST_SIZE)
|
SPRING_SERVLET_MULTIPART_MAX_REQUEST_SIZE=$(SPRING_SERVLET_MULTIPART_MAX_REQUEST_SIZE)
|
||||||
|
|||||||
@@ -16,6 +16,8 @@ Define the following required environment variables:
|
|||||||
| `IMGFLOAT_INITIAL_TWITCH_USERNAME_SYSADMIN` | Twitch username of the initial sysadmin user | example_broadcaster |
|
| `IMGFLOAT_INITIAL_TWITCH_USERNAME_SYSADMIN` | Twitch username of the initial sysadmin user | example_broadcaster |
|
||||||
| `SPRING_SERVLET_MULTIPART_MAX_FILE_SIZE` | Maximum upload file size | 10MB |
|
| `SPRING_SERVLET_MULTIPART_MAX_FILE_SIZE` | Maximum upload file size | 10MB |
|
||||||
| `SPRING_SERVLET_MULTIPART_MAX_REQUEST_SIZE` | Maximum upload request size | 10MB |
|
| `SPRING_SERVLET_MULTIPART_MAX_REQUEST_SIZE` | Maximum upload request size | 10MB |
|
||||||
|
| `IMGFLOAT_GITHUB_OWNER` | GitHub owner used to build desktop download links | Kruhlmann |
|
||||||
|
| `IMGFLOAT_GITHUB_REPO` | GitHub repo used to build desktop download links | imgfloat-j |
|
||||||
| `TWITCH_CLIENT_ID` | Oauth2 client id | i1bjnh4whieht5kzn307nvu3rn5pqi |
|
| `TWITCH_CLIENT_ID` | Oauth2 client id | i1bjnh4whieht5kzn307nvu3rn5pqi |
|
||||||
| `TWITCH_CLIENT_SECRET` | Oauth2 client secret | vpkn8cp7ona65l121j6q78l9gkmed3 |
|
| `TWITCH_CLIENT_SECRET` | Oauth2 client secret | vpkn8cp7ona65l121j6q78l9gkmed3 |
|
||||||
|
|
||||||
|
|||||||
@@ -40,6 +40,12 @@ public class SystemEnvironmentValidator {
|
|||||||
@Value("${IMGFLOAT_INITIAL_TWITCH_USERNAME_SYSADMIN:#{null}}")
|
@Value("${IMGFLOAT_INITIAL_TWITCH_USERNAME_SYSADMIN:#{null}}")
|
||||||
private String initialSysadmin;
|
private String initialSysadmin;
|
||||||
|
|
||||||
|
@Value("${IMGFLOAT_GITHUB_OWNER:#{null}}")
|
||||||
|
private String githubOwner;
|
||||||
|
|
||||||
|
@Value("${IMGFLOAT_GITHUB_REPO:#{null}}")
|
||||||
|
private String githubRepo;
|
||||||
|
|
||||||
private long maxUploadBytes;
|
private long maxUploadBytes;
|
||||||
private long maxRequestBytes;
|
private long maxRequestBytes;
|
||||||
|
|
||||||
@@ -70,6 +76,8 @@ public class SystemEnvironmentValidator {
|
|||||||
checkString(twitchClientSecret, "TWITCH_CLIENT_SECRET", missing);
|
checkString(twitchClientSecret, "TWITCH_CLIENT_SECRET", missing);
|
||||||
checkString(assetsPath, "IMGFLOAT_ASSETS_PATH", missing);
|
checkString(assetsPath, "IMGFLOAT_ASSETS_PATH", missing);
|
||||||
checkString(previewsPath, "IMGFLOAT_PREVIEWS_PATH", missing);
|
checkString(previewsPath, "IMGFLOAT_PREVIEWS_PATH", missing);
|
||||||
|
checkString(githubOwner, "IMGFLOAT_GITHUB_OWNER", missing);
|
||||||
|
checkString(githubRepo, "IMGFLOAT_GITHUB_REPO", missing);
|
||||||
|
|
||||||
if (!missing.isEmpty()) {
|
if (!missing.isEmpty()) {
|
||||||
throw new IllegalStateException("Missing or invalid environment variables:\n" + missing);
|
throw new IllegalStateException("Missing or invalid environment variables:\n" + missing);
|
||||||
@@ -84,6 +92,8 @@ public class SystemEnvironmentValidator {
|
|||||||
log.info(" - IMGFLOAT_INITIAL_TWITCH_USERNAME_SYSADMIN: {}", initialSysadmin);
|
log.info(" - IMGFLOAT_INITIAL_TWITCH_USERNAME_SYSADMIN: {}", initialSysadmin);
|
||||||
log.info(" - IMGFLOAT_ASSETS_PATH: {}", assetsPath);
|
log.info(" - IMGFLOAT_ASSETS_PATH: {}", assetsPath);
|
||||||
log.info(" - IMGFLOAT_PREVIEWS_PATH: {}", previewsPath);
|
log.info(" - IMGFLOAT_PREVIEWS_PATH: {}", previewsPath);
|
||||||
|
log.info(" - IMGFLOAT_GITHUB_OWNER: {}", githubOwner);
|
||||||
|
log.info(" - IMGFLOAT_GITHUB_REPO: {}", githubRepo);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkString(String value, String name, StringBuilder missing) {
|
private void checkString(String value, String name, StringBuilder missing) {
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import dev.kruhlmann.imgfloat.model.Settings;
|
|||||||
import dev.kruhlmann.imgfloat.service.AuthorizationService;
|
import dev.kruhlmann.imgfloat.service.AuthorizationService;
|
||||||
import dev.kruhlmann.imgfloat.service.ChannelDirectoryService;
|
import dev.kruhlmann.imgfloat.service.ChannelDirectoryService;
|
||||||
import dev.kruhlmann.imgfloat.service.GitInfoService;
|
import dev.kruhlmann.imgfloat.service.GitInfoService;
|
||||||
|
import dev.kruhlmann.imgfloat.service.GithubReleaseService;
|
||||||
import dev.kruhlmann.imgfloat.service.SettingsService;
|
import dev.kruhlmann.imgfloat.service.SettingsService;
|
||||||
import dev.kruhlmann.imgfloat.service.VersionService;
|
import dev.kruhlmann.imgfloat.service.VersionService;
|
||||||
import dev.kruhlmann.imgfloat.util.LogSanitizer;
|
import dev.kruhlmann.imgfloat.util.LogSanitizer;
|
||||||
@@ -29,6 +30,7 @@ public class ViewController {
|
|||||||
private final GitInfoService gitInfoService;
|
private final GitInfoService gitInfoService;
|
||||||
private final ObjectMapper objectMapper;
|
private final ObjectMapper objectMapper;
|
||||||
private final AuthorizationService authorizationService;
|
private final AuthorizationService authorizationService;
|
||||||
|
private final GithubReleaseService githubReleaseService;
|
||||||
private final long uploadLimitBytes;
|
private final long uploadLimitBytes;
|
||||||
|
|
||||||
public ViewController(
|
public ViewController(
|
||||||
@@ -38,6 +40,7 @@ public class ViewController {
|
|||||||
GitInfoService gitInfoService,
|
GitInfoService gitInfoService,
|
||||||
ObjectMapper objectMapper,
|
ObjectMapper objectMapper,
|
||||||
AuthorizationService authorizationService,
|
AuthorizationService authorizationService,
|
||||||
|
GithubReleaseService githubReleaseService,
|
||||||
long uploadLimitBytes
|
long uploadLimitBytes
|
||||||
) {
|
) {
|
||||||
this.channelDirectoryService = channelDirectoryService;
|
this.channelDirectoryService = channelDirectoryService;
|
||||||
@@ -46,6 +49,7 @@ public class ViewController {
|
|||||||
this.gitInfoService = gitInfoService;
|
this.gitInfoService = gitInfoService;
|
||||||
this.objectMapper = objectMapper;
|
this.objectMapper = objectMapper;
|
||||||
this.authorizationService = authorizationService;
|
this.authorizationService = authorizationService;
|
||||||
|
this.githubReleaseService = githubReleaseService;
|
||||||
this.uploadLimitBytes = uploadLimitBytes;
|
this.uploadLimitBytes = uploadLimitBytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -129,6 +133,7 @@ public class ViewController {
|
|||||||
private void addVersionAttributes(Model model) {
|
private void addVersionAttributes(Model model) {
|
||||||
model.addAttribute("version", versionService.getVersion());
|
model.addAttribute("version", versionService.getVersion());
|
||||||
model.addAttribute("releaseVersion", versionService.getReleaseVersion());
|
model.addAttribute("releaseVersion", versionService.getReleaseVersion());
|
||||||
|
model.addAttribute("downloadBaseUrl", githubReleaseService.getDownloadBaseUrl());
|
||||||
model.addAttribute("buildCommitShort", gitInfoService.getShortCommitSha());
|
model.addAttribute("buildCommitShort", gitInfoService.getShortCommitSha());
|
||||||
model.addAttribute("buildCommitUrl", gitInfoService.getCommitUrl());
|
model.addAttribute("buildCommitUrl", gitInfoService.getCommitUrl());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,45 @@
|
|||||||
|
package dev.kruhlmann.imgfloat.service;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class GithubReleaseService {
|
||||||
|
|
||||||
|
private static final Logger LOG = LoggerFactory.getLogger(GithubReleaseService.class);
|
||||||
|
|
||||||
|
private final VersionService versionService;
|
||||||
|
private final String githubOwner;
|
||||||
|
private final String githubRepo;
|
||||||
|
|
||||||
|
public GithubReleaseService(
|
||||||
|
VersionService versionService,
|
||||||
|
@Value("${IMGFLOAT_GITHUB_OWNER:#{null}}") String githubOwner,
|
||||||
|
@Value("${IMGFLOAT_GITHUB_REPO:#{null}}") String githubRepo
|
||||||
|
) {
|
||||||
|
this.versionService = versionService;
|
||||||
|
this.githubOwner = githubOwner;
|
||||||
|
this.githubRepo = githubRepo;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDownloadBaseUrl() {
|
||||||
|
validateConfiguration();
|
||||||
|
String releaseTag = versionService.getReleaseTag();
|
||||||
|
return String.format(
|
||||||
|
"https://github.com/%s/%s/releases/download/%s/",
|
||||||
|
githubOwner.trim(),
|
||||||
|
githubRepo.trim(),
|
||||||
|
releaseTag
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void validateConfiguration() {
|
||||||
|
if (!StringUtils.hasText(githubOwner) || !StringUtils.hasText(githubRepo)) {
|
||||||
|
LOG.error("GitHub download configuration is missing (owner={}, repo={})", githubOwner, githubRepo);
|
||||||
|
throw new IllegalStateException("Missing GitHub owner or repo configuration for download links");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,9 +2,12 @@ package dev.kruhlmann.imgfloat.service;
|
|||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
@@ -13,23 +16,38 @@ import org.springframework.stereotype.Component;
|
|||||||
public class VersionService {
|
public class VersionService {
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(VersionService.class);
|
private static final Logger LOG = LoggerFactory.getLogger(VersionService.class);
|
||||||
private final String version;
|
private static final Pattern PACKAGE_VERSION_PATTERN = Pattern.compile("\"version\"\\s*:\\s*\"([^\"]+)\"");
|
||||||
|
|
||||||
|
private final String serverVersion;
|
||||||
|
private final String clientVersion;
|
||||||
private final String releaseVersion;
|
private final String releaseVersion;
|
||||||
|
|
||||||
public VersionService() {
|
public VersionService() {
|
||||||
this.version = resolveVersion();
|
this.serverVersion = resolveServerVersion();
|
||||||
this.releaseVersion = normalizeReleaseVersion(this.version);
|
this.clientVersion = resolveClientVersion();
|
||||||
|
this.releaseVersion = normalizeReleaseVersion(this.clientVersion);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getVersion() {
|
public String getVersion() {
|
||||||
return version;
|
return serverVersion;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getReleaseVersion() {
|
public String getReleaseVersion() {
|
||||||
return releaseVersion;
|
return releaseVersion;
|
||||||
}
|
}
|
||||||
|
|
||||||
private String resolveVersion() {
|
public String getReleaseTag() {
|
||||||
|
if (releaseVersion == null || releaseVersion.isBlank()) {
|
||||||
|
return "latest";
|
||||||
|
}
|
||||||
|
if ("latest".equalsIgnoreCase(releaseVersion)) {
|
||||||
|
return "latest";
|
||||||
|
}
|
||||||
|
String normalized = releaseVersion.startsWith("v") ? releaseVersion.substring(1) : releaseVersion;
|
||||||
|
return "v" + normalized;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String resolveServerVersion() {
|
||||||
String pomVersion = getPomVersion();
|
String pomVersion = getPomVersion();
|
||||||
if (pomVersion != null && !pomVersion.isBlank()) {
|
if (pomVersion != null && !pomVersion.isBlank()) {
|
||||||
return pomVersion;
|
return pomVersion;
|
||||||
@@ -43,6 +61,15 @@ public class VersionService {
|
|||||||
return "unknown";
|
return "unknown";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String resolveClientVersion() {
|
||||||
|
String packageJsonVersion = getPackageJsonVersion();
|
||||||
|
if (packageJsonVersion != null && !packageJsonVersion.isBlank()) {
|
||||||
|
return packageJsonVersion;
|
||||||
|
}
|
||||||
|
|
||||||
|
return serverVersion;
|
||||||
|
}
|
||||||
|
|
||||||
private String normalizeReleaseVersion(String baseVersion) {
|
private String normalizeReleaseVersion(String baseVersion) {
|
||||||
if (baseVersion == null || baseVersion.isBlank()) {
|
if (baseVersion == null || baseVersion.isBlank()) {
|
||||||
return "latest";
|
return "latest";
|
||||||
@@ -131,4 +158,26 @@ public class VersionService {
|
|||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String getPackageJsonVersion() {
|
||||||
|
Path packageJsonPath = Paths.get("package.json");
|
||||||
|
if (!Files.exists(packageJsonPath) || !Files.isRegularFile(packageJsonPath)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
String packageJson = Files.readString(packageJsonPath, StandardCharsets.UTF_8);
|
||||||
|
Matcher matcher = PACKAGE_VERSION_PATTERN.matcher(packageJson);
|
||||||
|
if (matcher.find()) {
|
||||||
|
String version = matcher.group(1);
|
||||||
|
if (version != null && !version.isBlank()) {
|
||||||
|
return version.trim();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
LOG.warn("Unable to read version from package.json", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,9 +10,7 @@
|
|||||||
<span class="badge soft recommended-badge hidden">Recommended</span>
|
<span class="badge soft recommended-badge hidden">Recommended</span>
|
||||||
</div>
|
</div>
|
||||||
<p class="muted">Apple Silicon build (ARM64)</p>
|
<p class="muted">Apple Silicon build (ARM64)</p>
|
||||||
<a
|
<a class="button block" th:href="${downloadBaseUrl + 'Imgfloat-' + releaseVersion + '-arm64.dmg'}"
|
||||||
class="button block"
|
|
||||||
th:href="'https://github.com/Kruhlmann/imgfloat-j/releases/download/' + ${releaseVersion} + '/Imgfloat-' + ${releaseVersion} + '-arm64.dmg'"
|
|
||||||
>Download DMG</a
|
>Download DMG</a
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
@@ -22,9 +20,7 @@
|
|||||||
<span class="badge soft recommended-badge hidden">Recommended</span>
|
<span class="badge soft recommended-badge hidden">Recommended</span>
|
||||||
</div>
|
</div>
|
||||||
<p class="muted">Installer for Windows 10 and 11</p>
|
<p class="muted">Installer for Windows 10 and 11</p>
|
||||||
<a
|
<a class="button block" th:href="${downloadBaseUrl + 'Imgfloat-Setup-' + releaseVersion + '.exe'}"
|
||||||
class="button block"
|
|
||||||
th:href="'https://github.com/Kruhlmann/imgfloat-j/releases/download/' + ${releaseVersion} + '/Imgfloat.Setup.' + ${releaseVersion} + '.exe'"
|
|
||||||
>Download EXE</a
|
>Download EXE</a
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
@@ -34,9 +30,7 @@
|
|||||||
<span class="badge soft recommended-badge hidden">Recommended</span>
|
<span class="badge soft recommended-badge hidden">Recommended</span>
|
||||||
</div>
|
</div>
|
||||||
<p class="muted">AppImage for most distributions</p>
|
<p class="muted">AppImage for most distributions</p>
|
||||||
<a
|
<a class="button block" th:href="${downloadBaseUrl + 'Imgfloat-' + releaseVersion + '.AppImage'}"
|
||||||
class="button block"
|
|
||||||
th:href="'https://github.com/Kruhlmann/imgfloat-j/releases/download/' + ${releaseVersion} + '/Imgfloat-' + ${releaseVersion} + '.AppImage'"
|
|
||||||
>Download AppImage</a
|
>Download AppImage</a
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user