Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

liveview native app #763

Draft
wants to merge 7 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,5 @@ npm-debug.log
/assets/node_modules/

.env
.DS_Store
xcuserdata
28 changes: 28 additions & 0 deletions config/config.exs
Original file line number Diff line number Diff line change
Expand Up @@ -52,19 +52,47 @@ config :logger, :console,

# Use Jason for JSON parsing in Phoenix
config :phoenix, :json_library, Jason
config :phoenix, :template_engines, neex: LiveViewNative.Engine
config :phoenix_template, :format_encoders, swiftui: Phoenix.HTML.Engine

config :ash, :use_all_identities_in_manage_relationship?, false

config :tesla, :adapter, {Tesla.Adapter.Finch, name: Spendable.Finch}
config :oauth2, adapter: {Tesla.Adapter.Finch, name: Spendable.Finch}

config :spendable, Spendable.Guardian,
issuer: "https://accounts.google.com",
verify_issuer: true,
ttl: {1, :hour},
allowed_algos: ["RS256"],
secret_fetcher: Spendable.Guardian.KeyServer

config :goth, project_id: "cloud-57"

config :ueberauth, Ueberauth,
providers: [
google: {Ueberauth.Strategy.Google, []}
]

config :mime, :types, %{
"text/swiftui" => ["swiftui"],
"text/styles" => ["styles"]
}

config :live_view_native,
plugins: [
LiveViewNative.HTML,
LiveViewNative.SwiftUI
]

config :live_view_native_stylesheet,
content: [
swiftui: [
"lib/**/*swiftui*"
]
],
output: "priv/static/assets"

# Import environment specific config. This must remain at the bottom
# of this file so it overrides the configuration defined above.
import_config "#{config_env()}.exs"
6 changes: 5 additions & 1 deletion config/dev.exs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ config :spendable, SpendableWeb.Endpoint,
patterns: [
~r"priv/static/.*(js|css|png|jpeg|jpg|gif|svg)$",
~r"priv/gettext/.*(po)$",
~r"lib/spendable_web/(controllers|live|components)/.*(ex|heex)$"
~r"lib/spendable_web/(controllers|live|components|styles)/.*(ex|heex,neex)$"
]
]

Expand All @@ -53,3 +53,7 @@ config :phoenix, :stacktrace_depth, 20
config :phoenix, :plug_init_mode, :runtime

config :spendable, Plaid, base_url: "https://sandbox.plaid.com"

