Blame pagure/ui/app.py

Pierre-Yves Chibon 33b534
# -*- coding: utf-8 -*-
Pierre-Yves Chibon 2088eb
Pierre-Yves Chibon 2088eb
"""
Pierre-Yves Chibon a04944
 (c) 2014-2018 - Copyright Red Hat Inc
Pierre-Yves Chibon 2088eb
Pierre-Yves Chibon 2088eb
 Authors:
Pierre-Yves Chibon 2088eb
   Pierre-Yves Chibon <pingou@pingoured.fr></pingou@pingoured.fr>
farhaanbukhsh 141da6
   Farhaan Bukhsh <farhaan.bukhsh@gmail.com></farhaan.bukhsh@gmail.com>
Pierre-Yves Chibon 2088eb
Pierre-Yves Chibon 2088eb
"""
Pierre-Yves Chibon 2088eb
Pierre-Yves Chibon 67d1cc
from __future__ import unicode_literals, absolute_import
Aurélien Bompard dcf6f6
Pierre-Yves Chibon 170fc9
import datetime
Pierre-Yves Chibon 4635b5
import logging
Pierre-Yves Chibon 2088eb
from math import ceil
Pierre-Yves Chibon 2088eb
Pierre-Yves Chibon 170fc9
import flask
Pierre-Yves Chibon 2088eb
from sqlalchemy.exc import SQLAlchemyError
Pierre-Yves Chibon 2088eb
Pierre-Yves Chibon fe5017
import pagure.exceptions
Patrick Uiterwijk 0e5f4a
import pagure.lib.git
Pierre-Yves Chibon 930073
import pagure.lib.query
Pierre-Yves Chibon fe5017
import pagure.forms
Pierre-Yves Chibon fe5017
import pagure.ui.filters
Pierre-Yves Chibon b130e5
from pagure.config import config as pagure_config
Pierre-Yves Chibon a04944
from pagure.flask_app import _get_user, admin_session_timedout
Pierre-Yves Chibon b130e5
from pagure.ui import UI_NS
Pierre-Yves Chibon b130e5
from pagure.utils import (
Pierre-Yves Chibon b130e5
    authenticated,
Pierre-Yves Chibon b130e5
    is_safe_url,
Pierre-Yves Chibon b130e5
    login_required,
Aurélien Bompard a7f281
    get_task_redirect_url,
Aurélien Bompard 619e2a
    is_true,
Pierre-Yves Chibon b130e5
)
Pierre-Yves Chibon 2088eb
Pierre-Yves Chibon 2088eb
Pierre-Yves Chibon 4635b5
_log = logging.getLogger(__name__)
Pierre-Yves Chibon 4635b5
Pierre-Yves Chibon 4635b5
Pierre-Yves Chibon 314ec8
def _filter_acls(repos, acl, user):
Pierre-Yves Chibon 314ec8
    """ Filter the given list of repositories to return only the ones where
Pierre-Yves Chibon 314ec8
    the user has the specified acl.
Pierre-Yves Chibon 314ec8
    """
Pierre-Yves Chibon 9c2953
    if acl.lower() == "main admin":
Pierre-Yves Chibon 9c2953
        repos = [repo for repo in repos if user.username == repo.user.username]
Pierre-Yves Chibon 9c2953
    elif acl.lower() == "ticket" or "commit" or "admin":
Pierre-Yves Chibon 314ec8
        repos = [
Pierre-Yves Chibon 9c2953
            repo for repo in repos if user in repo.contributors[acl.lower()]
Pierre-Yves Chibon 314ec8
        ]
Pierre-Yves Chibon 314ec8
Pierre-Yves Chibon 314ec8
    return repos
Pierre-Yves Chibon 314ec8
Abhijeet Kasurde c65ec4
Pierre-Yves Chibon 9c2953
@UI_NS.route("/browse/projects", endpoint="browse_projects")
Pierre-Yves Chibon 9c2953
@UI_NS.route("/browse/projects/", endpoint="browse_projects")
Pierre-Yves Chibon 9c2953
@UI_NS.route("/")
Pierre-Yves Chibon 1e781f
def index():
Pierre-Yves Chibon 47950c
    """ Front page of the application.
Pierre-Yves Chibon 2088eb
    """
Pierre-Yves Chibon 7b3c51
    if (
Pierre-Yves Chibon 7b3c51
        authenticated()
Pierre-Yves Chibon 7b3c51
        and flask.request.path == "/"
Pierre-Yves Chibon 7b3c51
        and not flask.session.get("_requires_fpca", False)
Pierre-Yves Chibon 7b3c51
    ):
Pierre-Yves Chibon 08da0d
        flask.request.from_index = True
Pierre-Yves Chibon 9c2953
        return flask.redirect(flask.url_for("ui_ns.userdash_projects"))
Pierre-Yves Chibon f70191
Pierre-Yves Chibon 9c2953
    sorting = flask.request.args.get("sorting") or None
Pierre-Yves Chibon 9c2953
    page = flask.request.args.get("page", 1)
Pierre-Yves Chibon 2088eb
    try:
Pierre-Yves Chibon 47950c
        page = int(page)
Pierre-Yves Chibon 97816b
        if page < 1:
Pierre-Yves Chibon 97816b
            page = 1
Pierre-Yves Chibon 2088eb
    except ValueError:
Pierre-Yves Chibon 2088eb
        page = 1
Pierre-Yves Chibon 2088eb
Pierre-Yves Chibon 9c2953
    limit = pagure_config["ITEM_PER_PAGE"]
Pierre-Yves Chibon 2088eb
    start = limit * (page - 1)
Pierre-Yves Chibon 2088eb
Pierre-Yves Chibon 5872c5
    private = None
Pierre-Yves Chibon 5872c5
    if authenticated():
Pierre-Yves Chibon 5872c5
        private = flask.g.fas_user.username
Pierre-Yves Chibon 5872c5
Pierre-Yves Chibon 930073
    repos = pagure.lib.query.search_projects(
Pierre-Yves Chibon b130e5
        flask.g.session,
Pierre-Yves Chibon a66e54
        fork=False,
Pierre-Yves Chibon a66e54
        start=start,
Pierre-Yves Chibon a66e54
        limit=limit,
Pierre-Yves Chibon 5872c5
        sort=sorting,
Pierre-Yves Chibon 5872c5
        private=private,
Pierre-Yves Chibon 5872c5
    )
Ryan Lerch 770112
Pierre-Yves Chibon 930073
    num_repos = pagure.lib.query.search_projects(
Pierre-Yves Chibon 9c2953
        flask.g.session, fork=False, private=private, count=True
Pierre-Yves Chibon 9c2953
    )
vibhcool eb6723
    total_page = int(ceil(num_repos / float(limit)) if num_repos > 0 else 1)
Pierre-Yves Chibon bd2213
Pierre-Yves Chibon 2088eb
    return flask.render_template(
Pierre-Yves Chibon 9c2953
        "index.html",
Ryan Lerch e914ef
        select="projects",
Pierre-Yves Chibon 837e8c
        namespace=None,
Pierre-Yves Chibon 05fa8b
        repos=repos,
Pierre-Yves Chibon 05fa8b
        repos_length=num_repos,
Ryan Lerch 770112
        total_page=total_page,
Ryan Lerch 770112
        page=page,
Ryan Lerch 00bead
        sorting=sorting,
Pierre-Yves Chibon 05fa8b
    )
Pierre-Yves Chibon 05fa8b
Pierre-Yves Chibon 05fa8b
Ryan Lerch 336cd6
def get_userdash_common(user):
Ryan Lerch 336cd6
    userdash_counts = {}
Ryan Lerch 336cd6
Pierre-Yves Chibon 930073
    userdash_counts["repos_length"] = pagure.lib.query.list_users_projects(
Ryan Lerch 336cd6
        flask.g.session,
Ryan Lerch 336cd6
        username=flask.g.fas_user.username,
Ryan Lerch 336cd6
        exclude_groups=None,
Ryan Lerch 336cd6
        fork=False,
Ryan Lerch 336cd6
        private=flask.g.fas_user.username,
Ryan Lerch 336cd6
        count=True,
Ryan Lerch 336cd6
    )
Ryan Lerch 336cd6
Pierre-Yves Chibon 930073
    userdash_counts["forks_length"] = pagure.lib.query.search_projects(
Ryan Lerch 336cd6
        flask.g.session,
Ryan Lerch 336cd6
        username=flask.g.fas_user.username,
Ryan Lerch 336cd6
        fork=True,
Ryan Lerch 336cd6
        private=flask.g.fas_user.username,
Ryan Lerch 336cd6
        count=True,
Ryan Lerch 336cd6
    )
Ryan Lerch 336cd6
Pierre-Yves Chibon 9c2953
    userdash_counts["watchlist_length"] = len(
Pierre-Yves Chibon 930073
        pagure.lib.query.user_watch_list(
Pierre-Yves Chibon 9c2953
            flask.g.session,
Pierre-Yves Chibon 9c2953
            user=flask.g.fas_user.username,
Pierre-Yves Chibon 9c2953
            exclude_groups=pagure_config.get("EXCLUDE_GROUP_INDEX"),
Pierre-Yves Chibon 9c2953
        )
Pierre-Yves Chibon 9c2953
    )
Ryan Lerch 336cd6
Pierre-Yves Chibon 9c2953
    userdash_counts["groups_length"] = len(user.groups)
Ryan Lerch 336cd6
Pierre-Yves Chibon 930073
    search_data = pagure.lib.query.list_users_projects(
Ryan Lerch 336cd6
        flask.g.session,
Ryan Lerch 336cd6
        username=flask.g.fas_user.username,
Ryan Lerch 336cd6
        private=flask.g.fas_user.username,
Ryan Lerch 336cd6
    )
Ryan Lerch 336cd6
Ryan Lerch 336cd6
    return userdash_counts, search_data
Ryan Lerch 336cd6
Ryan Lerch 336cd6
Pierre-Yves Chibon 9c2953
@UI_NS.route("/dashboard/projects/")
Pierre-Yves Chibon 9c2953
@UI_NS.route("/dashboard/projects")
Ryan Lerch 336cd6
@login_required
Ryan Lerch 336cd6
def userdash_projects():
Ryan Lerch 336cd6
    """ User Dashboard page listing projects for the user
Ryan Lerch 336cd6
    """
Ryan Lerch 336cd6
    user = _get_user(username=flask.g.fas_user.username)
Ryan Lerch 336cd6
    userdash_counts, search_data = get_userdash_common(user)
Ryan Lerch 336cd6
Ryan Lerch 336cd6
    groups = []
Ryan Lerch 336cd6
Ryan Lerch 336cd6
    for group in user.groups:
Pierre-Yves Chibon 9c2953
        groups.append(
Pierre-Yves Chibon 930073
            pagure.lib.query.search_groups(
Pierre-Yves Chibon 9c2953
                flask.g.session, group_name=group, group_type="user"
Pierre-Yves Chibon 9c2953
            )
Pierre-Yves Chibon 9c2953
        )
Ryan Lerch 336cd6
Pierre-Yves Chibon 9c2953
    acl = flask.request.args.get("acl", "").strip().lower() or None
Pierre-Yves Chibon 9c2953
    search_pattern = flask.request.args.get("search_pattern", None)
Ryan Lerch 336cd6
    if search_pattern == "":
Ryan Lerch 336cd6
        search_pattern = None
Ryan Lerch 336cd6
Pierre-Yves Chibon 9c2953
    limit = pagure_config["ITEM_PER_PAGE"]
Ryan Lerch 336cd6
Pierre-Yves Chibon 9c2953
    repopage = flask.request.args.get("repopage", 1)
Ryan Lerch 336cd6
    try:
Ryan Lerch 336cd6
        repopage = int(repopage)
Ryan Lerch 336cd6
        if repopage < 1:
Ryan Lerch 336cd6
            repopage = 1
Ryan Lerch 336cd6
    except ValueError:
Ryan Lerch 336cd6
        repopage = 1
Ryan Lerch 336cd6
Ryan Lerch 336cd6
    pattern = "*" + search_pattern + "*" if search_pattern else search_pattern
Ryan Lerch 336cd6
Ryan Lerch 336cd6
    start = limit * (repopage - 1)
Pierre-Yves Chibon 930073
    repos = pagure.lib.query.list_users_projects(
Ryan Lerch 336cd6
        flask.g.session,
Ryan Lerch 336cd6
        username=flask.g.fas_user.username,
Ryan Lerch 336cd6
        exclude_groups=None,
Ryan Lerch 336cd6
        fork=False,
Ryan Lerch 336cd6
        pattern=pattern,
Ryan Lerch 336cd6
        private=flask.g.fas_user.username,
Ryan Lerch 336cd6
        start=start,
Ryan Lerch 336cd6
        limit=limit,
Ryan Lerch 336cd6
        acls=[acl] if acl else None,
Ryan Lerch 336cd6
    )
Ryan Lerch 336cd6
Pierre-Yves Chibon 930073
    filtered_repos_count = pagure.lib.query.list_users_projects(
Ryan Lerch 336cd6
        flask.g.session,
Ryan Lerch 336cd6
        username=flask.g.fas_user.username,
Ryan Lerch 336cd6
        exclude_groups=None,
Ryan Lerch 336cd6
        fork=False,
Ryan Lerch 336cd6
        pattern=pattern,
Ryan Lerch 336cd6
        private=flask.g.fas_user.username,
Ryan Lerch 336cd6
        count=True,
Ryan Lerch 336cd6
        acls=[acl] if acl else None,
Ryan Lerch 336cd6
    )
