Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

🐛 Ensure Email and Password are set #348

Merged
merged 1 commit into from
Jan 20, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 11 additions & 9 deletions internal/legacy/migration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,18 +75,20 @@ func (s *MigrationTestSuite) SetupTest() {
}

s.adminUser = User{
ID: 1,
Email: "[email protected]",
CreationDate: time.Now(),
IsSuperAdmin: true,
ID: 1,
Email: "[email protected]",
EncryptedPassword: "notempty",
CreationDate: time.Now(),
IsSuperAdmin: true,
}

s.user = User{
ID: 2,
Email: "[email protected]",
CreationDate: time.Now(),
IsSuperAdmin: false,
Tickers: []int{161},
ID: 2,
Email: "[email protected]",
EncryptedPassword: "notempty",
CreationDate: time.Now(),
IsSuperAdmin: false,
Tickers: []int{161},
}

s.upload = Upload{
Expand Down
113 changes: 84 additions & 29 deletions internal/storage/sql_storage_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@ func (s *SqlStorageTestSuite) BeforeTest(suiteName, testName string) {
}

func (s *SqlStorageTestSuite) TestFindUsers() {
user, err := NewUser("[email protected]", "password")
s.NoError(err)

s.Run("when no users exist", func() {
filter := NewUserFilter(nil)
users, err := s.store.FindUsers(filter)
Expand All @@ -62,7 +65,8 @@ func (s *SqlStorageTestSuite) TestFindUsers() {
})

s.Run("when users exist", func() {
err := s.db.Create(&User{Email: "[email protected]", IsSuperAdmin: false, Tickers: []Ticker{{ID: 1}}}).Error
user.Tickers = []Ticker{{ID: 1}}
err := s.db.Create(&user).Error
s.NoError(err)

s.Run("without preload", func() {
Expand Down Expand Up @@ -106,24 +110,28 @@ func (s *SqlStorageTestSuite) TestFindUsers() {
}

func (s *SqlStorageTestSuite) TestFindUserByID() {
user, err := NewUser("[email protected]", "password")
s.NoError(err)

s.Run("when user does not exist", func() {
_, err := s.store.FindUserByID(1)
s.Error(err)
})

s.Run("when user exists", func() {
err := s.db.Create(&User{ID: 1, Tickers: []Ticker{{ID: 1}}}).Error
user.Tickers = []Ticker{{ID: 1}}
err := s.db.Create(&user).Error
s.NoError(err)

s.Run("without preload", func() {
user, err := s.store.FindUserByID(1)
user, err := s.store.FindUserByID(user.ID)
s.NoError(err)
s.NotNil(user)
s.Empty(user.Tickers)
})

s.Run("with preload", func() {
user, err := s.store.FindUserByID(1, WithTickers())
user, err := s.store.FindUserByID(user.ID, WithTickers())
s.NoError(err)
s.NotNil(user)
s.Len(user.Tickers, 1)
Expand All @@ -132,25 +140,29 @@ func (s *SqlStorageTestSuite) TestFindUserByID() {
}

func (s *SqlStorageTestSuite) TestFindUsersByIDs() {
user, err := NewUser("[email protected]", "password")
s.NoError(err)

s.Run("when no users exist", func() {
users, err := s.store.FindUsersByIDs([]int{1, 2})
s.NoError(err)
s.Empty(users)
})

s.Run("when users exist", func() {
err := s.db.Create(&User{ID: 1, Tickers: []Ticker{{ID: 1}}}).Error
user.Tickers = []Ticker{{ID: 1}}
err := s.db.Create(&user).Error
s.NoError(err)

s.Run("without preload", func() {
users, err := s.store.FindUsersByIDs([]int{1})
users, err := s.store.FindUsersByIDs([]int{user.ID})
s.NoError(err)
s.Len(users, 1)
s.Empty(users[0].Tickers)
})

s.Run("with preload", func() {
users, err := s.store.FindUsersByIDs([]int{1}, WithTickers())
users, err := s.store.FindUsersByIDs([]int{user.ID}, WithTickers())
s.NoError(err)
s.Len(users, 1)
s.Len(users[0].Tickers, 1)
Expand All @@ -159,24 +171,29 @@ func (s *SqlStorageTestSuite) TestFindUsersByIDs() {
}

func (s *SqlStorageTestSuite) TestFindUserByEmail() {
user, err := NewUser("[email protected]", "password")
s.NoError(err)

s.Run("when user does not exist", func() {
_, err := s.store.FindUserByEmail("user@systemli.org")
_, err := s.store.FindUserByEmail("user@example.org")
s.Error(err)
})

s.Run("when user exists", func() {
err := s.db.Create(&User{Email: "[email protected]", Tickers: []Ticker{{ID: 1}}}).Error
user.Tickers = []Ticker{{ID: 1}}
err := s.db.Create(&user).Error
s.NoError(err)

s.Run("without preload", func() {
user, err := s.store.FindUserByEmail("user@systemli.org")
user, err := s.store.FindUserByEmail("user@example.org")
s.NoError(err)
s.NotNil(user)
s.Empty(user.Tickers)
})

s.Run("with preload", func() {
user, err := s.store.FindUserByEmail("[email protected]", WithTickers())
user.Tickers = []Ticker{{ID: 1}}
user, err := s.store.FindUserByEmail("[email protected]", WithTickers())
s.NoError(err)
s.NotNil(user)
s.Len(user.Tickers, 1)
Expand All @@ -185,14 +202,18 @@ func (s *SqlStorageTestSuite) TestFindUserByEmail() {
}

func (s *SqlStorageTestSuite) TestFindUsersByTicker() {
user, err := NewUser("[email protected]", "password")
s.NoError(err)

s.Run("when no users exist", func() {
users, err := s.store.FindUsersByTicker(Ticker{ID: 1})
s.NoError(err)
s.Empty(users)
})

s.Run("when users exist", func() {
err := s.db.Create(&User{Tickers: []Ticker{{ID: 1}}}).Error
user.Tickers = []Ticker{{ID: 1}}
err := s.db.Create(&user).Error
s.NoError(err)

s.Run("without preload", func() {
Expand All @@ -212,7 +233,7 @@ func (s *SqlStorageTestSuite) TestFindUsersByTicker() {
}

func (s *SqlStorageTestSuite) TestSaveUser() {
user, err := NewUser("user@systemli.org", "password")
user, err := NewUser("user@example.org", "password")
s.NoError(err)

s.Run("when user is new", func() {
Expand All @@ -225,8 +246,21 @@ func (s *SqlStorageTestSuite) TestSaveUser() {
s.Equal(int64(1), count)
})

s.Run("when email is empty", func() {
user.Email = ""
err = s.store.SaveUser(&user)
s.Error(err)
})

s.Run("when encrypted password is empty", func() {
user := User{Email: "[email protected]"}
user.EncryptedPassword = ""
err = s.store.SaveUser(&user)
s.Error(err)
})

s.Run("when user is existing", func() {
user.Email = "update@systemli.org"
user.Email = "update@example.org"

err = s.store.SaveUser(&user)
s.NoError(err)
Expand Down Expand Up @@ -265,8 +299,10 @@ func (s *SqlStorageTestSuite) TestDeleteUser() {
})

s.Run("when user exists", func() {
user := User{ID: 1}
err := s.db.Create(&user).Error
user, err := NewUser("[email protected]", "password")
s.NoError(err)

err = s.db.Create(&user).Error
s.NoError(err)

err = s.store.DeleteUser(user)
Expand Down Expand Up @@ -294,7 +330,9 @@ func (s *SqlStorageTestSuite) TestDeleteTickerUsers() {
count := s.db.Model(&ticker).Association("Users").Count()
s.Equal(int64(0), count)

user := User{ID: 1}
user, err := NewUser("[email protected]", "password")
s.NoError(err)

err = s.db.Create(&user).Error
s.NoError(err)

Expand Down Expand Up @@ -325,7 +363,9 @@ func (s *SqlStorageTestSuite) TestDeleteTickerUser() {
err := s.db.Create(&ticker).Error
s.NoError(err)

user := User{ID: 1}
user, err := NewUser("[email protected]", "password")
s.NoError(err)

err = s.db.Create(&user).Error
s.NoError(err)

Expand All @@ -348,7 +388,9 @@ func (s *SqlStorageTestSuite) TestAddTickerUser() {
err := s.db.Create(&ticker).Error
s.NoError(err)

user := User{Email: "[email protected]"}
user, err := NewUser("[email protected]", "password")
s.NoError(err)

err = s.db.Create(&user).Error
s.NoError(err)

Expand All @@ -375,7 +417,9 @@ func (s *SqlStorageTestSuite) TestFindTickerByID() {
})

s.Run("when ticker exists with users", func() {
user := User{Email: "[email protected]"}
user, err := NewUser("[email protected]", "password")
s.NoError(err)

err = s.db.Create(&user).Error
s.NoError(err)

Expand Down Expand Up @@ -405,8 +449,11 @@ func (s *SqlStorageTestSuite) TestFindTickersByIDs() {
})

s.Run("when tickers exist with users", func() {
user := User{Email: "[email protected]"}
user, err := NewUser("[email protected]", "password")
s.NoError(err)

err = s.db.Create(&user).Error
s.NoError(err)

err = s.db.Model(&Ticker{ID: 1}).Association("Users").Append(&user)
s.NoError(err)
Expand Down Expand Up @@ -457,8 +504,10 @@ func (s *SqlStorageTestSuite) TestFindTickersByUser() {
s.Empty(tickers)
})

user := User{Email: "[email protected]"}
err := s.db.Create(&user).Error
user, err := NewUser("[email protected]", "password")
s.NoError(err)

err = s.db.Create(&user).Error
s.NoError(err)

ticker := Ticker{Users: []User{user}, Active: false, Domain: "localhost", Title: "title"}
Expand Down Expand Up @@ -521,8 +570,10 @@ func (s *SqlStorageTestSuite) TestFindTickersByUser() {
}

func (s *SqlStorageTestSuite) TestFindTickerByUserAndID() {
user := User{Email: "[email protected]"}
err := s.db.Create(&user).Error
user, err := NewUser("[email protected]", "password")
s.NoError(err)

err = s.db.Create(&user).Error
s.NoError(err)

ticker := Ticker{Users: []User{user}}
Expand Down Expand Up @@ -619,8 +670,10 @@ func (s *SqlStorageTestSuite) TestSaveTicker() {
})

s.Run("when ticker is existing with users", func() {
user := User{Email: "[email protected]"}
err := s.db.Create(&user).Error
user, err := NewUser("[email protected]", "password")
s.NoError(err)

err = s.db.Create(&user).Error
s.NoError(err)

ticker.Users = append(ticker.Users, user)
Expand Down Expand Up @@ -665,8 +718,10 @@ func (s *SqlStorageTestSuite) TestDeleteTicker() {
})

s.Run("when ticker exists with user", func() {
user := User{Email: "[email protected]"}
err := s.db.Create(&user).Error
user, err := NewUser("[email protected]", "password")
s.NoError(err)

err = s.db.Create(&user).Error
s.NoError(err)

ticker := Ticker{ID: 1, Users: []User{user}}
Expand Down
18 changes: 17 additions & 1 deletion internal/storage/user.go
Original file line number Diff line number Diff line change
@@ -1,19 +1,21 @@
package storage

import (
"errors"
"net/http"
"strconv"
"time"

"golang.org/x/crypto/bcrypt"
"gorm.io/gorm"
)

type User struct {
ID int `gorm:"primaryKey"`
CreatedAt time.Time
UpdatedAt time.Time
Email string `gorm:"uniqueIndex;not null"`
EncryptedPassword string
EncryptedPassword string `gorm:"not null"`
IsSuperAdmin bool
Tickers []Ticker `gorm:"many2many:ticker_users;"`
}
Expand All @@ -35,6 +37,20 @@ func NewUser(email, password string) (User, error) {
return user, nil
}

// BeforeSave is a gorm hook that is called before saving a user
// It checks if the email and encrypted password are set
func (u *User) BeforeSave(tx *gorm.DB) error {
if u.Email == "" {
return errors.New("email is required")
}

if u.EncryptedPassword == "" {
return errors.New("encrypted password is required")
}

return nil
}

func (u *User) Authenticate(password string) bool {
err := bcrypt.CompareHashAndPassword([]byte(u.EncryptedPassword), []byte(password))
return err == nil
Expand Down
Loading