def delete(self, trip_id: int, user: User = None): """ @api {DELETE} /api/v1/trips/trip_id Trip deletion @apiVersion 1.0.0 @apiName DeleteTrip @apiGroup Trips @apiSuccessExample {json} Success-Response: HTTP/1.1 200 OK {} @apiError (NotFound 404) {Object} NoSuchTrip Such trip doesn't exist @apiError (InternalServerError 500) {Object} InternalServerError """ try: db_instance = TripsDatabase() deleted_trip = db_instance.trip_delete(user.id, trip_id) db_instance.close_connection() if not deleted_trip: return response_404("NoSuchTrip", "Such trip doesn't exist") return jsonify({}) except Exception as e: print(e) return response_500()
def login(): """ @api {POST} /api/v1/token User login @apiVersion 1.0.0 @apiName UserLogin @apiGroup Authentication @apiParam {String} username User's username. @apiParam {String} password User's password. @apiSuccess {String} token User's jwt. @apiSuccess {Object} user_info User's information. @apiSuccess {String} user_info.username User's username @apiSuccess {String} user_info.email User's email @apiSuccessExample {json} Success-Response: HTTP/1.1 200 OK { "token": "eyJ0eXA...", "user_info": { "username": "******", "email": "*****@*****.**" } } @apiError (Unauthorized 401) {Object} InvalidLogin Username or password is incorrect. @apiError (InternalServerError 500) {Object} InternalServerError """ try: # tries to get the value if none provided returns an emtpy string username = request.json.get('username', '') password = request.json.get('password', '') db_instance = UserDatabase() user = db_instance.verify_user(username, password) db_instance.close_connection() if not user: return response_401('username or password incorrect') token_payload = { 'id': user.id, 'iat': datetime.datetime.now().astimezone(), 'exp': datetime.datetime.now().astimezone() + datetime.timedelta(days=30) } token = jwt.encode(token_payload, SECRET_KEY, algorithm='HS256') return jsonify({ 'token': token.decode('ascii'), 'user_info': user.user_info() }) except Exception as e: print(e) return response_500()
def get_trips_list(self, user): """ @api {GET} /api/v1/trips Trips List @apiVersion 1.0.0 @apiName TripsList @apiGroup Trips @apiSuccess {Object[]} trips List with trips @apiSuccess {Integer} trips.id Trip's id @apiSuccess {String} trips.name Trip's name @apiSuccess {Integer} trips.user_id Trip's user_id @apiSuccess {Integer} trips.max_trip_days Trip's max_trip_days @apiSuccess {Boolean} trips.is_guided Trip's is_guided @apiSuccess {Boolean} trips.in_group Trip's in_group @apiSuccess {Integer} trips.max_price Trip's max_price @apiSuccessExample {json} Success-Response: HTTP/1.1 200 OK { "trips": [ { "id": 1, "name": "Short Travel", "user_id": 1, "max_trip_days": 20, "is_guided": True, "in_group": False, "max_price": 10 000 }, { "id": 2, "name": "Dream Trip", "user_id": 1, "max_trip_days": 30, "is_guided": True, "in_group": True, "max_price": 200 000 } ] } @apiError (InternalServerError 500) {Object} InternalServerError """ try: db_instance = TripsDatabase() trips_list = db_instance.trips_list(user.id) db_instance.close_connection() return jsonify({ "trips": [trip.serialize() for trip in trips_list] }) except: return response_500()
def verify_token(): """ @api {POST} /api/v1/token/verify Token Verification @apiVersion 1.0.0 @apiName VerifyToken @apiGroup Authentication @apiParam {String} token User's token. @apiSuccess {Object} user_info User's information @apiSuccess {String} user_info.username User's username @apiSuccess {String} user_info.email User's email @apiSuccessExample {json} Success-Response: HTTP/1.1 200 OK { "user_info": { "username": "******", "email": "*****@*****.**" } } @apiError (Unauthorized 401 ) {Object} InvalidToken @apiError (Unauthorized 401 ) {Object} ExpiredToken @apiError (InternalServerError 500) {Object} InternalServerError """ try: # tries to get the value if none provided returns an emtpy string token = request.json.get('token', '') payload = jwt.decode(token, SECRET_KEY, verify=True) user_id = payload["id"] db_instance = UserDatabase() user = db_instance.get_user_by_id(user_id) db_instance.close_connection() if not user: return response_401('Please provide a valid token') return jsonify({'user_info': user.user_info()}) except jwt.ExpiredSignatureError: return response_401('ExpiredToken') except Exception as e: print(e) return response_500()
def get_trip_info(self, user, trip_id): """ @api {GET} /api/v1/trips/<trip_id> Trip information @apiVersion 1.0.0 @apiName TripInfo @apiGroup Trips @apiSuccess {Integer} id Trip's id @apiSuccess {String} name Trip's name @apiSuccess {Integer} user_id Trip's user_id @apiSuccess {Integer} max_trip_days Trip's max_trip_days @apiSuccess {Boolean} is_guided Trip's is_guided @apiSuccess {Boolean} in_group Trip's in_group @apiSuccess {Integer} max_price Trip's max_price @apiSuccessExample {json} Success-Response: HTTP/1.1 200 OK { "id": 1, "name": "Short Travel", "user_id": 1, "max_trip_days": 20, "is_guided": True, "in_group": False, "max_price": 10000 } @apiError (NotFound 404) {Object} NoSuchTrip @apiError (InternalServerError 500) {Object} InternalServerError """ try: db_instance = TripsDatabase() trip_info = db_instance.trip_info(user.id, trip_id) db_instance.close_connection() if not trip_info: return response_404("NoSuchTrip", "Such trip doesn't exist") return jsonify(trip_info.serialize()) except Exception as e: print(e) return response_500()
def get(self): """ @api {GET} /api/v1/types/ Get Attraction Types @apiVersion 1.0.0 @apiName AttractionTypes @apiGroup Attractions @apiSuccess {Object[]} attraction_types List with all attraction types @apiSuccess {Integer} attraction_types.type_id Attraction type id @apiSuccess {String} attraction_types.type_name Attraction type name @apiSuccessExample {json} Success-Response: HTTP/1.1 200 OK { "attraction_types": [ { "type_id": 1, "type_name": "temples" }, { "type_id": 2, "type_name": "shrines" } ] } @apiError (InternalServerError 500) {Object} InternalServerError """ try: db_instance = AttractionsDatabase() attraction_types_list = db_instance.get_attraction_types() db_instance.close_connection() return jsonify({"attraction_types": attraction_types_list}) except Exception as e: print(e) return response_500()
def get(self): """ @api {GET} /api/v1/cities Get Cities @apiVersion 1.0.0 @apiName GetCities @apiGroup Attractions @apiSuccess {Object[]} cities List with all cities @apiSuccess {Integer} city_id City id @apiSuccess {String} city_name City name @apiSuccessExample {json} Success-Response: HTTP/1.1 200 OK { "cities": [ { "city_id": 1, "city_name": "Tokyo" }, { "city_id": 2, "city_name": "Osaka" } ] } @apiError (InternalServerError 500) {Object} InternalServerError """ try: db_instance = AttractionsDatabase() cities_list = db_instance.get_cities() db_instance.close_connection() return jsonify({"cities": cities_list}) except Exception as e: print(e) return response_500()
def register(): """ @api {POST} /api/v1/users User registration @apiVersion 1.0.0 @apiName UserRegistration @apiGroup Authentication @apiParam {String{2..25}} username User's username. @apiParam {String{8..}} password User's password. @apiParam {String} email User's email. @apiSuccessExample {json} Success-Response: HTTP/1.1 200 OK {} @apiError (Bad Request 400) {Object} InvalidUsername Username should have at least 2 characters and maximum 25, it can contain any char except white space. @apiError (Bad Request 400) {Object} InvalidPassword Password should have at least 8 characters and can contain any char except white space. @apiError (Bad Request 400) {Object} UnavailableUsername Username is unavailable. @apiError (Bad Request 400) {Object} InvalidEmailFormat Email should have an "@" sign and a email domain name with a domain ending of at least 2 characters. @apiError (InternalServerError 500) {Object} InternalServerError """ try: # tries to get the value if none provided returns an emtpy string username = request.json.get('username', '') password = request.json.get('password', '') email = request.json.get('email', '') # checks that the passed values are valid if not re.match(r'^[\S]{2,25}$', username): return response_400('InvalidUsername', 'Ussername should have at least 2 characters and maximum 25, it can contain any char ' 'except white space.') if not re.match(r"^[\S]{8,}$", password): return response_400('InvalidPassword', 'Password should have at least 8 characters and can contain any char except ' 'white space.') if not email or not re.fullmatch(r'([\w\.\-]+)@([\w]+)\.([\w]+){2,}', email): return response_400('InvalidEmailFormat', 'Email should have an "@" sign and a email domain name with a domain ending of at' ' least 2 characters.') db_instance = UserDatabase() db_instance.create_user(username, email.lower(), password) db_instance.close_connection() welcome_email(email) return jsonify({}) except IntegrityError as e: return response_400('UnavailableUsername', 'Username is unavailable.') except Exception as e: print(e) return response_500()
def get(self): """ @api {GET} /api/v1/attractions Search Attractions @apiVersion 1.0.0 @apiName SearchAttractions @apiGroup Attractions @apiParam {String} text User input which will be checked against the attraction's name @apiParam {Integer} attraction_type_id Shows a specific category of attractions @apiParam {Integer} city_id Shows attractions in a city @apiParam {Integer} max_price Shows attractions up to a max price @apiSuccess {Object[]} attractions List with attractions @apiSuccess {String} attractions.id Attraction's id @apiSuccess {String} attractions.attraction_name Attraction's name @apiSuccess {String} attractions.description Attraction's description @apiSuccess {Integer} attractions.price Attraction's price @apiSuccess {String} attractions.web_link Attraction's web_link @apiSuccess {String} attractions.picture_url Attraction's picture_url @apiSuccess {Object} attractions.city Attraction's city dictionary @apiSuccess {Integer} city.id Attraction's city id @apiSuccess {String} city.name Attraction's city name @apiSuccessExample {json} Success-Response: # todo add proper url examples HTTP/1.1 200 OK { "attractions": [ { "id": 1, "attraction_name": "Fuji Mountain", "description": "Highest mountain in Japan.", "price": 200, "web_link": "", "picture_url": "", "city": { "id": 1, "name": "Tokyo" } }, { "id": 1, "attraction_name": "Osaka Tower", "description": "The tower was 160 meters (525 feet) high.", "price": 130, "web_link": "", "picture_url": "", "city": { "id": 2, "name": "Osaka" } } ] } @apiError (NotFound 404) {Object} NoSuchTrip Such trip doesn't exist. @apiError (InternalServerError 500) {Object} InternalServerError """ try: text = request.args.get('text', None) attraction_type_id = request.args.get('attraction_type_id', None) city_id = request.args.get('city_id', None) max_price = request.args.get('max_price', None) db_instance = AttractionsDatabase() attractions_list = db_instance.get_attractions( text, attraction_type_id, city_id, max_price) db_instance.close_connection() return jsonify( {"attractions": [e.serialize() for e in attractions_list]}) except Exception as e: print(e) return response_500()
def patch(self, trip_id, user: User = None): """ @api {PATCH} /api/v1/trips/trip_id Trip update @apiVersion 1.0.0 @apiName TripUpdate @apiGroup Trips @apiParam {String} [name] Trip's name @apiParam {Integer} [max_trip_days] Trip's max_trip_days @apiParam {Boolean} [is_guided] Trip's is_guided @apiParam {Boolean} [in_group] Trip's in_group @apiParam {Integer} [max_price] Trip's max_price @apiParam {Boolean} [finalised] If true is passed in the user will receive an offer. @apiSuccessExample {json} Success-Response: HTTP/1.1 200 OK {} @apiError (BadRequest 400) {Object} NoParameter Please provide a parameter. @apiError (BadRequest 400) {Object} InvalidName Name should have at least 2 characters and maximum 25. @apiError (BadRequest 400) {Object} InvalidDaysNumber Please provide valid max_trip_days value. @apiError (BadRequest 400) {Object} InvalidPriceNumber Please provide a valid max_price value. @apiError (NotFound 404) {Object} NoSuchTrip Such trip doesn't exist @apiError (InternalServerError 500) {Object} InternalServerError """ try: # finalised is a fictional value in my database. # if a trip is finalised then the user will get emails with matching offers to their trip from tourist # agencies. finalised = request.json.get("finalised", None) # send dummy email on trip finalised as an offer example if finalised: offer_email(user.email) return jsonify({}) changed_fields = {} for key in ["name", "is_guided", "max_trip_days", "in_group", "max_price"]: value = request.json.get(key, None) if value is not None: changed_fields[key] = value if len(changed_fields) == 0: return response_400("NoParameter", "Please provide a parameter") # checks that the passed values are valid if not re.match(r'^[\S\s]{2,25}$', changed_fields["name"]): return response_400('InvalidName', 'Name should have at least 2 characters and maximum 25.') if "max_trip_days" in changed_fields and int(changed_fields["max_trip_days"]) < 1 or int(changed_fields[ "max_trip_days"]) > 30: return response_400("InvalidDaysNumber", "Please provide valid max_trip_days value") if "max_price" in changed_fields and int(changed_fields["max_price"]) < 1 or int(changed_fields[ "max_price"]) > 1000000: return response_400("InvalidPriceNumber", "Please provide a valid max_price value") db_instance = TripsDatabase() updated_trip = db_instance.update_trip(trip_id, user.id, changed_fields) db_instance.close_connection() if not updated_trip: return response_404("NoSuchTrip", "Such trip doesn't exist") return jsonify({}) except Exception as e: print(e) return response_500()
def post(self, user: User = None): """ @api {POST} /api/v1/trips Trip creation @apiVersion 1.0.0 @apiName CreateTrip @apiGroup Trips @apiParam {String} name Trip's name @apiParam {Integer} max_trip_days Trip's max_trip_days @apiParam {Boolean} is_guided Trip's is_guided @apiParam {Boolean} in_group Trip's in_group @apiParam {Integer} max_price Trip's max_price @apiSuccess {Integer} trip_id The id of the created trip @apiSuccessExample {json} Success-Response: HTTP/1.1 200 OK { "id": 1, "name": "Short Travel", "user_id": 1, "max_trip_days": 20, "is_guided": True, "in_group": False, "max_price": 10000 } @apiError (BadRequest 400) {Object} InvalidName Name should have at least 2 characters and maximum 25. @apiError (BadRequest 400) {Object} InvalidDaysNumber Please provide valid max_trip_days value. @apiError (BadRequest 400) {Object} InvalidPriceNumber Please provide a valid max_price value. @apiError (BadRequest 400) {Object} InvalidDataEntry @apiError (BadRequest 400) {Object} ParameterError Please provide all the parameters @apiError (InternalServerError 500) {Object} InternalServerError """ try: name = request.json['name'] max_trip_days = int(request.json['max_trip_days']) is_guided = bool(request.json['is_guided']) in_group = bool(request.json['in_group']) max_price = int(request.json['max_price']) # checks that the passed values are valid if not re.match(r'^[\S\s]{2,25}$', name): return response_400('InvalidName', 'Name should have at least 2 characters and maximum 25.') if max_trip_days < 1 or max_trip_days > 30: return response_400("InvalidDaysNumber", "Please provide valid max_trip_days value.") if max_price < 1 or max_price > 1000000: return response_400("InvalidPriceNumber", "Please provide a valid max_price value.") db_instance = TripsDatabase() new_trip = db_instance.trip_create(name, user.id, max_trip_days, is_guided, in_group, max_price) db_instance.close_connection() if not new_trip: return response_400("BadRequest", "Invalid data entry") return jsonify(new_trip.serialize()) except KeyError: return response_400("ParameterError", "Please provide all the parameters") except Exception as e: print(e) return response_500()