Example #1
0
def get_group_repos(username, org_id, groups):
    """Get repos shared to groups.
    """
    group_repos = []
    if org_id:
        # For each group I joined...
        for grp in groups:
            # Get group repos, and for each group repos...
            for r_id in seafile_api.get_org_group_repoids(org_id, grp.id):
                # No need to list my own repo
                repo_owner = seafile_api.get_org_repo_owner(r_id)
                if repo_owner == username:
                    continue
                # Convert repo properties due to the different collumns in Repo
                # and SharedRepo
                r = seafile_api.get_repo(r_id)
                if not r:
                    continue
                r.repo_id = r.id
                r.repo_name = r.name
                r.repo_desc = r.desc
                r.last_modified = get_repo_last_modify(r)
                r.share_type = 'group'
                r.user = repo_owner
                r.user_perm = seafile_api.check_repo_access_permission(
                    r_id, username)
                r.group = grp
                group_repos.append(r)
    else:
        # For each group I joined...
        for grp in groups:
            # Get group repos, and for each group repos...
            for r_id in seafile_api.get_group_repoids(grp.id):
                # No need to list my own repo
                repo_owner = seafile_api.get_repo_owner(r_id)
                if repo_owner == username:
                    continue
                # Convert repo properties due to the different collumns in Repo
                # and SharedRepo
                r = seafile_api.get_repo(r_id)
                if not r:
                    continue
                r.repo_id = r.id
                r.repo_name = r.name
                r.repo_desc = r.desc
                r.last_modified = get_repo_last_modify(r)
                r.share_type = 'group'
                r.user = repo_owner
                r.user_perm = seafile_api.check_repo_access_permission(
                    r_id, username)
                r.group = grp
                group_repos.append(r)
    return group_repos
Example #2
0
def list_shared_links(request):
    """List shared links, and remove invalid links(file/dir is deleted or moved).
    """
    username = request.user.username
    
    # download links
    fileshares = FileShare.objects.filter(username=username)
    p_fileshares = []           # personal file share
    for fs in fileshares:
        if is_personal_repo(fs.repo_id):  # only list files in personal repos
            r = seafile_api.get_repo(fs.repo_id)
            if not r:
                fs.delete()
                continue

            if fs.s_type == 'f':
                if seafile_api.get_file_id_by_path(r.id, fs.path) is None:
                    fs.delete()
                    continue
                fs.filename = os.path.basename(fs.path)
                fs.shared_link = gen_file_share_link(fs.token) 
            else:
                if seafile_api.get_dir_id_by_path(r.id, fs.path) is None:
                    fs.delete()
                    continue
                fs.filename = os.path.basename(fs.path.rstrip('/'))
                fs.shared_link = gen_dir_share_link(fs.token)
            fs.repo = r
            p_fileshares.append(fs)

    # upload links
    uploadlinks = UploadLinkShare.objects.filter(username=username)
    p_uploadlinks = []
    for link in uploadlinks:
        if is_personal_repo(link.repo_id):
            r = seafile_api.get_repo(link.repo_id)
            if not r:
                link.delete()
                continue
            if seafile_api.get_dir_id_by_path(r.id, link.path) is None:
                link.delete()
                continue
            link.dir_name = os.path.basename(link.path.rstrip('/'))
            link.shared_link = gen_shared_upload_link(link.token)
            link.repo = r
            p_uploadlinks.append(link)

    
    return render_to_response('share/links.html', {
            "fileshares": p_fileshares,
            "uploadlinks": p_uploadlinks,
            }, context_instance=RequestContext(request))
Example #3
0
    def put(self, request, repo_id):
        """ Copy a single file/folder to other place.
        """

        # check parameter for src
        path = request.GET.get('path', None)
        if not path:
            error_msg = 'path invalid.'
            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        try:
            dirent = seafile_api.get_dirent_by_path(repo_id, path)
        except Exception as e:
            logger.error(e)
            error_msg = 'Internal Server Error'
            return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)

        if not dirent:
            error_msg = 'File or folder %s not found.' % path
            return api_error(status.HTTP_404_NOT_FOUND, error_msg)

        if path == '/':
            error_msg = 'path invalid.'
            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        # normalize path to '/1/2/3' format
        # NOT ends with '/'
        path = normalize_file_path(path)

        # now get `src_dir` and `obj_name` according to normalized path
        src_repo_id = repo_id
        src_dir = os.path.dirname(path)
        src_obj_name = os.path.basename(path)

        # check parameter for dst
        dst_repo_id = request.data.get('dst_repo_id', src_repo_id)
        if dst_repo_id != src_repo_id and not seafile_api.get_repo(dst_repo_id):
            error_msg = 'Library %s not found.' % dst_repo_id
            return api_error(status.HTTP_404_NOT_FOUND, error_msg)

        dst_dir = request.data.get('dst_dir', '/')
        if dst_dir != '/':
            dst_dir = normalize_dir_path(dst_dir)
            if not seafile_api.get_dir_id_by_path(dst_repo_id, dst_dir):
                error_msg = 'Folder %s not found.' % dst_dir
                return api_error(status.HTTP_404_NOT_FOUND, error_msg)

        # copy file
        username = request.user.username
        dst_obj_name = check_filename_with_rename(dst_repo_id, dst_dir,
                src_obj_name)
        try:
            seafile_api.copy_file(src_repo_id, src_dir, src_obj_name, dst_repo_id,
                      dst_dir, dst_obj_name, username, need_progress=0, synchronous=1)
        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, 'dst_item_name': dst_obj_name})
Example #4
0
    def _get_upload_link_info(self, uls):
        data = {}
        token = uls.token

        repo_id = uls.repo_id
        try:
            repo = seafile_api.get_repo(repo_id)
        except Exception as e:
            logger.error(e)
            repo = None

        path = uls.path
        if path:
            obj_name = '/' if path == '/' else os.path.basename(path.rstrip('/'))
        else:
            obj_name = ''

        if uls.ctime:
            ctime = datetime_to_isoformat_timestr(uls.ctime)
        else:
            ctime = ''

        data['repo_id'] = repo_id
        data['repo_name'] = repo.repo_name if repo else ''
        data['path'] = path
        data['obj_name'] = obj_name
        data['view_cnt'] = uls.view_cnt
        data['ctime'] = ctime
        data['link'] = gen_shared_upload_link(token)
        data['token'] = token
        data['username'] = uls.username

        return data
Example #5
0
    def get(self, request, repo_id, format=None):
        """ Get all file/folder in a library
        """

        repo = seafile_api.get_repo(repo_id)

        parent_dir = request.GET.get('parent_dir', '/')
        parent_dir = normalize_dir_path(parent_dir)
        dir_id = seafile_api.get_dir_id_by_path(repo_id, parent_dir)
        if not dir_id:
            error_msg = 'Folder %s not found.' % parent_dir
            return api_error(status.HTTP_404_NOT_FOUND, error_msg)

        repo_owner = get_repo_owner(request, repo_id)

        try:
            dirs = seafile_api.list_dir_with_perm(repo_id,
                parent_dir, dir_id, repo_owner, -1, -1)
        except SearpcError as e:
            logger.error(e)
            error_msg = 'Internal Server Error'
            return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)

        return_results = {}
        return_results['repo_name'] = repo.repo_name
        return_results['repo_id'] = repo.repo_id
        return_results['is_system_library'] = True if \
            repo.id == get_system_default_repo_id() else False
        return_results['dirent_list'] = []

        for dirent in dirs:
            dirent_info = get_dirent_info(dirent)
            return_results['dirent_list'].append(dirent_info)

        return Response(return_results)
Example #6
0
    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)
Example #7
0
    def format_file_comment_msg(self):
        try:
            d = json.loads(self.detail)
        except Exception as e:
            logger.error(e)
            return _(u"Internal error")

        repo_id = d['repo_id']
        file_path = d['file_path']
        author = d['author']
        comment = d['comment']

        repo = seafile_api.get_repo(repo_id)
        if repo is None or not seafile_api.get_file_id_by_path(repo.id,
                                                               file_path):
            self.delete()
            return None

        file_name = os.path.basename(file_path)
        msg = _("File <a href='%(file_url)s'>%(file_name)s</a> has a new comment from user %(author)s") % {
            'file_url': reverse('view_lib_file', args=[repo_id, file_path]),
            'file_name': escape(file_name),
            'author': escape(email2nickname(author)),
        }
        return msg
Example #8
0
    def format_repo_share_msg(self):
        """
        
        Arguments:
        - `self`:
        """
        try:
            d = json.loads(self.detail)
        except Exception as e:
            logger.error(e)
            return _(u"Internal error")

        share_from = email2nickname(d['share_from'])
        repo_id = d['repo_id']

        repo = seafile_api.get_repo(repo_id)
        if repo is None:
            self.delete()
            return None

        msg = _(u"%(user)s has shared a library named <a href='%(href)s'>%(repo_name)s</a> to you.") %  {
            'user': escape(share_from),
            'href': reverse('view_common_lib_dir', args=[repo.id, '']),
            'repo_name': escape(repo.name),
            }
        return msg
Example #9
0
    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)
Example #10
0
def personal_wiki_use_lib(request):
    if request.method != 'POST':
        raise Http404

    repo_id = request.POST.get('dst_repo', '')
    username = request.user.username
    next = reverse('personal_wiki', args=[])
    repo = seafile_api.get_repo(repo_id)
    if repo is None:
        messages.error(request, _('Failed to set wiki library.'))
        return HttpResponseRedirect(next)

    if check_folder_permission(request, repo_id, '/') != 'rw':
        messages.error(request, _('Permission denied.'))
        return HttpResponseRedirect(next)

    PersonalWiki.objects.save_personal_wiki(username=username, repo_id=repo_id)

    # create home page if not exist
    page_name = "home.md"
    if not seaserv.get_file_id_by_path(repo_id, "/" + page_name):
        if not seaserv.post_empty_file(repo_id, "/", page_name, username):
            messages.error(request, _('Failed to create home page. Please retry later'))

    return HttpResponseRedirect(next)
Example #11
0
    def post(self, request, repo_id):

        repo = seafile_api.get_repo(repo_id)
        if not repo:
            error_msg = "Library %s not found." % repo_id
            return api_error(status.HTTP_404_NOT_FOUND, error_msg)

        password = request.POST.get("password", None)
        if not password:
            error_msg = "password invalid."
            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        try:
            seafile_api.set_passwd(repo_id, request.user.username, password)
            return Response({"success": True})
        except SearpcError as e:
            if e.msg == "Bad arguments":
                error_msg = "Bad arguments"
                return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
            elif e.msg == "Incorrect password":
                error_msg = _(u"Wrong password")
                return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
            elif e.msg == "Internal server error":
                error_msg = _(u"Internal server error")
                return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
            else:
                error_msg = _(u"Decrypt library error")
                return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
Example #12
0
    def add(self, wiki_name, username, permission='private', repo_id=None,
            org_id=-1):
        if not permission:
            permission = 'private'

        from .utils import slugfy_wiki_name
        slug = slugfy_wiki_name(wiki_name)
        if self.filter(slug=slug).count() > 0:
            raise DuplicateWikiNameError

        now = timezone.now()
        if repo_id is None:     # create new repo to store the wiki pages
            if org_id > 0:
                repo_id = seafile_api.create_org_repo(wiki_name, '', username,
                                                      passwd=None, org_id=org_id)
            else:
                repo_id = seafile_api.create_repo(wiki_name, '', username,
                                                  passwd=None)

        repo = seafile_api.get_repo(repo_id)
        assert repo is not None

        wiki = self.model(username=username, name=wiki_name, slug=slug,
                          repo_id=repo.id, permission=permission,
                          created_at=now)
        wiki.save(using=self._db)
        return wiki
Example #13
0
    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)