Ryan Lerch 336cd6
Ryan Lerch 336cd6
    repo_list = []
Ryan Lerch 336cd6
    for repo in repos:
Ryan Lerch 336cd6
        access = ""
Ryan Lerch 336cd6
        if repo.user.user == user.username:
Ryan Lerch 336cd6
            access = "main admin"
Ryan Lerch 336cd6
        else:
Ryan Lerch 336cd6
            for repoaccess in repo.contributors:
Ryan Lerch 336cd6
                for repouser in repo.contributors[repoaccess]:
Ryan Lerch 336cd6
                    if repouser.username == user.username:
Ryan Lerch 336cd6
                        access = repoaccess
Ryan Lerch 336cd6
        grouplist = []
Ryan Lerch 336cd6
        for group in groups:
Ryan Lerch 336cd6
            if repo in group.projects:
Ryan Lerch 336cd6
                thegroup = {"group_name": "", "access": ""}
Pierre-Yves Chibon 9c2953
                thegroup["group_name"] = group.group_name
Ryan Lerch 336cd6
                for a in repo.contributor_groups:
Ryan Lerch 336cd6
                    for gr in repo.contributor_groups[a]:
Ryan Lerch 336cd6
                        if group.group_name == gr.group_name:
Ryan Lerch 336cd6
                            thegroup["access"] = a
Ryan Lerch 336cd6
                grouplist.append(thegroup)
Pierre-Yves Chibon 9c2953
        repo_list.append(
Pierre-Yves Chibon 9c2953
            {"repo": repo, "grouplist": grouplist, "access": access}
Pierre-Yves Chibon 9c2953
        )
Ryan Lerch 336cd6
Ryan Lerch 336cd6
    total_repo_page = int(
Pierre-Yves Chibon 9c2953
        ceil(filtered_repos_count / float(limit))
Pierre-Yves Chibon 9c2953
        if filtered_repos_count > 0
Pierre-Yves Chibon 9c2953
        else 1
Pierre-Yves Chibon 9c2953
    )
Ryan Lerch 336cd6
Ryan Lerch 336cd6
    return flask.render_template(
Pierre-Yves Chibon 9c2953
        "userdash_projects.html",
Ryan Lerch 336cd6
        username=flask.g.fas_user.username,
Ryan Lerch 336cd6
        user=user,
Ryan Lerch 336cd6
        select="projects",
Ryan Lerch 336cd6
        repo_list=repo_list,
Ryan Lerch 336cd6
        repopage=repopage,
Ryan Lerch 336cd6
        total_repo_page=total_repo_page,
Ryan Lerch 336cd6
        userdash_counts=userdash_counts,
Ryan Lerch 336cd6
        search_data=search_data,
Ryan Lerch 336cd6
        acl=acl,
Ryan Lerch 336cd6
        filtered_repos_count=filtered_repos_count,
Ryan Lerch 336cd6
        search_pattern=search_pattern,
Ryan Lerch 336cd6
    )
Ryan Lerch 336cd6
Ryan Lerch 336cd6
Pierre-Yves Chibon 9c2953
@UI_NS.route("/dashboard/activity/")
Pierre-Yves Chibon 9c2953
@UI_NS.route("/dashboard/activity")
Ryan Lerch 336cd6
@login_required
Ryan Lerch 336cd6
def userdash_activity():
Ryan Lerch 336cd6
    """ User Dashboard page listing user activity
Ryan Lerch 336cd6
    """
Ryan Lerch 336cd6
    user = _get_user(username=flask.g.fas_user.username)
Ryan Lerch 336cd6
    userdash_counts, search_data = get_userdash_common(user)
Ryan Lerch 336cd6
Pierre-Yves Chibon 930073
    messages = pagure.lib.query.get_watchlist_messages(
Pierre-Yves Chibon 9c2953
        flask.g.session, user, limit=20
Pierre-Yves Chibon 9c2953
    )
Ryan Lerch 336cd6
Ryan Lerch 336cd6
    return flask.render_template(
Pierre-Yves Chibon 9c2953
        "userdash_activity.html",
Ryan Lerch 336cd6
        username=flask.g.fas_user.username,
Ryan Lerch 336cd6
        user=user,
Ryan Lerch 336cd6
        select="activity",
Ryan Lerch 336cd6
        messages=messages,
Ryan Lerch 336cd6
        userdash_counts=userdash_counts,
Ryan Lerch 336cd6
        search_data=search_data,
Ryan Lerch 336cd6
    )
Ryan Lerch 336cd6
Ryan Lerch 336cd6
Pierre-Yves Chibon 9c2953
@UI_NS.route("/dashboard/groups/")
Pierre-Yves Chibon 9c2953
@UI_NS.route("/dashboard/groups")
Ryan Lerch 336cd6
@login_required
Ryan Lerch 336cd6
def userdash_groups():
Ryan Lerch 336cd6
    """ User Dashboard page listing a user's groups
Ryan Lerch 336cd6
    """
Ryan Lerch 336cd6
    user = _get_user(username=flask.g.fas_user.username)
Ryan Lerch 336cd6
    userdash_counts, search_data = get_userdash_common(user)
Ryan Lerch 336cd6
Ryan Lerch 336cd6
    groups = []
Ryan Lerch 336cd6
Ryan Lerch 336cd6
    for group in user.groups:
Pierre-Yves Chibon 9c2953
        groups.append(
Pierre-Yves Chibon 930073
            pagure.lib.query.search_groups(
Pierre-Yves Chibon 9c2953
                flask.g.session, group_name=group, group_type="user"
Pierre-Yves Chibon 9c2953
            )
Pierre-Yves Chibon 9c2953
        )
Ryan Lerch 336cd6
Ryan Lerch 336cd6
    return flask.render_template(
Pierre-Yves Chibon 9c2953
        "userdash_groups.html",
Ryan Lerch 336cd6
        username=flask.g.fas_user.username,
Ryan Lerch 336cd6
        user=user,
Ryan Lerch 336cd6
        select="groups",
Ryan Lerch 336cd6
        groups=groups,
Ryan Lerch 336cd6
        userdash_counts=userdash_counts,
Ryan Lerch 336cd6
        search_data=search_data,
Ryan Lerch 336cd6
    )
Ryan Lerch 336cd6
Ryan Lerch 336cd6
Pierre-Yves Chibon 9c2953
@UI_NS.route("/dashboard/forks/")
Pierre-Yves Chibon 9c2953
@UI_NS.route("/dashboard/forks")
Ryan Lerch 336cd6
@login_required
Ryan Lerch 336cd6
def userdash_forks():
Ryan Lerch 336cd6
    """ Forks tab of the user dashboard
Ryan Lerch 336cd6
    """
Ryan Lerch 336cd6
    user = _get_user(username=flask.g.fas_user.username)
Ryan Lerch 336cd6
    userdash_counts, search_data = get_userdash_common(user)
Ryan Lerch 336cd6
Pierre-Yves Chibon 9c2953
    limit = pagure_config["ITEM_PER_PAGE"]
Ryan Lerch 336cd6
Ryan Lerch 336cd6
    # FORKS
Pierre-Yves Chibon 9c2953
    forkpage = flask.request.args.get("forkpage", 1)
Ryan Lerch 336cd6
    try:
Ryan Lerch 336cd6
        forkpage = int(forkpage)
Ryan Lerch 336cd6
        if forkpage < 1:
Ryan Lerch 336cd6
            forkpage = 1
Ryan Lerch 336cd6
    except ValueError:
Ryan Lerch 336cd6
        forkpage = 1
Ryan Lerch 336cd6
Ryan Lerch 336cd6
    start = limit * (forkpage - 1)
Pierre-Yves Chibon 930073
    forks = pagure.lib.query.search_projects(
Ryan Lerch 336cd6
        flask.g.session,
Ryan Lerch 336cd6
        username=flask.g.fas_user.username,
Ryan Lerch 336cd6
        fork=True,
Ryan Lerch 336cd6
        private=flask.g.fas_user.username,
Ryan Lerch 336cd6
        start=start,
Ryan Lerch 336cd6
        limit=limit,
Ryan Lerch 336cd6
    )
Ryan Lerch 336cd6
Ryan Lerch 336cd6
    total_fork_page = int(
Pierre-Yves Chibon 9c2953
        ceil(userdash_counts["forks_length"] / float(limit))
Pierre-Yves Chibon 9c2953
        if userdash_counts["forks_length"] > 0
Pierre-Yves Chibon 9c2953
        else 1
Pierre-Yves Chibon 9c2953
    )
Ryan Lerch 336cd6
Ryan Lerch 336cd6
    return flask.render_template(
Pierre-Yves Chibon 9c2953
        "userdash_forks.html",
Ryan Lerch 336cd6
        username=flask.g.fas_user.username,
Ryan Lerch 336cd6
        user=user,
Ryan Lerch 336cd6
        select="forks",
Ryan Lerch 336cd6
        forks=forks,
Ryan Lerch 336cd6
        forkpage=forkpage,
Ryan Lerch 336cd6
        total_fork_page=total_fork_page,
Ryan Lerch 336cd6
        userdash_counts=userdash_counts,
Ryan Lerch 336cd6
        search_data=search_data,
Ryan Lerch 336cd6
    )
Ryan Lerch 336cd6
Ryan Lerch 336cd6
Pierre-Yves Chibon 9c2953
@UI_NS.route("/dashboard/watchlist/")
Pierre-Yves Chibon 9c2953
@UI_NS.route("/dashboard/watchlist")
Ryan Lerch 336cd6
@login_required
Ryan Lerch 336cd6
def userdash_watchlist():
Ryan Lerch 336cd6
    """ User Dashboard page for a user's watchlist
Ryan Lerch 336cd6
    """
Ryan Lerch 336cd6
Pierre-Yves Chibon 930073
    watch_list = pagure.lib.query.user_watch_list(
Ryan Lerch 336cd6
        flask.g.session,
Ryan Lerch 336cd6
        user=flask.g.fas_user.username,
Pierre-Yves Chibon 9c2953
        exclude_groups=pagure_config.get("EXCLUDE_GROUP_INDEX"),
Ryan Lerch 336cd6
    )
Ryan Lerch 336cd6
Ryan Lerch 336cd6
    user = _get_user(username=flask.g.fas_user.username)
Ryan Lerch 336cd6
    userdash_counts, search_data = get_userdash_common(user)
Ryan Lerch 336cd6
Ryan Lerch 336cd6
    return flask.render_template(
Pierre-Yves Chibon 9c2953
        "userdash_watchlist.html",
Ryan Lerch 336cd6
        username=flask.g.fas_user.username,
Ryan Lerch 336cd6
        user=user,
Ryan Lerch 336cd6
        select="watchlist",
Ryan Lerch 336cd6
        watch_list=watch_list,
Ryan Lerch 336cd6
        userdash_counts=userdash_counts,
Ryan Lerch 336cd6
        search_data=search_data,
Ryan Lerch 336cd6
    )
Ryan Lerch 336cd6
Ryan Lerch 336cd6
Pierre-Yves Chibon 05fa8b
def index_auth():
Pierre-Yves Chibon 05fa8b
    """ Front page for authenticated user.
Pierre-Yves Chibon 05fa8b
    """
Abhijeet Kasurde c65ec4
    user = _get_user(username=flask.g.fas_user.username)
Pierre-Yves Chibon 05fa8b
Pierre-Yves Chibon 9c2953
    acl = flask.request.args.get("acl", "").strip().lower() or None
Pierre-Yves Chibon 5cdb69
Pierre-Yves Chibon 9c2953
    repopage = flask.request.args.get("repopage", 1)
Pierre-Yves Chibon 05fa8b
    try:
Pierre-Yves Chibon 05fa8b
        repopage = int(repopage)
Pierre-Yves Chibon 97816b
        if repopage < 1:
Pierre-Yves Chibon 11d3da
            repopage = 1
Pierre-Yves Chibon 05fa8b
    except ValueError:
Pierre-Yves Chibon 05fa8b
        repopage = 1
Pierre-Yves Chibon 05fa8b
Pierre-Yves Chibon 9c2953
    limit = pagure_config["ITEM_PER_PAGE"]
Pierre-Yves Chibon 05fa8b
Pierre-Yves Chibon 76c266
    # PROJECTS
Pierre-Yves Chibon 76c266
    start = limit * (repopage - 1)
Pierre-Yves Chibon 930073
    repos = pagure.lib.query.search_projects(
Pierre-Yves Chibon b130e5
        flask.g.session,
Pierre-Yves Chibon 05fa8b
        username=flask.g.fas_user.username,
Pierre-Yves Chibon 9c2953
        exclude_groups=pagure_config.get("EXCLUDE_GROUP_INDEX"),
Pierre-Yves Chibon 76c266
        fork=False,
Pierre-Yves Chibon 76c266
        private=flask.g.fas_user.username,
Pierre-Yves Chibon 76c266
        start=start,
Pierre-Yves Chibon 76c266
        limit=limit,
Pierre-Yves Chibon 76c266
    )
Pierre-Yves Chibon 5cdb69
    if repos and acl:
Pierre-Yves Chibon 314ec8
        repos = _filter_acls(repos, acl, user)
Pierre-Yves Chibon 5cdb69
Pierre-Yves Chibon 930073
    repos_length = pagure.lib.query.search_projects(
Pierre-Yves Chibon 76c266
        flask.g.session,
Pierre-Yves Chibon 76c266
        username=flask.g.fas_user.username,
Pierre-Yves Chibon 9c2953
        exclude_groups=pagure_config.get("EXCLUDE_GROUP_INDEX"),
Pierre-Yves Chibon 76c266
        fork=False,
Pierre-Yves Chibon 76c266
        private=flask.g.fas_user.username,
Pierre-Yves Chibon 76c266
        count=True,
Pierre-Yves Chibon 76c266
    )
Pierre-Yves Chibon 76c266
    total_repo_page = int(
Pierre-Yves Chibon 9c2953
        ceil(repos_length / float(limit)) if repos_length > 0 else 1
Pierre-Yves Chibon 9c2953
    )
Pierre-Yves Chibon 76c266
Pierre-Yves Chibon 76c266
    # FORKS
Pierre-Yves Chibon 9c2953
    forkpage = flask.request.args.get("forkpage", 1)
Pierre-Yves Chibon 76c266
    try:
Pierre-Yves Chibon 76c266
        forkpage = int(forkpage)
Pierre-Yves Chibon 76c266
        if forkpage < 1:
Pierre-Yves Chibon 76c266
            forkpage = 1
Pierre-Yves Chibon 76c266
    except ValueError:
Pierre-Yves Chibon 76c266
        forkpage = 1
Pierre-Yves Chibon 05fa8b
Pierre-Yves Chibon 76c266
    start = limit * (forkpage - 1)
Pierre-Yves Chibon 930073
    forks = pagure.lib.query.search_projects(
Pierre-Yves Chibon b130e5
        flask.g.session,
Pierre-Yves Chibon 05fa8b
        username=flask.g.fas_user.username,
farhaanbukhsh b25a08
        fork=True,
Pierre-Yves Chibon 76c266
        private=flask.g.fas_user.username,
Pierre-Yves Chibon 76c266
        start=start,
Pierre-Yves Chibon 76c266
        limit=limit,
Pierre-Yves Chibon 76c266
    )
farhaanbukhsh 354dc1
Pierre-Yves Chibon 930073
    forks_length = pagure.lib.query.search_projects(
Pierre-Yves Chibon 76c266
        flask.g.session,
Pierre-Yves Chibon 76c266
        username=flask.g.fas_user.username,
Pierre-Yves Chibon 76c266
        fork=True,
Pierre-Yves Chibon 76c266
        private=flask.g.fas_user.username,
Pierre-Yves Chibon 76c266
        start=start,
Pierre-Yves Chibon 76c266
        limit=limit,
Pierre-Yves Chibon 76c266
        count=True,
Pierre-Yves Chibon 76c266
    )
Pierre-Yves Chibon 76c266
    total_fork_page = int(
Pierre-Yves Chibon 9c2953
        ceil(forks_length / float(limit)) if forks_length > 0 else 1
Pierre-Yves Chibon 9c2953
    )
Pierre-Yves Chibon 05fa8b
Pierre-Yves Chibon 930073
    watch_list = pagure.lib.query.user_watch_list(
Pierre-Yves Chibon b130e5
        flask.g.session,
Pierre-Yves Chibon 9803ba
        user=flask.g.fas_user.username,
Pierre-Yves Chibon 9c2953
        exclude_groups=pagure_config.get("EXCLUDE_GROUP_INDEX"),
Pierre-Yves Chibon 9803ba
    )
Vivek Anand 272efb
Pierre-Yves Chibon 05fa8b
    return flask.render_template(
Pierre-Yves Chibon 9c2953
        "userdash_projects.html",
Pierre-Yves Chibon 05fa8b
        username=flask.g.fas_user.username,
Pierre-Yves Chibon 05fa8b
        user=user,
Pierre-Yves Chibon 05fa8b
        forks=forks,
Pierre-Yves Chibon 05fa8b
        repos=repos,
Vivek Anand 272efb
        watch_list=watch_list,
Johan Cwiklinski b95406
        repopage=repopage,
Pierre-Yves Chibon 05fa8b
        repos_length=repos_length,
Pierre-Yves Chibon 76c266
        total_repo_page=total_repo_page,
Pierre-Yves Chibon 76c266
        forkpage=forkpage,
Pierre-Yves Chibon 05fa8b
        forks_length=forks_length,
Pierre-Yves Chibon 76c266
        total_fork_page=total_fork_page,
Pierre-Yves Chibon 2088eb
    )
Pierre-Yves Chibon 2088eb
Pierre-Yves Chibon 2088eb
Pierre-Yves Chibon 9c2953
@UI_NS.route("/search/")
Pierre-Yves Chibon 9c2953
@UI_NS.route("/search")
Pierre-Yves Chibon 30af48
def search():
Pierre-Yves Chibon 30af48
    """ Search this pagure instance for projects or users.
Pierre-Yves Chibon 30af48
    """
Pierre-Yves Chibon 9c2953
    stype = flask.request.args.get("type", "projects")
Pierre-Yves Chibon 9c2953
    term = flask.request.args.get("term")
Pierre-Yves Chibon 9c2953
    page = flask.request.args.get("page", 1)
Pierre-Yves Chibon 9c2953
    direct = is_true(flask.request.values.get("direct", False))
Pierre-Yves Chibon 1ca90b
Pierre-Yves Chibon 30af48
    try:
Pierre-Yves Chibon 30af48
        page = int(page)
Pierre-Yves Chibon 97816b
        if page < 1:
Pierre-Yves Chibon 97816b
            page = 1
Pierre-Yves Chibon 30af48
    except ValueError:
Pierre-Yves Chibon 30af48
        page = 1
Pierre-Yves Chibon 30af48
Pierre-Yves Chibon 1ca90b
    if direct:
Pierre-Yves Chibon 9c2953
        return flask.redirect(flask.url_for("ui_ns.view_repo", repo="") + term)
Pierre-Yves Chibon 9c2953
Pierre-Yves Chibon 9c2953
    if stype == "projects":
Pierre-Yves Chibon 1ca90b
        return flask.redirect(
Pierre-Yves Chibon 9c2953
            flask.url_for("ui_ns.view_projects", pattern=term)
Pierre-Yves Chibon 1ca90b
        )
Pierre-Yves Chibon 9c2953
    elif stype == "projects_forks":
Pierre-Yves Chibon 9c2953
        return flask.redirect(
Pierre-Yves Chibon 9c2953
            flask.url_for("view_projects", pattern=term, forks=True)
Pierre-Yves Chibon 9c2953
        )
Pierre-Yves Chibon 9c2953
    elif stype == "groups":
Pierre-Yves Chibon 9c2953
        return flask.redirect(flask.url_for("ui_ns.view_group", group=term))
Pierre-Yves Chibon 30af48
    else:
Pierre-Yves Chibon 9c2953
        return flask.redirect(flask.url_for("ui_ns.view_users", username=term))
Pierre-Yves Chibon 30af48
Pierre-Yves Chibon 30af48
Pierre-Yves Chibon 9c2953
@UI_NS.route("/users/")
Pierre-Yves Chibon 9c2953
@UI_NS.route("/users")
Pierre-Yves Chibon 9c2953
@UI_NS.route("/users/<username>")</username>
Pierre-Yves Chibon 30af48
def view_users(username=None):
Pierre-Yves Chibon 47950c
    """ Present the list of users.
Pierre-Yves Chibon 2088eb
    """
Pierre-Yves Chibon 9c2953
    page = flask.request.args.get("page", 1)
Pierre-Yves Chibon 47950c
    try:
Pierre-Yves Chibon 47950c
        page = int(page)
Pierre-Yves Chibon 9d16ce
        if page < 1:
Pierre-Yves Chibon 9d16ce
            page = 1
Pierre-Yves Chibon 47950c
    except ValueError:
Pierre-Yves Chibon 47950c
        page = 1
Mathieu Bridon 4c73b0
Pierre-Yves Chibon 930073
    users = pagure.lib.query.search_user(flask.g.session, pattern=username)
Pierre-Yves Chibon 30af48
farhaanbukhsh 354dc1
    private = False
Farhaan Bukhsh 079703
    # Condition to check non-authorized user should't be able to access private
Farhaan Bukhsh 079703
    # project of other users
Pierre-Yves Chibon 3604c1
    if authenticated() and username == flask.g.fas_user.username:
farhaanbukhsh 4e0a2c
        private = flask.g.fas_user.username
farhaanbukhsh 4e0a2c
Pierre-Yves Chibon 9c2953
    limit = pagure_config["ITEM_PER_PAGE"]
Pierre-Yves Chibon 47950c
    start = limit * (page - 1)
Pierre-Yves Chibon 47950c
    end = limit * page
Pierre-Yves Chibon 47950c
    users_length = len(users)
Pierre-Yves Chibon 47950c
    users = users[start:end]
Pierre-Yves Chibon 2088eb
Pierre-Yves Chibon 47950c
    total_page = int(ceil(users_length / float(limit)))
Pierre-Yves Chibon 2088eb
Ryan Lerch 614942
    for user in users:
Pierre-Yves Chibon 930073
        repos_length = pagure.lib.query.search_projects(
Pierre-Yves Chibon b130e5
            flask.g.session,
Clement Verna e4212e
            username=user.user,
Clement Verna e4212e
            fork=False,
farhaanbukhsh b25a08
            count=True,
Pierre-Yves Chibon 9c2953
            private=private,
Pierre-Yves Chibon 9c2953
        )
Ryan Lerch 614942
Pierre-Yves Chibon 930073
        forks_length = pagure.lib.query.search_projects(
Pierre-Yves Chibon b130e5
            flask.g.session,
Clement Verna e4212e
            username=user.user,
Clement Verna e4212e
            fork=True,
farhaanbukhsh b25a08
            count=True,
Pierre-Yves Chibon 9c2953
            private=private,
Pierre-Yves Chibon 9c2953
        )
Ryan Lerch 614942
        user.repos_length = repos_length
Ryan Lerch 614942
        user.forks_length = forks_length
Ryan Lerch 614942
Pierre-Yves Chibon 2088eb
    return flask.render_template(
Pierre-Yves Chibon 9c2953
        "user_list.html",
Pierre-Yves Chibon 47950c
        users=users,
Pierre-Yves Chibon 4cdfa6
        users_length=users_length,
Pierre-Yves Chibon 47950c
        total_page=total_page,
Pierre-Yves Chibon 47950c
        page=page,
Pierre-Yves Chibon 9c2953
        select="users",
Pierre-Yves Chibon 664d79
    )
Pierre-Yves Chibon 664d79
Pierre-Yves Chibon 664d79
Pierre-Yves Chibon 9c2953
@UI_NS.route("/projects/")
Pierre-Yves Chibon 9c2953
@UI_NS.route("/projects")
Pierre-Yves Chibon 9c2953
@UI_NS.route("/projects/<pattern>")</pattern>
Pierre-Yves Chibon 9c2953
@UI_NS.route("/projects/<namespace>/<pattern>")</pattern></namespace>
Pierre-Yves Chibon 4501da
def view_projects(pattern=None, namespace=None):
Pierre-Yves Chibon 664d79
    """ Present the list of projects.
Pierre-Yves Chibon 664d79
    """
Pierre-Yves Chibon 9c2953
    forks = flask.request.args.get("forks")
Pierre-Yves Chibon 9c2953
    page = flask.request.args.get("page", 1)
Pierre-Yves Chibon 664d79
Pierre-Yves Chibon 664d79
    try:
Pierre-Yves Chibon 664d79
        page = int(page)
Pierre-Yves Chibon 9d16ce
        if page < 1:
Pierre-Yves Chibon 9d16ce
            page = 1
Pierre-Yves Chibon 664d79
    except ValueError:
Pierre-Yves Chibon 664d79
        page = 1
Pierre-Yves Chibon 664d79
Pierre-Yves Chibon 9c2953
    select = "projects"
Pierre-Yves Chibon 664d79
    # If forks is specified, we want both forks and projects
Aurélien Bompard 619e2a
    if is_true(forks):
Pierre-Yves Chibon 664d79
        forks = None
Pierre-Yves Chibon 9c2953
        select = "projects_forks"
Pierre-Yves Chibon ab7d20
    else:
Pierre-Yves Chibon ab7d20
        forks = False
farhaanbukhsh 354dc1
    private = False
Pierre-Yves Chibon 664d79
farhaanbukhsh 4e0a2c
    if authenticated():
farhaanbukhsh 4e0a2c
        private = flask.g.fas_user.username
farhaanbukhsh 4e0a2c
Pierre-Yves Chibon 9c2953
    limit = pagure_config["ITEM_PER_PAGE"]
Pierre-Yves Chibon 664d79
    start = limit * (page - 1)
Pierre-Yves Chibon 664d79
Pierre-Yves Chibon 930073
    projects = pagure.lib.query.search_projects(
Pierre-Yves Chibon 9c2953
        flask.g.session,
Pierre-Yves Chibon 9c2953
        pattern=pattern,
Pierre-Yves Chibon 9c2953
        namespace=namespace,
Pierre-Yves Chibon 9c2953
        fork=forks,
Pierre-Yves Chibon 9c2953
        start=start,
Pierre-Yves Chibon 9c2953
        limit=limit,
Pierre-Yves Chibon 9c2953
        private=private,
Pierre-Yves Chibon 9c2953
    )
