Compare commits

...
Sign in to create a new pull request.

16 commits

Author SHA1 Message Date
14695b976d
Update licenses 2026-05-06 08:03:31 +02:00
a4b6b3cb1e
Update email templates 2026-05-06 08:02:34 +02:00
b582b10360
Implement mailer and add welcome email for POP account 2026-05-05 18:58:40 +02:00
a6b926c9bf
Email should not yet be unique in database 2026-04-30 15:01:12 +02:00
cc203dd57f
Update go dependencies 2026-04-30 14:48:44 +02:00
46c3a30159
Prettify templates 2026-04-30 14:48:34 +02:00
6654463aee
Authelia users sync 2026-04-30 14:45:39 +02:00
9e1b06a448
If person has SSO account, show warning about changing the email address 2026-04-17 16:29:35 +02:00
4318a7b66d
Uodate person account model: no password and created as time 2026-04-17 16:28:57 +02:00
2e332b8f3e
Ability to create account for members 2026-03-18 19:17:25 +01:00
07db65f63f
Do not check email valid if email is empty 2026-03-13 14:50:38 +01:00
aeb43e4775
Email is unique for people + start work on authelia integration 2026-03-13 14:42:40 +01:00
76981f31c8
Fix flaw: was able to duplicate user emails because case sensitive check 2026-03-13 14:26:27 +01:00
1038deb225
Fix page contacts page title 2026-03-13 14:12:22 +01:00
96783b4912
Update PNPM libs 2026-03-06 20:15:25 +01:00
b619874a81
Docker compose: pin postgres version 2026-03-06 18:26:47 +01:00
24 changed files with 2057 additions and 927 deletions

View file

@ -5,3 +5,11 @@ APP_LISTEN_PORT=3000
APP_BEHIND_PROXY=false
DATABASE_DSN="host=localhost user=camarades password=camarades dbname=camarades port=5432 sslmode=disable TimeZone=Europe/Zurich"
SESSIONS_LOCATION=./sessions.db
AUTHELIA_USERS_LOCATION=./users.yml
AUTHELIA_RESET_URL=https://login.popvaud.ch/reset-password/step1
MAIL_HOST=mail.infomaniak.com
MAIL_PORT=587
MAIL_USERNAME=no-reply@popvaud.ch
MAIL_PASSWORD=very-secure-password
MAIL_FROM_NAME=POP Vaud
MAIL_FROM_ADDRESS=no-reply@popvaud.ch

1
.gitignore vendored
View file

@ -6,3 +6,4 @@ static/assets
pop-camarades
*.db
__debug_bin*
users.yml

View file

@ -1,6 +1,6 @@
services:
postgres:
image: postgres:latest
image: postgres:17
container_name: camarades-postgres
ports:
- "127.0.0.1:5432:5432"

View file

