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

Enhanced session expiration handling #89

Merged
merged 5 commits into from
May 31, 2024
Merged
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
4 changes: 2 additions & 2 deletions internal/webserver/embedded/js/delete.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,11 @@ deleteForm.addEventListener('submit', event => {
'Content-Type': 'application/x-www-form-urlencoded'
},
body: new URLSearchParams({
'id': deleteForm.elements['id'].value,
'id': deleteForm.elements['id'].value,
})
})
.then((response) => {
if (response.ok) {
if (response.ok || response.status == "403") {
location.reload();
} else {
let message = document.getElementById("error-message-container");
Expand Down
3 changes: 3 additions & 0 deletions internal/webserver/embedded/js/highlight.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ Array.from(links).forEach((link) => {
}
return;
}
if (response.status == "403") {
location.reload()
}
})
.catch(function (error) {
// Catch errors
Expand Down
14 changes: 9 additions & 5 deletions internal/webserver/embedded/js/send-email.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ Array.from(forms).forEach(form => {
const submit = form.querySelector('button');
let sendIcon = form.querySelector('.bi-send-fill');
let spinner = form.querySelector('.spinner-border');

submit.setAttribute("disabled", true);
spinner.classList.remove("visually-hidden");
sendIcon.classList.add("visually-hidden");
Expand All @@ -20,16 +20,20 @@ Array.from(forms).forEach(form => {
},
body: new URLSearchParams({
'email': form.elements[0].value,
'slug': form.elements[1].value,
'slug': form.elements[1].value,
})
})
.then((response) => {
let message = form.querySelector(".send-email-message")
message.classList.remove("visually-hidden");
if (!response.ok) {
message.innerHTML = form.getAttribute("data-error-message");
message.classList.remove("text-success");
message.classList.add("text-danger");
if (response.status == "403") {
location.reload()
} else {
message.innerHTML = form.getAttribute("data-error-message");
message.classList.remove("text-success");
message.classList.add("text-danger");
}
} else {
message.innerHTML = form.getAttribute("data-success-message");
message.classList.remove("text-danger");
Expand Down
3 changes: 2 additions & 1 deletion internal/webserver/embedded/translations/es.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
"Send": Enviar
"Actions": Acciones
"Send to email unavailable, no email service configured": "Enviar a correo electrónico no disponible, no se ha configurado ningún servicio"
"Document sent succesfully": "Documento enviado con éxito"
"Document sent successfully": "Documento enviado con éxito"
"There was an error sending the document, please try again later": "Hubo un error al enviar el documento, por favor, vuelva a intentarlo más tarde"
"Read": "Leer"
"Users": "Usuarios"
Expand Down Expand Up @@ -132,3 +132,4 @@
"Show settings": "Mostrar configuración"
"Go left": "Ir a la izquierda"
"Go right": "Ir a la derecha"
"Session expired, please log in again.": "Sesión expirada, por favor identifícate de nuevo."
3 changes: 2 additions & 1 deletion internal/webserver/embedded/translations/fr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
"Send": Envoyer
"Actions": Actions
"Send to email unavailable, no email service configured": "Envoyer par e-mail indisponible, aucun service de messagerie configuré"
"Document sent succesfully": "Document envoyé avec succès"
"Document sent successfully": "Document envoyé avec succès"
"There was an error sending the document, please try again later": "Une erreur s'est produite lors de l'envoi du document, veuillez réessayer ultérieurement"
"Read": "Lire"
"Users": "Utilisateurs"
Expand Down Expand Up @@ -132,3 +132,4 @@
"Show settings": "Afficher les paramètres"
"Go left": "Aller à gauche"
"Go right": "Aller à droite"
"Session expired, please log in again.": "Session expirée, veuillez vous reconnecter."
14 changes: 7 additions & 7 deletions internal/webserver/embedded/views/document.html
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ <h3 class="card-text text-center mx-1 mt-3">
</svg>
&nbsp;&nbsp;{{t .Lang "Read"}}
</a>

<a href="/download/{{.Document.Slug}}" class="btn btn-outline-secondary" download>
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-cloud-download" viewBox="0 0 16 16">
<path d="M4.406 1.342A5.53 5.53 0 0 1 8 0c2.69 0 4.923 2 5.166 4.579C14.758 4.804 16 6.137 16 7.773 16 9.569 14.502 11 12.687 11H10a.5.5 0 0 1 0-1h2.688C13.979 10 15 8.988 15 7.773c0-1.216-1.02-2.228-2.313-2.228h-.5v-.5C12.188 2.825 10.328 1 8 1a4.53 4.53 0 0 0-2.941 1.1c-.757.652-1.153 1.438-1.153 2.055v.448l-.445.049C2.064 4.805 1 5.952 1 7.318 1 8.785 2.23 10 3.781 10H6a.5.5 0 0 1 0 1H3.781C1.708 11 0 9.366 0 7.318c0-1.763 1.266-3.223 2.942-3.593.143-.863.698-1.723 1.464-2.383z"/>
Expand All @@ -47,20 +47,20 @@ <h3 class="card-text text-center mx-1 mt-3">
</svg>
&nbsp;&nbsp;{{t .Lang "Highlight"}}
</a>

<a href="/highlights" class="btn btn-outline-secondary dehighlight {{if not .Document.Highlighted}}visually-hidden{{end}}" data-slug="{{.Document.Slug}}" data-dehighlight="{{.OnDehighlight}}" data-method="DELETE">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-star-fill" viewBox="0 0 16 16">
<path d="M3.612 15.443c-.386.198-.824-.149-.746-.592l.83-4.73L.173 6.765c-.329-.314-.158-.888.283-.95l4.898-.696L7.538.792c.197-.39.73-.39.927 0l2.184 4.327 4.898.696c.441.062.612.636.282.95l-3.522 3.356.83 4.73c.078.443-.36.79-.746.592L8 13.187l-4.389 2.256z"/>
</svg>
&nbsp;&nbsp;{{t .Lang "Remove from highlights"}}
</a>
{{end}}
{{end}}

{{if not .EmailSendingConfigured}}
<p class="text-start">{{t .Lang "Send to email unavailable, no email service configured"}}</p>
{{else}}
<div>
<form method="post" action="send" data-success-message='{{t .Lang "Document sent succesfully"}}' data-error-message='{{t .Lang "There was an error sending the document, please try again later"}}' class="send-email mt-3">
<form method="post" action="send" data-success-message='{{t .Lang "Document sent successfully"}}' data-error-message='{{t .Lang "There was an error sending the document, please try again later"}}' class="send-email mt-3">
<label for="email" class="form-label text-start">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-envelope-fill" viewBox="0 0 16 16">
<path d="M.05 3.555A2 2 0 0 1 2 2h12a2 2 0 0 1 1.95 1.555L8 8.414.05 3.555ZM0 4.697v7.104l5.803-3.558L0 4.697ZM6.761 8.83l-6.57 4.027A2 2 0 0 0 2 14h12a2 2 0 0 0 1.808-1.144l-6.57-4.027L8 9.586l-1.239-.757Zm3.436-.586L16 11.801V4.697l-5.803 3.546Z"/>
Expand Down Expand Up @@ -155,7 +155,7 @@ <h4>{{t $lang "Other documents in collection \"%s\"" .Document.Series}}</h4>
{{end}}
</div>
</section>
{{end}}
{{end}}

{{ $length := len .SameAuthors }} {{ if gt $length 0 }}
<section class="row mt-5">
Expand All @@ -178,7 +178,7 @@ <h4>
{{end}}
</div>
</section>
{{end}}
{{end}}

{{ $length := len .SameSubjects }} {{ if gt $length 0 }}
<section class="row mt-5">
Expand All @@ -198,7 +198,7 @@ <h4>{{t $lang "Other documents with similar subjects"}}</h4>
{{end}}
</div>
</section>
{{end}}
{{end}}
</div>
</div>

Expand Down
18 changes: 13 additions & 5 deletions internal/webserver/embedded/views/layout.html
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ <h5 class="offcanvas-title" id="offcanvasNavbarLabel">Coreander</h5>
<a class="dropdown-item" href="/{{.Lang}}/highlights/{{.Session.Username}}">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-star-fill" viewBox="0 0 16 16">
<path d="M3.612 15.443c-.386.198-.824-.149-.746-.592l.83-4.73L.173 6.765c-.329-.314-.158-.888.283-.95l4.898-.696L7.538.792c.197-.39.73-.39.927 0l2.184 4.327 4.898.696c.441.062.612.636.282.95l-3.522 3.356.83 4.73c.078.443-.36.79-.746.592L8 13.187l-4.389 2.256z"/>
</svg>
</svg>
{{t .Lang "Highlights"}}
</a>
</li>
Expand All @@ -85,11 +85,11 @@ <h5 class="offcanvas-title" id="offcanvasNavbarLabel">Coreander</h5>
<a class="dropdown-item" href="/{{.Lang}}/upload">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-cloud-upload-fill" viewBox="0 0 16 16">
<path fill-rule="evenodd" d="M8 0a5.53 5.53 0 0 0-3.594 1.342c-.766.66-1.321 1.52-1.464 2.383C1.266 4.095 0 5.555 0 7.318 0 9.366 1.708 11 3.781 11H7.5V5.707L5.354 7.854a.5.5 0 1 1-.708-.708l3-3a.5.5 0 0 1 .708 0l3 3a.5.5 0 0 1-.708.708L8.5 5.707V11h4.188C14.502 11 16 9.57 16 7.773c0-1.636-1.242-2.969-2.834-3.194C12.923 1.999 10.69 0 8 0m-.5 14.5V11h1v3.5a.5.5 0 0 1-1 0"/>
</svg>
</svg>
{{t .Lang "Upload document"}}
</a>
</li>
{{end}}
</li>
{{end}}
<li>
<hr class="dropdown-divider">
</li>
Expand Down Expand Up @@ -144,7 +144,7 @@ <h5 class="offcanvas-title" id="offcanvasNavbarLabel">Coreander</h5>
</div>
</div>
{{end}}

{{if .Error}}
<div class="row text-start">
<div class="alert alert-danger" role="alert">
Expand All @@ -153,6 +153,14 @@ <h5 class="offcanvas-title" id="offcanvasNavbarLabel">Coreander</h5>
</div>
{{end}}

{{if .Warning}}
<div class="row text-start">
<div class="alert alert-warning" role="alert">
{{t .Lang .Warning}}
</div>
</div>
{{end}}

{{if .Message}}
<div class="row text-start">
<div class="alert alert-success" role="alert">
Expand Down
14 changes: 7 additions & 7 deletions internal/webserver/embedded/views/partials/actions.html
Original file line number Diff line number Diff line change
Expand Up @@ -24,23 +24,23 @@
</svg>
&nbsp;&nbsp;{{t .Lang "Highlight"}}
</a>
</li>
</li>

<li class="dehighlight {{if not .Document.Highlighted}}visually-hidden{{end}}">
<a href="/highlights" class="dropdown-item dehighlight" data-slug="{{.Document.Slug}}" data-dehighlight="{{.OnDehighlight}}" data-method="DELETE">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-star-fill" viewBox="0 0 16 16">
<path d="M3.612 15.443c-.386.198-.824-.149-.746-.592l.83-4.73L.173 6.765c-.329-.314-.158-.888.283-.95l4.898-.696L7.538.792c.197-.39.73-.39.927 0l2.184 4.327 4.898.696c.441.062.612.636.282.95l-3.522 3.356.83 4.73c.078.443-.36.79-.746.592L8 13.187l-4.389 2.256z"/>
</svg>
&nbsp;&nbsp;{{t .Lang "Remove from highlights"}}
</a>
</li>
{{end}}
</li>
{{end}}
<div class="dropdown-divider"></div>
{{if not .EmailSendingConfigured}}
<li class="dropdown-item disabled">{{t .Lang "Send to email unavailable, no email service configured"}}</li>
{{else}}
<li>
<form method="post" action="send" data-success-message='{{t .Lang "Document sent succesfully"}}' data-error-message='{{t .Lang "There was an error sending the document, please try again later"}}' class="send-email">
<form method="post" action="send" data-success-message='{{t .Lang "Document sent successfully"}}' data-error-message='{{t .Lang "There was an error sending the document, please try again later"}}' class="send-email">
<div class="px-3 py-1">
<label for="email" class="form-label">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-envelope-fill" viewBox="0 0 16 16">
Expand All @@ -57,10 +57,10 @@
<path d="M15.964.686a.5.5 0 0 0-.65-.65L.767 5.855H.766l-.452.18a.5.5 0 0 0-.082.887l.41.26.001.002 4.995 3.178 3.178 4.995.002.002.26.41a.5.5 0 0 0 .886-.083l6-15Zm-1.833 1.89L6.637 10.07l-.215-.338a.5.5 0 0 0-.154-.154l-.338-.215 7.494-7.494 1.178-.471-.47 1.178Z"/>
</svg>
<span class="spinner-border spinner-border-sm visually-hidden" aria-hidden="true"></span>
</button>
</button>
</div>
<p class="text-end">
<small class="text-muted"><em>{{t .Lang "Sent from %s" .EmailFrom}}</em></small>
<small class="text-muted"><em>{{t .Lang "Sent from %s" .EmailFrom}}</em></small>
</p>
</div>
<div class="p-3 visually-hidden fs-6 send-email-message"></div>
Expand Down
15 changes: 10 additions & 5 deletions internal/webserver/middleware.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ func AlwaysRequireAuthentication(jwtSecret []byte, sender Sender) func(*fiber.Ct
return c.Next()
},
ErrorHandler: func(c *fiber.Ctx, err error) error {
return forbidden(c, sender)
return forbidden(c, sender, err)
},
})
}
Expand All @@ -97,25 +97,30 @@ func ConfigurableAuthentication(jwtSecret []byte, sender Sender, requireAuth boo
return c.Next()
},
ErrorHandler: func(c *fiber.Ctx, err error) error {
err = c.Next()
if requireAuth {
return forbidden(c, sender)
return forbidden(c, sender, err)
}
return err
return c.Next()
},
})
}

func forbidden(c *fiber.Ctx, sender Sender) error {
func forbidden(c *fiber.Ctx, sender Sender, err error) error {
emailSendingConfigured := true
if _, ok := sender.(*infrastructure.NoEmail); ok {
emailSendingConfigured = false
}
message := ""
if err.Error() != "missing or malformed JWT" {
message = "Session expired, please log in again."
}

return c.Status(fiber.StatusForbidden).Render("auth/login", fiber.Map{
"Lang": chooseBestLanguage(c),
"Title": "Login",
"Version": c.App().Config().AppName,
"EmailSendingConfigured": emailSendingConfigured,
"DisableLoginLink": true,
"Warning": message,
}, "layout")
}
4 changes: 2 additions & 2 deletions internal/webserver/routes.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,11 +69,11 @@ func routes(app *fiber.App, controllers Controllers, jwtSecret []byte, sender Se
langGroup.Get("/upload", alwaysRequireAuthentication, RequireAdmin, controllers.Documents.UploadForm)
langGroup.Post("/upload", alwaysRequireAuthentication, RequireAdmin, controllers.Documents.Upload)

langGroup.Get("/logout", alwaysRequireAuthentication, controllers.Auth.SignOut)

// Authentication requirement is configurable for all routes below this middleware
app.Use(configurableAuthentication)

langGroup.Get("/logout", controllers.Auth.SignOut)

app.Get("/cover/:slug", controllers.Documents.Cover)

langGroup.Get("/document/:slug", controllers.Documents.Detail)
Expand Down