github.com/serge-v/zero@v1.0.2-0.20220911142406-af4b6a19e68a/examples/how-to-user-registration/db.go (about)

     1  package main
     2  
     3  import (
     4  	"crypto/rand"
     5  	"encoding/json"
     6  	"log"
     7  	"math/big"
     8  	"os"
     9  )
    10  
    11  type user struct {
    12  	Email      string
    13  	Password   string
    14  	Confirmed  bool
    15  	RandomHash string
    16  }
    17  
    18  type userDB struct {
    19  	fname string
    20  	Users []user
    21  }
    22  
    23  func loadDB(fname string) userDB {
    24  	db := userDB{fname: fname}
    25  	f, err := os.Open(fname)
    26  	if err != nil && os.IsNotExist(err) {
    27  		return db
    28  	}
    29  	defer f.Close()
    30  
    31  	dec := json.NewDecoder(f)
    32  	if err := dec.Decode(&db); err != nil {
    33  		log.Fatal(err)
    34  	}
    35  
    36  	return db
    37  }
    38  
    39  func (db *userDB) saveDB() error {
    40  	f, err := os.Create(db.fname)
    41  	if err != nil {
    42  		return err
    43  	}
    44  	defer f.Close()
    45  	enc := json.NewEncoder(f)
    46  	enc.SetIndent("", "\t")
    47  	if err := enc.Encode(db); err != nil {
    48  		return err
    49  	}
    50  	return nil
    51  }
    52  
    53  func (db *userDB) findUser(email string) (*user, bool) {
    54  	for _, u := range db.Users {
    55  		if u.Email == email {
    56  			return &u, true
    57  		}
    58  	}
    59  	return nil, false
    60  }
    61  
    62  func (db *userDB) createUser(email, password string) (*user, error) {
    63  	if u, found := db.findUser(email); found {
    64  		return u, nil
    65  	}
    66  
    67  	randomHash, err := generateRandomString(20)
    68  	if err != nil {
    69  		return nil, err
    70  	}
    71  
    72  	u := user{
    73  		Email:      email,
    74  		Password:   password,
    75  		RandomHash: randomHash,
    76  	}
    77  
    78  	db.Users = append(db.Users, u)
    79  	if err := db.saveDB(); err != nil {
    80  		return nil, err
    81  	}
    82  
    83  	return &u, nil
    84  }
    85  
    86  func generateRandomString(n int) (string, error) {
    87  	const letters = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
    88  	ret := make([]byte, n)
    89  	for i := 0; i < n; i++ {
    90  		num, err := rand.Int(rand.Reader, big.NewInt(int64(len(letters))))
    91  		if err != nil {
    92  			return "", err
    93  		}
    94  		ret[i] = letters[num.Int64()]
    95  	}
    96  
    97  	return string(ret), nil
    98  }