Pierre-Yves Chibon 664d79
Pierre-Yves Chibon 664d79
    if len(projects) == 1:
Pierre-Yves Chibon 9c2953
        flask.flash("Only one result found, redirecting you to it")
Pierre-Yves Chibon 9c2953
        return flask.redirect(
Pierre-Yves Chibon 9c2953
            flask.url_for(
Pierre-Yves Chibon 9c2953
                "ui_ns.view_repo",
Pierre-Yves Chibon 9c2953
                repo=projects[0].name,
Pierre-Yves Chibon 9c2953
                namespace=projects[0].namespace,
Pierre-Yves Chibon 9c2953
                username=projects[0].user.username
Pierre-Yves Chibon 9c2953
                if projects[0].is_fork
Pierre-Yves Chibon 9c2953
                else None,
Pierre-Yves Chibon 9c2953
            )
Pierre-Yves Chibon 9c2953
        )
Pierre-Yves Chibon 664d79
Pierre-Yves Chibon 930073
    projects_length = pagure.lib.query.search_projects(
Pierre-Yves Chibon 9c2953
        flask.g.session,
Pierre-Yves Chibon 9c2953
        pattern=pattern,
Pierre-Yves Chibon 9c2953
        namespace=namespace,
Pierre-Yves Chibon 9c2953
        fork=forks,
Pierre-Yves Chibon 9c2953
        count=True,
Pierre-Yves Chibon 9c2953
        private=private,
Pierre-Yves Chibon 9c2953
    )
Pierre-Yves Chibon 664d79
Pierre-Yves Chibon 664d79
    total_page = int(ceil(projects_length / float(limit)))
Pierre-Yves Chibon 664d79
Pierre-Yves Chibon 48b2c5
    if namespace in pagure_config["ALLOWED_PREFIX"]:
Pierre-Yves Chibon 48b2c5
        namespace = None
Pierre-Yves Chibon 48b2c5
Pierre-Yves Chibon 664d79
    return flask.render_template(
Pierre-Yves Chibon 9c2953
        "index.html",
Pierre-Yves Chibon 48b2c5
        namespace=namespace,
Pierre-Yves Chibon 664d79
        repos=projects,
Gaurav Kumar 567cf2
        repos_length=projects_length,
Pierre-Yves Chibon 664d79
        total_page=total_page,
Pierre-Yves Chibon 664d79
        page=page,
Pierre-Yves Chibon 664d79
        select=select,
Pierre-Yves Chibon 2088eb
    )
Pierre-Yves Chibon 2088eb
Pierre-Yves Chibon 84f83a
Ryan Lerch e1f88b
def get_userprofile_common(user):
Ryan Lerch e1f88b
    userprofile_counts = {}
Ryan Lerch e1f88b
Pierre-Yves Chibon 930073
    userprofile_counts["repos_length"] = pagure.lib.query.search_projects(
Ryan Lerch e1f88b
        flask.g.session,
Ryan Lerch e1f88b
        username=user.username,
Ryan Lerch e1f88b
        fork=False,
Ryan Lerch e1f88b
        exclude_groups=None,
Ryan Lerch e1f88b
        private=False,
Pierre-Yves Chibon 9c2953
        count=True,
Pierre-Yves Chibon 9c2953
    )
Ryan Lerch e1f88b
Pierre-Yves Chibon 930073
    userprofile_counts["forks_length"] = pagure.lib.query.search_projects(
Ryan Lerch e1f88b
        flask.g.session,
Ryan Lerch e1f88b
        username=user.username,
Ryan Lerch e1f88b
        fork=True,
Ryan Lerch e1f88b
        private=False,
Pierre-Yves Chibon 9c2953
        count=True,
Pierre-Yves Chibon 9c2953
    )
Ryan Lerch e1f88b
Ryan Lerch e1f88b
    return userprofile_counts
Ryan Lerch e1f88b
Pierre-Yves Chibon f0babf
Pierre-Yves Chibon 9c2953
@UI_NS.route("/user/<username>/")</username>
Pierre-Yves Chibon 9c2953
@UI_NS.route("/user/<username>")</username>
Pierre-Yves Chibon 47950c
def view_user(username):
Pierre-Yves Chibon 47950c
    """ Front page of a specific user.
Pierre-Yves Chibon 2088eb
    """
Abhijeet Kasurde c65ec4
    user = _get_user(username=username)
Pierre-Yves Chibon 2088eb
Ryan Lerch e1f88b
    # public profile, so never show private repos,
Ryan Lerch e1f88b
    # even if the user is viewing themself
Ryan Lerch e1f88b
    private = False
Ryan Lerch e1f88b
Pierre-Yves Chibon 930073
    owned_repos = pagure.lib.query.list_users_projects(
Ryan Lerch e1f88b
        flask.g.session,
Ryan Lerch e1f88b
        username=username,
Ryan Lerch e1f88b
        exclude_groups=None,
Ryan Lerch e1f88b
        fork=False,
Ryan Lerch e1f88b
        private=private,
Ryan Lerch e1f88b
        limit=6,
Ryan Lerch e1f88b
        acls=["main admin"],
Ryan Lerch e1f88b
    )
Ryan Lerch e1f88b
Ryan Lerch e1f88b
    userprofile_common = get_userprofile_common(user)
Ryan Lerch e1f88b
Ryan Lerch e1f88b
    return flask.render_template(
Pierre-Yves Chibon 9c2953
        "userprofile_overview.html",
Ryan Lerch e1f88b
        username=username,
Ryan Lerch e1f88b
        user=user,
Ryan Lerch e1f88b
        owned_repos=owned_repos,
Pierre-Yves Chibon 9c2953
        repos_length=userprofile_common["repos_length"],
Pierre-Yves Chibon 9c2953
        forks_length=userprofile_common["forks_length"],
Pierre-Yves Chibon 9c2953
        select="overview",
Ryan Lerch e1f88b
    )
Ryan Lerch e1f88b
Ryan Lerch e1f88b
Pierre-Yves Chibon 9c2953
@UI_NS.route("/user/<username>/projects/")</username>
Pierre-Yves Chibon 9c2953
@UI_NS.route("/user/<username>/projects")</username>
Ryan Lerch e1f88b
def userprofile_projects(username):
Ryan Lerch e1f88b
    """ Public Profile view of a user's projects.
Ryan Lerch e1f88b
    """
Ryan Lerch e1f88b
    user = _get_user(username=username)
Ryan Lerch e1f88b
Pierre-Yves Chibon 9c2953
    repopage = flask.request.args.get("repopage", 1)
Ryan Lerch e1f88b
    try:
Ryan Lerch e1f88b
        repopage = int(repopage)
Ryan Lerch e1f88b
        if repopage < 1:
Ryan Lerch e1f88b
            repopage = 1
Ryan Lerch e1f88b
    except ValueError:
Ryan Lerch e1f88b
        repopage = 1
Ryan Lerch e1f88b
Pierre-Yves Chibon 9c2953
    limit = pagure_config["ITEM_PER_PAGE"]
Ryan Lerch e1f88b
    repo_start = limit * (repopage - 1)
Ryan Lerch e1f88b
Pierre-Yves Chibon 930073
    repos = pagure.lib.query.search_projects(
Ryan Lerch e1f88b
        flask.g.session,
Ryan Lerch e1f88b
        username=username,
Ryan Lerch e1f88b
        fork=False,
Pierre-Yves Chibon 9c2953
        exclude_groups=pagure_config.get("EXCLUDE_GROUP_INDEX"),
Ryan Lerch e1f88b
        start=repo_start,
Ryan Lerch e1f88b
        limit=limit,
Pierre-Yves Chibon 9c2953
        private=False,
Pierre-Yves Chibon 9c2953
    )
Ryan Lerch e1f88b
Ryan Lerch e1f88b
    userprofile_common = get_userprofile_common(user)
Ryan Lerch e1f88b
    total_page_repos = int(
Pierre-Yves Chibon 9c2953
        ceil(userprofile_common["repos_length"] / float(limit))
Pierre-Yves Chibon 9c2953
    )
Ryan Lerch e1f88b
Ryan Lerch e1f88b
    return flask.render_template(
Pierre-Yves Chibon 9c2953
        "userprofile_projects.html",
Ryan Lerch e1f88b
        username=username,
Ryan Lerch e1f88b
        user=user,
Ryan Lerch e1f88b
        repos=repos,
Ryan Lerch e1f88b
        total_page_repos=total_page_repos,
Ryan Lerch e1f88b
        repopage=repopage,
Pierre-Yves Chibon 9c2953
        repos_length=userprofile_common["repos_length"],
Pierre-Yves Chibon 9c2953
        forks_length=userprofile_common["forks_length"],
Ryan Lerch e1f88b
        select="projects",
Ryan Lerch e1f88b
    )
Ryan Lerch e1f88b
Pierre-Yves Chibon f0babf
Pierre-Yves Chibon 9c2953
@UI_NS.route("/user/<username>/forks/")</username>
Pierre-Yves Chibon 9c2953
@UI_NS.route("/user/<username>/forks")</username>
Ryan Lerch e1f88b
def userprofile_forks(username):
Ryan Lerch e1f88b
    """ Public Profile view of a user's forks.
Ryan Lerch e1f88b
    """
Ryan Lerch e1f88b
    user = _get_user(username=username)
Ryan Lerch e1f88b
Pierre-Yves Chibon 9c2953
    forkpage = flask.request.args.get("forkpage", 1)
Ryan Lerch e1f88b
    try:
Ryan Lerch e1f88b
        forkpage = int(forkpage)
Ryan Lerch e1f88b
        if forkpage < 1:
Ryan Lerch e1f88b
            forkpage = 1
Ryan Lerch e1f88b
    except ValueError:
Ryan Lerch e1f88b
        forkpage = 1
Ryan Lerch e1f88b
Pierre-Yves Chibon 9c2953
    limit = pagure_config["ITEM_PER_PAGE"]
Ryan Lerch e1f88b
    fork_start = limit * (forkpage - 1)
Ryan Lerch e1f88b
Pierre-Yves Chibon 930073
    forks = pagure.lib.query.search_projects(
Ryan Lerch e1f88b
        flask.g.session,
Ryan Lerch e1f88b
        username=username,
Ryan Lerch e1f88b
        fork=True,
Ryan Lerch e1f88b
        start=fork_start,
Ryan Lerch e1f88b
        limit=limit,
Pierre-Yves Chibon 9c2953
        private=False,
Pierre-Yves Chibon 9c2953
    )
Ryan Lerch e1f88b
Ryan Lerch e1f88b
    userprofile_common = get_userprofile_common(user)
Ryan Lerch e1f88b
    total_page_forks = int(
Pierre-Yves Chibon 9c2953
        ceil(userprofile_common["forks_length"] / float(limit))
Pierre-Yves Chibon 9c2953
    )
Ryan Lerch e1f88b
Ryan Lerch e1f88b
    return flask.render_template(
Pierre-Yves Chibon 9c2953
        "userprofile_forks.html",
Ryan Lerch e1f88b
        username=username,
Ryan Lerch e1f88b
        user=user,
Ryan Lerch e1f88b
        forks=forks,
Ryan Lerch e1f88b
        total_page_forks=total_page_forks,
Ryan Lerch e1f88b
        forkpage=forkpage,
Pierre-Yves Chibon 9c2953
        repos_length=userprofile_common["repos_length"],
Pierre-Yves Chibon 9c2953
        forks_length=userprofile_common["forks_length"],
Ryan Lerch e1f88b
        select="forks",
Ryan Lerch e1f88b
    )
Ryan Lerch e1f88b
Ryan Lerch e1f88b
Ryan Lerch e1f88b
# original view_user()
Pierre-Yves Chibon 9c2953
@UI_NS.route("/user2/<username>/")</username>
Pierre-Yves Chibon 9c2953
@UI_NS.route("/user2/<username>")</username>
Ryan Lerch e1f88b
def view_user2(username):
Ryan Lerch e1f88b
    """ Front page of a specific user.
Ryan Lerch e1f88b
    """
Ryan Lerch e1f88b
    user = _get_user(username=username)
Ryan Lerch e1f88b
Pierre-Yves Chibon 9c2953
    acl = flask.request.args.get("acl", "").strip().lower() or None
Pierre-Yves Chibon 5cdb69
Pierre-Yves Chibon 9c2953
    repopage = flask.request.args.get("repopage", 1)
Pierre-Yves Chibon 2088eb
    try:
Pierre-Yves Chibon 47950c
        repopage = int(repopage)
Pierre-Yves Chibon 9d16ce
        if repopage < 1:
Pierre-Yves Chibon 9d16ce
            repopage = 1
Pierre-Yves Chibon 2088eb
    except ValueError:
Pierre-Yves Chibon 47950c
        repopage = 1
Mathieu Bridon 6dd1b4
Pierre-Yves Chibon 9c2953
    forkpage = flask.request.args.get("forkpage", 1)
Pierre-Yves Chibon 47950c
    try:
Pierre-Yves Chibon 47950c
        forkpage = int(forkpage)
Pierre-Yves Chibon 9d16ce
        if forkpage < 1:
Pierre-Yves Chibon 9d16ce
            forkpage = 1
Pierre-Yves Chibon 47950c
    except ValueError:
Pierre-Yves Chibon 47950c
        forkpage = 1
Pierre-Yves Chibon 12e862
Pierre-Yves Chibon 9c2953
    limit = pagure_config["ITEM_PER_PAGE"]
