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/', 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//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)