Skip to content

Commit

Permalink
Merge pull request #11 from seatable/perm-cache
Browse files Browse the repository at this point in the history
perm cache by redis
  • Loading branch information
freeplant authored Jun 30, 2021
2 parents abf63cd + 5ff8040 commit 52dd285
Show file tree
Hide file tree
Showing 7 changed files with 90 additions and 43 deletions.
2 changes: 1 addition & 1 deletion docker/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ RUN rm -f /usr/bin/python && \
ln -s /usr/local/bin/pip3.6 /usr/bin/pip && \
ln -s /usr/local/bin/pip3.6 /usr/bin/pip3

RUN pip3 install uvicorn pillow sqlalchemy==1.4.6 pymysql future requests \
RUN pip3 install uvicorn pillow sqlalchemy==1.4.6 pymysql future requests redis \
-i https://mirrors.aliyun.com/pypi/simple && rm -r /root/.cache/pip


Expand Down
15 changes: 14 additions & 1 deletion docker/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
version: '2.0'
services:
redis:
image: redis:5.0.7
container_name: seatable-thumbnail-redis
networks:
- seatable-thumbnail-net

seatable:
image: docker.seafile.top/seafile-dev/seatable-thumbnail-server:1.3.0
image: docker.seafile.top/seafile-dev/seatable-thumbnail-server:2.1.1
container_name: seatable-thumbnail
ports:
- "80:80"
Expand All @@ -11,3 +17,10 @@ services:
environment:
- SEATABLE_THUMBNAIL_SERVER_HOSTNAME=thumbnail.seatable.cn
- SEATABLE_THUMBNAIL_SERVER_LETSENCRYPT=True
depends_on:
- redis
networks:
- seatable-thumbnail-net

networks:
seatable-thumbnail-net:
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ sqlalchemy==1.4.6
pymysql
future # seaf-server
requests
redis

# psd_tools
# moviepy
4 changes: 4 additions & 0 deletions seatable_thumbnail/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
import redis

import seatable_thumbnail.settings as settings

Expand All @@ -12,3 +13,6 @@
engine = create_engine(db_url, **db_kwargs)
Base = declarative_base()
DBSession = sessionmaker(bind=engine)


redis_client = redis.Redis(host=settings.REDIS_HOST, decode_responses=True)
106 changes: 65 additions & 41 deletions seatable_thumbnail/permissions.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,41 @@
DTableGroupShare, DTableViewUserShare, DTableViewGroupShare, \
DTableExternalLinks, DTableCollectionTables
from seatable_thumbnail.constants import PERMISSION_READ, PERMISSION_READ_WRITE
from seatable_thumbnail import redis_client

CACHE_TIMEOUT = 1800


class ThumbnailPermission(object):
def __init__(self, db_session, **info):
self.db_session = db_session
self.__dict__.update(info)
self.dtable = self.db_session.query(
DTables).filter_by(uuid=self.dtable_uuid).first()
self.cache_key = self.session_key + ':' + self.dtable_uuid

def check(self):
return self.has_dtable_asset_read_permission()
if self.has_cache_permission():
return True

if self.has_dtable_asset_read_permission():
self.set_cache_permission()
return True

return False

def has_cache_permission(self):
try:
return redis_client.get(self.cache_key) == '1'
except Exception as e:
return False

def set_cache_permission(self):
try:
redis_client.set(self.cache_key, '1', ex=CACHE_TIMEOUT)
except Exception as e:
pass

def has_dtable_asset_read_permission(self):
# three ways to access asset
# four ways to access asset
# 1. through external link to get image
# 2. through collection table to get image
# 3. through dtable perm, including dtable share, dtable custom share
Expand All @@ -41,12 +62,47 @@ def can_access_image_through_external_link(self):

return self.external_link['dtable_uuid'] == self.dtable_uuid

def has_collection_table_permission(self):
if not hasattr(self, 'collection_table'):
return False
if not self.collection_table.get('token'):
return False
if not self.collection_table.get('dtable_uuid'):
return False

token = self.collection_table['token']
obj = self.db_session.query(
DTableCollectionTables).filter_by(token=token).first()
if not obj:
return False

return self.collection_table['dtable_uuid'] == self.dtable_uuid

def is_group_member(self, group_id, email, in_structure=None):

group_id = int(group_id)

if in_structure in (True, False):
return ccnet_api.is_group_user(group_id, email, in_structure)

group = ccnet_api.get_group(group_id)
if not group:
return False

if group.parent_group_id == 0:
# -1: top address book group
# 0: group not in address book
# >0: sub group in address book
# if `in_structure` is False, NOT check sub groups in address book
return ccnet_api.is_group_user(group_id, email, in_structure=False)
else:
return ccnet_api.is_group_user(group_id, email)

def check_dtable_permission(self):
"""Check workspace/dtable access permission of a user.
"""
owner = self.workspace_owner
username = self.username
dtable = self.dtable
if not hasattr(self, 'org_id'):
self.org_id = -1
org_id = self.org_id
Expand All @@ -59,6 +115,10 @@ def check_dtable_permission(self):
if username == owner:
return PERMISSION_READ_WRITE

self.dtable = self.db_session.query(
DTables).filter_by(uuid=self.dtable_uuid).first()
dtable = self.dtable

if dtable: # check user's all permissions from `share`, `group-share` and checkout higher one
dtable_share = self.db_session.query(
DTableShare).filter_by(dtable_id=dtable.id, to_user=username).first()
Expand Down Expand Up @@ -121,39 +181,3 @@ def get_group_view_share_permission(self):
if not target_view_share:
return ''
return target_view_share.permission

def is_group_member(self, group_id, email, in_structure=None):

group_id = int(group_id)

if in_structure in (True, False):
return ccnet_api.is_group_user(group_id, email, in_structure)

group = ccnet_api.get_group(group_id)
if not group:
return False

if group.parent_group_id == 0:
# -1: top address book group
# 0: group not in address book
# >0: sub group in address book
# if `in_structure` is False, NOT check sub groups in address book
return ccnet_api.is_group_user(group_id, email, in_structure=False)
else:
return ccnet_api.is_group_user(group_id, email)

def has_collection_table_permission(self):
if not hasattr(self, 'collection_table'):
return False
if not self.collection_table.get('token'):
return False
if not self.collection_table.get('dtable_uuid'):
return False

token = self.collection_table['token']
obj = self.db_session.query(
DTableCollectionTables).filter_by(token=token).first()
if not obj:
return False

return self.collection_table['dtable_uuid'] == self.dtable_uuid
1 change: 1 addition & 0 deletions seatable_thumbnail/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ def session_check(self):
DjangoSession).filter_by(session_key=session_key).first()
self.session_data = self.parse_django_session(django_session.session_data)

self.session_data['session_key'] = session_key
username = self.session_data.get('_auth_user_name')
external_link = self.session_data.get('external_link')
collection_table = self.session_data.get('collection_table')
Expand Down
4 changes: 4 additions & 0 deletions seatable_thumbnail/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@
DATABASE_NAME = ''


# redis
REDIS_HOST = 'redis'


# dir
# LOG_DIR = 'logs/'
# THUMBNAIL_DIR = 'thumbnail/'
Expand Down

0 comments on commit 52dd285

Please sign in to comment.