Pierre-Yves Chibon 47950c
    repo_start = limit * (repopage - 1)
Pierre-Yves Chibon 47950c
    fork_start = limit * (forkpage - 1)
Pierre-Yves Chibon 47950c
farhaanbukhsh 354dc1
    private = False
Pierre-Yves Chibon 3604c1
    if authenticated() and username == flask.g.fas_user.username:
farhaanbukhsh 4e0a2c
        private = flask.g.fas_user.username
farhaanbukhsh 4e0a2c
Pierre-Yves Chibon 930073
    repos = pagure.lib.query.search_projects(
Pierre-Yves Chibon b130e5
        flask.g.session,
Pierre-Yves Chibon e480a3
        username=username,
Pierre-Yves Chibon 47950c
        fork=False,
Pierre-Yves Chibon 9c2953
        exclude_groups=pagure_config.get("EXCLUDE_GROUP_INDEX"),
Pierre-Yves Chibon 47950c
        start=repo_start,
farhaanbukhsh 4e0a2c
        limit=limit,
Pierre-Yves Chibon 9c2953
        private=private,
Pierre-Yves Chibon 9c2953
    )
Pierre-Yves Chibon 5cdb69
Pierre-Yves Chibon 5cdb69
    if repos and acl:
Pierre-Yves Chibon 314ec8
        repos = _filter_acls(repos, acl, user)
Pierre-Yves Chibon 5cdb69
Pierre-Yves Chibon 930073
    repos_length = pagure.lib.query.search_projects(
Pierre-Yves Chibon c77934
        flask.g.session,
Pierre-Yves Chibon c77934
        username=username,
Pierre-Yves Chibon c77934
        fork=False,
Pierre-Yves Chibon 9c2953
        exclude_groups=pagure_config.get("EXCLUDE_GROUP_INDEX"),
Pierre-Yves Chibon c77934
        private=private,
Pierre-Yves Chibon 9c2953
        count=True,
Pierre-Yves Chibon 9c2953
    )
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 930073
    forks = pagure.lib.query.search_projects(
Pierre-Yves Chibon b130e5
        flask.g.session,
Pierre-Yves Chibon e480a3
        username=username,
Pierre-Yves Chibon 47950c
        fork=True,
Pierre-Yves Chibon 47950c
        start=fork_start,
farhaanbukhsh 3f2e6f
        limit=limit,
Pierre-Yves Chibon 9c2953
        private=private,
Pierre-Yves Chibon 9c2953
    )
Pierre-Yves Chibon c77934
Pierre-Yves Chibon 930073
    forks_length = pagure.lib.query.search_projects(
Pierre-Yves Chibon c77934
        flask.g.session,
Pierre-Yves Chibon c77934
        username=username,
Pierre-Yves Chibon c77934
        fork=True,
Pierre-Yves Chibon c77934
        private=private,
Pierre-Yves Chibon 9c2953
        count=True,
Pierre-Yves Chibon 9c2953
    )
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
    total_page_repos = int(ceil(repos_length / float(limit)))
Pierre-Yves Chibon 47950c
    total_page_forks = int(ceil(forks_length / float(limit)))
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 12e862
    return flask.render_template(
Pierre-Yves Chibon 9c2953
        "userprofile_overview.html",
Pierre-Yves Chibon ac8023
        username=username,
Pierre-Yves Chibon a5eab2
        user=user,
Pierre-Yves Chibon 47950c
        repos=repos,
Pierre-Yves Chibon 47950c
        total_page_repos=total_page_repos,
Pierre-Yves Chibon 47950c
        forks=forks,
Pierre-Yves Chibon 47950c
        total_page_forks=total_page_forks,
Pierre-Yves Chibon 47950c
        repopage=repopage,
Pierre-Yves Chibon 47950c
        forkpage=forkpage,
Johan Cwiklinski 63918a
        repos_length=repos_length,
Johan Cwiklinski 63918a
        forks_length=forks_length,
Pierre-Yves Chibon 12e862
    )
Pierre-Yves Chibon eb2817
Pierre-Yves Chibon eb2817
Pierre-Yves Chibon 9c2953
@UI_NS.route("/user/<username>/requests/")</username>
Pierre-Yves Chibon 9c2953
@UI_NS.route("/user/<username>/requests")</username>
Pierre-Yves Chibon 331e1c
def view_user_requests(username):
Pierre-Yves Chibon 331e1c
    """ Shows the pull-requests for the specified user.
Pierre-Yves Chibon 331e1c
    """
Abhijeet Kasurde c65ec4
    user = _get_user(username=username)
Pierre-Yves Chibon 331e1c
Pierre-Yves Chibon 930073
    requests = pagure.lib.query.get_pull_request_of_user(
Pierre-Yves Chibon 9c2953
        flask.g.session, username=username
Pierre-Yves Chibon 331e1c
    )
Pierre-Yves Chibon 331e1c
Ryan Lerch ca8575
    userprofile_common = get_userprofile_common(user)
Ryan Lerch ca8575
Pierre-Yves Chibon 331e1c
    return flask.render_template(
Ryan Lerch ca8575
        "userprofile_pullrequests.html",
Ryan Lerch ca8575
        username=username,
Ryan Lerch ca8575
        user=user,
Ryan Lerch ca8575
        requests=requests,
Ryan Lerch ca8575
        select="requests",
Ryan Lerch ca8575
        repos_length=userprofile_common["repos_length"],
Ryan Lerch ca8575
        forks_length=userprofile_common["forks_length"],
Pierre-Yves Chibon 331e1c
    )
Pierre-Yves Chibon 331e1c
Pierre-Yves Chibon 331e1c
Pierre-Yves Chibon 9c2953
@UI_NS.route("/user/<username>/issues/")</username>
Pierre-Yves Chibon 9c2953
@UI_NS.route("/user/<username>/issues")</username>
Jeremy Cline babe37
def view_user_issues(username):
Jeremy Cline babe37
    """
Pierre-Yves Chibon 06fa53
    Shows the issues created or assigned to the specified user.
Jeremy Cline babe37
Jeremy Cline babe37
    :param username: The username to retrieve the issues for
Jeremy Cline babe37
    :type  username: str
Jeremy Cline babe37
    """
Vivek Anand 6e91ca
Pierre-Yves Chibon 9c2953
    if not pagure_config.get("ENABLE_TICKETS", True):
Pierre-Yves Chibon c6cc5c
        flask.abort(
Pierre-Yves Chibon c6cc5c
            404,
Pierre-Yves Chibon c6cc5c
            description="Tickets have been disabled on this pagure instance",
Pierre-Yves Chibon c6cc5c
        )
Vivek Anand 6e91ca
Abhijeet Kasurde c65ec4
    user = _get_user(username=username)
Ryan Lerch eea5a4
    userprofile_common = get_userprofile_common(user)
Jeremy Cline babe37
Jeremy Cline babe37
    return flask.render_template(
Ryan Lerch eea5a4
        "userprofile_issues.html",
Ryan Lerch eea5a4
        username=username,
Ryan Lerch eea5a4
        user=user,
Ryan Lerch eea5a4
        repos_length=userprofile_common["repos_length"],
Ryan Lerch eea5a4
        forks_length=userprofile_common["forks_length"],
Patrick Uiterwijk a32fb7
        select="issues",
Jeremy Cline babe37
    )
Jeremy Cline babe37
Jeremy Cline babe37
Pierre-Yves Chibon 9c2953
@UI_NS.route("/user/<username>/stars/")</username>
Pierre-Yves Chibon 9c2953
@UI_NS.route("/user/<username>/stars")</username>
Ryan Lerch e1f88b
def userprofile_starred(username):
Vivek Anand f019f5
    """
Vivek Anand f019f5
    Shows the starred projects of the specified user.
Vivek Anand f019f5
Vivek Anand 7746b7
    :arg username: The username whose stars we have to retrieve
Vivek Anand f019f5
    """
Vivek Anand f019f5
Vivek Anand f019f5
    user = _get_user(username=username)
Ryan Lerch e1f88b
    userprofile_common = get_userprofile_common(user)
Vivek Anand f019f5
Vivek Anand f019f5
    return flask.render_template(
Pierre-Yves Chibon 9c2953
        "userprofile_starred.html",
Vivek Anand f019f5
        username=username,
Vivek Anand f019f5
        user=user,
Vivek Anand f019f5
        repos=[star.project for star in user.stars],
Pierre-Yves Chibon 9c2953
        repos_length=userprofile_common["repos_length"],
Pierre-Yves Chibon 9c2953
        forks_length=userprofile_common["forks_length"],
Ryan Lerch e1f88b
        select="starred",
Ryan Lerch e1f88b
    )
Ryan Lerch e1f88b
Pierre-Yves Chibon f0babf
Pierre-Yves Chibon 9c2953
@UI_NS.route("/user/<username>/groups/")</username>
Pierre-Yves Chibon 9c2953
@UI_NS.route("/user/<username>/groups")</username>
Ryan Lerch e1f88b
def userprofile_groups(username):
Ryan Lerch e1f88b
    """
Ryan Lerch e1f88b
    Shows the groups of a user
Ryan Lerch e1f88b
    """
Ryan Lerch e1f88b
Ryan Lerch e1f88b
    user = _get_user(username=username)
Ryan Lerch e1f88b
    userprofile_common = get_userprofile_common(user)
Ryan Lerch e1f88b
Ryan Lerch e1f88b
    groups = []
Ryan Lerch e1f88b
    for groupname in user.groups:
Ryan Lerch e1f88b
        groups.append(
Pierre-Yves Chibon 930073
            pagure.lib.query.search_groups(
Pierre-Yves Chibon 930073
                flask.g.session, group_name=groupname
Pierre-Yves Chibon 930073
            )
Pierre-Yves Chibon 9c2953
        )
Ryan Lerch e1f88b
Ryan Lerch e1f88b
    return flask.render_template(
Pierre-Yves Chibon 9c2953
        "userprofile_groups.html",
Ryan Lerch e1f88b
        username=username,
Ryan Lerch e1f88b
        user=user,
Ryan Lerch e1f88b
        groups=groups,
Pierre-Yves Chibon 9c2953
        repos_length=userprofile_common["repos_length"],
Pierre-Yves Chibon 9c2953
        forks_length=userprofile_common["forks_length"],
Ryan Lerch e1f88b
        select="groups",
Vivek Anand f019f5
    )
Vivek Anand f019f5
Vivek Anand f019f5
Pierre-Yves Chibon 9c2953
@UI_NS.route("/new/", methods=("GET", "POST"))
Pierre-Yves Chibon 9c2953
@UI_NS.route("/new", methods=("GET", "POST"))
Pierre-Yves Chibon cf7f54
@login_required
Pierre-Yves Chibon 47950c
def new_project():
Pierre-Yves Chibon 47950c
    """ Form to create a new project.
Pierre-Yves Chibon a204a8
    """
Pierre-Yves Chibon 08da0d
Pierre-Yves Chibon 930073
    user = pagure.lib.query.search_user(
Pierre-Yves Chibon 9c2953
        flask.g.session, username=flask.g.fas_user.username
Pierre-Yves Chibon 9c2953
    )
Ryan Lerch 743aca
Pierre-Yves Chibon 9c2953
    if not pagure_config.get(
Pierre-Yves Chibon 9c2953
        "ENABLE_NEW_PROJECTS", True
Pierre-Yves Chibon 9c2953
    ) or not pagure_config.get("ENABLE_UI_NEW_PROJECTS", True):
Pierre-Yves Chibon 9c2953
        flask.abort(
Pierre-Yves Chibon 9c2953
            404,
Pierre-Yves Chibon c6cc5c
            description="Creation of new project is not allowed on this \
Pierre-Yves Chibon 9c2953
                pagure instance",
Pierre-Yves Chibon 9c2953
        )
Pierre-Yves Chibon 8c1d55
Pierre-Yves Chibon 9c2953
    namespaces = pagure_config["ALLOWED_PREFIX"][:]
Pierre-Yves Chibon 0da54e
    if user:
Pierre-Yves Chibon 0da54e
        namespaces.extend([grp for grp in user.groups])
Pierre-Yves Chibon 9c2953
    if pagure_config.get("USER_NAMESPACE", False):
Pierre-Yves Chibon 3175b1
        namespaces.insert(0, flask.g.fas_user.username)
Pierre-Yves Chibon db3f3c
Pierre-Yves Chibon db3f3c
    form = pagure.forms.ProjectForm(namespaces=namespaces)
Pierre-Yves Chibon db3f3c
Pierre-Yves Chibon a204a8
    if form.validate_on_submit():
Pierre-Yves Chibon 47950c
        name = form.name.data
Pierre-Yves Chibon 47950c
        description = form.description.data
Pierre-Yves Chibon 3fe3ff
        url = form.url.data
Pierre-Yves Chibon 3fe3ff
        avatar_email = form.avatar_email.data
Ryan Lerch 743aca
        create_readme = form.create_readme.data
Farhaan Bukhsh 6ee1b8
        private = False
Pierre-Yves Chibon 9c2953
        if pagure_config.get("PRIVATE_PROJECTS", False):
Farhaan Bukhsh 6ee1b8
            private = form.private.data
Pierre-Yves Chibon aeff2b
        namespace = form.namespace.data
Pierre-Yves Chibon aeff2b
        if namespace:
Pierre-Yves Chibon aeff2b
            namespace = namespace.strip()
