Пример #1
0
def configure_statuses(request):
    project_name = request.matchdict['project_name']
    session = DBSession()
    try:
        project = session.query(Project).filter_by(name=project_name).one()
    except NoResultFound:
        raise HTTPNotFound()
    if not has_permission(request, PERM_MANAGE_PROJECT, project):
        raise HTTPForbidden()
    posted_statuses = map(int, request.POST.getall('statuses'))
    # The UI should not allow to remove default statuses, but let's
    # enforce it here.
    for default_status in DEFAULT_STATUSES:
        if default_status['id'] not in posted_statuses:
            msg = _('You cannot remove this status.')
            request.session.flash(msg, 'error')
            return configure_statuses_form(request)
    # The UI should not allow to remove statuses that are being used,
    # but let's enforce it here.
    # FIXME: to do
    current_statuses = {}
    for status in project.statuses:
        current_statuses[status.id] = status
    statuses = zip(posted_statuses, request.POST.getall('labels'))
    # Change existing statuses and add new ones
    new_id = session.execute(
        'SELECT MAX(id) FROM statuses '
        'WHERE project_id=%d' % project.id).fetchone()[0]
    for position, (status_id, label) in enumerate(statuses, 1):
        if not status_id:
            new_id += 1
            status = Status(id=new_id, project_id=project.id,
                            label=label, position=position)
            session.add(status)
        else:
            status = current_statuses[status_id]
            if label != status.label:
                status.label = label
            if position != status.position:
                status.position = position
    # Remove statuses
    for status in project.statuses:
        if status.id not in posted_statuses:
            session.delete(status)
    msg = _('Your changes have been saved.')
    request.session.flash(msg, 'success')
    url = request.route_url('project_configure_statuses',
                            project_name=project.name)
    return HTTPSeeOther(location=url)
Пример #2
0
def add_user_form(request, form=None):
    if not request.user.is_admin:
        raise HTTPForbidden()
    if form is None:
        form = AddUserForm()
    return {'api': TemplateAPI(request, _(u'Add a new user')),
            'form': form}
Пример #3
0
def add_project_form(request, form=None):
    if not request.user.is_admin:
        raise HTTPForbidden()
    if form is None:
        form = AddProjectForm()
    return {'api': TemplateAPI(request, _(u'Add project')),
            'form': form}
Пример #4
0
def list_projects(request):
    if not request.user.is_admin:
        raise HTTPForbidden()
    session = DBSession()
    projects = session.query(Project).order_by(Project.title).all()
    return {'api': TemplateAPI(request, _(u'Projects')),
            'projects': projects}
Пример #5
0
def list_users(request):
    """List users (in the control panel)."""
    if not request.user.is_admin:
        raise HTTPForbidden()
    session = DBSession()
    # FIXME: paginate
    users = session.query(User).order_by(User.fullname).all()
    return {'api': TemplateAPI(request, _(u'Users')),
            'users': users}
Пример #6
0
Файл: auth.py Проект: dbaty/Yait
def logout(request, _forget=forget):
    """Logout the user.

    ``_forget`` is only customized in tests.
    """
    headers = _forget(request)
    msg = _(u'You have been successfully logged out.')
    request.session.flash(msg, 'success')
    return HTTPSeeOther(location=request.application_url, headers=headers)
Пример #7
0
 def setup(self, project, db_session):
     self.project = project
     self.db_session = db_session
     # 'assignee'
     assignee_choices = [('', _(u'Nobody'))]
     assignee_choices += self._get_possible_assignees()
     self.assignee.choices = assignee_choices
     # 'status'
     self.status.choices = [(s.id, s.label) for s in self.project.statuses]
