Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

perm cache by redis #11

Merged
merged 1 commit into from
Jun 30, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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