Пример #1
0
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))
Пример #2
0
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)
Пример #3
0
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)
Пример #4
0
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()
Пример #5
0
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)
Пример #6
0
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
Пример #7
0
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', '')))
Пример #8
0
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")
Пример #9
0
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()
Пример #10
0
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
Пример #11
0
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
Пример #12
0
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)
Пример #13
0
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
Пример #14
0
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
Пример #15
0
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
Пример #16
0
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
Пример #17
0
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
Пример #18
0
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)
Пример #19
0
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)
Пример #20
0
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)
Пример #21
0
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()
Пример #22
0
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)))
Пример #23
0
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)
Пример #24
0
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)
Пример #25
0
def index():
    models = AircraftModel.query() \
        .order_by(AircraftModel.kind) \
        .order_by(AircraftModel.name) \
        .all()

    return jsonify(models=AircraftModelSchema().dump(models, many=True).data)
Пример #26
0
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)
Пример #27
0
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)
Пример #28
0
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()
Пример #29
0
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)
Пример #30
0
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()
Пример #31
0
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)
Пример #32
0
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)
Пример #33
0
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()
Пример #34
0
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()
Пример #35
0
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)
Пример #36
0
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()
Пример #37
0
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]))
Пример #38
0
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)
Пример #39
0
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)
Пример #40
0
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)
Пример #41
0
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)
Пример #42
0
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)
Пример #43
0
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)
Пример #44
0
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)
Пример #45
0
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)))
Пример #46
0
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)
Пример #47
0
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)
Пример #48
0
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)