예제 #1
0
파일: login.py 프로젝트: tenstormavi/pagure
def reset_password(token):
    """ Method to allow a user to reset his/her password.
    """
    form = forms.ResetPasswordForm()

    user_obj = pagure.lib.search_user(SESSION, token=token)
    if not user_obj:
        flask.flash("No user associated with this token.", "error")
        return flask.redirect(flask.url_for("auth_login"))
    elif not user_obj.token:
        flask.flash("Invalid user, this user never asked for a password change", "error")
        return flask.redirect(flask.url_for("auth_login"))

    if form.validate_on_submit():

        password = "******" % (form.password.data, APP.config.get("PASSWORD_SEED", None))
        user_obj.password = hashlib.sha512(password).hexdigest()
        user_obj.token = None
        SESSION.add(user_obj)

        try:
            SESSION.commit()
            flask.flash("Password changed")
        except SQLAlchemyError as err:
            SESSION.rollback()
            flask.flash("Could not set the new password.", "error")
            APP.logger.debug("Password lost change - Error setting password.")
            APP.logger.exception(err)

        return flask.redirect(flask.url_for("auth_login"))

    return flask.render_template("login/password_reset.html", form=form, token=token)
예제 #2
0
def _check_session_cookie():
    """ Set the user into flask.g if the user is logged in.
    """
    cookie_name = APP.config.get('SESSION_COOKIE_NAME', 'pagure')
    cookie_name = '%s_local_cookie' % cookie_name
    session_id = None
    user = None
    login_time = None

    if cookie_name and cookie_name in flask.request.cookies:
        sessionid = flask.request.cookies.get(cookie_name)
        session = pagure.lib.login.get_session_by_visitkey(
            SESSION, sessionid)
        if session and session.user:
            now = datetime.datetime.now()
            if now > session.expiry:
                flask.flash('Session timed-out', 'error')
            elif APP.config.get('CHECK_SESSION_IP', True) \
                    and session.user_ip != flask.request.remote_addr:
                flask.flash('Session expired', 'error')
            else:
                new_expiry = now + datetime.timedelta(days=30)
                session_id = session.visit_key
                user = session.user
                login_time = session.created

                session.expiry = new_expiry
                SESSION.add(session)
                try:
                    SESSION.commit()
                except SQLAlchemyError, err:  # pragma: no cover
                    flask.flash(
                        'Could not prolong the session in the db, '
                        'please report this error to an admin', 'error')
                    APP.logger.exception(err)
예제 #3
0
파일: repo.py 프로젝트: kunaaljain/pagure
def update_project(repo, username=None):
    """ Update the description of a project.
    """
    if admin_session_timedout():
        flask.flash('Action canceled, try it again', 'error')
        url = flask.url_for(
            'view_settings', username=username, repo=repo.name)
        return flask.redirect(
            flask.url_for('auth_login', next=url))

    repo = pagure.lib.get_project(SESSION, repo, user=username)

    if not repo:
        flask.abort(404, 'Project not found')

    if not is_repo_admin(repo):
        flask.abort(
            403,
            'You are not allowed to change the settings for this project')

    form = pagure.forms.ProjectFormSimplified()

    if form.validate_on_submit():
        try:
            repo.description = form.description.data
            repo.avatar_email = form.avatar_email.data.strip()
            repo.url = form.url.data.strip()
            SESSION.add(repo)
            SESSION.commit()
            flask.flash('Project updated')
        except SQLAlchemyError, err:  # pragma: no cover
            SESSION.rollback()
            flask.flash(str(err), 'error')
예제 #4
0
파일: login.py 프로젝트: girish946/pagure
def new_user():
    """ Create a new user.
    """
    form = forms.NewUserForm()
    if form.validate_on_submit():

        username = form.user.data
        if pagure.lib.search_user(SESSION, username=username):
            flask.flash('Username already taken.', 'error')
            return flask.redirect(flask.request.url)

        email = form.email_address.data
        if pagure.lib.search_user(SESSION, email=email):
            flask.flash('Email address already taken.', 'error')
            return flask.redirect(flask.request.url)

        password = '******' % (
            form.password.data, APP.config.get('PASSWORD_SEED', None))
        form.password.data = hashlib.sha512(password).hexdigest()

        token = pagure.lib.login.id_generator(40)

        user = model.User()
        user.token = token
        form.populate_obj(obj=user)
        user.default_email = form.email_address.data
        SESSION.add(user)
        SESSION.flush()

        emails = [email.email for email in user.emails]
        if form.email_address.data not in emails:
            useremail = model.UserEmail(
                user_id=user.id,
                email=form.email_address.data)
            SESSION.add(useremail)
            SESSION.flush()

        try:
            SESSION.flush()
            send_confirmation_email(user)
            flask.flash(
                'User created, please check your email to activate the '
                'account')
        except SQLAlchemyError as err:
            SESSION.rollback()
            flask.flash('Could not create user.')
            APP.logger.debug('Could not create user.')
            APP.logger.exception(err)

        SESSION.commit()

        return flask.redirect(flask.url_for('auth_login'))

    return flask.render_template(
        'login/user_new.html',
        form=form,
    )
예제 #5
0
파일: fork.py 프로젝트: pvl/pagure
def request_pull_edit(repo, requestid, username=None):
    """ Edit the title of a pull-request.
    """

    repo = pagure.lib.get_project(SESSION, repo, user=username)

    if not repo:
        flask.abort(404, 'Project not found')

    if not repo.settings.get('pull_requests', True):
        flask.abort(404, 'No pull-requests found for this project')

    request = pagure.lib.search_pull_requests(
        SESSION, project_id=repo.id, requestid=requestid)

    if not request:
        flask.abort(404, 'Pull-request not found')

    if request.status != 'Open':
        flask.abort(400, 'Pull-request is already closed')

    if not is_repo_admin(repo) \
            and flask.g.fas_user.username != request.user.username:
        flask.abort(403, 'You are not allowed to edit this pull-request')

    form = pagure.forms.RequestPullForm()
    if form.validate_on_submit():
        request.title = form.title.data.strip()
        request.initial_comment = form.initial_comment.data.strip()
        SESSION.add(request)
        try:
            SESSION.commit()
            flask.flash('Request pull edited!')
        except SQLAlchemyError as err:  # pragma: no cover
            SESSION.rollback()
            APP.logger.exception(err)
            flask.flash(
                'Could not edit this pull-request in the database',
                'error')
        return flask.redirect(flask.url_for(
            'request_pull', username=username,
            repo=repo.name, requestid=requestid))
    elif flask.request.method == 'GET':
        form.title.data = request.title
        form.initial_comment.data = request.initial_comment

    return flask.render_template(
        'pull_request_title.html',
        select='requests',
        request=request,
        repo=repo,
        username=username,
        form=form,
    )
예제 #6
0
파일: login.py 프로젝트: gzfarmer/pagure
def change_password():
    """ Method to change the password for local auth users.
    """

    form = forms.ChangePasswordForm()
    user_obj = pagure.lib.search_user(
        SESSION, username=flask.g.fas_user.username)

    if not user_obj:
        flask.abort(404, 'User not found')

    if form.validate_on_submit():

        try:
            password_checks = check_password(
                form.old_password.data, user_obj.password,
                seed=APP.config.get('PASSWORD_SEED', None))
        except pagure.exceptions.PagureException as err:
            APP.logger.exception(err)
            flask.flash(
                'Could not update your password, either user or password '
                'could not be checked', 'error')
            return flask.redirect(flask.url_for('auth_login'))

        if password_checks:
            user_obj.password = generate_hashed_value(form.password.data)
            SESSION.add(user_obj)

        else:
            flask.flash(
                'Could not update your password, either user or password '
                'could not be checked', 'error')
            return flask.redirect(flask.url_for('auth_login'))

        try:
            SESSION.commit()
            flask.flash(
                'Password changed')
        except SQLAlchemyError as err:  # pragma: no cover
            SESSION.rollback()
            flask.flash('Could not set the new password.', 'error')
            APP.logger.debug(
                'Password change  - Error setting new password.')
            APP.logger.exception(err)

        return flask.redirect(flask.url_for('auth_login'))

    return flask.render_template(
        'login/password_recover.html',
        form=form,
    )
