浏览代码

feat: refactoring for refactoring sake

Douglas A 2 年之前
父节点
当前提交
0a1c72c855
共有 5 个文件被更改,包括 287 次插入119 次删除
  1. 23 16
      main.go
  2. 20 0
      model/user.go
  3. 110 100
      routes/auth.go
  4. 94 0
      routes/routes.go
  5. 40 3
      routes/user.go

+ 23 - 16
main.go

@@ -3,6 +3,7 @@ package main
 import (
 	"log"
 	"net/http"
+	"os"
 
 	"github.com/andreanidouglas/auth/model"
 	"github.com/andreanidouglas/auth/routes"
@@ -10,27 +11,33 @@ import (
 )
 
 func health_check(w http.ResponseWriter, r *http.Request) {
-    w.WriteHeader(200)
+	w.WriteHeader(200)
 }
 
-func main () {
+func main() {
 
-    db := model.NewDb("./auth.db")
-    db.Setup()
-    passwd, err := bcrypt.GenerateFromPassword([]byte("d5022a"), 5)
-    if err != nil {
-        log.Fatalf("Could not create password: %v", err)
-    }
-    u := model.User{Email: "cmtedouglas@hotmail.com", Password: string(passwd), Name: "Douglas", ID: 1}
-    model.CreateUser(&u, &db)
+	db := model.NewDb("./auth.db")
+	db.Setup()
+	passwd, err := bcrypt.GenerateFromPassword([]byte("d5022a"), 5)
+	if err != nil {
+		log.Fatalf("Could not create password: %v", err)
+	}
+	u := model.User{Email: "cmtedouglas@hotmail.com", Password: string(passwd), Name: "Douglas", ID: 1}
+	model.CreateUser(&u, &db)
+	logging := log.New(os.Stdout, "AUTH-GO: ", 0)
 
-    routes.Init()
-    
-    http.HandleFunc("/auth/login", routes.Login)
-    http.HandleFunc("/api/users", routes.AuthMiddleware(health_check))
+	r := routes.New(logging, db)
+	ur := routes.UserRoutes{}
+	ar := routes.AuthRoutes{}
 
-    http.ListenAndServe(":8080", nil)
+	ur.Register(&r)
+	ar.Register(&r)
 
-}
+	for _, route := range r.Routes {
+		logging.Printf("Registered [%s] %s protected: %v\n", route.Method, route.Path, route.Authentication)
+		http.HandleFunc(route.Path, route.Handler)
+	}
 
+	logging.Fatalln(http.ListenAndServe(":3535", nil))
 
+}

+ 20 - 0
model/user.go

@@ -7,6 +7,12 @@ type User struct {
     Name string `json:"name"`
 }
 
+type UserDetails struct {
+    ID uint64 `json:"id"`
+    Email string `json:"email"`
+    Name string `json:"name"`
+}
+
 func CreateUser(user *User, db *Db) error {
     statement := "INSERT INTO users (email, password, name) values ($1, $2, $3)"
 
@@ -46,3 +52,17 @@ func GetUser(email string, db *Db) (*User, error) {
     return &user, nil
 
 }
+
+func GetUserById(id uint64, db *Db) (*UserDetails, error) {
+    stmt := "SELECT id, name, email FROM users WHERE id=$1 LIMIT 1"
+    var user UserDetails
+    rows, err := db.conn.Query(stmt, id)
+    for rows.Next() {
+        err = rows.Scan(&user.ID, &user.Name, &user.Email)
+        if err != nil {
+            return nil, err
+        }
+    }
+
+    return &user, nil
+}

+ 110 - 100
routes/auth.go

@@ -7,130 +7,140 @@ import (
 	"net/http"
 
 	"github.com/andreanidouglas/auth/model"
-	"github.com/gorilla/securecookie"
-	"golang.org/x/crypto/bcrypt"
 
+	"github.com/gorilla/securecookie"
 	"github.com/gorilla/sessions"
+	"golang.org/x/crypto/bcrypt"
 )
 
 type user struct {
-    Email string `json:"email"`
-    Password string `jsob:"password"`
+	Email    string `json:"email"`
+	Password string `jsob:"password"`
 }
 
 type authenticated struct {
-    Email string
-    Authenticated bool
+	Email         string
+	Authenticated bool
 }
 
 const (
-    AUTH_KEY string =  "session_id"
-    USER_ID string = "user_id"
+	AUTH_KEY string = "session_id"
+	USER_ID  string = "user_id"
 )
 
 var store *sessions.CookieStore
 
-func Init() {
-    auth_key := securecookie.GenerateRandomKey(64)
-    encryption_key := securecookie.GenerateRandomKey(32)
+type AuthRoutes struct{}
 
-    store = sessions.NewCookieStore(
-        auth_key,
-        encryption_key,
-    )
+func (a *AuthRoutes) Register(r *Routes) {
+	AuthInit()
+	Login(r)
+}
+
+func AuthInit() {
+	auth_key := securecookie.GenerateRandomKey(64)
+	encryption_key := securecookie.GenerateRandomKey(32)
 
-    store.Options = &sessions.Options{
-        Path: "/auth",
-        MaxAge: 60 * 15,
-        HttpOnly: true,
-    }
+	store = sessions.NewCookieStore(
+		auth_key,
+		encryption_key,
+	)
 
-    gob.Register(authenticated{})
+	store.Options = &sessions.Options{
+		Path:     "/auth",
+		MaxAge:   60 * 15,
+		HttpOnly: true,
+	}
+
+	gob.Register(authenticated{})
 }
 
 func getUser(s *sessions.Session) authenticated {
-    val := s.Values["user"]
-    var user = authenticated{}
-    user, ok := val.(authenticated)
-    if !ok {
-        return authenticated{Authenticated: false}
-    }
-    return user
+	val := s.Values["user"]
+	var user = authenticated{}
+	user, ok := val.(authenticated)
+	if !ok {
+		return authenticated{Authenticated: false}
+	}
+	return user
 }
 
 func AuthMiddleware(next http.HandlerFunc) func(http.ResponseWriter, *http.Request) {
-    
-    return func(w http.ResponseWriter, r *http.Request) {
-
-        fmt.Printf("got store: %v", store)
-        session, err := store.Get(r, "cookie-name")
-        if err != nil {
-            w.WriteHeader(500)
-            fmt.Fprintf(w, "Internal Server Error: %v", err)
-            return 
-        }
-
-        authed := getUser(session)
-        if auth := authed.Authenticated; !auth {
-            w.WriteHeader(403)
-            fmt.Fprintf(w, "Unauthorized")
-            return
-        }
-
-        next.ServeHTTP(w, r)
-    }
+
+	return func(w http.ResponseWriter, r *http.Request) {
+
+		fmt.Printf("got store: %v", store)
+		session, err := store.Get(r, "cookie-name")
+		if err != nil {
+			w.WriteHeader(500)
+			fmt.Fprintf(w, "Internal Server Error: %v", err)
+			return
+		}
+
+		authed := getUser(session)
+		if auth := authed.Authenticated; !auth {
+			w.WriteHeader(403)
+			fmt.Fprintf(w, "Unauthorized")
+			return
+		}
+
+		next.ServeHTTP(w, r)
+	}
 }
 
-func Login(w http.ResponseWriter, r *http.Request) {
-    accepts := r.Header.Get("Accepts")
-    if accepts != "application/json" {
-        w.WriteHeader(400)
-        fmt.Fprintf(w, "Could not process request. Incorrect body type")
-        return 
-    }
-
-    sessions, err := store.Get(r, "cookie-name")
-    if err != nil {
-        w.WriteHeader(500)
-        fmt.Fprintf(w, "Internal server error: %v", err)
-    }
-
-    db := model.NewDb("./auth.db")
-    db.Setup()
-
-    var data user
-
-    err = json.NewDecoder(r.Body).Decode(&data)
-    if err != nil {
-        w.WriteHeader(400)
-        fmt.Fprintf(w, "Could not process request. Incorrect body format")
-        return
-    }
-    
-    var user model.User
-    if !model.CheckEmail(data.Email, &user, &db) {
-        w.WriteHeader(403)
-        fmt.Fprintf(w, "Unauthorized")
-        return
-    }
-
-    err = bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(data.Password))
-    if err != nil {
-        w.WriteHeader(403)
-        fmt.Fprintf(w, "Unauthorized")
-        return
-    }
-    authed := authenticated {
-        Email: user.Email,
-        Authenticated: true,
-    }
-    sessions.Values["user"] = authed
-    err = sessions.Save(r, w)
-    if err != nil {
-        w.WriteHeader(500)
-        fmt.Fprintf(w, "Internal Server Error: %v", err)
-    }
-
-    w.WriteHeader(200)
-    fmt.Fprintf(w, "Authorized")
+func Login(route *Routes) {
+
+	handler := func(w http.ResponseWriter, r *http.Request) {
+		accepts := r.Header.Get("Content-Type")
+		if accepts != "application/json" {
+			w.WriteHeader(400)
+			route.logger.Printf("[%s: %s]: 400 [Invalid headers]", r.RemoteAddr, r.RequestURI)
+			fmt.Fprintf(w, "Could not process request. Invalid content type")
+			return
+		}
+
+		sessions, err := store.Get(r, "cookie-name")
+		if err != nil {
+			w.WriteHeader(500)
+			fmt.Fprintf(w, "Internal server error: %v", err)
+		}
+
+		var data user
+
+		err = json.NewDecoder(r.Body).Decode(&data)
+		if err != nil {
+			w.WriteHeader(400)
+			fmt.Fprintf(w, "Could not process request. Incorrect body format")
+			return
+		}
+
+		var user model.User
+		if !model.CheckEmail(data.Email, &user, &route.Pool) {
+			w.WriteHeader(403)
+			fmt.Fprintf(w, "Unauthorized")
+			return
+		}
+
+		err = bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(data.Password))
+		if err != nil {
+			w.WriteHeader(403)
+			fmt.Fprintf(w, "Unauthorized")
+			return
+		}
+		authed := authenticated{
+			Email:         user.Email,
+			Authenticated: true,
+		}
+		sessions.Values["user"] = authed
+		err = sessions.Save(r, w)
+		if err != nil {
+			w.WriteHeader(500)
+			fmt.Fprintf(w, "Internal Server Error: %v", err)
+		}
+
+		w.WriteHeader(200)
+		fmt.Fprintf(w, "Authorized")
+	}
+
+	route.RegisterRoute("/api/login", "POST", false, handler)
 }

+ 94 - 0
routes/routes.go

@@ -0,0 +1,94 @@
+package routes
+
+import (
+	"fmt"
+	"log"
+	"net/http"
+
+	"github.com/andreanidouglas/auth/model"
+)
+
+type Method string
+
+const (
+	GET  Method = "GET"
+	POST Method = "POST"
+)
+
+type Route struct {
+	Path           string
+	Handler        http.HandlerFunc
+	Authentication bool
+	Method         Method
+}
+
+type Routes struct {
+	Pool   model.Db
+	logger *log.Logger
+	Routes []Route
+}
+
+func New(log *log.Logger, db model.Db) Routes {
+
+	return Routes{
+		Pool:   db,
+		logger: log,
+		Routes: make([]Route, 0, 5),
+	}
+
+}
+
+func (r *Routes) RegisterRoute(path string, method Method, authenticated bool, handler func(http.ResponseWriter, *http.Request)) {
+
+	if authenticated {
+		handler = AuthMiddleware(handler)
+	}
+
+	switch method {
+	case GET:
+		{
+			handler = r.Get(handler)
+		}
+	case POST:
+		{
+			handler = r.Post(handler)
+		}
+	}
+
+	r.Routes = append(r.Routes, Route{
+		Path:           path,
+		Authentication: authenticated,
+		Method:         method,
+		Handler:        handler,
+	})
+}
+
+func (self *Routes) Post(next http.HandlerFunc) func(http.ResponseWriter, *http.Request) {
+
+	return func(w http.ResponseWriter, r *http.Request) {
+
+		if r.Method == "POST" {
+			self.logger.Printf("[%s: %s]: 200 [POST]", r.RemoteAddr, r.RequestURI)
+			next.ServeHTTP(w, r)
+		} else {
+			self.logger.Printf("[%s: %s]: 405 [Invalid method]", r.RemoteAddr, r.RequestURI)
+			w.WriteHeader(405)
+			fmt.Fprintln(w, "Invalid Method")
+		}
+	}
+}
+
+func (self *Routes) Get(next http.HandlerFunc) func(http.ResponseWriter, *http.Request) {
+
+	return func(w http.ResponseWriter, r *http.Request) {
+
+		if r.Method == "Get" {
+			self.logger.Printf("[%s: %s]: 200 [GET]", r.RemoteAddr, r.RequestURI)
+			next.ServeHTTP(w, r)
+		} else {
+			self.logger.Printf("[%s: %s]: 405 [Invalid method]", r.RemoteAddr, r.RequestURI)
+			w.WriteHeader(405)
+			fmt.Fprintln(w, "Invalid Method")
+		}
+	}
+}

+ 40 - 3
routes/user.go

@@ -1,8 +1,45 @@
 package routes
 
-import "net/http"
+import (
+	"encoding/json"
+	"fmt"
+	"net/http"
 
+	"github.com/andreanidouglas/auth/model"
+)
 
-func GetUserDetail(w http.ResponseWriter, r *http.Request) {
-    
+type UserRequest struct {
+	ID uint64 `json:"id"`
+}
+
+type UserRoutes struct{}
+
+func (u *UserRoutes) Register(r *Routes) {
+	GetUserDetail(r)
+}
+
+func GetUserDetail(route *Routes) {
+
+	handler := func(w http.ResponseWriter, r *http.Request) {
+		var request_body UserRequest
+
+		json_decoder := json.NewDecoder(r.Body)
+		json_decoder.Decode(&request_body)
+
+		user, err := model.GetUserById(request_body.ID, &route.Pool)
+		if err != nil {
+			w.WriteHeader(500)
+			fmt.Fprintf(w, "Error getting user details: %v", err)
+			return
+		}
+
+		err_json := json.NewEncoder(w).Encode(user)
+		if err_json != nil {
+			w.WriteHeader(500)
+			fmt.Fprintf(w, "Error serializing user: %v", err_json)
+			return
+		}
+	}
+
+	route.RegisterRoute("/api/user", "POST", true, handler)
 }