Example #1
0
def group_wiki_pages(request, group):
    """
    List wiki pages in group.
    """
    username = request.user.username
    try:
        repo = get_group_wiki_repo(group, username)
        pages = get_wiki_pages(repo)
    except SearpcError:
        return render_error(request, _("Internal Server Error"))
    except WikiDoesNotExist:
        return render_error(request, _("Wiki does not exists."))

    repo_perm = seafile_api.check_repo_access_permission(repo.id, username)
    mods_available = get_available_mods_by_group(group.id)
    mods_enabled = get_enabled_mods_by_group(group.id)

    return render_to_response(
        "group/group_wiki_pages.html",
        {
            "group": group,
            "pages": pages,
            "is_staff": group.is_staff,
            "repo_id": repo.id,
            "search_repo_id": repo.id,
            "search_wiki": True,
            "repo_perm": repo_perm,
            "mods_enabled": mods_enabled,
            "mods_available": mods_available,
        },
        context_instance=RequestContext(request),
    )
Example #2
0
def personal_wiki_page_new(request, page_name="home"):

    if request.method == 'POST':
        page_name = request.POST.get('page_name', '')
        if not page_name:
            return HttpResponseRedirect(request.META.get('HTTP_REFERER'))
        page_name = clean_page_name(page_name)

        try:
            repo = get_personal_wiki_repo(request.user.username)
        except WikiDoesNotExist:
            return render_error(request, _('Wiki is not found.'))

        filename = page_name + ".md"
        filepath = "/" + page_name + ".md"

        # check whether file exists
        if seaserv.get_file_id_by_path(repo.id, filepath):
            return render_error(request, _('Page "%s" already exists.') % filename)

        if not seaserv.post_empty_file(repo.id, "/", filename, request.user.username):
            return render_error(request, _('Failed to create wiki page. Please retry later.'))

        url = "%s?p=%s&from=personal_wiki_page_new" % (
            reverse('file_edit', args=[repo.id]),
            urlquote(filepath.encode('utf-8')))
        return HttpResponseRedirect(url)
Example #3
0
def group_wiki_page_new(request, group, page_name="home"):
    if group.view_perm == "pub":
        raise Http404

    if request.method == "POST":
        form = MessageForm(request.POST)

        page_name = request.POST.get("page_name", "")
        if not page_name:
            return HttpResponseRedirect(request.META.get("HTTP_REFERER"))
        page_name = clean_page_name(page_name)

        try:
            repo = get_group_wiki_repo(group, request.user.username)
        except WikiDoesNotExist:
            return render_error(request, _("Wiki is not found."))

        filename = page_name + ".md"
        filepath = "/" + page_name + ".md"

        # check whether file exists
        if get_file_id_by_path(repo.id, filepath):
            return render_error(request, _('Page "%s" already exists.') % filename)

        if not post_empty_file(repo.id, "/", filename, request.user.username):
            return render_error(request, _("Failed to create wiki page. Please retry later."))

        url = "%s?p=%s&from=wiki_page_new&gid=%s" % (
            reverse("file_edit", args=[repo.id]),
            urllib2.quote(filepath.encode("utf-8")),
            group.id,
        )
        return HttpResponseRedirect(url)
Example #4
0
def personal_wiki_pages(request):
    """
    List personal wiki pages.
    """

    username = request.user.username

    if request.cloud_mode and request.user.org is not None:
        org_id = request.user.org.org_id
        joined_groups = seaserv.get_org_groups_by_user(org_id, username)
    else:
        joined_groups = seaserv.get_personal_groups_by_user(username)

    if joined_groups:
        joined_groups.sort(lambda x, y: cmp(x.group_name.lower(), y.group_name.lower()))

    try:
        repo = get_personal_wiki_repo(username)
        pages = get_wiki_pages(repo)
    except SearpcError:
        return render_error(request, _('Internal Server Error'))
    except WikiDoesNotExist:
        return render_error(request, _('Wiki does not exists.'))

    return render_to_response("wiki/personal_wiki_pages.html", {
            "pages": pages,
            "repo_id": repo.id,
            "search_repo_id": repo.id,
            "search_wiki": True,
            "grps": joined_groups,
            }, context_instance=RequestContext(request))
Example #5
0
def group_wiki_pages(request, group):
    """
    List wiki pages in group.
    """
    username = request.user.username
    try:
        repo = get_group_wiki_repo(group, username)
        pages = get_wiki_pages(repo)
    except SearpcError:
        return render_error(request, _('Internal Server Error'))
    except WikiDoesNotExist:
        return render_error(request, _('Wiki does not exists.'))

    if is_registered_user(username):
        repo_perm = seafile_api.check_permission_by_path(repo.id, '/', username)
    else:
        # when anonymous user visit public group wiki, set permission as 'r'
        repo_perm = 'r'

    mods_available = get_available_mods_by_group(group.id)
    mods_enabled = get_enabled_mods_by_group(group.id)

    return render_to_response("group/group_wiki_pages.html", {
            "group": group,
            "pages": pages,
            "is_staff": group.is_staff,
            "repo_id": repo.id,
            "search_repo_id": repo.id,
            "search_wiki": True,
            "repo_perm": repo_perm,
            "mods_enabled": mods_enabled,
            "mods_available": mods_available,
            }, context_instance=RequestContext(request))
Example #6
0
def render_file_revisions (request, repo_id):
    """List all history versions of a file."""

    days_str = request.GET.get('days', '')
    try:
        days = int(days_str)
    except ValueError:
        days = 7

    path = request.GET.get('p', '/')
    if path[-1] == '/':
        path = path[:-1]
    u_filename = os.path.basename(path)

    if not path:
        return render_error(request)

    repo = get_repo(repo_id)
    if not repo:
        error_msg = _(u"Library does not exist")
        return render_error(request, error_msg)

    filetype = get_file_type_and_ext(u_filename)[0].lower()
    if filetype == 'text' or filetype == 'markdown':
        can_compare = True
    else:
        can_compare = False

    try:
        commits = seafile_api.get_file_revisions(repo_id, path, -1, -1, days)
    except SearpcError, e:
        logger.error(e.msg)
        return render_error(request, e.msg)
Example #7
0
def group_quit(request, group_id):
    try:
        group_id_int = int(group_id)
    except ValueError:
        return render_error(request, _(u"group id  is not a valid argument."))

    try:
        ccnet_threaded_rpc.quit_group(group_id_int, request.user.username)
        seafserv_threaded_rpc.remove_repo_group(group_id_int, request.user.username)
    except SearpcError, e:
        return render_error(request, e.msg)
Example #8
0
def repo_remove_share(request):
    """
    If repo is shared from one person to another person, only these two peson
    can remove share.
    If repo is shared from one person to a group, then only the one share the
    repo and group staff can remove share.
    """
    repo_id = request.GET.get('repo_id', '')
    group_id = request.GET.get('gid', '')
    from_email = request.GET.get('from', '')
    if not is_valid_username(from_email):
        return render_error(request, _(u'Argument is not valid'))
    username = request.user.username

    # if request params don't have 'gid', then remove repos that share to
    # to other person; else, remove repos that share to groups
    if not group_id:
        to_email = request.GET.get('to', '')
        if not is_valid_username(to_email):
            return render_error(request, _(u'Argument is not valid'))

        if username != from_email and username != to_email:
            return render_permission_error(request, _(u'Failed to remove share'))

        if is_org_context(request):
            org_id = request.user.org.org_id
            org_remove_share(org_id, repo_id, from_email, to_email)
        else:
            seaserv.remove_share(repo_id, from_email, to_email)
    else:
        try:
            group_id = int(group_id)
        except:
            return render_error(request, _(u'group id is not valid'))

        group = seaserv.get_group(group_id)
        if not group:
            return render_error(request, _(u"Failed to unshare: the group doesn't exist."))

        if not seaserv.check_group_staff(group_id, username) \
                and username != from_email:
            return render_permission_error(request, _(u'Failed to remove share'))

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

    messages.success(request, _('Successfully removed share'))

    next = request.META.get('HTTP_REFERER', SITE_ROOT)
    return HttpResponseRedirect(next)
Example #9
0
def group_share_repo(request, repo_id, group_id, from_email, permission):
    """
    Share a repo to a group.
    
    """
    # Check whether group exists
    group = get_group(group_id)
    if not group:
        return render_error(request, _(u"Failed to share: the group doesn't exist."))
    
    if seafserv_threaded_rpc.group_share_repo(repo_id, group_id, from_email, permission) != 0:
        return render_error(request, _(u"Failed to share: internal error."))
Example #10
0
def personal_wiki_pages(request):
    """
    List personal wiki pages.
    """
    try:
        repo = get_personal_wiki_repo(request.user.username)
        pages = get_wiki_pages(repo)
    except SearpcError:
        return render_error(request, _("Internal Server Error"))
    except WikiDoesNotExist:
        return render_error(request, _("Wiki does not exists."))

    return render_to_response(
        "wiki/personal_wiki_pages.html", {"pages": pages, "repo_id": repo.id}, context_instance=RequestContext(request)
    )
Example #11
0
def repo_remove_share(request):
    """
    If repo is shared from one person to another person, only these two peson
    can remove share.
    If repo is shared from one person to a group, then only the one share the
    repo and group staff can remove share.
    """
    repo_id = request.GET.get('repo_id', '')
    group_id = request.GET.get('gid', '')
    from_email = request.GET.get('from', '')
    if not is_valid_username(from_email):
        return render_error(request, _(u'Argument is not valid'))

    # if request params don't have 'gid', then remove repos that share to
    # to other person; else, remove repos that share to groups
    if not group_id:
        to_email = request.GET.get('to', '')
        if not is_valid_username(to_email):
            return render_error(request, _(u'Argument is not valid'))

        if request.user.username != from_email and \
                request.user.username != to_email:
            return render_permission_error(request, _(u'Failed to remove share'))
        remove_share(repo_id, from_email, to_email)
    else:
        try:
            group_id_int = int(group_id)
        except:
            return render_error(request, _(u'group id is not valid'))

        if not check_group_staff(group_id_int, request.user.username) \
                and request.user.username != from_email:
            return render_permission_error(request, _(u'Failed to remove share'))

        if is_org_group(group_id_int):
            org_id = get_org_id_by_group(group_id_int)
            del_org_group_repo(repo_id, org_id, group_id_int)
        else:
            from seahub.group.views import group_unshare_repo
            group_unshare_repo(request, repo_id, group_id_int, from_email)

    messages.success(request, _('Successfully removed share'))

    next = request.META.get('HTTP_REFERER', None)
    if not next:
        next = SITE_ROOT

    return HttpResponseRedirect(next)
Example #12
0
def group_dismiss(request, group_id):
    """
    Dismiss a group, only group staff can perform this operation.
    """
    next = request.META.get('HTTP_REFERER', None)
    if not next:
        next = SITE_ROOT

    try:
        group_id_int = int(group_id)
    except ValueError:
        return HttpResponseRedirect(next)

    # Check whether user is group staff
    user = request.user.username
    if not ccnet_threaded_rpc.check_group_staff(group_id_int, user):
        return render_permission_error(request, _(u'Only administrators can dismiss the group'))

    try:
        ccnet_threaded_rpc.remove_group(group_id_int, user)
        seafserv_threaded_rpc.remove_repo_group(group_id_int, None)

        if request.user.org:
            org_id = request.user.org['org_id']
            url_prefix = request.user.org['url_prefix']
            ccnet_threaded_rpc.remove_org_group(org_id, group_id_int)
            return HttpResponseRedirect(reverse('org_groups',
                                                args=[url_prefix]))

    except SearpcError, e:
        return render_error(request, _(e.msg))
Example #13
0
def view_shared_file(request, token):
    """
    Preview file via shared link.
    """
    assert token is not None    # Checked by URLconf

    try:
        fileshare = FileShare.objects.get(token=token)
    except FileShare.DoesNotExist:
        raise Http404

    shared_by = fileshare.username
    repo_id = fileshare.repo_id
    repo = get_repo(repo_id)
    if not repo:
        raise Http404

    path = fileshare.path.rstrip('/') # Normalize file path 
    obj_id = seafile_api.get_file_id_by_path(repo_id, path)
    if not obj_id:
        return render_error(request, _(u'File does not exist'))
    file_size = seafile_api.get_file_size(obj_id)
    
    filename = os.path.basename(path)
    filetype, fileext = get_file_type_and_ext(filename)
    access_token = seafserv_rpc.web_get_access_token(repo.id, obj_id,
                                                     'view', '')
    raw_path = gen_file_get_url(access_token, filename)
    inner_path = gen_inner_file_get_url(access_token, filename)

    # get file content
    ret_dict = {'err': '', 'file_content': '', 'encoding': '', 'file_enc': '',
                'file_encoding_list': [], 'html_exists': False,
                'filetype': filetype}
    fsize = get_file_size(obj_id)
    exceeds_limit, err_msg = file_size_exceeds_preview_limit(fsize, filetype)
    if exceeds_limit:
        err = err_msg
    else:
        """Choose different approach when dealing with different type of file."""

        if is_textual_file(file_type=filetype):
            handle_textual_file(request, filetype, inner_path, ret_dict)
        elif filetype == DOCUMENT:
            handle_document(inner_path, obj_id, fileext, ret_dict)
        elif filetype == PDF:
            handle_pdf(inner_path, obj_id, fileext, ret_dict)

        # Increase file shared link view_cnt, this operation should be atomic
        fileshare.view_cnt = F('view_cnt') + 1
        fileshare.save()

        # send statistic messages
        if ret_dict['filetype'] != 'Unknown':
            try:
                obj_size = seafserv_threaded_rpc.get_file_size(obj_id)
                send_message('seahub.stats', 'file-view\t%s\t%s\t%s\t%s' % \
                             (repo.id, shared_by, obj_id, obj_size))
            except SearpcError, e:
                logger.error('Error when sending file-view message: %s' % str(e))
Example #14
0
    def _decorated(request):

        error = False
        if not ENABLE_OAUTH:
            logger.error('OAuth not enabled.')
            error = True
        else:
            if not CLIENT_ID or not CLIENT_SECRET or not AUTHORIZATION_URL \
                    or not REDIRECT_URL or not TOKEN_URL or not USER_INFO_URL \
                    or not SCOPE or not PROVIDER_DOMAIN:
                logger.error('OAuth relevant settings invalid.')
                logger.error('CLIENT_ID: %s' % CLIENT_ID)
                logger.error('CLIENT_SECRET: %s' % CLIENT_SECRET)
                logger.error('AUTHORIZATION_URL: %s' % AUTHORIZATION_URL)
                logger.error('REDIRECT_URL: %s' % REDIRECT_URL)
                logger.error('TOKEN_URL: %s' % TOKEN_URL)
                logger.error('USER_INFO_URL: %s' % USER_INFO_URL)
                logger.error('SCOPE: %s' % SCOPE)
                logger.error('PROVIDER_DOMAIN: %s' % PROVIDER_DOMAIN)
                error = True

        if error:
            return render_error(request,
                                _('Error, please contact administrator.'))

        return func(request)
