login added mostly done

This commit is contained in:
darius 2024-05-19 23:56:53 +02:00
parent 20e23ef9c1
commit 57423aaedf
16 changed files with 158 additions and 13 deletions

View File

@ -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
}

View File

@ -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)

View File

@ -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"))
}

View File

@ -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
View File

@ -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
View File

@ -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=

View File

@ -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
View File

@ -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
View 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
View 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"),
),
),
),
)
}

View File

@ -35,7 +35,8 @@ func Navbar() g.Node {
b.NavbarEnd(
b.NavbarItem(
b.Buttons(
b.ButtonA(
b.ButtonAHref(
"/login",
b.Primary,
"Log in",
),

View File

@ -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
}

View 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())
}

View File

@ -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")),

View File

@ -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
}

View File

@ -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