mirror of
https://github.com/gabehf/BudgetBuddy.git
synced 2026-03-08 23:18:15 -07:00
Added Login and Create Account
This commit is contained in:
parent
197afc4f59
commit
272e4e43b1
7 changed files with 334 additions and 0 deletions
93
routes/createAccount.go
Normal file
93
routes/createAccount.go
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
package routes
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
"net/mail"
|
||||
"strings"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/jacobmveber-01839764/BudgetBuddy/db"
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||
"go.mongodb.org/mongo-driver/mongo/readpref"
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
)
|
||||
|
||||
func CreateAccount(w http.ResponseWriter, r *http.Request) {
|
||||
// prepare DB
|
||||
err := db.Client.Ping(context.Background(), readpref.Primary())
|
||||
if err != nil {
|
||||
db.Connect()
|
||||
}
|
||||
var userCollection = db.Client.Database("budgetbuddy").Collection("users")
|
||||
|
||||
// var v contains POST credentials
|
||||
var v Credentials
|
||||
r.ParseForm()
|
||||
v.Email = r.FormValue("email")
|
||||
v.Password = r.FormValue("password")
|
||||
if v.Email == "" || v.Password == "" {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
if len(v.Password) < 8 || len(v.Password) > 255 || !EmailIsValid(v.Email) {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
fmt.Fprint(w, "{\"error\":\"there was a problem with your request. Please try again with different values\"}")
|
||||
return
|
||||
}
|
||||
|
||||
// search if user with that username already exists
|
||||
find := userCollection.FindOne(r.Context(), bson.D{primitive.E{Key: "email", Value: strings.ToLower(v.Email)}})
|
||||
if find.Err() == nil {
|
||||
w.WriteHeader(http.StatusConflict)
|
||||
fmt.Fprint(w, "{\"error\":\"user already exists with that email\"}")
|
||||
return
|
||||
}
|
||||
|
||||
// create a new session for the new user
|
||||
sessionID := uuid.NewString()
|
||||
session := &http.Cookie{
|
||||
Name: "session",
|
||||
Value: sessionID,
|
||||
Path: "/",
|
||||
Secure: true,
|
||||
SameSite: http.SameSiteLaxMode,
|
||||
MaxAge: 0,
|
||||
}
|
||||
http.SetCookie(w, session)
|
||||
|
||||
// hash and store the user's hashed password
|
||||
hashedPass, err := bcrypt.GenerateFromPassword([]byte(v.Password), 8)
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
fmt.Fprintf(w, "{\"error\":\"internal server error, please try again later\"}")
|
||||
}
|
||||
|
||||
// add the new user to the database
|
||||
v.Session = sessionID
|
||||
v.Password = string(hashedPass)
|
||||
_, err = userCollection.InsertOne(r.Context(), v)
|
||||
if err != nil {
|
||||
log.Println("* Error inserting new user")
|
||||
}
|
||||
|
||||
// return the account information to the user
|
||||
ret, err := json.Marshal(LoginResponse{
|
||||
Email: v.Email,
|
||||
Session: v.Session,
|
||||
})
|
||||
if err != nil {
|
||||
fmt.Println("* Error marshalling bson.D response")
|
||||
}
|
||||
fmt.Fprint(w, string(ret))
|
||||
}
|
||||
|
||||
func EmailIsValid(email string) bool {
|
||||
_, err := mail.ParseAddress(email)
|
||||
return err == nil
|
||||
}
|
||||
102
routes/login.go
Normal file
102
routes/login.go
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
package routes
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/jacobmveber-01839764/BudgetBuddy/db"
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||
"go.mongodb.org/mongo-driver/mongo/options"
|
||||
"go.mongodb.org/mongo-driver/mongo/readpref"
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
)
|
||||
|
||||
type Credentials struct {
|
||||
Email string `json:"email" bson:"email"`
|
||||
Password string `json:"password" bson:"password"`
|
||||
Session string `json:"session" bson:"session"`
|
||||
}
|
||||
|
||||
type LoginResponse struct {
|
||||
Email string `json:"email"`
|
||||
Session string `json:"session"`
|
||||
}
|
||||
|
||||
func Login(w http.ResponseWriter, r *http.Request) {
|
||||
// prepare DB
|
||||
err := db.Client.Ping(context.Background(), readpref.Primary())
|
||||
if err != nil {
|
||||
db.Connect()
|
||||
}
|
||||
var userCollection = db.Client.Database("budgetbuddy").Collection("users")
|
||||
|
||||
// var v contains POST credentials
|
||||
var v Credentials
|
||||
r.ParseForm()
|
||||
v.Email = r.FormValue("email")
|
||||
v.Password = r.FormValue("password")
|
||||
if v.Email == "" || v.Password == "" {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
// cmp struct will be compared with v to verify credentials
|
||||
var cmp Credentials
|
||||
|
||||
found := userCollection.FindOne(r.Context(), bson.D{primitive.E{Key: "email", Value: strings.ToLower(v.Email)}})
|
||||
if found.Err() != nil {
|
||||
w.WriteHeader(http.StatusUnauthorized)
|
||||
fmt.Fprintf(w, "{\"error\":\"account with that email does not exist\"}")
|
||||
return
|
||||
}
|
||||
err = found.Decode(&cmp)
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
err = bcrypt.CompareHashAndPassword([]byte(cmp.Password), []byte(v.Password))
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusUnauthorized)
|
||||
fmt.Fprintf(w, "{\"error\":\"invalid password\"}")
|
||||
return
|
||||
}
|
||||
|
||||
// prepare ReturnedAccount struct to be sent back to the client
|
||||
var account LoginResponse
|
||||
err = found.Decode(&account)
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
// set new session cookie for user, either persistent (remember me) or temporary
|
||||
sessionID := uuid.NewString()
|
||||
var session = &http.Cookie{
|
||||
Name: "session",
|
||||
Value: sessionID,
|
||||
Path: "/",
|
||||
Secure: true,
|
||||
SameSite: http.SameSiteLaxMode,
|
||||
MaxAge: 0,
|
||||
}
|
||||
http.SetCookie(w, session)
|
||||
|
||||
// update the new user session in the DB
|
||||
filter := bson.D{primitive.E{Key: "email", Value: strings.ToLower(account.Email)}}
|
||||
opts := options.Update().SetUpsert(true)
|
||||
update := bson.D{primitive.E{Key: "$set", Value: bson.D{primitive.E{Key: "session", Value: sessionID}}}}
|
||||
userCollection.UpdateOne(context.TODO(), filter, update, opts)
|
||||
|
||||
acc, err := json.Marshal(account)
|
||||
if err != nil {
|
||||
fmt.Println("Error marshalling bson.D response")
|
||||
}
|
||||
fmt.Fprint(w, string(acc))
|
||||
// fmt.Println("logged in user successfully")
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue