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

feat: Elixir Phoenix example #74

Draft
wants to merge 8 commits into
base: master
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
6 changes: 6 additions & 0 deletions elixir-ory-network/.formatter.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[
import_deps: [:ecto, :ecto_sql, :phoenix, :plug],
subdirectories: ["priv/*/migrations"],
plugins: [Phoenix.LiveView.HTMLFormatter],
inputs: ["*.{heex,ex,exs}", "{config,lib,test}/**/*.{heex,ex,exs}", "priv/*/seeds.exs"]
]
40 changes: 40 additions & 0 deletions elixir-ory-network/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# The directory Mix will write compiled artifacts to.
/_build/

# If you run "mix test --cover", coverage assets end up here.
/cover/

# The directory Mix downloads your dependencies sources to.
/deps/

# Where 3rd-party dependencies like ExDoc output generated docs.
/doc/

# Ignore .fetch files in case you like to edit your project deps locally.
/.fetch

# If the VM crashes, it generates a dump, let's ignore it too.
erl_crash.dump

# Also ignore archive artifacts (built via "mix archive.build").
*.ez

# Temporary files, for example, from tests.
/tmp/

# Ignore package tarball (built via "mix hex.build").
example-*.tar

# Ignore assets that are produced by build tools.
/priv/static/assets/

# Ignore digested assets cache.
/priv/static/cache_manifest.json

# In case you use Node.js/npm, you want to ignore these.
npm-debug.log
/assets/node_modules/


