Selaa lähdekoodia

Automatically set token cookie after login

master
Immanuel Onyeka 8 kuukautta sitten
vanhempi
commit
5627960ad4
3 muutettua tiedostoa jossa 113 lisäystä ja 43 poistoa
  1. +4
    -1
      grav-admin/user/js/registration/registration.vue
  2. +1
    -1
      migrations/0_29092022_setup_tables.sql
  3. +108
    -41
      skouter.go

+ 4
- 1
grav-admin/user/js/registration/registration.vue Näytä tiedosto

@@ -59,7 +59,10 @@ function create(user) {
}).then(resp => { }).then(resp => {
if (resp.ok) { if (resp.ok) {
return resp.json().then(u => { err.value = "" }). return resp.json().then(u => { err.value = "" }).
then( () => intent(user) )
then( () => {
token.value = getCookie("skouter")
intent(user)
} )
} else { } else {
resp.text().then( e => err.value = e) resp.text().then( e => err.value = e)
} }


+ 1
- 1
migrations/0_29092022_setup_tables.sql Näytä tiedosto

@@ -28,7 +28,7 @@ CREATE TABLE user (
email VARCHAR(40) UNIQUE NOT NULL, email VARCHAR(40) UNIQUE NOT NULL,
first_name VARCHAR(30) NOT NULL, first_name VARCHAR(30) NOT NULL,
last_name VARCHAR(30) NOT NULL, last_name VARCHAR(30) NOT NULL,
customer_id VARCHAR(255) NOT NULL DEFAULT '',
customer_id VARCHAR(255) UNIQUE NOT NULL DEFAULT '',
phone VARCHAR(20) NOT NULL DEFAULT '', phone VARCHAR(20) NOT NULL DEFAULT '',
address INT NOT NULL, address INT NOT NULL,
password CHAR(64) NOT NULL, password CHAR(64) NOT NULL,


+ 108
- 41
skouter.go Näytä tiedosto

@@ -371,25 +371,6 @@ func match(path, pattern string, args *[]string) bool {
return true return true
} }


func createToken(id int, role string) (*http.Cookie, error) {
token := jwt.NewWithClaims(jwt.SigningMethodHS256,
UserClaims{Id: id, Role: role,
Exp: time.Now().Add(time.Minute * 30).Format(time.UnixDate)})

tokenStr, err := token.SignedString([]byte(os.Getenv("JWT_SECRET")))
if err != nil {
log.Println("Token could not be signed: ", err, tokenStr)
return nil, errors.New("Token generation error.")
}

cookie := http.Cookie{Name: "skouter",
Value: tokenStr,
Path: "/",
Expires: time.Now().Add(time.Hour * 24)}

return &cookie, nil
}

func (estimate *Estimate) makeResults() []Result { func (estimate *Estimate) makeResults() []Result {
var results []Result var results []Result
amortize := func(principle float64, rate float64, periods float64) int { amortize := func(principle float64, rate float64, periods float64) int {
@@ -901,42 +882,40 @@ func login(w http.ResponseWriter, db *sql.DB, r *http.Request) {
return return
} }


cookie, err := createToken(id, role)
err = setTokenCookie(id, role, w)
if err != nil { if err != nil {
http.Error(w, err.Error(), 500) http.Error(w, err.Error(), 500)
} }
http.SetCookie(w, cookie)
_, err = w.Write([]byte(cookie.Value))
if err != nil {
http.Error(w, "Could not complete token write.",
http.StatusInternalServerError)
}
} }


func getToken(w http.ResponseWriter, db *sql.DB, r *http.Request) {
claims, err := getClaims(r)
// Will verify existing signature and expiry time
func setTokenCookie(id int, role string, w http.ResponseWriter) error {
token := jwt.NewWithClaims(jwt.SigningMethodHS256, token := jwt.NewWithClaims(jwt.SigningMethodHS256,
UserClaims{Id: claims.Id, Role: claims.Role,
UserClaims{Id: id, Role: role,
Exp: time.Now().Add(time.Minute * 30).Format(time.UnixDate)}) Exp: time.Now().Add(time.Minute * 30).Format(time.UnixDate)})


tokenStr, err := token.SignedString([]byte(os.Getenv("JWT_SECRET"))) tokenStr, err := token.SignedString([]byte(os.Getenv("JWT_SECRET")))
if err != nil { if err != nil {
log.Println("Token could not be signed: ", err, tokenStr) log.Println("Token could not be signed: ", err, tokenStr)
http.Error(w, "Token generation error.", http.StatusInternalServerError)
return
return err
} }
cookie := http.Cookie{Name: "skouter", cookie := http.Cookie{Name: "skouter",
Value: tokenStr,
Path: "/",
Expires: time.Now().Add(time.Hour * 24)}
Value: tokenStr,
Path: "/",
Expires: time.Now().Add(time.Hour * 24)}
http.SetCookie(w, &cookie) http.SetCookie(w, &cookie)
_, err = w.Write([]byte(tokenStr))
return nil
}

func getToken(w http.ResponseWriter, db *sql.DB, r *http.Request) {
claims, _ := getClaims(r)
err := setTokenCookie(claims.Id, claims.Role, w)

if err != nil { if err != nil {
http.Error(w, http.Error(w,
"Could not complete token write.",
"Token generation error",
http.StatusInternalServerError) http.StatusInternalServerError)
} }
} }
@@ -1194,6 +1173,66 @@ func queryUser(db *sql.DB, id int) (User, error) {
return user, nil return user, nil
} }


func queryCustomer(db *sql.DB, id string) (User, error) {
var user User
var query string
var err error

query = `SELECT
u.id,
u.email,
u.first_name,
u.last_name,
coalesce(u.branch_id, 0),
u.country,
u.title,
coalesce(u.status, ''),
coalesce(u.customer_id, ''),
u.verified,
u.role,
u.address,
u.phone
FROM user u WHERE u.customer_id = ?
`
row := db.QueryRow(query, id)

if err != nil {
return user, err
}

err = row.Scan(
&user.Id,
&user.Email,
&user.FirstName,
&user.LastName,
&user.Branch.Id,
&user.Country,
&user.Title,
&user.Status,
&user.CustomerId,
&user.Verified,
&user.Role,
&user.Address.Id,
&user.Phone,
)

if err != nil {
return user, err
}

user.Address, err = queryAddress(db, user.Address.Id)
if err != nil {
return user, err
}

user.Branch, err = queryBranch(db, user.Branch.Id)
if err != nil {
return user, err
}

return user, nil
}

// Can probably be deleted. // Can probably be deleted.
func queryUsers(db *sql.DB, id int) ([]User, error) { func queryUsers(db *sql.DB, id int) ([]User, error) {
var users []User var users []User
@@ -1728,6 +1767,12 @@ func createUser(w http.ResponseWriter, db *sql.DB, r *http.Request) {
http.Error(w, err.Error(), 422) http.Error(w, err.Error(), 422)
return return
} }
err = setTokenCookie(user.Id, user.Role, w)
if err != nil {
http.Error(w, err.Error(), 500)
return
}


json.NewEncoder(w).Encode(user) json.NewEncoder(w).Encode(user)
} }
@@ -2976,6 +3021,9 @@ func createSubscription(cid string) (*stripe.Subscription, error) {
return s, err return s, err
} }


