Пример #1
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}
Пример #2
0
def home(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_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.id).filter_by(project_id=project.id).\
        filter(Issue.status!=ISSUE_STATUS_CLOSED)
    n_assigned = issues.filter_by(assignee=request.user.id).count()
    n_watching = 0  # FIXME
    n_not_assigned = issues.filter_by(assignee=None).count()
    search_form = make_simplified_search_form(project, session)
    recent_activity = get_recent_activity(session, project, request)
    return {'api': TemplateAPI(request, project.title),
            'project': project,
            'can_participate': can_participate,
            'can_manage_project': can_manage_project,
            'n_assigned': n_assigned,
            'n_watching': n_watching,
            'n_not_assigned': n_not_assigned,
            'search_form': search_form,
            'recent_activity': recent_activity}
Пример #3
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}
Пример #4
0
Файл: auth.py Проект: dbaty/Yait
def has_permission(request, permission, context=None):
    """Return whether the current user is granted the given
    ``permission`` in this ``context``.

    Context must be a ``Project`` on which the permission is to be
    checked, or ``None`` if the permission is to be checked on the
    root level. In the latter case, only ``PERM_ADMIN_SITE`` may be
    checked (because other permissions do not make sense outside of
    projects).
    """
    if permission not in ALL_PERMS:
        raise ValueError(u'Unknown permission: "%s"' % permission)
    if not context and permission != PERM_ADMIN_SITE:
        raise ValueError(
            u'Wrong permission on a site: "%s"' % permission)
    if context and permission == PERM_ADMIN_SITE:
        raise ValueError(
            u'Wrong permission on a project: "%s"' % permission)

    cache_key_admin = '_user_is_site_admin'
    if getattr(request, cache_key_admin, None):
        return True

    if context is None:
        cache_key = '_user_site_perms'
    else:
        cache_key = '_user_perms_%s' % context.name
    if getattr(request, cache_key, None) is not None:
        return permission in getattr(request, cache_key)

    # Shortcuts for public projects and anonymous users
    if context is not None and context.public and \
            permission == PERM_VIEW_PROJECT:
        return True
    user_id = request.user.id
    if not user_id:
        return False

    session = DBSession()
    user_perms = ()
    if request.user.is_admin:
        user_perms = PERMISSIONS_FOR_ROLE[ROLE_SITE_ADMIN]
        setattr(request, cache_key_admin, True)
    elif context is not None:
        try:
            row = session.query(Role).filter_by(
                user_id=user_id, project_id=context.id).one()
        except NoResultFound:
            pass
        else:
            user_perms = PERMISSIONS_FOR_ROLE[row.role]

    setattr(request, cache_key, user_perms)
    return permission in user_perms
Пример #5
0
Файл: auth.py Проект: dbaty/Yait
def check_password(login, password):
    """Return the corresponding user if the given credentials are
    correct.
    """
    session = DBSession()
    try:
        user = session.query(User).filter_by(login=login).one()
    except NoResultFound:
        return None
    if not user.validate_password(password):
        return None
    return user
Пример #6
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)
Пример #7
0
def edit_user_form(request, form=None):
    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()
    if form is None:
        form = EditUserForm(obj=user)
    return {'api': TemplateAPI(request, user.fullname),
            'user': user,
            'form': form}
Пример #8
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)
Пример #9
0
 def all_projects(self):
     """Return all projects that the current user has access to."""
     user = self.request.user
     session = DBSession()
     if user.is_admin:
         projects = session.query(Project)
     elif user.id:
         public = session.query(Project).filter_by(public=True)
         has_role = session.query(Project).join(Role).filter(
             Project.id == Role.project_id)
         projects = has_role.union(public)
     else:
         projects = session.query(Project).filter_by(public=True)
     return projects.order_by(Project.title).all()
Пример #10
0
def configure_statuses_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()
    used = [s[0] for s in session.query(distinct(Issue.status)).\
        filter_by(project_id=project.id).all()]
    # FIXME: We may want to include default statuses in 'used' as well.
    return {'api': TemplateAPI(request, project.title),
            'project': project,
            'can_manage_project': True,
            'used': used}
