style all the sign-in pages

This commit is contained in:
Andre Staltz 2021-03-26 17:30:57 +02:00 committed by Henry
parent 1170275816
commit 09fcd573b4
12 changed files with 115 additions and 128 deletions

View File

@ -1,24 +1,30 @@
// get the challenge from out of the HTML
const sc = document.querySelector("#challenge").dataset.sc
const ssbUriLink = document.querySelector('#start-auth-uri');
const waitingElem = document.querySelector('#waiting');
const errorElem = document.querySelector('#failed');
const challengeElem = document.querySelector('#challenge');
const sc = challengeElem.dataset.sc;
const evtSource = new EventSource(`/withssb/events?sc=${sc}`);
const ping = document.querySelector('#ping');
const failed = document.querySelector('#failed');
ssbUriLink.addEventListener('click', (e) => {
errorElem.classList.add('hidden');
waitingElem.classList.remove('hidden');
});
evtSource.onerror = (e) => {
failed.textContent = "Warning: The connection to the server was interupted."
}
waitingElem.classList.add('hidden');
errorElem.classList.remove('hidden');
console.error(e.data);
};
// TODO: change to some css-style progress indicator
evtSource.addEventListener("ping", (e) => {
ping.textContent = e.data;
})
evtSource.addEventListener('failed', (e) => {
waitingElem.classList.add('hidden');
errorElem.classList.remove('hidden');
console.error(e.data);
});
evtSource.addEventListener("failed", (e) => {
failed.textContent = e.data;
})
evtSource.addEventListener("success", (e) => {
evtSource.close()
window.location = `/withssb/finalize?token=${e.data}`
})
evtSource.addEventListener('success', (e) => {
waitingElem.classList.add('hidden');
evtSource.close();
window.location = `/withssb/finalize?token=${e.data}`;
});

View File