Example #15
0
    def _decorated(request, *args, **kwargs):
        repo_id = kwargs.get("repo_id", None)
        if not repo_id:
            raise Exception, "Repo id is not found in url."
        repo = get_repo(repo_id)
        if not repo:
            raise Http404
        username = request.user.username
        if repo.encrypted:
            try:
                server_crypto = UserOptions.objects.is_server_crypto(username)
            except CryptoOptionNotSetError:
                return render_to_response("options/set_user_options.html", {}, context_instance=RequestContext(request))

            if (repo.enc_version == 1 or (repo.enc_version == 2 and server_crypto)) and not is_passwd_set(
                repo_id, username
            ):
                return render_to_response(
                    "decrypt_repo_form.html",
                    {"repo": repo, "next": request.get_full_path(), "force_server_crypto": FORCE_SERVER_CRYPTO},
                    context_instance=RequestContext(request),
                )

            if repo.enc_version == 2 and not server_crypto:
                return render_error(request, _(u"Files in this library can not be viewed online."))

        return func(request, *args, **kwargs)
Example #16
0
def repo_history(request, repo_id):
    """
    List library modification histories.
    """
    user_perm = check_folder_permission(request, repo_id, '/')
    if not user_perm:
        return render_permission_error(request, _(u'Unable to view library modification'))

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

    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.props.encrypted and \
            (repo.enc_version == 1 or (repo.enc_version == 2 and server_crypto)):
        try:
            ret = seafserv_rpc.is_passwd_set(repo_id, username)
            if ret == 1:
                password_set = True
        except SearpcError, e:
            return render_error(request, e.msg)

        if not password_set:
            return HttpResponseRedirect(reverse("view_common_lib_dir", args=[repo_id, '']))
Example #17
0
    def _decorated(request, *args, **kwargs):
        repo_id = kwargs.get('repo_id', None)
        if not repo_id:
            raise Exception, 'Repo id is not found in url.'
        repo = get_repo(repo_id)
        if not repo:
            raise Http404
        username = request.user.username
        if repo.encrypted:
            try:
                server_crypto = UserOptions.objects.is_server_crypto(username)
            except CryptoOptionNotSetError:
                return render_to_response('options/set_user_options.html', {
                        }, context_instance=RequestContext(request))

            if (repo.enc_version == 1 or (repo.enc_version == 2 and server_crypto)) \
                    and not is_passwd_set(repo_id, username):
                return render_to_response('decrypt_repo_form.html', {
                        'repo': repo,
                        'next': request.get_full_path(),
                        }, context_instance=RequestContext(request))

            if repo.enc_version == 2 and not server_crypto:
                return render_error(request, _(u'Files in this library can not be viewed online.'))

        return func(request, *args, **kwargs)
Example #18
0
def org_group_remove(request, url_prefix, group_id):
    # Request header may missing HTTP_REFERER, we need to handle that case.
    next = request.META.get("HTTP_REFERER", None)
    if not next:
        next = seahub_settings.SITE_ROOT

    try:
        group_id_int = int(group_id)
    except ValueError:
        return HttpResponseRedirect(next)

    # Check whether is the org group.
    org_id = get_org_id_by_group(group_id_int)
    if request.user.org["org_id"] != org_id:
        return render_permission_error(
            request,
            _(u"This group doesn't belong to current organazation"),
            extra_ctx={"org": request.user.org, "base_template": "org_base.html"},
        )

    try:
        ccnet_threaded_rpc.remove_group(group_id_int, request.user.username)
        seafserv_threaded_rpc.remove_repo_group(group_id_int, None)
        ccnet_threaded_rpc.remove_org_group(org_id, group_id_int)
    except SearpcError, e:
        return render_error(request, e.msg, extra_ctx={"org": request.user.org, "base_template": "org_base.html"})
Example #19
0
def repo_history_view(request, repo_id):
    """View repo in history.
    """
    repo = get_repo(repo_id)
    if not repo:
        raise Http404

    username = request.user.username
    path = get_path_from_request(request)
    user_perm = check_folder_permission(request, repo.id, '/')
    if user_perm is None:
        return render_error(request, _(u'Permission denied'))

    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

    if repo.encrypted and \
        (repo.enc_version == 1 or (repo.enc_version == 2 and server_crypto)) \
        and not is_password_set(repo.id, username):
        return render_to_response(
            'decrypt_repo_form.html', {
                'repo':
                repo,
                'next':
                get_next_url_from_request(request)
                or reverse('repo', args=[repo.id]),
                'force_server_crypto':
                FORCE_SERVER_CRYPTO,
            },
            context_instance=RequestContext(request))

    commit_id = request.GET.get('commit_id', None)
    if commit_id is None:
        return HttpResponseRedirect(reverse('repo', args=[repo.id]))
    current_commit = get_commit(repo.id, repo.version, commit_id)
    if not current_commit:
        current_commit = get_commit(repo.id, repo.version, repo.head_cmmt_id)

    file_list, dir_list, dirent_more = get_repo_dirents(
        request, repo, current_commit, path)
    zipped = get_nav_path(path, repo.name)

    repo_owner = seafile_api.get_repo_owner(repo.id)
    is_repo_owner = True if username == repo_owner else False

    return render_to_response(
        'repo_history_view.html', {
            'repo': repo,
            "is_repo_owner": is_repo_owner,
            'user_perm': user_perm,
            'current_commit': current_commit,
            'dir_list': dir_list,
            'file_list': file_list,
            'path': path,
            'zipped': zipped,
        },
        context_instance=RequestContext(request))
Example #20
0
def personal_wiki(request, page_name="home"):
    username = request.user.username
    wiki_exists = True
    try:
        content, repo, dirent = get_personal_wiki_page(username, page_name)
    except WikiDoesNotExist:
        wiki_exists = False
        owned_repos = seafile_api.get_owned_repo_list(username)
        owned_repos = [r for r in owned_repos if not r.encrypted]
        return render_to_response(
            "wiki/personal_wiki.html",
            {"wiki_exists": wiki_exists, "owned_repos": owned_repos},
            context_instance=RequestContext(request),
        )
    except WikiPageMissing:
        repo = get_personal_wiki_repo(username)
        filename = clean_page_name(page_name) + ".md"
        if not seaserv.post_empty_file(repo.id, "/", filename, username):
            return render_error(request, _("Failed to create wiki page. Please retry later."))
        return HttpResponseRedirect(reverse("personal_wiki", args=[page_name]))
    else:
        url_prefix = reverse("personal_wiki", args=[])
        content = convert_wiki_link(content, url_prefix, repo.id, username)

        # fetch file latest contributor and last modified
        path = "/" + dirent.obj_name
        file_path_hash = hashlib.md5(urllib2.quote(path.encode("utf-8"))).hexdigest()[:12]
        contributors, last_modified, last_commit_id = FileContributors.objects.get_file_contributors(
            repo.id, path.encode("utf-8"), file_path_hash, dirent.obj_id
        )
        latest_contributor = contributors[0] if contributors else None

        wiki_index_exists = True
        index_pagename = "index"
        index_content = None
        try:
            index_content, index_repo, index_dirent = get_personal_wiki_page(username, index_pagename)
        except (WikiDoesNotExist, WikiPageMissing) as e:
            wiki_index_exists = False
        else:
            index_content = convert_wiki_link(index_content, url_prefix, index_repo.id, username)

        return render_to_response(
            "wiki/personal_wiki.html",
            {
                "wiki_exists": wiki_exists,
                "content": content,
                "page": os.path.splitext(dirent.obj_name)[0],
                "last_modified": last_modified,
                "latest_contributor": latest_contributor,
                "path": path,
                "repo_id": repo.id,
                "search_repo_id": repo.id,
                "search_wiki": True,
                "wiki_index_exists": wiki_index_exists,
                "index_content": index_content,
            },
            context_instance=RequestContext(request),
        )
Example #21
0
def group_unshare_repo(request, repo_id, group_id, from_email):
    """
    Unshare a repo in group.
    
    """
    # Check whether group exists
    group = get_group(group_id)
    if not group:
        return render_error(request, _(u"Failed to unshare: the group doesn't exist."))

    # Check whether user is group staff or the one share the repo
    if not check_group_staff(group_id, from_email) and \
            seafserv_threaded_rpc.get_group_repo_owner(repo_id) != from_email:
        return render_permission_error(request, _(u"Operation failed: only administrators and the owner of the library can unshare it."))
        
    if seafserv_threaded_rpc.group_unshare_repo(repo_id, group_id, from_email) != 0:
        return render_error(request, _(u"Failed to unshare: internal error."))
Example #22
0
def personal_wiki(request, page_name="home"):
    username = request.user.username
    wiki_exists = True
    try:
        content, repo, dirent = get_personal_wiki_page(username, page_name)
    except WikiDoesNotExist:
        wiki_exists = False
        owned_repos = seafile_api.get_owned_repo_list(username)
        owned_repos = [r for r in owned_repos if not r.encrypted]
        return render_to_response("wiki/personal_wiki.html", {
                "wiki_exists": wiki_exists,
                "owned_repos": owned_repos,
                }, context_instance=RequestContext(request))
    except WikiPageMissing:
        repo = get_personal_wiki_repo(username)
        filename = clean_page_name(page_name) + '.md'
        if not seaserv.post_empty_file(repo.id, "/", filename, username):
            return render_error(request, _("Failed to create wiki page. Please retry later."))
        return HttpResponseRedirect(reverse('personal_wiki', args=[page_name]))
    else:
        url_prefix = reverse('personal_wiki', args=[])
        content = convert_wiki_link(content, url_prefix, repo.id, username)
        
        # fetch file modified time and modifier
        path = '/' + dirent.obj_name
        try:
            dirent = seafile_api.get_dirent_by_path(repo.id, path)
            if dirent:
                latest_contributor, last_modified = dirent.modifier, dirent.mtime
            else:
                latest_contributor, last_modified = None, 0
        except SearpcError as e:
            logger.error(e)
            latest_contributor, last_modified = None, 0

        wiki_index_exists = True
        index_pagename = 'index'
        index_content = None
        try:
            index_content, index_repo, index_dirent = get_personal_wiki_page(username, index_pagename)
        except (WikiDoesNotExist, WikiPageMissing) as e:
            wiki_index_exists = False
        else:
            index_content = convert_wiki_link(index_content, url_prefix, index_repo.id, username)

        return render_to_response("wiki/personal_wiki.html", { 
            "wiki_exists": wiki_exists,
            "content": content,
            "page": os.path.splitext(dirent.obj_name)[0],
            "last_modified": last_modified,
            "latest_contributor": latest_contributor or _("Unknown"),
            "path": path,
            "repo_id": repo.id,
            "search_repo_id": repo.id,
            "search_wiki": True,
            "wiki_index_exists": wiki_index_exists,
            "index_content": index_content,
            }, context_instance=RequestContext(request))
Example #23
0
File: file.py Project: swpd/seahub
def view_file_via_shared_dir(request, token):
    assert token is not None    # Checked by URLconf

    try:
        fileshare = FileShare.objects.get(token=token)
    except FileShare.DoesNotExist:
        raise Http404

    shared_by = fileshare.username
    repo_id = fileshare.repo_id
    repo = get_repo(repo_id)
    if not repo:
        raise Http404
    
    path = request.GET.get('p', '').rstrip('/')
    if not path:
        raise Http404
    if not path.startswith(fileshare.path): # Can not view upper dir of shared dir
        raise Http404
    zipped = gen_path_link(path, '')

    obj_id = seafile_api.get_file_id_by_path(repo_id, path)
    if not obj_id:
        return render_error(request, _(u'File does not exist'))
    file_size = seafile_api.get_file_size(obj_id)

    filename = os.path.basename(path)
    filetype, fileext = get_file_type_and_ext(filename)
    access_token = seafserv_rpc.web_get_access_token(repo.id, obj_id,
                                                     'view', '')
    raw_path = gen_file_get_url(access_token, filename)
    inner_path = gen_inner_file_get_url(access_token, filename)

    # get file content
    ret_dict = {'err': '', 'file_content': '', 'encoding': '', 'file_enc': '',
                'file_encoding_list': [], 'html_exists': False,
                'filetype': filetype}
    fsize = get_file_size(obj_id)
    exceeds_limit, err_msg = file_size_exceeds_preview_limit(fsize, filetype)
    if exceeds_limit:
        err = err_msg
    else:
        """Choose different approach when dealing with different type of file."""

        if is_textual_file(file_type=filetype):
            handle_textual_file(request, filetype, inner_path, ret_dict)
        elif filetype == DOCUMENT:
            handle_document(inner_path, obj_id, fileext, ret_dict)
        elif filetype == PDF:
            handle_pdf(inner_path, obj_id, fileext, ret_dict)

        # send statistic messages
        try:
            obj_size = seafserv_threaded_rpc.get_file_size(obj_id)
            send_message('seahub.stats', 'file-view\t%s\t%s\t%s\t%s' % \
                         (repo.id, shared_by, obj_id, obj_size))
        except SearpcError, e:
            logger.error('Error when sending file-view message: %s' % str(e))
Example #24
0
def repo_download_dir(request, repo_id):
    repo = get_repo(repo_id)
    if not repo:
        return render_error(request, _(u'Library does not exist'))

    path = request.GET.get('p', '/')
    if path[-1] != '/':         # Normalize dir path
        path += '/'

    if not seafile_api.get_dir_id_by_path(repo.id, path):
        return render_error(request, _('"%s" does not exist.') % path)

    if len(path) > 1:
        dirname = os.path.basename(path.rstrip('/')) # Here use `rstrip` to cut out last '/' in path
    else:
        dirname = repo.name

    allow_download = True if check_folder_permission(request, repo_id, '/') else False

    if allow_download:

        dir_id = seafile_api.get_dir_id_by_commit_and_path(repo.id,
            repo.head_cmmt_id, path)
        try:
            total_size = seafile_api.get_dir_size(repo.store_id,
                repo.version, dir_id)
        except Exception, e:
            logger.error(str(e))
            return render_error(request, _(u'Internal Error'))

        if total_size > MAX_DOWNLOAD_DIR_SIZE:
            return render_error(request, _(u'Unable to download directory "%s": size is too large.') % dirname)

        is_windows = 0
        if is_windows_operating_system(request):
            is_windows = 1

        fake_obj_id = {
            'obj_id': dir_id,
            'dir_name': dirname,
            'is_windows': is_windows
        }

        token = seafile_api.get_fileserver_access_token(
                repo_id, json.dumps(fake_obj_id), 'download-dir', request.user.username)
Example #25
0
def group_wiki_page_edit(request, group, page_name="home"):
    repo = find_wiki_repo(request, group)
    if not repo:
        return render_error(request, _('Wiki is not found.'))

    filepath = "/" + page_name + ".md"
    url = "%srepo/%s/file/edit/?p=%s&from=wiki_page_edit&gid=%s" % \
        (SITE_ROOT, repo.id, filepath, group.id)
    return HttpResponseRedirect(url)
