-
-
Notifications
You must be signed in to change notification settings - Fork 17
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Added Built-in Functions and tests for it (#44)
* feat: Added Built-in Functions and tests for it Signed-off-by: Rushikesh Tote <[email protected]> * fix: globMatch function had different functionality from Casbin Go's globMatch Signed-off-by: Rushikesh Tote <[email protected]>
- Loading branch information
Showing
3 changed files
with
262 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -28,6 +28,11 @@ jobs: | |
- name: Set up luarocks | ||
uses: leafo/[email protected] | ||
|
||
- name: Install PCRE | ||
run: | | ||
sudo apt-get update | ||
sudo apt-get install libpcre3 libpcre3-dev | ||
- name: Install dependencies | ||
run: | | ||
until luarocks install lualogging | ||
|
@@ -54,6 +59,14 @@ jobs: | |
do | ||
sleep 1 | ||
done | ||
until luarocks install lrexlib-pcre | ||
do | ||
sleep 1 | ||
done | ||
until luarocks install luaposix | ||
do | ||
sleep 1 | ||
done | ||
- name: Run tests | ||
run: busted spec -o htest | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,145 @@ | ||
--Copyright 2021 The casbin Authors. All Rights Reserved. | ||
-- | ||
--Licensed under the Apache License, Version 2.0 (the "License"); | ||
--you may not use this file except in compliance with the License. | ||
--You may obtain a copy of the License at | ||
-- | ||
-- http://www.apache.org/licenses/LICENSE-2.0 | ||
-- | ||
--Unless required by applicable law or agreed to in writing, software | ||
--distributed under the License is distributed on an "AS IS" BASIS, | ||
--WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
--See the License for the specific language governing permissions and | ||
--limitations under the License. | ||
|
||
local builtInFunctions = require("src.util.BuiltInFunctions") | ||
|
||
describe("BuiltInFunctions tests", function () | ||
it("keyMatch tests", function () | ||
assert.is.False(BuiltInFunctions.keyMatch("/foo", "/")) | ||
assert.is.True(BuiltInFunctions.keyMatch("/foo", "/foo")) | ||
assert.is.True(BuiltInFunctions.keyMatch("/foo", "/foo*")) | ||
assert.is.False(BuiltInFunctions.keyMatch("/foo", "/foo/*")) | ||
assert.is.False(BuiltInFunctions.keyMatch("/foo/bar", "/foo")) | ||
assert.is.True(BuiltInFunctions.keyMatch("/foo/bar", "/foo*")) | ||
assert.is.True(BuiltInFunctions.keyMatch("/foo/bar", "/foo/*")) | ||
assert.is.False(BuiltInFunctions.keyMatch("/foobar", "/foo")) | ||
assert.is.True(BuiltInFunctions.keyMatch("/foobar", "/foo*")) | ||
assert.is.False(BuiltInFunctions.keyMatch("/foobar", "/foo/*")) | ||
end) | ||
|
||
it("keyGet tests", function () | ||
assert.are.same("", BuiltInFunctions.keyGet("/foo", "/foo")) | ||
assert.are.same("", BuiltInFunctions.keyGet("/foo", "/foo*")) | ||
assert.are.same("", BuiltInFunctions.keyGet("/foo", "/foo/*")) | ||
assert.are.same("", BuiltInFunctions.keyGet("/foo/bar", "/foo")) | ||
assert.are.same("/bar", BuiltInFunctions.keyGet("/foo/bar", "/foo*")) | ||
assert.are.same("bar", BuiltInFunctions.keyGet("/foo/bar", "/foo/*")) | ||
assert.are.same("", BuiltInFunctions.keyGet("/foobar", "/foo")) | ||
assert.are.same("bar", BuiltInFunctions.keyGet("/foobar", "/foo*")) | ||
assert.are.same("", BuiltInFunctions.keyGet("/foobar", "/foo/*")) | ||
end) | ||
|
||
it("keyMatch2 tests", function () | ||
assert.is.False(BuiltInFunctions.keyMatch2("/foo", "/")) | ||
assert.is.True(BuiltInFunctions.keyMatch2("/foo", "/foo")) | ||
assert.is.True(BuiltInFunctions.keyMatch2("/foo", "/foo*")) | ||
assert.is.False(BuiltInFunctions.keyMatch2("/foo", "/foo/*")) | ||
assert.is.False(BuiltInFunctions.keyMatch2("/foo/bar", "/foo")) -- different with KeyMatch. | ||
assert.is.False(BuiltInFunctions.keyMatch2("/foo/bar", "/foo*")) | ||
assert.is.True(BuiltInFunctions.keyMatch2("/foo/bar", "/foo/*")) | ||
assert.is.False(BuiltInFunctions.keyMatch2("/foobar", "/foo")) -- different with KeyMatch. | ||
assert.is.False(BuiltInFunctions.keyMatch2("/foobar", "/foo*")) | ||
assert.is.False(BuiltInFunctions.keyMatch2("/foobar", "/foo/*")) | ||
|
||
assert.is.False(BuiltInFunctions.keyMatch2("/", "/:resource")) | ||
assert.is.True(BuiltInFunctions.keyMatch2("/resource1", "/:resource")) | ||
assert.is.False(BuiltInFunctions.keyMatch2("/myid", "/:id/using/:resId")) | ||
assert.is.True(BuiltInFunctions.keyMatch2("/myid/using/myresid", "/:id/using/:resId")) | ||
|
||
assert.is.False(BuiltInFunctions.keyMatch2("/proxy/myid", "/proxy/:id/*")) | ||
assert.is.True(BuiltInFunctions.keyMatch2("/proxy/myid/", "/proxy/:id/*")) | ||
assert.is.True(BuiltInFunctions.keyMatch2("/proxy/myid/res", "/proxy/:id/*")) | ||
assert.is.True(BuiltInFunctions.keyMatch2("/proxy/myid/res/res2", "/proxy/:id/*")) | ||
assert.is.True(BuiltInFunctions.keyMatch2("/proxy/myid/res/res2/res3", "/proxy/:id/*")) | ||
assert.is.False(BuiltInFunctions.keyMatch2("/proxy/", "/proxy/:id/*")) | ||
|
||
assert.is.True(BuiltInFunctions.keyMatch2("/alice", "/:id")) | ||
assert.is.True(BuiltInFunctions.keyMatch2("/alice/all", "/:id/all")) | ||
assert.is.False(BuiltInFunctions.keyMatch2("/alice", "/:id/all")) | ||
assert.is.False(BuiltInFunctions.keyMatch2("/alice/all", "/:id")) | ||
|
||
assert.is.False(BuiltInFunctions.keyMatch2("/alice/all", "/:/all")) | ||
end) | ||
|
||
it("keyMatch3 tests", function () | ||
assert.is.True(BuiltInFunctions.keyMatch3("/foo", "/foo")) | ||
assert.is.True(BuiltInFunctions.keyMatch3("/foo", "/foo*")) | ||
assert.is.False(BuiltInFunctions.keyMatch3("/foo", "/foo/*")) | ||
assert.is.False(BuiltInFunctions.keyMatch3("/foo/bar", "/foo")) | ||
assert.is.False(BuiltInFunctions.keyMatch3("/foo/bar", "/foo*")) | ||
assert.is.True(BuiltInFunctions.keyMatch3("/foo/bar", "/foo/*")) | ||
assert.is.False(BuiltInFunctions.keyMatch3("/foobar", "/foo")) | ||
assert.is.False(BuiltInFunctions.keyMatch3("/foobar", "/foo*")) | ||
assert.is.False(BuiltInFunctions.keyMatch3("/foobar", "/foo/*")) | ||
|
||
assert.is.False(BuiltInFunctions.keyMatch3("/", "/{resource}")) | ||
assert.is.True(BuiltInFunctions.keyMatch3("/resource1", "/{resource}")) | ||
assert.is.False(BuiltInFunctions.keyMatch3("/myid", "/{id}/using/{resId}")) | ||
assert.is.True(BuiltInFunctions.keyMatch3("/myid/using/myresid", "/{id}/using/{resId}")) | ||
|
||
assert.is.False(BuiltInFunctions.keyMatch3("/proxy/myid", "/proxy/{id}/*")) | ||
assert.is.True(BuiltInFunctions.keyMatch3("/proxy/myid/", "/proxy/{id}/*")) | ||
assert.is.True(BuiltInFunctions.keyMatch3("/proxy/myid/res", "/proxy/{id}/*")) | ||
assert.is.True(BuiltInFunctions.keyMatch3("/proxy/myid/res/res2", "/proxy/{id}/*")) | ||
assert.is.True(BuiltInFunctions.keyMatch3("/proxy/myid/res/res2/res3", "/proxy/{id}/*")) | ||
assert.is.False(BuiltInFunctions.keyMatch3("/proxy/", "/proxy/{id}/*")) | ||
|
||
assert.is.False(BuiltInFunctions.keyMatch3("/myid/using/myresid", "/{id/using/{resId}")) | ||
end) | ||
|
||
it("regexMatch tests", function () | ||
assert.is.True(BuiltInFunctions.regexMatch("/topic/create", "/topic/create")) | ||
assert.is.True(BuiltInFunctions.regexMatch("/topic/create/123", "/topic/create")) | ||
assert.is.False(BuiltInFunctions.regexMatch("/topic/delete", "/topic/create")) | ||
assert.is.False(BuiltInFunctions.regexMatch("/topic/edit", "/topic/edit/[0-9]+")) | ||
assert.is.True(BuiltInFunctions.regexMatch("/topic/edit/123", "/topic/edit/[0-9]+")) | ||
assert.is.False(BuiltInFunctions.regexMatch("/topic/edit/abc", "/topic/edit/[0-9]+")) | ||
assert.is.False(BuiltInFunctions.regexMatch("/foo/delete/123", "/topic/delete/[0-9]+")) | ||
assert.is.True(BuiltInFunctions.regexMatch("/topic/delete/0", "/topic/delete/[0-9]+")) | ||
assert.is.False(BuiltInFunctions.regexMatch("/topic/edit/123s", "/topic/delete/[0-9]+")) | ||
end) | ||
|
||
it("globMatch tests", function () | ||
assert.is.True(BuiltInFunctions.globMatch("/foo", "/foo")) | ||
assert.is.True(BuiltInFunctions.globMatch("/foo", "/foo*")) | ||
assert.is.False(BuiltInFunctions.globMatch("/foo", "/foo/*")) | ||
assert.is.False(BuiltInFunctions.globMatch("/foo/bar", "/foo")) | ||
assert.is.False(BuiltInFunctions.globMatch("/foo/bar", "/foo*")) | ||
assert.is.True(BuiltInFunctions.globMatch("/foo/bar", "/foo/*")) | ||
assert.is.False(BuiltInFunctions.globMatch("/foobar", "/foo")) | ||
assert.is.True(BuiltInFunctions.globMatch("/foobar", "/foo*")) | ||
assert.is.False(BuiltInFunctions.globMatch("/foobar", "/foo/*")) | ||
|
||
assert.is.False(BuiltInFunctions.globMatch("/prefix/foo", "*/foo")) | ||
assert.is.False(BuiltInFunctions.globMatch("/prefix/foo", "*/foo*")) | ||
assert.is.False(BuiltInFunctions.globMatch("/prefix/foo", "*/foo/*")) | ||
assert.is.False(BuiltInFunctions.globMatch("/prefix/foo/bar", "*/foo")) | ||
assert.is.False(BuiltInFunctions.globMatch("/prefix/foo/bar", "*/foo*")) | ||
assert.is.False(BuiltInFunctions.globMatch("/prefix/foo/bar", "*/foo/*")) | ||
assert.is.False(BuiltInFunctions.globMatch("/prefix/foobar", "*/foo")) | ||
assert.is.False(BuiltInFunctions.globMatch("/prefix/foobar", "*/foo*")) | ||
assert.is.False(BuiltInFunctions.globMatch("/prefix/foobar", "*/foo/*")) | ||
|
||
assert.is.False(BuiltInFunctions.globMatch("/prefix/subprefix/foo", "*/foo")) | ||
assert.is.False(BuiltInFunctions.globMatch("/prefix/subprefix/foo", "*/foo*")) | ||
assert.is.False(BuiltInFunctions.globMatch("/prefix/subprefix/foo", "*/foo/*")) | ||
assert.is.False(BuiltInFunctions.globMatch("/prefix/subprefix/foo/bar", "*/foo")) | ||
assert.is.False(BuiltInFunctions.globMatch("/prefix/subprefix/foo/bar", "*/foo*")) | ||
assert.is.False(BuiltInFunctions.globMatch("/prefix/subprefix/foo/bar", "*/foo/*")) | ||
assert.is.False(BuiltInFunctions.globMatch("/prefix/subprefix/foobar", "*/foo")) | ||
assert.is.False(BuiltInFunctions.globMatch("/prefix/subprefix/foobar", "*/foo*")) | ||
assert.is.False(BuiltInFunctions.globMatch("/prefix/subprefix/foobar", "*/foo/*")) | ||
|
||
end) | ||
end) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
--Copyright 2021 The casbin Authors. All Rights Reserved. | ||
-- | ||
--Licensed under the Apache License, Version 2.0 (the "License"); | ||
--you may not use this file except in compliance with the License. | ||
--You may obtain a copy of the License at | ||
-- | ||
-- http://www.apache.org/licenses/LICENSE-2.0 | ||
-- | ||
--Unless required by applicable law or agreed to in writing, software | ||
--distributed under the License is distributed on an "AS IS" BASIS, | ||
--WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
--See the License for the specific language governing permissions and | ||
--limitations under the License. | ||
|
||
local rex = require ("rex_pcre") | ||
local posix = require("posix.fnmatch") | ||
|
||
BuiltInFunctions = {} | ||
|
||
-- KeyMatch determines whether key1 matches the pattern of key2 (similar to RESTful path), key2 can contain a *. | ||
-- For example, "/foo/bar" matches "/foo/*" | ||
function BuiltInFunctions.keyMatch(key1, key2) | ||
local i, _ = string.find(key2, "*") | ||
|
||
if not i then | ||
return (key1 == key2) | ||
end | ||
|
||
if #key1>=i then | ||
return (string.sub(key1, 1, i-1) == string.sub(key2, 1, i-1)) | ||
end | ||
return (key1 == string.sub(key2, 1, i-1)) | ||
end | ||
|
||
-- KeyGet returns the matched part | ||
-- For example, "/foo/bar/foo" matches "/foo/*" | ||
-- "bar/foo" will been returned | ||
function BuiltInFunctions.keyGet(key1, key2) | ||
local i, _ = string.find(key2, "*") | ||
|
||
if not i then | ||
return "" | ||
end | ||
if #key1>=i then | ||
if string.sub(key1, 1, i-1) == string.sub(key2, 1, i-1) then | ||
return string.sub(key1, i) | ||
end | ||
end | ||
return "" | ||
end | ||
|
||
-- KeyMatch2 determines whether key1 matches the pattern of key2 (similar to RESTful path), key2 can contain a *. | ||
-- For example, "/foo/bar" matches "/foo/*", "/resource1" matches "/:resource" | ||
function BuiltInFunctions.keyMatch2(key1, key2) | ||
key2 = string.gsub(key2, "/%*", "/.*") | ||
local key = rex.gsub(key2, ":[^/]+", "[^/]+") | ||
return BuiltInFunctions.regexMatch(key1, "^"..key.."$") | ||
end | ||
|
||
-- KeyMatch3 determines whether key1 matches the pattern of key2 (similar to RESTful path), key2 can contain a *. | ||
-- For example, "/foo/bar" matches "/foo/*", "/resource1" matches "/{resource}" | ||
function BuiltInFunctions.keyMatch3(key1, key2) | ||
key2 = string.gsub(key2, "/%*", "/.*") | ||
local key = rex.gsub(key2, "{[^/]+}", "[^/]+") | ||
return BuiltInFunctions.regexMatch(key1, "^"..key.."$") | ||
end | ||
|
||
-- RegexMatch determines whether key1 matches the pattern of key2 in regular expression. | ||
function BuiltInFunctions.regexMatch(key1, key2) | ||
local res = rex.match(key1, key2) | ||
if res then | ||
return true | ||
else | ||
return false | ||
end | ||
end | ||
|
||
-- GlobMatch determines whether key1 matches the pattern of key2 using glob pattern | ||
function BuiltInFunctions.globMatch(key1, key2) | ||
if posix.fnmatch(key2, key1, posix.FNM_PATHNAME or posix.FNM_PERIOD) == 0 then | ||
return true | ||
else | ||
return false | ||
end | ||
end | ||
|
||
-- GenerateGFunction is the factory method of the g(_, _) function. | ||
function BuiltInFunctions.generateGFunction(rm) | ||
local function f(args) | ||
local name1 = args[1] | ||
local name2 = args[2] | ||
|
||
if not rm then | ||
return name1 == name2 | ||
elseif #args==2 then | ||
return rm:hasLink(name1, name2) | ||
else | ||
local domain = args[3] | ||
return rm:hasLink(name1, name2, domain) | ||
end | ||
end | ||
|
||
return f | ||
end |