예제 #7
0
파일: login.py 프로젝트: girish946/pagure
def do_login():
    """ Lo the user in user.
    """
    form = forms.LoginForm()
    next_url = flask.request.args.get('next_url')
    if not next_url or next_url == 'None':
        next_url = flask.url_for('index')

    if form.validate_on_submit():
        username = form.username.data
        password = '******' % (
            form.password.data, APP.config.get('PASSWORD_SEED', None))
        password = hashlib.sha512(password).hexdigest()

        user_obj = pagure.lib.search_user(SESSION, username=username)
        if not user_obj or user_obj.password != password:
            flask.flash('Username or password invalid.', 'error')
            return flask.redirect(flask.url_for('auth_login'))
        elif user_obj.token:
            flask.flash(
                'Invalid user, did you confirm the creation with the url '
                'provided by email?', 'error')
            return flask.redirect(flask.url_for('auth_login'))
        else:
            visit_key = pagure.lib.login.id_generator(40)
            now = datetime.datetime.utcnow()
            expiry = now + datetime.timedelta(days=30)
            session = model.PagureUserVisit(
                user_id=user_obj.id,
                user_ip=flask.request.remote_addr,
                visit_key=visit_key,
                expiry=expiry,
            )
            SESSION.add(session)
            try:
                SESSION.commit()
                flask.g.fas_user = user_obj
                flask.g.fas_session_id = visit_key
                flask.g.fas_user.login_time = now
                flask.flash('Welcome %s' % user_obj.username)
            except SQLAlchemyError as err:  # pragma: no cover
                flask.flash(
                    'Could not set the session in the db, '
                    'please report this error to an admin', 'error')
                APP.logger.exception(err)

        return flask.redirect(next_url)
    else:
        flask.flash('Insufficient information provided', 'error')
    return flask.redirect(flask.url_for('auth_login'))
예제 #8
0
def new_user():
    """ Create a new user.
    """
    form = forms.NewUserForm()
    if form.validate_on_submit():

        username = form.user.data
        if pagure.lib.search_user(SESSION, username=username):
            flask.flash('Username already taken.', 'error')
            return flask.redirect(flask.request.url)

        email = form.email_address.data
        if pagure.lib.search_user(SESSION, email=email):
            flask.flash('Email address already taken.', 'error')
            return flask.redirect(flask.request.url)

        form.password.data = generate_hashed_value(form.password.data)

        token = pagure.lib.login.id_generator(40)

        user = model.User()
        user.token = token
        form.populate_obj(obj=user)
        user.default_email = form.email_address.data
        SESSION.add(user)
        SESSION.flush()

        pagure.lib.add_email_to_user(
            SESSION, user, form.email_address.data)

        try:
            SESSION.commit()
            send_confirmation_email(user)
            flask.flash(
                'User created, please check your email to activate the '
                'account')
        except SQLAlchemyError as err:  # pragma: no cover
            SESSION.rollback()
            flask.flash('Could not create user.')
            APP.logger.debug('Could not create user.')
            APP.logger.exception(err)

        return flask.redirect(flask.url_for('auth_login'))

    return flask.render_template(
        'login/user_new.html',
        form=form,
    )
예제 #9
0
def lost_password():
    """ Method to allow a user to change his/her password assuming the email
    is not compromised.
    """
    form = forms.LostPasswordForm()
    if form.validate_on_submit():

        username = form.username.data
        user_obj = pagure.lib.search_user(SESSION, username=username)
        if not user_obj:
            flask.flash('Username invalid.', 'error')
            return flask.redirect(flask.url_for('auth_login'))
        elif user_obj.token:
            current_time = datetime.datetime.utcnow()
            invalid_period = user_obj.updated_on + \
                datetime.timedelta(minutes=3)
            if current_time < invalid_period:
                flask.flash(
                    'An email was sent to you less than 3 minutes ago, '
                    'did you check your spam folder? Otherwise, '
                    'try again after some time.', 'error')
                return flask.redirect(flask.url_for('auth_login'))

        token = pagure.lib.login.id_generator(40)
        user_obj.token = token
        SESSION.add(user_obj)

        try:
            SESSION.commit()
            send_lostpassword_email(user_obj)
            flask.flash(
                'Check your email to finish changing your password')
        except SQLAlchemyError as err:  # pragma: no cover
            SESSION.rollback()
            flask.flash(
                'Could not set the token allowing changing a password.',
                'error')
            APP.logger.debug('Password lost change - Error setting token.')
            APP.logger.exception(err)

        return flask.redirect(flask.url_for('auth_login'))

    return flask.render_template(
        'login/password_change.html',
        form=form,
    )
예제 #10
0
def confirm_user(token):
    """ Confirm a user account.
    """
    user_obj = pagure.lib.search_user(SESSION, token=token)
    if not user_obj:
        flask.flash('No user associated with this token.', 'error')
    else:
        user_obj.token = None
        SESSION.add(user_obj)

        try:
            SESSION.commit()
            flask.flash('Email confirmed, account activated')
            return flask.redirect(flask.url_for('auth_login'))
        except SQLAlchemyError, err:  # pragma: no cover
            flask.flash(
                'Could not set the account as active in the db, '
                'please report this error to an admin', 'error')
            APP.logger.exception(err)
예제 #11
0
def lost_password():
    """ Method to allow a user to change his/her password assuming the email
    is not compromised.
    """
    form = forms.LostPasswordForm()
    if form.validate_on_submit():

        username = form.username.data
        user_obj = pagure.lib.search_user(SESSION, username=username)
        if not user_obj:
            flask.flash('Username invalid.', 'error')
            return flask.redirect(flask.url_for('auth_login'))
        elif user_obj.token:
            flask.flash(
                'Invalid user, did you confirm the creation with the url '
                'provided by email? Or did you already ask for a password '
                'change?', 'error')
            return flask.redirect(flask.url_for('auth_login'))

        token = pagure.lib.login.id_generator(40)
        user_obj.token = token
        SESSION.add(user_obj)

        try:
            SESSION.commit()
            send_lostpassword_email(user_obj)
            flask.flash(
                'Check your email to finish changing your password')
        except SQLAlchemyError as err:
            SESSION.rollback()
            flask.flash(
                'Could not set the token allowing changing a password.',
                'error')
            APP.logger.debug('Password lost change - Error setting token.')
            APP.logger.exception(err)

        return flask.redirect(flask.url_for('auth_login'))

    return flask.render_template(
        'login/password_change.html',
        form=form,
    )
예제 #12
0
파일: fork.py 프로젝트: jepio/pagure
def request_pull_edit(repo, requestid, username=None):
    """ Edit the title of a pull-request.
    """

    repo = pagure.lib.get_project(SESSION, repo, user=username)

    if not repo:
        flask.abort(404, "Project not found")

    if not repo.settings.get("pull_requests", True):
        flask.abort(404, "No pull-requests found for this project")

    request = pagure.lib.search_pull_requests(SESSION, project_id=repo.id, requestid=requestid)

    if not request:
        flask.abort(404, "Pull-request not found")

    if request.status != "Open":
        flask.abort(400, "Pull-request is already closed")

    if not is_repo_admin(repo) and flask.g.fas_user.username != request.user.username:
        flask.abort(403, "You are not allowed to edit this pull-request")

    form = pagure.forms.RequestPullForm()
    if form.validate_on_submit():
        request.title = form.title.data
        SESSION.add(request)
        try:
            SESSION.commit()
            flask.flash("Request pull edited!")
        except SQLAlchemyError as err:  # pragma: no cover
            SESSION.rollback()
            APP.logger.exception(err)
            flask.flash("Could not edit this pull-request in the database", "error")
        return flask.redirect(flask.url_for("request_pull", username=username, repo=repo.name, requestid=requestid))
    elif flask.request.method == "GET":
        form.title.data = request.title

    return flask.render_template(
        "pull_request_title.html", select="requests", request=request, repo=repo, username=username, form=form
    )
예제 #13
0
파일: login.py 프로젝트: sudhirverma/pagure
def reset_password(token):
    """ Method to allow a user to reset his/her password.
    """
    form = forms.ResetPasswordForm()

    user_obj = pagure.lib.search_user(SESSION, token=token)
    if not user_obj:
        flask.flash('No user associated with this token.', 'error')
        return flask.redirect(flask.url_for('auth_login'))
    elif not user_obj.token:
        flask.flash(
            'Invalid user, this user never asked for a password change',
            'error')
        return flask.redirect(flask.url_for('auth_login'))

    if form.validate_on_submit():

        user_obj.password = generate_hashed_value(form.password.data)

        user_obj.token = None
        SESSION.add(user_obj)

        try:
            SESSION.commit()
            flask.flash(
                'Password changed')
        except SQLAlchemyError as err:  # pragma: no cover
            SESSION.rollback()
            flask.flash('Could not set the new password.', 'error')
            APP.logger.debug(
                'Password lost change - Error setting password.')
            APP.logger.exception(err)

        return flask.redirect(flask.url_for('auth_login'))

    return flask.render_template(
        'login/password_reset.html',
        form=form,
        token=token,
    )