// Creates a new subscription instance for a new user or retrieves the
// existing instance if possible. It's main purpose is to supply a
// client secret used for sending billing information to stripe.
func subscribe(w http.ResponseWriter, db *sql.DB, r *http.Request) { func subscribe(w http.ResponseWriter, db *sql.DB, r *http.Request) {
claims, err := getClaims(r) claims, err := getClaims(r)
user, err := queryUser(db, claims.Id) user, err := queryUser(db, claims.Id)
@@ -3038,7 +3086,10 @@ func subscribe(w http.ResponseWriter, db *sql.DB, r *http.Request) {
} }


// A successful subscription payment should be confirmed by Stripe and
// Updated through this hook.
func invoicePaid(w http.ResponseWriter, db *sql.DB, r *http.Request) { func invoicePaid(w http.ResponseWriter, db *sql.DB, r *http.Request) {
var invoice stripe.Invoice
b, err := io.ReadAll(r.Body) b, err := io.ReadAll(r.Body)
if err != nil { if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest) http.Error(w, err.Error(), http.StatusBadRequest)
@@ -3055,14 +3106,30 @@ func invoicePaid(w http.ResponseWriter, db *sql.DB, r *http.Request) {
return return
} }
// OK should be sent before any processing to confirm with Stripe that
// the hook was received
w.WriteHeader(http.StatusOK) w.WriteHeader(http.StatusOK)
if event.Type != "invoice.paid" { if event.Type != "invoice.paid" {
log.Println("Invalid event type sent to invoice-paid.") log.Println("Invalid event type sent to invoice-paid.")
return return
} }
log.Println(event.Type)
// json.Unmarshal(event.Data.Raw, &
json.Unmarshal(event.Data.Raw, &invoice)
log.Println(event.Type, invoice.ID, invoice.Customer.ID)
user, err := queryCustomer(db, invoice.Customer.ID)
if err != nil {
log.Printf("Could not query customer: %v", err)
return
}
s, err := subscription.Get(invoice.Subscription.ID, nil)
if err != nil {
log.Printf("Could not fetch subscription: %v", err)
return
}
log.Println(user.Id, s.ID)
} }


func invoiceFailed(w http.ResponseWriter, db *sql.DB, r *http.Request) { func invoiceFailed(w http.ResponseWriter, db *sql.DB, r *http.Request) {


Loading…
Peruuta
Tallenna