Example #26
0
def _download_dir_from_share_link(request, fileshare, repo, real_path):
    # check whether owner's traffic over the limit
    if user_traffic_over_limit(fileshare.username):
        return render_error(
            request,
            _(u'Unable to access file: share link traffic is used up.'))

    shared_by = fileshare.username
    if real_path == '/':
        dirname = repo.name
    else:
        dirname = os.path.basename(real_path.rstrip('/'))

    dir_id = seafile_api.get_dir_id_by_path(repo.id, real_path)
    if not dir_id:
        return render_error(request,
                            _(u'Unable to download: folder not found.'))

    try:
        total_size = seaserv.seafserv_threaded_rpc.get_dir_size(
            repo.store_id, repo.version, dir_id)
    except Exception as e:
        logger.error(str(e))
        return render_error(request, _(u'Internal Error'))

    if total_size > seaserv.MAX_DOWNLOAD_DIR_SIZE:
        return render_error(
            request,
            _(u'Unable to download directory "%s": size is too large.') %
            dirname)

    token = seafile_api.get_fileserver_access_token(
        repo.id, dir_id, 'download-dir', request.user.username)

    try:
        seaserv.send_message(
            'seahub.stats', 'dir-download\t%s\t%s\t%s\t%s' %
            (repo.id, shared_by, dir_id, total_size))
    except Exception as e:
        logger.error('Error when sending dir-download message: %s' % str(e))

    return HttpResponseRedirect(gen_file_get_url(token, dirname))
Example #27
0
def unsetinnerpub(request, repo_id):
    """Unshare repos in organization or in share admin page.

    Only system admin, organization admin or repo owner can perform this op.
    """
    repo = get_repo(repo_id)
    perm = request.GET.get('permission', None)
    if perm is None:
        return render_error(request, _(u'Argument is not valid'))
    if not repo:
        messages.error(request, _('Failed to unshare the library, as it does not exist.'))
        return HttpResponseRedirect(reverse('share_admin'))

    # permission check
    username = request.user.username
    if is_org_context(request):
        org_id = request.user.org.org_id
        repo_owner = seafile_api.get_org_repo_owner(repo.id)
        is_repo_owner = True if repo_owner == username else False
        if not (request.user.org.is_staff or is_repo_owner):
            raise Http404
    else:
        repo_owner = seafile_api.get_repo_owner(repo.id)
        is_repo_owner = True if repo_owner == username else False
        if not (request.user.is_staff or is_repo_owner):
            raise Http404

    try:
        if is_org_context(request):
            org_id = request.user.org.org_id
            seaserv.seafserv_threaded_rpc.unset_org_inner_pub_repo(org_id,
                                                                   repo.id)
        else:
            seaserv.unset_inner_pub_repo(repo.id)

            origin_repo_id, origin_path = get_origin_repo_info(repo.id)
            if origin_repo_id is not None:
                perm_repo_id = origin_repo_id
                perm_path = origin_path
            else:
                perm_repo_id = repo.id
                perm_path =  '/'

            send_perm_audit_msg('delete-repo-perm', username, 'all',
                                perm_repo_id, perm_path, perm)

        messages.success(request, _('Unshare "%s" successfully.') % repo.name)
    except SearpcError:
        messages.error(request, _('Failed to unshare "%s".') % repo.name)

    referer = request.META.get('HTTP_REFERER', None)
    next = settings.SITE_ROOT if referer is None else referer

    return HttpResponseRedirect(next)
Example #28
0
def group_wiki_pages(request, group):
    """
    List wiki pages in group.
    """
    repo = find_wiki_repo(request, group)
    if not repo:
        return render_error(request, _('Wiki is not found.'))

    try:
        dir_id = seafserv_threaded_rpc.get_dir_id_by_path(repo.id, '/')
    except SearpcError, e:
        dir_id = None
Example #29
0
def group_wiki_page_new(request, group, page_name="home"):
    if request.method == 'POST':
        form = MessageForm(request.POST)

        page_name = request.POST.get('page_name', '')
        if not page_name:
            return HttpResponseRedirect(request.META.get('HTTP_REFERER'))
        page_name = normalize_page_name(page_name) # normalize page name

        repo = find_wiki_repo(request, group)
        if not repo:
            return render_error(request, _('Wiki is not found.'))
        
        filename = page_name + ".md"
        filepath = "/" + page_name + ".md"
        if not post_empty_file(repo.id, "/", filename, request.user.username):
            return render_error(request, _('Failed to create wiki page. Please retry later.'))

        url = "%srepo/%s/file/edit/?p=%s&from=wiki_page_new&gid=%s" % \
            (SITE_ROOT, repo.id, filepath, group.id)
        return HttpResponseRedirect(url)
Example #30
0
def personal_wiki_page_edit(request, page_name="home"):
    try:
        repo = get_personal_wiki_repo(request.user.username)
    except WikiDoesNotExist:
        return render_error(request, _('Wiki is not found.'))

    filepath = "/" + page_name + ".md"
    url = "%s?p=%s&from=personal_wiki_page_edit" % (
            reverse('file_edit', args=[repo.id]),
            urllib2.quote(filepath.encode('utf-8')))

    return HttpResponseRedirect(url)
Example #31
0
def view_shared_file(request, token):
    """
    Preview file via shared link.
    """
    assert token is not None  # Checked by URLconf

    try:
        fileshare = FileShare.objects.get(token=token)
    except FileShare.DoesNotExist:
        raise Http404

    if fileshare.use_passwd:
        valid_access = cache.get('SharedLink_' + request.user.username + token,
                                 False)
        if not valid_access:
            d = {
                'token': token,
                'view_name': 'view_shared_file',
            }
            if request.method == 'POST':
                post_values = request.POST.copy()
                post_values['enc_password'] = fileshare.password
                form = SharedLinkPasswordForm(post_values)
                d['form'] = form
                if form.is_valid():
                    # set cache for non-anonymous user
                    if request.user.is_authenticated():
                        cache.set(
                            'SharedLink_' + request.user.username + token,
                            True, settings.SHARE_ACCESS_PASSWD_TIMEOUT)
                else:
                    return render_to_response(
                        'share_access_validation.html',
                        d,
                        context_instance=RequestContext(request))
            else:
                return render_to_response(
                    'share_access_validation.html',
                    d,
                    context_instance=RequestContext(request))

    shared_by = fileshare.username
    repo_id = fileshare.repo_id
    repo = get_repo(repo_id)
    if not repo:
        raise Http404

    path = fileshare.path.rstrip('/')  # Normalize file path
    obj_id = seafile_api.get_file_id_by_path(repo_id, path)
    if not obj_id:
        return render_error(request, _(u'File does not exist'))
    file_size = seafile_api.get_file_size(obj_id)

    filename = os.path.basename(path)
    filetype, fileext = get_file_type_and_ext(filename)
    access_token = seafserv_rpc.web_get_access_token(repo.id, obj_id, 'view',
                                                     '')
    raw_path = gen_file_get_url(access_token, filename)
    inner_path = gen_inner_file_get_url(access_token, filename)

    # get file content
    ret_dict = {
        'err': '',
        'file_content': '',
        'encoding': '',
        'file_enc': '',
        'file_encoding_list': [],
        'html_exists': False,
        'filetype': filetype
    }
    fsize = get_file_size(obj_id)
    exceeds_limit, err_msg = file_size_exceeds_preview_limit(fsize, filetype)
    if exceeds_limit:
        err = err_msg
    else:
        """Choose different approach when dealing with different type of file."""

        if is_textual_file(file_type=filetype):
            handle_textual_file(request, filetype, inner_path, ret_dict)
        elif filetype == DOCUMENT:
            handle_document(inner_path, obj_id, fileext, ret_dict)
        elif filetype == SPREADSHEET:
            handle_spreadsheet(inner_path, obj_id, fileext, ret_dict)
        elif filetype == OPENDOCUMENT:
            if fsize == 0:
                ret_dict['err'] = _(u'Invalid file format.')
        elif filetype == PDF:
            handle_pdf(inner_path, obj_id, fileext, ret_dict)

        # Increase file shared link view_cnt, this operation should be atomic
        fileshare.view_cnt = F('view_cnt') + 1
        fileshare.save()

        # send statistic messages
        if ret_dict['filetype'] != 'Unknown':
            try:
                obj_size = seafserv_threaded_rpc.get_file_size(obj_id)
                send_message('seahub.stats', 'file-view\t%s\t%s\t%s\t%s' % \
                             (repo.id, shared_by, obj_id, obj_size))
            except SearpcError, e:
                logger.error('Error when sending file-view message: %s' %
                             str(e))
Example #32
0
def dingtalk_connect_callback(request):

    if not ENABLE_DINGTALK:
        return render_error(request, _('Error, please contact administrator.'))

    state = request.GET.get('state', '')
    if not state or state != request.session.get('dingtalk_connect_state', ''):
        logger.error('invalid state')
        return render_error(request, _('Error, please contact administrator.'))

    timestamp = str(int(time.time() * 1000)).encode('utf-8')
    appsecret = DINGTALK_QR_CONNECT_APP_SECRET.encode('utf-8')
    signature = base64.b64encode(
        hmac.new(appsecret, timestamp, digestmod=sha256).digest())
    parameters = {
        'accessKey': DINGTALK_QR_CONNECT_APP_ID,
        'timestamp': timestamp,
        'signature': signature,
    }

    code = request.GET.get('code')
    data = {"tmp_auth_code": code}

    full_user_info_url = DINGTALK_QR_CONNECT_USER_INFO_URL + '?' + urllib.parse.urlencode(
        parameters)
    user_info_resp = requests.post(full_user_info_url, data=json.dumps(data))
    user_info = user_info_resp.json()['user_info']

    # seahub authenticate user
    if 'unionid' not in user_info:
        logger.error('Required user info not found.')
        logger.error(user_info)
        return render_error(request, _('Error, please contact administrator.'))

    username = request.user.username
    dingtalk_union_id = user_info['unionid']

    auth_user = SocialAuthUser.objects.get_by_provider_and_uid(
        'dingtalk', dingtalk_union_id)
    if auth_user:
        logger.error('dingtalk account already exists %s' % dingtalk_union_id)
        return render_error(request, '出错了,此钉钉账号已被绑定')

    SocialAuthUser.objects.add(username, 'dingtalk', dingtalk_union_id)

    # update user's profile
    name = user_info['nick'] if 'nick' in user_info else ''
    if name:

        profile = Profile.objects.get_profile_by_user(username)
        if not profile:
            profile = Profile(user=username)

        profile.nickname = name.strip()
        profile.save()

    user_detail_info = dingtalk_get_detailed_user_info(user_info['unionid'])
    contact_email = user_detail_info.get('email', '')
    if contact_email:
        profile.contact_email = contact_email
        profile.save()

    response = HttpResponseRedirect(
        request.session['dingtalk_connect_redirect'])
    return response
Example #33
0
def render_repo(request, repo):
    """Steps to show repo page:
    If user has permission to view repo
      If repo is encrypt and password is not set on server
        return decrypt repo page
      If repo is not encrypt or password is set on server
        Show repo direntries based on requested path
    If user does not have permission to view repo
      return permission deny page
    """
    username = request.user.username
    path = get_path_from_request(request)
    user_perm = check_repo_access_permission(repo.id, request.user)
    if user_perm is None:
        return render_error(request, _(u'Permission denied'))

    sub_lib_enabled = UserOptions.objects.is_sub_lib_enabled(username)

    server_crypto = False
    if repo.encrypted:
        try:
            server_crypto = UserOptions.objects.is_server_crypto(username)
        except CryptoOptionNotSetError:
            return render_to_response('options/set_user_options.html', {},
                                      context_instance=RequestContext(request))

        if (repo.enc_version == 1 or (repo.enc_version == 2 and server_crypto)) \
                and not is_password_set(repo.id, username):
            return render_to_response('decrypt_repo_form.html', {
                'repo':
                repo,
                'next':
                get_next_url_from_request(request)
                or reverse('repo', args=[repo.id]),
                'force_server_crypto':
                FORCE_SERVER_CRYPTO,
            },
                                      context_instance=RequestContext(request))

    # query context args
    fileserver_root = get_fileserver_root()
    max_upload_file_size = get_max_upload_file_size()

    protocol = request.is_secure() and 'https' or 'http'
    domain = RequestSite(request).domain

    for g in request.user.joined_groups:
        g.avatar = grp_avatar(g.id, 20)

    head_commit = get_commit(repo.id, repo.version, repo.head_cmmt_id)
    if not head_commit:
        raise Http404

    if new_merge_with_no_conflict(head_commit):
        info_commit = get_commit_before_new_merge(head_commit)
    else:
        info_commit = head_commit

    repo_size = get_repo_size(repo.id)
    no_quota = is_no_quota(repo.id)
    if is_org_context(request):
        repo_owner = seafile_api.get_org_repo_owner(repo.id)
    else:
        repo_owner = seafile_api.get_repo_owner(repo.id)
    is_repo_owner = True if repo_owner == username else False
    if is_repo_owner and not repo.is_virtual:
        show_repo_settings = True
    else:
        show_repo_settings = False

    file_list, dir_list, dirent_more = get_repo_dirents_with_perm(request,
                                                                  repo,
                                                                  head_commit,
                                                                  path,
                                                                  offset=0,
                                                                  limit=100)
    more_start = None
    if dirent_more:
        more_start = 100
    zipped = get_nav_path(path, repo.name)
    repo_groups = get_shared_groups_by_repo_and_user(repo.id, username)
    if len(repo_groups) > 1:
        repo_group_str = render_to_string("snippets/repo_group_list.html",
                                          {'groups': repo_groups})
    else:
        repo_group_str = ''

    fileshare = get_fileshare(repo.id, username, path)
    dir_shared_link = get_dir_share_link(fileshare)
    uploadlink = get_uploadlink(repo.id, username, path)
    dir_shared_upload_link = get_dir_shared_upload_link(uploadlink)

    for f in file_list:
        file_path = posixpath.join(path, f.obj_name)
        if allow_generate_thumbnail(request, repo.id, file_path):
            f.allow_generate_thumbnail = True
            if os.path.exists(
                    os.path.join(THUMBNAIL_ROOT, str(THUMBNAIL_DEFAULT_SIZE),
                                 f.obj_id)):
                src = get_thumbnail_src(repo.id, THUMBNAIL_DEFAULT_SIZE,
                                        file_path)
                f.encoded_thumbnail_src = urlquote(src)

    return render_to_response('repo.html', {
        'repo': repo,
        'user_perm': user_perm,
        'repo_owner': repo_owner,
        'is_repo_owner': is_repo_owner,
        'show_repo_settings': show_repo_settings,
        'current_commit': head_commit,
        'info_commit': info_commit,
        'password_set': True,
        'repo_size': repo_size,
        'dir_list': dir_list,
        'file_list': file_list,
        'dirent_more': dirent_more,
        'more_start': more_start,
        'path': path,
        'zipped': zipped,
        'groups': repo_groups,
        'repo_group_str': repo_group_str,
        'no_quota': no_quota,
        'max_upload_file_size': max_upload_file_size,
        'fileserver_root': fileserver_root,
        'protocol': protocol,
        'domain': domain,
        'fileshare': fileshare,
        'dir_shared_link': dir_shared_link,
        'uploadlink': uploadlink,
        'dir_shared_upload_link': dir_shared_upload_link,
        'ENABLE_SUB_LIBRARY': ENABLE_SUB_LIBRARY,
        'server_crypto': server_crypto,
        'sub_lib_enabled': sub_lib_enabled,
        'enable_upload_folder': ENABLE_UPLOAD_FOLDER,
        'ENABLE_THUMBNAIL': ENABLE_THUMBNAIL,
    },
                              context_instance=RequestContext(request))
