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  }