Skip to content

Commit

Permalink
First commit
Browse files Browse the repository at this point in the history
  • Loading branch information
leeqvip committed Jan 14, 2019
1 parent 0d58e0f commit cddd622
Show file tree
Hide file tree
Showing 70 changed files with 2,088 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Expand Up @@ -102,3 +102,5 @@ venv.bak/

# mypy
.mypy_cache/
_trial_temp
.idea
13 changes: 13 additions & 0 deletions .travis.yml
@@ -0,0 +1,13 @@
language: python
python:
- "3.6"
- "3.7"
script:
- python -m unittest discover -s tests -t tests
deploy:
provider: pypi
user: "techlee"
password:
secure: "Your encrypted password"
on:
tags: true
297 changes: 297 additions & 0 deletions README.md

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions casbin/__init__.py
@@ -0,0 +1 @@
from .enforcer import *
1 change: 1 addition & 0 deletions casbin/config/__init__.py
@@ -0,0 +1 @@
from .config import Config
127 changes: 127 additions & 0 deletions casbin/config/config.py
@@ -0,0 +1,127 @@
from io import StringIO


class Config:
"""represents an implementation of the ConfigInterface"""

# DEFAULT_SECTION specifies the name of a section if no name provided
DEFAULT_SECTION = 'default'
# DEFAULT_COMMENT defines what character(s) indicate a comment `#`
DEFAULT_COMMENT = '#'
# DEFAULT_COMMENT_SEM defines what alternate character(s) indicate a comment `;`
DEFAULT_COMMENT_SEM = ';'
# DEFAULT_MULTI_LINE_SEPARATOR defines what character indicates a multi-line content
DEFAULT_MULTI_LINE_SEPARATOR = '\\'

_data = dict()

def __init__(self):
self._data = dict()

@staticmethod
def new_config(conf_name):
c = Config()
c._parse(conf_name)
return c

@staticmethod
def new_config_from_text(text):
c = Config()
f = StringIO(text)
c._parse_buffer(f)
return c

def add_config(self, section, option, value):
if section == '':
section = self.DEFAULT_SECTION

if section not in self._data.keys():
self._data[section] = {}

self._data[section][option] = value

def _parse(self, fname):
with open(fname, 'rb') as f:
self._parse_buffer(f)

def _parse_buffer(self, f):
section = ''
line_num = 0
buf = []
can_write = False
while True:
if can_write:
self._write(section, line_num, buf)
can_write = False
line_num = line_num + 1

line = f.readline()

if not line:
if len(buf) > 0:
self._write(section, line_num, buf)
break
line = line.strip().decode()

if '' == line or self.DEFAULT_COMMENT == line[0:1] or self.DEFAULT_COMMENT_SEM == line[0:1]:
can_write = True
continue
elif '[' == line[0:1] and ']' == line[-1]:
if len(buf) > 0:
self._write(section, line_num, buf)
can_write = False
section = line[1:-1]
else:
p = ''
if self.DEFAULT_MULTI_LINE_SEPARATOR == line[-1]:
p = line[0:-1].strip()
else:
p = line
can_write = True
buf.append(p)

def _write(self, section, line_num, b):

buf = "".join(b)
if len(buf) <= 0:
return
option_val = buf.split('=', 1)

if len(option_val) != 2:
raise RuntimeError('parse the content error : line {} , {} = ?'.format(line_num, option_val[0]))

option = option_val[0].strip()
value = option_val[1].strip()

self.add_config(section, option, value)

del b[:]

def set(self, key, value):
if len(key) == 0:
raise RuntimeError("key is empty")

keys = key.lower().split('::')
if len(keys) >= 2:
section = keys[0]
option = keys[1]
else:
section = ""
option = keys[0]
self.add_config(section, option, value)

def get(self, key):
"""section.key or key"""

keys = key.lower().split('::')
if len(keys) >= 2:
section = keys[0]
option = keys[1]
else:
section = self.DEFAULT_SECTION
option = keys[0]

if section in self._data.keys():
if option in self._data[section].keys():
return self._data[section][option]
return ''
2 changes: 2 additions & 0 deletions casbin/effect/__init__.py
@@ -0,0 +1,2 @@
from .default_effector import DefaultEffector
from .effector import Effector
44 changes: 44 additions & 0 deletions casbin/effect/default_effector.py
@@ -0,0 +1,44 @@
from .effector import Effector


class DefaultEffector(Effector):
"""default effector for Casbin."""

def merge_effects(self, expr, effects, results):
"""merges all matching results collected by the enforcer into a single decision."""

result = False
if expr == "some(where (p_eft == allow))":
for eft in effects:
if eft == self.ALLOW:
result = True
break

elif expr == "!some(where (p_eft == deny))":
result = True

for eft in effects:
if eft == self.DENY:
result = False
break

elif expr == "some(where (p_eft == allow)) && !some(where (p_eft == deny))":
for eft in effects:
if eft == self.ALLOW:
result = True
elif eft == self.DENY:
result = False
break

elif expr == "priority(p_eft) || deny":
for eft in effects:
if eft != self.INDETERMINATE:
if eft == self.ALLOW:
result = True
else:
result = False
break
else:
raise RuntimeError("unsupported effect")

return result
12 changes: 12 additions & 0 deletions casbin/effect/effector.py
@@ -0,0 +1,12 @@
class Effector:
"""Effector is the interface for Casbin effectors."""

ALLOW = 0

INDETERMINATE = 1

DENY = 2

def merge_effects(self, expr, effects, results):
"""merges all matching results collected by the enforcer into a single decision."""
pass

0 comments on commit cddd622

Please sign in to comment.