Some more validation, add sponsors section to guidelines

This commit is contained in:
Nassim Jahnke 2022-04-04 16:23:40 +02:00
parent 6b11854f46
commit c2b65fcf3d
No known key found for this signature in database
GPG Key ID: 6BE3B555EBC5982B
12 changed files with 70 additions and 12 deletions

View File

@ -5,13 +5,19 @@ import Markdown from "~/components/Markdown.vue";
import Button from "~/components/design/Button.vue";
import DeletePageModal from "~/components/modals/DeletePageModal.vue";
const props = defineProps<{
raw: string;
editing: boolean;
deletable: boolean;
cancellable: boolean;
saveable: boolean;
}>();
const props = withDefaults(
defineProps<{
raw: string;
editing: boolean;
deletable: boolean;
cancellable: boolean;
saveable: boolean;
maxlength?: number;
}>(),
{
maxlength: 30_000,
}
);
const emit = defineEmits<{
(e: "save", edited: string): void;
@ -56,7 +62,7 @@ function deletePage() {
<template>
<div class="relative">
<div v-show="internalEditing && !preview" class="pl-10">
<InputTextarea v-model="rawEdited" :rows="rawEdited.split(/\r\n|\r|\n/g).length + 3"></InputTextarea>
<InputTextarea v-model="rawEdited" :rows="rawEdited.split(/\r\n|\r|\n/g).length + 3" :maxlength="maxlength" counter></InputTextarea>
</div>
<Markdown v-show="!internalEditing" :raw="raw" class="pl-5" />
<Markdown v-if="preview" :raw="rawEdited" class="pl-5" />

View File

@ -249,6 +249,7 @@
"lastUpdatedTooltip": "Last updated {0}"
},
"promotedVersions": "Promoted Versions",
"sponsors": "Sponsors",
"license": {
"link": "Licensed under "
},

View File

@ -27,13 +27,16 @@ const context = useContext();
const router = useRouter();
const { editingPage, open, savePage, page } = await useProjectPage(route, router, context, i18n, props.project);
//TODO Save/load in/from project
const sponsors = "It is I, sponsor man";
useHead(useSeo(props.project.name, props.project.description, route, projectIconUrl(props.project.namespace.owner, props.project.namespace.slug)));
</script>
<template>
<div class="flex flex-wrap md:flex-nowrap gap-4">
<section class="basis-full md:basis-9/12 flex-grow overflow-auto">
<Card class="p-0">
<Card class="p-0 overflow-clip">
<MarkdownEditor
v-if="hasPerms(NamedPermission.EDIT_PAGE)"
ref="editor"
@ -46,6 +49,22 @@ useHead(useSeo(props.project.name, props.project.description, route, projectIcon
/>
<Markdown v-else :raw="page.contents" />
</Card>
<Card v-if="sponsors" class="mt-2 pl-3 p-0 overflow-clip">
<h1 class="mt-5 ml-5 text-xl">{{ i18n.t("project.sponsors") }}</h1>
<!-- todo -->
<!--<MarkdownEditor
v-if="hasPerms(NamedPermission.EDIT_PAGE)"
ref="editor"
v-model:editing="editingPage"
:raw="sponsors"
:deletable="false"
:saveable="true"
:cancellable="true"
:maxlength="500"
@save="savePage"
/>-->
<Markdown v-if="sponsors?.length !== 0" :raw="sponsors"
/></Card>
</section>
<section class="basis-full md:basis-3/12 space-y-4 min-w-280px">
<ProjectInfo :project="project"></ProjectInfo>

View File

@ -9,7 +9,7 @@ import Markdown from "~/components/Markdown.vue";
const i18n = useI18n();
const route = useRoute();
// TODO Discuss and write proper guideliness, move to docs site, remove table
// TODO Discuss and write proper guideliness, move to docs site
const text = `
Remember that these are just guidelines and that the Hangar team may choose to allow or disallow an action that is not
explicitly listed here at our own discretion.
@ -57,6 +57,12 @@ On the resource page, you may link to the following:
* Donation links - you can also go to your project's donation settings to display them more prominently
* Paid subscription services (such as Patreon) to receive early previews of upcoming, free releases
### Sponsors
In project settings, you are given a text area to write sponsors into. Listed sponsors may only be donators (for example
one-time donators or Patreon subscribers) or OSS license sponsors (for example when being provided IntelliJ, YourKit, or
JProfiler license keys). Use this field in moderation and keep it secondary to your project's documentation. Only
information about sponsors may be put into the sponsors field.
## Obfuscation
To circumvent license issues and the effort involved in reviewing obfuscated code, we do not allow submitted plugins to be obfuscated in any capacity.

View File

@ -24,6 +24,7 @@ public class ProjectsConfig {
private int maxPageNameLen = 25;
private int maxPages = 50;
private int maxChannels = 5;
private int maxBBCodeLen = 30_000;
private int initLoad = 25;
private int initVersionLoad = 10;
private int maxDescLen = 120;
@ -115,6 +116,14 @@ public class ProjectsConfig {
this.maxChannels = maxChannels;
}
public void setMaxBBCodeLen(int maxBBCodeLen) {
this.maxBBCodeLen = maxBBCodeLen;
}
public int getMaxBBCodeLen() {
return maxBBCodeLen;
}
public int getInitLoad() {
return initLoad;
}

View File

@ -103,6 +103,10 @@ public class VersionController extends HangarComponent {
@PermissionRequired(type = PermissionType.PROJECT, perms = NamedPermission.EDIT_VERSION, args = "{#projectId}")
@PostMapping(path = "/version/{projectId}/{versionId}/saveDescription", consumes = MediaType.APPLICATION_JSON_VALUE)
public void saveDescription(@PathVariable long projectId, @PathVariable long versionId, @Valid @RequestBody StringContent stringContent) {
if (stringContent.getContent().length() > config.pages.getMaxLen()) {
throw new HangarApiException(HttpStatus.BAD_REQUEST, "page.new.error.maxLength");
}
ProjectVersionTable projectVersionTable = versionService.getProjectVersionTable(versionId);
if (projectVersionTable == null) {
throw new HangarApiException(HttpStatus.NOT_FOUND);

View File

@ -51,6 +51,9 @@ public class ProjectPageController extends HangarComponent {
@Anyone
@PostMapping(path = "/render", produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<String> renderMarkdown(@RequestBody @Valid StringContent content) {
if (content.getContent().length() > 1_000_000) { //TODO
throw new HangarApiException("page.new.error.name.maxLength");
}
return ResponseEntity.ok(markdownService.render(content.getContent()));
}
@ -58,6 +61,9 @@ public class ProjectPageController extends HangarComponent {
@ResponseBody
@PostMapping(path = "/convert-bbcode", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.TEXT_PLAIN_VALUE)
public String convertBBCode(@RequestBody @Valid StringContent bbCodeContent) {
if (bbCodeContent.getContent().length() > config.projects.getMaxBBCodeLen()) {
throw new HangarApiException("page.new.error.name.maxLength");
}
BBCodeConverter bbCodeConverter = new BBCodeConverter();
return bbCodeConverter.convertToMarkdown(bbCodeContent.getContent());
}

View File

@ -13,6 +13,7 @@ public class NewProjectForm extends ProjectSettingsForm {
@Validate(SpEL = "@validate.max(#root, @hangarConfig.projects.maxNameLen)", message = "project.new.error.tooLongName")
@Validate(SpEL = "@validate.regex(#root, @hangarConfig.projects.nameRegex)", message = "project.new.error.invalidName")
private final String name;
@Validate(SpEL = "@validate.max(#root, @hangarConfig.pages.maxLen)", message = "page.new.error.maxLength")
private final String pageContent;
public NewProjectForm(ProjectSettings settings, Category category, String description, long ownerId, String name, String pageContent) {

View File

@ -31,6 +31,7 @@ public class PendingVersion {
@Size(min = 1, max = 3, message = "version.new.error.invalidNumOfPlatforms")
private final Map<Platform, @Size(min = 1, message = "version.edit.error.noPlatformVersions") SortedSet<@NotBlank(message = "version.new.error.invalidPlatformVersion") String>> platformDependencies;
@NotBlank(message = "version.new.error.noDescription")
@Validate(SpEL = "@validate.max(#root, @hangarConfig.pages.maxLen)", message = "page.new.error.maxLength")
private final String description;
private final FileInfo fileInfo;
@Validate(SpEL = "@validate.optionalRegex(#root, @hangarConfig.urlRegex)", message = "validation.invalidUrl")

View File

@ -13,7 +13,7 @@ public class ValidationService {
private final HangarConfig config;
private static final Set<String> bannedRoutes = Set.of("api", "authors", "linkout", "logged-out", "new", "notifications", "staff", "admin", "organizations", "tools", "recommended", "null", "undefined");
private static final Set<String> bannedRoutes = Set.of("api", "authors", "linkout", "logged-out", "new", "notifications", "staff", "admin", "organizations", "tools", "recommended", "null", "undefined", "tos");
public ValidationService(HangarConfig config) {
this.config = config;

View File

@ -48,7 +48,7 @@ public class ProjectPageService extends HangarComponent {
throw new HangarApiException(HttpStatus.BAD_REQUEST, "page.new.error.minLength");
}
if (contents.length() > config.pages.getMaxLen()) {
if (contents.length() > config.pages.getMaxLen()) {
throw new HangarApiException(HttpStatus.BAD_REQUEST, "page.new.error.maxLength");
}
@ -134,6 +134,10 @@ public class ProjectPageService extends HangarComponent {
@Transactional
public void saveProjectPage(long projectId, long pageId, String newContents) {
if (newContents.length() > config.pages.getMaxLen()) {
throw new HangarApiException(HttpStatus.BAD_REQUEST, "page.new.error.maxLength");
}
ProjectPageTable pageTable = projectPagesDAO.getProjectPage(projectId, pageId);
if (pageTable == null) {
throw new HangarApiException(HttpStatus.NOT_FOUND, "No page found");

View File

@ -103,6 +103,7 @@ hangar:
projects:
max-name-len: 25
max-pages: 50
max-bbcode-len: 20000
max-channels: 5
init-load: 25
init-version-load: 10