Example #14
0
    def delete(self, request, repo_id, file_tag_id):
        """delete a tag from a file
        """
        # 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_tag = FileTags.objects.get_file_tag_by_id(file_tag_id)
        if not file_tag:
            error_msg = 'file_tag %s not found.' % file_tag_id
            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:
            FileTags.objects.delete_file_tag(file_tag_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"}, status=status.HTTP_200_OK)
Example #15
0
    def format_repo_share_msg(self, notice):
        d = json.loads(notice.detail)
        repo_id = d['repo_id']
        repo = seafile_api.get_repo(repo_id)
        path = d['path']
        org_id = d.get('org_id', None)
        if path == '/':
            shared_type = 'library'
        else:
            shared_type = 'folder'
            if org_id:
                owner = seafile_api.get_org_repo_owner(repo_id)
                repo = seafile_api.get_org_virtual_repo(
                    org_id, repo_id, path, owner)
            else:
                owner = seafile_api.get_repo_owner(repo_id)
                repo = seafile_api.get_virtual_repo(repo_id, path, owner)

        repo_url = reverse('lib_view', args=[repo_id, repo.name, ''])
        notice.repo_url = repo_url
        notice.notice_from = escape(email2nickname(d['share_from']))
        notice.repo_name = repo.name
        notice.avatar_src = self.get_avatar_src(d['share_from'])
        notice.shared_type = shared_type

        return notice
Example #16
0
def edit_profile(request):
    """
    Show and edit user profile.
    """
    username = request.user.username
    form_class = DetailedProfileForm

    if request.method == 'POST':
        form = form_class(request.POST)
        if form.is_valid():
            form.save(username=username)
            messages.success(request, _(u'Successfully edited profile.'))

            return HttpResponseRedirect(reverse('edit_profile'))
        else:
            messages.error(request, _(u'Failed to edit profile'))
    else:
        profile = Profile.objects.get_profile_by_user(username)
        d_profile = DetailedProfile.objects.get_detailed_profile_by_user(
            username)

        init_dict = {}
        if profile:
            init_dict['nickname'] = profile.nickname
            init_dict['login_id'] = profile.login_id
            init_dict['contact_email'] = profile.contact_email
        if d_profile:
            init_dict['department'] = d_profile.department
            init_dict['telephone'] = d_profile.telephone
        form = form_class(init_dict)

    # common logic
    try:
        server_crypto = UserOptions.objects.is_server_crypto(username)
    except CryptoOptionNotSetError:
        # Assume server_crypto is ``False`` if this option is not set.
        server_crypto = False

    sub_lib_enabled = UserOptions.objects.is_sub_lib_enabled(username)

    default_repo_id = UserOptions.objects.get_default_repo(username)
    if default_repo_id:
        default_repo = seafile_api.get_repo(default_repo_id)
    else:
        default_repo = None

    owned_repos = get_owned_repo_list(request)
    owned_repos = filter(lambda r: not r.is_virtual, owned_repos)

    return render_to_response('profile/set_profile.html', {
            'form': form,
            'server_crypto': server_crypto,
            "sub_lib_enabled": sub_lib_enabled,
            'force_server_crypto': settings.FORCE_SERVER_CRYPTO,
            'default_repo': default_repo,
            'owned_repos': owned_repos,
            'is_pro': is_pro_version(),
            'is_ldap_user': is_ldap_user(request.user),
            'two_factor_auth_enabled': has_two_factor_auth(),
            }, context_instance=RequestContext(request))
Example #17
0
    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()
Example #18
0
def check_group_folder_perm_args(from_user, repo_id, path, group_id, perm = None):
    if not seafile_api.get_repo(repo_id):
        return {'error': _(u'Library does not exist.'), 'status': 400}

    if check_repo_access_permission(repo_id, from_user) != 'rw':
        return {'error': _('Permission denied'), 'status': 403}

    if perm is not None:
        # add or toggle folder perm
        if seafile_api.get_dir_id_by_path(repo_id, path) is None:
            return {'error': _('Invalid path'), 'status': 400}

        if perm != 'r' and perm != 'rw':
            return {'error': _('Invalid folder permission'), 'status': 400}

    if not path.startswith('/'):
        return {'error': _('Path should start with "/"'), 'status': 400}

    if path != '/' and path.endswith('/'):
        return {'error': _('Path should NOT ends with "/"'), 'status': 400}

    if not seaserv.get_group(group_id):
        return {'error': _('Invalid group'), 'status': 400}

    return {'success': True}
Example #19
0
def check_user_folder_perm_args(from_user, repo_id, path, to_user, perm=None):
    if not seafile_api.get_repo(repo_id):
        return {'error': _(u'Library does not exist.'), 'status': 400}

    if check_repo_access_permission(repo_id, from_user) != 'rw':
        return {'error': _('Permission denied'), 'status': 403}

    if perm is not None:
        # add or toggle folder perm
        if seafile_api.get_dir_id_by_path(repo_id, path) is None:
            return {'error': _('Invalid path'), 'status': 400}

        if perm != 'r' and perm != 'rw':
            return {'error': _('Invalid folder permission'), 'status': 400}

    if not path.startswith('/'):
        return {'error': _('Path should start with "/"'), 'status': 400}

    if path != '/' and path.endswith('/'):
        return {'error': _('Path should NOT ends with "/"'), 'status': 400}

    try:
        user = User.objects.get(email = to_user)
    except User.DoesNotExist:
        user = None

    if user is None:
        return {'error': _('Invalid username, should be a user already registered'), 'status': 400}

    return {'success': True}
Example #20
0
    def format_file_uploaded_msg(self):
        """
        
        Arguments:
        - `self`:
        """
        d = json.loads(self.detail)
        filename = d['file_name']
        repo_id = d['repo_id']
        if d['uploaded_to'] == '/':
            # current upload path is '/'
            file_path = '/' + filename
            link = reverse('view_common_lib_dir', args=[repo_id, ''])
            name = seafile_api.get_repo(repo_id).name
        else:
            uploaded_to = d['uploaded_to'].rstrip('/')
            file_path = uploaded_to + '/' + filename
            link = reverse('view_common_lib_dir', args=[repo_id, urlquote(uploaded_to.lstrip('/'))])
            name = os.path.basename(uploaded_to)

        file_link = reverse('view_lib_file', args=[repo_id, urlquote(file_path)])

        msg = _(u"A file named <a href='%(file_link)s'>%(file_name)s</a> is uploaded to <a href='%(link)s'>%(name)s</a>") % {
            'file_link': file_link,
            'file_name': escape(filename),
            'link': link,
            'name': escape(name),
            }
        return msg
Example #21
0
    def setUp(self):

        self.login_as(self.admin)

        # create group for admin user
        self.admin_group_1_name = randstring(6)
        self.admin_group_1_id = ccnet_threaded_rpc.create_group(self.admin_group_1_name,
                self.admin.email)

        # create another group for admin user
        self.admin_group_2_name = randstring(6)
        self.admin_group_2_id = ccnet_threaded_rpc.create_group(self.admin_group_2_name,
                self.admin.email)

        # create repo for admin user
        self.admin_repo_name = randstring(6)
        r = seafile_api.get_repo(self.create_repo(name=self.admin_repo_name,
            desc='', username=self.admin.email, passwd=None))
        self.admin_repo_id = r.id

        # set common user as staff in admin user's group
        ccnet_threaded_rpc.group_add_member(self.admin_group_1_id,
                self.admin.email, self.user.email)
        ccnet_threaded_rpc.group_set_admin(self.admin_group_1_id, self.user.email)

        # add common user to admin user's another group
        ccnet_threaded_rpc.group_add_member(self.admin_group_2_id,
                self.admin.email, self.user.email)

        # share admin user's repo to common user
        seafile_api.share_repo(self.admin_repo_id, self.admin.email,
                               self.user.email, 'rw')
Example #22
0
def get_file_revisions_after_renamed(repo_id, path):
    all_file_revisions = []
    repo = seafile_api.get_repo(repo_id)
    commit_id = repo.head_cmmt_id

    start_time = time.time()
    keep_on_search = True
    while keep_on_search:
        file_revisions = seafile_api.get_file_revisions(repo_id,
                commit_id, path, 50)

        all_file_revisions += file_revisions[0:-1]

        end_time = time.time()
        next_start_commit = file_revisions[-1].next_start_commit
        rev_renamed_old_path = file_revisions[-2].rev_renamed_old_path if \
                len(file_revisions) > 1 else None

        if not next_start_commit or \
                rev_renamed_old_path  or \
                end_time - start_time > GET_FILE_HISTORY_TIMEOUT:
            # have searched all commits or
            # found a file renamed/moved commit or
            # timeout
            keep_on_search = False
        else:
            # keep on searching, use next_start_commit
            # as the commit_id start to search
            commit_id = next_start_commit

    return all_file_revisions
Example #23
0
    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)
Example #24
0
    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})
Example #25
0
    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})
Example #26
0
    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)
Example #27
0
    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})
Example #28
0
    def repo_restored_cb(sender, **kwargs):
        repo_id = kwargs['repo_id']
        operator = kwargs['operator']
        repo = seafile_api.get_repo(repo_id)
        org_id = get_org_id_by_repo_id(repo_id)
        if org_id > 0:
            related_users = seafile_api.org_get_shared_users_by_repo(org_id, repo_id)
            repo_owner = seafile_api.get_org_repo_owner(repo_id)
        else:
            related_users = seafile_api.get_shared_users_by_repo(repo_id)
            repo_owner = seafile_api.get_repo_owner(repo_id)

        related_users.append(repo_owner)

        record = {
            'op_type':'recover',
            'obj_type':'repo',
            'timestamp': datetime.datetime.utcnow(),
            'repo_id': repo_id,
            'repo_name': repo.repo_name,
            'path': '/',
            'op_user': operator,
            'related_users': [related_users],
            'org_id': org_id,
        }

        from utils import SeafEventsSession
        session = SeafEventsSession()
        seafevents.save_user_activity(session, record)
        session.close()
Example #29
0
def get_all_file_revisions(repo_id, path, commit_id=None):
    """ Only used for test revert file.

    py.test tests/api/endpoints/test_file_view.py::FileViewTest::test_can_revert_file
    """

    all_file_revisions = []

    if not commit_id:
        repo = seafile_api.get_repo(repo_id)
        commit_id = repo.head_cmmt_id

    file_revisions = seafile_api.get_file_revisions(repo_id,
            commit_id, path, -1)
    all_file_revisions += file_revisions

    # if commit's rev_renamed_old_path value not None, seafile will stop searching.
    # so always uses `rev_renamed_old_path` info.
    next_start_commit = file_revisions[-1].next_start_commit
    if next_start_commit:
        path = file_revisions[-2].rev_renamed_old_path if \
                len(file_revisions) > 1 else None
        file_revisions = get_all_file_revisions(repo_id, path,
                next_start_commit)
        all_file_revisions += file_revisions

    # from seafile_api:
    # @next_start_commit: commit_id for next page.
    # An extra commit which only contains @next_start_commit will be appended to the list.
    return all_file_revisions[0:-1]
Example #30
0
    def get_file_info(self, username, repo_id, file_path):

        repo = seafile_api.get_repo(repo_id)
        file_obj = seafile_api.get_dirent_by_path(repo_id, file_path)
        file_name = file_obj.obj_name
        file_size = file_obj.size

        can_preview, error_msg = can_preview_file(file_name, file_size, repo)
        can_edit, error_msg  = can_edit_file(file_name, file_size, repo)

        try:
            is_locked, locked_by_me = check_file_lock(repo_id, file_path, username)
        except Exception as e:
            logger.error(e)
            is_locked = False

        file_info = {
            'type': 'file',
            'repo_id': repo_id,
            'parent_dir': os.path.dirname(file_path),
            'obj_name': file_name,
            'obj_id': file_obj.obj_id,
            'size': file_size,
            'mtime': timestamp_to_isoformat_timestr(file_obj.mtime),
            'is_locked': is_locked,
            'can_preview': can_preview,
            'can_edit': can_edit,
        }

        return file_info
Example #31
0
    def post(self, request):
        """ Create share link.

        Permission checking:
        1. default(NOT guest) user;
        """

        # argument check
        repo_id = request.data.get('repo_id', None)
        if not repo_id:
            error_msg = 'repo_id invalid.'
            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        path = request.data.get('path', None)
        if not path:
            error_msg = 'path invalid.'
            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        password = request.data.get('password', None)
        if password and len(password) < config.SHARE_LINK_PASSWORD_MIN_LENGTH:
            error_msg = _('Password is too short.')
            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        try:
            expire_days = int(request.data.get('expire_days', 0))
        except ValueError:
            error_msg = 'expire_days invalid.'
            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        if expire_days <= 0:
            if SHARE_LINK_EXPIRE_DAYS_DEFAULT > 0:
                expire_days = SHARE_LINK_EXPIRE_DAYS_DEFAULT

        if SHARE_LINK_EXPIRE_DAYS_MIN > 0:
            if expire_days < SHARE_LINK_EXPIRE_DAYS_MIN:
                error_msg = _('Expire days should be greater or equal to %s') % \
                        SHARE_LINK_EXPIRE_DAYS_MIN
                return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        if SHARE_LINK_EXPIRE_DAYS_MAX > 0:
            if expire_days > SHARE_LINK_EXPIRE_DAYS_MAX:
                error_msg = _('Expire days should be less than or equal to %s') % \
                        SHARE_LINK_EXPIRE_DAYS_MAX
                return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        if expire_days <= 0:
            expire_date = None
        else:
            expire_date = timezone.now() + relativedelta(days=expire_days)

        try:
            perm = check_permissions_arg(request)
        except Exception:
            error_msg = 'permissions 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 path != '/':
            dirent = seafile_api.get_dirent_by_path(repo_id, path)
            if not dirent:
                error_msg = 'Dirent %s not found.' % path
                return api_error(status.HTTP_404_NOT_FOUND, error_msg)

        # permission check
        if repo.encrypted:
            error_msg = 'Permission denied.'
            return api_error(status.HTTP_403_FORBIDDEN, error_msg)

        username = request.user.username
        repo_folder_permission = seafile_api.check_permission_by_path(
            repo_id, path, username)
        if parse_repo_perm(
                repo_folder_permission).can_generate_share_link is False:
            error_msg = 'Permission denied.'
            return api_error(status.HTTP_403_FORBIDDEN, error_msg)

        if repo_folder_permission in (PERMISSION_PREVIEW_EDIT, PERMISSION_PREVIEW) \
                and perm != FileShare.PERM_VIEW_ONLY:
            error_msg = 'Permission denied.'
            return api_error(status.HTTP_403_FORBIDDEN, error_msg)

        if repo_folder_permission in (PERMISSION_READ) \
                and perm not in (FileShare.PERM_VIEW_DL, FileShare.PERM_VIEW_ONLY):
            error_msg = 'Permission denied.'
            return api_error(status.HTTP_403_FORBIDDEN, error_msg)

        if path != '/':
            s_type = 'd' if stat.S_ISDIR(dirent.mode) else 'f'
            if s_type == 'f':
                file_name = os.path.basename(path.rstrip('/'))
                can_edit, error_msg = can_edit_file(file_name, dirent.size,
                                                    repo)
                if not can_edit and perm in (FileShare.PERM_EDIT_DL,
                                             FileShare.PERM_EDIT_ONLY):
                    error_msg = 'Permission denied.'
                    return api_error(status.HTTP_403_FORBIDDEN, error_msg)
        else:
            s_type = 'd'

        # create share link
        org_id = request.user.org.org_id if is_org_context(request) else None
        if s_type == 'f':
            fs = FileShare.objects.get_file_link_by_path(
                username, repo_id, path)
            if fs:
                error_msg = _('Share link %s already exists.' % fs.token)
                return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
            fs = FileShare.objects.create_file_link(username,
                                                    repo_id,
                                                    path,
                                                    password,
                                                    expire_date,
                                                    permission=perm,
                                                    org_id=org_id)

        elif s_type == 'd':
            fs = FileShare.objects.get_dir_link_by_path(
                username, repo_id, path)
            if fs:
                error_msg = _('Share link %s already exists.' % fs.token)
                return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
            fs = FileShare.objects.create_dir_link(username,
                                                   repo_id,
                                                   path,
                                                   password,
                                                   expire_date,
                                                   permission=perm,
                                                   org_id=org_id)

        link_info = get_share_link_info(fs)
        return Response(link_info)
