diff --git a/database.go b/database.go
new file mode 100644
index 0000000..0e0aff6
--- /dev/null
+++ b/database.go
@@ -0,0 +1,136 @@
+package main
+
+import (
+ "encoding/json"
+ "fmt"
+ "os"
+
+ "golang.org/x/crypto/bcrypt"
+)
+
+// PublicUser is the "public" version of the "User" struct, this excludes private information
+type PublicUser struct {
+ Username string `json:"username"`
+}
+
+// User represents a user in the database
+type User struct {
+ Username string `json:"username"`
+ PasswordBCrypt []byte `json:"passwordBCrypt"`
+}
+
+func (u User) PublicUser() PublicUser {
+ return PublicUser{
+ Username: u.Username,
+ }
+}
+
+type Database interface {
+ GetUsers() ([]User, error)
+ GetUser(username string) (User, error)
+ CreateUser(user User) error
+}
+
+type memDB struct {
+ Users map[string]User `json:"users"`
+}
+
+func NewInMemoryDB() (Database, error) {
+ var db memDB
+
+ exampleFile, err := os.Open("example-db.local.json")
+ if err != nil {
+ return nil, err
+ }
+
+ if err := json.NewDecoder(exampleFile).Decode(&db); err != nil {
+ return nil, err
+ }
+
+ return &db, nil
+}
+
+func (db *memDB) GetUsers() ([]User, error) {
+ users := make([]User, 0, len(db.Users))
+ for _, u := range db.Users {
+ users = append(users, u)
+ }
+
+ return users, nil
+}
+
+func (db *memDB) GetUser(username string) (User, error) {
+ user, ok := db.Users[username]
+ if !ok {
+ return User{}, fmt.Errorf(`no user with username %q`, username)
+ }
+
+ return user, nil
+}
+
+func (db *memDB) CreateUser(user User) error {
+ if _, ok := db.Users[user.Username]; ok {
+ return fmt.Errorf(`user with username %q already exists`, user.Username)
+ }
+
+ db.Users[user.Username] = user
+ return nil
+}
+
+type Auth interface {
+ Register(username, password string) error
+ Login(username, password string) (string, error)
+ UserForSession(token string) (string, error)
+ GetUser(username string) (User, error)
+}
+
+type memAuth struct {
+ db Database
+
+ sessions map[string]string
+}
+
+func NewInMemoryAuth(db Database) Auth {
+ return &memAuth{db, map[string]string{}}
+}
+
+func (auth *memAuth) Register(username, password string) error {
+ passwordBCrypt, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
+ if err != nil {
+ return err
+ }
+
+ return auth.db.CreateUser(User{
+ Username: username,
+ PasswordBCrypt: passwordBCrypt,
+ })
+}
+
+func (auth *memAuth) Login(username, password string) (string, error) {
+ user, err := auth.db.GetUser(username)
+ if err != nil {
+ return "", err
+ }
+
+ if err := bcrypt.CompareHashAndPassword(user.PasswordBCrypt, []byte(password)); err != nil {
+ return "", err
+ }
+
+ token := GenerateRandomString(16)
+ auth.sessions[token] = username
+
+ return token, nil
+}
+
+func (auth *memAuth) UserForSession(token string) (string, error) {
+ username, ok := auth.sessions[token]
+ if !ok {
+ return "", fmt.Errorf(`invalid session token`)
+ }
+
+ return username, nil
+}
+
+func (auth *memAuth) GetUser(username string) (User, error) {
+ return auth.db.GetUser(username)
+}
diff --git a/frontend/crea-partita.html b/frontend/crea-partita.html
new file mode 100644
index 0000000..d5b76f3
--- /dev/null
+++ b/frontend/crea-partita.html
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+ Login • Lupus Lite
+
+
+ Crea Partita | Lupus Lite
+
+
\ No newline at end of file
diff --git a/frontend/index.html b/frontend/index.html
index 122a604..5645ed9 100644
--- a/frontend/index.html
+++ b/frontend/index.html
@@ -8,7 +8,7 @@
-
+
@@ -16,9 +16,15 @@
Lupus Lite
- Lorem ipsum dolor sit amet consectetur adipisicing elit. Labore qui quibusdam placeat officiis necessitatibus. Unde quis eos quo. Laborum, quis.
+
+ Ottieni un link di accesso ad un partita oppure accedi e creane una nuova.
+
- Login
+