Пример #11
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}
Пример #12
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)
Пример #13
0
def configure_form(request, form=None):
    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()
    if form is None:
        data = {'title': project.title,
                'public': project.public}
        form = make_edit_project_form(**data)
    return {'api': TemplateAPI(request, project.title),
            'project': project,
            'can_manage_project': True,
            'form': form}
Пример #14
0
def view(request, form=None):
    project_name = request.matchdict['project_name']
    try:
        issue_ref = int(request.matchdict['issue_ref'])
    except ValueError:
        # 'issue_ref' is not an integer. The route connected to this
        # view matched because no other route matched. This could be a
        # typo, for example: '/p/project-foo/confgure'.
        raise HTTPNotFound()
    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()
    try:
        issue = session.query(Issue).filter_by(
            project_id=project.id, ref=issue_ref).one()
    except NoResultFound:
        raise HTTPNotFound()
    if form is None:
        data = {'assignee': issue.assignee,
                'deadline': issue.deadline,
                'kind': issue.kind,
                'priority': issue.priority,
                'status': issue.status,
                'time_estimated': issue.time_estimated,
                'time_billed': issue.time_billed,
                'title': issue.title}
        form = make_add_change_form(project, session, **data)
    can_see_priv = has_permission(
        request, PERM_SEE_PRIVATE_TIMING_INFO, project)
    can_participate = has_permission(
        request, PERM_PARTICIPATE_IN_PROJECT, project)
    can_manage_project = has_permission(request, PERM_MANAGE_PROJECT, project)
    time_info = issue.get_time_info(include_private_info=can_see_priv)
    return {'api': TemplateAPI(request, issue.title),
            'project': project,
            'issue': issue,
            'time_info': time_info,
            'form': form,
            'can_participate': can_participate,
            'can_manage_project': can_manage_project,
            'can_see_private_time_info': can_see_priv}
Пример #15
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}
Пример #16
0
def recent_activity(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_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)
    recent_activity = get_recent_activity(session, project, request)
    return {'api': TemplateAPI(request, project.title),
            'project': project,
            'can_participate': can_participate,
            'can_manage_project': can_manage_project,
            'recent_activity': recent_activity}
Пример #17
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}
Пример #18
0
Файл: auth.py Проект: dbaty/Yait
def _get_user(request):
    """Return an instance of the ``User`` class if the user is logged
    in, or ``AnonymousUser`` otherwise.

    This function is never called explicitely by our code: it
    corresponds to the ``user`` reified property on requests (see
    ``app`` module where we call ``set_request_property()``).
    """
    user = None
    user_id = authenticated_userid(request)
    if user_id:
        session = DBSession()
        try:
            user = session.query(User).filter_by(id=user_id).one()
        except NoResultFound:
            user = None
    if user is None:
        return _AnonymousUser()
    return user
Пример #19
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)
Пример #20
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)}
Пример #21
0
def add(request):
    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()
    form = make_add_issue_form(project, session, request.POST)
    if not form.validate():
        return add_form(request, form)

    last_ref = session.execute(
        'SELECT MAX(ref) FROM issues '
        'WHERE project_id=%d' % project.id).fetchone()[0]
    if last_ref is None:
        last_ref = 0
    ref = last_ref + 1
    reporter = request.user.id
    now = datetime.utcnow()
    issue = Issue(project_id=project.id,
                  date_created=now,
                  date_edited=now,
                  reporter=reporter,
                  ref=ref)
    form.populate_obj(issue)
    session.add(issue)
    session.flush()
    change = Change(project_id=project.id,
                    issue_id=issue.id,
                    type=CHANGE_TYPE_OPENING,
                    author=reporter,
                    date=now,
                    changes={})
    form.populate_obj(change)
    session.add(change)
    route_args = {'project_name': project_name, 'issue_ref': issue.ref}
    url = request.route_url('issue_view', **route_args)
    return HTTPSeeOther(location=url)
Пример #22
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)
Пример #23
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)
Пример #24
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)
Пример #25
0
 def statuses(self):
     return dict(DBSession.query(Status.id, Status.label).all())
Пример #26
0
 def fullnames(self):
     return dict(DBSession.query(User.id, User.fullname).all())
Пример #27
0
 def validate_name(self, field):
     session = DBSession()
     if session.query(Project).filter_by(name=field.data).first():
         raise ValidationError(u'This name is not available.')