Skip to content

Instantly share code, notes, and snippets.

@arsduo
Last active June 16, 2017 14:59
Show Gist options
  • Save arsduo/4f65667df8296670bbccda855d207b59 to your computer and use it in GitHub Desktop.
Save arsduo/4f65667df8296670bbccda855d207b59 to your computer and use it in GitHub Desktop.
How does it even work? The Elm+Elixir Starter Kit supporting materials
defmodule Elmelixirstarter.AuthController do
use Elmelixirstarter.Web, :controller
# run incoming requests through Ueberauth
plug Ueberauth
# ...other code...
# We use Elixir's powerful pattern matching to sort auth failures from successes
def callback(%{assigns: %{ueberauth_failure: _fails}} = conn, _params) do
conn
|> put_flash(:error, "Failed to authenticate.")
|> redirect(to: "/")
end
def callback(%{assigns: %{ueberauth_auth: auth}} = conn, _params) do
# On success, find or create a user record, sign them in, and send them back to home
{:ok, user} = lookup_and_update_user(auth) || save_user_data(%User{}, auth)
conn
|> Guardian.Plug.sign_in(user)
|> redirect(to: "/")
end
# ...other code...
end
exports.config = {
// ...other configuration...
paths: {
watched: ["web/static", "test/static", "elm"],
// ...
},
plugins: {
// ...
sass: {mode: "native"},
elmBrunch: {
elmFolder: "elm",
mainModules: ["Main.elm"],
outputFolder: "web/static/vendor",
// for now, automatically compile everything in debug mode; you'll want to change this when releasing to production
makeParameters: ["--debug"]
},
},
// ...other configuration...
}
# ...other configuration...
config :ueberauth, Ueberauth,
providers: [ twitter: { Ueberauth.Strategy.Twitter, [] } ]
# Make sure to set your Twitter callback URL on your OAuth app!
# For development, it should be http://localhost:4000/auth/twitter/callback
config :ueberauth, Ueberauth.Strategy.Twitter.OAuth,
# in development/test, these are handled by Docker (by default)
consumer_key: System.get_env("TWITTER_CONSUMER_KEY"),
consumer_secret: System.get_env("TWITTER_CONSUMER_SECRET")
# ...other configuration...
# ...other steps...
# Install Elm
ADD ./elm/elm-package.json ./elm/elm-package.json
WORKDIR /usr/src/app/elm
RUN yarn global add elm \
&& elm-package install -y
WORKDIR /usr/src/app
# Install Phoenix and other Elixir packages
ADD mix.* ./
RUN mix local.hex --force \
&& mix local.rebar --force \
&& mix hex.info
RUN mix deps.get
...other steps...
html : Model -> Html Msg
html model =
let
homeMarkup : List (Html Msg)
homeMarkup =
case model.user of
UserSignedOut ->
[ a [ href "/auth/twitter", class "btn btn-success" ] [ text "Sign in" ] ]
UserSignedIn user ->
[ div []
[ text ("Hi " ++ user.name)
]
]
in
div [ class "splash-screen" ]
homeMarkup
-- ...other code...
main : Program Never Model Msg
main =
-- the key point is init: we start out with a blank application state (model) and immediately ask the user API for info
Html.program { init = ( Model.init, UserApi.validateUser ), view = view, update = update, subscriptions = subscriptions }
-- ...other code...
-- ...other code...
-- update incorporates data from a message into the application's state (the model), returning a new model
-- in this case, we're incorporating whether the user successfully logged in or not
update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
case msg of
UserStateChecked (Ok user) ->
( { model | user = (UserSignedIn user) }, Cmd.none )
UserStateChecked (Err err) ->
( { model | user = UserSignedOut }, Cmd.none )
-- ...other code...
var app = Elm.MyApp.fullscreen({
// Poison is an Elixir JSON library
user: <%= Poison.encode!(user) %>
});
-- ...other code...
validateUser : Cmd Messages.Msg
validateUser =
let
userIndexUrl =
"/api/me"
-- make the GET request and run the results through a decoder (not shown)
getRequest =
Http.get userIndexUrl userDecoder
in
-- after sending the request, send Messages.UserStateChecked with the result
Http.send Messages.UserStateChecked getRequest
-- ...other code...
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment