Add ability to enable, disable and view team syncing in UI and API
Also extracts out some common testing infrastructure to make testing APIs easier now using pytest
This commit is contained in:
parent
a17b637032
commit
8ea3977140
9 changed files with 298 additions and 27 deletions
|
@ -1,5 +1,7 @@
|
|||
""" Create, list and manage an organization's teams. """
|
||||
|
||||
import json
|
||||
|
||||
from functools import wraps
|
||||
|
||||
from flask import request
|
||||
|
@ -7,13 +9,16 @@ from flask import request
|
|||
import features
|
||||
|
||||
from app import avatar, authentication
|
||||
from auth.permissions import AdministerOrganizationPermission, ViewTeamPermission
|
||||
from auth.permissions import (AdministerOrganizationPermission, ViewTeamPermission,
|
||||
SuperUserPermission)
|
||||
|
||||
from auth.auth_context import get_authenticated_user
|
||||
from auth import scopes
|
||||
from data import model
|
||||
from endpoints.api import (resource, nickname, ApiResource, validate_json_request, request_error,
|
||||
log_action, internal_only, require_scope, path_param, query_param,
|
||||
truthy_bool, parse_args, require_user_admin, show_if, format_date)
|
||||
truthy_bool, parse_args, require_user_admin, show_if, format_date,
|
||||
verify_not_prod, require_fresh_login)
|
||||
from endpoints.exception import Unauthorized, NotFound, InvalidRequest
|
||||
from util.useremails import send_org_invite_email
|
||||
from util.names import parse_robot_username
|
||||
|
@ -200,6 +205,57 @@ class OrganizationTeam(ApiResource):
|
|||
raise Unauthorized()
|
||||
|
||||
|
||||
@resource('/v1/organization/<orgname>/team/<teamname>/syncing')
|
||||
@path_param('orgname', 'The name of the organization')
|
||||
@path_param('teamname', 'The name of the team')
|
||||
class OrganizationTeamSyncing(ApiResource):
|
||||
""" Resource for managing syncing of a team by a backing group. """
|
||||
@require_scope(scopes.ORG_ADMIN)
|
||||
@require_scope(scopes.SUPERUSER)
|
||||
@nickname('enableOrganizationTeamSync')
|
||||
@verify_not_prod
|
||||
@require_fresh_login
|
||||
def post(self, orgname, teamname):
|
||||
# User must be both the org admin AND a superuser.
|
||||
if SuperUserPermission().can() and AdministerOrganizationPermission(orgname).can():
|
||||
try:
|
||||
team = model.team.get_organization_team(orgname, teamname)
|
||||
except model.InvalidTeamException:
|
||||
raise NotFound()
|
||||
|
||||
config = request.get_json()
|
||||
|
||||
# Ensure that the specified config points to a valid group.
|
||||
status, err = authentication.check_group_lookup_args(config)
|
||||
if not status:
|
||||
raise InvalidRequest('Could not sync to group: %s' % err)
|
||||
|
||||
# Set the team's syncing config.
|
||||
model.team.set_team_syncing(team, authentication.federated_service, config)
|
||||
|
||||
return team_view(orgname, team)
|
||||
|
||||
raise Unauthorized()
|
||||
|
||||
@require_scope(scopes.ORG_ADMIN)
|
||||
@require_scope(scopes.SUPERUSER)
|
||||
@nickname('disableOrganizationTeamSync')
|
||||
@verify_not_prod
|
||||
@require_fresh_login
|
||||
def delete(self, orgname, teamname):
|
||||
# User must be both the org admin AND a superuser.
|
||||
if SuperUserPermission().can() and AdministerOrganizationPermission(orgname).can():
|
||||
try:
|
||||
team = model.team.get_organization_team(orgname, teamname)
|
||||
except model.InvalidTeamException:
|
||||
raise NotFound()
|
||||
|
||||
model.team.remove_team_syncing(orgname, teamname)
|
||||
return team_view(orgname, team)
|
||||
|
||||
raise Unauthorized()
|
||||
|
||||
|
||||
@resource('/v1/organization/<orgname>/team/<teamname>/members')
|
||||
@path_param('orgname', 'The name of the organization')
|
||||
@path_param('teamname', 'The name of the team')
|
||||
|
@ -231,16 +287,28 @@ class TeamMemberList(ApiResource):
|
|||
data = {
|
||||
'name': teamname,
|
||||
'members': [member_view(m) for m in members] + [invite_view(i) for i in invites],
|
||||
'can_edit': edit_permission.can()
|
||||
'can_edit': edit_permission.can(),
|
||||
}
|
||||
|
||||
sync_info = model.team.get_team_sync_information(orgname, teamname)
|
||||
if sync_info is not None:
|
||||
data['synced'] = {
|
||||
'last_updated': format_date(sync_info.last_updated),
|
||||
'service': sync_info.service.name,
|
||||
'config': sync_info.config,
|
||||
}
|
||||
if authentication.federated_service:
|
||||
if SuperUserPermission().can():
|
||||
data['can_sync'] = {
|
||||
'service': authentication.federated_service,
|
||||
}
|
||||
|
||||
data['can_sync'].update(authentication.service_metadata())
|
||||
|
||||
sync_info = model.team.get_team_sync_information(orgname, teamname)
|
||||
if sync_info is not None:
|
||||
data['synced'] = {
|
||||
'service': sync_info.service.name,
|
||||
}
|
||||
|
||||
if SuperUserPermission().can():
|
||||
data['synced'].update({
|
||||
'last_updated': format_date(sync_info.last_updated),
|
||||
'config': json.loads(sync_info.config),
|
||||
})
|
||||
|
||||
return data
|
||||
|
||||
|
|
Reference in a new issue