login added mostly done
This commit is contained in:
parent
20e23ef9c1
commit
57423aaedf
@ -10,11 +10,16 @@ func ApiRoutes() *http.ServeMux {
|
||||
// Take incoming requests and dispatch them to the matching webHandler
|
||||
mux := http.NewServeMux()
|
||||
|
||||
// Register the routes and webHandler
|
||||
// routes
|
||||
mux.HandleFunc("/", handlers.CatchAllHandler)
|
||||
mux.HandleFunc("POST /register", handlers.CreateUser)
|
||||
mux.HandleFunc("GET /check", handlers.CheckRoleHandler)
|
||||
|
||||
//user
|
||||
mux.HandleFunc("GET /user/{id}", handlers.GetUser)
|
||||
|
||||
//auth
|
||||
mux.HandleFunc("POST /login", handlers.Login)
|
||||
mux.HandleFunc("POST /register", handlers.CreateUser)
|
||||
|
||||
return mux
|
||||
}
|
||||
|
||||
@ -17,7 +17,7 @@ func Login(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
if isHtmx == "true" {
|
||||
u = &ent.User{
|
||||
Name: r.PostFormValue("name"),
|
||||
Email: r.PostFormValue("email"),
|
||||
Password: r.PostFormValue("password"),
|
||||
}
|
||||
} else {
|
||||
@ -35,12 +35,18 @@ func Login(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
if bcrypt.CheckPasswordHash(u.Password, User.Password) {
|
||||
|
||||
jwtToken := jwt.CreateUserJWT(u.Name, u.ID, string(u.Role))
|
||||
jwtToken := jwt.CreateUserJWT(User.Name, User.ID, string(User.Role))
|
||||
|
||||
if jwtToken != "" {
|
||||
w.Header().Set("HX-Location", "/")
|
||||
|
||||
cookie := &http.Cookie{Name: "jwt", Value: jwtToken, HttpOnly: true, Secure: true, SameSite: http.SameSiteStrictMode}
|
||||
cookie := &http.Cookie{Name: "jwt",
|
||||
Value: jwtToken,
|
||||
//HttpOnly: true,
|
||||
//Secure: true,
|
||||
//SameSite: http.SameSiteNoneMode,
|
||||
//Expires: time.Now().Add(24 * time.Hour),
|
||||
}
|
||||
|
||||
http.SetCookie(w, cookie)
|
||||
|
||||
w.WriteHeader(http.StatusOK)
|
||||
|
||||
@ -1,6 +1,10 @@
|
||||
package handlers
|
||||
|
||||
import "net/http"
|
||||
import (
|
||||
"net/http"
|
||||
"portfolio/api/service/jwt"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
func CatchAllHandler(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(http.StatusGone)
|
||||
@ -9,3 +13,20 @@ func CatchAllHandler(w http.ResponseWriter, r *http.Request) {
|
||||
InternalServerErrorHandler(w, err)
|
||||
}
|
||||
}
|
||||
|
||||
func CheckRoleHandler(w http.ResponseWriter, r *http.Request) {
|
||||
jwtCookie, _ := r.Cookie("jwt")
|
||||
|
||||
if jwtCookie != nil {
|
||||
uid, audience, err := jwt.VerifyJWT(jwtCookie.Value)
|
||||
if err != nil {
|
||||
InternalServerErrorHandler(w, err)
|
||||
return
|
||||
}
|
||||
w.WriteHeader(http.StatusOK)
|
||||
w.Write([]byte("id: " + strconv.Itoa(uid) + "\naudience: " + audience))
|
||||
return
|
||||
}
|
||||
w.WriteHeader(http.StatusUnprocessableEntity)
|
||||
w.Write([]byte("Cookie not found"))
|
||||
}
|
||||
|
||||
@ -12,7 +12,7 @@ import (
|
||||
func GetLogin(ctx context.Context, U *ent.User) (*ent.User, error) {
|
||||
u, err := database.Client.User.
|
||||
Query().
|
||||
Where(user.Name(U.Name)).
|
||||
Where(user.Email(U.Email)).
|
||||
Only(ctx)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed querying user: %w", err)
|
||||
|
||||
2
go.mod
2
go.mod
@ -9,6 +9,7 @@ require (
|
||||
github.com/joho/godotenv v1.5.1
|
||||
github.com/lib/pq v1.10.9
|
||||
github.com/maragudk/gomponents v0.20.2
|
||||
github.com/maragudk/gomponents-htmx v0.5.0
|
||||
github.com/willoma/bulma-gomponents v0.11.1
|
||||
github.com/willoma/gomplements v0.6.1
|
||||
golang.org/x/crypto v0.23.0
|
||||
@ -23,6 +24,7 @@ require (
|
||||
github.com/google/uuid v1.6.0 // indirect
|
||||
github.com/hashicorp/hcl/v2 v2.19.1 // indirect
|
||||
github.com/mitchellh/go-wordwrap v1.0.1 // indirect
|
||||
github.com/rs/cors v1.11.0 // indirect
|
||||
github.com/zclconf/go-cty v1.14.2 // indirect
|
||||
golang.org/x/mod v0.17.0 // indirect
|
||||
golang.org/x/text v0.15.0 // indirect
|
||||
|
||||
4
go.sum
4
go.sum
@ -36,12 +36,16 @@ github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw=
|
||||
github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
||||
github.com/maragudk/gomponents v0.20.2 h1:39FhnBNNCJzqNcD9Hmvp/5xj0otweFoyvVgFG6kXoy0=
|
||||
github.com/maragudk/gomponents v0.20.2/go.mod h1:nHkNnZL6ODgMBeJhrZjkMHVvNdoYsfmpKB2/hjdQ0Hg=
|
||||
github.com/maragudk/gomponents-htmx v0.5.0 h1:sWtiRa72YmymgxccjTNZW3h0akKsZvnhYke9RQiS9dk=
|
||||
github.com/maragudk/gomponents-htmx v0.5.0/go.mod h1:XgI7WE6ECWlyeVQ9Ix3R6aoKS4HtCSYtuQ4iH27GVDE=
|
||||
github.com/mattn/go-sqlite3 v1.14.16 h1:yOQRA0RpS5PFz/oikGwBEqvAWhWg5ufRz4ETLjwpU1Y=
|
||||
github.com/mattn/go-sqlite3 v1.14.16/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
|
||||
github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0=
|
||||
github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/rs/cors v1.11.0 h1:0B9GE/r9Bc2UxRMMtymBkHTenPkHDv0CW4Y98GBY+po=
|
||||
github.com/rs/cors v1.11.0/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU=
|
||||
github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ=
|
||||
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
|
||||
github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
|
||||
|
||||
@ -27,6 +27,8 @@ github.com/jessevdk/go-flags v1.5.0 h1:1jKYvbxEjfUl0fmqTCOfonvskHHXMjBySTLW4y9LF
|
||||
github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4=
|
||||
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
||||
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
||||
github.com/maragudk/is v0.1.0 h1:obq9anZNmOYcaNbeT0LMyjIexdNeYTw/TLAPD/BnZHA=
|
||||
github.com/maragudk/is v0.1.0/go.mod h1:W/r6+TpnISu+a88OLXQy5JQGCOhXQXXLD2e5b4xMn5c=
|
||||
github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ=
|
||||
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||
github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0=
|
||||
|
||||
19
main.go
19
main.go
@ -2,6 +2,7 @@ package main
|
||||
|
||||
import (
|
||||
"github.com/joho/godotenv"
|
||||
"github.com/rs/cors"
|
||||
"log"
|
||||
"net/http"
|
||||
"portfolio/api"
|
||||
@ -23,11 +24,25 @@ func main() {
|
||||
//init web routes
|
||||
webMux := web.WebRoutes()
|
||||
// Run web server
|
||||
go http.ListenAndServe(":4000", webMux)
|
||||
go http.ListenAndServe(":4000", cors.AllowAll().Handler(webMux))
|
||||
|
||||
c := cors.New(cors.Options{
|
||||
AllowedOrigins: []string{"*"},
|
||||
AllowedMethods: []string{
|
||||
http.MethodHead,
|
||||
http.MethodGet,
|
||||
http.MethodPost,
|
||||
http.MethodPut,
|
||||
http.MethodPatch,
|
||||
http.MethodDelete,
|
||||
},
|
||||
AllowedHeaders: []string{"*"},
|
||||
AllowCredentials: true,
|
||||
})
|
||||
|
||||
//init api routes
|
||||
apiMux := api.ApiRoutes()
|
||||
//run api server
|
||||
http.ListenAndServe(":4001", apiMux)
|
||||
http.ListenAndServe(":4001", c.Handler(apiMux))
|
||||
|
||||
}
|
||||
|
||||
42
web/components/inputs.go
Normal file
42
web/components/inputs.go
Normal file
@ -0,0 +1,42 @@
|
||||
package components
|
||||
|
||||
import (
|
||||
"github.com/delaneyj/gomponents-iconify/iconify/mdi"
|
||||
g "github.com/maragudk/gomponents"
|
||||
b "github.com/willoma/bulma-gomponents"
|
||||
e "github.com/willoma/gomplements"
|
||||
)
|
||||
|
||||
func Email(valid bool, invalid bool, color e.Element) e.Element {
|
||||
return b.Field(
|
||||
b.Label("Email"),
|
||||
b.Control(
|
||||
b.IconsLeft,
|
||||
b.InputEmail(
|
||||
e.Name("email"),
|
||||
color,
|
||||
e.Placeholder("Email input"),
|
||||
),
|
||||
b.Icon(mdi.Email(), b.Left),
|
||||
),
|
||||
g.If(invalid, b.Help(b.Danger, "This email is invalid")),
|
||||
g.If(valid, b.Help(b.Success, "This email is valid")),
|
||||
)
|
||||
}
|
||||
|
||||
func Password(valid bool, invalid bool, color e.Element) e.Element {
|
||||
return b.Field(
|
||||
b.Label("Email"),
|
||||
b.Control(
|
||||
b.IconsLeft,
|
||||
b.InputPassword(
|
||||
e.Name("password"),
|
||||
color,
|
||||
e.Placeholder("password input"),
|
||||
),
|
||||
b.Icon(mdi.FormTextboxPassword(), b.Left),
|
||||
),
|
||||
g.If(invalid, b.Help(b.Danger, "This password is invalid")),
|
||||
g.If(valid, b.Help(b.Success, "This password is valid")),
|
||||
)
|
||||
}
|
||||
23
web/components/login.go
Normal file
23
web/components/login.go
Normal file
@ -0,0 +1,23 @@
|
||||
package components
|
||||
|
||||
import (
|
||||
g "github.com/maragudk/gomponents"
|
||||
hx "github.com/maragudk/gomponents-htmx"
|
||||
. "github.com/maragudk/gomponents/html"
|
||||
b "github.com/willoma/bulma-gomponents"
|
||||
)
|
||||
|
||||
func Login() g.Node {
|
||||
return FormEl(hx.Post("http://localhost:4001/login"),
|
||||
b.Section(
|
||||
Email(false, false, nil),
|
||||
Password(false, false, nil),
|
||||
b.Field(
|
||||
b.Grouped,
|
||||
b.Control(
|
||||
b.Button(b.Link, "login"),
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
@ -35,7 +35,8 @@ func Navbar() g.Node {
|
||||
b.NavbarEnd(
|
||||
b.NavbarItem(
|
||||
b.Buttons(
|
||||
b.ButtonA(
|
||||
b.ButtonAHref(
|
||||
"/login",
|
||||
b.Primary,
|
||||
"Log in",
|
||||
),
|
||||
|
||||
@ -8,7 +8,7 @@ import (
|
||||
|
||||
func AboutPageHandler(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
err := Page("Homepage", createAboutBody(w, r)).Render(w)
|
||||
err := Page("About page", createAboutBody(w, r)).Render(w)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
22
web/handlers/loginPageHandler.go
Normal file
22
web/handlers/loginPageHandler.go
Normal file
@ -0,0 +1,22 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
g "github.com/maragudk/gomponents"
|
||||
. "github.com/maragudk/gomponents/html"
|
||||
"net/http"
|
||||
"portfolio/web/components"
|
||||
)
|
||||
|
||||
func LoginPageHandler(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
err := Page("login page", createLoginBody(w, r)).Render(w)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func createLoginBody(w http.ResponseWriter, r *http.Request) g.Node {
|
||||
|
||||
return Body(components.Login())
|
||||
}
|
||||
@ -14,6 +14,7 @@ func Page(title string, body g.Node) g.Node {
|
||||
Language: "en",
|
||||
Head: []g.Node{
|
||||
Script(Src("https://cdn.tailwindcss.com?plugins=typography")),
|
||||
Script(Src("https://unpkg.com/htmx.org")),
|
||||
Link(Rel("icon"), Type("image/x-icon"), Href("assets/images/favicon.ico")),
|
||||
//Link(Rel("stylesheet"), Href("https://cdn.jsdelivr.net/npm/bulma@1.0.0/css/bulma.min.css")),
|
||||
Link(Rel("stylesheet"), Href("assets/css/style.css")),
|
||||
|
||||
@ -10,7 +10,7 @@ import (
|
||||
|
||||
func ProjectPageHandler(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
err := Page("Homepage", createProjectBody(w, r)).Render(w)
|
||||
err := Page("Project page", createProjectBody(w, r)).Render(w)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
@ -14,6 +14,7 @@ func WebRoutes() *http.ServeMux {
|
||||
mux.HandleFunc("/", handlers.HomePageHandler)
|
||||
mux.HandleFunc("/projects", handlers.ProjectPageHandler)
|
||||
mux.HandleFunc("/about", handlers.AboutPageHandler)
|
||||
mux.HandleFunc("/login", handlers.LoginPageHandler)
|
||||
|
||||
mux.Handle("/assets/", http.StripPrefix("/assets/", http.FileServer(http.Dir("./web/assets"))))
|
||||
return mux
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user