Add an endpoint for getting Projects related to a Team

This adds a subcontroller under teams, to expose the mapping of Teams to
Projects. It also provides methods to add and remove Projects from a
Team.

Change-Id: I064082001a2a2d3080c35a1e937d420fd473d96c
This commit is contained in:
Adam Coldrick 2019-03-07 16:31:51 +00:00 committed by Adam Coldrick
parent e7fe27fa22
commit 84518d0ccc
2 changed files with 112 additions and 1 deletions

View File

@ -29,6 +29,7 @@ from storyboard.api.v1 import wmodels
from storyboard.common import decorators
from storyboard.common import exception as exc
from storyboard.db.api import base as api_base
from storyboard.db.api import projects as projects_api
from storyboard.db.api import teams as teams_api
from storyboard.db.api import users as users_api
@ -96,6 +97,65 @@ class UsersSubcontroller(rest.RestController):
teams_api.team_delete_user(team_id, user_id)
class ProjectsSubcontroller(rest.RestController):
"""This controller should be used to list, add or remove projects from a Team.
"""
@decorators.db_exceptions
@secure(checks.guest)
@wsme_pecan.wsexpose([wmodels.Project], int)
def get(self, team_id):
"""Get projects related to a team.
Example::
curl https://my.example.org/api/v1/teams/1/projects
:param team_id: An ID of the team.
"""
team = teams_api.team_get(team_id)
if not team:
raise exc.NotFound(_("Team %s not found") % team_id)
return [wmodels.Project.from_db_model(project)
for project in team.projects]
@decorators.db_exceptions
@secure(checks.superuser)
@wsme_pecan.wsexpose(wmodels.Project, int, int)
def put(self, team_id, project_id):
"""Relate a project to a team.
Example::
TODO
:param team_id: An ID of the team.
:param project_id: An ID of the project.
"""
teams_api.team_add_project(team_id, project_id)
project = projects_api.project_get(project_id)
return wmodels.Project.from_db_model(project)
@decorators.db_exceptions
@secure(checks.superuser)
@wsme_pecan.wsexpose(None, int, int, status_code=204)
def delete(self, team_id, project_id):
"""Delete a user from a team.
Example::
TODO
:param team_id: An ID of the team.
:param user_id: An ID of the user.
"""
teams_api.team_delete_project(team_id, project_id)
class TeamsController(rest.RestController):
"""REST controller for Teams."""
@ -220,6 +280,7 @@ class TeamsController(rest.RestController):
raise exc.NotFound(_("Team %s not found") % team_id)
users = UsersSubcontroller()
projects = ProjectsSubcontroller()
def _is_int(self, s):
try:
@ -234,7 +295,7 @@ class TeamsController(rest.RestController):
# It's a request by a name or id
first_token = args[0]
if self._is_int(first_token):
if len(args) > 1 and args[1] == "users":
if len(args) > 1 and args[1] in ("projects", "users"):
# Route to users subcontroller
return super(TeamsController, self)._route(args, request)

View File

@ -19,6 +19,7 @@ from wsme.exc import ClientSideError
from storyboard._i18n import _
from storyboard.common import exception as exc
from storyboard.db.api import base as api_base
from storyboard.db.api import projects
from storyboard.db.api import users
from storyboard.db import models
@ -108,6 +109,55 @@ def team_delete_user(team_id, user_id):
return team
def team_add_project(team_id, project_id):
session = api_base.get_session()
with session.begin(subtransactions=True):
team = _entity_get(team_id, session)
if team is None:
raise exc.NotFound(_("Team %s not found") % team_id)
project = projects.project_get(project_id)
if project is None:
raise exc.NotFound(_("Project %s not found") % project_id)
if project_id in [p.id for p in team.projects]:
raise ClientSideError(_("The Project %(user_id)d is already "
"in Team %(team_id)d") %
{'project_id': project_id,
'team_id': team_id})
team.projects.append(project)
session.add(team)
return team
def team_delete_project(team_id, project_id):
session = api_base.get_session()
with session.begin(subtransactions=True):
team = _entity_get(team_id, session)
if team is None:
raise exc.NotFound(_("Team %s not found") % team_id)
project = projects.project_get(project_id)
if project is None:
raise exc.NotFound(_("Project %s not found") % project_id)
if project_id not in [p.id for p in team.projects]:
raise ClientSideError(_("The Project %(user_id)d is not in "
"Team %(team_id)d") %
{'project_id': project_id,
'team_id': team_id})
project_entry = [p for p in team.projects if p.id == project_id][0]
team.projects.remove(project_entry)
session.add(team)
return team
def team_delete(team_id):
team = team_get(team_id)