summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--controllers/errors.go53
-rw-r--r--static/css/main.css (renamed from static/css/style.css)0
-rw-r--r--templates/auth/login.django54
-rw-r--r--templates/error.django8
-rw-r--r--templates/layouts/generic.django27
-rw-r--r--types/errors.go10
-rw-r--r--utils/shortcuts/error.go25
7 files changed, 144 insertions, 33 deletions
diff --git a/controllers/errors.go b/controllers/errors.go
new file mode 100644
index 0000000..019083a
--- /dev/null
+++ b/controllers/errors.go
@@ -0,0 +1,53 @@
+package controllers
+
+import (
+ "lain/types"
+ "lain/utils/shortcuts"
+
+ "github.com/gofiber/fiber/v2"
+)
+
+func BadRequest(context *fiber.Ctx, err error) error {
+ return shortcuts.RenderError(types.TemplateError{
+ Context: context,
+ PageTitle: "400 – Bad Request",
+ ErrorMessage: shortcuts.BuildErrorMessage(err, "The request could not be understood by the server."),
+ StatusCode: fiber.StatusBadRequest,
+ })
+}
+
+func Forbidden(context *fiber.Ctx, err error) error {
+ return shortcuts.RenderError(types.TemplateError{
+ Context: context,
+ PageTitle: "403 – Forbidden",
+ ErrorMessage: shortcuts.BuildErrorMessage(err, "You do not have permission to access this resource."),
+ StatusCode: fiber.StatusForbidden,
+ })
+}
+
+func InternalServerError(context *fiber.Ctx, err error) error {
+ return shortcuts.RenderError(types.TemplateError{
+ Context: context,
+ PageTitle: "500 – Internal Server Error",
+ ErrorMessage: shortcuts.BuildErrorMessage(err, "An unexpected error occurred on the server."),
+ StatusCode: fiber.StatusInternalServerError,
+ })
+}
+
+func NotFound(context *fiber.Ctx, err error) error {
+ return shortcuts.RenderError(types.TemplateError{
+ Context: context,
+ PageTitle: "404 – Not Found",
+ ErrorMessage: shortcuts.BuildErrorMessage(err, "The page you are looking for does not exist."),
+ StatusCode: fiber.StatusNotFound,
+ })
+}
+
+func Unauthorized(context *fiber.Ctx, err error) error {
+ return shortcuts.RenderError(types.TemplateError{
+ Context: context,
+ PageTitle: "401 – Unauthorized",
+ ErrorMessage: shortcuts.BuildErrorMessage(err, "You must be logged in to access this resource."),
+ StatusCode: fiber.StatusUnauthorized,
+ })
+}
diff --git a/static/css/style.css b/static/css/main.css
index 683a620..683a620 100644
--- a/static/css/style.css
+++ b/static/css/main.css
diff --git a/templates/auth/login.django b/templates/auth/login.django
index 0fbdceb..33ed81a 100644
--- a/templates/auth/login.django
+++ b/templates/auth/login.django
@@ -1,37 +1,25 @@
-<!DOCTYPE html>
-<html lang="en">
- <head>
- <meta charset="UTF-8" />
- <meta name="viewport" content="width=device-width, initial-scale=1.0" />
- <title>{{ Title }}</title>
- <link rel="stylesheet" href="/static/css/style.css" />
- </head>
- <body class="login-page">
- <div class="login-container">
- <h1>{{ AppName }}</h1>
- <p class="subtitle">{{ AppDescription }}</p>
+{% extends 'layouts/generic.django' %}
+{% block content %}
+ <div class="login-container">
+ <h1>{{ AppName }}</h1>
+ <p class="subtitle">{{ AppDescription }}</p>
- {% if Error %}
- <div class="error">{{ Error }}</div>
- {% endif %}
+ {% if Error %}
+ <div class="error">{{ Error }}</div>
+ {% endif %}
- <form method="POST" action="{% url 'auth.login' %}">
- <div class="field">
- <label>Email</label>
- <input type="email" name="email" required autofocus />
- </div>
+ <form method="POST" action="{% url 'auth.login' %}">
+ <div class="field">
+ <label>Email</label>
+ <input type="email" name="email" required autofocus />
+ </div>
- <div class="field">
- <label>Password</label>
- <input type="password" name="password" required />
- </div>
+ <div class="field">
+ <label>Password</label>
+ <input type="password" name="password" required />
+ </div>
- <button type="submit">Login</button>
- </form>
-
- <footer>
- {{ AppName }} - Powered by {{ AppEngine }} - &copy; <a href="https://shi.foo" target="_blank" rel="noopener noreferrer">shi.foo</a> 2025
- </footer>
- </div>
- </body>
-</html>
+ <button type="submit">Login</button>
+ </form>
+ </div>
+{% endblock %}
diff --git a/templates/error.django b/templates/error.django
new file mode 100644
index 0000000..f766688
--- /dev/null
+++ b/templates/error.django
@@ -0,0 +1,8 @@
+{% extends 'layouts/generic.django' %}
+{% block content %}
+ <div class="error-container">
+ <h1>{{ ErrorTitle }}</h1>
+ <p>{{ ErrorMessage }}</p>
+ <a href="{% url 'auth.login' %}">Go back home</a>
+ </div>
+{% endblock %}
diff --git a/templates/layouts/generic.django b/templates/layouts/generic.django
new file mode 100644
index 0000000..3ca183b
--- /dev/null
+++ b/templates/layouts/generic.django
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <meta charset="UTF-8" />
+ <title>{{ Title }} - {{ Appname }}</title>
+ <link rel="stylesheet" href="/static/css/main.css" />
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+ <link rel="manifest" href="/static/extra/site.webmanifest" />
+ {% block head %}
+
+ {% endblock %}
+ </head>
+ <body>
+ <main class="content">
+ {% block content %}
+
+ {% endblock %}
+ </main>
+
+ <footer>
+ {{ AppName }} - Powered by {{ AppEngine }} - &copy; <a href="https://shi.foo" target="_blank" rel="noopener noreferrer">shi.foo</a> 2025
+ </footer>
+ </body>
+ {% block scripts %}
+
+ {% endblock %}
+</html>
diff --git a/types/errors.go b/types/errors.go
new file mode 100644
index 0000000..11f60f9
--- /dev/null
+++ b/types/errors.go
@@ -0,0 +1,10 @@
+package types
+
+import "github.com/gofiber/fiber/v2"
+
+type TemplateError struct {
+ Context *fiber.Ctx
+ PageTitle string
+ ErrorMessage error
+ StatusCode int
+}
diff --git a/utils/shortcuts/error.go b/utils/shortcuts/error.go
new file mode 100644
index 0000000..4cb0e81
--- /dev/null
+++ b/utils/shortcuts/error.go
@@ -0,0 +1,25 @@
+package shortcuts
+
+import (
+ "errors"
+ "lain/types"
+ "lain/utils/meta"
+
+ "github.com/gofiber/fiber/v2"
+)
+
+func BuildErrorMessage(err error, alternateString string) error {
+ if err != nil {
+ return err
+ }
+
+ return errors.New(alternateString)
+}
+
+func RenderError(error types.TemplateError) error {
+ meta.SetPageTitle(error.Context, error.PageTitle)
+ return RenderWithStatus(error.Context, "error", fiber.Map{
+ "ErrorTitle": error.PageTitle,
+ "ErrorMessage": error.ErrorMessage.Error(),
+ }, error.StatusCode)
+}