Пример #8
0
def configure_roles(request):
    project_name = request.matchdict['project_name']
    session = DBSession()
    try:
        project = session.query(Project).filter_by(name=project_name).one()
    except NoResultFound:
        raise HTTPNotFound()
    if not has_permission(request, PERM_MANAGE_PROJECT, project):
        raise HTTPForbidden()
    current_roles = {}
    for role in session.query(Role).filter_by(project_id=project.id):
        current_roles[role.user_id] = role.role
    updated_roles = []
    for field, role_id in request.POST.items():
        if not field.startswith('role_'):  # pragma: no cover
            continue
        user_id = int(field[1 + field.rfind('_'):])
        if not request.user.is_admin:
            if user_id == request.user.id:
                # Manager cannot revoke his/her own manager role. This
                # is not allowed by the UI but we handle the case
                # anyway.
                msg = _(u'You cannot revoke your own manager role.')
                request.session.flash(msg, 'error')
                return configure_roles_form(request)
            if user_id not in current_roles:
                # A non-administrator cannot grant a role to a user
                # who has no prior role in this project. This is not
                # allowed by the UI but we handle the case anyway.
                msg = _(u'Granting a role to a new user is not allowed '
                        u'because you are not an administrator.')
                request.session.flash(msg, 'error')
                return configure_roles_form(request)
        role_id = int(role_id)
        if role_id:
            updated_roles.append(Role(project_id=project.id,
                                      user_id=user_id,
                                      role=role_id))
    session.query(Role).filter_by(project_id=project.id).delete()
    session.add_all(updated_roles)
    request.session.flash(_(u'Roles have been updated'), 'success')
    location = request.route_url('project_configure_roles',
                                 project_name=project.name)
    return HTTPSeeOther(location=location)
Пример #9
0
Файл: auth.py Проект: dbaty/Yait
def login_form(request, login_failed=False):
    next = request.GET.get('next') or request.POST.get('next') or \
        request.route_url('home')
    api = TemplateAPI(request, _(u'Log in'))
    api.show_login_link = False
    return {'api': api,
            'next': next,
            'login_failed': login_failed,
            'needs_login': '******' in request.GET,
            'login': request.POST.get('login', '')}
Пример #10
0
def edit_user(request):
    if not request.user.is_admin:
        raise HTTPForbidden()
    user_id = int(request.matchdict['user_id'])
    session = DBSession()
    try:
        user = session.query(User).filter_by(id=user_id).one()
    except NoResultFound:
        raise HTTPNotFound()
    form = EditUserForm(request.POST)
    if not form.validate():
        return edit_user_form(request, form)
    data = form.data
    if user_id == request.user.id and not form.data['is_admin']:
        msg = _(u"You cannot revoke your own administrator's rights.")
        request.session.flash(msg, 'error')
        return edit_user_form(request, form)
    user.update(**data)
    request.session.flash(_(u'User has been edited.'), 'success')
    location = request.route_url('users')
    return HTTPSeeOther(location)
Пример #11
0
def issues(request):
    """A list of issues that correspond to the filter requested in the
    GET parameters.
    """
    project_name = request.matchdict['project_name']
    session = DBSession()
    try:
        project = session.query(Project).filter_by(name=project_name).one()
    except NoResultFound:
        raise HTTPNotFound()
    if not has_permission(request, PERM_VIEW_PROJECT, project):
        raise HTTPForbidden()
    can_participate = has_permission(
        request, PERM_PARTICIPATE_IN_PROJECT, project)
    can_manage_project = has_permission(request, PERM_MANAGE_PROJECT, project)
    issues = session.query(Issue).filter_by(project_id=project.id).\
        filter(Issue.status!=ISSUE_STATUS_CLOSED)
    filter = request.GET.get('filter')
    if filter == 'assigned-to-me':
        issues = issues.filter_by(assignee=request.user.id)
        filter_label = _('Assigned to me')
    elif filter == 'watching':
        # FIXME: not implemented yet
        filter_label = None
    elif filter == 'not-assigned':
        filter_label = _('Not assigned')
        issues = issues.filter_by(assignee=None)
    else:
        filter_label = None
        issues = ()
    if issues:
        issues = issues.all()
    return {'api': TemplateAPI(request, project.title),
            'project': project,
            'can_participate': can_participate,
            'can_manage_project': can_manage_project,
            'filter': filter,
            'filter_label': filter_label,
            'issues': issues,
            'count': len(issues)}
Пример #12
0
def delete_project(request):
    if not request.user.is_admin:
        raise HTTPForbidden()
    project_id = int(request.POST.get('project_id'))
    session = DBSession()
    project = session.query(Project).filter_by(id=project_id).one()
    name, title = project.name, project.title
    session.delete(project)
    msg = _(u'Project "${name}" ("${title}") has been deleted.') % {
        'name': name, 'title': title}
    request.session.flash(msg, 'success')
    url = request.route_url('projects')
    return HTTPSeeOther(location=url)