Patrick Uiterwijk 3f97f6
        if form.repospanner_region:
Patrick Uiterwijk 3f97f6
            repospanner_region = form.repospanner_region.data
Patrick Uiterwijk 3f97f6
        else:
Patrick Uiterwijk 3f97f6
            repospanner_region = None
Patrick Uiterwijk ac10ea
        if form.ignore_existing_repos:
Patrick Uiterwijk ac10ea
            ignore_existing_repos = form.ignore_existing_repos.data
Patrick Uiterwijk ac10ea
        else:
Patrick Uiterwijk ac10ea
            ignore_existing_repos = False
Pierre-Yves Chibon a204a8
Pierre-Yves Chibon 227f4c
        mirrored_from = form.mirrored_from.data
Pierre-Yves Chibon cdb351
        if mirrored_from and pagure_config.get("DISABLE_MIRROR_IN", False):
Pierre-Yves Chibon cdb351
            flask.flash(
Pierre-Yves Chibon cdb351
                "Mirroring in projects has been disabled in this instance",
Pierre-Yves Chibon cdb351
                "error",
Pierre-Yves Chibon cdb351
            )
Pierre-Yves Chibon cdb351
            return flask.render_template("new_project.html", form=form)
Pierre-Yves Chibon 227f4c
Pierre-Yves Chibon a204a8
        try:
Pierre-Yves Chibon 930073
            task = pagure.lib.query.new_project(
Pierre-Yves Chibon b130e5
                flask.g.session,
Pierre-Yves Chibon 47950c
                name=name,
farhaanbukhsh 4e0a2c
                private=private,
Pierre-Yves Chibon 47950c
                description=description,
Pierre-Yves Chibon db3f3c
                namespace=namespace,
Patrick Uiterwijk 3f97f6
                repospanner_region=repospanner_region,
Pierre-Yves Chibon 3fe3ff
                url=url,
Pierre-Yves Chibon 3fe3ff
                avatar_email=avatar_email,
Pierre-Yves Chibon a204a8
                user=flask.g.fas_user.username,
Pierre-Yves Chibon 9c2953
                blacklist=pagure_config["BLACKLISTED_PROJECTS"],
Pierre-Yves Chibon 9c2953
                allowed_prefix=pagure_config["ALLOWED_PREFIX"],
Ryan Lerch 743aca
                add_readme=create_readme,
Pierre-Yves Chibon 227f4c
                mirrored_from=mirrored_from,
Ryan Lerch 743aca
                userobj=user,
Pierre-Yves Chibon b130e5
                prevent_40_chars=pagure_config.get(
Pierre-Yves Chibon 9c2953
                    "OLD_VIEW_COMMIT_ENABLED", False
Pierre-Yves Chibon 9c2953
                ),
Pierre-Yves Chibon 9c2953
                user_ns=pagure_config.get("USER_NAMESPACE", False),
Patrick Uiterwijk ac10ea
                ignore_existing_repo=ignore_existing_repos,
Pierre-Yves Chibon a204a8
            )
Pierre-Yves Chibon b130e5
            flask.g.session.commit()
Aurélien Bompard a7f281
            return pagure.utils.wait_for_task(task)
Pierre-Yves Chibon fa97f7
        except pagure.exceptions.PagureException as err:
Pierre-Yves Chibon 9c2953
            flask.flash(str(err), "error")
Pierre-Yves Chibon fa97f7
        except SQLAlchemyError as err:  # pragma: no cover
Pierre-Yves Chibon b130e5
            flask.g.session.rollback()
Pierre-Yves Chibon 9c2953
            flask.flash(str(err), "error")
Pierre-Yves Chibon 542ff6
Pierre-Yves Chibon 9c2953
    return flask.render_template("new_project.html", form=form)
Pierre-Yves Chibon 68537a
Pierre-Yves Chibon 68537a
Pierre-Yves Chibon 9c2953
@UI_NS.route("/wait/<taskid>")</taskid>
Patrick Uiterwijk 0f077b
def wait_task(taskid):
Pierre-Yves Chibon a95a67
    """ Shows a wait page until the task finishes. """
Pierre-Yves Chibon a95a67
    task = pagure.lib.tasks.get_result(taskid)
Pierre-Yves Chibon a95a67
Pierre-Yves Chibon 9c2953
    is_js = is_true(flask.request.args.get("js"))
Pierre-Yves Chibon a95a67
Pierre-Yves Chibon 9c2953
    prev = flask.request.args.get("prev")
Pierre-Yves Chibon a95a67
    if not is_safe_url(prev):
Pierre-Yves Chibon 9c2953
        prev = flask.url_for("index")
Pierre-Yves Chibon a95a67
Pierre-Yves Chibon 9c2953
    count = flask.request.args.get("count", 0)
Pierre-Yves Chibon a95a67
    try:
Pierre-Yves Chibon a95a67
        count = int(count)
Pierre-Yves Chibon a95a67
        if count < 1:
Pierre-Yves Chibon a95a67
            count = 0
Pierre-Yves Chibon a95a67
    except ValueError:
Pierre-Yves Chibon a95a67
        count = 0
Pierre-Yves Chibon a95a67
Pierre-Yves Chibon a95a67
    if task.ready():
Pierre-Yves Chibon a95a67
        if is_js:
Pierre-Yves Chibon a95a67
            flask.abort(417)
Aurélien Bompard a7f281
        return flask.redirect(get_task_redirect_url(task, prev))
Patrick Uiterwijk 0f077b
    else:
Pierre-Yves Chibon a95a67
        if is_js:
Pierre-Yves Chibon 9c2953
            return flask.jsonify({"count": count + 1, "status": task.status})
Pierre-Yves Chibon a95a67
Patrick Uiterwijk 0f077b
        return flask.render_template(
Pierre-Yves Chibon 9c2953
            "waiting.html", task=task, count=count, prev=prev
Pierre-Yves Chibon a95a67
        )
Patrick Uiterwijk 0f077b
Patrick Uiterwijk 3caaa0
Patrick Uiterwijk 9b237b
@UI_NS.route("/settings/")
Patrick Uiterwijk 9b237b
@UI_NS.route("/settings")
Pierre-Yves Chibon cf7f54
@login_required
Pierre-Yves Chibon 68537a
def user_settings():
Pierre-Yves Chibon 68537a
    """ Update the user settings.
Pierre-Yves Chibon 68537a
    """
Pierre-Yves Chibon 9aecb8
    if admin_session_timedout():
Pierre-Yves Chibon 9aecb8
        return flask.redirect(
Pierre-Yves Chibon 9c2953
            flask.url_for("auth_login", next=flask.request.url)
Pierre-Yves Chibon 9c2953
        )
Pierre-Yves Chibon 9aecb8
Abhijeet Kasurde c65ec4
    user = _get_user(username=flask.g.fas_user.username)
Patrick Uiterwijk 9b237b
    form = pagure.forms.ConfirmationForm()
Pierre-Yves Chibon 9c2953
    return flask.render_template("user_settings.html", user=user, form=form)
Pierre-Yves Chibon 06abd9
Jeremy Cline babe37
Pierre-Yves Chibon 9c2953
@UI_NS.route("/settings/usersettings", methods=["POST"])
Pierre-Yves Chibon b933a2
@login_required
Pierre-Yves Chibon b933a2
def update_user_settings():
Pierre-Yves Chibon b933a2
    """ Update the user's settings set in the settings page.
Pierre-Yves Chibon b933a2
    """
Pierre-Yves Chibon b933a2
    if admin_session_timedout():
Pierre-Yves Chibon 9c2953
        if flask.request.method == "POST":
Pierre-Yves Chibon 9c2953
            flask.flash("Action canceled, try it again", "error")
Pierre-Yves Chibon b933a2
        return flask.redirect(
Pierre-Yves Chibon 9c2953
            flask.url_for("auth_login", next=flask.request.url)
Pierre-Yves Chibon 9c2953
        )
Pierre-Yves Chibon b933a2
Abhijeet Kasurde c65ec4
    user = _get_user(username=flask.g.fas_user.username)
Pierre-Yves Chibon b933a2
Pierre-Yves Chibon b933a2
    form = pagure.forms.ConfirmationForm()
Pierre-Yves Chibon b933a2
Pierre-Yves Chibon b933a2
    if form.validate_on_submit():
Pierre-Yves Chibon b933a2
        settings = {}
Pierre-Yves Chibon b933a2
        for key in flask.request.form:
Pierre-Yves Chibon 9c2953
            if key == "csrf_token":
Pierre-Yves Chibon b933a2
                continue
Pierre-Yves Chibon b933a2
            settings[key] = flask.request.form[key]
Pierre-Yves Chibon b933a2
Pierre-Yves Chibon b933a2
        try:
Pierre-Yves Chibon 930073
            message = pagure.lib.query.update_user_settings(
Pierre-Yves Chibon 9c2953
                flask.g.session, settings=settings, user=user.username
Pierre-Yves Chibon b933a2
            )
Pierre-Yves Chibon b130e5
            flask.g.session.commit()
Pierre-Yves Chibon b933a2
            flask.flash(message)
Pierre-Yves Chibon b933a2
        except pagure.exceptions.PagureException as msg:
Pierre-Yves Chibon b130e5
            flask.g.session.rollback()
Pierre-Yves Chibon 9c2953
            flask.flash(msg, "error")
Pierre-Yves Chibon b933a2
        except SQLAlchemyError as err:  # pragma: no cover
Pierre-Yves Chibon b130e5
            flask.g.session.rollback()
Pierre-Yves Chibon 9c2953
            flask.flash(str(err), "error")
Pierre-Yves Chibon b933a2
Pierre-Yves Chibon 9c2953
    return flask.redirect(flask.url_for("ui_ns.user_settings"))
Pierre-Yves Chibon b933a2
Pierre-Yves Chibon 06abd9
Pierre-Yves Chibon 3f434c
@UI_NS.route("/settings/usersettings/addkey", methods=["POST"])
Patrick Uiterwijk 9b237b
@login_required
Patrick Uiterwijk 9b237b
def add_user_sshkey():
Patrick Uiterwijk 9b237b
    """ Add the specified SSH key to the user.
Patrick Uiterwijk 9b237b
    """
Patrick Uiterwijk 9b237b
    if admin_session_timedout():
Patrick Uiterwijk 9b237b
        if flask.request.method == "POST":
Patrick Uiterwijk 9b237b
            flask.flash("Action canceled, try it again", "error")
Patrick Uiterwijk 9b237b
        return flask.redirect(
Patrick Uiterwijk 9b237b
            flask.url_for("auth_login", next=flask.request.url)
Patrick Uiterwijk 9b237b
        )
Patrick Uiterwijk 9b237b
Patrick Uiterwijk 9b237b
    form = pagure.forms.AddSSHKeyForm()
Patrick Uiterwijk 9b237b
Patrick Uiterwijk 9b237b
    if form.validate_on_submit():
Pierre-Yves Chibon ae0b93
        user = _get_user(username=flask.g.fas_user.username)
Patrick Uiterwijk 9b237b
        try:
Pierre-Yves Chibon 930073
            msg = pagure.lib.query.add_sshkey_to_project_or_user(
Patrick Uiterwijk 9b237b
                flask.g.session,
Patrick Uiterwijk 9b237b
                ssh_key=form.ssh_key.data,
Patrick Uiterwijk 9b237b
                pushaccess=True,
Pierre-Yves Chibon ae0b93
                creator=user,
Pierre-Yves Chibon ae0b93
                user=user,
Patrick Uiterwijk 9b237b
            )
Patrick Uiterwijk 9b237b
            flask.g.session.commit()
Pierre-Yves Chibon 930073
            pagure.lib.query.create_user_ssh_keys_on_disk(
Pierre-Yves Chibon ae0b93
                user, pagure_config.get("GITOLITE_KEYDIR", None)
Patrick Uiterwijk 9b237b
            )
Patrick Uiterwijk 9b237b
            pagure.lib.tasks.gitolite_post_compile_only.delay()
Patrick Uiterwijk 9b237b
            flask.flash(msg)
Patrick Uiterwijk 9b237b
            return flask.redirect(
Patrick Uiterwijk 9b237b
                flask.url_for("ui_ns.user_settings") + "#nav-ssh-tab"
Patrick Uiterwijk 9b237b
            )
Patrick Uiterwijk 9b237b
        except pagure.exceptions.PagureException as msg:
Patrick Uiterwijk 9b237b
            flask.g.session.rollback()
Patrick Uiterwijk 9b237b
            _log.debug(msg)
Patrick Uiterwijk 9b237b
            flask.flash(str(msg), "error")
Patrick Uiterwijk 9b237b
        except SQLAlchemyError as err:  # pragma: no cover
Patrick Uiterwijk 9b237b
            flask.g.session.rollback()
Patrick Uiterwijk 9b237b
            _log.exception(err)
Patrick Uiterwijk 9b237b
            flask.flash("SSH key could not be added", "error")
Patrick Uiterwijk 9b237b
Pierre-Yves Chibon 3f434c
    return flask.redirect(
Pierre-Yves Chibon 3f434c
        flask.url_for("ui_ns.user_settings") + "#nav-ssh-tab"
Pierre-Yves Chibon 3f434c
    )
