class Sightings(Resource): """ Manipulations with Sightings. """ @api.parameters(PaginationParameters()) @api.response(schemas.BaseSightingSchema(many=True)) def get(self, args): """ List of Sighting. Returns a list of Sighting starting from ``offset`` limited by ``limit`` parameter. """ return Sighting.query.offset(args['offset']).limit(args['limit']) @api.login_required(oauth_scopes=['sightings:write']) @api.parameters(parameters.CreateSightingParameters()) @api.response(schemas.DetailedSightingSchema()) @api.response(code=HTTPStatus.CONFLICT) def post(self, args): """ Create a new instance of Sighting. """ context = api.commit_or_abort( db.session, default_error_message='Failed to create a new Sighting') with context: sighting = Sighting(**args) db.session.add(sighting) return sighting
class Users(Resource): """ Manipulations with users. """ @api.login_required(oauth_scopes=['users:read']) @api.permission_required(permissions.AdminRolePermission()) @api.parameters(PaginationParameters()) @api.response(schemas.BaseUserSchema(many=True)) def get(self, args): """ List of users. Returns a list of users starting from ``offset`` limited by ``limit`` parameter. """ #return User.query.offset(args['offset']).limit(args['limit']) return User.objects.skip(args['offset']).limit(args['limit']) @api.parameters(parameters.AddUserParameters()) @api.response(schemas.DetailedUserSchema()) @api.response(code=HTTPStatus.FORBIDDEN) @api.response(code=HTTPStatus.CONFLICT) @api.doc(id='create_user') def post(self, args): """ Create a new user. """ with api.commit_or_abort( default_error_message="Failed to create a new user."): new_user = User(**args) new_user.save() #db.session.add(new_user) return new_user
def paginate(self, parameters=None, locations=None): """ Endpoint parameters registration decorator special for pagination. If ``parameters`` is not provided default PaginationParameters will be used. Also, any custom Parameters can be used, but it needs to have ``limit`` and ``offset`` fields. """ if not parameters: # Use default parameters if None specified from app.extensions.api.parameters import PaginationParameters parameters = PaginationParameters() if not all(mandatory in parameters.declared_fields for mandatory in ('limit', 'offset')): raise AttributeError( '`limit` and `offset` fields must be in Parameter passed to `paginate()`' ) def decorator(func): @wraps(func) def wrapper(self_, parameters_args, *args, **kwargs): queryset = func(self_, parameters_args, *args, **kwargs) total_count = queryset.count() return (queryset.offset(parameters_args['offset']).limit( parameters_args['limit']), HTTPStatus.OK, { 'X-Total-Count': total_count }) return self.parameters(parameters, locations)(wrapper) return decorator
class Organizations(Resource): """ Manipulations with Organizations. """ @api.parameters(PaginationParameters()) @api.response(schemas.BaseOrganizationSchema(many=True)) def get(self, args): """ List of Organization. Returns a list of Organization starting from ``offset`` limited by ``limit`` parameter. """ return Organization.query.offset(args['offset']).limit(args['limit']) @api.login_required(oauth_scopes=['organizations:write']) @api.parameters(parameters.CreateOrganizationParameters()) @api.response(schemas.DetailedOrganizationSchema()) @api.response(code=HTTPStatus.CONFLICT) def post(self, args): """ Create a new instance of Organization. """ context = api.commit_or_abort( db.session, default_error_message='Failed to create a new Organization') with context: organization = Organization(**args) db.session.add(organization) return organization
class Users(Resource): """ Manipulations with users. """ @api.login_required(oauth_scopes=['users:read']) @api.permission_required(permissions.AdminRolePermission()) @api.parameters(PaginationParameters()) @api.response(schemas.BaseUserSchema(many=True)) def get(self, args): """ List of users. Returns a list of users starting from ``offset`` limited by ``limit`` parameter. """ return User.query.offset(args['offset']).limit(args['limit']) @api.parameters(parameters.AddUserParameters()) @api.response(schemas.DetailedUserSchema()) @api.response(code=http_exceptions.Forbidden.code) @api.response(code=http_exceptions.Conflict.code) def post(self, args): """ Create a new user. """ with api.commit_or_abort( db.session, default_error_message="Failed to create a new user."): new_user = User(**args) db.session.add(new_user) return new_user
class Assets(Resource): """ Manipulations with Assets. """ @api.login_required(oauth_scopes=['assets:read']) @api.permission_required(permissions.AdminRolePermission()) @api.response(schemas.BaseAssetSchema(many=True)) @api.parameters(PaginationParameters()) def get(self, args): """ List of Assets. Returns a list of Asset starting from ``offset`` limited by ``limit`` parameter. """ return Asset.query.offset(args['offset']).limit(args['limit']) @api.login_required(oauth_scopes=['assets:write']) @api.permission_required(permissions.AdminRolePermission()) @api.response(schemas.DetailedAssetSchema()) @api.response(code=HTTPStatus.CONFLICT) def post(self): """ Create a new instance of Asset. """ return process_file_upload()
class Teams(Resource): """ Manipulations with teams. """ @api_v1.login_required(scopes=['teams:read']) @api_v1.parameters(PaginationParameters()) @api_v1.response(schemas.BaseTeamSchema(many=True)) def get(self, args): """ List of teams. Returns a list of teams starting from ``offset`` limited by ``limit`` parameter. """ return Team.query.all()[args['offset']:args['offset'] + args['limit']] @api_v1.login_required(scopes=['teams:write']) @api_v1.parameters(parameters.CreateTeamParameters()) @api_v1.response(schemas.DetailedTeamSchema()) @api_v1.response(code=http_exceptions.Conflict.code) def post(self, args): """ Create a new team. """ team = Team(**args) # pylint: disable=no-member db.session.add(team) try: db.session.commit() except sqlalchemy.exc.IntegrityError: db.session.rollback() # TODO: handle errors better abort(code=http_exceptions.Conflict.code, message="Could not create a new team.") return team
class Teams(Resource): """ Manipulations with teams. """ @api.parameters(PaginationParameters()) @api.response(schemas.BaseTeamSchema(many=True)) def get(self, args): """ List of teams. Returns a list of teams starting from ``offset`` limited by ``limit`` parameter. """ return Team.query.offset(args['offset']).limit(args['limit']) @api.login_required(oauth_scopes=['teams:write']) @api.parameters(parameters.CreateTeamParameters()) @api.response(schemas.DetailedTeamSchema()) @api.response(code=HTTPStatus.CONFLICT) def post(self, args): """ Create a new team. """ with api.commit_or_abort( db.session, default_error_message="Failed to create a new team"): team = Team(**args) db.session.add(team) team_member = TeamMember(team=team, user=current_user, is_leader=True) db.session.add(team_member) return team
class TeamMembers(Resource): """ Manipulations with members of a specific team. """ @api.login_required(oauth_scopes=['teams:read']) @api.resolve_object_by_model(Team, 'team') @api.permission_required( permissions.OwnerRolePermission, kwargs_on_request=lambda kwargs: {'obj': kwargs['team']} ) @api.permission_required(permissions.OwnerRolePermission(partial=True)) @api.parameters(PaginationParameters()) @api.response(schemas.BaseTeamMemberSchema(many=True)) def get(self, args, team): """ Get team members by team ID. """ return team.members[args['offset']: args['offset'] + args['limit']] @api.login_required(oauth_scopes=['teams:write']) @api.resolve_object_by_model(Team, 'team') @api.permission_required( permissions.OwnerRolePermission, kwargs_on_request=lambda kwargs: {'obj': kwargs['team']} ) @api.permission_required(permissions.WriteAccessPermission()) @api.parameters(parameters.AddTeamMemberParameters()) @api.response(schemas.BaseTeamMemberSchema()) @api.response(code=http_exceptions.Conflict.code) def post(self, args, team): """ Add a new member to a team. """ try: user_id = args.pop('user_id') user = User.query.get(user_id) if user is None: abort( code=http_exceptions.NotFound.code, message="User with id %d does not exist" % user_id ) try: team_member = TeamMember(team=team, user=user, **args) except ValueError as exception: abort(code=http_exceptions.Conflict.code, message=str(exception)) db.session.add(team_member) try: db.session.commit() except sqlalchemy.exc.IntegrityError: abort( code=http_exceptions.Conflict.code, message="Could not update team details." ) finally: db.session.rollback() return team_member
class Payments(Resource): """ Manipulations with Payments. """ @api.parameters(PaginationParameters()) @api.response(schemas.BasePaymentSchema(many=True)) def get(self, args): """ List of Payment. Returns a list of Payment starting from ``offset`` limited by ``limit`` parameter. """ return Payment.query.offset(args['offset']).limit(args['limit']) @api.parameters(parameters.CreatePaymentParameters()) @api.response(schemas.DetailedPaymentSchema()) @api.response(code=HTTPStatus.CONFLICT) def post(self, args): """ Create a new instance of Payment. """ with api.commit_or_abort( db.session, default_error_message="Failed to create a new Payment"): payment = Payment(**args) db.session.add(payment) return payment
class AssetTransactions(Resource): """ Transactions of a given asset """ @api.parameters(PaginationParameters()) @api.response(TransactionSchema(many=True)) def get(self, args, asset_id): """ Get transactions of an asset with the id 'asset_id'. """ return blockchain.get_asset_transactions(asset_id=asset_id, offset=args['offset'], limit=args['limit'])
class Users(Resource): """ Manipulations with users. """ @api_v1.login_required(scopes=['users:read']) @api_v1.permission_required(permissions.AdminRolePermission()) @api_v1.parameters(PaginationParameters()) @api_v1.response(schemas.BaseUserSchema(many=True)) def get(self, args): """ List of users. Returns a list of users starting from ``offset`` limited by ``limit`` parameter. """ return User.query.all()[args['offset']: args['offset'] + args['limit']] @api_v1.parameters(parameters.AddUserParameters()) @api_v1.response(schemas.DetailedUserSchema()) @api_v1.response(code=http_exceptions.Forbidden.code) @api_v1.response(code=http_exceptions.Conflict.code) def post(self, args): """ Create a new user. """ # Check reCAPTCHA if necessary recaptcha_key = args.pop('recaptcha_key', None) captcha_is_valid = False if not recaptcha_key: no_captcha_permission = permissions.AdminRolePermission() if no_captcha_permission.check(): captcha_is_valid = True elif recaptcha_key == 'secret_key': captcha_is_valid = True if not captcha_is_valid: abort(code=http_exceptions.Forbidden.code, message="CAPTCHA key is incorrect.") new_user = User(**args) # pylint: disable=no-member db.session.add(new_user) try: db.session.commit() except sqlalchemy.exc.IntegrityError: db.session.rollback() # TODO: handle errors better abort(code=http_exceptions.Conflict.code, message="Could not create a new user.") return new_user
class Projects(Resource): """ Manipulations with Projects. """ @api.permission_required( permissions.ModuleAccessPermission, kwargs_on_request=lambda kwargs: { 'module': Project, 'action': AccessOperation.READ, }, ) @api.parameters(PaginationParameters()) @api.response(schemas.BaseProjectSchema(many=True)) def get(self, args): """ List of Project. Returns a list of Project starting from ``offset`` limited by ``limit`` parameter. """ return Project.query.offset(args['offset']).limit(args['limit']) @api.permission_required( permissions.ModuleAccessPermission, kwargs_on_request=lambda kwargs: { 'module': Project, 'action': AccessOperation.WRITE, }, ) @api.login_required(oauth_scopes=['projects:write']) @api.parameters(parameters.CreateProjectParameters()) @api.response(schemas.DetailedProjectSchema()) @api.response(code=HTTPStatus.CONFLICT) def post(self, args): """ Create a new instance of Project. """ context = api.commit_or_abort( db.session, default_error_message='Failed to create a new Project') args['owner_guid'] = current_user.guid project = Project(**args) # User who creates the project gets added to it project.add_user(current_user) with context: db.session.add(project) db.session.refresh(project) return project
class TeamMembers(Resource): """ Manipulations with members of a specific team. """ @api.permission_required( permissions.OwnerRolePermission, kwargs_on_request=lambda kwargs: {'obj': kwargs['team']} ) @api.permission_required(permissions.OwnerRolePermission(partial=True)) @api.parameters(PaginationParameters()) @api.response(schemas.BaseTeamMemberSchema(many=True)) def get(self, args, team): """ Get team members by team ID. """ return team.members.skip(args['offset']).limit(args['limit']) @api.login_required(oauth_scopes=['teams:write']) @api.permission_required( permissions.OwnerRolePermission, kwargs_on_request=lambda kwargs: {'obj': kwargs['team']} ) @api.permission_required(permissions.WriteAccessPermission()) @api.parameters(parameters.AddTeamMemberParameters()) @api.response(schemas.BaseTeamMemberSchema()) @api.response(code=HTTPStatus.CONFLICT) def post(self, args, team): """ Add a new member to a team. """ with api.commit_or_abort( default_error_message="Failed to update team details." ): user_id = args.pop('user_id') #user = User.query.get(user_id) user = User.objects(user_id=user_id).first() if user is None: abort( code=HTTPStatus.NOT_FOUND, message="User with id %d does not exist" % user_id ) team_member = TeamMember(team=team, user=user, **args) team_member.save() #db.session.add(team_member) return team_member
class OAuth2Clients(Resource): """ Manipulations with OAuth2 clients. """ # @api.parameters(parameters.ListOAuth2ClientsParameters()) @api.parameters(PaginationParameters()) @api.response(schemas.DetailedOAuth2ClientSchema(many=True)) def get(self, args): """ List of OAuth2 Clients. Returns a list of OAuth2 Clients starting from ``offset`` limited by ``limit`` parameter. """ oauth2_clients = OAuth2Client.query oauth2_clients = oauth2_clients.filter( OAuth2Client.user_guid == current_user.guid, OAuth2Client.level != OAuth2Client.ClientLevels.confidential, ) if oauth2_clients.count() == 0 and current_user.is_admin: default_scopes = list( api_v1.authorizations['oauth2_password']['scopes'].keys()) args_ = { 'default_scopes': default_scopes, } _generate_new_client(args_) return self.get() return oauth2_clients.offset(args['offset']).limit(args['limit']) @api.login_required(oauth_scopes=['auth:write']) @api.parameters(parameters.CreateOAuth2ClientParameters()) @api.response(schemas.DetailedOAuth2ClientSchema()) @api.response(code=HTTPStatus.FORBIDDEN) @api.response(code=HTTPStatus.CONFLICT) @api.doc(id='create_oauth_client') def post(self, args): """ Create a new OAuth2 Client. Essentially, OAuth2 Client is a ``guid`` and ``secret`` pair associated with a user. """ new_oauth2_client = _generate_new_client(args) return new_oauth2_client
class TeamMembers(Resource): """ Manipulations with members of a specific team. """ @api_v1.login_required(scopes=['teams:read']) @api_v1.permission_required(permissions.OwnerRolePermission(partial=True)) @api_v1.parameters(PaginationParameters()) @api_v1.response(schemas.BaseTeamMemberSchema(many=True)) def get(self, args, team_id): """ Get team members by team ID. """ team = Team.query.get_or_404(team_id) with permissions.OwnerRolePermission(obj=team): return team.members[args['offset']:args['offset'] + args['limit']] @api_v1.login_required(scopes=['teams:write']) @api_v1.permission_required(permissions.OwnerRolePermission(partial=True)) @api_v1.parameters(parameters.AddTeamMemberParameters()) @api_v1.response(code=http_exceptions.Conflict.code) def post(self, args, team_id): """ Add a new member to a team. """ team = Team.query.get_or_404(team_id) # pylint: disable=no-member with permissions.OwnerRolePermission(obj=team): with permissions.WriteAccessPermission(): user_id = args.pop('user_id') user = User.query.get(user_id) if user is None: abort(code=http_exceptions.NotFound.code, message="User with id %d does not exist" % user_id) team_member = TeamMember(team=team, user=user, **args) db.session.add(team_member) try: db.session.commit() except sqlalchemy.exc.IntegrityError: db.session.rollback() # TODO: handle errors better abort(code=http_exceptions.Conflict.code, message="Could not update team details.") return None
class Assets(Resource): """ Manipulations with Assets. """ @api.login_required(oauth_scopes=['assets:read']) @api.permission_required(permissions.AdminRolePermission()) @api.response(schemas.BaseAssetSchema(many=True)) @api.parameters(PaginationParameters()) def get(self, args): """ List of Assets. Returns a list of Asset starting from ``offset`` limited by ``limit`` parameter. """ return (Asset.query.order_by(Asset.guid).offset(args['offset']).limit( args['limit']))
class Teams(Resource): """ Manipulations with teams. """ @api.login_required(oauth_scopes=['teams:read']) @api.parameters(PaginationParameters()) @api.response(schemas.BaseTeamSchema(many=True)) def get(self, args): """ List of teams. Returns a list of teams starting from ``offset`` limited by ``limit`` parameter. """ return Team.query.offset(args['offset']).limit(args['limit']) @api.login_required(oauth_scopes=['teams:write']) @api.parameters(parameters.CreateTeamParameters()) @api.response(schemas.DetailedTeamSchema()) @api.response(code=http_exceptions.Conflict.code) def post(self, args): """ Create a new team. """ try: try: team = Team(**args) except ValueError as exception: abort(code=http_exceptions.Conflict.code, message=str(exception)) db.session.add(team) try: db.session.commit() except sqlalchemy.exc.IntegrityError: abort(code=http_exceptions.Conflict.code, message="Could not create a new team.") finally: db.session.rollback() return team
class Submissions(Resource): """ Manipulations with Submissions. """ @api.permission_required( permissions.ModuleAccessPermission, kwargs_on_request=lambda kwargs: { 'module': Submission, 'action': AccessOperation.READ, }, ) @api.parameters(PaginationParameters()) @api.response(schemas.BaseSubmissionSchema(many=True)) def get(self, args): """ List of Submission. Returns a list of Submission starting from ``offset`` limited by ``limit`` parameter. """ return Submission.query.offset(args['offset']).limit(args['limit']) @api.permission_required( permissions.ModuleAccessPermission, kwargs_on_request=lambda kwargs: { 'module': Submission, 'action': AccessOperation.WRITE, }, ) @api.login_required(oauth_scopes=['submissions:write']) @api.parameters(parameters.CreateSubmissionParameters()) @api.response(schemas.DetailedSubmissionSchema()) @api.response(code=HTTPStatus.CONFLICT) def post(self, args): r""" Create a new instance of Submission. CommandLine: EMAIL='test@localhost' PASSWORD='******' TIMESTAMP=$(date '+%Y%m%d-%H%M%S%Z') curl \ -X POST \ -c cookie.jar \ -F email=${EMAIL} \ -F password=${PASSWORD} \ https://houston.dyn.wildme.io/api/v1/auth/sessions | jq curl \ -X GET \ -b cookie.jar \ https://houston.dyn.wildme.io/api/v1/users/me | jq curl \ -X POST \ -b cookie.jar \ -F description="This is a test submission (via CURL), please ignore" \ https://houston.dyn.wildme.io/api/v1/submissions/ | jq """ context = api.commit_or_abort( db.session, default_error_message='Failed to create a new Submission') with context: args['owner_guid'] = current_user.guid submission = Submission(**args) db.session.add(submission) repo, project = submission.ensure_repository() return submission