예제 #14
0
파일: login.py 프로젝트: sudhirverma/pagure
def _check_session_cookie():
    """ Set the user into flask.g if the user is logged in.
    """
    cookie_name = APP.config.get('SESSION_COOKIE_NAME', 'pagure')
    cookie_name = '%s_local_cookie' % cookie_name
    session_id = None
    user = None
    login_time = None

    if cookie_name and cookie_name in flask.request.cookies:
        sessionid = flask.request.cookies.get(cookie_name)
        session = pagure.lib.login.get_session_by_visitkey(
            SESSION, sessionid)
        if session and session.user:
            now = datetime.datetime.now()
            if now > session.expiry:
                flask.flash('Session timed-out', 'error')
            elif APP.config.get('CHECK_SESSION_IP', True) \
                    and session.user_ip != flask.request.remote_addr:
                flask.flash('Session expired', 'error')
            else:
                new_expiry = now + datetime.timedelta(days=30)
                session_id = session.visit_key
                user = session.user
                login_time = session.created

                session.expiry = new_expiry
                SESSION.add(session)
                try:
                    SESSION.commit()
                except SQLAlchemyError as err:  # pragma: no cover
                    flask.flash(
                        'Could not prolong the session in the db, '
                        'please report this error to an admin', 'error')
                    APP.logger.exception(err)

    flask.g.fas_session_id = session_id
    flask.g.fas_user = user
    if user:
        flask.g.fas_user.login_time = login_time
예제 #15
0
파일: login.py 프로젝트: gzfarmer/pagure
def reset_password(token):
    """ Method to allow a user to reset his/her password.
    """
    form = forms.ResetPasswordForm()

    user_obj = pagure.lib.search_user(SESSION, token=token)
    if not user_obj:
        flask.flash('No user associated with this token.', 'error')
        return flask.redirect(flask.url_for('auth_login'))
    elif not user_obj.token:
        flask.flash(
            'Invalid user, this user never asked for a password change',
            'error')
        return flask.redirect(flask.url_for('auth_login'))

    if form.validate_on_submit():

        user_obj.password = generate_hashed_value(form.password.data)

        user_obj.token = None
        SESSION.add(user_obj)

        try:
            SESSION.commit()
            flask.flash(
                'Password changed')
        except SQLAlchemyError as err:  # pragma: no cover
            SESSION.rollback()
            flask.flash('Could not set the new password.', 'error')
            APP.logger.debug(
                'Password lost change - Error setting password.')
            APP.logger.exception(err)

        return flask.redirect(flask.url_for('auth_login'))

    return flask.render_template(
        'login/password_reset.html',
        form=form,
        token=token,
    )
예제 #16
0
파일: repo.py 프로젝트: tenstormavi/pagure
def update_project(repo, username=None):
    """ Update the description of a project.
    """
    if admin_session_timedout():
        flask.flash('Action canceled, try it again', 'error')
        url = flask.url_for(
            'view_settings', username=username, repo=repo)
        return flask.redirect(
            flask.url_for('auth_login', next=url))

    repo = pagure.lib.get_project(SESSION, repo, user=username)

    if not repo:
        flask.abort(404, 'Project not found')

    if not is_repo_admin(repo):
        flask.abort(
            403,
            'You are not allowed to change the settings for this project')

    form = pagure.forms.ProjectFormSimplified()

    if form.validate_on_submit():
        try:
            repo.description = form.description.data
            repo.avatar_email = form.avatar_email.data.strip()
            repo.url = form.url.data.strip()
            pagure.lib.update_tags(
                SESSION, repo,
                tags=[t.strip() for t in form.tags.data.split(',')],
                username=flask.g.fas_user.username,
                ticketfolder=None,
                redis=None)
            SESSION.add(repo)
            SESSION.commit()
            flask.flash('Project updated')
        except SQLAlchemyError, err:  # pragma: no cover
            SESSION.rollback()
            flask.flash(str(err), 'error')
예제 #17
0
파일: repo.py 프로젝트: aavrug/pagure
def update_project(repo, username=None):
    """ Update the description of a project.
    """
    if admin_session_timedout():
        flask.flash("Action canceled, try it again", "error")
        url = flask.url_for("view_settings", username=username, repo=repo)
        return flask.redirect(flask.url_for("auth_login", next=url))

    repo = pagure.lib.get_project(SESSION, repo, user=username)

    if not repo:
        flask.abort(404, "Project not found")

    if not is_repo_admin(repo):
        flask.abort(403, "You are not allowed to change the settings for this project")

    form = pagure.forms.ProjectFormSimplified()

    if form.validate_on_submit():
        try:
            repo.description = form.description.data
            repo.avatar_email = form.avatar_email.data.strip()
            repo.url = form.url.data.strip()
            pagure.lib.update_tags(
                SESSION,
                repo,
                tags=[t.strip() for t in form.tags.data.split(",")],
                username=flask.g.fas_user.username,
                ticketfolder=None,
            )
            SESSION.add(repo)
            SESSION.commit()
            flask.flash("Project updated")
        except SQLAlchemyError as err:  # pragma: no cover
            SESSION.rollback()
            flask.flash(str(err), "error")

    return flask.redirect(flask.url_for("view_settings", username=username, repo=repo.name))
예제 #18
0
파일: issues.py 프로젝트: Gahlot/pagure
def new_issue(repo, username=None, namespace=None):
    """ Create a new issue
    """
    repo = flask.g.repo

    if not repo.settings.get('issue_tracker', True):
        flask.abort(404, 'No issue tracker found for this project')

    form = pagure.forms.IssueFormSimplied()
    if form.validate_on_submit():
        title = form.title.data
        content = form.issue_content.data
        private = form.private.data

        try:
            user_obj = pagure.lib.get_user(
                SESSION, flask.g.fas_user.username)
        except pagure.exceptions.PagureException:
            flask.abort(
                404,
                'No such user found in the database: %s' % (
                    flask.g.fas_user.username))

        try:
            issue = pagure.lib.new_issue(
                SESSION,
                repo=repo,
                title=title,
                content=content,
                private=private or False,
                user=flask.g.fas_user.username,
                ticketfolder=APP.config['TICKETS_FOLDER'],
            )
            SESSION.commit()
            # If there is a file attached, attach it.
            filestream = flask.request.files.get('filestream')
            if filestream and '<!!image>' in issue.content:
                new_filename = pagure.lib.git.add_file_to_git(
                    repo=repo,
                    issue=issue,
                    ticketfolder=APP.config['TICKETS_FOLDER'],
                    user=user_obj,
                    filename=filestream.filename,
                    filestream=filestream.stream,
                )
                # Replace the <!!image> tag in the comment with the link
                # to the actual image
                filelocation = flask.url_for(
                    'view_issue_raw_file',
                    repo=repo.name,
                    username=username,
                    filename=new_filename,
                )
                new_filename = new_filename.split('-', 1)[1]
                url = '[![%s](%s)](%s)' % (
                    new_filename, filelocation, filelocation)
                issue.content = issue.content.replace('<!!image>', url)
                SESSION.add(issue)
                SESSION.commit()

            return flask.redirect(flask.url_for(
                '.view_issue', username=username, repo=repo.name,
                namespace=namespace, issueid=issue.id))
        except pagure.exceptions.PagureException as err:
            flask.flash(str(err), 'error')
        except SQLAlchemyError as err:  # pragma: no cover
            SESSION.rollback()
            flask.flash(str(err), 'error')

    types = None
    default = None
    ticketrepopath = os.path.join(APP.config['TICKETS_FOLDER'], repo.path)
    if os.path.exists(ticketrepopath):
        ticketrepo = pygit2.Repository(ticketrepopath)
        if not ticketrepo.is_empty and not ticketrepo.head_is_unborn:
            commit = ticketrepo[ticketrepo.head.target]
            # Get the different ticket types
            files = __get_file_in_tree(
                ticketrepo, commit.tree, ['templates'],
                bail_on_tree=True)
            if files:
                types = [f.name.rstrip('.md') for f in files]
            # Get the default template
            default_file = __get_file_in_tree(
                ticketrepo, commit.tree, ['templates', 'default.md'],
                bail_on_tree=True)
            if default_file:
                default, _ = pagure.doc_utils.convert_readme(
                    default_file.data, 'md')

    if flask.request.method == 'GET':
        form.private.data = repo.settings.get(
            'issues_default_to_private', False)

    return flask.render_template(
        'new_issue.html',
        select='issues',
        form=form,
        repo=repo,
        username=username,
        types=types,
        default=default,
    )