Patrick Uiterwijk 9b237b
Patrick Uiterwijk 9b237b
Patrick Uiterwijk 9b237b
@UI_NS.route("/settings/usersettings/removekey/<int:keyid>", methods=["POST"])</int:keyid>
Patrick Uiterwijk 9b237b
@login_required
Patrick Uiterwijk 9b237b
def remove_user_sshkey(keyid):
Patrick Uiterwijk 9b237b
    """ Removes an SSH key from the user.
Patrick Uiterwijk 9b237b
    """
Patrick Uiterwijk 9b237b
    if admin_session_timedout():
Patrick Uiterwijk 9b237b
        if flask.request.method == "POST":
Patrick Uiterwijk 9b237b
            flask.flash("Action canceled, try it again", "error")
Patrick Uiterwijk 9b237b
        return flask.redirect(
Patrick Uiterwijk 9b237b
            flask.url_for("auth_login", next=flask.request.url)
Patrick Uiterwijk 9b237b
        )
Patrick Uiterwijk 9b237b
    form = pagure.forms.ConfirmationForm()
Patrick Uiterwijk 9b237b
    if form.validate_on_submit():
Pierre-Yves Chibon ae0b93
        user = _get_user(username=flask.g.fas_user.username)
Patrick Uiterwijk 9b237b
        found = False
Patrick Uiterwijk 9b237b
        for key in user.sshkeys:
Patrick Uiterwijk 9b237b
            if key.id == keyid:
Patrick Uiterwijk 9b237b
                flask.g.session.delete(key)
Patrick Uiterwijk 9b237b
                found = True
Patrick Uiterwijk 9b237b
                break
Patrick Uiterwijk 9b237b
Patrick Uiterwijk 9b237b
        if not found:
Patrick Uiterwijk 9b237b
            flask.flash("SSH key does not exist in user.", "error")
Patrick Uiterwijk 9b237b
            return flask.redirect(
Patrick Uiterwijk 9b237b
                flask.url_for("ui_ns.user_settings") + "#nav-ssh-tab"
Patrick Uiterwijk 9b237b
            )
Patrick Uiterwijk 9b237b
Patrick Uiterwijk 9b237b
        try:
Patrick Uiterwijk 9b237b
            flask.g.session.commit()
Pierre-Yves Chibon 930073
            pagure.lib.query.create_user_ssh_keys_on_disk(
Pierre-Yves Chibon ae0b93
                user, pagure_config.get("GITOLITE_KEYDIR", None)
Patrick Uiterwijk 9b237b
            )
Patrick Uiterwijk 9b237b
            pagure.lib.tasks.gitolite_post_compile_only.delay()
Patrick Uiterwijk 9b237b
            flask.flash("SSH key removed")
Patrick Uiterwijk 9b237b
        except SQLAlchemyError as err:  # pragma: no cover
Patrick Uiterwijk 9b237b
            flask.g.session.rollback()
Patrick Uiterwijk 9b237b
            _log.exception(err)
Patrick Uiterwijk 9b237b
            flask.flash("SSH key could not be removed", "error")
Patrick Uiterwijk 9b237b
Patrick Uiterwijk 9b237b
    return flask.redirect(
Patrick Uiterwijk 9b237b
        flask.url_for("ui_ns.user_settings") + "#nav-ssh-tab"
Patrick Uiterwijk 9b237b
    )
Patrick Uiterwijk 9b237b
Patrick Uiterwijk 9b237b
Pierre-Yves Chibon 9c2953
@UI_NS.route("/markdown/", methods=["POST"])
Pierre-Yves Chibon 06abd9
def markdown_preview():
Pierre-Yves Chibon 06abd9
    """ Return the provided markdown text in html.
Pierre-Yves Chibon 06abd9
Pierre-Yves Chibon 06abd9
    The text has to be provided via the parameter 'content' of a POST query.
Pierre-Yves Chibon 06abd9
    """
Pierre-Yves Chibon fe5017
    form = pagure.forms.ConfirmationForm()
Pierre-Yves Chibon abe470
    if form.validate_on_submit():
Pierre-Yves Chibon 9c2953
        return pagure.ui.filters.markdown_filter(flask.request.form["content"])
Pierre-Yves Chibon abe470
    else:
Pierre-Yves Chibon c6cc5c
        flask.abort(400, description="Invalid request")
Pierre-Yves Chibon 8fea23
Pierre-Yves Chibon 8fea23
Pierre-Yves Chibon 9c2953
@UI_NS.route("/settings/email/drop", methods=["POST"])
Pierre-Yves Chibon cf7f54
@login_required
Pierre-Yves Chibon 8fea23
def remove_user_email():
Pierre-Yves Chibon 8fea23
    """ Remove the specified email from the logged in user.
Pierre-Yves Chibon 8fea23
    """
Pierre-Yves Chibon 8fea23
    if admin_session_timedout():
Pierre-Yves Chibon 8fea23
        return flask.redirect(
Pierre-Yves Chibon 9c2953
            flask.url_for("auth_login", next=flask.request.url)
Pierre-Yves Chibon 9c2953
        )
Pierre-Yves Chibon 8fea23
Abhijeet Kasurde c65ec4
    user = _get_user(username=flask.g.fas_user.username)
Pierre-Yves Chibon 8fea23
Pierre-Yves Chibon 41220d
    if len(user.emails) == 1:
Pierre-Yves Chibon 9c2953
        flask.flash("You must always have at least one email", "error")
Pierre-Yves Chibon 9c2953
        return flask.redirect(flask.url_for("ui_ns.user_settings"))
Pierre-Yves Chibon 41220d
Pierre-Yves Chibon 8fea23
    form = pagure.forms.UserEmailForm()
Pierre-Yves Chibon 3b581f
Pierre-Yves Chibon 8fea23
    if form.validate_on_submit():
Pierre-Yves Chibon 8fea23
        email = form.email.data
Pierre-Yves Chibon 8fea23
        useremails = [mail.email for mail in user.emails]
Pierre-Yves Chibon 8fea23
Pierre-Yves Chibon 8fea23
        if email not in useremails:
Pierre-Yves Chibon 8fea23
            flask.flash(
Pierre-Yves Chibon 9c2953
                "You do not have the email: %s, nothing to remove" % email,
Pierre-Yves Chibon 9c2953
                "error",
Pierre-Yves Chibon 8fea23
            )
Pierre-Yves Chibon 9c2953
            return flask.redirect(flask.url_for("ui_ns.user_settings"))
Pierre-Yves Chibon 8fea23
Pierre-Yves Chibon 8fea23
        for mail in user.emails:
Pierre-Yves Chibon 8fea23
            if mail.email == email:
Pierre-Yves Chibon 8fea23
                user.emails.remove(mail)
Pierre-Yves Chibon 8fea23
                break
Pierre-Yves Chibon 8fea23
        try:
Pierre-Yves Chibon b130e5
            flask.g.session.commit()
Pierre-Yves Chibon 9c2953
            flask.flash("Email removed")
Pierre-Yves Chibon 8fea23
        except SQLAlchemyError as err:  # pragma: no cover
Pierre-Yves Chibon b130e5
            flask.g.session.rollback()
Pierre-Yves Chibon 4635b5
            _log.exception(err)
Pierre-Yves Chibon 9c2953
            flask.flash("Email could not be removed", "error")
Pierre-Yves Chibon 8fea23
Pierre-Yves Chibon 9c2953
    return flask.redirect(flask.url_for("ui_ns.user_settings"))
Pierre-Yves Chibon cc2e2c
Pierre-Yves Chibon cc2e2c
Pierre-Yves Chibon 9c2953
@UI_NS.route("/settings/email/add/", methods=["GET", "POST"])
Pierre-Yves Chibon 9c2953
@UI_NS.route("/settings/email/add", methods=["GET", "POST"])
Pierre-Yves Chibon cf7f54
@login_required
Pierre-Yves Chibon cc2e2c
def add_user_email():
Pierre-Yves Chibon cc2e2c
    """ Add a new email for the logged in user.
Pierre-Yves Chibon cc2e2c
    """
Pierre-Yves Chibon cc2e2c
    if admin_session_timedout():
Pierre-Yves Chibon cc2e2c
        return flask.redirect(
Pierre-Yves Chibon 9c2953
            flask.url_for("auth_login", next=flask.request.url)
Pierre-Yves Chibon 9c2953
        )
Pierre-Yves Chibon cc2e2c
Abhijeet Kasurde c65ec4
    user = _get_user(username=flask.g.fas_user.username)
Pierre-Yves Chibon cc2e2c
Pierre-Yves Chibon 3b581f
    form = pagure.forms.UserEmailForm(
Pierre-Yves Chibon 9c2953
        emails=[mail.email for mail in user.emails]
Pierre-Yves Chibon 9c2953
    )
Pierre-Yves Chibon cc2e2c
    if form.validate_on_submit():
Pierre-Yves Chibon cc2e2c
        email = form.email.data
Pierre-Yves Chibon cc2e2c
Pierre-Yves Chibon cc2e2c
        try:
Pierre-Yves Chibon 930073
            pagure.lib.query.add_user_pending_email(
Pierre-Yves Chibon 930073
                flask.g.session, user, email
Pierre-Yves Chibon 930073
            )
Pierre-Yves Chibon b130e5
            flask.g.session.commit()
Pierre-Yves Chibon 9c2953
            flask.flash("Email pending validation")
Pierre-Yves Chibon 9c2953
            return flask.redirect(flask.url_for("ui_ns.user_settings"))
Pierre-Yves Chibon fa97f7
        except pagure.exceptions.PagureException as err:
Pierre-Yves Chibon 9c2953
            flask.flash(str(err), "error")
Pierre-Yves Chibon cc2e2c
        except SQLAlchemyError as err:  # pragma: no cover
Pierre-Yves Chibon b130e5
            flask.g.session.rollback()
Pierre-Yves Chibon 4635b5
            _log.exception(err)
Pierre-Yves Chibon 9c2953
            flask.flash("Email could not be added", "error")
Pierre-Yves Chibon cc2e2c
Pierre-Yves Chibon 9c2953
    return flask.render_template("user_emails.html", user=user, form=form)
Pierre-Yves Chibon bf1daf
Pierre-Yves Chibon bf1daf
Pierre-Yves Chibon 9c2953
@UI_NS.route("/settings/email/default", methods=["POST"])
Pierre-Yves Chibon cf7f54
@login_required
Pierre-Yves Chibon 05db06
def set_default_email():
Pierre-Yves Chibon 05db06
    """ Set the default email address of the user.
Pierre-Yves Chibon 05db06
    """
Pierre-Yves Chibon 05db06
    if admin_session_timedout():
Pierre-Yves Chibon 05db06
        return flask.redirect(
Pierre-Yves Chibon 9c2953
            flask.url_for("auth_login", next=flask.request.url)
Pierre-Yves Chibon 9c2953
        )
Pierre-Yves Chibon 05db06
Abhijeet Kasurde c65ec4
    user = _get_user(username=flask.g.fas_user.username)
Pierre-Yves Chibon 05db06
Pierre-Yves Chibon 05db06
    form = pagure.forms.UserEmailForm()
Pierre-Yves Chibon 05db06
    if form.validate_on_submit():
Pierre-Yves Chibon 05db06
        email = form.email.data
Pierre-Yves Chibon 05db06
        useremails = [mail.email for mail in user.emails]
Pierre-Yves Chibon 05db06
Pierre-Yves Chibon 05db06
        if email not in useremails:
Pierre-Yves Chibon 05db06
            flask.flash(
Pierre-Yves Chibon 9c2953
                "You do not have the email: %s, nothing to set" % email,
Pierre-Yves Chibon 9c2953
                "error",
Pierre-Yves Chibon 05db06
            )
Pierre-Yves Chibon 05db06
Pierre-Yves Chibon 9c2953
            return flask.redirect(flask.url_for("ui_ns.user_settings"))
Pierre-Yves Chibon 9c2953
Pierre-Yves Chibon 05db06
        user.default_email = email
Pierre-Yves Chibon 05db06
Pierre-Yves Chibon 05db06
        try:
Pierre-Yves Chibon b130e5
            flask.g.session.commit()
Pierre-Yves Chibon 9c2953
            flask.flash("Default email set to: %s" % email)
Pierre-Yves Chibon 05db06
        except SQLAlchemyError as err:  # pragma: no cover
Pierre-Yves Chibon b130e5
            flask.g.session.rollback()
Pierre-Yves Chibon 4635b5
            _log.exception(err)
Pierre-Yves Chibon 9c2953
            flask.flash("Default email could not be set", "error")
Pierre-Yves Chibon 05db06
Pierre-Yves Chibon 9c2953
    return flask.redirect(flask.url_for("ui_ns.user_settings"))
Pierre-Yves Chibon 05db06
Pierre-Yves Chibon 05db06
Pierre-Yves Chibon 9c2953
@UI_NS.route("/settings/email/resend", methods=["POST"])
Pierre-Yves Chibon afab72
@login_required
Pierre-Yves Chibon afab72
def reconfirm_email():
Pierre-Yves Chibon afab72
    """ Re-send the email address of the user.
Pierre-Yves Chibon afab72
    """
Pierre-Yves Chibon afab72
    if admin_session_timedout():
Pierre-Yves Chibon afab72
        return flask.redirect(
Pierre-Yves Chibon 9c2953
            flask.url_for("auth_login", next=flask.request.url)
Pierre-Yves Chibon 9c2953
        )
Pierre-Yves Chibon afab72
Abhijeet Kasurde c65ec4
    user = _get_user(username=flask.g.fas_user.username)
