fix: permissions wildcarding so that for ex: 'ls *' includes ls * AND 'ls' to prevent having to double state commands or use 'ls*'
This commit is contained in:
@@ -2,16 +2,18 @@ import { sortBy, pipe } from "remeda"
|
|||||||
|
|
||||||
export namespace Wildcard {
|
export namespace Wildcard {
|
||||||
export function match(str: string, pattern: string) {
|
export function match(str: string, pattern: string) {
|
||||||
const regex = new RegExp(
|
let escaped = pattern
|
||||||
"^" +
|
.replace(/[.+^${}()|[\]\\]/g, "\\$&") // escape special regex chars
|
||||||
pattern
|
.replace(/\*/g, ".*") // * becomes .*
|
||||||
.replace(/[.+^${}()|[\]\\]/g, "\\$&") // escape special regex chars
|
.replace(/\?/g, ".") // ? becomes .
|
||||||
.replace(/\*/g, ".*") // * becomes .*
|
|
||||||
.replace(/\?/g, ".") + // ? becomes .
|
// If pattern ends with " *" (space + wildcard), make the trailing part optional
|
||||||
"$",
|
// This allows "ls *" to match both "ls" and "ls -la"
|
||||||
"s", // s flag enables multiline matching
|
if (escaped.endsWith(" .*")) {
|
||||||
)
|
escaped = escaped.slice(0, -3) + "( .*)?"
|
||||||
return regex.test(str)
|
}
|
||||||
|
|
||||||
|
return new RegExp("^" + escaped + "$", "s").test(str)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function all(input: string, patterns: Record<string, any>) {
|
export function all(input: string, patterns: Record<string, any>) {
|
||||||
|
|||||||
@@ -7,6 +7,26 @@ test("match handles glob tokens", () => {
|
|||||||
expect(Wildcard.match("foo+bar", "foo+bar")).toBe(true)
|
expect(Wildcard.match("foo+bar", "foo+bar")).toBe(true)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test("match with trailing space+wildcard matches command with or without args", () => {
|
||||||
|
// "ls *" should match "ls" (no args) and "ls -la" (with args)
|
||||||
|
expect(Wildcard.match("ls", "ls *")).toBe(true)
|
||||||
|
expect(Wildcard.match("ls -la", "ls *")).toBe(true)
|
||||||
|
expect(Wildcard.match("ls foo bar", "ls *")).toBe(true)
|
||||||
|
|
||||||
|
// "ls*" (no space) should NOT match "ls" alone — wait, it should because .* matches empty
|
||||||
|
// but it WILL match "lstmeval" which is the dangerous case users should avoid
|
||||||
|
expect(Wildcard.match("ls", "ls*")).toBe(true)
|
||||||
|
expect(Wildcard.match("lstmeval", "ls*")).toBe(true)
|
||||||
|
|
||||||
|
// "ls *" (with space) should NOT match "lstmeval"
|
||||||
|
expect(Wildcard.match("lstmeval", "ls *")).toBe(false)
|
||||||
|
|
||||||
|
// multi-word commands
|
||||||
|
expect(Wildcard.match("git status", "git *")).toBe(true)
|
||||||
|
expect(Wildcard.match("git", "git *")).toBe(true)
|
||||||
|
expect(Wildcard.match("git commit -m foo", "git *")).toBe(true)
|
||||||
|
})
|
||||||
|
|
||||||
test("all picks the most specific pattern", () => {
|
test("all picks the most specific pattern", () => {
|
||||||
const rules = {
|
const rules = {
|
||||||
"*": "deny",
|
"*": "deny",
|
||||||
|
|||||||
Reference in New Issue
Block a user