Merge branch 'koh'

Conflicts:
	auth/scopes.py
	requirements-nover.txt
	requirements.txt
	static/css/quay.css
	static/directives/namespace-selector.html
	static/js/app.js
	static/partials/manage-application.html
	templates/oauthorize.html
This commit is contained in:
Jimmy Zelinskie 2014-12-01 12:30:09 -08:00
commit f3259c862b
57 changed files with 537 additions and 141 deletions

View file

@ -2,18 +2,19 @@ import logging
from flask import request
from app import billing as stripe
from app import billing as stripe, avatar
from endpoints.api import (resource, nickname, ApiResource, validate_json_request, request_error,
related_user_resource, internal_only, Unauthorized, NotFound,
require_user_admin, log_action, show_if)
require_user_admin, log_action, show_if, path_param,
require_scope)
from endpoints.api.team import team_view
from endpoints.api.user import User, PrivateRepositories
from auth.permissions import (AdministerOrganizationPermission, OrganizationMemberPermission,
CreateRepositoryPermission)
from auth.auth_context import get_authenticated_user
from auth import scopes
from data import model
from data.billing import get_plan
from util.gravatar import compute_hash
import features
@ -28,7 +29,7 @@ def org_view(o, teams):
view = {
'name': o.username,
'email': o.email if is_admin else '',
'gravatar': compute_hash(o.email),
'avatar': avatar.compute_hash(o.email, name=o.username),
'teams': {t.name : team_view(o.username, t) for t in teams},
'is_admin': is_admin
}
@ -97,7 +98,7 @@ class OrganizationList(ApiResource):
@resource('/v1/organization/<orgname>')
@internal_only
@path_param('orgname', 'The name of the organization')
@related_user_resource(User)
class Organization(ApiResource):
""" Resource for managing organizations. """
@ -118,6 +119,8 @@ class Organization(ApiResource):
},
},
}
@require_scope(scopes.ORG_ADMIN)
@nickname('getOrganization')
def get(self, orgname):
""" Get the details for the specified organization """
@ -133,6 +136,7 @@ class Organization(ApiResource):
raise Unauthorized()
@require_scope(scopes.ORG_ADMIN)
@nickname('changeOrganizationDetails')
@validate_json_request('UpdateOrg')
def put(self, orgname):
@ -163,11 +167,14 @@ class Organization(ApiResource):
@resource('/v1/organization/<orgname>/private')
@path_param('orgname', 'The name of the organization')
@internal_only
@related_user_resource(PrivateRepositories)
@show_if(features.BILLING)
class OrgPrivateRepositories(ApiResource):
""" Custom verb to compute whether additional private repositories are available. """
@require_scope(scopes.ORG_ADMIN)
@nickname('getOrganizationPrivateAllowed')
def get(self, orgname):
""" Return whether or not this org is allowed to create new private repositories. """
@ -199,9 +206,11 @@ class OrgPrivateRepositories(ApiResource):
@resource('/v1/organization/<orgname>/members')
@internal_only
@path_param('orgname', 'The name of the organization')
class OrgnaizationMemberList(ApiResource):
""" Resource for listing the members of an organization. """
@require_scope(scopes.ORG_ADMIN)
@nickname('getOrganizationMembers')
def get(self, orgname):
""" List the members of the specified organization. """
@ -232,9 +241,12 @@ class OrgnaizationMemberList(ApiResource):
@resource('/v1/organization/<orgname>/members/<membername>')
@internal_only
@path_param('orgname', 'The name of the organization')
@path_param('membername', 'The username of the organization member')
class OrganizationMember(ApiResource):
""" Resource for managing individual organization members. """
@require_scope(scopes.ORG_ADMIN)
@nickname('getOrganizationMember')
def get(self, orgname, membername):
""" Get information on the specific orgnaization member. """
@ -265,8 +277,10 @@ class OrganizationMember(ApiResource):
@resource('/v1/app/<client_id>')
@path_param('client_id', 'The OAuth client ID')
class ApplicationInformation(ApiResource):
""" Resource that returns public information about a registered application. """
@nickname('getApplicationInformation')
def get(self, client_id):
""" Get information on the specified application. """
@ -274,14 +288,16 @@ class ApplicationInformation(ApiResource):
if not application:
raise NotFound()
org_hash = compute_hash(application.organization.email)
gravatar = compute_hash(application.gravatar_email) if application.gravatar_email else org_hash
org_hash = avatar.compute_hash(application.organization.email,
name=application.organization.username)
app_hash = (avatar.compute_hash(application.avatar_email, name=application.name) if
application.avatar_email else org_hash)
return {
'name': application.name,
'description': application.description,
'uri': application.application_uri,
'gravatar': gravatar,
'avatar': app_hash,
'organization': org_view(application.organization, [])
}
@ -297,12 +313,12 @@ def app_view(application):
'client_id': application.client_id,
'client_secret': application.client_secret if is_admin else None,
'redirect_uri': application.redirect_uri if is_admin else None,
'gravatar_email': application.gravatar_email if is_admin else None,
'avatar_email': application.avatar_email if is_admin else None,
}
@resource('/v1/organization/<orgname>/applications')
@internal_only
@path_param('orgname', 'The name of the organization')
class OrganizationApplications(ApiResource):
""" Resource for managing applications defined by an organizations. """
schemas = {
@ -330,15 +346,15 @@ class OrganizationApplications(ApiResource):
'type': 'string',
'description': 'The human-readable description for the application',
},
'gravatar_email': {
'avatar_email': {
'type': 'string',
'description': 'The e-mail address of the gravatar to use for the application',
'description': 'The e-mail address of the avatar to use for the application',
}
},
},
}
@require_scope(scopes.ORG_ADMIN)
@nickname('getOrganizationApplications')
def get(self, orgname):
""" List the applications for the specified organization """
@ -354,6 +370,7 @@ class OrganizationApplications(ApiResource):
raise Unauthorized()
@require_scope(scopes.ORG_ADMIN)
@nickname('createOrganizationApplication')
@validate_json_request('NewApp')
def post(self, orgname):
@ -371,7 +388,7 @@ class OrganizationApplications(ApiResource):
app_data.get('application_uri', ''),
app_data.get('redirect_uri', ''),
description = app_data.get('description', ''),
gravatar_email = app_data.get('gravatar_email', None),)
avatar_email = app_data.get('avatar_email', None),)
app_data.update({
@ -386,7 +403,8 @@ class OrganizationApplications(ApiResource):
@resource('/v1/organization/<orgname>/applications/<client_id>')
@internal_only
@path_param('orgname', 'The name of the organization')
@path_param('client_id', 'The OAuth client ID')
class OrganizationApplicationResource(ApiResource):
""" Resource for managing an application defined by an organizations. """
schemas = {
@ -416,14 +434,15 @@ class OrganizationApplicationResource(ApiResource):
'type': 'string',
'description': 'The human-readable description for the application',
},
'gravatar_email': {
'avatar_email': {
'type': 'string',
'description': 'The e-mail address of the gravatar to use for the application',
'description': 'The e-mail address of the avatar to use for the application',
}
},
},
}
@require_scope(scopes.ORG_ADMIN)
@nickname('getOrganizationApplication')
def get(self, orgname, client_id):
""" Retrieves the application with the specified client_id under the specified organization """
@ -442,6 +461,7 @@ class OrganizationApplicationResource(ApiResource):
raise Unauthorized()
@require_scope(scopes.ORG_ADMIN)
@nickname('updateOrganizationApplication')
@validate_json_request('UpdateApp')
def put(self, orgname, client_id):
@ -462,7 +482,7 @@ class OrganizationApplicationResource(ApiResource):
application.application_uri = app_data['application_uri']
application.redirect_uri = app_data['redirect_uri']
application.description = app_data.get('description', '')
application.gravatar_email = app_data.get('gravatar_email', None)
application.avatar_email = app_data.get('avatar_email', None)
application.save()
app_data.update({
@ -475,7 +495,7 @@ class OrganizationApplicationResource(ApiResource):
return app_view(application)
raise Unauthorized()
@require_scope(scopes.ORG_ADMIN)
@nickname('deleteOrganizationApplication')
def delete(self, orgname, client_id):
""" Deletes the application under this organization. """
@ -498,6 +518,8 @@ class OrganizationApplicationResource(ApiResource):
@resource('/v1/organization/<orgname>/applications/<client_id>/resetclientsecret')
@path_param('orgname', 'The name of the organization')
@path_param('client_id', 'The OAuth client ID')
@internal_only
class OrganizationApplicationResetClientSecret(ApiResource):
""" Custom verb for resetting the client secret of an application. """