diff --git a/cmd/backend/users.go b/cmd/backend/users.go index 741ee99..0677334 100644 --- a/cmd/backend/users.go +++ b/cmd/backend/users.go @@ -143,12 +143,17 @@ func (db *DB) AddUser(c *Config, u *User, pass string) (int64, error) { return 0, fmt.Errorf("error encrypting last name: %v", err) } + aesEmail, err := aesEncrypt(c, u.Email) + if err != nil { + return 0, fmt.Errorf("error encrypting email: %v", err) + } + query := ` - INSERT INTO users (username, password, first_name, last_name, role) - VALUES (?, ?, ?, ?, ?) + INSERT INTO users (username, password, first_name, last_name, email, role) + VALUES (?, ?, ?, ?, ?, ?) ` - result, err := db.Exec(query, u.UserName, string(hashedPass), aesFirstName, aesLastName, u.Role) + result, err := db.Exec(query, u.UserName, string(hashedPass), aesFirstName, aesLastName, aesEmail, u.Role) if err != nil { return 0, fmt.Errorf("error inserting new user %v into DB: %v", u.UserName, err) } @@ -243,18 +248,18 @@ func (tx *Tx) ChangePassword(id int64, oldPass, newPass string) error { // TODO: No need for ID field in general func (db *DB) GetUser(c *Config, id int64) (*User, error) { - var aesFirstName, aesLastName string + var aesFirstName, aesLastName, aesEmail string var err error user := new(User) query := ` - SELECT id, username, first_name, last_name, role + SELECT id, username, first_name, last_name, email, role FROM users WHERE id = ? ` row := db.QueryRow(query, id) - if err := row.Scan(&user.ID, &user.UserName, &aesFirstName, &aesLastName, &user.Role); err != nil { + if err := row.Scan(&user.ID, &user.UserName, &aesFirstName, &aesLastName, &aesEmail, &user.Role); err != nil { return nil, fmt.Errorf("error reading user information: %v", err) } @@ -268,20 +273,18 @@ func (db *DB) GetUser(c *Config, id int64) (*User, error) { return nil, fmt.Errorf("error decrypting last name: %v", err) } + user.Email, err = aesDecrypt(c, aesEmail) + if err != nil { + return nil, fmt.Errorf("error decrypting email: %v", err) + } + return user, nil } -func (db *DB) UpdateOwnUserAttributes(c *Config, id int64, userName, firstName, lastName, oldPass, newPass, newPass2 string) error { - passwordEmpty := true - if len(newPass) > 0 || len(newPass2) > 0 { - if newPass != newPass2 { - return fmt.Errorf("error: passwords do not match") - } - passwordEmpty = false - } - - tx := new(Tx) +func (db *DB) UpdateOwnUserAttributes(c *Config, id int64, userName, firstName, lastName, email, oldPass, newPass string) error { var err error + tx := new(Tx) + passwordEmpty := len(newPass) > 0 for i := 0; i < TxMaxRetries; i++ { err := func() error { @@ -315,10 +318,19 @@ func (db *DB) UpdateOwnUserAttributes(c *Config, id int64, userName, firstName, return fmt.Errorf("error encrypting last name: %v", err) } + aesEmail, err := aesEncrypt(c, email) + if err != nil { + if rollbackErr := tx.Rollback(); rollbackErr != nil { + log.Fatalf("transaction error: %v, rollback error: %v", err, rollbackErr) + } + return fmt.Errorf("error encrypting email: %v", err) + } + if err = tx.UpdateAttributes( &Attribute{Table: "users", ID: id, AttName: "username", Value: userName}, &Attribute{Table: "users", ID: id, AttName: "first_name", Value: aesFirstName}, &Attribute{Table: "users", ID: id, AttName: "last_name", Value: aesLastName}, + &Attribute{Table: "users", ID: id, AttName: "email", Value: aesEmail}, ); err != nil { if rollbackErr := tx.Rollback(); rollbackErr != nil { log.Fatalf("transaction error: %v, rollback error: %v", err, rollbackErr) @@ -348,8 +360,8 @@ func (db *DB) AddFirstUser(c *Config, u *User, pass string) (int64, error) { txOptions := &sql.TxOptions{Isolation: sql.LevelSerializable} selectQuery := "SELECT COUNT(*) FROM users" insertQuery := ` - INSERT INTO users (username, password, first_name, last_name, role) - VALUES (?, ?, ?, ?, ?) + INSERT INTO users (username, password, first_name, last_name, email, role) + VALUES (?, ?, ?, ?, ?, ?) ` for i := 0; i < TxMaxRetries; i++ { @@ -396,7 +408,15 @@ func (db *DB) AddFirstUser(c *Config, u *User, pass string) (int64, error) { return 0, fmt.Errorf("error encrypting last name: %v", err) } - result, err := tx.Exec(insertQuery, u.UserName, string(hashedPass), aesFirstName, aesLastName, u.Role) + aesEmail, err := aesEncrypt(c, u.Email) + if err != nil { + if rollbackErr := tx.Rollback(); rollbackErr != nil { + log.Fatalf("transaction error: %v, rollback error: %v", err, rollbackErr) + } + return 0, fmt.Errorf("error encrypting email: %v", err) + } + + result, err := tx.Exec(insertQuery, u.UserName, string(hashedPass), aesFirstName, aesLastName, aesEmail, u.Role) if err != nil { if rollbackErr := tx.Rollback(); rollbackErr != nil { log.Fatalf("transaction error: %v, rollback error: %v", err, rollbackErr) @@ -428,10 +448,10 @@ func (db *DB) AddFirstUser(c *Config, u *User, pass string) (int64, error) { } func (db *DB) GetAllUsers(c *Config) (map[int64]*User, error) { - var aesFirstName, aesLastName string + var aesFirstName, aesLastName, aesEmail string var err error - query := "SELECT id, username, first_name, last_name, role FROM users" + query := "SELECT id, username, first_name, last_name, email, role FROM users" rows, err := db.Query(query) if err != nil { @@ -441,7 +461,7 @@ func (db *DB) GetAllUsers(c *Config) (map[int64]*User, error) { users := make(map[int64]*User, 0) for rows.Next() { user := new(User) - if err = rows.Scan(&user.ID, &user.UserName, &aesFirstName, &aesLastName, &user.Role); err != nil { + if err = rows.Scan(&user.ID, &user.UserName, &aesFirstName, &aesLastName, &aesEmail, &user.Role); err != nil { return nil, fmt.Errorf("error getting user info: %v", err) } @@ -455,6 +475,11 @@ func (db *DB) GetAllUsers(c *Config) (map[int64]*User, error) { return nil, fmt.Errorf("error decrypting last name: %v", err) } + user.Email, err = aesDecrypt(c, aesEmail) + if err != nil { + return nil, fmt.Errorf("error decrypting email: %v", err) + } + users[user.ID] = user } @@ -481,17 +506,10 @@ func (tx *Tx) SetPassword(id int64, newPass string) error { return nil } -func (db *DB) UpdateUserAttributes(c *Config, id int64, userName, firstName, lastName, newPass, newPass2 string, role int) error { - passwordEmpty := true - if len(newPass) > 0 || len(newPass2) > 0 { - if newPass != newPass2 { - return fmt.Errorf("error: passwords do not match") - } - passwordEmpty = false - } - - tx := new(Tx) +func (db *DB) UpdateUserAttributes(c *Config, id int64, userName, firstName, lastName, email, newPass string, role int) error { var err error + tx := new(Tx) + passwordEmpty := len(newPass) > 0 for i := 0; i < TxMaxRetries; i++ { err := func() error { @@ -525,10 +543,19 @@ func (db *DB) UpdateUserAttributes(c *Config, id int64, userName, firstName, las return fmt.Errorf("error encrypting last name: %v", err) } + aesEmail, err := aesEncrypt(c, email) + if err != nil { + if rollbackErr := tx.Rollback(); rollbackErr != nil { + log.Fatalf("transaction error: %v, rollback error: %v", err, rollbackErr) + } + return fmt.Errorf("error encrypting email: %v", err) + } + if err = tx.UpdateAttributes( &Attribute{Table: "users", ID: id, AttName: "username", Value: userName}, &Attribute{Table: "users", ID: id, AttName: "first_name", Value: aesFirstName}, &Attribute{Table: "users", ID: id, AttName: "last_name", Value: aesLastName}, + &Attribute{Table: "users", ID: id, AttName: "email", Value: aesEmail}, &Attribute{Table: "users", ID: id, AttName: "role", Value: role}, ); err != nil { if rollbackErr := tx.Rollback(); rollbackErr != nil { diff --git a/cmd/frontend/users.go b/cmd/frontend/users.go index a2aa4d7..46df586 100644 --- a/cmd/frontend/users.go +++ b/cmd/frontend/users.go @@ -11,8 +11,8 @@ import ( ) func checkUserStrings(user *b.User) (string, int, bool) { - userLen := 15 - nameLen := 50 + userLen := 255 + nameLen := 56 // max value when aes encrypting up to 255 bytes if len(user.UserName) > userLen { return "Benutzername", userLen, false @@ -55,12 +55,13 @@ func AddUser(c *b.Config, db *b.DB, s *b.CookieStore) http.HandlerFunc { UserName: r.PostFormValue("username"), FirstName: r.PostFormValue("first-name"), LastName: r.PostFormValue("last-name"), + Email: r.PostFormValue("email"), } pass := r.PostFormValue("password") pass2 := r.PostFormValue("password2") + email2 := r.PostFormValue("email2") - if len(user.UserName) == 0 || len(user.FirstName) == 0 || - len(user.LastName) == 0 || len(pass) == 0 || len(pass2) == 0 { + if len(user.UserName) == 0 || len(user.FirstName) == 0 || len(user.LastName) == 0 || len(user.Email) == 0 || len(email2) == 0 || len(pass) == 0 || len(pass2) == 0 { http.Error(w, "Bitte alle Felder ausfüllen.", http.StatusBadRequest) return } @@ -76,6 +77,11 @@ func AddUser(c *b.Config, db *b.DB, s *b.CookieStore) http.HandlerFunc { return } + if user.Email != email2 { + http.Error(w, "Die Emailadressen stimmen nicht überein.", http.StatusBadRequest) + return + } + if pass != pass2 { http.Error(w, "Die Passwörter stimmen nicht überein.", http.StatusBadRequest) return @@ -153,11 +159,13 @@ func UpdateSelf(c *b.Config, db *b.DB, s *b.CookieStore) http.HandlerFunc { UserName: r.PostFormValue("username"), FirstName: r.PostFormValue("first-name"), LastName: r.PostFormValue("last-name"), + Email: r.PostFormValue("email"), } oldPass := r.PostFormValue("old-password") newPass := r.PostFormValue("password") newPass2 := r.PostFormValue("password2") + email2 := r.PostFormValue("email2") if len(user.UserName) == 0 { http.Error(w, "Bitte den Benutzernamen ausfüllen.", http.StatusBadRequest) @@ -169,6 +177,20 @@ func UpdateSelf(c *b.Config, db *b.DB, s *b.CookieStore) http.HandlerFunc { return } + if len(user.Email) == 0 || len(email2) == 0 { + http.Error(w, "Bitte die Emailadresse ausfüllen.", http.StatusBadRequest) + return + } + if user.Email != email2 { + http.Error(w, "Die Emailadressen stimmen nicht überein", http.StatusBadRequest) + return + } + + if newPass != newPass2 { + http.Error(w, "Die Passwörter stimmen nicht überein", http.StatusBadRequest) + return + } + userString, stringLen, ok := checkUserStrings(user) if !ok { http.Error(w, fmt.Sprint(userString, " ist zu lang. Maximal ", stringLen, " Zeichen erlaubt."), http.StatusBadRequest) @@ -180,7 +202,7 @@ func UpdateSelf(c *b.Config, db *b.DB, s *b.CookieStore) http.HandlerFunc { return } - if err = db.UpdateOwnUserAttributes(c, user.ID, user.UserName, user.FirstName, user.LastName, oldPass, newPass, newPass2); err != nil { + if err = db.UpdateOwnUserAttributes(c, user.ID, user.UserName, user.FirstName, user.LastName, user.Email, oldPass, newPass); err != nil { log.Println("error: user:", user.ID, err) http.Error(w, "Benutzerdaten konnten nicht aktualisiert werden.", http.StatusInternalServerError) return @@ -206,13 +228,14 @@ func AddFirstUser(c *b.Config, db *b.DB, s *b.CookieStore) http.HandlerFunc { UserName: r.PostFormValue("username"), FirstName: r.PostFormValue("first-name"), LastName: r.PostFormValue("last-name"), + Email: r.PostFormValue("email"), Role: b.Admin, } pass := r.PostFormValue("password") pass2 := r.PostFormValue("password2") + email2 := r.PostFormValue("email2") - if len(user.UserName) == 0 || len(user.FirstName) == 0 || - len(user.LastName) == 0 || len(pass) == 0 || len(pass2) == 0 { + if len(user.UserName) == 0 || len(user.FirstName) == 0 || len(user.LastName) == 0 || len(user.Email) == 0 || len(email2) == 0 || len(pass) == 0 || len(pass2) == 0 { http.Error(w, "Bitte alle Felder ausfüllen.", http.StatusBadRequest) return } @@ -223,6 +246,11 @@ func AddFirstUser(c *b.Config, db *b.DB, s *b.CookieStore) http.HandlerFunc { return } + if user.Email != email2 { + http.Error(w, "Die Emailadressen stimmen nicht überein.", http.StatusBadRequest) + return + } + if pass != pass2 { http.Error(w, "Die Passwörter stimmen nicht überein.", http.StatusBadRequest) return @@ -352,19 +380,34 @@ func UpdateUser(c *b.Config, db *b.DB, s *b.CookieStore) http.HandlerFunc { user.UserName = r.PostFormValue("username") if len(user.UserName) == 0 { - http.Error(w, "Bitte den Benutzernamen ausfüllen.", http.StatusInternalServerError) + http.Error(w, "Bitte den Benutzernamen ausfüllen.", http.StatusBadRequest) return } user.FirstName = r.PostFormValue("first-name") user.LastName = r.PostFormValue("last-name") if len(user.FirstName) == 0 || len(user.LastName) == 0 { - http.Error(w, "Bitte den vollständigen Namen ausfüllen.", http.StatusInternalServerError) + http.Error(w, "Bitte den vollständigen Namen ausfüllen.", http.StatusBadRequest) + return + } + + user.Email = r.PostFormValue("email") + email2 := r.PostFormValue("email2") + if len(user.Email) == 0 || len(email2) == 0 { + http.Error(w, "Bitte die Emailadresse ausfüllen.", http.StatusBadRequest) + return + } + if user.Email != email2 { + http.Error(w, "Die Emailadressen stimmen nicht überein.", http.StatusBadRequest) return } newPass := r.PostFormValue("password") newPass2 := r.PostFormValue("password2") + if newPass != newPass2 { + http.Error(w, "Die Passwörter stimmen nicht überein.", http.StatusBadRequest) + return + } userString, stringLen, ok := checkUserStrings(user) if !ok { @@ -377,7 +420,7 @@ func UpdateUser(c *b.Config, db *b.DB, s *b.CookieStore) http.HandlerFunc { return } - if err = db.UpdateUserAttributes(c, user.ID, user.UserName, user.FirstName, user.LastName, newPass, newPass2, user.Role); err != nil { + if err = db.UpdateUserAttributes(c, user.ID, user.UserName, user.FirstName, user.LastName, user.Email, newPass, user.Role); err != nil { log.Println("error: user:", user.ID, err) http.Error(w, "Benutzerdaten konnten nicht aktualisiert werden.", http.StatusInternalServerError) return diff --git a/create_db.sql b/create_db.sql index 0fd917e..44df846 100644 --- a/create_db.sql +++ b/create_db.sql @@ -6,11 +6,11 @@ DROP TABLE IF EXISTS users; CREATE TABLE users ( id INT AUTO_INCREMENT, - username VARCHAR(15) NOT NULL UNIQUE, + username VARCHAR(255) NOT NULL UNIQUE, password VARCHAR(60) NOT NULL, first_name VARCHAR(255) NOT NULL, last_name VARCHAR(255) NOT NULL, - -- email VARCHAR(255) NOT NULL, + email VARCHAR(255) NOT NULL, -- profile_pic_link VARCHAR(255) NOT NULL, role INT NOT NULL, PRIMARY KEY (id) diff --git a/web/templates/add-user.html b/web/templates/add-user.html index 1c5847d..013b8eb 100644 --- a/web/templates/add-user.html +++ b/web/templates/add-user.html @@ -7,22 +7,36 @@ +
+
+
+
+ +
+ + +
+ +
+ + +
diff --git a/web/templates/edit-self.html b/web/templates/edit-self.html index 334da84..c5de034 100644 --- a/web/templates/edit-self.html +++ b/web/templates/edit-self.html @@ -32,6 +32,16 @@
+ +
+ + +
+ +
+ + +
diff --git a/web/templates/edit-user.html b/web/templates/edit-user.html index 335f7eb..6725f2a 100644 --- a/web/templates/edit-user.html +++ b/web/templates/edit-user.html @@ -27,6 +27,16 @@
+ +
+ + +
+ +
+ + +
diff --git a/web/templates/first-user.html b/web/templates/first-user.html index 4fb84f2..7019acc 100644 --- a/web/templates/first-user.html +++ b/web/templates/first-user.html @@ -5,23 +5,37 @@
- +
+
+
+
- +
+
- + +
+ +
+ + +
+ +
+ +