Add license validations

This commit is contained in:
Nassim Jahnke 2022-12-29 15:01:25 +01:00
parent b46ac2a719
commit 1c7b8be3ce
No known key found for this signature in database
GPG Key ID: 6BE3B555EBC5982B
8 changed files with 41 additions and 8 deletions

View File

@ -12,8 +12,10 @@ import org.springframework.boot.convert.DurationUnit;
public record ProjectsConfig( // TODO split into ProjectsConfig and VersionsConfig
@DefaultValue("^[a-zA-Z0-9-_]{3,}$") PatternWrapper nameRegex,
@DefaultValue("^[a-zA-Z0-9-_.+]+$") PatternWrapper versionNameRegex,
@DefaultValue("^[a-zA-Z0-9-_.() +]*$") PatternWrapper licenseNameRegex,
@DefaultValue("25") int maxNameLen,
@DefaultValue("30") int maxVersionNameLen,
@DefaultValue("15") int maxLicenseNameLen,
@DefaultValue("100") int maxDependencies,
@DefaultValue("50") int maxPages,
@DefaultValue("5") int maxChannels,
@ -37,6 +39,10 @@ public record ProjectsConfig( // TODO split into ProjectsConfig and VersionsConf
return new Validation(this.nameRegex(), this.maxNameLen(), null);
}
public Validation licenseName() {
return new Validation(this.licenseNameRegex(), this.maxLicenseNameLen(), null);
}
public Validation projectDescription() {
return Validation.max(this.maxDescLen());
}

View File

@ -11,13 +11,17 @@ public class ProjectLicense {
private static final HangarConfig config = StaticContextAccessor.getBean(HangarConfig.class);
private final String name;
// @el(root: String)
private final @Validate(SpEL = "@validations.regex(#root, @hangarConfig.projects.licenseNameRegex)", message = "project.new.error.invalidLicense")
@Validate(SpEL = "@validations.max(#root, @hangarConfig.projects.maxLicenseNameLen)", message = "project.new.error.tooLongLicense") String name;
// @el(root: String)
private final @Validate(SpEL = "@validate.regex(#root, @hangarConfig.urlRegex)", message = "validation.invalidUrl") String url;
// @el(root: String)
private final @Validate(SpEL = "@validate.required(#root)") String type;
private final @Validate(SpEL = "@validate.required(#root)")
@Validate(SpEL = "@validations.regex(#root, @hangarConfig.projects.licenseNameRegex)", message = "project.new.error.invalidLicense")
@Validate(SpEL = "@validations.max(#root, @hangarConfig.projects.maxLicenseNameLen)", message = "project.new.error.tooLongLicense") String type;
@JsonCreator
@JdbiConstructor
@ -35,7 +39,7 @@ public class ProjectLicense {
return this.name;
}
public String getUrl() {
public @Nullable String getUrl() {
return this.url;
}

View File

@ -17,6 +17,7 @@ public record Validations(
public record Project(
Validation name,
Validation desc,
Validation license,
Validation keywords,
Validation channels,
Validation pageName,
@ -30,6 +31,7 @@ public record Validations(
final Project project = new Project(
config.projects.projectName(),
config.projects.projectDescription(),
config.projects.licenseName(),
config.projects.projectKeywords(),
config.channels.channelName(),
config.pages.pageName(),

View File

@ -102,6 +102,7 @@ hangar:
projects:
max-name-len: 25
max-version-name-len: 30
max-license-name-len: 15
max-dependencies: 100
max-pages: 50
max-bbcode-len: 20000
@ -121,6 +122,7 @@ hangar:
show-unreviewed-download-warning: false
name-regex: "^[a-zA-Z0-9-_]{3,}$"
version-name-regex: "^[a-zA-Z0-9-_.+]+$"
license-name-regex: "^[a-zA-Z0-9-_.() +]*$"
orgs:
create-limit: 5

View File

@ -272,6 +272,8 @@
"tooLongName": "Project name is too long",
"tooShortName": "This name is too short",
"tooLongDesc": "Project description is too long",
"tooLongLicense": "License name is too long",
"invalidLicense": "License name is invalid",
"tooLongSponsors": "Project sponsor box is too long",
"tooManyKeywords": "Project has too many keywords",
"noCategory": "Project must have a category",

View File

@ -27,7 +27,7 @@ import { useNotificationStore } from "~/lib/store/notification";
import InputTag from "~/lib/components/ui/InputTag.vue";
import TextAreaModal from "~/lib/components/modals/TextAreaModal.vue";
import ProjectSettingsSection from "~/components/projects/ProjectSettingsSection.vue";
import { maxLength, required, requiredIf, url } from "~/lib/composables/useValidationHelpers";
import { maxLength, required, pattern, requiredIf, url } from "~/lib/composables/useValidationHelpers";
import { validProjectName } from "~/composables/useHangarValidations";
import "vue-advanced-cropper/dist/style.css";
@ -352,12 +352,20 @@ useHead(
<InputText v-model.trim="form.settings.wiki" :label="i18n.t('project.new.step3.wiki')" :rules="[url()]" />
</ProjectSettingsSection>
<ProjectSettingsSection title="project.settings.license" description="project.settings.licenseSub">
<div class="flex">
<div class="flex md:gap-2 <md:flex-wrap">
<div class="basis-full" :md="isCustomLicense ? 'basis-4/12' : 'basis-6/12'">
<InputSelect v-model="form.settings.license.type" :values="useLicenseOptions" :label="i18n.t('project.settings.licenseType')" />
</div>
<div v-if="isCustomLicense" class="basis-full md:basis-8/12">
<InputText v-model.trim="form.settings.license.name" :label="i18n.t('project.settings.licenseCustom')" />
<InputText
v-model.trim="form.settings.license.name"
:label="i18n.t('project.settings.licenseCustom')"
:rules="[
requiredIf()(isCustomLicense),
maxLength()(useBackendData.validations?.project?.license?.max),
pattern()(useBackendData.validations?.project?.license?.regex),
]"
/>
</div>
<div v-if="!isUnspecifiedLicense" class="basis-full" :md="isCustomLicense ? 'basis-full' : 'basis-6/12'">
<InputText v-model.trim="form.settings.license.url" :label="i18n.t('project.settings.licenseUrl')" :rules="[url()]" />

View File

@ -230,12 +230,20 @@ function createProject() {
{{ i18n.t("project.new.step3.license") }}
<hr />
</div>
<div class="flex flex-wrap">
<div class="flex md:gap-2 <md:flex-wrap">
<div class="basis-full mt-4" :md="isCustomLicense ? 'basis-4/12' : 'basis-6/12'">
<InputSelect v-model="form.settings.license.type" :values="useLicenseOptions" :label="i18n.t('project.new.step3.type')" :rules="[required()]" />
</div>
<div v-if="isCustomLicense" class="basis-full md:basis-8/12 mt-4">
<InputText v-model.trim="form.settings.license.name" :label="i18n.t('project.new.step3.customName')" :rules="[requiredIf()(isCustomLicense)]" />
<InputText
v-model.trim="form.settings.license.name"
:label="i18n.t('project.new.step3.customName')"
:rules="[
requiredIf()(isCustomLicense),
maxLength()(useBackendData.validations.project.license.max),
pattern()(useBackendData.validations.project.license.regex),
]"
/>
</div>
<div v-if="!licenseUnset" class="basis-full mt-4" :md="isCustomLicense ? 'basis-full' : 'basis-6/12'">
<InputText v-model.trim="form.settings.license.url" :label="i18n.t('project.new.step3.url')" :rules="[url()]" />

View File

@ -45,6 +45,7 @@ declare module "hangar-api" {
project: {
name: Validation;
desc: Validation;
license: Validation;
keywords: Validation;
channels: Validation;
pageName: Validation;