From 1d61efeda03f2fb956c1a0c7faea35c327544f06 Mon Sep 17 00:00:00 2001 From: Antonio De Lucreziis Date: Mon, 13 Jun 2022 02:36:31 +0200 Subject: [PATCH] Aggiunte tante cose relative al profilo utente --- auth/auth.go | 40 ++++++++++----- auth/ldap.go | 69 +++++++++---------------- auth/memory.go | 98 +++++++++++++++++------------------ frontend/Makefile | 12 ++--- frontend/rollup.config.js | 19 ++++--- frontend/src/profilo.js | 16 ++++++ main.go | 13 ++++- public/style.css | 44 +++++++++++++++- public/theme-dark.css | 23 +++++++-- views/home.html | 4 +- views/profilo.html | 105 ++++++++++++++++++++++++++++++++++---- 11 files changed, 298 insertions(+), 145 deletions(-) create mode 100644 frontend/src/profilo.js diff --git a/auth/auth.go b/auth/auth.go index ac02bee..5c39517 100644 --- a/auth/auth.go +++ b/auth/auth.go @@ -4,32 +4,44 @@ import "fmt" var ErrInvalidSession = fmt.Errorf(`invalid session token`) -type User interface { - GetUsername() string - GetName() string - GetSurname() string - GetFullName() string +type User struct { + Username string `json:"username"` + Name string `json:"name"` + Surname string `json:"surname"` + FullName string `json:"fullName"` + Email string `json:"email"` } -type Session interface { - GetUsername() string - GetToken() string +func (u User) WithDefaultFullName() User { + return User{ + Username: u.Username, + Name: u.Name, + Surname: u.Surname, + Email: u.Email, + + FullName: u.Username + " " + u.Surname, + } +} + +type Session struct { + Username string `json:"username"` + Token string `json:"token"` } type AuthenticatorService interface { - GetUser(username string) (User, error) - GetUsers() ([]User, error) - GetSession(token string) (Session, error) - Login(username, password string) (Session, error) + GetUser(username string) (*User, error) + GetUsers() ([]*User, error) + GetSession(token string) (*Session, error) + Login(username, password string) (*Session, error) } -func UserForSession(as AuthenticatorService, token string) (User, error) { +func UserForSession(as AuthenticatorService, token string) (*User, error) { session, err := as.GetSession(token) if err != nil { return nil, err } - user, err := as.GetUser(session.GetUsername()) + user, err := as.GetUser(session.Username) if err != nil { return nil, err } diff --git a/auth/ldap.go b/auth/ldap.go index 183da64..16f092e 100644 --- a/auth/ldap.go +++ b/auth/ldap.go @@ -7,47 +7,24 @@ import ( "log" "net/http" "path" - "time" ) -type LDAPUser struct { - Username string `json:"username"` +type ldapUser struct { + User NumericId int `json:"id"` - Name string `json:"name"` - Surname string `json:"surname"` - Email string `json:"email"` Role string `json:"role"` Gecos string `json:"gecos"` } -func (u LDAPUser) GetUsername() string { - return u.Username -} - -func (u LDAPUser) GetName() string { - return u.Name -} - -func (u LDAPUser) GetSurname() string { - return u.Surname -} - -func (u LDAPUser) GetFullName() string { - return u.Gecos -} - -type SimpleSession struct { - Token string `json:"token"` - Username string `json:"username"` - CreatedOn time.Time `json:"createdOn"` -} +func (u ldapUser) AsUser() *User { + return &User{ + Username: u.Username, + Name: u.Name, + Surname: u.Surname, + Email: u.Email, -func (s SimpleSession) GetUsername() string { - return s.Username -} - -func (s SimpleSession) GetToken() string { - return s.Token + FullName: u.Gecos, + } } type LDAPAuthService struct { @@ -99,31 +76,31 @@ func (a *LDAPAuthService) doPostRequest(url string, request interface{}, respons return json.NewDecoder(res.Body).Decode(response) } -func (a *LDAPAuthService) GetUser(username string) (User, error) { - var user LDAPUser +func (a *LDAPAuthService) GetUser(username string) (*User, error) { + var user ldapUser if err := a.doGetRequest(fmt.Sprintf("/user/%s", username), &user); err != nil { return nil, err } - return &user, nil + return user.AsUser(), nil } -func (a *LDAPAuthService) GetUsers() ([]User, error) { - ldapUsers := []*LDAPUser{} +func (a *LDAPAuthService) GetUsers() ([]*User, error) { + ldapUsers := []*ldapUser{} if err := a.doGetRequest(fmt.Sprintf("/users"), &ldapUsers); err != nil { return nil, err } - users := make([]User, len(ldapUsers)) + users := make([]*User, len(ldapUsers)) for i, u := range ldapUsers { - users[i] = u + users[i] = u.AsUser() } return users, nil } -func (a *LDAPAuthService) GetSession(token string) (Session, error) { - var response SimpleSession +func (a *LDAPAuthService) GetSession(token string) (*Session, error) { + var response Session if err := a.doGetRequest(fmt.Sprintf("/session/%s", token), &response); err != nil { return nil, err } @@ -131,14 +108,14 @@ func (a *LDAPAuthService) GetSession(token string) (Session, error) { return &response, nil } -func (a *LDAPAuthService) Login(username, password string) (Session, error) { - body := map[string]interface{}{ +func (a *LDAPAuthService) Login(username, password string) (*Session, error) { + reqBody := map[string]interface{}{ "username": username, "password": password, } - var response SimpleSession - if err := a.doPostRequest(fmt.Sprintf("/login"), body, &response); err != nil { + var response Session + if err := a.doPostRequest(fmt.Sprintf("/login"), reqBody, &response); err != nil { return nil, err } diff --git a/auth/memory.go b/auth/memory.go index 65c02a8..f0e060b 100644 --- a/auth/memory.go +++ b/auth/memory.go @@ -7,108 +7,102 @@ import ( ) var exampleMemoryUsers = &Memory{ - Users: map[string]*MemoryUser{ + Users: map[string]*memoryUser{ "aziis98": { - Username: "aziis98", - Name: "Antonio", - Surname: "De Lucreziis", + User: User{ + Username: "aziis98", + Name: "Antonio", + Surname: "De Lucreziis", + Email: "aziis98@example.org", + }.WithDefaultFullName(), Password: "123", }, "bachoseven": { - Username: "bachoseven", - Name: "Francesco", - Surname: "Minnocci", + User: User{ + Username: "bachoseven", + Name: "Francesco", + Surname: "Minnocci", + Email: "bachoseven@example.org", + }.WithDefaultFullName(), Password: "234", }, }, - Sessions: map[string]*MemorySession{}, + Sessions: map[string]*memorySession{}, } -type MemoryUser struct { - Username string `json:"username"` - Name string `json:"name"` - Surname string `json:"surname"` - +type memoryUser struct { + User Password string `json:"-"` } -func (u *MemoryUser) GetUsername() string { - return u.Username -} - -func (u *MemoryUser) GetName() string { - return u.Name -} - -func (u *MemoryUser) GetSurname() string { - return u.Surname -} - -func (u *MemoryUser) GetFullName() string { - return u.Name + " " + u.Surname +func (u memoryUser) AsUser() *User { + return &User{ + Username: u.Username, + Name: u.Name, + Surname: u.Surname, + FullName: u.FullName, + Email: u.Email, + } } -type MemorySession struct { +type memorySession struct { Username string Token string } -func (s *MemorySession) GetUsername() string { - return s.Username -} - -func (s *MemorySession) GetToken() string { - return s.Token +func (s memorySession) AsSession() *Session { + return &Session{ + Username: s.Username, + Token: s.Token, + } } type Memory struct { - Users map[string]*MemoryUser - Sessions map[string]*MemorySession + Users map[string]*memoryUser + Sessions map[string]*memorySession } -func (m *Memory) GetUser(username string) (User, error) { +func (m *Memory) GetUser(username string) (*User, error) { user, ok := m.Users[username] if !ok { return nil, fmt.Errorf(`no user with that username`) } - return user, nil + return user.AsUser(), nil } -func (m *Memory) GetUsers() ([]User, error) { - users := make([]User, len(m.Users)) +func (m *Memory) GetUsers() ([]*User, error) { + users := make([]*User, len(m.Users)) i := 0 for _, u := range m.Users { - users[i] = u + users[i] = u.AsUser() i++ } return users, nil } -func (m *Memory) GetSession(token string) (Session, error) { +func (m *Memory) GetSession(token string) (*Session, error) { session, ok := m.Sessions[token] if !ok { return nil, ErrInvalidSession } - return session, nil + return session.AsSession(), nil } -func (m *Memory) Login(username string, password string) (Session, error) { - user, err := m.GetUser(username) - if err != nil { - return nil, err +func (m *Memory) Login(username string, password string) (*Session, error) { + user, ok := m.Users[username] + if !ok { + return nil, fmt.Errorf(`no user with that username`) } - memUser := user.(*MemoryUser) - - if memUser.Password != password { + if user.Password != password { return nil, fmt.Errorf(`invalid credentials`) } - session := &MemorySession{username, util.GenerateRandomString(15)} + session := &memorySession{username, util.GenerateRandomString(15)} m.Sessions[session.Token] = session - return session, nil + return session.AsSession(), nil } diff --git a/frontend/Makefile b/frontend/Makefile index 3f9bea8..3b3e0b7 100644 --- a/frontend/Makefile +++ b/frontend/Makefile @@ -1,14 +1,10 @@ -JS_SOURCES = src/utenti.js -JS_BUNDLES = $(patsubst src/%.js, dist/%.min.js, $(JS_SOURCES)) +JS_SOURCES = src/utenti.js src/profilo.js .PHONY: all -all: $(JS_BUNDLES) - -dist/%.min.js: src/%.js - rollup -c rollup.config.js $< +all: $(JS_SOURCES) + rollup -c .PHONY: debug debug: - @echo "JS_SOURCES = $(JS_SOURCES)" - @echo "JS_BUNDLES = $(JS_BUNDLES)" \ No newline at end of file + @echo "JS_SOURCES = $(JS_SOURCES)" \ No newline at end of file diff --git a/frontend/rollup.config.js b/frontend/rollup.config.js index 3447719..02cadfb 100644 --- a/frontend/rollup.config.js +++ b/frontend/rollup.config.js @@ -1,6 +1,4 @@ import { defineConfig } from 'rollup' - -// import resolve from '@rollup/plugin-node-resolve' import { terser } from 'rollup-plugin-terser' export default defineConfig([ @@ -16,9 +14,18 @@ export default defineConfig([ 'fuse.js': 'Fuse', }, }, - plugins: [ - // resolve(), - terser(), - ], + plugins: [terser()], + }, + { + input: 'src/profilo.js', + external: ['alpinejs'], + output: { + file: 'dist/profilo.min.js', + format: 'iife', + globals: { + alpinejs: 'Alpine', + }, + }, + plugins: [terser()], }, ]) diff --git a/frontend/src/profilo.js b/frontend/src/profilo.js new file mode 100644 index 0000000..d24f29f --- /dev/null +++ b/frontend/src/profilo.js @@ -0,0 +1,16 @@ +import Alpine from 'alpinejs' + +Alpine.data('profilo', () => ({ + init() { + console.log('Profilo!') + }, +})) + +Alpine.data('passwordForm', () => ({ + password: '', + passwordAgain: '', + passwordSame: true, + onUpdate() { + this.passwordSame = this.password === this.passwordAgain + }, +})) diff --git a/main.go b/main.go index 0c08f5d..84f6328 100644 --- a/main.go +++ b/main.go @@ -81,6 +81,15 @@ func main() { return c.JSON(utenti) }) + app.Get("/api/profilo", func(c *fiber.Ctx) error { + user := c.Locals("user") + if user == nil { + return fmt.Errorf(`user not logged in`) + } + + return c.JSON(user) + }) + app.Get("/storia", func(c *fiber.Ctx) error { storia, err := GetStoria() if err != nil { @@ -137,7 +146,7 @@ func main() { c.Cookie(&fiber.Cookie{ Name: "session-token", Path: "/", - Value: session.GetToken(), + Value: session.Token, Expires: inThreeDays, }) @@ -145,7 +154,7 @@ func main() { }) app.Get("/profilo", func(c *fiber.Ctx) error { - user, ok := c.Locals("user").(auth.User) + user, ok := c.Locals("user").(*auth.User) if !ok || user == nil { return fmt.Errorf(`user not logged in`) } diff --git a/public/style.css b/public/style.css index bb68780..08e11f4 100644 --- a/public/style.css +++ b/public/style.css @@ -29,6 +29,8 @@ --shadow-1: 0 0 16px 0 #00000018; --text-input-bg: #fff; + --text-input-readonly-bg: #e4e4e4; + --text-input-readonly-fg: #777; --bg-darker-2-1: #c8c8c8; --accent-2-lighter: #5cc969; @@ -401,11 +403,24 @@ li { line-height: 1.8; } +p + p { + padding-top: 0.5rem; +} + ul, ol { padding: 0 0 0 1.5rem; } +hr { + width: 50ch; + height: 1px; + margin: 0; + + border: none; + background-color: var(--bg-darker-2); +} + pre { margin: 0.5rem 0; @@ -431,21 +446,27 @@ p.center { /* Controls */ -a { +a:not(.button) { color: var(--accent-1-fg); font-weight: var(--font-weight-medium); text-decoration: none; } -a:hover { +a:not(.button):hover { color: var(--accent-1); text-decoration: underline; } +a.button { + text-decoration: none; +} + /* Buttons */ button, .button { + display: inline-block; + font-family: var(--font-sf); font-weight: var(--font-weight-medium); font-size: 17px; @@ -544,6 +565,19 @@ input[type='password'] { font-family: caption; } +input[type='text']:read-only, +input[type='password']:read-only { + background: var(--text-input-readonly-bg); + color: var(--text-input-readonly-fg); + box-shadow: 0 0 8px 0 #00000010; +} + +input[type='text'].error, +input[type='password'].error { + background: #faa; + color: #311; +} + /* Compound Controls */ .compound { @@ -617,10 +651,16 @@ form .field-set { padding: 1rem; } +form .field-set .fill { + grid-column: 1 / span 2; +} + form .field-set label { grid-column: 1 / 2; align-self: center; justify-self: end; + + font-weight: var(--font-weight-medium); } form .field-set input { diff --git a/public/theme-dark.css b/public/theme-dark.css index 65ebd01..2048d8e 100644 --- a/public/theme-dark.css +++ b/public/theme-dark.css @@ -1,4 +1,3 @@ - body.dark-mode { --bg: #282828; --fg: #a6cc92; @@ -24,8 +23,10 @@ body.dark-mode { --font-weight-bold: 700; --shadow-1: 0 0 16px 0 #16182077; - + --text-input-bg: var(--bg-darker); + --text-input-readonly-bg: hsl(10, 10%, 22%); + --text-input-readonly-fg: hsl(10, 10%, 40%); --bg-darker-2-1: #c8c8c8; --accent-2-lighter: #5cc969; @@ -62,6 +63,19 @@ body.dark-mode { background: #4b4342; } +.dark-mode input[type='text']:read-only, +.dark-mode input[type='password']:read-only { + background: var(--text-input-readonly-bg); + color: var(--text-input-readonly-fg); + box-shadow: 0 0 8px 0 #00000010; +} + +.dark-mode input[type='text'].error, +.dark-mode input[type='password'].error { + background: #633; + color: #faa; +} + .dark-mode pre { background: var(--bg-darker); border: 1px solid var(--bg-darker-2); @@ -72,6 +86,7 @@ body.dark-mode { filter: invert(1); } -.dark-mode table td, .dark-mode table th { +.dark-mode table td, +.dark-mode table th { border-color: var(--fg); -} \ No newline at end of file +} diff --git a/views/home.html b/views/home.html index fa2b6a0..4758ff8 100644 --- a/views/home.html +++ b/views/home.html @@ -88,10 +88,12 @@ - +
+
Vuoi diventare un macchinista?
+

Ti interessa (o interesserebbe) smanettare al PC, montare e smontare i cose? Stai spesso in dipartimento? Allora diff --git a/views/profilo.html b/views/profilo.html index d26ca4f..5d960e2 100644 --- a/views/profilo.html +++ b/views/profilo.html @@ -1,20 +1,105 @@ {{template "base" .}} - -{{define "title"}}Profilo @{{ .User.Username }} • PHC{{end}} - +{{define "title"}}Profilo di @{{ .User.Username }} • PHC{{end}} {{define "body"}} -

+ + +

Profilo di @{{ .User.Username }}

-

Impostazioni

-

- Lorem ipsum dolor sit amet consectetur adipisicing elit. Quae earum amet delectus cumque obcaecati minus quos aliquid fugiat reprehenderit voluptatum? -

- Logout + Logout

+
+
+

Appunti e Dispense

+

+ Per gestire i tuoi appunti e le tue dispense caricate nella sezione Appunti del sito vai + alla pagina appunti condivisi. +

+
+
+

Impostazioni

+
+
+
+ Sito PHC +
+

+ Aggiorna i campi relativi al sito del PHC, l'immagine del profilo verrà visualizzata sulla tua pagina utente phc.dm.unipi.it/u/{{ .User.Username }} e nella lista di tutti gli utenti. +

+
+ + + + +
+

+ Puoi anche aggiungere link ad altri tuoi profili su siti esterni (quando riempi l'ultimo campo se ne crea uno nuovo sotto) +

+
+ + + + + + +
+
+ +
+
+
+
+ Informazioni Utente +
+

+ Aggiorna i campi modificabili dell'account Poisson +

+
+ + + + + + + + +
+
+ +
+
+
+
+ Modifica Password +
+

+ Aggiorna la password di Poisson +

+
+ + + + + + +
+
+ +
+
+
+
+

Recupero Credenziali Poisson

- Per il recupero credenziali vieni direttamente al PHC a parlarne con calma con noi altrimenti puoi inviaci una email all'indirizzo {{ .Config.Email }} e poi recuperare le nuove credenziali sul sito credenziali.phc.dm.unipi.it. + Per il recupero credenziali vieni direttamente al PHC a parlarne con calma con noi altrimenti puoi inviaci una email + all'indirizzo {{ .Config.Email }} e poi recuperare le nuove credenziali sul + sito credenziali.phc.dm.unipi.it.

{{end}} \ No newline at end of file