Example #34
0
def dtable_asset_preview(request, workspace_id, dtable_id, path):

    # resource check
    workspace = Workspaces.objects.get_workspace_by_id(workspace_id)
    if not workspace:
        return render_error(request, 'Workspace does not exist.')

    repo_id = workspace.repo_id
    repo = seafile_api.get_repo(repo_id)
    if not repo:
        return render_error(request, 'Library does not exist.')

    dtable = DTables.objects.get_dtable_by_uuid(dtable_id)
    if not dtable:
        return render_error(request, 'DTable does not exist.')

    asset_path = normalize_file_path(os.path.join('/asset', dtable_id, path))
    asset_id = seafile_api.get_file_id_by_path(repo_id, asset_path)
    if not asset_id:
        return render_error(request, 'Asset file does not exist.')

    # permission check
    username = request.user.username
    if not check_dtable_permission(username, workspace, dtable):
        return render_permission_error(request, _('Permission denied.'))

    file_enc = request.GET.get('file_enc', 'auto')
    if file_enc not in FILE_ENCODING_LIST:
        file_enc = 'auto'

    token = seafile_api.get_fileserver_access_token(repo_id,
                                                    asset_id,
                                                    'view',
                                                    '',
                                                    use_onetime=False)

    file_name = os.path.basename(normalize_file_path(path))
    file_type, file_ext = get_file_type_and_ext(file_name)

    inner_path = gen_inner_file_get_url(token, file_name)
    error_msg, file_content, encoding = get_file_content(
        file_type, inner_path, file_enc)

    raw_path = gen_file_get_url(token, file_name)
    download_url = '%s/workspace/%s/asset/%s/%s?dl=1' % (
        DTABLE_WEB_SERVICE_URL.strip('/'), workspace_id, dtable_id, path)

    return_dict = {
        'repo': repo,
        'filename': file_name,
        'file_path': asset_path,
        'file_type': file_type,
        'file_ext': file_ext,
        'raw_path': raw_path,
        'download_url': download_url,
        'file_content': file_content,
        'err':
        'File preview unsupported' if file_type == 'Unknown' else error_msg,
    }

    return render(request, 'dtable_asset_file_view_react.html', return_dict)
Example #35
0
def dtable_form_edit(request, token):
    """
    Permission:
    1. owner
    2. group member
    3. shared user with `rw` permission
    """

    # resource check
    form_obj = DTableForms.objects.get_form_by_token(token)
    if not form_obj:
        return render_error(request, 'Table\'s form does not exist.')

    workspace_id = form_obj.workspace_id
    workspace = Workspaces.objects.get_workspace_by_id(workspace_id)
    if not workspace:
        return render_error(request, 'Workspace does not exist.')

    dtable_uuid = form_obj.dtable_uuid
    dtable = DTables.objects.get_dtable_by_uuid(dtable_uuid)
    if not dtable:
        return render_error(request, 'Table does not exist.')

    # permission check
    username = request.user.username
    permission = check_dtable_permission(username, workspace, dtable)
    if permission != PERMISSION_READ_WRITE:
        return render_permission_error(request, 'Permission denied.')

    if not check_user_workspace_quota(workspace):
        return render_error(request, 'Asset quota exceeded.')

    # generate json web token
    payload = {
        'exp': int(time.time()) + 60 * 5,
        'dtable_uuid': dtable_uuid,
        'username': "******",
        'permission': permission,
    }

    try:
        access_token = jwt.encode(payload,
                                  DTABLE_PRIVATE_KEY,
                                  algorithm='HS256')
    except Exception as e:
        logger.error(e)
        return render_error(request, _('Internal Server Error'))

    url = '%s/api/v1/dtables/%s/metadata/' % (DTABLE_SERVER_URL.strip('/'),
                                              dtable_uuid)
    req = requests.Request(
        url, headers={"Authorization": "Token %s" % access_token.decode()})

    try:
        dtable_metadata = requests.urlopen(req).read().decode()
    except Exception as e:
        logger.error(e)
        return render_error(request, _('Internal Server Error'))

    share_type = form_obj.share_type
    shared_groups = list()
    if share_type == SHARED_GROUPS:
        group_ids = DTableFormShare.objects.list_by_form(form_obj)
        shared_groups = [{
            'id': group_id,
            'name': group_id_to_name(group_id)
        } for group_id in group_ids]

    return_dict = {
        'dtable_metadata': dtable_metadata,
        'dtable_name': dtable.name,
        'workspace_id': workspace_id,
        'form_id': form_obj.form_id,
        'form_config': form_obj.form_config,
        'dtable_uuid': dtable.uuid.hex,
        'dtable_web_service_url': DTABLE_WEB_SERVICE_URL,
        'form_token': token,
        'share_type': share_type,
        'shared_groups': json.dumps(shared_groups),
    }

    return render(request, 'dtable_edit_form_view_react.html', return_dict)
Example #36
0
def dtable_plugin_asset_view(request, workspace_id, name, plugin_id, path):
    """
    Permission:
    1. owner
    2. group member
    3. shared user
    """

    try:
        plugin_record = DTablePlugins.objects.get(pk=plugin_id)
    except DTablePlugins.DoesNotExist:
        error_msg = 'Plugin %s not found.' % plugin_id
        return render_error(request, error_msg)

    workspace = Workspaces.objects.get_workspace_by_id(workspace_id)
    if not workspace:
        error_msg = 'Workspace %s not found.' % workspace_id
        return render_error(request, error_msg)

    if '@seafile_group' in workspace.owner:
        group_id = workspace.owner.split('@')[0]
        group = ccnet_api.get_group(int(group_id))
        if not group:
            error_msg = 'Group %s not found.' % group_id
            return render_error(request, error_msg)
    table_name = name
    dtable = DTables.objects.get_dtable(workspace, table_name)
    if not dtable:
        error_msg = 'DTable %s not found.' % table_name
        return render_error(request, error_msg)

    # permission check
    username = request.user.username
    permission = check_dtable_permission(username, workspace, dtable)
    if not permission:
        error_msg = 'Permission denied.'
        return render_error(request, error_msg)

    repo_id = workspace.repo_id
    repo = seafile_api.get_repo(repo_id)
    if not repo:
        error_msg = 'Library %s not found.' % repo_id
        return render_error(request, error_msg)

    plugin_file_path = os.path.join('/asset', str(dtable.uuid), 'plugins',
                                    plugin_record.name)
    asset_path = os.path.join(plugin_file_path, path)

    plugin_file_dir_id = seafile_api.get_file_id_by_path(repo_id, asset_path)
    if not plugin_file_dir_id:
        return render_error(request, 'Asset file does not exist.')

    token = seafile_api.get_fileserver_access_token(workspace.repo_id,
                                                    plugin_file_dir_id,
                                                    'view',
                                                    '',
                                                    use_onetime=False)

    url = gen_file_get_url(token, asset_path)
    import requests
    r = requests.get(url)
    response = HttpResponse(r.content)

    content_type = mimetypes.guess_type(path)
    if type:
        response['Content-Type'] = content_type[0]

    return response
Example #37
0
def dtable_file_view(request, workspace_id, name):
    """

    Permission:
    1. owner
    2. group member
    3. shared user
    """
    # resource check
    workspace = Workspaces.objects.get_workspace_by_id(workspace_id)
    if not workspace:
        return render_error(request, 'Workspace does not exist.')

    group_id = ''
    if '@seafile_group' in workspace.owner:
        group_id = workspace.owner.split('@')[0]
        group = seaserv.get_group(group_id)
        if not group:
            error_msg = 'Group %s not found.' % group_id
            return render_error(request, error_msg)

    repo_id = workspace.repo_id
    repo = seafile_api.get_repo(repo_id)
    if not repo:
        return render_error(request, 'Library does not exist.')

    dtable = DTables.objects.get_dtable(workspace, name)
    if not dtable:
        return render_error(request, 'DTable does not exist.')

    # permission check
    username = request.user.username
    permission = check_dtable_permission(username, workspace, dtable)
    if not permission:
        return render_permission_error(request, _('Permission denied.'))

    is_admin = False
    if group_id:
        is_admin = is_group_admin_or_owner(group_id, username)
    else:
        # open your own dtable
        is_admin = username == workspace.owner

    seafile_url = ''
    repo_api_token = ''
    try:
        seafile_connector = SeafileConnectors.objects.get(dtable=dtable)
        seafile_url = seafile_connector.seafile_url
        repo_api_token = seafile_connector.repo_api_token
    except SeafileConnectors.DoesNotExist:
        pass

    return_dict = {
        'version':
        SEATABLE_VERSION,
        'dtable_baidu_map_key':
        DTABLE_BAIDU_MAP_KEY,
        'dtable_google_map_key':
        DTABLE_GOOGLE_MAP_KEY,
        'seatable_market_url':
        SEATABLE_MARKET_URL,
        'filename':
        name,
        'workspace_id':
        workspace_id,
        'dtable_uuid':
        dtable.uuid.hex,
        'permission':
        permission if check_user_workspace_quota(workspace) else 'r',
        'media_url':
        MEDIA_URL,
        'seafile_url':
        seafile_url,
        'repo_api_token':
        repo_api_token,
        'dtable_server':
        DTABLE_SERVER_URL,
        'dtable_socket':
        DTABLE_SOCKET_URL,
        'dtable_enable_geolocation_column':
        DTABLE_ENABLE_GEOLOCATION_COLUMN,
        'is_admin':
        is_admin,
        'asset_quota_exceeded':
        dtable.creator == request.user.username
        and not check_user_workspace_quota(workspace),
    }

    return render(request, 'dtable_file_view_react.html', return_dict)
Example #38
0
def oauth_callback(request):
    """ Step 3: Retrieving an access token.
    The user has been redirected back from the provider to your registered
    callback URL. With this redirection comes an authorization code included
    in the redirect URL. We will use that to obtain an access token.
    """
    session = OAuth2Session(client_id=CLIENT_ID,
                            scope=SCOPE,
                            state=request.session.get('oauth_state', None),
                            redirect_uri=REDIRECT_URL)

    try:
        token = session.fetch_token(
            TOKEN_URL,
            client_secret=CLIENT_SECRET,
            authorization_response=request.get_full_path())

        if 'user_id' in session._client.__dict__['token']:
            # used for sjtu.edu.cn
            # https://xjq12311.gitbooks.io/sjtu-engtc/content/
            user_id = session._client.__dict__['token']['user_id']
            user_info_resp = session.get(USER_INFO_URL +
                                         '?user_id=%s' % user_id)
        else:
            user_info_url = USER_INFO_URL
            if ACCESS_TOKEN_IN_URI:
                code = request.GET.get('code')
                user_info_url = USER_INFO_URL + '?access_token=%s&code=%s' % (
                    token['access_token'], code)
            user_info_resp = session.get(user_info_url)

    except Exception as e:
        logger.error(e)
        return render_error(request, _('Error, please contact administrator.'))

    def format_user_info(user_info_resp):
        logger.info('user info resp: %s' % user_info_resp.text)
        error = False
        user_info = {}
        user_info_json = user_info_resp.json()

        for item, attr in list(ATTRIBUTE_MAP.items()):
            required, user_attr = attr
            value = user_info_json.get(item, '')

            if value:
                # ccnet email
                if user_attr == 'email':
                    user_info[user_attr] = value if is_valid_email(str(value)) else \
                            '%s@%s' % (str(value), PROVIDER_DOMAIN)
                else:
                    user_info[user_attr] = value
            elif required:
                error = True

        return user_info, error

    user_info, error = format_user_info(user_info_resp)
    if error:
        logger.error('Required user info not found.')
        logger.error(user_info)
        return render_error(request, _('Error, please contact administrator.'))

    # seahub authenticate user
    email = user_info['email']

    try:
        user = auth.authenticate(remote_user=email)
    except User.DoesNotExist:
        user = None

    if not user or not user.is_active:
        logger.error('User %s not found or inactive.' % email)
        # a page for authenticate user failed
        return render_error(request, _('User %s not found.') % email)

    # User is valid.  Set request.user and persist user in the session
    # by logging the user in.
    request.user = user
    auth.login(request, user)

    # update user's profile
    name = user_info['name'] if 'name' in user_info else ''
    contact_email = user_info['contact_email'] if \
            'contact_email' in user_info else ''

    profile = Profile.objects.get_profile_by_user(email)
    if not profile:
        profile = Profile(user=email)

    if name:
        profile.nickname = name.strip()
        profile.save()

    if contact_email:
        profile.contact_email = contact_email.strip()
        profile.save()

    # generate auth token for Seafile client
    api_token = get_api_token(request)

    # redirect user to home page
    response = HttpResponseRedirect(request.session['oauth_redirect'])
    response.set_cookie('seahub_auth', email + '@' + api_token.key)
    return response
Example #39
0
def file_revisions(request, repo_id):
    """List file revisions in file version history page.
    """
    repo = get_repo(repo_id)
    if not repo:
        error_msg = _(u"Library does not exist")
        return render_error(request, error_msg)

    # perm check
    if not check_folder_permission(request, repo_id, '/'):
        error_msg = _(u"Permission denied.")
        return render_error(request, error_msg)

    path = request.GET.get('p', '/')
    if not path:
        return render_error(request)

    if path[-1] == '/':
        path = path[:-1]

    u_filename = os.path.basename(path)

    filetype, file_ext = [x.lower() for x in get_file_type_and_ext(u_filename)]
    if filetype == 'text' or filetype == 'markdown':
        can_compare = True
    else:
        can_compare = False

    # Check whether user is repo owner
    if validate_owner(request, repo_id):
        is_owner = True
    else:
        is_owner = False

    zipped = gen_path_link(path, repo.name)

    can_revert_file = True
    username = request.user.username

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

    repo_perm = seafile_api.check_permission_by_path(repo_id, path, username)
    if repo_perm != 'rw' or (is_locked and not locked_by_me):
        can_revert_file = False

    # for 'go back'
    referer = request.GET.get('referer', '')

    # Whether use new file revisions page which read file history from db.
    if request.GET.get('_new', None) is not None:
        if request.GET.get('_new') == '0':
            use_new_page = False
        else:
            use_new_page = True
    else:
        suffix_list = seafevents_api.get_file_history_suffix()
        if suffix_list and isinstance(suffix_list, list):
            suffix_list = [x.lower() for x in suffix_list]
        else:
            logger.error('Wrong type of suffix_list: %s' % repr(suffix_list))
            suffix_list = []
        use_new_page = True if file_ext in suffix_list else False

    if use_new_page:
        return render(
            request, 'file_revisions_new.html', {
                'repo': repo,
                'path': path,
                'u_filename': u_filename,
                'zipped': zipped,
                'is_owner': is_owner,
                'can_compare': can_compare,
                'can_revert_file': can_revert_file,
                'referer': referer,
            })

    return render(
        request, 'file_revisions.html', {
            'repo': repo,
            'path': path,
            'u_filename': u_filename,
            'zipped': zipped,
            'is_owner': is_owner,
            'can_compare': can_compare,
            'can_revert_file': can_revert_file,
            'can_download_file': parse_repo_perm(repo_perm).can_download,
            'referer': referer,
        })