Example #32
0
    def post(self, request, repo_id, format=None):
        """ Create, rename, move, copy file

        Permission checking:
        1. create: user with 'rw' permission for current parent dir;
        2. rename: user with 'rw' permission for current file;
        3. move  : user with 'rw' permission for current file, 'rw' permission for dst parent dir;
        4. copy  : user with 'r' permission for current file, 'rw' permission for dst parent dir;
        """

        # argument check
        path = request.GET.get('p', None)
        if not path or path[0] != '/':
            error_msg = 'p invalid.'
            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        operation = request.data.get('operation', None)
        if not operation:
            error_msg = 'operation invalid.'
            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        operation = operation.lower()
        if operation not in ('create', 'rename', 'move', 'copy'):
            error_msg = "operation can only be 'create', 'rename', 'move' or 'copy'."
            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)

        username = request.user.username
        parent_dir = os.path.dirname(path)

        if operation == 'create':
            # resource check
            try:
                parent_dir_id = seafile_api.get_dir_id_by_path(
                    repo_id, parent_dir)
            except SearpcError as e:
                logger.error(e)
                error_msg = 'Internal Server Error'
                return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR,
                                 error_msg)

            if not parent_dir_id:
                error_msg = 'Folder %s not found.' % parent_dir
                return api_error(status.HTTP_404_NOT_FOUND, error_msg)

            # permission check
            if check_folder_permission(request, repo_id, parent_dir) != 'rw':
                error_msg = 'Permission denied.'
                return api_error(status.HTTP_403_FORBIDDEN, error_msg)

            # create file
            new_file_name = os.path.basename(path)
            new_file_name = check_filename_with_rename(repo_id, parent_dir,
                                                       new_file_name)

            try:
                seafile_api.post_empty_file(repo_id, parent_dir, new_file_name,
                                            username)
            except SearpcError, e:
                logger.error(e)
                error_msg = 'Internal Server Error'
                return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR,
                                 error_msg)

            new_file_path = posixpath.join(parent_dir, new_file_name)
            file_info = self.get_file_info(username, repo_id, new_file_path)
            return Response(file_info)
