1
0
mirror of https://github.com/haiwen/seahub.git synced 2025-09-09 02:42:47 +00:00
Files
seahub/seahub/api2/endpoints/metadata_manage.py
shenzheng-1 9fbc7a8d34 add video details and extract button (#6908)
* add video details and extract button

* update

* update

* update

---------

Co-authored-by: zheng.shen <zheng.shen@seafile.com>
2024-10-18 13:25:10 +08:00

1108 lines
43 KiB
Python

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, gen_unique_id, init_metadata, \
get_unmodifiable_columns, can_read_metadata, init_faces, add_init_face_recognition_task, get_metadata_by_faces, extract_file_details
from seahub.repo_metadata.metadata_server_api import MetadataServerAPI, list_metadata_view_records
from seahub.utils.timeutils import datetime_to_isoformat_timestr
from seahub.utils.repo import is_repo_admin
from seaserv import seafile_api
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
"""
# 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 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.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 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.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 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', 100)
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)
# 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, 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.utils 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:
record_id = record.get('_id')
to_updated_record = record_id_to_record.get(record_id)
update = {
METADATA_TABLE.columns.id.name: record_id,
}
column_name, value = list(to_updated_record.items())[0]
if column_name not in unmodifiable_column_names:
try:
column = next(column for column in columns if column['name'] == column_name)
if value and column['type'] == 'date':
column_data = column.get('data', {})
format = column_data.get('format', 'YYYY-MM-DD')
saved_format = '%Y-%m-%d'
if 'HH:mm:ss' in format:
saved_format = '%Y-%m-%d %H:%M:%S'
elif 'HH:mm' in format:
saved_format = '%Y-%m-%d %H:%M'
datetime_obj = datetime.strptime(value, saved_format)
update[column_name] = datetime_to_isoformat_timestr(datetime_obj)
elif column['type'] == 'single-select' and not value:
update[column_name] = None
else:
update[column_name] = value
rows.append(update)
except Exception as e:
pass
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 MetadataRecordInfo(APIView):
authentication_classes = (TokenAuthentication, SessionAuthentication)
permission_classes = (IsAuthenticated,)
throttle_classes = (UserRateThrottle,)
def get(self, request, repo_id):
parent_dir = request.GET.get('parent_dir')
name = request.GET.get('name')
if not parent_dir:
error_msg = 'parent_dir invalid'
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
if not name:
error_msg = '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.utils import METADATA_TABLE
sql = f'SELECT * FROM `{METADATA_TABLE.name}` WHERE \
`{METADATA_TABLE.columns.parent_dir.name}`=? AND `{METADATA_TABLE.columns.file_name.name}`=?;'
parameters = [parent_dir, 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)
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.utils 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.utils 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.utils 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 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
view_name = request.data.get('name')
view_type = request.data.get('type', 'table')
view_data = request.data.get('data', {})
if not view_name:
error_msg = 'view name 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)
try:
new_view = RepoMetadataViews.objects.add_view(repo_id, view_name, view_type, 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({'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.view_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)
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)
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.view_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.delete_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({'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')
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)
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.view_ids:
error_msg = 'view_id %s does not exists.' % view_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:
result = RepoMetadataViews.objects.duplicate_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': result})
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):
# put view_id in front of target_view_id
view_id = request.data.get('view_id')
if not view_id:
error_msg = 'view_id is invalid.'
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
target_view_id = request.data.get('target_view_id')
if not target_view_id:
error_msg = 'target_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)
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.view_ids:
error_msg = 'view_id %s does not exists.' % view_id
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
if target_view_id not in views.view_ids:
error_msg = 'target_view_id %s does not exists.' % target_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:
results = RepoMetadataViews.objects.move_view(repo_id, view_id, target_view_id)
except Exception as 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', 100)
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:
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 not permission:
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.utils import METADATA_TABLE, FACES_TABLE
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)
tables = metadata.get('tables', [])
faces_table_id = [table['id'] for table in tables if table['name'] == FACES_TABLE.name]
faces_table_id = faces_table_id[0] if faces_table_id else None
if not faces_table_id:
return api_error(status.HTTP_404_NOT_FOUND, 'face recognition not be used')
sql = f'SELECT * FROM `{FACES_TABLE.name}` WHERE `{FACES_TABLE.columns.photo_links.name}` IS NOT NULL 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 = query_result.get('results')
if not faces:
error_msg = 'Records not found'
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
try:
query_result = get_metadata_by_faces(faces, metadata_server_api)
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:
error_msg = 'Records not found'
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
classify_result = dict()
for row in query_result:
link_row_ids = [item['row_id'] for item in row.get(METADATA_TABLE.columns.face_links.name, [])]
if not link_row_ids:
continue
for link_row_id in link_row_ids:
if link_row_id not in classify_result:
classify_result[link_row_id] = []
file_name = row.get(METADATA_TABLE.columns.file_name.name, '')
parent_dir = row.get(METADATA_TABLE.columns.parent_dir.name, '')
size = row.get(METADATA_TABLE.columns.size.name, 0)
mtime = row.get('_mtime')
classify_result[link_row_id].append({
'path': os.path.join(parent_dir, file_name),
'file_name': file_name,
'parent_dir': parent_dir,
'size': size,
'mtime': mtime
})
id_to_name = {item.get(FACES_TABLE.columns.id.name): item.get(FACES_TABLE.columns.name.name, '') for item in faces}
classify_result = [{
'record_id': key,
'name': id_to_name.get(key, ''),
'link_photos': value
} for key, value in classify_result.items()]
return Response({'results': classify_result})
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')
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)
from seafevents.repo_metadata.utils import FACES_TABLE
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)
tables = metadata.get('tables', [])
faces_table_id = [table['id'] for table in tables if table['name'] == FACES_TABLE.name]
faces_table_id = faces_table_id[0] if faces_table_id else None
if not faces_table_id:
return api_error(status.HTTP_404_NOT_FOUND, 'face recognition not be used')
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 FaceRecognitionManage(APIView):
authentication_classes = (TokenAuthentication, SessionAuthentication)
permission_classes = (IsAuthenticated, )
throttle_classes = (UserRateThrottle, )
def get(self, request, repo_id):
# 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)
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)
metadata_server_api = MetadataServerAPI(repo_id, request.user.username)
from seafevents.repo_metadata.utils import FACES_TABLE
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)
tables = metadata.get('tables', [])
faces_table_id = [table['id'] for table in tables if table['name'] == FACES_TABLE.name]
is_enabled = True if faces_table_id else False
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)
params = {
'repo_id': repo_id,
}
metadata_server_api = MetadataServerAPI(repo_id, request.user.username)
init_faces(metadata_server_api)
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})
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})