Skip to content

Commit

Permalink
refactor: allow consecutive dashes in identifier regex
Browse files Browse the repository at this point in the history
Also added tests to validate the regex, and the difference between
identifiers and user identifiers.
  • Loading branch information
edvald committed Jan 30, 2019
1 parent 8a21abc commit 37fe9c3
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 24 deletions.
12 changes: 8 additions & 4 deletions docs/reference/config.md
Original file line number Diff line number Diff line change
Expand Up @@ -506,8 +506,8 @@ module:
# Optional.
dependencies:
# Valid RFC1035/RFC1123 (DNS) label (may contain lowercase letters, numbers and dashes,
# must start with a letter, and cannot end with a dash) and additionally cannot contain
# consecutive dashes, or be longer than 63 characters.
# must start with a letter, and cannot end with a dash) and must not be longer than 63
# characters.
#
# Optional.
-
Expand Down Expand Up @@ -854,12 +854,16 @@ module:
# Optional.
dependencies:
# Valid RFC1035/RFC1123 (DNS) label (may contain lowercase letters, numbers and dashes, must
# start with a letter, and cannot end with a dash) and additionally cannot contain consecutive
# dashes, or be longer than 63 characters.
# start with a letter, and cannot end with a dash) and must not be longer than 63 characters.
#
# Optional.
-

# Optionally override the release name used when installing (defaults to the module name).
#
# Optional.
releaseName:

# The repository URL to fetch the chart from.
#
# Optional.
Expand Down
9 changes: 4 additions & 5 deletions garden-service/src/config/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,24 +30,23 @@ export const joiPrimitive = () => Joi.alternatives().try(Joi.number(), Joi.strin
.description("Number, string or boolean")

export const absolutePathRegex = /^\/.*/ // Note: Only checks for the leading slash
export const identifierRegex = /^[a-z][a-z0-9]*(-[a-z0-9]+)*$/
export const userIdentifierRegex = /^(?!garden)[a-z][a-z0-9]*(-[a-z0-9]+)*$/
// from https://stackoverflow.com/a/12311250/3290965
export const identifierRegex = /^(?![0-9]+$)(?!.*-$)(?!-)[a-z0-9-]{1,63}$/
export const userIdentifierRegex = /^(?!garden)(?=.{1,63}$)[a-z][a-z0-9]*(-[a-z0-9]+)*$/
export const envVarRegex = /^(?!garden)[a-z_][a-z0-9_]*$/i

export const joiIdentifier = () => Joi.string()
.regex(identifierRegex)
.max(63)
.description(
"Valid RFC1035/RFC1123 (DNS) label (may contain lowercase letters, numbers and dashes, must start with a letter, " +
"and cannot end with a dash) and additionally cannot contain consecutive dashes, or be longer than 63 characters.",
"and cannot end with a dash) and must not be longer than 63 characters.",
)

export const joiStringMap = (valueSchema: JoiObject) => Joi
.object().pattern(/.+/, valueSchema)

export const joiUserIdentifier = () => Joi.string()
.regex(userIdentifierRegex)
.max(63)
.description(
"Valid RFC1035/RFC1123 (DNS) label (may contain lowercase letters, numbers and dashes, must start with a letter, " +
"and cannot end with a dash), cannot contain consecutive dashes or start with `garden`, " +
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { expect } from "chai"
import * as Joi from "joi"
const stripAnsi = require("strip-ansi")
import { identifierRegex, validate, envVarRegex } from "../../../src/config/common"
import { identifierRegex, validate, envVarRegex, userIdentifierRegex } from "../../../src/config/common"
import { expectError } from "../../helpers"

describe("envVarRegex", () => {
Expand Down Expand Up @@ -38,33 +38,73 @@ describe("envVarRegex", () => {
})
})

const validIdentifiers = {
"myname": "a valid identifier",
"my-name": "a valid identifier with a dash",
"my9-9name": "numbers in the middle of a string",
"o12345670123456701234567012345670123456701234567012345670123456": "a 63 char identifier",
"a": "a single char identifier",
}

const invalidIdentifiers = {
"01010": "string with only numbers",
"-abc": "starting with a dash",
"abc-": "ending with a dash",
"": "an empty string",
"o123456701234567012345670123456701234567012345670123456701234567": "a 64 char identifier",
"UPPER": "an uppercase string",
"upPer": "a partially uppercase string",
}

describe("identifierRegex", () => {
it("should accept a valid identifier", () => {
expect(identifierRegex.test("my-name")).to.be.true
})
for (const [value, description] of Object.entries(validIdentifiers)) {
it("should allow " + description, () => {
expect(identifierRegex.test(value)).to.be.true
})
}

for (const [value, description] of Object.entries(invalidIdentifiers)) {
it("should disallow " + description, () => {
expect(identifierRegex.test(value)).to.be.false
})
}

it("should allow numbers in middle of the string", () => {
expect(identifierRegex.test("my9-9name")).to.be.true
it("should allow consecutive dashes", () => {
expect(identifierRegex.test("my--name")).to.be.true
})

it("should disallow ending with a dash", () => {
expect(identifierRegex.test("my-name-")).to.be.false
it("should allow starting with a number", () => {
expect(identifierRegex.test("9name")).to.be.true
})

it("should disallow uppercase characters", () => {
expect(identifierRegex.test("myName")).to.be.false
it("should allow strings starting with 'garden'", () => {
expect(identifierRegex.test("garden-party")).to.be.true
})
})

describe("userIdentifierRegex", () => {
for (const [value, description] of Object.entries(validIdentifiers)) {
it("should allow " + description, () => {
expect(userIdentifierRegex.test(value)).to.be.true
})
}

for (const [value, description] of Object.entries(invalidIdentifiers)) {
it("should disallow " + description, () => {
expect(userIdentifierRegex.test(value)).to.be.false
})
}

it("should disallow starting with a dash", () => {
expect(identifierRegex.test("-my-name")).to.be.false
it("should allow consecutive dashes", () => {
expect(userIdentifierRegex.test("my--name")).to.be.false
})

it("should disallow starting with a number", () => {
expect(identifierRegex.test("9name")).to.be.false
expect(userIdentifierRegex.test("9name")).to.be.false
})

it("should disallow consecutive dashes", () => {
expect(identifierRegex.test("my--name")).to.be.false
it("should allow strings starting with 'garden'", () => {
expect(userIdentifierRegex.test("garden-party")).to.be.false
})
})

Expand Down

0 comments on commit 37fe9c3

Please sign in to comment.