mirror of
https://github.com/kataras/iris.git
synced 2025-03-13 10:14:14 +01:00
115 lines
2.6 KiB
Go
115 lines
2.6 KiB
Go
package user
|
|
|
|
import (
|
|
"errors"
|
|
"sync"
|
|
"time"
|
|
)
|
|
|
|
// IDGenerator would be our user ID generator
|
|
// but here we keep the order of users by their IDs
|
|
// so we will use numbers that can be easly written
|
|
// to the browser to get results back from the REST API.
|
|
// var IDGenerator = func() string {
|
|
// return uuid.NewV4().String()
|
|
// }
|
|
|
|
// DataSource is our data store example.
|
|
type DataSource struct {
|
|
Users map[int64]Model
|
|
mu sync.RWMutex
|
|
}
|
|
|
|
// NewDataSource returns a new user data source.
|
|
func NewDataSource() *DataSource {
|
|
return &DataSource{
|
|
Users: make(map[int64]Model),
|
|
}
|
|
}
|
|
|
|
// GetBy returns receives a query function
|
|
// which is fired for every single user model inside
|
|
// our imaginary database.
|
|
// When that function returns true then it stops the iteration.
|
|
//
|
|
// It returns the query's return last known boolean value
|
|
// and the last known user model
|
|
// to help callers to reduce the loc.
|
|
//
|
|
// But be carefully, the caller should always check for the "found"
|
|
// because it may be false but the user model has actually real data inside it.
|
|
//
|
|
// It's actually a simple but very clever prototype function
|
|
// I'm think of and using everywhere since then,
|
|
// hope you find it very useful too.
|
|
func (d *DataSource) GetBy(query func(Model) bool) (user Model, found bool) {
|
|
d.mu.RLock()
|
|
for _, user = range d.Users {
|
|
found = query(user)
|
|
if found {
|
|
break
|
|
}
|
|
}
|
|
d.mu.RUnlock()
|
|
return
|
|
}
|
|
|
|
// GetByID returns a user model based on its ID.
|
|
func (d *DataSource) GetByID(id int64) (Model, bool) {
|
|
return d.GetBy(func(u Model) bool {
|
|
return u.ID == id
|
|
})
|
|
}
|
|
|
|
// GetByUsername returns a user model based on the Username.
|
|
func (d *DataSource) GetByUsername(username string) (Model, bool) {
|
|
return d.GetBy(func(u Model) bool {
|
|
return u.Username == username
|
|
})
|
|
}
|
|
|
|
func (d *DataSource) getLastID() (lastID int64) {
|
|
d.mu.RLock()
|
|
for id := range d.Users {
|
|
if id > lastID {
|
|
lastID = id
|
|
}
|
|
}
|
|
d.mu.RUnlock()
|
|
|
|
return lastID
|
|
}
|
|
|
|
// InsertOrUpdate adds or updates a user to the (memory) storage.
|
|
func (d *DataSource) InsertOrUpdate(user Model) (Model, error) {
|
|
// no matter what we will update the password hash
|
|
// for both update and insert actions.
|
|
hashedPassword, err := GeneratePassword(user.password)
|
|
if err != nil {
|
|
return user, err
|
|
}
|
|
user.HashedPassword = hashedPassword
|
|
|
|
// update
|
|
if id := user.ID; id > 0 {
|
|
_, found := d.GetByID(id)
|
|
if !found {
|
|
return user, errors.New("ID should be zero or a valid one that maps to an existing User")
|
|
}
|
|
d.mu.Lock()
|
|
d.Users[id] = user
|
|
d.mu.Unlock()
|
|
return user, nil
|
|
}
|
|
|
|
// insert
|
|
id := d.getLastID() + 1
|
|
user.ID = id
|
|
d.mu.Lock()
|
|
user.CreatedAt = time.Now()
|
|
d.Users[id] = user
|
|
d.mu.Unlock()
|
|
|
|
return user, nil
|
|
}
|