Пример #13
0
def add_user(request):
    if not request.user.is_admin:
        raise HTTPForbidden()
    form = AddUserForm(request.POST)
    if not form.validate():
        return add_user_form(request, form)
    data = form.data
    data.pop('password_confirm')
    user = User(**data)
    session = DBSession()
    session.add(user)
    request.session.flash(_(u'User has been added.'), 'success')
    location = request.route_url('users')
    return HTTPSeeOther(location)
Пример #14
0
def get_recent_activity(db_session, project, request):
    """Return a list of strings that describe the recent activity in
    the given ``project``.
    """
    activity = []
    for issue, change in db_session.query(Issue, Change).\
            filter(Change.project_id==project.id).\
            filter(Issue.id==Change.issue_id).\
            order_by(Change.date.desc()).\
            limit(RECENT_ACTIVITY_LENGTH).all():
        action = _(CHANGE_ACTIONS[change.type])
        issue_url = request.route_url(
            'issue_view', project_name=project.name, issue_ref=issue.ref)
        change_url = '%s#change-%d' % (issue_url, change.id)
        info = {'author': request.cache.fullnames[change.author],
                'action': action,
                'issue_ref': issue.ref,
                'issue_url': issue_url,
                'change_url': change_url,
                'title': issue.title}
        msg = _('${author} <a href="${change_url}">${action}</a> issue '
                '<a href="${issue_url}">#${issue_ref}: ${title}</a>.') % info
        activity.append({'desc': msg, 'text': change.get_rendered_text()})
    return activity
Пример #15
0
def configure(request):
    project_name = request.matchdict['project_name']
    session = DBSession()
    try:
        project = session.query(Project).filter_by(name=project_name).one()
    except NoResultFound:
        raise HTTPNotFound()
    if not has_permission(request, PERM_MANAGE_PROJECT, project):
        raise HTTPForbidden()
    form = make_edit_project_form(request.POST)
    if not form.validate():
        return configure_form(request, form)
    project.update(**form.data)
    msg = _(u'Changes have been saved.')
    request.session.flash(msg, 'success')
    url = request.route_url('project_configure', project_name=project.name)
    return HTTPSeeOther(url)
Пример #16
0
def configure_roles_form(request):
    project_name = request.matchdict['project_name']
    session = DBSession()
    try:
        project = session.query(Project).filter_by(name=project_name).one()
    except NoResultFound:
        raise HTTPNotFound()
    if not has_permission(request, PERM_MANAGE_PROJECT, project):
        raise HTTPForbidden()
    roles = []
    for role_id, label in ROLE_LABELS.items():
        roles.append({'id': role_id, 'label': label})
    user_roles = []
    for role, user in session.query(Role, User).\
            filter(Role.project_id==project.id).\
            filter(Role.user_id==User.id).\
            order_by(User.fullname):
        user_roles.append({'user_id': user.id,
                           'fullname': user.fullname,
                           'role': role.role})
    if request.user.is_admin:
        ids_with_role = [u['user_id'] for u in user_roles]
        users_with_no_role = [{'id': 0, 'fullname': _(u'Select a user...')}]
        # 'ids_with_role' may be empty. SQLAlchemy informs us in this
        # case that
        #     the IN-predicate on "users.id" was invoked with an empty
        #     sequence. This results in a contradiction, which
        #     nonetheless can be expensive to evaluate.
        # Hence the construction of a tuple that contains at least -1 (an
        # impossible user id).
        for user in session.query(User).\
                filter(~User.id.in_((-1, ) + tuple(ids_with_role))).\
                filter_by(is_admin=False).\
                order_by(User.fullname):
            users_with_no_role.append({'id': user.id,
                                       'fullname': user.fullname})
    else:
        # Project managers are not allowed to grant a role to users
        # who do not have a prior role in the project.
        users_with_no_role = ()
    return {'api': TemplateAPI(request, project.title),
            'can_manage_project': True,
            'project': project,
            'roles': roles,
            'user_roles': user_roles,
            'users_with_no_role': users_with_no_role}