Example #33
0
    def put(self, request, repo_id, format=None):
        """ transfer a library, rename 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_repo_name = request.data.get('name', None)
        if new_repo_name:
            try:
                res = seafile_api.edit_repo(repo_id, new_repo_name, '', None)
            except Exception as e:
                logger.error(e)
                error_msg = 'Internal Server Error'
                return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR,
                                 error_msg)

            if res == -1:
                e = 'Admin rename failed: ID of library is %s, edit_repo api called failed.' % \
                        repo_id
                logger.error(e)
                error_msg = 'Internal Server Error'
                return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR,
                                 error_msg)

        new_owner = request.data.get('owner', None)
        if new_owner:
            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 = _(u'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 seafile_api.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)

            if new_owner == repo_owner:
                error_msg = _(u"Library can not be transferred to owner.")
                return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

            # 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 is_group_member(shared_group_id, new_owner):
                    continue

                seafile_api.set_group_repo(repo_id, shared_group_id, new_owner,
                                           shared_group.perm)

            # reshare repo to links
            try:
                UploadLinkShare.objects.filter(
                    username=repo_owner,
                    repo_id=repo_id).update(username=new_owner)
                FileShare.objects.filter(
                    username=repo_owner,
                    repo_id=repo_id).update(username=new_owner)
            except Exception as e:
                logger.error(e)
                error_msg = 'Internal Server Error'
                return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR,
                                 error_msg)

            # 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

            # send admin operation log signal
            admin_op_detail = {
                "id": repo_id,
                "name": repo.name,
                "from": repo_owner,
                "to": new_owner,
            }
            admin_operation.send(sender=None,
                                 admin_name=request.user.username,
                                 operation=REPO_TRANSFER,
                                 detail=admin_op_detail)

        repo = seafile_api.get_repo(repo_id)
        repo_info = get_repo_info(repo)

        return Response(repo_info)
Example #34
0
    def delete(self, request, repo_id, format=None):
        """ delete a library

        Permission checking:
        1. only admin can perform this action.
        """
        if get_system_default_repo_id() == repo_id:
            error_msg = _('System library can not be deleted.')
            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        repo = seafile_api.get_repo(repo_id)
        if not repo:
            # for case of `seafile-data` has been damaged
            # no `repo object` will be returned from seafile api
            # delete the database record anyway
            try:
                seafile_api.remove_repo(repo_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})

        repo_name = repo.name
        repo_owner = seafile_api.get_repo_owner(repo_id)
        if not repo_owner:
            repo_owner = seafile_api.get_org_repo_owner(repo_id)

        try:
            seafile_api.remove_repo(repo_id)

            try:
                org_id = seafile_api.get_org_id_by_repo_id(repo_id)
                related_usernames = get_related_users_by_repo(
                    repo_id, org_id if org_id > 0 else None)
            except Exception as e:
                logger.error(e)
                org_id = -1
                related_usernames = []

            # send signal for seafevents
            repo_deleted.send(sender=None,
                              org_id=-1,
                              operator=request.user.username,
                              usernames=related_usernames,
                              repo_owner=repo_owner,
                              repo_id=repo_id,
                              repo_name=repo.name)

        except Exception 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": repo_id,
            "name": repo_name,
            "owner": repo_owner,
        }
        admin_operation.send(sender=None,
                             admin_name=request.user.username,
                             operation=REPO_DELETE,
                             detail=admin_op_detail)

        return Response({'success': True})
Example #35
0
def get_onlyoffice_dict(request,
                        username,
                        repo_id,
                        file_path,
                        file_id='',
                        can_edit=False,
                        can_download=True):

    repo = seafile_api.get_repo(repo_id)
    if repo.is_virtual:
        origin_repo_id = repo.origin_repo_id
        origin_file_path = posixpath.join(repo.origin_path,
                                          file_path.strip('/'))
        # for view history/trash/snapshot file
        if not file_id:
            file_id = seafile_api.get_file_id_by_path(origin_repo_id,
                                                      origin_file_path)
    else:
        origin_repo_id = repo_id
        origin_file_path = file_path
        if not file_id:
            file_id = seafile_api.get_file_id_by_path(repo_id, file_path)

    dl_token = seafile_api.get_fileserver_access_token(repo_id,
                                                       file_id,
                                                       'download',
                                                       username,
                                                       use_onetime=True)
    if not dl_token:
        return None

    filetype, fileext = get_file_type_and_ext(file_path)
    if fileext in ('xls', 'xlsx', 'ods', 'fods', 'csv'):
        document_type = 'spreadsheet'
    elif fileext in ('pptx', 'ppt', 'odp', 'fodp', 'ppsx', 'pps'):
        document_type = 'presentation'
    else:
        document_type = 'text'

    cache_key = generate_onlyoffice_cache_key(repo_id, file_path)
    doc_key = cache.get(cache_key)

    # temporary solution when failed to get data from cache(django_pylibmc)
    # when init process for the first time
    if not doc_key:
        doc_key = cache.get(cache_key)

    if not doc_key and if_locked_by_online_office(repo_id, file_path):
        logger.error('no doc_key in cache and locked by online office')

    if not doc_key:
        info_bytes = force_bytes(origin_repo_id + origin_file_path + file_id)
        doc_key = hashlib.md5(info_bytes).hexdigest()[:20]

    doc_info = json.dumps({
        'repo_id': repo_id,
        'file_path': file_path,
        'username': username
    })
    cache.set("ONLYOFFICE_%s" % doc_key, doc_info, None)

    file_name = os.path.basename(file_path.rstrip('/'))
    doc_url = gen_file_get_url(dl_token, file_name)

    base_url = get_site_scheme_and_netloc()
    onlyoffice_editor_callback_url = reverse('onlyoffice_editor_callback')
    callback_url = urllib.parse.urljoin(base_url,
                                        onlyoffice_editor_callback_url)

    return_dict = {
        'repo_id': repo_id,
        'path': file_path,
        'ONLYOFFICE_APIJS_URL': ONLYOFFICE_APIJS_URL,
        'file_type': fileext,
        'doc_key': doc_key,
        'doc_title': file_name,
        'doc_url': doc_url,
        'document_type': document_type,
        'callback_url': callback_url,
        'can_edit': can_edit,
        'can_download': can_download,
        'username': username,
        'onlyoffice_force_save': ONLYOFFICE_FORCE_SAVE,
        'enable_watermark': ENABLE_WATERMARK and not can_edit,
    }

    if ONLYOFFICE_JWT_SECRET:
        import jwt
        config = {
            "document": {
                "fileType": fileext,
                "key": doc_key,
                "title": file_name,
                "url": doc_url,
                "permissions": {
                    "download": can_download,
                    "edit": can_edit,
                    "print": can_download,
                    "review": True
                }
            },
            "documentType": document_type,
            "editorConfig": {
                "callbackUrl": callback_url,
                "lang": request.LANGUAGE_CODE,
                "mode": can_edit,
                "customization": {
                    "forcesave": ONLYOFFICE_FORCE_SAVE,
                },
                "user": {
                    "name": email2nickname(username)
                }
            }
        }

        return_dict['onlyoffice_jwt_token'] = jwt.encode(
            config, ONLYOFFICE_JWT_SECRET)

    return return_dict
Example #36
0
def edit_profile(request):
    """
    Show and edit user profile.
    """
    username = request.user.username
    form_class = DetailedProfileForm

    if request.method == 'POST':
        form = form_class(user=request.user, data=request.POST)
        if form.is_valid():
            form.save()
            messages.success(request, _('Successfully edited profile.'))

            return HttpResponseRedirect(reverse('edit_profile'))
        else:
            messages.error(request, _('Failed to edit profile'))
    else:
        profile = Profile.objects.get_profile_by_user(username)
        d_profile = DetailedProfile.objects.get_detailed_profile_by_user(
            username)

        init_dict = {}
        if profile:
            init_dict['nickname'] = profile.nickname
            init_dict['login_id'] = profile.login_id
            init_dict['contact_email'] = profile.contact_email
            init_dict['list_in_address_book'] = profile.list_in_address_book
        if d_profile:
            init_dict['department'] = d_profile.department
            init_dict['telephone'] = d_profile.telephone

        form = form_class(user=request.user, data=init_dict)

    # common logic
    try:
        server_crypto = UserOptions.objects.is_server_crypto(username)
    except CryptoOptionNotSetError:
        # Assume server_crypto is ``False`` if this option is not set.
        server_crypto = False

    sub_lib_enabled = UserOptions.objects.is_sub_lib_enabled(username)

    default_repo_id = UserOptions.objects.get_default_repo(username)
    if default_repo_id:
        default_repo = seafile_api.get_repo(default_repo_id)
    else:
        default_repo = None

    owned_repos = get_owned_repo_list(request)
    owned_repos = [r for r in owned_repos if not r.is_virtual]

    if settings.ENABLE_WEBDAV_SECRET:
        decoded = UserOptions.objects.get_webdav_decoded_secret(username)
        webdav_passwd = decoded if decoded else ''
    else:
        webdav_passwd = ''

    email_inverval = UserOptions.objects.get_file_updates_email_interval(username)
    email_inverval = email_inverval if email_inverval is not None else 0

    if work_weixin_oauth_check():
        enable_wechat_work = True

        from seahub.auth.models import SocialAuthUser
        from seahub.work_weixin.settings import WORK_WEIXIN_PROVIDER
        social_connected = SocialAuthUser.objects.filter(
            username=request.user.username, provider=WORK_WEIXIN_PROVIDER).count() > 0
    else:
        enable_wechat_work = False
        social_connected = False

    if ENABLE_DINGTALK:
        enable_dingtalk = True
        from seahub.auth.models import SocialAuthUser
        social_connected_dingtalk = SocialAuthUser.objects.filter(
            username=request.user.username, provider='dingtalk').count() > 0
    else:
        enable_dingtalk = False
        social_connected_dingtalk = False

    resp_dict = {
            'form': form,
            'server_crypto': server_crypto,
            "sub_lib_enabled": sub_lib_enabled,
            'ENABLE_ADDRESSBOOK_OPT_IN': settings.ENABLE_ADDRESSBOOK_OPT_IN,
            'default_repo': default_repo,
            'owned_repos': owned_repos,
            'is_pro': is_pro_version(),
            'is_ldap_user': is_ldap_user(request.user),
            'two_factor_auth_enabled': has_two_factor_auth(),
            'ENABLE_CHANGE_PASSWORD': settings.ENABLE_CHANGE_PASSWORD,
            'ENABLE_WEBDAV_SECRET': settings.ENABLE_WEBDAV_SECRET,
            'ENABLE_DELETE_ACCOUNT': ENABLE_DELETE_ACCOUNT,
            'ENABLE_UPDATE_USER_INFO': ENABLE_UPDATE_USER_INFO,
            'webdav_passwd': webdav_passwd,
            'email_notification_interval': email_inverval,
            'social_next_page': reverse('edit_profile'),
            'enable_wechat_work': enable_wechat_work,
            'social_connected': social_connected,
            'enable_dingtalk': enable_dingtalk,
            'social_connected_dingtalk': social_connected_dingtalk,
            'ENABLE_USER_SET_CONTACT_EMAIL': settings.ENABLE_USER_SET_CONTACT_EMAIL,
            'user_unusable_password': request.user.enc_password == UNUSABLE_PASSWORD,
    }

    if has_two_factor_auth():
        from seahub.two_factor.models import StaticDevice, default_device

        try:
            backup_tokens = StaticDevice.objects.get(
                user=request.user.username).token_set.count()
        except StaticDevice.DoesNotExist:
            backup_tokens = 0

        resp_dict['default_device'] = default_device(request.user)
        resp_dict['backup_tokens'] = backup_tokens

    #template = 'profile/set_profile.html'
    template = 'profile/set_profile_react.html'
    return render(request, template, resp_dict)
Example #37
0
def share_repo(request):
    """
    Handle POST method to share a repo to public/groups/users based on form
    data. Return to ``myhome`` page and notify user whether success or failure. 
    """
    next = request.META.get('HTTP_REFERER', None)
    if not next:
        next = SITE_ROOT

    form = RepoShareForm(request.POST)
    if not form.is_valid():
        # TODO: may display error msg on form
        raise Http404

    email_or_group = form.cleaned_data['email_or_group']
    repo_id = form.cleaned_data['repo_id']
    permission = form.cleaned_data['permission']
    from_email = request.user.username

    repo = seafile_api.get_repo(repo_id)
    if not repo:
        raise Http404

    # Test whether user is the repo owner.
    if not validate_owner(request, repo_id):
        msg = _(u'Only the owner of the library has permission to share it.')
        messages.error(request, msg)
        return HttpResponseRedirect(next)

    # Parsing input values.
    share_to_list = string2list(email_or_group)
    share_to_all, share_to_group_names, share_to_users = False, [], []
    for share_to in share_to_list:
        if share_to == 'all':
            share_to_all = True
        elif share_to.find('@') == -1:
            share_to_group_names.append(share_to)
        else:
            share_to = share_to.lower()
            if is_valid_username(share_to):
                share_to_users.append(share_to)

    share_to_groups = []
    # get all personal groups
    for group in request.user.joined_groups:
        # for every group that user joined, if group name matchs,
        # then has find the group
        if group.group_name in share_to_group_names:
            share_to_groups.append(group)

    if share_to_all and not CLOUD_MODE:
        share_to_public(request, repo, permission)

    if not check_user_share_quota(
            from_email, repo, users=share_to_users, groups=share_to_groups):
        messages.error(
            request,
            _('Failed to share "%s", no enough quota. <a href="http://seafile.com/">Upgrade account.</a>'
              ) % repo.name)
        return HttpResponseRedirect(next)

    for group in share_to_groups:
        share_to_group(request, repo, from_email, group, permission)

    for email in share_to_users:
        # Add email to contacts.
        mail_sended.send(sender=None, user=request.user.username, email=email)
        share_to_user(request, repo, from_email, email, permission)

    return HttpResponseRedirect(next)
Example #38
0
    def get(self, request, repo_id, format=None):
        """ Return history of library

        Permission checking:
        1. all authenticated user can perform this action.
        """

        # resource check
        repo = seafile_api.get_repo(repo_id)
        if not repo:
            error_msg = 'Library %s not found.' % repo_id
            return api_error(status.HTTP_404_NOT_FOUND, error_msg)

        # permission check
        if check_folder_permission(request, repo_id, '/') is None:
            error_msg = 'Permission denied.'
            return api_error(status.HTTP_403_FORBIDDEN, error_msg)

        username = request.user.username
        try:
            server_crypto = UserOptions.objects.is_server_crypto(username)
        except CryptoOptionNotSetError:
            # Assume server_crypto is ``False`` if this option is not set.
            server_crypto = False

        password_set = False
        if repo.encrypted and \
                (repo.enc_version == 1 or (repo.enc_version == 2 and server_crypto)):
            try:
                ret = seafile_api.is_password_set(repo_id, username)
                if ret == 1:
                    password_set = True
            except Exception as e:
                logger.error(e)
                error_msg = 'Internal Server Error'
                return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)

            if not password_set:
                error_msg = 'Library is encrypted, but password is not set in server.'
                return api_error(status.HTTP_403_FORBIDDEN, error_msg)

        try:
            page = int(request.GET.get('page', '1'))
            per_page = int(request.GET.get('per_page', '100'))
        except ValueError:
            page = 1
            per_page = 100

        if page <= 0:
            error_msg = 'page invalid.'
            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        if per_page <= 0:
            error_msg = 'per_page invalid.'
            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        start = (page - 1) * per_page
        limit = per_page + 1

        try:
            all_commits = seafile_api.get_commit_list(repo_id, start, limit)
        except Exception as e:
            logger.error(e)
            error_msg = 'Internal Server Error'
            return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)

        items = []
        commits = all_commits[:per_page]
        for commit in commits:
            if new_merge_with_no_conflict(commit):
                continue

            item_info = self.get_item_info(commit)
            items.append(item_info)

        commit_tag_dict = {}
        if ENABLE_REPO_SNAPSHOT_LABEL:
            try:
                revision_tags = RevisionTags.objects.filter(repo_id=repo_id)
            except Exception as e:
                logger.error(e)
                revision_tags = []

            for tag in revision_tags:
                if tag.revision_id in commit_tag_dict:
                    commit_tag_dict[tag.revision_id].append(tag.tag.name)
                else:
                    commit_tag_dict[tag.revision_id] = [tag.tag.name]

        for item in items:
            item['tags'] = []
            for commit_id, tags in list(commit_tag_dict.items()):
                if commit_id == item['commit_id']:
                    item['tags'] = tags

        result = {
            'data': items,
            'more': True if len(all_commits) == per_page + 1 else False
        }

        return Response(result)
Example #39
0
def convert_repo_path_when_can_not_view_folder(request, repo_id, path):

    content_type = 'application/json; charset=utf-8'

    path = normalize_dir_path(path)
    username = request.user.username
    converted_repo_path = seafile_api.convert_repo_path(
        repo_id, path, username)
    if not converted_repo_path:
        err_msg = _('Permission denied.')
        return HttpResponse(json.dumps({'error': err_msg}),
                            status=403,
                            content_type=content_type)

    converted_repo_path = json.loads(converted_repo_path)

    repo_id = converted_repo_path['repo_id']
    repo = seafile_api.get_repo(repo_id)
    if not repo:
        err_msg = 'Library not found.'
        return HttpResponse(json.dumps({'error': err_msg}),
                            status=404,
                            content_type=content_type)

    path = converted_repo_path['path']
    path = normalize_dir_path(path)
    dir_id = seafile_api.get_dir_id_by_path(repo.id, path)
    if not dir_id:
        err_msg = 'Folder not found.'
        return HttpResponse(json.dumps({'error': err_msg}),
                            status=404,
                            content_type=content_type)

    group_id = ''
    if 'group_id' in converted_repo_path:
        group_id = converted_repo_path['group_id']
        if not ccnet_api.get_group(group_id):
            err_msg = 'Group not found.'
            return HttpResponse(json.dumps({'error': err_msg}),
                                status=404,
                                content_type=content_type)

        if not is_group_member(group_id, username):
            err_msg = _('Permission denied.')
            return HttpResponse(json.dumps({'error': err_msg}),
                                status=403,
                                content_type=content_type)

    user_perm = check_folder_permission(request, repo_id, path)
    if not user_perm:
        err_msg = _('Permission denied.')
        return HttpResponse(json.dumps({'error': err_msg}),
                            status=403,
                            content_type=content_type)

    if not group_id:
        next_url = '#shared-libs/lib/%s/%s' % (repo_id, path.strip('/'))
    else:
        next_url = '#group/%s/lib/%s/%s' % (group_id, repo_id, path.strip('/'))

    return HttpResponse(json.dumps({'next_url': next_url}),
                        content_type=content_type)
Example #40
0
class FileView(APIView):
    """
    Support uniform interface for file related operations,
    including create/delete/rename/view, etc.
    """

    authentication_classes = (TokenAuthentication, SessionAuthentication)
    permission_classes = (IsAuthenticated, )
    throttle_classes = (UserRateThrottle, )

    def get_file_info(self, username, repo_id, file_path):

        file_obj = seafile_api.get_dirent_by_path(repo_id, file_path)
        is_locked, locked_by_me = check_file_lock(repo_id, file_path, username)
        file_info = {
            'type': 'file',
            'repo_id': repo_id,
            'parent_dir': os.path.dirname(file_path),
            'obj_name': file_obj.obj_name,
            'obj_id': file_obj.obj_id,
            'size': file_obj.size,
            'mtime': timestamp_to_isoformat_timestr(file_obj.mtime),
            'is_locked': is_locked,
        }

        return file_info

    def get(self, request, repo_id, format=None):
        """ Get file info.

        Permission checking:
        1. user with either 'r' or 'rw' permission.
        """

        # argument check
        path = request.GET.get('p', None)
        if not path:
            error_msg = 'p 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)

        try:
            file_id = seafile_api.get_file_id_by_path(repo_id, path)
        except SearpcError as e:
            logger.error(e)
            error_msg = 'Internal Server Error'
            return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)

        if not file_id:
            error_msg = 'File %s not found.' % path
            return api_error(status.HTTP_404_NOT_FOUND, error_msg)

        # permission check
        parent_dir = os.path.dirname(path)
        if check_folder_permission(request, repo_id, parent_dir) is None:
            error_msg = 'Permission denied.'
            return api_error(status.HTTP_403_FORBIDDEN, error_msg)

        file_info = self.get_file_info(request.user.username, repo_id, path)
        return Response(file_info)

    def post(self, request, repo_id, format=None):
        """ Create, rename, move, copy file

        Permission checking:
        1. create: user with 'rw' permission for current parent dir;
        2. rename: user with 'rw' permission for current file;
        3. move  : user with 'rw' permission for current file, 'rw' permission for dst parent dir;
        4. copy  : user with 'r' permission for current file, 'rw' permission for dst parent dir;
        """

        # argument check
        path = request.GET.get('p', None)
        if not path or path[0] != '/':
            error_msg = 'p invalid.'
            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        operation = request.data.get('operation', None)
        if not operation:
            error_msg = 'operation invalid.'
            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        operation = operation.lower()
        if operation not in ('create', 'rename', 'move', 'copy'):
            error_msg = "operation can only be 'create', 'rename', 'move' or 'copy'."
            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)

        username = request.user.username
        parent_dir = os.path.dirname(path)

        if operation == 'create':
            # resource check
            try:
                parent_dir_id = seafile_api.get_dir_id_by_path(
                    repo_id, parent_dir)
            except SearpcError as e:
                logger.error(e)
                error_msg = 'Internal Server Error'
                return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR,
                                 error_msg)

            if not parent_dir_id:
                error_msg = 'Folder %s not found.' % parent_dir
                return api_error(status.HTTP_404_NOT_FOUND, error_msg)

            # permission check
            if check_folder_permission(request, repo_id, parent_dir) != 'rw':
                error_msg = 'Permission denied.'
                return api_error(status.HTTP_403_FORBIDDEN, error_msg)

            # create file
            new_file_name = os.path.basename(path)
            new_file_name = check_filename_with_rename(repo_id, parent_dir,
                                                       new_file_name)

            try:
                seafile_api.post_empty_file(repo_id, parent_dir, new_file_name,
                                            username)
            except SearpcError, e:
                logger.error(e)
                error_msg = 'Internal Server Error'
                return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR,
                                 error_msg)

            new_file_path = posixpath.join(parent_dir, new_file_name)
            file_info = self.get_file_info(username, repo_id, new_file_path)
            return Response(file_info)

        if operation == 'rename':
            # argument check
            new_file_name = request.data.get('newname', None)
            if not new_file_name:
                error_msg = 'newname invalid.'
                return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

            if len(new_file_name) > MAX_UPLOAD_FILE_NAME_LEN:
                error_msg = 'newname is too long.'
                return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

            oldname = os.path.basename(path)
            if oldname == new_file_name:
                error_msg = 'The new name is the same to the old'
                return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

            # resource check
            try:
                file_id = seafile_api.get_file_id_by_path(repo_id, path)
            except SearpcError as e:
                logger.error(e)
                error_msg = 'Internal Server Error'
                return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR,
                                 error_msg)

            if not file_id:
                error_msg = 'File %s not found.' % path
                return api_error(status.HTTP_404_NOT_FOUND, error_msg)

            # permission check
            if check_folder_permission(request, repo_id, parent_dir) != 'rw':
                error_msg = 'Permission denied.'
                return api_error(status.HTTP_403_FORBIDDEN, error_msg)

            # rename file
            new_file_name = check_filename_with_rename(repo_id, parent_dir,
                                                       new_file_name)
            try:
                seafile_api.rename_file(repo_id, parent_dir, oldname,
                                        new_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)

            new_file_path = posixpath.join(parent_dir, new_file_name)
            file_info = self.get_file_info(username, repo_id, new_file_path)
            return Response(file_info)

        if operation == 'move':
            # argument check
            dst_repo_id = request.data.get('dst_repo', None)
            dst_dir = request.data.get('dst_dir', None)
            if not dst_repo_id:
                error_msg = 'dst_repo invalid.'
                return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

            if not dst_dir:
                error_msg = 'dst_dir invalid.'
                return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

            # resource check for source file
            try:
                file_id = seafile_api.get_file_id_by_path(repo_id, path)
            except SearpcError as e:
                logger.error(e)
                error_msg = 'Internal Server Error'
                return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR,
                                 error_msg)

            if not file_id:
                error_msg = 'File %s not found.' % path
                return api_error(status.HTTP_404_NOT_FOUND, error_msg)

            # resource check for dst repo and dir
            dst_repo = seafile_api.get_repo(dst_repo_id)
            if not dst_repo:
                error_msg = 'Library %s not found.' % dst_repo_id
                return api_error(status.HTTP_404_NOT_FOUND, error_msg)

            dst_dir_id = seafile_api.get_dir_id_by_path(dst_repo_id, dst_dir)
            if not dst_dir_id:
                error_msg = 'Folder %s not found.' % dst_dir
                return api_error(status.HTTP_404_NOT_FOUND, error_msg)

            # permission check for source file
            src_repo_id = repo_id
            src_dir = os.path.dirname(path)
            if check_folder_permission(request, src_repo_id, src_dir) != 'rw':
                error_msg = 'Permission denied.'
                return api_error(status.HTTP_403_FORBIDDEN, error_msg)

            # permission check for dst dir
            if check_folder_permission(request, dst_repo_id, dst_dir) != 'rw':
                error_msg = 'Permission denied.'
                return api_error(status.HTTP_403_FORBIDDEN, error_msg)

            # move file
            if dst_dir[
                    -1] != '/':  # Append '/' to the end of directory if necessary
                dst_dir += '/'

            if src_repo_id == dst_repo_id and src_dir == dst_dir:
                file_info = self.get_file_info(username, repo_id, path)
                return Response(file_info)

            filename = os.path.basename(path)
            new_file_name = check_filename_with_rename(dst_repo_id, dst_dir,
                                                       filename)
            try:
                seafile_api.move_file(src_repo_id,
                                      src_dir,
                                      filename,
                                      dst_repo_id,
                                      dst_dir,
                                      new_file_name,
                                      replace=False,
                                      username=username,
                                      need_progress=0,
                                      synchronous=1)
            except SearpcError as e:
                logger.error(e)
                error_msg = 'Internal Server Error'
                return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR,
                                 error_msg)

            dst_file_path = posixpath.join(dst_dir, new_file_name)
            dst_file_info = self.get_file_info(username, dst_repo_id,
                                               dst_file_path)
            return Response(dst_file_info)

        if operation == 'copy':
            # argument check
            dst_repo_id = request.data.get('dst_repo', None)
            dst_dir = request.data.get('dst_dir', None)
            if not dst_repo_id:
                error_msg = 'dst_repo_id invalid.'
                return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

            if not dst_dir:
                error_msg = 'dst_dir invalid.'
                return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

            # resource check for source file
            try:
                file_id = seafile_api.get_file_id_by_path(repo_id, path)
            except SearpcError as e:
                logger.error(e)
                error_msg = 'Internal Server Error'
                return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR,
                                 error_msg)

            if not file_id:
                error_msg = 'File %s not found.' % path
                return api_error(status.HTTP_404_NOT_FOUND, error_msg)

            # resource check for dst repo and dir
            dst_repo = seafile_api.get_repo(dst_repo_id)
            if not dst_repo:
                error_msg = 'Library %s not found.' % dst_repo_id
                return api_error(status.HTTP_404_NOT_FOUND, error_msg)

            dst_dir_id = seafile_api.get_dir_id_by_path(dst_repo_id, dst_dir)
            if not dst_dir_id:
                error_msg = 'Folder %s not found.' % dst_dir
                return api_error(status.HTTP_404_NOT_FOUND, error_msg)

            # permission check for source file
            src_repo_id = repo_id
            src_dir = os.path.dirname(path)
            if not check_folder_permission(request, src_repo_id, src_dir):
                error_msg = 'Permission denied.'
                return api_error(status.HTTP_403_FORBIDDEN, error_msg)

            # permission check for dst dir
            if check_folder_permission(request, dst_repo_id, dst_dir) != 'rw':
                error_msg = 'Permission denied.'
                return api_error(status.HTTP_403_FORBIDDEN, error_msg)

            # copy file
            if dst_dir[
                    -1] != '/':  # Append '/' to the end of directory if necessary
                dst_dir += '/'

            if src_repo_id == dst_repo_id and src_dir == dst_dir:
                file_info = self.get_file_info(username, repo_id, path)
                return Response(file_info)

            filename = os.path.basename(path)
            new_file_name = check_filename_with_rename(dst_repo_id, dst_dir,
                                                       filename)
            try:
                seafile_api.copy_file(src_repo_id,
                                      src_dir,
                                      filename,
                                      dst_repo_id,
                                      dst_dir,
                                      new_file_name,
                                      username,
                                      0,
                                      synchronous=1)
            except SearpcError as e:
                logger.error(e)
                error_msg = 'Internal Server Error'
                return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR,
                                 error_msg)

            dst_file_path = posixpath.join(dst_dir, new_file_name)
            dst_file_info = self.get_file_info(username, dst_repo_id,
                                               dst_file_path)
            return Response(dst_file_info)
Example #41
0
    def get(self, request, token):
        """ Only used for get dirents in a folder share link.

        Permission checking:
        1, If enable SHARE_LINK_LOGIN_REQUIRED, user must have been authenticated.
        2, If enable ENABLE_SHARE_LINK_AUDIT, user must have been authenticated, or have been audited.
        3, If share link is encrypted, share link password must have been checked.
        """

        # argument check
        thumbnail_size = request.GET.get('thumbnail_size', 48)
        try:
            thumbnail_size = int(thumbnail_size)
        except ValueError:
            error_msg = 'thumbnail_size invalid.'
            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        # permission check

        # check if login required
        if SHARE_LINK_LOGIN_REQUIRED and \
                not request.user.is_authenticated():
            error_msg = 'Permission denied.'
            return api_error(status.HTTP_403_FORBIDDEN, error_msg)

        # check share link audit
        if is_pro_version() and ENABLE_SHARE_LINK_AUDIT and \
                not request.user.is_authenticated() and \
                not request.session.get('anonymous_email'):
            error_msg = 'Permission denied.'
            return api_error(status.HTTP_403_FORBIDDEN, error_msg)

        # resource check
        try:
            share_link = FileShare.objects.get(token=token)
        except FileShare.DoesNotExist:
            error_msg = 'Share link %s not found.' % token
            return api_error(status.HTTP_404_NOT_FOUND, error_msg)

        # check share link password
        if share_link.is_encrypted() and not check_share_link_access(
                request, token):
            error_msg = 'Permission denied.'
            return api_error(status.HTTP_403_FORBIDDEN, error_msg)

        if share_link.s_type != 'd':
            error_msg = 'Share link %s is not a folder share link.' % token
            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        repo_id = share_link.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)

        share_link_path = share_link.path
        request_path = request.GET.get('path', '/')
        if request_path == '/':
            path = share_link_path
        else:
            path = posixpath.join(share_link_path, request_path.strip('/'))

        path = normalize_dir_path(path)
        dir_id = seafile_api.get_dir_id_by_path(repo_id, path)
        if not dir_id:
            error_msg = 'Folder %s not found.' % request_path
            return api_error(status.HTTP_404_NOT_FOUND, error_msg)

        try:
            current_commit = seafile_api.get_commit_list(repo_id, 0, 1)[0]
            dirent_list = seafile_api.list_dir_by_commit_and_path(
                repo_id, current_commit.id, path, -1, -1)
        except Exception as e:
            logger.error(e)
            error_msg = 'Internal Server Error'
            return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)

        result = []
        for dirent in dirent_list:

            # don't return parent folder(share link path) info to user
            # so use request_path here
            dirent_path = posixpath.join(request_path, dirent.obj_name)

            dirent_info = {}
            dirent_info['size'] = dirent.size
            dirent_info['last_modified'] = timestamp_to_isoformat_timestr(
                dirent.mtime)

            if stat.S_ISDIR(dirent.mode):
                dirent_info['is_dir'] = True
                dirent_info['folder_path'] = normalize_dir_path(dirent_path)
                dirent_info['folder_name'] = dirent.obj_name
            else:
                dirent_info['is_dir'] = False
                dirent_info['file_path'] = normalize_file_path(dirent_path)
                dirent_info['file_name'] = dirent.obj_name

                file_type, file_ext = get_file_type_and_ext(dirent.obj_name)
                if file_type in (IMAGE, XMIND) or \
                        file_type == VIDEO and ENABLE_VIDEO_THUMBNAIL:

                    if os.path.exists(
                            os.path.join(THUMBNAIL_ROOT, str(thumbnail_size),
                                         dirent.obj_id)):
                        req_image_path = posixpath.join(
                            request_path, dirent.obj_name)
                        src = get_share_link_thumbnail_src(
                            token, thumbnail_size, req_image_path)
                        dirent_info['encoded_thumbnail_src'] = urlquote(src)

            result.append(dirent_info)

        return Response({'dirent_list': result})
Example #42
0
def get_repo(repo_id):
    return seafile_api.get_repo(repo_id)
Example #43
0
    def get(self, request):
        """get all workspaces
        """
        username = request.user.username

        org_id = -1
        if is_org_context(request):
            org_id = request.user.org.org_id

        if org_id > 0:
            groups = ccnet_api.get_org_groups_by_user(org_id, username)
        else:
            groups = ccnet_api.get_groups(username, return_ancestors=True)

        owner_list = list()
        owner_list.append(username)
        for group in groups:
            group_user = '******' % group.id
            owner_list.append(group_user)

        workspace_list = list()
        for owner in owner_list:
            try:
                workspace = Workspaces.objects.get_workspace_by_owner(owner)
            except Exception as e:
                logger.error(e)
                error_msg = 'Internal Server Error.'
                return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR,
                                 error_msg)

            if not workspace:
                if '@seafile_group' in owner:
                    continue

                # permission check
                if not request.user.permissions.can_add_repo():
                    error_msg = 'Permission denied.'
                    return api_error(status.HTTP_403_FORBIDDEN, error_msg)

                try:
                    if org_id > 0:
                        repo_id = seafile_api.create_org_repo(
                            _("My Workspace"), _("My Workspace"),
                            "dtable@seafile", org_id)
                    else:
                        repo_id = seafile_api.create_repo(
                            _("My Workspace"), _("My Workspace"),
                            "dtable@seafile")
                except Exception as e:
                    logger.error(e)
                    error_msg = 'Internal Server Error.'
                    return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR,
                                     error_msg)

                workspace = Workspaces.objects.create_workspace(owner, repo_id)

            # resource check
            repo_id = workspace.repo_id
            repo = seafile_api.get_repo(repo_id)
            if not repo:
                logger.warning('Library %s not found.' % repo_id)
                continue

            if '@seafile_group' in owner:
                group_id = int(owner.split('@')[0])
                owner_name = group_id_to_name(group_id)
                owner_type = "Group"
            else:
                owner_name = email2nickname(owner)
                owner_type = "Personal"

            table_list = DTables.objects.get_dtable_by_workspace(workspace)

            res = workspace.to_dict()
            res["owner_name"] = owner_name
            res["owner_type"] = owner_type
            res["table_list"] = table_list
            workspace_list.append(res)

        return Response({"workspace_list": workspace_list},
                        status=status.HTTP_200_OK)
Example #44
0
    def put(self, request, token):
        """ Update share link, currently only available for permission.

        Permission checking:
        share link creater
        """

        # argument check
        try:
            perm = check_permissions_arg(request)
        except Exception:
            error_msg = 'permissions invalud.'
            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        # resource check
        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)

        repo_id = fs.repo_id
        repo = seafile_api.get_repo(repo_id)
        if not repo_id:
            error_msg = 'Library %s not found.' % repo_id
            return api_error(status.HTTP_404_NOT_FOUND, error_msg)

        if fs.path != '/':
            dirent = seafile_api.get_dirent_by_path(repo_id, fs.path)
            if not dirent:
                error_msg = 'Dirent %s not found.' % repo_id
                return api_error(status.HTTP_404_NOT_FOUND, error_msg)

        # permission check
        username = request.user.username
        if not fs.is_owner(username):
            error_msg = 'Permission denied.'
            return api_error(status.HTTP_403_FORBIDDEN, error_msg)

        # get permission of origin repo/folder
        if fs.s_type == 'd':
            folder_path = normalize_dir_path(fs.path)
        else:
            file_path = normalize_file_path(fs.path)
            folder_path = os.path.dirname(file_path)

        username = request.user.username
        repo_folder_permission = seafile_api.check_permission_by_path(
            repo_id, folder_path, username)
        if not repo_folder_permission:
            error_msg = 'Permission denied.'
            return api_error(status.HTTP_403_FORBIDDEN, error_msg)

        if repo_folder_permission in (PERMISSION_PREVIEW_EDIT, PERMISSION_PREVIEW) \
                and perm != FileShare.PERM_VIEW_ONLY:
            error_msg = 'Permission denied.'
            return api_error(status.HTTP_403_FORBIDDEN, error_msg)

        if repo_folder_permission in (PERMISSION_READ) \
                and perm not in (FileShare.PERM_VIEW_DL, FileShare.PERM_VIEW_ONLY):
            error_msg = 'Permission denied.'
            return api_error(status.HTTP_403_FORBIDDEN, error_msg)

        if fs.s_type == 'f':
            file_name = os.path.basename(fs.path.rstrip('/'))
            can_edit, error_msg = can_edit_file(file_name, dirent.size, repo)
            if not can_edit and perm in (FileShare.PERM_EDIT_DL,
                                         FileShare.PERM_EDIT_ONLY):
                error_msg = 'Permission denied.'
                return api_error(status.HTTP_403_FORBIDDEN, error_msg)

        # update share link permission
        fs.permission = perm
        fs.save()

        link_info = get_share_link_info(fs)
        return Response(link_info)
Example #45
0
    def post(self, request):
        """ Create upload link.

        Permission checking:
        1. default(NOT guest) user;
        2. user with 'rw' permission;
        """

        # argument check
        repo_id = request.data.get('repo_id', None)
        if not repo_id:
            error_msg = 'repo_id invalid.'
            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        path = request.data.get('path', None)
        if not path:
            error_msg = 'path invalid.'
            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        password = request.data.get('password', None)
        if password and len(password) < config.SHARE_LINK_PASSWORD_MIN_LENGTH:
            error_msg = _('Password is too short')
            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        expire_days = request.data.get('expire_days', '')
        expiration_time = request.data.get('expiration_time', '')
        if expire_days and expiration_time:
            error_msg = 'Can not pass expire_days and expiration_time at the same time.'
            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        expire_date = None
        if expire_days:
            try:
                expire_days = int(expire_days)
            except ValueError:
                error_msg = 'expire_days invalid.'
                return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

            if expire_days <= 0:
                error_msg = 'expire_days invalid.'
                return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

            if UPLOAD_LINK_EXPIRE_DAYS_MIN > 0:
                if expire_days < UPLOAD_LINK_EXPIRE_DAYS_MIN:
                    error_msg = _('Expire days should be greater or equal to %s') % \
                            UPLOAD_LINK_EXPIRE_DAYS_MIN
                    return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

            if UPLOAD_LINK_EXPIRE_DAYS_MAX > 0:
                if expire_days > UPLOAD_LINK_EXPIRE_DAYS_MAX:
                    error_msg = _('Expire days should be less than or equal to %s') % \
                            UPLOAD_LINK_EXPIRE_DAYS_MAX
                    return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

            expire_date = timezone.now() + relativedelta(days=expire_days)

        elif expiration_time:

            try:
                expire_date = dateutil.parser.isoparse(expiration_time)
            except Exception as e:
                logger.error(e)
                error_msg = 'expiration_time invalid, should be iso format, for example: 2020-05-17T10:26:22+08:00'
                return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

            expire_date = expire_date.astimezone(
                get_current_timezone()).replace(tzinfo=None)

            if UPLOAD_LINK_EXPIRE_DAYS_MIN > 0:
                expire_date_min_limit = timezone.now() + relativedelta(
                    days=UPLOAD_LINK_EXPIRE_DAYS_MIN)
                expire_date_min_limit = expire_date_min_limit.replace(
                    hour=0).replace(minute=0).replace(second=0)

                if expire_date < expire_date_min_limit:
                    error_msg = _('Expiration time should be later than %s.') % \
                            expire_date_min_limit.strftime("%Y-%m-%d %H:%M:%S")
                    return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

            if UPLOAD_LINK_EXPIRE_DAYS_MAX > 0:
                expire_date_max_limit = timezone.now() + relativedelta(
                    days=UPLOAD_LINK_EXPIRE_DAYS_MAX)
                expire_date_max_limit = expire_date_max_limit.replace(
                    hour=23).replace(minute=59).replace(second=59)

                if expire_date > expire_date_max_limit:
                    error_msg = _('Expiration time should be earlier than %s.') % \
                            expire_date_max_limit.strftime("%Y-%m-%d %H:%M:%S")
                    return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        else:
            if UPLOAD_LINK_EXPIRE_DAYS_DEFAULT > 0:
                expire_date = timezone.now() + relativedelta(
                    days=UPLOAD_LINK_EXPIRE_DAYS_DEFAULT)

        # 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)

        try:
            dir_id = seafile_api.get_dir_id_by_path(repo_id, path)
        except SearpcError as e:
            logger.error(e)
            error_msg = 'Internal Server Error'
            return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)

        if not dir_id:
            error_msg = 'folder %s not found.' % path
            return api_error(status.HTTP_404_NOT_FOUND, error_msg)

        if check_folder_permission(request, repo_id, path) != 'rw':
            error_msg = 'Permission denied.'
            return api_error(status.HTTP_403_FORBIDDEN, error_msg)

        username = request.user.username
        uls = UploadLinkShare.objects.get_upload_link_by_path(
            username, repo_id, path)
        if not uls:
            uls = UploadLinkShare.objects.create_upload_link_share(
                username, repo_id, path, password, expire_date)

        link_info = get_upload_link_info(uls)
        return Response(link_info)
Example #46
0
    def delete(self, request, repo_id, format=None):
        """ Delete repo group folder perm.

        Permission checking:
        1. is group admin
        """

        # arguments check
        group_id = request.data.get('group_id', None)
        path = request.data.get('folder_path', None)

        if not group_id:
            error_msg = 'group_id invalid.'
            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        if not path:
            error_msg = 'folder_path invalid.'
            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        try:
            group_id = int(group_id)
        except ValueError:
            error_msg = 'group_id invalid.'
            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        # resource check
        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)

        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)
        library_group_id = get_group_id_by_repo_owner(repo_owner)
        if not ccnet_api.get_group(library_group_id):
            error_msg = 'Group %s not found.' % group_id
            return api_error(status.HTTP_404_NOT_FOUND, error_msg)

        # permission check
        username = request.user.username
        if not is_group_admin(library_group_id, username):
            error_msg = 'Permission denied.'
            return api_error(status.HTTP_403_FORBIDDEN, error_msg)

        # delete permission
        path = path.rstrip('/') if path != '/' else path
        permission = seafile_api.get_folder_group_perm(repo_id, path, group_id)
        if not permission:
            return Response({'success': True})

        try:
            seafile_api.rm_folder_group_perm(repo_id, path, group_id)
            send_perm_audit_msg('delete-repo-perm', username, group_id,
                                repo_id, path, permission)
            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)
Example #47
0
    def post(self, request, group_id):
        """ Add a group owned library.

        Permission checking:
        1. role permission, can_add_repo;
        1. is group admin;
        """

        # argument check
        repo_name = request.data.get("name", None)
        if not repo_name or \
                not is_valid_dirent_name(repo_name):
            error_msg = "name invalid."
            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        password = request.data.get("passwd", None)
        if password and not config.ENABLE_ENCRYPTED_LIBRARY:
            error_msg = 'NOT allow to create encrypted library.'
            return api_error(status.HTTP_403_FORBIDDEN, error_msg)

        permission = request.data.get('permission', PERMISSION_READ_WRITE)
        if permission not in [PERMISSION_READ, PERMISSION_READ_WRITE]:
            error_msg = 'permission invalid.'
            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        # permission check
        if not request.user.permissions.can_add_repo():
            error_msg = 'Permission denied.'
            return api_error(status.HTTP_403_FORBIDDEN, error_msg)

        if not is_group_admin(group_id, request.user.username):
            error_msg = 'Permission denied.'
            return api_error(status.HTTP_403_FORBIDDEN, error_msg)

        group_quota = seafile_api.get_group_quota(group_id)
        group_quota = int(group_quota)
        if group_quota <= 0 and group_quota != -2:
            error_msg = 'No group quota.'
            return api_error(status.HTTP_403_FORBIDDEN, error_msg)

        # create group owned repo
        group_id = int(group_id)
        if is_pro_version() and ENABLE_STORAGE_CLASSES:

            if STORAGE_CLASS_MAPPING_POLICY in ('USER_SELECT', 'ROLE_BASED'):

                storages = get_library_storages(request)
                storage_id = request.data.get("storage_id", None)
                if storage_id and storage_id not in [
                        s['storage_id'] for s in storages
                ]:
                    error_msg = 'storage_id invalid.'
                    return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

                repo_id = seafile_api.add_group_owned_repo(
                    group_id, repo_name, password, permission, storage_id)
            else:
                # STORAGE_CLASS_MAPPING_POLICY == 'REPO_ID_MAPPING'
                repo_id = seafile_api.add_group_owned_repo(
                    group_id, repo_name, password, permission)
        else:
            repo_id = seafile_api.add_group_owned_repo(group_id, repo_name,
                                                       password, permission)

        # for activities
        org_id = -1
        username = request.user.username
        library_template = request.data.get("library_template", '')
        repo_created.send(sender=None,
                          org_id=org_id,
                          creator=username,
                          repo_id=repo_id,
                          repo_name=repo_name,
                          library_template=library_template)

        # for notification
        repo = seafile_api.get_repo(repo_id)
        share_repo_to_group_successful.send(sender=None,
                                            from_user=username,
                                            group_id=group_id,
                                            repo=repo,
                                            path='/',
                                            org_id=org_id)

        info = get_group_owned_repo_info(request, repo_id)
        # TODO
        info['permission'] = permission
        return Response(info)
Example #48
0
    def get(self, request):
        """ Get all share links of a user.

        Permission checking:
        1. default(NOT guest) user;
        """

        username = request.user.username

        repo_id = request.GET.get('repo_id', '')
        path = request.GET.get('path', '')

        fileshares = []
        # get all share links of current user
        if not repo_id and not path:
            fileshares = FileShare.objects.filter(username=username)

        # share links in repo
        if repo_id and not 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)

            fileshares = FileShare.objects.filter(username=username) \
                                          .filter(repo_id=repo_id)

        # share links by repo and path
        if repo_id and 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)

            if path != '/':
                dirent = seafile_api.get_dirent_by_path(repo_id, path)
                if not dirent:
                    error_msg = 'Dirent %s not found.' % path
                    return api_error(status.HTTP_404_NOT_FOUND, error_msg)

                if stat.S_ISDIR(dirent.mode):
                    path = normalize_dir_path(path)
                else:
                    path = normalize_file_path(path)

            fileshares = FileShare.objects.filter(username=username) \
                                          .filter(repo_id=repo_id) \
                                          .filter(path=path)

        repo_folder_permission_dict = {}
        for fileshare in fileshares:

            if fileshare.s_type == 'd':
                folder_path = normalize_dir_path(fileshare.path)
            else:
                file_path = normalize_file_path(fileshare.path)
                folder_path = os.path.dirname(file_path)

            repo_id = fileshare.repo_id
            if repo_id not in repo_folder_permission_dict:
                permission = seafile_api.check_permission_by_path(
                    repo_id, folder_path, fileshare.username)
                repo_folder_permission_dict[repo_id] = permission

        links_info = []
        for fs in fileshares:
            link_info = get_share_link_info(fs)
            link_info['repo_folder_permission'] = \
                    repo_folder_permission_dict.get(link_info['repo_id'], '')
            links_info.append(link_info)

        if len(links_info) == 1:
            result = links_info
        else:
            dir_list = [x for x in links_info if x['is_dir']]
            file_list = [x for x in links_info if not x['is_dir']]

            dir_list.sort(key=lambda x: x['obj_name'])
            file_list.sort(key=lambda x: x['obj_name'])

            result = dir_list + file_list

        return Response(result)
Example #49
0
def get_wopi_dict(request_user, repo_id, file_path, action_name='view'):
    """ Prepare dict data for WOPI host page
    """

    if action_name not in ('view', 'edit'):
        return None

    file_name = os.path.basename(file_path)
    file_ext = os.path.splitext(file_name)[1][1:].lower()

    if OFFICE_SERVER_TYPE.lower() == 'collaboraoffice':
        if file_ext == 'doc':
            file_ext = 'docx'

        if file_ext == 'ppt':
            file_ext = 'pptx'

        if file_ext == 'xls':
            file_ext = 'xlsx'

    wopi_key = generate_discovery_cache_key(action_name, file_ext)
    action_url = cache.get(wopi_key)

    if not action_url:
        # can not get action_url from cache

        try:
            if OFFICE_WEB_APP_CLIENT_CERT and OFFICE_WEB_APP_CLIENT_KEY:
                xml = requests.get(OFFICE_WEB_APP_BASE_URL,
                                   cert=(OFFICE_WEB_APP_CLIENT_CERT,
                                         OFFICE_WEB_APP_CLIENT_KEY),
                                   verify=OFFICE_WEB_APP_SERVER_CA)
            elif OFFICE_WEB_APP_CLIENT_PEM:
                xml = requests.get(OFFICE_WEB_APP_BASE_URL,
                                   cert=OFFICE_WEB_APP_CLIENT_PEM,
                                   verify=OFFICE_WEB_APP_SERVER_CA)
            else:
                xml = requests.get(OFFICE_WEB_APP_BASE_URL,
                                   verify=OFFICE_WEB_APP_SERVER_CA)
        except Exception as e:
            logger.error(e)
            return None

        try:
            root = ET.fromstring(xml.content)
        except Exception as e:
            logger.error(e)
            return None

        for action in root.getiterator('action'):
            attr = action.attrib
            ext = attr.get('ext')
            name = attr.get('name')
            urlsrc = attr.get('urlsrc')

            if ext and name and urlsrc:

                tmp_action_url = re.sub(r'<.*>', '', urlsrc)
                tmp_wopi_key = generate_discovery_cache_key(name, ext)
                cache.set(tmp_wopi_key, tmp_action_url,
                          OFFICE_WEB_APP_DISCOVERY_EXPIRATION)

                if wopi_key == tmp_wopi_key:
                    action_url = tmp_action_url
            else:
                continue

    if not action_url:
        # can not get action_url from hosting discovery page
        return None

    # generate full action url
    repo = seafile_api.get_repo(repo_id)
    if repo.is_virtual:
        origin_repo_id = repo.origin_repo_id
        origin_file_path = posixpath.join(repo.origin_path,
                                          file_path.strip('/'))
        repo_path_info = '_'.join([origin_repo_id, origin_file_path])
    else:
        repo_path_info = '_'.join([repo_id, file_path])

    fake_file_id = hashlib.sha1(repo_path_info.encode('utf8')).hexdigest()
    base_url = get_site_scheme_and_netloc()
    check_file_info_endpoint = reverse('WOPIFilesView', args=[fake_file_id])
    WOPISrc = urlparse.urljoin(base_url, check_file_info_endpoint)

    query_dict = {'WOPISrc': WOPISrc}
    if action_url[-1] in ('?', '&'):
        full_action_url = action_url + urllib.urlencode(query_dict)
    elif '?' in action_url:
        full_action_url = action_url + '&' + urllib.urlencode(query_dict)
    else:
        full_action_url = action_url + '?' + urllib.urlencode(query_dict)

    lang_code = Profile.objects.get_user_language(request_user)
    if lang_code.lower() == 'zh-cn':
        full_action_url += '&ui=zh-CN&rs=zh-CN'

    # generate access token
    user_repo_path_info = (request_user, repo_id, file_path)

    # collobora office only allowed alphanumeric and _
    uid = uuid.uuid4()
    access_token = uid.hex
    key = generate_access_token_cache_key(access_token)
    cache.set(key, user_repo_path_info, WOPI_ACCESS_TOKEN_EXPIRATION)

    # access_token_ttl property tells office web app
    # when access token expires
    expire_sec = WOPI_ACCESS_TOKEN_EXPIRATION
    expiration = timezone.now() + relativedelta(seconds=expire_sec)
    milliseconds_ttl = time.mktime(expiration.timetuple()) * 1000
    access_token_ttl = int(milliseconds_ttl)

    wopi_dict = {}
    wopi_dict['action_url'] = full_action_url
    wopi_dict['access_token'] = access_token
    wopi_dict['access_token_ttl'] = access_token_ttl

    return wopi_dict
Example #50
0
    def put(self, request, repo_id, format=None):
        """ Modify repo group folder perm.

        Permission checking:
        1. is group admin
        """

        # argument check
        path = request.data.get('folder_path', None)
        if not path:
            error_msg = 'folder_path invalid.'
            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        perm = request.data.get('permission', None)
        if not perm or perm not in [PERMISSION_READ, PERMISSION_READ_WRITE]:
            error_msg = 'permission 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 invalid.'
            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        try:
            group_id = int(group_id)
        except ValueError:
            error_msg = 'group_id 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)

        path = normalize_dir_path(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)

        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)

        repo_owner = get_repo_owner(request, repo_id)
        library_group_id = get_group_id_by_repo_owner(repo_owner)
        if not ccnet_api.get_group(library_group_id):
            error_msg = 'Group %s not found.' % group_id
            return api_error(status.HTTP_404_NOT_FOUND, error_msg)

        permission = seafile_api.get_folder_group_perm(repo_id, path, group_id)
        if not permission:
            error_msg = 'Folder permission not found.'
            return api_error(status.HTTP_404_NOT_FOUND, error_msg)

        # permission check
        username = request.user.username
        if not is_group_admin(library_group_id, username):
            error_msg = 'Permission denied.'
            return api_error(status.HTTP_403_FORBIDDEN, error_msg)

        # modify permission
        try:
            seafile_api.set_folder_group_perm(repo_id, path, perm, group_id)
            send_perm_audit_msg('modify-repo-perm', username, group_id,
                                repo_id, path, perm)
            new_perm = seafile_api.get_folder_group_perm(
                repo_id, path, group_id)
            result = self._get_group_folder_perm_info(group_id, repo_id, path,
                                                      new_perm)
            return Response(result)
        except Exception as e:
            logger.error(e)
            error_msg = 'Internal Server Error'
            return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
Example #51
0
    def post(self, request):

        # argument check
        operation = request.data.get('operation')

        # operation could be `share`, `delete`, `transfer`
        # we now only use `share`
        if not operation or operation not in ('share'):
            error_msg = 'operation invalid.'
            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        result = {}
        result['failed'] = []
        result['success'] = []

        username = request.user.username
        repo_id_list = request.data.getlist('repo_id')
        valid_repo_id_list = []

        # filter out invalid repo id
        for repo_id in repo_id_list:

            if not seafile_api.get_repo(repo_id):
                result['failed'].append({
                    'repo_id':
                    repo_id,
                    'error_msg':
                    'Library %s not found.' % repo_id
                })
                continue

            if is_org_context(request):
                org_id = request.user.org.org_id
                org_repo_owner = seafile_api.get_org_repo_owner(repo_id)
                if not username == org_repo_owner:
                    result['failed'].append({
                        'repo_id': repo_id,
                        'error_msg': 'Permission denied.'
                    })
                    continue
            else:
                if not seafile_api.is_repo_owner(username, repo_id):
                    result['failed'].append({
                        'repo_id': repo_id,
                        'error_msg': 'Permission denied.'
                    })
                    continue

            valid_repo_id_list.append(repo_id)

        # share repo
        if operation == 'share':

            share_type = request.data.get('share_type')
            if share_type != 'user' and share_type != 'group':
                error_msg = 'share_type invalid.'
                return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

            permission = request.data.get('permission', 'rw')
            if permission not in ('r', 'rw'):
                error_msg = 'permission invalid.'
                return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

            # share repo to user
            if share_type == 'user':
                to_username = request.data.get('username', None)
                if not to_username:
                    error_msg = 'username invalid.'
                    return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

                try:
                    User.objects.get(email=to_username)
                except User.DoesNotExist:
                    error_msg = 'User %s not found.' % to_username
                    return api_error(status.HTTP_404_NOT_FOUND, error_msg)

                # check if to_user is an org user
                try:
                    org_of_to_user = ccnet_api.get_orgs_by_user(to_username)
                except Exception as e:
                    logger.debug(e)
                    org_of_to_user = []

                if is_org_context(request):
                    org_id = request.user.org.org_id
                    org_name = request.user.org.org_name
                    if len(org_of_to_user
                           ) == 0 or org_id != org_of_to_user[0].org_id:
                        error_msg = 'User %s is not member of organization %s.' \
                                % (to_username, org_name)
                        return api_error(status.HTTP_403_FORBIDDEN, error_msg)
                else:
                    if len(org_of_to_user) >= 1:
                        error_msg = 'User %s is member of organization %s.' \
                                % (to_username, org_of_to_user[0].org_name)
                        return api_error(status.HTTP_403_FORBIDDEN, error_msg)

                for repo_id in valid_repo_id_list:
                    if self.has_shared_to_user(request, repo_id, to_username):
                        result['failed'].append({
                            'repo_id':
                            repo_id,
                            'error_msg':
                            'This item has been shared to %s.' % to_username
                        })
                        continue

                    try:
                        if is_org_context(request):
                            org_id = request.user.org.org_id
                            seaserv.seafserv_threaded_rpc.org_add_share(
                                org_id, repo_id, username, to_username,
                                permission)
                        else:
                            seafile_api.share_repo(repo_id, username,
                                                   to_username, permission)

                        # send a signal when sharing repo successful
                        repo = seafile_api.get_repo(repo_id)
                        share_repo_to_user_successful.send(sender=None,
                                                           from_user=username,
                                                           to_user=to_username,
                                                           repo=repo)

                        result['success'].append({
                            "repo_id": repo_id,
                            "username": to_username,
                            "permission": permission
                        })

                        send_perm_audit_msg('add-repo-perm', username,
                                            to_username, repo_id, '/',
                                            permission)
                    except Exception as e:
                        logger.error(e)
                        result['failed'].append({
                            'repo_id':
                            repo_id,
                            'error_msg':
                            'Internal Server Error'
                        })

            # share repo to group
            if share_type == 'group':
                to_group_id = request.data.get('group_id', None)
                if not to_group_id:
                    error_msg = 'group_id invalid.'
                    return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

                try:
                    to_group_id = int(to_group_id)
                except ValueError:
                    error_msg = 'group_id invalid.'
                    return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

                group = ccnet_api.get_group(to_group_id)
                if not group:
                    error_msg = 'Group %s not found.' % to_group_id
                    return api_error(status.HTTP_404_NOT_FOUND, error_msg)

                group_name = group.group_name
                if not ccnet_api.is_group_user(to_group_id, username):
                    error_msg = 'User %s is not member of group %s.' % (
                        username, group_name)
                    return api_error(status.HTTP_403_FORBIDDEN, error_msg)

                for repo_id in valid_repo_id_list:
                    if self.has_shared_to_group(request, repo_id, to_group_id):
                        result['failed'].append({
                            'repo_id':
                            repo_id,
                            'error_msg':
                            'This item has been shared to %s.' % group_name
                        })
                        continue

                    try:
                        if is_org_context(request):
                            org_id = request.user.org.org_id
                            seafile_api.add_org_group_repo(
                                repo_id, org_id, to_group_id, username,
                                permission)
                        else:
                            seafile_api.set_group_repo(repo_id, to_group_id,
                                                       username, permission)

                        # send a signal when sharing repo successful
                        repo = seafile_api.get_repo(repo_id)
                        share_repo_to_group_successful.send(
                            sender=None,
                            from_user=username,
                            group_id=to_group_id,
                            repo=repo)

                        result['success'].append({
                            "repo_id": repo_id,
                            "group_id": to_group_id,
                            "group_name": group_name,
                            "permission": permission
                        })

                        send_perm_audit_msg('add-repo-perm', username,
                                            to_group_id, repo_id, '/',
                                            permission)

                    except SearpcError as e:
                        logger.error(e)
                        result['failed'].append({
                            'repo_id':
                            repo_id,
                            'error_msg':
                            'Internal Server Error'
                        })

        return Response(result)
Example #52
0
    def post(self, request, repo_id, format=None):
        """ Add repo group folder perm.

        Permission checking:
        1. is group admin
        """

        # argument check
        path = request.data.get('folder_path', None)
        if not path:
            error_msg = 'folder_path invalid.'
            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        perm = request.data.get('permission', None)
        if not perm or perm not in [PERMISSION_READ, PERMISSION_READ_WRITE]:
            error_msg = 'permission 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)

        path = normalize_dir_path(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)

        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)

        # 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 = {}
        result['failed'] = []
        result['success'] = []

        group_ids = request.data.getlist('group_id')
        for group_id in group_ids:
            try:
                group_id = int(group_id)
            except ValueError:
                result['failed'].append({
                    'group_id': group_id,
                    'error_msg': 'group_id invalid.'
                })
                continue

            if not ccnet_api.get_group(group_id):
                result['failed'].append({
                    'group_id':
                    group_id,
                    'error_msg':
                    'Group %s not found.' % group_id
                })
                continue

            permission = seafile_api.get_folder_group_perm(
                repo_id, path, group_id)
            if permission:
                result['failed'].append({
                    'group_id':
                    group_id,
                    'error_msg':
                    _(u'Permission already exists.')
                })
                continue

            try:
                seafile_api.add_folder_group_perm(repo_id, path, perm,
                                                  group_id)
                send_perm_audit_msg('add-repo-perm', username, group_id,
                                    repo_id, path, perm)
            except Exception as e:
                logger.error(e)
                result['failed'].append({
                    'group_id': group_id,
                    'error_msg': 'Internal Server Error'
                })

            new_perm = seafile_api.get_folder_group_perm(
                repo_id, path, group_id)
            new_perm_info = self._get_group_folder_perm_info(
                group_id, repo_id, path, new_perm)
            result['success'].append(new_perm_info)

        return Response(result)
Example #53
0
    def post(self, request):
        """ Multi copy folders.

        Permission checking:
        1. User must has `r/rw` permission for src folder.
        2. User must has `rw` permission for dst folder.

        Parameter:
        {
            "src_repo_id":"7460f7ac-a0ff-4585-8906-bb5a57d2e118",
            "dst_repo_id":"a3fa768d-0f00-4343-8b8d-07b4077881db",
            "paths":[
                {"src_path":"/1/2/3/","dst_path":"/4/5/6/"},
                {"src_path":"/a/b/c/","dst_path":"/d/e/f/"},
            ]
        }
        """

        # argument check
        path_list = request.data.get('paths', None)
        if not path_list:
            error_msg = 'paths invalid.'
            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        src_repo_id = request.data.get('src_repo_id', None)
        if not src_repo_id:
            error_msg = 'src_repo_id invalid.'
            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        dst_repo_id = request.data.get('dst_repo_id', None)
        if not dst_repo_id:
            error_msg = 'dst_repo_id invalid.'
            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        # permission check, user must has `r/rw` permission for src repo.
        if check_folder_permission(request, src_repo_id, '/') is None:
            error_msg = 'Permission denied.'
            return api_error(status.HTTP_403_FORBIDDEN, error_msg)

        # permission check, user must has `rw` permission for dst repo.
        if check_folder_permission(request, dst_repo_id, '/') != 'rw':
            error_msg = 'Permission denied.'
            return api_error(status.HTTP_403_FORBIDDEN, error_msg)

        # resource check
        src_repo = seafile_api.get_repo(src_repo_id)
        if not src_repo:
            error_msg = 'Library %s not found.' % src_repo_id
            return api_error(status.HTTP_404_NOT_FOUND, error_msg)

        dst_repo = seafile_api.get_repo(dst_repo_id)
        if not dst_repo:
            error_msg = 'Library %s not found.' % dst_repo_id
            return api_error(status.HTTP_404_NOT_FOUND, error_msg)

        result = {}
        result['failed'] = []
        result['success'] = []
        username = request.user.username

        for path_item in path_list:

            src_path = path_item['src_path']
            src_path = normalize_dir_path(src_path)
            src_parent_dir = os.path.dirname(src_path.rstrip('/'))
            src_parent_dir = normalize_dir_path(src_parent_dir)
            src_obj_name = os.path.basename(src_path.rstrip('/'))

            dst_path = path_item['dst_path']
            dst_path = normalize_dir_path(dst_path)
            dst_parent_dir = dst_path
            dst_obj_name = src_obj_name

            common_dict = {
                'src_repo_id': src_repo_id,
                'src_path': src_path,
                'dst_repo_id': dst_repo_id,
                'dst_path': dst_path,
            }

            # src/dst parameter check
            if src_repo_id == dst_repo_id and \
                    dst_path.startswith(src_path):
                error_dict = {
                    'error_msg':
                    "The destination directory is the same as the source, or is it's subfolder."
                }
                common_dict.update(error_dict)
                result['failed'].append(common_dict)
                continue

            if src_path == '/':
                error_dict = {'error_msg': "The source path can not be '/'."}
                common_dict.update(error_dict)
                result['failed'].append(common_dict)
                continue

            if len(dst_parent_dir + dst_obj_name) > MAX_PATH:
                error_dict = {'error_msg': "'Destination path is too long."}
                common_dict.update(error_dict)
                result['failed'].append(common_dict)
                continue

            # src resource check
            if not seafile_api.get_dir_id_by_path(src_repo_id, src_path):
                error_dict = {'error_msg': 'Folder %s not found.' % src_path}
                common_dict.update(error_dict)
                result['failed'].append(common_dict)
                continue

            # dst resource check
            if not seafile_api.get_dir_id_by_path(dst_repo_id, dst_path):
                error_dict = {'error_msg': 'Folder %s not found.' % dst_path}
                common_dict.update(error_dict)
                result['failed'].append(common_dict)
                continue

            # src path permission check, user must has `r/rw` permission for src folder.
            if check_folder_permission(request, src_repo_id,
                                       src_parent_dir) is None:
                error_dict = {'error_msg': 'Permission denied.'}
                common_dict.update(error_dict)
                result['failed'].append(common_dict)
                continue

            # dst path permission check, user must has `rw` permission for dst folder.
            if check_folder_permission(request, dst_repo_id, dst_path) != 'rw':
                error_dict = {'error_msg': 'Permission denied.'}
                common_dict.update(error_dict)
                result['failed'].append(common_dict)
                continue

            try:
                # need_progress=0, synchronous=1
                seafile_api.copy_file(src_repo_id, src_parent_dir,
                                      src_obj_name, dst_repo_id,
                                      dst_parent_dir, dst_obj_name, username,
                                      0, 1)
            except Exception as e:
                logger.error(e)
                error_dict = {'error_msg': 'Internal Server Error'}
                common_dict.update(error_dict)
                result['failed'].append(common_dict)
                continue

            result['success'].append(common_dict)

        return Response(result)
Example #54
0
    def post(self, request):
        """ Multi create folders.

        Permission checking:
        1. user with `rw` permission for every layer of subdirectories.

        Parameter:
        {
            "repo_id": "4dfdf5b6-806f-4a35-b2b7-604051d2114e",
            "paths": ["/1/2/", "/3/4/", "/5/6"]
        }
        """

        # argument check
        path_list = request.data.get('paths', None)
        if not path_list:
            error_msg = 'paths invalid.'
            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        repo_id = request.data.get('repo_id', None)
        if not repo_id:
            error_msg = 'repo_id 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)

        # permission check
        if check_folder_permission(request, repo_id, '/') != 'rw':
            error_msg = 'Permission denied.'
            return api_error(status.HTTP_403_FORBIDDEN, error_msg)

        result = {}
        result['failed'] = []
        result['success'] = []
        username = request.user.username

        for path in path_list:

            common_dict = {
                'repo_id': repo_id,
                'path': path,
            }

            path = normalize_dir_path(path)
            obj_name_list = path.strip('/').split('/')

            for obj_name in obj_name_list:
                try:
                    # check if path is valid
                    is_valid_name = seafile_api.is_valid_filename(
                        'fake_repo_id', obj_name)
                except Exception as e:
                    logger.error(e)
                    error_dict = {'error_msg': 'Internal Server Error'}
                    common_dict.update(error_dict)
                    result['failed'].append(common_dict)
                    continue

                if not is_valid_name:
                    error_dict = {'error_msg': 'path invalid.'}
                    common_dict.update(error_dict)
                    result['failed'].append(common_dict)
                    continue

            if seafile_api.get_dir_id_by_path(repo_id, path):
                error_dict = {'error_msg': 'Folder already exists.'}
                common_dict.update(error_dict)
                result['failed'].append(common_dict)
                continue

            # check parent directory's permission
            parent_dir = os.path.dirname(path.rstrip('/'))
            try:
                permission = get_folder_permission_recursively(
                    username, repo_id, parent_dir)
            except Exception as e:
                logger.error(e)
                error_dict = {'error_msg': 'Internal Server Error'}
                common_dict.update(error_dict)
                result['failed'].append(common_dict)
                continue

            if permission != 'rw':
                error_dict = {'error_msg': 'Permission denied.'}
                common_dict.update(error_dict)
                result['failed'].append(common_dict)
                continue

            try:
                # TODO
                # move seafile_api.mkdir_with_parents() to CE version
                # rename obj name if name is existed
                seafile_api.mkdir_with_parents(repo_id, '/', path.strip('/'),
                                               username)
            except Exception as e:
                logger.error(e)
                error_dict = {'error_msg': 'Internal Server Error'}
                common_dict.update(error_dict)
                result['failed'].append(common_dict)
                continue

            result['success'].append(common_dict)

        return Response(result)
Example #55
0
    def post(self, request):
        """ Create share link.

        Permission checking:
        1. default(NOT guest) user;
        """

        # argument check
        repo_id = request.data.get('repo_id', None)
        if not repo_id:
            error_msg = 'repo_id invalid.'
            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        path = request.data.get('path', None)
        if not path:
            error_msg = 'path invalid.'
            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        password = request.data.get('password', None)
        if password and len(password) < config.SHARE_LINK_PASSWORD_MIN_LENGTH:
            error_msg = _('Password is too short.')
            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        try:
            expire_days = int(request.data.get('expire_days', 0))
        except ValueError:
            expire_days = 0

        if SHARE_LINK_EXPIRE_DAYS_MIN > 0:
            if expire_days < SHARE_LINK_EXPIRE_DAYS_MIN:
                error_msg = _('Expire days should be greater or equal to %s' %
                        SHARE_LINK_EXPIRE_DAYS_MIN)
                return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        if SHARE_LINK_EXPIRE_DAYS_MAX > 0:
            if expire_days > SHARE_LINK_EXPIRE_DAYS_MAX:
                error_msg = _('Expire days should be less than or equal to %s' %
                        SHARE_LINK_EXPIRE_DAYS_MAX)
                return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        if expire_days <= 0:
            expire_date = None
        else:
            expire_date = timezone.now() + relativedelta(days=expire_days)

        perm = self._check_permissions_arg(request)

        # 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 repo.encrypted:
            error_msg = 'Permission denied.'
            return api_error(status.HTTP_403_FORBIDDEN, error_msg)

        try:
            obj_id, s_type = self._generate_obj_id_and_type_by_path(repo_id, path)
        except SearpcError as e:
            logger.error(e)
            error_msg = 'Internal Server Error'
            return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)

        if not obj_id:
            if s_type == 'f':
                error_msg = 'file %s not found.' % path
            elif s_type == 'd':
                error_msg = 'folder %s not found.' % path
            else:
                error_msg = 'path %s not found.' % path

            return api_error(status.HTTP_404_NOT_FOUND, error_msg)

        # permission check
        if not check_folder_permission(request, repo_id, path):
            error_msg = 'Permission denied.'
            return api_error(status.HTTP_403_FORBIDDEN, error_msg)

        username = request.user.username
        if s_type == 'f':
            fs = FileShare.objects.get_file_link_by_path(username, repo_id, path)
            if not fs:
                fs = FileShare.objects.create_file_link(username, repo_id, path,
                                                        password, expire_date,
                                                        permission=perm)

        elif s_type == 'd':
            fs = FileShare.objects.get_dir_link_by_path(username, repo_id, path)
            if not fs:
                fs = FileShare.objects.create_dir_link(username, repo_id, path,
                                                       password, expire_date,
                                                       permission=perm)

        if is_org_context(request):
            org_id = request.user.org.org_id
            OrgFileShare.objects.set_org_file_share(org_id, fs)

        link_info = get_share_link_info(fs)
        return Response(link_info)
Example #56
0
    def post(self, request, group_id):
        """ Add a group owned library by system admin.
        """

        if not request.user.admin_permissions.can_manage_group():
            return api_error(status.HTTP_403_FORBIDDEN, 'Permission denied.')

        # argument check
        repo_name = request.data.get("repo_name", None)
        if not repo_name or \
                not is_valid_dirent_name(repo_name):
            error_msg = "repo_name invalid."
            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        password = request.data.get("password", None)

        permission = request.data.get('permission', PERMISSION_READ_WRITE)
        if permission not in get_available_repo_perms():
            permission = normalize_custom_permission_name(permission)
            if not permission:
                error_msg = 'permission invalid.'
                return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        # permission check
        group_quota = seafile_api.get_group_quota(group_id)
        group_quota = int(group_quota)
        if group_quota <= 0 and group_quota != -2:
            error_msg = 'No group quota.'
            return api_error(status.HTTP_403_FORBIDDEN, error_msg)

        if is_org_context(request):
            # request called by org admin
            org_id = request.user.org.org_id
        else:
            org_id = -1

        # create group owned repo
        group_id = int(group_id)
        if is_pro_version() and ENABLE_STORAGE_CLASSES:

            if STORAGE_CLASS_MAPPING_POLICY in ('USER_SELECT', 'ROLE_BASED'):

                storages = get_library_storages(request)
                storage_id = request.data.get("storage_id", None)
                if storage_id and storage_id not in [
                        s['storage_id'] for s in storages
                ]:
                    error_msg = 'storage_id invalid.'
                    return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

                repo_id = seafile_api.add_group_owned_repo(
                    group_id,
                    repo_name,
                    permission,
                    password,
                    enc_version=ENCRYPTED_LIBRARY_VERSION,
                    storage_id=storage_id)
            else:
                # STORAGE_CLASS_MAPPING_POLICY == 'REPO_ID_MAPPING'
                if org_id and org_id > 0:
                    repo_id = seafile_api.org_add_group_owned_repo(
                        org_id, group_id, repo_name, permission, password,
                        ENCRYPTED_LIBRARY_VERSION)
                else:
                    repo_id = seafile_api.add_group_owned_repo(
                        group_id, repo_name, permission, password,
                        ENCRYPTED_LIBRARY_VERSION)
        else:
            if org_id and org_id > 0:
                repo_id = seafile_api.org_add_group_owned_repo(
                    org_id, group_id, repo_name, permission, password,
                    ENCRYPTED_LIBRARY_VERSION)
            else:
                repo_id = seafile_api.add_group_owned_repo(
                    group_id, repo_name, permission, password,
                    ENCRYPTED_LIBRARY_VERSION)

        # for activities
        username = request.user.username
        library_template = request.data.get("library_template", '')
        repo_created.send(sender=None,
                          org_id=org_id,
                          creator=username,
                          repo_id=repo_id,
                          repo_name=repo_name,
                          library_template=library_template)

        # for notification
        repo = seafile_api.get_repo(repo_id)
        share_repo_to_group_successful.send(sender=None,
                                            from_user=username,
                                            group_id=group_id,
                                            repo=repo,
                                            path='/',
                                            org_id=org_id)

        info = get_group_owned_repo_info(request, repo_id)
        # TODO
        info['permission'] = permission
        return Response(info)
Example #57
0
    def do_action(self):
        now = datetime.datetime.now()

        try:
            cmd_last_check = CommandsLastCheck.objects.get(
                command_type=self.label)
            logger.debug('Last check time is %s' % cmd_last_check.last_check)

            unseen_notices = UserNotification.objects.get_all_notifications(
                seen=False, time_since=cmd_last_check.last_check)

            logger.debug('Update last check time to %s' % now)
            cmd_last_check.last_check = now
            cmd_last_check.save()
        except CommandsLastCheck.DoesNotExist:
            logger.debug('No last check time found, get all unread notices.')
            unseen_notices = UserNotification.objects.get_all_notifications(
                seen=False)

            logger.debug('Create new last check time: %s' % now)
            CommandsLastCheck(command_type=self.label, last_check=now).save()

        email_ctx = {}
        for notice in unseen_notices:
            if notice.to_user in email_ctx:
                email_ctx[notice.to_user] += 1
            else:
                email_ctx[notice.to_user] = 1

        for to_user, count in email_ctx.items():
            # save current language
            cur_language = translation.get_language()

            # get and active user language
            user_language = self.get_user_language(to_user)
            translation.activate(user_language)
            logger.debug('Set language code to %s for user: %s' %
                         (user_language, to_user))
            self.stdout.write('[%s] Set language code to %s' %
                              (str(datetime.datetime.now()), user_language))

            notices = []
            for notice in unseen_notices:
                logger.info('Processing unseen notice: [%s]' % (notice))

                d = json.loads(notice.detail)

                repo_id = d.get('repo_id', None)
                group_id = d.get('group_id', None)
                try:
                    if repo_id and not seafile_api.get_repo(repo_id):
                        notice.delete()
                        continue

                    if group_id and not ccnet_api.get_group(group_id):
                        notice.delete()
                        continue
                except Exception as e:
                    logger.error(e)
                    continue

                if notice.to_user != to_user:
                    continue

                elif notice.is_group_msg():
                    notice = self.format_group_message(notice)

                elif notice.is_repo_share_msg():
                    notice = self.format_repo_share_msg(notice)

                elif notice.is_repo_share_to_group_msg():
                    notice = self.format_repo_share_to_group_msg(notice)

                elif notice.is_file_uploaded_msg():
                    notice = self.format_file_uploaded_msg(notice)

                elif notice.is_group_join_request():
                    notice = self.format_group_join_request(notice)

                elif notice.is_add_user_to_group():
                    notice = self.format_add_user_to_group(notice)

                elif notice.is_file_comment_msg():
                    notice = self.format_file_comment_msg(notice)

                elif notice.is_guest_invitation_accepted_msg():
                    notice = self.format_guest_invitation_accepted_msg(notice)

                if notice is None:
                    continue

                notices.append(notice)

            if not notices:
                continue

            contact_email = Profile.objects.get_contact_email_by_user(to_user)
            to_user = contact_email  # use contact email if any
            c = {
                'to_user': to_user,
                'notice_count': count,
                'notices': notices,
            }

            try:
                send_html_email(
                    _('New notice on %s') % settings.SITE_NAME,
                    'notifications/notice_email.html', c, None, [to_user])

                logger.info('Successfully sent email to %s' % to_user)
                self.stdout.write('[%s] Successfully sent email to %s' %
                                  (str(datetime.datetime.now()), to_user))
            except Exception as e:
                logger.error('Failed to send email to %s, error detail: %s' %
                             (to_user, e))
                self.stderr.write(
                    '[%s] Failed to send email to %s, error detail: %s' %
                    (str(datetime.datetime.now()), to_user, e))

            # restore current language
            translation.activate(cur_language)
Example #58
0
    def get(self, request):
        """ Get all share links of a user.

        Permission checking:
        1. default(NOT guest) user;
        """

        # get all share links
        username = request.user.username
        fileshares = FileShare.objects.filter(username=username)

        repo_id = request.GET.get('repo_id', None)
        if 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)

            # filter share links by repo
            fileshares = filter(lambda fs: fs.repo_id == repo_id, fileshares)

            path = request.GET.get('path', None)
            if path:
                try:
                    obj_id, s_type = self._generate_obj_id_and_type_by_path(repo_id, path)
                except SearpcError as e:
                    logger.error(e)
                    error_msg = 'Internal Server Error'
                    return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)

                if not obj_id:
                    if s_type == 'f':
                        error_msg = 'file %s not found.' % path
                    elif s_type == 'd':
                        error_msg = 'folder %s not found.' % path
                    else:
                        error_msg = 'path %s not found.' % path

                    return api_error(status.HTTP_404_NOT_FOUND, error_msg)

                # if path invalid, filter share links by repo
                if s_type == 'd' and path[-1] != '/':
                    path = path + '/'

                fileshares = filter(lambda fs: fs.path == path, fileshares)

        links_info = []
        for fs in fileshares:
            link_info = get_share_link_info(fs)
            links_info.append(link_info)

        if len(links_info) == 1:
            result = links_info
        else:
            dir_list = filter(lambda x: x['is_dir'], links_info)
            file_list = filter(lambda x: not x['is_dir'], links_info)

            dir_list.sort(lambda x, y: cmp(x['obj_name'], y['obj_name']))
            file_list.sort(lambda x, y: cmp(x['obj_name'], y['obj_name']))

            result = dir_list + file_list

        return Response(result)
Example #59
0
    def delete(self, request, workspace_id):
        """delete a table
        """
        # 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)

        table_path = normalize_file_path(table_file_name)
        table_file_id = seafile_api.get_file_id_by_path(repo_id, table_path)
        if not table_file_id:
            error_msg = 'file %s not found.' % table_file_name
            return api_error(status.HTTP_404_NOT_FOUND, error_msg)

        # permission check
        username = request.user.username
        owner = workspace.owner
        if '@seafile_group' in owner:
            group_id = int(owner.split('@')[0])
            if not is_group_member(group_id, username):
                error_msg = 'Permission denied.'
                return api_error(status.HTTP_403_FORBIDDEN, error_msg)
        else:
            if username != 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)

        # delete asset
        asset_dir_path = '/asset/' + str(dtable.uuid)
        asset_dir_id = seafile_api.get_dir_id_by_path(repo_id, asset_dir_path)
        if asset_dir_id:
            parent_dir = os.path.dirname(asset_dir_path)
            file_name = os.path.basename(asset_dir_path)
            try:
                seafile_api.del_file(repo_id, parent_dir, file_name, owner)
            except SearpcError as e:
                logger.error(e)
                error_msg = 'Internal Server Error'
                return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR,
                                 error_msg)

        # delete table
        try:
            seafile_api.del_file(repo_id, '/', table_file_name, owner)
        except SearpcError as e:
            logger.error(e)
            error_msg = 'Internal Server Error'
            return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)

        try:
            DTables.objects.delete_dtable(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({'success': True}, status=status.HTTP_200_OK)
Example #60
0
    def delete(self, request, repo_id, format=None):

        if not seafile_api.get_repo(repo_id):
            return api_error(status.HTTP_400_BAD_REQUEST, 'Library does not exist')

        username = request.user.username
        share_type = request.GET.get('share_type', None)
        if share_type == 'personal':

            from_email = request.GET.get('from', None)
            if not is_valid_username(from_email):
                return api_error(status.HTTP_400_BAD_REQUEST, 'Invalid argument')

            if is_org_context(request):
                org_id = request.user.org.org_id
                seaserv.seafserv_threaded_rpc.org_remove_share(org_id,
                                                               repo_id,
                                                               from_email,
                                                               username)
            else:
                seaserv.remove_share(repo_id, from_email, username)

        elif share_type == 'group':

            from_email = request.GET.get('from', None)
            if not is_valid_username(from_email):
                return api_error(status.HTTP_400_BAD_REQUEST, 'Invalid argument')

            group_id = request.GET.get('group_id', None)
            group = seaserv.get_group(group_id)
            if not group:
                return api_error(status.HTTP_400_BAD_REQUEST, 'Group does not exist')

            if not seaserv.check_group_staff(group_id, username) and \
                not seafile_api.is_repo_owner(username, repo_id):
                return api_error(status.HTTP_403_FORBIDDEN, 'Permission denied')

            if seaserv.is_org_group(group_id):
                org_id = seaserv.get_org_id_by_group(group_id)
                seaserv.del_org_group_repo(repo_id, org_id, group_id)
            else:
                seafile_api.unset_group_repo(repo_id, group_id, from_email)

        elif share_type == 'public':

            if is_org_context(request):
                org_repo_owner = seafile_api.get_org_repo_owner(repo_id)
                is_org_repo_owner = True if org_repo_owner == username else False

                if not request.user.org.is_staff and not is_org_repo_owner:
                    return api_error(status.HTTP_403_FORBIDDEN, 'Permission denied')

                org_id = request.user.org.org_id
                seaserv.seafserv_threaded_rpc.unset_org_inner_pub_repo(org_id,
                                                                       repo_id)
            else:
                if not seafile_api.is_repo_owner(username, repo_id) and \
                    not request.user.is_staff:
                    return api_error(status.HTTP_403_FORBIDDEN, 'Permission denied')

                seaserv.unset_inner_pub_repo(repo_id)
        else:
            return api_error(status.HTTP_400_BAD_REQUEST, 'Invalid argument')

        return Response({'success': True}, status=status.HTTP_200_OK)