Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ ENV APP_PATH=/app
ENV DATA_PATH=/data
ENV JETLOG_PORT=3000
ENV TOKEN_DURATION=7
ENV ENABLE_EXTERNAL_APIS=true
ENV USE_IPV6=false

RUN mkdir -p ${APP_PATH}
Expand Down
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ A self-hostable personal flight tracker and viewer
- [Features](#features)
- [Getting Started](#getting-started)
- [Importing & Exporting](#importing--exporting)
- [Privacy Notice](#privacy-notice)
- [Contributing](#contributing)
- [Stack](#stack)
- [Acknowledgements](#acknowledgements)
Expand Down Expand Up @@ -61,6 +62,14 @@ you can also export to CSV, iCal

For details on how to import your data, have a look at the [importing wiki](https://github.com/pbogre/jetlog/wiki/Importing)

## Privacy Notice

Jetlog itself does not collect any user data outside of your own setup. However,
it relies on external APIs ([adsbdb](https://www.adsbdb.com/)) for some features
such as automatic flight fetching from the flight number. Since you cannot always
be sure of how external APIs use your data, you may wish to opt out of these by setting
the `ENABLE_EXTERNAL_APIS` environment variable to `false`.

## Contributing

If you would like to contribute to this project by opening an issue or a pull request,
Expand Down
3 changes: 2 additions & 1 deletion client/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@ import axios, {Axios} from 'axios';
import TokenStorage from './storage/tokenStorage';

const config = await fetch('./config').then((response) => response.json())
.catch(() => ({ BASE_URL: '/' }));
.catch(() => ({ BASE_URL: '/', ENABLE_EXTERNAL_APIS: true }));

export const BASE_URL = config.BASE_URL == '/' ? '' : config.BASE_URL;
export const ENABLE_EXTERNAL_APIS = config.ENABLE_EXTERNAL_APIS;

// TODO improve this because there's a lot of repetition (get, post, delete are pretty much exactly the same)
// perhaps one method for each endpoint? i.e. API.getFlights(), ...
Expand Down
14 changes: 10 additions & 4 deletions client/pages/New.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { useNavigate } from 'react-router-dom';

import { Heading, Label, Button, Input, Select, TextArea } from '../components/Elements';
import SearchInput from '../components/SearchInput'
import API from '../api';
import API, { ENABLE_EXTERNAL_APIS } from '../api';
import { objectFromForm } from '../utils';
import { Airline, Airport, User } from '../models';
import ConfigStorage from '../storage/configStorage';
Expand Down Expand Up @@ -151,6 +151,10 @@ export default function New() {
};

const attemptFetchFlight = async () => {
if (!ENABLE_EXTERNAL_APIS) {
return;
}

API.getRemote(`https://api.adsbdb.com/v0/callsign/${flightNumber}`)
.then(async (data: Object) => {
const originICAO = data["response"]["flightroute"]["origin"]["icao_code"];
Expand Down Expand Up @@ -246,9 +250,11 @@ export default function New() {
onChange={(e) => setFlightNumber(e.target.value)}
/>
</div>
<div className="h-10 flex items-center">
<Button text="Fetch" onClick={attemptFetchFlight} disabled={!flightNumber} />
</div>
{ ENABLE_EXTERNAL_APIS &&
<div className="h-10 flex items-center">
<Button text="Fetch" onClick={attemptFetchFlight} disabled={!flightNumber} />
</div>
}
</div>
<div>
<Label text="Connection" />
Expand Down
12 changes: 7 additions & 5 deletions client/pages/Settings.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React, { useState, useEffect } from 'react';
import { useNavigate } from 'react-router-dom';

import API from '../api';
import API, { ENABLE_EXTERNAL_APIS } from '../api';
import { Heading, Label, Input, Checkbox, Subheading, Button, Dialog, Select } from '../components/Elements'
import ConfigStorage, { ConfigInterface } from '../storage/configStorage';
import { User } from '../models';
Expand Down Expand Up @@ -255,10 +255,12 @@ export default function Settings() {
<Button text="Run" disabled={disableJobs} onClick={computeConnections} />
</div>

<div className="flex justify-between">
<Label text="Fetch missing airlines" />
<Button text="Run" disabled={disableJobs} onClick={fetchAirlinesFromCallsigns} />
</div>
{ ENABLE_EXTERNAL_APIS &&
<div className="flex justify-between">
<Label text="Fetch missing airlines" />
<Button text="Run" disabled={disableJobs} onClick={fetchAirlinesFromCallsigns} />
</div>
}
</div>


Expand Down
3 changes: 2 additions & 1 deletion server/environment.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import os
import sys

def _get_environment_variable(key: str, cast_int: bool = False, required: bool = True) -> str|int|None:
def _get_environment_variable(key: str, cast_int: bool = False, cast_str: bool = False, required: bool = True) -> str|int|None:
value = os.environ.get(key)

if not value:
Expand All @@ -23,3 +23,4 @@ def _get_environment_variable(key: str, cast_int: bool = False, required: bool =
SECRET_KEY = _get_environment_variable("SECRET_KEY")
AUTH_HEADER = _get_environment_variable("AUTH_HEADER", required=False)
TOKEN_DURATION = _get_environment_variable("TOKEN_DURATION", cast_int=True)
ENABLE_EXTERNAL_APIS = str(_get_environment_variable("ENABLE_EXTERNAL_APIS")).lower() == "true"
7 changes: 6 additions & 1 deletion server/main.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from server.routers import flights, airports, airlines, statistics, geography, importing, exporting
from server.auth import users, auth
from server.environment import ENABLE_EXTERNAL_APIS
from fastapi import FastAPI, Depends, Request
from fastapi.responses import HTMLResponse, JSONResponse
from fastapi.staticfiles import StaticFiles
Expand Down Expand Up @@ -34,7 +35,11 @@

@app.get("/config")
async def get_config(request: Request):
return JSONResponse({"BASE_URL": request.scope.get("root_path", "/")})
config = {
"BASE_URL": request.scope.get("root_path", "/"),
"ENABLE_EXTERNAL_APIS": ENABLE_EXTERNAL_APIS
}
return JSONResponse(config)

@app.get("/", include_in_schema=False)
@app.get("/new", include_in_schema=False)
Expand Down
3 changes: 3 additions & 0 deletions server/routers/flights.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from server.database import database
from server.environment import ENABLE_EXTERNAL_APIS
from server.models import AirlineModel, AirportModel, ClassType, CustomModel, FlightModel, AircraftSide, FlightPurpose, SeatType, User
from server.auth.users import get_current_user

Expand Down Expand Up @@ -363,6 +364,8 @@ async def compute_connections(user: User = Depends(get_current_user)) -> dict:

@router.post("/airlines_from_callsigns", status_code=200)
async def fetch_airlines_from_callsigns(user: User = Depends(get_current_user)) -> dict:
if not ENABLE_EXTERNAL_APIS:
raise HTTPException(status_code=400, detail="This endpoint relies on the use of an external API, which you have opted out of.")
import requests

res = database.execute_read_query("""SELECT flight_number, COUNT(*)
Expand Down