Add team permissions support
This commit is contained in:
parent
97fa69a361
commit
1cd4fa8d9b
6 changed files with 120 additions and 39 deletions
|
@ -112,6 +112,10 @@ def create_team(name, org, team_role_name, description=''):
|
|||
description=description)
|
||||
|
||||
|
||||
def remove_team(name, org):
|
||||
# TODO: have code to remove the team, and all its repo permissions, etc.
|
||||
pass
|
||||
|
||||
def add_user_to_team(user, team):
|
||||
return TeamMember.create(user=user, team=team)
|
||||
|
||||
|
@ -124,29 +128,16 @@ def remove_user_from_team(user, team):
|
|||
raise InvalidTeamException('User does not belong to team.')
|
||||
|
||||
|
||||
def set_team_org_permission(team, org, team_role_name):
|
||||
new_role = TeamRole.get(TeamRole.name == tean_role_name)
|
||||
def get_team_org_role(team):
|
||||
return TeamRole.get(TeamRole.id == team.role.id)
|
||||
|
||||
def set_team_org_permission(team, team_role_name):
|
||||
new_role = TeamRole.get(TeamRole.name == team_role_name)
|
||||
team.role = new_role
|
||||
team.save()
|
||||
return team
|
||||
|
||||
|
||||
def set_team_org_permission(team, org, role_name):
|
||||
new_role = Role.get(Role.name == role_name)
|
||||
|
||||
# Fetch any existing permission for this user on the repo
|
||||
try:
|
||||
perm = TeamPermission.get(TeamPermission.team == team,
|
||||
TeamPermission.organization == org)
|
||||
perm.role = new_role
|
||||
perm.save()
|
||||
return perm
|
||||
except TeamPermission.DoesNotExist:
|
||||
new_perm = TeamPermission.create(team=team, organization=org,
|
||||
role=new_role)
|
||||
return new_perm
|
||||
|
||||
|
||||
def create_federated_user(username, email, service_name, service_id):
|
||||
new_user = create_user(username, None, email)
|
||||
new_user.verified = True
|
||||
|
|
|
@ -215,10 +215,10 @@ def get_matching_entities(prefix):
|
|||
users = model.get_matching_users(prefix, organization)
|
||||
|
||||
def team_view(team):
|
||||
return {
|
||||
result = {
|
||||
'name': team.name,
|
||||
'kind': 'team',
|
||||
'is_org_member': True,
|
||||
'is_org_member': True
|
||||
}
|
||||
|
||||
def user_view(user):
|
||||
|
@ -242,11 +242,13 @@ user_files = UserRequestFiles(app.config['AWS_ACCESS_KEY'],
|
|||
|
||||
def team_view(orgname, t):
|
||||
view_permission = ViewTeamPermission(orgname, t.name)
|
||||
role = model.get_team_org_role(t).name
|
||||
return {
|
||||
'id': t.id,
|
||||
'name': t.name,
|
||||
'description': t.description,
|
||||
'can_view': view_permission.can()
|
||||
'can_view': view_permission.can(),
|
||||
'role': role
|
||||
}
|
||||
|
||||
@app.route('/api/organization/<orgname>', methods=['GET'])
|
||||
|
@ -255,11 +257,12 @@ def get_organization(orgname):
|
|||
|
||||
def org_view(o, teams):
|
||||
admin_org = AdministerOrganizationPermission(orgname)
|
||||
is_admin = admin_org.can()
|
||||
return {
|
||||
'name': o.username,
|
||||
'gravatar': compute_hash(o.email),
|
||||
'teams': {t.name : team_view(orgname, t) for t in teams},
|
||||
'is_admin': admin_org.can()
|
||||
'is_admin': is_admin
|
||||
}
|
||||
|
||||
if current_user.is_anonymous():
|
||||
|
@ -313,13 +316,25 @@ def update_organization_team(orgname, teamname):
|
|||
if edit_permission.can():
|
||||
team = None
|
||||
|
||||
json = request.get_json()
|
||||
is_existing = False
|
||||
try:
|
||||
team = model.get_organization_team(orgname, teamname)
|
||||
is_existing = True
|
||||
except:
|
||||
abort(404)
|
||||
# Create the new team.
|
||||
description = json['description'] if 'description' in json else ''
|
||||
role = json['role'] if 'role' in json else 'member'
|
||||
|
||||
team = model.create_team(teamname, orgname, role, description)
|
||||
|
||||
if is_existing:
|
||||
if 'description' in json:
|
||||
team.description = json['description']
|
||||
team.save()
|
||||
if 'role' in json:
|
||||
team = model.set_team_org_permission(team, json['role'])
|
||||
|
||||
team.description = request.get_json()['description']
|
||||
team.save()
|
||||
return jsonify(team_view(orgname, team))
|
||||
|
||||
abort(403)
|
||||
|
|
|
@ -1391,8 +1391,25 @@ p.editable:hover i {
|
|||
}
|
||||
|
||||
.org-view .team-listing {
|
||||
margin: 10px;
|
||||
padding: 10px;
|
||||
padding: 4px;
|
||||
}
|
||||
|
||||
.org-view .header-col {
|
||||
color: #444;
|
||||
padding-left: 30px;
|
||||
}
|
||||
|
||||
.org-view .header-col dd {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.org-view .header-col .info-icon {
|
||||
float: none;
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.org-view .team-listing .btn-group {
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.org-view .team-listing i {
|
||||
|
|
|
@ -1076,7 +1076,14 @@ function NewRepoCtrl($scope, $location, $http, $timeout, UserService, Restangula
|
|||
});
|
||||
}
|
||||
|
||||
function OrgViewCtrl($scope, Restangular, $routeParams) {
|
||||
function OrgViewCtrl($rootScope, $scope, Restangular, $routeParams) {
|
||||
$('.info-icon').popover({
|
||||
'trigger': 'hover',
|
||||
'html': true
|
||||
});
|
||||
|
||||
$rootScope.title = 'Loading...';
|
||||
|
||||
var orgname = $routeParams.orgname;
|
||||
|
||||
var loadOrganization = function() {
|
||||
|
@ -1084,11 +1091,24 @@ function OrgViewCtrl($scope, Restangular, $routeParams) {
|
|||
getOrganization.get().then(function(resp) {
|
||||
$scope.organization = resp;
|
||||
$scope.loading = false;
|
||||
|
||||
$rootScope.title = orgname;
|
||||
}, function() {
|
||||
$scope.loading = false;
|
||||
});
|
||||
};
|
||||
|
||||
$scope.setRole = function(teamname, role) {
|
||||
$scope.organization.teams[teamname].role = role;
|
||||
|
||||
var updateTeam = Restangular.one(getRestUrl('organization', orgname, 'team', teamname));
|
||||
var data = $scope.organization.teams[teamname];
|
||||
updateTeam.customPUT(data).then(function(resp) {
|
||||
}, function() {
|
||||
$('#cannotChangeTeamModal').modal({});
|
||||
});
|
||||
};
|
||||
|
||||
loadOrganization();
|
||||
}
|
||||
|
||||
|
|
|
@ -9,16 +9,54 @@
|
|||
<div class="org-view container" ng-show="!loading && organization">
|
||||
<div class="organization-header" organization="organization"></div>
|
||||
|
||||
<div class="team-listing" ng-repeat="(name, team) in organization.teams">
|
||||
<div class="team-title">
|
||||
<i class="fa fa-group"></i>
|
||||
<span ng-show="team.can_view">
|
||||
<a href="/organization/{{ organization.name }}/teams/{{ team.name }}">{{ team.name }}</a>
|
||||
</span>
|
||||
<span ng-show="!team.can_view">
|
||||
{{ team.name }}
|
||||
</span>
|
||||
<div class="row visible-sm visible-md visible-lg">
|
||||
<div class="col-sm-8"></div>
|
||||
<div class="col-sm-4 header-col">
|
||||
Team Permissions
|
||||
<i class="info-icon fa fa-info-circle" data-placement="bottom" data-original-title="" title=""
|
||||
data-content="Global permissions for the team and its members<br><br><dl><dt>Member</dt><dd>Permissions are assigned on a per repository basis</dd><dt>Creator</dt><dd>A team can create its own repositories</dd><dt>Admin</dt><dd>A team has full control of the organization</dd></dl>"></i>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="team-listing" ng-repeat="(name, team) in organization.teams">
|
||||
<div class="row">
|
||||
<div class="col-sm-8">
|
||||
<div class="team-title">
|
||||
<i class="fa fa-group"></i>
|
||||
<span ng-show="team.can_view">
|
||||
<a href="/organization/{{ organization.name }}/teams/{{ team.name }}">{{ team.name }}</a>
|
||||
</span>
|
||||
<span ng-show="!team.can_view">
|
||||
{{ team.name }}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="team-description markdown-view" content="team.description" first-line-only="true"></div>
|
||||
</div>
|
||||
|
||||
<div class="btn-group btn-group-sm col-sm-4" ng-show="organization.is_admin">
|
||||
<button type="button" class="btn btn-default" ng-click="setRole(name, 'member')" ng-class="{admin: '', creator: '', member: 'active'}[team.role]">Member</button>
|
||||
<button type="button" class="btn btn-default" ng-click="setRole(name, 'creator')" ng-class="{admin: '', creator: 'active', member: ''}[team.role]">Creator</button>
|
||||
<button type="button" class="btn btn-primary" ng-click="setRole(name, 'admin')" ng-class="{admin: 'active', creator: '', member: ''}[team.role]">Admin</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="team-description markdown-view" content="team.description" first-line-only="true"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Modal message dialog -->
|
||||
<div class="modal fade" id="cannotChangeTeamModal">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
||||
<h4 class="modal-title">Cannot change team</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
You do not have permission to change properties on teams.
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
|
||||
</div>
|
||||
</div><!-- /.modal-content -->
|
||||
</div><!-- /.modal-dialog -->
|
||||
</div><!-- /.modal -->
|
||||
|
|
|
@ -66,7 +66,7 @@
|
|||
<div class="btn-group btn-group-sm">
|
||||
<button type="button" class="btn btn-default" ng-click="setRole(name, 'read', 'user')" ng-class="{read: 'active', write: '', admin: ''}[permission.role]">Read only</button>
|
||||
<button type="button" class="btn btn-default" ng-click="setRole(name, 'write', 'user')" ng-class="{read: '', write: 'active', admin: ''}[permission.role]">Write</button>
|
||||
<button type="button" class="btn btn-default" ng-click="setRole(name, 'admin', 'user')" ng-class="{read: '', write: '', admin: 'active'}[permission.role]">Admin</button>
|
||||
<button type="button" class="btn btn-primary" ng-click="setRole(name, 'admin', 'user')" ng-class="{read: '', write: '', admin: 'active'}[permission.role]">Admin</button>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
|
|
Reference in a new issue