feat: mastodon accounts
This commit is contained in:
parent
fcffea0ef7
commit
96e778ff91
18 changed files with 215 additions and 3 deletions
|
@ -2,10 +2,13 @@
|
|||
# and accessories/*/env/secret in config/deploy.yml. All secrets should be pulled from either
|
||||
# password manager, ENV, or a file. DO NOT ENTER RAW CREDENTIALS HERE! This file needs to be safe for git.
|
||||
|
||||
SECRETS=$(kamal secrets fetch --adapter 1password --account Perrault --from Private/sloanelybutsurely.com KAMAL_REGISTRY_PASSWORD POSTGRES_PASSWORD SECRET_KEY_BASE)
|
||||
SECRETS=$(kamal secrets fetch --adapter 1password --account Perrault --from Private/sloanelybutsurely.com KAMAL_REGISTRY_PASSWORD POSTGRES_PASSWORD SECRET_KEY_BASE MASTODON_CLIENT_ID MASTODON_CLIENT_SECRET)
|
||||
|
||||
KAMAL_REGISTRY_PASSWORD=$(kamal secrets extract KAMAL_REGISTRY_PASSWORD $SECRETS)
|
||||
POSTGRES_PASSWORD=$(kamal secrets extract POSTGRES_PASSWORD $SECRETS)
|
||||
SECRET_KEY_BASE=$(kamal secrets extract SECRET_KEY_BASE $SECRETS)
|
||||
|
||||
DATABASE_URL="postgresql://sloanely_but_surely_prod:$POSTGRES_PASSWORD@sloanelybutsurely-db:5432/sloanely_but_surely_prod"
|
||||
|
||||
MASTODON_CLIENT_ID=$(kamal secrets extract MASTODON_CLIENT_ID $SECRETS)
|
||||
MASTODON_CLIENT_SECRET=$(kamal secrets extract MASTODON_CLIENT_SECRET $SECRETS)
|
||||
|
|
|
@ -59,4 +59,18 @@ config :tailwind,
|
|||
|
||||
config :flop, repo: Core.Repo
|
||||
|
||||
config :tesla, adapter: Tesla.Adapter.Mint
|
||||
|
||||
config :ueberauth, Ueberauth,
|
||||
providers: [
|
||||
mastodon:
|
||||
{Ueberauth.Strategy.Mastodon,
|
||||
[
|
||||
instance: "https://tech.lgbt",
|
||||
client_id: {System, :get_env, ["MASTODON_CLIENT_ID"]},
|
||||
client_secret: {System, :get_env, ["MASTODON_CLIENT_SECRET"]},
|
||||
scope: "read write push"
|
||||
]}
|
||||
]
|
||||
|
||||
import_config "#{config_env()}.exs"
|
||||
|
|
|
@ -12,6 +12,8 @@ env:
|
|||
secret:
|
||||
- DATABASE_URL
|
||||
- SECRET_KEY_BASE
|
||||
- MASTODON_CLIENT_ID
|
||||
- MASTODON_CLIENT_SECRET
|
||||
|
||||
# Enable SSL auto certification via Let's Encrypt and allow for multiple apps on a single web server.
|
||||
# Remove this section when using multiple web servers and ensure you terminate SSL at your load balancer.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
defmodule Core do
|
||||
@moduledoc false
|
||||
use Boundary, deps: [Schema], exports: [Accounts, Posts, Author, DateTime, Release]
|
||||
use Boundary, deps: [Schema], exports: [Accounts, Posts, Author, DateTime, Release, Syndication]
|
||||
end
|
||||
|
|
14
lib/core/syndication.ex
Normal file
14
lib/core/syndication.ex
Normal file
|
@ -0,0 +1,14 @@
|
|||
defmodule Core.Syndication do
|
||||
alias __MODULE__
|
||||
|
||||
def get_mastodon_account(user) do
|
||||
Core.Repo.get_by(Schema.MastodonAccount, user_id: user.id)
|
||||
end
|
||||
|
||||
def save_mastodon_account(user, attrs) do
|
||||
user
|
||||
|> Ecto.build_assoc(:mastodon_account)
|
||||
|> Syndication.MastodonAccount.changeset(attrs)
|
||||
|> Core.Repo.insert()
|
||||
end
|
||||
end
|
11
lib/core/syndication/mastodon_account.ex
Normal file
11
lib/core/syndication/mastodon_account.ex
Normal file
|
@ -0,0 +1,11 @@
|
|||
defmodule Core.Syndication.MastodonAccount do
|
||||
import Ecto.Changeset
|
||||
|
||||
def changeset(%Schema.MastodonAccount{} = mastodon_account, attrs) do
|
||||
mastodon_account
|
||||
|> cast(attrs, [:uid, :access_token])
|
||||
|> validate_required([:uid, :access_token])
|
||||
|> unique_constraint(:user_id)
|
||||
|> unique_constraint(:uid)
|
||||
end
|
||||
end
|
|
@ -1,6 +1,6 @@
|
|||
defmodule Schema do
|
||||
@moduledoc false
|
||||
use Boundary, deps: [], exports: [Post, User, UserToken]
|
||||
use Boundary, deps: [], exports: [Post, User, UserToken, MastodonAccount]
|
||||
|
||||
defmacro __using__(_) do
|
||||
quote do
|
||||
|
|
12
lib/schema/mastodon_account.ex
Normal file
12
lib/schema/mastodon_account.ex
Normal file
|
@ -0,0 +1,12 @@
|
|||
defmodule Schema.MastodonAccount do
|
||||
use Schema
|
||||
|
||||
schema "mastodon_accounts" do
|
||||
field :uid, :string
|
||||
field :access_token, :string, redact: true
|
||||
|
||||
belongs_to :user, Schema.User
|
||||
|
||||
timestamps()
|
||||
end
|
||||
end
|
|
@ -8,6 +8,8 @@ defmodule Schema.User do
|
|||
field :hashed_password, :string, redact: true
|
||||
field :current_password, :string, virtual: true, redact: true
|
||||
|
||||
has_one :mastodon_account, Schema.MastodonAccount
|
||||
|
||||
timestamps(type: :utc_datetime_usec)
|
||||
end
|
||||
end
|
||||
|
|
26
lib/web/controllers/auth_controller.ex
Normal file
26
lib/web/controllers/auth_controller.ex
Normal file
|
@ -0,0 +1,26 @@
|
|||
defmodule Web.AuthController do
|
||||
use Web, :controller
|
||||
|
||||
plug Ueberauth
|
||||
|
||||
def callback(
|
||||
%{assigns: %{ueberauth_auth: %{provider: :mastodon} = auth, current_user: user}} = conn,
|
||||
_params
|
||||
) do
|
||||
{:ok, _mastodon_account} =
|
||||
Core.Syndication.save_mastodon_account(user, %{
|
||||
uid: auth.uid,
|
||||
access_token: auth.credentials.token
|
||||
})
|
||||
|
||||
conn
|
||||
|> put_flash(:info, "Mastodon account registered")
|
||||
|> redirect(to: ~p"/admin/syndication")
|
||||
end
|
||||
|
||||
def callback(conn, _params) do
|
||||
conn
|
||||
|> put_flash(:error, "Mastodon auth failure")
|
||||
|> redirect(to: ~p"/admin/syndication")
|
||||
end
|
||||
end
|
|
@ -12,6 +12,11 @@
|
|||
microblog
|
||||
</.link>
|
||||
</li>
|
||||
<li>
|
||||
<.link navigate={~p"/admin/syndication"}>
|
||||
syndication
|
||||
</.link>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</header>
|
||||
|
|
13
lib/web/live/admin_syndication_live.ex
Normal file
13
lib/web/live/admin_syndication_live.ex
Normal file
|
@ -0,0 +1,13 @@
|
|||
defmodule Web.AdminSyndicationLive do
|
||||
use Web, :live_view
|
||||
|
||||
def mount(_params, _session, socket) do
|
||||
mastodon_account = Core.Syndication.get_mastodon_account(socket.assigns.current_user)
|
||||
|
||||
socket =
|
||||
socket
|
||||
|> assign(:mastodon_account, mastodon_account)
|
||||
|
||||
{:ok, socket}
|
||||
end
|
||||
end
|
37
lib/web/live/admin_syndication_live.html.heex
Normal file
37
lib/web/live/admin_syndication_live.html.heex
Normal file
|
@ -0,0 +1,37 @@
|
|||
<div class="flex flex-col py-4 px-6">
|
||||
<header class="mb-4">
|
||||
<nav>
|
||||
<ul class="flex flex-row gap-x-4">
|
||||
<li>
|
||||
<.link navigate={~p"/admin/writing"}>
|
||||
writing
|
||||
</.link>
|
||||
</li>
|
||||
<li>
|
||||
<.link navigate={~p"/admin/microblog"}>
|
||||
microblog
|
||||
</.link>
|
||||
</li>
|
||||
<li>
|
||||
<.link class="underline" patch={~p"/admin/syndication"}>
|
||||
syndication
|
||||
</.link>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</header>
|
||||
|
||||
<main class="flex flex-col">
|
||||
<div>
|
||||
<strong>Mastodon: </strong>
|
||||
<%= if @mastodon_account do %>
|
||||
<.link href={@mastodon_account.uid} target="_blank">{@mastodon_account.uid}</.link>
|
||||
<% else %>
|
||||
<.link href={~p"/auth/mastodon"}>Connect account</.link>
|
||||
<% end %>
|
||||
</div>
|
||||
<div>
|
||||
<strong>Bluesky: </strong>Coming soon!
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
|
@ -25,6 +25,13 @@ defmodule Web.Router do
|
|||
post "/admin/users/log_in", UserSessionController, :create
|
||||
end
|
||||
|
||||
scope "/auth", Web do
|
||||
pipe_through [:browser, :require_authenticated_user]
|
||||
|
||||
get "/mastodon", AuthController, :request
|
||||
get "/mastodon/callback", AuthController, :callback
|
||||
end
|
||||
|
||||
scope "/admin", Web do
|
||||
pipe_through [:browser, :require_authenticated_user]
|
||||
|
||||
|
@ -36,6 +43,8 @@ defmodule Web.Router do
|
|||
|
||||
live "/posts/new", AdminPostLive, :new
|
||||
live "/posts/:post_id", AdminPostLive, :edit
|
||||
|
||||
live "/syndication", AdminSyndicationLive, :index
|
||||
end
|
||||
end
|
||||
|
||||
|
|
4
mix.exs
4
mix.exs
|
@ -66,6 +66,10 @@ defmodule SlaonelyButSurely.MixProject do
|
|||
{:flop_phoenix, "~> 0.24.1"},
|
||||
{:oban, "~> 2.19"},
|
||||
{:igniter, "~> 0.5", only: [:dev]},
|
||||
{:ueberauth, "~> 0.10"},
|
||||
{:ueberauth_mastodon, "~> 0.3.0"},
|
||||
{:tesla, "~> 1.14"},
|
||||
{:mint, "~> 1.7"},
|
||||
|
||||
# Added dev and/or test dependencies
|
||||
{:credo, "~> 1.7", only: [:dev, :test], runtime: false},
|
||||
|
|
4
mix.lock
4
mix.lock
|
@ -31,6 +31,7 @@
|
|||
"igniter": {:hex, :igniter, "0.5.47", "7a1041d5e38303e526fa6b6de37c9e78013f5cb573833ed51183d18e3a152f10", [:mix], [{:glob_ex, "~> 0.1.7", [hex: :glob_ex, repo: "hexpm", optional: false]}, {:inflex, "~> 2.0", [hex: :inflex, repo: "hexpm", optional: false]}, {:jason, "~> 1.4", [hex: :jason, repo: "hexpm", optional: false]}, {:owl, "~> 0.11", [hex: :owl, repo: "hexpm", optional: false]}, {:phx_new, "~> 1.7", [hex: :phx_new, repo: "hexpm", optional: true]}, {:req, "~> 0.5", [hex: :req, repo: "hexpm", optional: false]}, {:rewrite, ">= 1.1.1 and < 2.0.0-0", [hex: :rewrite, repo: "hexpm", optional: false]}, {:sourceror, "~> 1.4", [hex: :sourceror, repo: "hexpm", optional: false]}, {:spitfire, ">= 0.1.3 and < 1.0.0-0", [hex: :spitfire, repo: "hexpm", optional: false]}], "hexpm", "53a900909e20f217a25d15a34fef629c562b4822c1fb39cfa5d6999bc72992ed"},
|
||||
"inflex": {:hex, :inflex, "2.1.0", "a365cf0821a9dacb65067abd95008ca1b0bb7dcdd85ae59965deef2aa062924c", [:mix], [], "hexpm", "14c17d05db4ee9b6d319b0bff1bdf22aa389a25398d1952c7a0b5f3d93162dd8"},
|
||||
"jason": {:hex, :jason, "1.4.4", "b9226785a9aa77b6857ca22832cffa5d5011a667207eb2a0ad56adb5db443b8a", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "c5eb0cab91f094599f94d55bc63409236a8ec69a21a67814529e8d5f6cc90b3b"},
|
||||
"mastodon_client": {:hex, :mastodon_client, "0.1.0", "7f1a9e54367d0e126c76d0bb1097de346fb9c6da6d682a6b57bc936c92d643eb", [:mix], [{:hackney, "~> 1.18", [hex: :hackney, repo: "hexpm", optional: true]}, {:jason, "~> 1.2", [hex: :jason, repo: "hexpm", optional: true]}, {:tesla, "~> 1.4", [hex: :tesla, repo: "hexpm", optional: false]}], "hexpm", "3daa37fc7a95430eb0b77cdb168af58b8db84efea6e0f3244d15d45f39a87160"},
|
||||
"mdex": {:hex, :mdex, "0.5.0", "252c83cebc6a089801dfc1e142b4d98c9c358378ec7096a94796bce8bd13b0fc", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:nimble_options, "~> 1.0", [hex: :nimble_options, repo: "hexpm", optional: false]}, {:rustler, "~> 0.32", [hex: :rustler, repo: "hexpm", optional: false]}, {:rustler_precompiled, "~> 0.7", [hex: :rustler_precompiled, repo: "hexpm", optional: false]}], "hexpm", "73e3ddee03130267e3be6aaf47a7f423c6f86add4bb5c62b352465cd9fb87d95"},
|
||||
"metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [:rebar3], [], "hexpm", "69b09adddc4f74a40716ae54d140f93beb0fb8978d8636eaded0c31b6f099f16"},
|
||||
"mime": {:hex, :mime, "2.0.6", "8f18486773d9b15f95f4f4f1e39b710045fa1de891fada4516559967276e4dc2", [:mix], [], "hexpm", "c9945363a6b26d747389aac3643f8e0e09d30499a138ad64fe8fd1d13d9b153e"},
|
||||
|
@ -65,12 +66,15 @@
|
|||
"telemetry": {:hex, :telemetry, "1.3.0", "fedebbae410d715cf8e7062c96a1ef32ec22e764197f70cda73d82778d61e7a2", [:rebar3], [], "hexpm", "7015fc8919dbe63764f4b4b87a95b7c0996bd539e0d499be6ec9d7f3875b79e6"},
|
||||
"telemetry_metrics": {:hex, :telemetry_metrics, "1.1.0", "5bd5f3b5637e0abea0426b947e3ce5dd304f8b3bc6617039e2b5a008adc02f8f", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "e7b79e8ddfde70adb6db8a6623d1778ec66401f366e9a8f5dd0955c56bc8ce67"},
|
||||
"telemetry_poller": {:hex, :telemetry_poller, "1.1.0", "58fa7c216257291caaf8d05678c8d01bd45f4bdbc1286838a28c4bb62ef32999", [:rebar3], [{:telemetry, "~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "9eb9d9cbfd81cbd7cdd24682f8711b6e2b691289a0de6826e58452f28c103c8f"},
|
||||
"tesla": {:hex, :tesla, "1.14.1", "71c5b031b4e089c0fbfb2b362e24b4478465773ae4ef569760a8c2899ad1e73c", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:exjsx, ">= 3.0.0", [hex: :exjsx, repo: "hexpm", optional: true]}, {:finch, "~> 0.13", [hex: :finch, repo: "hexpm", optional: true]}, {:fuse, "~> 2.4", [hex: :fuse, repo: "hexpm", optional: true]}, {:gun, ">= 1.0.0", [hex: :gun, repo: "hexpm", optional: true]}, {:hackney, "~> 1.21", [hex: :hackney, repo: "hexpm", optional: true]}, {:ibrowse, "4.4.2", [hex: :ibrowse, repo: "hexpm", optional: true]}, {:jason, ">= 1.0.0", [hex: :jason, repo: "hexpm", optional: true]}, {:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:mint, "~> 1.0", [hex: :mint, repo: "hexpm", optional: true]}, {:mox, "~> 1.0", [hex: :mox, repo: "hexpm", optional: true]}, {:msgpax, "~> 2.3", [hex: :msgpax, repo: "hexpm", optional: true]}, {:poison, ">= 1.0.0", [hex: :poison, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: true]}], "hexpm", "c1dde8140a49a3bef5bb622356e77ac5a24ad0c8091f12c3b7fc1077ce797155"},
|
||||
"text_diff": {:hex, :text_diff, "0.1.0", "1caf3175e11a53a9a139bc9339bd607c47b9e376b073d4571c031913317fecaa", [:mix], [], "hexpm", "d1ffaaecab338e49357b6daa82e435f877e0649041ace7755583a0ea3362dbd7"},
|
||||
"thousand_island": {:hex, :thousand_island, "1.3.10", "a9971ebab1dfb36e2710a86b37c3f54973fbc9470d892035334415521fb53328", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "17ab1f1b13aadb1f4b4c8e5b59c06874d701119fed082884c9c6d38addad254f"},
|
||||
"timex": {:hex, :timex, "3.7.11", "bb95cb4eb1d06e27346325de506bcc6c30f9c6dea40d1ebe390b262fad1862d1", [:mix], [{:combine, "~> 0.10", [hex: :combine, repo: "hexpm", optional: false]}, {:gettext, "~> 0.20", [hex: :gettext, repo: "hexpm", optional: false]}, {:tzdata, "~> 1.1", [hex: :tzdata, repo: "hexpm", optional: false]}], "hexpm", "8b9024f7efbabaf9bd7aa04f65cf8dcd7c9818ca5737677c7b76acbc6a94d1aa"},
|
||||
"toml": {:hex, :toml, "0.7.0", "fbcd773caa937d0c7a02c301a1feea25612720ac3fa1ccb8bfd9d30d822911de", [:mix], [], "hexpm", "0690246a2478c1defd100b0c9b89b4ea280a22be9a7b313a8a058a2408a2fa70"},
|
||||
"typed_struct": {:hex, :typed_struct, "0.3.0", "939789e3c1dca39d7170c87f729127469d1315dcf99fee8e152bb774b17e7ff7", [:mix], [], "hexpm", "c50bd5c3a61fe4e198a8504f939be3d3c85903b382bde4865579bc23111d1b6d"},
|
||||
"tzdata": {:hex, :tzdata, "1.1.2", "45e5f1fcf8729525ec27c65e163be5b3d247ab1702581a94674e008413eef50b", [:mix], [{:hackney, "~> 1.17", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm", "cec7b286e608371602318c414f344941d5eb0375e14cfdab605cca2fe66cba8b"},
|
||||
"ueberauth": {:hex, :ueberauth, "0.10.8", "ba78fbcbb27d811a6cd06ad851793aaf7d27c3b30c9e95349c2c362b344cd8f0", [:mix], [{:plug, "~> 1.5", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "f2d3172e52821375bccb8460e5fa5cb91cfd60b19b636b6e57e9759b6f8c10c1"},
|
||||
"ueberauth_mastodon": {:hex, :ueberauth_mastodon, "0.3.0", "e0b80adc29d8734f74cac908d25e2113739112ea84b95f3c9f27ef3161128426", [:mix], [{:hackney, "~> 1.20", [hex: :hackney, repo: "hexpm", optional: true]}, {:mastodon_client, "~> 0.1", [hex: :mastodon_client, repo: "hexpm", optional: false]}, {:ueberauth, "~> 0.10.0", [hex: :ueberauth, repo: "hexpm", optional: false]}], "hexpm", "28a049497b3b708a232c8d6da1c7fb80c92ae4a6961f2c9274dfe9333a1aa7d0"},
|
||||
"unicode_util_compat": {:hex, :unicode_util_compat, "0.7.0", "bc84380c9ab48177092f43ac89e4dfa2c6d62b40b8bd132b1059ecc7232f9a78", [:rebar3], [], "hexpm", "25eee6d67df61960cf6a794239566599b09e17e668d3700247bc498638152521"},
|
||||
"websock": {:hex, :websock, "0.5.3", "2f69a6ebe810328555b6fe5c831a851f485e303a7c8ce6c5f675abeb20ebdadc", [:mix], [], "hexpm", "6105453d7fac22c712ad66fab1d45abdf049868f253cf719b625151460b8b453"},
|
||||
"websock_adapter": {:hex, :websock_adapter, "0.5.8", "3b97dc94e407e2d1fc666b2fb9acf6be81a1798a2602294aac000260a7c4a47d", [:mix], [{:bandit, ">= 0.6.0", [hex: :bandit, repo: "hexpm", optional: true]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 2.6", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:websock, "~> 0.5", [hex: :websock, repo: "hexpm", optional: false]}], "hexpm", "315b9a1865552212b5f35140ad194e67ce31af45bcee443d4ecb96b5fd3f3782"},
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
defmodule Core.Repo.Migrations.CreateMastodonAuthTables do
|
||||
use Ecto.Migration
|
||||
|
||||
def change do
|
||||
create table(:mastodon_accounts, primary_key: false) do
|
||||
add :id, :uuid, primary_key: true
|
||||
add :user_id, references(:users, type: :binary_id, on_delete: :delete_all), null: false
|
||||
add :uid, :text, null: false
|
||||
add :access_token, :text, null: false
|
||||
|
||||
timestamps(type: :utc_datetime_usec)
|
||||
end
|
||||
|
||||
create unique_index(:mastodon_accounts, [:user_id])
|
||||
create unique_index(:mastodon_accounts, [:uid])
|
||||
end
|
||||
end
|
39
scripts/register_mastodon_application.exs
Executable file
39
scripts/register_mastodon_application.exs
Executable file
|
@ -0,0 +1,39 @@
|
|||
#!/usr/bin/env elixir
|
||||
|
||||
Mix.install([
|
||||
{:req, "~> 0.5.10"}
|
||||
])
|
||||
|
||||
{opts, []} =
|
||||
OptionParser.parse!(System.argv(),
|
||||
strict: [
|
||||
instance: :string,
|
||||
client_name: :string,
|
||||
redirect_uri: :string,
|
||||
scopes: :string,
|
||||
website: :string
|
||||
]
|
||||
)
|
||||
|
||||
instance = Keyword.fetch!(opts, :instance)
|
||||
client_name = Keyword.get(opts, :client_name, "sloanelybutsurely.com")
|
||||
|
||||
redirect_uri =
|
||||
Keyword.get(opts, :redirect_uri, "https://sloanelybutsurely.com/auth/mastodon/callback")
|
||||
|
||||
scopes = Keyword.get(opts, :scopes, "read write push")
|
||||
website = Keyword.get(opts, :website, "https://sloanelybutsurely.com")
|
||||
|
||||
%{status: 200, body: resp} =
|
||||
Req.post!(
|
||||
base_url: instance,
|
||||
url: "/api/v1/apps",
|
||||
json: %{
|
||||
client_name: client_name,
|
||||
redirect_uris: [redirect_uri],
|
||||
scopes: scopes,
|
||||
website: website
|
||||
}
|
||||
)
|
||||
|
||||
IO.inspect(resp)
|
Loading…
Reference in a new issue