mirror of
https://github.com/HangarMC/Hangar.git
synced 2025-03-13 15:39:18 +08:00
External url for versions (#129)
* work * significant progress * some work * some more work * redirects & warnings * safe host list * external url download counter
This commit is contained in:
parent
0946b4bb0f
commit
8e148a82b4
66
src/main/frontend/src/PlatformChoice.vue
Normal file
66
src/main/frontend/src/PlatformChoice.vue
Normal file
@ -0,0 +1,66 @@
|
||||
<template>
|
||||
<div>
|
||||
<div v-show="loading">
|
||||
<i class="fas fa-spinner fa-spin"></i>
|
||||
<span>Loading platforms for you...</span>
|
||||
</div>
|
||||
<div v-show="!loading && selectedPlatform == null">
|
||||
<span v-for="platform in platforms" @click="select(platform)" style="cursor: pointer;">
|
||||
<Tag :name="platform.name" :color="platform.tag" />
|
||||
</span>
|
||||
</div>
|
||||
<div v-if="!loading && selectedPlatform != null">
|
||||
<span @click="unselect">
|
||||
<i class="fas fa-times-circle"></i>
|
||||
</span>
|
||||
<input type="hidden" name="platform" :value="selectedPlatform.id" form="form-publish">
|
||||
<Tag :name="selectedPlatform.name" :color="selectedPlatform.tag" />
|
||||
<div>
|
||||
<template v-for="(v, index) in selectedPlatform.possibleVersions">
|
||||
<label :for="'version-' + v" style="margin-left: 10px;">{{ v }}</label>
|
||||
<input form="form-publish" :id="'version-' + v" type="checkbox" name="versions" :value="v">
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import Tag from './components/Tag';
|
||||
|
||||
export default {
|
||||
name: 'platform-choice',
|
||||
components: {
|
||||
Tag
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
platforms: [],
|
||||
loading: true,
|
||||
selectedPlatform: null
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
select: function(platform) {
|
||||
this.selectedPlatform = platform;
|
||||
},
|
||||
unselect: function() {
|
||||
this.selectedPlatform = null;
|
||||
}
|
||||
},
|
||||
created() {
|
||||
var self = this;
|
||||
$.ajax({
|
||||
url: '/api/v1/platforms',
|
||||
dataType: 'json',
|
||||
|
||||
complete: function() {
|
||||
self.loading = false;
|
||||
},
|
||||
|
||||
success: function(platforms) {
|
||||
self.platforms = platforms;
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
</script>
|
@ -11,7 +11,7 @@
|
||||
</div>
|
||||
<div v-show="!loading">
|
||||
<div class="list-group">
|
||||
<a v-for="version in versions" :href="routes.Versions.show(htmlDecode(projectOwner), htmlDecode(projectSlug), version.name).absoluteURL()" class="list-group-item"
|
||||
<a v-for="version in versions" :href="routes.Versions.show(htmlDecode(projectOwner), htmlDecode(projectSlug), version.name).absoluteURL()" class="list-group-item list-group-item-action"
|
||||
:class="[classForVisibility(version.visibility)]">
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
@ -37,7 +37,12 @@
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<i class="far fa-fw fa-file"></i>
|
||||
{{ formatSize(version.file_info.size_bytes) }}
|
||||
<span v-if="version.file_info.size_bytes">
|
||||
{{ formatSize(version.file_info.size_bytes) }}
|
||||
</span>
|
||||
<span v-else>
|
||||
(external)
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -21,6 +21,7 @@ import {
|
||||
faDownload,
|
||||
faEdit,
|
||||
faExclamationCircle,
|
||||
faExclamationTriangle,
|
||||
faExternalLinkAlt,
|
||||
faEye,
|
||||
faEyeSlash,
|
||||
@ -92,6 +93,6 @@ library.add(fasStar, fasGem, faEye, faDownload, faServer, faComment, faWrench, f
|
||||
faCheck, faReply, faSave, faTimes, faPencilAlt, faArrowLeft, faCog, faPlayCircle, faEdit, faKey, faCalendar, faFile,
|
||||
faUpload, faPaperPlane, faPlusSquare, faSearch, farStar, faExternalLinkAlt, faMinusSquare, faBug, faFileArchive,
|
||||
faTerminal, faStopCircle, faClipboard, faWindowClose, faSadTear, faUnlockAlt, farGem, faLink, farCheckCircle, faClock,
|
||||
faInfo, fasCheckCircle, faTimesCircle, faEyeSlash, faUserTag, faTags);
|
||||
faInfo, fasCheckCircle, faTimesCircle, faEyeSlash, faUserTag, faTags, faExclamationTriangle);
|
||||
|
||||
dom.watch();
|
||||
|
7
src/main/frontend/src/entries/platform-choice.js
Normal file
7
src/main/frontend/src/entries/platform-choice.js
Normal file
@ -0,0 +1,7 @@
|
||||
import Vue from 'vue'
|
||||
|
||||
const root = require('../PlatformChoice.vue').default;
|
||||
const app = new Vue({
|
||||
el: '#platform-choice',
|
||||
render: createElement => createElement(root)
|
||||
});
|
@ -120,10 +120,11 @@ function initModal() {
|
||||
function initColorPicker() {
|
||||
var modal = getModal();
|
||||
// Initialize popover to stay opened when hovered over
|
||||
modal.find(".color-picker").popover({
|
||||
var colorPicker = modal.find(".color-picker");
|
||||
colorPicker.popover({
|
||||
html: true,
|
||||
trigger: 'manual',
|
||||
container: $(this).attr('id'),
|
||||
container: colorPicker.attr('id'),
|
||||
placement: 'right',
|
||||
sanitize: false,
|
||||
content: function() {
|
||||
|
@ -63,8 +63,9 @@ function reset() {
|
||||
var bs = alert.find('.alert');
|
||||
bs.removeClass('alert-danger').addClass('alert-info');
|
||||
bs.find('[data-fa-i2svg]').attr('data-prefix', 'far');
|
||||
bs.find('[data-fa-i2svg]').removeClass('fa-exclamation-circle').addClass('fa-file-archive').tooltip('destroy');
|
||||
|
||||
if (bs.find('[data-fa-i2svg]').data('ui-tooltip')) {
|
||||
bs.find('[data-fa-i2svg]').removeClass('fa-exclamation-circle').addClass('fa-file-archive').tooltip('destroy');
|
||||
}
|
||||
return alert;
|
||||
}
|
||||
|
||||
@ -78,6 +79,7 @@ $(function() {
|
||||
}
|
||||
|
||||
$('#pluginFile').on('change', function() {
|
||||
|
||||
var alert = reset();
|
||||
if (this.files.length === 0) {
|
||||
$('#form-upload')[0].reset();
|
||||
@ -104,6 +106,8 @@ $(function() {
|
||||
alert.find('.file-size').text(filesize(this.files[0].size));
|
||||
alert.fadeIn('slow');
|
||||
|
||||
$("#form-url-upload").css('display', 'none');
|
||||
|
||||
if(success) {
|
||||
var alertInner = alert.find('.alert');
|
||||
var button = alert.find('button');
|
||||
@ -115,9 +119,10 @@ $(function() {
|
||||
icon.addClass('fa-upload');
|
||||
|
||||
var newTitle = 'Upload plugin';
|
||||
button.tooltip('hide')
|
||||
.attr('data-original-title', newTitle)
|
||||
.tooltip('fixTitle');
|
||||
button
|
||||
.tooltip('option', 'hide', false)
|
||||
.data('original-title', newTitle)
|
||||
.tooltip();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
@ -5,12 +5,15 @@ import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.boot.context.properties.NestedConfigurationProperty;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Component
|
||||
@ConfigurationProperties(prefix = "hangar.security")
|
||||
public class HangarSecurityConfig {
|
||||
|
||||
private boolean secure = false;
|
||||
private long unsafeDownloadMaxAge = 600000;
|
||||
private List<String> safeDownloadHosts = List.of();
|
||||
@NestedConfigurationProperty
|
||||
public SecurityApiConfig api;
|
||||
|
||||
@ -125,6 +128,14 @@ public class HangarSecurityConfig {
|
||||
this.unsafeDownloadMaxAge = unsafeDownloadMaxAge;
|
||||
}
|
||||
|
||||
public List<String> getSafeDownloadHosts() {
|
||||
return safeDownloadHosts;
|
||||
}
|
||||
|
||||
public void setSafeDownloadHosts(List<String> safeDownloadHosts) {
|
||||
this.safeDownloadHosts = safeDownloadHosts;
|
||||
}
|
||||
|
||||
public SecurityApiConfig getApi() {
|
||||
return api;
|
||||
}
|
||||
|
@ -15,6 +15,7 @@ import io.papermc.hangar.db.model.ProjectsTable;
|
||||
import io.papermc.hangar.db.model.UserProjectRolesTable;
|
||||
import io.papermc.hangar.db.model.UsersTable;
|
||||
import io.papermc.hangar.model.Category;
|
||||
import io.papermc.hangar.model.Platform;
|
||||
import io.papermc.hangar.model.Role;
|
||||
import io.papermc.hangar.model.SsoSyncData;
|
||||
import io.papermc.hangar.model.TagColor;
|
||||
@ -209,11 +210,22 @@ public class Apiv1Controller extends HangarController {
|
||||
|
||||
@GetMapping("/v1/tags/{tagId}")
|
||||
public ResponseEntity<ObjectNode> tagColor(@PathVariable("tagId") TagColor tag) {
|
||||
ObjectNode tagColor = mapper.createObjectNode();
|
||||
tagColor.set("id", mapper.valueToTree(tag.ordinal()));
|
||||
tagColor.set("backgroundColor", mapper.valueToTree(tag.getBackground()));
|
||||
tagColor.set("foregroundColor", mapper.valueToTree(tag.getForeground()));
|
||||
return ResponseEntity.of(Optional.of(tagColor));
|
||||
return ResponseEntity.of(Optional.of(writeTagColor(tag)));
|
||||
}
|
||||
|
||||
@GetMapping("/v1/platforms")
|
||||
public ResponseEntity<ArrayNode> platformList() {
|
||||
ArrayNode platforms = mapper.createArrayNode();
|
||||
for (Platform pl : Platform.getValues()) {
|
||||
ObjectNode platformObj = mapper.createObjectNode()
|
||||
.put("id", pl.ordinal())
|
||||
.put("name", pl.getName())
|
||||
.put("category", pl.getPlatformCategory().getName());
|
||||
platformObj.set("possibleVersions", mapper.valueToTree(pl.getPossibleVersions()));
|
||||
platformObj.set("tag", writeTagColor(pl.getTagColor()));
|
||||
platforms.add(platformObj);
|
||||
}
|
||||
return ResponseEntity.ok(platforms);
|
||||
}
|
||||
|
||||
@GetMapping("/v1/users")
|
||||
@ -232,6 +244,13 @@ public class Apiv1Controller extends HangarController {
|
||||
return ResponseEntity.ok((ObjectNode) userObj);
|
||||
}
|
||||
|
||||
private ObjectNode writeTagColor(TagColor tagColor) {
|
||||
return mapper.createObjectNode()
|
||||
.put("id", tagColor.ordinal())
|
||||
.put("background", tagColor.getBackground())
|
||||
.put("foreground", tagColor.getForeground());
|
||||
}
|
||||
|
||||
private ArrayNode writeUsers(List<UsersTable> usersTables) {
|
||||
ArrayNode usersArray = mapper.createArrayNode();
|
||||
List<Long> userIds = usersTables.stream().map(UsersTable::getId).collect(Collectors.toList());
|
||||
|
@ -50,7 +50,7 @@ public class ChannelsController extends HangarController {
|
||||
@Secured("ROLE_USER")
|
||||
@PostMapping("/{author}/{slug}/channels")
|
||||
public ModelAndView create(@PathVariable String author, @PathVariable String slug, @RequestParam("channel-input") String channelId, @RequestParam("channel-color-input") Color channelColor) {
|
||||
channelService.addProjectChannel(projectsTable.get().getId(), channelId, channelColor);
|
||||
channelService.addProjectChannel(projectsTable.get().getId(), channelId, channelColor, false);
|
||||
return Routes.CHANNELS_SHOW_LIST.getRedirect(author, slug);
|
||||
}
|
||||
|
||||
|
@ -19,7 +19,9 @@ import io.papermc.hangar.exceptions.HangarException;
|
||||
import io.papermc.hangar.model.Color;
|
||||
import io.papermc.hangar.model.DownloadType;
|
||||
import io.papermc.hangar.model.NamedPermission;
|
||||
import io.papermc.hangar.model.Platform;
|
||||
import io.papermc.hangar.model.Visibility;
|
||||
import io.papermc.hangar.model.generated.Dependency;
|
||||
import io.papermc.hangar.model.generated.ReviewState;
|
||||
import io.papermc.hangar.model.viewhelpers.ProjectData;
|
||||
import io.papermc.hangar.model.viewhelpers.ScopedProjectData;
|
||||
@ -31,6 +33,7 @@ import io.papermc.hangar.service.DownloadsService;
|
||||
import io.papermc.hangar.service.StatsService;
|
||||
import io.papermc.hangar.service.UserActionLogService;
|
||||
import io.papermc.hangar.service.VersionService;
|
||||
import io.papermc.hangar.service.plugindata.PluginFileWithData;
|
||||
import io.papermc.hangar.service.pluginupload.PendingVersion;
|
||||
import io.papermc.hangar.service.pluginupload.PluginUploadService;
|
||||
import io.papermc.hangar.service.pluginupload.ProjectFiles;
|
||||
@ -70,6 +73,7 @@ import org.springframework.web.util.WebUtils;
|
||||
import javax.servlet.http.Cookie;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.net.URI;
|
||||
import java.nio.file.Path;
|
||||
import java.time.OffsetDateTime;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
@ -77,6 +81,7 @@ import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
@Controller
|
||||
public class VersionsController extends HangarController {
|
||||
@ -147,6 +152,9 @@ public class VersionsController extends HangarController {
|
||||
public Object downloadJarById(@PathVariable String pluginId, @PathVariable String name, @RequestParam Optional<String> token) {
|
||||
ProjectsTable project = projectsTable.get();
|
||||
ProjectVersionsTable pvt = projectVersionsTable.get();
|
||||
if (pvt.isExternal()) {
|
||||
throw new ResponseStatusException(HttpStatus.NOT_FOUND, "No jar for this version found");
|
||||
}
|
||||
if (token.isPresent()) {
|
||||
confirmDownload0(DownloadType.JAR_FILE, token);
|
||||
return sendJar(project, pvt, token.get(), true);
|
||||
@ -217,6 +225,38 @@ public class VersionsController extends HangarController {
|
||||
return _showCreator(author, slug, pendingVersion);
|
||||
}
|
||||
|
||||
private final Pattern URL_PATTERN = Pattern.compile("^https?://[^\\s$.?#].[^\\s]*$");
|
||||
|
||||
@ProjectPermission(NamedPermission.CREATE_VERSION)
|
||||
@UserLock(route = Routes.PROJECTS_SHOW, args = "{#author, #slug}")
|
||||
@Secured("ROLE_USER")
|
||||
@PostMapping(value = "/{author}/{slug}/versions/new/create", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
|
||||
public ModelAndView create(@PathVariable String author, @PathVariable String slug, @RequestParam String externalUrl) {
|
||||
ProjectData projData = projectData.get();
|
||||
if (!URL_PATTERN.matcher(externalUrl).matches()) { // TODO check list of allowed hosts
|
||||
ModelAndView mav = _showCreator(author, slug, null);
|
||||
return fillModel(AlertUtil.showAlert(mav, AlertType.ERROR, "error.invalidUrl"));
|
||||
}
|
||||
|
||||
ProjectChannelsTable channel = channelService.getFirstChannel(projData.getProject());
|
||||
PendingVersion pendingVersion = new PendingVersion(
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
projData.getProject().getId(),
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
projData.getProjectOwner().getId(),
|
||||
channel.getName(),
|
||||
channel.getColor(),
|
||||
null,
|
||||
externalUrl,
|
||||
false
|
||||
);
|
||||
return _showCreator(author, slug, pendingVersion);
|
||||
}
|
||||
|
||||
@ProjectPermission(NamedPermission.CREATE_VERSION)
|
||||
@UserLock(route = Routes.PROJECTS_SHOW, args = "{#author, #slug}")
|
||||
@Secured("ROLE_USER")
|
||||
@ -274,10 +314,13 @@ public class VersionsController extends HangarController {
|
||||
@ProjectPermission(NamedPermission.CREATE_VERSION)
|
||||
@UserLock(route = Routes.PROJECTS_SHOW, args = "{#author, #slug}")
|
||||
@Secured("ROLE_USER")
|
||||
@PostMapping(value = "/{author}/{slug}/versions/{version:.+}", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
|
||||
@PostMapping(value = "/{author}/{slug}/versions/publish", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
|
||||
public ModelAndView publish(@PathVariable String author,
|
||||
@PathVariable String slug,
|
||||
@PathVariable("version") String versionName,
|
||||
@RequestParam String versionString,
|
||||
@RequestParam String externalUrl,
|
||||
@RequestParam Platform platform,
|
||||
@RequestParam(required = false) String versionDescription,
|
||||
@RequestParam(defaultValue = "false") boolean unstable,
|
||||
@RequestParam(defaultValue = "false") boolean recommended,
|
||||
@RequestParam("channel-input") String channelInput,
|
||||
@ -287,14 +330,35 @@ public class VersionsController extends HangarController {
|
||||
@RequestParam(required = false) String content,
|
||||
@RequestParam List<String> versions,
|
||||
RedirectAttributes attributes) {
|
||||
ProjectsTable project = projectsTable.get();
|
||||
PendingVersion pendingVersion = new PendingVersion(
|
||||
versionString,
|
||||
List.of(new Dependency(platform.getDependencyId(), String.join(",", versions), true)),
|
||||
versionDescription,
|
||||
project.getId(),
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
project.getOwnerId(),
|
||||
channelInput,
|
||||
channelColorInput,
|
||||
null,
|
||||
externalUrl,
|
||||
forumPost
|
||||
);
|
||||
return _publish(author, slug, versionString, unstable, recommended, channelInput, channelColorInput, versions, forumPost, nonReviewed,content, pendingVersion, platform, attributes);
|
||||
}
|
||||
|
||||
private ModelAndView _publish(String author, String slug, String versionName, boolean unstable, boolean recommended, String channelInput, Color channelColorInput, List<String> versions, boolean forumPost, boolean isNonReviewed, String content, PendingVersion pendingVersion, Platform platform, RedirectAttributes attributes) {
|
||||
ProjectData projData = projectData.get();
|
||||
Color channelColor = channelColorInput == null ? hangarConfig.channels.getColorDefault() : channelColorInput;
|
||||
PendingVersion pendingVersion = cacheManager.getCache(CacheConfig.PENDING_VERSION_CACHE).get(projData.getProject().getId() + "/" + versionName, PendingVersion.class);
|
||||
|
||||
if (pendingVersion == null) {
|
||||
AlertUtil.showAlert(attributes, AlertUtil.AlertType.ERROR, "error.plugin.timeout");
|
||||
return Routes.VERSIONS_SHOW_CREATOR.getRedirect(author, slug);
|
||||
}
|
||||
if (versions.stream().anyMatch(s -> !pendingVersion.getPlugin().getPlatform().getPossibleVersions().contains(s))) {
|
||||
|
||||
if (versions.stream().anyMatch(s -> !platform.getPossibleVersions().contains(s))) {
|
||||
AlertUtil.showAlert(attributes, AlertType.ERROR, "error.plugin.invalidVersion");
|
||||
return Routes.VERSIONS_SHOW_CREATOR.getRedirect(author, slug);
|
||||
}
|
||||
@ -316,7 +380,7 @@ public class VersionsController extends HangarController {
|
||||
AlertUtil.showAlert(attributes, AlertUtil.AlertType.ERROR, alertMsg, alertArgs);
|
||||
return Routes.VERSIONS_SHOW_CREATOR.getRedirect(author, slug);
|
||||
}
|
||||
channel = channelService.addProjectChannel(projData.getProject().getId(), channelInput.trim(), channelColor);
|
||||
channel = channelService.addProjectChannel(projData.getProject().getId(), channelInput.trim(), channelColor, isNonReviewed);
|
||||
} else {
|
||||
channel = channelOptional.get();
|
||||
}
|
||||
@ -326,7 +390,8 @@ public class VersionsController extends HangarController {
|
||||
channel.getColor(),
|
||||
forumPost,
|
||||
content,
|
||||
versions
|
||||
versions,
|
||||
platform
|
||||
);
|
||||
|
||||
if (versionService.exists(newPendingVersion)) {
|
||||
@ -354,6 +419,42 @@ public class VersionsController extends HangarController {
|
||||
userActionLogService.version(request, LoggedActionType.VERSION_UPLOADED.with(VersionContext.of(projData.getProject().getId(), version.getId())), "published", "");
|
||||
|
||||
return Routes.VERSIONS_SHOW.getRedirect(author, slug, versionName);
|
||||
|
||||
}
|
||||
|
||||
@ProjectPermission(NamedPermission.CREATE_VERSION)
|
||||
@UserLock(route = Routes.PROJECTS_SHOW, args = "{#author, #slug}")
|
||||
@Secured("ROLE_USER")
|
||||
@PostMapping(value = "/{author}/{slug}/versions/{version:.+}", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
|
||||
public ModelAndView publish(@PathVariable String author,
|
||||
@PathVariable String slug,
|
||||
@PathVariable("version") String versionName,
|
||||
@RequestParam(defaultValue = "false") boolean unstable,
|
||||
@RequestParam(defaultValue = "false") boolean recommended,
|
||||
@RequestParam("channel-input") String channelInput,
|
||||
@RequestParam(value = "channel-color-input", required = false) Color channelColorInput,
|
||||
@RequestParam(value = "non-reviewed", defaultValue = "false") boolean nonReviewed,
|
||||
@RequestParam(value = "forum-post", defaultValue = "false") boolean forumPost,
|
||||
@RequestParam(required = false) String content,
|
||||
@RequestParam List<String> versions,
|
||||
RedirectAttributes attributes) {
|
||||
ProjectsTable project = projectsTable.get();
|
||||
PendingVersion pendingVersion = cacheManager.getCache(CacheConfig.PENDING_VERSION_CACHE).get(project.getId() + "/" + versionName, PendingVersion.class);
|
||||
return _publish(author,
|
||||
slug,
|
||||
versionName,
|
||||
unstable,
|
||||
recommended,
|
||||
channelInput,
|
||||
channelColorInput,
|
||||
versions,
|
||||
forumPost,
|
||||
nonReviewed,
|
||||
content,
|
||||
pendingVersion,
|
||||
Optional.ofNullable(pendingVersion).map(PendingVersion::getPlugin).map(PluginFileWithData::getPlatform).orElse(null),
|
||||
attributes
|
||||
);
|
||||
}
|
||||
|
||||
@GetMapping("/{author}/{slug}/versions/{version:.*}")
|
||||
@ -400,7 +501,7 @@ public class VersionsController extends HangarController {
|
||||
}
|
||||
|
||||
@GetMapping("/{author}/{slug}/versions/{version}/confirm")
|
||||
public Object showDownloadConfirm(@PathVariable String author, @PathVariable String slug, @PathVariable String version, @RequestParam(defaultValue = "0") DownloadType downloadType, @RequestParam Optional<Boolean> api, @RequestParam(required = false) String dummy) {
|
||||
public Object showDownloadConfirm(@PathVariable String author, @PathVariable String slug, @PathVariable String version, @RequestParam(defaultValue = "0") DownloadType downloadType, @RequestParam(defaultValue = "false") boolean api, @RequestParam(required = false) String dummy) {
|
||||
ProjectVersionsTable versionsTable = projectVersionsTable.get();
|
||||
ProjectsTable project = projectsTable.get();
|
||||
if (versionsTable.getReviewState() == ReviewState.REVIEWED) {
|
||||
@ -424,15 +525,16 @@ public class VersionsController extends HangarController {
|
||||
}
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.set(HttpHeaders.CONTENT_DISPOSITION, "inline; filename=\"README.txt\"");
|
||||
if (api.orElse(false)) {
|
||||
if (api) {
|
||||
removeAddWarnings(address, expiration, token);
|
||||
headers.setContentType(MediaType.APPLICATION_JSON);
|
||||
ObjectNode objectNode = mapper.createObjectNode();
|
||||
objectNode.put("message", apiMsg);
|
||||
objectNode.put("post", Routes.VERSIONS_CONFIRM_DOWNLOAD.getRouteUrl(author, slug, version, downloadType.ordinal() + "", token, null));
|
||||
objectNode.put("url", Routes.VERSIONS_DOWNLOAD_JAR_BY_ID.getRouteUrl(project.getPluginId(), versionsTable.getVersionString(), token));
|
||||
objectNode.put("curl", curlInstruction);
|
||||
objectNode.put("token", token);
|
||||
String downloadUrl = versionsTable.getExternalUrl() != null ? versionsTable.getExternalUrl() : Routes.VERSIONS_DOWNLOAD_JAR_BY_ID.getRouteUrl(project.getPluginId(), versionsTable.getVersionString(), token);
|
||||
ObjectNode objectNode = mapper.createObjectNode()
|
||||
.put("message", apiMsg)
|
||||
.put("post", Routes.VERSIONS_CONFIRM_DOWNLOAD.getRouteUrl(author, slug, version, downloadType.ordinal() + "", token, null))
|
||||
.put("url", downloadUrl)
|
||||
.put("curl", curlInstruction)
|
||||
.put("token", token);
|
||||
return new ResponseEntity<>(objectNode.toPrettyString(), headers, HttpStatus.MULTIPLE_CHOICES);
|
||||
} else {
|
||||
Optional<String> userAgent = Optional.ofNullable(request.getHeader(HttpHeaders.USER_AGENT)).map(String::toLowerCase);
|
||||
@ -467,8 +569,9 @@ public class VersionsController extends HangarController {
|
||||
|
||||
@PostMapping(value = "/{author}/{slug}/versions/{version}/confirm", produces = MediaType.APPLICATION_OCTET_STREAM_VALUE)
|
||||
@ResponseBody
|
||||
public Object confirmDownload(@PathVariable String author, @PathVariable String slug, @PathVariable String version, @RequestParam(defaultValue = "0") DownloadType downloadType, @RequestParam Optional<String> token, @RequestParam(required = false) String dummy) {
|
||||
if (projectVersionsTable.get().getReviewState() == ReviewState.REVIEWED) {
|
||||
public ModelAndView confirmDownload(@PathVariable String author, @PathVariable String slug, @PathVariable String version, @RequestParam(defaultValue = "0") DownloadType downloadType, @RequestParam Optional<String> token, @RequestParam(required = false) String dummy) {
|
||||
ProjectVersionsTable pvt = projectVersionsTable.get();
|
||||
if (pvt.getReviewState() == ReviewState.REVIEWED) {
|
||||
return Routes.PROJECTS_SHOW.getRedirect(author, slug);
|
||||
}
|
||||
ProjectVersionUnsafeDownloadsTable download;
|
||||
@ -482,6 +585,8 @@ public class VersionsController extends HangarController {
|
||||
return Routes.VERSIONS_DOWNLOAD.getRedirect(author, slug, version, token.orElse(null), "");
|
||||
case JAR_FILE:
|
||||
return Routes.VERSIONS_DOWNLOAD_JAR.getRedirect(author, slug, version, token.orElse(null), "");
|
||||
case EXTERNAL_DOWNLOAD:
|
||||
return new ModelAndView("redirect:" + pvt.getExternalUrl());
|
||||
default:
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
@ -539,15 +644,16 @@ public class VersionsController extends HangarController {
|
||||
}
|
||||
|
||||
private Object sendVersion(ProjectsTable project, ProjectVersionsTable version, String token, boolean confirm) {
|
||||
boolean isSafeExternalHost = version.isExternal() && hangarConfig.security.getSafeDownloadHosts().contains(URI.create(version.getExternalUrl()).getHost());
|
||||
boolean passed = checkConfirmation(version, token);
|
||||
if (passed || confirm) {
|
||||
if (passed || confirm || isSafeExternalHost) {
|
||||
return _sendVersion(project, version);
|
||||
} else {
|
||||
return Routes.VERSIONS_SHOW_DOWNLOAD_CONFIRM.getRedirect(
|
||||
project.getOwnerName(),
|
||||
project.getSlug(),
|
||||
version.getVersionString(),
|
||||
DownloadType.UPLOADED_FILE.ordinal() + "",
|
||||
(version.getExternalUrl() != null ? DownloadType.EXTERNAL_DOWNLOAD.ordinal() : DownloadType.UPLOADED_FILE.ordinal()) + "",
|
||||
false + "",
|
||||
"dummy"
|
||||
);
|
||||
@ -566,7 +672,7 @@ public class VersionsController extends HangarController {
|
||||
response.addCookie(newCookie);
|
||||
return true;
|
||||
} else {
|
||||
ProjectVersionDownloadWarningsTable warning = downloadWarningDao.get().find(token, version.getId(), RequestUtil.getRemoteInetAddress(request));
|
||||
ProjectVersionDownloadWarningsTable warning = downloadWarningDao.get().findConfirmedWarning(token, version.getId(), RequestUtil.getRemoteInetAddress(request));
|
||||
|
||||
if (warning == null) {
|
||||
return false;
|
||||
@ -580,12 +686,14 @@ public class VersionsController extends HangarController {
|
||||
}
|
||||
}
|
||||
|
||||
private FileSystemResource _sendVersion(ProjectsTable project, ProjectVersionsTable version) {
|
||||
|
||||
private Object _sendVersion(ProjectsTable project, ProjectVersionsTable version) {
|
||||
statsService.addVersionDownloaded(version);
|
||||
if (version.getExternalUrl() != null) {
|
||||
return new ModelAndView("redirect:" + version.getExternalUrl());
|
||||
}
|
||||
Path path = projectFiles.getVersionDir(project.getOwnerName(), project.getName(), version.getVersionString()).resolve(version.getFileName());
|
||||
response.setHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + version.getFileName() + "\"");
|
||||
|
||||
statsService.addVersionDownloaded(version);
|
||||
return new FileSystemResource(path);
|
||||
}
|
||||
|
||||
@ -615,7 +723,7 @@ public class VersionsController extends HangarController {
|
||||
}
|
||||
|
||||
private Object sendJar(ProjectsTable project, ProjectVersionsTable version, String token, boolean api) {
|
||||
if (project.getVisibility() == Visibility.SOFTDELETE) {
|
||||
if (project.getVisibility() == Visibility.SOFTDELETE || version.isExternal()) {
|
||||
throw new ResponseStatusException(HttpStatus.NOT_FOUND);
|
||||
} else {
|
||||
boolean passed = checkConfirmation(version, token);
|
||||
|
@ -22,7 +22,7 @@ import java.util.Map;
|
||||
@RegisterBeanMapper(ProjectChannelsTable.class)
|
||||
public interface ProjectChannelDao {
|
||||
|
||||
@SqlUpdate("insert into project_channels (created_at, name, color, project_id) values (:now, :name, :color, :projectId)")
|
||||
@SqlUpdate("insert into project_channels (created_at, name, color, project_id, is_non_reviewed) values (:now, :name, :color, :projectId, :isNonReviewed)")
|
||||
@Timestamped
|
||||
@GetGeneratedKeys
|
||||
ProjectChannelsTable insert(@BindBean ProjectChannelsTable projectChannel);
|
||||
|
@ -24,12 +24,12 @@ public interface ProjectVersionDao {
|
||||
@Timestamped
|
||||
@GetGeneratedKeys
|
||||
@SqlUpdate("INSERT INTO project_versions " +
|
||||
"(created_at, version_string, dependencies, description, project_id, channel_id, file_size, hash, file_name, author_id, create_forum_post) VALUES " +
|
||||
"(:now, :versionString, :dependencies, :description, :projectId, :channelId, :fileSize, :hash, :fileName, :authorId, :createForumPost)")
|
||||
"(created_at, version_string, dependencies, description, project_id, channel_id, file_size, hash, file_name, author_id, create_forum_post, external_url) VALUES " +
|
||||
"(:now, :versionString, :dependencies, :description, :projectId, :channelId, :fileSize, :hash, :fileName, :authorId, :createForumPost, :externalUrl)")
|
||||
ProjectVersionsTable insert(@BindBean ProjectVersionsTable projectVersionsTable);
|
||||
|
||||
@SqlUpdate("UPDATE project_versions SET visibility = :visibility, reviewer_id = :reviewerId, approved_at = :approvedAt, description = :description, " +
|
||||
"review_state = :reviewState " +
|
||||
"review_state = :reviewState, external_url = :externalUrl " +
|
||||
"WHERE id = :id")
|
||||
void update(@BindBean ProjectVersionsTable projectVersionsTable);
|
||||
|
||||
|
@ -25,7 +25,7 @@ public interface ProjectVersionDownloadWarningDao {
|
||||
" AND version_id = :versionId" +
|
||||
" AND address = :address" +
|
||||
" AND is_confirmed IS TRUE")
|
||||
ProjectVersionDownloadWarningsTable find(String token, long versionId, InetAddress address);
|
||||
ProjectVersionDownloadWarningsTable findConfirmedWarning(String token, long versionId, InetAddress address);
|
||||
|
||||
@SqlQuery("SELECT pvdw.* FROM project_version_download_warnings pvdw " +
|
||||
"WHERE pvdw.address = :address" +
|
||||
|
@ -19,11 +19,11 @@ public class ProjectChannelsTable {
|
||||
//
|
||||
}
|
||||
|
||||
public ProjectChannelsTable(String name, Color color, long projectId) {
|
||||
public ProjectChannelsTable(String name, Color color, long projectId, boolean isNonReviewed) {
|
||||
this.name = name;
|
||||
this.color = color;
|
||||
this.projectId = projectId;
|
||||
this.isNonReviewed = false;
|
||||
this.isNonReviewed = isNonReviewed;
|
||||
}
|
||||
|
||||
public long getId() {
|
||||
|
@ -3,6 +3,7 @@ package io.papermc.hangar.db.model;
|
||||
|
||||
import io.papermc.hangar.model.Visibility;
|
||||
import io.papermc.hangar.model.generated.ReviewState;
|
||||
import org.jdbi.v3.core.annotation.Unmappable;
|
||||
import org.jdbi.v3.core.enums.EnumByOrdinal;
|
||||
|
||||
import java.time.OffsetDateTime;
|
||||
@ -17,7 +18,7 @@ public class ProjectVersionsTable {
|
||||
private String description;
|
||||
private long projectId;
|
||||
private long channelId;
|
||||
private long fileSize;
|
||||
private Long fileSize;
|
||||
private String hash;
|
||||
private String fileName;
|
||||
private Long reviewerId;
|
||||
@ -27,8 +28,9 @@ public class ProjectVersionsTable {
|
||||
private ReviewState reviewState = ReviewState.UNREVIEWED;
|
||||
private boolean createForumPost = true;
|
||||
private Long postId;
|
||||
private String externalUrl;
|
||||
|
||||
public ProjectVersionsTable(String versionString, List<String> dependencies, String description, long projectId, long channelId, long fileSize, String hash, String fileName, long authorId, boolean createForumPost) {
|
||||
public ProjectVersionsTable(String versionString, List<String> dependencies, String description, long projectId, long channelId, Long fileSize, String hash, String fileName, long authorId, boolean createForumPost, String externalUrl) {
|
||||
this.versionString = versionString;
|
||||
this.dependencies = dependencies;
|
||||
this.description = description;
|
||||
@ -39,6 +41,7 @@ public class ProjectVersionsTable {
|
||||
this.fileName = fileName;
|
||||
this.authorId = authorId;
|
||||
this.createForumPost = createForumPost;
|
||||
this.externalUrl = externalUrl;
|
||||
}
|
||||
|
||||
public ProjectVersionsTable() { }
|
||||
@ -106,11 +109,11 @@ public class ProjectVersionsTable {
|
||||
}
|
||||
|
||||
|
||||
public long getFileSize() {
|
||||
public Long getFileSize() {
|
||||
return fileSize;
|
||||
}
|
||||
|
||||
public void setFileSize(long fileSize) {
|
||||
public void setFileSize(Long fileSize) {
|
||||
this.fileSize = fileSize;
|
||||
}
|
||||
|
||||
@ -199,6 +202,20 @@ public class ProjectVersionsTable {
|
||||
this.postId = postId;
|
||||
}
|
||||
|
||||
|
||||
public String getExternalUrl() {
|
||||
return externalUrl;
|
||||
}
|
||||
|
||||
public void setExternalUrl(String externalUrl) {
|
||||
this.externalUrl = externalUrl;
|
||||
}
|
||||
|
||||
@Unmappable
|
||||
public boolean isExternal() {
|
||||
return this.externalUrl != null && this.fileName == null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ProjectVersionsTable{" +
|
||||
|
@ -10,5 +10,10 @@ public enum DownloadType {
|
||||
/**
|
||||
* The download was for just the JAR file of the upload.
|
||||
*/
|
||||
JAR_FILE
|
||||
JAR_FILE,
|
||||
|
||||
/**
|
||||
* The download is on an external site.
|
||||
*/
|
||||
EXTERNAL_DOWNLOAD
|
||||
}
|
||||
|
@ -3,8 +3,8 @@ package io.papermc.hangar.model;
|
||||
public enum TagColor { // remember, once we push to production, the order of these enums cannot change
|
||||
|
||||
PAPER("#F7CF0D", "#333333"),
|
||||
WATERFALL("#F7CF0D", "#FFFFFF"),
|
||||
VELOCITY("#039BE5","#FFFFFF"),
|
||||
WATERFALL("#F7CF0D", "#333333"),
|
||||
VELOCITY("#039BE5","#333333"),
|
||||
|
||||
UNSTABLE("#FFDAB9", "#333333");
|
||||
|
||||
|
@ -20,16 +20,17 @@ public class PendingVersion {
|
||||
private final List<Dependency> dependencies;
|
||||
private final String description;
|
||||
private final long projectId;
|
||||
private final long fileSize;
|
||||
private final Long fileSize;
|
||||
private final String hash;
|
||||
private final String fileName;
|
||||
private final long authorId;
|
||||
private final String channelName;
|
||||
private final Color channelColor;
|
||||
private final PluginFileWithData plugin;
|
||||
private final String externalUrl;
|
||||
private final boolean createForumPost;
|
||||
|
||||
public PendingVersion(String versionString, List<Dependency> dependencies, String description, long projectId, long fileSize, String hash, String fileName, long authorId, String channelName, Color channelColor, PluginFileWithData plugin, boolean createForumPost) {
|
||||
public PendingVersion(String versionString, List<Dependency> dependencies, String description, long projectId, Long fileSize, String hash, String fileName, long authorId, String channelName, Color channelColor, PluginFileWithData plugin, String externalUrl, boolean createForumPost) {
|
||||
this.versionString = versionString;
|
||||
this.dependencies = dependencies;
|
||||
this.description = description;
|
||||
@ -41,6 +42,7 @@ public class PendingVersion {
|
||||
this.channelName = channelName;
|
||||
this.channelColor = channelColor;
|
||||
this.plugin = plugin;
|
||||
this.externalUrl = externalUrl;
|
||||
this.createForumPost = createForumPost;
|
||||
}
|
||||
|
||||
@ -60,7 +62,7 @@ public class PendingVersion {
|
||||
return projectId;
|
||||
}
|
||||
|
||||
public long getFileSize() {
|
||||
public Long getFileSize() {
|
||||
return fileSize;
|
||||
}
|
||||
|
||||
@ -88,6 +90,10 @@ public class PendingVersion {
|
||||
return plugin;
|
||||
}
|
||||
|
||||
public String getExternalUrl() {
|
||||
return externalUrl;
|
||||
}
|
||||
|
||||
public boolean isCreateForumPost() {
|
||||
return createForumPost;
|
||||
}
|
||||
@ -96,8 +102,8 @@ public class PendingVersion {
|
||||
return Platform.getGhostTags(-1L, dependencies);
|
||||
}
|
||||
|
||||
public PendingVersion copy(String channelName, Color channelColor, boolean createForumPost, String description, List<String> versions) {
|
||||
Optional<Dependency> optional = dependencies.stream().filter(d -> d.getPluginId().equals(plugin.getPlatform().getDependencyId())).findAny();
|
||||
public PendingVersion copy(String channelName, Color channelColor, boolean createForumPost, String description, List<String> versions, Platform platform) {
|
||||
Optional<Dependency> optional = dependencies.stream().filter(d -> d.getPluginId().equals(platform.getDependencyId())).findAny();
|
||||
optional.ifPresent(dependency -> dependency.setVersion(String.join(",", versions))); // Should always be present, if not, there are other problems
|
||||
return new PendingVersion(
|
||||
versionString,
|
||||
@ -111,7 +117,7 @@ public class PendingVersion {
|
||||
channelName,
|
||||
channelColor,
|
||||
plugin,
|
||||
createForumPost
|
||||
externalUrl, createForumPost
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -80,6 +80,7 @@ public class PluginUploadService {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public PendingVersion processSubsequentPluginUpload(MultipartFile file, UsersTable owner, ProjectsTable project) throws HangarException {
|
||||
PluginFileWithData plugin = processPluginUpload(file, owner);
|
||||
// TODO not sure what to do w/plugin id, that isn't stored in the metadata for the file
|
||||
@ -127,6 +128,7 @@ public class PluginUploadService {
|
||||
channelName,
|
||||
config.getChannels().getColorDefault(),
|
||||
plugin,
|
||||
null,
|
||||
forumSync
|
||||
);
|
||||
}
|
||||
|
@ -21,12 +21,12 @@ public class ChannelFactory {
|
||||
this.channelDao = channelDao;
|
||||
}
|
||||
|
||||
public ProjectChannelsTable createChannel(long projectId, String channelName, Color color) {
|
||||
public ProjectChannelsTable createChannel(long projectId, String channelName, Color color, boolean isNonReviewed) {
|
||||
if (!hangarConfig.channels.isValidChannelName(channelName)) {
|
||||
throw new HangarException("error.channel.invalidName", channelName);
|
||||
}
|
||||
|
||||
ProjectChannelsTable channel = new ProjectChannelsTable(channelName, color, projectId);
|
||||
ProjectChannelsTable channel = new ProjectChannelsTable(channelName, color, projectId, isNonReviewed);
|
||||
channelDao.get().insert(channel);
|
||||
return channel;
|
||||
}
|
||||
|
@ -52,10 +52,10 @@ public class ChannelService {
|
||||
return channelDao.get().getChannelsWithVersionCount(projectId);
|
||||
}
|
||||
|
||||
public ProjectChannelsTable addProjectChannel(long projectId, String channelName, Color color) {
|
||||
public ProjectChannelsTable addProjectChannel(long projectId, String channelName, Color color, boolean isNonReviewed) {
|
||||
InvalidChannelCreationReason reason = channelDao.get().validateChannelCreation(projectId, channelName, color.getValue(), hangarConfig.projects.getMaxChannels());
|
||||
checkInvalidChannelCreationReason(reason);
|
||||
return channelFactory.createChannel(projectId, channelName, color);
|
||||
return channelFactory.createChannel(projectId, channelName, color, isNonReviewed);
|
||||
}
|
||||
|
||||
public void updateProjectChannel(long projectId, String oldChannel, String channelName, Color color) {
|
||||
|
@ -93,7 +93,7 @@ public class ProjectFactory {
|
||||
String slug = StringUtils.slugify(name);
|
||||
ProjectsTable projectsTable = new ProjectsTable(pluginId, name, slug, ownerUser.getName(), ownerUser.getUserId(), category, description, Visibility.NEW);
|
||||
|
||||
ProjectChannelsTable channelsTable = new ProjectChannelsTable(hangarConfig.channels.getNameDefault(), hangarConfig.channels.getColorDefault(), -1);
|
||||
ProjectChannelsTable channelsTable = new ProjectChannelsTable(hangarConfig.channels.getNameDefault(), hangarConfig.channels.getColorDefault(), -1, false);
|
||||
|
||||
String content = "# " + name + "\n\n" + hangarConfig.pages.home.getMessage();
|
||||
ProjectPagesTable pagesTable = new ProjectPage( -1, hangarConfig.pages.home.getName(), StringUtils.slugify(hangarConfig.pages.home.getName()), content, false, null);
|
||||
@ -163,10 +163,13 @@ public class ProjectFactory {
|
||||
pendingVersion.getHash(),
|
||||
pendingVersion.getFileName(),
|
||||
pendingVersion.getAuthorId(),
|
||||
pendingVersion.isCreateForumPost()
|
||||
pendingVersion.isCreateForumPost(),
|
||||
pendingVersion.getExternalUrl()
|
||||
));
|
||||
if (pendingVersion.getPlugin() != null) {
|
||||
pendingVersion.getPlugin().getData().createTags(version.getId(), versionService); // TODO not sure what this is for
|
||||
}
|
||||
|
||||
pendingVersion.getPlugin().getData().createTags(version.getId(), versionService); // TODO not sure what this is for
|
||||
Platform.createPlatformTags(versionService, version.getId(), Dependency.from(version.getDependencies()));
|
||||
|
||||
List<UsersTable> watchers = projectService.getProjectWatchers(project.getProject().getId(), 0, null);
|
||||
@ -178,11 +181,13 @@ public class ProjectFactory {
|
||||
new String[]{"notification.project.newVersion", project.getProject().getName(), version.getVersionString()},
|
||||
project.getNamespace() + "/versions/" + version.getVersionString()
|
||||
));
|
||||
try {
|
||||
uploadPlugin(project, pendingVersion.getPlugin(), version);
|
||||
} catch (IOException e) {
|
||||
versionService.deleteVersion(version.getId());
|
||||
throw new HangarException("error.version.fileIOError");
|
||||
if (pendingVersion.getPlugin() != null) {
|
||||
try {
|
||||
uploadPlugin(project, pendingVersion.getPlugin(), version);
|
||||
} catch (IOException e) {
|
||||
versionService.deleteVersion(version.getId());
|
||||
throw new HangarException("error.version.fileIOError");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -10,138 +10,134 @@ import static java.util.List.of;
|
||||
|
||||
public enum Routes {
|
||||
|
||||
SHOW_PROJECT_VISIBILITY("showProjectVisibility", "/admin/approval/projects", of(), of()),
|
||||
ACTOR_COUNT("actorCount", "/pantopticon/actor-count", of(), of("timeoutMs")),
|
||||
ACTOR_TREE("actorTree", "/pantopticon/actor-tree", of(), of("timeoutMs")),
|
||||
UPDATE_USER("updateUser", "/admin/user/{user}/update", of("user"), of()),
|
||||
SHOW_QUEUE("showQueue", "/admin/approval/versions", of(), of()),
|
||||
SHOW_LOG("showLog", "/admin/log", of(), of("page", "userFilter", "projectFilter", "versionFilter", "pageFilter", "actionFilter", "subjectFilter")),
|
||||
SHOW_PLATFORM_VERSIONS("showPlatformVersions", "/admin/versions", of(), of()),
|
||||
UPDATE_PLATFORM_VERSIONS("updatePlatformVersions", "/admin/versions/{platform}", of("platform"), of()),
|
||||
REMOVE_TRAIL("removeTrail", "/{path}/", of("path"), of()),
|
||||
FAVICON_REDIRECT("faviconRedirect", "/favicon.ico", of(), of()),
|
||||
SHOW_FLAGS("showFlags", "/admin/flags", of(), of()),
|
||||
SITEMAP_INDEX("sitemapIndex", "/sitemap.xml", of(), of()),
|
||||
GLOBAL_SITEMAP("globalSitemap", "/global-sitemap.xml", of(), of()),
|
||||
SHOW_STATS("showStats", "/admin/stats", of(), of("from", "to")),
|
||||
LINK_OUT("linkOut", "/linkout", of(), of("remoteUrl")),
|
||||
SHOW_HEALTH("showHealth", "/admin/health", of(), of()),
|
||||
SHOW_HOME("showHome", "/", of(), of()),
|
||||
ROBOTS("robots", "/robots.txt", of(), of()),
|
||||
SET_FLAG_RESOLVED("setFlagResolved", "/admin/flags/{id}/resolve/{resolved}", of("id", "resolved"), of()),
|
||||
SWAGGER("swagger", "/api", of(), of()),
|
||||
SHOW_ACTIVITIES("showActivities", "/admin/activities/{user}", of("user"), of()),
|
||||
USER_ADMIN("userAdmin", "/admin/user/{user}", of("user"), of()),
|
||||
JAVA_SCRIPT_ROUTES("javaScriptRoutes", "/javascriptRoutes", of(), of()),
|
||||
SHOW_PROJECT_VISIBILITY("showProjectVisibility", Paths.SHOW_PROJECT_VISIBILITY, of(), of()),
|
||||
ACTOR_COUNT("actorCount", Paths.ACTOR_COUNT, of(), of("timeoutMs")),
|
||||
ACTOR_TREE("actorTree", Paths.ACTOR_TREE, of(), of("timeoutMs")),
|
||||
UPDATE_USER("updateUser", Paths.UPDATE_USER, of("user"), of()),
|
||||
SHOW_QUEUE("showQueue", Paths.SHOW_QUEUE, of(), of()),
|
||||
SHOW_LOG("showLog", Paths.SHOW_LOG, of(), of("page", "userFilter", "projectFilter", "versionFilter", "pageFilter", "actionFilter", "subjectFilter")),
|
||||
SHOW_PLATFORM_VERSIONS("showPlatformVersions", Paths.SHOW_PLATFORM_VERSIONS, of(), of()),
|
||||
UPDATE_PLATFORM_VERSIONS("updatePlatformVersions", Paths.UPDATE_PLATFORM_VERSIONS, of("platform"), of()),
|
||||
REMOVE_TRAIL("removeTrail", Paths.REMOVE_TRAIL, of("path"), of()),
|
||||
FAVICON_REDIRECT("faviconRedirect", Paths.FAVICON_REDIRECT, of(), of()),
|
||||
SHOW_FLAGS("showFlags", Paths.SHOW_FLAGS, of(), of()),
|
||||
SITEMAP_INDEX("sitemapIndex", Paths.SITEMAP_INDEX, of(), of()),
|
||||
GLOBAL_SITEMAP("globalSitemap", Paths.GLOBAL_SITEMAP, of(), of()),
|
||||
SHOW_STATS("showStats", Paths.SHOW_STATS, of(), of("from", "to")),
|
||||
LINK_OUT("linkOut", Paths.LINK_OUT, of(), of("remoteUrl")),
|
||||
SHOW_HEALTH("showHealth", Paths.SHOW_HEALTH, of(), of()),
|
||||
SHOW_HOME("showHome", Paths.SHOW_HOME, of(), of()),
|
||||
ROBOTS("robots", Paths.ROBOTS, of(), of()),
|
||||
SET_FLAG_RESOLVED("setFlagResolved", Paths.SET_FLAG_RESOLVED, of("id", "resolved"), of()),
|
||||
SWAGGER("swagger", Paths.SWAGGER, of(), of()),
|
||||
SHOW_ACTIVITIES("showActivities", Paths.SHOW_ACTIVITIES, of("user"), of()),
|
||||
USER_ADMIN("userAdmin", Paths.USER_ADMIN, of("user"), of()),
|
||||
JAVA_SCRIPT_ROUTES("javaScriptRoutes", Paths.JAVA_SCRIPT_ROUTES, of(), of()),
|
||||
|
||||
PROJECTS_RENAME("projects.rename", "/{author}/{slug}/manage/rename", of("author", "slug"), of()),
|
||||
PROJECTS_SET_WATCHING("projects.setWatching", "/{author}/{slug}/watchers/{watching}", of("author", "slug", "watching"), of()),
|
||||
PROJECTS_SHOW_SETTINGS("projects.showSettings", "/{author}/{slug}/manage", of("author", "slug"), of()),
|
||||
PROJECTS_SET_INVITE_STATUS("projects.setInviteStatus", "/invite/{id}/{status}", of("id", "status"), of()),
|
||||
PROJECTS_TOGGLE_STARRED("projects.toggleStarred", "/{author}/{slug}/stars/toggle", of("author", "slug"), of()),
|
||||
PROJECTS_SHOW_CREATOR("projects.showCreator", "/new", of(), of()),
|
||||
PROJECTS_SHOW_STARGAZERS("projects.showStargazers", "/{author}/{slug}/stars", of("author", "slug"), of("page")),
|
||||
PROJECTS_SHOW_WATCHERS("projects.showWatchers", "/{author}/{slug}/watchers", of("author", "slug"), of("page")),
|
||||
PROJECTS_UPLOAD_ICON("projects.uploadIcon", "/{author}/{slug}/icon", of("author", "slug"), of()),
|
||||
PROJECTS_SHOW_ICON("projects.showIcon", "/{author}/{slug}/icon", of("author", "slug"), of()),
|
||||
PROJECTS_SEND_FOR_APPROVAL("projects.sendForApproval", "/{author}/{slug}/manage/sendforapproval", of("author", "slug"), of()),
|
||||
PROJECTS_SET_INVITE_STATUS_ON_BEHALF("projects.setInviteStatusOnBehalf", "/invite/{id}/{status}/{behalf}", of("id", "status", "behalf"), of()),
|
||||
PROJECTS_DELETE("projects.delete", "/{author}/{slug}/manage/hardDelete", of("author", "slug"), of()),
|
||||
PROJECTS_ADD_MESSAGE("projects.addMessage", "/{author}/{slug}/notes/addmessage", of("author", "slug"), of()),
|
||||
PROJECTS_SHOW_PENDING_ICON("projects.showPendingIcon", "/{author}/{slug}/icon/pending", of("author", "slug"), of()),
|
||||
PROJECTS_POST_DISCUSSION_REPLY("projects.postDiscussionReply", "/{author}/{slug}/discuss/reply", of("author", "slug"), of()),
|
||||
PROJECTS_SHOW("projects.show", "/{author}/{slug}", of("author", "slug"), of()),
|
||||
PROJECTS_SHOW_DISCUSSION("projects.showDiscussion", "/{author}/{slug}/discuss", of("author", "slug"), of()),
|
||||
PROJECTS_SOFT_DELETE("projects.softDelete", "/{author}/{slug}/manage/delete", of("author", "slug"), of()),
|
||||
PROJECTS_SHOW_FLAGS("projects.showFlags", "/{author}/{slug}/flags", of("author", "slug"), of()),
|
||||
PROJECTS_FLAG("projects.flag", "/{author}/{slug}/flag", of("author", "slug"), of()),
|
||||
PROJECTS_CREATE_PROJECT("projects.createProject", "/new", of(), of()),
|
||||
PROJECTS_RESET_ICON("projects.resetIcon", "/{author}/{slug}/icon/reset", of("author", "slug"), of()),
|
||||
PROJECTS_SAVE("projects.save", "/{author}/{slug}/manage/save", of("author", "slug"), of()),
|
||||
PROJECTS_SHOW_NOTES("projects.showNotes", "/{author}/{slug}/notes", of("author", "slug"), of()),
|
||||
PROJECTS_SET_VISIBLE("projects.setVisible", "/{author}/{slug}/visible/{visibility}", of("author", "slug", "visibility"), of()),
|
||||
PROJECTS_REMOVE_MEMBER("projects.removeMember", "/{author}/{slug}/manage/members/remove", of("author", "slug"), of()),
|
||||
|
||||
VERSIONS_RESTORE("versions.restore", "/{author}/{slug}/versions/{version}/restore", of("author", "slug", "version"), of()),
|
||||
VERSIONS_DOWNLOAD_RECOMMENDED_JAR("versions.downloadRecommendedJar", "/{author}/{slug}/versions/recommended/jar", of("author", "slug"), of("token")),
|
||||
VERSIONS_PUBLISH("versions.publish", "/{author}/{slug}/versions/{version}", of("author", "slug", "version"), of()),
|
||||
VERSIONS_SET_RECOMMENDED("versions.setRecommended", "/{author}/{slug}/versions/{version}/recommended", of("author", "slug", "version"), of()),
|
||||
VERSIONS_DOWNLOAD("versions.download", "/{author}/{slug}/versions/{version}/download", of("author", "slug", "version"), of("token", "confirm")),
|
||||
VERSIONS_SHOW_LOG("versions.showLog", "/{author}/{slug}/versionLog", of("author", "slug"), of("versionString")),
|
||||
VERSIONS_SHOW("versions.show", "/{author}/{slug}/versions/{version}", of("author", "slug", "version"), of()),
|
||||
VERSIONS_DOWNLOAD_JAR("versions.downloadJar", "/{author}/{slug}/versions/{version}/jar", of("author", "slug", "version"), of("token")),
|
||||
VERSIONS_APPROVE("versions.approve", "/{author}/{slug}/versions/{version}/approve", of("author", "slug", "version"), of()),
|
||||
VERSIONS_APPROVE_PARTIAL("versions.approvePartial", "/{author}/{slug}/versions/{version}/approvePartial", of("author", "slug", "version"), of()),
|
||||
VERSIONS_SAVE_DESCRIPTION("versions.saveDescription", "/{author}/{slug}/versions/{version}/save", of("author", "slug", "version"), of()),
|
||||
VERSIONS_DOWNLOAD_RECOMMENDED("versions.downloadRecommended", "/{author}/{slug}/versions/recommended/download", of("author", "slug"), of("token")),
|
||||
VERSIONS_SHOW_LIST("versions.showList", "/{author}/{slug}/versions", of("author", "slug"), of()),
|
||||
VERSIONS_DOWNLOAD_JAR_BY_ID("versions.downloadJarById", "/api/project/{pluginId}/versions/{name}/download", of("pluginId", "name"), of("token")),
|
||||
VERSIONS_DOWNLOAD_RECOMMENDED_JAR_BY_ID("versions.downloadRecommendedJarById", "/api/project/{pluginId}/versions/recommended/download", of("pluginId"), of("token")),
|
||||
VERSIONS_UPLOAD("versions.upload", "/{author}/{slug}/versions/new/upload", of("author", "slug"), of()),
|
||||
VERSIONS_SOFT_DELETE("versions.softDelete", "/{author}/{slug}/versions/{version}/delete", of("author", "slug", "version"), of()),
|
||||
VERSIONS_SHOW_DOWNLOAD_CONFIRM("versions.showDownloadConfirm", "/{author}/{slug}/versions/{version}/confirm", of("author", "slug", "version"), of("downloadType", "api", "dummy")),
|
||||
VERSIONS_SHOW_CREATOR("versions.showCreator", "/{author}/{slug}/versions/new", of("author", "slug"), of()),
|
||||
VERSIONS_DELETE("versions.delete", "/{author}/{slug}/versions/{version}/hardDelete", of("author", "slug", "version"), of()),
|
||||
VERSIONS_SHOW_CREATOR_WITH_META("versions.showCreatorWithMeta", "/{author}/{slug}/versions/new/{version}", of("author", "slug", "version"), of()),
|
||||
VERSIONS_CONFIRM_DOWNLOAD("versions.confirmDownload", "/{author}/{slug}/versions/{version}/confirm", of("author", "slug", "version"), of("downloadType", "token", "dummy")),
|
||||
|
||||
PAGES_SHOW_PREVIEW("pages.showPreview", "/pages/preview", of(), of()),
|
||||
PAGES_SAVE("pages.save", "/{author}/{slug}/pages/{page}/edit", of("author", "slug", "page"), of()),
|
||||
PAGES_SHOW_EDITOR("pages.showEditor", "/{author}/{slug}/pages/{page}/edit", of("author", "slug", "page"), of()),
|
||||
PAGES_SHOW("pages.show", "/{author}/{slug}/pages/{page}", of("author", "slug", "page"), of()),
|
||||
PAGES_DELETE("pages.delete", "/{author}/{slug}/pages/{page}/delete", of("author", "slug", "page"), of()),
|
||||
|
||||
USERS_SHOW_AUTHORS("users.showAuthors", "/authors", of(), of("sort", "page")),
|
||||
USERS_SAVE_TAGLINE("users.saveTagline", "/{user}/settings/tagline", of("user"), of()),
|
||||
USERS_SIGN_UP("users.signUp", "/signup", of(), of()),
|
||||
USERS_SHOW_NOTIFICATIONS("users.showNotifications", "/notifications", of(), of("notificationFilter", "inviteFilter")),
|
||||
USERS_SHOW_PROJECTS("users.showProjects", "/{user}", of("user"), of()),
|
||||
USERS_VERIFY("users.verify", "/verify", of(), of("returnPath")),
|
||||
USERS_MARK_NOTIFICATION_READ("users.markNotificationRead", "/notifications/read/{id}", of("id"), of()),
|
||||
USERS_LOGIN("users.login", "/login", of(), of("sso", "sig", "returnUrl")),
|
||||
USERS_SHOW_STAFF("users.showStaff", "/staff", of(), of("sort", "page")),
|
||||
USERS_SET_LOCKED("users.setLocked", "/{user}/settings/lock/{locked}", of("user", "locked"), of("sso", "sig")),
|
||||
USERS_MARK_PROMPT_READ("users.markPromptRead", "/prompts/read/{id}", of("id"), of()),
|
||||
USERS_LOGOUT("users.logout", "/logout", of(), of()),
|
||||
USERS_USER_SITEMAP("users.userSitemap", "/{user}/sitemap.xml", of("user"), of()),
|
||||
USERS_EDIT_API_KEYS("users.editApiKeys", "/{user}/settings/apiKeys", of("user"), of()),
|
||||
|
||||
ORG_UPDATE_MEMBERS("org.updateMembers", "/organizations/{organization}/settings/members", of("organization"), of()),
|
||||
ORG_UPDATE_AVATAR("org.updateAvatar", "/organizations/{organization}/settings/avatar", of("organization"), of()),
|
||||
ORG_SET_INVITE_STATUS("org.setInviteStatus", "/organizations/invite/{id}/{status}", of("id", "status"), of()),
|
||||
ORG_SHOW_CREATOR("org.showCreator", "/organizations/new", of(), of()),
|
||||
ORG_CREATE("org.create", "/organizations/new", of(), of()),
|
||||
ORG_REMOVE_MEMBER("org.removeMember", "/organizations/{organization}/settings/members/remove", of("organization"), of()),
|
||||
|
||||
REVIEWS_ADD_MESSAGE("reviews.addMessage", "/{author}/{slug}/versions/{version}/reviews/addmessage", of("author", "slug", "version"), of()),
|
||||
REVIEWS_BACKLOG_TOGGLE("reviews.backlogToggle", "/{author}/{slug}/versions/{version}/reviews/reviewtoggle", of("author", "slug", "version"), of()),
|
||||
REVIEWS_SHOW_REVIEWS("reviews.showReviews", "/{author}/{slug}/versions/{version}/reviews", of("author", "slug", "version"), of()),
|
||||
REVIEWS_APPROVE_REVIEW("reviews.approveReview", "/{author}/{slug}/versions/{version}/reviews/approve", of("author", "slug", "version"), of()),
|
||||
REVIEWS_EDIT_REVIEW("reviews.editReview", "/{author}/{slug}/versions/{version}/reviews/edit/{review}", of("author", "slug", "version", "review"), of()),
|
||||
REVIEWS_STOP_REVIEW("reviews.stopReview", "/{author}/{slug}/versions/{version}/reviews/stop", of("author", "slug", "version"), of()),
|
||||
REVIEWS_CREATE_REVIEW("reviews.createReview", "/{author}/{slug}/versions/{version}/reviews/init", of("author", "slug", "version"), of()),
|
||||
REVIEWS_TAKEOVER_REVIEW("reviews.takeoverReview", "/{author}/{slug}/versions/{version}/reviews/takeover", of("author", "slug", "version"), of()),
|
||||
REVIEWS_REOPEN_REVIEW("reviews.reopenReview", "/{author}/{slug}/versions/{version}/reviews/reopen", of("author", "slug", "version"), of()),
|
||||
|
||||
CHANNELS_DELETE("channels.delete", "/{author}/{slug}/channels/{channel}/delete", of("author", "slug", "channel"), of()),
|
||||
CHANNELS_SAVE("channels.save", "/{author}/{slug}/channels/{channel}", of("author", "slug", "channel"), of()),
|
||||
CHANNELS_SHOW_LIST("channels.showList", "/{author}/{slug}/channels", of("author", "slug"), of()),
|
||||
CHANNELS_CREATE("channels.create", "/{author}/{slug}/channels", of("author", "slug"), of()),
|
||||
|
||||
APIV1_SHOW_VERSION("apiv1.showVersion", "/api/v1/projects/{pluginId}/versions/{name}", of("pluginId", "name"), of()),
|
||||
APIV1_LIST_PROJECTS("apiv1.listProjects", "/api/v1/projects", of(), of("categories", "sort", "q", "limit", "offset")),
|
||||
APIV1_LIST_USERS("apiv1.listUsers", "/api/v1/users", of(), of("limit", "offset")),
|
||||
APIV1_LIST_VERSIONS("apiv1.listVersions", "/api/v1/projects/{pluginId}/versions", of("pluginId"), of("channels", "limit", "offset")),
|
||||
APIV1_REVOKE_KEY("apiv1.revokeKey", "/api/v1/projects/{pluginId}/keys/revoke", of("pluginId"), of()),
|
||||
APIV1_CREATE_KEY("apiv1.createKey", "/api/v1/projects/{pluginId}/keys/new", of("pluginId"), of()),
|
||||
APIV1_SHOW_PROJECT("apiv1.showProject", "/api/v1/projects/{pluginId}", of("pluginId"), of()),
|
||||
APIV1_SYNC_SSO("apiv1.syncSso", "/api/sync_sso", of(), of()),
|
||||
APIV1_TAG_COLOR("apiv1.tagColor", "/api/v1/tags/{tagId}", of("tagId"), of()),
|
||||
APIV1_SHOW_STATUS_Z("apiv1.showStatusZ", "/statusz", of(), of()),
|
||||
APIV1_SHOW_USER("apiv1.showUser", "/api/v1/users/{user}", of("user"), of()),
|
||||
APIV1_LIST_PAGES("apiv1.listPages", "/api/v1/projects/{pluginId}/pages", of("pluginId"), of("parentId")),
|
||||
APIV1_DEPLOY_VERSION("apiv1.deployVersion", "/api/v1/projects/{pluginId}/versions/{name}", of("pluginId", "name"), of()),
|
||||
APIV1_LIST_TAGS("apiv1.listTags", "/api/v1/projects/{plugin}/tags/{versionName}", of("plugin", "versionName"), of());
|
||||
PROJECTS_RENAME("projects.rename", Paths.PROJECTS_RENAME, of("author", "slug"), of()),
|
||||
PROJECTS_SET_WATCHING("projects.setWatching", Paths.PROJECTS_SET_WATCHING, of("author", "slug", "watching"), of()),
|
||||
PROJECTS_SHOW_SETTINGS("projects.showSettings", Paths.PROJECTS_SHOW_SETTINGS, of("author", "slug"), of()),
|
||||
PROJECTS_SET_INVITE_STATUS("projects.setInviteStatus", Paths.PROJECTS_SET_INVITE_STATUS, of("id", "status"), of()),
|
||||
PROJECTS_TOGGLE_STARRED("projects.toggleStarred", Paths.PROJECTS_TOGGLE_STARRED, of("author", "slug"), of()),
|
||||
PROJECTS_SHOW_CREATOR("projects.showCreator", Paths.PROJECTS_SHOW_CREATOR, of(), of()),
|
||||
PROJECTS_SHOW_STARGAZERS("projects.showStargazers", Paths.PROJECTS_SHOW_STARGAZERS, of("author", "slug"), of("page")),
|
||||
PROJECTS_SHOW_WATCHERS("projects.showWatchers", Paths.PROJECTS_SHOW_WATCHERS, of("author", "slug"), of("page")),
|
||||
PROJECTS_UPLOAD_ICON("projects.uploadIcon", Paths.PROJECTS_UPLOAD_ICON, of("author", "slug"), of()),
|
||||
PROJECTS_SHOW_ICON("projects.showIcon", Paths.PROJECTS_SHOW_ICON, of("author", "slug"), of()),
|
||||
PROJECTS_SEND_FOR_APPROVAL("projects.sendForApproval", Paths.PROJECTS_SEND_FOR_APPROVAL, of("author", "slug"), of()),
|
||||
PROJECTS_SET_INVITE_STATUS_ON_BEHALF("projects.setInviteStatusOnBehalf", Paths.PROJECTS_SET_INVITE_STATUS_ON_BEHALF, of("id", "status", "behalf"), of()),
|
||||
PROJECTS_DELETE("projects.delete", Paths.PROJECTS_DELETE, of("author", "slug"), of()),
|
||||
PROJECTS_ADD_MESSAGE("projects.addMessage", Paths.PROJECTS_ADD_MESSAGE, of("author", "slug"), of()),
|
||||
PROJECTS_SHOW_PENDING_ICON("projects.showPendingIcon", Paths.PROJECTS_SHOW_PENDING_ICON, of("author", "slug"), of()),
|
||||
PROJECTS_POST_DISCUSSION_REPLY("projects.postDiscussionReply", Paths.PROJECTS_POST_DISCUSSION_REPLY, of("author", "slug"), of()),
|
||||
PROJECTS_SHOW("projects.show", Paths.PROJECTS_SHOW, of("author", "slug"), of()),
|
||||
PROJECTS_SHOW_DISCUSSION("projects.showDiscussion", Paths.PROJECTS_SHOW_DISCUSSION, of("author", "slug"), of()),
|
||||
PROJECTS_SOFT_DELETE("projects.softDelete", Paths.PROJECTS_SOFT_DELETE, of("author", "slug"), of()),
|
||||
PROJECTS_SHOW_FLAGS("projects.showFlags", Paths.PROJECTS_SHOW_FLAGS, of("author", "slug"), of()),
|
||||
PROJECTS_FLAG("projects.flag", Paths.PROJECTS_FLAG, of("author", "slug"), of()),
|
||||
PROJECTS_CREATE_PROJECT("projects.createProject", Paths.PROJECTS_CREATE_PROJECT, of(), of()),
|
||||
PROJECTS_RESET_ICON("projects.resetIcon", Paths.PROJECTS_RESET_ICON, of("author", "slug"), of()),
|
||||
PROJECTS_SAVE("projects.save", Paths.PROJECTS_SAVE, of("author", "slug"), of()),
|
||||
PROJECTS_SHOW_NOTES("projects.showNotes", Paths.PROJECTS_SHOW_NOTES, of("author", "slug"), of()),
|
||||
PROJECTS_SET_VISIBLE("projects.setVisible", Paths.PROJECTS_SET_VISIBLE, of("author", "slug", "visibility"), of()),
|
||||
PROJECTS_REMOVE_MEMBER("projects.removeMember", Paths.PROJECTS_REMOVE_MEMBER, of("author", "slug"), of()),
|
||||
VERSIONS_RESTORE("versions.restore", Paths.VERSIONS_RESTORE, of("author", "slug", "version"), of()),
|
||||
VERSIONS_DOWNLOAD_RECOMMENDED_JAR("versions.downloadRecommendedJar", Paths.VERSIONS_DOWNLOAD_RECOMMENDED_JAR, of("author", "slug"), of("token")),
|
||||
VERSIONS_PUBLISH("versions.publish", Paths.VERSIONS_PUBLISH, of("author", "slug", "version"), of()),
|
||||
VERSIONS_PUBLISH_URL("versions.publishUrl", Paths.VERSIONS_PUBLISH_URL, of("author", "slug"), of()),
|
||||
VERSIONS_SET_RECOMMENDED("versions.setRecommended", Paths.VERSIONS_SET_RECOMMENDED, of("author", "slug", "version"), of()),
|
||||
VERSIONS_DOWNLOAD("versions.download", Paths.VERSIONS_DOWNLOAD, of("author", "slug", "version"), of("token", "confirm")),
|
||||
VERSIONS_SHOW_LOG("versions.showLog", Paths.VERSIONS_SHOW_LOG, of("author", "slug"), of("versionString")),
|
||||
VERSIONS_SHOW("versions.show", Paths.VERSIONS_SHOW, of("author", "slug", "version"), of()),
|
||||
VERSIONS_DOWNLOAD_JAR("versions.downloadJar", Paths.VERSIONS_DOWNLOAD_JAR, of("author", "slug", "version"), of("token")),
|
||||
VERSIONS_APPROVE("versions.approve", Paths.VERSIONS_APPROVE, of("author", "slug", "version"), of()),
|
||||
VERSIONS_APPROVE_PARTIAL("versions.approvePartial", Paths.VERSIONS_APPROVE_PARTIAL, of("author", "slug", "version"), of()),
|
||||
VERSIONS_SAVE_DESCRIPTION("versions.saveDescription", Paths.VERSIONS_SAVE_DESCRIPTION, of("author", "slug", "version"), of()),
|
||||
VERSIONS_DOWNLOAD_RECOMMENDED("versions.downloadRecommended", Paths.VERSIONS_DOWNLOAD_RECOMMENDED, of("author", "slug"), of("token")),
|
||||
VERSIONS_SHOW_LIST("versions.showList", Paths.VERSIONS_SHOW_LIST, of("author", "slug"), of()),
|
||||
VERSIONS_DOWNLOAD_JAR_BY_ID("versions.downloadJarById", Paths.VERSIONS_DOWNLOAD_JAR_BY_ID, of("pluginId", "name"), of("token")),
|
||||
VERSIONS_DOWNLOAD_RECOMMENDED_JAR_BY_ID("versions.downloadRecommendedJarById", Paths.VERSIONS_DOWNLOAD_RECOMMENDED_JAR_BY_ID, of("pluginId"), of("token")),
|
||||
VERSIONS_UPLOAD("versions.upload", Paths.VERSIONS_UPLOAD, of("author", "slug"), of()),
|
||||
VERSIONS_CREATE_EXTERNAL_URL("versions.createExternalUrl", Paths.VERSIONS_CREATE_EXTERNAL_URL, of("author", "slug"), of()),
|
||||
VERSIONS_SOFT_DELETE("versions.softDelete", Paths.VERSIONS_SOFT_DELETE, of("author", "slug", "version"), of()),
|
||||
VERSIONS_SHOW_DOWNLOAD_CONFIRM("versions.showDownloadConfirm", Paths.VERSIONS_SHOW_DOWNLOAD_CONFIRM, of("author", "slug", "version"), of("downloadType", "api", "dummy")),
|
||||
VERSIONS_SHOW_CREATOR("versions.showCreator", Paths.VERSIONS_SHOW_CREATOR, of("author", "slug"), of()),
|
||||
VERSIONS_DELETE("versions.delete", Paths.VERSIONS_DELETE, of("author", "slug", "version"), of()),
|
||||
VERSIONS_SHOW_CREATOR_WITH_META("versions.showCreatorWithMeta", Paths.VERSIONS_SHOW_CREATOR_WITH_META, of("author", "slug", "version"), of()),
|
||||
VERSIONS_CONFIRM_DOWNLOAD("versions.confirmDownload", Paths.VERSIONS_CONFIRM_DOWNLOAD, of("author", "slug", "version"), of("downloadType", "token", "dummy")),
|
||||
PAGES_SHOW_PREVIEW("pages.showPreview", Paths.PAGES_SHOW_PREVIEW, of(), of()),
|
||||
PAGES_SAVE("pages.save", Paths.PAGES_SAVE, of("author", "slug", "page"), of()),
|
||||
PAGES_SHOW_EDITOR("pages.showEditor", Paths.PAGES_SHOW_EDITOR, of("author", "slug", "page"), of()),
|
||||
PAGES_SHOW("pages.show", Paths.PAGES_SHOW, of("author", "slug", "page"), of()),
|
||||
PAGES_DELETE("pages.delete", Paths.PAGES_DELETE, of("author", "slug", "page"), of()),
|
||||
USERS_SHOW_AUTHORS("users.showAuthors", Paths.USERS_SHOW_AUTHORS, of(), of("sort", "page")),
|
||||
USERS_SAVE_TAGLINE("users.saveTagline", Paths.USERS_SAVE_TAGLINE, of("user"), of()),
|
||||
USERS_SIGN_UP("users.signUp", Paths.USERS_SIGN_UP, of(), of()),
|
||||
USERS_SHOW_NOTIFICATIONS("users.showNotifications", Paths.USERS_SHOW_NOTIFICATIONS, of(), of("notificationFilter", "inviteFilter")),
|
||||
USERS_SHOW_PROJECTS("users.showProjects", Paths.USERS_SHOW_PROJECTS, of("user"), of()),
|
||||
USERS_VERIFY("users.verify", Paths.USERS_VERIFY, of(), of("returnPath")),
|
||||
USERS_MARK_NOTIFICATION_READ("users.markNotificationRead", Paths.USERS_MARK_NOTIFICATION_READ, of("id"), of()),
|
||||
USERS_LOGIN("users.login", Paths.USERS_LOGIN, of(), of("sso", "sig", "returnUrl")),
|
||||
USERS_SHOW_STAFF("users.showStaff", Paths.USERS_SHOW_STAFF, of(), of("sort", "page")),
|
||||
USERS_SET_LOCKED("users.setLocked", Paths.USERS_SET_LOCKED, of("user", "locked"), of("sso", "sig")),
|
||||
USERS_MARK_PROMPT_READ("users.markPromptRead", Paths.USERS_MARK_PROMPT_READ, of("id"), of()),
|
||||
USERS_LOGOUT("users.logout", Paths.USERS_LOGOUT, of(), of()),
|
||||
USERS_USER_SITEMAP("users.userSitemap", Paths.USERS_USER_SITEMAP, of("user"), of()),
|
||||
USERS_EDIT_API_KEYS("users.editApiKeys", Paths.USERS_EDIT_API_KEYS, of("user"), of()),
|
||||
ORG_UPDATE_MEMBERS("org.updateMembers", Paths.ORG_UPDATE_MEMBERS, of("organization"), of()),
|
||||
ORG_UPDATE_AVATAR("org.updateAvatar", Paths.ORG_UPDATE_AVATAR, of("organization"), of()),
|
||||
ORG_SET_INVITE_STATUS("org.setInviteStatus", Paths.ORG_SET_INVITE_STATUS, of("id", "status"), of()),
|
||||
ORG_SHOW_CREATOR("org.showCreator", Paths.ORG_SHOW_CREATOR, of(), of()),
|
||||
ORG_CREATE("org.create", Paths.ORG_CREATE, of(), of()),
|
||||
ORG_REMOVE_MEMBER("org.removeMember", Paths.ORG_REMOVE_MEMBER, of("organization"), of()),
|
||||
REVIEWS_ADD_MESSAGE("reviews.addMessage", Paths.REVIEWS_ADD_MESSAGE, of("author", "slug", "version"), of()),
|
||||
REVIEWS_BACKLOG_TOGGLE("reviews.backlogToggle", Paths.REVIEWS_BACKLOG_TOGGLE, of("author", "slug", "version"), of()),
|
||||
REVIEWS_SHOW_REVIEWS("reviews.showReviews", Paths.REVIEWS_SHOW_REVIEWS, of("author", "slug", "version"), of()),
|
||||
REVIEWS_APPROVE_REVIEW("reviews.approveReview", Paths.REVIEWS_APPROVE_REVIEW, of("author", "slug", "version"), of()),
|
||||
REVIEWS_EDIT_REVIEW("reviews.editReview", Paths.REVIEWS_EDIT_REVIEW, of("author", "slug", "version", "review"), of()),
|
||||
REVIEWS_STOP_REVIEW("reviews.stopReview", Paths.REVIEWS_STOP_REVIEW, of("author", "slug", "version"), of()),
|
||||
REVIEWS_CREATE_REVIEW("reviews.createReview", Paths.REVIEWS_CREATE_REVIEW, of("author", "slug", "version"), of()),
|
||||
REVIEWS_TAKEOVER_REVIEW("reviews.takeoverReview", Paths.REVIEWS_TAKEOVER_REVIEW, of("author", "slug", "version"), of()),
|
||||
REVIEWS_REOPEN_REVIEW("reviews.reopenReview", Paths.REVIEWS_REOPEN_REVIEW, of("author", "slug", "version"), of()),
|
||||
CHANNELS_DELETE("channels.delete", Paths.CHANNELS_DELETE, of("author", "slug", "channel"), of()),
|
||||
CHANNELS_SAVE("channels.save", Paths.CHANNELS_SAVE, of("author", "slug", "channel"), of()),
|
||||
CHANNELS_SHOW_LIST("channels.showList", Paths.CHANNELS_SHOW_LIST, of("author", "slug"), of()),
|
||||
CHANNELS_CREATE("channels.create", Paths.CHANNELS_CREATE, of("author", "slug"), of()),
|
||||
APIV1_SHOW_VERSION("apiv1.showVersion", Paths.APIV1_SHOW_VERSION, of("pluginId", "name"), of()),
|
||||
APIV1_LIST_PROJECTS("apiv1.listProjects", Paths.APIV1_LIST_PROJECTS, of(), of("categories", "sort", "q", "limit", "offset")),
|
||||
APIV1_LIST_USERS("apiv1.listUsers", Paths.APIV1_LIST_USERS, of(), of("limit", "offset")),
|
||||
APIV1_LIST_VERSIONS("apiv1.listVersions", Paths.APIV1_LIST_VERSIONS, of("pluginId"), of("channels", "limit", "offset")),
|
||||
APIV1_REVOKE_KEY("apiv1.revokeKey", Paths.APIV1_REVOKE_KEY, of("pluginId"), of()),
|
||||
APIV1_CREATE_KEY("apiv1.createKey", Paths.APIV1_CREATE_KEY, of("pluginId"), of()),
|
||||
APIV1_SHOW_PROJECT("apiv1.showProject", Paths.APIV1_SHOW_PROJECT, of("pluginId"), of()),
|
||||
APIV1_SYNC_SSO("apiv1.syncSso", Paths.APIV1_SYNC_SSO, of(), of()),
|
||||
APIV1_TAG_COLOR("apiv1.tagColor", Paths.APIV1_TAG_COLOR, of("tagId"), of()),
|
||||
APIV1_SHOW_STATUS_Z("apiv1.showStatusZ", Paths.APIV1_SHOW_STATUS_Z, of(), of()),
|
||||
APIV1_SHOW_USER("apiv1.showUser", Paths.APIV1_SHOW_USER, of("user"), of()),
|
||||
APIV1_LIST_PAGES("apiv1.listPages", Paths.APIV1_LIST_PAGES, of("pluginId"), of("parentId")),
|
||||
APIV1_DEPLOY_VERSION("apiv1.deployVersion", Paths.APIV1_DEPLOY_VERSION, of("pluginId", "name"), of()),
|
||||
APIV1_LIST_TAGS("apiv1.listTags", Paths.APIV1_LIST_TAGS, of("plugin", "versionName"), of()),
|
||||
APIV1_LIST_PLATFORMS("apiv1.listPlatforms", Paths.APIV1_LIST_PLATFORMS, of(), of());
|
||||
|
||||
private static final Map<String, Routes> ROUTES = new HashMap<>();
|
||||
|
||||
@ -172,6 +168,10 @@ public enum Routes {
|
||||
this.queryParams = queryParams.toArray(new String[0]);
|
||||
}
|
||||
|
||||
public String getUrl() {
|
||||
return url;
|
||||
}
|
||||
|
||||
public String getRouteUrl(String... args) {
|
||||
if ((pathParams.length + queryParams.length) != args.length) {
|
||||
throw new RuntimeException("Args dont match for route " + name + " " + (pathParams.length + queryParams.length) + "!=" + args.length);
|
||||
@ -216,4 +216,144 @@ public enum Routes {
|
||||
public static ModelAndView getRedirectToUrl(String url) {
|
||||
return new ModelAndView("redirect:" + url);
|
||||
}
|
||||
|
||||
public static class Paths {
|
||||
public static final String SHOW_PROJECT_VISIBILITY = "/admin/approval/projects";
|
||||
public static final String ACTOR_COUNT = "/pantopticon/actor-count";
|
||||
public static final String ACTOR_TREE = "/pantopticon/actor-tree";
|
||||
public static final String UPDATE_USER = "/admin/user/{user}/update";
|
||||
public static final String SHOW_QUEUE = "/admin/approval/versions";
|
||||
public static final String SHOW_LOG = "/admin/log";
|
||||
public static final String SHOW_PLATFORM_VERSIONS = "/admin/versions";
|
||||
public static final String UPDATE_PLATFORM_VERSIONS = "/admin/versions/{platform}";
|
||||
public static final String REMOVE_TRAIL = "/{path}/";
|
||||
public static final String FAVICON_REDIRECT = "/favicon.ico";
|
||||
public static final String SHOW_FLAGS = "/admin/flags";
|
||||
public static final String SITEMAP_INDEX = "/sitemap.xml";
|
||||
public static final String GLOBAL_SITEMAP = "/global-sitemap.xml";
|
||||
public static final String SHOW_STATS = "/admin/stats";
|
||||
public static final String LINK_OUT = "/linkout";
|
||||
public static final String SHOW_HEALTH = "/admin/health";
|
||||
public static final String SHOW_HOME = "/";
|
||||
public static final String ROBOTS = "/robots.txt";
|
||||
public static final String SET_FLAG_RESOLVED = "/admin/flags/{id}/resolve/{resolved}";
|
||||
public static final String SWAGGER = "/api";
|
||||
public static final String SHOW_ACTIVITIES = "/admin/activities/{user}";
|
||||
public static final String USER_ADMIN = "/admin/user/{user}";
|
||||
public static final String JAVA_SCRIPT_ROUTES = "/javascriptRoutes";
|
||||
|
||||
public static final String PROJECTS_RENAME = "/{author}/{slug}/manage/rename";
|
||||
public static final String PROJECTS_SET_WATCHING = "/{author}/{slug}/watchers/{watching}";
|
||||
public static final String PROJECTS_SHOW_SETTINGS = "/{author}/{slug}/manage";
|
||||
public static final String PROJECTS_SET_INVITE_STATUS = "/invite/{id}/{status}";
|
||||
public static final String PROJECTS_TOGGLE_STARRED = "/{author}/{slug}/stars/toggle";
|
||||
public static final String PROJECTS_SHOW_CREATOR = "/new";
|
||||
public static final String PROJECTS_SHOW_STARGAZERS = "/{author}/{slug}/stars";
|
||||
public static final String PROJECTS_SHOW_WATCHERS = "/{author}/{slug}/watchers";
|
||||
public static final String PROJECTS_UPLOAD_ICON = "/{author}/{slug}/icon";
|
||||
public static final String PROJECTS_SHOW_ICON = "/{author}/{slug}/icon";
|
||||
public static final String PROJECTS_SEND_FOR_APPROVAL = "/{author}/{slug}/manage/sendforapproval";
|
||||
public static final String PROJECTS_SET_INVITE_STATUS_ON_BEHALF = "/invite/{id}/{status}/{behalf}";
|
||||
public static final String PROJECTS_DELETE = "/{author}/{slug}/manage/hardDelete";
|
||||
public static final String PROJECTS_ADD_MESSAGE = "/{author}/{slug}/notes/addmessage";
|
||||
public static final String PROJECTS_SHOW_PENDING_ICON = "/{author}/{slug}/icon/pending";
|
||||
public static final String PROJECTS_POST_DISCUSSION_REPLY = "/{author}/{slug}/discuss/reply";
|
||||
public static final String PROJECTS_SHOW = "/{author}/{slug}";
|
||||
public static final String PROJECTS_SHOW_DISCUSSION = "/{author}/{slug}/discuss";
|
||||
public static final String PROJECTS_SOFT_DELETE = "/{author}/{slug}/manage/delete";
|
||||
public static final String PROJECTS_SHOW_FLAGS = "/{author}/{slug}/flags";
|
||||
public static final String PROJECTS_FLAG = "/{author}/{slug}/flag";
|
||||
public static final String PROJECTS_CREATE_PROJECT = "/new";
|
||||
public static final String PROJECTS_RESET_ICON = "/{author}/{slug}/icon/reset";
|
||||
public static final String PROJECTS_SAVE = "/{author}/{slug}/manage/save";
|
||||
public static final String PROJECTS_SHOW_NOTES = "/{author}/{slug}/notes";
|
||||
public static final String PROJECTS_SET_VISIBLE = "/{author}/{slug}/visible/{visibility}";
|
||||
public static final String PROJECTS_REMOVE_MEMBER = "/{author}/{slug}/manage/members/remove";
|
||||
|
||||
public static final String VERSIONS_RESTORE = "/{author}/{slug}/versions/{version}/restore";
|
||||
public static final String VERSIONS_DOWNLOAD_RECOMMENDED_JAR = "/{author}/{slug}/versions/recommended/jar";
|
||||
public static final String VERSIONS_PUBLISH = "/{author}/{slug}/versions/{version}";
|
||||
public static final String VERSIONS_PUBLISH_URL = "/{author}/{slug}/versions/publish";
|
||||
public static final String VERSIONS_SET_RECOMMENDED = "/{author}/{slug}/versions/{version}/recommended";
|
||||
public static final String VERSIONS_DOWNLOAD = "/{author}/{slug}/versions/{version}/download";
|
||||
public static final String VERSIONS_SHOW_LOG = "/{author}/{slug}/versionLog";
|
||||
public static final String VERSIONS_SHOW = "/{author}/{slug}/versions/{version}";
|
||||
public static final String VERSIONS_DOWNLOAD_JAR = "/{author}/{slug}/versions/{version}/jar";
|
||||
public static final String VERSIONS_APPROVE = "/{author}/{slug}/versions/{version}/approve";
|
||||
public static final String VERSIONS_APPROVE_PARTIAL = "/{author}/{slug}/versions/{version}/approvePartial";
|
||||
public static final String VERSIONS_SAVE_DESCRIPTION = "/{author}/{slug}/versions/{version}/save";
|
||||
public static final String VERSIONS_DOWNLOAD_RECOMMENDED = "/{author}/{slug}/versions/recommended/download";
|
||||
public static final String VERSIONS_SHOW_LIST = "/{author}/{slug}/versions";
|
||||
public static final String VERSIONS_DOWNLOAD_JAR_BY_ID = "/api/project/{pluginId}/versions/{name}/download";
|
||||
public static final String VERSIONS_DOWNLOAD_RECOMMENDED_JAR_BY_ID = "/api/project/{pluginId}/versions/recommended/download";
|
||||
public static final String VERSIONS_UPLOAD = "/{author}/{slug}/versions/new/upload";
|
||||
public static final String VERSIONS_CREATE_EXTERNAL_URL = "/{author}/{slug}/versions/new/create";
|
||||
public static final String VERSIONS_SOFT_DELETE = "/{author}/{slug}/versions/{version}/delete";
|
||||
public static final String VERSIONS_SHOW_DOWNLOAD_CONFIRM = "/{author}/{slug}/versions/{version}/confirm";
|
||||
public static final String VERSIONS_SHOW_CREATOR = "/{author}/{slug}/versions/new";
|
||||
public static final String VERSIONS_DELETE = "/{author}/{slug}/versions/{version}/hardDelete";
|
||||
public static final String VERSIONS_SHOW_CREATOR_WITH_META = "/{author}/{slug}/versions/new/{version}";
|
||||
public static final String VERSIONS_CONFIRM_DOWNLOAD = "/{author}/{slug}/versions/{version}/confirm";
|
||||
|
||||
public static final String PAGES_SHOW_PREVIEW = "/pages/preview";
|
||||
public static final String PAGES_SAVE = "/{author}/{slug}/pages/{page}/edit";
|
||||
public static final String PAGES_SHOW_EDITOR = "/{author}/{slug}/pages/{page}/edit";
|
||||
public static final String PAGES_SHOW = "/{author}/{slug}/pages/{page}";
|
||||
public static final String PAGES_DELETE = "/{author}/{slug}/pages/{page}/delete";
|
||||
|
||||
public static final String USERS_SHOW_AUTHORS = "/authors";
|
||||
public static final String USERS_SAVE_TAGLINE = "/{user}/settings/tagline";
|
||||
public static final String USERS_SIGN_UP = "/signup";
|
||||
public static final String USERS_SHOW_NOTIFICATIONS = "/notifications";
|
||||
public static final String USERS_SHOW_PROJECTS = "/{user}";
|
||||
public static final String USERS_VERIFY = "/verify";
|
||||
public static final String USERS_MARK_NOTIFICATION_READ = "/notifications/read/{id}";
|
||||
public static final String USERS_LOGIN = "/login";
|
||||
public static final String USERS_SHOW_STAFF = "/staff";
|
||||
public static final String USERS_SET_LOCKED = "/{user}/settings/lock/{locked}";
|
||||
public static final String USERS_MARK_PROMPT_READ = "/prompts/read/{id}";
|
||||
public static final String USERS_LOGOUT = "/logout";
|
||||
public static final String USERS_USER_SITEMAP = "/{user}/sitemap.xml";
|
||||
public static final String USERS_EDIT_API_KEYS = "/{user}/settings/apiKeys";
|
||||
|
||||
public static final String ORG_UPDATE_MEMBERS = "/organizations/{organization}/settings/members";
|
||||
public static final String ORG_UPDATE_AVATAR = "/organizations/{organization}/settings/avatar";
|
||||
public static final String ORG_SET_INVITE_STATUS = "/organizations/invite/{id}/{status}";
|
||||
public static final String ORG_SHOW_CREATOR = "/organizations/new";
|
||||
public static final String ORG_CREATE = "/organizations/new";
|
||||
public static final String ORG_REMOVE_MEMBER = "/organizations/{organization}/settings/members/remove";
|
||||
|
||||
public static final String REVIEWS_ADD_MESSAGE = "/{author}/{slug}/versions/{version}/reviews/addmessage";
|
||||
public static final String REVIEWS_BACKLOG_TOGGLE = "/{author}/{slug}/versions/{version}/reviews/reviewtoggle";
|
||||
public static final String REVIEWS_SHOW_REVIEWS = "/{author}/{slug}/versions/{version}/reviews";
|
||||
public static final String REVIEWS_APPROVE_REVIEW = "/{author}/{slug}/versions/{version}/reviews/approve";
|
||||
public static final String REVIEWS_EDIT_REVIEW = "/{author}/{slug}/versions/{version}/reviews/edit/{review}";
|
||||
public static final String REVIEWS_STOP_REVIEW = "/{author}/{slug}/versions/{version}/reviews/stop";
|
||||
public static final String REVIEWS_CREATE_REVIEW = "/{author}/{slug}/versions/{version}/reviews/init";
|
||||
public static final String REVIEWS_TAKEOVER_REVIEW = "/{author}/{slug}/versions/{version}/reviews/takeover";
|
||||
public static final String REVIEWS_REOPEN_REVIEW = "/{author}/{slug}/versions/{version}/reviews/reopen";
|
||||
|
||||
public static final String CHANNELS_DELETE = "/{author}/{slug}/channels/{channel}/delete";
|
||||
public static final String CHANNELS_SAVE = "/{author}/{slug}/channels/{channel}";
|
||||
public static final String CHANNELS_SHOW_LIST = "/{author}/{slug}/channels";
|
||||
public static final String CHANNELS_CREATE = "/{author}/{slug}/channels";
|
||||
|
||||
public static final String APIV1_SHOW_VERSION = "/api/v1/projects/{pluginId}/versions/{name}";
|
||||
public static final String APIV1_LIST_PROJECTS = "/api/v1/projects";
|
||||
public static final String APIV1_LIST_USERS = "/api/v1/users";
|
||||
public static final String APIV1_LIST_VERSIONS = "/api/v1/projects/{pluginId}/versions";
|
||||
public static final String APIV1_REVOKE_KEY = "/api/v1/projects/{pluginId}/keys/revoke";
|
||||
public static final String APIV1_CREATE_KEY = "/api/v1/projects/{pluginId}/keys/new";
|
||||
public static final String APIV1_SHOW_PROJECT = "/api/v1/projects/{pluginId}";
|
||||
public static final String APIV1_SYNC_SSO = "/api/sync_sso";
|
||||
public static final String APIV1_TAG_COLOR = "/api/v1/tags/{tagId}";
|
||||
public static final String APIV1_SHOW_STATUS_Z = "/statusz";
|
||||
public static final String APIV1_SHOW_USER = "/api/v1/users/{user}";
|
||||
public static final String APIV1_LIST_PAGES = "/api/v1/projects/{pluginId}/pages";
|
||||
public static final String APIV1_DEPLOY_VERSION = "/api/v1/projects/{pluginId}/versions/{name}";
|
||||
public static final String APIV1_LIST_TAGS = "/api/v1/projects/{plugin}/tags/{versionName}";
|
||||
public static final String APIV1_LIST_PLATFORMS = "/api/v1/platforms";
|
||||
|
||||
private Paths() { }
|
||||
}
|
||||
}
|
@ -2,7 +2,6 @@ package io.papermc.hangar.util;
|
||||
|
||||
import io.papermc.hangar.config.hangar.HangarConfig;
|
||||
import io.papermc.hangar.db.model.ProjectsTable;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@ -39,6 +38,7 @@ public class TemplateHelper {
|
||||
}
|
||||
|
||||
public String formatFileSize(Long size) {
|
||||
if (size == null) return "";
|
||||
if (size < 1024) {
|
||||
return size + "B";
|
||||
}
|
||||
|
@ -122,6 +122,8 @@ hangar:
|
||||
max-failures: 5
|
||||
timeout: 10s
|
||||
reset: 5m
|
||||
safe-download-hosts:
|
||||
- "github.com"
|
||||
|
||||
|
||||
################
|
||||
|
@ -0,0 +1,3 @@
|
||||
ALTER TABLE project_versions ALTER COLUMN file_size DROP NOT NULL;
|
||||
ALTER TABLE project_versions ALTER COLUMN hash DROP NOT NULL;
|
||||
ALTER TABLE project_versions ALTER COLUMN file_name DROP NOT NULL;
|
@ -35,6 +35,7 @@ general.name = Name
|
||||
general.close = Close
|
||||
general.continue = Continue
|
||||
general.download = Download
|
||||
general.downloadExternal = Download (External)
|
||||
general.upload = Upload
|
||||
general.more = More
|
||||
general.sponsoredBy = Sponsored By
|
||||
@ -80,6 +81,7 @@ error.minLength = Content too short.
|
||||
error.maxLength = Content too long.
|
||||
error.noFile = No file submitted.
|
||||
error.invalidFile = That is an invalid file type.
|
||||
error.invalidUrl = That URL is invalid.
|
||||
error.nameUnavailable = That name is not available.
|
||||
error.noLogin = Login is temporarily unavailable, please try again later.
|
||||
error.loginFailed = Authentication failed.
|
||||
@ -149,6 +151,7 @@ project.delete.info.uniqueid = WARNING: You or anybody else will not be abl
|
||||
project.download.recommend = Download the latest recommended version
|
||||
project.download.recommend.warn = This project's recommended version has not been reviewed by our moderation staff and may not be safe for download.
|
||||
project.download.warn = This version has not been reviewed by our moderation staff and may not be safe for download.
|
||||
project.download.external = External Download
|
||||
project.flag = Flag
|
||||
project.flag.plural = Flags
|
||||
project.create = New Project
|
||||
@ -238,6 +241,7 @@ version = Version
|
||||
version.description = Description
|
||||
version.filename = File name
|
||||
version.fileSize = File size
|
||||
version.externalUrl = URL
|
||||
version.delete.cannotLast = Every project must have at least one version
|
||||
version.delete.alreadyDeleted = This version has already been deleted
|
||||
version.dependency.notOnOre = This plugin is not available for download on Hangar
|
||||
@ -247,6 +251,7 @@ version.create.title = New project release
|
||||
version.create.noDescription = No description given.
|
||||
version.create.upload = Upload
|
||||
version.create.selectFile = Select file
|
||||
version.create.externalUrl = External download URL
|
||||
version.create.publish = Publish
|
||||
version.create.tos = By clicking "Publish" you are agreeing to Hangar's <a href="https://docs.spongepowered.org/stable/en/about/tos.html">Terms of Service</a>.
|
||||
version.create.info = Release a new version for <strong>{0}</strong> (pluginid: {1}).
|
||||
@ -264,6 +269,7 @@ version.download.confirm.title = Download Warning for
|
||||
version.download.confirm.header = {1} {2} by {0}
|
||||
version.download.confirm.disclaimer = We disclaim all responsibility for any harm to your server or system should you choose not to heed this warning.
|
||||
version.download.confirm.reviewedChannel = This version has not been reviewed by our moderation staff yet and may not be safe to use.
|
||||
version.download.confirm.externalUrl = This version download is on an external site.
|
||||
version.download.confirmPartial.reviewedChannel = \
|
||||
This version has only been partially reviewed by our moderation staff and may not be safe for use. \
|
||||
While the core plugin has been reviewed, other resources like shaded libraries have not.
|
||||
|
@ -23,7 +23,7 @@
|
||||
maxlength="${config.channels.maxNameLen}"/>
|
||||
<input type="hidden" name="channel-color-input" class="channel-color-input" value="" />
|
||||
<a href="#">
|
||||
<span class="color-picker" data-toggle="popover" data-placement="right" data-trigger="hover">
|
||||
<span id="channel-color-picker" class="color-picker" data-toggle="popover" data-placement="right" data-trigger="hover">
|
||||
<i class="fas fa-circle channel-id" style=""></i>
|
||||
</span>
|
||||
</a>
|
||||
|
@ -15,6 +15,10 @@
|
||||
<script type="text/javascript" src="<@hangar.url "javascripts/pluginUpload.js" />"></script>
|
||||
<script type="text/javascript" src="<@hangar.url "javascripts/projectDetail.js" />"></script>
|
||||
<script type="text/javascript" src="<@hangar.url "javascripts/versionCreateChannelNew.js" />"></script>
|
||||
<#if pending?? && !pending.dependencies??>
|
||||
<script type="text/javascript" src="<@hangar.url "build/platform-choice.js" />"></script>
|
||||
</#if>
|
||||
|
||||
<script>
|
||||
DEFAULT_COLOR = '${config.channels.colorDefault.hex}';
|
||||
</script>
|
||||
@ -44,30 +48,58 @@
|
||||
<table class="plugin-meta-table">
|
||||
<tr>
|
||||
<td><strong><@spring.message "version" /></strong></td>
|
||||
<td>${version.versionString}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong><@spring.message "version.description" /></strong></td>
|
||||
<td>
|
||||
<#if version.description?has_content>
|
||||
${version.description}
|
||||
<#if version.versionString??>
|
||||
${version.versionString}
|
||||
<#else>
|
||||
<#if projectDescription?has_content>
|
||||
${projectDescription}
|
||||
<#else>
|
||||
<@spring.message "version.create.noDescription" />
|
||||
</#if>
|
||||
<div class="form-group">
|
||||
<label for="version-string-input" class="sr-only">Version String</label>
|
||||
<input id="version-string-input" class="form-control" type="text" form="form-publish" name="versionString" required placeholder="Version">
|
||||
</div>
|
||||
</#if>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong><@spring.message "version.filename" /></strong></td>
|
||||
<td>${version.fileName}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong><@spring.message "version.fileSize" /></strong></td>
|
||||
<td>${utils.formatFileSize(version.fileSize)}</td>
|
||||
<td><strong><@spring.message "version.description" /></strong></td>
|
||||
<td>
|
||||
<#if version.versionString??>
|
||||
<#if version.description?has_content>
|
||||
${version.description}
|
||||
<#else>
|
||||
<#if projectDescription?has_content>
|
||||
${projectDescription}
|
||||
<#else>
|
||||
<@spring.message "version.create.noDescription" />
|
||||
</#if>
|
||||
</#if>
|
||||
<#else>
|
||||
<div class="form-group">
|
||||
<label for="version-description-input" class="sr-only">Version Description</label>
|
||||
<input type="text" form="form-publish" name="versionDescription" class="form-control" id="version-description-input">
|
||||
</div>
|
||||
</#if>
|
||||
</td>
|
||||
</tr>
|
||||
<#if version.fileName?? && !version.externalUrl??>
|
||||
<tr>
|
||||
<td><strong><@spring.message "version.filename" /></strong></td>
|
||||
<td>${version.fileName}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong><@spring.message "version.fileSize" /></strong></td>
|
||||
<td>${utils.formatFileSize(version.fileSize)}</td>
|
||||
</tr>
|
||||
<#else>
|
||||
<tr>
|
||||
<td><strong><@spring.message "version.externalUrl" /></strong></td>
|
||||
<td>
|
||||
<div class="form-group">
|
||||
<label for="external-url-input" class="sr-only"></label>
|
||||
<input id="external-url-input" class="form-control" type="text" value="${version.externalUrl}" name="externalUrl" form="form-publish" required>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</#if>
|
||||
<tr>
|
||||
<td><strong>Channel</strong></td>
|
||||
<td class="form-inline">
|
||||
@ -80,49 +112,59 @@
|
||||
</#list>
|
||||
</select>
|
||||
<a href="#">
|
||||
<i id="channel-new" class="fas fa-plus" data-toggle="modal"
|
||||
data-target="#channel-settings"></i>
|
||||
<i id="channel-new" class="fas fa-plus" data-toggle="modal" data-target="#channel-settings"></i>
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>Platform</strong></td>
|
||||
<td>
|
||||
<div class="float-right" id="upload-platform-tags">
|
||||
<#list version.dependenciesAsGhostTags as pair>
|
||||
<@projectTag.tagTemplate @helper["io.papermc.hangar.model.viewhelpers.ViewTag"].fromVersionTag(pair.right) pair.left "form-publish" />
|
||||
</#list>
|
||||
</div>
|
||||
<#if version.dependencies??>
|
||||
<div class="float-right" id="upload-platform-tags">
|
||||
<#list version.dependenciesAsGhostTags as pair>
|
||||
<@projectTag.tagTemplate @helper["io.papermc.hangar.model.viewhelpers.ViewTag"].fromVersionTag(pair.right) pair.left "form-publish" />
|
||||
</#list>
|
||||
</div>
|
||||
<#else>
|
||||
<div id="platform-choice"></div>
|
||||
</#if>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong><@spring.message "version.create.unstable" /></strong></td>
|
||||
<td>
|
||||
<label for="is-unstable-version" class="form-check-label">
|
||||
<strong><@spring.message "version.create.unstable" /></strong>
|
||||
</label>
|
||||
</td>
|
||||
<td class="rv">
|
||||
<div class="checkbox-inline">
|
||||
<input form="form-publish" name="unstable" type="checkbox" value="true"/>
|
||||
<div class="form-check">
|
||||
<input id="is-unstable-version" class="form-check-input" form="form-publish" name="unstable" type="checkbox" value="true">
|
||||
</div>
|
||||
<div class="clearfix"></div>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><strong>Recommended</strong></td>
|
||||
<td>
|
||||
<label for="is-recommended-version" class="form-check-label">
|
||||
<strong>Recommended</strong>
|
||||
</label>
|
||||
</td>
|
||||
<td class="rv">
|
||||
<div class="checkbox-inline">
|
||||
<input form="form-publish" name="recommended" type="checkbox" checked
|
||||
value="true"/>
|
||||
<div class="form-check">
|
||||
<input id="is-recommended-version" class="form-check-input" form="form-publish" name="recommended" type="checkbox" checked value="true">
|
||||
</div>
|
||||
<div class="clearfix"></div>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><strong>Create forum post</strong></td>
|
||||
<td>
|
||||
<label for="create-forum-post-version" class="form-check-label"></label>
|
||||
<strong>Create forum post</strong>
|
||||
</td>
|
||||
<td class="rv">
|
||||
<div class="checkbox-inline">
|
||||
<div class="form-check">
|
||||
<#-- @ftlvariable name="forumSync" type="java.lang.Boolean" -->
|
||||
<input form="form-publish" name="forum-post" type="checkbox"
|
||||
<#if forumSync> checked </#if> value="true"/>
|
||||
<input id="create-forum-post-version" class="form-check-input" form="form-publish" name="forum-post" type="checkbox" <#if forumSync> checked </#if> value="true">
|
||||
</div>
|
||||
<div class="clearfix"></div>
|
||||
</td>
|
||||
@ -149,30 +191,36 @@
|
||||
</#if>
|
||||
|
||||
<@form.form action=Routes.VERSIONS_UPLOAD.getRouteUrl(ownerName, projectSlug) method="POST"
|
||||
enctype="multipart/form-data" id="form-upload">
|
||||
enctype="multipart/form-data" id="form-upload" class="form-inline">
|
||||
<@csrf.formField />
|
||||
<label class="btn btn-default float-left" for="pluginFile">
|
||||
<label class="btn btn-info float-left" for="pluginFile">
|
||||
<input id="pluginFile" name="pluginFile" type="file" style="display: none;" accept=".jar,.zip">
|
||||
<@spring.message "version.create.selectFile" />
|
||||
</label>
|
||||
|
||||
<@alertFile.alertFile />
|
||||
</@form.form>
|
||||
|
||||
<#if pending??>
|
||||
<#-- Ready to go! -->
|
||||
<#assign version = pending>
|
||||
<@form.form method="POST" action=Routes.VERSIONS_PUBLISH.getRouteUrl(ownerName, projectSlug, version.versionString)
|
||||
id="form-publish" class="float-right">
|
||||
<#if !pending??>
|
||||
<@form.form action=Routes.VERSIONS_CREATE_EXTERNAL_URL.getRouteUrl(ownerName, projectSlug) method="POST" id="form-url-upload" class="form-inline">
|
||||
<@csrf.formField />
|
||||
<input type="hidden" class="channel-color-input" name="channel-color-input"
|
||||
value="${config.channels.colorDefault.hex}" />
|
||||
<div class="input-group float-right" style="width: 50%">
|
||||
<input type="text" class="form-control" id="externalUrl" name="externalUrl" placeholder="<@spring.message "version.create.externalUrl" />" style="width: 70%">
|
||||
<div class="input-group-append">
|
||||
<button class="btn btn-info" type="submit">Create Version</button>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<input type="submit" name="create" value="<@spring.message "version.create.publish" />"
|
||||
class="btn btn-primary" />
|
||||
</div>
|
||||
</@form.form>
|
||||
<#else>
|
||||
<#assign version = pending>
|
||||
<#assign formAction>
|
||||
<#if version.versionString??>${Routes.VERSIONS_PUBLISH.getRouteUrl(ownerName, projectSlug, version.versionString)}<#else>${Routes.VERSIONS_PUBLISH_URL.getRouteUrl(ownerName, projectSlug)}</#if>
|
||||
</#assign>
|
||||
<@form.form method="POST" action=formAction id="form-publish" class="float-right">
|
||||
<@csrf.formField />
|
||||
<input type="hidden" class="channel-color-input" name="channel-color-input" value="${config.channels.colorDefault.hex}">
|
||||
<div><input type="submit" name="create" value="<@spring.message "version.create.publish" />" class="btn btn-primary"></div>
|
||||
</@form.form>
|
||||
</#if>
|
||||
|
||||
</div>
|
||||
|
@ -7,8 +7,8 @@
|
||||
<#-- @ftlvariable name="isTargetChannelNonReviewed" type="java.lang.Boolean" -->
|
||||
<#assign message><@spring.message "version.download.confirm.title" /> <@spring.messageArgs code="version.download.confirm.header" args=[project.ownerName, project.name, target.versionString] /></#assign>
|
||||
<@base.base title=message>
|
||||
<div class="row">
|
||||
<div class="col-md-6 col-md-offset-3">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-6">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<div class="col-12 col-sm-4 no-padding">
|
||||
@ -22,14 +22,19 @@
|
||||
<div class="alert alert-danger" style="margin-bottom: 10px">
|
||||
<#assign ReviewState=@helper["io.papermc.hangar.model.generated.ReviewState"] />
|
||||
<#-- @ftlvariable name="ReviewState" type="io.papermc.hangar.model.generated.ReviewState" -->
|
||||
<#if isTargetChannelNonReviewed || target.reviewState == ReviewState.BACKLOG>
|
||||
<@spring.message "version.download.confirm.nonReviewedChannel" />
|
||||
<#elseif target.reviewState != ReviewState.PARTIALLY_REVIEWED>
|
||||
<@spring.message "version.download.confirm.reviewedChannel" />
|
||||
<#else>
|
||||
<@spring.message "version.download.confirmPartial.reviewedChannel" />
|
||||
</#if>
|
||||
<#if isTargetChannelNonReviewed || target.reviewState == ReviewState.BACKLOG>
|
||||
<@spring.message "version.download.confirm.nonReviewedChannel" />
|
||||
<#elseif target.reviewState != ReviewState.UNREVIEWED>
|
||||
<@spring.message "version.download.confirm.reviewedChannel" />
|
||||
<#elseif target.reviewState != ReviewState.PARTIALLY_REVIEWED>
|
||||
<@spring.message "version.download.confirmPartial.reviewedChannel" />
|
||||
</#if>
|
||||
</div>
|
||||
<#if target.isExternal()>
|
||||
<div class="alert alert-danger" style="margin-bottom: 10px">
|
||||
<@spring.message "version.download.confirm.externalUrl" />
|
||||
</div>
|
||||
</#if>
|
||||
<p>
|
||||
<@spring.message "general.disclaimer" />:
|
||||
<span class="text-italic"><@spring.message "version.download.confirm.disclaimer" /></span>
|
||||
|
@ -5,20 +5,6 @@
|
||||
<#import "*/projects/view.ftlh" as projects />
|
||||
<#import "*/utils/editor.ftlh" as editor />
|
||||
|
||||
<#--
|
||||
@import controllers.sugar.Requests.OreRequest
|
||||
@import models.viewhelper.{ScopedProjectData, VersionData}
|
||||
@import ore.OreConfig
|
||||
@import ore.data.Platform
|
||||
@import ore.markdown.MarkdownRenderer
|
||||
@import ore.models.project.{ReviewState, Visibility}
|
||||
@import ore.permission.Permission
|
||||
@import util.StringFormatterUtils._
|
||||
@import util.syntax._
|
||||
@import views.html.helper.{CSRF, form}
|
||||
@import views.html.utils.editor
|
||||
@(v: VersionData, sp: ScopedProjectData)(implicit messages: Messages, request: OreRequest[_], flash: Flash, config: OreConfig, renderer: MarkdownRenderer, assetsFinder: AssetsFinder)-->
|
||||
|
||||
<#assign ReviewState=@helper["io.papermc.hangar.model.generated.ReviewState"] />
|
||||
<#assign Permission=@helper["io.papermc.hangar.model.Permission"] />
|
||||
<#assign Visibility=@helper["io.papermc.hangar.model.Visibility"] />
|
||||
@ -116,16 +102,20 @@
|
||||
|
||||
<div class="btn-group btn-download">
|
||||
<a href="${Routes.VERSIONS_DOWNLOAD.getRouteUrl(v.p.project.ownerName, v.p.project.slug, v.v.versionString, "", "")}"
|
||||
title="<@spring.message "project.download.recommend" />" data-toggle="tooltip"
|
||||
data-placement="bottom" class="btn btn-primary">
|
||||
<i class="fas fa-download"></i> <@spring.message "general.download" />
|
||||
title="<@spring.message "project.download.recommend" />" data-toggle="tooltip"
|
||||
data-placement="bottom" class="btn btn-primary">
|
||||
<i class="fas fa-download"></i>
|
||||
<#if v.v.externalUrl??>
|
||||
<@spring.message "general.downloadExternal" />
|
||||
<#else>
|
||||
<@spring.message "general.download" />
|
||||
</#if>
|
||||
</a>
|
||||
<button type="button" class="btn btn-primary dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
<span class="caret"></span>
|
||||
<span class="sr-only">Toggle Dropdown</span>
|
||||
</button>
|
||||
<div class="dropdown-menu dropdown-menu-right">
|
||||
<a href="${Routes.VERSIONS_DOWNLOAD.getRouteUrl(v.p.project.ownerName, v.p.project.slug, v.v.versionString, "", "")}" class="dropdown-item"><@spring.message "general.download" /></a>
|
||||
<a class="dropdown-item" href="${Routes.VERSIONS_DOWNLOAD.getRouteUrl(v.p.project.ownerName, v.p.project.slug, v.v.versionString, "", "")}"><@spring.message "general.download" /></a>
|
||||
<a href="#" class="copy-url dropdown-item" data-clipboard-text="${config.baseUrl}${Routes.VERSIONS_DOWNLOAD.getRouteUrl(v.p.project.ownerName, v.p.project.slug, v.v.versionString, "", "")}">Copy URL</a>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -26,7 +26,7 @@ Base template for Project overview.
|
||||
</#assign>
|
||||
|
||||
<#assign metaVar>
|
||||
<meta property="og:title" content="${p.project.ownerName} / ${p.project.name}" />
|
||||
<meta property="og:title" content="${p.project.ownerName}/${p.project.name}" />
|
||||
<meta property="og:type" content="website" />
|
||||
<meta property="og:url" content="${Routes.PROJECTS_SHOW.getRouteUrl(p.project.ownerName, p.project.slug)}" />
|
||||
<meta property="og:image" content="${p.iconUrl}" />
|
||||
|
@ -2,10 +2,9 @@
|
||||
<#import "*/utils/hangar.ftlh" as hangar />
|
||||
<#import "*/layout/base.ftlh" as base />
|
||||
|
||||
@import controllers.sugar.Requests.OreRequest
|
||||
@import ore.OreConfig
|
||||
@(title: String, recipient: String, body: String)(implicit messages: Messages, request: OreRequest[_], config: OreConfig, flash: Flash, assetsFinder: AssetsFinder)
|
||||
|
||||
<#-- @ftlvariable name="title" type="java.lang.String" -->
|
||||
<#-- @ftlvariable name="recipient" type="java.lang.String" -->
|
||||
<#-- @ftlvariable name="body" type="java.lang.String" -->
|
||||
<#assign message><@spring.message title /></#assign>
|
||||
<@base.base title=message scriptsEnabled=false showHeader=false showFooter=false>
|
||||
<div class="container">
|
||||
|
Loading…
x
Reference in New Issue
Block a user