Pierre-Yves Chibon afab72
Pierre-Yves Chibon afab72
    form = pagure.forms.UserEmailForm()
Pierre-Yves Chibon afab72
    if form.validate_on_submit():
Pierre-Yves Chibon afab72
        email = form.email.data
Pierre-Yves Chibon afab72
Pierre-Yves Chibon afab72
        try:
Pierre-Yves Chibon 930073
            pagure.lib.query.resend_pending_email(flask.g.session, user, email)
Pierre-Yves Chibon b130e5
            flask.g.session.commit()
Pierre-Yves Chibon 9c2953
            flask.flash("Confirmation email re-sent")
Pierre-Yves Chibon afab72
        except pagure.exceptions.PagureException as err:
Pierre-Yves Chibon 9c2953
            flask.flash(str(err), "error")
Pierre-Yves Chibon afab72
        except SQLAlchemyError as err:  # pragma: no cover
Pierre-Yves Chibon b130e5
            flask.g.session.rollback()
Pierre-Yves Chibon 4635b5
            _log.exception(err)
Pierre-Yves Chibon 9c2953
            flask.flash("Confirmation email could not be re-sent", "error")
Pierre-Yves Chibon afab72
Pierre-Yves Chibon 9c2953
    return flask.redirect(flask.url_for("ui_ns.user_settings"))
Pierre-Yves Chibon afab72
Pierre-Yves Chibon afab72
Pierre-Yves Chibon 9c2953
@UI_NS.route("/settings/email/confirm/<token>/")</token>
Pierre-Yves Chibon 9c2953
@UI_NS.route("/settings/email/confirm/<token>")</token>
Pierre-Yves Chibon bf1daf
def confirm_email(token):
Pierre-Yves Chibon bf1daf
    """ Confirm a new email.
Pierre-Yves Chibon bf1daf
    """
Pierre-Yves Chibon 658ad1
    if admin_session_timedout():
Pierre-Yves Chibon 658ad1
        return flask.redirect(
Pierre-Yves Chibon 9c2953
            flask.url_for("auth_login", next=flask.request.url)
Pierre-Yves Chibon 9c2953
        )
Pierre-Yves Chibon 658ad1
Pierre-Yves Chibon 930073
    email = pagure.lib.query.search_pending_email(flask.g.session, token=token)
Pierre-Yves Chibon bf1daf
    if not email:
Pierre-Yves Chibon 9c2953
        flask.flash("No email associated with this token.", "error")
Pierre-Yves Chibon bf1daf
    else:
Pierre-Yves Chibon bf1daf
        try:
Pierre-Yves Chibon 930073
            pagure.lib.query.add_email_to_user(
Pierre-Yves Chibon 9c2953
                flask.g.session, email.user, email.email
Pierre-Yves Chibon 9c2953
            )
Pierre-Yves Chibon b130e5
            flask.g.session.delete(email)
Pierre-Yves Chibon b130e5
            flask.g.session.commit()
Pierre-Yves Chibon 9c2953
            flask.flash("Email validated")
Karsten Hopp 5c0db6
        except pagure.exceptions.PagureException as err:
Karsten Hopp 5c0db6
            flask.flash(str(err), "error")
Karsten Hopp 5c0db6
            _log.exception(err)
Pierre-Yves Chibon fa97f7
        except SQLAlchemyError as err:  # pragma: no cover
Pierre-Yves Chibon b130e5
            flask.g.session.rollback()
Pierre-Yves Chibon bf1daf
            flask.flash(
Pierre-Yves Chibon 9c2953
                "Could not set the account as active in the db, "
Pierre-Yves Chibon 9c2953
                "please report this error to an admin",
Pierre-Yves Chibon 9c2953
                "error",
Pierre-Yves Chibon 9c2953
            )
Pierre-Yves Chibon 4635b5
            _log.exception(err)
Pierre-Yves Chibon bf1daf
Pierre-Yves Chibon 9c2953
    return flask.redirect(flask.url_for("ui_ns.user_settings"))
Pierre-Yves Chibon 3adf88
Pierre-Yves Chibon 3adf88
Pierre-Yves Chibon 9c2953
@UI_NS.route("/ssh_info/")
Pierre-Yves Chibon 9c2953
@UI_NS.route("/ssh_info")
Pierre-Yves Chibon 3adf88
def ssh_hostkey():
Pierre-Yves Chibon 3adf88
    """ Endpoint returning information about the SSH hostkey and fingerprint
Pierre-Yves Chibon 3adf88
    of the current pagure instance.
Pierre-Yves Chibon 3adf88
    """
Pierre-Yves Chibon 9c2953
    return flask.render_template("doc_ssh_keys.html")
Pierre-Yves Chibon 170fc9
Pierre-Yves Chibon 170fc9
Pierre-Yves Chibon 9c2953
@UI_NS.route("/settings/token/new/", methods=("GET", "POST"))
Pierre-Yves Chibon 9c2953
@UI_NS.route("/settings/token/new", methods=("GET", "POST"))
Pierre-Yves Chibon 170fc9
@login_required
Pierre-Yves Chibon 2c7572
def add_api_user_token():
Pierre-Yves Chibon 170fc9
    """ Create an user token (not project specific).
Pierre-Yves Chibon 170fc9
    """
Pierre-Yves Chibon 170fc9
    if admin_session_timedout():
Pierre-Yves Chibon 9c2953
        if flask.request.method == "POST":
Pierre-Yves Chibon 9c2953
            flask.flash("Action canceled, try it again", "error")
Pierre-Yves Chibon 170fc9
        return flask.redirect(
Pierre-Yves Chibon 9c2953
            flask.url_for("auth_login", next=flask.request.url)
Pierre-Yves Chibon 9c2953
        )
Pierre-Yves Chibon 170fc9
Pierre-Yves Chibon 170fc9
    # Ensure the user is in the DB at least
Abhijeet Kasurde c65ec4
    user = _get_user(username=flask.g.fas_user.username)
Pierre-Yves Chibon 170fc9
Pierre-Yves Chibon 930073
    acls = pagure.lib.query.get_acls(
Pierre-Yves Chibon 9c2953
        flask.g.session, restrict=pagure_config.get("CROSS_PROJECT_ACLS")
Pierre-Yves Chibon 9c2953
    )
Pierre-Yves Chibon 170fc9
    form = pagure.forms.NewTokenForm(acls=acls)
Pierre-Yves Chibon 170fc9
Pierre-Yves Chibon 170fc9
    if form.validate_on_submit():
Pierre-Yves Chibon 170fc9
        try:
Pierre-Yves Chibon 696f19
            pagure.lib.query.add_token_to_user(
Pierre-Yves Chibon b130e5
                flask.g.session,
Pierre-Yves Chibon 170fc9
                project=None,
Pierre-Yves Chibon 60a786
                description=form.description.data.strip() or None,
Pierre-Yves Chibon 170fc9
                acls=form.acls.data,
Pierre-Yves Chibon 0e867d
                username=user.username,
Pierre-Yves Chibon 170fc9
            )
Pierre-Yves Chibon b130e5
            flask.g.session.commit()
Pierre-Yves Chibon 696f19
            flask.flash("Token created")
Pierre-Yves Chibon 77bdcd
            return flask.redirect(
Pierre-Yves Chibon 9c2953
                flask.url_for("ui_ns.user_settings") + "#nav-api-tab"
Pierre-Yves Chibon 9c2953
            )
Pierre-Yves Chibon 170fc9
        except SQLAlchemyError as err:  # pragma: no cover
Pierre-Yves Chibon b130e5
            flask.g.session.rollback()
Pierre-Yves Chibon 4635b5
            _log.exception(err)
Pierre-Yves Chibon 9c2953
            flask.flash("API key could not be added", "error")
Pierre-Yves Chibon 170fc9
Pierre-Yves Chibon 170fc9
    # When form is displayed after an empty submission, show an error.
Pierre-Yves Chibon 9c2953
    if form.errors.get("acls"):
Pierre-Yves Chibon 9c2953
        flask.flash("You must select at least one permission.", "error")
Pierre-Yves Chibon 170fc9
Pierre-Yves Chibon 170fc9
    return flask.render_template(
Pierre-Yves Chibon 9c2953
        "add_token.html", select="settings", form=form, acls=acls
Pierre-Yves Chibon 170fc9
    )
Pierre-Yves Chibon 170fc9
Pierre-Yves Chibon 170fc9
Pierre-Yves Chibon 9c2953
@UI_NS.route("/settings/token/revoke/<token_id>/", methods=["POST"])</token_id>
Pierre-Yves Chibon 9c2953
@UI_NS.route("/settings/token/revoke/<token_id>", methods=["POST"])</token_id>
Pierre-Yves Chibon 170fc9
@login_required
Pierre-Yves Chibon 170fc9
def revoke_api_user_token(token_id):
chocos10 6e4a4f
    """ Revoke a user token (ie: not project specific).
Pierre-Yves Chibon 170fc9
    """
Pierre-Yves Chibon 170fc9
    if admin_session_timedout():
Pierre-Yves Chibon 9c2953
        flask.flash("Action canceled, try it again", "error")
Pierre-Yves Chibon 9c2953
        url = flask.url_for(".user_settings")
Pierre-Yves Chibon 9c2953
        return flask.redirect(flask.url_for("auth_login", next=url))
Pierre-Yves Chibon 170fc9
Pierre-Yves Chibon 930073
    token = pagure.lib.query.get_api_token(flask.g.session, token_id)
Pierre-Yves Chibon 170fc9
Pierre-Yves Chibon 9c2953
    if not token or token.user.username != flask.g.fas_user.username:
Pierre-Yves Chibon c6cc5c
        flask.abort(404, description="Token not found")
Pierre-Yves Chibon 170fc9
Pierre-Yves Chibon 170fc9
    form = pagure.forms.ConfirmationForm()
Pierre-Yves Chibon 170fc9
Pierre-Yves Chibon 170fc9
    if form.validate_on_submit():
Pierre-Yves Chibon 170fc9
        try:
Pierre-Yves Chibon 170fc9
            if token.expiration >= datetime.datetime.utcnow():
Pierre-Yves Chibon 170fc9
                token.expiration = datetime.datetime.utcnow()
Pierre-Yves Chibon b130e5
                flask.g.session.add(token)
Pierre-Yves Chibon b130e5
            flask.g.session.commit()
Pierre-Yves Chibon 9c2953
            flask.flash("Token revoked")
Pierre-Yves Chibon 170fc9
        except SQLAlchemyError as err:  # pragma: no cover
Pierre-Yves Chibon b130e5
            flask.g.session.rollback()
Pierre-Yves Chibon 4635b5
            _log.exception(err)
Pierre-Yves Chibon 170fc9
            flask.flash(
Pierre-Yves Chibon 9c2953
                "Token could not be revoked, please contact an admin", "error"
Pierre-Yves Chibon 9c2953
            )
Pierre-Yves Chibon 170fc9
Pierre-Yves Chibon 77bdcd
    return flask.redirect(
Pierre-Yves Chibon 9c2953
        flask.url_for("ui_ns.user_settings") + "#nav-api-token"
Pierre-Yves Chibon 9c2953
    )
Patrick Uiterwijk ce6d6d
Patrick Uiterwijk ce6d6d
Pierre-Yves Chibon 9c2953
@UI_NS.route("/settings/forcelogout/", methods=("POST",))
Pierre-Yves Chibon 9c2953
@UI_NS.route("/settings/forcelogout", methods=("POST",))
Patrick Uiterwijk ce6d6d
@login_required
Patrick Uiterwijk ce6d6d
def force_logout():
Patrick Uiterwijk ce6d6d
    """ Set refuse_sessions_before, logging the user out everywhere
Patrick Uiterwijk ce6d6d
    """
Patrick Uiterwijk ce6d6d
    if admin_session_timedout():
Slavek Kabrda 2200ff
        flask.flash("Action canceled, try it again", "error")
Patrick Uiterwijk ce6d6d
        return flask.redirect(
Pierre-Yves Chibon 9c2953
            flask.url_for("auth_login", next=flask.request.url)
Pierre-Yves Chibon 9c2953
        )
Patrick Uiterwijk ce6d6d
Slavek Kabrda 2200ff
    # we just need an empty form here to validate that csrf token is present
Slavek Kabrda 2200ff
    form = pagure.forms.PagureForm()
Slavek Kabrda 2200ff
    if form.validate_on_submit():
Slavek Kabrda 2200ff
        # Ensure the user is in the DB at least
Slavek Kabrda 2200ff
        user = _get_user(username=flask.g.fas_user.username)
Patrick Uiterwijk ce6d6d
Slavek Kabrda 2200ff
        user.refuse_sessions_before = datetime.datetime.utcnow()
Slavek Kabrda 2200ff
        flask.g.session.commit()
Slavek Kabrda 2200ff
        flask.flash("All active sessions logged out")
Pierre-Yves Chibon 9c2953
    return flask.redirect(flask.url_for("ui_ns.user_settings"))
Mary Kate Fain a16918
Mary Kate Fain a16918
Mary Kate Fain a16918
@UI_NS.route("/about")
Mary Kate Fain a16918
@UI_NS.route("/about/")
Mary Kate Fain a16918
def help():
Mary Kate Fain a16918
    """ A page to direct users to the appropriate places to get assistance,
Mary Kate Fain a16918
        or find basic instance information.
Mary Kate Fain a16918
    """
Mary Kate Fain a16918
    return flask.render_template("about.html")