package account import ( "arimelody-web/model" "database/sql" "errors" "strconv" ) type ( AccountRepositoryMemory struct { accounts []*model.Account } ) var _ AccountRepository = new(AccountRepositoryMemory) func NewAccountRepositoryMemory() *AccountRepositoryMemory { return &AccountRepositoryMemory{ accounts: make([]*model.Account, 0) } } func (repo *AccountRepositoryMemory) GetAll() ([]*model.Account, error) { return repo.accounts, nil } func (repo *AccountRepositoryMemory) GetCount() (int, error) { return len(repo.accounts), nil } func (repo *AccountRepositoryMemory) GetByID(id string) (*model.Account, error) { for _, account := range repo.accounts { if account.ID == id { return account, nil } } return nil, nil } func (repo *AccountRepositoryMemory) GetByUsername(username string) (*model.Account, error) { for _, account := range repo.accounts { if account.Username == username { return account, nil } } return nil, nil } func (repo *AccountRepositoryMemory) GetByEmail(email string) (*model.Account, error) { for _, account := range repo.accounts { if account.Email.Valid && account.Email.String == email { return account, nil } } return nil, nil } // Create an account, returning the new account ID. func (repo *AccountRepositoryMemory) Create(username string, password string, email *string, avatarURL *string) (string, error) { if account, err := repo.GetByUsername(username); err != nil { return "", errors.New("Failed to fetch other acccounts by username") } else if account != nil { return "", errors.New("Account with this username already exists") } emailRef := "" if email != nil { emailRef = *email } avatarURLRef := "" if avatarURL != nil { avatarURLRef = *avatarURL } id := strconv.Itoa(len(repo.accounts)) repo.accounts = append(repo.accounts, &model.Account{ ID: id, Username: username, Password: password, Email: sql.NullString{ String: emailRef, Valid: email != nil }, AvatarURL: sql.NullString{ String: avatarURLRef, Valid: avatarURL != nil }, }) return id, nil } // Intended for large profile updates. For smaller adjusments, // more specialised Change* and Remove* functions should be used. func (repo *AccountRepositoryMemory) Update(id string, username string, password string, email *string, avatarUrl *string) error { if account, err := repo.GetByUsername(username); err != nil { return errors.New("Failed to fetch other acccounts by username") } else if account != nil && account.ID != id { return errors.New("Account with this username already exists") } account, err := repo.GetByID(id) if err != nil { return err } account.Username = username account.Password = password account.Email.Valid = email != nil if account.Email.Valid { account.Email.String = *email } account.AvatarURL.Valid = avatarUrl != nil if account.AvatarURL.Valid { account.AvatarURL.String = *avatarUrl } return nil } func (repo *AccountRepositoryMemory) ChangeUsername(id string, username string) error { if account, err := repo.GetByUsername(username); err != nil { return errors.New("Failed to fetch other acccounts by username") } else if account != nil && account.ID != id { return errors.New("Account with this username already exists") } account, err := repo.GetByID(id) if err != nil { return err } account.Username = username return nil } func (repo *AccountRepositoryMemory) ChangePassword(id string, password string) error { account, err := repo.GetByID(id) if err != nil { return err } account.Password = password return nil } func (repo *AccountRepositoryMemory) ChangeEmail(id string, email string) error { account, err := repo.GetByID(id) if err != nil { return err } account.Email.Valid = true account.Email.String = email return nil } func (repo *AccountRepositoryMemory) RemoveEmail(id string) error { account, err := repo.GetByID(id) if err != nil { return err } account.Email.Valid = false account.Email.String = "" return nil } func (repo *AccountRepositoryMemory) ChangeAvatarURL(id string, avatarURL string) error { account, err := repo.GetByID(id) if err != nil { return err } account.AvatarURL.Valid = true account.AvatarURL.String = avatarURL return nil } func (repo *AccountRepositoryMemory) RemoveAvatar(id string) error { account, err := repo.GetByID(id) if err != nil { return err } account.AvatarURL.Valid = false account.AvatarURL.String = "" return nil } func (repo *AccountRepositoryMemory) Delete(id string) error { accountIndex := -1 for index, account := range repo.accounts { if account.ID == id { accountIndex = index break } } if accountIndex == -1 { return nil } repo.accounts = append( repo.accounts[:accountIndex], repo.accounts[accountIndex+1:]..., ) return nil } // Increment the number of account login failure attempts, // returning the current fail count. func (repo *AccountRepositoryMemory) IncrementFails(id string) (int, error) { account, err := repo.GetByID(id) if err != nil { return 0, err } account.FailAttempts += 1 return account.FailAttempts, nil } func (repo *AccountRepositoryMemory) ResetFails(id string) error { account, err := repo.GetByID(id) if err != nil { return err } account.FailAttempts = 0 return nil } func (repo *AccountRepositoryMemory) Lock(id string) error { account, err := repo.GetByID(id) if err != nil { return err } account.Locked = true return nil } func (repo *AccountRepositoryMemory) Unlock(id string) error { account, err := repo.GetByID(id) if err != nil { return err } account.Locked = false return nil }