Example #40
0
    if repo.props.encrypted and \
            (repo.enc_version == 1 or (repo.enc_version == 2 and server_crypto)):
        try:
            ret = seafserv_rpc.is_passwd_set(repo_id, username)
            if ret == 1:
                password_set = True
        except SearpcError, e:
            return render_error(request, e.msg)

        if not password_set:
            reverse_url = reverse('lib_view', args=[repo_id, repo.name, ''])
            return HttpResponseRedirect(reverse_url)

    commit_id = request.GET.get('commit_id', '')
    if not commit_id:
        return render_error(request, _(u'Please specify history ID'))

    try:
        seafserv_threaded_rpc.revert_on_server(repo_id, commit_id,
                                               request.user.username)
        messages.success(request, _('Successfully restored the library.'))
    except SearpcError, e:
        if e.msg == 'Bad arguments':
            return render_error(request, _(u'Invalid arguments.'))
        elif e.msg == 'No such repo':
            return render_error(request, _(u'Library does not exist'))
        elif e.msg == "Commit doesn't exist":
            return render_error(request,
                                _(u'History you specified does not exist'))
        else:
            return render_error(request, _(u'Unknown error'))
Example #41
0
def repo_download_dir(request, repo_id):
    repo = get_repo(repo_id)
    if not repo:
        return render_error(request, _('Library does not exist'))

    path = request.GET.get('p', '/')
    if path[-1] != '/':  # Normalize dir path
        path += '/'

    if not seafile_api.get_dir_id_by_path(repo.id, path):
        return render_error(request, _('"%s" does not exist.') % path)

    if len(path) > 1:
        dirname = os.path.basename(
            path.rstrip('/'))  # Here use `rstrip` to cut out last '/' in path
    else:
        dirname = repo.name

    allow_download = parse_repo_perm(
        check_folder_permission(request, repo_id, '/')).can_download

    if allow_download:

        dir_id = seafile_api.get_dir_id_by_commit_and_path(
            repo.id, repo.head_cmmt_id, path)
        try:
            total_size = seafile_api.get_dir_size(repo.store_id, repo.version,
                                                  dir_id)
        except Exception as e:
            logger.error(str(e))
            return render_error(request, _('Internal Server Error'))

        if total_size > MAX_DOWNLOAD_DIR_SIZE:
            return render_error(
                request,
                _('Unable to download directory "%s": size is too large.') %
                dirname)

        is_windows = 0
        if is_windows_operating_system(request):
            is_windows = 1

        fake_obj_id = {
            'obj_id': dir_id,
            'dir_name': dirname,
            'is_windows': is_windows
        }

        token = seafile_api.get_fileserver_access_token(
            repo_id, json.dumps(fake_obj_id), 'download-dir',
            request.user.username)

        if not token:
            return render_error(request, _('Internal Server Error'))

    else:
        return render_error(request, _('Unable to download "%s"') % dirname)

    url = gen_file_get_url(token, dirname)
    from seahub.views.file import send_file_access_msg
    send_file_access_msg(request, repo, path, 'web')
    return redirect(url)
Example #42
0
def repo_history(request, repo_id):
    """
    List library modification histories.
    """
    user_perm = check_folder_permission(request, repo_id, '/')
    if not user_perm:
        return render_permission_error(
            request, _('Unable to view library modification'))

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

    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.props.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 SearpcError as e:
            return render_error(request, e.msg)

        if not password_set:
            reverse_url = reverse('lib_view', args=[repo_id, repo.name, ''])
            return HttpResponseRedirect(reverse_url)

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

    per_page = 100
    commits_all = get_commits(repo_id, per_page * (current_page - 1),
                              per_page + 1)
    commits = commits_all[:per_page]
    for c in commits:
        c.show = False if new_merge_with_no_conflict(c) else True

    show_label = False
    if ENABLE_REPO_SNAPSHOT_LABEL:
        show_label = True
        snapshot_labels = RevisionTags.objects.filter(repo_id=repo_id)
        for c in commits:
            if c.show:
                c.labels = []
                for label in snapshot_labels:
                    if label.revision_id == c.id:
                        c.labels.append(label.tag.name)

    if len(commits_all) == per_page + 1:
        page_next = True
    else:
        page_next = False

    # for 'go back'
    referer = request.GET.get('referer', '')

    #template = 'repo_history.html'
    template = 'repo_history_react.html'

    return render(
        request, template, {
            "repo": repo,
            "commits": commits,
            'current_page': current_page,
            'prev_page': current_page - 1,
            'next_page': current_page + 1,
            'page_next': page_next,
            'user_perm': user_perm,
            'show_label': show_label,
            'referer': referer,
        })
Example #43
0
def react_fake_view(request, **kwargs):

    username = request.user.username

    if resolve(request.path).url_name == 'lib_view':

        repo_id = kwargs.get('repo_id', '')
        path = kwargs.get('path', '')

        if repo_id and path and \
                not check_folder_permission(request, repo_id, path):

            converted_repo_path = seafile_api.convert_repo_path(
                repo_id, path, username)
            if not converted_repo_path:
                error_msg = 'Permission denied.'
                return render_error(request, error_msg)

            repo_path_dict = json.loads(converted_repo_path)

            converted_repo_id = repo_path_dict['repo_id']
            converted_repo = seafile_api.get_repo(converted_repo_id)
            if not converted_repo:
                error_msg = 'Library %s not found.' % converted_repo_id
                return render_error(request, error_msg)

            converted_path = repo_path_dict['path']
            if not seafile_api.get_dirent_by_path(converted_repo_id,
                                                  converted_path):
                error_msg = 'Dirent %s not found.' % converted_path
                return render_error(request, error_msg)

            if not check_folder_permission(request, converted_repo_id,
                                           converted_path):
                error_msg = 'Permission denied.'
                return render_error(request, error_msg)

            next_url = reverse('lib_view',
                               args=[
                                   converted_repo_id, converted_repo.repo_name,
                                   converted_path.strip('/')
                               ])
            return HttpResponseRedirect(next_url)

    guide_enabled = UserOptions.objects.is_user_guide_enabled(username)
    if guide_enabled:
        create_default_library(request)

    try:
        expire_days = seafile_api.get_server_config_int(
            'library_trash', 'expire_days')
    except Exception as e:
        logger.error(e)
        expire_days = -1

    folder_perm_enabled = True if is_pro_version(
    ) and ENABLE_FOLDER_PERM else False

    try:
        max_upload_file_size = seafile_api.get_server_config_int(
            'fileserver', 'max_upload_size')
    except Exception as e:
        logger.error(e)
        max_upload_file_size = -1

    return render(
        request, "react_app.html", {
            "onlyoffice_desktop_editors_portal_login":
            ONLYOFFICE_DESKTOP_EDITORS_PORTAL_LOGIN,
            "guide_enabled": guide_enabled,
            'trash_repos_expire_days': expire_days if expire_days > 0 else 30,
            'dtable_web_server': DTABLE_WEB_SERVER,
            'max_upload_file_size': max_upload_file_size,
            'seafile_collab_server': SEAFILE_COLLAB_SERVER,
            'storages': get_library_storages(request),
            'library_templates': list(LIBRARY_TEMPLATES.keys()),
            'enable_repo_snapshot_label': settings.ENABLE_REPO_SNAPSHOT_LABEL,
            'resumable_upload_file_block_size':
            settings.RESUMABLE_UPLOAD_FILE_BLOCK_SIZE,
            'max_number_of_files_for_fileupload':
            settings.MAX_NUMBER_OF_FILES_FOR_FILEUPLOAD,
            'share_link_expire_days_default': SHARE_LINK_EXPIRE_DAYS_DEFAULT,
            'share_link_expire_days_min': SHARE_LINK_EXPIRE_DAYS_MIN,
            'share_link_expire_days_max': SHARE_LINK_EXPIRE_DAYS_MAX,
            'upload_link_expire_days_default': UPLOAD_LINK_EXPIRE_DAYS_DEFAULT,
            'upload_link_expire_days_min': UPLOAD_LINK_EXPIRE_DAYS_MIN,
            'upload_link_expire_days_max': UPLOAD_LINK_EXPIRE_DAYS_MAX,
            'enable_encrypted_library': config.ENABLE_ENCRYPTED_LIBRARY,
            'enable_repo_history_setting': config.ENABLE_REPO_HISTORY_SETTING,
            'enable_reset_encrypted_repo_password':
            ENABLE_RESET_ENCRYPTED_REPO_PASSWORD,
            'enableFileComment': settings.ENABLE_FILE_COMMENT,
            'is_email_configured': IS_EMAIL_CONFIGURED,
            'can_add_public_repo':
            request.user.permissions.can_add_public_repo(),
            'folder_perm_enabled': folder_perm_enabled,
            'file_audit_enabled': FILE_AUDIT_ENABLED,
            'custom_nav_items': json.dumps(CUSTOM_NAV_ITEMS),
            'enable_show_contact_email_when_search_user':
            settings.ENABLE_SHOW_CONTACT_EMAIL_WHEN_SEARCH_USER,
            'additional_share_dialog_note': ADDITIONAL_SHARE_DIALOG_NOTE,
            'additional_app_bottom_links': ADDITIONAL_APP_BOTTOM_LINKS,
            'additional_about_dialog_links': ADDITIONAL_ABOUT_DIALOG_LINKS,
            'enable_ocm': ENABLE_OCM,
            'ocm_remote_servers': OCM_REMOTE_SERVERS,
            'enable_share_to_department': settings.ENABLE_SHARE_TO_DEPARTMENT,
        })
Example #44
0
def file_revisions(request, repo_id):
    """List file revisions in file version history page.
    """
    repo = get_repo(repo_id)
    if not repo:
        error_msg = _(u"Library does not exist")
        return render_error(request, error_msg)

    # perm check
    if not check_folder_permission(request, repo_id, '/'):
        error_msg = _(u"Permission denied.")
        return render_error(request, error_msg)

    path = request.GET.get('p', '/')
    if not path:
        return render_error(request)

    if path[-1] == '/':
        path = path[:-1]

    u_filename = os.path.basename(path)

    filetype = get_file_type_and_ext(u_filename)[0].lower()
    if filetype == 'text' or filetype == 'markdown':
        can_compare = True
    else:
        can_compare = False

    # Check whether user is repo owner
    if validate_owner(request, repo_id):
        is_owner = True
    else:
        is_owner = False

    zipped = gen_path_link(path, repo.name)

    can_revert_file = True
    username = request.user.username

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

    if seafile_api.check_permission_by_path(repo_id, path, username) != 'rw' or \
        (is_locked and not locked_by_me):
        can_revert_file = False

    # for 'go back'
    referer = request.GET.get('referer', '')

    return render(request, 'file_revisions.html', {
        'repo': repo,
        'path': path,
        'u_filename': u_filename,
        'zipped': zipped,
        'is_owner': is_owner,
        'can_compare': can_compare,
        'can_revert_file': can_revert_file,
        'referer': referer,
        })
Example #45
0
def view_shared_upload_link(request, uploadlink):
    token = uploadlink.token

    password_check_passed, err_msg = check_share_link_common(
        request, uploadlink, is_upload_link=True)
    if not password_check_passed:
        d = {
            'token': token,
            'view_name': 'view_shared_upload_link',
            'err_msg': err_msg
        }
        return render(request, 'share_access_validation.html', d)

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

    path = uploadlink.path
    if path == '/':
        # use repo name as dir name if share whole library
        dir_name = repo.name
    else:
        dir_name = os.path.basename(path[:-1])

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

    if repo.encrypted or \
            seafile_api.check_permission_by_path(repo_id, '/', username) != 'rw':
        return render_error(request, _(u'Permission denied'))

    uploadlink.view_cnt = F('view_cnt') + 1
    uploadlink.save()

    no_quota = True if seaserv.check_quota(repo_id) < 0 else False

    return render(
        request, 'view_shared_upload_link.html', {
            'repo':
            repo,
            'path':
            path,
            'username':
            username,
            'dir_name':
            dir_name,
            'max_upload_file_size':
            seaserv.MAX_UPLOAD_FILE_SIZE,
            'no_quota':
            no_quota,
            'uploadlink':
            uploadlink,
            'enable_upload_folder':
            ENABLE_UPLOAD_FOLDER,
            'enable_resumable_fileupload':
            ENABLE_RESUMABLE_FILEUPLOAD,
            'max_number_of_files_for_fileupload':
            MAX_NUMBER_OF_FILES_FOR_FILEUPLOAD,
        })
Example #46
0
def repo_remove_share(request):
    """
    If repo is shared from one person to another person, only these two person
    can remove share.
    If repo is shared from one person to a group, then only the one share the
    repo and group staff can remove share.
    """
    repo_id = request.GET.get('repo_id', '')
    group_id = request.GET.get('gid', '')
    from_email = request.GET.get('from', '')
    perm = request.GET.get('permission', None)
    if not is_valid_username(from_email) or perm is None:
        return render_error(request, _(u'Argument is not valid'))
    username = request.user.username

    repo = seafile_api.get_repo(repo_id)
    if not repo:
        return render_error(request, _(u'Library does not exist'))

    origin_repo_id, origin_path = get_origin_repo_info(repo.id)
    if origin_repo_id is not None:
        perm_repo_id = origin_repo_id
        perm_path = origin_path
    else:
        perm_repo_id = repo.id
        perm_path = '/'

    # if request params don't have 'gid', then remove repos that share to
    # to other person; else, remove repos that share to groups
    if not group_id:
        to_email = request.GET.get('to', '')
        if not is_valid_username(to_email):
            return render_error(request, _(u'Argument is not valid'))

        if username != from_email and username != to_email:
            return render_permission_error(request,
                                           _(u'Failed to remove share'))

        if is_org_context(request):
            org_id = request.user.org.org_id
            org_remove_share(org_id, repo_id, from_email, to_email)
        else:
            seaserv.remove_share(repo_id, from_email, to_email)
            send_perm_audit_msg('delete-repo-perm', from_email, to_email, \
                                perm_repo_id, perm_path, perm)
    else:
        try:
            group_id = int(group_id)
        except:
            return render_error(request, _(u'group id is not valid'))

        group = seaserv.get_group(group_id)
        if not group:
            return render_error(
                request, _(u"Failed to unshare: the group doesn't exist."))

        if not seaserv.check_group_staff(group_id, username) \
                and username != from_email:
            return render_permission_error(request,
                                           _(u'Failed to remove share'))

        if is_org_group(group_id):
            org_id = get_org_id_by_group(group_id)
            del_org_group_repo(repo_id, org_id, group_id)
        else:
            seafile_api.unset_group_repo(repo_id, group_id, from_email)
            send_perm_audit_msg('delete-repo-perm', from_email, group_id, \
                                perm_repo_id, perm_path, perm)

    messages.success(request, _('Successfully removed share'))

    next = request.META.get('HTTP_REFERER', SITE_ROOT)
    return HttpResponseRedirect(next)
