|
@@ -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) { |
|
|
func setTokenCookie(id int, role string, w http.ResponseWriter) error { |
|
|
claims, err := getClaims(r) |
|
|
|
|
|
// Will verify existing signature and expiry time |
|
|
|
|
|
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 err |
|
|
return |
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
cookie := http.Cookie{Name: "skouter", |
|
|
cookie := http.Cookie{Name: "skouter", |
|
|
Value: tokenStr, |
|
|
Value: tokenStr, |
|
|
Path: "/", |
|
|
Path: "/", |
|
|
Expires: time.Now().Add(time.Hour * 24)} |
|
|
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, &invoice) |
|
|
// json.Unmarshal(event.Data.Raw, & |
|
|
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) { |
|
|