Пример #17
0
def list_user_roles(request):
    if not request.user.is_admin:
        raise HTTPForbidden()
    user_id = int(request.matchdict['user_id'])
    session = DBSession()
    try:
        user = session.query(User).filter_by(id=user_id).one()
    except NoResultFound:
        raise HTTPNotFound()
    roles = []
    for role, project in session.query(Role, Project).\
            filter(Role.user_id==user.id).\
            filter(Role.project_id==Project.id).\
            order_by(Project.title):
        roles.append((project, _(ROLE_LABELS[role.role])))
    return {'api': TemplateAPI(request, user.fullname),
            'user': user,
            'roles': roles}
Пример #18
0
def add_form(request, form=None):
    session = DBSession()
    project_name = request.matchdict['project_name']
    try:
        project = session.query(Project).filter_by(name=project_name).one()
    except NoResultFound:
        raise HTTPNotFound()
    if not has_permission(request, PERM_PARTICIPATE_IN_PROJECT, project):
        raise HTTPForbidden()
    if form is None:
        form = make_add_issue_form(project, session)
    can_see_priv = has_permission(
        request, PERM_SEE_PRIVATE_TIMING_INFO, project)
    can_manage_project = has_permission(request, PERM_MANAGE_PROJECT, project)
    return {'api': TemplateAPI(request, _(u'Add issue')),
            'project': project,
            'form': form,
            'can_see_private_time_info': can_see_priv,
            'can_manage_project': can_manage_project}
Пример #19
0
def update(request):
    project_name = request.matchdict['project_name']
    issue_ref = int(request.matchdict['issue_ref'])
    session = DBSession()
    try:
        project = session.query(Project).filter_by(name=project_name).one()
    except NoResultFound:
        raise HTTPNotFound()
    if not has_permission(request, PERM_PARTICIPATE_IN_PROJECT, project):
        raise HTTPForbidden()
    try:
        issue = session.query(Issue).filter_by(
            project_id=project.id, ref=issue_ref).one()
    except NoResultFound:
        raise HTTPNotFound()

    # FIXME: move logic outside so that it can be more easily tested.
    form = make_add_change_form(project, session, request.POST)
    if not form.validate():
        return view(request, form)
    now = datetime.utcnow()
    userid = request.user.id
    changes = {}
    for attr in (
        'title', 'status', 'assignee', 'deadline', 'priority', 'kind',
        'time_estimated', 'time_billed'):
        old_v = getattr(issue, attr)
        new_v = getattr(form, attr).data
        if old_v != new_v:
            changes[attr] = (old_v, new_v)
            setattr(issue, attr, new_v)
    if form.time_spent_real.data and \
            has_permission(request, PERM_SEE_PRIVATE_TIMING_INFO, project):
        changes['time_spent_real'] = (None, form.time_spent_real.data)
    if form.time_spent_public.data:
        changes['time_spent_public'] = (None, form.time_spent_public.data)

    if not changes and not form.text.data:
        error = _(u'You did not provide any comment or update.')
        form.errors['form'] = [error]
        return view(request, form)

    if form.status.data == ISSUE_STATUS_OPEN and \
            issue.status != ISSUE_STATUS_OPEN:
        change_type = CHANGE_TYPE_REOPENING
    elif form.status.data == ISSUE_STATUS_CLOSED:
        change_type = CHANGE_TYPE_CLOSING
    else:
        change_type = CHANGE_TYPE_UPDATE
    change = Change(project_id=project.id,
                    issue_id=issue.id,
                    type=change_type,
                    author=userid,
                    date=now,
                    text=form.text.data,
                    text_renderer=form.text_renderer.data,
                    changes=changes)
    if 'time_spent_real' in changes:
        change.time_spent_real = form.time_spent_real.data
    if 'time_spent_public' in changes:
        change.time_spent_public = form.time_spent_public.data
    session.add(change)
    route_args = {'project_name': project_name,
                  'issue_ref': issue.ref,
                  '_query': {'issue_updated': 1},
                  '_anchor': 'issue_updated'}
    url = request.route_url('issue_view', **route_args)
    return HTTPSeeOther(location=url)
Пример #20
0
def control_panel(request):
    if not request.user.is_admin:
        raise HTTPForbidden()
    return {'api': TemplateAPI(request, _(u'Control panel'))}