assets/vendor/heroicons
priv/database.db*
71 changes: 71 additions & 0 deletions elixir-ory-network/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
# Elixir Ory Cloud Phoenix Example
A basic Example of integrating [Ory](https://ory.sh) with [Phoenix](https://www.phoenixframework.org/). Highlighting a controller flow, using [plugs](https://hexdocs.pm/phoenix/plug.html) to render HEEx templates with session details, etc.

## Overview

A simple server-side rendered web application serving Custom UI for Ory Flows.

## Develop

### Prerequisites

[Elixir](https://elixir-lang.org/install.html) >= 1.14
[Erlang](https://www.erlang.org/downloads)
[Ory CLI](https://www.ory.sh/docs/guides/cli/installation)

### Configure your Ory Network/Kratos project
Set up your Custom UI to the following values:
| Custom UI | URL |
| --------------- | --------------------------------------- |
| Login UI | https://localhost:3000/auth/login |
| Register UI | https://localhost:3000/auth/register |

> NOTE: The other UIs are currently not implemented in this example.

### Environmental Variables

`$ORY_PROJECT` is used when running the Ory Proxy to prevent CORS issues.

### Run locally

First build the dependencies and setup Phoenix:

```sh
$ mix deps.get && mix deps.compile
$ mix setup
```

Start the Ory proxy for your `$ORY_PROJECT` slug in another shell
```sh
$ ory proxy http://localhost:4000 --dev --project $ORY_PROJECT --port 3000 --cookie-domain localhost
```

And finally start serving the Phoenix server
```sh
$ mix phx.server
```

### Run tests

TODO: Integrate proper tests. :)

```sh
$ mix test
```

## Deploy

Most deployment mechanisms will work fine, such as [Fly.io](https://fly.io).

## Contribute

Feel free to
[open a discussion](https://github.com/ory/examples/discussions/new) to provide
feedback or talk about ideas, or
[open an issue](https://github.com/ory/examples/issues/new) if you want to add
your example to the repository or encounter a bug. You can contribute to Ory in
many ways, see the
[Ory Contributing Guidelines](https://www.ory.sh/docs/ecosystem/contributing)
for more information.

<!-- Optional: Add a personal note or sponsor link from the author here.-->
5 changes: 5 additions & 0 deletions elixir-ory-network/assets/css/app.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
@import "tailwindcss/base";
@import "tailwindcss/components";
@import "tailwindcss/utilities";

/* This file is for your main application CSS */
41 changes: 41 additions & 0 deletions elixir-ory-network/assets/js/app.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// If you want to use Phoenix channels, run `mix help phx.gen.channel`
// to get started and then uncomment the line below.
// import "./user_socket.js"

// You can include dependencies in two ways.
//
// The simplest option is to put them in assets/vendor and
// import them using relative paths:
//
// import "../vendor/some-package.js"
//
// Alternatively, you can `npm install some-package --prefix assets` and import
// them using a path starting with the package name:
//
// import "some-package"
//

// Include phoenix_html to handle method=PUT/DELETE in forms and buttons.
import "phoenix_html"
// Establish Phoenix Socket and LiveView configuration.
import {Socket} from "phoenix"
import {LiveSocket} from "phoenix_live_view"
import topbar from "../vendor/topbar"

let csrfToken = document.querySelector("meta[name='csrf-token']").getAttribute("content")
let liveSocket = new LiveSocket("/live", Socket, {params: {_csrf_token: csrfToken}})

// Show progress bar on live navigation and form submits
topbar.config({barColors: {0: "#29d"}, shadowColor: "rgba(0, 0, 0, .3)"})
window.addEventListener("phx:page-loading-start", _info => topbar.show(300))
window.addEventListener("phx:page-loading-stop", _info => topbar.hide())

// connect if there are any LiveViews on the page
liveSocket.connect()

// expose liveSocket on window for web console debug logs and latency simulation:
// >> liveSocket.enableDebug()
// >> liveSocket.enableLatencySim(1000) // enabled for duration of browser session
// >> liveSocket.disableLatencySim()
window.liveSocket = liveSocket

68 changes: 68 additions & 0 deletions elixir-ory-network/assets/tailwind.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
// See the Tailwind configuration guide for advanced usage
// https://tailwindcss.com/docs/configuration

const plugin = require("tailwindcss/plugin")
const fs = require("fs")
const path = require("path")

module.exports = {
content: [
"./js/**/*.js",
"../lib/*_web.ex",
"../lib/*_web/**/*.*ex"
],
theme: {
extend: {
colors: {
brand: "#FD4F00",
}
},
},
plugins: [
require("@tailwindcss/forms"),
// Allows prefixing tailwind classes with LiveView classes to add rules
// only when LiveView classes are applied, for example:
//
// <div class="phx-click-loading:animate-ping">
//
plugin(({addVariant}) => addVariant("phx-no-feedback", [".phx-no-feedback&", ".phx-no-feedback &"])),
plugin(({addVariant}) => addVariant("phx-click-loading", [".phx-click-loading&", ".phx-click-loading &"])),
plugin(({addVariant}) => addVariant("phx-submit-loading", [".phx-submit-loading&", ".phx-submit-loading &"])),
plugin(({addVariant}) => addVariant("phx-change-loading", [".phx-change-loading&", ".phx-change-loading &"])),

// Embeds Heroicons (https://heroicons.com) into your app.css bundle
// See your `CoreComponents.icon/1` for more information.
//
plugin(function({matchComponents, theme}) {
let iconsDir = path.join(__dirname, "./vendor/heroicons/optimized")
let values = {}
let icons = [
["", "/24/outline"],
["-solid", "/24/solid"],
["-mini", "/20/solid"]
]
icons.forEach(([suffix, dir]) => {
fs.readdirSync(path.join(iconsDir, dir)).map(file => {
let name = path.basename(file, ".svg") + suffix
values[name] = {name, fullPath: path.join(iconsDir, dir, file)}
})
})
matchComponents({
"hero": ({name, fullPath}) => {
let content = fs.readFileSync(fullPath).toString().replace(/\r?\n|\r/g, "")
return {
[`--hero-${name}`]: `url('data:image/svg+xml;utf8,${content}')`,
"-webkit-mask": `var(--hero-${name})`,
"mask": `var(--hero-${name})`,
"mask-repeat": "no-repeat",
"background-color": "currentColor",
"vertical-align": "middle",
"display": "inline-block",
"width": theme("spacing.5"),
"height": theme("spacing.5")
}
}
}, {values})
})
]
}
Loading
Loading