예제 #19
0
def update_issue(repo, issueid, username=None, namespace=None):
    ''' Add a comment to an issue. '''
    is_js = flask.request.args.get('js', False)

    repo = flask.g.repo

    if flask.request.method == 'GET':
        if not is_js:
            flask.flash('Invalid method: GET', 'error')
        return flask.redirect(flask.url_for(
            'view_issue', username=username, repo=repo.name,
            namespace=repo.namespace, issueid=issueid))

    if not repo.settings.get('issue_tracker', True):
        flask.abort(404, 'No issue tracker found for this project')

    issue = pagure.lib.search_issues(SESSION, repo, issueid=issueid)

    if issue is None or issue.project != repo:
        flask.abort(404, 'Issue not found')

    if issue.private and not flask.g.repo_admin \
            and (not authenticated() or
                 not issue.user.user == flask.g.fas_user.username):
        flask.abort(
            403, 'This issue is private and you are not allowed to view it')

    if flask.request.form.get('edit_comment'):
        commentid = flask.request.form.get('edit_comment')
        form = pagure.forms.EditCommentForm()
        if form.validate_on_submit():
            return edit_comment_issue(
                repo.name, issueid, commentid, username=username)

    status = pagure.lib.get_issue_statuses(SESSION)
    form = pagure.forms.UpdateIssueForm(
        status=status,
        priorities=repo.priorities,
        milestones=repo.milestones,
        close_status=repo.close_status,
    )

    if form.validate_on_submit():
        repo_admin = flask.g.repo_admin

        if flask.request.form.get('drop_comment'):
            commentid = flask.request.form.get('drop_comment')

            comment = pagure.lib.get_issue_comment(
                SESSION, issue.uid, commentid)
            if comment is None or comment.issue.project != repo:
                flask.abort(404, 'Comment not found')

            if (flask.g.fas_user.username != comment.user.username
                    or comment.parent.status != 'Open') \
                    and not flask.g.repo_admin:
                flask.abort(
                    403,
                    'You are not allowed to remove this comment from '
                    'this issue')

            issue.last_updated = datetime.datetime.utcnow()
            SESSION.add(issue)
            SESSION.delete(comment)
            try:
                SESSION.commit()
                if not is_js:
                    flask.flash('Comment removed')
            except SQLAlchemyError as err:  # pragma: no cover
                is_js = False
                SESSION.rollback()
                LOG.error(err)
                if not is_js:
                    flask.flash(
                        'Could not remove the comment: %s' % commentid,
                        'error')
            if is_js:
                return 'ok'
            else:
                return flask.redirect(flask.url_for(
                    'view_issue', username=username, repo=repo.name,
                    namespace=repo.namespace, issueid=issueid))

        comment = form.comment.data
        depends = []
        for depend in form.depends.data.split(','):
            if depend.strip():
                try:
                    depends.append(int(depend.strip()))
                except ValueError:
                    pass

        blocks = []
        for block in form.blocks.data.split(','):
            if block.strip():
                try:
                    blocks.append(int(block.strip()))
                except ValueError:
                    pass

        assignee = form.assignee.data.strip() or None
        new_status = form.status.data.strip() or None
        close_status = form.close_status.data or None
        if new_status != 'Closed':
            close_status = None
        if close_status not in repo.close_status:
            close_status = None

        new_priority = None
        try:
            new_priority = int(form.priority.data)
        except:
            pass
        tags = [
            tag.strip()
            for tag in form.tag.data.split(',')
            if tag.strip()]

        new_milestone = None
        try:
            if repo.milestones:
                new_milestone = form.milestone.data.strip() or None
        except:
            pass

        try:
            messages = set()

            # New comment
            if comment:
                message = pagure.lib.add_issue_comment(
                    SESSION,
                    issue=issue,
                    comment=comment,
                    user=flask.g.fas_user.username,
                    ticketfolder=APP.config['TICKETS_FOLDER'],
                )
                SESSION.commit()
                if message and not is_js:
                    messages.add(message)

            # The status field can be updated by both the admin and the
            # person who opened the ticket.
            # Update status
            if repo_admin or flask.g.fas_user.username == issue.user.user:
                if new_status in status:
                    message = pagure.lib.edit_issue(
                        SESSION,
                        issue=issue,
                        status=new_status,
                        close_status=close_status,
                        private=issue.private,
                        user=flask.g.fas_user.username,
                        ticketfolder=APP.config['TICKETS_FOLDER'],
                    )
                    SESSION.commit()
                    if message:
                        messages.add(message)

            # All the other meta-data can be changed only by admins
            # while other field will be missing for non-admin and thus
            # reset if we let them
            if repo_admin:
                # Adjust (add/remove) tags
                messages.union(set(pagure.lib.update_tags(
                    SESSION, issue, tags,
                    username=flask.g.fas_user.username,
                    ticketfolder=APP.config['TICKETS_FOLDER']
                )))

            # The meta-data can be changed by admins and issue creator,
            # where issue creators can only change status of their issue while
            # other fields will be missing for non-admin and thus reset if we let them
            if repo_admin:
                # Assign or update assignee of the ticket
                message = pagure.lib.add_issue_assignee(
                    SESSION,
                    issue=issue,
                    assignee=assignee or None,
                    user=flask.g.fas_user.username,
                    ticketfolder=APP.config['TICKETS_FOLDER'],
                )
                SESSION.commit()
                if message and message != 'Nothing to change':
                    messages.add(message)

                # Update priority
                if str(new_priority) in repo.priorities:
                    message = pagure.lib.edit_issue(
                        SESSION,
                        issue=issue,
                        priority=new_priority,
                        private=issue.private,
                        user=flask.g.fas_user.username,
                        ticketfolder=APP.config['TICKETS_FOLDER'],
                    )
                    SESSION.commit()
                    if message:
                        messages.add(message)

                # Update milestone and privacy setting
                message = pagure.lib.edit_issue(
                    SESSION,
                    issue=issue,
                    milestone=new_milestone,
                    private=form.private.data,
                    user=flask.g.fas_user.username,
                    ticketfolder=APP.config['TICKETS_FOLDER'],
                )
                SESSION.commit()
                if message:
                    messages.add(message)

                # Update the custom keys/fields
                for key in repo.issue_keys:
                    value = flask.request.form.get(key.name)
                    if value:
                        if key.key_type == 'link':
                            links = value.split(',')
                            for link in links:
                                link = link.replace(' ', '')
                                if not urlpattern.match(link):
                                    flask.abort(
                                        400,
                                        'Meta-data "link" field '
                                        '(%s) has invalid url (%s) ' %
                                        (key.name, link))
                        messages.add(
                            pagure.lib.set_custom_key_value(
                                SESSION, issue, key, value)
                        )

                # Update ticket this one depends on
                messages.union(set(pagure.lib.update_dependency_issue(
                    SESSION, repo, issue, depends,
                    username=flask.g.fas_user.username,
                    ticketfolder=APP.config['TICKETS_FOLDER'],
                )))

                # Update ticket(s) depending on this one
                messages.union(set(pagure.lib.update_blocked_issue(
                    SESSION, repo, issue, blocks,
                    username=flask.g.fas_user.username,
                    ticketfolder=APP.config['TICKETS_FOLDER'],
                )))

            if not is_js:
                for message in messages:
                    flask.flash(message)

        except pagure.exceptions.PagureException as err:
            is_js = False
            SESSION.rollback()
            flask.flash(err.message, 'error')
        except SQLAlchemyError as err:  # pragma: no cover
            is_js = False
            SESSION.rollback()
            APP.logger.exception(err)
            flask.flash(str(err), 'error')
        except filelock.Timeout as err:  # pragma: no cover
            is_js = False
            SESSION.rollback()
            APP.logger.exception(err)
            flask.flash(
                    'We could not save all the info, please try again',
                    'error')
    else:
        if is_js:
            return 'notok: %s' % form.errors

    if is_js:
        return 'ok'
    else:
        return flask.redirect(flask.url_for(
            'view_issue',
            repo=repo.name,
            username=username,
            namespace=namespace,
            issueid=issueid)
        )
예제 #20
0
def new_issue(repo, username=None):
    """ Create a new issue
    """
    repo = pagure.lib.get_project(SESSION, repo, user=username)

    if repo is None:
        flask.abort(404, 'Project not found')

    if not repo.settings.get('issue_tracker', True):
        flask.abort(404, 'No issue tracker found for this project')

    status = pagure.lib.get_issue_statuses(SESSION)
    form = pagure.forms.IssueForm(status=status)
    if form.validate_on_submit():
        title = form.title.data
        content = form.issue_content.data
        private = form.private.data

        try:
            issue = pagure.lib.new_issue(
                SESSION,
                repo=repo,
                title=title,
                content=content,
                private=private or False,
                user=flask.g.fas_user.username,
                ticketfolder=APP.config['TICKETS_FOLDER'],
            )
            SESSION.commit()
            # If there is a file attached, attach it.
            filestream = flask.request.files.get('filestream')
            if filestream and '<!!image>' in issue.content:
                new_filename = pagure.lib.git.add_file_to_git(
                    repo=repo,
                    issue=issue,
                    ticketfolder=APP.config['TICKETS_FOLDER'],
                    user=flask.g.fas_user,
                    filename=filestream.filename,
                    filestream=filestream.stream,
                )
                # Replace the <!!image> tag in the comment with the link
                # to the actual image
                filelocation = flask.url_for(
                    'view_issue_raw_file',
                    repo=repo.name,
                    username=username,
                    filename=new_filename,
                )
                new_filename = new_filename.split('-', 1)[1]
                url = '[![%s](%s)](%s)' % (
                    new_filename, filelocation, filelocation)
                issue.content = issue.content.replace('<!!image>', url)
                SESSION.add(issue)
                SESSION.commit()

            flask.flash('Issue created')
            return flask.redirect(flask.url_for(
                '.view_issue', username=username, repo=repo.name,
                issueid=issue.id))
        except pagure.exceptions.PagureException as err:
            flask.flash(str(err), 'error')
        except SQLAlchemyError as err:  # pragma: no cover
            SESSION.rollback()
            flask.flash(str(err), 'error')

    return flask.render_template(
        'new_issue.html',
        select='issues',
        form=form,
        repo=repo,
        username=username,
        repo_admin=is_repo_admin(repo),
    )
