1
0
mirror of https://github.com/haiwen/seahub.git synced 2025-09-16 23:29:49 +00:00
Files
seahub/seahub/repo_metadata/apis.py
2025-04-03 16:29:42 +08:00

2778 lines
115 KiB
Python

import json
import logging
import os
from datetime import datetime
from rest_framework.authentication import SessionAuthentication
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from rest_framework import status
from rest_framework.views import APIView
from seahub.api2.utils import api_error
from seahub.api2.throttling import UserRateThrottle
from seahub.api2.authentication import TokenAuthentication
from seahub.repo_metadata.models import RepoMetadata, RepoMetadataViews
from seahub.views import check_folder_permission
from seahub.repo_metadata.utils import add_init_metadata_task, recognize_faces, gen_unique_id, init_metadata, \
get_unmodifiable_columns, can_read_metadata, init_faces, \
extract_file_details, get_table_by_name, remove_faces_table, FACES_SAVE_PATH, \
init_tags, init_tag_self_link_columns, remove_tags_table, add_init_face_recognition_task, init_ocr, \
remove_ocr_column, get_update_record, update_people_cover_photo
from seahub.repo_metadata.metadata_server_api import MetadataServerAPI, list_metadata_view_records
from seahub.utils.repo import is_repo_admin
from seaserv import seafile_api
from seahub.repo_metadata.constants import FACE_RECOGNITION_VIEW_ID
logger = logging.getLogger(__name__)
class MetadataManage(APIView):
authentication_classes = (TokenAuthentication, SessionAuthentication)
permission_classes = (IsAuthenticated, )
throttle_classes = (UserRateThrottle, )
def get(self, request, repo_id):
"""
check the repo has enabled the metadata manage or not
"""
# resource check
repo = seafile_api.get_repo(repo_id)
if not repo:
error_msg = 'Library %s not found.' % repo_id
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
# permission check
if not can_read_metadata(request, repo_id):
error_msg = 'Permission denied.'
return api_error(status.HTTP_403_FORBIDDEN, error_msg)
is_enabled = False
is_tags_enabled = False
tags_lang = ''
details_settings = '{}'
is_ocr_enabled = False
face_recognition_enabled = False
try:
record = RepoMetadata.objects.filter(repo_id=repo_id).first()
if record and record.enabled:
is_enabled = True
details_settings = record.details_settings
if not details_settings:
details_settings = '{}'
if record.tags_enabled:
is_tags_enabled = True
tags_lang = record.tags_lang
if record.ocr_enabled:
is_ocr_enabled = True
if record.face_recognition_enabled:
face_recognition_enabled = True
except Exception as e:
logger.error(e)
error_msg = 'Internal Server Error'
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
return Response({
'enabled': is_enabled,
'tags_enabled': is_tags_enabled,
'ocr_enabled': is_ocr_enabled,
'face_recognition_enabled': face_recognition_enabled,
'tags_lang': tags_lang,
'details_settings': details_settings,
})
def put(self, request, repo_id):
"""
enable a new repo's metadata manage
"""
# check dose the repo have opened metadata manage
metadata = RepoMetadata.objects.filter(repo_id=repo_id).first()
if metadata and metadata.enabled:
error_msg = f'The metadata module is enabled for repo {repo_id}.'
return api_error(status.HTTP_409_CONFLICT, error_msg)
# resource check
repo = seafile_api.get_repo(repo_id)
if not repo:
error_msg = 'Library %s not found.' % repo_id
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
if not is_repo_admin(request.user.username, repo_id):
error_msg = 'Permission denied.'
return api_error(status.HTTP_403_FORBIDDEN, error_msg)
params = {
'repo_id': repo_id,
'username': request.user.username
}
try:
RepoMetadata.objects.enable_metadata(repo_id)
except Exception as e:
logger.exception(e)
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, 'Internal Server Error')
metadata_server_api = MetadataServerAPI(repo_id, request.user.username)
init_metadata(metadata_server_api)
try:
task_id = add_init_metadata_task(params=params)
metadata_view = RepoMetadataViews.objects.filter(repo_id=repo_id).first()
if not metadata_view:
RepoMetadataViews.objects.add_view(repo_id, 'All files', 'table')
except Exception as e:
logger.error(e)
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, 'Internal Server Error')
return Response({'task_id': task_id})
def delete(self, request, repo_id):
"""
remove a repo's metadata manage
"""
# recource check
repo = seafile_api.get_repo(repo_id)
if not repo:
error_msg = 'Library %s not found.' % repo_id
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
# permission check
if not is_repo_admin(request.user.username, repo_id):
error_msg = 'Permission denied.'
return api_error(status.HTTP_403_FORBIDDEN, error_msg)
# check dose the repo have opened metadata manage
record = RepoMetadata.objects.filter(repo_id=repo_id).first()
if not record or not record.enabled:
error_msg = f'The repo {repo_id} has disabledd the metadata manage.'
return api_error(status.HTTP_409_CONFLICT, error_msg)
metadata_server_api = MetadataServerAPI(repo_id, request.user.username)
try:
metadata_server_api.delete_base()
except Exception as err:
logger.error(err)
error_msg = 'Internal Server Error'
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
try:
record.enabled = False
record.face_recognition_enabled = False
record.tags_enabled = False
record.details_settings = '{}'
record.ocr_enabled = False
record.save()
RepoMetadataViews.objects.filter(repo_id=repo_id).delete()
except Exception as e:
logger.error(e)
error_msg = 'Internal Server Error'
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
return Response({'success': True})
class MetadataDetailsSettingsView(APIView):
authentication_classes = (TokenAuthentication, SessionAuthentication)
permission_classes = (IsAuthenticated, )
throttle_classes = (UserRateThrottle, )
def put(self, request, repo_id):
settings = request.data.get('settings', {})
if not settings:
error_msg = 'settings invalid.'
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
# resource check
repo = seafile_api.get_repo(repo_id)
if not repo:
error_msg = f'Library {repo_id} not found.'
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
if not is_repo_admin(request.user.username, repo_id):
error_msg = 'Permission denied.'
return api_error(status.HTTP_403_FORBIDDEN, error_msg)
metadata = RepoMetadata.objects.filter(repo_id=repo_id).first()
if not metadata or not metadata.enabled:
error_msg = f'The metadata module is not enabled for repo {repo_id}.'
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
old_details_settings = metadata.details_settings if metadata.details_settings else '{}'
old_details_settings = json.loads(old_details_settings)
if not old_details_settings:
old_details_settings = {}
old_details_settings.update(settings)
try:
metadata.details_settings = json.dumps(old_details_settings)
metadata.save()
except Exception as e:
logger.exception(e)
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, 'Internal Server Error')
return Response({'success': True})
class MetadataOCRManageView(APIView):
authentication_classes = (TokenAuthentication, SessionAuthentication)
permission_classes = (IsAuthenticated, )
throttle_classes = (UserRateThrottle, )
def put(self, request, repo_id):
# resource check
repo = seafile_api.get_repo(repo_id)
if not repo:
error_msg = f'Library {repo_id} not found.'
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
if not is_repo_admin(request.user.username, repo_id):
error_msg = 'Permission denied.'
return api_error(status.HTTP_403_FORBIDDEN, error_msg)
metadata = RepoMetadata.objects.filter(repo_id=repo_id).first()
if not metadata or not metadata.enabled:
error_msg = f'The metadata module is not enabled for repo {repo_id}.'
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
try:
metadata.ocr_enabled = True
metadata.save()
except Exception as e:
logger.exception(e)
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, 'Internal Server Error')
metadata_server_api = MetadataServerAPI(repo_id, request.user.username)
init_ocr(metadata_server_api)
return Response({'success': True})
def delete(self, request, repo_id):
# resource check
repo = seafile_api.get_repo(repo_id)
if not repo:
error_msg = f'Library {repo_id} not found.'
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
# permission check
if not is_repo_admin(request.user.username, repo_id):
error_msg = 'Permission denied.'
return api_error(status.HTTP_403_FORBIDDEN, error_msg)
# check dose the repo have opened metadata manage
record = RepoMetadata.objects.filter(repo_id=repo_id).first()
if not record or not record.enabled or not record.ocr_enabled:
error_msg = f'The repo {repo_id} has disabled the OCR.'
return api_error(status.HTTP_409_CONFLICT, error_msg)
metadata_server_api = MetadataServerAPI(repo_id, request.user.username)
try:
remove_ocr_column(metadata_server_api)
except Exception as err:
logger.error(err)
error_msg = 'Internal Server Error'
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
try:
record.ocr_enabled = False
record.save()
except Exception as e:
logger.error(e)
error_msg = 'Internal Server Error'
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
return Response({'success': True})
class MetadataRecords(APIView):
authentication_classes = (TokenAuthentication, SessionAuthentication)
permission_classes = (IsAuthenticated, )
throttle_classes = (UserRateThrottle, )
def get(self, request, repo_id):
"""
fetch a metadata results
request body:
parent_dir: optional, if not specify, search from all dirs
name: optional, if not specify, search from all objects
page: optional, the current page
per_page: optional, if use page, default is 25
is_dir: optional, True or False
order_by: list with string, like ['`parent_dir` ASC']
"""
# args check
view_id = request.GET.get('view_id', '')
start = request.GET.get('start', 0)
limit = request.GET.get('limit', 1000)
try:
start = int(start)
limit = int(limit)
except:
start = 0
limit = 1000
if start < 0:
error_msg = 'start invalid'
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
if limit < 0:
error_msg = 'limit invalid'
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
if not view_id:
error_msg = 'view_id is invalid.'
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
# metadata enable check
metadata = RepoMetadata.objects.filter(repo_id=repo_id).first()
if not metadata or not metadata.enabled:
error_msg = f'The metadata module is disabled for repo {repo_id}.'
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
tags_enabled = False
if metadata.tags_enabled:
tags_enabled = True
# resource check
repo = seafile_api.get_repo(repo_id)
if not repo:
error_msg = 'Library %s not found.' % repo_id
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
# permission check
if not can_read_metadata(request, repo_id):
error_msg = 'Permission denied.'
return api_error(status.HTTP_403_FORBIDDEN, error_msg)
try:
view = RepoMetadataViews.objects.get_view(repo_id, view_id)
except Exception as e:
logger.exception(e)
error_msg = 'Internal Server Error'
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
if not view:
error_msg = 'Metadata view %s not found.' % view_id
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
try:
results = list_metadata_view_records(repo_id, request.user.username, view, tags_enabled, start, limit)
except Exception as err:
logger.error(err)
error_msg = 'Internal Server Error'
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
return Response(results)
def put(self, request, repo_id):
records_data = request.data.get('records_data')
if not records_data:
error_msg = 'records_data invalid.'
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
metadata = RepoMetadata.objects.filter(repo_id=repo_id).first()
if not metadata or not metadata.enabled:
error_msg = f'The metadata module is disabled for repo {repo_id}.'
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
permission = check_folder_permission(request, repo_id, '/')
if permission != 'rw':
error_msg = 'Permission denied.'
return api_error(status.HTTP_403_FORBIDDEN, error_msg)
repo = seafile_api.get_repo(repo_id)
if not repo:
error_msg = 'Library %s not found.' % repo_id
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
metadata_server_api = MetadataServerAPI(repo_id, request.user.username)
from seafevents.repo_metadata.constants import METADATA_TABLE
try:
columns_data = metadata_server_api.list_columns(METADATA_TABLE.id)
columns = columns_data.get('columns', [])
except Exception as e:
logger.exception(e)
error_msg = 'Internal Server Error'
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
unmodifiable_column_names = [column.get('name') for column in get_unmodifiable_columns()]
record_id_to_record = {}
sql = f'SELECT `_id` FROM `{METADATA_TABLE.name}` WHERE '
parameters = []
for record_data in records_data:
record = record_data.get('record', {})
if not record:
continue
record_id = record_data.get('record_id', '')
if not record_id:
error_msg = 'record_id invalid.'
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
sql += f' `{METADATA_TABLE.columns.id.name}` = ? OR '
parameters.append(record_id)
record_id_to_record[record_id] = record
sql = sql.rstrip('OR ')
sql += ';'
if not parameters:
return Response({'success': True})
try:
query_result = metadata_server_api.query_rows(sql, parameters)
except Exception as e:
logger.exception(e)
error_msg = 'Internal Server Error'
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
results = query_result.get('results')
if not results:
# file or folder has been deleted
return Response({'success': True})
rows = []
for record in results:
to_updated_record = record_id_to_record.get(record_id)
update = get_update_record(to_updated_record, columns, unmodifiable_column_names)
if update:
record_id = record.get('_id')
update[METADATA_TABLE.columns.id.name] = record_id
rows.append(update)
if rows:
try:
metadata_server_api.update_rows(METADATA_TABLE.id, rows)
except Exception as e:
logger.exception(e)
error_msg = 'Internal Server Error'
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
return Response({'success': True})
class MetadataRecord(APIView):
authentication_classes = (TokenAuthentication, SessionAuthentication)
permission_classes = (IsAuthenticated,)
throttle_classes = (UserRateThrottle,)
def get(self, request, repo_id):
record_id = request.GET.get('record_id')
parent_dir = request.GET.get('parent_dir')
file_name = request.GET.get('file_name')
if not record_id:
if not parent_dir:
error_msg = 'parent_dir invalid'
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
if not file_name:
error_msg = 'file_name invalid'
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
metadata = RepoMetadata.objects.filter(repo_id=repo_id).first()
if not metadata or not metadata.enabled:
error_msg = f'The metadata module is disabled for repo {repo_id}.'
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
if not can_read_metadata(request, repo_id):
error_msg = 'Permission denied.'
return api_error(status.HTTP_403_FORBIDDEN, error_msg)
repo = seafile_api.get_repo(repo_id)
if not repo:
error_msg = 'Library %s not found.' % repo_id
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
metadata_server_api = MetadataServerAPI(repo_id, request.user.username)
from seafevents.repo_metadata.constants import METADATA_TABLE
sql = f'SELECT * FROM `{METADATA_TABLE.name}` WHERE `{METADATA_TABLE.columns.id.name}`=?;'
parameters = [record_id]
if not record_id:
sql = f'SELECT * FROM `{METADATA_TABLE.name}` WHERE \
`{METADATA_TABLE.columns.parent_dir.name}`=? AND `{METADATA_TABLE.columns.file_name.name}`=?;'
parameters = [parent_dir, file_name]
try:
query_result = metadata_server_api.query_rows(sql, parameters)
except Exception as e:
logger.error(e)
error_msg = 'Internal Server Error'
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
rows = query_result.get('results')
if not rows:
error_msg = 'Record not found'
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
return Response(query_result)
def put(self, request, repo_id):
record_id = request.data.get('record_id')
parent_dir = request.data.get('parent_dir')
file_name = request.data.get('file_name')
if not record_id:
if not parent_dir:
error_msg = 'parent_dir invalid'
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
if not file_name:
error_msg = 'file_name invalid'
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
update_data = request.data.get('data')
if not update_data:
error_msg = 'data invalid'
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
metadata = RepoMetadata.objects.filter(repo_id=repo_id).first()
if not metadata or not metadata.enabled:
error_msg = f'The metadata module is disabled for repo {repo_id}.'
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
if not can_read_metadata(request, repo_id):
error_msg = 'Permission denied.'
return api_error(status.HTTP_403_FORBIDDEN, error_msg)
repo = seafile_api.get_repo(repo_id)
if not repo:
error_msg = f'Library {repo_id} not found.'
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
metadata_server_api = MetadataServerAPI(repo_id, request.user.username)
from seafevents.repo_metadata.constants import METADATA_TABLE
try:
columns_data = metadata_server_api.list_columns(METADATA_TABLE.id)
columns = columns_data.get('columns', [])
except Exception as e:
logger.exception(e)
error_msg = 'Internal Server Error'
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
sql = f'SELECT * FROM `{METADATA_TABLE.name}` WHERE `{METADATA_TABLE.columns.id.name}`=?;'
parameters = [record_id]
if not record_id:
sql = f'SELECT * FROM `{METADATA_TABLE.name}` WHERE \
`{METADATA_TABLE.columns.parent_dir.name}`=? AND `{METADATA_TABLE.columns.file_name.name}`=?;'
parameters = [parent_dir, file_name]
try:
query_result = metadata_server_api.query_rows(sql, parameters)
except Exception as e:
logger.error(e)
error_msg = 'Internal Server Error'
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
rows = query_result.get('results')
if not rows:
error_msg = 'Record not found'
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
unmodifiable_column_names = [column.get('name') for column in get_unmodifiable_columns()]
record = rows[0]
update_record = get_update_record(update_data, columns, unmodifiable_column_names)
if not update_record:
return Response({'success': True})
record_id = record.get('_id')
update_record[METADATA_TABLE.columns.id.name] = record_id
update_records = [update_record]
if update_records:
try:
metadata_server_api.update_rows(METADATA_TABLE.id, update_records)
except Exception as e:
logger.exception(e)
error_msg = 'Internal Server Error'
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
return Response({'success': True})
class MetadataColumns(APIView):
authentication_classes = (TokenAuthentication, SessionAuthentication)
permission_classes = (IsAuthenticated,)
throttle_classes = (UserRateThrottle,)
def post(self, request, repo_id):
column_name = request.data.get('column_name')
column_type = request.data.get('column_type', 'text')
column_key = request.data.get('column_key', '')
column_data = request.data.get('column_data', '')
if not column_name:
error_msg = 'column_name invalid.'
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
record = RepoMetadata.objects.filter(repo_id=repo_id).first()
if not record or not record.enabled:
error_msg = f'The metadata module is disabled for repo {repo_id}.'
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
repo = seafile_api.get_repo(repo_id)
if not repo:
error_msg = 'Library %s not found.' % repo_id
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
permission = check_folder_permission(request, repo_id, '/')
if permission != 'rw':
error_msg = 'Permission denied.'
return api_error(status.HTTP_403_FORBIDDEN, error_msg)
metadata_server_api = MetadataServerAPI(repo_id, request.user.username)
from seafevents.repo_metadata.constants import METADATA_TABLE, MetadataColumn
columns = metadata_server_api.list_columns(METADATA_TABLE.id).get('columns')
column_keys = set()
column_names = set()
for column in columns:
column_keys.add(column.get('key'))
column_names.add(column.get('name'))
if column_name in column_names:
error_msg = 'column_name duplicated.'
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
if column_key and column_key.startswith('_') and column_key in column_keys:
error_msg = 'predefined column duplicated'
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
if not column_key:
column_key = gen_unique_id(column_keys)
column = MetadataColumn(column_key, column_name, column_type, column_data)
column = column.to_dict()
try:
metadata_server_api.add_column(METADATA_TABLE.id, column)
except Exception as e:
logger.exception(e)
error_msg = 'Internal Server Error'
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
return Response({'column': column})
def put(self, request, repo_id):
column_key = request.data.get('column_key', '')
column_name = request.data.get('name', '')
column_data = request.data.get('data', '')
if not column_key:
error_msg = 'column_key invalid.'
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
if not column_name and not column_data:
error_msg = 'params invalid.'
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
metadata = RepoMetadata.objects.filter(repo_id=repo_id).first()
if not metadata or not metadata.enabled:
error_msg = f'The metadata module is disabled for repo {repo_id}.'
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
repo = seafile_api.get_repo(repo_id)
if not repo:
error_msg = 'Library %s not found.' % repo_id
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
permission = check_folder_permission(request, repo_id, '/')
if permission != 'rw':
error_msg = 'Permission denied.'
return api_error(status.HTTP_403_FORBIDDEN, error_msg)
from seafevents.repo_metadata.constants import METADATA_TABLE, MetadataColumn
metadata_server_api = MetadataServerAPI(repo_id, request.user.username)
columns = metadata_server_api.list_columns(METADATA_TABLE.id).get('columns')
try:
column = next(column for column in columns if column['key'] == column_key)
except Exception as e:
error_msg = 'Column not found'
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
new_column_name = column_name if column_name else column['name']
old_column_data = column.get('data', {})
new_column_data = {**old_column_data, **column_data} if column_data else column['data']
new_column = MetadataColumn(column_key, new_column_name, column['type'], new_column_data).to_dict()
try:
metadata_server_api.update_column(METADATA_TABLE.id, new_column)
except Exception as e:
logger.exception(e)
error_msg = 'Internal Server Error'
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
return Response({'column': new_column})
def delete(self, request, repo_id):
column_key = request.data.get('column_key', '')
if not column_key:
error_msg = 'column_key invalid.'
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
record = RepoMetadata.objects.filter(repo_id=repo_id).first()
if not record or not record.enabled:
error_msg = f'The metadata module is disabled for repo {repo_id}.'
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
repo = seafile_api.get_repo(repo_id)
if not repo:
error_msg = 'Library %s not found.' % repo_id
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
permission = check_folder_permission(request, repo_id, '/')
if permission != 'rw':
error_msg = 'Permission denied.'
return api_error(status.HTTP_403_FORBIDDEN, error_msg)
from seafevents.repo_metadata.constants import METADATA_TABLE
metadata_server_api = MetadataServerAPI(repo_id, request.user.username)
columns = metadata_server_api.list_columns(METADATA_TABLE.id).get('columns')
try:
column = next(column for column in columns if column['key'] == column_key)
except Exception as e:
error_msg = 'Column not found'
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
try:
metadata_server_api.delete_column(METADATA_TABLE.id, column_key)
except Exception as e:
logger.exception(e)
error_msg = 'Internal Server Error'
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
return Response({'success': True})
class MetadataFolders(APIView):
authentication_classes = (TokenAuthentication, SessionAuthentication)
permission_classes = (IsAuthenticated,)
throttle_classes = (UserRateThrottle,)
def post(self, request, repo_id):
# add metadata folder
folder_name = request.data.get('name')
# check view name
if not folder_name:
return api_error(status.HTTP_400_BAD_REQUEST, 'folder_name is invalid')
record = RepoMetadata.objects.filter(repo_id=repo_id).first()
if not record or not record.enabled:
error_msg = f'The metadata module is disabled for repo {repo_id}.'
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
repo = seafile_api.get_repo(repo_id)
if not repo:
error_msg = 'Library %s not found.' % repo_id
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
permission = check_folder_permission(request, repo_id, '/')
if permission != 'rw':
error_msg = 'Permission denied.'
return api_error(status.HTTP_403_FORBIDDEN, error_msg)
# check metadata_views
metadata_views = RepoMetadataViews.objects.filter(repo_id=repo_id).first()
if not metadata_views:
error_msg = 'The metadata views does not exists.'
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
try:
new_folder = RepoMetadataViews.objects.add_folder(repo_id, folder_name)
if not new_folder:
return api_error(status.HTTP_400_BAD_REQUEST, 'add folder failed')
except Exception as e:
logger.exception(e)
error_msg = 'Internal Server Error'
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
return Response({'folder': new_folder})
def put(self, request, repo_id):
# update metadata folder: name etc.
folder_id = request.data.get('folder_id', None)
folder_data = request.data.get('folder_data', None)
# check folder_id
if not folder_id:
return api_error(status.HTTP_400_BAD_REQUEST, 'folder_id is invalid')
# check folder_data
if not folder_data:
return api_error(status.HTTP_400_BAD_REQUEST, 'folder_data is invalid')
if folder_data.get('_id') or folder_data.get('type') or folder_data.get('children'):
return api_error(status.HTTP_400_BAD_REQUEST, 'folder_data is invalid')
record = RepoMetadata.objects.filter(repo_id=repo_id).first()
if not record or not record.enabled:
error_msg = f'The metadata module is disabled for repo {repo_id}.'
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
repo = seafile_api.get_repo(repo_id)
if not repo:
error_msg = 'Library %s not found.' % repo_id
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
permission = check_folder_permission(request, repo_id, '/')
if permission != 'rw':
error_msg = 'Permission denied.'
return api_error(status.HTTP_403_FORBIDDEN, error_msg)
# check metadata_views
metadata_views = RepoMetadataViews.objects.filter(repo_id=repo_id).first()
if not metadata_views:
error_msg = 'The metadata views does not exists.'
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
# check folder exist
if folder_id not in metadata_views.folders_ids:
return api_error(status.HTTP_400_BAD_REQUEST, 'folder %s does not exists.' % folder_id)
try:
result = RepoMetadataViews.objects.update_folder(repo_id, folder_id, folder_data)
except Exception as e:
logger.exception(e)
error_msg = 'Internal Server Error'
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
return Response({'success': True})
def delete(self, request, repo_id):
# delete metadata folder by id
# check folder_id
folder_id = request.data.get('folder_id', None)
if not folder_id:
return api_error(status.HTTP_400_BAD_REQUEST, 'folder_id is invalid')
record = RepoMetadata.objects.filter(repo_id=repo_id).first()
if not record or not record.enabled:
error_msg = f'The metadata module is disabled for repo {repo_id}.'
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
repo = seafile_api.get_repo(repo_id)
if not repo:
error_msg = 'Library %s not found.' % repo_id
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
permission = check_folder_permission(request, repo_id, '/')
if permission != 'rw':
error_msg = 'Permission denied.'
return api_error(status.HTTP_403_FORBIDDEN, error_msg)
# check metadata_views
metadata_views = RepoMetadataViews.objects.filter(repo_id=repo_id).first()
if not metadata_views:
error_msg = 'The metadata views does not exists.'
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
# check folder exist
if folder_id not in metadata_views.folders_ids:
return api_error(status.HTTP_400_BAD_REQUEST, 'folder %s does not exists.' % folder_id)
try:
result = RepoMetadataViews.objects.delete_folder(repo_id, folder_id)
except Exception as e:
logger.exception(e)
error_msg = 'Internal Server Error'
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
return Response({'success': True})
class MetadataViews(APIView):
authentication_classes = (TokenAuthentication, SessionAuthentication)
permission_classes = (IsAuthenticated,)
throttle_classes = (UserRateThrottle,)
def get(self, request, repo_id):
repo = seafile_api.get_repo(repo_id)
if not repo:
error_msg = 'Library %s not found.' % repo_id
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
if not can_read_metadata(request, repo_id):
error_msg = 'Permission denied.'
return api_error(status.HTTP_403_FORBIDDEN, error_msg)
try:
metadata_views = RepoMetadataViews.objects.list_views(repo_id)
except Exception as e:
logger.exception(e)
error_msg = 'Internal Server Error'
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
return Response(metadata_views)
def post(self, request, repo_id):
# Add a metadata view
metadata_views = RepoMetadataViews.objects.filter(repo_id=repo_id).first()
view_name = request.data.get('name')
folder_id = request.data.get('folder_id', None)
view_type = request.data.get('type', 'table')
view_data = request.data.get('data', {})
# check view name
if not view_name:
error_msg = 'view name is invalid.'
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
# check folder exist
if folder_id:
if not metadata_views:
error_msg = 'The metadata views does not exists.'
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
if folder_id not in metadata_views.folders_ids:
return api_error(status.HTTP_400_BAD_REQUEST, 'folder %s does not exists' % folder_id)
record = RepoMetadata.objects.filter(repo_id=repo_id).first()
if not record or not record.enabled:
error_msg = f'The metadata module is disabled for repo {repo_id}.'
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
repo = seafile_api.get_repo(repo_id)
if not repo:
error_msg = 'Library %s not found.' % repo_id
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
permission = check_folder_permission(request, repo_id, '/')
if permission != 'rw':
error_msg = 'Permission denied.'
return api_error(status.HTTP_403_FORBIDDEN, error_msg)
try:
new_view = RepoMetadataViews.objects.add_view(repo_id, view_name, view_type, view_data, folder_id)
if not new_view:
return api_error(status.HTTP_400_BAD_REQUEST, 'add view failed')
except Exception as e:
logger.exception(e)
error_msg = 'Internal Server Error'
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
return Response({'view': new_view})
def put(self, request, repo_id):
# Update a metadata view, including rename, change filters and so on
# by a json data
view_id = request.data.get('view_id', None)
view_data = request.data.get('view_data', None)
if not view_id:
error_msg = 'view_id is invalid.'
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
if not view_data:
error_msg = 'view_data is invalid.'
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
record = RepoMetadata.objects.filter(repo_id=repo_id).first()
if not record or not record.enabled:
error_msg = f'The metadata module is disabled for repo {repo_id}.'
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
views = RepoMetadataViews.objects.filter(
repo_id=repo_id,
).first()
if not views:
error_msg = 'The metadata views does not exists.'
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
if view_id not in views.views_ids:
error_msg = 'view_id %s does not exists.' % view_id
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
repo = seafile_api.get_repo(repo_id)
if not repo:
error_msg = 'Library %s not found.' % repo_id
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
permission = check_folder_permission(request, repo_id, '/')
if permission != 'rw':
error_msg = 'Permission denied.'
return api_error(status.HTTP_403_FORBIDDEN, error_msg)
try:
result = RepoMetadataViews.objects.update_view(repo_id, view_id, view_data)
except Exception as e:
logger.exception(e)
error_msg = 'Internal Server Error'
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
return Response({'success': True})
def delete(self, request, repo_id):
# Update a metadata view, including rename, change filters and so on
# by a json data
view_id = request.data.get('view_id', None)
folder_id = request.data.get('folder_id', None)
if not view_id:
error_msg = 'view_id is invalid.'
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
record = RepoMetadata.objects.filter(repo_id=repo_id).first()
if not record or not record.enabled:
error_msg = f'The metadata module is disabled for repo {repo_id}.'
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
metadata_views = RepoMetadataViews.objects.filter(
repo_id=repo_id
).first()
if not metadata_views:
error_msg = 'The metadata views does not exists.'
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
# check view exist
if view_id not in metadata_views.views_ids:
error_msg = 'view_id %s does not exists.' % view_id
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
# check folder exist
if folder_id and folder_id not in metadata_views.folders_ids:
return api_error(status.HTTP_400_BAD_REQUEST, 'folder %s does not exists' % folder_id)
repo = seafile_api.get_repo(repo_id)
if not repo:
error_msg = 'Library %s not found.' % repo_id
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
permission = check_folder_permission(request, repo_id, '/')
if permission != 'rw':
error_msg = 'Permission denied.'
return api_error(status.HTTP_403_FORBIDDEN, error_msg)
try:
result = RepoMetadataViews.objects.delete_view(repo_id, view_id, folder_id)
except Exception as e:
logger.exception(e)
error_msg = 'Internal Server Error'
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
return Response({'success': True})
class MetadataViewsDuplicateView(APIView):
authentication_classes = (TokenAuthentication, SessionAuthentication)
permission_classes = (IsAuthenticated,)
throttle_classes = (UserRateThrottle,)
def post(self, request, repo_id):
view_id = request.data.get('view_id')
folder_id = request.data.get('folder_id', None)
if not view_id:
error_msg = 'view_id invalid'
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
record = RepoMetadata.objects.filter(repo_id=repo_id).first()
if not record or not record.enabled:
error_msg = f'The metadata module is disabled for repo {repo_id}.'
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
metadata_views = RepoMetadataViews.objects.filter(
repo_id=repo_id
).first()
if not metadata_views:
error_msg = 'The metadata views does not exists.'
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
if view_id not in metadata_views.views_ids:
error_msg = 'view_id %s does not exists.' % view_id
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
# check folder exist
if folder_id and folder_id not in metadata_views.folders_ids:
return api_error(status.HTTP_400_BAD_REQUEST, 'folder %s does not exists' % folder_id)
repo = seafile_api.get_repo(repo_id)
if not repo:
error_msg = 'Library %s not found.' % repo_id
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
permission = check_folder_permission(request, repo_id, '/')
if permission != 'rw':
error_msg = 'Permission denied.'
return api_error(status.HTTP_403_FORBIDDEN, error_msg)
try:
new_view = RepoMetadataViews.objects.duplicate_view(repo_id, view_id, folder_id)
if not new_view:
return api_error(status.HTTP_400_BAD_REQUEST, 'duplicate view failed')
except Exception as e:
logger.exception(e)
error_msg = 'Internal Server Error'
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
return Response({'view': new_view})
class MetadataViewsDetailView(APIView):
authentication_classes = (TokenAuthentication, SessionAuthentication)
permission_classes = (IsAuthenticated,)
throttle_classes = (UserRateThrottle,)
def get(self, request, repo_id, view_id):
record = RepoMetadata.objects.filter(repo_id=repo_id).first()
if not record or not record.enabled:
error_msg = f'The metadata module is disabled for repo {repo_id}.'
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
repo = seafile_api.get_repo(repo_id)
if not repo:
error_msg = 'Library %s not found.' % repo_id
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
if not can_read_metadata(request, repo_id):
error_msg = 'Permission denied.'
return api_error(status.HTTP_403_FORBIDDEN, error_msg)
try:
view = RepoMetadataViews.objects.get_view(repo_id, view_id)
except Exception as e:
logger.exception(e)
error_msg = 'Internal Server Error'
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
return Response({'view': view})
class MetadataViewsMoveView(APIView):
authentication_classes = (TokenAuthentication, SessionAuthentication)
permission_classes = (IsAuthenticated,)
throttle_classes = (UserRateThrottle,)
def post(self, request, repo_id):
# move view or folder to another position
source_view_id = request.data.get('source_view_id')
source_folder_id = request.data.get('source_folder_id')
target_view_id = request.data.get('target_view_id')
target_folder_id = request.data.get('target_folder_id')
is_above_folder = request.data.get('is_above_folder', False)
# must drag view or folder
if not source_view_id and not source_folder_id:
return api_error(status.HTTP_400_BAD_REQUEST, 'source_view_id and source_folder_id is invalid')
# must move above to view/folder or move view into folder
if not target_view_id and not target_folder_id:
return api_error(status.HTTP_400_BAD_REQUEST, 'target_view_id and target_folder_id is invalid')
# not allowed to drag folder into folder
if not source_view_id and source_folder_id and target_view_id and target_folder_id:
return api_error(status.HTTP_400_BAD_REQUEST, 'not allowed to drag folder into folder')
record = RepoMetadata.objects.filter(repo_id=repo_id).first()
if not record or not record.enabled:
error_msg = f'The metadata module is disabled for repo {repo_id}.'
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
repo = seafile_api.get_repo(repo_id)
if not repo:
error_msg = 'Library %s not found.' % repo_id
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
permission = check_folder_permission(request, repo_id, '/')
if permission != 'rw':
error_msg = 'Permission denied.'
return api_error(status.HTTP_403_FORBIDDEN, error_msg)
metadata_views = RepoMetadataViews.objects.filter(
repo_id=repo_id,
).first()
if not metadata_views:
error_msg = 'The metadata views does not exists.'
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
# check dragged view exist
if source_view_id and source_view_id not in metadata_views.views_ids:
return api_error(status.HTTP_400_BAD_REQUEST, 'source_view_id %s does not exists.' % source_view_id)
# check dragged view exist
if source_folder_id and source_folder_id not in metadata_views.folders_ids:
return api_error(status.HTTP_400_BAD_REQUEST, 'source_view_id %s does not exists.' % source_view_id)
# check target view exist
if target_view_id and target_view_id not in metadata_views.views_ids:
return api_error(status.HTTP_400_BAD_REQUEST, 'target_view_id %s does not exists.' % target_view_id)
# check target view exist
if target_folder_id and target_folder_id not in metadata_views.folders_ids:
return api_error(status.HTTP_400_BAD_REQUEST, 'target_folder_id %s does not exists.' % target_folder_id)
try:
results = RepoMetadataViews.objects.move_view(repo_id, source_view_id, source_folder_id, target_view_id, target_folder_id, is_above_folder)
if not results:
return api_error(status.HTTP_400_BAD_REQUEST, 'move view or folder failed')
except Exception as e:
logger.error(e)
error_msg = 'Internal Server Error'
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
return Response({'navigation': results['navigation']})
class FacesRecords(APIView):
authentication_classes = (TokenAuthentication, SessionAuthentication)
permission_classes = (IsAuthenticated,)
throttle_classes = (UserRateThrottle,)
def get(self, request, repo_id):
start = request.GET.get('start', 0)
limit = request.GET.get('limit', 1000)
try:
start = int(start)
limit = int(limit)
except:
start = 0
limit = 1000
if start < 0:
error_msg = 'start invalid'
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
if limit < 0:
error_msg = 'limit invalid'
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
metadata = RepoMetadata.objects.filter(repo_id=repo_id).first()
if not metadata or not metadata.enabled or not metadata.face_recognition_enabled:
error_msg = f'The face recognition is disabled for repo {repo_id}.'
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
repo = seafile_api.get_repo(repo_id)
if not repo:
error_msg = 'Library %s not found.' % repo_id
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
if not can_read_metadata(request, repo_id):
error_msg = 'Permission denied.'
return api_error(status.HTTP_403_FORBIDDEN, error_msg)
metadata_server_api = MetadataServerAPI(repo_id, request.user.username)
from seafevents.repo_metadata.constants import FACES_TABLE
from seafevents.face_recognition.constants import UNKNOWN_PEOPLE_NAME
sql = f'SELECT * FROM `{FACES_TABLE.name}` LIMIT {start}, {limit}'
try:
query_result = metadata_server_api.query_rows(sql)
except Exception as e:
logger.error(e)
error_msg = 'Internal Server Error'
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
faces_records = query_result.get('results', [])
metadata_columns = query_result.get('metadata', [])
dirents = seafile_api.list_dir_by_path(repo_id, '/_Internal/Faces')
file_name_to_mtime_dict = {}
for dirent in dirents:
file_name, ext = os.path.splitext(dirent.obj_name)
file_name_to_mtime_dict[file_name] = dirent.mtime
valid_faces_records = []
for record in faces_records:
excluded_photo_ids = [item['row_id'] for item in record.get(FACES_TABLE.columns.excluded_photo_links.name, [])]
included_photo_links = record.get(FACES_TABLE.columns.included_photo_links.name, [])
valid_photo_links = [item for item in record.get(FACES_TABLE.columns.photo_links.name, []) if item['row_id'] not in excluded_photo_ids]
valid_photo_ids = [item['row_id'] for item in valid_photo_links]
valid_photo_links.extend([item for item in included_photo_links if item['row_id'] not in valid_photo_ids])
if not valid_photo_links:
continue
valid_faces_records.append({
FACES_TABLE.columns.id.name: record.get(FACES_TABLE.columns.id.name),
FACES_TABLE.columns.name.name: record.get(FACES_TABLE.columns.name.name),
FACES_TABLE.columns.photo_links.name: valid_photo_links,
'_is_someone': record.get(FACES_TABLE.columns.name.name) != UNKNOWN_PEOPLE_NAME,
'file_mtime': file_name_to_mtime_dict.get(record.get(FACES_TABLE.columns.id.name))
})
return Response({
'metadata': metadata_columns,
'results': valid_faces_records,
})
class FacesRecord(APIView):
authentication_classes = (TokenAuthentication, SessionAuthentication)
permission_classes = (IsAuthenticated,)
throttle_classes = (UserRateThrottle,)
def put(self, request, repo_id):
name = request.data.get('name')
record_id = request.data.get('record_id')
from seafevents.face_recognition.constants import UNKNOWN_PEOPLE_NAME
if not name or name == UNKNOWN_PEOPLE_NAME:
error_msg = 'name invalid'
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
if not record_id:
error_msg = 'record_id invalid'
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
metadata = RepoMetadata.objects.filter(repo_id=repo_id).first()
if not metadata or not metadata.enabled or not metadata.face_recognition_enabled:
error_msg = f'The face recognition is disabled for repo {repo_id}.'
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
# resource check
repo = seafile_api.get_repo(repo_id)
if not repo:
error_msg = 'Library %s not found.' % repo_id
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
if not is_repo_admin(request.user.username, repo_id):
error_msg = 'Permission denied.'
return api_error(status.HTTP_403_FORBIDDEN, error_msg)
metadata_server_api = MetadataServerAPI(repo_id, request.user.username)
from seafevents.repo_metadata.constants import FACES_TABLE
try:
faces_table = get_table_by_name(metadata_server_api, FACES_TABLE.name)
except Exception as e:
logger.error(e)
error_msg = 'Internal Server Error'
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
if not faces_table:
return api_error(status.HTTP_404_NOT_FOUND, 'faces table not found')
faces_table_id = faces_table['id']
sql = f'SELECT * FROM `{FACES_TABLE.name}` WHERE `{FACES_TABLE.columns.id.name}` = "{record_id}"'
try:
results = metadata_server_api.query_rows(sql).get('results', [])
except Exception as e:
logger.error(e)
error_msg = 'Internal Server Error'
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
if not results:
error_msg = 'Record not found'
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
update_row = {
FACES_TABLE.columns.id.name: record_id,
FACES_TABLE.columns.name.name: name,
}
try:
metadata_server_api.update_rows(faces_table_id, [update_row])
except Exception as e:
logger.error(e)
error_msg = 'Internal Server Error'
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
return Response({'success': True})
class PeoplePhotos(APIView):
authentication_classes = (TokenAuthentication, SessionAuthentication)
permission_classes = (IsAuthenticated,)
throttle_classes = (UserRateThrottle,)
def get(self, request, repo_id, people_id):
start = request.GET.get('start', 0)
limit = request.GET.get('limit', 1000)
try:
start = int(start)
limit = int(limit)
except:
start = 0
limit = 1000
if start < 0:
error_msg = 'start invalid'
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
if limit < 0:
error_msg = 'limit invalid'
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
metadata = RepoMetadata.objects.filter(repo_id=repo_id).first()
if not metadata or not metadata.enabled or not metadata.face_recognition_enabled:
error_msg = f'The face recognition is disabled for repo {repo_id}.'
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
repo = seafile_api.get_repo(repo_id)
if not repo:
error_msg = 'Library %s not found.' % repo_id
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
if not can_read_metadata(request, repo_id):
error_msg = 'Permission denied.'
return api_error(status.HTTP_403_FORBIDDEN, error_msg)
metadata_server_api = MetadataServerAPI(repo_id, request.user.username)
from seafevents.repo_metadata.constants import METADATA_TABLE, FACES_TABLE
sql = f'SELECT `{FACES_TABLE.columns.photo_links.name}`, `{FACES_TABLE.columns.excluded_photo_links.name}`, `{FACES_TABLE.columns.included_photo_links.name}` FROM `{FACES_TABLE.name}` WHERE `{FACES_TABLE.columns.id.name}` = "{people_id}"'
try:
query_result = metadata_server_api.query_rows(sql)
except Exception as e:
logger.error(e)
error_msg = 'Internal Server Error'
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
faces_records = query_result.get('results')
if not faces_records:
return Response({'metadata': [], 'results': []})
faces_record = faces_records[0]
try:
view = RepoMetadataViews.objects.get_view(repo_id, FACE_RECOGNITION_VIEW_ID)
except Exception as e:
logger.exception(e)
error_msg = 'Internal Server Error'
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
from seafevents.repo_metadata.utils import gen_sorts_sql
from seafevents.repo_metadata.constants import PrivatePropertyKeys
try:
columns = metadata_server_api.list_columns(METADATA_TABLE.id).get('columns')
order_sql = gen_sorts_sql(METADATA_TABLE, columns, view.get('sorts'))
except Exception as e:
logger.exception(e)
error_msg = 'Internal Server Error'
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
# Reduce the size of the response
select_columns = f'`{METADATA_TABLE.columns.id.name}`, `{METADATA_TABLE.columns.parent_dir.name}`, `{METADATA_TABLE.columns.file_name.name}`, `{METADATA_TABLE.columns.file_ctime.name}`, `{METADATA_TABLE.columns.file_mtime.name}`'
capture_time_column_name = next((column.get('name') for column in columns if column.get('key') == PrivatePropertyKeys.CAPTURE_TIME), None)
if capture_time_column_name:
select_columns = f'{select_columns}, `{capture_time_column_name}`'
try:
excluded_record_ids = [item['row_id'] for item in faces_record.get(FACES_TABLE.columns.excluded_photo_links.name, [])]
included_record_ids = [item['row_id'] for item in faces_record.get(FACES_TABLE.columns.included_photo_links.name, [])]
record_ids = [item['row_id'] for item in faces_record.get(FACES_TABLE.columns.photo_links.name, []) if item['row_id'] not in excluded_record_ids]
record_ids.extend([item for item in included_record_ids if item not in record_ids])
if not record_ids:
return Response({'metadata': [], 'results': []})
record_ids_str = ', '.join(["'%s'" % id for id in record_ids])
sql = f'SELECT {select_columns} FROM `{METADATA_TABLE.name}` WHERE `{METADATA_TABLE.columns.id.name}` IN ({record_ids_str}) {order_sql} LIMIT {start}, {limit}'
people_photos = metadata_server_api.query_rows(sql)
except Exception as e:
logger.error(e)
error_msg = 'Internal Server Error'
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
return Response(people_photos)
def post(self, request, repo_id):
people_ids = request.data.get('people_ids')
record_ids = request.data.get('record_ids')
if not people_ids or not isinstance(people_ids, list):
error_msg ='people_ids invalid.'
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
if not record_ids or not isinstance(record_ids, list):
error_msg = 'record_ids invalid.'
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
metadata = RepoMetadata.objects.filter(repo_id=repo_id).first()
if not metadata or not metadata.enabled or not metadata.face_recognition_enabled:
error_msg = f'The face recognition is disabled for repo {repo_id}.'
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
repo = seafile_api.get_repo(repo_id)
if not repo:
error_msg = 'Library %s not found.' % repo_id
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
if not is_repo_admin(request.user.username, repo_id):
error_msg = 'Permission denied.'
return api_error(status.HTTP_403_FORBIDDEN, error_msg)
from seafevents.repo_metadata.constants import FACES_TABLE
from seafevents.face_recognition.constants import UNKNOWN_PEOPLE_NAME
metadata_server_api = MetadataServerAPI(repo_id, request.user.username)
try:
faces_table = get_table_by_name(metadata_server_api, FACES_TABLE.name)
except Exception as e:
logger.error(e)
error_msg = 'Internal Server Error'
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
if not faces_table:
return api_error(status.HTTP_404_NOT_FOUND, 'faces table not found')
faces_table_id = faces_table['id']
people_id_placeholders = ', '.join(['?' for _ in people_ids])
sql = f'SELECT * FROM `{FACES_TABLE.name}` WHERE `{FACES_TABLE.columns.id.name}` IN ({people_id_placeholders}) OR `{FACES_TABLE.columns.name.name}` = "{UNKNOWN_PEOPLE_NAME}"'
try:
query_result = metadata_server_api.query_rows(sql, people_ids).get('results', [])
except Exception as e:
logger.error(e)
error_msg = 'Internal Server Error'
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
# build face record map
face_records = {record[FACES_TABLE.columns.id.name]: record for record in query_result if record[FACES_TABLE.columns.id.name] in people_ids}
unknown_people_record = next((item for item in query_result if item.get(FACES_TABLE.columns.name.name) == UNKNOWN_PEOPLE_NAME), None)
if not unknown_people_record:
return api_error(status.HTTP_404_NOT_FOUND, 'Unknown people not found')
row_id_map = {}
update_link_map = {}
for people_id in people_ids:
face_record = face_records.get(people_id)
if not face_record:
return api_error(status.HTTP_404_NOT_FOUND, f'people {people_id} not found')
excluded_record_ids = [item['row_id'] for item in face_record.get(FACES_TABLE.columns.excluded_photo_links.name, [])]
duplicate_record_ids = [record_id for record_id in record_ids if record_id in excluded_record_ids]
if duplicate_record_ids:
update_link_map[people_id] = [record_id for record_id in excluded_record_ids if record_id not in duplicate_record_ids]
row_id_map[people_id] = record_ids
# update links in batch
if update_link_map:
try:
metadata_server_api.update_link(FACES_TABLE.excluded_face_link_id, faces_table_id, update_link_map)
except Exception as e:
logger.error(e)
error_msg = 'Internal Server Error'
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
# insert links in batch
try:
metadata_server_api.insert_link(FACES_TABLE.included_face_link_id, faces_table_id, row_id_map)
unknown_people_record_id = unknown_people_record[FACES_TABLE.columns.id.name]
metadata_server_api.insert_link(FACES_TABLE.excluded_face_link_id, faces_table_id, {
unknown_people_record_id: [record_id for record_id in record_ids if record_id not in [item['row_id'] for item in unknown_people_record.get(FACES_TABLE.columns.excluded_photo_links.name, [])]]
})
except Exception as e:
logger.error(e)
error_msg = 'Internal Server Error'
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
return Response({'success': True})
def delete(self, request, repo_id, people_id):
record_ids = request.data.get('record_ids')
if not record_ids or not isinstance(record_ids, list):
error_msg = 'record_ids invalid.'
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
metadata = RepoMetadata.objects.filter(repo_id=repo_id).first()
if not metadata or not metadata.enabled or not metadata.face_recognition_enabled:
error_msg = f'The face recognition is disabled for repo {repo_id}.'
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
repo = seafile_api.get_repo(repo_id)
if not repo:
error_msg = 'Library %s not found.' % repo_id
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
if not is_repo_admin(request.user.username, repo_id):
error_msg = 'Permission denied.'
return api_error(status.HTTP_403_FORBIDDEN, error_msg)
from seafevents.repo_metadata.constants import FACES_TABLE
metadata_server_api = MetadataServerAPI(repo_id, request.user.username)
try:
faces_table = get_table_by_name(metadata_server_api, FACES_TABLE.name)
except Exception as e:
logger.error(e)
error_msg = 'Internal Server Error'
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
if not faces_table:
return api_error(status.HTTP_404_NOT_FOUND, 'faces table not found')
faces_table_id = faces_table['id']
sql = f'SELECT `{FACES_TABLE.columns.included_photo_links.name}` FROM `{FACES_TABLE.name}` WHERE `{FACES_TABLE.columns.id.name}` = "{people_id}"'
try:
query_result = metadata_server_api.query_rows(sql).get('results')
except Exception as e:
logger.error(e)
error_msg = 'Internal Server Error'
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
if not query_result:
return api_error(status.HTTP_404_NOT_FOUND, 'people not found')
face_record = query_result[0]
included_record_ids = [item['row_id'] for item in face_record.get(FACES_TABLE.columns.included_photo_links.name, [])]
duplicate_record_ids = [record_id for record_id in record_ids if record_id in included_record_ids]
if duplicate_record_ids:
try:
metadata_server_api.update_link(FACES_TABLE.included_face_link_id, faces_table_id, {
people_id: [record_id for record_id in included_record_ids if record_id not in duplicate_record_ids]
})
except Exception as e:
logger.error(e)
error_msg = 'Internal Server Error'
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
try:
metadata_server_api.insert_link(FACES_TABLE.excluded_face_link_id, faces_table_id, {
people_id: record_ids
})
except Exception as e:
logger.error(e)
error_msg = 'Internal Server Error'
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
return Response({'success': True})
class FaceRecognitionManage(APIView):
authentication_classes = (TokenAuthentication, SessionAuthentication)
permission_classes = (IsAuthenticated, )
throttle_classes = (UserRateThrottle, )
def get(self, request, repo_id):
# resource check
repo = seafile_api.get_repo(repo_id)
if not repo:
error_msg = 'Library %s not found.' % repo_id
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
metadata = RepoMetadata.objects.filter(repo_id=repo_id).first()
if not metadata or not metadata.enabled:
error_msg = f'The metadata module is not enabled for repo {repo_id}.'
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
# permission check
if not can_read_metadata(request, repo_id):
error_msg = 'Permission denied.'
return api_error(status.HTTP_403_FORBIDDEN, error_msg)
try:
record = RepoMetadata.objects.filter(repo_id=repo_id).first()
if record and record.face_recognition_enabled:
is_enabled = True
else:
is_enabled = False
except Exception as e:
logger.error(e)
error_msg = 'Internal Server Error'
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
return Response({'enabled': is_enabled})
def post(self, request, repo_id):
metadata = RepoMetadata.objects.filter(repo_id=repo_id).first()
if not metadata or not metadata.enabled:
error_msg = f'The metadata module is not enabled for repo {repo_id}.'
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
# resource check
repo = seafile_api.get_repo(repo_id)
if not repo:
error_msg = 'Library %s not found.' % repo_id
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
if not is_repo_admin(request.user.username, repo_id):
error_msg = 'Permission denied.'
return api_error(status.HTTP_403_FORBIDDEN, error_msg)
metadata_server_api = MetadataServerAPI(repo_id, request.user.username)
init_faces(metadata_server_api)
dir_id = seafile_api.get_dir_id_by_path(repo_id, FACES_SAVE_PATH)
if not dir_id:
seafile_api.mkdir_with_parents(repo_id, '/', FACES_SAVE_PATH, request.user.username)
try:
RepoMetadata.objects.enable_face_recognition(repo_id)
except Exception as e:
logger.exception(e)
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, 'Internal Server Error')
params = {
'repo_id': repo_id,
'username': request.user.username,
}
try:
task_id = add_init_face_recognition_task(params=params)
except Exception as e:
logger.error(e)
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, 'Internal Server Error')
return Response({'task_id': task_id})
def delete(self, request, repo_id):
# resource check
repo = seafile_api.get_repo(repo_id)
if not repo:
error_msg = 'Library %s not found.' % repo_id
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
# permission check
if not is_repo_admin(request.user.username, repo_id):
error_msg = 'Permission denied.'
return api_error(status.HTTP_403_FORBIDDEN, error_msg)
# check dose the repo have opened metadata manage
record = RepoMetadata.objects.filter(repo_id=repo_id).first()
if not record or not record.enabled or not record.face_recognition_enabled:
error_msg = f'The repo {repo_id} has disabled the face recognition manage.'
return api_error(status.HTTP_409_CONFLICT, error_msg)
metadata_server_api = MetadataServerAPI(repo_id, request.user.username)
try:
remove_faces_table(metadata_server_api)
except Exception as err:
logger.error(err)
error_msg = 'Internal Server Error'
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
parent_dir = os.path.dirname(FACES_SAVE_PATH)
file_name = os.path.basename(FACES_SAVE_PATH)
username = request.user.username
seafile_api.del_file(repo_id, parent_dir, json.dumps([file_name]), username)
try:
record.face_recognition_enabled = False
record.last_face_cluster_time = None
record.save()
except Exception as e:
logger.error(e)
error_msg = 'Internal Server Error'
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
return Response({'success': True})
class MetadataExtractFileDetails(APIView):
authentication_classes = (TokenAuthentication, SessionAuthentication)
permission_classes = (IsAuthenticated,)
throttle_classes = (UserRateThrottle,)
def post(self, request, repo_id):
obj_ids = request.data.get('obj_ids')
if not obj_ids or not isinstance(obj_ids, list) or len(obj_ids) > 50:
error_msg = 'obj_ids is invalid.'
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
record = RepoMetadata.objects.filter(repo_id=repo_id).first()
if not record or not record.enabled:
error_msg = f'The metadata module is disabled for repo {repo_id}.'
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
repo = seafile_api.get_repo(repo_id)
if not repo:
error_msg = 'Library %s not found.' % repo_id
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
permission = check_folder_permission(request, repo_id, '/')
if permission != 'rw':
error_msg = 'Permission denied.'
return api_error(status.HTTP_403_FORBIDDEN, error_msg)
params = {
'obj_ids': obj_ids,
'repo_id': repo_id
}
try:
resp = extract_file_details(params=params)
except Exception as e:
logger.exception(e)
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, 'Internal Server Error')
return Response({'details': resp})
class MetadataRecognizeFaces(APIView):
authentication_classes = (TokenAuthentication, SessionAuthentication)
permission_classes = (IsAuthenticated,)
throttle_classes = (UserRateThrottle,)
def post(self, request, repo_id):
obj_ids = request.data.get('obj_ids')
if not obj_ids or not isinstance(obj_ids, list) or len(obj_ids) > 50:
error_msg = 'obj_ids is invalid.'
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
record = RepoMetadata.objects.filter(repo_id=repo_id).first()
if not record or not record.enabled:
error_msg = f'The metadata module is disabled for repo {repo_id}.'
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
repo = seafile_api.get_repo(repo_id)
if not repo:
error_msg = 'Library %s not found.' % repo_id
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
permission = check_folder_permission(request, repo_id, '/')
if permission != 'rw':
error_msg = 'Permission denied.'
return api_error(status.HTTP_403_FORBIDDEN, error_msg)
params = {
'obj_ids': obj_ids,
'repo_id': repo_id
}
try:
recognize_faces(params=params)
except Exception as e:
logger.exception(e)
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, 'Internal Server Error')
return Response({'success': True})
# tags
class MetadataTagsStatusManage(APIView):
authentication_classes = (TokenAuthentication, SessionAuthentication)
permission_classes = (IsAuthenticated,)
throttle_classes = (UserRateThrottle,)
def put(self, request, repo_id):
lang = request.data.get('lang')
if not lang:
error_msg = 'lang invalid.'
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
# resource check
repo = seafile_api.get_repo(repo_id)
if not repo:
error_msg = 'Library %s not found.' % repo_id
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
if not is_repo_admin(request.user.username, repo_id):
error_msg = 'Permission denied.'
return api_error(status.HTTP_403_FORBIDDEN, error_msg)
metadata = RepoMetadata.objects.filter(repo_id=repo_id).first()
if not metadata or not metadata.enabled:
error_msg = f'The metadata module is not enabled for repo {repo_id}.'
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
old_tags_enabled = metadata.tags_enabled
try:
metadata.tags_enabled = True
metadata.tags_lang = lang
metadata.save()
except Exception as e:
logger.exception(e)
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, 'Internal Server Error')
if not old_tags_enabled:
metadata_server_api = MetadataServerAPI(repo_id, request.user.username)
init_tags(metadata_server_api)
return Response({'success': True})
def delete(self, request, repo_id):
# resource check
repo = seafile_api.get_repo(repo_id)
if not repo:
error_msg = 'Library %s not found.' % repo_id
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
# permission check
if not is_repo_admin(request.user.username, repo_id):
error_msg = 'Permission denied.'
return api_error(status.HTTP_403_FORBIDDEN, error_msg)
# check dose the repo have opened metadata manage
record = RepoMetadata.objects.filter(repo_id=repo_id).first()
if not record or not record.enabled or not record.tags_enabled:
error_msg = f'The repo {repo_id} has disabled the tags manage.'
return api_error(status.HTTP_409_CONFLICT, error_msg)
metadata_server_api = MetadataServerAPI(repo_id, request.user.username)
try:
remove_tags_table(metadata_server_api)
except Exception as err:
logger.error(err)
error_msg = 'Internal Server Error'
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
try:
record.tags_enabled = False
record.tags_lang = None
record.save()
except Exception as e:
logger.error(e)
error_msg = 'Internal Server Error'
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
return Response({'success': True})
class MetadataTags(APIView):
authentication_classes = (TokenAuthentication, SessionAuthentication)
permission_classes = (IsAuthenticated,)
throttle_classes = (UserRateThrottle,)
def get(self, request, repo_id):
start = request.GET.get('start', 0)
limit = request.GET.get('limit', 1000)
try:
start = int(start)
limit = int(limit)
except:
start = 0
limit = 1000
if start < 0:
error_msg = 'start invalid'
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
if limit < 0:
error_msg = 'limit invalid'
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
metadata = RepoMetadata.objects.filter(repo_id=repo_id).first()
if not metadata or not metadata.enabled or not metadata.tags_enabled:
error_msg = f'The tags is disabled for repo {repo_id}.'
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
repo = seafile_api.get_repo(repo_id)
if not repo:
error_msg = 'Library %s not found.' % repo_id
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
if not can_read_metadata(request, repo_id):
error_msg = 'Permission denied.'
return api_error(status.HTTP_403_FORBIDDEN, error_msg)
metadata_server_api = MetadataServerAPI(repo_id, request.user.username)
from seafevents.repo_metadata.constants import TAGS_TABLE
sql = f'SELECT * FROM `{TAGS_TABLE.name}` ORDER BY `_ctime` LIMIT {start}, {limit}'
try:
query_result = metadata_server_api.query_rows(sql)
except Exception as e:
logger.error(e)
error_msg = 'Internal Server Error'
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
return Response(query_result)
def post(self, request, repo_id):
tags_data = request.data.get('tags_data', [])
if not tags_data:
error_msg = 'Tags data is required.'
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
metadata = RepoMetadata.objects.filter(repo_id=repo_id).first()
if not metadata or not metadata.enabled or not metadata.tags_enabled:
error_msg = f'The tags is disabled for repo {repo_id}.'
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
repo = seafile_api.get_repo(repo_id)
if not repo:
error_msg = f'Library {repo_id} not found.'
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
if not can_read_metadata(request, repo_id):
error_msg = 'Permission denied.'
return api_error(status.HTTP_403_FORBIDDEN, error_msg)
metadata_server_api = MetadataServerAPI(repo_id, request.user.username)
from seafevents.repo_metadata.constants import TAGS_TABLE
try:
tags_table = get_table_by_name(metadata_server_api, TAGS_TABLE.name)
except Exception as e:
logger.error(e)
error_msg = 'Internal Server Error'
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
if not tags_table:
return api_error(status.HTTP_404_NOT_FOUND, 'tags table not found')
tags_table_id = tags_table['id']
exist_tags = []
new_tags = []
tags_names = [tag_data.get(TAGS_TABLE.columns.name.name, '') for tag_data in tags_data]
tags_names_str = ', '.join([f'"{tag_name}"' for tag_name in tags_names])
sql = f'SELECT * FROM {TAGS_TABLE.name} WHERE `{TAGS_TABLE.columns.name.name}` in ({tags_names_str})'
try:
exist_rows = metadata_server_api.query_rows(sql)
exist_tags = exist_rows.get('results', [])
except Exception as e:
logger.exception(e)
error_msg = 'Internal Server Error'
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
if exist_tags:
for tag_data in tags_data:
tag_name = tag_data.get(TAGS_TABLE.columns.name.name, '')
if tag_name not in tags_names:
new_tags.append(tag_data)
else:
new_tags = tags_data
tags = exist_tags
if not new_tags:
return Response({'tags': tags})
try:
resp = metadata_server_api.insert_rows(tags_table_id, new_tags)
except Exception as e:
logger.error(e)
error_msg = 'Internal Server Error'
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
row_ids = resp.get('row_ids', [])
row_ids_str = ', '.join([f'"{id}"' for id in row_ids])
sql = f'SELECT * FROM {TAGS_TABLE.name} WHERE `{TAGS_TABLE.columns.id.name}` in ({row_ids_str})'
try:
query_new_rows = metadata_server_api.query_rows(sql)
new_tags_data = query_new_rows.get('results', [])
tags.extend(new_tags_data)
except Exception as e:
logger.error(e)
error_msg = 'Internal Server Error'
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
return Response({'tags': tags})
def put(self, request, repo_id):
tags_data = request.data.get('tags_data')
if not tags_data:
error_msg = 'tags_data invalid.'
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
metadata = RepoMetadata.objects.filter(repo_id=repo_id).first()
if not metadata or not metadata.enabled or not metadata.tags_enabled:
error_msg = f'The tags is disabled for repo {repo_id}.'
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
repo = seafile_api.get_repo(repo_id)
if not repo:
error_msg = 'Library %s not found.' % repo_id
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
if not can_read_metadata(request, repo_id):
error_msg = 'Permission denied.'
return api_error(status.HTTP_403_FORBIDDEN, error_msg)
metadata_server_api = MetadataServerAPI(repo_id, request.user.username)
from seafevents.repo_metadata.constants import TAGS_TABLE
try:
tags_table = get_table_by_name(metadata_server_api, TAGS_TABLE.name)
except Exception as e:
logger.error(e)
error_msg = 'Internal Server Error'
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
if not tags_table:
return api_error(status.HTTP_404_NOT_FOUND, 'tags table not found')
tags_table_id = tags_table['id']
tag_id_to_tag = {}
sql = f'SELECT `_id` FROM `{TAGS_TABLE.name}` WHERE '
parameters = []
for tag_data in tags_data:
tag = tag_data.get('tag', {})
if not tag:
continue
tag_id = tag_data.get('tag_id', '')
if not tag_id:
error_msg = 'record_id invalid.'
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
sql += f' `{TAGS_TABLE.columns.id.name}` = ? OR '
parameters.append(tag_id)
tag_id_to_tag[tag_id] = tag
sql = sql.rstrip('OR ')
sql += ';'
if not parameters:
return Response({'success': True})
try:
query_result = metadata_server_api.query_rows(sql, parameters)
except Exception as e:
logger.exception(e)
error_msg = 'Internal Server Error'
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
results = query_result.get('results')
if not results:
# file or folder has been deleted
return Response({'success': True})
rows = []
for tag in results:
tag_id = tag.get('_id')
update = tag_id_to_tag.get(tag_id)
update[TAGS_TABLE.columns.id.name] = tag_id
rows.append(update)
if rows:
try:
metadata_server_api.update_rows(tags_table_id, rows)
except Exception as e:
logger.exception(e)
error_msg = 'Internal Server Error'
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
return Response({'success': True})
def delete(self, request, repo_id):
tag_ids = request.data.get('tag_ids', [])
if not tag_ids:
error_msg = 'Tag ids is required.'
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
metadata = RepoMetadata.objects.filter(repo_id=repo_id).first()
if not metadata or not metadata.enabled or not metadata.tags_enabled:
error_msg = f'The tags is disabled for repo {repo_id}.'
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
repo = seafile_api.get_repo(repo_id)
if not repo:
error_msg = 'Library %s not found.' % repo_id
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
if not can_read_metadata(request, repo_id):
error_msg = 'Permission denied.'
return api_error(status.HTTP_403_FORBIDDEN, error_msg)
metadata_server_api = MetadataServerAPI(repo_id, request.user.username)
from seafevents.repo_metadata.constants import TAGS_TABLE
try:
tags_table = get_table_by_name(metadata_server_api, TAGS_TABLE.name)
except Exception as e:
logger.error(e)
error_msg = 'Internal Server Error'
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
if not tags_table:
return api_error(status.HTTP_404_NOT_FOUND, 'tags table not found')
tags_table_id = tags_table['id']
try:
metadata_server_api.delete_rows(tags_table_id, tag_ids)
except Exception as e:
logger.error(e)
error_msg = 'Internal Server Error'
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
return Response({'success': True})
class MetadataTagsLinks(APIView):
authentication_classes = (TokenAuthentication, SessionAuthentication)
permission_classes = (IsAuthenticated,)
throttle_classes = (UserRateThrottle,)
def post(self, request, repo_id):
link_column_key = request.data.get('link_column_key')
row_id_map = request.data.get('row_id_map')
if not link_column_key:
return api_error(status.HTTP_400_BAD_REQUEST, 'link_column_key invalid')
if not row_id_map:
return api_error(status.HTTP_400_BAD_REQUEST, 'row_id_map invalid')
metadata = RepoMetadata.objects.filter(repo_id=repo_id).first()
if not metadata or not metadata.enabled:
error_msg = f'The metadata module is disabled for repo {repo_id}.'
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
repo = seafile_api.get_repo(repo_id)
if not repo:
error_msg = 'Library %s not found.' % repo_id
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
if not can_read_metadata(request, repo_id):
error_msg = 'Permission denied.'
return api_error(status.HTTP_403_FORBIDDEN, error_msg)
metadata_server_api = MetadataServerAPI(repo_id, request.user.username)
try:
metadata = metadata_server_api.get_metadata()
except Exception as e:
logger.error(e)
error_msg = 'Internal Server Error'
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
from seafevents.repo_metadata.constants import TAGS_TABLE
tables = metadata.get('tables', [])
tags_table_id = [table['id'] for table in tables if table['name'] == TAGS_TABLE.name]
tags_table_id = tags_table_id[0] if tags_table_id else None
if not tags_table_id:
return api_error(status.HTTP_404_NOT_FOUND, 'tags not be used')
try:
columns_data = metadata_server_api.list_columns(tags_table_id)
columns = columns_data.get('columns', [])
except Exception as e:
logger.error(e)
error_msg = 'Internal Server Error'
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
link_column = [column for column in columns if column['key'] == link_column_key and column['type'] == 'link']
link_column = link_column[0] if link_column else None
if not link_column:
# init self link columns
if link_column_key == TAGS_TABLE.columns.parent_links.key or link_column_key == TAGS_TABLE.columns.sub_links.key:
try:
init_tag_self_link_columns(metadata_server_api, tags_table_id)
link_id = TAGS_TABLE.self_link_id
is_linked_back = link_column_key == TAGS_TABLE.columns.sub_links.key if True else False
except Exception as e:
logger.error(e)
error_msg = 'Internal Server Error'
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
else:
return api_error(status.HTTP_400_BAD_REQUEST, 'link column %s not found' % link_column_key)
else:
link_column_data = link_column.get('data', {})
link_id = link_column_data.get('link_id', '')
is_linked_back = link_column_data.get('is_linked_back', False)
if not link_id:
return api_error(status.HTTP_400_BAD_REQUEST, 'invalid link column')
try:
metadata_server_api.insert_link(link_id, tags_table_id, row_id_map, is_linked_back)
except Exception as e:
logger.exception(e)
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, 'Internal Server Error')
return Response({'success': True})
def put(self, request, repo_id):
link_column_key = request.data.get('link_column_key')
row_id_map = request.data.get('row_id_map')
if not row_id_map:
return api_error(status.HTTP_400_BAD_REQUEST, 'row_id_map invalid')
metadata = RepoMetadata.objects.filter(repo_id=repo_id).first()
if not metadata or not metadata.enabled:
error_msg = f'The metadata module is disabled for repo {repo_id}.'
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
repo = seafile_api.get_repo(repo_id)
if not repo:
error_msg = 'Library %s not found.' % repo_id
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
if not can_read_metadata(request, repo_id):
error_msg = 'Permission denied.'
return api_error(status.HTTP_403_FORBIDDEN, error_msg)
metadata_server_api = MetadataServerAPI(repo_id, request.user.username)
try:
metadata = metadata_server_api.get_metadata()
except Exception as e:
logger.error(e)
error_msg = 'Internal Server Error'
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
from seafevents.repo_metadata.constants import TAGS_TABLE
tables = metadata.get('tables', [])
tags_table_id = [table['id'] for table in tables if table['name'] == TAGS_TABLE.name]
tags_table_id = tags_table_id[0] if tags_table_id else None
if not tags_table_id:
return api_error(status.HTTP_404_NOT_FOUND, 'tags not be used')
try:
columns_data = metadata_server_api.list_columns(tags_table_id)
columns = columns_data.get('columns', [])
except Exception as e:
logger.error(e)
error_msg = 'Internal Server Error'
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
link_column = [column for column in columns if column['key'] == link_column_key and column['type'] == 'link']
link_column = link_column[0] if link_column else None
if not link_column:
return api_error(status.HTTP_400_BAD_REQUEST, 'link column %s not found' % link_column_key)
link_column_data = link_column.get('data', {})
link_id = link_column_data.get('link_id', '')
is_linked_back = link_column_data.get('is_linked_back', False)
if not link_id:
return api_error(status.HTTP_400_BAD_REQUEST, 'invalid link column')
try:
metadata_server_api.update_link(link_id, tags_table_id, row_id_map, is_linked_back)
except Exception as e:
logger.exception(e)
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, 'Internal Server Error')
return Response({'success': True})
def delete(self, request, repo_id):
link_column_key = request.data.get('link_column_key')
row_id_map = request.data.get('row_id_map')
if not link_column_key:
return api_error(status.HTTP_400_BAD_REQUEST, 'link_id invalid')
if not row_id_map:
return api_error(status.HTTP_400_BAD_REQUEST, 'row_id_map invalid')
metadata = RepoMetadata.objects.filter(repo_id=repo_id).first()
if not metadata or not metadata.enabled:
error_msg = f'The metadata module is disabled for repo {repo_id}.'
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
repo = seafile_api.get_repo(repo_id)
if not repo:
error_msg = 'Library %s not found.' % repo_id
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
if not can_read_metadata(request, repo_id):
error_msg = 'Permission denied.'
return api_error(status.HTTP_403_FORBIDDEN, error_msg)
metadata_server_api = MetadataServerAPI(repo_id, request.user.username)
try:
metadata = metadata_server_api.get_metadata()
except Exception as e:
logger.error(e)
error_msg = 'Internal Server Error'
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
from seafevents.repo_metadata.constants import TAGS_TABLE
tables = metadata.get('tables', [])
tags_table_id = [table['id'] for table in tables if table['name'] == TAGS_TABLE.name]
tags_table_id = tags_table_id[0] if tags_table_id else None
if not tags_table_id:
return api_error(status.HTTP_404_NOT_FOUND, 'tags not be used')
try:
columns_data = metadata_server_api.list_columns(tags_table_id)
columns = columns_data.get('columns', [])
except Exception as e:
logger.error(e)
error_msg = 'Internal Server Error'
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
link_column = [column for column in columns if column['key'] == link_column_key and column['type'] == 'link']
link_column = link_column[0] if link_column else None
if not link_column:
return api_error(status.HTTP_400_BAD_REQUEST, 'link column %s not found' % link_column_key)
link_column_data = link_column.get('data', {})
link_id = link_column_data.get('link_id', '')
is_linked_back = link_column_data.get('is_linked_back', False)
if not link_id:
return api_error(status.HTTP_400_BAD_REQUEST, 'invalid link column')
try:
metadata_server_api.delete_link(link_id, tags_table_id, row_id_map, is_linked_back)
except Exception as e:
logger.exception(e)
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, 'Internal Server Error')
return Response({'success': True})
class MetadataFileTags(APIView):
authentication_classes = (TokenAuthentication, SessionAuthentication)
permission_classes = (IsAuthenticated,)
throttle_classes = (UserRateThrottle,)
def put(self, request, repo_id):
file_tags_data = request.data.get('file_tags_data')
if not file_tags_data:
error_msg = 'file_tags_data invalid.'
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
metadata = RepoMetadata.objects.filter(repo_id=repo_id).first()
if not metadata or not metadata.enabled or not metadata.tags_enabled:
error_msg = f'The tags is disabled for repo {repo_id}.'
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
repo = seafile_api.get_repo(repo_id)
if not repo:
error_msg = 'Library %s not found.' % repo_id
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
if not can_read_metadata(request, repo_id):
error_msg = 'Permission denied.'
return api_error(status.HTTP_403_FORBIDDEN, error_msg)
from seafevents.repo_metadata.constants import TAGS_TABLE, METADATA_TABLE
metadata_server_api = MetadataServerAPI(repo_id, request.user.username)
success_records = []
failed_records = []
for file_tags in file_tags_data:
record_id = file_tags.get('record_id', '')
tags = file_tags.get('tags', [])
if not record_id:
continue
try:
metadata_server_api.update_link(TAGS_TABLE.file_link_id, METADATA_TABLE.id, { record_id: tags })
success_records.append(record_id)
except Exception as e:
failed_records.append(record_id)
return Response({'success': success_records, 'fail': failed_records})
class MetadataTagFiles(APIView):
authentication_classes = (TokenAuthentication, SessionAuthentication)
permission_classes = (IsAuthenticated,)
throttle_classes = (UserRateThrottle,)
def get(self, request, repo_id, tag_id):
metadata = RepoMetadata.objects.filter(repo_id=repo_id).first()
if not metadata or not metadata.enabled or not metadata.tags_enabled:
error_msg = f'The tags is disabled for repo {repo_id}.'
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
repo = seafile_api.get_repo(repo_id)
if not repo:
error_msg = 'Library %s not found.' % repo_id
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
if not can_read_metadata(request, repo_id):
error_msg = 'Permission denied.'
return api_error(status.HTTP_403_FORBIDDEN, error_msg)
metadata_server_api = MetadataServerAPI(repo_id, request.user.username)
from seafevents.repo_metadata.constants import TAGS_TABLE, METADATA_TABLE
tag_files_record_sql = f'SELECT * FROM {TAGS_TABLE.name} WHERE `{TAGS_TABLE.columns.id.name}` = "{tag_id}"'
try:
tag_query = metadata_server_api.query_rows(tag_files_record_sql)
except Exception as e:
logger.error(e)
error_msg = 'Internal Server Error'
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
tag_files_records = tag_query.get('results', [])
if not tag_files_records:
return Response({'metadata': [], 'results': []})
tag_files_record_ids = tag_files_records[0].get(TAGS_TABLE.columns.file_links.name, [])
if not tag_files_record_ids:
return Response({'metadata': [], 'results': []})
tag_files_sql = 'SELECT `%s`, `%s`, `%s`, `%s`, `%s`, `%s` FROM %s WHERE `%s` IN (%s)' % (METADATA_TABLE.columns.id.name, METADATA_TABLE.columns.file_name.name, \
METADATA_TABLE.columns.parent_dir.name, METADATA_TABLE.columns.size.name, \
METADATA_TABLE.columns.file_mtime.name, METADATA_TABLE.columns.tags.name, \
METADATA_TABLE.name, METADATA_TABLE.columns.id.name, \
', '.join(["'%s'" % id.get('row_id') for id in tag_files_record_ids]))
try:
tag_files_query = metadata_server_api.query_rows(tag_files_sql)
except Exception as e:
logger.error(e)
error_msg = 'Internal Server Error'
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
return Response(tag_files_query)
class MetadataTagsFiles(APIView):
authentication_classes = (TokenAuthentication, SessionAuthentication)
permission_classes = (IsAuthenticated,)
throttle_classes = (UserRateThrottle,)
def post(self, request, repo_id):
tags_ids = request.data.get('tags_ids', None)
if not tags_ids:
return api_error(status.HTTP_400_BAD_REQUEST, 'tags_ids is invalid.')
metadata = RepoMetadata.objects.filter(repo_id=repo_id).first()
if not metadata or not metadata.enabled or not metadata.tags_enabled:
error_msg = f'The tags is disabled for repo {repo_id}.'
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
repo = seafile_api.get_repo(repo_id)
if not repo:
error_msg = 'Library %s not found.' % repo_id
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
if not can_read_metadata(request, repo_id):
error_msg = 'Permission denied.'
return api_error(status.HTTP_403_FORBIDDEN, error_msg)
metadata_server_api = MetadataServerAPI(repo_id, request.user.username)
from seafevents.repo_metadata.constants import TAGS_TABLE, METADATA_TABLE
tags_ids_str = ', '.join([f'"{id}"' for id in tags_ids])
sql = f'SELECT * FROM {TAGS_TABLE.name} WHERE `{TAGS_TABLE.columns.id.name}` in ({tags_ids_str})'
try:
query_new_rows = metadata_server_api.query_rows(sql)
found_tags = query_new_rows.get('results', [])
except Exception as e:
logger.error(e)
error_msg = 'Internal Server Error'
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, 'Internal Server Error')
if not found_tags:
return Response([])
tags_files_ids = []
for tag in found_tags:
tags_files_ids.extend(tag.get(TAGS_TABLE.columns.file_links.name, []))
if not tags_files_ids:
return Response([])
tags_files_sql = 'SELECT `%s`, `%s`, `%s`, `%s`, `%s`, `%s` FROM %s WHERE `%s` IN (%s)' % (METADATA_TABLE.columns.id.name, METADATA_TABLE.columns.file_name.name, \
METADATA_TABLE.columns.parent_dir.name, METADATA_TABLE.columns.size.name, \
METADATA_TABLE.columns.file_mtime.name, METADATA_TABLE.columns.tags.name, \
METADATA_TABLE.name, METADATA_TABLE.columns.id.name, \
', '.join(["'%s'" % id.get('row_id') for id in tags_files_ids]))
try:
tags_files_query = metadata_server_api.query_rows(tags_files_sql)
except Exception as e:
logger.error(e)
error_msg = 'Internal Server Error'
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
return Response(tags_files_query)
class MetadataMergeTags(APIView):
authentication_classes = (TokenAuthentication, SessionAuthentication)
permission_classes = (IsAuthenticated,)
throttle_classes = (UserRateThrottle,)
def post(self, request, repo_id):
target_tag_id = request.data.get('target_tag_id')
merged_tags_ids = request.data.get('merged_tags_ids')
if not target_tag_id:
return api_error(status.HTTP_400_BAD_REQUEST, 'target_tag_id invalid')
if not merged_tags_ids:
return api_error(status.HTTP_400_BAD_REQUEST, 'merged_tags_ids invalid')
metadata = RepoMetadata.objects.filter(repo_id=repo_id).first()
if not metadata or not metadata.enabled:
error_msg = f'The metadata module is disabled for repo {repo_id}.'
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
repo = seafile_api.get_repo(repo_id)
if not repo:
error_msg = 'Library %s not found.' % repo_id
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
if not can_read_metadata(request, repo_id):
error_msg = 'Permission denied.'
return api_error(status.HTTP_403_FORBIDDEN, error_msg)
metadata_server_api = MetadataServerAPI(repo_id, request.user.username)
try:
metadata = metadata_server_api.get_metadata()
except Exception as e:
logger.error(e)
error_msg = 'Internal Server Error'
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
from seafevents.repo_metadata.constants import TAGS_TABLE
tables = metadata.get('tables', [])
tags_table_id = [table['id'] for table in tables if table['name'] == TAGS_TABLE.name]
tags_table_id = tags_table_id[0] if tags_table_id else None
if not tags_table_id:
return api_error(status.HTTP_404_NOT_FOUND, 'tags not be used')
try:
columns_data = metadata_server_api.list_columns(tags_table_id)
columns = columns_data.get('columns', [])
except Exception as e:
logger.error(e)
error_msg = 'Internal Server Error'
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
op_tags_ids = [target_tag_id] + merged_tags_ids
op_tags_ids_str = ', '.join([f'"{id}"' for id in op_tags_ids])
sql = f'SELECT * FROM {TAGS_TABLE.name} WHERE `{TAGS_TABLE.columns.id.name}` in ({op_tags_ids_str})'
try:
query_new_rows = metadata_server_api.query_rows(sql)
op_tags = query_new_rows.get('results', [])
except Exception as e:
logger.error(e)
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, 'Internal Server Error')
if not op_tags:
return api_error(status.HTTP_400_BAD_REQUEST, 'tags not found')
target_tag = next((tag for tag in op_tags if tag.get(TAGS_TABLE.columns.id.name) == target_tag_id), None)
if not target_tag:
return api_error(status.HTTP_400_BAD_REQUEST, 'target_tag_id invalid')
merged_tags = [tag for tag in op_tags if tag[TAGS_TABLE.columns.id.name] in merged_tags_ids]
if not merged_tags:
return api_error(status.HTTP_400_BAD_REQUEST, 'merged_tags_ids invalid')
# get unique parent/child/file links from merged tags which not exist in target tag
exist_parent_tags_ids = [link['row_id'] for link in target_tag.get(TAGS_TABLE.columns.parent_links.key, [])]
exist_child_tags_ids = [link['row_id'] for link in target_tag.get(TAGS_TABLE.columns.sub_links.key, [])]
exist_files_ids = [link['row_id'] for link in target_tag.get(TAGS_TABLE.columns.file_links.key, [])]
new_parent_tags_ids = []
new_child_tags_ids = []
new_files_ids = []
for merged_tag in merged_tags:
merged_parent_tags_ids = [link['row_id'] for link in merged_tag.get(TAGS_TABLE.columns.parent_links.key, [])]
merged_child_tags_ids = [link['row_id'] for link in merged_tag.get(TAGS_TABLE.columns.sub_links.key, [])]
merged_files_ids = [link['row_id'] for link in merged_tag.get(TAGS_TABLE.columns.file_links.key, [])]
for merged_parent_tag_id in merged_parent_tags_ids:
if merged_parent_tag_id not in op_tags_ids and merged_parent_tag_id not in exist_parent_tags_ids:
new_parent_tags_ids.append(merged_parent_tag_id)
exist_parent_tags_ids.append(merged_parent_tag_id)
for merged_child_tag_id in merged_child_tags_ids:
if merged_child_tag_id not in op_tags_ids and merged_child_tag_id not in exist_child_tags_ids:
new_child_tags_ids.append(merged_child_tag_id)
exist_child_tags_ids.append(merged_child_tag_id)
for merged_file_id in merged_files_ids:
if merged_file_id not in exist_files_ids:
new_files_ids.append(merged_file_id)
exist_files_ids.append(merged_file_id)
parent_link_column = [column for column in columns if column['key'] == TAGS_TABLE.columns.parent_links.key and column['type'] == 'link']
parent_link_column = parent_link_column[0] if parent_link_column else None
# add new parent tags
if new_parent_tags_ids:
try:
metadata_server_api.insert_link(TAGS_TABLE.self_link_id, tags_table_id, { target_tag_id: new_parent_tags_ids })
except Exception as e:
logger.error(e)
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, 'Internal Server Error')
# add new child tags
if new_child_tags_ids:
try:
metadata_server_api.insert_link(TAGS_TABLE.self_link_id, tags_table_id, { target_tag_id: new_child_tags_ids }, True)
except Exception as e:
logger.error(e)
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, 'Internal Server Error')
# add new tag files
if new_files_ids:
try:
metadata_server_api.insert_link(TAGS_TABLE.file_link_id, tags_table_id, { target_tag_id: new_files_ids })
except Exception as e:
logger.error(e)
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, 'Internal Server Error')
# remove merge tags
try:
metadata_server_api.delete_rows(tags_table_id, merged_tags_ids)
except Exception as e:
logger.error(e)
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, 'Internal Server Error')
return Response({'success': True})
class PeopleCoverPhoto(APIView):
authentication_classes = (TokenAuthentication, SessionAuthentication)
permission_classes = (IsAuthenticated,)
throttle_classes = (UserRateThrottle,)
def put(self, request, repo_id, people_id):
record_id = request.data.get('record_id')
if not record_id:
error_msg = 'record_id invalid'
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
metadata = RepoMetadata.objects.filter(repo_id=repo_id).first()
if (
not metadata
or not metadata.enabled
or not metadata.face_recognition_enabled
):
error_msg = f'The face recognition is disabled for repo {repo_id}.'
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
# resource check
repo = seafile_api.get_repo(repo_id)
if not repo:
error_msg = 'Library %s not found.' % repo_id
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
if not is_repo_admin(request.user.username, repo_id):
error_msg = 'Permission denied.'
return api_error(status.HTTP_403_FORBIDDEN, error_msg)
metadata_server_api = MetadataServerAPI(repo_id, request.user.username)
from seafevents.repo_metadata.constants import METADATA_TABLE
sql = f'SELECT `{METADATA_TABLE.columns.obj_id.name}`, `{METADATA_TABLE.columns.parent_dir.name}`, `{METADATA_TABLE.columns.file_name.name}` FROM `{METADATA_TABLE.name}` WHERE `{METADATA_TABLE.columns.id.name}` = "{record_id}"'
try:
query_result = metadata_server_api.query_rows(sql).get('results')
except Exception as e:
logger.error(e)
error_msg = 'Internal Server Error'
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
if not query_result:
return api_error(status.HTTP_404_NOT_FOUND, 'record not found')
row = query_result[0]
obj_id = row.get(METADATA_TABLE.columns.obj_id.name)
parent_dir = row.get(METADATA_TABLE.columns.parent_dir.name)
file_name = row.get(METADATA_TABLE.columns.file_name.name)
path = os.path.join(parent_dir, file_name)
token = seafile_api.get_fileserver_access_token(repo_id, obj_id, 'download', request.user.username, use_onetime=True)
if not token:
error_msg = 'Internal Server Error'
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
params = {
'repo_id': repo_id,
'path': path,
'download_token': token,
'people_id': people_id,
}
try:
update_people_cover_photo(params)
except Exception as e:
logger.error(e)
error_msg = 'Internal Server Error'
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
return Response({'success': True})