def _decorated(view, request, org_id, email): # argument check org_id = int(org_id) if org_id == 0: error_msg = 'org_id invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) try: org = ccnet_api.get_org_by_id(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) # resource check if not org: error_msg = 'Organization %d not found.' % org_id return api_error(status.HTTP_404_NOT_FOUND, error_msg) try: User.objects.get(email=email) except User.DoesNotExist: error_msg = 'User %s not found.' % email return api_error(status.HTTP_404_NOT_FOUND, error_msg) if not is_org_user(email, org_id): error_msg = 'User %s is not member of organization %s.' \ % (email, org.org_name) return api_error(status.HTTP_400_BAD_REQUEST, error_msg) return func(view, request, org_id, email)
def delete(self, request, token): """ Delete upload link. Permission checking: 1. default(NOT guest) user; 2. link owner; """ if not self._can_generate_shared_link(request): error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) try: uls = UploadLinkShare.objects.get(token=token) except UploadLinkShare.DoesNotExist: return Response({'success': True}) username = request.user.username if not uls.is_owner(username): error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) try: uls.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 delete(self, request, format=None): platform = request.data.get('platform', '') device_id = request.data.get('device_id', '') user = request.data.get('user', '') if not platform: error_msg = 'platform invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) if not device_id: error_msg = 'device_id invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) if not user or not is_registered_user(user): error_msg = 'user invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) try: do_unlink_device(user, platform, device_id) except SearpcError 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, org_id): """ Get all users in an org. Permission checking: 1. only admin can perform this action. """ # argument check org_id = int(org_id) if org_id == 0: error_msg = 'org_id invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) org = ccnet_api.get_org_by_id(org_id) if not org: error_msg = 'Organization %d not found.' % org_id return api_error(status.HTTP_404_NOT_FOUND, error_msg) result = [] org_users = ccnet_api.get_org_emailusers(org.url_prefix, -1, -1) for org_user in org_users: user_info = get_org_user_info(org_id, org_user.email) user_info['active'] = org_user.is_active result.append(user_info) return Response({'users': result})
def post(self, request): """ Create a group """ if not self._can_add_group(request): error_msg = _(u'You do not have permission to create group.') return api_error(status.HTTP_403_FORBIDDEN, error_msg) username = request.user.username group_name = request.data.get('name', '') group_name = group_name.strip() # Check whether group name is validate. if not validate_group_name(group_name): error_msg = _(u'Group name can only contain letters, numbers, blank, hyphen or underscore') return api_error(status.HTTP_400_BAD_REQUEST, error_msg) # Check whether group name is duplicated. if check_group_name_conflict(request, group_name): error_msg = _(u'There is already a group with that name.') return api_error(status.HTTP_400_BAD_REQUEST, error_msg) # create group. try: group_id = seaserv.ccnet_threaded_rpc.create_group(group_name, username) except SearpcError as e: logger.error(e) error_msg = _(u'Failed') return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) # get info of new group group_info = get_group_info(request, group_id, GROUP_AVATAR_DEFAULT_SIZE) return Response(group_info, status=status.HTTP_201_CREATED)
def get(self, request): if not is_pro_version(): error_msg = 'Feature disabled.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) # check the date format, should be like '2015-10-10' start = request.GET.get('start', None) end = request.GET.get('end', None) if not check_time_period_valid(start, end): error_msg = 'start or end date invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) result = [] events = get_log_events_by_type_and_time('file_audit', start, end) if events: for ev in events: tmp_repo = seafile_api.get_repo(ev.repo_id) tmp_repo_name = tmp_repo.name if tmp_repo else '' result.append({ 'repo_id': ev.repo_id, 'repo_name': tmp_repo_name, 'time': datetime_to_isoformat_timestr(ev.timestamp), 'etype': ev.etype, 'ip': ev.ip, 'file_path': ev.file_path, 'etype': ev.etype, 'user_name': email2nickname(ev.user), 'user_email': ev.user }) return Response(result)
def _decorated(view, request, group_id, *args, **kwargs): group_id = int(group_id) # Checked by URL Conf try: group = seaserv.get_group(group_id) except SearpcError as e: logger.error(e) error_msg = _(u'Internal Server Error') return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) if not group: error_msg = _(u'Group does not exist.') return api_error(status.HTTP_400_BAD_REQUEST, error_msg) username = request.user.username try: is_group_member = seaserv.is_group_user(group_id, username) except SearpcError as e: logger.error(e) error_msg = _(u'Internal Server Error') return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) if not is_group_member: error_msg = _(u'Permission denied') return api_error(status.HTTP_403_FORBIDDEN, error_msg) return func(view, request, group_id, *args, **kwargs)
def get(self, request, org_id, email): """ get base info of a org user Permission checking: 1. only admin can perform this action. """ # argument check org_id = int(org_id) if org_id == 0: error_msg = 'org_id invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) org = ccnet_api.get_org_by_id(org_id) if not org: error_msg = 'Organization %d not found.' % org_id return api_error(status.HTTP_404_NOT_FOUND, error_msg) try: user_obj = User.objects.get(email=email) except User.DoesNotExist: error_msg = 'User %s not found.' % email return api_error(status.HTTP_404_NOT_FOUND, error_msg) user_info = get_org_user_info(org_id, email) user_info['active'] = user_obj.is_active return Response(user_info)
def _decorated(view, request, *args, **kwargs): if not is_pro_version() or not EVENTS_ENABLED: return api_error(status.HTTP_404_NOT_FOUND, 'Events not enabled.') start_time = request.GET.get("start", "") end_time = request.GET.get("end", "") if not start_time: error_msg = "Start time can not be empty" return api_error(status.HTTP_400_BAD_REQUEST, error_msg) if not end_time: error_msg = "End time can not be empty" return api_error(status.HTTP_400_BAD_REQUEST, error_msg) try: start_time = datetime.datetime.strptime(start_time, "%Y-%m-%d %H:%M:%S") except: error_msg = "Start time %s invalid" % start_time return api_error(status.HTTP_400_BAD_REQUEST, error_msg) try: end_time = datetime.datetime.strptime(end_time, "%Y-%m-%d %H:%M:%S") except: error_msg = "End time %s invalid" % end_time return api_error(status.HTTP_400_BAD_REQUEST, error_msg) return func(view, request, start_time, end_time, *args, **kwargs)
def delete(self, request, slug, page_name): """Delete a page in a wiki """ try: wiki = Wiki.objects.get(slug=slug) except Wiki.DoesNotExist: error_msg = "Wiki not found." return api_error(status.HTTP_404_NOT_FOUND, error_msg) username = request.user.username if wiki.username != username: error_msg = _('Permission denied.') return api_error(status.HTTP_403_FORBIDDEN, error_msg) try: repo = seafile_api.get_repo(wiki.repo_id) if not repo: error_msg = "Wiki library not found." return api_error(status.HTTP_404_NOT_FOUND, error_msg) except SearpcError: error_msg = _("Internal Server Error") return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) file_name = page_name + ".md" try: seafile_api.del_file(repo.id, '/', file_name, request.user.username) except SearpcError as e: logger.error(e) error_msg = _('Internal Server Error') return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) return Response()
def get(self, request, repo_id): """ List repo user share info. Permission checking: 1. is group admin """ # 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) repo_owner = get_repo_owner(request, repo_id) group_id = get_group_id_by_repo_owner(repo_owner) if not ccnet_api.get_group(group_id): error_msg = 'Group %s not found.' % group_id return api_error(status.HTTP_404_NOT_FOUND, error_msg) path = request.GET.get('path', '/') if not seafile_api.get_dir_id_by_path(repo_id, path): error_msg = 'Folder %s not found.' % path return api_error(status.HTTP_404_NOT_FOUND, error_msg) # permission check username = request.user.username if not is_group_admin(group_id, username): error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) result = self.list_user_shared_items(request, repo_id, path) return Response(result)
def delete(self, request, token): """ delete share link. """ if not self._can_generate_shared_link(request): error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) try: fs = FileShare.objects.get(token=token) except FileShare.DoesNotExist: error_msg = 'token %s not found.' % token return api_error(status.HTTP_404_NOT_FOUND, error_msg) username = request.user.username if not fs.is_owner(username): error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) try: fs.delete() return Response({'success': True}) except Exception as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
def delete(self, request, repo_id, org_id, format=None): """ User delete a repo shared to him/her. """ 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 check_folder_permission(request, repo_id, '/'): error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) username = request.user.username repo_owner = get_repo_owner(request, repo_id) try: if org_id: is_org = True seafile_api.org_remove_share(org_id, repo_id, repo_owner, username) else: is_org = False seafile_api.remove_share(repo_id, repo_owner, username) except Exception as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) permission = check_user_share_in_permission(repo_id, username, is_org) send_perm_audit_msg('delete-repo-perm', repo_owner, username, repo_id, '/', permission) return Response({'success': True})
def delete(self, request, group_id, repo_id, org_id): """ Delete a group owned library. Permission checking: 1. is group admin; """ 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) group_id = int(group_id) username = request.user.username if not is_group_admin(group_id, username): error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) try: SeafileAPI.delete_group_owned_repo(group_id, repo_id, 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) return Response({'success': True})
def delete(self, request, repo_id, org_id, format=None): """ Delete repo user share permission. Permission checking: 1. is group admin """ # parameter check to_user = request.data.get('username', None) if not to_user: error_msg = 'username invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) # permission check repo_owner = get_repo_owner(request, repo_id) group_id = get_group_id_by_repo_owner(repo_owner) username = request.user.username if not is_group_admin(group_id, username): error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) path = request.data.get('path', '/') SeafileAPI.delete_shared_user_by_repo_path( repo_id, repo_owner, to_user, path, org_id=org_id) permission = check_user_share_out_permission(repo_id, path, to_user, is_org_context(request)) send_perm_audit_msg('delete-repo-perm', username, to_user, repo_id, path, permission) return Response({'success': True})
def delete(self, request, repo_id, format=None): # delete file 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) path = request.GET.get('p', None) if not path: error_msg = 'p invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) file_id = seafile_api.get_file_id_by_path(repo_id, path) if not file_id: return Response({'success': True}) parent_dir = os.path.dirname(path) if check_folder_permission(request, repo_id, parent_dir) != 'rw': error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) parent_dir = os.path.dirname(path) file_name = os.path.basename(path) try: seafile_api.del_file(repo_id, parent_dir, file_name, request.user.username) except SearpcError as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) if request.GET.get('reloaddir', '').lower() == 'true': return reloaddir(request, repo, parent_dir) else: return Response({'success': True})
def get(self, request, repo_id): """list all tags of a file. """ # argument check file_path = request.GET.get('file_path') if not file_path: error_msg = 'file_path invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) file_path = normalize_file_path(file_path) # 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) file_id = seafile_api.get_file_id_by_path(repo_id, file_path) if not file_id: error_msg = 'File not found.' return api_error(status.HTTP_404_NOT_FOUND, error_msg) # permission check if not check_folder_permission(request, repo_id, '/'): error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) try: file_tags = FileTags.objects.get_file_tag_by_path(repo_id, file_path) 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({"file_tags": file_tags}, status=status.HTTP_200_OK)
def post(self, request, email, format=None): # migrate an account's repos and groups to an exist account if not is_valid_username(email): return api_error(status.HTTP_400_BAD_REQUEST, 'Email %s invalid.' % email) op = request.data.get('op', '').lower() if op == 'migrate': from_user = email to_user = request.data.get('to_user', '') if not is_valid_username(to_user): return api_error(status.HTTP_400_BAD_REQUEST, 'Email %s invalid.' % to_user) try: user2 = User.objects.get(email=to_user) except User.DoesNotExist: return api_error(status.HTTP_404_NOT_FOUND, 'User %s not found.' % to_user) # transfer owned repos to new user for r in seafile_api.get_owned_repo_list(from_user): seafile_api.set_repo_owner(r.id, user2.username) # transfer joined groups to new user for g in seaserv.get_personal_groups_by_user(from_user): if not seaserv.is_group_user(g.id, user2.username): # add new user to the group on behalf of the group creator ccnet_threaded_rpc.group_add_member(g.id, g.creator_name, to_user) if from_user == g.creator_name: ccnet_threaded_rpc.set_group_creator(g.id, to_user) return Response("success") else: return api_error(status.HTTP_400_BAD_REQUEST, 'op can only be migrate.')
def post(self, request, org_id, format=None): """Create a file draft if the user has read-write permission to the origin file """ repo_id = request.POST.get('repo_id', '') file_path = request.POST.get('file_path', '') 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) # perm check perm = check_folder_permission(request, repo.id, file_path) if perm != PERMISSION_READ_WRITE: error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) file_id = seafile_api.get_file_id_by_path(repo.id, file_path) if not file_id: return api_error(status.HTTP_404_NOT_FOUND, "File %s not found" % file_path) username = request.user.username try: d = Draft.objects.add(username, repo, file_path, file_id) return Response(d.to_dict()) except DraftFileExist: return api_error(status.HTTP_409_CONFLICT, 'Draft already exists.') except Exception as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
def post(self, request, repo_id, format=None): """Post a comments of a file. """ path = request.GET.get('p', '/').rstrip('/') if not path: return api_error(status.HTTP_400_BAD_REQUEST, 'Wrong path.') try: avatar_size = int(request.GET.get('avatar_size', AVATAR_DEFAULT_SIZE)) except ValueError: avatar_size = AVATAR_DEFAULT_SIZE try: obj_id = seafile_api.get_file_id_by_path(repo_id, path) except SearpcError as e: logger.error(e) return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, 'Internal error.') if not obj_id: return api_error(status.HTTP_404_NOT_FOUND, 'File not found.') comment = request.data.get('comment', '') if not comment: return api_error(status.HTTP_400_BAD_REQUEST, 'Comment can not be empty.') username = request.user.username o = FileComment.objects.add_by_file_path( repo_id=repo_id, file_path=path, author=username, comment=comment) comment = o.to_dict() comment.update(user_to_dict(request.user.username, request=request, avatar_size=avatar_size)) return Response(comment, status=201)
def post(self, request, token): """ Check if password for an encrypted upload link is correct. Permission checking: 1. only admin can perform this action. """ try: uploadlink = UploadLinkShare.objects.get(token=token) except UploadLinkShare.DoesNotExist: error_msg = 'Upload link %s not found.' % token return api_error(status.HTTP_404_NOT_FOUND, error_msg) if not uploadlink.is_encrypted(): error_msg = 'Upload link is not encrypted.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) password = request.POST.get('password') if not password: error_msg = 'password invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) if check_password(password, uploadlink.password): return Response({'success': True}) else: error_msg = 'Password is not correct.' return api_error(status.HTTP_403_FORBIDDEN, error_msg)
def _decorated(view, request, *args, **kwargs): # argument check if request.method == 'GET': repo_id = request.GET.get('repo_id', None) path = request.GET.get('path', '/') share_type = request.GET.get('share_type', None) else: repo_id = request.data.get('repo_id', None) path = request.data.get('path', '/') share_type = request.data.get('share_type', None) if not repo_id: error_msg = 'repo_id invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) if not share_type or share_type not in ('user', 'group'): error_msg = 'share_type invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) # resource check repo = seafile_api.get_repo(repo_id) if not repo: error_msg = 'Library %s not found.' % repo_id return api_error(status.HTTP_404_NOT_FOUND, error_msg) if not seafile_api.get_dir_id_by_path(repo_id, path): error_msg = 'Folder %s not found.' % path return api_error(status.HTTP_404_NOT_FOUND, error_msg) return func(view, request, repo, path, share_type, *args, **kwargs)
def put(self, request, repo_id, repo_tag_id): """update one repo_tag """ # argument check tag_name = request.data.get('name') if not tag_name: error_msg = 'name invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) tag_color = request.data.get('color') if not tag_color: error_msg = 'color invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) # resource check repo_tag = RepoTags.objects.get_repo_tag_by_id(repo_tag_id) if not repo_tag: error_msg = 'repo_tag not found.' return api_error(status.HTTP_404_NOT_FOUND, error_msg) # permission check if check_folder_permission(request, repo_id, '/') != PERMISSION_READ_WRITE: error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) try: repo_tag.name = tag_name repo_tag.color = tag_color repo_tag.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({"repo_tag": repo_tag.to_dict()}, status=status.HTTP_200_OK)
def get(self, request): if not is_pro_version(): error_msg = 'Feature disabled.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) # check the date format, should be like '2015-10-10' start = request.GET.get('start', None) end = request.GET.get('end', None) if not check_time_period_valid(start, end): error_msg = 'start or end date invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) # Filtering a DateTimeField with dates won't include items on the last day, # because the bounds are interpreted as '0am on the given date'. end = end + ' 23:59:59' result = [] from seahub_extra.sysadmin_extra.models import UserLoginLog logs = UserLoginLog.objects.filter(login_date__range=(start, end)) for log in logs: result.append({ 'login_time': datetime_to_isoformat_timestr(log.login_date), 'login_ip': log.login_ip, 'name': email2nickname(log.username), 'email':log.username }) return Response(result)
def put(self, request, group_id, email): """ Set/unset a specific group member as admin. """ username = request.user.username is_admin = request.data.get('is_admin', '') try: # only group owner can set/unset a specific group member as admin if not is_group_owner(group_id, username): error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) if not is_group_member(group_id, email): error_msg = 'Email %s invalid.' % email return api_error(status.HTTP_400_BAD_REQUEST, error_msg) # set/unset a specific group member as admin if is_admin.lower() == 'true': seaserv.ccnet_threaded_rpc.group_set_admin(group_id, email) elif is_admin.lower() == 'false': seaserv.ccnet_threaded_rpc.group_unset_admin(group_id, email) else: error_msg = 'is_admin invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) except SearpcError as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) member_info = get_group_member_info(request, group_id, email) return Response(member_info)
def get(self, request, group_id, format=None): """ Get all group members. """ try: avatar_size = int(request.GET.get('avatar_size', AVATAR_DEFAULT_SIZE)) except ValueError: avatar_size = AVATAR_DEFAULT_SIZE try: # only group member can get info of all group members if not is_group_member(group_id, request.user.username): error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) members = seaserv.get_group_members(group_id) except SearpcError as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) group_members = [] is_admin = request.GET.get('is_admin', 'false') for m in members: # only return group admins if is_admin == 'true' and not m.is_staff: continue member_info = get_group_member_info(request, group_id, m.user_name, avatar_size) group_members.append(member_info) return Response(group_members)
def get(self, request, group_id, email): """ Get info of a specific group member. """ try: # only group member can get info of a specific group member if not is_group_member(group_id, request.user.username): error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) if not is_group_member(group_id, email): error_msg = 'Email %s invalid.' % email return api_error(status.HTTP_400_BAD_REQUEST, error_msg) except SearpcError as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) try: avatar_size = int(request.GET.get('avatar_size', AVATAR_DEFAULT_SIZE)) except ValueError: avatar_size = AVATAR_DEFAULT_SIZE member_info = get_group_member_info(request, group_id, email, avatar_size) return Response(member_info)
def delete(self, request, pk): """Delete a reviewer """ try: d = Draft.objects.get(pk=pk) except Draft.DoesNotExist: return api_error(status.HTTP_404_NOT_FOUND, 'Draft %s not found' % pk) perm = check_folder_permission(request, d.origin_repo_id, '/') if perm is None: error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) reviewer = request.GET.get('username') if reviewer is None: return api_error(status.HTTP_400_BAD_REQUEST, 'Email %s invalid.' % reviewer) try: reviewer = DraftReviewer.objects.get(reviewer=reviewer, draft=d) except DraftReviewer.DoesNotExist: return Response(status.HTTP_200_OK) reviewer.delete() return Response(status.HTTP_200_OK)
def post(self, request, group_id): """ Add a group member. """ email = request.data.get('email', None) try: User.objects.get(email=email) except User.DoesNotExist: error_msg = 'User %s not found.' % email return api_error(status.HTTP_404_NOT_FOUND, error_msg) username = request.user.username try: # only group owner/admin can add a group member if not is_group_admin_or_owner(group_id, username): error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) if is_group_member(group_id, email): error_msg = _(u'User %s is already a group member.') % email return api_error(status.HTTP_400_BAD_REQUEST, error_msg) seaserv.ccnet_threaded_rpc.group_add_member(group_id, username, email) except SearpcError as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) member_info = get_group_member_info(request, group_id, email) return Response(member_info, status=status.HTTP_201_CREATED)
def get(self, request, token): """ Get library/file/folder info via smart link token. """ uuid_map = FileUUIDMap.objects.get_fileuuidmap_by_uuid(token) if not uuid_map: error_msg = 'token invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) repo_id = uuid_map.repo_id parent_path = uuid_map.parent_path filename = uuid_map.filename is_dir = uuid_map.is_dir # permission check if not check_folder_permission(request, repo_id, parent_path): error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) full_path = posixpath.join(parent_path, filename) result = {} result['repo_id'] = repo_id result['path'] = full_path result['is_dir'] = is_dir return Response(result)
def post(self, request): """ Create a group Permission checking: 1. Admin user; """ # argument check group_name = request.data.get('group_name', '') if not group_name: error_msg = 'group_name %s invalid.' % group_name return api_error(status.HTTP_400_BAD_REQUEST, error_msg) group_name = group_name.strip() # Check whether group name is validate. if not validate_group_name(group_name): error_msg = _( 'Group name can only contain letters, numbers, blank, hyphen, dot, single quote or underscore' ) return api_error(status.HTTP_400_BAD_REQUEST, error_msg) # Check whether group name is duplicated. pattern_matched_groups = ccnet_api.search_groups(group_name, -1, -1) for group in pattern_matched_groups: if group.group_name == group_name: error_msg = _('There is already a group with that name.') return api_error(status.HTTP_400_BAD_REQUEST, error_msg) group_owner = request.data.get('group_owner', '') if group_owner: try: User.objects.get(email=group_owner) except User.DoesNotExist: error_msg = 'User %s not found.' % group_owner return api_error(status.HTTP_404_NOT_FOUND, error_msg) username = request.user.username new_owner = group_owner or username # create group. try: group_id = ccnet_api.create_group(group_name, new_owner) except SearpcError as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) # send admin operation log signal admin_op_detail = { "id": group_id, "name": group_name, "owner": new_owner, } admin_operation.send(sender=None, admin_name=username, operation=GROUP_CREATE, detail=admin_op_detail) # get info of new group group_info = get_group_info(group_id) return Response(group_info, status=status.HTTP_201_CREATED)
def put(self, request, repo_id, format=None): """ transfer a library Permission checking: 1. only admin can perform this action. """ 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) new_owner = request.data.get('owner', None) if not new_owner: error_msg = 'owner invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) try: new_owner_obj = User.objects.get(email=new_owner) except User.DoesNotExist: error_msg = 'User %s not found.' % new_owner return api_error(status.HTTP_404_NOT_FOUND, error_msg) if not new_owner_obj.permissions.can_add_repo(): error_msg = 'Transfer failed: role of %s is %s, can not add library.' % \ (new_owner, new_owner_obj.role) return api_error(status.HTTP_403_FORBIDDEN, error_msg) if MULTI_TENANCY: try: if seafserv_threaded_rpc.get_org_id_by_repo_id(repo_id) > 0: error_msg = 'Can not transfer organization library.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) if ccnet_api.get_orgs_by_user(new_owner): error_msg = 'Can not transfer library to organization user %s' % new_owner return api_error(status.HTTP_403_FORBIDDEN, error_msg) except Exception as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) repo_owner = seafile_api.get_repo_owner(repo_id) # get repo shared to user/group list shared_users = seafile_api.list_repo_shared_to(repo_owner, repo_id) shared_groups = seafile_api.list_repo_shared_group_by_user( repo_owner, repo_id) # get all pub repos pub_repos = [] if not request.cloud_mode: pub_repos = seafile_api.list_inner_pub_repos_by_owner(repo_owner) # transfer repo seafile_api.set_repo_owner(repo_id, new_owner) # reshare repo to user for shared_user in shared_users: shared_username = shared_user.user if new_owner == shared_username: continue seafile_api.share_repo(repo_id, new_owner, shared_username, shared_user.perm) # reshare repo to group for shared_group in shared_groups: shared_group_id = shared_group.group_id if not ccnet_api.is_group_user(shared_group_id, new_owner): continue seafile_api.set_group_repo(repo_id, shared_group_id, new_owner, shared_group.perm) # check if current repo is pub-repo # if YES, reshare current repo to public for pub_repo in pub_repos: if repo_id != pub_repo.id: continue seafile_api.add_inner_pub_repo(repo_id, pub_repo.permission) break repo = seafile_api.get_repo(repo_id) repo_info = get_repo_info(repo) return Response(repo_info)
def put(self, request, org_id, email): """ update base info of a org user Permission checking: 1. only admin can perform this action. """ try: user = User.objects.get(email=email) except User.DoesNotExist: error_msg = 'User %s not found.' % email return api_error(status.HTTP_404_NOT_FOUND, error_msg) # update active active = request.data.get('active', None) if active: active = active.lower() if active not in ('true', 'false'): error_msg = "active invalid, should be 'true' or 'false'." return api_error(status.HTTP_400_BAD_REQUEST, error_msg) if active == 'true': user.is_active = True else: user.is_active = False try: # update user status result_code = user.save() except Exception as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) if result_code == -1: error_msg = 'Fail to update user %s.' % email return api_error(status.HTTP_403_FORBIDDEN, error_msg) # update name name = request.data.get('name', None) if name: profile = Profile.objects.get_profile_by_user(email) if profile is None: profile = Profile(user=email) profile.nickname = name profile.save() # update contact_email contact_email = request.data.get('contact_email', None) if contact_email: profile = Profile.objects.get_profile_by_user(email) if profile is None: profile = Profile(user=email) profile.contact_email = contact_email profile.save() # update user quota user_quota_mb = request.data.get("quota_total", None) if user_quota_mb: try: user_quota_mb = int(user_quota_mb) except Exception as e: logger.error(e) error_msg = "quota_total invalid." return api_error(status.HTTP_400_BAD_REQUEST, error_msg) user_quota = int(user_quota_mb) * get_file_size_unit('MB') org_quota = seafile_api.get_org_quota(org_id) # -1 means org has unlimited quota if org_quota > 0: org_quota_mb = org_quota / get_file_size_unit('MB') if user_quota_mb > org_quota_mb: error_msg = 'Failed to set quota: maximum quota is %d MB' % org_quota_mb return api_error(status.HTTP_400_BAD_REQUEST, error_msg) seafile_api.set_org_user_quota(org_id, email, user_quota) user_info = get_org_user_info(org_id, user) user_info['active'] = user.is_active return Response(user_info)
def put(self, request, group_id): """ Admin update a group 1. transfer a group. 2. set group quota Permission checking: 1. Admin user; """ # recourse check group_id = int(group_id) # Checked by URL Conf group = ccnet_api.get_group(group_id) if not group: error_msg = 'Group %d not found.' % group_id return api_error(status.HTTP_404_NOT_FOUND, error_msg) new_owner = request.data.get('new_owner', '') if new_owner: if not is_valid_username(new_owner): error_msg = 'new_owner %s invalid.' % new_owner return api_error(status.HTTP_400_BAD_REQUEST, error_msg) # check if new_owner exists, # NOT need to check old_owner for old_owner may has been deleted. try: User.objects.get(email=new_owner) except User.DoesNotExist: error_msg = 'User %s not found.' % new_owner return api_error(status.HTTP_404_NOT_FOUND, error_msg) old_owner = group.creator_name if new_owner == old_owner: error_msg = _('User %s is already group owner.') % new_owner return api_error(status.HTTP_400_BAD_REQUEST, error_msg) # transfer a group try: if not is_group_member(group_id, new_owner): ccnet_api.group_add_member(group_id, old_owner, new_owner) if not is_group_admin(group_id, new_owner): ccnet_api.group_set_admin(group_id, new_owner) ccnet_api.set_group_creator(group_id, new_owner) ccnet_api.group_unset_admin(group_id, old_owner) except SearpcError as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) # send admin operation log signal admin_op_detail = { "id": group_id, "name": group.group_name, "from": old_owner, "to": new_owner, } admin_operation.send(sender=None, admin_name=request.user.username, operation=GROUP_TRANSFER, detail=admin_op_detail) # set group quota group_quota = request.data.get('quota', '') if group_quota: try: group_quota = int(group_quota) except ValueError: error_msg = 'quota invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) if not (group_quota > 0 or group_quota == -2): error_msg = 'quota invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) try: seafile_api.set_group_quota(group_id, group_quota) except Exception as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) group_info = get_group_info(group_id) return Response(group_info)
def post(self, request, format=None): """Add a new wiki. """ use_exist_repo = request.POST.get('use_exist_repo', '') if not use_exist_repo: msg = 'Use exist repo is invalid' return api_error(status.HTTP_400_BAD_REQUEST, msg) name = request.POST.get('name', '') if not name: msg = 'Name is invalid' return api_error(status.HTTP_400_BAD_REQUEST, msg) if not is_valid_wiki_name(name): msg = _( 'Name can only contain letters, numbers, blank, hyphen or underscore.' ) return api_error(status.HTTP_400_BAD_REQUEST, msg) username = request.user.username org_id = -1 if is_org_context(request): org_id = request.user.org.org_id if use_exist_repo == 'false': try: wiki = Wiki.objects.add(name, username, org_id=org_id) except DuplicateWikiNameError: msg = _( '%s is taken by others, please try another name.') % name return api_error(status.HTTP_400_BAD_REQUEST, msg) except IntegrityError: msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, msg) # create home page page_name = "home.md" try: seafile_api.post_empty_file(wiki.repo_id, '/', page_name, request.user.username) except SearpcError as e: logger.error(e) msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, msg) return Response(wiki.to_dict()) if use_exist_repo == 'true': repo_id = request.POST.get('repo_id', '') if not repo_id: msg = 'Repo id is invalid.' return api_error(status.HTTP_400_BAD_REQUEST, 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) # repo owner is_repo_owner = seafile_api.is_repo_owner(username, repo_id) if not is_repo_owner: repo_admin = is_repo_admin(username, repo_id) if not repo_admin: is_group_repo_admin = is_group_repo_staff( repo_id, username) if not is_group_repo_admin: error_msg = _('Permission denied.') return api_error(status.HTTP_403_FORBIDDEN, error_msg) try: wiki = Wiki.objects.add(wiki_name=repo.repo_name, username=username, repo_id=repo.repo_id, org_id=org_id) except DuplicateWikiNameError: msg = _('%s is taken by others, please try another name.' ) % repo.repo_name return api_error(status.HTTP_400_BAD_REQUEST, msg) except IntegrityError: msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, msg) # create home page if not exist page_name = "home.md" if not seafile_api.get_file_id_by_path(repo_id, "/" + page_name): try: seafile_api.post_empty_file(repo_id, '/', page_name, username) except SearpcError as e: logger.error(e) msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, msg) return Response(wiki.to_dict())
def copy_dtable(src_workspace, src_dtable, dst_workspace, name, username): # create dtable try: dst_dtable = DTables.objects.create_dtable(username, dst_workspace, name) except Exception as e: logger.error('create table: %s in dst workspace: %s, error: %s', name, dst_workspace.id, e) error_msg = 'Internal Server Error' return None, api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) clear_tmp_files_and_dirs(str(dst_dtable.uuid)) dtable_file_name = name + FILE_TYPE cur_dtable_path = os.path.join(TMP_PATH, str(dst_dtable.uuid)) try: # .dtable src_dtable_file_id = seafile_api.get_file_id_by_path( src_workspace.repo_id, '/' + dtable_file_name) token = seafile_api.get_fileserver_access_token(src_workspace.repo_id, src_dtable_file_id, 'view', '', use_onetime=False) json_url = gen_inner_file_get_url(token, name + FILE_TYPE) response = requests.get(json_url) if response.status_code != 200: logger.error('request dtable url response error status: %s', response.status_code) return None, api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, 'Internal Server Error') if response.content: # rebuild asset images files url dtable_content = response.json() dtable_content = rebuild_content_asset(dtable_content, dst_dtable) # save content to local os.makedirs(cur_dtable_path) dtable_save_path = os.path.join(cur_dtable_path, dtable_file_name) with open(dtable_save_path, 'w') as f: json.dump(dtable_content, f) # upload content seafile_api.post_file(dst_workspace.repo_id, dtable_save_path, '/', dtable_file_name, username) else: seafile_api.post_empty_file(dst_workspace.repo_id, '/', dtable_file_name, username) except Exception as e: logger.error('copy dtable: %s.dtable file error: %s', name, e) DTables.objects.filter(id=dst_dtable.id).delete() error_msg = 'Internal Server Error' return None, api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) finally: clear_tmp_files_and_dirs(str(dst_dtable.uuid)) try: # asset dir by seafile_api.copy_file, sync-style temporary copy_asset(src_workspace.repo_id, src_dtable.uuid, dst_workspace.repo_id, dst_dtable.uuid, username) except Exception as e: logger.error('dtable: %s, copy asset dir error: %s', src_dtable.id, e) error_msg = 'Internal Server Error' DTables.objects.filter(id=dst_dtable.id).delete() if seafile_api.get_file_id_by_path(dst_workspace.repo_id, '/' + dtable_file_name): seafile_api.del_file(dst_workspace.repo_id, '/', dtable_file_name, username) return None, api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) finally: clear_tmp_files_and_dirs(str(dst_dtable.uuid)) return dst_dtable, None
def get(self, request, format=None): """ Only used for download dir when view dir share link from web. Permission checking: 1. authenticated user OR anonymous user has passed email code check(if necessary); """ # permission check if is_pro_version() and settings.ENABLE_SHARE_LINK_AUDIT: if not request.user.is_authenticated() and \ not request.session.get('anonymous_email'): # if anonymous user has passed email code check, # then his/her email info will be in session. error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) # argument check share_link_token = request.GET.get('share_link_token', None) if not share_link_token: error_msg = 'share_link_token invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) req_path = request.GET.get('path', None) if not req_path: error_msg = 'path invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) # recourse check fileshare = FileShare.objects.get_valid_dir_link_by_token(share_link_token) if not fileshare: error_msg = 'share_link_token %s not found.' % share_link_token return api_error(status.HTTP_404_NOT_FOUND, error_msg) if req_path[-1] != '/': req_path += '/' if req_path == '/': real_path = fileshare.path else: real_path = posixpath.join(fileshare.path, req_path.lstrip('/')) if real_path[-1] != '/': real_path += '/' repo_id = fileshare.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) dir_id = seafile_api.get_dir_id_by_path(repo_id, real_path) if not dir_id: error_msg = 'Folder %s not found.' % real_path return api_error(status.HTTP_404_NOT_FOUND, error_msg) # get file server access token dir_name = repo.name if real_path == '/' else \ os.path.basename(real_path.rstrip('/')) dir_size = seafile_api.get_dir_size( repo.store_id, repo.version, dir_id) if dir_size > seaserv.MAX_DOWNLOAD_DIR_SIZE: error_msg = 'Unable to download directory "%s": size is too large.' % dir_name return api_error(status.HTTP_400_BAD_REQUEST, error_msg) try: seaserv.send_message('seahub.stats', 'dir-download\t%s\t%s\t%s\t%s' % (repo_id, fileshare.username, dir_id, dir_size)) except Exception as e: logger.error(e) is_windows = 0 if is_windows_operating_system(request): is_windows = 1 fake_obj_id = { 'obj_id': dir_id, 'dir_name': dir_name, 'is_windows': is_windows } username = request.user.username try: zip_token = seafile_api.get_fileserver_access_token( repo_id, json.dumps(fake_obj_id), 'download-dir', 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 request.session.get('anonymous_email'): request.user.username = request.session.get('anonymous_email') send_file_access_msg(request, repo, real_path, 'share-link') return Response({'zip_token': zip_token})
def post(self, request, org_id): """ Add new user to org. Permission checking: 1. only admin can perform this action. """ # argument check org_id = int(org_id) if org_id == 0: error_msg = 'org_id invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) org = ccnet_api.get_org_by_id(org_id) if not org: error_msg = 'Organization %d not found.' % org_id return api_error(status.HTTP_404_NOT_FOUND, error_msg) email = request.POST.get('email', None) if not email or not is_valid_email(email): error_msg = 'email invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) password = request.POST.get('password', None) if not password: error_msg = 'password invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) active = request.POST.get('active', 'true') active = active.lower() if active not in ('true', 'false'): error_msg = 'active invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) is_active = active == 'true' try: existed_profile = Profile.objects.filter( contact_email=email).first() vid = existed_profile.user if existed_profile else email User.objects.get(email=vid) user_exists = True except User.DoesNotExist: user_exists = False if user_exists: error_msg = 'User %s already exists.' % email return api_error(status.HTTP_400_BAD_REQUEST, error_msg) # check user number limit by license if user_number_over_limit(): error_msg = 'The number of users exceeds the limit.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) # check user number limit by org member quota org_members = len(ccnet_api.get_org_emailusers(org.url_prefix, -1, -1)) if ORG_MEMBER_QUOTA_ENABLED: from seahub.organizations.models import OrgMemberQuota org_members_quota = OrgMemberQuota.objects.get_quota(org_id) if org_members_quota is not None and org_members >= org_members_quota: error_msg = 'Failed. You can only invite %d members.' % org_members_quota return api_error(status.HTTP_403_FORBIDDEN, error_msg) # create user try: user = User.objects.create_user(email, password, is_staff=False, is_active=is_active) except User.DoesNotExist as e: logger.error(e) error_msg = 'Fail to add user %s.' % email return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) # add user to org # set `is_staff` parameter as `0` try: ccnet_api.add_org_user(org_id, user.email, 0) except Exception as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) name = request.POST.get('name', None) if name: Profile.objects.add_or_update(user.email, name) if config.FORCE_PASSWORD_CHANGE: UserOptions.objects.set_force_passwd_change(email) user_info = get_org_user_info(org_id, user) user_info['active'] = is_active return Response(user_info)