예제 #21
0
파일: issues.py 프로젝트: cloudbehl/pagure
def edit_issue(repo, issueid, username=None):
    """ Edit the specified issue
    """
    repo = pagure.lib.get_project(SESSION, repo, user=username)

    if repo is None:
        flask.abort(404, 'Project not found')

    if not repo.settings.get('issue_tracker', True):
        flask.abort(404, 'No issue tracker found for this project')

    issue = pagure.lib.search_issues(SESSION, repo, issueid=issueid)

    if issue is None or issue.project != repo:
        flask.abort(404, 'Issue not found')

    if not (is_repo_admin(repo)
            or flask.g.fas_user.username == issue.user.username):
        flask.abort(
            403, 'You are not allowed to edit issues for this project')

    status = pagure.lib.get_issue_statuses(SESSION)
    form = pagure.forms.IssueForm(status=status)
    if form.validate_on_submit():
        title = form.title.data
        content = form.issue_content.data
        status = form.status.data
        private = form.private.data

        try:
            message = pagure.lib.edit_issue(
                SESSION,
                issue=issue,
                title=title,
                content=content,
                status=status,
                user=flask.g.fas_user.username,
                ticketfolder=APP.config['TICKETS_FOLDER'],
                private=private,
            )
            SESSION.commit()

            # If there is a file attached, attach it.
            filestream = flask.request.files.get('filestream')
            if filestream and '<!!image>' in issue.content:
                new_filename = pagure.lib.git.add_file_to_git(
                    repo=repo,
                    issue=issue,
                    ticketfolder=APP.config['TICKETS_FOLDER'],
                    user=flask.g.fas_user,
                    filename=filestream.filename,
                    filestream=filestream.stream,
                )
                # Replace the <!!image> tag in the comment with the link
                # to the actual image
                filelocation = flask.url_for(
                    'view_issue_raw_file',
                    repo=repo.name,
                    username=username,
                    filename=new_filename,
                )
                new_filename = new_filename.split('-', 1)[1]
                url = '[![%s](%s)](%s)' % (
                    new_filename, filelocation, filelocation)
                issue.content = issue.content.replace('<!!image>', url)
                SESSION.add(issue)
                SESSION.commit()
            flask.flash(message)
            url = flask.url_for(
                'view_issue', username=username,
                repo=repo.name, issueid=issueid)
            return flask.redirect(url)
        except pagure.exceptions.PagureException as err:
            flask.flash(str(err), 'error')
        except SQLAlchemyError as err:  # pragma: no cover
            SESSION.rollback()
            flask.flash(str(err), 'error')
    elif flask.request.method == 'GET':
        form.title.data = issue.title
        form.issue_content.data = issue.content
        form.status.data = issue.status
        form.private.data = issue.private

    return flask.render_template(
        'new_issue.html',
        select='issues',
        type='edit',
        form=form,
        repo=repo,
        username=username,
        issue=issue,
        issueid=issueid,
        repo_admin=is_repo_admin(repo),
    )
예제 #22
0
파일: issues.py 프로젝트: cloudbehl/pagure
def new_issue(repo, username=None):
    """ Create a new issue
    """
    repo = pagure.lib.get_project(SESSION, repo, user=username)

    if repo is None:
        flask.abort(404, 'Project not found')

    if not repo.settings.get('issue_tracker', True):
        flask.abort(404, 'No issue tracker found for this project')

    form = pagure.forms.IssueFormSimplied()
    if form.validate_on_submit():
        title = form.title.data
        content = form.issue_content.data
        private = form.private.data

        try:
            issue = pagure.lib.new_issue(
                SESSION,
                repo=repo,
                title=title,
                content=content,
                private=private or False,
                user=flask.g.fas_user.username,
                ticketfolder=APP.config['TICKETS_FOLDER'],
            )
            SESSION.commit()
            # If there is a file attached, attach it.
            filestream = flask.request.files.get('filestream')
            if filestream and '<!!image>' in issue.content:
                new_filename = pagure.lib.git.add_file_to_git(
                    repo=repo,
                    issue=issue,
                    ticketfolder=APP.config['TICKETS_FOLDER'],
                    user=flask.g.fas_user,
                    filename=filestream.filename,
                    filestream=filestream.stream,
                )
                # Replace the <!!image> tag in the comment with the link
                # to the actual image
                filelocation = flask.url_for(
                    'view_issue_raw_file',
                    repo=repo.name,
                    username=username,
                    filename=new_filename,
                )
                new_filename = new_filename.split('-', 1)[1]
                url = '[![%s](%s)](%s)' % (
                    new_filename, filelocation, filelocation)
                issue.content = issue.content.replace('<!!image>', url)
                SESSION.add(issue)
                SESSION.commit()

            return flask.redirect(flask.url_for(
                '.view_issue', username=username, repo=repo.name,
                issueid=issue.id))
        except pagure.exceptions.PagureException as err:
            flask.flash(str(err), 'error')
        except SQLAlchemyError as err:  # pragma: no cover
            SESSION.rollback()
            flask.flash(str(err), 'error')

    types = None
    default = None
    ticketrepopath = os.path.join(APP.config['TICKETS_FOLDER'], repo.path)
    if os.path.exists(ticketrepopath):
        ticketrepo = pygit2.Repository(ticketrepopath)
        if not ticketrepo.is_empty and not ticketrepo.head_is_unborn:
            commit = ticketrepo[ticketrepo.head.target]
            # Get the different ticket types
            files = __get_file_in_tree(
                ticketrepo, commit.tree, ['templates'],
                bail_on_tree=True)
            if files:
                types = [f.name.rstrip('.md') for f in files]
            # Get the default template
            default_file = __get_file_in_tree(
                ticketrepo, commit.tree, ['templates', 'default.md'],
                bail_on_tree=True)
            if default_file:
                default, _ = pagure.doc_utils.convert_readme(
                        default_file.data, 'md')

    return flask.render_template(
        'new_issue.html',
        select='issues',
        form=form,
        repo=repo,
        username=username,
        repo_admin=is_repo_admin(repo),
        types=types,
        default=default,
    )
예제 #23
0
def view_plugin(repo, plugin, username=None, namespace=None, full=True):
    """ Presents the settings of the project.
    """
    repo = flask.g.repo

    if not flask.g.repo_admin:
        flask.abort(
            403, 'You are not allowed to change the settings for this project')

    # Private repos are not allowed to leak information outside so disabling CI
    # enables us to keep the repos totally discreate and prevents from leaking
    # information outside
    if repo.private and plugin == 'Pagure CI':
        flask.abort(404, 'Plugin disabled')

    if plugin in APP.config.get('DISABLED_PLUGINS', []):
        flask.abort(404, 'Plugin disabled')

    if plugin == 'default':
        flask.abort(403, 'This plugin cannot be changed')

    plugin = pagure.lib.plugins.get_plugin(plugin)
    fields = []
    new = True
    dbobj = plugin.db_object()

    if hasattr(repo, plugin.backref):
        dbobj = getattr(repo, plugin.backref)

        # There should always be only one, but let's double check
        if dbobj:
            new = False
        else:
            dbobj = plugin.db_object()

    form = plugin.form(obj=dbobj)
    for field in plugin.form_fields:
        fields.append(getattr(form, field))

    if form.validate_on_submit():
        form.populate_obj(obj=dbobj)

        if new:
            dbobj.project_id = repo.id
            SESSION.add(dbobj)
        try:
            SESSION.flush()
        except SQLAlchemyError as err:  # pragma: no cover
            SESSION.rollback()
            _log.exception('Could not add plugin %s', plugin.name)
            flask.flash('Could not add plugin %s, please contact an admin' %
                        plugin.name)

            return flask.render_template('plugin.html',
                                         select='settings',
                                         full=full,
                                         repo=repo,
                                         username=username,
                                         namespace=namespace,
                                         plugin=plugin,
                                         form=form,
                                         fields=fields)

        if form.active.data:
            # Set up the main script if necessary
            plugin.set_up(repo)
            # Install the plugin itself
            try:
                plugin.install(repo, dbobj)
                flask.flash('Hook %s activated' % plugin.name)
            except FileNotFoundException as err:
                _log.exception(err)
                flask.abort(404, 'No git repo found')
        else:
            try:
                plugin.remove(repo)
                flask.flash('Hook %s deactivated' % plugin.name)
            except FileNotFoundException as err:
                _log.exception(err)
                flask.abort(404, 'No git repo found')

        SESSION.commit()

        return flask.redirect(
            flask.url_for('view_settings',
                          repo=repo.name,
                          username=username,
                          namespace=namespace))

    return flask.render_template('plugin.html',
                                 select='settings',
                                 full=full,
                                 repo=repo,
                                 namespace=namespace,
                                 username=username,
                                 plugin=plugin,
                                 form=form,
                                 fields=fields)
