def get(self, request, token): # resource check form_obj = DTableForms.objects.get_form_by_token(token) if not form_obj: error_msg = 'Form %s not found.' % token return api_error(status.HTTP_404_NOT_FOUND, error_msg) workspace_id = form_obj.workspace_id workspace = Workspaces.objects.get_workspace_by_id(workspace_id) if not workspace: error_msg = 'Workspace %s not found.' % workspace_id return api_error(status.HTTP_404_NOT_FOUND, error_msg) repo_id = workspace.repo_id dtable_uuid = form_obj.dtable_uuid dtable = DTables.objects.get_dtable_by_uuid(dtable_uuid) if not dtable: error_msg = 'Table %s not found.' % dtable_uuid return api_error(status.HTTP_404_NOT_FOUND, error_msg) # permission check if not check_form_submit_permission(request, form_obj): error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) if not check_user_workspace_quota(workspace): error_msg = 'Asset quota exceeded.' return api_error(HTTP_443_ABOVE_QUOTA, error_msg) # create asset dir asset_dir_path = '/asset/' + str(dtable.uuid) asset_dir_id = seafile_api.get_dir_id_by_path(repo_id, asset_dir_path) if not asset_dir_id: seafile_api.mkdir_with_parents(repo_id, '/', asset_dir_path[1:], '') # get token obj_id = json.dumps({'parent_dir': asset_dir_path}) try: token = seafile_api.get_fileserver_access_token(repo_id, obj_id, 'upload', '', use_onetime=False) except Exception as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) upload_link = gen_file_upload_url(token, 'upload-api') res = dict() res['upload_link'] = upload_link res['parent_path'] = asset_dir_path res['img_relative_path'] = FORM_UPLOAD_IMG_RELATIVE_PATH res['file_relative_path'] = os.path.join(UPLOAD_FILE_RELATIVE_PATH, str(datetime.today())[:7]) return Response(res)
def get(self, request, workspace_id, name): """get dtable access token """ table_name = name # resource check workspace = Workspaces.objects.get_workspace_by_id(workspace_id) if not workspace: error_msg = 'Workspace %s not found.' % workspace_id return api_error(status.HTTP_404_NOT_FOUND, error_msg) repo_id = workspace.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) dtable = DTables.objects.get_dtable(workspace, table_name) if not dtable: error_msg = 'dtable %s not found.' % table_name return api_error(status.HTTP_404_NOT_FOUND, error_msg) # permission check username = request.user.username permission = check_dtable_permission(username, workspace, dtable) if not permission: error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) # generate json web token payload = { 'exp': int(time.time()) + 86400 * 3, 'dtable_uuid': dtable.uuid.hex, 'username': username, 'permission': permission if check_user_workspace_quota(dtable.workspace) else 'r', } try: access_token = jwt.encode(payload, DTABLE_PRIVATE_KEY, algorithm='HS256') 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({ 'access_token': access_token, 'dtable_uuid': dtable.uuid.hex, 'dtable_server': DTABLE_SERVER_URL, 'dtable_socket': DTABLE_SOCKET_URL, })
def get(self, request): """get dtable share link access token """ # argument check token = request.GET.get('token', None) if not token: error_msg = 'token invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) # resource check dsl = DTableShareLinks.objects.filter(token=token).first() if not dsl: error_msg = 'Share link %s not found.' % token return api_error(status.HTTP_404_NOT_FOUND, error_msg) workspace = Workspaces.objects.get_workspace_by_id( dsl.dtable.workspace_id) if not workspace: error_msg = 'Workspace %s not found.' % dsl.workspace_id return api_error(status.HTTP_404_NOT_FOUND, error_msg) repo = seafile_api.get_repo(workspace.repo_id) if not repo: error_msg = 'Library %s not found.' % workspace.repo_id return api_error(status.HTTP_404_NOT_FOUND, error_msg) dtable = DTables.objects.get_dtable_by_uuid(dsl.dtable.uuid) if not dtable: error_msg = 'DTable %s not found.' % dsl.dtable.uuid return api_error(status.HTTP_404_NOT_FOUND, error_msg) # generate jwt payload = { 'exp': int(time.time()) + 86400 * 3, 'dtable_uuid': dtable.uuid.hex, 'username': dsl.username, 'permission': dsl.permission if check_user_workspace_quota(dtable.workspace) else 'r', } try: access_token = jwt.encode(payload, DTABLE_PRIVATE_KEY, algorithm='HS256') 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({ 'access_token': access_token, 'dtable_uuid': dtable.uuid.hex, })
def dtable_file_view(request, workspace_id, name): """ Permission: 1. owner 2. group member 3. shared user """ # resource check workspace = Workspaces.objects.get_workspace_by_id(workspace_id) if not workspace: return render_error(request, 'Workspace does not exist.') group_id = '' if '@seafile_group' in workspace.owner: group_id = workspace.owner.split('@')[0] group = seaserv.get_group(group_id) if not group: error_msg = 'Group %s not found.' % group_id return render_error(request, error_msg) repo_id = workspace.repo_id repo = seafile_api.get_repo(repo_id) if not repo: return render_error(request, 'Library does not exist.') dtable = DTables.objects.get_dtable(workspace, name) if not dtable: return render_error(request, 'DTable does not exist.') # permission check username = request.user.username permission = check_dtable_permission(username, workspace, dtable) if not permission: return render_permission_error(request, _('Permission denied.')) is_admin = False if group_id: is_admin = is_group_admin_or_owner(group_id, username) else: # open your own dtable is_admin = username == workspace.owner seafile_url = '' repo_api_token = '' try: seafile_connector = SeafileConnectors.objects.get(dtable=dtable) seafile_url = seafile_connector.seafile_url repo_api_token = seafile_connector.repo_api_token except SeafileConnectors.DoesNotExist: pass return_dict = { 'version': SEATABLE_VERSION, 'dtable_baidu_map_key': DTABLE_BAIDU_MAP_KEY, 'dtable_google_map_key': DTABLE_GOOGLE_MAP_KEY, 'seatable_market_url': SEATABLE_MARKET_URL, 'filename': name, 'workspace_id': workspace_id, 'dtable_uuid': dtable.uuid.hex, 'permission': permission if check_user_workspace_quota(workspace) else 'r', 'media_url': MEDIA_URL, 'seafile_url': seafile_url, 'repo_api_token': repo_api_token, 'dtable_server': DTABLE_SERVER_URL, 'dtable_socket': DTABLE_SOCKET_URL, 'dtable_enable_geolocation_column': DTABLE_ENABLE_GEOLOCATION_COLUMN, 'is_admin': is_admin, 'asset_quota_exceeded': dtable.creator == request.user.username and not check_user_workspace_quota(workspace), } return render(request, 'dtable_file_view_react.html', return_dict)
def dtable_form_edit(request, token): """ Permission: 1. owner 2. group member 3. shared user with `rw` permission """ # resource check form_obj = DTableForms.objects.get_form_by_token(token) if not form_obj: return render_error(request, 'Table\'s form does not exist.') workspace_id = form_obj.workspace_id workspace = Workspaces.objects.get_workspace_by_id(workspace_id) if not workspace: return render_error(request, 'Workspace does not exist.') dtable_uuid = form_obj.dtable_uuid dtable = DTables.objects.get_dtable_by_uuid(dtable_uuid) if not dtable: return render_error(request, 'Table does not exist.') # permission check username = request.user.username permission = check_dtable_permission(username, workspace, dtable) if permission != PERMISSION_READ_WRITE: return render_permission_error(request, 'Permission denied.') if not check_user_workspace_quota(workspace): return render_error(request, 'Asset quota exceeded.') # generate json web token payload = { 'exp': int(time.time()) + 60 * 5, 'dtable_uuid': dtable_uuid, 'username': "******", 'permission': permission, } try: access_token = jwt.encode(payload, DTABLE_PRIVATE_KEY, algorithm='HS256') except Exception as e: logger.error(e) return render_error(request, _('Internal Server Error')) url = '%s/api/v1/dtables/%s/metadata/' % (DTABLE_SERVER_URL.strip('/'), dtable_uuid) req = requests.Request( url, headers={"Authorization": "Token %s" % access_token.decode()}) try: dtable_metadata = requests.urlopen(req).read().decode() except Exception as e: logger.error(e) return render_error(request, _('Internal Server Error')) share_type = form_obj.share_type shared_groups = list() if share_type == SHARED_GROUPS: group_ids = DTableFormShare.objects.list_by_form(form_obj) shared_groups = [{ 'id': group_id, 'name': group_id_to_name(group_id) } for group_id in group_ids] return_dict = { 'dtable_metadata': dtable_metadata, 'dtable_name': dtable.name, 'workspace_id': workspace_id, 'form_id': form_obj.form_id, 'form_config': form_obj.form_config, 'dtable_uuid': dtable.uuid.hex, 'dtable_web_service_url': DTABLE_WEB_SERVICE_URL, 'form_token': token, 'share_type': share_type, 'shared_groups': json.dumps(shared_groups), } return render(request, 'dtable_edit_form_view_react.html', return_dict)
def dtable_form_view(request, token): # resource check form_obj = DTableForms.objects.get_form_by_token(token) if not form_obj: return render_error(request, 'Table\'s form does not exist.') workspace_id = form_obj.workspace_id workspace = Workspaces.objects.get_workspace_by_id(workspace_id) if not workspace: return render_error(request, 'Workspace does not exist.') dtable_uuid = form_obj.dtable_uuid dtable = DTables.objects.get_dtable_by_uuid(dtable_uuid) if not dtable: return render_error(request, 'Table does not exist.') # permission check if not check_form_submit_permission(request, form_obj): return render_permission_error(request, _('Permission denied.')) # asset quota check if not check_user_workspace_quota(workspace): return render_error(request, _('Asset quota exceeded.')) # generate json web token payload = { 'exp': int(time.time()) + 60 * 5, 'dtable_uuid': dtable_uuid, 'username': "******", 'permission': PERMISSION_READ, } try: access_token = jwt.encode(payload, DTABLE_PRIVATE_KEY, algorithm='HS256') except Exception as e: logger.error(e) return render_error(request, _('Internal Server Error')) url = '%s/api/v1/dtables/%s/metadata/' % (DTABLE_SERVER_URL.strip('/'), dtable_uuid) req = requests.Request( url, headers={"Authorization": "Token %s" % access_token.decode()}) try: dtable_metadata = requests.urlopen(req).read().decode() except Exception as e: logger.error(e) return render_error(request, _('Internal Server Error')) return_dict = { 'version': SEATABLE_VERSION, 'dtable_metadata': dtable_metadata, 'workspace_id': workspace_id, 'form_id': form_obj.form_id, 'form_config': form_obj.form_config, 'dtable_name': dtable.name, 'dtable_web_service_url': DTABLE_WEB_SERVICE_URL, 'form_token': token, } return render(request, 'dtable_share_form_view_react.html', return_dict)
def get(self, request, workspace_id): """get table file upload link Permission: 1. owner 2. group member 3. shared user with `rw` or `admin` permission """ # argument check table_name = request.GET.get('name', None) if not table_name: error_msg = 'name invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) # resource check workspace = Workspaces.objects.get_workspace_by_id(workspace_id) if not workspace: error_msg = 'Workspace %s not found.' % workspace_id return api_error(status.HTTP_404_NOT_FOUND, error_msg) repo_id = workspace.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) dtable = DTables.objects.get_dtable(workspace, table_name) if not dtable: error_msg = 'dtable %s not found.' % table_name return api_error(status.HTTP_404_NOT_FOUND, error_msg) # permission check username = request.user.username if check_dtable_permission(username, workspace, dtable) not in WRITE_PERMISSION_TUPLE: error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) # quota check if not check_user_workspace_quota(workspace): error_msg = 'Asset quota exceeded.' return api_error(HTTP_443_ABOVE_QUOTA, error_msg) # create asset dir asset_dir_path = os.path.join('/asset', str(dtable.uuid)) asset_dir_id = seafile_api.get_dir_id_by_path(repo_id, asset_dir_path) if not asset_dir_id: seafile_api.mkdir_with_parents(repo_id, '/', asset_dir_path[1:], username) # get token obj_id = json.dumps({'parent_dir': asset_dir_path}) try: token = seafile_api.get_fileserver_access_token(repo_id, obj_id, 'upload', '', use_onetime=False) except Exception as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) upload_link = gen_file_upload_url(token, 'upload-api') dtable.modifier = username dtable.save() res = dict() res['upload_link'] = upload_link res['parent_path'] = asset_dir_path res['img_relative_path'] = os.path.join(UPLOAD_IMG_RELATIVE_PATH, str(datetime.today())[:7]) res['file_relative_path'] = os.path.join(UPLOAD_FILE_RELATIVE_PATH, str(datetime.today())[:7]) return Response(res)
def post(self, request, token): """Submit a form """ # argument check row_data = request.POST.get("row_data", None) if not row_data: error_msg = 'row_data invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) table_id = request.POST.get("table_id", None) if not table_id: error_msg = 'table_id invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) # resource check form_obj = DTableForms.objects.get_form_by_token(token) if not form_obj: error_msg = 'Form %s not found.' % token return api_error(status.HTTP_404_NOT_FOUND, error_msg) workspace_id = form_obj.workspace_id workspace = Workspaces.objects.get_workspace_by_id(workspace_id) if not workspace: error_msg = 'Workspace %s not found.' % workspace_id return api_error(status.HTTP_404_NOT_FOUND, error_msg) dtable_uuid = form_obj.dtable_uuid dtable = DTables.objects.get_dtable_by_uuid(dtable_uuid) if not dtable: error_msg = 'Table %s not found.' % dtable_uuid return api_error(status.HTTP_404_NOT_FOUND, error_msg) # permission check if not check_form_submit_permission(request, form_obj): error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) # quota check if not check_user_workspace_quota(dtable.workspace): error_msg = 'Asset quota exceeded.' return api_error(HTTP_443_ABOVE_QUOTA, error_msg) # generate json web token payload = { 'exp': int(time.time()) + 60 * 5, 'dtable_uuid': dtable_uuid, 'username': "******", 'permission': PERMISSION_READ_WRITE, } try: access_token = jwt.encode(payload, settings.DTABLE_PRIVATE_KEY, algorithm='HS256') except Exception as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) headers = {"Authorization": "Token %s" % access_token.decode()} # get dtable columns from metadata metadata_url = '%s/api/v1/dtables/%s/metadata/' % \ (settings.DTABLE_SERVER_URL.strip('/'), form_obj.dtable_uuid) try: response = requests.get(metadata_url, headers=headers) response = response.json() tables = response.get('metadata')['tables'] table = [table for table in tables if table['_id'] == table_id][0] columns = table['columns'] except Exception as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) # migrate image files from assets/xxx/forms/xxx to assets/xxx/images/xxx row_data_dict = json.loads(row_data) form_column_keys = [ col['key'] for col in json.loads(form_obj.form_config)['columns'] ] image_keys = [ col['key'] for col in columns if col['key'] in form_column_keys and col['type'] == 'image' ] for key in image_keys: image_links = row_data_dict.get(key) if not image_links: continue new_links = [] for link in image_links: error, new_link = self._migrate_image(dtable, link.strip()) if error: return error new_links.append(new_link) row_data_dict[key] = new_links row_data_dict[ '_creator'] = request.user.username if request.user.is_authenticated( ) else 'anonymous' row_data_dict['_ctime'] = datetime.utcnow().replace( tzinfo=timezone.utc).isoformat(timespec='milliseconds') # insert row url = '%s/api/v1/dtables/%s/operations/' % \ (settings.DTABLE_SERVER_URL.strip('/'), form_obj.dtable_uuid) operation = { "op_type": "insert_row", "table_id": table_id, "row_data": row_data_dict, } try: req = requests.post(url, json=operation, headers=headers) except Exception as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) form_config = json.loads(form_obj.form_config) notification_config = form_config.get('notification_config', {}) if notification_config and notification_config.get( 'is_send_notification', False): for user in notification_config.get('notification_selected_users', []): try: submit_form.send(sender=None, dtable_id=dtable.id, table_id=table_id, form_name=form_config.get( 'form_name', ''), submit_user=request.user.username, to_user=user.get('email', '')) except Exception as e: logging.error(e) resp = json.loads(req.text) if req.text else {"success": False} return Response(resp, status=req.status_code)
def get(self, request): """get file upload link by dtable api token Permission: 1. valid token """ # argument check auth = request.META.get('HTTP_AUTHORIZATION', '').split() if not auth or auth[0].lower() != 'token' or len(auth) != 2: return api_error(status.HTTP_403_FORBIDDEN, 'Permission denied.') api_token = auth[1] # resource check try: api_token_obj = DTableAPIToken.objects.get_by_token(api_token) if not api_token_obj: return api_error(status.HTTP_404_NOT_FOUND, 'api token not found.') except Exception as e: logger.error(e) error_msg = 'Internal Server Error.' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) dtable = api_token_obj.dtable table_name = dtable.name workspace_id = dtable.workspace_id error, workspace, dtable = _resource_check(workspace_id, table_name) if error: return error if not check_user_workspace_quota(workspace): return api_error(HTTP_443_ABOVE_QUOTA, 'Asset quota exceeded.') # create asset dir repo_id = workspace.repo_id asset_dir_path = '/asset/' + str(dtable.uuid) asset_dir_id = seafile_api.get_dir_id_by_path(repo_id, asset_dir_path) if not asset_dir_id: try: seafile_api.mkdir_with_parents(repo_id, '/', asset_dir_path[1:], api_token_obj.generated_by) except Exception as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) # get token obj_id = json.dumps({'parent_dir': asset_dir_path}) try: token = seafile_api.get_fileserver_access_token(repo_id, obj_id, 'upload', '', use_onetime=False) except Exception as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) upload_link = gen_file_upload_url(token, 'upload-api') api_token_obj.update_last_access() res = dict() res['upload_link'] = upload_link res['parent_path'] = asset_dir_path return Response(res)
def get(self, request): """thirdpart app used dtable api token to get access token and dtable uuid """ # argument check token_list = request.META.get('HTTP_AUTHORIZATION', '').split() if not token_list or token_list[0].lower() != 'token' or len( token_list) != 2: return api_error(status.HTTP_403_FORBIDDEN, 'Permission denied.') api_token = token_list[1] # main try: api_token_obj = DTableAPIToken.objects.get_by_token(api_token) if api_token_obj is None: return api_error(status.HTTP_404_NOT_FOUND, 'api token not found.') api_token_obj.update_last_access() except Exception as e: logger.error(e) error_msg = 'Internal Server Error.' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) # resource check dtable = api_token_obj.dtable table_name = dtable.name workspace_id = dtable.workspace_id error, workspace, dtable = _resource_check(workspace_id, table_name) if error: return error # generate json web token payload = { 'exp': int(time.time()) + 86400 * 3, 'dtable_uuid': dtable.uuid.hex, 'username': '', 'permission': api_token_obj.permission if check_user_workspace_quota(dtable.workspace) else 'r', 'app_name': api_token_obj.app_name, } try: access_token = jwt.encode(payload, DTABLE_PRIVATE_KEY, algorithm='HS256') 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({ 'app_name': api_token_obj.app_name, 'access_token': access_token, 'dtable_uuid': dtable.uuid.hex, 'dtable_server': DTABLE_SERVER_URL, 'dtable_socket': DTABLE_SOCKET_URL, })