Remove recommended version setting

Missing migrations, possibly broke controller?
This commit is contained in:
Nassim Jahnke 2022-06-26 20:50:04 +02:00
parent 2b671c1482
commit 65bd042caa
No known key found for this signature in database
GPG Key ID: 6BE3B555EBC5982B
28 changed files with 182 additions and 384 deletions

View File

@ -12,7 +12,7 @@ import { useVuelidate } from "@vuelidate/core";
import InputCheckbox from "~/components/ui/InputCheckbox.vue"; import InputCheckbox from "~/components/ui/InputCheckbox.vue";
import { ChannelFlag } from "~/types/enums"; 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<{ const props = defineProps<{
projectId: number; projectId: number;

View File

@ -20,15 +20,13 @@ interface DownloadableVersion {
const props = withDefaults( const props = withDefaults(
defineProps<{ defineProps<{
project: HangarProject; project: HangarProject;
recommended?: boolean;
small?: 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; platform?: Platform;
version?: DownloadableVersion; version?: DownloadableVersion;
pinnedVersion?: PinnedVersion; pinnedVersion?: PinnedVersion;
}>(), }>(),
{ {
recommended: false,
small: false, small: false,
} }
); );
@ -38,7 +36,7 @@ function downloadLink(platform: Platform, version: DownloadableVersion) {
return version.externalUrl; 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`; 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}`; return import.meta.env.SSR ? path : `${window.location.protocol}//${window.location.host}${path}`;
} }
@ -48,27 +46,7 @@ const external = computed(() => false);
<template> <template>
<div class="flex items-center"> <div class="flex items-center">
<DropdownButton v-if="recommended" :button-size="small ? 'medium' : 'large'"> <DropdownButton v-if="pinnedVersion" :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'">
<template #button-label> <template #button-label>
<span class="items-center inline-flex"> <span class="items-center inline-flex">
<IconMdiDownloadOutline /> <IconMdiDownloadOutline />
@ -88,11 +66,31 @@ const external = computed(() => false);
</DropdownItem> </DropdownItem>
</DropdownButton> </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'"> <Button :size="small ? 'medium' : 'large'">
<IconMdiDownloadOutline /> <IconMdiDownloadOutline />
<span v-if="!small" class="ml-1">{{ external ? i18n.t("version.page.downloadExternal") : i18n.t("version.page.download") }}</span> <span v-if="!small" class="ml-1">{{ external ? i18n.t("version.page.downloadExternal") : i18n.t("version.page.download") }}</span>
</Button> </Button>
</a> </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> </div>
</template> </template>

View File

@ -118,7 +118,7 @@ async function sendForApproval() {
<p>{{ project.description }}</p> <p>{{ project.description }}</p>
</div> </div>
<div class="flex flex-col justify-around <sm:items-center space-y-2 items-end justify-between flex-shrink-0"> <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"> <div class="flex">
<Tooltip> <Tooltip>
<template #content> <template #content>

View File

@ -397,7 +397,6 @@
"channel": "Channel", "channel": "Channel",
"addChannel": "Add Channel", "addChannel": "Add Channel",
"unstable": "Unstable", "unstable": "Unstable",
"recommended": "Recommended",
"forumPost": "Forum Post", "forumPost": "Forum Post",
"release": { "release": {
"bulletin": "Release Bulletin", "bulletin": "Release Bulletin",
@ -475,10 +474,8 @@
"adminMsg": "Approved by {0} {1}", "adminMsg": "Approved by {0} {1}",
"reviewLogs": "Review logs", "reviewLogs": "Review logs",
"reviewStart": "Start review", "reviewStart": "Start review",
"setRecommended": "Set as Recommended",
"manage": "Management", "manage": "Management",
"visibility": "Visibility: {0}", "visibility": "Visibility: {0}",
"setRecommendedTooltip": "Set this version as recommended for {0} platform",
"pinned": { "pinned": {
"tooltip": { "tooltip": {
"none": "Pin this version to the main project page", "none": "Pin this version to the main project page",
@ -501,7 +498,6 @@
"download": "Download", "download": "Download",
"downloadExternal": "Download External", "downloadExternal": "Download External",
"adminActions": "Admin actions", "adminActions": "Admin actions",
"recommended": "Recommended version",
"partiallyApproved": "Partially approved", "partiallyApproved": "Partially approved",
"approved": "Approved", "approved": "Approved",
"userAdminLogs": "User Admin Logs", "userAdminLogs": "User Admin Logs",
@ -526,8 +522,7 @@
"success": { "success": {
"softDelete": "You have deleted this version", "softDelete": "You have deleted this version",
"hardDelete": "You have fully deleted this version", "hardDelete": "You have fully deleted this version",
"restore": "You have restored this version", "restore": "You have restored this version"
"recommended": "You have marked this version as recommended for {0} platform"
} }
}, },
"channel": { "channel": {
@ -537,7 +532,6 @@
"name": "Channel Name", "name": "Channel Name",
"color": "Channel Color", "color": "Channel Color",
"flags": { "flags": {
"skip_review_queue": "Exclude from moderation review queue?",
"unstable": "Versions are to be considered unstable", "unstable": "Versions are to be considered unstable",
"pinned": "Latest version is highlighted on main project page" "pinned": "Latest version is highlighted on main project page"
}, },
@ -557,6 +551,8 @@
} }
}, },
"manage": { "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", "title": "Release channels",
"reviewInfo": "Channel names may automatically be flagged for review and will only be published after", "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.", "subtitle": "Release channels represent the state of a plugin release. A project may have up to five release channels.",

View File

@ -20,6 +20,8 @@ import { projectIconUrl } from "~/composables/useUrlHelper";
import { useRoute } from "vue-router"; import { useRoute } from "vue-router";
import Tooltip from "~/components/design/Tooltip.vue"; import Tooltip from "~/components/design/Tooltip.vue";
import { useNotificationStore } from "~/store/notification"; import { useNotificationStore } from "~/store/notification";
import InputRadio from "~/components/ui/InputRadio.vue";
import { ref } from "vue";
const props = defineProps<{ const props = defineProps<{
user: User; 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 channels = await useProjectChannels(props.project.namespace.owner, props.project.namespace.slug).catch((e) => handleRequestError(e, ctx, i18n));
const validations = useBackendDataStore().validations; const validations = useBackendDataStore().validations;
const notifications = useNotificationStore(); const notifications = useNotificationStore();
//const mainChannel = ref(null); //TODO set
useHead( useHead(
useSeo("Channels | " + props.project.name, props.project.description, route, projectIconUrl(props.project.namespace.owner, props.project.namespace.slug)) 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> </script>
<template> <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> <Card>
<template #header>{{ i18n.t("channel.manage.title") }}</template> <template #header>{{ i18n.t("channel.manage.title") }}</template>
<p class="mb-2">{{ i18n.t("channel.manage.subtitle") }}</p> <p class="mb-2">{{ i18n.t("channel.manage.subtitle") }}</p>
@ -87,12 +100,6 @@ async function editChannel(channel: ProjectChannel) {
<tr> <tr>
<th><IconMdiTag />{{ i18n.t("channel.manage.channelName") }}</th> <th><IconMdiTag />{{ i18n.t("channel.manage.channelName") }}</th>
<th><IconMdiFormatListNumbered />{{ i18n.t("channel.manage.versionCount") }}</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><IconMdiPencil />{{ i18n.t("channel.manage.edit") }}</th>
<th v-if="channels.length !== 1"><IconMdiDelete />{{ i18n.t("channel.manage.trash") }}</th> <th v-if="channels.length !== 1"><IconMdiDelete />{{ i18n.t("channel.manage.trash") }}</th>
</tr> </tr>
@ -101,10 +108,6 @@ async function editChannel(channel: ProjectChannel) {
<tr v-for="channel in channels" :key="channel.name"> <tr v-for="channel in channels" :key="channel.name">
<td><Tag :name="channel.name" :color="{ background: channel.color }" /></td> <td><Tag :name="channel.name" :color="{ background: channel.color }" /></td>
<td>{{ channel.versionCount }}</td> <td>{{ channel.versionCount }}</td>
<td>
<IconMdiCheckboxBlankCircleOutline v-if="channel.flags.indexOf(ChannelFlag.SKIP_REVIEW_QUEUE) > -1" />
<IconMdiCheckCircle v-else />
</td>
<td> <td>
<ChannelModal :project-id="props.project.id" edit :channel="channel" @create="editChannel"> <ChannelModal :project-id="props.project.id" edit :channel="channel" @create="editChannel">
<template #activator="{ on, attrs }"> <template #activator="{ on, attrs }">

View File

@ -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) { async function setPinned(value: boolean) {
try { try {
await useInternalApi(`versions/version/${props.project.id}/${projectVersion.value?.id}/pinned?value=${value}`, true, "post"); 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"> <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" /> <TagComponent class="mr-1" :name="projectVersion.channel.name" :color="{ background: projectVersion.channel.color }" :short-form="true" />
{{ projectVersion.name }} {{ 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"> <Tooltip v-if="isReviewStateChecked" :content="approvalTooltip" class="text-base">
<IconMdiCheckCircleOutline class="text-2xl ml-1" /> <IconMdiCheckCircleOutline class="text-2xl ml-1" />
</Tooltip> </Tooltip>
@ -218,21 +205,6 @@ async function restoreVersion() {
</span> </span>
<div class="flex gap-2 flex-wrap mt-2"> <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> <Tooltip>
<template #content> <template #content>
<span v-if="projectVersion.pinnedStatus === PinnedStatus.CHANNEL">{{ i18n.t("version.page.pinned.tooltip.channel") }}</span> <span v-if="projectVersion.pinnedStatus === PinnedStatus.CHANNEL">{{ i18n.t("version.page.pinned.tooltip.channel") }}</span>

View File

@ -246,14 +246,6 @@ useHead(
</div>--> </div>-->
</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> <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"> <div v-for="platform in platforms" :key="platform.name" class="ml-2">
<InputCheckbox <InputCheckbox

View File

@ -44,7 +44,6 @@ declare module "hangar-api" {
channel: ProjectChannel; channel: ProjectChannel;
pinned: boolean; pinned: boolean;
pinnedStatus: PinnedStatus; pinnedStatus: PinnedStatus;
recommended: Platform[];
} }
interface Version extends VersionCompact, DependencyVersion { interface Version extends VersionCompact, DependencyVersion {

View File

@ -109,7 +109,7 @@ export enum Prompt {
export enum ChannelFlag { export enum ChannelFlag {
FROZEN = "FROZEN", FROZEN = "FROZEN",
UNSTABLE = "UNSTABLE", UNSTABLE = "UNSTABLE",
SKIP_REVIEW_QUEUE = "SKIP_REVIEW_QUEUE", SKIP_REVIEW_QUEUE = "SKIP_REVIEW_QUEUE", //TODO remove
PINNED = "PINNED", PINNED = "PINNED",
} }

View File

@ -42,7 +42,7 @@ declare module "hangar-internal" {
info: HangarProjectInfo; info: HangarProjectInfo;
pages: HangarProjectPage[]; pages: HangarProjectPage[];
pinnedVersions: PinnedVersion[]; pinnedVersions: PinnedVersion[];
recommendedVersions: Record<Platform, string | null>; mainChannelVersions: Record<Platform, HangarVersion>;
} }
interface ProjectPage extends Table { interface ProjectPage extends Table {

View File

@ -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.security.annotations.visibility.VisibilityRequired.Type;
import io.papermc.hangar.service.api.VersionsApiService; import io.papermc.hangar.service.api.VersionsApiService;
import io.papermc.hangar.service.internal.versions.DownloadService; import io.papermc.hangar.service.internal.versions.DownloadService;
import io.papermc.hangar.service.internal.versions.RecommendedVersionService;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.FileSystemResource; import org.springframework.core.io.FileSystemResource;
@ -39,13 +37,11 @@ public class VersionsController implements IVersionsController {
private final DownloadService downloadService; private final DownloadService downloadService;
private final VersionsApiService versionsApiService; private final VersionsApiService versionsApiService;
private final RecommendedVersionService recommendedVersionService;
@Autowired @Autowired
public VersionsController(DownloadService downloadService, VersionsApiService versionsApiService, RecommendedVersionService recommendedVersionService) { public VersionsController(DownloadService downloadService, VersionsApiService versionsApiService) {
this.downloadService = downloadService; this.downloadService = downloadService;
this.versionsApiService = versionsApiService; this.versionsApiService = versionsApiService;
this.recommendedVersionService = recommendedVersionService;
} }
@Override @Override
@ -70,14 +66,12 @@ public class VersionsController implements IVersionsController {
@Override @Override
@PermissionRequired(type = PermissionType.PROJECT, perms = NamedPermission.IS_SUBJECT_MEMBER, args = "{#author, #slug}") @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) { 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); return versionsApiService.getVersionStats(author, slug, versionString, platform, fromDate, toDate);
} }
@Override @Override
@VisibilityRequired(type = Type.VERSION, args = "{#author, #slug, #versionString, #platform}") @VisibilityRequired(type = Type.VERSION, args = "{#author, #slug, #versionString, #platform}")
public FileSystemResource downloadVersion(String author, String slug, String versionString, Platform 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); return downloadService.getVersionFile(author, slug, versionString, platform, false, null);
} }
} }

View File

@ -111,7 +111,7 @@ public interface IVersionsController {
@GetMapping("/projects/{author}/{slug}/versions/{name}/{platform}/stats") @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, 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 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("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 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); @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) @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, 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 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); @ApiParam("The platform of the version to return") @PathVariable Platform platform);
} }

View File

@ -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.LogAction;
import io.papermc.hangar.model.internal.logs.contexts.VersionContext; import io.papermc.hangar.model.internal.logs.contexts.VersionContext;
import io.papermc.hangar.model.internal.versions.HangarVersion; 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.LastDependencies;
import io.papermc.hangar.model.internal.versions.PendingVersion;
import io.papermc.hangar.security.annotations.permission.PermissionRequired; import io.papermc.hangar.security.annotations.permission.PermissionRequired;
import io.papermc.hangar.security.annotations.ratelimit.RateLimit; import io.papermc.hangar.security.annotations.ratelimit.RateLimit;
import io.papermc.hangar.security.annotations.unlocked.Unlocked; 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.security.annotations.visibility.VisibilityRequired.Type;
import io.papermc.hangar.service.internal.versions.DownloadService; import io.papermc.hangar.service.internal.versions.DownloadService;
import io.papermc.hangar.service.internal.versions.PinnedVersionService; 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.VersionDependencyService;
import io.papermc.hangar.service.internal.versions.VersionFactory; import io.papermc.hangar.service.internal.versions.VersionFactory;
import io.papermc.hangar.service.internal.versions.VersionService; 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.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
import javax.validation.Valid; import javax.validation.Valid;
import java.util.List; import java.util.List;
@ -55,16 +53,14 @@ public class VersionController extends HangarComponent {
private final VersionFactory versionFactory; private final VersionFactory versionFactory;
private final VersionService versionService; private final VersionService versionService;
private final VersionDependencyService versionDependencyService; private final VersionDependencyService versionDependencyService;
private final RecommendedVersionService recommendedVersionService;
private final DownloadService downloadService; private final DownloadService downloadService;
private final PinnedVersionService pinnedVersionService; private final PinnedVersionService pinnedVersionService;
@Autowired @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.versionFactory = versionFactory;
this.versionService = versionService; this.versionService = versionService;
this.versionDependencyService = versionDependencyService; this.versionDependencyService = versionDependencyService;
this.recommendedVersionService = recommendedVersionService;
this.downloadService = downloadService; this.downloadService = downloadService;
this.pinnedVersionService = pinnedVersionService; this.pinnedVersionService = pinnedVersionService;
} }
@ -144,14 +140,6 @@ public class VersionController extends HangarComponent {
versionDependencyService.updateVersionPluginDependencies(projectId, versionId, updatePluginDependencies); 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 @Unlocked
@ResponseStatus(HttpStatus.OK) @ResponseStatus(HttpStatus.OK)
@PermissionRequired(type = PermissionType.PROJECT, perms = NamedPermission.EDIT_SUBJECT_SETTINGS, args = "{#projectId}") @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}") @VisibilityRequired(type = Type.VERSION, args = "{#author, #slug, #versionString, #platform}")
@GetMapping(path = "/version/{author}/{slug}/versions/{versionString}/{platform}/download", produces = MediaType.APPLICATION_OCTET_STREAM_VALUE) @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) { 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); return downloadService.getVersionFile(author, slug, versionString, platform, true, token);
} }
@VisibilityRequired(type = Type.VERSION, args = "{#author, #slug, #versionString, #platform}") @VisibilityRequired(type = Type.VERSION, args = "{#author, #slug, #versionString, #platform}")
@GetMapping(path = "/version/{author}/{slug}/versions/{versionString}/{platform}/downloadCheck") @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) { 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); boolean requiresConfirmation = downloadService.requiresConfirmation(author, slug, versionString, platform);
if (requiresConfirmation) { if (requiresConfirmation) {
String token = downloadService.createConfirmationToken(author, slug, versionString, platform); String token = downloadService.createConfirmationToken(author, slug, versionString, platform);

View File

@ -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);
}

View File

@ -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'" + " WHEN exists(SELECT * FROM pinned_versions piv WHERE piv.version_id = pv.id AND lower(type) = 'version') THEN 'VERSION'" +
" ELSE 'NONE'" + " ELSE 'NONE'" +
" END AS pinnedStatus," + " 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" + " ru.name approved_by" +
" FROM project_versions pv" + " FROM project_versions pv" +
" JOIN project_channels pc ON pv.channel_id = pc.id" + " 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'" + " WHEN exists(SELECT * FROM pinned_versions piv WHERE piv.version_id = pv.id AND lower(type) = 'version') THEN 'VERSION'" +
" ELSE 'NONE'" + " ELSE 'NONE'" +
" END AS pinnedStatus," + " 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" + " ru.name approved_by" +
" FROM project_versions pv" + " FROM project_versions pv" +
" JOIN project_channels pc ON pv.channel_id = pc.id" + " JOIN project_channels pc ON pv.channel_id = pc.id" +

View File

@ -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) = 'channel') THEN 'CHANNEL'" +
" WHEN exists(SELECT * FROM pinned_versions piv WHERE piv.version_id = pv.id AND lower(type) = 'version') THEN 'VERSION'" + " WHEN exists(SELECT * FROM pinned_versions piv WHERE piv.version_id = pv.id AND lower(type) = 'version') THEN 'VERSION'" +
" ELSE 'NONE'" + " ELSE 'NONE'" +
" END AS pinnedStatus," + " 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" +
" FROM project_versions pv" + " FROM project_versions pv" +
" JOIN project_channels pc ON pv.channel_id = pc.id" + " JOIN project_channels pc ON pv.channel_id = pc.id" +
" JOIN projects p ON pv.project_id = p.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) = 'channel') THEN 'CHANNEL'" +
" WHEN exists(SELECT * FROM pinned_versions piv WHERE piv.version_id = pv.id AND lower(type) = 'version') THEN 'VERSION'" + " WHEN exists(SELECT * FROM pinned_versions piv WHERE piv.version_id = pv.id AND lower(type) = 'version') THEN 'VERSION'" +
" ELSE 'NONE'" + " ELSE 'NONE'" +
" END AS pinnedStatus," + " 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" +
" FROM project_versions pv" + " FROM project_versions pv" +
" JOIN project_channels pc ON pv.channel_id = pc.id" + " JOIN project_channels pc ON pv.channel_id = pc.id" +
" JOIN projects p ON pv.project_id = p.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) = 'channel') THEN 'CHANNEL'" +
" WHEN exists(SELECT * FROM pinned_versions piv WHERE piv.version_id = pv.id AND lower(type) = 'version') THEN 'VERSION'" + " WHEN exists(SELECT * FROM pinned_versions piv WHERE piv.version_id = pv.id AND lower(type) = 'version') THEN 'VERSION'" +
" ELSE 'NONE'" + " ELSE 'NONE'" +
" END AS pinnedStatus," + " 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" +
" FROM project_versions pv" + " FROM project_versions pv" +
" JOIN projects p ON pv.project_id = p.id" + " JOIN projects p ON pv.project_id = p.id" +
" JOIN project_channels pc ON pv.channel_id = pc.id" + " JOIN project_channels pc ON pv.channel_id = pc.id" +

View File

@ -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.Platform;
import io.papermc.hangar.model.common.projects.ReviewState; import io.papermc.hangar.model.common.projects.ReviewState;
import io.papermc.hangar.model.common.projects.Visibility; import io.papermc.hangar.model.common.projects.Visibility;
import java.time.OffsetDateTime; import java.time.OffsetDateTime;
import java.util.EnumMap; import java.util.EnumMap;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import org.jdbi.v3.core.enums.EnumByOrdinal; import org.jdbi.v3.core.enums.EnumByOrdinal;
import org.jdbi.v3.core.mapper.Nested; import org.jdbi.v3.core.mapper.Nested;
import org.jdbi.v3.core.mapper.reflect.ColumnName; 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<PluginDependency>> pluginDependencies;
private final Map<Platform, Set<String>> platformDependencies; 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) { 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, recommended, postId); super(createdAt, name, visibility, description, stats, fileInfo, externalUrl, author, reviewState, channel, pinnedStatus, postId);
this.pluginDependencies = new EnumMap<>(Platform.class); this.pluginDependencies = new EnumMap<>(Platform.class);
this.platformDependencies = new EnumMap<>(Platform.class); this.platformDependencies = new EnumMap<>(Platform.class);
} }

View File

@ -5,11 +5,11 @@ import io.papermc.hangar.model.Model;
import io.papermc.hangar.model.Named; import io.papermc.hangar.model.Named;
import io.papermc.hangar.model.Visible; import io.papermc.hangar.model.Visible;
import io.papermc.hangar.model.api.project.ProjectChannel; 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.ReviewState;
import io.papermc.hangar.model.common.projects.Visibility; import io.papermc.hangar.model.common.projects.Visibility;
import java.time.OffsetDateTime; import java.time.OffsetDateTime;
import java.util.List;
import org.jdbi.v3.core.enums.EnumByName; import org.jdbi.v3.core.enums.EnumByName;
import org.jdbi.v3.core.enums.EnumByOrdinal; import org.jdbi.v3.core.enums.EnumByOrdinal;
import org.jdbi.v3.core.mapper.Nested; 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 ReviewState reviewState;
private final ProjectChannel channel; private final ProjectChannel channel;
private final PinnedStatus pinnedStatus; private final PinnedStatus pinnedStatus;
private final List<Platform> recommended;
private final Long postId; 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); super(createdAt);
this.name = name; this.name = name;
this.visibility = visibility; this.visibility = visibility;
@ -42,7 +41,6 @@ public class VersionCompact extends Model implements Named, Visible {
this.reviewState = reviewState; this.reviewState = reviewState;
this.channel = channel; this.channel = channel;
this.pinnedStatus = pinnedStatus; this.pinnedStatus = pinnedStatus;
this.recommended = recommended;
this.postId = postId; this.postId = postId;
} }
@ -88,10 +86,6 @@ public class VersionCompact extends Model implements Named, Visible {
return this.pinnedStatus; return this.pinnedStatus;
} }
public List<Platform> getRecommended() {
return this.recommended;
}
public Long getPostId() { public Long getPostId() {
return this.postId; return this.postId;
} }

View File

@ -5,11 +5,11 @@ import org.jdbi.v3.core.enums.EnumByOrdinal;
@EnumByOrdinal @EnumByOrdinal
@JsonFormat(shape = JsonFormat.Shape.STRING) @JsonFormat(shape = JsonFormat.Shape.STRING)
// remember never to delete or re-order these, just deprecate it
public enum ChannelFlag { public enum ChannelFlag {
FROZEN(false), FROZEN(false),
UNSTABLE(true), UNSTABLE(true),
SKIP_REVIEW_QUEUE(true), @Deprecated(forRemoval = true)
SKIP_REVIEW_QUEUE(true), //TODO remove and add id migration
PINNED(true), PINNED(true),
; ;

View File

@ -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();
}
}

View File

@ -13,13 +13,15 @@ import io.papermc.hangar.model.db.roles.ProjectRoleTable;
import io.papermc.hangar.model.identified.ProjectIdentified; import io.papermc.hangar.model.identified.ProjectIdentified;
import io.papermc.hangar.model.internal.Joinable; import io.papermc.hangar.model.internal.Joinable;
import io.papermc.hangar.model.internal.user.JoinableMember; 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.Collection;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; 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 { 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 HangarProjectInfo info;
private final Collection<HangarProjectPage> pages; private final Collection<HangarProjectPage> pages;
private final List<PinnedVersion> pinnedVersions; 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); super(project);
this.id = id; this.id = id;
this.owner = owner; this.owner = owner;
@ -43,7 +45,7 @@ public class HangarProject extends Project implements Joinable<ProjectRoleTable>
this.info = info; this.info = info;
this.pages = pages; this.pages = pages;
this.pinnedVersions = pinnedVersions; this.pinnedVersions = pinnedVersions;
this.recommendedVersions = recommendedVersions; this.mainChannelVersions = mainChannelVersions;
} }
public long getId() { public long getId() {
@ -90,8 +92,8 @@ public class HangarProject extends Project implements Joinable<ProjectRoleTable>
return this.pinnedVersions; return this.pinnedVersions;
} }
public Map<Platform, String> getRecommendedVersions() { public Map<Platform, HangarVersion> getMainChannelVersions() {
return recommendedVersions; return mainChannelVersions;
} }
@Override @Override
@ -105,7 +107,6 @@ public class HangarProject extends Project implements Joinable<ProjectRoleTable>
", info=" + this.info + ", info=" + this.info +
", pages=" + this.pages + ", pages=" + this.pages +
", pinnedVersions=" + this.pinnedVersions + ", pinnedVersions=" + this.pinnedVersions +
", recommendedVersions=" + this.recommendedVersions +
"} " + super.toString(); "} " + 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 @EnumByName
@JsonFormat(shape = JsonFormat.Shape.STRING) @JsonFormat(shape = JsonFormat.Shape.STRING)

View File

@ -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.Version;
import io.papermc.hangar.model.api.project.version.VersionStats; import io.papermc.hangar.model.api.project.version.VersionStats;
import io.papermc.hangar.model.common.NamedPermission; 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.ReviewState;
import io.papermc.hangar.model.common.projects.Visibility; 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.enums.EnumByOrdinal;
import org.jdbi.v3.core.mapper.Nested; import org.jdbi.v3.core.mapper.Nested;
import org.jdbi.v3.core.mapper.reflect.ColumnName; import org.jdbi.v3.core.mapper.reflect.ColumnName;
import java.time.OffsetDateTime;
public class HangarVersion extends Version implements Identified { public class HangarVersion extends Version implements Identified {
private final long id; private final long id;
private final String approvedBy; 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) { 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, recommended, postId); super(createdAt, name, visibility, description, stats, fileInfo, externalUrl, author, reviewState, channel, pinnedStatus, postId);
this.id = id; this.id = id;
this.approvedBy = approvedBy; this.approvedBy = approvedBy;
} }

View File

@ -44,11 +44,10 @@ public class PendingVersion {
private final Color channelColor; private final Color channelColor;
private final Set<ChannelFlag> channelFlags; private final Set<ChannelFlag> channelFlags;
private final boolean forumSync; private final boolean forumSync;
private final boolean recommended;
private final boolean isFile; private final boolean isFile;
@JsonCreator(mode = Mode.PROPERTIES) @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.versionString = versionString;
this.pluginDependencies = pluginDependencies; this.pluginDependencies = pluginDependencies;
this.platformDependencies = platformDependencies; this.platformDependencies = platformDependencies;
@ -59,7 +58,6 @@ public class PendingVersion {
this.channelColor = channelColor; this.channelColor = channelColor;
this.channelFlags = channelFlags; this.channelFlags = channelFlags;
this.forumSync = forumSync; this.forumSync = forumSync;
this.recommended = recommended;
this.isFile = isFile; this.isFile = isFile;
} }
@ -74,7 +72,6 @@ public class PendingVersion {
this.channelName = projectChannelTable.getName(); this.channelName = projectChannelTable.getName();
this.channelColor = projectChannelTable.getColor(); this.channelColor = projectChannelTable.getColor();
this.channelFlags = projectChannelTable.getFlags(); this.channelFlags = projectChannelTable.getFlags();
this.recommended = false;
this.isFile = true; this.isFile = true;
} }
@ -93,7 +90,6 @@ public class PendingVersion {
this.channelName = projectChannelTable.getName(); this.channelName = projectChannelTable.getName();
this.channelColor = projectChannelTable.getColor(); this.channelColor = projectChannelTable.getColor();
this.channelFlags = projectChannelTable.getFlags(); this.channelFlags = projectChannelTable.getFlags();
this.recommended = false;
this.isFile = false; this.isFile = false;
} }
@ -138,10 +134,6 @@ public class PendingVersion {
return forumSync; return forumSync;
} }
public boolean isRecommended() {
return recommended;
}
@JsonProperty("isFile") @JsonProperty("isFile")
public boolean isFile() { public boolean isFile() {
return isFile; return isFile;
@ -160,7 +152,6 @@ public class PendingVersion {
", channelColor=" + channelColor + ", channelColor=" + channelColor +
", channelFlags=" + channelFlags + ", channelFlags=" + channelFlags +
", forumSync=" + forumSync + ", forumSync=" + forumSync +
", recommended=" + recommended +
", isFile=" + isFile + ", isFile=" + isFile +
'}'; '}';
} }

View File

@ -5,7 +5,6 @@ import io.papermc.hangar.model.common.Platform;
import io.papermc.hangar.security.annotations.HangarDecisionVoter; import io.papermc.hangar.security.annotations.HangarDecisionVoter;
import io.papermc.hangar.security.annotations.visibility.VisibilityRequiredMetadataExtractor.VisibilityRequiredAttribute; import io.papermc.hangar.security.annotations.visibility.VisibilityRequiredMetadataExtractor.VisibilityRequiredAttribute;
import io.papermc.hangar.service.internal.projects.ProjectService; 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 io.papermc.hangar.service.internal.versions.VersionService;
import org.aopalliance.intercept.MethodInvocation; import org.aopalliance.intercept.MethodInvocation;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@ -20,14 +19,12 @@ public class VisibilityRequiredVoter extends HangarDecisionVoter<VisibilityRequi
private final ProjectService projectService; private final ProjectService projectService;
private final VersionService versionService; private final VersionService versionService;
private final RecommendedVersionService recommendedVersionService;
@Autowired @Autowired
public VisibilityRequiredVoter(ProjectService projectService, VersionService versionService, RecommendedVersionService recommendedVersionService) { public VisibilityRequiredVoter(ProjectService projectService, VersionService versionService) {
super(VisibilityRequiredAttribute.class); super(VisibilityRequiredAttribute.class);
this.projectService = projectService; this.projectService = projectService;
this.versionService = versionService; this.versionService = versionService;
this.recommendedVersionService = recommendedVersionService;
} }
@Override @Override
@ -50,8 +47,7 @@ public class VisibilityRequiredVoter extends HangarDecisionVoter<VisibilityRequi
if (arguments.length == 1 && versionService.getProjectVersionTable((long) arguments[0]) != null) { if (arguments.length == 1 && versionService.getProjectVersionTable((long) arguments[0]) != null) {
return ACCESS_GRANTED; return ACCESS_GRANTED;
} else { } 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], (String) arguments[2], (Platform) arguments[3]) != null) {
if (versionService.getProjectVersionTable((String) arguments[0], (String) arguments[1], versionId, (Platform) arguments[3]) != null) {
return ACCESS_GRANTED; return ACCESS_GRANTED;
} else { } else {
return ACCESS_DENIED; return ACCESS_DENIED;

View File

@ -1,32 +1,16 @@
package io.papermc.hangar.service.internal.projects; 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.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.HangarUsersDAO;
import io.papermc.hangar.db.dao.internal.projects.HangarProjectsDAO; 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.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.exceptions.HangarApiException;
import io.papermc.hangar.model.api.project.Project; 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.Permission;
import io.papermc.hangar.model.common.Platform; import io.papermc.hangar.model.common.Platform;
import io.papermc.hangar.model.common.projects.Visibility; 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.HangarProject.HangarProjectInfo;
import io.papermc.hangar.model.internal.projects.HangarProjectPage; import io.papermc.hangar.model.internal.projects.HangarProjectPage;
import io.papermc.hangar.model.internal.user.JoinableMember; 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.PermissionService;
import io.papermc.hangar.service.internal.organizations.OrganizationService; import io.papermc.hangar.service.internal.organizations.OrganizationService;
import io.papermc.hangar.service.internal.uploads.ProjectFiles; 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.service.internal.visibility.ProjectVisibilityService;
import io.papermc.hangar.util.FileUtils; 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 @Service
public class ProjectService extends HangarComponent { public class ProjectService extends HangarComponent {
@ -62,10 +66,11 @@ public class ProjectService extends HangarComponent {
private final ProjectFiles projectFiles; private final ProjectFiles projectFiles;
private final PermissionService permissionService; private final PermissionService permissionService;
private final PinnedVersionService pinnedVersionService; private final PinnedVersionService pinnedVersionService;
private final RecommendedVersionService recommendedVersionService; private final VersionsApiDAO versionsApiDAO;
private final HangarVersionsDAO hangarVersionsDAO;
@Autowired @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.projectsDAO = projectDAO;
this.hangarUsersDAO = hangarUsersDAO; this.hangarUsersDAO = hangarUsersDAO;
this.hangarProjectsDAO = hangarProjectsDAO; this.hangarProjectsDAO = hangarProjectsDAO;
@ -75,7 +80,8 @@ public class ProjectService extends HangarComponent {
this.projectFiles = projectFiles; this.projectFiles = projectFiles;
this.permissionService = permissionService; this.permissionService = permissionService;
this.pinnedVersionService = pinnedVersionService; this.pinnedVersionService = pinnedVersionService;
this.recommendedVersionService = recommendedVersionService; this.versionsApiDAO = versionsApiDAO;
this.hangarVersionsDAO = hangarVersionsDAO;
} }
@Nullable @Nullable
@ -119,8 +125,33 @@ public class ProjectService extends HangarComponent {
HangarProjectInfo info = hangarProjectsDAO.getHangarProjectInfo(project.getLeft()); HangarProjectInfo info = hangarProjectsDAO.getHangarProjectInfo(project.getLeft());
Map<Long, HangarProjectPage> pages = projectPageService.getProjectPages(project.getLeft()); Map<Long, HangarProjectPage> pages = projectPageService.getProjectPages(project.getLeft());
final List<HangarProject.PinnedVersion> pinnedVersions = this.pinnedVersionService.getPinnedVersions(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) { public void saveSettings(String author, String slug, ProjectSettingsForm settingsForm) {

View File

@ -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");
}
}

View File

@ -1,27 +1,5 @@
package io.papermc.hangar.service.internal.versions; 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.HangarComponent;
import io.papermc.hangar.db.dao.internal.table.PlatformVersionDAO; import io.papermc.hangar.db.dao.internal.table.PlatformVersionDAO;
import io.papermc.hangar.db.dao.internal.table.versions.ProjectVersionsDAO; 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.exceptions.HangarApiException;
import io.papermc.hangar.model.api.project.version.FileInfo; import io.papermc.hangar.model.api.project.version.FileInfo;
import io.papermc.hangar.model.api.project.version.PluginDependency; 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.Platform;
import io.papermc.hangar.model.common.projects.Visibility; import io.papermc.hangar.model.common.projects.Visibility;
import io.papermc.hangar.model.db.PlatformVersionTable; 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.service.internal.visibility.ProjectVisibilityService;
import io.papermc.hangar.util.CryptoUtils; import io.papermc.hangar.util.CryptoUtils;
import io.papermc.hangar.util.StringUtils; 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 @Service
public class VersionFactory extends HangarComponent { public class VersionFactory extends HangarComponent {
@ -70,7 +68,6 @@ public class VersionFactory extends HangarComponent {
private final PluginDataService pluginDataService; private final PluginDataService pluginDataService;
private final ChannelService channelService; private final ChannelService channelService;
private final ProjectVisibilityService projectVisibilityService; private final ProjectVisibilityService projectVisibilityService;
private final RecommendedVersionService recommendedVersionService;
private final ProjectService projectService; private final ProjectService projectService;
private final NotificationService notificationService; private final NotificationService notificationService;
private final PlatformService platformService; private final PlatformService platformService;
@ -79,7 +76,7 @@ public class VersionFactory extends HangarComponent {
private final ValidationService validationService; private final ValidationService validationService;
@Autowired @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.projectVersionPlatformDependenciesDAO = projectVersionPlatformDependencyDAO;
this.projectVersionDependenciesDAO = projectVersionDependencyDAO; this.projectVersionDependenciesDAO = projectVersionDependencyDAO;
this.platformVersionDAO = platformVersionDAO; this.platformVersionDAO = platformVersionDAO;
@ -89,7 +86,6 @@ public class VersionFactory extends HangarComponent {
this.pluginDataService = pluginDataService; this.pluginDataService = pluginDataService;
this.channelService = channelService; this.channelService = channelService;
this.projectVisibilityService = projectVisibilityService; this.projectVisibilityService = projectVisibilityService;
this.recommendedVersionService = recommendedVersionService;
this.projectService = projectService; this.projectService = projectService;
this.notificationService = notificationService; this.notificationService = notificationService;
this.platformService = platformService; this.platformService = platformService;
@ -282,12 +278,6 @@ public class VersionFactory extends HangarComponent {
jobService.save(new UpdateDiscourseProjectTopicJob(projectId)); 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", "")); actionLogger.version(LogAction.VERSION_CREATED.create(VersionContext.of(projectId, projectVersionTable.getId()), "published", ""));
if (pendingVersion.isForumSync()) { if (pendingVersion.isForumSync()) {

View File

@ -26,7 +26,6 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;