예제 #24
0
파일: issue.py 프로젝트: tenstormavi/pagure
def api_new_issue(repo, username=None):
    """
    Create a new issue
    ------------------
    Open a new issue on a project.

    ::

        POST /api/0/<repo>/new_issue

    ::

        POST /api/0/fork/<username>/<repo>/new_issue

    Input
    ^^^^^

    +--------------+----------+--------------+-----------------------------+
    | Key          | Type     | Optionality  | Description                 |
    +==============+==========+==============+=============================+
    | ``title``    | string   | Mandatory    | The title of the issue      |
    +--------------+----------+--------------+-----------------------------+
    | ``content``  | string   | Mandatory    | | The description of the    |
    |              |          |              |   issue                     |
    +--------------+----------+--------------+-----------------------------+
    | ``private``  | boolean  | Optional     | | Include this key if       |
    |              |          |              |   you want a private issue  |
    |              |          |              |   to be created             |
    +--------------+----------+--------------+-----------------------------+

    Sample response
    ^^^^^^^^^^^^^^^

    ::

        {
          "message": "Issue created"
        }

    """
    repo = pagure.lib.get_project(SESSION, repo, user=username)
    output = {}

    if repo is None:
        raise pagure.exceptions.APIError(404, error_code=APIERROR.ENOPROJECT)

    if not repo.settings.get('issue_tracker', True):
        raise pagure.exceptions.APIError(404,
                                         error_code=APIERROR.ETRACKERDISABLED)

    if repo != flask.g.token.project:
        raise pagure.exceptions.APIError(401, error_code=APIERROR.EINVALIDTOK)

    form = pagure.forms.IssueFormSimplied(csrf_enabled=False)
    if form.validate_on_submit():
        title = form.title.data
        content = form.issue_content.data
        private = form.private.data

        try:
            issue = pagure.lib.new_issue(
                SESSION,
                repo=repo,
                title=title,
                content=content,
                private=private or False,
                user=flask.g.fas_user.username,
                ticketfolder=APP.config['TICKETS_FOLDER'],
            )
            SESSION.flush()
            # If there is a file attached, attach it.
            filestream = flask.request.files.get('filestream')
            if filestream and '<!!image>' in issue.content:
                new_filename = pagure.lib.git.add_file_to_git(
                    repo=repo,
                    issue=issue,
                    ticketfolder=APP.config['TICKETS_FOLDER'],
                    user=flask.g.fas_user,
                    filename=filestream.filename,
                    filestream=filestream.stream,
                )
                # Replace the <!!image> tag in the comment with the link
                # to the actual image
                filelocation = flask.url_for(
                    'view_issue_raw_file',
                    repo=repo.name,
                    username=username,
                    filename=new_filename,
                )
                new_filename = new_filename.split('-', 1)[1]
                url = '[![%s](%s)](%s)' % (new_filename, filelocation,
                                           filelocation)
                issue.content = issue.content.replace('<!!image>', url)
                SESSION.add(issue)
                SESSION.flush()

            SESSION.commit()
            output['message'] = 'Issue created'
        except SQLAlchemyError, err:  # pragma: no cover
            SESSION.rollback()
            APP.logger.exception(err)
            raise pagure.exceptions.APIError(400, error_code=APIERROR.EDBERROR)
예제 #25
0
파일: issues.py 프로젝트: Sadin/pagure
def new_issue(repo, username=None):
    """ Create a new issue
    """
    repo = pagure.lib.get_project(SESSION, repo, user=username)

    if repo is None:
        flask.abort(404, 'Project not found')

    if not repo.settings.get('issue_tracker', True):
        flask.abort(404, 'No issue tracker found for this project')

    status = pagure.lib.get_issue_statuses(SESSION)
    form = pagure.forms.IssueForm(status=status)
    if form.validate_on_submit():
        title = form.title.data
        content = form.issue_content.data
        private = form.private.data

        try:
            issue = pagure.lib.new_issue(
                SESSION,
                repo=repo,
                title=title,
                content=content,
                private=private or False,
                user=flask.g.fas_user.username,
                ticketfolder=APP.config['TICKETS_FOLDER'],
            )
            SESSION.commit()
            # If there is a file attached, attach it.
            filestream = flask.request.files.get('filestream')
            if filestream and '<!!image>' in issue.content:
                new_filename = pagure.lib.git.add_file_to_git(
                    repo=repo,
                    issue=issue,
                    ticketfolder=APP.config['TICKETS_FOLDER'],
                    user=flask.g.fas_user,
                    filename=filestream.filename,
                    filestream=filestream.stream,
                )
                # Replace the <!!image> tag in the comment with the link
                # to the actual image
                filelocation = flask.url_for(
                    'view_issue_raw_file',
                    repo=repo.name,
                    username=username,
                    filename=new_filename,
                )
                new_filename = new_filename.split('-', 1)[1]
                url = '[![%s](%s)](%s)' % (
                    new_filename, filelocation, filelocation)
                issue.content = issue.content.replace('<!!image>', url)
                SESSION.add(issue)
                SESSION.commit()

            flask.flash('Issue created')
            return flask.redirect(flask.url_for(
                '.view_issue', username=username, repo=repo.name,
                issueid=issue.id))
        except pagure.exceptions.PagureException, err:
            flask.flash(str(err), 'error')
        except SQLAlchemyError, err:  # pragma: no cover
            SESSION.rollback()
            flask.flash(str(err), 'error')
예제 #26
0
파일: issue.py 프로젝트: arielb2/pagure
def api_new_issue(repo, username=None):
    """
    Create a new issue
    ------------------
    This endpoint can be used to open an issue on a project

    ::

        /api/0/<repo>/new_issue

        /api/0/fork/<username>/<repo>/new_issue

    Accepts POST queries only.

    :arg title: The title of the issue/ticket to create
    :arg content: The content of the issue to create (ie the description of
        the problem)
    :arg private: A boolean specifying whether this issue is private or not

    Sample response:

    ::

        {
          "message": "Issue created"
        }

    """
    repo = pagure.lib.get_project(SESSION, repo, user=username)
    output = {}

    if repo is None:
        raise pagure.exceptions.APIError(404, error_code=APIERROR.ENOPROJECT)

    if not repo.settings.get('issue_tracker', True):
        raise pagure.exceptions.APIError(
            404, error_code=APIERROR.ETRACKERDISABLED)

    if repo != flask.g.token.project:
        raise pagure.exceptions.APIError(401, error_code=APIERROR.EINVALIDTOK)

    status = pagure.lib.get_issue_statuses(SESSION)
    form = pagure.forms.IssueForm(status=status, csrf_enabled=False)
    if form.validate_on_submit():
        title = form.title.data
        content = form.issue_content.data
        private = form.private.data

        try:
            issue = pagure.lib.new_issue(
                SESSION,
                repo=repo,
                title=title,
                content=content,
                private=private or False,
                user=flask.g.fas_user.username,
                ticketfolder=APP.config['TICKETS_FOLDER'],
            )
            SESSION.flush()
            # If there is a file attached, attach it.
            filestream = flask.request.files.get('filestream')
            if filestream and '<!!image>' in issue.content:
                new_filename = pagure.lib.git.add_file_to_git(
                    repo=repo,
                    issue=issue,
                    ticketfolder=APP.config['TICKETS_FOLDER'],
                    user=flask.g.fas_user,
                    filename=filestream.filename,
                    filestream=filestream.stream,
                )
                # Replace the <!!image> tag in the comment with the link
                # to the actual image
                filelocation = flask.url_for(
                    'view_issue_raw_file',
                    repo=repo.name,
                    username=username,
                    filename=new_filename,
                )
                new_filename = new_filename.split('-', 1)[1]
                url = '[![%s](%s)](%s)' % (
                    new_filename, filelocation, filelocation)
                issue.content = issue.content.replace('<!!image>', url)
                SESSION.add(issue)
                SESSION.flush()

            SESSION.commit()
            output['message'] = 'Issue created'
        except SQLAlchemyError, err:  # pragma: no cover
            SESSION.rollback()
            APP.logger.exception(err)
            raise pagure.exceptions.APIError(400, error_code=APIERROR.EDBERROR)