@ -17,7 +17,6 @@ import (
kitlog "github.com/go-kit/kit/log"
"github.com/go-kit/kit/log/level"
"github.com/gorilla/csrf"
"github.com/gorilla/mux"
"github.com/gorilla/sessions"
"github.com/skip2/go-qrcode"
@ -34,7 +33,7 @@ import (
)
var HTMLTemplates = []string{
"auth/start_login_form.tmpl",
"auth/decide_method.tmpl",
"auth/withssb_server_start.tmpl",
}
@ -96,7 +95,7 @@ func NewWithSSBHandler(
ssb.cookieStore = cookies
ssb.bridge = bridge
m.Get(router.AuthLogin).HandlerFunc(ssb.decideMethod)
m.Get(router.AuthWithSSBLogin).HandlerFunc(ssb.decideMethod)
m.Get(router.AuthWithSSBServerEvents).HandlerFunc(ssb.eventSource)
m.Get(router.AuthWithSSBFinalize).HandlerFunc(ssb.finalizeCookie)
@ -265,15 +264,6 @@ func (h WithSSBHandler) decideMethod(w http.ResponseWriter, req *http.Request) {
return
}
// without any query params: shows a form field so you can input alias or SSB ID
if alias == "" && cid == nil {
data := map[string]interface{}{
csrf.TemplateTag: csrf.TemplateField(req),
}
h.render.Render(w, req, "auth/start_login_form.tmpl", http.StatusOK, data)
return
}
// assume server-init sse dance
data, err := h.serverInitiated()
if err != nil {

View File

@ -108,7 +108,7 @@ func TestFallbackAuth(t *testing.T) {
}
ts.AuthFallbackDB.CheckReturns(int64(23), nil)
signInURL, err := ts.Router.Get(router.AuthFallbackSignIn).URL()
signInURL, err := ts.Router.Get(router.AuthFallbackLogin).URL()
r.Nil(err)
signInURL.Host = "localhost"

View File

@ -39,6 +39,7 @@ var HTMLTemplates = []string{
"aliases-resolved.html",
"invite/accept.tmpl",
"invite/consumed.tmpl",
"auth/fallback_sign_in.tmpl",
"notice/list.tmpl",
"notice/show.tmpl",
"error.tmpl",
@ -243,7 +244,15 @@ func New(
bridge,
)
m.Get(router.AuthFallbackSignIn).HandlerFunc(authWithPassword.Authorize)
m.Get(router.AuthLogin).Handler(r.StaticHTML("auth/decide_method.tmpl"))
m.Get(router.AuthFallbackFinalize).HandlerFunc(authWithPassword.Authorize)
m.Get(router.AuthFallbackLogin).Handler(r.HTML("auth/fallback_sign_in.tmpl", func(w http.ResponseWriter, req *http.Request) (interface{}, error) {
return map[string]interface{}{
csrf.TemplateTag: csrf.TemplateField(req),
}, nil
}))
m.Get(router.AuthLogout).HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
err = authWithSSB.Logout(w, req)

View File

@ -128,7 +128,7 @@ func TestNoticesEditButtonVisible(t *testing.T) {
ts.AuthFallbackDB.CheckReturns(testUser.ID, nil)
ts.MembersDB.GetByIDReturns(testUser, nil)
postEndpoint, err := ts.Router.Get(router.AuthFallbackSignIn).URL()
postEndpoint, err := ts.Router.Get(router.AuthFallbackLogin).URL()
r.Nil(err)
postEndpoint.Host = "localhost"
postEndpoint.Scheme = "https"

View File

@ -19,17 +19,17 @@ AuthSignIn = "Sign in"
AuthSignOut = "Sign out"
AuthTitle = "Member Authentication"
AuthWelcome = "TODO: Some text about the different login methods"
AuthWithSSBTitle = "Sign-in with SSB"
AuthWithSSBStart = "To begin, enter your alias on this room or your public key"
AuthWithSSBServerStart = "If you have a compatible device/application, you can sign-in here without a password. Open the QR-Code on your mobile device to complete the process or click the link below."
AuthFallbackWelcome = "Here you can log in with username and password."
AuthFallbackTitle = "Password Login"
AuthWelcome = "If you are a member of this room, you can access the internal dashboard. Click on your preferred sign-in method below:"
AuthWithSSBTitle = "Sign in with SSB"
AuthWithSSBInstruct = "Easy and secure method, if your SSB app supports it."
AuthWithSSBWelcome = "To sign-in with your SSB identity stored on this device, press the button below which will open a compatible SSB app, if it's installed."
AuthWithSSBInstructQR = "If your SSB app is on another device, you can scan the following QR code to sign-in with that device's SSB identity."
AuthWithSSBError = "Sign-in failed. Please make sure you use an SSB app that supports this method of login, and click the button above within a minute after this page was opened."
AuthFallbackTitle = "Password sign-in"
AuthFallbackWelcome = "Signing in with username and password is only possible if the administrator has given you one, because we do not support user registration."
AuthFallbackInstruct = "This method is an acceptable fallback, if you have a username and password."
AdminDashboardWelcome = "Welcome to your dashboard"
AdminDashboardTitle = "Room Admin Dashboard"

View File

@ -6,11 +6,13 @@ import "github.com/gorilla/mux"
// constant names for the named routes
const (
AuthFallbackSignIn = "auth:fallback:signin"
AuthLogin = "auth:login"
AuthLogout = "auth:logout"
AuthFallbackLogin = "auth:fallback:login"
AuthFallbackFinalize = "auth:fallback:finalize"
AuthWithSSBLogin = "auth:withssb:login"
AuthWithSSBServerEvents = "auth:withssb:sse"
AuthWithSSBFinalize = "auth:withssb:finalize"
)
@ -24,9 +26,10 @@ func Auth(m *mux.Router) *mux.Router {
m.Path("/login").Methods("GET").Name(AuthLogin)
m.Path("/logout").Methods("GET").Name(AuthLogout)
// register password fallback
m.Path("/password/signin").Methods("POST").Name(AuthFallbackSignIn)
m.Path("/fallback/login").Methods("GET").Name(AuthFallbackLogin)
m.Path("/fallback/finalize").Methods("POST").Name(AuthFallbackFinalize)
m.Path("/withssb/login").Methods("GET").Name(AuthWithSSBLogin)
m.Path("/withssb/events").Methods("GET").Name(AuthWithSSBServerEvents)
m.Path("/withssb/finalize").Methods("GET").Name(AuthWithSSBFinalize)

View File

@ -0,0 +1,30 @@
{{ define "title" }}{{i18n "AuthTitle"}}{{ end }}
{{ define "content" }}
<div class="flex flex-col justify-center items-center self-center max-w-lg">
<span class="text-center mt-8">{{i18n "AuthWelcome"}}</span>
</div>
<div class="flex flex-col sm:flex-row justify-center items-center sm:items-stretch">
<a
href="{{urlTo "auth:withssb:login"}}"
class="w-64 sm:mr-4 my-6 py-10 border-green-200 border-2 rounded-3xl flex flex-col justify-start items-center hover:border-green-400 hover:shadow-xl transition"
>
<svg class="w-12 h-12 text-green-500 mb-4" viewBox="0 0 24 24">
<path fill="currentColor" d="M12.66 13.67C12.32 14 11.93 14.29 11.5 14.5V21L9.5 23L7.5 21L9.5 19.29L8 18L9.5 16.71L7.5 15V14.5C6 13.77 5 12.26 5 10.5C5 8 7 6 9.5 6C9.54 6 9.58 6 9.61 6C9.59 6.07 9.54 6.12 9.5 6.18C9.23 6.79 9.08 7.43 9.03 8.08C8.43 8.28 8 8.84 8 9.5C8 10.33 8.67 11 9.5 11C9.53 11 9.57 11 9.6 11C10.24 12.25 11.34 13.2 12.66 13.67M16 6C16 5.37 15.9 4.75 15.72 4.18C17.06 4.56 18.21 5.55 18.73 6.96C19.33 8.62 18.89 10.39 17.75 11.59L20 17.68L18.78 20.25L16.22 19.05L17.5 16.76L15.66 16.06L16.63 14.34L14.16 13.41L14 12.95C12.36 12.77 10.88 11.7 10.27 10.04C9.42 7.71 10.63 5.12 12.96 4.27C13.14 4.21 13.33 4.17 13.5 4.13C12.84 2.87 11.53 2 10 2C7.79 2 6 3.79 6 6C6 6.09 6 6.17 6.03 6.26C5.7 6.53 5.4 6.82 5.15 7.15C5.06 6.78 5 6.4 5 6C5 3.24 7.24 1 10 1S15 3.24 15 6C15 7.16 14.6 8.21 13.94 9.06C16.08 8.88 16 6 16 6M12.81 8.1C12.87 8.27 12.96 8.41 13.06 8.54C13.62 7.88 13.97 7.04 14 6.11C13.89 6.13 13.8 6.15 13.7 6.18C12.92 6.47 12.5 7.33 12.81 8.1Z" />
</svg>
<h1 class="text-xl font-bold text-green-500">{{i18n "AuthWithSSBTitle"}}</h1>
<span class="mx-3 mt-2 text-center text-sm">{{i18n "AuthWithSSBInstruct"}}</span>
</a>
<a
href="{{urlTo "auth:fallback:login"}}"
class="w-64 sm:ml-4 my-6 py-10 border-gray-200 border-2 rounded-3xl flex flex-col justify-start items-center hover:border-gray-400 hover:shadow-xl transition"
>
<svg class="w-12 h-12 text-gray-500 mb-4" viewBox="0 0 24 24">
<path fill="currentColor" d="M17,7H22V17H17V19A1,1 0 0,0 18,20H20V22H17.5C16.95,22 16,21.55 16,21C16,21.55 15.05,22 14.5,22H12V20H14A1,1 0 0,0 15,19V5A1,1 0 0,0 14,4H12V2H14.5C15.05,2 16,2.45 16,3C16,2.45 16.95,2 17.5,2H20V4H18A1,1 0 0,0 17,5V7M2,7H13V9H4V15H13V17H2V7M20,15V9H17V15H20M8.5,12A1.5,1.5 0 0,0 7,10.5A1.5,1.5 0 0,0 5.5,12A1.5,1.5 0 0,0 7,13.5A1.5,1.5 0 0,0 8.5,12M13,10.89C12.39,10.33 11.44,10.38 10.88,11C10.32,11.6 10.37,12.55 11,13.11C11.55,13.63 12.43,13.63 13,13.11V10.89Z" />
</svg>
<h1 class="text-xl font-bold text-gray-500">{{i18n "AuthFallbackTitle"}}</h1>
<span class="mx-3 mt-2 text-center text-sm">{{i18n "AuthFallbackInstruct"}}</span>
</a>
</div>
{{end}}

View File

@ -0,0 +1,25 @@
{{ define "title" }}{{i18n "AuthTitle"}}{{ end }}
{{ define "content" }}
<div class="flex flex-col justify-center items-center self-center max-w-lg">
<span class="text-center mt-8">{{i18n "AuthFallbackWelcome"}}</span>
<form
id="password-fallback"
method="POST"
action="{{urlTo "auth:fallback:finalize"}}"
class="flex flex-row items-end"
>
{{ .csrfField }}
<div class="flex flex-col w-48">
<label class="mt-8 text-sm text-gray-600">Username</label>
<input type="text" name="user"
class="shadow rounded border border-transparent h-8 p-1 focus:outline-none focus:ring-2 focus:ring-green-400 focus:border-transparent">
<label class="mt-8 text-sm text-gray-600">Password</label>
<input type="password" name="pass"
class="shadow rounded border border-transparent h-8 p-1 focus:outline-none focus:ring-2 focus:ring-green-400 focus:border-transparent">
<button type="submit"
class="my-8 shadow rounded px-4 h-8 text-gray-100 bg-green-500 hover:bg-green-600 focus:outline-none focus:ring-2 focus:ring-green-600 focus:ring-opacity-50">Enter</button>
</div>
</form>
</div>
{{end}}

View File

@ -1,71 +0,0 @@
{{ define "title" }}{{i18n "AuthTitle"}}{{ end }}
{{ define "content" }}
<div id="page-header">
<h1 class="text-lg">{{i18n "AuthTitle"}}</h1>
<p id="welcome">{{i18n "AuthWelcome"}}</p>
</div>
<hr class="mt-5 pt-5">
<div>
<div id="page-header">
<h1 class="text-lg">{{i18n "AuthWithSSBTitle"}}</h1>
<p id="describe-withssb">{{i18n "AuthWithSSBStart"}}</p>
</div>
<div>
<form
id="start-siwssb"
method="GET"
action="{{urlTo "auth:login:check" }}"
class="flex flex-row items-end"
>
<label>Alias or SSB ID</label>
<input
type="text"
name="input"
class="shadow rounded border border-transparent h-8 p-1 focus:outline-none focus:ring-2 focus:ring-pink-400 focus:border-transparent"
>
<button
type="submit"
class="shadow rounded px-4 h-8 text-gray-100 bg-pink-600 hover:bg-pink-700 focus:outline-none focus:ring-2 focus:ring-pink-600 focus:ring-opacity-50"
>Enter</button>
</form>
</div>
</div>
<hr class="mt-5 pt-5">
<div>
<div id="page-header">
<h1 class="text-lg">{{i18n "AuthFallbackTitle"}}</h1>
<p id="describe-password">{{i18n "AuthFallbackWelcome"}}</p>
</div>
<div>
<form
id="password-fallback"
method="POST"
action={{urlTo "auth:fallback:signin" }}
class="flex flex-row items-end"
>
{{ .csrfField }}
<div class="w-96 grid grid-cols-2 gap-x-4 gap-y-1 mr-4">
<label>Username</label>
<label>Password</label>
<input
type="text"
name="user"
class="shadow rounded border border-transparent h-8 p-1 focus:outline-none focus:ring-2 focus:ring-pink-400 focus:border-transparent"
>
<input
type="password"
name="pass"
class="shadow rounded border border-transparent h-8 p-1 focus:outline-none focus:ring-2 focus:ring-pink-400 focus:border-transparent"
>
</div>
<button
type="submit"
class="shadow rounded px-4 h-8 text-gray-100 bg-pink-600 hover:bg-pink-700 focus:outline-none focus:ring-2 focus:ring-pink-600 focus:ring-opacity-50"
>Enter</button>
</form>
</div>
</div>
{{end}}

View File

@ -1,9 +1,5 @@
{{ define "title" }}{{i18n "AuthWithSSBTitle"}}{{ end }}
{{ define "content" }}
<div id="page-header">
<h1 id="welcome" class="text-lg">{{i18n "AuthWithSSBServerStart"}}</h1>
</div>
<div class="flex flex-col justify-center items-center self-center max-w-lg">
<span class="text-center mt-8">{{i18n "AuthWithSSBWelcome"}}</span>
@ -11,10 +7,14 @@
id="start-auth-uri"
href="{{.SSBURI}}"
target="_blank"
class="shadow rounded flex flex-row justify-center items-center mt-8 px-4 h-8 text-gray-100 bg-pink-600 hover:bg-pink-700 focus:outline-none focus:ring-2 focus:ring-pink-600 focus:ring-opacity-50"
class="shadow rounded flex flex-row justify-center items-center mt-8 px-4 h-8 text-gray-100 bg-green-500 hover:bg-green-600 focus:outline-none focus:ring-2 focus:ring-green-600 focus:ring-opacity-50"
>{{i18n "AuthWithSSBTitle"}}</a>
<div class="mt-8 w-64 h-px bg-gray-200"></div>
<p id="waiting" class="hidden mt-8 animate-pulse text-green-500">Waiting for confirmation</p>
<p id="failed" class="hidden mt-8 text-red-700 text-center">{{i18n "AuthWithSSBError"}}</p>
<hr class="mt-8 w-64 h-px bg-gray-200"></hr>
<span class="text-center mt-8">{{i18n "AuthWithSSBInstructQR"}}</span>
@ -28,11 +28,6 @@
/>
</div>
<div class="text-xs">
<h3>Server events</h3>
<p id="ping"></p>
<p id="failed" class="text-red-500"></p>
</div>
<div id="challenge" class="hidden" data-sc="{{.ServerChallenge}}"></div>
<script src="/assets/login-events.js"></script>
{{end}}

View File

@ -41,7 +41,7 @@
{{else}}
<a
href="{{urlTo "auth:login"}}"
class="pl-3 pr-4 py-2 sm:py-1 font-semibold text-sm text-gray-500 hover:text-green-600"
class="pl-3 pr-4 py-2 sm:py-1 font-semibold text-sm text-gray-500 hover:text-green-500"
>{{i18n "AuthSignIn"}}</a>
{{end}}
</div>