From bf5acf23b0b58ea91f681298cb8a2c08d6732777 Mon Sep 17 00:00:00 2001 From: Andrew71 Date: Fri, 11 Oct 2024 11:38:08 +0300 Subject: [PATCH] Initial commit --- README.md | 3 +++ auth.go | 35 +++++++++++++++++++++++++++++++++++ go.mod | 8 ++++++++ go.sum | 4 ++++ main.go | 32 ++++++++++++++++++++++++++++++++ user.go | 29 +++++++++++++++++++++++++++++ 6 files changed, 111 insertions(+) create mode 100644 README.md create mode 100644 auth.go create mode 100644 go.mod create mode 100644 go.sum create mode 100644 main.go create mode 100644 user.go diff --git a/README.md b/README.md new file mode 100644 index 0000000..0073a46 --- /dev/null +++ b/README.md @@ -0,0 +1,3 @@ +# PYE + +**Mission**: Science compels us to create a microservice! \ No newline at end of file diff --git a/auth.go b/auth.go new file mode 100644 index 0000000..65f0f88 --- /dev/null +++ b/auth.go @@ -0,0 +1,35 @@ +package main + +import ( + "net/http" + "net/mail" + "strings" +) + +func ValidEmail(email string) bool { + _, err := mail.ParseAddress(email) + return err == nil +} +func ValidPass(pass string) bool { + return len(pass) >= 8 // TODO: Obviously, we *might* want something more sophisticated here +} +func TakenEmail(email string) bool { + // TODO: Implement + return false +} +func Register(w http.ResponseWriter, r *http.Request) { + email, password, ok := r.BasicAuth() + + if !ok { + email = strings.TrimSpace(email) + password = strings.TrimSpace(password) + if !(ValidEmail(email) || ValidPass(password) || TakenEmail(email)) { + // TODO: Provide descriptive error and check if 400 is best code? + http.Error(w, "Invalid auth credentials", http.StatusBadRequest) + } + } + + // No email and password was provided + w.Header().Set("WWW-Authenticate", `Basic realm="restricted", charset="UTF-8"`) + http.Error(w, "This API requires authorization", http.StatusUnauthorized) +} diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..1aa3640 --- /dev/null +++ b/go.mod @@ -0,0 +1,8 @@ +module pye-auth + +go 1.22 + +require ( + github.com/google/uuid v1.6.0 + golang.org/x/crypto v0.28.0 +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..303efc6 --- /dev/null +++ b/go.sum @@ -0,0 +1,4 @@ +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw= +golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U= diff --git a/main.go b/main.go new file mode 100644 index 0000000..16dcb5e --- /dev/null +++ b/main.go @@ -0,0 +1,32 @@ +package main + +import ( + "fmt" + "net/http" +) + +func main() { + fmt.Println("Test") + + router := http.NewServeMux() + + router.HandleFunc("POST /todos", func(w http.ResponseWriter, r *http.Request) { + fmt.Println("create a todo") + }) + + router.HandleFunc("GET /todos", func(w http.ResponseWriter, r *http.Request) { + fmt.Println("get all todos") + }) + + router.HandleFunc("PATCH /todos/{id}", func(w http.ResponseWriter, r *http.Request) { + id := r.PathValue("id") + fmt.Println("update a todo by id", id) + }) + + router.HandleFunc("DELETE /todos/{id}", func(w http.ResponseWriter, r *http.Request) { + id := r.PathValue("id") + fmt.Println("delete a todo by id", id) + }) + + http.ListenAndServe(":7102", router) +} diff --git a/user.go b/user.go new file mode 100644 index 0000000..83c1eaa --- /dev/null +++ b/user.go @@ -0,0 +1,29 @@ +package main + +import ( + "github.com/google/uuid" + "golang.org/x/crypto/bcrypt" +) + +type User struct { + uuid uuid.UUID + email string + hash []byte // bcrypt hash of password +} + +func (u User) PasswordFits(password string) bool { + err := bcrypt.CompareHashAndPassword(u.hash, []byte(password)) + return err == nil +} + +func NewUser(email, password string) (User, error) { + hash, err := bcrypt.GenerateFromPassword([]byte(password), 14) + if err != nil { + return User{}, err + } + return User{uuid.New(), email, hash}, nil +} + +func CreateUser(User) { + +}