Work in progress: Require invite acceptance to join an org

This commit is contained in:
Joseph Schorr 2014-08-15 17:47:43 -04:00
parent f6f857eec2
commit 56d7a3524d
9 changed files with 157 additions and 13 deletions

View file

@ -1,12 +1,32 @@
from flask import request
from endpoints.api import (resource, nickname, ApiResource, validate_json_request, request_error,
log_action, Unauthorized, NotFound, internal_only, require_scope)
log_action, Unauthorized, NotFound, internal_only, require_scope,
query_param, truthy_bool, parse_args)
from auth.permissions import AdministerOrganizationPermission, ViewTeamPermission
from auth.auth_context import get_authenticated_user
from auth import scopes
from data import model
from util.useremails import send_org_invite_email
def add_or_invite_to_team(team, user=None, email=None, adder=None):
invite = model.add_or_invite_to_team(team, user, email, adder)
if not invite:
# User was added to the team directly.
return
orgname = team.organization.username
if user:
model.create_notification('org_team_invite', user, metadata = {
'code': invite.invite_token,
'adder': adder,
'org': orgname,
'team': team.name
})
send_org_invite_email(user.username if user else email, user.email if user else email,
orgname, team.name, adder, invite.invite_token)
return invite
def team_view(orgname, team):
view_permission = ViewTeamPermission(orgname, team.name)
@ -19,14 +39,26 @@ def team_view(orgname, team):
'role': role
}
def member_view(member):
def member_view(member, invited=False):
return {
'name': member.username,
'kind': 'user',
'is_robot': member.robot,
'invited': invited,
}
def invite_view(invite):
if invite.user:
return member_view(invite.user, invited=True)
else:
return {
'email': invite.email,
'kind': 'invite',
'invited': True
}
@resource('/v1/organization/<orgname>/team/<teamname>')
@internal_only
class OrganizationTeam(ApiResource):
@ -114,8 +146,10 @@ class OrganizationTeam(ApiResource):
@internal_only
class TeamMemberList(ApiResource):
""" Resource for managing the list of members for a team. """
@parse_args
@query_param('includePending', 'Whether to include pending members', type=truthy_bool, default=False)
@nickname('getOrganizationTeamMembers')
def get(self, orgname, teamname):
def get(self, args, orgname, teamname):
""" Retrieve the list of members for the specified team. """
view_permission = ViewTeamPermission(orgname, teamname)
edit_permission = AdministerOrganizationPermission(orgname)
@ -128,11 +162,17 @@ class TeamMemberList(ApiResource):
raise NotFound()
members = model.get_organization_team_members(team.id)
return {
data = {
'members': {m.username : member_view(m) for m in members},
'can_edit': edit_permission.can()
}
if args['includePending'] and edit_permission.can():
invites = model.get_organization_team_member_invites(team.id)
data['pending'] = [invite_view(i) for i in invites]
return data
raise Unauthorized()
@ -142,7 +182,7 @@ class TeamMember(ApiResource):
@require_scope(scopes.ORG_ADMIN)
@nickname('updateOrganizationTeamMember')
def put(self, orgname, teamname, membername):
""" Add a member to an existing team. """
""" Adds or invites a member to an existing team. """
permission = AdministerOrganizationPermission(orgname)
if permission.can():
team = None
@ -159,10 +199,19 @@ class TeamMember(ApiResource):
if not user:
raise request_error(message='Unknown user')
# Add the user to the team.
model.add_user_to_team(user, team)
log_action('org_add_team_member', orgname, {'member': membername, 'team': teamname})
return member_view(user)
# Add or invite the user to the team.
adder = None
if get_authenticated_user():
adder = get_authenticated_user().username
invite = add_or_invite_to_team(team, user=user, adder=adder)
if not invite:
log_action('org_add_team_member', orgname, {'member': membername, 'team': teamname})
return member_view(user, invited=False)
# User was invited.
log_action('org_invite_team_member', orgname, {'member': membername, 'team': teamname})
return member_view(user, invited=True)
raise Unauthorized()