Add OSM login

This commit is contained in:
Edward Betts 2021-06-16 15:42:04 +02:00
parent b18c846af9
commit 735e833fc9
3 changed files with 210 additions and 4 deletions

View file

@ -2,14 +2,15 @@ from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.schema import ForeignKey, Column
from sqlalchemy.orm import relationship, column_property, deferred
from sqlalchemy import func
from sqlalchemy.types import Integer, String, Float
from sqlalchemy.types import Integer, String, Float, Boolean, DateTime, Text
from sqlalchemy.dialects import postgresql
from sqlalchemy.sql.expression import cast
from sqlalchemy.ext.hybrid import hybrid_property
from sqlalchemy.ext.declarative import declared_attr
from geoalchemy2 import Geography, Geometry
from collections import defaultdict
from .database import session
from flask_login import UserMixin
from .database import session, now_utc
from . import wikidata, utils
import json
import re
@ -263,3 +264,30 @@ class Polygon(MapMixin, Base):
@hybrid_property
def area_in_sq_km(self):
return self.area / (1000 * 1000)
class User(Base, UserMixin):
__tablename__ = 'user'
id = Column(Integer, primary_key=True)
username = Column(String)
password = Column(String)
name = Column(String)
email = Column(String)
active = Column(Boolean, default=True)
sign_up = Column(DateTime, default=now_utc())
is_admin = Column(Boolean, default=False)
description = Column(Text)
img = Column(String) # OSM avatar
languages = Column(postgresql.ARRAY(String))
single = Column(String)
multi = Column(String)
units = Column(String)
wikipedia_tag = Column(Boolean, default=False)
osm_id = Column(Integer, index=True)
osm_account_created = Column(DateTime)
osm_oauth_token = Column(String)
osm_oauth_token_secret = Column(String)
def is_active(self):
return self.active

77
matcher/osm_oauth.py Normal file
View file

@ -0,0 +1,77 @@
from flask import current_app, session
from requests_oauthlib import OAuth1Session
from urllib.parse import urlencode
from datetime import datetime
from flask import g
from .model import User
from . import user_agent_headers
import lxml.etree
osm_api_base = "https://api.openstreetmap.org/api/0.6"
def api_put_request(path, **kwargs):
user = g.user
assert user.is_authenticated
oauth = OAuth1Session(
current_app.config["CLIENT_KEY"],
client_secret=current_app.config["CLIENT_SECRET"],
resource_owner_key=user.osm_oauth_token,
resource_owner_secret=user.osm_oauth_token_secret,
)
return oauth.request(
"PUT", osm_api_base + path, headers=user_agent_headers(), **kwargs
)
def api_request(path, **params):
user = g.user
assert user.is_authenticated
app = current_app
url = osm_api_base + path
if params:
url += "?" + urlencode(params)
client_key = app.config["CLIENT_KEY"]
client_secret = app.config["CLIENT_SECRET"]
oauth = OAuth1Session(
client_key,
client_secret=client_secret,
resource_owner_key=user.osm_oauth_token,
resource_owner_secret=user.osm_oauth_token_secret,
)
return oauth.get(url, timeout=4)
def parse_iso_date(value):
return datetime.strptime(value, "%Y-%m-%dT%H:%M:%SZ")
def parse_userinfo_call(xml):
root = lxml.etree.fromstring(xml)
user = root[0]
img = user.find(".//img")
account_created = parse_iso_date(user.get("account_created"))
assert user.tag == "user"
return {
"account_created": account_created,
"id": int(user.get("id")),
"username": user.get("display_name"),
"description": user.findtext(".//description"),
"img": (img.get("href") if img is not None else None),
}
def get_username():
if "user_id" not in session:
return # not authorized
user_id = session["user_id"]
user = User.query.get(user_id)
return user.username