def near(flight_id): flight = get_requested_record(Flight, flight_id, joinedload=[Flight.igc_file]) current_user = User.get(request.user_id) if request.user_id else None if not flight.is_viewable(current_user): return jsonify(), 404 try: latitude = float(request.args["lat"]) longitude = float(request.args["lon"]) time = float(request.args["time"]) except (KeyError, ValueError): abort(400) location = Location(latitude=latitude, longitude=longitude) time = from_seconds_of_day(flight.takeoff_time, time) flights = _get_near_flights(flight, location, time, 1000) def add_flight_path(flight): trace = _get_flight_path(flight, threshold=0.0001, max_points=10000) trace["additional"] = dict(registration=flight.registration, competition_id=flight.competition_id) return trace return jsonify(flights=map(add_flight_path, flights))
def read(): current_user = User.get(request.user_id) if not current_user: return jsonify(error='invalid-token'), 401 schema = CurrentUserSchema(exclude=('id')) return jsonify(schema.dump(current_user).data)
def create_club(): current_user = User.get(request.user_id) if not current_user: return jsonify(error="invalid-token"), 401 json = request.get_json() if json is None: return jsonify(error="invalid-request"), 400 try: data = ClubSchema(only=("name",)).load(json).data except ValidationError as e: return jsonify(error="validation-failed", fields=e.messages), 422 if Club.exists(name=data.get("name")): return jsonify(error="duplicate-club-name"), 422 # create the new club club = Club(**data) club.owner_id = current_user.id db.session.add(club) db.session.flush() # assign the user to the new club current_user.club = club # create the "user joined club" event create_club_join_event(club.id, current_user) db.session.commit() return jsonify(id=club.id)
def add_comment(flight_id): flight = get_requested_record(Flight, flight_id) current_user = User.get(request.user_id) if not current_user: return jsonify(), 403 json = request.get_json() if json is None: return jsonify(error="invalid-request"), 400 try: data = FlightCommentSchema().load(json).data except ValidationError as e: return jsonify(error="validation-failed", fields=e.messages), 422 comment = FlightComment() comment.user = current_user comment.flight = flight comment.text = data["text"] create_flight_comment_notifications(comment) db.session.commit() return jsonify()
def tracking_generate_key(): current_user = User.get(request.user_id) if not current_user: return jsonify(error='invalid-token'), 401 current_user.generate_tracking_key() db.session.commit() return jsonify(key=current_user.tracking_key_hex)
def new_post(): json = request.get_json() if json is None: return jsonify(error='invalid-request'), 400 try: data = CurrentUserSchema(only=('email', 'firstName', 'lastName', 'password')).load(json).data except ValidationError, e: return jsonify(error='validation-failed', fields=e.messages), 422
def check_current_password(): current_user = User.get(request.user_id) if not current_user: return jsonify(error='invalid-token'), 401 json = request.get_json() if not json: return jsonify(error='invalid-request'), 400 return jsonify(result=current_user.validate_password(json.get('password', '')))
def list(ids): if not ids: return jsonify(), 400 try: # Split the string into integer IDs ids = [int(id) for id in ids.split(",")] except ValueError: return jsonify(), 404 return _create_list(pinned=ids, default_sorting_column="date", default_sorting_order="desc")
def delete_user(user_id): current_user = User.get(request.user_id) if not current_user.is_manager(): return jsonify(), 403 user = get_requested_record(User, user_id) user.delete() db.session.commit() return jsonify()
def update(club_id): club = get_requested_record(Club, club_id) json = request.get_json() if json is None: return jsonify(error='invalid-request'), 400 try: data = ClubSchema(partial=True).load(json).data except ValidationError, e: return jsonify(error='validation-failed', fields=e.messages), 422
def verify(): current_user = User.get(request.user_id) json = request.get_json() if json is None: return jsonify(error='invalid-request'), 400 try: data = FlightSchema(partial=True).load(json, many=True).data except ValidationError, e: return jsonify(error='validation-failed', fields=e.messages), 422
def negotiate_locale(): available = request.args.get("available", "").split(",") available = [locale for locale in available if locale != ""] if len(available) == 0: return jsonify(error="invalid-request"), 400 preferred = [headers[0] for headers in request.accept_languages] locale = _negotiate_locale(preferred, available, sep="-") return jsonify(locale=locale)
def update(): current_user = User.get(request.user_id) if not current_user: return jsonify(error='invalid-token'), 401 json = request.get_json() if json is None: return jsonify(error='invalid-request'), 400 try: data = CurrentUserSchema(partial=True).load(json).data except ValidationError, e: return jsonify(error='validation-failed', fields=e.messages), 422
def create_club(): current_user = User.get(request.user_id) if not current_user: return jsonify(error='invalid-token'), 401 json = request.get_json() if json is None: return jsonify(error='invalid-request'), 400 try: data = ClubSchema(only=('name',)).load(json).data except ValidationError, e: return jsonify(error='validation-failed', fields=e.messages), 422
def json(flight_id): flight = get_requested_record( Flight, flight_id, joinedload=(Flight.igc_file, Flight.model) ) current_user = User.get(request.user_id) if request.user_id else None if not flight.is_viewable(current_user): return jsonify(), 404 # Return HTTP Status code 304 if an upstream or browser cache already # contains the response and if the igc file did not change to reduce # latency and server load # This implementation is very basic. Sadly Flask (0.10.1) does not have # this feature last_modified = flight.time_modified.strftime("%a, %d %b %Y %H:%M:%S GMT") modified_since = request.headers.get("If-Modified-Since") etag = request.headers.get("If-None-Match") if (modified_since and modified_since == last_modified) or ( etag and etag == flight.igc_file.md5 ): return ("", 304) trace = _get_flight_path(flight, threshold=0.0001, max_points=10000) if not trace: abort(404) model = AircraftModelSchema().dump(flight.model).data or None resp = make_response( jsonify( points=trace["points"], barogram_t=trace["barogram_t"], barogram_h=trace["barogram_h"], enl=trace["enl"], contests=trace["contests"], elevations_t=trace["elevations_t"], elevations_h=trace["elevations_h"], sfid=flight.id, geoid=trace["geoid"], additional=dict( registration=flight.registration, competition_id=flight.competition_id, model=model, ), ) ) resp.headers["Last-Modified"] = last_modified resp.headers["Etag"] = flight.igc_file.md5 return resp
def update(flight_id): flight = get_requested_record(Flight, flight_id) current_user = User.get(request.user_id) if not flight.is_writable(current_user): return jsonify(), 403 json = request.get_json() if json is None: return jsonify(error="invalid-request"), 400 try: data = FlightSchema(partial=True).load(json).data except ValidationError, e: return jsonify(error="validation-failed", fields=e.messages), 422
def add_comment(flight_id): flight = get_requested_record(Flight, flight_id) current_user = User.get(request.user_id) if not current_user: return jsonify(), 403 json = request.get_json() if json is None: return jsonify(error="invalid-request"), 400 try: data = FlightCommentSchema().load(json).data except ValidationError, e: return jsonify(error="validation-failed", fields=e.messages), 422
def skylines_team(): path = os.path.join(os.path.dirname(os.path.abspath(__file__)), '..', '..', '..', 'AUTHORS.md') with open(path) as f: content = f.read().decode('utf-8') return jsonify(content=content)
def index(): fix_schema = TrackingFixSchema(only=('time', 'location', 'altitude', 'elevation', 'pilot')) airport_schema = AirportSchema(only=('id', 'name', 'countryCode')) @cache.memoize(timeout=(60 * 60)) def get_nearest_airport(track): airport = Airport.by_location(track.location, None) if not airport: return None return dict(airport=airport_schema.dump(airport).data, distance=airport.distance(track.location)) tracks = [] for t in TrackingFix.get_latest(): nearest_airport = get_nearest_airport(t) track = fix_schema.dump(t).data if nearest_airport: track['nearestAirport'] = nearest_airport['airport'] track['nearestAirportDistance'] = nearest_airport['distance'] tracks.append(track) if request.user_id: followers = [f.destination_id for f in Follower.query(source_id=request.user_id)] else: followers = [] return jsonify(friends=followers, tracks=tracks)
def latest(): fixes = [] for fix in TrackingFix.get_latest(): json = dict( time=fix.time.isoformat() + "Z", location=fix.location.to_wkt(), pilot=dict(id=fix.pilot_id, name=fix.pilot.name), ) optional_attributes = [ "track", "ground_speed", "airspeed", "altitude", "vario", "engine_noise_level", ] for attr in optional_attributes: value = getattr(fix, attr) if value is not None: json[attr] = value fixes.append(json) return jsonify(fixes=fixes)
def follow(user_id): user = get_requested_record(User, user_id) current_user = User.get(request.user_id) Follower.follow(current_user, user) create_follower_notification(user, current_user) db.session.commit() return jsonify()
def list(): query = Notification.query(recipient_id=request.user_id) \ .join('event') \ .options(contains_eager('event')) \ .options(subqueryload('event.actor')) \ .outerjoin(Event.flight) \ .options(contains_eager('event.flight')) \ .filter(or_(Event.flight == None, Flight.is_rankable())) \ .order_by(Event.time.desc()) query = _filter_query(query, request.args) page = request.args.get('page', type=int, default=1) per_page = request.args.get('per_page', type=int, default=50) query = query.limit(per_page) query = query.offset((page - 1) * per_page) def get_event(notification): event = notification.event event.unread = (notification.time_read is None) return event events = map(get_event, query) return jsonify(events=(map(convert_event, events)))
def check_email(): current_user = User.get(request.user_id) if request.user_id else None json = request.get_json() if not json: return jsonify(error='invalid-request'), 400 email = json.get('email', '') result = 'available' if current_user and email == current_user.email_address: result = 'self' elif User.exists(email_address=email): result = 'unavailable' return jsonify(result=result)
def _list(): query = ( Notification.query(recipient_id=request.user_id) .join("event") .options(contains_eager("event")) .options(subqueryload("event.actor")) .outerjoin(Event.flight) .options(contains_eager("event.flight")) .filter(or_(Event.flight == None, Flight.is_rankable())) .order_by(Event.time.desc()) ) query = _filter_query(query, request.args) page = request.args.get("page", type=int, default=1) per_page = request.args.get("per_page", type=int, default=50) query = query.limit(per_page) query = query.offset((page - 1) * per_page) def get_event(notification): event = notification.event event.unread = notification.time_read is None return event events = list(convert_event(get_event(notification)) for notification in query) return jsonify(events=events)
def index(): models = AircraftModel.query() \ .order_by(AircraftModel.kind) \ .order_by(AircraftModel.name) \ .all() return jsonify(models=AircraftModelSchema().dump(models, many=True).data)
def check_email(): current_user = User.get(request.user_id) if request.user_id else None json = request.get_json() if not json: return jsonify(error="invalid-request"), 400 email = json.get("email", "") result = "available" if current_user and email == current_user.email_address: result = "self" elif User.exists(email_address=email): result = "unavailable" return jsonify(result=result)
def license(): path = os.path.join(os.path.dirname(os.path.abspath(__file__)), '..', '..', '..', 'LICENSE') with open(path) as f: content = f.read().decode('utf-8') return jsonify(content=content)
def recover_step2_post(json): try: data = CurrentUserSchema(only=("password", "recoveryKey")).load(json).data except ValidationError as e: return jsonify(error="validation-failed", fields=e.messages), 422 user = User.by_recover_key(int(data["recover_key"], base=16)) if not user: return jsonify(error="recovery-key-unknown"), 422 user.password = data["password"] user.recover_key = None db.session.commit() return jsonify()
def _list(): location = parse_location(request.args) airspaces = airspace_list_schema.dump(Airspace.by_location(location).all(), many=True).data waves = wave_list_schema.dump(MountainWaveProject.by_location(location), many=True).data return jsonify(airspaces=airspaces, waves=waves)
def delete_account(): current_user = User.get(request.user_id) json = request.get_json() if json is None: return jsonify(error='invalid-request'), 400 if 'password' not in json: return jsonify(error='password-missing'), 400 if not current_user.validate_password(json['password']): return jsonify(error='wrong-password'), 403 current_user.delete() db.session.commit() return jsonify()
def _list(): users = User.query().options(joinedload(User.club)).order_by( func.lower(User.name)) fields = ["id", "name"] if "club" in request.args: users = users.filter_by(club_id=request.args.get("club")) else: fields.append("club") return jsonify(users=UserSchema(only=fields).dump(users, many=True).data)
def new_post(): json = request.get_json() if json is None: return jsonify(error="invalid-request"), 400 try: data = (CurrentUserSchema(only=("email", "firstName", "lastName", "password")).load(json).data) except ValidationError as e: return jsonify(error="validation-failed", fields=e.messages), 422 user = User(**data) user.created_ip = request.remote_addr db.session.add(user) create_new_user_event(user) db.session.commit() return jsonify(user=UserSchema().dump(user).data)
def update(club_id): current_user = User.get(request.user_id) if not current_user: return jsonify(error='invalid-token'), 401 club = get_requested_record(Club, club_id) if not club.is_writable(current_user): return jsonify(error='forbidden'), 403 json = request.get_json() if json is None: return jsonify(error='invalid-request'), 400 try: data = ClubSchema(partial=True).load(json).data except ValidationError as e: return jsonify(error='validation-failed', fields=e.messages), 422 if 'name' in data: name = data.get('name') if name != club.name and Club.exists(name=name): return jsonify(error='duplicate-club-name'), 422 club.name = name if 'website' in data: club.website = data.get('website') db.session.commit() return jsonify()
def delete(flight_id): flight = get_requested_record(Flight, flight_id, joinedload=[Flight.igc_file]) current_user = User.get(request.user_id) if not flight.is_writable(current_user): abort(403) files.delete_file(flight.igc_file.filename) db.session.delete(flight) db.session.delete(flight.igc_file) db.session.commit() return jsonify()
def _list(): users = User.query() \ .options(joinedload(User.club)) \ .order_by(func.lower(User.name)) fields = ['id', 'name'] if 'club' in request.args: users = users.filter_by(club_id=request.args.get('club')) else: fields.append('club') return jsonify(users=UserSchema(only=fields).dump(users, many=True).data)
def recover_step1_post(json): try: data = CurrentUserSchema(only=("email", )).load(json).data except ValidationError as e: return jsonify(error="validation-failed", fields=e.messages), 422 user = User.by_email_address(data["email_address"]) if not user: return jsonify(error="email-unknown"), 422 user.generate_recover_key(request.remote_addr) db.session.commit() current_user = User.get(request.user_id) if request.user_id else None if current_user and current_user.admin: url = u"http://skylines.aero/users/recover?key=%x" % user.recover_key return jsonify(url=url) try: send_recover_mail(user) except ServiceUnavailable: return jsonify(error="mail-service-unavailable"), 503 return jsonify()
def _list(): query = (Event.query().options(subqueryload("user")).options( subqueryload("club")).outerjoin(Event.flight).options( contains_eager(Event.flight)).filter( or_(Event.flight == None, Flight.is_rankable())).order_by(Event.time.desc())) query = _filter_query(query, request.args) page = request.args.get("page", type=int, default=1) per_page = request.args.get("per_page", type=int, default=50) events = query.limit(per_page).offset((page - 1) * per_page).all() return jsonify(events=([convert_event(event) for event in events]))
def followers(user_id): user = get_requested_record(User, user_id) # Query list of pilots that are following the selected user query = (Follower.query(destination=user).join("source").options( contains_eager("source")).options( subqueryload("source.club")).order_by(User.name)) user_schema = UserSchema(only=("id", "name", "club")) followers = user_schema.dump([follower.source for follower in query], many=True).data add_current_user_follows(followers) return jsonify(followers=followers)
def pilots(): data = _handle_request_rank(User, "pilot_id") user_schema = UserSchema(only=("id", "name", "club")) json = [] for pilot, count, total, rank in data["result"]: row = { "rank": rank, "flights": count, "points": total, "user": user_schema.dump(pilot).data, } json.append(row) return jsonify(ranking=json, total=g.paginators["result"].count)
def airports(): data = _handle_request(Airport, 'takeoff_airport_id') airport_schema = AirportSchema(only=('id', 'name', 'countryCode')) json = [] for airport, count, total, rank in data['result']: row = { 'rank': rank, 'flights': count, 'points': total, 'airport': airport_schema.dump(airport).data, } json.append(row) return jsonify(ranking=json, total=g.paginators['result'].count)
def pilots(): data = _handle_request(User, 'pilot_id') user_schema = UserSchema(only=('id', 'name', 'club')) json = [] for pilot, count, total, rank in data['result']: row = { 'rank': rank, 'flights': count, 'points': total, 'user': user_schema.dump(pilot).data, } json.append(row) return jsonify(ranking=json, total=g.paginators['result'].count)
def clubs(): data = _handle_request(Club, 'club_id') club_schema = ClubSchema(only=('id', 'name')) json = [] for club, count, total, rank in data['result']: row = { 'rank': rank, 'flights': count, 'points': total, 'club': club_schema.dump(club).data, } json.append(row) return jsonify(ranking=json, total=g.paginators['result'].count)
def airports(): data = _handle_request_rank(Airport, "takeoff_airport_id") airport_schema = AirportSchema(only=("id", "name", "countryCode")) json = [] for airport, count, total, rank in data["result"]: row = { "rank": rank, "flights": count, "points": total, "airport": airport_schema.dump(airport).data, } json.append(row) return jsonify(ranking=json, total=g.paginators["result"].count)
def clubs(): data = _handle_request_rank(Club, "club_id") club_schema = ClubSchema(only=("id", "name")) json = [] for club, count, total, rank in data["result"]: row = { "rank": rank, "flights": count, "points": total, "club": club_schema.dump(club).data, } json.append(row) return jsonify(ranking=json, total=g.paginators["result"].count)
def _list(): query = Event.query() \ .options(subqueryload('actor')) \ .options(subqueryload('user')) \ .options(subqueryload('club')) \ .outerjoin(Event.flight) \ .options(contains_eager(Event.flight)) \ .filter(or_(Event.flight == None, Flight.is_rankable())) \ .order_by(Event.time.desc()) query = _filter_query(query, request.args) page = request.args.get('page', type=int, default=1) per_page = request.args.get('per_page', type=int, default=50) events = query.limit(per_page).offset((page - 1) * per_page).all() return jsonify(events=(map(convert_event, events)))
def following(user_id): user = get_requested_record(User, user_id) # Query list of pilots that are following the selected user query = Follower.query(source=user) \ .join('destination') \ .options(contains_eager('destination')) \ .options(subqueryload('destination.club')) \ .order_by(User.name) user_schema = UserSchema(only=('id', 'name', 'club')) following = user_schema.dump([follower.destination for follower in query], many=True).data add_current_user_follows(following) return jsonify(following=following)
def read(user_id): user = get_requested_record(User, user_id) user_schema = CurrentUserSchema( ) if user_id == request.user_id else UserSchema() user_json = user_schema.dump(user).data if request.user_id: current_user = User.get(request.user_id) user_json["followed"] = current_user.follows(user) if "extended" in request.args: user_json["distanceFlights"] = _distance_flights(user) user_json["stats"] = _quick_stats(user) user_json["takeoffLocations"] = _get_takeoff_locations(user) mark_user_notifications_read(user) return jsonify(user_json)
def read(user_ids): pilots = get_requested_record_list(User, user_ids, joinedload=[User.club]) color_gen = color.generator() for pilot in pilots: pilot.color = next(color_gen) traces = list(map(_get_flight_path, pilots)) if not any(traces): traces = None user_schema = UserSchema() pilots_json = [] for pilot in pilots: json = user_schema.dump(pilot).data json["color"] = pilot.color pilots_json.append(json) flights = [] if traces: for pilot, trace in zip(pilots, traces): if trace: flights.append({ "sfid": pilot.id, "points": trace["points"], "barogram_t": trace["barogram_t"], "barogram_h": trace["barogram_h"], "enl": trace["enl"], "contests": None, "elevations_t": trace["barogram_t"], "elevations_h": trace["elevations"], "geoid": trace["geoid"], "additional": { "competition_id": pilot.tracking_callsign or pilot.initials(), "color": pilot.color, }, }) return jsonify(flights=flights, pilots=pilots_json)