184 lines
5.3 KiB
Python
184 lines
5.3 KiB
Python
|
import logging
|
||
|
import stripe
|
||
|
|
||
|
from flask import request
|
||
|
from flask.ext.restful import abort
|
||
|
|
||
|
from endpoints.api import resource, nickname, ApiResource, validate_json_request, request_error
|
||
|
from endpoints.api.team import team_view
|
||
|
from auth.permissions import (AdministerOrganizationPermission, OrganizationMemberPermission,
|
||
|
CreateRepositoryPermission)
|
||
|
from auth.auth_context import get_authenticated_user
|
||
|
from data import model
|
||
|
from data.plans import get_plan
|
||
|
from util.gravatar import compute_hash
|
||
|
|
||
|
|
||
|
logger = logging.getLogger(__name__)
|
||
|
|
||
|
|
||
|
|
||
|
def org_view(o, teams):
|
||
|
admin_org = AdministerOrganizationPermission(o.username)
|
||
|
is_admin = admin_org.can()
|
||
|
view = {
|
||
|
'name': o.username,
|
||
|
'email': o.email if is_admin else '',
|
||
|
'gravatar': compute_hash(o.email),
|
||
|
'teams': {t.name : team_view(o.username, t) for t in teams},
|
||
|
'is_admin': is_admin
|
||
|
}
|
||
|
|
||
|
if is_admin:
|
||
|
view['invoice_email'] = o.invoice_email
|
||
|
|
||
|
return view
|
||
|
|
||
|
|
||
|
@resource('/v1/organization/', methods=['POST'])
|
||
|
class OrganizationList(ApiResource):
|
||
|
""" Resource for creating organizations. """
|
||
|
schemas = {
|
||
|
'NewOrg': {
|
||
|
'id': 'NewOrg',
|
||
|
'type': 'object',
|
||
|
'description': 'Description of a new organization.',
|
||
|
'required': True,
|
||
|
'properties': {
|
||
|
'name': {
|
||
|
'type': 'string',
|
||
|
'description': 'Organization username',
|
||
|
'required': True,
|
||
|
},
|
||
|
'email': {
|
||
|
'type': 'string',
|
||
|
'description': 'Organization contact email',
|
||
|
'required': True,
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
}
|
||
|
|
||
|
@nickname('createOrganization')
|
||
|
@validate_json_request('NewOrg')
|
||
|
def post(self):
|
||
|
""" Create a new organization. """
|
||
|
org_data = request.get_json()
|
||
|
existing = None
|
||
|
|
||
|
try:
|
||
|
existing = model.get_organization(org_data['name'])
|
||
|
except model.InvalidOrganizationException:
|
||
|
pass
|
||
|
|
||
|
if not existing:
|
||
|
try:
|
||
|
existing = model.get_user(org_data['name'])
|
||
|
except model.InvalidUserException:
|
||
|
pass
|
||
|
|
||
|
if existing:
|
||
|
msg = 'A user or organization with this name already exists'
|
||
|
return request_error(message=msg)
|
||
|
|
||
|
try:
|
||
|
model.create_organization(org_data['name'], org_data['email'], get_authenticated_user())
|
||
|
return 'Created', 201
|
||
|
except model.DataModelException as ex:
|
||
|
return request_error(exception=ex)
|
||
|
|
||
|
|
||
|
@resource('/v1/organization/<orgname>', methods=['GET'])
|
||
|
class Organization(ApiResource):
|
||
|
""" Resource for managing organizations. """
|
||
|
schemas = {
|
||
|
'UpdateOrg': {
|
||
|
'id': 'UpdateOrg',
|
||
|
'type': 'object',
|
||
|
'description': 'Description of updates for an existing organization',
|
||
|
'required': True,
|
||
|
'properties': {
|
||
|
'email': {
|
||
|
'type': 'string',
|
||
|
'description': 'Organization contact email',
|
||
|
},
|
||
|
'invoice_email': {
|
||
|
'type': 'boolean',
|
||
|
'description': 'Whether the organization desires to receive emails for invoices',
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
}
|
||
|
@nickname('getOrganization')
|
||
|
def get(self, orgname):
|
||
|
""" Get the details for the specified organization """
|
||
|
permission = OrganizationMemberPermission(orgname)
|
||
|
if permission.can():
|
||
|
try:
|
||
|
org = model.get_organization(orgname)
|
||
|
except model.InvalidOrganizationException:
|
||
|
abort(404)
|
||
|
|
||
|
teams = model.get_teams_within_org(org)
|
||
|
return org_view(org, teams)
|
||
|
|
||
|
abort(403)
|
||
|
|
||
|
# @org_api_call('change_user_details')
|
||
|
@nickname('changeOrganizationDetails')
|
||
|
@validate_json_request('UpdateOrg')
|
||
|
def put(self, orgname):
|
||
|
""" Change the details for the specified organization. """
|
||
|
try:
|
||
|
org = model.get_organization(orgname)
|
||
|
except model.InvalidOrganizationException:
|
||
|
abort(404)
|
||
|
|
||
|
org_data = request.get_json()
|
||
|
if 'invoice_email' in org_data:
|
||
|
logger.debug('Changing invoice_email for organization: %s', org.username)
|
||
|
model.change_invoice_email(org, org_data['invoice_email'])
|
||
|
|
||
|
if 'email' in org_data and org_data['email'] != org.email:
|
||
|
new_email = org_data['email']
|
||
|
if model.find_user_by_email(new_email):
|
||
|
return request_error(message='E-mail address already used')
|
||
|
|
||
|
logger.debug('Changing email address for organization: %s', org.username)
|
||
|
model.update_email(org, new_email)
|
||
|
|
||
|
teams = model.get_teams_within_org(org)
|
||
|
return org_view(org, teams)
|
||
|
|
||
|
|
||
|
@resource('/v1/organization/<orgname>/private')
|
||
|
class OrgPrivateRepositories(ApiResource):
|
||
|
""" Custom verb to compute whether additional private repositories are available. """
|
||
|
# @org_api_call('get_user_private_allowed')
|
||
|
@nickname('getOrganizationPrivateAllowed')
|
||
|
def get(self, orgname):
|
||
|
permission = CreateRepositoryPermission(orgname)
|
||
|
if permission.can():
|
||
|
organization = model.get_organization(orgname)
|
||
|
private_repos = model.get_private_repo_count(organization.username)
|
||
|
data = {
|
||
|
'privateAllowed': False
|
||
|
}
|
||
|
|
||
|
if organization.stripe_id:
|
||
|
cus = stripe.Customer.retrieve(organization.stripe_id)
|
||
|
if cus.subscription:
|
||
|
repos_allowed = 0
|
||
|
plan = get_plan(cus.subscription.plan.id)
|
||
|
if plan:
|
||
|
repos_allowed = plan['privateRepos']
|
||
|
|
||
|
data['privateAllowed'] = (private_repos < repos_allowed)
|
||
|
|
||
|
|
||
|
if AdministerOrganizationPermission(orgname).can():
|
||
|
data['privateCount'] = private_repos
|
||
|
|
||
|
return data
|
||
|
|
||
|
abort(403)
|