diff --git a/handlers.go b/handlers.go index 6e7942e..9a841aa 100644 --- a/handlers.go +++ b/handlers.go @@ -23,508 +23,508 @@ import "github.com/stripe/stripe-go/v78/webhook" import "github.com/stripe/stripe-go/v78/customer" import "github.com/stripe/stripe-go/v78/subscription" -type templatedata struct { - AuthenticatedUser int32 - FormErrors map[string]string - Account Account - Prices []stripe.Price - ClientSecret string - ActiveSubscription bool +type TemplateData struct { + AuthenticatedUser int32 + FormErrors map[string]string + Account Account + Prices []stripe.Price + ClientSecret string + ActiveSubscription bool } func favicon(w http.ResponseWriter, r *http.Request) { - http.ServeFile(w, r, "favicon.ico") + 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 { - log.Println(err) - return 0 - } + session, err := store.Get(r, "id") + if err != nil { + log.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 - } + 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 + // 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.ExistsAccount(id) + exists := users.ExistsAccount(id) - if !exists { - session, _ := store.Get(r, "id") + if !exists { + session, _ := store.Get(r, "id") - session.Values["id"] = 0 - session.Save(r, w) + session.Values["id"] = 0 + session.Save(r, w) - return 0 - } + return 0 + } - return id + return id } func home(w http.ResponseWriter, r *http.Request) { - if r.URL.Path != "/" { - http.NotFound(w, r) - return - } + if r.URL.Path != "/" { + http.NotFound(w, r) + return + } - id := authenticated_user(w, r) - account, err := users.GetAccount(id) - activesubscription := subscriptions.HasActiveSubscription(id) + id := authenticated_user(w, r) + account, err := users.GetAccount(id) + activesubscription := subscriptions.HasActiveSubscription(id) - text, err := template.ParseFiles("ui/base.html", "ui/index.html") - if err != nil { - http.Error(w, "Internal Server Error", 500) - log.Fatal(err) - } + 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: + switch r.Method { + case http.MethodGet: - err := text.Execute(w, templatedata{AuthenticatedUser: id, Account: account, ActiveSubscription: activesubscription}) - if err != nil { - log.Fatal(err) - http.Error(w, "Internal Server Error", 500) - } + err := text.Execute(w, TemplateData{AuthenticatedUser: id, Account: account, ActiveSubscription: activesubscription}) + 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) - } - } + 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) - } + 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: + switch r.Method { + case http.MethodGet: - err := text.Execute(w, templatedata{}) - if err != nil { - log.Fatal(err) - http.Error(w, "Internal Server Error", 500) - } + 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) + 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(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 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 { + 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 := 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 - } + 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) - } + 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 - } + return + } - if id > 0 { - session.Values["id"] = id - //log.Println("Logged in with id:", id) - session.Save(r, w) - http.Redirect(w, r, "/account", http.StatusSeeOther) - } - } + if id > 0 { + session.Values["id"] = id + //log.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) - } + 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.GetAccount(id) - activesubscription := subscriptions.HasActiveSubscription(id) + id := authenticated_user(w, r) + account, err := users.GetAccount(id) + activesubscription := subscriptions.HasActiveSubscription(id) - switch r.Method { - case http.MethodGet: + switch r.Method { + case http.MethodGet: - err := text.Execute(w, templatedata{AuthenticatedUser: id, Account: account, ActiveSubscription: activesubscription}) - if err != nil { - log.Fatal(err) - http.Error(w, "Internal Server Error", 500) - } + err := text.Execute(w, TemplateData{AuthenticatedUser: id, Account: account, ActiveSubscription: activesubscription}) + if err != nil { + log.Fatal(err) + http.Error(w, "Internal Server Error", 500) + } - case http.MethodPost: - session, _ := store.Get(r, "id") + case http.MethodPost: + session, _ := store.Get(r, "id") - session.Values["id"] = 0 - session.Save(r, w) - http.Redirect(w, r, "/", http.StatusSeeOther) - } + 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) - } + 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.GetAccount(id) + id := authenticated_user(w, r) + account, err := users.GetAccount(id) - switch r.Method { - case http.MethodGet: + 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) - } + 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")} + 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) + 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(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 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 { + 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 := 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) + _, err := users.Insert(account.Username, string(account.Password), account.Firstname, account.Lastname, account.Email) - if err == ErrDuplicateEmail || err == ErrDuplicateUsername { + if err == ErrDuplicateEmail || err == ErrDuplicateUsername { - } else if err != nil { + } else if err != nil { - } + } - http.Redirect(w, r, "/login", http.StatusSeeOther) - } + 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, 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.GetAccount(id) + id := authenticated_user(w, r) + account, err := users.GetAccount(id) - //log.Println(id, account) + //log.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) - } + 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) - } - } + 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) - // } + //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) + id := authenticated_user(w, r) - switch r.Method { - case http.MethodPost: - log.Println("Deleting account with id ", id) - users.Delete(id) + switch r.Method { + case http.MethodPost: + log.Println("Deleting account with id ", id) + users.Delete(id) - session, _ := store.Get(r, "id") + session, _ := store.Get(r, "id") - session.Values["id"] = 0 - session.Save(r, w) + session.Values["id"] = 0 + session.Save(r, w) - http.Redirect(w, r, "/", http.StatusSeeOther) - } + http.Redirect(w, r, "/", http.StatusSeeOther) + } } func subscribe(w http.ResponseWriter, r *http.Request) { - id := authenticated_user(w, r) - account, err := users.GetAccount(id) + id := authenticated_user(w, r) + account, err := users.GetAccount(id) - params := &stripe.PriceListParams{} - params.Limit = stripe.Int64(3) - params.AddExpand("data.product") - results := price.List(params) + params := &stripe.PriceListParams{} + params.Limit = stripe.Int64(3) + params.AddExpand("data.product") + results := price.List(params) - prices := make([]stripe.Price, 0) + prices := make([]stripe.Price, 0) - for results.Next() { - //log.Println(results.Current()) - prices = append(prices, *results.Price()) - } + for results.Next() { + //log.Println(results.Current()) + prices = append(prices, *results.Price()) + } - fm := template.FuncMap{ - "divide": func(a, b float64) float64 { - return a / b - }, - } + 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 - } + 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) - } + 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.GetAccount(id) + id := authenticated_user(w, r) + account, err := users.GetAccount(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 { - log.Println(err) - } + 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 { + log.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) - } + 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) - } + 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.GetAccount(id) - if err != nil { - log.Println(err) - } + id := authenticated_user(w, r) + account, err := users.GetAccount(id) + if err != nil { + log.Println(err) + } - params := &stripe.BillingPortalSessionParams{ - Customer: stripe.String(account.StripeID), - ReturnURL: stripe.String("http://localhost:8080/account"), - } + params := &stripe.BillingPortalSessionParams{ + Customer: stripe.String(account.StripeID), + ReturnURL: stripe.String("http://localhost:8080/account"), + } - result, err := session.New(params) - if err != nil { - log.Println(err) - } + result, err := session.New(params) + if err != nil { + log.Println(err) + } - http.Redirect(w, r, result.URL, http.StatusSeeOther) + http.Redirect(w, r, result.URL, http.StatusSeeOther) } func webhooks(w http.ResponseWriter, r *http.Request) { - const MaxBodyBytes = int64(65536) - r.Body = http.MaxBytesReader(w, r.Body, MaxBodyBytes) - payload, err := ioutil.ReadAll(r.Body) - if err != nil { - log.Printf("Error reading request body: %v\n", err) - w.WriteHeader(http.StatusServiceUnavailable) - return - } + const MaxBodyBytes = int64(65536) + r.Body = http.MaxBytesReader(w, r.Body, MaxBodyBytes) + payload, err := ioutil.ReadAll(r.Body) + if err != nil { + log.Printf("Error reading request body: %v\n", err) + w.WriteHeader(http.StatusServiceUnavailable) + return + } - endpointsecret := "whsec_43420f280f7695d9aa411c17da9ffac9afcecc3d36687035a8cb26f7f892f1cf" + endpointsecret := "whsec_43420f280f7695d9aa411c17da9ffac9afcecc3d36687035a8cb26f7f892f1cf" - event, err := webhook.ConstructEvent(payload, r.Header.Get("Stripe-Signature"), endpointsecret) + event, err := webhook.ConstructEvent(payload, r.Header.Get("Stripe-Signature"), endpointsecret) - if err != nil { - log.Printf("Error verifying webhook signature: %v\n", err) - w.WriteHeader(http.StatusBadRequest) // Return a 400 error on a bad signature - return - } + if err != nil { + log.Printf("Error verifying webhook signature: %v\n", err) + w.WriteHeader(http.StatusBadRequest) // Return a 400 error on a bad signature + return + } - err = json.Unmarshal(payload, &event) - if err != nil { - log.Printf("Failed to parse webhook body json: %v\n", err.Error()) - w.WriteHeader(http.StatusBadRequest) - return - } + err = json.Unmarshal(payload, &event) + if err != nil { + log.Printf("Failed to parse webhook body json: %v\n", err.Error()) + w.WriteHeader(http.StatusBadRequest) + return + } - // Unmarshal the event data into an appropriate struct depending on its Type - switch event.Type { - case "checkout.session.completed": - var checkoutSession stripe.CheckoutSession - err := json.Unmarshal(event.Data.Raw, &checkoutSession) - if err != nil { - log.Printf("Error parsing webhook JSON: %v\n", err) - w.WriteHeader(http.StatusBadRequest) - return - } - // Then define and call a func to handle the successful payment intent. - // handlePaymentIntentSucceeded(paymentIntent) - handle_checkout_session_completed(checkoutSession) + // Unmarshal the event data into an appropriate struct depending on its Type + switch event.Type { + case "checkout.session.completed": + var checkoutSession stripe.CheckoutSession + err := json.Unmarshal(event.Data.Raw, &checkoutSession) + if err != nil { + log.Printf("Error parsing webhook JSON: %v\n", err) + w.WriteHeader(http.StatusBadRequest) + return + } + // Then define and call a func to handle the successful payment intent. + // handlePaymentIntentSucceeded(paymentIntent) + handle_checkout_session_completed(checkoutSession) - case "payment_intent.succeeded": - var paymentIntent stripe.PaymentIntent - err := json.Unmarshal(event.Data.Raw, &paymentIntent) - if err != nil { - log.Printf("Error parsing webhook JSON: %v\n", err) - w.WriteHeader(http.StatusBadRequest) - return - } - // Then define and call a func to handle the successful payment intent. - // handlePaymentIntentSucceeded(paymentIntent) + case "payment_intent.succeeded": + var paymentIntent stripe.PaymentIntent + err := json.Unmarshal(event.Data.Raw, &paymentIntent) + if err != nil { + log.Printf("Error parsing webhook JSON: %v\n", err) + w.WriteHeader(http.StatusBadRequest) + return + } + // Then define and call a func to handle the successful payment intent. + // handlePaymentIntentSucceeded(paymentIntent) - case "payment_method.attached": - var paymentMethod stripe.PaymentMethod - err := json.Unmarshal(event.Data.Raw, &paymentMethod) - if err != nil { - log.Printf("Error parsing webhook JSON: %v\n", err) - w.WriteHeader(http.StatusBadRequest) - return - } + case "payment_method.attached": + var paymentMethod stripe.PaymentMethod + err := json.Unmarshal(event.Data.Raw, &paymentMethod) + if err != nil { + log.Printf("Error parsing webhook JSON: %v\n", err) + w.WriteHeader(http.StatusBadRequest) + return + } - case "setup_intent.succeeded": - var setupIntent stripe.SetupIntent - err := json.Unmarshal(event.Data.Raw, &setupIntent) - if err != nil { - log.Printf("Error parsing webhook JSON: %v\n", err) - w.WriteHeader(http.StatusBadRequest) - return - } + case "setup_intent.succeeded": + var setupIntent stripe.SetupIntent + err := json.Unmarshal(event.Data.Raw, &setupIntent) + if err != nil { + log.Printf("Error parsing webhook JSON: %v\n", err) + w.WriteHeader(http.StatusBadRequest) + return + } - // ... handle other event types - default: - log.Printf("Unhandled event type: %s\n", event.Type) - } + // ... handle other event types + default: + log.Printf("Unhandled event type: %s\n", event.Type) + } - w.WriteHeader(http.StatusOK) + w.WriteHeader(http.StatusOK) } func handle_checkout_session_completed(checkoutsession stripe.CheckoutSession) error { - //toprint, _ := json.MarshalIndent(checkoutSession, "", " ") - //log.Println(string(toprint)) + //toprint, _ := json.MarshalIndent(checkoutSession, "", " ") + //log.Println(string(toprint)) - subscription, err := subscription.Get(checkoutsession.Subscription.ID, nil); - if err != nil { - log.Println(err) - return err - } + subscription, err := subscription.Get(checkoutsession.Subscription.ID, nil); + if err != nil { + log.Println(err) + return err + } - //log.Println(subscription.Customer.ID) + //log.Println(subscription.Customer.ID) - //var status SubscriptionStatus - //switch subscription.Status { - // case "incomplete": - // status = incomplete - // case "incomplete_expired": - // status = incomplete_expired - // case "trialing": - // status = trialing - // case "active": - // status = active - // case "past_due": - // status = past_due - // case "canceled": - // status = canceled - // case "unpaid": - // status = unpaid - // case "paused": - // status = paused - //} + //var status SubscriptionStatus + //switch subscription.Status { + // case "incomplete": + // status = incomplete + // case "incomplete_expired": + // status = incomplete_expired + // case "trialing": + // status = trialing + // case "active": + // status = active + // case "past_due": + // status = past_due + // case "canceled": + // status = canceled + // case "unpaid": + // status = unpaid + // case "paused": + // status = paused + //} - subscriptions.Insert(checkoutsession.Customer.ID, subscription.ID, checkoutsession.ID, subscription.Status) + subscriptions.Insert(checkoutsession.Customer.ID, subscription.ID, checkoutsession.ID, subscription.Status) - return nil + return nil } func handle_payment_method_attached(paymentmethod stripe.PaymentMethod) error { - //toprint, _ := json.MarshalIndent(setupintent, "", " ") - //log.Println(string(toprint)) + //toprint, _ := json.MarshalIndent(setupintent, "", " ") + //log.Println(string(toprint)) - // make this the new customer's default payment method - params := &stripe.CustomerParams{} - params.DefaultSource = &paymentmethod.ID - /*result*/_, err := customer.Update(paymentmethod.Customer.ID, params) - //log.Println(result) - if err != nil { - log.Println(err) - return err - } + // make this the new customer's default payment method + params := &stripe.CustomerParams{} + params.DefaultSource = &paymentmethod.ID + /*result*/_, err := customer.Update(paymentmethod.Customer.ID, params) + //log.Println(result) + if err != nil { + log.Println(err) + return err + } - return nil + return nil } diff --git a/main.go b/main.go index 687d6fe..062eb78 100644 --- a/main.go +++ b/main.go @@ -23,77 +23,77 @@ var store = sessions.NewCookieStore(key) var emailrx = regexp.MustCompile("/^[a-zA-Z0-9.!#$%&'*+\\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/") func main() { - addr := flag.String("addr", "127.0.0.1:8080", "HTTP network addr") - prodaddr := flag.String("prodaddr", "45.76.84.7:443", "HTTP network addr") + addr := flag.String("addr", "127.0.0.1:8080", "HTTP network addr") + prodaddr := flag.String("prodaddr", "45.76.84.7:443", "HTTP network addr") - production := flag.Bool("production", false, "Whether to use production port and TLS") - _ = addr - flag.Parse() - log.Println("Hello, Sailor!") + production := flag.Bool("production", false, "Whether to use production port and TLS") + _ = addr + flag.Parse() + log.Println("Hello, Sailor!") - stripe.Key = "sk_test_51PGebgKUHKCjyTmc97rfDPcvew6EhqDz2qp3U7XoAMIilAU9IVo2NO4P7ylkTvbBafFVr94trha1VYY32jRWMw2K00Yq7YJXFf" + stripe.Key = "sk_test_51PGebgKUHKCjyTmc97rfDPcvew6EhqDz2qp3U7XoAMIilAU9IVo2NO4P7ylkTvbBafFVr94trha1VYY32jRWMw2K00Yq7YJXFf" - store.MaxAge(0) + store.MaxAge(0) - db, err := sql.Open("postgres", "postgres://elves_database:iK2SoVbDhdCki5n3LxGyP6zKpLspt4@80.240.25.87/elves_database") - if err != nil { - log.Fatal(err) - } - defer db.Close() + db, err := sql.Open("postgres", "postgres://elves_database:iK2SoVbDhdCki5n3LxGyP6zKpLspt4@80.240.25.87/elves_database") + if err != nil { + log.Fatal(err) + } + defer db.Close() - users = &Usermodel{db} - subscriptions = &SubscriptionModel{db} + users = &Usermodel{db} + subscriptions = &SubscriptionModel{db} - mux := http.NewServeMux() + mux := http.NewServeMux() - //rows, err := db.Query("SELECT * FROM accounts") - //if err != nil { - // log.Fatal(err) - //} - //defer rows.Close() + //rows, err := db.Query("SELECT * FROM accounts") + //if err != nil { + // log.Fatal(err) + //} + //defer rows.Close() - //accounts := make([]*Account, 0) - //for rows.Next() { - // acc := new(Account) - // err := rows.Scan(&acc.id, &acc.Username, &acc.password, &acc.Color) - // if err != nil { - // log.Fatal(err) - // } - // accounts = append(accounts, acc) - //} + //accounts := make([]*Account, 0) + //for rows.Next() { + // acc := new(Account) + // err := rows.Scan(&acc.id, &acc.Username, &acc.password, &acc.Color) + // if err != nil { + // log.Fatal(err) + // } + // accounts = append(accounts, acc) + //} - //if err = rows.Err() err != nil { - // log.Fatal(err) - //} + //if err = rows.Err() err != nil { + // log.Fatal(err) + //} - //for _, acc := range accounts { - // log.Println(acc) - //} + //for _, acc := range accounts { + // log.Println(acc) + //} - mux.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir("static")))) + mux.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir("static")))) - mux.HandleFunc("/favicon.ico", favicon) + mux.HandleFunc("/favicon.ico", favicon) - mux.HandleFunc("/", home) - mux.HandleFunc("/login", login) - mux.HandleFunc("/logout", logout) - mux.HandleFunc("/register", register) - mux.HandleFunc("/account", require_authenticated_user(account)) - mux.HandleFunc("/deleteaccount", require_authenticated_user(deleteaccount)) - mux.HandleFunc("/subscribe", require_authenticated_user(subscribe_stripe)) - mux.HandleFunc("/managebilling", require_authenticated_user(managebilling)) - mux.HandleFunc("/webhook", webhooks) + mux.HandleFunc("/", home) + mux.HandleFunc("/login", login) + mux.HandleFunc("/logout", logout) + mux.HandleFunc("/register", register) + mux.HandleFunc("/account", require_authenticated_user(account)) + mux.HandleFunc("/deleteaccount", require_authenticated_user(deleteaccount)) + mux.HandleFunc("/subscribe", require_authenticated_user(subscribe_stripe)) + mux.HandleFunc("/managebilling", require_authenticated_user(managebilling)) + mux.HandleFunc("/webhook", webhooks) - if *production { + if *production { - server := &http.Server{ - Addr: *prodaddr, - Handler: log_connection(secure_headers(mux)), - } + server := &http.Server{ + Addr: *prodaddr, + Handler: log_connection(secure_headers(mux)), + } - log.Fatal(server.ListenAndServeTLS("/home/alfheim/cert/config/live/alfheimgame.com/fullchain.pem", "/home/alfheim/cert/config/live/alfheimgame.com/privkey.pem")) - } else { - log.Fatal(http.ListenAndServe(*addr, log_connection(secure_headers(mux)))) - } + log.Fatal(server.ListenAndServeTLS("/home/alfheim/cert/config/live/alfheimgame.com/fullchain.pem", "/home/alfheim/cert/config/live/alfheimgame.com/privkey.pem")) + } else { + log.Fatal(http.ListenAndServe(*addr, log_connection(secure_headers(mux)))) + } } diff --git a/static/style.css b/static/style.css index d8c7d4b..034d993 100644 --- a/static/style.css +++ b/static/style.css @@ -1,201 +1,201 @@ html { - height: 100%; - padding: 8px; - /*background: no-repeat url(/static/image.png); - background-size: cover; - background-position: center;*/ - background-color: black; - box-sizing: border-box; + height: 100%; + padding: 8px; + /*background: no-repeat url(/static/image.png); + background-size: cover; + background-position: center;*/ + background-color: black; + box-sizing: border-box; } body { - background-color: #3475CB; - font-family: "Vollkorn"; - color: white; - margin-top: 0px; - margin-left: auto; - margin-right: auto; - margin-bottom: 0px; - min-height: 100%; - max-width: 900px; + background-color: #3475CB; + font-family: "Vollkorn"; + color: white; + margin-top: 0px; + margin-left: auto; + margin-right: auto; + margin-bottom: 0px; + display: flex; + flex-direction: column; + min-height: 100%; + max-width: 900px; } header { - max-width: 100%; + max-width: 100%; } nav { - padding-left: 8px; - padding-right: 8px; - display: flex; - align-items: center; - justify-content: space-between; + padding-left: 8px; + padding-right: 8px; + display: flex; + align-items: center; + justify-content: space-between; } .navbuttons a { - display: inline-block; + display: inline-block; } .maintitle { - margin: 0px; - font-size: 6rem; - color: white; + margin: 0px; + font-size: 6rem; + color: white; } @media (max-width: 1080px) { - .maintitle { - font-size: 4rem; - } + .maintitle { + font-size: 4rem; + } } .loginbutton { - align-self: center; - display: flex; + align-self: center; + display: flex; border: 12px solid; border-image-source: url("/static/panel-000.png"); border-image-slice: 12 fill; - padding-top: 15px; - padding-right: 20px; - padding-bottom: 15px; - padding-left: 20px; - color: black; - /*box-shadow: 10px 10px 5px lightblue;*/ + padding-top: 15px; + padding-right: 20px; + padding-bottom: 15px; + padding-left: 20px; + color: black; + /*box-shadow: 10px 10px 5px lightblue;*/ } main { - margin: 0px; - display: flex; - flex-direction: column; - justify-content: center; - align-items: center; - min-height: 100%; - max-height: 100%; - margin-left: auto; - margin-right: auto; + margin: 0px; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + min-height: 100%; + max-height: 100%; + margin-left: auto; + margin-right: auto; } p { - text-align: center; - font-size: 1rem; + text-align: center; + font-size: 1rem; } .account-wrapper { - background: transparent; - border: 2px solid white; - backdrop-filter: blur(20px); - box-shadow: 0 0 10px rgba(0, 0, 0, 0.2); - border-radius: 15px; - padding: 30px 40px; - font-size: 1.5rem; + background: transparent; + border: 2px solid white; + backdrop-filter: blur(20px); + box-shadow: 0 0 10px rgba(0, 0, 0, 0.2); + border-radius: 15px; + padding: 30px 40px; + font-size: 1.5rem; } .wrapper { - display: inline-block; - background: transparent; - border: 2px solid white; - backdrop-filter: blur(20px); - box-shadow: 0 0 10px rgba(0, 0, 0, 0.2); - border-radius: 15px; - padding: 30px 40px; - width: 80%; - text-align: center; + display: inline-block; + background: transparent; + border: 2px solid white; + backdrop-filter: blur(20px); + box-shadow: 0 0 10px rgba(0, 0, 0, 0.2); + border-radius: 15px; + padding: 30px 40px; + width: 80%; + text-align: center; } .wrapper h1 { - font-size: 1.5rem; - text-align: center; + font-size: 1.5rem; + text-align: center; } .wrapper .input-box { - width: 100%; + width: 100%; } .input-box input { - box-sizing: border-box; - background: transparent; - width: 100%; - height: 100%; - outline: none; - border: 2px solid rgba(255, 255, 255, .2); - border-radius: 25px; - padding: 10px 45px 10px 20px + box-sizing: border-box; + background: transparent; + width: 100%; + height: 100%; + outline: none; + border: 2px solid rgba(255, 255, 255, .2); + border-radius: 25px; + padding: 10px 45px 10px 20px } .input-box input::placeholder { - color: white; + color: white; } .wrapper .input-error { - width: 100%; + width: 100%; } .error { - color: rgba(240, 0, 0, .8); + color: rgba(240, 0, 0, .8); } .input-error input { - box-sizing: border-box; - background: transparent; - width: 100%; - height: 100%; - outline: none; - border: 2px solid rgba(255, 0, 0, .2); - border-radius: 25px; - padding: 10px 45px 10px 20px + box-sizing: border-box; + background: transparent; + width: 100%; + height: 100%; + outline: none; + border: 2px solid rgba(255, 0, 0, .2); + border-radius: 25px; + padding: 10px 45px 10px 20px } .input-error input::placeholder { - color: red; + color: red; } .login-btn-wrapper { - display: flex; - justify-content: center; + display: flex; + justify-content: center; } .wrapper .btn { - width: 100%; - outline: none; - border: none; - border-radius: 20px; + width: 100%; + outline: none; + border: none; + border-radius: 20px; } .wrapper .register-link { - display: flex; - justify-content: center; + display: flex; + justify-content: center; } input { - font-family: inherit; + font-family: inherit; } footer { - position: relative; - left: 0; - bottom: 0; - width: 100%; - background-color: #132123; - color: white; - text-align: center; + margin-top: auto; + width: 100%; + background-color: #132123; + color: white; + text-align: center; } a:link { - text-decoration: none; + text-decoration: none; } .wrapper a:link { - text-decoration: none; + text-decoration: none; } .wrapper a:visited { - text-decoration: none; + text-decoration: none; } .wrapper a:hover { - text-decoration: underline; + text-decoration: underline; } video { - width: 100%; - height: auto; + width: 100%; + height: auto; } diff --git a/ui/base.html b/ui/base.html index 0c81a52..42f9e32 100644 --- a/ui/base.html +++ b/ui/base.html @@ -1,54 +1,48 @@ - - - - Alfheim - - - - - - - - + + Alfheim + + + + + + + + - -
- +
-
- {{template "body" .}} -
+
+ {{template "body" .}} +
- - + +