mirror of
https://github.com/HangarMC/Hangar.git
synced 2024-11-27 06:01:08 +08:00
Remove recommended version setting
Missing migrations, possibly broke controller?
This commit is contained in:
parent
2b671c1482
commit
65bd042caa
@ -12,7 +12,7 @@ import { useVuelidate } from "@vuelidate/core";
|
||||
import InputCheckbox from "~/components/ui/InputCheckbox.vue";
|
||||
import { ChannelFlag } from "~/types/enums";
|
||||
|
||||
const possibleFlags = [ChannelFlag.UNSTABLE, ChannelFlag.SKIP_REVIEW_QUEUE, ChannelFlag.PINNED]; // TODO maybe load from backend? unsure if needed
|
||||
const possibleFlags = [ChannelFlag.UNSTABLE, ChannelFlag.PINNED]; // TODO maybe load from backend? unsure if needed
|
||||
|
||||
const props = defineProps<{
|
||||
projectId: number;
|
||||
|
@ -20,15 +20,13 @@ interface DownloadableVersion {
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
project: HangarProject;
|
||||
recommended?: boolean;
|
||||
small?: boolean;
|
||||
// Define either version and platform or pinnedVersion
|
||||
// Define either version and platform or pinnedVersion, or neither to use main channel versions
|
||||
platform?: Platform;
|
||||
version?: DownloadableVersion;
|
||||
pinnedVersion?: PinnedVersion;
|
||||
}>(),
|
||||
{
|
||||
recommended: false,
|
||||
small: false,
|
||||
}
|
||||
);
|
||||
@ -38,7 +36,7 @@ function downloadLink(platform: Platform, version: DownloadableVersion) {
|
||||
return version.externalUrl;
|
||||
}
|
||||
|
||||
const versionString = props.recommended ? "recommended" : version.name;
|
||||
const versionString = version.name;
|
||||
const path = `/api/v1/projects/${props.project.namespace.owner}/${props.project.namespace.slug}/versions/${versionString}/${platform.toLowerCase()}/download`;
|
||||
return import.meta.env.SSR ? path : `${window.location.protocol}//${window.location.host}${path}`;
|
||||
}
|
||||
@ -48,27 +46,7 @@ const external = computed(() => false);
|
||||
|
||||
<template>
|
||||
<div class="flex items-center">
|
||||
<DropdownButton v-if="recommended" :button-size="small ? 'medium' : 'large'">
|
||||
<template #button-label>
|
||||
<span class="items-center inline-flex">
|
||||
<IconMdiDownloadOutline />
|
||||
<span v-if="!small" class="ml-1">{{ external ? i18n.t("version.page.downloadExternal") : i18n.t("version.page.download") }}</span>
|
||||
</span>
|
||||
</template>
|
||||
<DropdownItem
|
||||
v-for="(url, pl, idx) in project.recommendedVersions"
|
||||
:key="`${pl}-${idx}`"
|
||||
class="flex items-center"
|
||||
:href="url || downloadLink(pl, null)"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
<PlatformLogo :platform="pl" :size="24" class="mr-1" />
|
||||
{{ backendData.platforms.get(pl).name }}
|
||||
</DropdownItem>
|
||||
</DropdownButton>
|
||||
|
||||
<DropdownButton v-else-if="pinnedVersion" :button-size="small ? 'medium' : 'large'">
|
||||
<DropdownButton v-if="pinnedVersion" :button-size="small ? 'medium' : 'large'">
|
||||
<template #button-label>
|
||||
<span class="items-center inline-flex">
|
||||
<IconMdiDownloadOutline />
|
||||
@ -88,11 +66,31 @@ const external = computed(() => false);
|
||||
</DropdownItem>
|
||||
</DropdownButton>
|
||||
|
||||
<a v-else :href="downloadLink(platform, version)" target="_blank" rel="noopener noreferrer">
|
||||
<a v-else-if="platform && version" :href="downloadLink(platform, version)" target="_blank" rel="noopener noreferrer">
|
||||
<Button :size="small ? 'medium' : 'large'">
|
||||
<IconMdiDownloadOutline />
|
||||
<span v-if="!small" class="ml-1">{{ external ? i18n.t("version.page.downloadExternal") : i18n.t("version.page.download") }}</span>
|
||||
</Button>
|
||||
</a>
|
||||
|
||||
<DropdownButton v-else :button-size="small ? 'medium' : 'large'">
|
||||
<template #button-label>
|
||||
<span class="items-center inline-flex">
|
||||
<IconMdiDownloadOutline />
|
||||
<span v-if="!small" class="ml-1">{{ i18n.t("version.page.download") }}</span>
|
||||
</span>
|
||||
</template>
|
||||
<DropdownItem
|
||||
v-for="(v, p) in project.mainChannelVersions"
|
||||
:key="p"
|
||||
class="flex items-center"
|
||||
:href="downloadLink(p, v)"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
<PlatformLogo :platform="p" :size="24" class="mr-1" />
|
||||
{{ backendData.platforms?.get(p).name }}
|
||||
</DropdownItem>
|
||||
</DropdownButton>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -118,7 +118,7 @@ async function sendForApproval() {
|
||||
<p>{{ project.description }}</p>
|
||||
</div>
|
||||
<div class="flex flex-col justify-around <sm:items-center space-y-2 items-end justify-between flex-shrink-0">
|
||||
<DownloadButton v-if="project.recommendedVersions && Object.keys(project.recommendedVersions).length > 0" :project="project" recommended />
|
||||
<DownloadButton v-if="Object.keys(project.mainChannelVersions).length !== 0" :project="project" />
|
||||
<div class="flex">
|
||||
<Tooltip>
|
||||
<template #content>
|
||||
|
@ -397,7 +397,6 @@
|
||||
"channel": "Channel",
|
||||
"addChannel": "Add Channel",
|
||||
"unstable": "Unstable",
|
||||
"recommended": "Recommended",
|
||||
"forumPost": "Forum Post",
|
||||
"release": {
|
||||
"bulletin": "Release Bulletin",
|
||||
@ -475,10 +474,8 @@
|
||||
"adminMsg": "Approved by {0} {1}",
|
||||
"reviewLogs": "Review logs",
|
||||
"reviewStart": "Start review",
|
||||
"setRecommended": "Set as Recommended",
|
||||
"manage": "Management",
|
||||
"visibility": "Visibility: {0}",
|
||||
"setRecommendedTooltip": "Set this version as recommended for {0} platform",
|
||||
"pinned": {
|
||||
"tooltip": {
|
||||
"none": "Pin this version to the main project page",
|
||||
@ -501,7 +498,6 @@
|
||||
"download": "Download",
|
||||
"downloadExternal": "Download External",
|
||||
"adminActions": "Admin actions",
|
||||
"recommended": "Recommended version",
|
||||
"partiallyApproved": "Partially approved",
|
||||
"approved": "Approved",
|
||||
"userAdminLogs": "User Admin Logs",
|
||||
@ -526,8 +522,7 @@
|
||||
"success": {
|
||||
"softDelete": "You have deleted this version",
|
||||
"hardDelete": "You have fully deleted this version",
|
||||
"restore": "You have restored this version",
|
||||
"recommended": "You have marked this version as recommended for {0} platform"
|
||||
"restore": "You have restored this version"
|
||||
}
|
||||
},
|
||||
"channel": {
|
||||
@ -537,7 +532,6 @@
|
||||
"name": "Channel Name",
|
||||
"color": "Channel Color",
|
||||
"flags": {
|
||||
"skip_review_queue": "Exclude from moderation review queue?",
|
||||
"unstable": "Versions are to be considered unstable",
|
||||
"pinned": "Latest version is highlighted on main project page"
|
||||
},
|
||||
@ -557,6 +551,8 @@
|
||||
}
|
||||
},
|
||||
"manage": {
|
||||
"mainTitle": "Main stable channel",
|
||||
"mainSubtitle": "The most recent builds on the main stable channel will be provided in the download button in the project's header.",
|
||||
"title": "Release channels",
|
||||
"reviewInfo": "Channel names may automatically be flagged for review and will only be published after",
|
||||
"subtitle": "Release channels represent the state of a plugin release. A project may have up to five release channels.",
|
||||
|
@ -20,6 +20,8 @@ import { projectIconUrl } from "~/composables/useUrlHelper";
|
||||
import { useRoute } from "vue-router";
|
||||
import Tooltip from "~/components/design/Tooltip.vue";
|
||||
import { useNotificationStore } from "~/store/notification";
|
||||
import InputRadio from "~/components/ui/InputRadio.vue";
|
||||
import { ref } from "vue";
|
||||
|
||||
const props = defineProps<{
|
||||
user: User;
|
||||
@ -31,6 +33,7 @@ const route = useRoute();
|
||||
const channels = await useProjectChannels(props.project.namespace.owner, props.project.namespace.slug).catch((e) => handleRequestError(e, ctx, i18n));
|
||||
const validations = useBackendDataStore().validations;
|
||||
const notifications = useNotificationStore();
|
||||
//const mainChannel = ref(null); //TODO set
|
||||
|
||||
useHead(
|
||||
useSeo("Channels | " + props.project.name, props.project.description, route, projectIconUrl(props.project.namespace.owner, props.project.namespace.slug))
|
||||
@ -78,6 +81,16 @@ async function editChannel(channel: ProjectChannel) {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<!--<Card class="mb-4">
|
||||
<template #header>{{ i18n.t("channel.manage.mainTitle") }}</template>
|
||||
<p class="mb-2">{{ i18n.t("channel.manage.mainSubtitle") }}</p>
|
||||
<ul>
|
||||
<li v-for="channel in channels" :key="channel.name" class="inline-flex w-full">
|
||||
<InputRadio v-model="mainChannel" :value="channel.name" />
|
||||
<Tag :name="channel.name" :color="{ background: channel.color }"></Tag>
|
||||
</li>
|
||||
</ul>
|
||||
</Card>-->
|
||||
<Card>
|
||||
<template #header>{{ i18n.t("channel.manage.title") }}</template>
|
||||
<p class="mb-2">{{ i18n.t("channel.manage.subtitle") }}</p>
|
||||
@ -87,12 +100,6 @@ async function editChannel(channel: ProjectChannel) {
|
||||
<tr>
|
||||
<th><IconMdiTag />{{ i18n.t("channel.manage.channelName") }}</th>
|
||||
<th><IconMdiFormatListNumbered />{{ i18n.t("channel.manage.versionCount") }}</th>
|
||||
<Tooltip>
|
||||
<template #content>
|
||||
{{ i18n.t("channel.manage.reviewInfo") }}
|
||||
</template>
|
||||
<th><IconMdiFileFind />{{ i18n.t("channel.manage.reviewed") }}</th>
|
||||
</Tooltip>
|
||||
<th><IconMdiPencil />{{ i18n.t("channel.manage.edit") }}</th>
|
||||
<th v-if="channels.length !== 1"><IconMdiDelete />{{ i18n.t("channel.manage.trash") }}</th>
|
||||
</tr>
|
||||
@ -101,10 +108,6 @@ async function editChannel(channel: ProjectChannel) {
|
||||
<tr v-for="channel in channels" :key="channel.name">
|
||||
<td><Tag :name="channel.name" :color="{ background: channel.color }" /></td>
|
||||
<td>{{ channel.versionCount }}</td>
|
||||
<td>
|
||||
<IconMdiCheckboxBlankCircleOutline v-if="channel.flags.indexOf(ChannelFlag.SKIP_REVIEW_QUEUE) > -1" />
|
||||
<IconMdiCheckCircle v-else />
|
||||
</td>
|
||||
<td>
|
||||
<ChannelModal :project-id="props.project.id" edit :channel="channel" @create="editChannel">
|
||||
<template #activator="{ on, attrs }">
|
||||
|
@ -96,16 +96,6 @@ async function savePage(content: string) {
|
||||
}
|
||||
}
|
||||
|
||||
async function setRecommended() {
|
||||
try {
|
||||
await useInternalApi(`versions/version/${props.project.id}/${projectVersion.value?.id}/${platform.value?.enumName}/recommend`, true, "post");
|
||||
notification.success(i18n.t("version.success.recommended", [platform.value?.name]));
|
||||
router.go(0);
|
||||
} catch (e) {
|
||||
handleRequestError(e as AxiosError, ctx, i18n);
|
||||
}
|
||||
}
|
||||
|
||||
async function setPinned(value: boolean) {
|
||||
try {
|
||||
await useInternalApi(`versions/version/${props.project.id}/${projectVersion.value?.id}/pinned?value=${value}`, true, "post");
|
||||
@ -164,9 +154,6 @@ async function restoreVersion() {
|
||||
<h1 class="text-3xl sm:inline-flex items-center">
|
||||
<TagComponent class="mr-1" :name="projectVersion.channel.name" :color="{ background: projectVersion.channel.color }" :short-form="true" />
|
||||
{{ projectVersion.name }}
|
||||
<Tooltip v-if="projectVersion.recommended.includes(platform?.enumName)" :content="i18n.t('version.page.recommended')" class="text-base">
|
||||
<IconMdiDiamondStone :title="i18n.t('version.page.recommended')" class="text-2xl ml-1" />
|
||||
</Tooltip>
|
||||
<Tooltip v-if="isReviewStateChecked" :content="approvalTooltip" class="text-base">
|
||||
<IconMdiCheckCircleOutline class="text-2xl ml-1" />
|
||||
</Tooltip>
|
||||
@ -218,21 +205,6 @@ async function restoreVersion() {
|
||||
</span>
|
||||
|
||||
<div class="flex gap-2 flex-wrap mt-2">
|
||||
<Tooltip
|
||||
v-if="
|
||||
hasPerms(NamedPermission.EDIT_VERSION) &&
|
||||
projectVersion.visibility !== Visibility.SOFT_DELETE &&
|
||||
!projectVersion.recommended.includes(platform?.enumName)
|
||||
"
|
||||
>
|
||||
<template #content>
|
||||
<span>{{ i18n.t("version.page.setRecommendedTooltip", [platform?.name]) }}</span>
|
||||
</template>
|
||||
<Button size="small" @click="setRecommended">
|
||||
<IconMdiDiamond class="mr-1" />
|
||||
{{ i18n.t("version.page.setRecommended") }}
|
||||
</Button>
|
||||
</Tooltip>
|
||||
<Tooltip>
|
||||
<template #content>
|
||||
<span v-if="projectVersion.pinnedStatus === PinnedStatus.CHANNEL">{{ i18n.t("version.page.pinned.tooltip.channel") }}</span>
|
||||
|
@ -246,14 +246,6 @@ useHead(
|
||||
</div>-->
|
||||
</div>
|
||||
|
||||
<!-- todo: remove -->
|
||||
<h2 class="mt-5 text-xl">{{ t("version.new.form.tags") }}</h2>
|
||||
<div class="flex flex-wrap">
|
||||
<div class="basis-4/12 mt-2">
|
||||
<InputCheckbox v-model="pendingVersion.recommended" :label="t('version.new.form.recommended')" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h2 class="mt-5 mb-2 text-xl">{{ t("version.new.form.platforms") }}</h2>
|
||||
<div v-for="platform in platforms" :key="platform.name" class="ml-2">
|
||||
<InputCheckbox
|
||||
|
1
frontend/src/types/api/versions.d.ts
vendored
1
frontend/src/types/api/versions.d.ts
vendored
@ -44,7 +44,6 @@ declare module "hangar-api" {
|
||||
channel: ProjectChannel;
|
||||
pinned: boolean;
|
||||
pinnedStatus: PinnedStatus;
|
||||
recommended: Platform[];
|
||||
}
|
||||
|
||||
interface Version extends VersionCompact, DependencyVersion {
|
||||
|
@ -109,7 +109,7 @@ export enum Prompt {
|
||||
export enum ChannelFlag {
|
||||
FROZEN = "FROZEN",
|
||||
UNSTABLE = "UNSTABLE",
|
||||
SKIP_REVIEW_QUEUE = "SKIP_REVIEW_QUEUE",
|
||||
SKIP_REVIEW_QUEUE = "SKIP_REVIEW_QUEUE", //TODO remove
|
||||
PINNED = "PINNED",
|
||||
}
|
||||
|
||||
|
2
frontend/src/types/internal/projects.d.ts
vendored
2
frontend/src/types/internal/projects.d.ts
vendored
@ -42,7 +42,7 @@ declare module "hangar-internal" {
|
||||
info: HangarProjectInfo;
|
||||
pages: HangarProjectPage[];
|
||||
pinnedVersions: PinnedVersion[];
|
||||
recommendedVersions: Record<Platform, string | null>;
|
||||
mainChannelVersions: Record<Platform, HangarVersion>;
|
||||
}
|
||||
|
||||
interface ProjectPage extends Table {
|
||||
|
@ -19,8 +19,6 @@ import io.papermc.hangar.security.annotations.visibility.VisibilityRequired;
|
||||
import io.papermc.hangar.security.annotations.visibility.VisibilityRequired.Type;
|
||||
import io.papermc.hangar.service.api.VersionsApiService;
|
||||
import io.papermc.hangar.service.internal.versions.DownloadService;
|
||||
import io.papermc.hangar.service.internal.versions.RecommendedVersionService;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.core.io.FileSystemResource;
|
||||
@ -39,13 +37,11 @@ public class VersionsController implements IVersionsController {
|
||||
|
||||
private final DownloadService downloadService;
|
||||
private final VersionsApiService versionsApiService;
|
||||
private final RecommendedVersionService recommendedVersionService;
|
||||
|
||||
@Autowired
|
||||
public VersionsController(DownloadService downloadService, VersionsApiService versionsApiService, RecommendedVersionService recommendedVersionService) {
|
||||
public VersionsController(DownloadService downloadService, VersionsApiService versionsApiService) {
|
||||
this.downloadService = downloadService;
|
||||
this.versionsApiService = versionsApiService;
|
||||
this.recommendedVersionService = recommendedVersionService;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -70,14 +66,12 @@ public class VersionsController implements IVersionsController {
|
||||
@Override
|
||||
@PermissionRequired(type = PermissionType.PROJECT, perms = NamedPermission.IS_SUBJECT_MEMBER, args = "{#author, #slug}")
|
||||
public Map<String, VersionStats> getVersionStats(String author, String slug, String versionString, Platform platform, @NotNull OffsetDateTime fromDate, @NotNull OffsetDateTime toDate) {
|
||||
versionString = recommendedVersionService.fixVersionString(author, slug, versionString, platform); // TODO remove recommended special casing
|
||||
return versionsApiService.getVersionStats(author, slug, versionString, platform, fromDate, toDate);
|
||||
}
|
||||
|
||||
@Override
|
||||
@VisibilityRequired(type = Type.VERSION, args = "{#author, #slug, #versionString, #platform}")
|
||||
public FileSystemResource downloadVersion(String author, String slug, String versionString, Platform platform) {
|
||||
versionString = recommendedVersionService.fixVersionString(author, slug, versionString, platform); // TODO remove recommended special casing
|
||||
return downloadService.getVersionFile(author, slug, versionString, platform, false, null);
|
||||
}
|
||||
}
|
||||
|
@ -111,7 +111,7 @@ public interface IVersionsController {
|
||||
@GetMapping("/projects/{author}/{slug}/versions/{name}/{platform}/stats")
|
||||
Map<String, VersionStats> getVersionStats(@ApiParam("The author of the version to return the stats for") @PathVariable String author,
|
||||
@ApiParam("The slug of the project to return stats for") @PathVariable String slug,
|
||||
@ApiParam("The version to return the stats for. Can be 'recommended'.") @PathVariable("name") String versionString,
|
||||
@ApiParam("The version to return the stats for.") @PathVariable("name") String versionString,
|
||||
@ApiParam("The platform of the version to return") @PathVariable Platform platform,
|
||||
@ApiParam(value = "The first date to include in the result", required = true) @RequestParam @NotNull OffsetDateTime fromDate,
|
||||
@ApiParam(value = "The last date to include in the result", required = true) @RequestParam @NotNull OffsetDateTime toDate);
|
||||
@ -133,6 +133,6 @@ public interface IVersionsController {
|
||||
@GetMapping(value = "/projects/{author}/{slug}/versions/{name}/{platform}/download", produces = MediaType.APPLICATION_OCTET_STREAM_VALUE)
|
||||
FileSystemResource downloadVersion(@ApiParam("The author of the project to return the version for") @PathVariable String author,
|
||||
@ApiParam("The slug of the project to return") @PathVariable String slug,
|
||||
@ApiParam("The name of the version to return. Can be 'recommended'.") @PathVariable("name") String versionString,
|
||||
@ApiParam("The name of the version to return.") @PathVariable("name") String versionString,
|
||||
@ApiParam("The platform of the version to return") @PathVariable Platform platform);
|
||||
}
|
||||
|
@ -13,8 +13,8 @@ import io.papermc.hangar.model.internal.api.requests.versions.UpdatePluginDepend
|
||||
import io.papermc.hangar.model.internal.logs.LogAction;
|
||||
import io.papermc.hangar.model.internal.logs.contexts.VersionContext;
|
||||
import io.papermc.hangar.model.internal.versions.HangarVersion;
|
||||
import io.papermc.hangar.model.internal.versions.PendingVersion;
|
||||
import io.papermc.hangar.model.internal.versions.LastDependencies;
|
||||
import io.papermc.hangar.model.internal.versions.PendingVersion;
|
||||
import io.papermc.hangar.security.annotations.permission.PermissionRequired;
|
||||
import io.papermc.hangar.security.annotations.ratelimit.RateLimit;
|
||||
import io.papermc.hangar.security.annotations.unlocked.Unlocked;
|
||||
@ -22,7 +22,6 @@ import io.papermc.hangar.security.annotations.visibility.VisibilityRequired;
|
||||
import io.papermc.hangar.security.annotations.visibility.VisibilityRequired.Type;
|
||||
import io.papermc.hangar.service.internal.versions.DownloadService;
|
||||
import io.papermc.hangar.service.internal.versions.PinnedVersionService;
|
||||
import io.papermc.hangar.service.internal.versions.RecommendedVersionService;
|
||||
import io.papermc.hangar.service.internal.versions.VersionDependencyService;
|
||||
import io.papermc.hangar.service.internal.versions.VersionFactory;
|
||||
import io.papermc.hangar.service.internal.versions.VersionService;
|
||||
@ -42,7 +41,6 @@ import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import org.springframework.web.bind.annotation.ResponseStatus;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.validation.Valid;
|
||||
import java.util.List;
|
||||
|
||||
@ -55,16 +53,14 @@ public class VersionController extends HangarComponent {
|
||||
private final VersionFactory versionFactory;
|
||||
private final VersionService versionService;
|
||||
private final VersionDependencyService versionDependencyService;
|
||||
private final RecommendedVersionService recommendedVersionService;
|
||||
private final DownloadService downloadService;
|
||||
private final PinnedVersionService pinnedVersionService;
|
||||
|
||||
@Autowired
|
||||
public VersionController(VersionFactory versionFactory, VersionService versionService, VersionDependencyService versionDependencyService, RecommendedVersionService recommendedVersionService, DownloadService downloadService, final PinnedVersionService pinnedVersionService) {
|
||||
public VersionController(VersionFactory versionFactory, VersionService versionService, VersionDependencyService versionDependencyService, DownloadService downloadService, final PinnedVersionService pinnedVersionService) {
|
||||
this.versionFactory = versionFactory;
|
||||
this.versionService = versionService;
|
||||
this.versionDependencyService = versionDependencyService;
|
||||
this.recommendedVersionService = recommendedVersionService;
|
||||
this.downloadService = downloadService;
|
||||
this.pinnedVersionService = pinnedVersionService;
|
||||
}
|
||||
@ -144,14 +140,6 @@ public class VersionController extends HangarComponent {
|
||||
versionDependencyService.updateVersionPluginDependencies(projectId, versionId, updatePluginDependencies);
|
||||
}
|
||||
|
||||
@Unlocked
|
||||
@ResponseStatus(HttpStatus.OK)
|
||||
@PermissionRequired(type = PermissionType.PROJECT, perms = NamedPermission.EDIT_VERSION, args = "{#projectId}")
|
||||
@PostMapping("/version/{projectId}/{versionId}/{platform}/recommend")
|
||||
public void setRecommended(@PathVariable long projectId, @PathVariable long versionId, @PathVariable Platform platform) {
|
||||
recommendedVersionService.setRecommendedVersion(projectId, versionId, platform);
|
||||
}
|
||||
|
||||
@Unlocked
|
||||
@ResponseStatus(HttpStatus.OK)
|
||||
@PermissionRequired(type = PermissionType.PROJECT, perms = NamedPermission.EDIT_SUBJECT_SETTINGS, args = "{#projectId}")
|
||||
@ -193,14 +181,12 @@ public class VersionController extends HangarComponent {
|
||||
@VisibilityRequired(type = Type.VERSION, args = "{#author, #slug, #versionString, #platform}")
|
||||
@GetMapping(path = "/version/{author}/{slug}/versions/{versionString}/{platform}/download", produces = MediaType.APPLICATION_OCTET_STREAM_VALUE)
|
||||
public FileSystemResource download(@PathVariable String author, @PathVariable String slug, @PathVariable String versionString, @PathVariable Platform platform, @RequestParam(required = false) String token) {
|
||||
versionString = recommendedVersionService.fixVersionString(author, slug, versionString, platform); // TODO remove recommended special casing
|
||||
return downloadService.getVersionFile(author, slug, versionString, platform, true, token);
|
||||
}
|
||||
|
||||
@VisibilityRequired(type = Type.VERSION, args = "{#author, #slug, #versionString, #platform}")
|
||||
@GetMapping(path = "/version/{author}/{slug}/versions/{versionString}/{platform}/downloadCheck")
|
||||
public ResponseEntity<String> downloadCheck(@PathVariable String author, @PathVariable String slug, @PathVariable String versionString, @PathVariable Platform platform) {
|
||||
versionString = recommendedVersionService.fixVersionString(author, slug, versionString, platform); // TODO remove recommended special casing
|
||||
boolean requiresConfirmation = downloadService.requiresConfirmation(author, slug, versionString, platform);
|
||||
if (requiresConfirmation) {
|
||||
String token = downloadService.createConfirmationToken(author, slug, versionString, platform);
|
||||
|
@ -1,40 +0,0 @@
|
||||
package io.papermc.hangar.db.dao.internal.table.versions;
|
||||
|
||||
import io.papermc.hangar.model.common.Platform;
|
||||
import io.papermc.hangar.model.db.versions.RecommendedProjectVersionTable;
|
||||
import org.jdbi.v3.core.enums.EnumByOrdinal;
|
||||
import org.jdbi.v3.sqlobject.config.KeyColumn;
|
||||
import org.jdbi.v3.sqlobject.config.ValueColumn;
|
||||
import org.jdbi.v3.sqlobject.customizer.BindBean;
|
||||
import org.jdbi.v3.sqlobject.customizer.Timestamped;
|
||||
import org.jdbi.v3.sqlobject.statement.SqlQuery;
|
||||
import org.jdbi.v3.sqlobject.statement.SqlUpdate;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@Repository
|
||||
public interface RecommendedProjectVersionsDAO {
|
||||
|
||||
@Timestamped
|
||||
@SqlUpdate("INSERT INTO recommended_project_versions (created_at, version_id, project_id, platform) VALUES (:now, :versionId, :projectId, :platform)")
|
||||
void insert(@BindBean RecommendedProjectVersionTable recommendedProjectVersionTable);
|
||||
|
||||
@SqlUpdate("DELETE FROM recommended_project_versions WHERE project_id = :projectId AND platform = :platform")
|
||||
void delete(long projectId, @EnumByOrdinal Platform platform);
|
||||
|
||||
@KeyColumn("platform")
|
||||
@ValueColumn("external_url")
|
||||
@SqlQuery("SELECT rpv.platform, pv.external_url FROM recommended_project_versions rpv JOIN project_versions pv ON rpv.version_id = pv.id WHERE rpv.project_id = :projectId ORDER BY platform")
|
||||
Map<Platform, String> getRecommendedVersions(long projectId);
|
||||
|
||||
@KeyColumn("platform")
|
||||
@ValueColumn("version_string")
|
||||
@SqlQuery("SELECT platform, version_string " +
|
||||
"FROM recommended_project_versions rpv " +
|
||||
" JOIN projects p on p.id = rpv.project_id " +
|
||||
" JOIN project_versions pv on rpv.version_id = pv.id " +
|
||||
"WHERE p.owner_name = :owner AND p.slug = :slug " +
|
||||
"ORDER BY platform")
|
||||
Map<Platform, String> getRecommendedVersions(String owner, String slug);
|
||||
}
|
@ -40,7 +40,6 @@ public interface HangarVersionsDAO {
|
||||
" WHEN exists(SELECT * FROM pinned_versions piv WHERE piv.version_id = pv.id AND lower(type) = 'version') THEN 'VERSION'" +
|
||||
" ELSE 'NONE'" +
|
||||
" END AS pinnedStatus," +
|
||||
" array(SELECT DISTINCT rpv.platform FROM recommended_project_versions rpv WHERE rpv.version_id = pv.id ORDER BY rpv.platform) as recommended," +
|
||||
" ru.name approved_by" +
|
||||
" FROM project_versions pv" +
|
||||
" JOIN project_channels pc ON pv.channel_id = pc.id" +
|
||||
@ -82,7 +81,6 @@ public interface HangarVersionsDAO {
|
||||
" WHEN exists(SELECT * FROM pinned_versions piv WHERE piv.version_id = pv.id AND lower(type) = 'version') THEN 'VERSION'" +
|
||||
" ELSE 'NONE'" +
|
||||
" END AS pinnedStatus," +
|
||||
" array(SELECT DISTINCT rpv.platform FROM recommended_project_versions rpv WHERE rpv.version_id = pv.id ORDER BY rpv.platform) as recommended," +
|
||||
" ru.name approved_by" +
|
||||
" FROM project_versions pv" +
|
||||
" JOIN project_channels pc ON pv.channel_id = pc.id" +
|
||||
|
@ -51,8 +51,7 @@ public interface VersionsApiDAO {
|
||||
" WHEN exists(SELECT * FROM pinned_versions piv WHERE piv.version_id = pv.id AND lower(type) = 'channel') THEN 'CHANNEL'" +
|
||||
" WHEN exists(SELECT * FROM pinned_versions piv WHERE piv.version_id = pv.id AND lower(type) = 'version') THEN 'VERSION'" +
|
||||
" ELSE 'NONE'" +
|
||||
" END AS pinnedStatus," +
|
||||
" array(SELECT DISTINCT rpv.platform FROM recommended_project_versions rpv WHERE rpv.version_id = pv.id ORDER BY rpv.platform) as recommended" +
|
||||
" END AS pinnedStatus" +
|
||||
" FROM project_versions pv" +
|
||||
" JOIN project_channels pc ON pv.channel_id = pc.id" +
|
||||
" JOIN projects p ON pv.project_id = p.id" +
|
||||
@ -91,8 +90,7 @@ public interface VersionsApiDAO {
|
||||
" WHEN exists(SELECT * FROM pinned_versions piv WHERE piv.version_id = pv.id AND lower(type) = 'channel') THEN 'CHANNEL'" +
|
||||
" WHEN exists(SELECT * FROM pinned_versions piv WHERE piv.version_id = pv.id AND lower(type) = 'version') THEN 'VERSION'" +
|
||||
" ELSE 'NONE'" +
|
||||
" END AS pinnedStatus," +
|
||||
" array(SELECT DISTINCT rpv.platform FROM recommended_project_versions rpv WHERE rpv.version_id = pv.id ORDER BY rpv.platform) as recommended" +
|
||||
" END AS pinnedStatus" +
|
||||
" FROM project_versions pv" +
|
||||
" JOIN project_channels pc ON pv.channel_id = pc.id" +
|
||||
" JOIN projects p ON pv.project_id = p.id" +
|
||||
@ -134,8 +132,7 @@ public interface VersionsApiDAO {
|
||||
" WHEN exists(SELECT * FROM pinned_versions piv WHERE piv.version_id = pv.id AND lower(type) = 'channel') THEN 'CHANNEL'" +
|
||||
" WHEN exists(SELECT * FROM pinned_versions piv WHERE piv.version_id = pv.id AND lower(type) = 'version') THEN 'VERSION'" +
|
||||
" ELSE 'NONE'" +
|
||||
" END AS pinnedStatus," +
|
||||
" array(SELECT DISTINCT rpv.platform FROM recommended_project_versions rpv WHERE rpv.version_id = pv.id ORDER BY rpv.platform) as recommended" +
|
||||
" END AS pinnedStatus" +
|
||||
" FROM project_versions pv" +
|
||||
" JOIN projects p ON pv.project_id = p.id" +
|
||||
" JOIN project_channels pc ON pv.channel_id = pc.id" +
|
||||
|
@ -4,11 +4,12 @@ import io.papermc.hangar.model.api.project.ProjectChannel;
|
||||
import io.papermc.hangar.model.common.Platform;
|
||||
import io.papermc.hangar.model.common.projects.ReviewState;
|
||||
import io.papermc.hangar.model.common.projects.Visibility;
|
||||
|
||||
import java.time.OffsetDateTime;
|
||||
import java.util.EnumMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.jdbi.v3.core.enums.EnumByOrdinal;
|
||||
import org.jdbi.v3.core.mapper.Nested;
|
||||
import org.jdbi.v3.core.mapper.reflect.ColumnName;
|
||||
@ -18,8 +19,8 @@ public class Version extends VersionCompact {
|
||||
private final Map<Platform, Set<PluginDependency>> pluginDependencies;
|
||||
private final Map<Platform, Set<String>> platformDependencies;
|
||||
|
||||
public Version(final OffsetDateTime createdAt, @ColumnName("version_string") final String name, final Visibility visibility, final String description, @Nested("vs") final VersionStats stats, @Nested("fi") final FileInfo fileInfo, final String externalUrl, final String author, @EnumByOrdinal final ReviewState reviewState, @Nested("pc") final ProjectChannel channel, final PinnedStatus pinnedStatus, final List<Platform> recommended, final Long postId) {
|
||||
super(createdAt, name, visibility, description, stats, fileInfo, externalUrl, author, reviewState, channel, pinnedStatus, recommended, postId);
|
||||
public Version(final OffsetDateTime createdAt, @ColumnName("version_string") final String name, final Visibility visibility, final String description, @Nested("vs") final VersionStats stats, @Nested("fi") final FileInfo fileInfo, final String externalUrl, final String author, @EnumByOrdinal final ReviewState reviewState, @Nested("pc") final ProjectChannel channel, final PinnedStatus pinnedStatus, final Long postId) {
|
||||
super(createdAt, name, visibility, description, stats, fileInfo, externalUrl, author, reviewState, channel, pinnedStatus, postId);
|
||||
this.pluginDependencies = new EnumMap<>(Platform.class);
|
||||
this.platformDependencies = new EnumMap<>(Platform.class);
|
||||
}
|
||||
|
@ -5,11 +5,11 @@ import io.papermc.hangar.model.Model;
|
||||
import io.papermc.hangar.model.Named;
|
||||
import io.papermc.hangar.model.Visible;
|
||||
import io.papermc.hangar.model.api.project.ProjectChannel;
|
||||
import io.papermc.hangar.model.common.Platform;
|
||||
import io.papermc.hangar.model.common.projects.ReviewState;
|
||||
import io.papermc.hangar.model.common.projects.Visibility;
|
||||
|
||||
import java.time.OffsetDateTime;
|
||||
import java.util.List;
|
||||
|
||||
import org.jdbi.v3.core.enums.EnumByName;
|
||||
import org.jdbi.v3.core.enums.EnumByOrdinal;
|
||||
import org.jdbi.v3.core.mapper.Nested;
|
||||
@ -27,10 +27,9 @@ public class VersionCompact extends Model implements Named, Visible {
|
||||
private final ReviewState reviewState;
|
||||
private final ProjectChannel channel;
|
||||
private final PinnedStatus pinnedStatus;
|
||||
private final List<Platform> recommended;
|
||||
private final Long postId;
|
||||
|
||||
protected VersionCompact(final OffsetDateTime createdAt, @ColumnName("version_string") final String name, final Visibility visibility, final String description, @Nested("vs") final VersionStats stats, @Nested("fi") final FileInfo fileInfo, final String externalUrl, final String author, @EnumByOrdinal final ReviewState reviewState, @Nested("pc") final ProjectChannel channel, final PinnedStatus pinnedStatus, final List<Platform> recommended, final Long postId) {
|
||||
protected VersionCompact(final OffsetDateTime createdAt, @ColumnName("version_string") final String name, final Visibility visibility, final String description, @Nested("vs") final VersionStats stats, @Nested("fi") final FileInfo fileInfo, final String externalUrl, final String author, @EnumByOrdinal final ReviewState reviewState, @Nested("pc") final ProjectChannel channel, final PinnedStatus pinnedStatus, final Long postId) {
|
||||
super(createdAt);
|
||||
this.name = name;
|
||||
this.visibility = visibility;
|
||||
@ -42,7 +41,6 @@ public class VersionCompact extends Model implements Named, Visible {
|
||||
this.reviewState = reviewState;
|
||||
this.channel = channel;
|
||||
this.pinnedStatus = pinnedStatus;
|
||||
this.recommended = recommended;
|
||||
this.postId = postId;
|
||||
}
|
||||
|
||||
@ -88,10 +86,6 @@ public class VersionCompact extends Model implements Named, Visible {
|
||||
return this.pinnedStatus;
|
||||
}
|
||||
|
||||
public List<Platform> getRecommended() {
|
||||
return this.recommended;
|
||||
}
|
||||
|
||||
public Long getPostId() {
|
||||
return this.postId;
|
||||
}
|
||||
|
@ -5,11 +5,11 @@ import org.jdbi.v3.core.enums.EnumByOrdinal;
|
||||
|
||||
@EnumByOrdinal
|
||||
@JsonFormat(shape = JsonFormat.Shape.STRING)
|
||||
// remember never to delete or re-order these, just deprecate it
|
||||
public enum ChannelFlag {
|
||||
FROZEN(false),
|
||||
UNSTABLE(true),
|
||||
SKIP_REVIEW_QUEUE(true),
|
||||
@Deprecated(forRemoval = true)
|
||||
SKIP_REVIEW_QUEUE(true), //TODO remove and add id migration
|
||||
PINNED(true),
|
||||
;
|
||||
|
||||
|
@ -1,51 +0,0 @@
|
||||
package io.papermc.hangar.model.db.versions;
|
||||
|
||||
import io.papermc.hangar.model.common.Platform;
|
||||
import io.papermc.hangar.model.db.Table;
|
||||
import org.jdbi.v3.core.enums.EnumByOrdinal;
|
||||
import org.jdbi.v3.core.mapper.reflect.JdbiConstructor;
|
||||
|
||||
import java.time.OffsetDateTime;
|
||||
|
||||
public class RecommendedProjectVersionTable extends Table {
|
||||
|
||||
private final long versionId;
|
||||
private final long projectId;
|
||||
private final Platform platform;
|
||||
|
||||
@JdbiConstructor
|
||||
public RecommendedProjectVersionTable(OffsetDateTime createdAt, long id, long versionId, long projectId, @EnumByOrdinal Platform platform) {
|
||||
super(createdAt, id);
|
||||
this.versionId = versionId;
|
||||
this.projectId = projectId;
|
||||
this.platform = platform;
|
||||
}
|
||||
|
||||
public RecommendedProjectVersionTable(long versionId, long projectId, Platform platform) {
|
||||
this.versionId = versionId;
|
||||
this.projectId = projectId;
|
||||
this.platform = platform;
|
||||
}
|
||||
|
||||
public long getVersionId() {
|
||||
return versionId;
|
||||
}
|
||||
|
||||
public long getProjectId() {
|
||||
return projectId;
|
||||
}
|
||||
|
||||
@EnumByOrdinal
|
||||
public Platform getPlatform() {
|
||||
return platform;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "RecommendedProjectVersionTable{" +
|
||||
"versionId=" + versionId +
|
||||
", projectId=" + projectId +
|
||||
", platform=" + platform +
|
||||
"} " + super.toString();
|
||||
}
|
||||
}
|
@ -13,13 +13,15 @@ import io.papermc.hangar.model.db.roles.ProjectRoleTable;
|
||||
import io.papermc.hangar.model.identified.ProjectIdentified;
|
||||
import io.papermc.hangar.model.internal.Joinable;
|
||||
import io.papermc.hangar.model.internal.user.JoinableMember;
|
||||
import io.papermc.hangar.model.internal.versions.HangarVersion;
|
||||
import org.jdbi.v3.core.enums.EnumByName;
|
||||
import org.jdbi.v3.core.mapper.Nested;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import org.jdbi.v3.core.enums.EnumByName;
|
||||
import org.jdbi.v3.core.mapper.Nested;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class HangarProject extends Project implements Joinable<ProjectRoleTable>, ProjectIdentified {
|
||||
|
||||
@ -31,9 +33,9 @@ public class HangarProject extends Project implements Joinable<ProjectRoleTable>
|
||||
private final HangarProjectInfo info;
|
||||
private final Collection<HangarProjectPage> pages;
|
||||
private final List<PinnedVersion> pinnedVersions;
|
||||
private final Map<Platform, String> recommendedVersions;
|
||||
private final Map<Platform, HangarVersion> mainChannelVersions;
|
||||
|
||||
public HangarProject(final Project project, final long id, final ProjectOwner owner, final List<JoinableMember<ProjectRoleTable>> members, final String lastVisibilityChangeComment, final String lastVisibilityChangeUserName, final HangarProjectInfo info, final Collection<HangarProjectPage> pages, final List<PinnedVersion> pinnedVersions, final Map<Platform, String> recommendedVersions) {
|
||||
public HangarProject(final Project project, final long id, final ProjectOwner owner, final List<JoinableMember<ProjectRoleTable>> members, final String lastVisibilityChangeComment, final String lastVisibilityChangeUserName, final HangarProjectInfo info, final Collection<HangarProjectPage> pages, final List<PinnedVersion> pinnedVersions, final Map<Platform, HangarVersion> mainChannelVersions) {
|
||||
super(project);
|
||||
this.id = id;
|
||||
this.owner = owner;
|
||||
@ -43,7 +45,7 @@ public class HangarProject extends Project implements Joinable<ProjectRoleTable>
|
||||
this.info = info;
|
||||
this.pages = pages;
|
||||
this.pinnedVersions = pinnedVersions;
|
||||
this.recommendedVersions = recommendedVersions;
|
||||
this.mainChannelVersions = mainChannelVersions;
|
||||
}
|
||||
|
||||
public long getId() {
|
||||
@ -90,8 +92,8 @@ public class HangarProject extends Project implements Joinable<ProjectRoleTable>
|
||||
return this.pinnedVersions;
|
||||
}
|
||||
|
||||
public Map<Platform, String> getRecommendedVersions() {
|
||||
return recommendedVersions;
|
||||
public Map<Platform, HangarVersion> getMainChannelVersions() {
|
||||
return mainChannelVersions;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -105,7 +107,6 @@ public class HangarProject extends Project implements Joinable<ProjectRoleTable>
|
||||
", info=" + this.info +
|
||||
", pages=" + this.pages +
|
||||
", pinnedVersions=" + this.pinnedVersions +
|
||||
", recommendedVersions=" + this.recommendedVersions +
|
||||
"} " + super.toString();
|
||||
}
|
||||
|
||||
@ -160,7 +161,8 @@ public class HangarProject extends Project implements Joinable<ProjectRoleTable>
|
||||
}
|
||||
|
||||
|
||||
public record PinnedVersion(Type type, String name, Set<Platform> platforms, @Nested("pc") ProjectChannel channel, @Nested("fi") @Nullable FileInfo fileInfo, @Nullable String externalUrl) {
|
||||
public record PinnedVersion(Type type, String name, Set<Platform> platforms, @Nested("pc") ProjectChannel channel,
|
||||
@Nested("fi") @Nullable FileInfo fileInfo, @Nullable String externalUrl) {
|
||||
|
||||
@EnumByName
|
||||
@JsonFormat(shape = JsonFormat.Shape.STRING)
|
||||
|
@ -7,22 +7,21 @@ import io.papermc.hangar.model.api.project.version.FileInfo;
|
||||
import io.papermc.hangar.model.api.project.version.Version;
|
||||
import io.papermc.hangar.model.api.project.version.VersionStats;
|
||||
import io.papermc.hangar.model.common.NamedPermission;
|
||||
import io.papermc.hangar.model.common.Platform;
|
||||
import io.papermc.hangar.model.common.projects.ReviewState;
|
||||
import io.papermc.hangar.model.common.projects.Visibility;
|
||||
import java.time.OffsetDateTime;
|
||||
import java.util.List;
|
||||
import org.jdbi.v3.core.enums.EnumByOrdinal;
|
||||
import org.jdbi.v3.core.mapper.Nested;
|
||||
import org.jdbi.v3.core.mapper.reflect.ColumnName;
|
||||
|
||||
import java.time.OffsetDateTime;
|
||||
|
||||
public class HangarVersion extends Version implements Identified {
|
||||
|
||||
private final long id;
|
||||
private final String approvedBy;
|
||||
|
||||
public HangarVersion(final OffsetDateTime createdAt, @ColumnName("version_string") final String name, final Visibility visibility, final String description, @Nested("vs") final VersionStats stats, @Nested("fi") final FileInfo fileInfo, final String externalUrl, final String author, @EnumByOrdinal final ReviewState reviewState, @Nested("pc") final ProjectChannel channel, final PinnedStatus pinnedStatus, final List<Platform> recommended, final long id, final String approvedBy, final long postId) {
|
||||
super(createdAt, name, visibility, description, stats, fileInfo, externalUrl, author, reviewState, channel, pinnedStatus, recommended, postId);
|
||||
public HangarVersion(final OffsetDateTime createdAt, @ColumnName("version_string") final String name, final Visibility visibility, final String description, @Nested("vs") final VersionStats stats, @Nested("fi") final FileInfo fileInfo, final String externalUrl, final String author, @EnumByOrdinal final ReviewState reviewState, @Nested("pc") final ProjectChannel channel, final PinnedStatus pinnedStatus, final long id, final String approvedBy, final long postId) {
|
||||
super(createdAt, name, visibility, description, stats, fileInfo, externalUrl, author, reviewState, channel, pinnedStatus, postId);
|
||||
this.id = id;
|
||||
this.approvedBy = approvedBy;
|
||||
}
|
||||
|
@ -44,11 +44,10 @@ public class PendingVersion {
|
||||
private final Color channelColor;
|
||||
private final Set<ChannelFlag> channelFlags;
|
||||
private final boolean forumSync;
|
||||
private final boolean recommended;
|
||||
private final boolean isFile;
|
||||
|
||||
@JsonCreator(mode = Mode.PROPERTIES)
|
||||
public PendingVersion(String versionString, Map<Platform, Set<PluginDependency>> pluginDependencies, EnumMap<Platform, SortedSet<String>> platformDependencies, String description, FileInfo fileInfo, String externalUrl, String channelName, Color channelColor, Set<ChannelFlag> channelFlags, boolean forumSync, boolean recommended, boolean isFile) {
|
||||
public PendingVersion(String versionString, Map<Platform, Set<PluginDependency>> pluginDependencies, EnumMap<Platform, SortedSet<String>> platformDependencies, String description, FileInfo fileInfo, String externalUrl, String channelName, Color channelColor, Set<ChannelFlag> channelFlags, boolean forumSync, boolean isFile) {
|
||||
this.versionString = versionString;
|
||||
this.pluginDependencies = pluginDependencies;
|
||||
this.platformDependencies = platformDependencies;
|
||||
@ -59,7 +58,6 @@ public class PendingVersion {
|
||||
this.channelColor = channelColor;
|
||||
this.channelFlags = channelFlags;
|
||||
this.forumSync = forumSync;
|
||||
this.recommended = recommended;
|
||||
this.isFile = isFile;
|
||||
}
|
||||
|
||||
@ -74,7 +72,6 @@ public class PendingVersion {
|
||||
this.channelName = projectChannelTable.getName();
|
||||
this.channelColor = projectChannelTable.getColor();
|
||||
this.channelFlags = projectChannelTable.getFlags();
|
||||
this.recommended = false;
|
||||
this.isFile = true;
|
||||
}
|
||||
|
||||
@ -93,7 +90,6 @@ public class PendingVersion {
|
||||
this.channelName = projectChannelTable.getName();
|
||||
this.channelColor = projectChannelTable.getColor();
|
||||
this.channelFlags = projectChannelTable.getFlags();
|
||||
this.recommended = false;
|
||||
this.isFile = false;
|
||||
}
|
||||
|
||||
@ -138,10 +134,6 @@ public class PendingVersion {
|
||||
return forumSync;
|
||||
}
|
||||
|
||||
public boolean isRecommended() {
|
||||
return recommended;
|
||||
}
|
||||
|
||||
@JsonProperty("isFile")
|
||||
public boolean isFile() {
|
||||
return isFile;
|
||||
@ -160,7 +152,6 @@ public class PendingVersion {
|
||||
", channelColor=" + channelColor +
|
||||
", channelFlags=" + channelFlags +
|
||||
", forumSync=" + forumSync +
|
||||
", recommended=" + recommended +
|
||||
", isFile=" + isFile +
|
||||
'}';
|
||||
}
|
||||
|
@ -5,7 +5,6 @@ import io.papermc.hangar.model.common.Platform;
|
||||
import io.papermc.hangar.security.annotations.HangarDecisionVoter;
|
||||
import io.papermc.hangar.security.annotations.visibility.VisibilityRequiredMetadataExtractor.VisibilityRequiredAttribute;
|
||||
import io.papermc.hangar.service.internal.projects.ProjectService;
|
||||
import io.papermc.hangar.service.internal.versions.RecommendedVersionService;
|
||||
import io.papermc.hangar.service.internal.versions.VersionService;
|
||||
import org.aopalliance.intercept.MethodInvocation;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@ -20,14 +19,12 @@ public class VisibilityRequiredVoter extends HangarDecisionVoter<VisibilityRequi
|
||||
|
||||
private final ProjectService projectService;
|
||||
private final VersionService versionService;
|
||||
private final RecommendedVersionService recommendedVersionService;
|
||||
|
||||
@Autowired
|
||||
public VisibilityRequiredVoter(ProjectService projectService, VersionService versionService, RecommendedVersionService recommendedVersionService) {
|
||||
public VisibilityRequiredVoter(ProjectService projectService, VersionService versionService) {
|
||||
super(VisibilityRequiredAttribute.class);
|
||||
this.projectService = projectService;
|
||||
this.versionService = versionService;
|
||||
this.recommendedVersionService = recommendedVersionService;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -50,8 +47,7 @@ public class VisibilityRequiredVoter extends HangarDecisionVoter<VisibilityRequi
|
||||
if (arguments.length == 1 && versionService.getProjectVersionTable((long) arguments[0]) != null) {
|
||||
return ACCESS_GRANTED;
|
||||
} else {
|
||||
String versionId = recommendedVersionService.fixVersionString((String) arguments[0], (String) arguments[1], (String) arguments[2], (Platform) arguments[3]); // TODO remove recommended special casing
|
||||
if (versionService.getProjectVersionTable((String) arguments[0], (String) arguments[1], versionId, (Platform) arguments[3]) != null) {
|
||||
if (versionService.getProjectVersionTable((String) arguments[0], (String) arguments[1], (String) arguments[2], (Platform) arguments[3]) != null) {
|
||||
return ACCESS_GRANTED;
|
||||
} else {
|
||||
return ACCESS_DENIED;
|
||||
|
@ -1,32 +1,16 @@
|
||||
package io.papermc.hangar.service.internal.projects;
|
||||
|
||||
import io.papermc.hangar.service.internal.versions.PinnedVersionService;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Base64;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Function;
|
||||
|
||||
import io.papermc.hangar.HangarComponent;
|
||||
import io.papermc.hangar.controller.extras.pagination.filters.versions.VersionChannelFilter;
|
||||
import io.papermc.hangar.controller.extras.pagination.filters.versions.VersionPlatformFilter;
|
||||
import io.papermc.hangar.db.dao.internal.HangarUsersDAO;
|
||||
import io.papermc.hangar.db.dao.internal.projects.HangarProjectsDAO;
|
||||
import io.papermc.hangar.db.dao.internal.table.projects.ProjectsDAO;
|
||||
import io.papermc.hangar.db.dao.internal.versions.HangarVersionsDAO;
|
||||
import io.papermc.hangar.db.dao.v1.VersionsApiDAO;
|
||||
import io.papermc.hangar.exceptions.HangarApiException;
|
||||
import io.papermc.hangar.model.api.project.Project;
|
||||
import io.papermc.hangar.model.api.requests.RequestPagination;
|
||||
import io.papermc.hangar.model.common.Permission;
|
||||
import io.papermc.hangar.model.common.Platform;
|
||||
import io.papermc.hangar.model.common.projects.Visibility;
|
||||
@ -43,12 +27,32 @@ import io.papermc.hangar.model.internal.projects.HangarProject;
|
||||
import io.papermc.hangar.model.internal.projects.HangarProject.HangarProjectInfo;
|
||||
import io.papermc.hangar.model.internal.projects.HangarProjectPage;
|
||||
import io.papermc.hangar.model.internal.user.JoinableMember;
|
||||
import io.papermc.hangar.model.internal.versions.HangarVersion;
|
||||
import io.papermc.hangar.service.PermissionService;
|
||||
import io.papermc.hangar.service.internal.organizations.OrganizationService;
|
||||
import io.papermc.hangar.service.internal.uploads.ProjectFiles;
|
||||
import io.papermc.hangar.service.internal.versions.RecommendedVersionService;
|
||||
import io.papermc.hangar.service.internal.versions.PinnedVersionService;
|
||||
import io.papermc.hangar.service.internal.visibility.ProjectVisibilityService;
|
||||
import io.papermc.hangar.util.FileUtils;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Base64;
|
||||
import java.util.EnumMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Function;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
@Service
|
||||
public class ProjectService extends HangarComponent {
|
||||
@ -62,10 +66,11 @@ public class ProjectService extends HangarComponent {
|
||||
private final ProjectFiles projectFiles;
|
||||
private final PermissionService permissionService;
|
||||
private final PinnedVersionService pinnedVersionService;
|
||||
private final RecommendedVersionService recommendedVersionService;
|
||||
private final VersionsApiDAO versionsApiDAO;
|
||||
private final HangarVersionsDAO hangarVersionsDAO;
|
||||
|
||||
@Autowired
|
||||
public ProjectService(ProjectsDAO projectDAO, HangarUsersDAO hangarUsersDAO, HangarProjectsDAO hangarProjectsDAO, ProjectVisibilityService projectVisibilityService, OrganizationService organizationService, ProjectPageService projectPageService, ProjectFiles projectFiles, PermissionService permissionService, final PinnedVersionService pinnedVersionService, RecommendedVersionService recommendedVersionService) {
|
||||
public ProjectService(ProjectsDAO projectDAO, HangarUsersDAO hangarUsersDAO, HangarProjectsDAO hangarProjectsDAO, ProjectVisibilityService projectVisibilityService, OrganizationService organizationService, ProjectPageService projectPageService, ProjectFiles projectFiles, PermissionService permissionService, final PinnedVersionService pinnedVersionService, final VersionsApiDAO versionsApiDAO, final HangarVersionsDAO hangarVersionsDAO) {
|
||||
this.projectsDAO = projectDAO;
|
||||
this.hangarUsersDAO = hangarUsersDAO;
|
||||
this.hangarProjectsDAO = hangarProjectsDAO;
|
||||
@ -75,7 +80,8 @@ public class ProjectService extends HangarComponent {
|
||||
this.projectFiles = projectFiles;
|
||||
this.permissionService = permissionService;
|
||||
this.pinnedVersionService = pinnedVersionService;
|
||||
this.recommendedVersionService = recommendedVersionService;
|
||||
this.versionsApiDAO = versionsApiDAO;
|
||||
this.hangarVersionsDAO = hangarVersionsDAO;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@ -119,8 +125,33 @@ public class ProjectService extends HangarComponent {
|
||||
HangarProjectInfo info = hangarProjectsDAO.getHangarProjectInfo(project.getLeft());
|
||||
Map<Long, HangarProjectPage> pages = projectPageService.getProjectPages(project.getLeft());
|
||||
final List<HangarProject.PinnedVersion> pinnedVersions = this.pinnedVersionService.getPinnedVersions(project.getLeft());
|
||||
Map<Platform, String> recommendedVersions = recommendedVersionService.getRecommendedVersions(project.getLeft());
|
||||
return new HangarProject(project.getRight(), project.getLeft(), projectOwner, members, lastVisibilityChangeComment, lastVisibilityChangeUserName, info, pages.values(), pinnedVersions, recommendedVersions);
|
||||
|
||||
final Map<Platform, HangarVersion> mainChannelVersions = new EnumMap<>(Platform.class);
|
||||
for (final Platform platform : Platform.getValues()) {
|
||||
final HangarVersion version = getLastVersion(author, slug, platform, config.channels.getNameDefault());
|
||||
if (version != null) {
|
||||
mainChannelVersions.put(platform, version);
|
||||
}
|
||||
}
|
||||
|
||||
return new HangarProject(project.getRight(), project.getLeft(), projectOwner, members, lastVisibilityChangeComment, lastVisibilityChangeUserName, info, pages.values(), pinnedVersions, mainChannelVersions);
|
||||
}
|
||||
|
||||
public @Nullable HangarVersion getLastVersion(String author, String slug, Platform platform, @Nullable String channel) {
|
||||
RequestPagination pagination = new RequestPagination(1L, 0L);
|
||||
pagination.getFilters().add(new VersionPlatformFilter.VersionPlatformFilterInstance(new Platform[]{platform}));
|
||||
if (channel != null) {
|
||||
// Find the last version with the specified channel
|
||||
pagination.getFilters().add(new VersionChannelFilter.VersionChannelFilterInstance(new String[]{channel}));
|
||||
}
|
||||
|
||||
Long versionId = versionsApiDAO.getVersions(author, slug, false, getHangarUserId(), pagination).entrySet().stream().map(Map.Entry::getKey).findAny().orElse(null);
|
||||
if (versionId != null) {
|
||||
return hangarVersionsDAO.getVersion(versionId, getGlobalPermissions().has(Permission.SeeHidden), getHangarUserId());
|
||||
}
|
||||
|
||||
// Try again with any channel, else empty
|
||||
return channel != null ? getLastVersion(author, slug, platform, null) : null;
|
||||
}
|
||||
|
||||
public void saveSettings(String author, String slug, ProjectSettingsForm settingsForm) {
|
||||
|
@ -1,49 +0,0 @@
|
||||
package io.papermc.hangar.service.internal.versions;
|
||||
|
||||
import io.papermc.hangar.HangarComponent;
|
||||
import io.papermc.hangar.db.dao.internal.table.versions.RecommendedProjectVersionsDAO;
|
||||
import io.papermc.hangar.exceptions.HangarApiException;
|
||||
import io.papermc.hangar.model.common.Platform;
|
||||
import io.papermc.hangar.model.db.versions.RecommendedProjectVersionTable;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@Service
|
||||
public class RecommendedVersionService extends HangarComponent {
|
||||
|
||||
private final RecommendedProjectVersionsDAO recommendedProjectVersionsDAO;
|
||||
|
||||
@Autowired
|
||||
public RecommendedVersionService(RecommendedProjectVersionsDAO recommendedProjectVersionsDAO) {
|
||||
this.recommendedProjectVersionsDAO = recommendedProjectVersionsDAO;
|
||||
}
|
||||
|
||||
public void setRecommendedVersion(long projectId, long versionId, Platform platform) {
|
||||
recommendedProjectVersionsDAO.delete(projectId, platform);
|
||||
recommendedProjectVersionsDAO.insert(new RecommendedProjectVersionTable(versionId, projectId, platform));
|
||||
}
|
||||
|
||||
public Map<Platform, String> getRecommendedVersions(long projectId) {
|
||||
return recommendedProjectVersionsDAO.getRecommendedVersions(projectId);
|
||||
}
|
||||
|
||||
public Map<Platform, String> getRecommendedVersions(String owner, String slug) {
|
||||
return recommendedProjectVersionsDAO.getRecommendedVersions(owner, slug);
|
||||
}
|
||||
|
||||
// TODO we shouldn't have a recommended endpoint, the url should direct on the frontend
|
||||
public String fixVersionString(String author, String slug, String versionString, Platform platform) {
|
||||
if (!"recommended".equals(versionString)) {
|
||||
return versionString;
|
||||
}
|
||||
Map<Platform, String> recommendedVersions = getRecommendedVersions(author, slug);
|
||||
String recommendedVersion = recommendedVersions.get(platform);
|
||||
if (recommendedVersion != null) {
|
||||
return recommendedVersion;
|
||||
}
|
||||
throw new HangarApiException(HttpStatus.NOT_FOUND, "No recommended version found");
|
||||
}
|
||||
}
|
@ -1,27 +1,5 @@
|
||||
package io.papermc.hangar.service.internal.versions;
|
||||
|
||||
import io.papermc.hangar.model.common.ChannelFlag;
|
||||
import java.util.stream.Collectors;
|
||||
import org.spongepowered.configurate.ConfigurateException;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.StandardCopyOption;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.EnumMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.SortedSet;
|
||||
|
||||
import io.papermc.hangar.HangarComponent;
|
||||
import io.papermc.hangar.db.dao.internal.table.PlatformVersionDAO;
|
||||
import io.papermc.hangar.db.dao.internal.table.versions.ProjectVersionsDAO;
|
||||
@ -31,6 +9,7 @@ import io.papermc.hangar.db.dao.v1.VersionsApiDAO;
|
||||
import io.papermc.hangar.exceptions.HangarApiException;
|
||||
import io.papermc.hangar.model.api.project.version.FileInfo;
|
||||
import io.papermc.hangar.model.api.project.version.PluginDependency;
|
||||
import io.papermc.hangar.model.common.ChannelFlag;
|
||||
import io.papermc.hangar.model.common.Platform;
|
||||
import io.papermc.hangar.model.common.projects.Visibility;
|
||||
import io.papermc.hangar.model.db.PlatformVersionTable;
|
||||
@ -57,6 +36,25 @@ import io.papermc.hangar.service.internal.versions.plugindata.PluginFileWithData
|
||||
import io.papermc.hangar.service.internal.visibility.ProjectVisibilityService;
|
||||
import io.papermc.hangar.util.CryptoUtils;
|
||||
import io.papermc.hangar.util.StringUtils;
|
||||
import org.spongepowered.configurate.ConfigurateException;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.StandardCopyOption;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.EnumMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.SortedSet;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Service
|
||||
public class VersionFactory extends HangarComponent {
|
||||
@ -70,7 +68,6 @@ public class VersionFactory extends HangarComponent {
|
||||
private final PluginDataService pluginDataService;
|
||||
private final ChannelService channelService;
|
||||
private final ProjectVisibilityService projectVisibilityService;
|
||||
private final RecommendedVersionService recommendedVersionService;
|
||||
private final ProjectService projectService;
|
||||
private final NotificationService notificationService;
|
||||
private final PlatformService platformService;
|
||||
@ -79,7 +76,7 @@ public class VersionFactory extends HangarComponent {
|
||||
private final ValidationService validationService;
|
||||
|
||||
@Autowired
|
||||
public VersionFactory(ProjectVersionPlatformDependenciesDAO projectVersionPlatformDependencyDAO, ProjectVersionDependenciesDAO projectVersionDependencyDAO, PlatformVersionDAO platformVersionDAO, ProjectVersionsDAO projectVersionDAO, VersionsApiDAO versionsApiDAO, ProjectFiles projectFiles, PluginDataService pluginDataService, ChannelService channelService, ProjectVisibilityService projectVisibilityService, RecommendedVersionService recommendedVersionService, ProjectService projectService, NotificationService notificationService, PlatformService platformService, UsersApiService usersApiService, JobService jobService, ValidationService validationService) {
|
||||
public VersionFactory(ProjectVersionPlatformDependenciesDAO projectVersionPlatformDependencyDAO, ProjectVersionDependenciesDAO projectVersionDependencyDAO, PlatformVersionDAO platformVersionDAO, ProjectVersionsDAO projectVersionDAO, VersionsApiDAO versionsApiDAO, ProjectFiles projectFiles, PluginDataService pluginDataService, ChannelService channelService, ProjectVisibilityService projectVisibilityService, ProjectService projectService, NotificationService notificationService, PlatformService platformService, UsersApiService usersApiService, JobService jobService, ValidationService validationService) {
|
||||
this.projectVersionPlatformDependenciesDAO = projectVersionPlatformDependencyDAO;
|
||||
this.projectVersionDependenciesDAO = projectVersionDependencyDAO;
|
||||
this.platformVersionDAO = platformVersionDAO;
|
||||
@ -89,7 +86,6 @@ public class VersionFactory extends HangarComponent {
|
||||
this.pluginDataService = pluginDataService;
|
||||
this.channelService = channelService;
|
||||
this.projectVisibilityService = projectVisibilityService;
|
||||
this.recommendedVersionService = recommendedVersionService;
|
||||
this.projectService = projectService;
|
||||
this.notificationService = notificationService;
|
||||
this.platformService = platformService;
|
||||
@ -282,12 +278,6 @@ public class VersionFactory extends HangarComponent {
|
||||
jobService.save(new UpdateDiscourseProjectTopicJob(projectId));
|
||||
}
|
||||
|
||||
if (pendingVersion.isRecommended()) {
|
||||
for (Platform platform : pendingVersion.getPlatformDependencies().keySet()) {
|
||||
recommendedVersionService.setRecommendedVersion(projectId, projectVersionTable.getId(), platform);
|
||||
}
|
||||
}
|
||||
|
||||
actionLogger.version(LogAction.VERSION_CREATED.create(VersionContext.of(projectId, projectVersionTable.getId()), "published", ""));
|
||||
|
||||
if (pendingVersion.isForumSync()) {
|
||||
|
@ -26,7 +26,6 @@ import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
Loading…
Reference in New Issue
Block a user