def delete(self, request, workspace_id, name, group_id): # resource check workspace, dtable, error = self._resource_check( workspace_id, name, group_id) if error: return error user = request.user # permission check # check user' permission to dtable/workspace if not permitted then check group permission if not check_dtable_admin_permission( user.username, workspace.owner): # if not the workspace/group admin if not check_dtable_admin_permission( user.username, group_id + '@seafile_group' ): # if not the admin of the group which dtable was shared to error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) try: DTableGroupShare.objects.filter(dtable=dtable, group_id=group_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})
def put(self, request, workspace_id, name, group_id): # argument check permission = request.data.get('permission') if not permission or permission not in (PERMISSION_READ, PERMISSION_READ_WRITE): error_msg = 'permission is invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) # resource check workspace, dtable, error = self._resource_check( workspace_id, name, group_id) if error: return error user = request.user # permission check if not check_dtable_admin_permission(user.username, workspace.owner): error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) try: updates = {'permission': permission} DTableGroupShare.objects.filter( dtable=dtable, group_id=group_id).update(**updates) 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 _permission_check_for_api_token(username, owner): # only owner or group admin if not check_dtable_admin_permission(username, owner): error_msg = _('Permission denied.') return api_error(status.HTTP_403_FORBIDDEN, error_msg) return None
def post(self, request): # role permission check if not request.user.permissions.can_generate_share_link(): error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) # argument check workspace_id = request.data.get('workspace_id') if not workspace_id: error_msg = 'workspace_id invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) table_name = request.data.get('table_name') if not table_name: error_msg = 'table_name invalid' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) link_permission = request.data.get('permission') if link_permission and link_permission not in [ perm[0] for perm in DTableShareLinks.PERMISSION_CHOICES ]: error_msg = _('Permission invalid') return api_error(status.HTTP_400_BAD_REQUEST, error_msg) link_permission = link_permission if link_permission else PERMISSION_READ # resource check workspace = Workspaces.objects.get_workspace_by_id(workspace_id) if not workspace: error_msg = _('Workspace %(workspace)s not found' % {'workspace': 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 %(repo)s not found' % {'repo': workspace.repo_id}) return api_error(status.HTTP_404_NOT_FOUND, error_msg) dtable = DTables.objects.get_dtable(workspace_id, table_name) if not dtable: error_msg = _('DTable %(table)s not found' % {'table': table_name}) return api_error(status.HTTP_404_NOT_FOUND, error_msg) # permission check if not check_dtable_admin_permission(request.user.username, dtable.workspace.owner): error_msg = _('Permission denied.') return api_error(status.HTTP_403_FORBIDDEN, error_msg) username = request.user.username try: sdl = DTableShareLinks.objects.create_link( dtable.id, username, permission=link_permission) except Exception as e: logger.error(e) error_msg = _('Internal Server Error') return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) data = get_share_dtable_link_info(sdl, dtable) return Response(data)
def post(self, request): # arguments check link = request.data.get('link') if not link: error_msg = 'link is invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) dst_workspace_id = request.data.get('dst_workspace_id') if not dst_workspace_id: error_msg = 'dst_workspace_id is invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) # check link token, error = self._check_link(link) if error: return error # resource check dtable_external_link = DTableExternalLinks.objects.filter( token=token).select_related('dtable', 'dtable__workspace').first() if not dtable_external_link: error_msg = 'link %s not found.' % (link, ) return api_error(status.HTTP_404_NOT_FOUND, error_msg) if dtable_external_link.dtable.deleted: error_msg = 'link %s not found.' % (link, ) return api_error(status.HTTP_404_NOT_FOUND, error_msg) username = request.user.username # self workspace check dst_workspace = Workspaces.objects.filter(id=dst_workspace_id).first() if not dst_workspace: error_msg = 'workspace %s not found.' % (dst_workspace_id, ) return api_error(status.HTTP_404_NOT_FOUND, error_msg) if not check_dtable_admin_permission(username, dst_workspace.owner): error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) if DTables.objects.filter( workspace=dst_workspace, name=dtable_external_link.dtable.name).exists(): error_msg = 'Table %s already exists in this workspace.' % ( dtable_external_link.dtable.name, ) return api_error(status.HTTP_400_BAD_REQUEST, error_msg) # copy dst_dtable, error = copy_dtable(dtable_external_link.dtable.workspace, dtable_external_link.dtable, dst_workspace, dtable_external_link.dtable.name, username) if error: return error return Response({'dtable': dst_dtable.to_dict()})
def post(self, request): # argument check try: src_workspace_id = int(request.data.get('src_workspace_id')) dst_workspace_id = int(request.data.get('dst_workspace_id')) except: error_msg = 'src_workspace_id or dst_workspace_id is invalid' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) name = request.data.get('name') if not name: error_msg = 'name is invalid' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) # resource check src_workspace = Workspaces.objects.get_workspace_by_id( src_workspace_id) if not src_workspace: error_msg = 'workspace: %s not found' % src_workspace_id return api_error(status.HTTP_404_NOT_FOUND, error_msg) src_dtable = DTables.objects.get_dtable(src_workspace, name) if not src_dtable: error_msg = 'dtable: %s not found' % name return api_error(status.HTTP_404_NOT_FOUND, error_msg) dst_workspace = Workspaces.objects.get_workspace_by_id( dst_workspace_id) if not dst_workspace_id: error_msg = 'workspace: %s not found' % dst_workspace_id return api_error(status.HTTP_404_NOT_FOUND, error_msg) # permission check # must be dist workspace's owner or admin username = request.user.username if not check_dtable_permission(username, src_workspace, src_dtable) or \ not check_dtable_admin_permission(username, dst_workspace.owner): error_msg = 'Permission denied' return api_error(status.HTTP_403_FORBIDDEN, error_msg) # dtable-name check if DTables.objects.get_dtable(dst_workspace, name): error_msg = 'Table %s already exists in this workspace.' % (name) return api_error(status.HTTP_400_BAD_REQUEST, error_msg) # create dtable dst_dtable, error = copy_dtable(src_workspace, src_dtable, dst_workspace, name, username) if error: return error return Response({'dtable': dst_dtable.to_dict()})
def delete(self, request, token): dsl = DTableShareLinks.objects.filter(token=token).first() if not dsl: return Response({'success': True}) username = request.user.username if not check_dtable_admin_permission(username, dsl.dtable.workspace.owner): error_msg = _('Permission denied.') return api_error(status.HTTP_400_BAD_REQUEST, error_msg) try: dsl.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})
def get(self, request, workspace_id, 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) dtable = DTables.objects.get_dtable(workspace, name) if not dtable: error_msg = 'Table %s not found.' % (name, ) return api_error(status.HTTP_404_NOT_FOUND, error_msg) # permission check user = request.user if not check_dtable_admin_permission(user.username, workspace.owner): error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) dgses = DTableGroupShare.objects.filter( dtable=dtable).order_by('created_at') dtable_group_shares = [ _get_dtable_group_share_info(dgs) for dgs in dgses ] return Response({'dtable_group_share_list': dtable_group_shares})
def delete(self, request, workspace_id): """delete a table Permission: 1. owner 2. group admin """ # argument check table_name = request.data.get('name') if not table_name: error_msg = 'name invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) table_file_name = table_name + FILE_TYPE # 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 not check_dtable_admin_permission(username, workspace.owner): error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) # repo status check repo_status = repo.status if repo_status != 0: error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) # rename .dtable file new_dtable_name, old_dtable_file_name, new_dtable_file_name = convert_dtable_trash_names( dtable) table_path = normalize_file_path(table_file_name) table_file_id = seafile_api.get_file_id_by_path(repo_id, table_path) # if has .dtable file, then rename, else skip if table_file_id: seafile_api.rename_file(repo_id, '/', old_dtable_file_name, new_dtable_file_name, username) try: DTables.objects.filter(id=dtable.id).update( deleted=True, delete_time=datetime.utcnow(), name=new_dtable_name) except Exception as e: logger.error('delete dtable: %s error: %s', dtable.id, e) return Response({'success': True}, status=status.HTTP_200_OK)
def put(self, request, workspace_id): """rename a table Permission: 1. owner 2. group adminn """ # argument check old_table_name = request.data.get('old_name') if not old_table_name: error_msg = 'old_name invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) new_table_name = request.data.get('new_name') if not new_table_name: error_msg = 'new_name invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) new_table_file_name = new_table_name + FILE_TYPE if not is_valid_dirent_name(new_table_file_name): error_msg = 'new_name invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) if len(new_table_file_name) > MAX_UPLOAD_FILE_NAME_LEN: error_msg = 'new_name is too long.' 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, old_table_name) if not dtable: error_msg = 'dtable %s not found.' % old_table_name return api_error(status.HTTP_404_NOT_FOUND, error_msg) old_table_file_name = old_table_name + FILE_TYPE old_table_path = normalize_file_path(old_table_file_name) table_file_id = seafile_api.get_file_id_by_path( repo_id, old_table_path) if not table_file_id: error_msg = 'file %s not found.' % old_table_file_name return api_error(status.HTTP_404_NOT_FOUND, error_msg) # permission check username = request.user.username if not check_dtable_admin_permission(username, workspace.owner): error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) # repo status check repo_status = repo.status if repo_status != 0: error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) # rename table new_table_file_name = check_filename_with_rename( repo_id, '/', new_table_file_name) try: seafile_api.rename_file(repo_id, '/', old_table_file_name, new_table_file_name, username) except SearpcError as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) try: dtable.name = new_table_name dtable.modifier = username dtable.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({"table": dtable.to_dict()}, status=status.HTTP_200_OK)
def post(self, request): """create a table file Permission: 1. owner 2. group admin """ # role permission check if not request.user.permissions.can_add_dtable(): error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) # argument check table_owner = request.POST.get('owner') if not table_owner: error_msg = 'owner invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) table_name = request.POST.get('name') if not table_name: error_msg = 'name invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) table_file_name = table_name + FILE_TYPE if not is_valid_dirent_name(table_file_name): error_msg = 'name invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) # resource check workspace = Workspaces.objects.get_workspace_by_owner(table_owner) if not workspace: org_id = -1 if is_org_context(request): org_id = request.user.org.org_id try: workspace = create_repo_and_workspace(table_owner, org_id) except Exception as e: logger.error(e) error_msg = 'Internal Server Error.' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) existed_dtables = DTables.objects.filter(workspace=workspace, name=table_name) if len(existed_dtables) > 0: error_msg = _( 'Table %s already exists in this workspace.') % table_name return api_error(status.HTTP_400_BAD_REQUEST, 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) # permission check username = request.user.username if not check_dtable_admin_permission(username, workspace.owner): error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) # repo status check repo_status = repo.status if repo_status != 0: error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) # create new empty table table_file_name = check_filename_with_rename(repo_id, '/', table_file_name) try: seafile_api.post_empty_file(repo_id, '/', table_file_name, username) except SearpcError as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) try: dtable = DTables.objects.create_dtable(username, workspace, 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) return Response({"table": dtable.to_dict()}, status=status.HTTP_201_CREATED)
def delete(self, request, workspace_id, name, plugin_id): """ delete a plugin file 1. check params, perms and resources 2. delete asset file 3. delete record in database permission: dtable admin """ # 1. check params, perms and resources try: plugin_record = DTablePlugins.objects.get(pk=plugin_id) except DTablePlugins.DoesNotExist: error_msg = 'Plugin %s not found.' % plugin_id return api_error(status.HTTP_404_NOT_FOUND, error_msg) 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) if '@seafile_group' in workspace.owner: group_id = workspace.owner.split('@')[0] group = ccnet_api.get_group(int(group_id)) if not group: error_msg = 'Group %s not found.' % group_id return api_error(status.HTTP_404_NOT_FOUND, error_msg) table_name = name 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_admin_permission(username, workspace.owner) if not permission: error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, 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) plugin_file_path = '/asset/' + str(dtable.uuid) + '/plugins/' + plugin_record.name plugin_file_dir_id = seafile_api.get_dir_id_by_path(repo_id, plugin_file_path) if not plugin_file_dir_id: error_msg = 'Plugin %s not found.' % plugin_id return api_error(status.HTTP_404_NOT_FOUND, error_msg) try: delete_plugin_asset_folder(repo_id, username, plugin_file_path) except Exception as e: logger.error(e) return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, 'Internal Server Error') plugin_record.delete() return Response({'success': True})
def put(self, request, workspace_id, name, plugin_id): """ update a plugin 1. check params, perms and resources 2. read new plugin file, read its info.json 3. delete old asset file, replace with new asset file 4. update database record permission: dtable admin """ request.upload_handlers = [TemporaryFileUploadHandler(request=request)] # 1. check params, perms and resources try: plugin_record = DTablePlugins.objects.get(pk=plugin_id) except DTablePlugins.DoesNotExist: error_msg = 'Plugin %s not found.' % plugin_id return api_error(status.HTTP_404_NOT_FOUND, error_msg) 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) if '@seafile_group' in workspace.owner: group_id = workspace.owner.split('@')[0] group = ccnet_api.get_group(int(group_id)) if not group: error_msg = 'Group %s not found.' % group_id return api_error(status.HTTP_404_NOT_FOUND, error_msg) table_name = name 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_admin_permission(username, workspace.owner) if not permission: error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, 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) plugin_file_path = '/asset/' + str(dtable.uuid) + '/plugins/' + plugin_record.name plugin_file_dir_id = seafile_api.get_dir_id_by_path(repo_id, plugin_file_path) if not plugin_file_dir_id: error_msg = 'Plugin %s not found.' % plugin_id return api_error(status.HTTP_404_NOT_FOUND, error_msg) plugin_file = request.FILES.get('plugin', None) if not plugin_file: error_msg = 'plugin invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) if plugin_file.size >> 20 > 300: error_msg = _('File is too large.') return api_error(status.HTTP_400_BAD_REQUEST, error_msg) uploaded_temp_path = plugin_file.temporary_file_path() if not is_zipfile(uploaded_temp_path): error_msg = _('A zip file is required.') return api_error(status.HTTP_400_BAD_REQUEST, error_msg) # read from zip with ZipFile(uploaded_temp_path, 'r') as zip_file: folder_path = get_folder_path(zip_file.namelist()) try: info_json_str = zip_file.read(os.path.join(folder_path, INFO_FILE_NAME)) info = json.loads(info_json_str) except Exception: error_msg = _('"info.json" not found.') return api_error(status.HTTP_400_BAD_REQUEST, error_msg) try: zip_file.read(os.path.join(folder_path, MAINJS_FILE_NAME)) except Exception: error_msg = _('"main.js" not found.') return api_error(status.HTTP_400_BAD_REQUEST, error_msg) new_plugin_name = info.get('name', '') zip_file.extractall(TMP_EXTRACTED_PATH) plugin_path = '/asset/' + str(dtable.uuid) + '/plugins/' # if new_plugin_name == old plugin name, no need to check name if new_plugin_name != plugin_record.name: if DTablePlugins.objects.filter(name=new_plugin_name, dtable=dtable).count() > 0: error_msg = _('Plugin with name %s is already in dtable %s.') % (new_plugin_name, dtable.name) return api_error(status.HTTP_400_BAD_REQUEST, error_msg) # check if duplicate plugin name within a dtable asset if seafile_api.get_dir_id_by_path(repo_id, os.path.join(plugin_path, new_plugin_name)): error_msg = _('Plugin with name %s is already in dtable %s.') % (new_plugin_name, dtable.name) return api_error(status.HTTP_400_BAD_REQUEST, error_msg) # delete old asset file try: delete_plugin_asset_folder(repo_id, username, plugin_file_path) except Exception as e: logger.error(e) return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, 'Internal Server Error') # create file in asset dir, and delete TMP_EXTRACTED_PATH try: create_plugin_asset_files(repo_id, username, new_plugin_name, plugin_path, folder_path) except Exception as e: logger.error(e) return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, 'Internal Server Error') shutil.rmtree(TMP_EXTRACTED_PATH) # 4. update record in database plugin_record.name = new_plugin_name plugin_record.info = info_json_str plugin_record.save() return Response(plugin_record.to_dict())
def post(self, request, workspace_id, name): """ upload a plugin *.zip file 1. check params, perms and resources 2. read info from zip file, and extract zip in TMP_EXTRACTED_PATH 3. create file in asset dir, and delete TMP_EXTRACTED_PATH 4. record in database There are two tmp files in this api. First is django upload tmp file, it will be removed automatically. Second is extracted folder 'TMP_EXTRACTED_PATH', we removed it manually. permission: workspace owner or admin """ # use TemporaryFileUploadHandler, which contains TemporaryUploadedFile # TemporaryUploadedFile has temporary_file_path() method # in order to change upload_handlers, we must exempt csrf check request.upload_handlers = [TemporaryFileUploadHandler(request=request)] table_name = name from_market = request.data.get('from_market', 'false').lower() 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) if '@seafile_group' in workspace.owner: group_id = workspace.owner.split('@')[0] group = ccnet_api.get_group(int(group_id)) if not group: error_msg = 'Group %s not found.' % group_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_admin_permission(username, workspace.owner) if not permission: error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, 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) if from_market not in ['true', 'false']: # from_market invalid error_msg = 'from_market invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) if from_market == 'true': """ if we add plugin from market 1. get plugin_download_url from market by plugin_name 2. download plugin zip by plugin_download_url 3. extract zip in TMP_EXTRACTED_PATH 4. create file in asset dir, and delete TMP_EXTRACTED_PATH 5. record in database """ plugin_name = request.data.get('plugin_name', '') if not plugin_name: error_msg = 'plugin_name invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) if DTablePlugins.objects.filter(name=plugin_name, dtable=dtable).count() > 0: error_msg = _('Plugin with name %s is already in dtable %s.') % (plugin_name, dtable.name) return api_error(status.HTTP_400_BAD_REQUEST, error_msg) # get plugin_download_url from market by plugin_name # download plugin zip by plugin_download_url seamarket_plugin_api_url = SEATABLE_MARKET_URL.rstrip('/') + '/api/plugins/' + plugin_name + '/' res = requests.get(seamarket_plugin_api_url) download_url = json.loads(res.content).get('download_url', '') if not download_url: error_msg = 'plugin %s not found.' % plugin_name return api_error(status.HTTP_404_NOT_FOUND, error_msg) plugin_zip_file_response = requests.get(download_url) os.mkdir('/tmp/plugin_download_from_market') tmp_zip_path = '/tmp/plugin_download_from_market/plugin_zip' with open(tmp_zip_path, 'wb') as f: f.write(plugin_zip_file_response.content) # extract zip in TMP_EXTRACTED_PATH with ZipFile(tmp_zip_path, 'r') as zip_file: folder_path = get_folder_path(zip_file.namelist()) try: info_json_str = zip_file.read(os.path.join(folder_path, INFO_FILE_NAME)) except Exception: error_msg = _('"info.json" not found.') return api_error(status.HTTP_400_BAD_REQUEST, error_msg) zip_file.extractall(TMP_EXTRACTED_PATH) shutil.rmtree('/tmp/plugin_download_from_market') # create file in asset dir, and delete TMP_EXTRACTED_PATH # if no plugins path, create it plugin_path = '/asset/' + str(dtable.uuid) + '/plugins/' plugin_path_id = seafile_api.get_dir_id_by_path(repo_id, plugin_path) if not plugin_path_id: try: seafile_api.mkdir_with_parents(repo_id, '/', plugin_path[1:], username) except Exception as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) # if asset dir has plugin with same name, we replace old with new if seafile_api.get_dir_id_by_path(repo_id, os.path.join(plugin_path, plugin_name)): delete_plugin_asset_folder(repo_id, username, os.path.join(plugin_path, plugin_name)) # create path and file try: create_plugin_asset_files(repo_id, username, plugin_name, plugin_path, folder_path) except Exception as e: logger.error(e) return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, 'Internal Server Error') # remove extracted tmp file shutil.rmtree(TMP_EXTRACTED_PATH) # 4. record in database plugin_record = DTablePlugins.objects.create( dtable=dtable, added_by=username, added_time=datetime.now(), name=plugin_name, info=info_json_str ) return Response(plugin_record.to_dict()) # 1. check params plugin_file = request.FILES.get('plugin', None) if not plugin_file: error_msg = 'plugin invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) if plugin_file.size >> 20 > 300: error_msg = _('File is too large.') return api_error(status.HTTP_400_BAD_REQUEST, error_msg) # 2. read info from zip file, and extract zip in TMP_EXTRACTED_PATH uploaded_temp_path = plugin_file.temporary_file_path() if not is_zipfile(uploaded_temp_path): error_msg = _('A zip file is required.') return api_error(status.HTTP_400_BAD_REQUEST, error_msg) with ZipFile(uploaded_temp_path, 'r') as zip_file: folder_path = get_folder_path(zip_file.namelist()) try: info_json_str = zip_file.read(os.path.join(folder_path, INFO_FILE_NAME)) info = json.loads(info_json_str) except Exception: error_msg = _('"info.json" not found.') return api_error(status.HTTP_400_BAD_REQUEST, error_msg) try: zip_file.read(os.path.join(folder_path, MAINJS_FILE_NAME)) except Exception: error_msg = _('"main.js" not found.') return api_error(status.HTTP_400_BAD_REQUEST, error_msg) plugin_name = info.get('name', '') zip_file.extractall(TMP_EXTRACTED_PATH) if DTablePlugins.objects.filter(name=plugin_name, dtable=dtable).count() > 0: error_msg = _('Plugin with name %s is already in dtable %s.') % (plugin_name, dtable.name) return api_error(status.HTTP_400_BAD_REQUEST, error_msg) # 3. create file in asset dir, and delete TMP_EXTRACTED_PATH # if no plugins path, create it plugin_path = '/asset/' + str(dtable.uuid) + '/plugins/' plugin_path_id = seafile_api.get_dir_id_by_path(repo_id, plugin_path) if not plugin_path_id: try: seafile_api.mkdir_with_parents(repo_id, '/', plugin_path[1:], username) except Exception as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) # if asset dir has plugin with same name, we replace old with new if seafile_api.get_dir_id_by_path(repo_id, os.path.join(plugin_path, plugin_name)): delete_plugin_asset_folder(repo_id, username, os.path.join(plugin_path, plugin_name)) # create path and file try: create_plugin_asset_files(repo_id, username, plugin_name, plugin_path, folder_path) except Exception as e: logger.error(e) return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, 'Internal Server Error') # remove extracted tmp file shutil.rmtree(TMP_EXTRACTED_PATH) # 4. record in database plugin_record = DTablePlugins.objects.create( dtable=dtable, added_by=username, added_time=datetime.now(), name=plugin_name, info=info_json_str ) return Response(plugin_record.to_dict())
def post(self, request, workspace_id, name): # arguments check permission = request.data.get('permission') if not permission or permission not in (PERMISSION_READ, PERMISSION_READ_WRITE): error_msg = 'permission is invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) group_id = request.data.get('group_id') if not group_id: error_msg = 'group_id is invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) user = request.user # org check if is_org_context(request): org_id = request.user.org.org_id org_name = request.user.org.org_name if ccnet_api.get_org_id_by_group(int(group_id)) != org_id: error_msg = 'Group %s is not an organization %s group.' % ( group_id, org_name) return api_error(status.HTTP_400_BAD_REQUEST, error_msg) # resource check if not Workspaces.objects.get_workspace_by_owner('%s@seafile_group' % (group_id, )): error_msg = 'Group %s workspace not found.' % (group_id, ) return api_error(status.HTTP_404_NOT_FOUND, error_msg) 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 = DTables.objects.get_dtable(workspace, name) if not dtable: error_msg = 'Table %s not found.' % (name, ) return api_error(status.HTTP_404_NOT_FOUND, error_msg) if '@seafile_group' in workspace.owner and group_id == workspace.owner.split( '@')[0]: error_msg = 'Disable to share table to the group which table belongs to.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) # permission check if not check_dtable_admin_permission(user.username, workspace.owner): error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) try: if DTableGroupShare.objects.filter(dtable=dtable, group_id=group_id).exists(): error_msg = 'table %s already shared to the group.' % ( dtable.name, ) return api_error(status.HTTP_400_BAD_REQUEST, error_msg) dgs = DTableGroupShare.objects.create(dtable=dtable, group_id=group_id, permission=permission, created_by=user.username) 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( {'dtable_group_share': _get_dtable_group_share_info(dgs)})
def _permission_check(user, owner): if not user.permissions.can_generate_external_link(): return None return check_dtable_admin_permission(user.username, owner)
def post(self, request): """ Create a Common Dataset :param dataset_name: name of dataset :param dtable_name: name of dtable :param table_name: name of subtable :param view_name: name of view 1. check params, resources and permissions 2. get dtable data from dtable_esrver 3. store data in database """ if not request.user.permissions.can_create_common_dataset(): error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) # params check dataset_name = request.data.get('dataset_name', '') if not dataset_name: error_msg = 'dataset_name invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) dtable_name = request.data.get('dtable_name', '') if not dtable_name: error_msg = 'dtable_name invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) table_name = request.data.get('table_name', '') if not table_name: error_msg = 'table_name invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) view_name = request.data.get('view_name', '') if not view_name: error_msg = 'view_name invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) # resource check org_id = -1 if is_org_context(request): org_id = request.user.org.org_id # check duplicate by name set_with_duplicate_name = DTableCommonDataset.objects.filter( org_id=org_id, dataset_name=dataset_name) if len(set_with_duplicate_name) >= 1: error_msg = _( 'Common Dataset with name: %s already exists.') % dataset_name return api_error(status.HTTP_400_BAD_REQUEST, error_msg) dtable = DTables.objects.filter(name=dtable_name).first() if not dtable: error_msg = 'DTable %s not found.' % dtable_name return api_error(status.HTTP_404_NOT_FOUND, error_msg) if not dtable.is_owned_by_group: error_msg = _( 'Common Dataset could only be created from group owned dtables.' ) return api_error(status.HTTP_400_BAD_REQUEST, error_msg) workspace = Workspaces.objects.get_workspace_by_id(dtable.workspace_id) if not workspace: error_msg = 'Workspace %s not found.' % dtable.workspace_id return api_error(status.HTTP_404_NOT_FOUND, error_msg) # permission check if not check_dtable_admin_permission(request.user.username, workspace.owner): error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) access_permission = check_dtable_permission(request.user.username, workspace, dtable) if not access_permission: error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) # generate json web token # internal usage exp 60 seconds, username = dtable-web payload = { 'exp': int(time.time()) + 60, 'dtable_uuid': dtable.uuid.hex, 'username': '******', 'permission': access_permission, } 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) url = DTABLE_SERVER_URL + 'dtables/' + dtable.uuid.hex headers = {'Authorization': 'Token ' + access_token.decode('utf-8')} query_param = { 'lang': 'en', } try: res = requests.get(url, headers=headers, params=query_param) except requests.HTTPError as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) res = json.loads(res.content) tables = res.get('tables', []) target_table = next( filter(lambda table: table.get('name') == table_name, tables), None) if not target_table: error_msg = 'table %s not found.' % table_name return api_error(status.HTTP_404_NOT_FOUND, error_msg) target_view = next( filter(lambda view: view.get('name') == view_name, target_table['views']), None) if not target_view: error_msg = 'view %s not found.' % view_name return api_error(status.HTTP_404_NOT_FOUND, error_msg) # check duplicate by dtable uuid, table id, view id set_duplicates = DTableCommonDataset.objects.filter( org_id=org_id, dtable_uuid=dtable.uuid, table_id=target_table['_id'], view_id=target_view['_id']) if len(set_duplicates) >= 1: error_msg = _( 'Common Dataset with dtable name: %s, table name: %s, view name: %s already exists.' ) % (dtable_name, table_name, view_name) return api_error(status.HTTP_400_BAD_REQUEST, error_msg) common_dataset = DTableCommonDataset.objects.create( org_id=org_id, dtable_uuid=dtable.uuid, table_id=target_table['_id'], view_id=target_view['_id'], creator=request.user.username, created_at=timezone.now(), dataset_name=dataset_name, ) return Response(common_dataset.to_dict())