Example #47
0
def dtable_external_download_link_view(request, token):

    dtable_external_link = DTableExternalLinks.objects.filter(
        token=token).first()
    if not dtable_external_link:
        raise Http404

    # resource check
    workspace_id = dtable_external_link.dtable.workspace.id
    workspace = Workspaces.objects.get_workspace_by_id(workspace_id)
    if not workspace:
        raise Http404

    name = dtable_external_link.dtable.name
    dtable = DTables.objects.get_dtable(workspace, name)
    if not dtable:
        return render_error(request, _('DTable does not exist'))

    repo_id = workspace.repo_id
    repo = seafile_api.get_repo(repo_id)
    if not repo:
        error_msg = 'Library %s not found.' % repo_id
        return render_error(request, error_msg)

    # get dtable_file_dir_id and asset_dir_id
    dtable_file_dir_id = seafile_api.get_file_id_by_path(
        repo_id, '/' + name + '.dtable/')
    if not dtable_file_dir_id:
        error_msg = 'DTable %s not found.' % name
        return render_error(request, error_msg)

    params = {}
    params['username'] = '******'
    params['table_name'] = name
    params['repo_id'] = repo_id
    params['dtable_uuid'] = str(dtable.uuid)

    try:
        task_id = add_dtable_io_task(type='export', params=params)
    except Exception as e:
        return render_error(request, 'Server is busy. Please try again later.')

    finished = False
    while not finished:
        resp = query_dtable_io_status(task_id)

        finished = json.loads(resp.content)['is_finished']
        time.sleep(1)

    tmp_zip_path = os.path.join('/tmp/dtable-io', str(dtable.uuid),
                                'zip_file') + '.zip'
    if not os.path.exists(tmp_zip_path):
        return render_error(request, _('Internal Server Error'))

    with open(tmp_zip_path, 'rb') as f:
        zip_stream = f.read()
    os.remove(tmp_zip_path)

    response = HttpResponse(zip_stream,
                            content_type="application/x-zip-compressed")
    response[
        'Content-Disposition'] = 'attachment;filename*=UTF-8\'\'' + urlquote(
            dtable.dtable_name) + '.dtable'
    return response
Example #48
0
def share_permission_admin(request):
    """Change repo share permission in ShareAdmin.
    """
    share_type = request.GET.get('share_type', '')
    content_type = 'application/json; charset=utf-8'

    form = RepoShareForm(request.POST)
    form.is_valid()

    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:
        return render_error(request, _(u'Library does not exist'))

    origin_repo_id, origin_path = get_origin_repo_info(repo.id)
    if origin_repo_id is not None:
        perm_repo_id = origin_repo_id
        perm_path = origin_path
    else:
        perm_repo_id = repo.id
        perm_path = '/'

    if share_type == 'personal':
        if not is_valid_username(email_or_group):
            return HttpResponse(json.dumps({'success': False}),
                                status=400,
                                content_type=content_type)

        try:
            if is_org_context(request):
                org_id = request.user.org.org_id
                seaserv.seafserv_threaded_rpc.org_set_share_permission(
                    org_id, repo_id, from_email, email_or_group, permission)
            else:
                seafile_api.set_share_permission(repo_id, from_email,
                                                 email_or_group, permission)
                send_perm_audit_msg('modify-repo-perm', from_email, \
                        email_or_group, perm_repo_id, perm_path, permission)

        except SearpcError:
            return HttpResponse(json.dumps({'success': False}),
                                status=500,
                                content_type=content_type)
        return HttpResponse(json.dumps({'success': True}),
                            content_type=content_type)

    elif share_type == 'group':
        try:
            if is_org_context(request):
                org_id = request.user.org.org_id
                seaserv.seafserv_threaded_rpc.set_org_group_repo_permission(
                    org_id, int(email_or_group), repo_id, permission)
            else:
                group_id = int(email_or_group)
                seafile_api.set_group_repo_permission(group_id, repo_id,
                                                      permission)
                send_perm_audit_msg('modify-repo-perm', from_email, \
                                    group_id, perm_repo_id, perm_path, permission)
        except SearpcError:
            return HttpResponse(json.dumps({'success': False}),
                                status=500,
                                content_type=content_type)
        return HttpResponse(json.dumps({'success': True}),
                            content_type=content_type)

    elif share_type == 'public':
        try:
            if is_org_context(request):
                org_id = request.user.org.org_id
                seaserv.seafserv_threaded_rpc.set_org_inner_pub_repo(
                    org_id, repo_id, permission)
            else:
                seafile_api.add_inner_pub_repo(repo_id, permission)
                send_perm_audit_msg('modify-repo-perm', from_email, 'all', \
                                    perm_repo_id, perm_path, permission)
        except SearpcError:
            return HttpResponse(json.dumps({'success': False}),
                                status=500,
                                content_type=content_type)
        return HttpResponse(json.dumps({'success': True}),
                            content_type=content_type)

    else:
        return HttpResponse(json.dumps({'success': False}),
                            status=400,
                            content_type=content_type)
Example #49
0
def dtable_row_share_link_view(request, token):

    # resource check
    dtable_row_share = DTableRowShares.objects.get_dtable_row_share_by_token(
        token)
    if not dtable_row_share:
        return render_error(request, 'DTable row share link does not exist.')

    workspace_id = dtable_row_share.workspace_id
    workspace = Workspaces.objects.get_workspace_by_id(workspace_id)
    if not workspace:
        return render_error(request, 'Workspace does not exist.')

    repo_id = workspace.repo_id
    repo = seafile_api.get_repo(repo_id)
    if not repo:
        return render_error(request, 'Library does not exist.')

    dtable_uuid = dtable_row_share.dtable_uuid
    dtable = DTables.objects.get_dtable_by_uuid(dtable_uuid)
    if not dtable:
        return render_error(request, 'DTable %s does not exist' % dtable_uuid)

    # generate json web token
    username = request.user.username
    payload = {
        'exp': int(time.time()) + 86400 * 3,
        'dtable_uuid': dtable.uuid.hex,
        'username': username,
        'permission': PERMISSION_READ,
    }

    try:
        access_token = jwt.encode(payload,
                                  DTABLE_PRIVATE_KEY,
                                  algorithm='HS256')
    except Exception as e:
        logger.error(e)
        return render_error(request, _('Internal Server Error'))

    url_for_row = '%s/api/v1/dtables/%s/tables/%s/rows/%s/' % \
        (DTABLE_SERVER_URL.strip('/'), dtable_uuid, dtable_row_share.table_id, dtable_row_share.row_id)
    req_for_row = requests.Request(
        url_for_row,
        headers={"Authorization": "Token %s" % access_token.decode()})

    url_for_columns = '%s/api/v1/dtables/%s/tables/%s/columns/' % \
        (DTABLE_SERVER_URL.strip('/'), dtable_uuid, dtable_row_share.table_id)
    req_for_columns = requests.Request(
        url_for_columns,
        headers={"Authorization": "Token %s" % access_token.decode()})

    try:
        row_content = requests.urlopen(req_for_row).read().decode()
        columns = requests.urlopen(req_for_columns).read().decode()
    except Exception as e:
        logger.error(e)
        return render_error(request, _('Internal Server Error'))

    return_dict = {
        'row_content': row_content,
        'columns': columns,
        'workspace_id': workspace_id,
        'dtable_name': dtable.name
    }

    return render(request, 'dtable_shared_row_view_react.html', return_dict)
Example #50
0
def group_wiki(request, group, page_name="home"):
    username = request.user.username

    # get available modules(wiki, etc)
    mods_available = get_available_mods_by_group(group.id)
    mods_enabled = get_enabled_mods_by_group(group.id)

    wiki_exists = True
    try:
        content, repo, dirent = get_group_wiki_page(username, group, page_name)
    except WikiDoesNotExist:
        wiki_exists = False
        group_repos = get_group_repos(group.id, username)
        group_repos = [r for r in group_repos if not r.encrypted]
        return render_to_response("group/group_wiki.html", {
            "group": group,
            "is_staff": group.is_staff,
            "wiki_exists": wiki_exists,
            "mods_enabled": mods_enabled,
            "mods_available": mods_available,
            "group_repos": group_repos,
        },
                                  context_instance=RequestContext(request))
    except WikiPageMissing:
        '''create that page for user if he/she is a group member'''
        if not is_group_user(group.id, username):
            raise Http404

        repo = get_group_wiki_repo(group, username)
        # No need to check whether repo is none, since repo is already created

        filename = page_name_to_file_name(clean_page_name(page_name))
        if not post_empty_file(repo.id, "/", filename, username):
            return render_error(
                request, _("Failed to create wiki page. Please retry later."))
        return HttpResponseRedirect(
            reverse('group_wiki', args=[group.id, page_name]))
    else:
        # fetch file modified time and modifier
        path = '/' + dirent.obj_name
        try:
            dirent = seafile_api.get_dirent_by_path(repo.id, path)
            if dirent:
                latest_contributor, last_modified = dirent.modifier, dirent.mtime
            else:
                latest_contributor, last_modified = None, 0
        except SearpcError as e:
            logger.error(e)
            latest_contributor, last_modified = None, 0

        if is_registered_user(username):
            repo_perm = seafile_api.check_permission_by_path(
                repo.id, '/', username)
        else:
            # when anonymous user visit public group wiki, set permission as 'r'
            repo_perm = 'r'

        wiki_index_exists = True
        index_pagename = 'index'
        index_content = None
        try:
            index_content, index_repo, index_dirent = get_group_wiki_page(
                username, group, index_pagename)
        except (WikiDoesNotExist, WikiPageMissing) as e:
            wiki_index_exists = False

        return render_to_response(
            "group/group_wiki.html", {
                "group": group,
                "is_staff": group.is_staff,
                "wiki_exists": wiki_exists,
                "content": content,
                "page": os.path.splitext(dirent.obj_name)[0],
                "last_modified": last_modified,
                "latest_contributor": latest_contributor or _("Unknown"),
                "path": path,
                "repo_id": repo.id,
                "search_repo_id": repo.id,
                "search_wiki": True,
                "mods_enabled": mods_enabled,
                "mods_available": mods_available,
                "repo_perm": repo_perm,
                "wiki_index_exists": wiki_index_exists,
                "index_content": index_content,
            },
            context_instance=RequestContext(request))
Example #51
0
def dtable_form_view(request, token):

    # resource check
    form_obj = DTableForms.objects.get_form_by_token(token)
    if not form_obj:
        return render_error(request, 'Table\'s form does not exist.')

    workspace_id = form_obj.workspace_id
    workspace = Workspaces.objects.get_workspace_by_id(workspace_id)
    if not workspace:
        return render_error(request, 'Workspace does not exist.')

    dtable_uuid = form_obj.dtable_uuid
    dtable = DTables.objects.get_dtable_by_uuid(dtable_uuid)
    if not dtable:
        return render_error(request, 'Table does not exist.')

    # permission check
    if not check_form_submit_permission(request, form_obj):
        return render_permission_error(request, _('Permission denied.'))

    # asset quota check
    if not check_user_workspace_quota(workspace):
        return render_error(request, _('Asset quota exceeded.'))

    # generate json web token
    payload = {
        'exp': int(time.time()) + 60 * 5,
        'dtable_uuid': dtable_uuid,
        'username': "******",
        'permission': PERMISSION_READ,
    }

    try:
        access_token = jwt.encode(payload,
                                  DTABLE_PRIVATE_KEY,
                                  algorithm='HS256')
    except Exception as e:
        logger.error(e)
        return render_error(request, _('Internal Server Error'))

    url = '%s/api/v1/dtables/%s/metadata/' % (DTABLE_SERVER_URL.strip('/'),
                                              dtable_uuid)
    req = requests.Request(
        url, headers={"Authorization": "Token %s" % access_token.decode()})

    try:
        dtable_metadata = requests.urlopen(req).read().decode()
    except Exception as e:
        logger.error(e)
        return render_error(request, _('Internal Server Error'))

    return_dict = {
        'version': SEATABLE_VERSION,
        'dtable_metadata': dtable_metadata,
        'workspace_id': workspace_id,
        'form_id': form_obj.form_id,
        'form_config': form_obj.form_config,
        'dtable_name': dtable.name,
        'dtable_web_service_url': DTABLE_WEB_SERVICE_URL,
        'form_token': token,
    }

    return render(request, 'dtable_share_form_view_react.html', return_dict)
Example #52
0
def work_weixin_oauth_connect_callback(request):
    if not work_weixin_oauth_check():
        return render_error(request, _('Feature is not enabled.'))

    code = request.GET.get('code', None)
    state = request.GET.get('state', None)
    if state != request.session.get('work_weixin_oauth_connect_state',
                                    None) or not code:
        logger.error(
            'can not get right code or state from work weixin request')
        return render_error(request, _('Error, please contact administrator.'))

    access_token = get_work_weixin_access_token()
    if not access_token:
        logger.error('can not get work weixin access_token')
        return render_error(request, _('Error, please contact administrator.'))

    data = {
        'access_token': access_token,
        'code': code,
    }
    api_response = requests.get(WORK_WEIXIN_GET_USER_INFO_URL, params=data)
    api_response_dic = handler_work_weixin_api_response(api_response)
    if not api_response_dic:
        logger.error('can not get work weixin user info')
        return render_error(request, _('Error, please contact administrator.'))

    if not api_response_dic.get('UserId', None):
        logger.error('can not get UserId in work weixin user info response')
        return render_error(request, _('Error, please contact administrator.'))

    user_id = api_response_dic.get('UserId')
    uid = WORK_WEIXIN_UID_PREFIX + user_id
    email = request.user.username

    work_weixin_user = SocialAuthUser.objects.get_by_provider_and_uid(
        WORK_WEIXIN_PROVIDER, uid)
    if work_weixin_user:
        logger.error('work weixin account already exists %s' % user_id)
        return render_error(request, '出错了,此企业微信账号已被绑定')

    SocialAuthUser.objects.add(email, WORK_WEIXIN_PROVIDER, uid)

    # update user info
    if WORK_WEIXIN_USER_INFO_AUTO_UPDATE:
        user_info_data = {
            'access_token': access_token,
            'userid': user_id,
        }
        user_info_api_response = requests.get(WORK_WEIXIN_GET_USER_PROFILE_URL,
                                              params=user_info_data)
        user_info_api_response_dic = handler_work_weixin_api_response(
            user_info_api_response)
        if user_info_api_response_dic:
            api_user = user_info_api_response_dic
            api_user['username'] = email
            api_user['contact_email'] = api_user['email']
            update_work_weixin_user_info(api_user)

    # redirect user to page
    response = HttpResponseRedirect(
        request.session.get('work_weixin_oauth_connect_redirect', '/'))
    return response