@ -94,7 +94,7 @@ func Contacts(c *fiber.Ctx) error {
db.Order("position asc").Find(&fields, "person_type = ?", "contact")
return c.Render("people", fiber.Map{
"PageTitle": "Contacts",
"PageTitle": "Sympathisants",
"MembersPage": false,
"People": results.Results,
"Pagination": results.Pagination,
@ -462,7 +462,9 @@ func ContactAdd(c *fiber.Ctx) error {
case "FirstName":
errors = append(errors, "Le prénom est requis et ne peut pas contenir plus de 100 caractères")
case "Email":
errors = append(errors, "L'adresse email doit être valide")
if len(data.Email) > 0 {
errors = append(errors, "L'adresse email doit être valide")
}
case "Phone":
errors = append(errors, "Le numéro de téléphone fixe est trop long")
case "Mobile":
@ -495,6 +497,18 @@ func ContactAdd(c *fiber.Ctx) error {
person.PostalCode = data.PostalCode
person.City = data.City
if len(data.Email) > 0 {
var personEmail []models.Person
result := db.Find(&personEmail, "LOWER(email) = LOWER(?)", data.Email)
if result.Error != nil {
return result.Error
}
if result.RowsAffected > 0 {
errors = append(errors, "L'adresse email est déjà utilisée par un membre ou un sympathisant")
}
}
sectionID, err := strconv.ParseUint(data.Section, 10, 0)
if err == nil {
for _, section := range sections {
@ -711,7 +725,9 @@ func ContactEdit(c *fiber.Ctx) error {
case "FirstName":
errors = append(errors, "Le prénom est requis et ne peut pas contenir plus de 100 caractères")
case "Email":
errors = append(errors, "L'adresse email doit être valide")
if len(data.Email) > 0 {
errors = append(errors, "L'adresse email doit être valide")
}
case "Phone":
errors = append(errors, "Le numéro de téléphone fixe est trop long")
case "Mobile":
@ -744,6 +760,18 @@ func ContactEdit(c *fiber.Ctx) error {
person.PostalCode = data.PostalCode
person.City = data.City
if len(data.Email) > 0 {
var personEmail []models.Person
result := db.Find(&personEmail, "LOWER(email) = LOWER(?) AND id <> ?", data.Email, person.ID)
if result.Error != nil {
return result.Error
}
if result.RowsAffected > 0 {
errors = append(errors, "L'adresse email est déjà utilisée par un membre ou un sympathisant")
}
}
sectionID, err := strconv.ParseUint(data.Section, 10, 0)
if err == nil {
for _, section := range sections {

View file

@ -8,17 +8,19 @@ import (
"time"
"git.readonly.ch/bouzoure/pop-camarades/helpers"
"git.readonly.ch/bouzoure/pop-camarades/helpers/authelia"
"git.readonly.ch/bouzoure/pop-camarades/helpers/database"
"git.readonly.ch/bouzoure/pop-camarades/models"
"github.com/charmbracelet/log"
"github.com/go-playground/validator/v10"
"github.com/gofiber/fiber/v2"
"github.com/google/uuid"
)
type PersonValidation struct {
LastName string `validate:"max=100"`
FirstName string `validate:"required,min=1,max=100"`
Email string `validate:"max=100"`
Email string `validate:"max=100,email"`
Phone string `validate:"max=100"`
Mobile string `validate:"max=100"`
Address1 string `validate:"max=100"`
@ -477,7 +479,9 @@ func MemberAdd(c *fiber.Ctx) error {
case "FirstName":
errors = append(errors, "Le prénom est requis et ne peut pas contenir plus de 100 caractères")
case "Email":
errors = append(errors, "L'adresse email doit être valide")
if len(data.Email) > 0 {
errors = append(errors, "L'adresse email doit être valide")
}
case "Phone":
errors = append(errors, "Le numéro de téléphone fixe est trop long")
case "Mobile":
@ -498,6 +502,18 @@ func MemberAdd(c *fiber.Ctx) error {
}
}
if len(data.Email) > 0 {
var personEmail []models.Person
result := db.Find(&personEmail, "LOWER(email) = LOWER(?)", data.Email)
if result.Error != nil {
return result.Error
}
if result.RowsAffected > 0 {
errors = append(errors, "L'adresse email est déjà utilisée par un membre ou un sympathisant")
}
}
person.IsContact = false
person.IsMember = true
person.LastName = data.LastName
@ -622,6 +638,16 @@ func MemberAdd(c *fiber.Ctx) error {
}
}
if c.FormValue("account-enabled") == "on" {
personAccount := models.PersonAccount{
PersonID: person.ID,
UUID: uuid.New(),
Enabled: true,
Groups: strings.Join(authelia.GetPersonGroups(person.ID), "|||"),
}
db.Create(&personAccount)
}
c.Redirect(fmt.Sprintf(
"/members/%d",
person.ID,
@ -700,6 +726,9 @@ func MemberEdit(c *fiber.Ctx) error {
person.ID,
)
var personAccount models.PersonAccount
db.Find(&personAccount, "person_id = ?", person.ID)
var errors []string
if c.Method() == "POST" {
data := PersonValidation{
@ -726,7 +755,9 @@ func MemberEdit(c *fiber.Ctx) error {
case "FirstName":
errors = append(errors, "Le prénom est requis et ne peut pas contenir plus de 100 caractères")
case "Email":
errors = append(errors, "L'adresse email doit être valide")
if len(data.Email) > 0 {
errors = append(errors, "L'adresse email doit être valide")
}
case "Phone":
errors = append(errors, "Le numéro de téléphone fixe est trop long")
case "Mobile":
@ -747,6 +778,18 @@ func MemberEdit(c *fiber.Ctx) error {
}
}
if len(data.Email) > 0 {
var personEmail []models.Person
result := db.Find(&personEmail, "LOWER(email) = LOWER(?) AND id <> ?", data.Email, person.ID)
if result.Error != nil {
return result.Error
}
if result.RowsAffected > 0 {
errors = append(errors, "L'adresse email est déjà utilisée par un membre ou un sympathisant")
}
}
person.IsContact = false
person.IsMember = true
person.LastName = data.LastName
@ -878,6 +921,33 @@ func MemberEdit(c *fiber.Ctx) error {
return result.Error
}
if c.FormValue("account-enabled") == "on" && personAccount.ID <= 0 {
personAccount = models.PersonAccount{
PersonID: person.ID,
UUID: uuid.New(),
Enabled: true,
Groups: strings.Join(authelia.GetPersonGroups(person.ID), "|||"),
}
db.Create(&personAccount)
} else if c.FormValue("account-enabled") == "on" && personAccount.ID > 0 {
personAccount.Enabled = true
personAccount.Groups = strings.Join(authelia.GetPersonGroups(person.ID), "|||")
if personAccount.AccountCreated.Valid {
personAccount.UpdateNeeded = true
}
db.Save(&personAccount)
} else if c.FormValue("account-enabled") != "on" && personAccount.ID > 0 {
personAccount.Enabled = false
if personAccount.AccountCreated.Valid {
personAccount.UpdateNeeded = true
}
db.Save(&personAccount)
}
c.Redirect(fmt.Sprintf(
"/members/%d",
person.ID,
@ -886,12 +956,13 @@ func MemberEdit(c *fiber.Ctx) error {
}
return c.Render("person_form", fiber.Map{
"PageTitle": title,
"Person": person,
"Sections": sections,
"Fields": fields,
"FieldValues": fieldValues,
"Errors": errors,
"PageTitle": title,
"Person": person,
"Sections": sections,
"Fields": fields,
"FieldValues": fieldValues,
"PersonAccount": personAccount,
"Errors": errors,
})
}

View file

@ -109,7 +109,7 @@ func UserAdd(c *fiber.Ctx) error {
user.Email = data.Email
var usersEmail []models.User
result := db.Find(&usersEmail, "email = ?", user.Email)
result := db.Find(&usersEmail, "LOWER(email) = LOWER(?)", user.Email)
if result.Error != nil {
return result.Error
}

70
go.mod
View file

@ -1,77 +1,83 @@
module git.readonly.ch/bouzoure/pop-camarades
go 1.23.4
go 1.25.3
require (
github.com/brianvoe/gofakeit/v7 v7.3.0
github.com/charmbracelet/log v0.4.2
github.com/alexedwards/argon2id v1.0.0
github.com/brianvoe/gofakeit/v7 v7.14.1
github.com/charmbracelet/log v1.0.0
github.com/flosch/pongo2/v6 v6.0.0
github.com/go-playground/validator/v10 v10.27.0
github.com/gofiber/fiber/v2 v2.52.8
github.com/go-playground/validator/v10 v10.30.2
github.com/gofiber/fiber/v2 v2.52.13
github.com/gofiber/helmet/v2 v2.2.26
github.com/gofiber/storage/badger/v2 v2.0.1
github.com/gofiber/storage/badger/v2 v2.1.5
github.com/gofiber/template/django/v3 v3.1.14
github.com/golobby/dotenv v1.3.2
github.com/google/uuid v1.6.0
github.com/pquerna/otp v1.5.0
github.com/yuin/goldmark v1.7.12
golang.org/x/crypto v0.40.0
github.com/sethvargo/go-password v0.3.1
github.com/wneessen/go-mail v0.7.2
github.com/yuin/goldmark v1.8.2
go.yaml.in/yaml/v4 v4.0.0-rc.4
golang.org/x/crypto v0.50.0
gorm.io/driver/postgres v1.6.0
gorm.io/gorm v1.30.0
gorm.io/gorm v1.31.1
)
require (
github.com/andybalholm/brotli v1.2.0 // indirect
github.com/andybalholm/brotli v1.2.1 // indirect
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
github.com/boombuler/barcode v1.0.2 // indirect
github.com/boombuler/barcode v1.1.0 // indirect
github.com/cespare/xxhash v1.1.0 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/charmbracelet/colorprofile v0.3.1 // indirect
github.com/charmbracelet/colorprofile v0.4.3 // indirect
github.com/charmbracelet/lipgloss v1.1.0 // indirect
github.com/charmbracelet/x/ansi v0.9.3 // indirect
github.com/charmbracelet/x/cellbuf v0.0.13 // indirect
github.com/charmbracelet/x/term v0.2.1 // indirect
github.com/charmbracelet/x/ansi v0.11.7 // indirect
github.com/charmbracelet/x/cellbuf v0.0.15 // indirect
github.com/charmbracelet/x/term v0.2.2 // indirect
github.com/clipperhouse/displaywidth v0.11.0 // indirect
github.com/clipperhouse/uax29/v2 v2.7.0 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/dgraph-io/badger/v3 v3.2103.5 // indirect
github.com/dgraph-io/ristretto v0.2.0 // indirect
github.com/dustin/go-humanize v1.0.1 // indirect
github.com/gabriel-vasile/mimetype v1.4.9 // indirect
github.com/go-logfmt/logfmt v0.6.0 // indirect
github.com/gabriel-vasile/mimetype v1.4.13 // indirect
github.com/go-logfmt/logfmt v0.6.1 // indirect
github.com/go-playground/locales v0.14.1 // indirect
github.com/go-playground/universal-translator v0.18.1 // indirect
github.com/gofiber/template v1.8.3 // indirect
github.com/gofiber/utils v1.1.0 // indirect
github.com/gofiber/utils/v2 v2.0.0-beta.10 // indirect
github.com/gofiber/utils v1.2.0 // indirect
github.com/gofiber/utils/v2 v2.0.4 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect
github.com/golang/protobuf v1.5.4 // indirect
github.com/golang/snappy v1.0.0 // indirect
github.com/golobby/cast v1.3.3 // indirect
github.com/google/flatbuffers v25.2.10+incompatible // indirect
github.com/google/flatbuffers v25.12.19+incompatible // indirect
github.com/jackc/pgpassfile v1.0.0 // indirect
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect
github.com/jackc/pgx/v5 v5.7.5 // indirect
github.com/jackc/pgx/v5 v5.9.2 // indirect
github.com/jackc/puddle/v2 v2.2.2 // indirect
github.com/jinzhu/inflection v1.0.0 // indirect
github.com/jinzhu/now v1.1.5 // indirect
github.com/klauspost/compress v1.18.0 // indirect
github.com/klauspost/compress v1.18.5 // indirect
github.com/leodido/go-urn v1.4.0 // indirect
github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
github.com/lucasb-eyer/go-colorful v1.4.0 // indirect
github.com/mattn/go-colorable v0.1.14 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mattn/go-runewidth v0.0.16 // indirect
github.com/mattn/go-isatty v0.0.22 // indirect
github.com/mattn/go-runewidth v0.0.23 // indirect
github.com/muesli/termenv v0.16.0 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/rivo/uniseg v0.4.7 // indirect
github.com/valyala/bytebufferpool v1.0.0 // indirect
github.com/valyala/fasthttp v1.63.0 // indirect
github.com/valyala/fasthttp v1.70.0 // indirect
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect
go.opencensus.io v0.24.0 // indirect
golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b // indirect
golang.org/x/net v0.42.0 // indirect
golang.org/x/sync v0.16.0 // indirect
golang.org/x/sys v0.34.0 // indirect
golang.org/x/text v0.27.0 // indirect
google.golang.org/protobuf v1.36.6 // indirect
golang.org/x/exp v0.0.0-20260410095643-746e56fc9e2f // indirect
golang.org/x/net v0.53.0 // indirect
golang.org/x/sync v0.20.0 // indirect
golang.org/x/sys v0.43.0 // indirect
golang.org/x/text v0.36.0 // indirect
google.golang.org/protobuf v1.36.11 // indirect
)

183
go.sum
View file

@ -2,35 +2,41 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMT
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE=
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
github.com/andybalholm/brotli v1.2.0 h1:ukwgCxwYrmACq68yiUqwIWnGY0cTPox/M94sVwToPjQ=
github.com/andybalholm/brotli v1.2.0/go.mod h1:rzTDkvFWvIrjDXZHkuS16NPggd91W3kUSvPlQ1pLaKY=
github.com/alexedwards/argon2id v1.0.0 h1:wJzDx66hqWX7siL/SRUmgz3F8YMrd/nfX/xHHcQQP0w=
github.com/alexedwards/argon2id v1.0.0/go.mod h1:tYKkqIjzXvZdzPvADMWOEZ+l6+BD6CtBXMj5fnJppiw=
github.com/andybalholm/brotli v1.2.1 h1:R+f5xP285VArJDRgowrfb9DqL18yVK0gKAW/F+eTWro=
github.com/andybalholm/brotli v1.2.1/go.mod h1:rzTDkvFWvIrjDXZHkuS16NPggd91W3kUSvPlQ1pLaKY=
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k=
github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8=
github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
github.com/boombuler/barcode v1.0.2 h1:79yrbttoZrLGkL/oOI8hBrUKucwOL0oOjUgEguGMcJ4=
github.com/boombuler/barcode v1.0.2/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
github.com/brianvoe/gofakeit/v7 v7.3.0 h1:TWStf7/lLpAjKw+bqwzeORo9jvrxToWEwp9b1J2vApQ=
github.com/brianvoe/gofakeit/v7 v7.3.0/go.mod h1:QXuPeBw164PJCzCUZVmgpgHJ3Llj49jSLVkKPMtxtxA=
github.com/boombuler/barcode v1.1.0 h1:ChaYjBR63fr4LFyGn8E8nt7dBSt3MiU3zMOZqFvVkHo=
github.com/boombuler/barcode v1.1.0/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
github.com/brianvoe/gofakeit/v7 v7.14.1 h1:a7fe3fonbj0cW3wgl5VwIKfZtiH9C3cLnwcIXWT7sow=
github.com/brianvoe/gofakeit/v7 v7.14.1/go.mod h1:QXuPeBw164PJCzCUZVmgpgHJ3Llj49jSLVkKPMtxtxA=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/charmbracelet/colorprofile v0.3.1 h1:k8dTHMd7fgw4bnFd7jXTLZrSU/CQrKnL3m+AxCzDz40=
github.com/charmbracelet/colorprofile v0.3.1/go.mod h1:/GkGusxNs8VB/RSOh3fu0TJmQ4ICMMPApIIVn0KszZ0=
github.com/charmbracelet/colorprofile v0.4.3 h1:QPa1IWkYI+AOB+fE+mg/5/4HRMZcaXex9t5KX76i20Q=
github.com/charmbracelet/colorprofile v0.4.3/go.mod h1:/zT4BhpD5aGFpqQQqw7a+VtHCzu+zrQtt1zhMt9mR4Q=
github.com/charmbracelet/lipgloss v1.1.0 h1:vYXsiLHVkK7fp74RkV7b2kq9+zDLoEU4MZoFqR/noCY=
github.com/charmbracelet/lipgloss v1.1.0/go.mod h1:/6Q8FR2o+kj8rz4Dq0zQc3vYf7X+B0binUUBwA0aL30=
github.com/charmbracelet/log v0.4.2 h1:hYt8Qj6a8yLnvR+h7MwsJv/XvmBJXiueUcI3cIxsyig=
github.com/charmbracelet/log v0.4.2/go.mod h1:qifHGX/tc7eluv2R6pWIpyHDDrrb/AG71Pf2ysQu5nw=
github.com/charmbracelet/x/ansi v0.9.3 h1:BXt5DHS/MKF+LjuK4huWrC6NCvHtexww7dMayh6GXd0=
github.com/charmbracelet/x/ansi v0.9.3/go.mod h1:3RQDQ6lDnROptfpWuUVIUG64bD2g2BgntdxH0Ya5TeE=
github.com/charmbracelet/x/cellbuf v0.0.13 h1:/KBBKHuVRbq1lYx5BzEHBAFBP8VcQzJejZ/IA3iR28k=
github.com/charmbracelet/x/cellbuf v0.0.13/go.mod h1:xe0nKWGd3eJgtqZRaN9RjMtK7xUYchjzPr7q6kcvCCs=
github.com/charmbracelet/x/term v0.2.1 h1:AQeHeLZ1OqSXhrAWpYUtZyX1T3zVxfpZuEQMIQaGIAQ=
github.com/charmbracelet/x/term v0.2.1/go.mod h1:oQ4enTYFV7QN4m0i9mzHrViD7TQKvNEEkHUMCmsxdUg=
github.com/charmbracelet/log v1.0.0 h1:HVVVMmfOorfj3BA9i8X8UL69Hoz9lI0PYwXfJvOdRc4=
github.com/charmbracelet/log v1.0.0/go.mod h1:uYgY3SmLpwJWxmlrPwXvzVYujxis1vAKRV/0VQB7yWA=
github.com/charmbracelet/x/ansi v0.11.7 h1:kzv1kJvjg2S3r9KHo8hDdHFQLEqn4RBCb39dAYC84jI=
github.com/charmbracelet/x/ansi v0.11.7/go.mod h1:9qGpnAVYz+8ACONkZBUWPtL7lulP9No6p1epAihUZwQ=
github.com/charmbracelet/x/cellbuf v0.0.15 h1:ur3pZy0o6z/R7EylET877CBxaiE1Sp1GMxoFPAIztPI=
github.com/charmbracelet/x/cellbuf v0.0.15/go.mod h1:J1YVbR7MUuEGIFPCaaZ96KDl5NoS0DAWkskup+mOY+Q=
github.com/charmbracelet/x/term v0.2.2 h1:xVRT/S2ZcKdhhOuSP4t5cLi5o+JxklsoEObBSgfgZRk=
github.com/charmbracelet/x/term v0.2.2/go.mod h1:kF8CY5RddLWrsgVwpw4kAa6TESp6EB5y3uxGLeCqzAI=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/clipperhouse/displaywidth v0.11.0 h1:lBc6kY44VFw+TDx4I8opi/EtL9m20WSEFgwIwO+UVM8=
github.com/clipperhouse/displaywidth v0.11.0/go.mod h1:bkrFNkf81G8HyVqmKGxsPufD3JhNl3dSqnGhOoSD/o0=
github.com/clipperhouse/uax29/v2 v2.7.0 h1:+gs4oBZ2gPfVrKPthwbMzWZDaAFPGYK72F0NJv2v7Vk=
github.com/clipperhouse/uax29/v2 v2.7.0/go.mod h1:EFJ2TJMRUaplDxHKj1qAEhCtQPW2tJSwu5BF98AuoVM=
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk=
@ -59,34 +65,34 @@ github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7
github.com/flosch/pongo2/v6 v6.0.0 h1:lsGru8IAzHgIAw6H2m4PCyleO58I40ow6apih0WprMU=
github.com/flosch/pongo2/v6 v6.0.0/go.mod h1:CuDpFm47R0uGGE7z13/tTlt1Y6zdxvr2RLT5LJhsHEU=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/fxamacker/cbor/v2 v2.8.0 h1:fFtUGXUzXPHTIUdne5+zzMPTfffl3RD5qYnkY40vtxU=
github.com/fxamacker/cbor/v2 v2.8.0/go.mod h1:vM4b+DJCtHn+zz7h3FFp/hDAI9WNWCsZj23V5ytsSxQ=
github.com/gabriel-vasile/mimetype v1.4.9 h1:5k+WDwEsD9eTLL8Tz3L0VnmVh9QxGjRmjBvAG7U/oYY=
github.com/gabriel-vasile/mimetype v1.4.9/go.mod h1:WnSQhFKJuBlRyLiKohA/2DtIlPFAbguNaG7QCHcyGok=
github.com/go-logfmt/logfmt v0.6.0 h1:wGYYu3uicYdqXVgoYbvnkrPVXkuLM1p1ifugDMEdRi4=
github.com/go-logfmt/logfmt v0.6.0/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs=
github.com/fxamacker/cbor/v2 v2.9.1 h1:2rWm8B193Ll4VdjsJY28jxs70IdDsHRWgQYAI80+rMQ=
github.com/fxamacker/cbor/v2 v2.9.1/go.mod h1:vM4b+DJCtHn+zz7h3FFp/hDAI9WNWCsZj23V5ytsSxQ=
github.com/gabriel-vasile/mimetype v1.4.13 h1:46nXokslUBsAJE/wMsp5gtO500a4F3Nkz9Ufpk2AcUM=
github.com/gabriel-vasile/mimetype v1.4.13/go.mod h1:d+9Oxyo1wTzWdyVUPMmXFvp4F9tea18J8ufA774AB3s=
github.com/go-logfmt/logfmt v0.6.1 h1:4hvbpePJKnIzH1B+8OR/JPbTx37NktoI9LE2QZBBkvE=
github.com/go-logfmt/logfmt v0.6.1/go.mod h1:EV2pOAQoZaT1ZXZbqDl5hrymndi4SY9ED9/z6CO0XAk=
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
github.com/go-playground/validator/v10 v10.27.0 h1:w8+XrWVMhGkxOaaowyKH35gFydVHOvC0/uWoy2Fzwn4=
github.com/go-playground/validator/v10 v10.27.0/go.mod h1:I5QpIEbmr8On7W0TktmJAumgzX4CA1XNl4ZmDuVHKKo=
github.com/gofiber/fiber/v2 v2.52.8 h1:xl4jJQ0BV5EJTA2aWiKw/VddRpHrKeZLF0QPUxqn0x4=
github.com/gofiber/fiber/v2 v2.52.8/go.mod h1:YEcBbO/FB+5M1IZNBP9FO3J9281zgPAreiI1oqg8nDw=
github.com/go-playground/validator/v10 v10.30.2 h1:JiFIMtSSHb2/XBUbWM4i/MpeQm9ZK2xqPNk8vgvu5JQ=
github.com/go-playground/validator/v10 v10.30.2/go.mod h1:mAf2pIOVXjTEBrwUMGKkCWKKPs9NheYGabeB04txQSc=
github.com/gofiber/fiber/v2 v2.52.13 h1:TOKP64iqC9b5P49VrBW5tHhUOvDyrtJ0xePEfzJbCbk=
github.com/gofiber/fiber/v2 v2.52.13/go.mod h1:YEcBbO/FB+5M1IZNBP9FO3J9281zgPAreiI1oqg8nDw=
github.com/gofiber/helmet/v2 v2.2.26 h1:KreQVUpCIGppPQ6Yt8qQMaIR4fVXMnvBdsda0dJSsO8=
github.com/gofiber/helmet/v2 v2.2.26/go.mod h1:XE0DF4cgf0M5xIt7qyAK5zOi8jJblhxfSDv9DAmEEQo=
github.com/gofiber/storage/badger/v2 v2.0.1 h1:iIB5Dh2dypJjdEruYgBf7H4l5a98R5pVKVLk5wbY5bo=
github.com/gofiber/storage/badger/v2 v2.0.1/go.mod h1:2LA5uR3q4xFVd0oXIZWK+7yzlO2vzLa/D062R7fowFI=
github.com/gofiber/storage/badger/v2 v2.1.5 h1:29aVC10GRbaFWk6ramu5rY1N3Xq3TDaFR5pk1NutitY=
github.com/gofiber/storage/badger/v2 v2.1.5/go.mod h1:pOu//ssR5WDvBsOeuYF6uXrHs4qiy3BOAX43goUM3so=
github.com/gofiber/template v1.8.3 h1:hzHdvMwMo/T2kouz2pPCA0zGiLCeMnoGsQZBTSYgZxc=
github.com/gofiber/template v1.8.3/go.mod h1:bs/2n0pSNPOkRa5VJ8zTIvedcI/lEYxzV3+YPXdBvq8=
github.com/gofiber/template/django/v3 v3.1.14 h1:SvTvs+u5vTZuu1Y2pMUD2NhaGIjBj9FmDA3XD50QBvw=
github.com/gofiber/template/django/v3 v3.1.14/go.mod h1:gP4vH+T1ajZw7yaejqG1dZVdHQkMC/jPoQbmlG812I0=
github.com/gofiber/utils v1.1.0 h1:vdEBpn7AzIUJRhe+CiTOJdUcTg4Q9RK+pEa0KPbLdrM=
github.com/gofiber/utils v1.1.0/go.mod h1:poZpsnhBykfnY1Mc0KeEa6mSHrS3dV0+oBWyeQmb2e0=
github.com/gofiber/utils/v2 v2.0.0-beta.10 h1:yDQgcBKTnZiZ4S0YY+hpTnf5iJYwVaFA2HsOgOesAyY=
github.com/gofiber/utils/v2 v2.0.0-beta.10/go.mod h1:qEZ175nSOkl5xciHmqxwNDsWzwiB39gB8RgU1d3U4mQ=
github.com/gofiber/utils v1.2.0 h1:NCaqd+Efg3khhN++eeUUTyBz+byIxAsmIjpl8kKOMIc=
github.com/gofiber/utils v1.2.0/go.mod h1:poZpsnhBykfnY1Mc0KeEa6mSHrS3dV0+oBWyeQmb2e0=
github.com/gofiber/utils/v2 v2.0.4 h1:WwAxUA7L4MW2DjdEHF234lfqvBqd2vYYuBtA9TJq2ec=
github.com/gofiber/utils/v2 v2.0.4/go.mod h1:GGERKU3Vhj5z6hS8YKvxL99A54DjOvTFZ0cjZnG4Lj4=
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
@ -115,8 +121,8 @@ github.com/golobby/cast v1.3.3/go.mod h1:0oDO5IT84HTXcbLDf1YXuk0xtg/cRDrxhbpWKxw
github.com/golobby/dotenv v1.3.2 h1:9vA8XqXXIB3cX/5xQ1CTbOCPegioHtHXIxeFng+uOqQ=
github.com/golobby/dotenv v1.3.2/go.mod h1:9MMVXqzLNluhVxCv3X/DLYBNUb289f05tr+df1+7278=
github.com/google/flatbuffers v1.12.1/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8=
github.com/google/flatbuffers v25.2.10+incompatible h1:F3vclr7C3HpB1k9mxCGRMXq6FdUalZ6H/pNX4FP1v0Q=
github.com/google/flatbuffers v25.2.10+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8=
github.com/google/flatbuffers v25.12.19+incompatible h1:haMV2JRRJCe1998HeW/p0X9UaMTK6SDo0ffLn2+DbLs=
github.com/google/flatbuffers v25.12.19+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
@ -124,8 +130,8 @@ github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
@ -135,8 +141,8 @@ github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsI
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 h1:iCEnooe7UlwOQYpKFhBabPMi4aNAfoODPEFNiAnClxo=
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM=
github.com/jackc/pgx/v5 v5.7.5 h1:JHGfMnQY+IEtGM63d+NGMjoRpysB2JBwDr5fsngwmJs=
github.com/jackc/pgx/v5 v5.7.5/go.mod h1:aruU7o91Tc2q2cFp5h4uP3f6ztExVpyVv88Xl/8Vl8M=
github.com/jackc/pgx/v5 v5.9.2 h1:3ZhOzMWnR4yJ+RW1XImIPsD1aNSz4T4fyP7zlQb56hw=
github.com/jackc/pgx/v5 v5.9.2/go.mod h1:mal1tBGAFfLHvZzaYh77YS/eC6IX9OWbRV1QIIM0Jn4=
github.com/jackc/puddle/v2 v2.2.2 h1:PR8nw+E/1w0GLuRFSmiioY6UooMp6KJv0/61nB7icHo=
github.com/jackc/puddle/v2 v2.2.2/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4=
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
@ -146,8 +152,8 @@ github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/klauspost/compress v1.12.3/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg=
github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo=
github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ=
github.com/klauspost/compress v1.18.5 h1:/h1gH5Ce+VWNLSWqPzOVn6XBO+vJbCNGvjoaGBFW2IE=
github.com/klauspost/compress v1.18.5/go.mod h1:cwPg85FWrGar70rWktvGQj8/hthj3wpl0PGDogxkrSQ=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
@ -158,15 +164,15 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY=
github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
github.com/lucasb-eyer/go-colorful v1.4.0 h1:UtrWVfLdarDgc44HcS7pYloGHJUjHV/4FwW4TvVgFr4=
github.com/lucasb-eyer/go-colorful v1.4.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE=
github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc=
github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/mattn/go-isatty v0.0.22 h1:j8l17JJ9i6VGPUFUYoTUKPSgKe/83EYU2zBC7YNKMw4=
github.com/mattn/go-isatty v0.0.22/go.mod h1:ZXfXG4SQHsB/w3ZeOYbR0PrPwLy+n6xiMrJlRFqopa4=
github.com/mattn/go-runewidth v0.0.23 h1:7ykA0T0jkPpzSvMS5i9uoNn2Xy3R383f9HDx3RybWcw=
github.com/mattn/go-runewidth v0.0.23/go.mod h1:XBkDxAl56ILZc9knddidhrOlY5R/pDhgLpndooCuJAs=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/muesli/termenv v0.16.0 h1:S5AlUN9dENB57rsbnkPyfdGuWIlkmzJjbFf0Tf5FWUc=
@ -181,14 +187,15 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH
github.com/pquerna/otp v1.5.0 h1:NMMR+WrmaqXU4EzdGJEE1aUUI0AMRzsp96fFFWNPwxs=
github.com/pquerna/otp v1.5.0/go.mod h1:dkJfzwRKNiegxyNb54X/3fLwhCynbMspSyWKnvi1AEg=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
github.com/shamaton/msgpack/v2 v2.2.3 h1:uDOHmxQySlvlUYfQwdjxyybAOzjlQsD1Vjy+4jmO9NM=
github.com/shamaton/msgpack/v2 v2.2.3/go.mod h1:6khjYnkx73f7VQU7wjcFS9DFjs+59naVWJv1TB7qdOI=
github.com/sethvargo/go-password v0.3.1 h1:WqrLTjo7X6AcVYfC6R7GtSyuUQR9hGyAj/f1PYQZCJU=
github.com/sethvargo/go-password v0.3.1/go.mod h1:rXofC1zT54N7R8K/h1WDUdkf9BOx5OptoxrMBcrXzvs=
github.com/shamaton/msgpack/v3 v3.1.0 h1:jsk0vEAqVvvS9+fTZ5/EcQ9tz860c9pWxJ4Iwecz8gU=
github.com/shamaton/msgpack/v3 v3.1.0/go.mod h1:DcQG8jrdrQCIxr3HlMYkiXdMhK+KfN2CitkyzsQV4uc=
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI=
github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
@ -208,13 +215,15 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
github.com/valyala/fasthttp v1.63.0 h1:DisIL8OjB7ul2d7cBaMRcKTQDYnrGy56R4FCiuDP0Ns=
github.com/valyala/fasthttp v1.63.0/go.mod h1:REc4IeW+cAEyLrRPa5A81MIjvz0QE1laoTX2EaPHKJM=
github.com/valyala/fasthttp v1.70.0 h1:LAhMGcWk13QZWm85+eg8ZBNbrq5mnkWFGbHMUJHIdXA=
github.com/valyala/fasthttp v1.70.0/go.mod h1:oDZEHHkJ/Buyklg6uURmYs19442zFSnCIfX3j1FY3pE=
github.com/wneessen/go-mail v0.7.2 h1:xxPnhZ6IZLSgxShebmZ6DPKh1b6OJcoHfzy7UjOkzS8=
github.com/wneessen/go-mail v0.7.2/go.mod h1:+TkW6QP3EVkgTEqHtVmnAE/1MRhmzb8Y9/W3pweuS+k=
github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no=
@ -224,25 +233,32 @@ github.com/xyproto/randomstring v1.0.5 h1:YtlWPoRdgMu3NZtP45drfy1GKoojuR7hmRcnhZ
github.com/xyproto/randomstring v1.0.5/go.mod h1:rgmS5DeNXLivK7YprL0pY+lTuhNQW3iGxZ18UQApw/E=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.7.12 h1:YwGP/rrea2/CnCtUHgjuolG/PnMxdQtPMO5PvaE2/nY=
github.com/yuin/goldmark v1.7.12/go.mod h1:ip/1k0VRfGynBgxOz0yCqHrbZXhcjxyuS66Brc7iBKg=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
github.com/yuin/goldmark v1.8.2 h1:kEGpgqJXdgbkhcOgBxkC0X0PmoPG1ZyoZ117rDVp4zE=
github.com/yuin/goldmark v1.8.2/go.mod h1:ip/1k0VRfGynBgxOz0yCqHrbZXhcjxyuS66Brc7iBKg=
go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk=
go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0=
go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo=
go.yaml.in/yaml/v4 v4.0.0-rc.4 h1:UP4+v6fFrBIb1l934bDl//mmnoIZEDK0idg1+AIvX5U=
go.yaml.in/yaml/v4 v4.0.0-rc.4/go.mod h1:aZqd9kCMsGL7AuUv/m/PvWLdg5sjJsZ4oHDEnfPPfY0=
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.40.0 h1:r4x+VvoG5Fm+eJcxMaY8CQM7Lb0l1lsmjGBQ6s8BfKM=
golang.org/x/crypto v0.40.0/go.mod h1:Qr1vMER5WyS2dfPHAlsOj01wgLbsyWtFn/aY+5+ZdxY=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
golang.org/x/crypto v0.50.0 h1:zO47/JPrL6vsNkINmLoo/PH1gcxpls50DNogFvB5ZGI=
golang.org/x/crypto v0.50.0/go.mod h1:3muZ7vA7PBCE6xgPX7nkzzjiUq87kRItoJQM1Yo8S+Q=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b h1:M2rDM6z3Fhozi9O7NWsxAkg/yqS/lQJ6PmkyIV3YP+o=
golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b/go.mod h1:3//PLf8L/X+8b4vuAfHzxeRUl04Adcb341+IGKfnqS8=
golang.org/x/exp v0.0.0-20260410095643-746e56fc9e2f h1:W3F4c+6OLc6H2lb//N1q4WpJkhzJCK5J6kUi1NTVXfM=
golang.org/x/exp v0.0.0-20260410095643-746e56fc9e2f/go.mod h1:J1xhfL/vlindoeF/aINzNzt2Bket5bjo9sdOYzOsU80=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@ -252,8 +268,12 @@ golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLL
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.42.0 h1:jzkYrhi3YQWD6MLBJcsklgQsoAcw89EcZbJw8Z614hs=
golang.org/x/net v0.42.0/go.mod h1:FF1RA5d3u7nAYA4z2TkclSCKh68eSXtiFwcWQpPXdt8=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
golang.org/x/net v0.53.0 h1:d+qAbo5L0orcWAr0a9JweQpjXF19LMXJE8Ey7hwOdUA=
golang.org/x/net v0.53.0/go.mod h1:JvMuJH7rrdiCfbeHoo3fCQU24Lf5JJwT9W3sJFulfgs=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@ -261,22 +281,39 @@ golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw=
golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4=
golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20221010170243-090e33056c14/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.34.0 h1:H5Y5sJ2L2JRdyv7ROF1he/lPdvFsd0mJHFw2ThKHxLA=
golang.org/x/sys v0.34.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.43.0 h1:Rlag2XtaFTxp19wS8MXlJwTvoh8ArU6ezoyFsMyCTNI=
golang.org/x/sys v0.43.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.27.0 h1:4fGWRpyh641NLlecmyl4LOe6yDdfaYNrGb2zdfo4JV4=
golang.org/x/text v0.27.0/go.mod h1:1D28KMCvyooCX9hBiosv5Tz/+YLxj0j7XhWjpSUF7CU=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/text v0.36.0 h1:JfKh3XmcRPqZPKevfXVpI1wXPTqbkE5f7JA92a55Yxg=
golang.org/x/text v0.36.0/go.mod h1:NIdBknypM8iqVmPiuco0Dh6P5Jcdk8lJL0CUebqK164=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
@ -285,6 +322,8 @@ golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBn
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
@ -310,8 +349,8 @@ google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY=
google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY=
google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=
google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
@ -322,7 +361,7 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gorm.io/driver/postgres v1.6.0 h1:2dxzU8xJ+ivvqTRph34QX+WrRaJlmfyPqXmoGVjMBa4=
gorm.io/driver/postgres v1.6.0/go.mod h1:vUw0mrGgrTK+uPHEhAdV4sfFELrByKVGnaVRkXDhtWo=
gorm.io/gorm v1.30.0 h1:qbT5aPv1UH8gI99OsRlvDToLxW5zR7FzS9acZDOZcgs=
gorm.io/gorm v1.30.0/go.mod h1:8Z33v652h4//uMA76KjeDH8mJXPm1QNCYrMeatR0DOE=
gorm.io/gorm v1.31.1 h1:7CA8FTFz/gRfgqgpeKIBcervUn3xSyPUmr6B2WXJ7kg=
gorm.io/gorm v1.31.1/go.mod h1:XyQVbO2k6YkOis7C2437jSit3SsDK72s7n7rsSHd+Gs=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=

View file

@ -0,0 +1,74 @@
package authelia
import (
"os"
"git.readonly.ch/bouzoure/pop-camarades/helpers"
"go.yaml.in/yaml/v4"
)
type AutheliaUser struct {
Password string `yaml:"password"`
DisplayName string `yaml:"displayname"`
Email string `yaml:"email"`
Groups []string `yaml:"groups"`
GivenName string `yaml:"given_name"`
MiddleName string `yaml:"middle_name"`
FamilyName string `yaml:"family_name"`
Nickname string `yaml:"nickname"`
Gender string `yaml:"gender"`
Birthdate string `yaml:"birthdate"`
Website string `yaml:"website"`
Profile string `yaml:"profile"`
Picture string `yaml:"picture"`
ZoneInfo string `yaml:"zoneinfo"`
Locale string `yaml:"locale"`
PhoneNumber string `yaml:"phone_number"`
PhoneExtension string `yaml:"phone_extension"`
Disabled bool `yaml:"disabled"`
Address any `yaml:"address"`
Extra map[string]any `yaml:"extra"`
}
type AutheliaUsers struct {
Users map[string]AutheliaUser `yaml:"users"`
}
func ReadDatabase() (AutheliaUsers, error) {
var users AutheliaUsers
// Get config
config, err := helpers.GetConfig()
if err != nil {
return users, err
}
// Read YAML file
filePath := config.Authelia.UsersLocation
fileContent, err := os.ReadFile(filePath)
if err != nil {
return users, err
}
// Unmarshal YAML
err = yaml.Unmarshal(fileContent, &users)
return users, err
}
func WriteDatabase(users AutheliaUsers) error {
// Get config
config, err := helpers.GetConfig()
if err != nil {
return err
}
// Marshal YAML
yamlData, err := yaml.Marshal(users)
if err != nil {
return err
}
filePath := config.Authelia.UsersLocation
return os.WriteFile(filePath, yamlData, 0644)
}

View file

@ -0,0 +1,57 @@
package authelia
import (
"fmt"
"strings"
"git.readonly.ch/bouzoure/pop-camarades/helpers"
"git.readonly.ch/bouzoure/pop-camarades/models"
)
func GetPersonGroups(userid uint) []string {
var groups []string
db, err := helpers.GetDatabase()
if err != nil {
return groups
}
var person models.Person
db.Preload("Section").Find(&person, "id = ?", userid)
if person.SectionID <= 0 {
return groups
}
groups = append(groups, fmt.Sprintf(
"section_%s",
strings.ReplaceAll(person.Section.ShortName, " ", "_"),
))
if person.Section.ParentSectionID == nil {
return groups
}
parentID := person.Section.ParentSectionID
for {
var section models.Section
db.Preload("parent_section").Find(&section, "id = ?", parentID)
if section.ID <= 0 {
return groups
}
groups = append(groups, fmt.Sprintf(
"section_%s",
strings.ReplaceAll(section.ShortName, " ", "_"),
))
if section.ParentSectionID != nil {
parentID = person.Section.ParentSectionID
} else {
break
}
}
return groups
}

66
helpers/authelia/mail.go Normal file
View file

@ -0,0 +1,66 @@
package authelia
import (
ht "html/template"
tt "text/template"
"git.readonly.ch/bouzoure/pop-camarades/helpers"
"git.readonly.ch/bouzoure/pop-camarades/models"
)
type InputWelcomeMail struct {
Person models.Person
ResetURL string
}
func SendWelcomeMail(person models.Person) error {
config, err := helpers.GetConfig()
if err != nil {
return err
}
mailer, err := helpers.GetMailer()
if err != nil {
return err
}
msg, err := helpers.NewMessage()
if err != nil {
return err
}
mailsFS, err := helpers.GetEmbeddedFS("mails")
if err != nil {
return err
}
inputValues := InputWelcomeMail{
Person: person,
ResetURL: config.Authelia.ResetURL,
}
tplHTML, err := ht.ParseFS(mailsFS, "mails/welcome.html")
if err != nil {
return err
}
tplTXT, err := tt.ParseFS(mailsFS, "mails/welcome.txt")
if err != nil {
return err
}
msg.Subject("Ton compte POP Vaud a été créé")
msg.AddTo(person.Email)
err = msg.SetBodyHTMLTemplate(tplHTML, inputValues)
if err != nil {
return err
}
err = msg.AddAlternativeTextTemplate(tplTXT, inputValues)
if err != nil {
return err
}
return mailer.DialAndSend(msg)
}

115
helpers/authelia/users.go Normal file
View file

@ -0,0 +1,115 @@
package authelia
import (
"fmt"
"strings"
"time"
"git.readonly.ch/bouzoure/pop-camarades/helpers"
"git.readonly.ch/bouzoure/pop-camarades/models"
"github.com/alexedwards/argon2id"
"github.com/charmbracelet/log"
"github.com/sethvargo/go-password/password"
)
func SyncUsers() error {
db, err := helpers.GetDatabase()
if err != nil {
return err
}
var accounts []models.PersonAccount
result := db.Joins("Person").Find(
&accounts, "account_created IS NULL OR update_needed = ?", true,
)
if result.Error != nil {
return result.Error
}
// If no accounts to create or update -> skip sync
if result.RowsAffected <= 0 {
return nil
}
users, err := ReadDatabase()
if err != nil {
return err
}
for _, account := range accounts {
accountExists := false
for uuid, user := range users.Users {
if uuid == account.UUID.String() {
accountExists = true
// Update account
user.Disabled = !account.Enabled
user.Groups = strings.Split(account.Groups, "|||")
user.GivenName = account.Person.FirstName
user.FamilyName = account.Person.LastName
user.DisplayName = fmt.Sprintf("%s %s",
account.Person.FirstName, account.Person.LastName,
)
user.Email = account.Person.Email
// Overwrite old user struct
users.Users[uuid] = user
// Exit loop early
break
}
}
if !accountExists {
// Generate random password
randomPassword, err := password.Generate(64, 10, 10, false, false)
if err != nil {
log.Error(err)
continue
}
argonParams := argon2id.Params{
Iterations: 3,
Memory: 65536,
Parallelism: 4,
KeyLength: 32,
SaltLength: 16,
}
hashedPassword, err := argon2id.CreateHash(randomPassword, &argonParams)
if err != nil {
log.Error(err)
continue
}
// Create account
user := AutheliaUser{
Disabled: !account.Enabled,
Groups: strings.Split(account.Groups, "|||"),
GivenName: account.Person.FirstName,
FamilyName: account.Person.LastName,
DisplayName: fmt.Sprintf("%s %s",
account.Person.FirstName, account.Person.LastName,
),
Email: account.Person.Email,
Password: hashedPassword,
}
// Insert new user
users.Users[account.UUID.String()] = user
}
account.UpdateNeeded = false
if !account.AccountCreated.Valid {
err := SendWelcomeMail(account.Person)
if err != nil {
log.Error(err)
}
account.AccountCreated.Scan(time.Now())
}
db.Save(&account)
}
return WriteDatabase(users)
}

View file

@ -20,6 +20,18 @@ type Config struct {
Sessions struct {
Location string `env:"SESSIONS_LOCATION"`
}
Authelia struct {
UsersLocation string `env:"AUTHELIA_USERS_LOCATION"`
ResetURL string `env:"AUTHELIA_RESET_URL"`
}
Mail struct {
Host string `env:"MAIL_HOST"`
Port int `env:"MAIL_PORT"`
Username string `env:"MAIL_USERNAME"`
Password string `env:"MAIL_PASSWORD"`
FromName string `env:"MAIL_FROM_NAME"`
FromAddress string `env:"MAIL_FROM_ADDRESS"`
}
}
var configParsed bool

View file

@ -52,6 +52,7 @@ func GetDatabase() (*gorm.DB, error) {
&models.Role{},
&models.UserRole{},
&models.Person{},
&models.PersonAccount{},
&models.List{},
&models.ListItem{},
&models.Field{},

49
helpers/mailer.go Normal file
View file

@ -0,0 +1,49 @@
package helpers
import (
"github.com/wneessen/go-mail"
)
var mailer *mail.Client
var mailerSet bool
func GetMailer() (*mail.Client, error) {
if mailerSet {
return mailer, nil
}
config, err := GetConfig()
if err != nil {
return mailer, err
}
mailer, err = mail.NewClient(
config.Mail.Host,
mail.WithPort(config.Mail.Port),
mail.WithSMTPAuth(mail.SMTPAuthAutoDiscover),
mail.WithUsername(config.Mail.Username),
mail.WithPassword(config.Mail.Password),
)
if err != nil {
return mailer, err
}
mailerSet = true
return mailer, nil
}
func NewMessage() (*mail.Msg, error) {
msg := mail.NewMsg()
config, err := GetConfig()
if err != nil {
return msg, err
}
msg.FromFormat(
config.Mail.FromName,
config.Mail.FromAddress,
)
return msg, nil
}

69
mails/welcome.html Normal file
View file

@ -0,0 +1,69 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Ton compte POP Vaud a été créé</title>
</head>
<body style="margin:0; padding:0; font-family: Arial, sans-serif; line-height: 1.5; color: #333;">
<table width="100%" cellpadding="0" cellspacing="0" border="0" style="background-color: #f5f5f5; padding: 20px;">
<tr>
<td align="center">
<table width="600" cellpadding="0" cellspacing="0" border="0" style="background-color: #ffffff; border-radius: 5px; overflow: hidden; box-shadow: 0 0 10px rgba(0,0,0,0.1);">
<!-- En-tête -->
<tr>
<td style="padding: 20px 20px 0; text-align: center; background-color: #d32f2f; color: #ffffff;">
<h1 style="margin: 0; font-size: 24px;">POP Vaud</h1>
</td>
</tr>
<!-- Contenu -->
<tr>
<td style="padding: 20px;">
<p style="margin: 0 0 20px 0; font-size: 16px;">Cher·e camarade,</p>
<p style="margin: 0 0 20px 0;">
Ton compte POP Vaud a été créé avec succès. Tu peux désormais accéder aux applications du parti.
</p>
<h2 style="margin: 0 0 10px 0; font-size: 18px; color: #d32f2f;">Informations de connexion :</h2>
<p style="margin: 0 0 20px 0;">
<strong>Nom d'utilisateur :</strong> {{.Person.Email}}
</p>
<p style="margin: 0 0 20px 0;">
Pour commencer, réinitialise ton mot de passe en utilisant le lien suivant :
</p>
<p style="margin: 0 0 20px 0; text-align: center;">
<a href="{{.ResetURL}}" style="display: inline-block; padding: 10px 20px; background-color: #d32f2f; color: #ffffff; text-decoration: none; border-radius: 4px; font-weight: bold;">Réinitialiser mon mot de passe</a>
</p>
<h2 style="margin: 0 0 10px 0; font-size: 18px; color: #d32f2f;">Applications disponibles :</h2>
<ul style="margin: 0 0 20px 0; padding-left: 20px;">
<li style="margin: 0 0 10px 0;"><a href="https://wiki.popvaud.ch" style="color: #d32f2f; text-decoration: none;">Wiki POP Vaud</a></li>
<li style="margin: 0 0 10px 0;"><a href="https://nuage.popvaud.ch" style="color: #d32f2f; text-decoration: none;">Nuage POP Vaud</a></li>
</ul>
<p style="margin: 0 0 20px 0;">
En cas de problème, contacte <a href="mailto:informatique@popvaud.ch" style="color: #d32f2f; text-decoration: none;">informatique@popvaud.ch</a>.
</p>
<p style="margin: 0; text-align: center; font-style: italic; color: #d32f2f;">
Vive la révolution !
</p>
</td>
</tr>
<!-- Pied de page -->
<tr>
<td style="padding: 20px; text-align: center; background-color: #f5f5f5; color: #666; font-size: 14px;">
Les Camarades du POP Vaud
</td>
</tr>
</table>
</td>
</tr>
</table>
</body>
</html>

19
mails/welcome.txt Normal file
View file

@ -0,0 +1,19 @@
Cher·e camarade,
Ton compte POP Vaud a été créé avec succès. Tu peux désormais accéder aux applications du parti.
Informations de connexion :
- Nom d'utilisateur : {{.Person.Email}}
Pour commencer, réinitialise ton mot de passe en utilisant le lien suivant :
{{.ResetURL}}
Applications disponibles :
- Wiki POP Vaud : https://wiki.popvaud.ch
- Nuage POP Vaud : https://nuage.popvaud.ch
En cas de problème, contacte informatique@popvaud.ch.
Vive la révolution !
Les camarades du POP Vaud

17
main.go
View file

@ -9,6 +9,7 @@ import (
"git.readonly.ch/bouzoure/pop-camarades/controllers"
"git.readonly.ch/bouzoure/pop-camarades/helpers"
"git.readonly.ch/bouzoure/pop-camarades/helpers/authelia"
"git.readonly.ch/bouzoure/pop-camarades/jobs"
"git.readonly.ch/bouzoure/pop-camarades/middlewares"
"github.com/flosch/pongo2/v6"
@ -25,12 +26,16 @@ var embedStatic embed.FS
//go:embed views
var embedViews embed.FS
//go:embed mails
var embedMails embed.FS
func main() {
log := helpers.GetLogger()
// Add embedded filesystems to shared state
helpers.AddEmbeddedFS("static", &embedStatic)
helpers.AddEmbeddedFS("views", &embedViews)
helpers.AddEmbeddedFS("mails", &embedMails)
// Fetch app config
config, err := helpers.GetConfig()
@ -57,6 +62,18 @@ func main() {
// Note: jobs will be executed at launch and after every interval
go helpers.RegisterJob(60*time.Minute, "clean saved sessions", jobs.CleanSavedSessions)
// Goroutine to update Authelia accounts in the background
go func() {
for {
err = authelia.SyncUsers()
if err != nil {
log.Error(err)
}
time.Sleep(time.Minute)
}
}()
// Initialize the Pongo2 templating engine
// If we are in dev mode, load templates from directory
// Otherwise, use the templates embedded in the binary

View file

@ -1,6 +1,11 @@
package models
import "gorm.io/gorm"
import (
"database/sql"
"github.com/google/uuid"
"gorm.io/gorm"
)
type Person struct {
gorm.Model
@ -18,3 +23,15 @@ type Person struct {
SectionID uint
Section Section
}
type PersonAccount struct {
gorm.Model
PersonID uint
Person Person
UUID uuid.UUID `gorm:"unique"`
Enabled bool
Groups string
AccountCreated sql.NullTime
InvitationSent sql.NullTime
UpdateNeeded bool
}

View file

@ -10,7 +10,7 @@ import (
type User struct {
gorm.Model
Name string
Email string
Email string `gorm:"unique"`
Password string
TotpSecret sql.NullString
IsAdmin bool

View file

@ -8,9 +8,9 @@
"url": "https://git.readonly.ch/bouzoure/pop-camarades"
},
"devDependencies": {
"@parcel/transformer-sass": "2.15.4",
"parcel": "^2.15.4",
"prettier": "^3.6.2",
"@parcel/transformer-sass": "^2.16.4",
"parcel": "^2.16.4",
"prettier": "^3.8.1",
"prettier-plugin-jinja-template": "^2.1.0"
},
"source": "frontend/index.js",
@ -32,7 +32,7 @@
"build": "go build"
},
"dependencies": {
"bootstrap": "^5.3.7",
"bootstrap": "^5.3.8",
"bootstrap-icons": "^1.13.1",
"jquery": "^3.7.1"
}

1463
pnpm-lock.yaml generated

File diff suppressed because it is too large Load diff

View file

@ -685,12 +685,45 @@ Public License instead of this License. But first, please read
```
## github.com/alexedwards/argon2id
* Name: github.com/alexedwards/argon2id
* Version: v1.0.0
* License: [MIT](https://github.com/alexedwards/argon2id/blob/v1.0.0/LICENSE)
```
MIT License
Copyright (c) 2018 Alex Edwards
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
```
## github.com/andybalholm/brotli
* Name: github.com/andybalholm/brotli
* Version: v1.2.0
* Version: v1.2.1
* License: [MIT](https://github.com/andybalholm/brotli/blob/v1.2.0/LICENSE)
* License: [MIT](https://github.com/andybalholm/brotli/blob/v1.2.1/LICENSE)
```
@ -716,6 +749,45 @@ THE SOFTWARE.
```
## github.com/andybalholm/brotli/flate
* Name: github.com/andybalholm/brotli/flate
* Version: v1.2.1
* License: [BSD-3-Clause](https://github.com/andybalholm/brotli/blob/v1.2.1/flate/LICENSE)
```
Copyright (c) 2009 The Go Authors. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
* Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
```
## github.com/aymanbagabas/go-osc52/v2
* Name: github.com/aymanbagabas/go-osc52/v2
@ -752,9 +824,9 @@ SOFTWARE.
## github.com/boombuler/barcode
* Name: github.com/boombuler/barcode
* Version: v1.0.2
* Version: v1.1.0
* License: [MIT](https://github.com/boombuler/barcode/blob/v1.0.2/LICENSE)
* License: [MIT](https://github.com/boombuler/barcode/blob/v1.1.0/LICENSE)
```
@ -785,9 +857,9 @@ SOFTWARE.
## github.com/brianvoe/gofakeit/v7
* Name: github.com/brianvoe/gofakeit/v7
* Version: v7.3.0
* Version: v7.14.1
* License: [MIT](https://github.com/brianvoe/gofakeit/blob/v7.3.0/LICENSE.txt)
* License: [MIT](https://github.com/brianvoe/gofakeit/blob/v7.14.1/LICENSE.txt)
```
@ -884,9 +956,9 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
## github.com/charmbracelet/colorprofile
* Name: github.com/charmbracelet/colorprofile
* Version: v0.3.1
* Version: v0.4.3
* License: [MIT](https://github.com/charmbracelet/colorprofile/blob/v0.3.1/LICENSE)
* License: [MIT](https://github.com/charmbracelet/colorprofile/blob/v0.4.3/LICENSE)
```
@ -950,9 +1022,9 @@ SOFTWARE.
## github.com/charmbracelet/log
* Name: github.com/charmbracelet/log
* Version: v0.4.2
* Version: v1.0.0
* License: [MIT](https://github.com/charmbracelet/log/blob/v0.4.2/LICENSE)
* License: [MIT](https://github.com/charmbracelet/log/blob/v1.0.0/LICENSE)
```
@ -983,9 +1055,9 @@ SOFTWARE.
## github.com/charmbracelet/x/ansi
* Name: github.com/charmbracelet/x/ansi
* Version: v0.9.3
* Version: v0.11.7
* License: [MIT](https://github.com/charmbracelet/x/blob/ansi/v0.9.3/ansi/LICENSE)
* License: [MIT](https://github.com/charmbracelet/x/blob/ansi/v0.11.7/ansi/LICENSE)
```
@ -1016,9 +1088,9 @@ SOFTWARE.
## github.com/charmbracelet/x/cellbuf
* Name: github.com/charmbracelet/x/cellbuf
* Version: v0.0.13
* Version: v0.0.15
* License: [MIT](https://github.com/charmbracelet/x/blob/cellbuf/v0.0.13/cellbuf/LICENSE)
* License: [MIT](https://github.com/charmbracelet/x/blob/cellbuf/v0.0.15/cellbuf/LICENSE)
```
@ -1049,9 +1121,9 @@ SOFTWARE.
## github.com/charmbracelet/x/term
* Name: github.com/charmbracelet/x/term
* Version: v0.2.1
* Version: v0.2.2
* License: [MIT](https://github.com/charmbracelet/x/blob/term/v0.2.1/term/LICENSE)
* License: [MIT](https://github.com/charmbracelet/x/blob/term/v0.2.2/term/LICENSE)
```
@ -1079,6 +1151,72 @@ SOFTWARE.
```
## github.com/clipperhouse/displaywidth
* Name: github.com/clipperhouse/displaywidth
* Version: v0.11.0
* License: [MIT](https://github.com/clipperhouse/displaywidth/blob/v0.11.0/LICENSE)
```
MIT License
Copyright (c) 2025 Matt Sherman
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
```
## github.com/clipperhouse/uax29/v2/graphemes
* Name: github.com/clipperhouse/uax29/v2/graphemes
* Version: v2.7.0
* License: [MIT](https://github.com/clipperhouse/uax29/blob/v2.7.0/LICENSE)
```
MIT License
Copyright (c) 2020 Matt Sherman
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
```
## github.com/dgraph-io/badger/v3
* Name: github.com/dgraph-io/badger/v3
@ -1599,9 +1737,9 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
## github.com/gabriel-vasile/mimetype
* Name: github.com/gabriel-vasile/mimetype
* Version: v1.4.9
* Version: v1.4.13
* License: [MIT](https://github.com/gabriel-vasile/mimetype/blob/v1.4.9/LICENSE)
* License: [MIT](https://github.com/gabriel-vasile/mimetype/blob/v1.4.13/LICENSE)
```
@ -1632,9 +1770,9 @@ SOFTWARE.
## github.com/go-logfmt/logfmt
* Name: github.com/go-logfmt/logfmt
* Version: v0.6.0
* Version: v0.6.1
* License: [MIT](https://github.com/go-logfmt/logfmt/blob/v0.6.0/LICENSE)
* License: [MIT](https://github.com/go-logfmt/logfmt/blob/v0.6.1/LICENSE)
```
@ -1731,9 +1869,9 @@ SOFTWARE.
## github.com/go-playground/validator/v10
* Name: github.com/go-playground/validator/v10
* Version: v10.27.0
* Version: v10.30.2
* License: [MIT](https://github.com/go-playground/validator/blob/v10.27.0/LICENSE)
* License: [MIT](https://github.com/go-playground/validator/blob/v10.30.2/LICENSE)
```
@ -1765,9 +1903,9 @@ SOFTWARE.
## github.com/gofiber/fiber/v2
* Name: github.com/gofiber/fiber/v2
* Version: v2.52.8
* Version: v2.52.13
* License: [MIT](https://github.com/gofiber/fiber/blob/v2.52.8/LICENSE)
* License: [MIT](https://github.com/gofiber/fiber/blob/v2.52.13/LICENSE)
```
@ -1798,9 +1936,9 @@ SOFTWARE.
## github.com/gofiber/fiber/v2/internal/schema
* Name: github.com/gofiber/fiber/v2/internal/schema
* Version: v2.52.8
* Version: v2.52.13
* License: [BSD-3-Clause](https://github.com/gofiber/fiber/blob/v2.52.8/internal/schema/LICENSE)
* License: [BSD-3-Clause](https://github.com/gofiber/fiber/blob/v2.52.13/internal/schema/LICENSE)
```
@ -1870,9 +2008,9 @@ SOFTWARE.
## github.com/gofiber/storage/badger/v2
* Name: github.com/gofiber/storage/badger/v2
* Version: v2.0.1
* Version: v2.1.5
* License: [MIT](https://github.com/gofiber/storage/blob/badger/v2.0.1/badger/LICENSE)
* License: [MIT](https://github.com/gofiber/storage/blob/badger/v2.1.5/badger/LICENSE)
```
@ -1969,9 +2107,9 @@ SOFTWARE.
## github.com/gofiber/utils
* Name: github.com/gofiber/utils
* Version: v1.1.0
* Version: v1.2.0
* License: [MIT](https://github.com/gofiber/utils/blob/v1.1.0/LICENSE)
* License: [MIT](https://github.com/gofiber/utils/blob/v1.2.0/LICENSE)
```
@ -2002,9 +2140,9 @@ SOFTWARE.
## github.com/gofiber/utils/v2
* Name: github.com/gofiber/utils/v2
* Version: v2.0.0-beta.10
* Version: v2.0.4
* License: [MIT](https://github.com/gofiber/utils/blob/v2.0.0-beta.10/LICENSE)
* License: [MIT](https://github.com/gofiber/utils/blob/v2.0.4/LICENSE)
```
@ -2430,9 +2568,9 @@ SOFTWARE.
## github.com/google/flatbuffers/go
* Name: github.com/google/flatbuffers/go
* Version: v25.2.10
* Version: v25.12.19
* License: [Apache-2.0](https://github.com/google/flatbuffers/blob/v25.2.10/LICENSE)
* License: [Apache-2.0](https://github.com/google/flatbuffers/blob/v25.12.19/LICENSE)
```
@ -2751,9 +2889,9 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
## github.com/jackc/pgx/v5
* Name: github.com/jackc/pgx/v5
* Version: v5.7.5
* Version: v5.9.2
* License: [MIT](https://github.com/jackc/pgx/blob/v5.7.5/LICENSE)
* License: [MIT](https://github.com/jackc/pgx/blob/v5.9.2/LICENSE)
```
@ -2885,9 +3023,9 @@ THE SOFTWARE.
## github.com/klauspost/compress
* Name: github.com/klauspost/compress
* Version: v1.18.0
* Version: v1.18.5
* License: [Apache-2.0](https://github.com/klauspost/compress/blob/v1.18.0/LICENSE)
* License: [Apache-2.0](https://github.com/klauspost/compress/blob/v1.18.5/LICENSE)
```
@ -3201,9 +3339,9 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
## github.com/klauspost/compress/internal/snapref
* Name: github.com/klauspost/compress/internal/snapref
* Version: v1.18.0
* Version: v1.18.5
* License: [BSD-3-Clause](https://github.com/klauspost/compress/blob/v1.18.0/internal/snapref/LICENSE)
* License: [BSD-3-Clause](https://github.com/klauspost/compress/blob/v1.18.5/internal/snapref/LICENSE)
```
@ -3240,9 +3378,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
## github.com/klauspost/compress/zstd/internal/xxhash
* Name: github.com/klauspost/compress/zstd/internal/xxhash
* Version: v1.18.0
* Version: v1.18.5
* License: [MIT](https://github.com/klauspost/compress/blob/v1.18.0/zstd/internal/xxhash/LICENSE.txt)
* License: [MIT](https://github.com/klauspost/compress/blob/v1.18.5/zstd/internal/xxhash/LICENSE.txt)
```
@ -3307,9 +3445,9 @@ SOFTWARE.
## github.com/lucasb-eyer/go-colorful
* Name: github.com/lucasb-eyer/go-colorful
* Version: v1.2.0
* Version: v1.4.0
* License: [MIT](https://github.com/lucasb-eyer/go-colorful/blob/v1.2.0/LICENSE)
* License: [MIT](https://github.com/lucasb-eyer/go-colorful/blob/v1.4.0/LICENSE)
```
@ -3359,9 +3497,9 @@ SOFTWARE.
## github.com/mattn/go-isatty
* Name: github.com/mattn/go-isatty
* Version: v0.0.20
* Version: v0.0.22
* License: [MIT](https://github.com/mattn/go-isatty/blob/v0.0.20/LICENSE)
* License: [MIT](https://github.com/mattn/go-isatty/blob/v0.0.22/LICENSE)
```
@ -3380,9 +3518,9 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
## github.com/mattn/go-runewidth
* Name: github.com/mattn/go-runewidth
* Version: v0.0.16
* Version: v0.0.23
* License: [MIT](https://github.com/mattn/go-runewidth/blob/v0.0.16/LICENSE)
* License: [MIT](https://github.com/mattn/go-runewidth/blob/v0.0.23/LICENSE)
```
@ -3725,6 +3863,38 @@ SOFTWARE.
```
## github.com/sethvargo/go-password/password
* Name: github.com/sethvargo/go-password/password
* Version: v0.3.1
* License: [MIT](https://github.com/sethvargo/go-password/blob/v0.3.1/LICENSE)
```
Copyright 2017 Seth Vargo <seth@sethvargo.com>
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
```
## github.com/valyala/bytebufferpool
* Name: github.com/valyala/bytebufferpool
@ -3762,9 +3932,9 @@ SOFTWARE.
## github.com/valyala/fasthttp
* Name: github.com/valyala/fasthttp
* Version: v1.63.0
* Version: v1.70.0
* License: [MIT](https://github.com/valyala/fasthttp/blob/v1.63.0/LICENSE)
* License: [MIT](https://github.com/valyala/fasthttp/blob/v1.70.0/LICENSE)
```
@ -3783,9 +3953,9 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
## github.com/valyala/fasthttp/reuseport
* Name: github.com/valyala/fasthttp/reuseport
* Version: v1.63.0
* Version: v1.70.0
* License: [MIT](https://github.com/valyala/fasthttp/blob/v1.63.0/reuseport/LICENSE)
* License: [MIT](https://github.com/valyala/fasthttp/blob/v1.70.0/reuseport/LICENSE)
```
@ -3812,6 +3982,77 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
```
## github.com/wneessen/go-mail
* Name: github.com/wneessen/go-mail
* Version: v0.7.2
* License: [MIT](https://github.com/wneessen/go-mail/blob/v0.7.2/LICENSE)
```
MIT License
Copyright (c) 2022-2025 The go-mail Authors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
```
## github.com/wneessen/go-mail/smtp
* Name: github.com/wneessen/go-mail/smtp
* Version: v0.7.2
* License: [BSD-3-Clause](https://github.com/wneessen/go-mail/blob/v0.7.2/smtp/LICENSE)
```
Copyright (c) 2009 The Go Authors. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
* Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
```
## github.com/xo/terminfo
* Name: github.com/xo/terminfo
@ -3848,9 +4089,9 @@ SOFTWARE.
## github.com/yuin/goldmark
* Name: github.com/yuin/goldmark
* Version: v1.7.12
* Version: v1.8.2
* License: [MIT](https://github.com/yuin/goldmark/blob/v1.7.12/LICENSE)
* License: [MIT](https://github.com/yuin/goldmark/blob/v1.8.2/LICENSE)
```
@ -4091,12 +4332,226 @@ SOFTWARE.
limitations under the License.
```
## go.yaml.in/yaml/v4
* Name: go.yaml.in/yaml/v4
* Version: v4.0.0-rc.4
* License: [Apache-2.0](https://github.com/yaml/go-yaml/blob/v4.0.0-rc.4/LICENSE)
```
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright 2025 - The go-yaml Project Contributors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
```
## golang.org/x/crypto
* Name: golang.org/x/crypto
* Version: v0.40.0
* Version: v0.50.0
* License: [BSD-3-Clause](https://cs.opensource.google/go/x/crypto/+/v0.40.0:LICENSE)
* License: [BSD-3-Clause](https://cs.opensource.google/go/x/crypto/+/v0.50.0:LICENSE)
```
@ -4133,9 +4588,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
## golang.org/x/net
* Name: golang.org/x/net
* Version: v0.42.0
* Version: v0.53.0
* License: [BSD-3-Clause](https://cs.opensource.google/go/x/net/+/v0.42.0:LICENSE)
* License: [BSD-3-Clause](https://cs.opensource.google/go/x/net/+/v0.53.0:LICENSE)
```
@ -4172,9 +4627,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
## golang.org/x/sync/semaphore
* Name: golang.org/x/sync/semaphore
* Version: v0.16.0
* Version: v0.20.0
* License: [BSD-3-Clause](https://cs.opensource.google/go/x/sync/+/v0.16.0:LICENSE)
* License: [BSD-3-Clause](https://cs.opensource.google/go/x/sync/+/v0.20.0:LICENSE)
```
@ -4211,9 +4666,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
## golang.org/x/sys
* Name: golang.org/x/sys
* Version: v0.34.0
* Version: v0.43.0
* License: [BSD-3-Clause](https://cs.opensource.google/go/x/sys/+/v0.34.0:LICENSE)
* License: [BSD-3-Clause](https://cs.opensource.google/go/x/sys/+/v0.43.0:LICENSE)
```
@ -4250,9 +4705,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
## golang.org/x/text
* Name: golang.org/x/text
* Version: v0.27.0
* Version: v0.36.0
* License: [BSD-3-Clause](https://cs.opensource.google/go/x/text/+/v0.27.0:LICENSE)
* License: [BSD-3-Clause](https://cs.opensource.google/go/x/text/+/v0.36.0:LICENSE)
```
@ -4289,9 +4744,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
## google.golang.org/protobuf
* Name: google.golang.org/protobuf
* Version: v1.36.6
* Version: v1.36.11
* License: [BSD-3-Clause](https://github.com/protocolbuffers/protobuf-go/blob/v1.36.6/LICENSE)
* License: [BSD-3-Clause](https://github.com/protocolbuffers/protobuf-go/blob/v1.36.11/LICENSE)
```
@ -4361,9 +4816,9 @@ THE SOFTWARE.
## gorm.io/gorm
* Name: gorm.io/gorm
* Version: v1.30.0
* Version: v1.31.1
* License: [MIT](https://github.com/go-gorm/gorm/blob/v1.30.0/LICENSE)
* License: [MIT](https://github.com/go-gorm/gorm/blob/v1.31.1/LICENSE)
```

View file

@ -18,13 +18,13 @@
{% if Person.ID %}
{% if Person.IsMember %}
<li class="breadcrumb-item">
<a href="/admin/members/{{ Person.ID }}">
<a href="/members/{{ Person.ID }}">
{{ Person.LastName }} {{ Person.FirstName }}
</a>
</li>
{% else %}
<li class="breadcrumb-item">
<a href="/admin/contacts/{{ Person.ID }}">
<a href="/contacts/{{ Person.ID }}">
{{ Person.LastName }} {{ Person.FirstName }}
</a>
</li>
@ -95,6 +95,12 @@
value="{{ Person.Email }}"
autocomplete="off"
/>
{% if PersonAccount.Enabled %}
<div class="text-danger mt-2">
Attention! Cette adresse email est liée à un compte SSO. En cas de
changement, la connexion devra se faire avec la nouvelle adresse.
</div>
{% endif %}
</div>
</div>
@ -345,6 +351,29 @@
</div>
{% endfor %}
{% if Person.IsMember or MembersPage %}
<div class="mt-4 mb-3">
<span class="h4"> Compte POP Vaud </span>
</div>
<div class="mb-1">
<input
type="checkbox"
class="form-check-input me-2"
id="account-enabled"
name="account-enabled"
autocomplete="off"
{% if PersonAccount.Enabled %}
checked
{% endif %}
/>
<label for="account-enabled" class="form-label">
Dispose d'un accès SSO
<b class="text-danger">(test, ne pas toucher, MERCI)</b>
</label>
</div>
{% endif %}
<div class="my-5">
<button class="btn btn-outline-primary" type="submit">
<i class="me-1 bi-floppy"></i>