Partially support federated login

Two things:
1. I've never attempted to support this before.
2. It seems surprisingly and perhaps deceptively simpler than what I
   expected. I'm unsure what to do once Google's API authenticates the user. I
   currently look-up the user's role, trips, etc. using their email address. The
   role is stored in the Accounts table alongside username, email, password. I
   will speak with the interviewer tomorrow about this.
This commit is contained in:
William Carroll 2020-08-02 21:27:08 +01:00
parent d6b91b93cb
commit b9ed4a2dc1
4 changed files with 59 additions and 17 deletions

View file

@ -13,19 +13,7 @@
<div id="mount"></div>
<script>
function onSignIn(googleUser) {
var profile = googleUser.getBasicProfile();
console.log('ID: ' + profile.getId());
console.log('Name: ' + profile.getName());
console.log('Image URL: ' + profile.getImageUrl());
console.log('Email: ' + profile.getEmail());
}
function signOut() {
console.log('Signing out!');
var auth2 = gapi.auth2.getAuthInstance();
auth2.signOut().then(function() {
console.log('User signed out.');
});
console.log(googleUser);
}
var app = Elm.Main.init({node: document.getElementById("mount")});
@ -33,6 +21,18 @@
app.ports.printPage.subscribe(function() {
window.print();
});
app.ports.googleSignIn.subscribe(function() {
var auth2 = gapi.auth2.getAuthInstance();
var googleUser = auth2.signIn();
});
app.ports.googleSignOut.subscribe(function() {
var auth2 = gapi.auth2.getAuthInstance();
auth2.signOut().then(function() {
console.log('Google user successfully signed out.');
});
});
</script>
</body>
</html>

View file

@ -10,6 +10,16 @@ import UI
import Utils
googleSignIn : Html State.Msg
googleSignIn =
div
[ class "g-signin2"
, attribute "onsuccess" "onSignIn"
, onClick State.GoogleSignIn
]
[]
loginForm : State.Model -> Html State.Msg
loginForm model =
div
@ -111,11 +121,28 @@ loginForm model =
]
, case model.loginTab of
State.LoginForm ->
UI.simpleButton { handleClick = State.AttemptLogin, label = "Login" }
div [ [ "flex", "space-around" ] |> Tailwind.use |> class ]
[ UI.simpleButton
{ handleClick = State.AttemptLogin
, label = "Login"
}
, div [ [ "pl-4" ] |> Tailwind.use |> class ] [ googleSignIn ]
]
State.SignUpForm ->
if String.length model.username > 0 && String.length model.email > 0 && String.length model.password > 0 then
UI.simpleButton { handleClick = State.AttemptSignUp, label = "Sign up" }
if
List.all identity
[ String.length model.username > 0
, String.length model.email > 0
, String.length model.password > 0
]
then
div []
[ UI.simpleButton
{ handleClick = State.AttemptSignUp
, label = "Sign up"
}
]
else
UI.disabledButton { label = "Sign up" }

View file

@ -43,6 +43,8 @@ type Msg
| ClearErrors
| ToggleLoginForm
| PrintPage
| GoogleSignIn
| GoogleSignOut
| UpdateInviteEmail String
| UpdateInviteRole (Maybe Role)
| ReceiveTodaysDate Date.Date
@ -608,6 +610,12 @@ adminHome flags url key =
port printPage : () -> Cmd msg
port googleSignIn : () -> Cmd msg
port googleSignOut : () -> Cmd msg
{-| The initial state for the application.
-}
init : () -> Url.Url -> Nav.Key -> ( Model, Cmd Msg )
@ -732,6 +740,12 @@ update msg model =
PrintPage ->
( model, printPage () )
GoogleSignIn ->
( model, googleSignIn () )
GoogleSignOut ->
( model, googleSignOut () )
UpdateInviteEmail x ->
( { model | inviteEmail = x }, Cmd.none )

View file

@ -98,7 +98,8 @@ baseButton { label, enabled, handleClick, extraClasses } =
"cursor-not-allowed"
, "text-white"
, "font-bold"
, "py-2"
, "py-1"
, "shadow-lg"
, "px-4"
, "rounded"
, "focus:outline-none"