From 837a1bfa651188d500df9606742bc80c60978916 Mon Sep 17 00:00:00 2001 From: Christopher James Hayward Date: Sat, 1 Jul 2023 14:24:59 -0400 Subject: [PATCH] Implement gateway --- cmd/gateway/main.go | 48 +++++++++++++++++++ gateway/gateway.go | 114 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 162 insertions(+) create mode 100644 cmd/gateway/main.go create mode 100644 gateway/gateway.go diff --git a/cmd/gateway/main.go b/cmd/gateway/main.go new file mode 100644 index 0000000..2b34553 --- /dev/null +++ b/cmd/gateway/main.go @@ -0,0 +1,48 @@ +package main + +import ( + "flag" + "fmt" + "net/http" + + "git.chrishayward.xyz/x/users/gateway" + "git.chrishayward.xyz/x/users/proto" + "google.golang.org/grpc" +) + +var ( + port = flag.Int("port", 8081, "--port=8081") + serverAddr = flag.String("serverAddr", "localhost", "--serverAddr=localhost") + serverPort = flag.Int("serverPort", 8080, "--serverPort=8080") + serverSecret = flag.String("serverSecret", "...", "--serverSecret=...") +) + +func main() { + // Parse the optional flags. + flag.Parse() + + // Create the connection to the server. + conn, err := grpc.Dial(fmt.Sprintf("%s:%d", *serverAddr, *serverPort)) + if err != nil { + fmt.Printf("Failed to connect: %v", err) + } + + // Defer closing the connection. + defer conn.Close() + + // Create the client. + client := proto.NewUsersClient(conn) + + // Setup HTTP endpoints. + http.HandleFunc("/register", gateway.Register(client)) + http.HandleFunc("/login", gateway.Login(client)) + http.HandleFunc("/authorize", gateway.Authorize(client, serverSecret)) + http.HandleFunc("/reset_password", gateway.ResetPassword(client)) + http.HandleFunc("/change_password", gateway.ChangePassword(client)) + + // Listen for requests. + fmt.Printf("Forwarding from :%d to %s:%d", *port, *serverAddr, *serverPort) + if err := http.ListenAndServe(fmt.Sprintf(":%d", *port), nil); err != nil { + fmt.Printf("Failed to listen: %v", err) + } +} diff --git a/gateway/gateway.go b/gateway/gateway.go new file mode 100644 index 0000000..0ba5fdf --- /dev/null +++ b/gateway/gateway.go @@ -0,0 +1,114 @@ +package gateway + +import ( + "fmt" + "net/http" + + "git.chrishayward.xyz/x/users/proto" +) + +func Register(client proto.UsersClient) http.HandlerFunc { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + password, passwordAgain := + r.URL.Query().Get("password"), + r.URL.Query().Get("password_again") + _, err := client.Register(r.Context(), &proto.RegisterRequest{ + Form: &proto.UserForm{ + Email: r.URL.Query().Get("email"), + Password: &password, + PasswordAgain: &passwordAgain, + }, + }) + + if err != nil { + w.WriteHeader(http.StatusBadRequest) + w.Write([]byte(err.Error())) + } + + w.WriteHeader(http.StatusOK) + }) +} + +func Login(client proto.UsersClient) http.HandlerFunc { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + password, passwordAgain := + r.URL.Query().Get("password"), + r.URL.Query().Get("password_again") + res, err := client.Login(r.Context(), &proto.LoginRequest{ + Form: &proto.UserForm{ + Email: r.URL.Query().Get("email"), + Password: &password, + PasswordAgain: &passwordAgain, + }, + }) + + if err != nil { + w.WriteHeader(http.StatusBadRequest) + w.Write([]byte(err.Error())) + } + + w.WriteHeader(http.StatusOK) + w.Write([]byte(res.Token.Token)) + }) +} + +func Authorize(client proto.UsersClient, serverSecret *string) http.HandlerFunc { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + res, err := client.Authorize(r.Context(), &proto.AuthorizeRequest{ + Secret: *serverSecret, + Token: &proto.UserToken{ + Token: r.URL.Query().Get("token"), + }, + }) + + if err != nil { + w.WriteHeader(http.StatusBadRequest) + w.Write([]byte(err.Error())) + } + + w.WriteHeader(http.StatusOK) + w.Write([]byte(fmt.Sprintf("%d", res.User.Id))) + }) +} + +func ResetPassword(client proto.UsersClient) http.HandlerFunc { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + res, err := client.ResetPassword(r.Context(), &proto.ResetPasswordRequest{ + Form: &proto.UserForm{ + Email: r.URL.Query().Get("email"), + }, + }) + + if err != nil { + w.WriteHeader(http.StatusBadRequest) + w.Write([]byte(err.Error())) + } + + w.WriteHeader(http.StatusOK) + w.Write([]byte(fmt.Sprintf( + "Please follow this link to update your password: http://localhost:%d/change_password?token=%s\n", + *port, res.Token.Token))) + }) +} + +func ChangePassword(client proto.UsersClient) http.HandlerFunc { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + password, passwordAgain := + r.URL.Query().Get("password"), + r.URL.Query().Get("password_again") + _, err := client.ChangePassword(r.Context(), &proto.ChangePasswordRequest{ + Form: &proto.UserForm{ + Email: r.URL.Query().Get("email"), + Password: &password, + PasswordAgain: &passwordAgain, + }, + }) + + if err != nil { + w.WriteHeader(http.StatusBadRequest) + w.Write([]byte(err.Error())) + } + + w.WriteHeader(http.StatusOK) + }) +}