class Echo(Resource): """Echo.""" parser = api.parser() parser.add_argument('echo_str', required=True, type=str, help='string to echo') model = api.model( 'Echo', { 'success': fields.Boolean(description="success flag"), 'message': fields.String(description="echo output"), }) decorators = [limiter.limit("10/second")] @token_required @api.marshal_with(model) @api.doc(parser=parser, security='apikey') def get(self): echo_str = request.args.get('echo_str', None) if echo_str is None: return { 'success': False, 'message': "Missing echo_str parameter." }, 400 return {'success': True, 'message': "{}".format(echo_str)}
class Register(Resource): """Register.""" parser = api.parser() parser.add_argument('email', required=True, type=inputs.email(), help='email address', location='form') parser.add_argument('password', required=True, type=str, help='password', location='form') decorators = [limiter.limit("1/minute")] model = api.model( 'Register', { 'success': fields.Boolean(description="success flag"), 'message': fields.String(description="message"), 'email': fields.String(description="email"), 'id': fields.Integer(description="id"), }) @api.marshal_with(model) @api.doc(parser=parser) def post(self): data = self.parser.parse_args() data['verification_code'] = str(uuid.uuid4()) user = User(**data) db.session.add(user) try: db.session.commit() except Exception as e: current_app.logger.error(traceback.format_exc()) return { 'success': False, 'message': "Registration failed. Please contact support." }, 500 msg = Message("Verify your Pele API account", recipients=[user.email]) msg.body = "Use your verification code below to verify your Pele API " + \ "account at {}:\n\n{}".format(url_for('api_v0-1.doc', _external=True), data['verification_code']) mail.send(msg) user_dict = user.to_dict() user_dict['success'] = True user_dict[ 'message'] = "Verification email sent. Verify before using the API." return user_dict, 201
class MetadataById(Resource): """Get metadata by dataset ID.""" model = api.model('MetadataById', { 'success': fields.Boolean(description="success flag"), 'message': fields.String(description="message"), 'result': fields.Nested(METADATA_MODEL, allow_null=True, skip_none=True), }) decorators = [limiter.limit("10/second")] @token_required @api.marshal_with(model) @api.doc(security='apikey') def get(self, dataset_id): index = current_app.config["ES_INDEX"] result = current_app.es_util.query_id(index, dataset_id) return { 'success': True, 'result': result }
class OverlapsByIdTypeDataset(Resource): """Get all dataset results that overlap temporally and spatially with dataset ID of a certain type and dataset.""" model = api.model('OverlapsByIdTypeDataset', { 'success': fields.Boolean(description="success flag"), 'message': fields.String(description="message"), 'results': fields.List(fields.Raw), 'total': fields.Integer(description="total"), 'count': fields.Integer(description="count"), 'page_size': fields.Integer(description="page size"), 'offset': fields.Integer(description="starting offset (0 index)"), }) decorators = [limiter.limit("10/second")] @token_required @api.marshal_with(model) @api.doc(security='apikey') def get(self, dataset_id, type_name, dataset_name, ret_fields): terms = { 'dataset_type.keyword': type_name, 'dataset.keyword': dataset_name, } try: index = current_app.config["ES_INDEX"] page_size, offset = get_page_size_and_offset(request) total, docs = current_app.es_util.overlaps(index, dataset_id, terms, ret_fields, offset, page_size) return { 'success': True, 'total': total, 'count': len(docs), 'page_size': page_size, 'offset': offset, 'results': docs } except Exception as e: current_app.logger.error(traceback.format_exc()) return { 'success': False, 'message': str(e), }, 500
class Types(Resource): """GRQ dataset types.""" model = api.model('Type', { 'success': fields.Boolean(description="success flag"), 'message': fields.String(description="message"), 'types': fields.List(fields.String, description="types"), 'total': fields.Integer(description="total"), 'count': fields.Integer(description="count"), 'page_size': fields.Integer(description="page size"), 'offset': fields.Integer(description="starting offset (0 index)"), }) decorators = [limiter.limit("10/second")] @token_required @api.marshal_with(model) @api.doc(security='apikey') def get(self): try: index = current_app.config["ES_INDEX"] page_size, offset = get_page_size_and_offset(request) total, types = current_app.es_util.query_types(index, offset, page_size) return { 'success': True, 'total': total, 'count': len(types), 'page_size': page_size, 'offset': offset, 'types': types } except Exception as e: current_app.logger.error(traceback.format_exc()) return { 'success': False, 'message': str(e), }, 500
class Login(Resource): """Login.""" model = api.model( 'Login', { 'success': fields.Boolean(description="success flag"), 'message': fields.String(description="message"), 'token': fields.String(description="API token"), }) decorators = [limiter.limit("3/minute")] @auth.login_required @api.marshal_with(model) def post(self): user = g.user if not user: return {'message': 'Invalid credentials'}, 401 try: token = jwt.encode( { 'sub': user.email, 'iat': datetime.utcnow(), 'exp': datetime.utcnow() + timedelta( seconds=current_app.config['TOKEN_EXPIRATION_SECS']) }, current_app.config['SECRET_KEY']) except Exception as e: current_app.logger.error(traceback.format_exc()) return { 'success': False, 'message': "Login failed. Please contact support." }, 500 return {'success': True, 'token': token.decode('UTF-8')}
class Verify(Resource): """Verify.""" parser = api.parser() parser.add_argument('email', required=True, type=inputs.email(), help='email address', location='form') parser.add_argument('verification_code', required=True, type=str, help='verification code', location='form') model = api.model( 'Verify', { 'success': fields.Boolean(description="success flag"), 'message': fields.String(description="message"), }) decorators = [limiter.limit("3/minute")] @api.marshal_with(model) @api.doc(parser=parser) def post(self): data = self.parser.parse_args() user = User.verify(**data) if not user: return {'message': 'Invalid verification code'}, 401 return { 'success': True, 'message': 'Mahalo for verifying. You may now login to receive an API token.' }
class FieldsByTypeDataset(Resource): """Results by type name and dataset name.""" arg_parser = pele_ns.parser() arg_parser.add_argument('start_time', type=str, help="GTE to start_time field", required=False) arg_parser.add_argument('end_time', type=str, help="Less than to end_time field", required=False) arg_parser.add_argument('polygon', type=str, help="Bounding geo-polygon", required=False) json_parser = pele_ns.parser() json_parser.add_argument('start_time', location='json', help="GTE to start_time field", required=False) json_parser.add_argument('end_time', location='json', help="Less than to end_time field", required=False) json_parser.add_argument('polygon', location='json', type=list, help="Bounding geo-polygon", required=False) model = api.model('FieldsByTypeDataset', { 'success': fields.Boolean(description="success flag"), 'message': fields.String(description="message"), 'results': fields.List(fields.Raw), 'total': fields.Integer(description="total"), 'count': fields.Integer(description="count"), 'page_size': fields.Integer(description="page size"), 'offset': fields.Integer(description="starting offset (0 index)"), }) decorators = [limiter.limit("10/second")] @token_required @pele_ns.expect(arg_parser) @api.marshal_with(model) @api.doc(security='apikey') def get(self, type_name, dataset_name, ret_fields): start_time = request.args.get('start_time', None) end_time = request.args.get('end_time', None) polygon = request.args.get('polygon', None) if polygon is not None: try: polygon = parse_polygon(polygon) except Exception as e: return { 'success': False, 'message': str(e) }, 400 terms = { 'dataset_type.keyword': type_name, 'dataset.keyword': dataset_name, } try: index = current_app.config["ES_INDEX"] index = "{}_*_{}".format(index, dataset_name.lower()) page_size, offset = get_page_size_and_offset(request) total, docs = current_app.es_util.query_fields(index, terms, ret_fields, offset, page_size, start_time=start_time, end_time=end_time, polygon=polygon) return { 'success': True, 'total': total, 'count': len(docs), 'page_size': page_size, 'offset': offset, 'results': docs } except Exception as e: current_app.logger.error(traceback.format_exc()) return { 'success': False, 'message': str(e), }, 500 @token_required @pele_ns.expect(json_parser) @api.marshal_with(model) @api.doc(security='apikey') def post(self, type_name, dataset_name, ret_fields): start_time = request.args.get('start_time', None) end_time = request.args.get('end_time', None) polygon = request.args.get('polygon', None) terms = { 'dataset_type.keyword': type_name, 'dataset.keyword': dataset_name, } try: index = current_app.config["ES_INDEX"] index = "{}_*_{}".format(index, dataset_name.lower()) page_size, offset = get_page_size_and_offset(request) total, docs = current_app.es_util.query_fields(index, terms, ret_fields, offset, page_size, start_time=start_time, end_time=end_time, polygon=polygon) return { 'success': True, 'total': total, 'count': len(docs), 'page_size': page_size, 'offset': offset, 'results': docs } except Exception as e: current_app.logger.error(traceback.format_exc()) return { 'success': False, 'message': str(e), }, 500