Example #53
0
def work_weixin_oauth_callback(request):
    if not work_weixin_oauth_check():
        return render_error(request, _('Feature is not enabled.'))

    code = request.GET.get('code', None)
    state = request.GET.get('state', None)
    if state != request.session.get('work_weixin_oauth_state',
                                    None) or not code:
        logger.error(
            'can not get right code or state from work weixin request')
        return render_error(request, _('Error, please contact administrator.'))

    access_token = get_work_weixin_access_token()
    if not access_token:
        logger.error('can not get work weixin access_token')
        return render_error(request, _('Error, please contact administrator.'))

    data = {
        'access_token': access_token,
        'code': code,
    }
    api_response = requests.get(WORK_WEIXIN_GET_USER_INFO_URL, params=data)
    api_response_dic = handler_work_weixin_api_response(api_response)
    if not api_response_dic:
        logger.error('can not get work weixin user info')
        return render_error(request, _('Error, please contact administrator.'))

    if not api_response_dic.get('UserId', None):
        logger.error('can not get UserId in work weixin user info response')
        return render_error(request, _('Error, please contact administrator.'))

    user_id = api_response_dic.get('UserId')
    uid = WORK_WEIXIN_UID_PREFIX + user_id

    work_weixin_user = SocialAuthUser.objects.get_by_provider_and_uid(
        WORK_WEIXIN_PROVIDER, uid)
    if work_weixin_user:
        email = work_weixin_user.username
        is_new_user = False
    else:
        email = gen_user_virtual_id()
        is_new_user = True

    try:
        user = auth.authenticate(remote_user=email)
    except User.DoesNotExist:
        user = None

    if not user:
        return render_error(
            request,
            _('Error, new user registration is not allowed, please contact administrator.'
              ))

    if is_new_user:
        SocialAuthUser.objects.add(email, WORK_WEIXIN_PROVIDER, uid)

    # update user info
    if is_new_user or WORK_WEIXIN_USER_INFO_AUTO_UPDATE:
        user_info_data = {
            'access_token': access_token,
            'userid': user_id,
        }
        user_info_api_response = requests.get(WORK_WEIXIN_GET_USER_PROFILE_URL,
                                              params=user_info_data)
        user_info_api_response_dic = handler_work_weixin_api_response(
            user_info_api_response)
        if user_info_api_response_dic:
            api_user = user_info_api_response_dic
            api_user['username'] = email
            api_user['contact_email'] = api_user['email']
            update_work_weixin_user_info(api_user)

    if not user.is_active:
        return render_error(
            request,
            _('Your account is created successfully, please wait for administrator to activate your account.'
              ))

    # User is valid.  Set request.user and persist user in the session
    # by logging the user in.
    request.user = user
    request.session['remember_me'] = REMEMBER_ME
    auth.login(request, user)

    # generate auth token for Seafile client
    api_token = get_api_token(request)

    # redirect user to page
    response = HttpResponseRedirect(
        request.session.get('work_weixin_oauth_redirect', '/'))
    response.set_cookie('seahub_auth', user.username + '@' + api_token.key)
    return response
Example #54
0
def file_edit(request, repo_id):
    repo = get_repo(repo_id)
    if not repo:
        raise Http404

    if request.method == 'POST':
        return file_edit_submit(request, repo_id)

    if get_user_permission(request, repo_id) != 'rw':
        return render_permission_error(request, _(u'Unable to edit file'))

    path = request.GET.get('p', '/')
    if path[-1] == '/':
        path = path[:-1]
    u_filename = os.path.basename(path)
    filename = urllib2.quote(u_filename.encode('utf-8'))

    head_id = repo.head_cmmt_id

    obj_id = get_file_id_by_path(repo_id, path)
    if not obj_id:
        return render_error(request, _(u'The file does not exist.'))

    token = web_get_access_token(repo_id, obj_id, 'view', request.user.username)

    # generate path and link
    zipped = gen_path_link(path, repo.name)

    filetype, fileext = get_file_type_and_ext(filename)

    op = None
    err = ''
    file_content = None
    encoding = None
    file_encoding_list = FILE_ENCODING_LIST
    if filetype == TEXT or filetype == MARKDOWN or filetype == SF: 
        if repo.encrypted:
            repo.password_set = seafserv_rpc.is_passwd_set(repo_id, request.user.username)
            if not repo.password_set:
                op = 'decrypt'
        if not op:
            raw_path = gen_file_get_url(token, filename)
            file_enc = request.GET.get('file_enc', 'auto')
            if not file_enc in FILE_ENCODING_LIST:
                file_enc = 'auto'
            err, file_content, encoding = repo_file_get(raw_path, file_enc)
            if encoding and encoding not in FILE_ENCODING_LIST:
                file_encoding_list.append(encoding)
    else:
        err = _(u'Edit online is not offered for this type of file.')

    # Redirect to different place according to from page when user click
    # cancel button on file edit page.
    cancel_url = reverse('repo_view_file', args=[repo.id]) + '?p=' + urlquote(path)
    page_from = request.GET.get('from', '')
    gid = request.GET.get('gid', '')
    wiki_name = os.path.splitext(u_filename)[0]
    if page_from == 'wiki_page_edit' or page_from == 'wiki_page_new':
        cancel_url = reverse('group_wiki', args=[gid, wiki_name])
    elif page_from == 'personal_wiki_page_edit' or page_from == 'personal_wiki_page_new':
        cancel_url = reverse('personal_wiki', args=[wiki_name])

    search_repo_id = None
    if not repo.encrypted:
        search_repo_id = repo.id

    return render_to_response('file_edit.html', {
        'repo':repo,
        'u_filename':u_filename,
        'wiki_name': wiki_name,
        'path':path,
        'zipped':zipped,
        'filetype':filetype,
        'fileext':fileext,
        'op':op,
        'err':err,
        'file_content':file_content,
        'encoding': encoding,
        'file_encoding_list':file_encoding_list,
        'head_id': head_id,
        'from': page_from,
        'gid': gid,
        'cancel_url': cancel_url,
        'search_repo_id': search_repo_id,
    }, context_instance=RequestContext(request))
Example #55
0
def dingtalk_callback(request):

    if not ENABLE_DINGTALK:
        return render_error(request, _('Error, please contact administrator.'))

    state = request.GET.get('state', '')
    if not state or state != request.session.get('dingtalk_login_state', ''):
        logger.error('invalid state')
        return render_error(request, _('Error, please contact administrator.'))

    timestamp = str(int(time.time() * 1000)).encode('utf-8')
    appsecret = DINGTALK_QR_CONNECT_APP_SECRET.encode('utf-8')
    signature = base64.b64encode(
        hmac.new(appsecret, timestamp, digestmod=sha256).digest())
    parameters = {
        'accessKey': DINGTALK_QR_CONNECT_APP_ID,
        'timestamp': timestamp,
        'signature': signature,
    }

    code = request.GET.get('code')
    data = {"tmp_auth_code": code}

    full_user_info_url = DINGTALK_QR_CONNECT_USER_INFO_URL + '?' + urllib.parse.urlencode(
        parameters)
    user_info_resp = requests.post(full_user_info_url, data=json.dumps(data))
    user_info = user_info_resp.json()['user_info']

    # seahub authenticate user
    if 'unionid' not in user_info:
        logger.error('Required user info not found.')
        logger.error(user_info)
        return render_error(request, _('Error, please contact administrator.'))

    auth_user = SocialAuthUser.objects.get_by_provider_and_uid(
        'dingtalk', user_info['unionid'])
    if auth_user:
        email = auth_user.username
    else:
        email = gen_user_virtual_id()
        SocialAuthUser.objects.add(email, 'dingtalk', user_info['unionid'])

    try:
        user = auth.authenticate(remote_user=email)
    except User.DoesNotExist:
        user = None
    except Exception as e:
        logger.error(e)
        return render_error(request, _('Error, please contact administrator.'))

    if not user or not user.is_active:
        return render_error(request,
                            _('User %s not found or inactive.') % email)

    # User is valid.  Set request.user and persist user in the session
    # by logging the user in.
    request.user = user
    request.session['remember_me'] = DINGTALK_QR_CONNECT_LOGIN_REMEMBER_ME
    auth.login(request, user)

    # update user's profile
    name = user_info['nick'] if 'nick' in user_info else ''
    if name:

        profile = Profile.objects.get_profile_by_user(email)
        if not profile:
            profile = Profile(user=email)

        profile.nickname = name.strip()
        profile.save()

    user_detail_info = dingtalk_get_detailed_user_info(user_info['unionid'])
    contact_email = user_detail_info.get('email', '')
    if contact_email:
        profile.contact_email = contact_email
        profile.save()

    # generate auth token for Seafile client
    api_token = get_api_token(request)

    # redirect user to home page
    response = HttpResponseRedirect(
        request.session.get('dingtalk_login_redirect', '/'))
    response.set_cookie('seahub_auth', email + '@' + api_token.key)
    return response
Example #56
0
def view_file(request, repo_id):
    """
    Steps to view file:
    1. Get repo id and file path.
    2. Check user's permission.
    3. Check whether this file can be viewed online.
    4.1 Get file content if file is text file.
    4.2 Prepare flash if file is document.
    4.3 Prepare or use pdfjs if file is pdf.
    4.4 Other file return it's raw path.
    """
    username = request.user.username
    # check arguments
    repo = get_repo(repo_id)
    if not repo:
        raise Http404

    path = request.GET.get('p', '/')
    obj_id = get_file_id_by_path(repo_id, path)
    if not obj_id:
        return render_error(request, _(u'File does not exist'))

    # construct some varibles
    u_filename = os.path.basename(path)
    filename_utf8 = urllib2.quote(u_filename.encode('utf-8'))
    current_commit = get_commits(repo_id, 0, 1)[0]

    # Check whether user has permission to view file and get file raw path,
    # render error page if permission is deny.
    raw_path, user_perm = get_file_view_path_and_perm(request, repo_id,
                                                      obj_id, u_filename)
    if not user_perm:
        return render_permission_error(request, _(u'Unable to view file'))

    # get file type and extension
    filetype, fileext = get_file_type_and_ext(u_filename)

    img_prev = None
    img_next = None
    ret_dict = {'err': '', 'file_content': '', 'encoding': '', 'file_enc': '',
                'file_encoding_list': [], 'html_exists': False,
                'filetype': filetype}
    
    # Check file size
    fsize = get_file_size(obj_id)

    if fsize > FILE_PREVIEW_MAX_SIZE:
        err = _(u'File size surpasses %s, can not be opened online.') % \
            filesizeformat(FILE_PREVIEW_MAX_SIZE)
        ret_dict['err'] = err

    elif filetype in (DOCUMENT, PDF) and fsize > OFFICE_PREVIEW_MAX_SIZE:
        err = _(u'File size surpasses %s, can not be opened online.') % \
            filesizeformat(OFFICE_PREVIEW_MAX_SIZE)
        ret_dict['err'] = err

    else:
        """Choose different approach when dealing with different type of file."""
        if is_textual_file(file_type=filetype):
            handle_textual_file(request, filetype, raw_path, ret_dict)
            if filetype == MARKDOWN:
                c = ret_dict['file_content']
                ret_dict['file_content'] = convert_md_link(c, repo_id, username)
        elif filetype == DOCUMENT:
            handle_document(raw_path, obj_id, fileext, ret_dict)
        elif filetype == PDF:
            handle_pdf(raw_path, obj_id, fileext, ret_dict)
        elif filetype == IMAGE:
            parent_dir = os.path.dirname(path)
            dirs = list_dir_by_path(current_commit.id, parent_dir)
            if not dirs:
                raise Http404

            img_list = []
            for dirent in dirs:
                if not stat.S_ISDIR(dirent.props.mode):
                    fltype, flext = get_file_type_and_ext(dirent.obj_name)
                    if fltype == 'Image':
                        img_list.append(dirent.obj_name)

            if len(img_list) > 1:
                img_list.sort(lambda x, y : cmp(x.lower(), y.lower()))
                cur_img_index = img_list.index(u_filename) 
                if cur_img_index != 0:
                    img_prev = os.path.join(parent_dir, img_list[cur_img_index - 1])
                if cur_img_index != len(img_list) - 1:
                    img_next = os.path.join(parent_dir, img_list[cur_img_index + 1])
        else:
            pass

    # generate file path navigator
    zipped = gen_path_link(path, repo.name)

    # file shared link
    l = FileShare.objects.filter(repo_id=repo_id).filter(
        username=username).filter(path=path)
    fileshare = l[0] if len(l) > 0 else None
    http_or_https = request.is_secure() and 'https' or 'http'
    domain = RequestSite(request).domain
    if fileshare:
        file_shared_link = gen_shared_link(request, fileshare.token, 'f')
    else:
        file_shared_link = ''

    # my contacts used in shared link autocomplete
    contacts = Contact.objects.filter(user_email=username)

    """List repo groups"""
    # Get groups this repo is shared.    
    if request.user.org:
        org_id = request.user.org['org_id']
        repo_shared_groups = get_org_groups_by_repo(org_id, repo_id)
    else:
        repo_shared_groups = get_shared_groups_by_repo(repo_id)
    # Filter out groups that user in joined.
    groups = [ x for x in repo_shared_groups if is_group_user(x.id, username)]
    if len(groups) > 1:
        ctx = {}
        ctx['groups'] = groups
        repogrp_str = render_to_string("snippets/repo_group_list.html", ctx)
    else:
        repogrp_str = '' 
    
    file_path_hash = md5_constructor(urllib2.quote(path.encode('utf-8'))).hexdigest()[:12]            

    # fetch file contributors and latest contributor
    contributors, last_modified, last_commit_id = get_file_contributors(repo_id, path.encode('utf-8'), file_path_hash, obj_id)
    latest_contributor = contributors[0] if contributors else None

    # check whether file is starred
    is_starred = False
    org_id = -1
    if request.user.org:
        org_id = request.user.org['org_id']
    is_starred = is_file_starred(username, repo.id, path.encode('utf-8'), org_id)

    template = 'view_file_%s.html' % ret_dict['filetype'].lower()
    search_repo_id = None
    if not repo.encrypted:
        search_repo_id = repo.id
    return render_to_response(template, {
            'repo': repo,
            'obj_id': obj_id,
            'filename': u_filename,
            'path': path,
            'zipped': zipped,
            'current_commit': current_commit,
            'fileext': fileext,
            'raw_path': raw_path,
            'fileshare': fileshare,
            'protocol': http_or_https,
            'domain': domain,
            'file_shared_link': file_shared_link,
            'contacts': contacts,
            'err': ret_dict['err'],
            'file_content': ret_dict['file_content'],
            'file_enc': ret_dict['file_enc'],
            'encoding': ret_dict['encoding'],
            'file_encoding_list':ret_dict['file_encoding_list'],
            'html_exists': ret_dict['html_exists'],
            'html_detail': ret_dict.get('html_detail', {}),
            'filetype': ret_dict['filetype'],
            "applet_root": get_ccnetapplet_root(),
            'groups': groups,
            'use_pdfjs':USE_PDFJS,
            'contributors': contributors,
            'latest_contributor': latest_contributor,
            'last_modified': last_modified,
            'last_commit_id': last_commit_id,
            'repo_group_str': repogrp_str,
            'is_starred': is_starred,
            'user_perm': user_perm,
            'img_prev': img_prev,
            'img_next': img_next,
            'search_repo_id': search_repo_id,
            }, context_instance=RequestContext(request))
