Add page to see login attempts for a company
This commit is contained in:
parent
f7fdc594d5
commit
a11ca5b470
|
@ -0,0 +1,28 @@
|
||||||
|
-- Deploy camper:company_login_attempt to pg
|
||||||
|
-- requires: roles
|
||||||
|
-- requires: schema_camper
|
||||||
|
-- requires: login_attempt
|
||||||
|
-- requires: user
|
||||||
|
-- requires: company_user
|
||||||
|
-- requires: current_company_id
|
||||||
|
|
||||||
|
begin;
|
||||||
|
|
||||||
|
set search_path to camper, public;
|
||||||
|
|
||||||
|
create or replace view company_login_attempt with (security_barrier) as
|
||||||
|
select attempt_id
|
||||||
|
, user_name
|
||||||
|
, ip_address
|
||||||
|
, success
|
||||||
|
, attempted_at
|
||||||
|
from auth.login_attempt
|
||||||
|
join auth."user" on "user".email = user_name
|
||||||
|
join company_user using (user_id)
|
||||||
|
where company_id = current_company_id()
|
||||||
|
;
|
||||||
|
;
|
||||||
|
|
||||||
|
grant select on table company_login_attempt to admin;
|
||||||
|
|
||||||
|
commit;
|
|
@ -35,6 +35,13 @@ func (h *AdminHandler) Handler(user *auth.User, company *auth.Company, conn *dat
|
||||||
default:
|
default:
|
||||||
httplib.MethodNotAllowed(w, r, http.MethodGet, http.MethodPost)
|
httplib.MethodNotAllowed(w, r, http.MethodGet, http.MethodPost)
|
||||||
}
|
}
|
||||||
|
case "login-attempts":
|
||||||
|
switch r.Method {
|
||||||
|
case http.MethodGet:
|
||||||
|
serveLoginAttemptIndex(w, r, user, company, conn)
|
||||||
|
default:
|
||||||
|
httplib.MethodNotAllowed(w, r, http.MethodGet, http.MethodPost)
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
http.NotFound(w, r)
|
http.NotFound(w, r)
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,59 @@
|
||||||
|
package user
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"net/http"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"dev.tandem.ws/tandem/camper/pkg/auth"
|
||||||
|
"dev.tandem.ws/tandem/camper/pkg/database"
|
||||||
|
"dev.tandem.ws/tandem/camper/pkg/template"
|
||||||
|
)
|
||||||
|
|
||||||
|
func serveLoginAttemptIndex(w http.ResponseWriter, r *http.Request, loginAttempt *auth.User, company *auth.Company, conn *database.Conn) {
|
||||||
|
loginAttempts, err := collectLoginAttemptEntries(r.Context(), conn)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
loginAttempts.MustRender(w, r, loginAttempt, company)
|
||||||
|
}
|
||||||
|
|
||||||
|
func collectLoginAttemptEntries(ctx context.Context, conn *database.Conn) (loginAttemptIndex, error) {
|
||||||
|
rows, err := conn.Query(ctx, `
|
||||||
|
select user_name
|
||||||
|
, host(ip_address)
|
||||||
|
, attempted_at
|
||||||
|
, success
|
||||||
|
from company_login_attempt
|
||||||
|
order by attempted_at desc
|
||||||
|
limit 500
|
||||||
|
`)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer rows.Close()
|
||||||
|
|
||||||
|
var entries loginAttemptIndex
|
||||||
|
for rows.Next() {
|
||||||
|
entry := &loginAttemptEntry{}
|
||||||
|
if err = rows.Scan(&entry.UserName, &entry.IPAddress, &entry.Date, &entry.Success); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
entries = append(entries, entry)
|
||||||
|
}
|
||||||
|
|
||||||
|
return entries, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type loginAttemptEntry struct {
|
||||||
|
UserName string
|
||||||
|
IPAddress string
|
||||||
|
Date time.Time
|
||||||
|
Success bool
|
||||||
|
}
|
||||||
|
|
||||||
|
type loginAttemptIndex []*loginAttemptEntry
|
||||||
|
|
||||||
|
func (page *loginAttemptIndex) MustRender(w http.ResponseWriter, r *http.Request, loginAttempt *auth.User, company *auth.Company) {
|
||||||
|
template.MustRenderAdmin(w, r, loginAttempt, company, "user/login-attempts.gohtml", page)
|
||||||
|
}
|
42
po/ca.po
42
po/ca.po
|
@ -8,7 +8,7 @@ msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: camper\n"
|
"Project-Id-Version: camper\n"
|
||||||
"Report-Msgid-Bugs-To: jordi@tandem.blog\n"
|
"Report-Msgid-Bugs-To: jordi@tandem.blog\n"
|
||||||
"POT-Creation-Date: 2024-01-17 19:40+0100\n"
|
"POT-Creation-Date: 2024-01-17 20:25+0100\n"
|
||||||
"PO-Revision-Date: 2023-07-22 23:45+0200\n"
|
"PO-Revision-Date: 2023-07-22 23:45+0200\n"
|
||||||
"Last-Translator: jordi fita mas <jordi@tandem.blog>\n"
|
"Last-Translator: jordi fita mas <jordi@tandem.blog>\n"
|
||||||
"Language-Team: Catalan <ca@dodds.net>\n"
|
"Language-Team: Catalan <ca@dodds.net>\n"
|
||||||
|
@ -512,7 +512,6 @@ msgid "Name"
|
||||||
msgstr "Nom"
|
msgstr "Nom"
|
||||||
|
|
||||||
#: web/templates/admin/legal/index.gohtml:29
|
#: web/templates/admin/legal/index.gohtml:29
|
||||||
#: web/templates/admin/user/index.gohtml:42
|
|
||||||
msgid "No legal texts added yet."
|
msgid "No legal texts added yet."
|
||||||
msgstr "No s’ha afegit cap text legal encara."
|
msgstr "No s’ha afegit cap text legal encara."
|
||||||
|
|
||||||
|
@ -763,12 +762,14 @@ msgstr "Tipus"
|
||||||
#: web/templates/admin/campsite/index.gohtml:28
|
#: web/templates/admin/campsite/index.gohtml:28
|
||||||
#: web/templates/admin/campsite/type/index.gohtml:49
|
#: web/templates/admin/campsite/type/index.gohtml:49
|
||||||
#: web/templates/admin/season/index.gohtml:41
|
#: web/templates/admin/season/index.gohtml:41
|
||||||
|
#: web/templates/admin/user/login-attempts.gohtml:27
|
||||||
msgid "Yes"
|
msgid "Yes"
|
||||||
msgstr "Sí"
|
msgstr "Sí"
|
||||||
|
|
||||||
#: web/templates/admin/campsite/index.gohtml:28
|
#: web/templates/admin/campsite/index.gohtml:28
|
||||||
#: web/templates/admin/campsite/type/index.gohtml:49
|
#: web/templates/admin/campsite/type/index.gohtml:49
|
||||||
#: web/templates/admin/season/index.gohtml:41
|
#: web/templates/admin/season/index.gohtml:41
|
||||||
|
#: web/templates/admin/user/login-attempts.gohtml:27
|
||||||
msgid "No"
|
msgid "No"
|
||||||
msgstr "No"
|
msgstr "No"
|
||||||
|
|
||||||
|
@ -1062,8 +1063,35 @@ msgctxt "input"
|
||||||
msgid "Language"
|
msgid "Language"
|
||||||
msgstr "Idioma"
|
msgstr "Idioma"
|
||||||
|
|
||||||
|
#: web/templates/admin/user/login-attempts.gohtml:6
|
||||||
|
#: web/templates/admin/user/login-attempts.gohtml:11
|
||||||
|
msgctxt "title"
|
||||||
|
msgid "Login Attempts"
|
||||||
|
msgstr "Intents d’entrada"
|
||||||
|
|
||||||
|
#: web/templates/admin/user/login-attempts.gohtml:15
|
||||||
|
msgctxt "header"
|
||||||
|
msgid "Date"
|
||||||
|
msgstr "Data"
|
||||||
|
|
||||||
|
#: web/templates/admin/user/login-attempts.gohtml:16
|
||||||
|
#: web/templates/admin/user/index.gohtml:18
|
||||||
|
msgctxt "header"
|
||||||
|
msgid "Email"
|
||||||
|
msgstr "Correu-e"
|
||||||
|
|
||||||
|
#: web/templates/admin/user/login-attempts.gohtml:17
|
||||||
|
msgctxt "header"
|
||||||
|
msgid "IP Address"
|
||||||
|
msgstr "Adreça IP"
|
||||||
|
|
||||||
|
#: web/templates/admin/user/login-attempts.gohtml:18
|
||||||
|
msgctxt "header"
|
||||||
|
msgid "Success"
|
||||||
|
msgstr "Èxit"
|
||||||
|
|
||||||
#: web/templates/admin/user/index.gohtml:6
|
#: web/templates/admin/user/index.gohtml:6
|
||||||
#: web/templates/admin/user/index.gohtml:12
|
#: web/templates/admin/user/index.gohtml:13
|
||||||
#: web/templates/admin/layout.gohtml:70
|
#: web/templates/admin/layout.gohtml:70
|
||||||
msgctxt "title"
|
msgctxt "title"
|
||||||
msgid "Users"
|
msgid "Users"
|
||||||
|
@ -1074,10 +1102,10 @@ msgctxt "action"
|
||||||
msgid "Add User"
|
msgid "Add User"
|
||||||
msgstr "Afegeix usuari"
|
msgstr "Afegeix usuari"
|
||||||
|
|
||||||
#: web/templates/admin/user/index.gohtml:18
|
#: web/templates/admin/user/index.gohtml:12
|
||||||
msgctxt "header"
|
msgctxt "action"
|
||||||
msgid "Email"
|
msgid "Logs"
|
||||||
msgstr "Correu-e"
|
msgstr "Registres"
|
||||||
|
|
||||||
#: web/templates/admin/user/index.gohtml:19
|
#: web/templates/admin/user/index.gohtml:19
|
||||||
msgctxt "header"
|
msgctxt "header"
|
||||||
|
|
44
po/es.po
44
po/es.po
|
@ -8,7 +8,7 @@ msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: camper\n"
|
"Project-Id-Version: camper\n"
|
||||||
"Report-Msgid-Bugs-To: jordi@tandem.blog\n"
|
"Report-Msgid-Bugs-To: jordi@tandem.blog\n"
|
||||||
"POT-Creation-Date: 2024-01-17 19:40+0100\n"
|
"POT-Creation-Date: 2024-01-17 20:25+0100\n"
|
||||||
"PO-Revision-Date: 2023-07-22 23:46+0200\n"
|
"PO-Revision-Date: 2023-07-22 23:46+0200\n"
|
||||||
"Last-Translator: jordi fita mas <jordi@tandem.blog>\n"
|
"Last-Translator: jordi fita mas <jordi@tandem.blog>\n"
|
||||||
"Language-Team: Spanish <es@tp.org.es>\n"
|
"Language-Team: Spanish <es@tp.org.es>\n"
|
||||||
|
@ -512,7 +512,6 @@ msgid "Name"
|
||||||
msgstr "Nombre"
|
msgstr "Nombre"
|
||||||
|
|
||||||
#: web/templates/admin/legal/index.gohtml:29
|
#: web/templates/admin/legal/index.gohtml:29
|
||||||
#: web/templates/admin/user/index.gohtml:42
|
|
||||||
msgid "No legal texts added yet."
|
msgid "No legal texts added yet."
|
||||||
msgstr "No se ha añadido ningún texto legal todavía."
|
msgstr "No se ha añadido ningún texto legal todavía."
|
||||||
|
|
||||||
|
@ -763,12 +762,14 @@ msgstr "Tipo"
|
||||||
#: web/templates/admin/campsite/index.gohtml:28
|
#: web/templates/admin/campsite/index.gohtml:28
|
||||||
#: web/templates/admin/campsite/type/index.gohtml:49
|
#: web/templates/admin/campsite/type/index.gohtml:49
|
||||||
#: web/templates/admin/season/index.gohtml:41
|
#: web/templates/admin/season/index.gohtml:41
|
||||||
|
#: web/templates/admin/user/login-attempts.gohtml:27
|
||||||
msgid "Yes"
|
msgid "Yes"
|
||||||
msgstr "Sí"
|
msgstr "Sí"
|
||||||
|
|
||||||
#: web/templates/admin/campsite/index.gohtml:28
|
#: web/templates/admin/campsite/index.gohtml:28
|
||||||
#: web/templates/admin/campsite/type/index.gohtml:49
|
#: web/templates/admin/campsite/type/index.gohtml:49
|
||||||
#: web/templates/admin/season/index.gohtml:41
|
#: web/templates/admin/season/index.gohtml:41
|
||||||
|
#: web/templates/admin/user/login-attempts.gohtml:27
|
||||||
msgid "No"
|
msgid "No"
|
||||||
msgstr "No"
|
msgstr "No"
|
||||||
|
|
||||||
|
@ -1062,22 +1063,49 @@ msgctxt "input"
|
||||||
msgid "Language"
|
msgid "Language"
|
||||||
msgstr "Idioma"
|
msgstr "Idioma"
|
||||||
|
|
||||||
|
#: web/templates/admin/user/login-attempts.gohtml:6
|
||||||
|
#: web/templates/admin/user/login-attempts.gohtml:11
|
||||||
|
msgctxt "title"
|
||||||
|
msgid "Login Attempts"
|
||||||
|
msgstr "Intentos de entrada"
|
||||||
|
|
||||||
|
#: web/templates/admin/user/login-attempts.gohtml:15
|
||||||
|
msgctxt "header"
|
||||||
|
msgid "Date"
|
||||||
|
msgstr "Fecha"
|
||||||
|
|
||||||
|
#: web/templates/admin/user/login-attempts.gohtml:16
|
||||||
|
#: web/templates/admin/user/index.gohtml:18
|
||||||
|
msgctxt "header"
|
||||||
|
msgid "Email"
|
||||||
|
msgstr "Correo-e"
|
||||||
|
|
||||||
|
#: web/templates/admin/user/login-attempts.gohtml:17
|
||||||
|
msgctxt "header"
|
||||||
|
msgid "IP Address"
|
||||||
|
msgstr "Dirección IP"
|
||||||
|
|
||||||
|
#: web/templates/admin/user/login-attempts.gohtml:18
|
||||||
|
msgctxt "header"
|
||||||
|
msgid "Success"
|
||||||
|
msgstr "Éxito"
|
||||||
|
|
||||||
#: web/templates/admin/user/index.gohtml:6
|
#: web/templates/admin/user/index.gohtml:6
|
||||||
#: web/templates/admin/user/index.gohtml:12
|
#: web/templates/admin/user/index.gohtml:13
|
||||||
#: web/templates/admin/layout.gohtml:70
|
#: web/templates/admin/layout.gohtml:70
|
||||||
msgctxt "title"
|
msgctxt "title"
|
||||||
msgid "Users"
|
msgid "Users"
|
||||||
msgstr ""
|
msgstr "Usuarios"
|
||||||
|
|
||||||
#: web/templates/admin/user/index.gohtml:11
|
#: web/templates/admin/user/index.gohtml:11
|
||||||
msgctxt "action"
|
msgctxt "action"
|
||||||
msgid "Add User"
|
msgid "Add User"
|
||||||
msgstr "Añadir usuario"
|
msgstr "Añadir usuario"
|
||||||
|
|
||||||
#: web/templates/admin/user/index.gohtml:18
|
#: web/templates/admin/user/index.gohtml:12
|
||||||
msgctxt "header"
|
msgctxt "action"
|
||||||
msgid "Email"
|
msgid "Logs"
|
||||||
msgstr "Correo-e"
|
msgstr "Registros"
|
||||||
|
|
||||||
#: web/templates/admin/user/index.gohtml:19
|
#: web/templates/admin/user/index.gohtml:19
|
||||||
msgctxt "header"
|
msgctxt "header"
|
||||||
|
|
42
po/fr.po
42
po/fr.po
|
@ -8,7 +8,7 @@ msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: camper\n"
|
"Project-Id-Version: camper\n"
|
||||||
"Report-Msgid-Bugs-To: jordi@tandem.blog\n"
|
"Report-Msgid-Bugs-To: jordi@tandem.blog\n"
|
||||||
"POT-Creation-Date: 2024-01-17 19:40+0100\n"
|
"POT-Creation-Date: 2024-01-17 20:25+0100\n"
|
||||||
"PO-Revision-Date: 2023-12-20 10:13+0100\n"
|
"PO-Revision-Date: 2023-12-20 10:13+0100\n"
|
||||||
"Last-Translator: Oriol Carbonell <info@oriolcarbonell.cat>\n"
|
"Last-Translator: Oriol Carbonell <info@oriolcarbonell.cat>\n"
|
||||||
"Language-Team: French <traduc@traduc.org>\n"
|
"Language-Team: French <traduc@traduc.org>\n"
|
||||||
|
@ -513,7 +513,6 @@ msgid "Name"
|
||||||
msgstr "Nom"
|
msgstr "Nom"
|
||||||
|
|
||||||
#: web/templates/admin/legal/index.gohtml:29
|
#: web/templates/admin/legal/index.gohtml:29
|
||||||
#: web/templates/admin/user/index.gohtml:42
|
|
||||||
msgid "No legal texts added yet."
|
msgid "No legal texts added yet."
|
||||||
msgstr "Aucune texte juridique n’a encore été ajoutée."
|
msgstr "Aucune texte juridique n’a encore été ajoutée."
|
||||||
|
|
||||||
|
@ -764,12 +763,14 @@ msgstr "Type"
|
||||||
#: web/templates/admin/campsite/index.gohtml:28
|
#: web/templates/admin/campsite/index.gohtml:28
|
||||||
#: web/templates/admin/campsite/type/index.gohtml:49
|
#: web/templates/admin/campsite/type/index.gohtml:49
|
||||||
#: web/templates/admin/season/index.gohtml:41
|
#: web/templates/admin/season/index.gohtml:41
|
||||||
|
#: web/templates/admin/user/login-attempts.gohtml:27
|
||||||
msgid "Yes"
|
msgid "Yes"
|
||||||
msgstr "Oui"
|
msgstr "Oui"
|
||||||
|
|
||||||
#: web/templates/admin/campsite/index.gohtml:28
|
#: web/templates/admin/campsite/index.gohtml:28
|
||||||
#: web/templates/admin/campsite/type/index.gohtml:49
|
#: web/templates/admin/campsite/type/index.gohtml:49
|
||||||
#: web/templates/admin/season/index.gohtml:41
|
#: web/templates/admin/season/index.gohtml:41
|
||||||
|
#: web/templates/admin/user/login-attempts.gohtml:27
|
||||||
msgid "No"
|
msgid "No"
|
||||||
msgstr "Non"
|
msgstr "Non"
|
||||||
|
|
||||||
|
@ -1063,8 +1064,35 @@ msgctxt "input"
|
||||||
msgid "Language"
|
msgid "Language"
|
||||||
msgstr "Langue"
|
msgstr "Langue"
|
||||||
|
|
||||||
|
#: web/templates/admin/user/login-attempts.gohtml:6
|
||||||
|
#: web/templates/admin/user/login-attempts.gohtml:11
|
||||||
|
msgctxt "title"
|
||||||
|
msgid "Login Attempts"
|
||||||
|
msgstr "Tentatives de connexion"
|
||||||
|
|
||||||
|
#: web/templates/admin/user/login-attempts.gohtml:15
|
||||||
|
msgctxt "header"
|
||||||
|
msgid "Date"
|
||||||
|
msgstr "Date"
|
||||||
|
|
||||||
|
#: web/templates/admin/user/login-attempts.gohtml:16
|
||||||
|
#: web/templates/admin/user/index.gohtml:18
|
||||||
|
msgctxt "header"
|
||||||
|
msgid "Email"
|
||||||
|
msgstr "E-mail"
|
||||||
|
|
||||||
|
#: web/templates/admin/user/login-attempts.gohtml:17
|
||||||
|
msgctxt "header"
|
||||||
|
msgid "IP Address"
|
||||||
|
msgstr "Adresse IP"
|
||||||
|
|
||||||
|
#: web/templates/admin/user/login-attempts.gohtml:18
|
||||||
|
msgctxt "header"
|
||||||
|
msgid "Success"
|
||||||
|
msgstr "Succès"
|
||||||
|
|
||||||
#: web/templates/admin/user/index.gohtml:6
|
#: web/templates/admin/user/index.gohtml:6
|
||||||
#: web/templates/admin/user/index.gohtml:12
|
#: web/templates/admin/user/index.gohtml:13
|
||||||
#: web/templates/admin/layout.gohtml:70
|
#: web/templates/admin/layout.gohtml:70
|
||||||
msgctxt "title"
|
msgctxt "title"
|
||||||
msgid "Users"
|
msgid "Users"
|
||||||
|
@ -1075,10 +1103,10 @@ msgctxt "action"
|
||||||
msgid "Add User"
|
msgid "Add User"
|
||||||
msgstr "Ajouter un utilisateur"
|
msgstr "Ajouter un utilisateur"
|
||||||
|
|
||||||
#: web/templates/admin/user/index.gohtml:18
|
#: web/templates/admin/user/index.gohtml:12
|
||||||
msgctxt "header"
|
msgctxt "action"
|
||||||
msgid "Email"
|
msgid "Logs"
|
||||||
msgstr "E-mail"
|
msgstr "Journaux"
|
||||||
|
|
||||||
#: web/templates/admin/user/index.gohtml:19
|
#: web/templates/admin/user/index.gohtml:19
|
||||||
msgctxt "header"
|
msgctxt "header"
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
-- Revert camper:company_login_attempt from pg
|
||||||
|
|
||||||
|
begin;
|
||||||
|
|
||||||
|
drop view if exists camper.company_login_attempt;
|
||||||
|
|
||||||
|
commit;
|
|
@ -155,3 +155,4 @@ translate_cover_carousel_slide [roles schema_camper cover_carousel_i18n] 2024-01
|
||||||
remove_cover_carousel_slide [roles schema_camper cover_carousel cover_carousel_i18n] 2024-01-16T18:27:48Z jordi fita mas <jordi@tandem.blog> # Add function to remove sliders from the cover carousel
|
remove_cover_carousel_slide [roles schema_camper cover_carousel cover_carousel_i18n] 2024-01-16T18:27:48Z jordi fita mas <jordi@tandem.blog> # Add function to remove sliders from the cover carousel
|
||||||
order_cover_carousel [schema_camper roles cover_carousel] 2024-01-16T18:40:12Z jordi fita mas <jordi@tandem.blog> # Add function to order cover carousel
|
order_cover_carousel [schema_camper roles cover_carousel] 2024-01-16T18:40:12Z jordi fita mas <jordi@tandem.blog> # Add function to order cover carousel
|
||||||
company_user_profile [roles schema_camper user company_user current_company_id] 2024-01-17T17:37:19Z jordi fita mas <jordi@tandem.blog> # Add view to list users for admins
|
company_user_profile [roles schema_camper user company_user current_company_id] 2024-01-17T17:37:19Z jordi fita mas <jordi@tandem.blog> # Add view to list users for admins
|
||||||
|
company_login_attempt [roles schema_camper login_attempt user company_user current_company_id] 2024-01-17T19:02:26Z jordi fita mas <jordi@tandem.blog> # Add view to see login attempts for current company
|
||||||
|
|
|
@ -0,0 +1,107 @@
|
||||||
|
-- Test company_login_attempt
|
||||||
|
set client_min_messages to warning;
|
||||||
|
create extension if not exists pgtap;
|
||||||
|
reset client_min_messages;
|
||||||
|
|
||||||
|
begin;
|
||||||
|
|
||||||
|
select plan(17);
|
||||||
|
|
||||||
|
set search_path to camper, auth, public;
|
||||||
|
|
||||||
|
select has_view('company_login_attempt');
|
||||||
|
select table_privs_are('company_login_attempt', 'guest', array []::text[]);
|
||||||
|
select table_privs_are('company_login_attempt', 'employee', array []::text[]);
|
||||||
|
select table_privs_are('company_login_attempt', 'admin', array ['SELECT']);
|
||||||
|
select table_privs_are('company_login_attempt', 'authenticator', array []::text[]);
|
||||||
|
|
||||||
|
select has_column('company_login_attempt', 'attempt_id');
|
||||||
|
select col_type_is('company_login_attempt', 'attempt_id', 'bigint');
|
||||||
|
|
||||||
|
select has_column('company_login_attempt', 'user_name');
|
||||||
|
select col_type_is('company_login_attempt', 'user_name', 'text');
|
||||||
|
|
||||||
|
select has_column('company_login_attempt', 'ip_address');
|
||||||
|
select col_type_is('company_login_attempt', 'ip_address', 'inet');
|
||||||
|
|
||||||
|
select has_column('company_login_attempt', 'success');
|
||||||
|
select col_type_is('company_login_attempt', 'success', 'boolean');
|
||||||
|
|
||||||
|
select has_column('company_login_attempt', 'attempted_at');
|
||||||
|
select col_type_is('company_login_attempt', 'attempted_at', 'timestamp with time zone');
|
||||||
|
|
||||||
|
|
||||||
|
set client_min_messages to warning;
|
||||||
|
truncate company_host cascade;
|
||||||
|
truncate company_user cascade;
|
||||||
|
truncate company cascade;
|
||||||
|
truncate auth."user" cascade;
|
||||||
|
truncate auth.login_attempt cascade;
|
||||||
|
reset client_min_messages;
|
||||||
|
|
||||||
|
insert into auth."user" (user_id, email, name, password, cookie, cookie_expires_at, lang_tag)
|
||||||
|
values (1, 'demo@tandem.blog', 'Demo', 'test', '44facbb30d8a419dfd4bfbc44a4b5539d4970148dfc84bed0e', current_timestamp + interval '1 month', 'ca')
|
||||||
|
, (5, 'admin@tandem.blog', 'Admin', 'test', '12af4c88b528c2ad4222e3740496ecbc58e76e26f087657524', current_timestamp + interval '1 month', 'es')
|
||||||
|
, (7, 'another@tandem.blog', 'Another Employee', 'test', default, default, default)
|
||||||
|
;
|
||||||
|
|
||||||
|
insert into company (company_id, business_name, vatin, trade_name, phone, email, web, address, city, province, postal_code, rtc_number, tourist_tax, country_code, currency_code, default_lang_tag)
|
||||||
|
values (2, 'Company 2', 'XX123', '', '555-555-555', 'a@a', '', '', '', '', '', '', 60, 'ES', 'EUR', 'ca')
|
||||||
|
, (4, 'Company 4', 'XX234', '', '666-666-666', 'b@b', '', '', '', '', '', '', 60, 'FR', 'USD', 'es')
|
||||||
|
;
|
||||||
|
|
||||||
|
insert into company_user (company_id, user_id, role)
|
||||||
|
values (2, 1, 'admin')
|
||||||
|
, (4, 5, 'admin')
|
||||||
|
, (4, 7, 'employee')
|
||||||
|
;
|
||||||
|
|
||||||
|
insert into company_host (company_id, host)
|
||||||
|
values (2, 'co2')
|
||||||
|
, (4, 'co4')
|
||||||
|
;
|
||||||
|
|
||||||
|
prepare login_attempt as
|
||||||
|
select user_name, ip_address, success, attempted_at
|
||||||
|
from company_login_attempt
|
||||||
|
;
|
||||||
|
|
||||||
|
select login('demo@tandem.blog', 'test', '::1'::inet);
|
||||||
|
select login('demo@tandem.blog', '123', '127.0.0.1'::inet);
|
||||||
|
select login('admin@tandem.blog', '123', '192.168.1.1'::inet);
|
||||||
|
select login('admin@tandem.blog', 'test', '::1'::inet);
|
||||||
|
select login('admin@tandem.blog', 'test', '192.168.2.1'::inet);
|
||||||
|
select login('another@tandem.blog', 'test', '192.168.3.1'::inet);
|
||||||
|
select login('unknown@tandem.blog', 'test', '192.168.4.1'::inet);
|
||||||
|
|
||||||
|
select set_cookie('44facbb30d8a419dfd4bfbc44a4b5539d4970148dfc84bed0e/demo@tandem.blog', 'co2');
|
||||||
|
|
||||||
|
select bag_eq(
|
||||||
|
'login_attempt',
|
||||||
|
$$ values ('demo@tandem.blog', '::1'::inet, true, current_timestamp)
|
||||||
|
, ('demo@tandem.blog', '127.0.0.1'::inet, false, current_timestamp)
|
||||||
|
$$,
|
||||||
|
'Should only see login attempts from the first company'
|
||||||
|
);
|
||||||
|
|
||||||
|
reset role;
|
||||||
|
|
||||||
|
select set_cookie('12af4c88b528c2ad4222e3740496ecbc58e76e26f087657524/admin@tandem.blog', 'co4');
|
||||||
|
|
||||||
|
select bag_eq(
|
||||||
|
'login_attempt',
|
||||||
|
$$ values ('admin@tandem.blog', '192.168.1.1'::inet, false, current_timestamp)
|
||||||
|
, ('admin@tandem.blog', '::1'::inet, true, current_timestamp)
|
||||||
|
, ('admin@tandem.blog', '192.168.2.1'::inet, true, current_timestamp)
|
||||||
|
, ('another@tandem.blog', '192.168.3.1'::inet, true, current_timestamp)
|
||||||
|
$$,
|
||||||
|
'Should only see login_attempts from the second company'
|
||||||
|
);
|
||||||
|
|
||||||
|
reset role;
|
||||||
|
|
||||||
|
|
||||||
|
select *
|
||||||
|
from finish();
|
||||||
|
|
||||||
|
rollback;
|
|
@ -0,0 +1,14 @@
|
||||||
|
-- Verify camper:company_login_attempt on pg
|
||||||
|
|
||||||
|
begin;
|
||||||
|
|
||||||
|
select attempt_id
|
||||||
|
, user_name
|
||||||
|
, ip_address
|
||||||
|
, success
|
||||||
|
, attempted_at
|
||||||
|
from camper.company_login_attempt
|
||||||
|
where false
|
||||||
|
;
|
||||||
|
|
||||||
|
rollback;
|
|
@ -9,36 +9,33 @@
|
||||||
{{ define "content" -}}
|
{{ define "content" -}}
|
||||||
{{- /*gotype: dev.tandem.ws/tandem/camper/pkg/user.userIndex*/ -}}
|
{{- /*gotype: dev.tandem.ws/tandem/camper/pkg/user.userIndex*/ -}}
|
||||||
<a href="/admin/users/new">{{( pgettext "Add User" "action" )}}</a>
|
<a href="/admin/users/new">{{( pgettext "Add User" "action" )}}</a>
|
||||||
|
<a href="/admin/users/login-attempts">{{( pgettext "Logs" "action" )}}</a>
|
||||||
<h2>{{( pgettext "Users" "title" )}}</h2>
|
<h2>{{( pgettext "Users" "title" )}}</h2>
|
||||||
{{ if .Users -}}
|
<table>
|
||||||
<table>
|
<thead>
|
||||||
<thead>
|
<tr>
|
||||||
|
<th scope="col">{{( pgettext "Name" "header" )}}</th>
|
||||||
|
<th scope="col">{{( pgettext "Email" "header" )}}</th>
|
||||||
|
<th scope="col">{{( pgettext "Role" "header" )}}</th>
|
||||||
|
<th scope="col">{{( pgettext "Actions" "header" )}}</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{{ $confirm := ( gettext "Are you sure you wish to delete this user?" )}}
|
||||||
|
{{ range .Users -}}
|
||||||
<tr>
|
<tr>
|
||||||
<th scope="col">{{( pgettext "Name" "header" )}}</th>
|
<td><a href="{{ .URL }}">{{ .Name }}</a></td>
|
||||||
<th scope="col">{{( pgettext "Email" "header" )}}</th>
|
<td><a href="{{ .URL }}">{{ .Email }}</a></td>
|
||||||
<th scope="col">{{( pgettext "Role" "header" )}}</th>
|
<td>{{( pgettext .Role "role" )}}</td>
|
||||||
<th scope="col">{{( pgettext "Actions" "header" )}}</th>
|
<td>
|
||||||
|
<button data-hx-delete="{{ .URL }}"
|
||||||
|
data-hx-confirm="{{ $confirm }}"
|
||||||
|
data-hx-headers='{ {{ CSRFHeader }} }'>
|
||||||
|
{{( pgettext "Delete" "action" )}}
|
||||||
|
</button>
|
||||||
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
{{- end }}
|
||||||
<tbody>
|
</tbody>
|
||||||
{{ $confirm := ( gettext "Are you sure you wish to delete this user?" )}}
|
</table>
|
||||||
{{ range .Users -}}
|
|
||||||
<tr>
|
|
||||||
<td><a href="{{ .URL }}">{{ .Name }}</a></td>
|
|
||||||
<td><a href="{{ .URL }}">{{ .Email }}</a></td>
|
|
||||||
<td>{{( pgettext .Role "role" )}}</td>
|
|
||||||
<td>
|
|
||||||
<button data-hx-delete="{{ .URL }}"
|
|
||||||
data-hx-confirm="{{ $confirm }}"
|
|
||||||
data-hx-headers='{ {{ CSRFHeader }} }'>
|
|
||||||
{{( pgettext "Delete" "action" )}}
|
|
||||||
</button>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
{{- end }}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
{{ else -}}
|
|
||||||
<p>{{( gettext "No legal texts added yet." )}}</p>
|
|
||||||
{{- end }}
|
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
<!--
|
||||||
|
SPDX-FileCopyrightText: 2023 jordi fita mas <jordi@tandem.blog>
|
||||||
|
SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
-->
|
||||||
|
{{ define "title" -}}
|
||||||
|
{{( pgettext "Login Attempts" "title" )}}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
{{ define "content" -}}
|
||||||
|
{{- /*gotype: dev.tandem.ws/tandem/camper/pkg/user.loginAttemptIndex*/ -}}
|
||||||
|
<h2>{{( pgettext "Login Attempts" "title" )}}</h2>
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th scope="col">{{( pgettext "Date" "header" )}}</th>
|
||||||
|
<th scope="col">{{( pgettext "Email" "header" )}}</th>
|
||||||
|
<th scope="col">{{( pgettext "IP Address" "header" )}}</th>
|
||||||
|
<th scope="col">{{( pgettext "Success" "header" )}}</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{{ range . -}}
|
||||||
|
<tr>
|
||||||
|
<td>{{ .Date }}</td>
|
||||||
|
<td>{{ .UserName }}</td>
|
||||||
|
<td>{{ .IPAddress }}</td>
|
||||||
|
<td>{{ if .Success }}{{( gettext "Yes" )}}{{ else }}{{( gettext "No" )}}{{ end }}</td>
|
||||||
|
</tr>
|
||||||
|
{{- end }}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
{{- end }}
|
Loading…
Reference in New Issue