github.com/bosssauce/ponzu@v0.11.1-0.20200102001432-9bc41b703131/system/db/user.go (about) 1 package db 2 3 import ( 4 "bytes" 5 "encoding/json" 6 "errors" 7 "fmt" 8 "math/rand" 9 "net/http" 10 "time" 11 12 "github.com/ponzu-cms/ponzu/system/admin/user" 13 14 "github.com/boltdb/bolt" 15 "github.com/nilslice/jwt" 16 ) 17 18 // ErrUserExists is used for the db to report to admin user of existing user 19 var ErrUserExists = errors.New("Error. User exists.") 20 21 // ErrNoUserExists is used for the db to report to admin user of non-existing user 22 var ErrNoUserExists = errors.New("Error. No user exists.") 23 24 // SetUser sets key:value pairs in the db for user settings 25 func SetUser(usr *user.User) (int, error) { 26 err := store.Update(func(tx *bolt.Tx) error { 27 email := []byte(usr.Email) 28 users := tx.Bucket([]byte("__users")) 29 if users == nil { 30 return bolt.ErrBucketNotFound 31 } 32 33 // check if user is found by email, fail if nil 34 exists := users.Get(email) 35 if exists != nil { 36 return ErrUserExists 37 } 38 39 // get NextSequence int64 and set it as the User.ID 40 id, err := users.NextSequence() 41 if err != nil { 42 return err 43 } 44 usr.ID = int(id) 45 46 // marshal User to json and put into bucket 47 j, err := json.Marshal(usr) 48 if err != nil { 49 return err 50 } 51 52 err = users.Put(email, j) 53 if err != nil { 54 return err 55 } 56 57 return nil 58 }) 59 if err != nil { 60 return 0, err 61 } 62 63 return usr.ID, nil 64 } 65 66 // UpdateUser sets key:value pairs in the db for existing user settings 67 func UpdateUser(usr, updatedUsr *user.User) error { 68 // ensure user ID remains the same 69 if updatedUsr.ID != usr.ID { 70 updatedUsr.ID = usr.ID 71 } 72 73 err := store.Update(func(tx *bolt.Tx) error { 74 users := tx.Bucket([]byte("__users")) 75 if users == nil { 76 return bolt.ErrBucketNotFound 77 } 78 79 // check if user is found by email, fail if nil 80 exists := users.Get([]byte(usr.Email)) 81 if exists == nil { 82 return ErrNoUserExists 83 } 84 85 // marshal User to json and put into bucket 86 j, err := json.Marshal(updatedUsr) 87 if err != nil { 88 return err 89 } 90 91 err = users.Put([]byte(updatedUsr.Email), j) 92 if err != nil { 93 return err 94 } 95 96 // if email address was changed, delete the old record of former 97 // user with original email address 98 if usr.Email != updatedUsr.Email { 99 err = users.Delete([]byte(usr.Email)) 100 if err != nil { 101 return err 102 } 103 104 } 105 106 return nil 107 }) 108 if err != nil { 109 return err 110 } 111 112 return nil 113 } 114 115 // DeleteUser deletes a user from the db by email 116 func DeleteUser(email string) error { 117 err := store.Update(func(tx *bolt.Tx) error { 118 b := tx.Bucket([]byte("__users")) 119 if b == nil { 120 return bolt.ErrBucketNotFound 121 } 122 123 err := b.Delete([]byte(email)) 124 if err != nil { 125 return err 126 } 127 128 return nil 129 }) 130 if err != nil { 131 return err 132 } 133 134 return nil 135 } 136 137 // User gets the user by email from the db 138 func User(email string) ([]byte, error) { 139 val := &bytes.Buffer{} 140 err := store.View(func(tx *bolt.Tx) error { 141 b := tx.Bucket([]byte("__users")) 142 if b == nil { 143 return bolt.ErrBucketNotFound 144 } 145 146 usr := b.Get([]byte(email)) 147 148 _, err := val.Write(usr) 149 if err != nil { 150 return err 151 } 152 153 return nil 154 }) 155 if err != nil { 156 return nil, err 157 } 158 159 if val.Bytes() == nil { 160 return nil, ErrNoUserExists 161 } 162 163 return val.Bytes(), nil 164 } 165 166 // UserAll returns all users from the db 167 func UserAll() ([][]byte, error) { 168 var users [][]byte 169 err := store.View(func(tx *bolt.Tx) error { 170 b := tx.Bucket([]byte("__users")) 171 if b == nil { 172 return bolt.ErrBucketNotFound 173 } 174 175 err := b.ForEach(func(k, v []byte) error { 176 users = append(users, v) 177 return nil 178 }) 179 if err != nil { 180 return err 181 } 182 183 return nil 184 }) 185 if err != nil { 186 return nil, err 187 } 188 189 return users, nil 190 } 191 192 // CurrentUser extracts the user from the request data and returns the current user from the db 193 func CurrentUser(req *http.Request) ([]byte, error) { 194 if !user.IsValid(req) { 195 return nil, fmt.Errorf("Error. Invalid User.") 196 } 197 198 token, err := req.Cookie("_token") 199 if err != nil { 200 return nil, err 201 } 202 203 claims := jwt.GetClaims(token.Value) 204 email, ok := claims["user"] 205 if !ok { 206 return nil, fmt.Errorf("Error. No user data found in request token.") 207 } 208 209 usr, err := User(email.(string)) 210 if err != nil { 211 return nil, err 212 } 213 214 return usr, nil 215 } 216 217 // SetRecoveryKey generates and saves a random secret key to verify an email 218 // address submitted in order to recover/reset an account password 219 func SetRecoveryKey(email string) (string, error) { 220 r := rand.New(rand.NewSource(time.Now().Unix())) 221 key := fmt.Sprintf("%d", r.Int63()) 222 223 err := store.Update(func(tx *bolt.Tx) error { 224 b, err := tx.CreateBucketIfNotExists([]byte("__recoveryKeys")) 225 if err != nil { 226 return err 227 } 228 229 err = b.Put([]byte(email), []byte(key)) 230 if err != nil { 231 return err 232 } 233 234 return nil 235 }) 236 if err != nil { 237 return "", err 238 } 239 240 return key, nil 241 } 242 243 // RecoveryKey gets a previously set recovery key to verify an email address 244 // submitted in order to recover/reset an account password 245 func RecoveryKey(email string) (string, error) { 246 key := &bytes.Buffer{} 247 248 err := store.View(func(tx *bolt.Tx) error { 249 b := tx.Bucket([]byte("__recoveryKeys")) 250 if b == nil { 251 return bolt.ErrBucketNotFound 252 } 253 254 _, err := key.Write(b.Get([]byte(email))) 255 if err != nil { 256 return err 257 } 258 259 return nil 260 }) 261 if err != nil { 262 return "", err 263 } 264 265 return key.String(), nil 266 }