Example #57
0
def view_file_via_shared_dir(request, token):
    assert token is not None  # Checked by URLconf

    try:
        fileshare = FileShare.objects.get(token=token)
    except FileShare.DoesNotExist:
        raise Http404

    shared_by = fileshare.username
    repo_id = fileshare.repo_id
    repo = get_repo(repo_id)
    if not repo:
        raise Http404

    path = request.GET.get('p', '').rstrip('/')
    if not path:
        raise Http404
    if not path.startswith(
            fileshare.path):  # Can not view upper dir of shared dir
        raise Http404
    zipped = gen_path_link(path, '')

    obj_id = seafile_api.get_file_id_by_path(repo_id, path)
    if not obj_id:
        return render_error(request, _(u'File does not exist'))
    file_size = seafile_api.get_file_size(obj_id)

    filename = os.path.basename(path)
    filetype, fileext = get_file_type_and_ext(filename)
    access_token = seafserv_rpc.web_get_access_token(repo.id, obj_id, 'view',
                                                     '')
    raw_path = gen_file_get_url(access_token, filename)
    inner_path = gen_inner_file_get_url(access_token, filename)

    img_prev = None
    img_next = None

    # get file content
    ret_dict = {
        'err': '',
        'file_content': '',
        'encoding': '',
        'file_enc': '',
        'file_encoding_list': [],
        'html_exists': False,
        'filetype': filetype
    }
    fsize = get_file_size(obj_id)
    exceeds_limit, err_msg = file_size_exceeds_preview_limit(fsize, filetype)
    if exceeds_limit:
        err = err_msg
    else:
        """Choose different approach when dealing with different type of file."""

        if is_textual_file(file_type=filetype):
            handle_textual_file(request, filetype, inner_path, ret_dict)
        elif filetype == DOCUMENT:
            handle_document(inner_path, obj_id, fileext, ret_dict)
        elif filetype == SPREADSHEET:
            handle_spreadsheet(inner_path, obj_id, fileext, ret_dict)
        elif filetype == PDF:
            handle_pdf(inner_path, obj_id, fileext, ret_dict)
        elif filetype == IMAGE:
            current_commit = get_commits(repo_id, 0, 1)[0]
            parent_dir = os.path.dirname(path)
            dirs = seafile_api.list_dir_by_commit_and_path(
                current_commit.id, parent_dir)
            if not dirs:
                raise Http404

            img_list = []
            for dirent in dirs:
                if not stat.S_ISDIR(dirent.props.mode):
                    fltype, flext = get_file_type_and_ext(dirent.obj_name)
                    if fltype == 'Image':
                        img_list.append(dirent.obj_name)

            if len(img_list) > 1:
                img_list.sort(lambda x, y: cmp(x.lower(), y.lower()))
                cur_img_index = img_list.index(filename)
                if cur_img_index != 0:
                    img_prev = posixpath.join(parent_dir,
                                              img_list[cur_img_index - 1])
                if cur_img_index != len(img_list) - 1:
                    img_next = posixpath.join(parent_dir,
                                              img_list[cur_img_index + 1])

        # send statistic messages
        if ret_dict['filetype'] != 'Unknown':
            try:
                obj_size = seafserv_threaded_rpc.get_file_size(obj_id)
                send_message('seahub.stats', 'file-view\t%s\t%s\t%s\t%s' % \
                             (repo.id, shared_by, obj_id, obj_size))
            except SearpcError, e:
                logger.error('Error when sending file-view message: %s' %
                             str(e))
Example #58
0
def view_shared_dir(request, fileshare):

    token = fileshare.token

    password_check_passed, err_msg = check_share_link_common(request, fileshare)
    if not password_check_passed:
        d = {'token': token, 'view_name': 'view_shared_dir', 'err_msg': err_msg}
        return render(request, 'share_access_validation.html', d)

    username = fileshare.username
    repo_id = fileshare.repo_id

    # Get path from frontend, use '/' if missing, and construct request path
    # with fileshare.path to real path, used to fetch dirents by RPC.
    req_path = request.GET.get('p', '/')
    req_path = normalize_dir_path(req_path)

    if req_path == '/':
        real_path = fileshare.path
    else:
        real_path = posixpath.join(fileshare.path, req_path.lstrip('/'))

    real_path = normalize_dir_path(real_path)

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

    if repo.encrypted or not \
            seafile_api.check_permission_by_path(repo_id, '/', username):
        return render_error(request, _('Permission denied'))

    # Check path still exist, otherwise show error
    if not seafile_api.get_dir_id_by_path(repo.id, fileshare.path):
        return render_error(request, _('"%s" does not exist.') % fileshare.path)

    if fileshare.path == '/':
        # use repo name as dir name if share whole library
        dir_name = repo.name
    else:
        dir_name = os.path.basename(real_path[:-1])

    current_commit = seaserv.get_commits(repo_id, 0, 1)[0]
    file_list, dir_list, dirent_more = get_repo_dirents(request, repo,
                                                        current_commit, real_path)

    # generate dir navigator
    if fileshare.path == '/':
        zipped = gen_path_link(req_path, repo.name)
    else:
        zipped = gen_path_link(req_path, os.path.basename(fileshare.path[:-1]))

    if req_path == '/':  # When user view the root of shared dir..
        # increase shared link view_cnt,
        fileshare = FileShare.objects.get(token=token)
        fileshare.view_cnt = F('view_cnt') + 1
        fileshare.save()

    traffic_over_limit = user_traffic_over_limit(fileshare.username)

    permissions = fileshare.get_permissions()

    # mode to view dir/file items
    mode = request.GET.get('mode', 'list')
    if mode != 'list':
        mode = 'grid'
    thumbnail_size = THUMBNAIL_DEFAULT_SIZE if mode == 'list' else THUMBNAIL_SIZE_FOR_GRID

    for f in file_list:
        file_type, file_ext = get_file_type_and_ext(f.obj_name)
        if file_type == IMAGE:
            f.is_img = True
        if file_type == VIDEO:
            f.is_video = True

        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), f.obj_id)):
                req_image_path = posixpath.join(req_path, f.obj_name)
                src = get_share_link_thumbnail_src(token, thumbnail_size, req_image_path)
                f.encoded_thumbnail_src = urlquote(src)

    # for 'upload file'
    no_quota = True if seaserv.check_quota(repo_id) < 0 else False

    template = 'view_shared_dir_react.html'

    dir_share_link = request.path
    desc_for_ogp = _('Share link for %s.') % dir_name

    return render(request, template, {
            'repo': repo,
            'token': token,
            'path': req_path,
            'username': username,
            'dir_name': dir_name,
            'dir_path': real_path,
            'file_list': file_list,
            'dir_list': dir_list,
            'zipped': zipped,
            'traffic_over_limit': traffic_over_limit,
            'no_quota': no_quota,
            'permissions': permissions,
            'mode': mode,
            'thumbnail_size': thumbnail_size,
            'dir_share_link': dir_share_link,
            'desc_for_ogp': desc_for_ogp,
            'enable_share_link_report_abuse': ENABLE_SHARE_LINK_REPORT_ABUSE,
            'enable_video_thumbnail': ENABLE_VIDEO_THUMBNAIL,
            })
Example #59
0
def view_shared_dir(request, fileshare):
    token = fileshare.token

    password_check_passed, err_msg = check_share_link_common(
        request, fileshare)
    if not password_check_passed:
        d = {
            'token': token,
            'view_name': 'view_shared_dir',
            'err_msg': err_msg
        }
        return render_to_response('share_access_validation.html',
                                  d,
                                  context_instance=RequestContext(request))

    username = fileshare.username
    repo_id = fileshare.repo_id

    # Get path from frontend, use '/' if missing, and construct request path
    # with fileshare.path to real path, used to fetch dirents by RPC.
    req_path = request.GET.get('p', '/')
    if req_path[-1] != '/':
        req_path += '/'

    if req_path == '/':
        real_path = fileshare.path
    else:
        real_path = posixpath.join(fileshare.path, req_path.lstrip('/'))
    if real_path[-1] != '/':  # Normalize dir path
        real_path += '/'

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

    # Check path still exist, otherwise show error
    if not seafile_api.get_dir_id_by_path(repo.id, fileshare.path):
        return render_error(request,
                            _('"%s" does not exist.') % fileshare.path)

    if fileshare.path == '/':
        # use repo name as dir name if share whole library
        dir_name = repo.name
    else:
        dir_name = os.path.basename(real_path[:-1])

    current_commit = seaserv.get_commits(repo_id, 0, 1)[0]
    file_list, dir_list, dirent_more = get_repo_dirents(
        request, repo, current_commit, real_path)

    # generate dir navigator
    if fileshare.path == '/':
        zipped = gen_path_link(req_path, repo.name)
    else:
        zipped = gen_path_link(req_path, os.path.basename(fileshare.path[:-1]))

    if req_path == '/':  # When user view the root of shared dir..
        # increase shared link view_cnt,
        fileshare = FileShare.objects.get(token=token)
        fileshare.view_cnt = F('view_cnt') + 1
        fileshare.save()

    traffic_over_limit = user_traffic_over_limit(fileshare.username)

    # mode to view dir/file items
    mode = request.GET.get('mode', 'list')
    if mode != 'list':
        mode = 'grid'
    thumbnail_size = THUMBNAIL_DEFAULT_SIZE if mode == 'list' else THUMBNAIL_SIZE_FOR_GRID

    for f in file_list:
        file_type, file_ext = get_file_type_and_ext(f.obj_name)
        if file_type == IMAGE:
            f.is_img = True
        if file_type == VIDEO:
            f.is_video = True

        if (file_type == IMAGE or file_type == VIDEO) and ENABLE_THUMBNAIL:
            if os.path.exists(
                    os.path.join(THUMBNAIL_ROOT, str(thumbnail_size),
                                 f.obj_id)):
                req_image_path = posixpath.join(req_path, f.obj_name)
                src = get_share_link_thumbnail_src(token, thumbnail_size,
                                                   req_image_path)
                f.encoded_thumbnail_src = urlquote(src)

    return render_to_response('view_shared_dir.html', {
        'repo': repo,
        'token': token,
        'path': req_path,
        'username': username,
        'dir_name': dir_name,
        'file_list': file_list,
        'dir_list': dir_list,
        'zipped': zipped,
        'traffic_over_limit': traffic_over_limit,
        'ENABLE_THUMBNAIL': ENABLE_THUMBNAIL,
        'mode': mode,
        'thumbnail_size': thumbnail_size,
    },
                              context_instance=RequestContext(request))
Example #60
0
def view_shared_dir(request, token):
    assert token is not None  # Checked by URLconf

    fileshare = FileShare.objects.get_valid_dir_link_by_token(token)
    if fileshare is None:
        raise Http404

    if fileshare.is_encrypted():
        if not check_share_link_access(request, token):
            d = {
                'token': token,
                'view_name': 'view_shared_dir',
            }
            if request.method == 'POST':
                post_values = request.POST.copy()
                post_values['enc_password'] = fileshare.password
                form = SharedLinkPasswordForm(post_values)
                d['form'] = form
                if form.is_valid():
                    set_share_link_access(request, token)
                else:
                    return render_to_response(
                        'share_access_validation.html',
                        d,
                        context_instance=RequestContext(request))
            else:
                return render_to_response(
                    'share_access_validation.html',
                    d,
                    context_instance=RequestContext(request))

    username = fileshare.username
    repo_id = fileshare.repo_id

    # Get path from frontend, use '/' if missing, and construct request path
    # with fileshare.path to real path, used to fetch dirents by RPC.
    req_path = request.GET.get('p', '/')
    if req_path[-1] != '/':
        req_path += '/'

    if req_path == '/':
        real_path = fileshare.path
    else:
        real_path = posixpath.join(fileshare.path, req_path.lstrip('/'))
    if real_path[-1] != '/':  # Normalize dir path
        real_path += '/'

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

    # Check path still exist, otherwise show error
    if not seafile_api.get_dir_id_by_path(repo.id, fileshare.path):
        return render_error(request,
                            _('"%s" does not exist.') % fileshare.path)

    # download shared dir
    if request.GET.get('dl', '') == '1':
        return _download_dir_from_share_link(request, fileshare, repo,
                                             real_path)

    if fileshare.path == '/':
        # use repo name as dir name if share whole library
        dir_name = repo.name
    else:
        dir_name = os.path.basename(real_path[:-1])

    current_commit = seaserv.get_commits(repo_id, 0, 1)[0]
    file_list, dir_list, dirent_more = get_repo_dirents(
        request, repo, current_commit, real_path)

    # generate dir navigator
    if fileshare.path == '/':
        zipped = gen_path_link(req_path, repo.name)
    else:
        zipped = gen_path_link(req_path, os.path.basename(fileshare.path[:-1]))

    if req_path == '/':  # When user view the root of shared dir..
        # increase shared link view_cnt,
        fileshare = FileShare.objects.get(token=token)
        fileshare.view_cnt = F('view_cnt') + 1
        fileshare.save()

    traffic_over_limit = user_traffic_over_limit(fileshare.username)

    for f in file_list:
        file_type, file_ext = get_file_type_and_ext(f.obj_name)
        if file_type == IMAGE:
            f.is_img = True
        if allow_generate_thumbnail(username, repo, f):
            f.allow_generate_thumbnail = True
            if os.path.exists(
                    os.path.join(THUMBNAIL_ROOT, THUMBNAIL_DEFAULT_SIZE,
                                 f.obj_id)):
                f.thumbnail_src = get_thumbnail_src(repo.id, f.obj_id,
                                                    THUMBNAIL_DEFAULT_SIZE)

    return render_to_response('view_shared_dir.html', {
        'repo': repo,
        'token': token,
        'path': req_path,
        'username': username,
        'dir_name': dir_name,
        'file_list': file_list,
        'dir_list': dir_list,
        'zipped': zipped,
        'traffic_over_limit': traffic_over_limit,
        'ENABLE_THUMBNAIL': ENABLE_THUMBNAIL,
        'PREVIEW_DEFAULT_SIZE': PREVIEW_DEFAULT_SIZE,
    },
                              context_instance=RequestContext(request))