def get_solely_admined_organizations(user_obj): """ Returns the organizations admined solely by the given user. """ orgs = ( User.select() .where(User.organization == True) .join(Team) .join(TeamRole) .where(TeamRole.name == "admin") .switch(Team) .join(TeamMember) .where(TeamMember.user == user_obj) .distinct() ) # Filter to organizations where the user is the sole admin. solely_admined = [] for org in orgs: admin_user_count = ( TeamMember.select() .join(Team) .join(TeamRole) .where(Team.organization == org, TeamRole.name == "admin") .switch(TeamMember) .join(User) .where(User.robot == False) .distinct() .count() ) if admin_user_count == 1: solely_admined.append(org) return solely_admined
def add_or_invite_to_team(inviter, team, user_obj=None, email=None, requires_invite=True): # If the user is a member of the organization, then we simply add the # user directly to the team. Otherwise, an invite is created for the user/email. # We return None if the user was directly added and the invite object if the user was invited. if user_obj and requires_invite: orgname = team.organization.username # If the user is part of the organization (or a robot), then no invite is required. if user_obj.robot: requires_invite = False if not user_obj.username.startswith(orgname + "+"): raise InvalidTeamMemberException( "Cannot add the specified robot to this team, " + "as it is not a member of the organization") else: query = (TeamMember.select().where( TeamMember.user == user_obj).join(Team).join(User).where( User.username == orgname, User.organization == True)) requires_invite = not any(query) # If we have a valid user and no invite is required, simply add the user to the team. if user_obj and not requires_invite: add_user_to_team(user_obj, team) return None email_address = email if not user_obj else None return TeamMemberInvite.create(user=user_obj, email=email_address, team=team, inviter=inviter)
def remove_organization_member(org, user_obj): org_admins = [u.username for u in __get_org_admin_users(org)] if len(org_admins) == 1 and user_obj.username in org_admins: raise DataModelException( "Cannot remove user as they are the only organization admin") with db_transaction(): # Find and remove the user from any repositories under the org. permissions = list( RepositoryPermission.select( RepositoryPermission.id).join(Repository).where( Repository.namespace_user == org, RepositoryPermission.user == user_obj)) if permissions: RepositoryPermission.delete().where( RepositoryPermission.id << permissions).execute() # Find and remove the user from any teams under the org. members = list( TeamMember.select(TeamMember.id).join(Team).where( Team.organization == org, TeamMember.user == user_obj)) if members: TeamMember.delete().where(TeamMember.id << members).execute()
def get_teams_within_org(organization, has_external_auth=False): """ Returns a AttrDict of team info (id, name, description), its role under the org, the number of repositories on which it has permission, and the number of members. """ query = Team.select().where( Team.organization == organization).join(TeamRole) def _team_view(team): return { "id": team.id, "name": team.name, "description": team.description, "role_name": Team.role.get_name(team.role_id), "repo_count": 0, "member_count": 0, "is_synced": False, } teams = {team.id: _team_view(team) for team in query} if not teams: # Just in case. Should ideally never happen. return [] # Add repository permissions count. permission_tuples = (RepositoryPermission.select( RepositoryPermission.team, fn.Count(RepositoryPermission.id)).where( RepositoryPermission.team << list(teams.keys())).group_by( RepositoryPermission.team).tuples()) for perm_tuple in permission_tuples: teams[perm_tuple[0]]["repo_count"] = perm_tuple[1] # Add the member count. members_tuples = (TeamMember.select(TeamMember.team, fn.Count( TeamMember.id)).where(TeamMember.team << list(teams.keys())).group_by( TeamMember.team).tuples()) for member_tuple in members_tuples: teams[member_tuple[0]]["member_count"] = member_tuple[1] # Add syncing information. if has_external_auth: sync_query = TeamSync.select( TeamSync.team).where(TeamSync.team << list(teams.keys())) for team_sync in sync_query: teams[team_sync.team_id]["is_synced"] = True return [AttrDict(team_info) for team_info in list(teams.values())]
def _user_teams(user, resource): changed = False p_exact_teams = resource["exact_teams"] p_add_teams = resource["add_teams"] p_remove_teams = resource["remove_teams"] team_names = p_exact_teams or p_add_teams or p_remove_teams if team_names is None: return False teams = [] for name in team_names: try: teams.append(Team.get(Team.name == name)) except model.InvalidTeamException: abort(400, message="Team '%s' does not exist" % name) teams = set(teams) current_teams = set(Team.select().join(TeamMember).join(User)).where( User.username == user.username) teams_to_add = teams - current_teams teams_to_remove = current_teams - teams if p_add_teams: teams_to_remove = [] elif p_remove_teams: teams_to_add = [] for team in teams_to_add: changed = True model.team.add_user_to_team(user, team) query = TeamMember.select().join(User).switch(TeamMember).join(Team).join( TeamRole) for team in teams_to_remove: changed = True found = list( query.where(User.username == user.username, Team.name == team.name)) found[0].delete_instance() return changed
def remove_user_from_team(org_name, team_name, username, removed_by_username): Org = User.alias() joined = TeamMember.select().join(User).switch(TeamMember).join(Team) with_role = joined.join(TeamRole) with_org = with_role.switch(Team).join(Org, on=(Org.id == Team.organization)) found = list( with_org.where(User.username == username, Org.username == org_name, Team.name == team_name)) if not found: raise DataModelException("User %s does not belong to team %s" % (username, team_name)) if username == removed_by_username: admin_team_query = __get_user_admin_teams(org_name, username) admin_team_names = {team.name for team in admin_team_query} if team_name in admin_team_names and len(admin_team_names) <= 1: msg = "User cannot remove themselves from their only admin team." raise DataModelException(msg) user_in_team = found[0] user_in_team.delete_instance()
def _is_team_member(team, user): return user.id in [ member.user_id for member in TeamMember.select().where(TeamMember.team == team) ]
def list_organization_members_by_teams(organization): query = (TeamMember.select( Team, User).join(Team).switch(TeamMember).join(User).where( Team.organization == organization)) return query
def fix_ident(ident): return str(ident).translate(None, "-/.") with open("outfile.dot", "w") as outfile: outfile.write("digraph relationships {\n") for repo in Repository.select(): ns = fix_ident(repo.namespace_user.username) outfile.write("%s_%s -> %s\n" % (ns, fix_ident(repo.name), ns)) teams_in_orgs = set() for member in TeamMember.select(): if "+" in member.user.username: continue org_name = fix_ident(member.team.organization.username) team_to_org = (member.team.name, member.team.organization.username) if not team_to_org in teams_in_orgs: teams_in_orgs.add(team_to_org) outfile.write("%s_%s -> %s\n" % (org_name, fix_ident(member.team.name), org_name)) team_name = fix_ident(member.team.name) outfile.write("%s -> %s_%s\n" % (fix_ident(member.user.username), org_name, team_name))