2020-10-26 20:44:15 +01:00
|
|
|
defmodule Ueberauth.Strategy.OpenStreetMap do
|
2015-11-18 04:34:55 +01:00
|
|
|
@moduledoc """
|
2020-10-26 20:44:15 +01:00
|
|
|
Opestreetmap Strategy for Überauth.
|
2015-11-18 04:34:55 +01:00
|
|
|
"""
|
|
|
|
|
|
|
|
use Ueberauth.Strategy, uid_field: :id_str
|
|
|
|
|
|
|
|
alias Ueberauth.Auth.Info
|
|
|
|
alias Ueberauth.Auth.Credentials
|
|
|
|
alias Ueberauth.Auth.Extra
|
2020-10-26 20:44:15 +01:00
|
|
|
alias Ueberauth.Strategy.OpenStreetMap
|
2015-11-18 04:34:55 +01:00
|
|
|
|
|
|
|
@doc """
|
2020-10-26 20:44:15 +01:00
|
|
|
Handles initial request for OpenStreetMap authentication.
|
2015-11-18 04:34:55 +01:00
|
|
|
"""
|
|
|
|
def handle_request!(conn) do
|
2020-10-26 20:44:15 +01:00
|
|
|
token = OpenStreetMap.OAuth.request_token!([], [redirect_uri: callback_url(conn)])
|
2015-11-18 04:34:55 +01:00
|
|
|
|
|
|
|
conn
|
2020-10-26 20:44:15 +01:00
|
|
|
|> put_session(:OpenStreetMap_token, token)
|
|
|
|
|> redirect!(OpenStreetMap.OAuth.authorize_url!(token))
|
2015-11-18 04:34:55 +01:00
|
|
|
end
|
|
|
|
|
|
|
|
@doc """
|
2020-10-26 20:44:15 +01:00
|
|
|
Handles the callback from OpenStreetMap.
|
2015-11-18 04:34:55 +01:00
|
|
|
"""
|
|
|
|
def handle_callback!(%Plug.Conn{params: %{"oauth_verifier" => oauth_verifier}} = conn) do
|
2020-10-26 20:44:15 +01:00
|
|
|
token = get_session(conn, :OpenStreetMap_token)
|
|
|
|
case OpenStreetMap.OAuth.access_token(token, oauth_verifier) do
|
2015-11-18 04:34:55 +01:00
|
|
|
{:ok, access_token} -> fetch_user(conn, access_token)
|
|
|
|
{:error, error} -> set_errors!(conn, [error(error.code, error.reason)])
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
@doc false
|
|
|
|
def handle_callback!(conn) do
|
|
|
|
set_errors!(conn, [error("missing_code", "No code received")])
|
|
|
|
end
|
|
|
|
|
|
|
|
@doc false
|
|
|
|
def handle_cleanup!(conn) do
|
|
|
|
conn
|
2020-10-26 20:44:15 +01:00
|
|
|
|> put_private(:OpenStreetMap_user, nil)
|
|
|
|
|> put_session(:OpenStreetMap_token, nil)
|
2015-11-18 04:34:55 +01:00
|
|
|
end
|
|
|
|
|
|
|
|
@doc """
|
|
|
|
Fetches the uid field from the response.
|
|
|
|
"""
|
|
|
|
def uid(conn) do
|
|
|
|
uid_field =
|
|
|
|
conn
|
|
|
|
|> option(:uid_field)
|
|
|
|
|> to_string
|
|
|
|
|
2020-10-26 20:44:15 +01:00
|
|
|
conn.private.OpenStreetMap_user[uid_field]
|
2015-11-18 04:34:55 +01:00
|
|
|
end
|
|
|
|
|
|
|
|
@doc """
|
2020-10-26 20:44:15 +01:00
|
|
|
Includes the credentials from the OpenStreetMap response.
|
2015-11-18 04:34:55 +01:00
|
|
|
"""
|
|
|
|
def credentials(conn) do
|
2020-10-26 20:44:15 +01:00
|
|
|
{token, secret} = conn.private.OpenStreetMap_token
|
2015-11-18 04:34:55 +01:00
|
|
|
|
2015-12-19 18:28:42 +01:00
|
|
|
%Credentials{token: token, secret: secret}
|
2015-11-18 04:34:55 +01:00
|
|
|
end
|
|
|
|
|
|
|
|
@doc """
|
|
|
|
Fetches the fields to populate the info section of the `Ueberauth.Auth` struct.
|
|
|
|
"""
|
|
|
|
def info(conn) do
|
2020-10-26 20:44:15 +01:00
|
|
|
user = conn.private.OpenStreetMap_user
|
2015-11-18 04:34:55 +01:00
|
|
|
|
|
|
|
%Info{
|
|
|
|
email: user["email"],
|
2018-02-13 19:29:08 +01:00
|
|
|
image: user["profile_image_url_https"],
|
2015-11-18 04:34:55 +01:00
|
|
|
name: user["name"],
|
|
|
|
nickname: user["screen_name"],
|
|
|
|
description: user["description"],
|
2018-02-13 19:30:01 +01:00
|
|
|
location: user["location"],
|
2015-11-18 04:34:55 +01:00
|
|
|
urls: %{
|
2020-10-26 20:44:15 +01:00
|
|
|
OpenStreetMap: "https://OpenStreetMap.com/#{user["screen_name"]}",
|
2015-11-18 04:34:55 +01:00
|
|
|
Website: user["url"]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
end
|
|
|
|
|
|
|
|
@doc """
|
2020-10-26 20:44:15 +01:00
|
|
|
Stores the raw information (including the token) obtained from the OpenStreetMap callback.
|
2015-11-18 04:34:55 +01:00
|
|
|
"""
|
|
|
|
def extra(conn) do
|
2020-10-26 20:44:15 +01:00
|
|
|
{token, _secret} = get_session(conn, :OpenStreetMap_token)
|
2015-11-18 04:34:55 +01:00
|
|
|
|
|
|
|
%Extra{
|
|
|
|
raw_info: %{
|
|
|
|
token: token,
|
2020-10-26 20:44:15 +01:00
|
|
|
user: conn.private.OpenStreetMap_user
|
2015-11-18 04:34:55 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
end
|
|
|
|
|
|
|
|
defp fetch_user(conn, token) do
|
2017-03-15 20:15:49 +01:00
|
|
|
params = [{"include_entities", false}, {"skip_status", true}, {"include_email", true}]
|
2019-10-23 19:49:20 +02:00
|
|
|
|
2020-10-26 20:44:15 +01:00
|
|
|
case OpenStreetMap.OAuth.get("/1.1/account/verify_credentials.json", params, token) do
|
2017-03-15 20:15:49 +01:00
|
|
|
{:ok, %{status_code: 401, body: _, headers: _}} ->
|
2015-11-18 04:34:55 +01:00
|
|
|
set_errors!(conn, [error("token", "unauthorized")])
|
|
|
|
|
2019-10-23 19:49:20 +02:00
|
|
|
{:ok, %{status_code: status_code, body: body, headers: _}} when status_code in 200..399 ->
|
2015-11-18 04:34:55 +01:00
|
|
|
conn
|
2020-10-26 20:44:15 +01:00
|
|
|
|> put_private(:OpenStreetMap_token, token)
|
|
|
|
|> put_private(:OpenStreetMap_user, body)
|
2019-10-23 19:49:20 +02:00
|
|
|
|
2017-03-15 20:15:49 +01:00
|
|
|
{:ok, %{status_code: _, body: body, headers: _}} ->
|
2015-11-18 04:34:55 +01:00
|
|
|
error = List.first(body["errors"])
|
|
|
|
set_errors!(conn, [error("token", error["message"])])
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
defp option(conn, key) do
|
2017-03-15 20:15:49 +01:00
|
|
|
default = Keyword.get(default_options(), key)
|
|
|
|
|
|
|
|
conn
|
|
|
|
|> options
|
|
|
|
|> Keyword.get(key, default)
|
2015-11-18 04:34:55 +01:00
|
|
|
end
|
|
|
|
end
|