config :live_view_native_stylesheet,
annotations: true,
pretty: true
1 change: 1 addition & 0 deletions lib/spendable/application.ex
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ defmodule Spendable.Application do
def start(_type, _args) do
all_env_children = [
{Finch, name: Spendable.Finch},
Spendable.Guardian.KeyServer,
SpendableWeb.Telemetry,
Spendable.Repo,
{Phoenix.PubSub, name: Spendable.PubSub},
Expand Down
11 changes: 11 additions & 0 deletions lib/spendable/guardian.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
defmodule Spendable.Guardian do
use Guardian, otp_app: :spendable

def subject_for_token(_sub, _claims) do
{:error, :not_supported}
end

def resource_from_claims(_claims) do
{:error, :not_supported}
end
end
47 changes: 47 additions & 0 deletions lib/spendable/guardian/key_server.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
defmodule Spendable.Guardian.KeyServer do
@behaviour Guardian.Token.Jwt.SecretFetcher

use GenServer

def start_link(_opts) do
GenServer.start_link(__MODULE__, :ok, name: __MODULE__)
end

@impl GenServer
def init(_opts) do
:ets.new(__MODULE__, [:named_table, :public])
{:ok, nil}
end

@impl Guardian.Token.Jwt.SecretFetcher
# coveralls-ignore-next-line not supported
def fetch_signing_secret(_mod, _opts), do: {:error, :not_supported}

@impl Guardian.Token.Jwt.SecretFetcher
def fetch_verifying_secret(_mod, %{"kid" => kid}, _opts) do
case lookup(kid) do
{:ok, jwk} ->
{:ok, jwk}

:error ->
load_public_keys()
lookup(kid)
end
end

defp lookup(kid) do
case :ets.lookup(__MODULE__, kid) do
[{^kid, key}] -> {:ok, key}
[] -> :error
end
end

defp load_public_keys() do
{:ok, %{body: body}} = Tesla.get("https://www.googleapis.com/oauth2/v3/certs")
%{"keys" => public_keys} = Jason.decode!(body)

Enum.each(public_keys, fn %{"kid" => kid} = key ->
:ets.insert(__MODULE__, {kid, JOSE.JWK.from(key)})
end)
end
end
72 changes: 72 additions & 0 deletions lib/spendable_native.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
defmodule SpendableNative do
import SpendableWeb, only: [verified_routes: 0]

def live_view() do
quote do
use LiveViewNative.LiveView,
formats: [
:swiftui
],
layouts: [
swiftui: {SpendableWeb.Layouts.SwiftUI, :app}
]

unquote(verified_routes())
end
end

def render_component(opts) do
opts =
opts
|> Keyword.take([:format])
|> Keyword.put(:as, :render)

quote do
use LiveViewNative.Component, unquote(opts)

unquote(helpers(opts[:format]))
end
end

def component(opts) do
opts = Keyword.take(opts, [:format, :root, :as])

quote do
use LiveViewNative.Component, unquote(opts)

unquote(helpers(opts[:format]))
end
end

def layout(opts) do
opts = Keyword.take(opts, [:format, :root])

quote do
use LiveViewNative.Component, unquote(opts)

import LiveViewNative.Component, only: [csrf_token: 1]

unquote(helpers(opts[:format]))
end
end

defp helpers(_format) do
gettext_quoted =
quote do
import SpendableWeb.Gettext
end

[gettext_quoted, verified_routes()]
end

@doc """
When used, dispatch to the appropriate controller/view/etc.
"""
defmacro __using__([which | opts]) when is_atom(which) do
apply(__MODULE__, which, [opts])
end

defmacro __using__(which) when is_atom(which) do
apply(__MODULE__, which, [])
end
end
6 changes: 6 additions & 0 deletions lib/spendable_web.ex
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,12 @@ defmodule SpendableWeb do
use Phoenix.LiveView,
layout: {SpendableWeb.Layouts, :app}

use LiveViewNative.LiveView,
formats: [:swiftui],
layouts: [
swiftui: {SpendableWeb.Layouts.SwiftUI, :app}
]

unquote(html_helpers())
end
end
Expand Down
5 changes: 5 additions & 0 deletions lib/spendable_web/components/layouts.swiftui.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
defmodule SpendableWeb.Layouts.SwiftUI do
use SpendableNative, [:layout, format: :swiftui]

embed_templates "layouts_swiftui/*"
end
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<%= @inner_content %>
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<.csrf_token />
<Style url={~p"/assets/app.swiftui.styles"} />
<NavigationStack>
<%= @inner_content %>
</NavigationStack>
4 changes: 0 additions & 4 deletions lib/spendable_web/controllers/auth_controller.ex
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,6 @@ defmodule SpendableWeb.AuthController do

alias Spendable.User

def login(conn, _params) do
render(conn, :login, layout: false)
end

def callback(%{assigns: %{ueberauth_failure: _fails}} = conn, _params) do
conn
|> put_flash(:error, "Failed to authenticate.")
Expand Down
7 changes: 7 additions & 0 deletions lib/spendable_web/controllers/page_controller.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
defmodule SpendableWeb.PageController do
use SpendableWeb, :controller

def privacy_policy(conn, _params) do
render(conn, :privacy_policy, layout: false)
end
end
5 changes: 5 additions & 0 deletions lib/spendable_web/controllers/page_html.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
defmodule SpendableWeb.PageHTML do
use SpendableWeb, :html

embed_templates "page_html/*"
end
56 changes: 56 additions & 0 deletions lib/spendable_web/controllers/page_html/privacy_policy.html.heex
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
<div class="container mx-auto px-4 py-8 max-w-4xl flex place-items-center h-full">
<div class="bg-gray-800 shadow overflow-hidden sm:rounded-lg">
<div class="px-4 py-5 sm:px-6">
<h1 class="text-2xl leading-9 font-extrabold tracking-tight text-gray-100">Privacy Policy for Spendable</h1>
</div>
<div class="border-t border-gray-400">
<dl>
<div class="bg-gray-800 px-4 py-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6">
<dt class="text-sm leading-5 font-medium text-gray-400">Introduction</dt>
<dd class="mt-1 text-sm leading-5 text-gray-100 sm:mt-0 sm:col-span-2">
At Spendable, we are committed to protecting your privacy. This Privacy Policy outlines the types of information we may process and how we ensure its protection and your privacy.
</dd>
</div>
<div class="bg-gray-800 px-4 py-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6">
<dt class="text-sm leading-5 font-medium text-gray-400">No Collection of Personal Information</dt>
<dd class="mt-1 text-sm leading-5 text-gray-100 sm:mt-0 sm:col-span-2">
Spendable does not actively collect personal information about visitors to our services. Users are free to interact with our services without providing any personal data.
</dd>
</div>
<div class="bg-gray-800 px-4 py-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6">
<dt class="text-sm leading-5 font-medium text-gray-400">Financial Data</dt>
<dd class="mt-1 text-sm leading-5 text-gray-100 sm:mt-0 sm:col-span-2">
While we do not collect personal information, we do store financial data that users voluntarily provide. This information is essential for providing personalized financial services and support.
</dd>
</div>
<div class="bg-gray-800 px-4 py-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6">
<dt class="text-sm leading-5 font-medium text-gray-400">Storage and Use of Financial Data</dt>
<dd class="mt-1 text-sm leading-5 text-gray-100 sm:mt-0 sm:col-span-2">
Any financial data provided by our users is stored securely and used solely for the purpose of delivering the services requested by the user. This data is maintained until it is explicitly requested to be deleted by the user.
</dd>
</div>
<div class="bg-gray-800 px-4 py-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6">
<dt class="text-sm leading-5 font-medium text-gray-400">Data Security</dt>
<dd class="mt-1 text-sm leading-5 text-gray-100 sm:mt-0 sm:col-span-2">
Spendable implements robust security measures to protect the data we handle. These measures are designed to prevent unauthorized access, alteration, disclosure, or destruction of your financial data.
</dd>
</div>
<div class="bg-gray-800 px-4 py-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6">
<dt class="text-sm leading-5 font-medium text-gray-400">Changes to This Policy</dt>
<dd class="mt-1 text-sm leading-5 text-gray-100 sm:mt-0 sm:col-span-2">
We may update this Privacy Policy from time to time. We encourage users to frequently check this page for any changes and to stay informed about how we are helping to protect the financial information we collect.
</dd>
</div>
<div class="bg-gray-800 px-4 py-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6">
<dt class="text-sm leading-5 font-medium text-gray-400">Contact Us</dt>
<dd class="mt-1 text-sm leading-5 text-gray-100 sm:mt-0 sm:col-span-2">
If you have any questions about this Privacy Policy, the practices of this site, or your dealings with this site, please contact us at:
<ul class="mt-2">
<li>Email: [email protected]</li>
</ul>
</dd>
</div>
</dl>
</div>
</div>
</div>
1 change: 1 addition & 0 deletions lib/spendable_web/endpoint.ex
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ defmodule SpendableWeb.Endpoint do
if code_reloading? do
socket "/phoenix/live_reload/socket", Phoenix.LiveReloader.Socket
plug Phoenix.LiveReloader
plug LiveViewNative.LiveReloader
plug Phoenix.CodeReloader
plug Phoenix.Ecto.CheckRepoStatus, otp_app: :spendable
end
Expand Down
Loading
Loading