Various updates.
This commit is contained in:
parent
ff41bb21d2
commit
2424fe0fdf
187
web_view.py
187
web_view.py
|
@ -4,26 +4,13 @@ import json
|
||||||
import re
|
import re
|
||||||
from time import sleep, time
|
from time import sleep, time
|
||||||
|
|
||||||
|
import flask
|
||||||
import flask_login
|
import flask_login
|
||||||
import GeoIP
|
import GeoIP
|
||||||
import lxml
|
import lxml
|
||||||
import maxminddb
|
import maxminddb
|
||||||
import requests
|
import requests
|
||||||
import sqlalchemy
|
import sqlalchemy
|
||||||
from flask import (
|
|
||||||
Flask,
|
|
||||||
Response,
|
|
||||||
abort,
|
|
||||||
flash,
|
|
||||||
g,
|
|
||||||
jsonify,
|
|
||||||
redirect,
|
|
||||||
render_template,
|
|
||||||
request,
|
|
||||||
session,
|
|
||||||
stream_with_context,
|
|
||||||
url_for,
|
|
||||||
)
|
|
||||||
from requests_oauthlib import OAuth1Session
|
from requests_oauthlib import OAuth1Session
|
||||||
from sqlalchemy import func
|
from sqlalchemy import func
|
||||||
from sqlalchemy.sql.expression import update
|
from sqlalchemy.sql.expression import update
|
||||||
|
@ -48,7 +35,7 @@ from matcher.data import property_map
|
||||||
srid = 4326
|
srid = 4326
|
||||||
re_point = re.compile(r"^POINT\((.+) (.+)\)$")
|
re_point = re.compile(r"^POINT\((.+) (.+)\)$")
|
||||||
|
|
||||||
app = Flask(__name__)
|
app = flask.Flask(__name__)
|
||||||
app.debug = True
|
app.debug = True
|
||||||
app.config.from_object("config.default")
|
app.config.from_object("config.default")
|
||||||
error_mail.setup_error_mail(app)
|
error_mail.setup_error_mail(app)
|
||||||
|
@ -72,8 +59,9 @@ def shutdown_session(exception=None):
|
||||||
|
|
||||||
|
|
||||||
@app.before_request
|
@app.before_request
|
||||||
def global_user():
|
def global_user() -> None:
|
||||||
g.user = flask_login.current_user._get_current_object()
|
"""Make user object available globally."""
|
||||||
|
flask.g.user = flask_login.current_user._get_current_object()
|
||||||
|
|
||||||
|
|
||||||
def dict_repr_values(d):
|
def dict_repr_values(d):
|
||||||
|
@ -81,7 +69,8 @@ def dict_repr_values(d):
|
||||||
|
|
||||||
|
|
||||||
def cors_jsonify(*args, **kwargs):
|
def cors_jsonify(*args, **kwargs):
|
||||||
response = jsonify(*args, **kwargs)
|
"""Add CORS header to JSON."""
|
||||||
|
response = flask.jsonify(*args, **kwargs)
|
||||||
response.headers["Access-Control-Allow-Origin"] = "*"
|
response.headers["Access-Control-Allow-Origin"] = "*"
|
||||||
return response
|
return response
|
||||||
|
|
||||||
|
@ -112,24 +101,24 @@ def check_for_tagged_qid(qid):
|
||||||
def geoip_user_record():
|
def geoip_user_record():
|
||||||
gi = GeoIP.open(app.config["GEOIP_DATA"], GeoIP.GEOIP_STANDARD)
|
gi = GeoIP.open(app.config["GEOIP_DATA"], GeoIP.GEOIP_STANDARD)
|
||||||
|
|
||||||
remote_ip = request.get("ip", request.remote_addr)
|
remote_ip = flask.request.get("ip", flask.request.remote_addr)
|
||||||
return gi.record_by_addr(remote_ip)
|
return gi.record_by_addr(remote_ip)
|
||||||
|
|
||||||
|
|
||||||
def get_user_location():
|
def get_user_location():
|
||||||
remote_ip = request.args.get("ip", request.remote_addr)
|
remote_ip = flask.request.args.get("ip", flask.request.remote_addr)
|
||||||
maxmind = maxminddb_reader.get(remote_ip)
|
maxmind = maxminddb_reader.get(remote_ip)
|
||||||
return maxmind.get("location") if maxmind else None
|
return maxmind.get("location") if maxmind else None
|
||||||
|
|
||||||
|
|
||||||
@app.route("/")
|
@app.route("/")
|
||||||
def redirect_from_root():
|
def redirect_from_root():
|
||||||
return redirect(url_for("map_start_page"))
|
return flask.redirect(flask.url_for("map_start_page"))
|
||||||
|
|
||||||
|
|
||||||
@app.route("/index")
|
@app.route("/index")
|
||||||
def index_page():
|
def index_page():
|
||||||
return render_template("index.html")
|
return flask.render_template("index.html")
|
||||||
|
|
||||||
|
|
||||||
def get_username() -> str | None:
|
def get_username() -> str | None:
|
||||||
|
@ -142,14 +131,14 @@ def get_username() -> str | None:
|
||||||
def isa_page(item_id):
|
def isa_page(item_id):
|
||||||
item = api.get_item(item_id)
|
item = api.get_item(item_id)
|
||||||
|
|
||||||
if request.method == "POST":
|
if flask.request.method == "POST":
|
||||||
tag_or_key = request.form["tag_or_key"]
|
tag_or_key = flask.request.form["tag_or_key"]
|
||||||
extra = model.ItemExtraKeys(item=item, tag_or_key=tag_or_key)
|
extra = model.ItemExtraKeys(item=item, tag_or_key=tag_or_key)
|
||||||
database.session.add(extra)
|
database.session.add(extra)
|
||||||
database.session.commit()
|
database.session.commit()
|
||||||
flash("extra OSM tag/key added")
|
flask.flash("extra OSM tag/key added")
|
||||||
|
|
||||||
return redirect(url_for(request.endpoint, item_id=item_id))
|
return flask.redirect(flask.url_for(flask.request.endpoint, item_id=item_id))
|
||||||
|
|
||||||
q = model.ItemExtraKeys.query.filter_by(item=item)
|
q = model.ItemExtraKeys.query.filter_by(item=item)
|
||||||
extra = [e.tag_or_key for e in q]
|
extra = [e.tag_or_key for e in q]
|
||||||
|
@ -164,13 +153,13 @@ def isa_page(item_id):
|
||||||
"item_id": s["numeric-id"],
|
"item_id": s["numeric-id"],
|
||||||
"label": subclass.label(),
|
"label": subclass.label(),
|
||||||
"description": subclass.description(),
|
"description": subclass.description(),
|
||||||
"isa_page_url": url_for("isa_page", item_id=s["numeric-id"]),
|
"isa_page_url": flask.url_for("isa_page", item_id=s["numeric-id"]),
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
tags = api.get_tags_for_isa_item(item)
|
tags = api.get_tags_for_isa_item(item)
|
||||||
|
|
||||||
return render_template(
|
return flask.render_template(
|
||||||
"isa.html",
|
"isa.html",
|
||||||
item=item,
|
item=item,
|
||||||
extra=extra,
|
extra=extra,
|
||||||
|
@ -183,25 +172,25 @@ def isa_page(item_id):
|
||||||
@app.route("/admin/skip_isa")
|
@app.route("/admin/skip_isa")
|
||||||
def admin_skip_isa_list():
|
def admin_skip_isa_list():
|
||||||
q = model.Item.query.join(model.SkipIsA).order_by(model.Item.item_id)
|
q = model.Item.query.join(model.SkipIsA).order_by(model.Item.item_id)
|
||||||
return render_template("admin/skip_isa.html", q=q)
|
return flask.render_template("admin/skip_isa.html", q=q)
|
||||||
|
|
||||||
|
|
||||||
@app.route("/identifier")
|
@app.route("/identifier")
|
||||||
def identifier_index():
|
def identifier_index():
|
||||||
return render_template("identifier_index.html", property_map=property_map)
|
return flask.render_template("identifier_index.html", property_map=property_map)
|
||||||
|
|
||||||
|
|
||||||
@app.route("/commons/<filename>")
|
@app.route("/commons/<filename>")
|
||||||
def get_commons_image(filename):
|
def get_commons_image(filename):
|
||||||
detail = commons.image_detail([filename], thumbheight=1200, thumbwidth=1200)
|
detail = commons.image_detail([filename], thumbheight=1200, thumbwidth=1200)
|
||||||
image = detail[filename]
|
image = detail[filename]
|
||||||
return redirect(image["thumburl"])
|
return flask.redirect(image["thumburl"])
|
||||||
|
|
||||||
|
|
||||||
@app.route("/identifier/<pid>")
|
@app.route("/identifier/<pid>")
|
||||||
def identifier_page(pid):
|
def identifier_page(pid):
|
||||||
per_page = 10
|
per_page = 10
|
||||||
page = int(request.args.get("page", 1))
|
page = int(flask.request.args.get("page", 1))
|
||||||
property_dict = {pid: (osm_keys, label) for pid, osm_keys, label in property_map}
|
property_dict = {pid: (osm_keys, label) for pid, osm_keys, label in property_map}
|
||||||
osm_keys, label = property_dict[pid]
|
osm_keys, label = property_dict[pid]
|
||||||
|
|
||||||
|
@ -237,7 +226,7 @@ def identifier_page(pid):
|
||||||
|
|
||||||
osm_total = len(osm_points)
|
osm_total = len(osm_points)
|
||||||
|
|
||||||
return render_template(
|
return flask.render_template(
|
||||||
"identifier_page.html",
|
"identifier_page.html",
|
||||||
pid=pid,
|
pid=pid,
|
||||||
osm_keys=osm_keys,
|
osm_keys=osm_keys,
|
||||||
|
@ -260,14 +249,14 @@ def map_start_page():
|
||||||
lat, lon = 42.2917, -85.5872
|
lat, lon = 42.2917, -85.5872
|
||||||
radius = 5
|
radius = 5
|
||||||
|
|
||||||
return redirect(
|
return flask.redirect(
|
||||||
url_for(
|
flask.url_for(
|
||||||
"map_location",
|
"map_location",
|
||||||
lat=f"{lat:.5f}",
|
lat=f"{lat:.5f}",
|
||||||
lon=f"{lon:.5f}",
|
lon=f"{lon:.5f}",
|
||||||
zoom=16,
|
zoom=16,
|
||||||
radius=radius,
|
radius=radius,
|
||||||
ip=request.args.get("ip"),
|
ip=flask.request.args.get("ip"),
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -278,7 +267,7 @@ def documentation_page() -> str:
|
||||||
user = flask_login.current_user
|
user = flask_login.current_user
|
||||||
username = user.username if user.is_authenticated else None
|
username = user.username if user.is_authenticated else None
|
||||||
|
|
||||||
return render_template(
|
return flask.render_template(
|
||||||
"documentation.html", active_tab="documentation", username=username
|
"documentation.html", active_tab="documentation", username=username
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -287,12 +276,12 @@ def documentation_page() -> str:
|
||||||
def search_page() -> str:
|
def search_page() -> str:
|
||||||
"""Search."""
|
"""Search."""
|
||||||
loc = get_user_location()
|
loc = get_user_location()
|
||||||
q = request.args.get("q")
|
q = flask.request.args.get("q")
|
||||||
|
|
||||||
user = flask_login.current_user
|
user = flask_login.current_user
|
||||||
username = user.username if user.is_authenticated else None
|
username = user.username if user.is_authenticated else None
|
||||||
|
|
||||||
return render_template(
|
return flask.render_template(
|
||||||
"map.html",
|
"map.html",
|
||||||
active_tab="map",
|
active_tab="map",
|
||||||
lat=f'{loc["latitude"]:.5f}',
|
lat=f'{loc["latitude"]:.5f}',
|
||||||
|
@ -307,8 +296,8 @@ def search_page() -> str:
|
||||||
|
|
||||||
@app.route("/map/<int:zoom>/<float(signed=True):lat>/<float(signed=True):lon>")
|
@app.route("/map/<int:zoom>/<float(signed=True):lat>/<float(signed=True):lon>")
|
||||||
def map_location(zoom, lat, lon):
|
def map_location(zoom, lat, lon):
|
||||||
qid = request.args.get("item")
|
qid = flask.request.args.get("item")
|
||||||
isa_param = request.args.get("isa")
|
isa_param = flask.request.args.get("isa")
|
||||||
if qid:
|
if qid:
|
||||||
api.get_item(qid[1:])
|
api.get_item(qid[1:])
|
||||||
|
|
||||||
|
@ -324,13 +313,13 @@ def map_location(zoom, lat, lon):
|
||||||
}
|
}
|
||||||
isa_list.append(cur)
|
isa_list.append(cur)
|
||||||
|
|
||||||
return render_template(
|
return flask.render_template(
|
||||||
"map.html",
|
"map.html",
|
||||||
active_tab="map",
|
active_tab="map",
|
||||||
zoom=zoom,
|
zoom=zoom,
|
||||||
lat=lat,
|
lat=lat,
|
||||||
lon=lon,
|
lon=lon,
|
||||||
radius=request.args.get("radius"),
|
radius=flask.request.args.get("radius"),
|
||||||
username=get_username(),
|
username=get_username(),
|
||||||
mode="map",
|
mode="map",
|
||||||
q=None,
|
q=None,
|
||||||
|
@ -343,15 +332,15 @@ def lookup_item(item_id):
|
||||||
item = api.get_item(item_id)
|
item = api.get_item(item_id)
|
||||||
if not item:
|
if not item:
|
||||||
# TODO: show nicer page for Wikidata item not found
|
# TODO: show nicer page for Wikidata item not found
|
||||||
return abort(404)
|
return flask.abort(404)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
lat, lon = item.locations[0].get_lat_lon()
|
lat, lon = item.locations[0].get_lat_lon()
|
||||||
except IndexError:
|
except IndexError:
|
||||||
# TODO: show nicer page for Wikidata item without coordinates
|
# TODO: show nicer page for Wikidata item without coordinates
|
||||||
return abort(404)
|
return flask.abort(404)
|
||||||
|
|
||||||
return render_template(
|
return flask.render_template(
|
||||||
"map.html",
|
"map.html",
|
||||||
active_tab="map",
|
active_tab="map",
|
||||||
zoom=16,
|
zoom=16,
|
||||||
|
@ -364,17 +353,17 @@ def lookup_item(item_id):
|
||||||
item_type_filter=[],
|
item_type_filter=[],
|
||||||
)
|
)
|
||||||
|
|
||||||
url = url_for("map_location", zoom=16, lat=lat, lon=lon, item=item.qid)
|
url = flask.url_for("map_location", zoom=16, lat=lat, lon=lon, item=item.qid)
|
||||||
return redirect(url)
|
return flask.redirect(url)
|
||||||
|
|
||||||
|
|
||||||
@app.route("/search/map")
|
@app.route("/search/map")
|
||||||
def search_map_page():
|
def search_map_page():
|
||||||
user_lat, user_lon = get_user_location() or (None, None)
|
user_lat, user_lon = get_user_location() or (None, None)
|
||||||
|
|
||||||
q = request.args.get("q")
|
q = flask.request.args.get("q")
|
||||||
if not q:
|
if not q:
|
||||||
return render_template("map.html", user_lat=user_lat, user_lon=user_lon)
|
return flask.render_template("map.html", user_lat=user_lat, user_lon=user_lon)
|
||||||
|
|
||||||
hits = nominatim.lookup(q)
|
hits = nominatim.lookup(q)
|
||||||
for hit in hits:
|
for hit in hits:
|
||||||
|
@ -382,7 +371,7 @@ def search_map_page():
|
||||||
del hit["geotext"]
|
del hit["geotext"]
|
||||||
bbox = [hit["boundingbox"] for hit in hits]
|
bbox = [hit["boundingbox"] for hit in hits]
|
||||||
|
|
||||||
return render_template(
|
return flask.render_template(
|
||||||
"search_map.html",
|
"search_map.html",
|
||||||
hits=hits,
|
hits=hits,
|
||||||
bbox_list=bbox,
|
bbox_list=bbox,
|
||||||
|
@ -393,23 +382,23 @@ def search_map_page():
|
||||||
|
|
||||||
@app.route("/old_search")
|
@app.route("/old_search")
|
||||||
def old_search_page():
|
def old_search_page():
|
||||||
q = request.args.get("q")
|
q = flask.request.args.get("q")
|
||||||
if not q:
|
if not q:
|
||||||
return render_template("search.html", hits=None, bbox_list=None)
|
return flask.render_template("search.html", hits=None, bbox_list=None)
|
||||||
hits = nominatim.lookup(q)
|
hits = nominatim.lookup(q)
|
||||||
for hit in hits:
|
for hit in hits:
|
||||||
if "geotext" in hit:
|
if "geotext" in hit:
|
||||||
del hit["geotext"]
|
del hit["geotext"]
|
||||||
bbox = [hit["boundingbox"] for hit in hits]
|
bbox = [hit["boundingbox"] for hit in hits]
|
||||||
return render_template("search.html", hits=hits, bbox_list=bbox)
|
return flask.render_template("search.html", hits=hits, bbox_list=bbox)
|
||||||
|
|
||||||
|
|
||||||
def read_bounds_param():
|
def read_bounds_param():
|
||||||
return [float(i) for i in request.args["bounds"].split(",")]
|
return [float(i) for i in flask.request.args["bounds"].split(",")]
|
||||||
|
|
||||||
|
|
||||||
def read_isa_filter_param():
|
def read_isa_filter_param():
|
||||||
isa_param = request.args.get("isa")
|
isa_param = flask.request.args.get("isa")
|
||||||
if isa_param:
|
if isa_param:
|
||||||
return set(qid.strip() for qid in isa_param.upper().split(","))
|
return set(qid.strip() for qid in isa_param.upper().split(","))
|
||||||
|
|
||||||
|
@ -432,7 +421,7 @@ def api_wikidata_items_count():
|
||||||
@app.route("/api/1/isa_search")
|
@app.route("/api/1/isa_search")
|
||||||
def api_isa_search():
|
def api_isa_search():
|
||||||
t0 = time()
|
t0 = time()
|
||||||
search_terms = request.args.get("q")
|
search_terms = flask.request.args.get("q")
|
||||||
items = api.isa_incremental_search(search_terms)
|
items = api.isa_incremental_search(search_terms)
|
||||||
t1 = time() - t0
|
t1 = time() - t0
|
||||||
|
|
||||||
|
@ -577,7 +566,7 @@ def api_find_osm_candidates(item_id):
|
||||||
@app.route("/api/1/missing")
|
@app.route("/api/1/missing")
|
||||||
def api_missing_wikidata_items():
|
def api_missing_wikidata_items():
|
||||||
t0 = time()
|
t0 = time()
|
||||||
qids_arg = request.args.get("qids")
|
qids_arg = flask.request.args.get("qids")
|
||||||
if not qids_arg:
|
if not qids_arg:
|
||||||
return cors_jsonify(
|
return cors_jsonify(
|
||||||
success=False,
|
success=False,
|
||||||
|
@ -594,9 +583,9 @@ def api_missing_wikidata_items():
|
||||||
continue
|
continue
|
||||||
qids.append(qid)
|
qids.append(qid)
|
||||||
if not qids:
|
if not qids:
|
||||||
return jsonify(success=True, items=[], isa_count=[])
|
return flask.jsonify(success=True, items=[], isa_count=[])
|
||||||
|
|
||||||
lat, lon = request.args.get("lat"), request.args.get("lon")
|
lat, lon = flask.request.args.get("lat"), flask.request.args.get("lon")
|
||||||
|
|
||||||
ret = api.missing_wikidata_items(qids, lat, lon)
|
ret = api.missing_wikidata_items(qids, lat, lon)
|
||||||
t1 = time() - t0
|
t1 = time() - t0
|
||||||
|
@ -605,7 +594,7 @@ def api_missing_wikidata_items():
|
||||||
|
|
||||||
@app.route("/api/1/search")
|
@app.route("/api/1/search")
|
||||||
def api_search():
|
def api_search():
|
||||||
q = request.args["q"]
|
q = flask.request.args["q"]
|
||||||
hits = nominatim.lookup(q)
|
hits = nominatim.lookup(q)
|
||||||
for hit in hits:
|
for hit in hits:
|
||||||
hit["name"] = nominatim.get_hit_name(hit)
|
hit["name"] = nominatim.get_hit_name(hit)
|
||||||
|
@ -629,7 +618,8 @@ def api_polygon(osm_type, osm_id):
|
||||||
|
|
||||||
|
|
||||||
@app.route("/refresh/Q<int:item_id>")
|
@app.route("/refresh/Q<int:item_id>")
|
||||||
def refresh_item(item_id):
|
def refresh_item(item_id: int) -> str:
|
||||||
|
"""Refresh the local mirror of a Wikidata item."""
|
||||||
assert not model.Item.query.get(item_id)
|
assert not model.Item.query.get(item_id)
|
||||||
|
|
||||||
qid = f"Q{item_id}"
|
qid = f"Q{item_id}"
|
||||||
|
@ -651,50 +641,55 @@ def refresh_item(item_id):
|
||||||
|
|
||||||
|
|
||||||
@app.route("/login")
|
@app.route("/login")
|
||||||
def login_openstreetmap():
|
def login_openstreetmap() -> flask.Response:
|
||||||
return redirect(url_for("start_oauth", next=request.args.get("next")))
|
"""Redirect to login."""
|
||||||
|
return flask.redirect(
|
||||||
|
flask.url_for("start_oauth", next=flask.request.args.get("next"))
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@app.route("/logout")
|
@app.route("/logout")
|
||||||
def logout():
|
def logout() -> flask.Response:
|
||||||
next_url = request.args.get("next") or url_for("map_start_page")
|
"""Logout."""
|
||||||
|
next_url = flask.request.args.get("next") or flask.url_for("map_start_page")
|
||||||
flask_login.logout_user()
|
flask_login.logout_user()
|
||||||
flash("you are logged out")
|
flask.flash("you are logged out")
|
||||||
return redirect(next_url)
|
return flask.redirect(next_url)
|
||||||
|
|
||||||
|
|
||||||
@app.route("/done/")
|
@app.route("/done/")
|
||||||
def done():
|
def done():
|
||||||
flash("login successful")
|
flask.flash("login successful")
|
||||||
return redirect(url_for("map_start_page"))
|
return flask.redirect(flask.url_for("map_start_page"))
|
||||||
|
|
||||||
|
|
||||||
@app.route("/oauth/start")
|
@app.route("/oauth/start")
|
||||||
def start_oauth():
|
def start_oauth():
|
||||||
next_page = request.args.get("next")
|
"""Start OAuth."""
|
||||||
|
next_page = flask.request.args.get("next")
|
||||||
if next_page:
|
if next_page:
|
||||||
session["next"] = next_page
|
flask.session["next"] = next_page
|
||||||
|
|
||||||
client_key = app.config["CLIENT_KEY"]
|
client_key = app.config["CLIENT_KEY"]
|
||||||
client_secret = app.config["CLIENT_SECRET"]
|
client_secret = app.config["CLIENT_SECRET"]
|
||||||
|
|
||||||
request_token_url = "https://www.openstreetmap.org/oauth/request_token"
|
request_token_url = "https://www.openstreetmap.org/oauth/request_token"
|
||||||
|
|
||||||
callback = url_for("oauth_callback", _external=True)
|
callback = flask.url_for("oauth_callback", _external=True)
|
||||||
|
|
||||||
oauth = OAuth1Session(
|
oauth = OAuth1Session(
|
||||||
client_key, client_secret=client_secret, callback_uri=callback
|
client_key, client_secret=client_secret, callback_uri=callback
|
||||||
)
|
)
|
||||||
fetch_response = oauth.fetch_request_token(request_token_url)
|
fetch_response = oauth.fetch_request_token(request_token_url)
|
||||||
|
|
||||||
session["owner_key"] = fetch_response.get("oauth_token")
|
flask.session["owner_key"] = fetch_response.get("oauth_token")
|
||||||
session["owner_secret"] = fetch_response.get("oauth_token_secret")
|
flask.session["owner_secret"] = fetch_response.get("oauth_token_secret")
|
||||||
|
|
||||||
base_authorization_url = "https://www.openstreetmap.org/oauth/authorize"
|
base_authorization_url = "https://www.openstreetmap.org/oauth/authorize"
|
||||||
authorization_url = oauth.authorization_url(
|
authorization_url = oauth.authorization_url(
|
||||||
base_authorization_url, oauth_consumer_key=client_key
|
base_authorization_url, oauth_consumer_key=client_key
|
||||||
)
|
)
|
||||||
return redirect(authorization_url)
|
return flask.redirect(authorization_url)
|
||||||
|
|
||||||
|
|
||||||
@login_manager.user_loader
|
@login_manager.user_loader
|
||||||
|
@ -711,24 +706,24 @@ def oauth_callback():
|
||||||
oauth = OAuth1Session(
|
oauth = OAuth1Session(
|
||||||
client_key,
|
client_key,
|
||||||
client_secret=client_secret,
|
client_secret=client_secret,
|
||||||
resource_owner_key=session["owner_key"],
|
resource_owner_key=flask.session["owner_key"],
|
||||||
resource_owner_secret=session["owner_secret"],
|
resource_owner_secret=flask.session["owner_secret"],
|
||||||
)
|
)
|
||||||
|
|
||||||
oauth_response = oauth.parse_authorization_response(request.url)
|
oauth_response = oauth.parse_authorization_response(flask.request.url)
|
||||||
verifier = oauth_response.get("oauth_verifier")
|
verifier = oauth_response.get("oauth_verifier")
|
||||||
access_token_url = "https://www.openstreetmap.org/oauth/access_token"
|
access_token_url = "https://www.openstreetmap.org/oauth/access_token"
|
||||||
oauth = OAuth1Session(
|
oauth = OAuth1Session(
|
||||||
client_key,
|
client_key,
|
||||||
client_secret=client_secret,
|
client_secret=client_secret,
|
||||||
resource_owner_key=session["owner_key"],
|
resource_owner_key=flask.session["owner_key"],
|
||||||
resource_owner_secret=session["owner_secret"],
|
resource_owner_secret=flask.session["owner_secret"],
|
||||||
verifier=verifier,
|
verifier=verifier,
|
||||||
)
|
)
|
||||||
|
|
||||||
oauth_tokens = oauth.fetch_access_token(access_token_url)
|
oauth_tokens = oauth.fetch_access_token(access_token_url)
|
||||||
session["owner_key"] = oauth_tokens.get("oauth_token")
|
flask.session["owner_key"] = oauth_tokens.get("oauth_token")
|
||||||
session["owner_secret"] = oauth_tokens.get("oauth_token_secret")
|
flask.session["owner_secret"] = oauth_tokens.get("oauth_token_secret")
|
||||||
|
|
||||||
r = oauth.get(osm_api_base + "/user/details")
|
r = oauth.get(osm_api_base + "/user/details")
|
||||||
info = osm_oauth.parse_userinfo_call(r.content)
|
info = osm_oauth.parse_userinfo_call(r.content)
|
||||||
|
@ -751,8 +746,8 @@ def oauth_callback():
|
||||||
database.session.commit()
|
database.session.commit()
|
||||||
flask_login.login_user(user)
|
flask_login.login_user(user)
|
||||||
|
|
||||||
next_page = session.get("next") or url_for("map_start_page")
|
next_page = flask.session.get("next") or flask.url_for("map_start_page")
|
||||||
return redirect(next_page)
|
return flask.redirect(next_page)
|
||||||
|
|
||||||
|
|
||||||
def validate_edit_list(edits):
|
def validate_edit_list(edits):
|
||||||
|
@ -771,7 +766,7 @@ def validate_edit_list(edits):
|
||||||
@app.route("/api/1/edit", methods=["POST"])
|
@app.route("/api/1/edit", methods=["POST"])
|
||||||
def api_new_edit_session():
|
def api_new_edit_session():
|
||||||
user = flask_login.current_user
|
user = flask_login.current_user
|
||||||
incoming = request.json
|
incoming = flask.request.json
|
||||||
|
|
||||||
validate_edit_list(incoming["edit_list"])
|
validate_edit_list(incoming["edit_list"])
|
||||||
es = model.EditSession(
|
es = model.EditSession(
|
||||||
|
@ -789,7 +784,7 @@ def api_new_edit_session():
|
||||||
def api_edit_session(session_id):
|
def api_edit_session(session_id):
|
||||||
es = model.EditSession.query.get(session_id)
|
es = model.EditSession.query.get(session_id)
|
||||||
assert flask_login.current_user.id == es.user_id
|
assert flask_login.current_user.id == es.user_id
|
||||||
incoming = request.json
|
incoming = flask.request.json
|
||||||
|
|
||||||
for f in "edit_list", "comment":
|
for f in "edit_list", "comment":
|
||||||
if f not in incoming:
|
if f not in incoming:
|
||||||
|
@ -889,9 +884,9 @@ def process_edit(changeset_id, e):
|
||||||
|
|
||||||
@app.route("/api/1/save/<int:session_id>")
|
@app.route("/api/1/save/<int:session_id>")
|
||||||
def api_save_changeset(session_id: int):
|
def api_save_changeset(session_id: int):
|
||||||
assert g.user.is_authenticated
|
assert flask.g.user.is_authenticated
|
||||||
|
|
||||||
mock = g.user.mock_upload
|
mock = flask.g.user.mock_upload
|
||||||
api_call = api_mock_save_changeset if mock else api_real_save_changeset
|
api_call = api_mock_save_changeset if mock else api_real_save_changeset
|
||||||
return api_call(session_id)
|
return api_call(session_id)
|
||||||
|
|
||||||
|
@ -899,14 +894,14 @@ def api_save_changeset(session_id: int):
|
||||||
@app.route("/sql", methods=["GET", "POST"])
|
@app.route("/sql", methods=["GET", "POST"])
|
||||||
def run_sql() -> str:
|
def run_sql() -> str:
|
||||||
"""Web form where the user can run an SQL query."""
|
"""Web form where the user can run an SQL query."""
|
||||||
if request.method != "POST":
|
if flask.request.method != "POST":
|
||||||
return render_template("run_sql.html")
|
return flask.render_template("run_sql.html")
|
||||||
|
|
||||||
sql = request.form["sql"]
|
sql = flask.request.form["sql"]
|
||||||
conn = database.session.connection()
|
conn = database.session.connection()
|
||||||
result = conn.execute(sqlalchemy.text(sql))
|
result = conn.execute(sqlalchemy.text(sql))
|
||||||
|
|
||||||
return render_template("run_sql.html", result=result)
|
return flask.render_template("run_sql.html", result=result)
|
||||||
|
|
||||||
|
|
||||||
def api_real_save_changeset(session_id):
|
def api_real_save_changeset(session_id):
|
||||||
|
@ -959,7 +954,9 @@ def api_real_save_changeset(session_id):
|
||||||
edit.close_changeset(changeset_id)
|
edit.close_changeset(changeset_id)
|
||||||
yield send("done")
|
yield send("done")
|
||||||
|
|
||||||
return Response(stream_with_context(stream(g.user)), mimetype="text/event-stream")
|
return flask.Response(
|
||||||
|
flask.stream_with_context(stream(flask.g.user)), mimetype="text/event-stream"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def api_mock_save_changeset(session_id):
|
def api_mock_save_changeset(session_id):
|
||||||
|
@ -997,7 +994,7 @@ def api_mock_save_changeset(session_id):
|
||||||
sleep(1)
|
sleep(1)
|
||||||
yield send("done")
|
yield send("done")
|
||||||
|
|
||||||
return Response(stream(g.user), mimetype="text/event-stream")
|
return flask.Response(stream(flask.g.user), mimetype="text/event-stream")
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|
Loading…
Reference in a new issue