Skip to content

Commit

Permalink
Hide routing possibilities if Mapbox/ORS tokens are not set (#233)
Browse files Browse the repository at this point in the history
  • Loading branch information
cdauth committed Apr 12, 2024
1 parent 381d8ee commit 2ceab20
Show file tree
Hide file tree
Showing 17 changed files with 49 additions and 42 deletions.
24 changes: 12 additions & 12 deletions docs/src/developers/server/config.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,18 @@ The config of the FacilMap server can be set either by using environment variabl
| `APP_NAME` | | | If specified, will replace “FacilMap” as the name of the app throughout the UI. |
| `TRUST_PROXY` | | | Whether to trust the X-Forwarded-* headers. Can be `true` or a comma-separated list of IP subnets (see the [express documentation](https://expressjs.com/en/guide/behind-proxies.html)). Currently only used to calculate the base URL for the `opensearch.xml` file. |
| `BASE_URL` | | | If `TRUST_PROXY` does not work for your particular setup, you can manually specify the base URL where FacilMap can be publicly reached here. |
| `HOST` | | | The ip address to listen on (leave empty to listen on all addresses) |
| `PORT` | | `8080` | The port to listen on. |
| `DB_TYPE` | | `mysql` | The type of database. Either `mysql`, `postgres`, `mariadb`, `sqlite`, or `mssql`. |
| `DB_HOST` | | `localhost` | The host name of the database server. |
| `DB_PORT` | | | The port of the database server (optional). |
| `DB_NAME` | | `facilmap` | The name of the database. |
| `DB_USER` | | `facilmap` | The username to connect to the database with. |
| `DB_PASSWORD` | | `facilmap` | The password to connect to the database with. |
| `ORS_TOKEN` | * | | [OpenRouteService API key](https://openrouteservice.org/). |
| `MAPBOX_TOKEN` | * | | [Mapbox API key](https://www.mapbox.com/signup/). |
| `MAXMIND_USER_ID` | | | [MaxMind user ID](https://www.maxmind.com/en/geolite2/signup). |
| `MAXMIND_LICENSE_KEY` | | | MaxMind license key. |
| `HOST` | | | The ip address to listen on (leave empty to listen on all addresses) |
| `PORT` | | `8080` | The port to listen on. |
| `DB_TYPE` | | `mysql` | The type of database. Either `mysql`, `postgres`, `mariadb`, `sqlite`, or `mssql`. |
| `DB_HOST` | | `localhost` | The host name of the database server. |
| `DB_PORT` | | | The port of the database server (optional). |
| `DB_NAME` | | `facilmap` | The name of the database. |
| `DB_USER` | | `facilmap` | The username to connect to the database with. |
| `DB_PASSWORD` | | `facilmap` | The password to connect to the database with. |
| `ORS_TOKEN` | | | [OpenRouteService API key](https://openrouteservice.org/). If not specified, advanced routing settings will not be shown. |
| `MAPBOX_TOKEN` | | | [Mapbox API key](https://www.mapbox.com/signup/). If neither this nor `ORS_TOKEN` are specified, the routing tab and any routing options will be hidden. |
| `MAXMIND_USER_ID` | | | [MaxMind user ID](https://www.maxmind.com/en/geolite2/signup). |
| `MAXMIND_LICENSE_KEY` | | | MaxMind license key. |
| `LIMA_LABS_TOKEN` | | | [Lima Labs](https://maps.lima-labs.com/) API key |
| `HIDE_COMMERCIAL_MAP_LINKS` | | | Set to `1` to hide the links to Google/Bing Maps in the “Map style” menu. |
| `CUSTOM_CSS_FILE` | | | The path of a CSS file that should be included ([see more details below](#custom-css-file)). |
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/lib/components/edit-line-dialog.vue
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@
</ValidatedField>
</div>

<div v-if="resolvedCanControl.includes('mode') && line.mode !== 'track'" class="row mb-3">
<div v-if="resolvedCanControl.includes('mode') && line.mode !== 'track' && context.settings.routing" class="row mb-3">
<label class="col-sm-3 col-form-label">{{i18n.t("edit-line-dialog.routing-mode")}}</label>
<div class="col-sm-9">
<RouteMode v-model="line.mode"></RouteMode>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -361,7 +361,7 @@
</div>
</template>

<template v-if="resolvedCanControl.includes('mode')">
<template v-if="resolvedCanControl.includes('mode') && context.settings.routing">
<div class="row mb-3">
<label :for="`${id}-default-mode-input`" class="col-sm-3 col-form-label">{{i18n.t("edit-type-dialog.default-route-mode")}}</label>
<div class="col-sm-9">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,8 @@
interactive: true,
linkLogo: false,
updateHash: false,
routing: true,
advancedRouting: true,
...props.settings
}))),
components: shallowReadonly(components),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ export interface FacilMapSettings {
interactive: boolean;
linkLogo: boolean;
updateHash: boolean;
routing: boolean;
advancedRouting: boolean;
}

export interface FacilMapComponents {
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/lib/components/facil-map.vue
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@

<template v-if="context.components.searchBox">
<SearchFormTab v-if="context.settings.search"></SearchFormTab>
<RouteFormTab v-if="context.settings.search"></RouteFormTab>
<RouteFormTab v-if="context.settings.search && context.settings.routing"></RouteFormTab>
<OverpassFormTab v-if="context.settings.search"></OverpassFormTab>
<MarkerInfoTab></MarkerInfoTab>
<LineInfoTab></LineInfoTab>
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/lib/components/route-form/route-form.vue
Original file line number Diff line number Diff line change
Expand Up @@ -633,7 +633,7 @@
<Icon icon="plus" :alt="i18n.t('route-form.add-destination-alt')"></Icon>
</button>

<RouteMode v-model="routeMode" :tabindex="destinations.length+2" tooltip-placement="bottom"></RouteMode>
<RouteMode v-if="context.settings.routing" v-model="routeMode" :tabindex="destinations.length+2" tooltip-placement="bottom"></RouteMode>

<button
type="submit"
Expand Down
4 changes: 3 additions & 1 deletion frontend/src/lib/components/ui/route-mode.vue
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,12 @@
import vTooltip, { type TooltipPlacement } from "../../utils/tooltip";
import DropdownMenu from "../ui/dropdown-menu.vue";
import { useI18n } from "../../utils/i18n";
import { injectContextRequired } from "../facil-map-context-provider/facil-map-context-provider.vue";
type Mode = Exclude<DecodedRouteMode['mode'], 'track'>;
type Type = DecodedRouteMode['type'];
const context = injectContextRequired();
const i18n = useI18n();
const props = withDefaults(defineProps<{
Expand Down Expand Up @@ -184,7 +186,7 @@
</label>
</template>

<div class="btn-group">
<div v-if="context.settings.advancedRouting" class="btn-group">
<DropdownMenu
:tabindex="tabindex != null ? tabindex + constants.modes.length : undefined"
tooltip="Customize"
Expand Down
4 changes: 3 additions & 1 deletion frontend/src/map/map.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,9 @@ const Root = defineComponent({
legend: toBoolean(queryParams.legend, true),
interactive: toBoolean(queryParams.interactive, parent === window),
linkLogo: parent !== window,
updateHash: true
updateHash: true,
routing: config.supportsRoutes,
advancedRouting: config.supportsAdvancedRoutes
},
"onUpdate:padId": (v) => padId.value = v,
"onUpdate:padName": (v) => padName.value = v
Expand Down
2 changes: 2 additions & 0 deletions server/src/frontend.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ function getInjectedConfig(): InjectedConfig {
nominatimUrl: config.nominatimUrl,
limaLabsToken: config.limaLabsToken,
hideCommercialMapLinks: config.hideCommercialMapLinks,
supportsRoutes: !!config.mapboxToken || !!config.orsToken,
supportsAdvancedRoutes: !!config.orsToken
};
}

Expand Down
2 changes: 1 addition & 1 deletion server/src/i18n/de.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
"load-error": "{{appName}} konnte nicht geladen werden!"
},
"routing": {
"ors-token-warning": "Warnung: Kein ORS-Token konfiguriert. Bitten Sie den Administrator, die Umgebungsvariable ORS_TOKEN zu setzen.",
"ors-token-warning": "Kein ORS-Token konfiguriert. Bitten Sie den Administrator, die Umgebungsvariable ORS_TOKEN zu setzen.",
"too-much-distance-error": "Die Distanz zwischen den Routenpunkten ist zu groß. Versuchen Sie, einige Zwischenpunkte hinzuzufügen.",
"invalid-response-error": "Ungültige Antwort vom Routenserver.",
"mapbox-token-warning": "Kein Mapbox-Token konfiguriert. Bitten Sie den Administrator, die Umgebungsvariable MAPBOX_TOKEN zu setzen.",
Expand Down
2 changes: 1 addition & 1 deletion server/src/i18n/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
"load-error": "Could not load {{appName}}!"
},
"routing": {
"ors-token-warning": "Warning: No ORS token configured. Please ask the administrator to set ORS_TOKEN in the environment or in config.env.",
"ors-token-warning": "No ORS token configured. Please ask the administrator to set ORS_TOKEN in the environment or in config.env.",
"too-much-distance-error": "Too much distance between route points. Consider adding some via points.",
"invalid-response-error": "Invalid response from routing server.",
"mapbox-token-warning": "No Mapbox token configured. Please ask the administrator to set MAPBOX_TOKEN in the environment or in config.env.",
Expand Down
2 changes: 1 addition & 1 deletion server/src/routing/ors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import type { RawRouteInfo } from "./routing.js";
import { getI18n } from "../i18n.js";

if (!config.orsToken)
console.error("Warning: No ORS token configured, calculating routes will fail. Please set ORS_TOKEN in the environment or in config.env.");
console.error("Warning: No ORS token configured, calculating routes with advanced settings will not be supported. Please set ORS_TOKEN in the environment or in config.env.");

const ROUTING_URL = `https://api.openrouteservice.org/v2/directions`;

Expand Down
2 changes: 1 addition & 1 deletion server/src/routing/osrm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import type { RawRouteInfo } from "./routing.js";
import { getI18n } from "../i18n.js";

if (!config.mapboxToken)
console.error("Warning: No Mapbox token configured, calculating routes will fail. Please set MAPBOX_TOKEN in the environment or in config.env.");
console.error("Warning: No Mapbox token configured, calculating simple routes will fall back to ORS. Please set MAPBOX_TOKEN in the environment or in config.env.");

const ROUTING_URL = "https://api.mapbox.com/directions/v5/mapbox";

Expand Down
25 changes: 5 additions & 20 deletions server/src/routing/routing.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { calculateBbox, isInBbox } from "../utils/geo.js";
import type { Bbox, BboxWithZoom, CRU, Line, Point, Route, RouteInfo, RouteMode, TrackPoint } from "facilmap-types";
import { decodeRouteMode, type DecodedRouteMode, calculateDistance, round } from "facilmap-utils";
import { decodeRouteMode, calculateDistance, round, isSimpleRoute } from "facilmap-utils";
import { calculateOSRMRoute } from "./osrm.js";
import { calculateORSRoute, getMaximumDistanceBetweenRoutePoints } from "./ors.js";
import config from "../config.js";

// The OpenLayers resolution for zoom level 1 is 0.7031249999891753
// and for zoom level 20 0.0000013411044763239684
Expand All @@ -18,12 +19,13 @@ export type RawRouteInfo = Omit<RouteInfo, "trackPoints" | keyof Bbox> & {
export async function calculateRoute(routePoints: Point[], encodedMode: RouteMode | undefined): Promise<RouteInfo> {
const decodedMode = decodeRouteMode(encodedMode);

const simple = isSimpleRoute(decodedMode);
const simple = (!config.mapboxToken && config.orsToken) ? false : isSimpleRoute(decodedMode);

let route: RawRouteInfo | undefined;

if(simple || _needsOSRM(routePoints, decodedMode))
if (simple) {
route = await calculateOSRMRoute(routePoints, decodedMode.mode);
}

if(!simple) {
if(route) {
Expand Down Expand Up @@ -98,23 +100,6 @@ export async function calculateRouteForLine(line: Pick<Line<CRU.CREATE_VALIDATED
return result as RouteInfo;
}


export function isSimpleRoute(decodedMode: DecodedRouteMode): boolean {
return !decodedMode.type &&
(!decodedMode.preference || decodedMode.preference == "fastest") &&
(!decodedMode.avoid || decodedMode.avoid.length == 0) &&
!decodedMode.details;
}

function _needsOSRM(routePoints: Point[], decodedMode: DecodedRouteMode) {
const maxDist = getMaximumDistanceBetweenRoutePoints(decodedMode);
for(let i=1; i<routePoints.length; i++) {
if(calculateDistance([ routePoints[i-1], routePoints[i] ]) > maxDist)
return true;
}
return false;
}

function _getTrackPointsFromTrack(trackPoints: Point[], maxDistance: number) {
const result: Point[] = [ trackPoints[0] ];
for(let i=1; i<trackPoints.length; i++) {
Expand Down
10 changes: 10 additions & 0 deletions utils/src/routing.ts
Original file line number Diff line number Diff line change
Expand Up @@ -192,4 +192,14 @@ export function parseRouteQuery(query: string): RouteQuery {
queries: queryParts.from.concat(queryParts.via, queryParts.to),
mode
};
}

/**
* If true, this route can be handled by OSRM, ORS is not needed.
*/
export function isSimpleRoute(decodedMode: DecodedRouteMode): boolean {
return !decodedMode.type &&
(!decodedMode.preference || decodedMode.preference == "fastest") &&
(!decodedMode.avoid || decodedMode.avoid.length == 0) &&
!decodedMode.details;
}
2 changes: 2 additions & 0 deletions utils/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,6 @@ export interface InjectedConfig {
nominatimUrl: string;
limaLabsToken?: string;
hideCommercialMapLinks?: boolean;
supportsRoutes: boolean;
supportsAdvancedRoutes: boolean;
}

0 comments on commit 2ceab20

Please sign in to comment.