예제 #27
0
파일: issues.py 프로젝트: Gahlot/pagure
def edit_issue(repo, issueid, username=None, namespace=None):
    """ Edit the specified issue
    """
    repo = flask.g.repo

    if not repo.settings.get('issue_tracker', True):
        flask.abort(404, 'No issue tracker found for this project')

    issue = pagure.lib.search_issues(SESSION, repo, issueid=issueid)

    if issue is None or issue.project != repo:
        flask.abort(404, 'Issue not found')

    if not (flask.g.repo_admin
            or flask.g.fas_user.username == issue.user.username):
        flask.abort(
            403, 'You are not allowed to edit issues for this project')

    status = pagure.lib.get_issue_statuses(SESSION)
    form = pagure.forms.IssueForm(status=status)
    if form.validate_on_submit():
        title = form.title.data
        content = form.issue_content.data
        status = form.status.data
        private = form.private.data

        try:
            user_obj = pagure.lib.get_user(
                SESSION, flask.g.fas_user.username)
        except pagure.exceptions.PagureException:
            flask.abort(
                404, 'No such user found in the database: %s' % (
                    flask.g.fas_user.username))

        try:
            message = pagure.lib.edit_issue(
                SESSION,
                issue=issue,
                title=title,
                content=content,
                status=status,
                user=flask.g.fas_user.username,
                ticketfolder=APP.config['TICKETS_FOLDER'],
                private=private,
            )
            SESSION.commit()

            # If there is a file attached, attach it.
            filestream = flask.request.files.get('filestream')
            if filestream and '<!!image>' in issue.content:
                new_filename = pagure.lib.git.add_file_to_git(
                    repo=repo,
                    issue=issue,
                    ticketfolder=APP.config['TICKETS_FOLDER'],
                    user=user_obj,
                    filename=filestream.filename,
                    filestream=filestream.stream,
                )
                # Replace the <!!image> tag in the comment with the link
                # to the actual image
                filelocation = flask.url_for(
                    'view_issue_raw_file',
                    repo=repo.name,
                    namespace=repo.namespace,
                    username=username,
                    filename=new_filename,
                )
                new_filename = new_filename.split('-', 1)[1]
                url = '[![%s](%s)](%s)' % (
                    new_filename, filelocation, filelocation)
                issue.content = issue.content.replace('<!!image>', url)
                SESSION.add(issue)
                SESSION.commit()
            flask.flash(message)
            url = flask.url_for(
                'view_issue', username=username, namespace=namespace,
                repo=repo.name, issueid=issueid)
            return flask.redirect(url)
        except pagure.exceptions.PagureException as err:
            flask.flash(str(err), 'error')
        except SQLAlchemyError as err:  # pragma: no cover
            SESSION.rollback()
            flask.flash(str(err), 'error')
    elif flask.request.method == 'GET':
        form.title.data = issue.title
        form.issue_content.data = issue.content
        form.status.data = issue.status
        form.private.data = issue.private

    return flask.render_template(
        'new_issue.html',
        select='issues',
        type='edit',
        form=form,
        repo=repo,
        username=username,
        issue=issue,
        issueid=issueid,
    )
예제 #28
0
def api_new_issue(repo, username=None):
    """
    Create a new issue
    ------------------
    Open a new issue on a project.

    ::

        POST /api/0/<repo>/new_issue

    ::

        POST /api/0/fork/<username>/<repo>/new_issue

    Input
    ^^^^^

    +--------------+----------+--------------+-----------------------------+
    | Key          | Type     | Optionality  | Description                 |
    +==============+==========+==============+=============================+
    | ``title``    | string   | Mandatory    | The title of the issue      |
    +--------------+----------+--------------+-----------------------------+
    | ``content``  | string   | Mandatory    | | The description of the    |
    |              |          |              |   issue                     |
    +--------------+----------+--------------+-----------------------------+
    | ``private``  | boolean  | Optional     | | Include this key if       |
    |              |          |              |   you want a private issue  |
    |              |          |              |   to be created             |
    +--------------+----------+--------------+-----------------------------+

    Sample response
    ^^^^^^^^^^^^^^^

    ::

        {
          "message": "Issue created"
        }

    """
    repo = pagure.lib.get_project(SESSION, repo, user=username)
    output = {}

    if repo is None:
        raise pagure.exceptions.APIError(404, error_code=APIERROR.ENOPROJECT)

    if not repo.settings.get('issue_tracker', True):
        raise pagure.exceptions.APIError(
            404, error_code=APIERROR.ETRACKERDISABLED)

    if repo != flask.g.token.project:
        raise pagure.exceptions.APIError(401, error_code=APIERROR.EINVALIDTOK)

    form = pagure.forms.IssueFormSimplied(csrf_enabled=False)
    if form.validate_on_submit():
        title = form.title.data
        content = form.issue_content.data
        private = str(form.private.data).lower() in ['true', '1']

        try:
            issue = pagure.lib.new_issue(
                SESSION,
                repo=repo,
                title=title,
                content=content,
                private=private,
                user=flask.g.fas_user.username,
                ticketfolder=APP.config['TICKETS_FOLDER'],
            )
            SESSION.flush()
            # If there is a file attached, attach it.
            filestream = flask.request.files.get('filestream')
            if filestream and '<!!image>' in issue.content:
                new_filename = pagure.lib.git.add_file_to_git(
                    repo=repo,
                    issue=issue,
                    ticketfolder=APP.config['TICKETS_FOLDER'],
                    user=flask.g.fas_user,
                    filename=filestream.filename,
                    filestream=filestream.stream,
                )
                # Replace the <!!image> tag in the comment with the link
                # to the actual image
                filelocation = flask.url_for(
                    'view_issue_raw_file',
                    repo=repo.name,
                    username=username,
                    filename=new_filename,
                )
                new_filename = new_filename.split('-', 1)[1]
                url = '[![%s](%s)](%s)' % (
                    new_filename, filelocation, filelocation)
                issue.content = issue.content.replace('<!!image>', url)
                SESSION.add(issue)
                SESSION.flush()

            SESSION.commit()
            output['message'] = 'Issue created'
        except SQLAlchemyError as err:  # pragma: no cover
            SESSION.rollback()
            APP.logger.exception(err)
            raise pagure.exceptions.APIError(400, error_code=APIERROR.EDBERROR)

    else:
        raise pagure.exceptions.APIError(400, error_code=APIERROR.EINVALIDREQ)

    jsonout = flask.jsonify(output)
    return jsonout
예제 #29
0
파일: plugins.py 프로젝트: 0-T-0/pagure
def view_plugin(repo, plugin, username=None, full=True):
    """ Presents the settings of the project.
    """
    repo = pagure.lib.get_project(SESSION, repo, user=username)

    if not repo:
        flask.abort(404, 'Project not found')

    if not is_repo_admin(repo):
        flask.abort(
            403,
            'You are not allowed to change the settings for this project')

    if plugin in APP.config.get('DISABLED_PLUGINS', []):
        flask.abort(404, 'Plugin disabled')

    plugin = get_plugin(plugin)
    fields = []
    new = True
    dbobj = plugin.db_object()
    if hasattr(repo, plugin.backref):
        dbobj = getattr(repo, plugin.backref)
        # There should always be only one, but let's double check
        if dbobj and len(dbobj) > 0:
            dbobj = dbobj[0]
            new = False
        else:
            dbobj = plugin.db_object()

    form = plugin.form(obj=dbobj)
    for field in plugin.form_fields:
        fields.append(getattr(form, field))

    if form.validate_on_submit():
        form.populate_obj(obj=dbobj)
        if new:
            dbobj.project_id = repo.id
            SESSION.add(dbobj)
        try:
            SESSION.flush()
        except SQLAlchemyError as err:  # pragma: no cover
            SESSION.rollback()
            APP.logger.debug('Could not add plugin %s', plugin.name)
            APP.logger.exception(err)
            flask.flash(
                'Could not add plugin %s, please contact an admin'
                % plugin.name)

            return flask.render_template(
                'plugin.html',
                select='settings',
                full=full,
                repo=repo,
                username=username,
                plugin=plugin,
                form=form,
                fields=fields)

        if form.active.data:
            # Set up the main script if necessary
            plugin.set_up(repo)
            # Install the plugin itself
            try:
                plugin.install(repo, dbobj)
                flask.flash('Hook %s activated' % plugin.name)
            except FileNotFoundException as err:
                pagure.APP.logger.exception(err)
                flask.abort(404, 'No git repo found')
        else:
            try:
                plugin.remove(repo)
                flask.flash('Hook %s inactived' % plugin.name)
            except FileNotFoundException as err:
                pagure.APP.logger.exception(err)
                flask.abort(404, 'No git repo found')

        SESSION.commit()

        return flask.redirect(flask.url_for(
            'view_settings', repo=repo.name, username=username))

    return flask.render_template(
        'plugin.html',
        select='settings',
        full=full,
        repo=repo,
        username=username,
        plugin=plugin,
        form=form,
        fields=fields)
