fix: validation rules
This commit is contained in:
parent
95fbc5167a
commit
4b9a7613fa
@ -7,8 +7,8 @@
|
||||
persist: ['data']
|
||||
network:
|
||||
# valid values for interface: ['public', 'local']
|
||||
interface: ''
|
||||
port: 5432
|
||||
interface: 'public'
|
||||
port: 1
|
||||
domain: 'db.foo.org'
|
||||
ssl: false
|
||||
pg_admin:
|
||||
@ -20,8 +20,8 @@
|
||||
allowed_ssh_public_keys: ['ssh-ed25519 <snip> my special ssh key']
|
||||
persist: []
|
||||
network:
|
||||
interface: ''
|
||||
port: 5432
|
||||
interface: 'public'
|
||||
port: 2
|
||||
domain: 'api.foo.org'
|
||||
ssl: true
|
||||
- ui:
|
||||
@ -30,7 +30,7 @@
|
||||
allowed_ssh_public_keys: ['ssh-ed25519 <snip> my special ssh key']
|
||||
persist: []
|
||||
network:
|
||||
interface: ''
|
||||
port: 5432
|
||||
interface: 'public'
|
||||
port: 3
|
||||
domain: 'foo.org'
|
||||
ssl: true
|
||||
|
@ -8,8 +8,10 @@ const parseSegmentLinuxUser = (o) =>
|
||||
"linux_user" in o
|
||||
? "username" in o.linux_user
|
||||
? Either.right({
|
||||
username: o.linux_user.username,
|
||||
allowedSshPublicKeys: o.allowed_ssh_public_keys || [],
|
||||
username: o.linux_user.username.trim(),
|
||||
allowedSshPublicKeys: (o.allowed_ssh_public_keys || []).map(
|
||||
(pubkey) => pubkey.trim()
|
||||
),
|
||||
})
|
||||
: Either.left(new Error("linux_user.username required"))
|
||||
: Either.left(new Error("linux_user required"));
|
||||
@ -45,7 +47,10 @@ const parseSegmentPgAdmin = flow(
|
||||
)
|
||||
)
|
||||
),
|
||||
Either.map((pg) => ({ username: pg.username, password: pg.password }))
|
||||
Either.map((pg) => ({
|
||||
username: pg.username.trim(),
|
||||
password: pg.password.trim(),
|
||||
}))
|
||||
);
|
||||
|
||||
const parseSegmentNetwork = flow(
|
||||
@ -68,39 +73,56 @@ const parseSegmentNetwork = flow(
|
||||
)
|
||||
),
|
||||
Either.flatMap((n) =>
|
||||
"port" in n
|
||||
? Either.right(n)
|
||||
: Either.left(
|
||||
new Error(
|
||||
["network.port required", `in: ${JSON.stringify(n)}`].join("\n")
|
||||
)
|
||||
)
|
||||
),
|
||||
Either.flatMap((n) =>
|
||||
"domain" in n
|
||||
"port" in n && typeof n.port === "number" && Number.isInteger(n.port)
|
||||
? Either.right(n)
|
||||
: Either.left(
|
||||
new Error(
|
||||
[
|
||||
"network.domain required",
|
||||
" (to not listen on a public domain, set this property to empty string '')",
|
||||
"network.port required and must be an integer",
|
||||
`in: ${JSON.stringify(n)}`,
|
||||
].join("\n")
|
||||
)
|
||||
)
|
||||
),
|
||||
Either.flatMap((n) =>
|
||||
"ssl" in n
|
||||
n.interface === 'public' || (n.interface === "local" && !"domain" in n)
|
||||
? Either.right(n)
|
||||
: Either.left(
|
||||
new Error(
|
||||
["network.ssl required", `in: ${JSON.stringify(n)}`].join("\n")
|
||||
[
|
||||
"network.interface is 'local', network.domain must not be present.",
|
||||
`in: ${JSON.stringify(n)}`,
|
||||
].join("\n")
|
||||
)
|
||||
)
|
||||
),
|
||||
Either.flatMap((n) =>
|
||||
n.interface === 'public' && "domain" in n && typeof n.domain === "string" && n.domain.length > 0
|
||||
? Either.right(n)
|
||||
: Either.left(
|
||||
new Error(
|
||||
[
|
||||
"network.interface is 'public', network.domain be set to a value.",
|
||||
`in: ${JSON.stringify(n)}`,
|
||||
].join("\n")
|
||||
)
|
||||
)
|
||||
),
|
||||
Either.flatMap((n) =>
|
||||
"ssl" in n && typeof n.ssl === "boolean"
|
||||
? Either.right(n)
|
||||
: Either.left(
|
||||
new Error(
|
||||
[
|
||||
"network.ssl required and must be a bool",
|
||||
`in: ${JSON.stringify(n)}`,
|
||||
].join("\n")
|
||||
)
|
||||
)
|
||||
),
|
||||
Either.map((n) => ({
|
||||
ssl: n.ssl,
|
||||
domain: n.domain || undefined,
|
||||
domain: (n.domain || "").trim(),
|
||||
interface: n.interface,
|
||||
port: n.port,
|
||||
}))
|
||||
@ -153,13 +175,31 @@ const parseService = (svc) =>
|
||||
)
|
||||
);
|
||||
|
||||
const ensureUniq = ({getWith, onConflict, isConflict}) => array => pipe(array,
|
||||
Array_.map(getWith),
|
||||
Array_.reduce(Either.right([]), (res, cur) =>
|
||||
Either.flatMap(seen =>
|
||||
isConflict(seen, cur)
|
||||
? Either.left(onConflict(cur))
|
||||
: Either.right([...seen, cur])
|
||||
)(res)
|
||||
),
|
||||
Either.map(() => array)
|
||||
);
|
||||
const ensureServicesDoNotOverlap = flow(
|
||||
ensureUniq({getWith: s => s.linuxUser.username, onConflict: usr => new Error(`linux_user.username must be unique: ${usr}`), isConflict: (seen, cur) => seen.includes(cur)}),
|
||||
Either.flatMap(ensureUniq({getWith: s => s.network.port, onConflict: port => new Error(`network.port must be unique: ${port}`), isConflict: (seen, cur) => seen.includes(cur)})),
|
||||
Either.flatMap(ensureUniq({getWith: s => s.network.domain, onConflict: domain => new Error(`network.domain must be unique: ${domain}`), isConflict: (seen, cur) => seen.includes(cur)}))
|
||||
);
|
||||
|
||||
const parse = flow(
|
||||
(cfg) => Either.tryCatch(() => yaml.parse(cfg), id),
|
||||
Either.filterOrElse(
|
||||
(p) => p instanceof Array,
|
||||
() => new Error("config must have top-level array elements")
|
||||
),
|
||||
Either.flatMap((svcs) => Either.sequenceArray(svcs.map(parseService)))
|
||||
Either.flatMap((svcs) => Either.sequenceArray(svcs.map(parseService))),
|
||||
Either.tap(ensureServicesDoNotOverlap)
|
||||
);
|
||||
|
||||
module.exports = { parse };
|
||||
|
Loading…
Reference in New Issue
Block a user