Skip to content

Commit

Permalink
Removed email from user, made username primary identifier
Browse files Browse the repository at this point in the history
  • Loading branch information
Forceu committed Dec 31, 2024
1 parent 2919e59 commit 14b2186
Show file tree
Hide file tree
Showing 13 changed files with 62 additions and 139 deletions.
9 changes: 3 additions & 6 deletions internal/configuration/Configuration.go
Original file line number Diff line number Diff line change
Expand Up @@ -115,13 +115,12 @@ func MigrateToV2(authPassword string) {

newAdmin := models.User{
Name: adminName,
Email: adminName,
Permissions: models.UserPermissionAll,
UserLevel: models.UserLevelSuperAdmin,
Password: authPassword,
}
database.SaveUser(newAdmin, true)
user, ok := database.GetUserByEmail(adminName)
user, ok := database.GetUserByName(adminName)
if !ok {
fmt.Println("ERROR: Could not retrieve new admin user after saving")
os.Exit(1)
Expand Down Expand Up @@ -194,7 +193,7 @@ func LoadFromSetup(config models.Configuration, cloudConfig *cloudconfig.CloudCo
save()
Load()
ConnectDatabase()
err := database.EditSuperAdmin(serverSettings.Authentication.Username, serverSettings.Authentication.Username, passwordHash)
err := database.EditSuperAdmin(serverSettings.Authentication.Username, passwordHash)
if err != nil {
fmt.Println("Could not edit superadmin, as none was found, but other users were present.")
os.Exit(1)
Expand Down Expand Up @@ -228,9 +227,7 @@ func SetDeploymentPassword(newPassword string) {
os.Exit(1)
}
serverSettings.Authentication.SaltAdmin = helper.GenerateRandomString(30)
err := database.EditSuperAdmin(serverSettings.Authentication.Username,
serverSettings.Authentication.Username,
hashUserPassword(newPassword))
err := database.EditSuperAdmin(serverSettings.Authentication.Username, hashUserPassword(newPassword))
if err != nil {
fmt.Println("No super-admin user found, but database contains other users. Aborting.")
os.Exit(1)
Expand Down
24 changes: 10 additions & 14 deletions internal/configuration/database/Database.go
Original file line number Diff line number Diff line change
Expand Up @@ -253,18 +253,18 @@ func GetUser(id int) (models.User, bool) {
return db.GetUser(id)
}

// GetUserByEmail returns a models.User if valid or false if the email is not valid
func GetUserByEmail(email string) (models.User, bool) {
email = strings.ToLower(email)
return db.GetUserByEmail(email)
// GetUserByName returns a models.User if valid or false if the email is not valid
func GetUserByName(username string) (models.User, bool) {
username = strings.ToLower(username)
return db.GetUserByName(username)
}

// SaveUser saves a user to the database. If isNewUser is true, a new Id will be generated
func SaveUser(user models.User, isNewUser bool) {
if user.Email == "" {
panic("email cannot be empty")
if user.Name == "" {
panic("username cannot be empty")
}
user.Email = strings.ToLower(user.Email)
user.Name = strings.ToLower(user.Name)
db.SaveUser(user, isNewUser)
}

Expand All @@ -291,27 +291,23 @@ func GetSuperAdmin() (models.User, bool) {

// EditSuperAdmin changes parameters of the super admin. If no user exists, a new superadmin will be created
// Returns an error if at least one user exists, but no superadmin
func EditSuperAdmin(name, email, password string) error {
func EditSuperAdmin(email, password string) error {
user, ok := GetSuperAdmin()
if !ok {
if len(GetAllUsers()) != 0 {
return errors.New("at least one user exists, but no superadmin found")
}
newAdmin := models.User{
Name: name,
Email: email,
Name: email,
Permissions: models.UserPermissionAll,
UserLevel: models.UserLevelSuperAdmin,
Password: password,
}
db.SaveUser(newAdmin, true)
return nil
}
if name != "" {
user.Name = name
}
if email != "" {
user.Email = email
user.Name = email
}
if password != "" {
user.Password = password
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ type Database interface {
// GetUser returns a models.User if valid or false if the ID is not valid
GetUser(id int) (models.User, bool)
// GetUserByEmail returns a models.User if valid or false if the email is not valid
GetUserByEmail(email string) (models.User, bool)
GetUserByName(email string) (models.User, bool)
// SaveUser saves a user to the database. If isNewUser is true, a new Id will be generated
SaveUser(user models.User, isNewUser bool)
// UpdateUserLastOnline writes the last online time to the database
Expand Down
8 changes: 4 additions & 4 deletions internal/configuration/database/provider/redis/users.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,17 +41,17 @@ func orderUsers(users []models.User) []models.User {
return cmp.Or(
cmp.Compare(a.UserLevel, b.UserLevel),
cmp.Compare(b.LastOnline, a.LastOnline),
cmp.Compare(a.Email, b.Email),
cmp.Compare(a.Name, b.Name),
)
})
return users
}

// GetUserByEmail returns a models.User if valid or false if the email is not valid
func (p DatabaseProvider) GetUserByEmail(email string) (models.User, bool) {
// GetUserByName returns a models.User if valid or false if the email is not valid
func (p DatabaseProvider) GetUserByName(username string) (models.User, bool) {
users := p.GetAllUsers()
for _, user := range users {
if user.Email == email {
if user.Name == username {
return user, true
}
}
Expand Down
6 changes: 2 additions & 4 deletions internal/configuration/database/provider/sqlite/Sqlite.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,8 @@ func (p DatabaseProvider) Upgrade(currentDbVersion int) {
) WITHOUT ROWID;
CREATE TABLE "Users" (
"Id" INTEGER NOT NULL UNIQUE,
"Email" TEXT NOT NULL UNIQUE,
"Name" TEXT NOT NULL UNIQUE,
"Password" TEXT,
"Name" TEXT NOT NULL,
"Permissions" INTEGER NOT NULL,
"Userlevel" INTEGER NOT NULL,
"LastOnline" INTEGER NOT NULL DEFAULT 0,
Expand Down Expand Up @@ -189,9 +188,8 @@ func (p DatabaseProvider) createNewDatabase() error {
) WITHOUT ROWID;
CREATE TABLE "Users" (
"Id" INTEGER NOT NULL UNIQUE,
"Email" TEXT NOT NULL UNIQUE,
"Name" TEXT NOT NULL UNIQUE,
"Password" TEXT,
"Name" TEXT NOT NULL,
"Permissions" INTEGER NOT NULL,
"Userlevel" INTEGER NOT NULL,
"LastOnline" INTEGER NOT NULL DEFAULT 0,
Expand Down
22 changes: 11 additions & 11 deletions internal/configuration/database/provider/sqlite/users.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,12 @@ import (
func (p DatabaseProvider) GetAllUsers() []models.User {
var password sql.NullString
var result []models.User
rows, err := p.sqliteDb.Query("SELECT * FROM Users ORDER BY Userlevel ASC, LastOnline DESC, Email ASC")
rows, err := p.sqliteDb.Query("SELECT * FROM Users ORDER BY Userlevel ASC, LastOnline DESC, Name ASC")
helper.Check(err)
defer rows.Close()
for rows.Next() {
user := models.User{}
err = rows.Scan(&user.Id, &user.Email, &password, &user.Name, &user.Permissions, &user.UserLevel, &user.LastOnline)
err = rows.Scan(&user.Id, &user.Name, &password, &user.Permissions, &user.UserLevel, &user.LastOnline)
helper.Check(err)
if password.Valid {
user.Password = password.String
Expand All @@ -32,7 +32,7 @@ func (p DatabaseProvider) GetUser(id int) (models.User, bool) {
var result models.User
var password sql.NullString
row := p.sqliteDb.QueryRow("SELECT * FROM Users WHERE Id = ?", id)
err := row.Scan(&result.Id, &result.Email, &password, &result.Name, &result.Permissions, &result.UserLevel, &result.LastOnline)
err := row.Scan(&result.Id, &result.Name, &password, &result.Permissions, &result.UserLevel, &result.LastOnline)
if err != nil {
if errors.Is(err, sql.ErrNoRows) {
return models.User{}, false
Expand All @@ -46,12 +46,12 @@ func (p DatabaseProvider) GetUser(id int) (models.User, bool) {
return result, true
}

// GetUserByEmail returns a models.User if valid or false if the email is not valid
func (p DatabaseProvider) GetUserByEmail(email string) (models.User, bool) {
// GetUserByName returns a models.User if valid or false if the name is not valid
func (p DatabaseProvider) GetUserByName(username string) (models.User, bool) {
var result models.User
var password sql.NullString
row := p.sqliteDb.QueryRow("SELECT * FROM Users WHERE email = ?", email)
err := row.Scan(&result.Id, &result.Email, &password, &result.Name, &result.Permissions, &result.UserLevel, &result.LastOnline)
row := p.sqliteDb.QueryRow("SELECT * FROM Users WHERE Name = ?", username)
err := row.Scan(&result.Id, &result.Name, &password, &result.Permissions, &result.UserLevel, &result.LastOnline)
if err != nil {
if errors.Is(err, sql.ErrNoRows) {
return models.User{}, false
Expand All @@ -68,12 +68,12 @@ func (p DatabaseProvider) GetUserByEmail(email string) (models.User, bool) {
// SaveUser saves a user to the database. If isNewUser is true, a new Id will be generated
func (p DatabaseProvider) SaveUser(user models.User, isNewUser bool) {
if isNewUser {
_, err := p.sqliteDb.Exec("INSERT INTO Users ( Name, Email, Password, Permissions, Userlevel, LastOnline) VALUES (?, ?, ?, ?, ?, ?)",
user.Name, user.Email, user.Password, user.Permissions, user.UserLevel, user.LastOnline)
_, err := p.sqliteDb.Exec("INSERT INTO Users ( Name, Password, Permissions, Userlevel, LastOnline) VALUES (?, ?, ?, ?, ?)",
user.Name, user.Password, user.Permissions, user.UserLevel, user.LastOnline)
helper.Check(err)
} else {
_, err := p.sqliteDb.Exec("INSERT OR REPLACE INTO Users (Id, Name, Email, Password, Permissions, Userlevel, LastOnline) VALUES (?, ?, ?, ?, ?, ?, ?)",
user.Id, user.Name, user.Email, user.Password, user.Permissions, user.UserLevel, user.LastOnline)
_, err := p.sqliteDb.Exec("INSERT OR REPLACE INTO Users (Id, Name, Password, Permissions, Userlevel, LastOnline) VALUES (?, ?, ?, ?, ?, ?)",
user.Id, user.Name, user.Password, user.Permissions, user.UserLevel, user.LastOnline)
helper.Check(err)
}
}
Expand Down
1 change: 0 additions & 1 deletion internal/models/User.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import (
type User struct {
Id int `json:"id" redis:"id"`
Name string `json:"name" redis:"Name"`
Email string `json:"email" redis:"Email"`
Permissions uint16 `json:"permissions" redis:"Permissions"`
UserLevel uint8 `json:"userLevel" redis:"UserLevel"`
LastOnline int64 `json:"lastOnline" redis:"LastOnline"`
Expand Down
16 changes: 4 additions & 12 deletions internal/webserver/api/Api.go
Original file line number Diff line number Diff line change
Expand Up @@ -340,27 +340,21 @@ func createApiKey(w http.ResponseWriter, request apiRequest, user models.User) {

func addUser(w http.ResponseWriter, request apiRequest) {
name := request.usermodInfo.newUserName
email := request.usermodInfo.newUserEmail
if len(name) < 2 {
sendError(w, http.StatusBadRequest, "Invalid user name provided.")
if len(name) < 4 {
sendError(w, http.StatusBadRequest, "Invalid username provided.")
return
}
if len(email) < 4 || !strings.Contains(email, "@") {
sendError(w, http.StatusBadRequest, "Invalid email provided.")
return
}
_, ok := database.GetUserByEmail(email)
_, ok := database.GetUserByName(name)
if ok {
sendError(w, http.StatusConflict, "User already exists.")
return
}
newUser := models.User{
Name: name,
Email: email,
UserLevel: models.UserLevelUser,
}
database.SaveUser(newUser, true)
user, ok := database.GetUserByEmail(email)
user, ok := database.GetUserByName(name)
if !ok {
sendError(w, http.StatusInternalServerError, "Could not save user")
return
Expand Down Expand Up @@ -776,7 +770,6 @@ type userModInfo struct {
deleteUserFiles bool
newRank string
newUserName string
newUserEmail string
}
type fileModInfo struct {
id string
Expand Down Expand Up @@ -864,7 +857,6 @@ func parseRequest(r *http.Request) (apiRequest, error) {
basicPermissions: r.Header.Get("basicPermissions") == "true",
deleteUserFiles: r.Header.Get("deleteFiles") == "true",
newUserName: r.Header.Get("username"),
newUserEmail: r.Header.Get("email"),
},
}, nil
}
Expand Down
17 changes: 8 additions & 9 deletions internal/webserver/authentication/Authentication.go
Original file line number Diff line number Diff line change
Expand Up @@ -111,11 +111,11 @@ func isGrantedHeader(r *http.Request) (int, bool) {
return -1, false
}
if len(authSettings.HeaderUsers) == 0 {
user := getOrCreateUser(userName, userName)
user := getOrCreateUser(userName)
return user.Id, true
}
if isUserInArray(userName, authSettings.HeaderUsers) {
user := getOrCreateUser(userName, userName)
user := getOrCreateUser(userName)
return user.Id, true
}
return -1, false
Expand Down Expand Up @@ -264,7 +264,7 @@ func CheckOauthUserAndRedirect(userInfo OAuthUserInfo, w http.ResponseWriter) er
if userInfo.Email == "" {
userInfo.Email = username
}
user := getOrCreateUser(username, userInfo.Email)
user := getOrCreateUser(userInfo.Email)
sessionmanager.CreateSession(w, true, authSettings.OAuthRecheckInterval, user.Id)
redirect(w, "admin")
return nil
Expand All @@ -273,16 +273,15 @@ func CheckOauthUserAndRedirect(userInfo OAuthUserInfo, w http.ResponseWriter) er
return nil
}

func getOrCreateUser(username, email string) models.User {
user, ok := database.GetUserByEmail(email)
func getOrCreateUser(username string) models.User {
user, ok := database.GetUserByName(username)
if !ok {
user = models.User{
Name: username,
Email: username,
UserLevel: models.UserLevelUser,
}
database.SaveUser(user, true)
user, ok = database.GetUserByEmail(email)
user, ok = database.GetUserByName(username)
if !ok {
panic("unable to read new user")
}
Expand Down Expand Up @@ -311,8 +310,8 @@ func isGrantedSession(w http.ResponseWriter, r *http.Request) (int, bool) {
}

// IsCorrectUsernameAndPassword checks if a provided username and password is correct
func IsCorrectUsernameAndPassword(userEmail, password string) (models.User, bool) {
user, ok := database.GetUserByEmail(userEmail)
func IsCorrectUsernameAndPassword(username, password string) (models.User, bool) {
user, ok := database.GetUserByName(username)
if !ok {
return models.User{}, false
}
Expand Down
5 changes: 2 additions & 3 deletions internal/webserver/web/static/js/admin_api.js
Original file line number Diff line number Diff line change
Expand Up @@ -221,16 +221,15 @@ async function apiFilesDelete(id) {
// users


async function apiUserCreate(userName, userEmail) {
async function apiUserCreate(userName) {
const apiUrl = './api/user/create';

const requestOptions = {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'apikey': systemKey,
'username': userName,
'email': userEmail
'username': userName

},
};
Expand Down
Loading

0 comments on commit 14b2186

Please sign in to comment.