예제 #30
0
def do_login():
    """ Log in the user.
    """
    form = forms.LoginForm()
    next_url = flask.request.form.get('next_url')
    if not next_url or next_url == 'None':
        next_url = flask.url_for('index')

    if form.validate_on_submit():
        username = form.username.data
        user_obj = pagure.lib.search_user(SESSION, username=username)
        if not user_obj:
            flask.flash('Username or password invalid.', 'error')
            return flask.redirect(flask.url_for('auth_login'))

        try:
            password_checks = check_password(form.password.data,
                                             user_obj.password,
                                             seed=APP.config.get(
                                                 'PASSWORD_SEED', None))
        except pagure.exceptions.PagureException as err:
            _log.exception(err)
            flask.flash('Username or password of invalid format.', 'error')
            return flask.redirect(flask.url_for('auth_login'))

        if not password_checks:
            flask.flash('Username or password invalid.', 'error')
            return flask.redirect(flask.url_for('auth_login'))

        elif user_obj.token:
            flask.flash(
                'Invalid user, did you confirm the creation with the url '
                'provided by email?', 'error')
            return flask.redirect(flask.url_for('auth_login'))

        else:

            if not user_obj.password.startswith('$2$'):
                user_obj.password = generate_hashed_value(form.password.data)
                SESSION.add(user_obj)

            visit_key = pagure.lib.login.id_generator(40)
            now = datetime.datetime.utcnow()
            expiry = now + datetime.timedelta(days=30)
            session = model.PagureUserVisit(
                user_id=user_obj.id,
                user_ip=flask.request.remote_addr,
                visit_key=visit_key,
                expiry=expiry,
            )
            SESSION.add(session)
            try:
                SESSION.commit()
                flask.g.fas_user = user_obj
                flask.g.fas_session_id = visit_key
                flask.g.fas_user.login_time = now
                flask.flash('Welcome %s' % user_obj.username)
            except SQLAlchemyError as err:  # pragma: no cover
                flask.flash(
                    'Could not set the session in the db, '
                    'please report this error to an admin', 'error')
                _log.exception(err)

        return flask.redirect(next_url)
    else:
        flask.flash('Insufficient information provided', 'error')
    return flask.redirect(flask.url_for('auth_login'))
예제 #31
0
파일: plugins.py 프로젝트: girish946/pagure
def view_plugin(repo, plugin, username=None, full=True):
    """ Presents the settings of the project.
    """
    repo = pagure.lib.get_project(SESSION, repo, user=username)

    if not repo:
        flask.abort(404, 'Project not found')

    if not is_repo_admin(repo):
        flask.abort(
            403, 'You are not allowed to change the settings for this project')

    if plugin in APP.config.get('DISABLED_PLUGINS', []):
        flask.abort(404, 'Plugin disabled')

    plugin = get_plugin(plugin)
    fields = []
    new = True
    dbobj = plugin.db_object()
    if hasattr(repo, plugin.backref):
        dbobj = getattr(repo, plugin.backref)
        # There should always be only one, but let's double check
        if dbobj and len(dbobj) > 0:
            dbobj = dbobj[0]
            new = False
        else:
            dbobj = plugin.db_object()

    form = plugin.form(obj=dbobj)
    for field in plugin.form_fields:
        fields.append(getattr(form, field))

    if form.validate_on_submit():
        form.populate_obj(obj=dbobj)
        if new:
            dbobj.project_id = repo.id
            SESSION.add(dbobj)
        try:
            SESSION.flush()
        except SQLAlchemyError as err:  # pragma: no cover
            SESSION.rollback()
            APP.logger.debug('Could not add plugin %s', plugin.name)
            APP.logger.exception(err)
            flask.flash('Could not add plugin %s, please contact an admin' %
                        plugin.name)

            return flask.render_template('plugin.html',
                                         select='settings',
                                         full=full,
                                         repo=repo,
                                         username=username,
                                         plugin=plugin,
                                         form=form,
                                         fields=fields)

        if form.active.data:
            # Set up the main script if necessary
            plugin.set_up(repo)
            # Install the plugin itself
            plugin.install(repo, dbobj)
            flask.flash('Hook %s activated' % plugin.name)
        else:
            plugin.remove(repo)
            flask.flash('Hook %s inactived' % plugin.name)

        SESSION.commit()

        return flask.redirect(
            flask.url_for('view_settings', repo=repo.name, username=username))

    return flask.render_template('plugin.html',
                                 select='settings',
                                 full=full,
                                 repo=repo,
                                 username=username,
                                 plugin=plugin,
                                 form=form,
                                 fields=fields)
예제 #32
0
def api_new_issue(repo, username=None, namespace=None):
    """
    Create a new issue
    ------------------
    Open a new issue on a project.

    ::

        POST /api/0/<repo>/new_issue
        POST /api/0/<namespace>/<repo>/new_issue

    ::

        POST /api/0/fork/<username>/<repo>/new_issue
        POST /api/0/fork/<username>/<namespace>/<repo>/new_issue

    Input
    ^^^^^

    +-------------------+--------+-------------+---------------------------+
    | Key               | Type   | Optionality | Description               |
    +===================+========+=============+===========================+
    | ``title``         | string | Mandatory   | The title of the issue    |
    +-------------------+--------+-------------+---------------------------+
    | ``issue_content`` | string | Mandatory   | | The description of the  |
    |                   |        |             |   issue                   |
    +-------------------+--------+-------------+---------------------------+
    | ``private``       | boolean| Optional    | | Include this key if     |
    |                   |        |             |   you want a private issue|
    |                   |        |             |   to be created           |
    +-------------------+--------+-------------+---------------------------+
    | ``priority``      | string | Optional    | | The priority to set to  |
    |                   |        |             |   this ticket from the    |
    |                   |        |             |   list of priorities set  |
    |                   |        |             |   in the project          |
    +-------------------+--------+-------------+---------------------------+
    | ``milestone``     | string | Optional    | | The milestone to assign |
    |                   |        |             |   to this ticket from the |
    |                   |        |             |   list of milestones set  |
    |                   |        |             |   in the project          |
    +-------------------+--------+-------------+---------------------------+
    | ``tag``           | string | Optional    | | Comma separated list of |
    |                   |        |             |   tags to link to this    |
    |                   |        |             |   ticket from the list of |
    |                   |        |             |   tags in the project     |
    +-------------------+--------+-------------+---------------------------+
    | ``assignee``      | string | Optional    | | The username of the user|
    |                   |        |             |   to assign this ticket to|
    +-------------------+--------+-------------+---------------------------+

    Sample response
    ^^^^^^^^^^^^^^^

    ::

        {
          "issue": {
            "assignee": null,
            "blocks": [],
            "close_status": null,
            "closed_at": null,
            "comments": [],
            "content": "This issue needs attention",
            "custom_fields": [],
            "date_created": "1479458613",
            "depends": [],
            "id": 1,
            "milestone": null,
            "priority": null,
            "private": false,
            "status": "Open",
            "tags": [],
            "title": "test issue",
            "user": {
              "fullname": "PY C",
              "name": "pingou"
            }
          },
          "message": "Issue created"
        }

    """
    output = {}
    repo = _get_repo(repo, username, namespace)
    _check_issue_tracker(repo)
    _check_token(repo, project_token=False)

    user_obj = pagure.lib.get_user(SESSION, flask.g.fas_user.username)
    if not user_obj:
        raise pagure.exceptions.APIError(404, error_code=APIERROR.ENOUSER)

    form = pagure.forms.IssueFormSimplied(priorities=repo.priorities,
                                          milestones=repo.milestones,
                                          csrf_enabled=False)
    if form.validate_on_submit():
        title = form.title.data
        content = form.issue_content.data
        milestone = form.milestone.data or None
        private = str(form.private.data).lower() in ['true', '1']
        priority = form.priority.data or None
        assignee = flask.request.form.get('assignee', '').strip() or None
        tags = [
            tag.strip() for tag in flask.request.form.get('tag', '').split(',')
            if tag.strip()
        ]

        try:
            issue = pagure.lib.new_issue(
                SESSION,
                repo=repo,
                title=title,
                content=content,
                private=private,
                assignee=assignee,
                milestone=milestone,
                priority=priority,
                tags=tags,
                user=flask.g.fas_user.username,
                ticketfolder=APP.config['TICKETS_FOLDER'],
            )
            SESSION.flush()
            # If there is a file attached, attach it.
            filestream = flask.request.files.get('filestream')
            if filestream and '<!!image>' in issue.content:
                new_filename = pagure.lib.add_attachment(
                    repo=repo,
                    issue=issue,
                    attachmentfolder=APP.config['ATTACHMENTS_FOLDER'],
                    user=user_obj,
                    filename=filestream.filename,
                    filestream=filestream.stream,
                )
                # Replace the <!!image> tag in the comment with the link
                # to the actual image
                filelocation = flask.url_for(
                    'view_issue_raw_file',
                    repo=repo.name,
                    username=username,
                    filename=new_filename,
                )
                new_filename = new_filename.split('-', 1)[1]
                url = '[![%s](%s)](%s)' % (new_filename, filelocation,
                                           filelocation)
                issue.content = issue.content.replace('<!!image>', url)
                SESSION.add(issue)
                SESSION.flush()

            SESSION.commit()
            output['message'] = 'Issue created'
            output['issue'] = issue.to_json(public=True)
        except SQLAlchemyError as err:  # pragma: no cover
            SESSION.rollback()
            APP.logger.exception(err)
            raise pagure.exceptions.APIError(400, error_code=APIERROR.EDBERROR)

    else:
        raise pagure.exceptions.APIError(400,
                                         error_code=APIERROR.EINVALIDREQ,
                                         errors=form.errors)

    jsonout = flask.jsonify(output)
    return jsonout