// // Created by vfs on 02.05.2024. // package main; import "fmt"; import "log"; import "net/http"; import "html/template"; //import "strconv"; import "strings"; import "unicode/utf8"; import "errors"; import "runtime/debug"; import "github.com/stripe/stripe-go/v78"; import "github.com/stripe/stripe-go/v78/price"; import "github.com/stripe/stripe-go/v78/customersession"; import "github.com/stripe/stripe-go/v78/billingportal/session"; type templatedata struct { AuthenticatedUser int32; FormErrors map[string]string; Account Account; Prices []stripe.Price; ClientSecret string; } func favicon(w http.ResponseWriter, r *http.Request) { http.ServeFile(w, r, "favicon.ico"); } func authenticated_user(w http.ResponseWriter, r *http.Request) int32 { session, err := store.Get(r, "id"); if err != nil { fmt.Println(err); return 0; } id, ok := session.Values["id"].(int32); if !ok { trace := fmt.Sprintf("%s\n%s", errors.New("type assertion to int32 failed").Error(), debug.Stack()); _ = trace; //log.Println(trace); return 0; } // check if the saved id exists in the database, otherwise it's a bad id and has to be removed from the cookies exists := users.Exists_account(id); if !exists { session, _ := store.Get(r, "id"); session.Values["id"] = 0; session.Save(r, w); return 0; } return id; } func home(w http.ResponseWriter, r *http.Request) { if r.URL.Path != "/" { http.NotFound(w, r); return; } id := authenticated_user(w, r); account, err := users.Get_account(id); text, err := template.ParseFiles("ui/base.html", "ui/index.html"); if err != nil { http.Error(w, "Internal Server Error", 500); log.Fatal(err); } switch r.Method { case http.MethodGet: err := text.Execute(w, templatedata{AuthenticatedUser: id, Account: account}); if err != nil { log.Fatal(err); http.Error(w, "Internal Server Error", 500); } case http.MethodPost: err := text.Execute(w, templatedata{}); if err != nil { log.Fatal(err); http.Error(w, "Internal Server Error", 500); } } } func login(w http.ResponseWriter, r *http.Request) { text, err := template.ParseFiles("ui/base.html", "ui/login.html"); if err != nil { http.Error(w, "Internal Server Error", 500); log.Fatal(err); } switch r.Method { case http.MethodGet: err := text.Execute(w, templatedata{}); if err != nil { log.Fatal(err); http.Error(w, "Internal Server Error", 500); } case http.MethodPost: session, _ := store.Get(r, "id");; password := r.FormValue("password"); username := r.FormValue("username"); errors := make(map[string]string); if strings.TrimSpace(username) == "" { errors["username"] = "This field cannot be blank"; } else if utf8.RuneCountInString(username) > 20 { errors["username"] = "This field is too long (the maximum is 20 characters)"; } if strings.TrimSpace(password) == "" { errors["password"] = "This field cannot be blank"; } else if utf8.RuneCountInString(password) < 8 { errors["password"] = "This field is too short (the minimum is 8 characters)"; } if len(errors) > 0 { err := text.Execute(w, templatedata{AuthenticatedUser: authenticated_user(w, r), FormErrors: errors}); if err != nil { log.Fatal(err); http.Error(w, "Internal Server Error", 500); } return; } id, err := users.Authenticate(username, password); if err == ErrInvalidCredentials { errors["generic"] = "Email or Password is incorrect"; err := text.Execute(w, templatedata{AuthenticatedUser: authenticated_user(w, r), FormErrors: errors}); if err != nil { log.Fatal(err); http.Error(w, "Internal Server Error", 500); } return; } if id > 0 { session.Values["id"] = id; fmt.Println("Logged in with id:", id); session.Save(r, w); http.Redirect(w, r, "/account", http.StatusSeeOther); } } } func logout(w http.ResponseWriter, r *http.Request) { text, err := template.ParseFiles("ui/base.html", "ui/logout.html"); if err != nil { http.Error(w, "Internal Server Error", 500); log.Fatal(err); } id := authenticated_user(w, r); account, err := users.Get_account(id); switch r.Method { case http.MethodGet: err := text.Execute(w, templatedata{AuthenticatedUser: id, Account: account}); if err != nil { log.Fatal(err); http.Error(w, "Internal Server Error", 500); } case http.MethodPost: session, _ := store.Get(r, "id"); session.Values["id"] = 0; session.Save(r, w); http.Redirect(w, r, "/", http.StatusSeeOther); } } func register(w http.ResponseWriter, r *http.Request) { text, err := template.ParseFiles("ui/base.html", "ui/register.html"); if err != nil { http.Error(w, "Internal Server Error", 500); log.Fatal(err); } id := authenticated_user(w, r); account, err := users.Get_account(id); switch r.Method { case http.MethodGet: err := text.Execute(w, templatedata{AuthenticatedUser: id, Account: account}); if err != nil { log.Fatal(err); http.Error(w, "Internal Server Error", 500); } case http.MethodPost: account := Account{Username: r.FormValue("username"), Password: []byte(r.FormValue("password")), Firstname: r.FormValue("firstname"), Lastname: r.FormValue("lastname"), Email: r.FormValue("email")}; errors := make(map[string]string); if strings.TrimSpace(account.Username) == "" { errors["username"] = "This field cannot be blank"; } else if utf8.RuneCountInString(account.Username) > 20 { errors["username"] = "This field is too long (the maximum is 20 characters)"; } if strings.TrimSpace(string(account.Password)) == "" { errors["password"] = "This field cannot be blank"; } else if utf8.RuneCountInString(string(account.Password)) < 8 { errors["password"] = "This field is too short (the minimum is 8 characters)"; } if len(errors) > 0 { err := text.Execute(w, templatedata{AuthenticatedUser: authenticated_user(w, r), FormErrors: errors}); if err != nil { log.Fatal(err); http.Error(w, "Internal Server Error", 500); } } err := users.Insert(account.Username, string(account.Password), account.Firstname, account.Lastname, account.Email); if err == ErrDuplicateEmail || err == ErrDuplicateUsername { } else if err != nil { } http.Redirect(w, r, "/login", http.StatusSeeOther); } } func account(w http.ResponseWriter, r *http.Request) { //id, err := strconv.Atoi(r.URL.Query().Get("id")); //if err != nil || id < 1 {; // http.NotFound(w, r); // return; //}; //account, err := users.Get_account(int32(id));; //if err != nil {; // log.Fatal(err);; //}; id := authenticated_user(w, r); account, err := users.Get_account(id); fmt.Println(id, account) text, err := template.ParseFiles("ui/base.html", "ui/account.html"); if err != nil { http.Error(w, "Internal Server Error", 500); log.Fatal(err); } switch r.Method { case http.MethodGet: err := text.Execute(w, templatedata{AuthenticatedUser: id, Account: account}); if err != nil { log.Fatal(err); http.Error(w, "Internal Server Error", 500); } } //case http.MethodPost: // text.Execute(w, false); // if err != nil {; // log.Fatal(err); // http.Error(w, "Internal Server Error", 500); // }; } func deleteaccount(w http.ResponseWriter, r *http.Request) { id := authenticated_user(w, r); switch r.Method { case http.MethodPost: fmt.Println("Deleting account with id ", id); users.Delete(id); session, _ := store.Get(r, "id"); session.Values["id"] = 0; session.Save(r, w); http.Redirect(w, r, "/", http.StatusSeeOther); } } func subscribe(w http.ResponseWriter, r *http.Request) { id := authenticated_user(w, r); account, err := users.Get_account(id); params := &stripe.PriceListParams{}; params.Limit = stripe.Int64(3) params.AddExpand("data.product"); results := price.List(params); prices := make([]stripe.Price, 0); for results.Next() { fmt.Println(results.Current()) prices = append(prices, *results.Price()); } fm := template.FuncMap{ "divide": func(a, b float64) float64 { return a / b; }, }; text, err := template.New("base.html").Funcs(fm).ParseFiles("ui/base.html", "ui/subscribe.html"); if err != nil { http.Error(w, "Internal Server Error", 500); log.Fatal(err); return; } err = text.Execute(w, templatedata{AuthenticatedUser: id, Account: account, Prices: prices}); if err != nil { log.Fatal(err); http.Error(w, "Internal Server Error", 500); } } func subscribe_stripe(w http.ResponseWriter, r *http.Request) { id := authenticated_user(w, r); account, err := users.Get_account(id); params := &stripe.CustomerSessionParams{ Customer: stripe.String(account.StripeID), Components: &stripe.CustomerSessionComponentsParams{ PricingTable: &stripe.CustomerSessionComponentsPricingTableParams{ Enabled: stripe.Bool(true), }, }, }; result, err := customersession.New(params); if err != nil { fmt.Println(err); } text, err := template.ParseFiles("ui/base.html", "ui/subscribe_stripe.html"); if err != nil { http.Error(w, "Internal Server Error", 500); log.Fatal(err); } err = text.Execute(w, templatedata{AuthenticatedUser: id, Account: account, ClientSecret: result.ClientSecret}); if err != nil { log.Fatal(err); http.Error(w, "Internal Server Error", 500); } } func managebilling(w http.ResponseWriter, r *http.Request) { id := authenticated_user(w, r); account, err := users.Get_account(id); if err != nil { fmt.Println(err); } params := &stripe.BillingPortalSessionParams{ Customer: stripe.String(account.StripeID), ReturnURL: stripe.String("http://localhost:8080/account"), }; result, err := session.New(params); if err != nil { fmt.Println(err); } http.Redirect(w, r, result.URL, http.StatusSeeOther); }