diff options
| author | nsfisis <nsfisis@gmail.com> | 2024-07-27 21:07:16 +0900 |
|---|---|---|
| committer | nsfisis <nsfisis@gmail.com> | 2024-07-27 21:07:16 +0900 |
| commit | 3ca36032c7aabbc7b8cee8f0f59d18d1264242ae (patch) | |
| tree | de34134feb14d53f3a31e34ab8e2d8c9af9adc67 /backend | |
| parent | b70fa3abf9c96871cc3e39090e9a00da4ad87b8b (diff) | |
| download | iosdc-japan-2025-albatross-3ca36032c7aabbc7b8cee8f0f59d18d1264242ae.tar.gz iosdc-japan-2025-albatross-3ca36032c7aabbc7b8cee8f0f59d18d1264242ae.tar.zst iosdc-japan-2025-albatross-3ca36032c7aabbc7b8cee8f0f59d18d1264242ae.zip | |
backend: jwt
Diffstat (limited to 'backend')
| -rw-r--r-- | backend/auth/auth.go (renamed from backend/auth.go) | 6 | ||||
| -rw-r--r-- | backend/auth/jwt.go | 54 | ||||
| -rw-r--r-- | backend/db/query.sql.go | 31 | ||||
| -rw-r--r-- | backend/go.mod | 6 | ||||
| -rw-r--r-- | backend/go.sum | 15 | ||||
| -rw-r--r-- | backend/main.go | 17 | ||||
| -rw-r--r-- | backend/query.sql | 10 |
7 files changed, 118 insertions, 21 deletions
diff --git a/backend/auth.go b/backend/auth/auth.go index 7cf0c58..40e54a6 100644 --- a/backend/auth.go +++ b/backend/auth/auth.go @@ -1,4 +1,4 @@ -package main +package auth import ( "context" @@ -7,8 +7,8 @@ import ( "github.com/nsfisis/iosdc-2024-albatross-backend/db" ) -func authLogin(ctx context.Context, queries *db.Queries, username, password string) (int, error) { - userAuth, err := queries.GetUserAuthFromUsername(ctx, username) +func Login(ctx context.Context, queries *db.Queries, username, password string) (int, error) { + userAuth, err := queries.GetUserAuthByUsername(ctx, username) if err != nil { return 0, err } diff --git a/backend/auth/jwt.go b/backend/auth/jwt.go new file mode 100644 index 0000000..aa35de6 --- /dev/null +++ b/backend/auth/jwt.go @@ -0,0 +1,54 @@ +package auth + +import ( + "time" + + "github.com/golang-jwt/jwt/v5" + echojwt "github.com/labstack/echo-jwt/v4" + "github.com/labstack/echo/v4" + + "github.com/nsfisis/iosdc-2024-albatross-backend/db" +) + +type JWTClaims struct { + UserID int `json:"user_id"` + Username string `json:"username"` + DisplayUsername string `json:"display_username"` + IconPath *string `json:"icon_path"` + IsAdmin bool `json:"is_admin"` + jwt.RegisteredClaims +} + +func NewJWT(user *db.User) (string, error) { + var iconPath *string + if user.IconPath.Valid { + iconPath = &user.IconPath.String + } + claims := &JWTClaims{ + UserID: int(user.UserID), + Username: user.Username, + DisplayUsername: user.DisplayUsername, + IconPath: iconPath, + IsAdmin: user.IsAdmin, + RegisteredClaims: jwt.RegisteredClaims{ + ExpiresAt: jwt.NewNumericDate(time.Now().Add(time.Hour * 24)), + }, + } + token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims) + return token.SignedString([]byte("TODO")) +} + +func NewJWTMiddleware() echo.MiddlewareFunc { + return echojwt.WithConfig(echojwt.Config{ + NewClaimsFunc: func(c echo.Context) jwt.Claims { + return new(JWTClaims) + }, + SigningKey: []byte("TODO"), + }) +} + +func GetJWTClaimsFromEchoContext(c echo.Context) *JWTClaims { + user := c.Get("user").(*jwt.Token) + claims := user.Claims.(*JWTClaims) + return claims +} diff --git a/backend/db/query.sql.go b/backend/db/query.sql.go index 5c4f910..72c6502 100644 --- a/backend/db/query.sql.go +++ b/backend/db/query.sql.go @@ -11,13 +11,14 @@ import ( "github.com/jackc/pgx/v5/pgtype" ) -const getUserAuthFromUsername = `-- name: GetUserAuthFromUsername :one +const getUserAuthByUsername = `-- name: GetUserAuthByUsername :one SELECT users.user_id, username, display_username, icon_path, is_admin, created_at, user_auth_id, user_auths.user_id, auth_type, password_hash FROM users JOIN user_auths ON users.user_id = user_auths.user_id WHERE users.username = $1 +LIMIT 1 ` -type GetUserAuthFromUsernameRow struct { +type GetUserAuthByUsernameRow struct { UserID int32 Username string DisplayUsername string @@ -30,9 +31,9 @@ type GetUserAuthFromUsernameRow struct { PasswordHash pgtype.Text } -func (q *Queries) GetUserAuthFromUsername(ctx context.Context, username string) (GetUserAuthFromUsernameRow, error) { - row := q.db.QueryRow(ctx, getUserAuthFromUsername, username) - var i GetUserAuthFromUsernameRow +func (q *Queries) GetUserAuthByUsername(ctx context.Context, username string) (GetUserAuthByUsernameRow, error) { + row := q.db.QueryRow(ctx, getUserAuthByUsername, username) + var i GetUserAuthByUsernameRow err := row.Scan( &i.UserID, &i.Username, @@ -47,3 +48,23 @@ func (q *Queries) GetUserAuthFromUsername(ctx context.Context, username string) ) return i, err } + +const getUserById = `-- name: GetUserById :one +SELECT user_id, username, display_username, icon_path, is_admin, created_at FROM users +WHERE users.user_id = $1 +LIMIT 1 +` + +func (q *Queries) GetUserById(ctx context.Context, userID int32) (User, error) { + row := q.db.QueryRow(ctx, getUserById, userID) + var i User + err := row.Scan( + &i.UserID, + &i.Username, + &i.DisplayUsername, + &i.IconPath, + &i.IsAdmin, + &i.CreatedAt, + ) + return i, err +} diff --git a/backend/go.mod b/backend/go.mod index 38020c7..4203c35 100644 --- a/backend/go.mod +++ b/backend/go.mod @@ -3,8 +3,11 @@ module github.com/nsfisis/iosdc-2024-albatross-backend go 1.22.3 require ( + github.com/golang-jwt/jwt/v5 v5.2.1 github.com/gorilla/websocket v1.5.3 github.com/jackc/pgx/v5 v5.5.5 + github.com/labstack/echo-jwt/v4 v4.2.0 + github.com/labstack/echo/v4 v4.12.0 github.com/sqlc-dev/sqlc v1.26.0 ) @@ -17,6 +20,7 @@ require ( github.com/dustin/go-humanize v1.0.1 // indirect github.com/fatih/structtag v1.2.0 // indirect github.com/go-sql-driver/mysql v1.8.1 // indirect + github.com/golang-jwt/jwt v3.2.2+incompatible // indirect github.com/golang/protobuf v1.5.3 // indirect github.com/google/cel-go v0.20.1 // indirect github.com/google/uuid v1.6.0 // indirect @@ -26,7 +30,6 @@ require ( github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect github.com/jackc/puddle/v2 v2.2.1 // indirect github.com/jinzhu/inflection v1.0.0 // indirect - github.com/labstack/echo/v4 v4.12.0 // indirect github.com/labstack/gommon v0.4.2 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect @@ -54,6 +57,7 @@ require ( golang.org/x/sync v0.6.0 // indirect golang.org/x/sys v0.19.0 // indirect golang.org/x/text v0.14.0 // indirect + golang.org/x/time v0.5.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20240123012728-ef4313101c80 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 // indirect google.golang.org/grpc v1.62.1 // indirect diff --git a/backend/go.sum b/backend/go.sum index 29c1143..38a504b 100644 --- a/backend/go.sum +++ b/backend/go.sum @@ -18,6 +18,10 @@ github.com/fatih/structtag v1.2.0 h1:/OdNE99OxoI/PqaW/SuSK9uxxT3f/tcSZgon/ssNSx4 github.com/fatih/structtag v1.2.0/go.mod h1:mBJUNpUnHmRKrKlQQlmCrh5PuhftFbNv8Ys4/aAZl94= github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y= github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg= +github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY= +github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= +github.com/golang-jwt/jwt/v5 v5.2.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17wHk= +github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= @@ -53,13 +57,14 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/labstack/echo-jwt/v4 v4.2.0 h1:odSISV9JgcSCuhgQSV/6Io3i7nUmfM/QkBeR5GVJj5c= +github.com/labstack/echo-jwt/v4 v4.2.0/go.mod h1:MA2RqdXdEn4/uEglx0HcUOgQSyBaTh5JcaHIan3biwU= github.com/labstack/echo/v4 v4.12.0 h1:IKpw49IMryVB2p1a4dzwlhP1O2Tf2E0Ir/450lH+kI0= github.com/labstack/echo/v4 v4.12.0/go.mod h1:UP9Cr2DJXbOK3Kr9ONYzNowSh7HP0aG0ShAyycHSJvM= github.com/labstack/gommon v0.4.2 h1:F8qTUNXgG1+6WQmqoUWnz8WiEU60mXVVw0P4ht1WRA0= github.com/labstack/gommon v0.4.2/go.mod h1:QlUFxVM+SNXhDL/Z7YhocGIBYOiwB0mXm1+1bAPHPyU= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= -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-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= @@ -130,8 +135,6 @@ go.uber.org/zap v1.19.0/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo= go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.20.0 h1:jmAMJJZXr5KiCw05dfYK9QnqaqKLYXijU23lsEdcQqg= -golang.org/x/crypto v0.20.0/go.mod h1:Xwo95rrVNIoSMx9wa1JroENMToLWn3RNVrTBpLHgZPQ= golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30= golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M= golang.org/x/exp v0.0.0-20231108232855-2478ac86f678 h1:mchzmB1XO2pMaKFRqk/+MV3mgGG96aqaPXaMifQU47w= @@ -141,8 +144,6 @@ golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0= golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4= -golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -151,13 +152,13 @@ golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y= -golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= +golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= diff --git a/backend/main.go b/backend/main.go index 26859e5..e878bed 100644 --- a/backend/main.go +++ b/backend/main.go @@ -11,6 +11,7 @@ import ( "github.com/jackc/pgx/v5" "github.com/labstack/echo/v4" + "github.com/nsfisis/iosdc-2024-albatross-backend/auth" "github.com/nsfisis/iosdc-2024-albatross-backend/db" ) @@ -123,7 +124,7 @@ func handleApiLogin(c echo.Context, queries *db.Queries) error { } type LoginResponseData struct { - UserId int `json:"userId"` + Token string `json:"token"` } ctx := c.Request().Context() @@ -133,13 +134,23 @@ func handleApiLogin(c echo.Context, queries *db.Queries) error { return echo.NewHTTPError(http.StatusBadRequest, err.Error()) } - userId, err := authLogin(ctx, queries, requestData.Username, requestData.Password) + userId, err := auth.Login(ctx, queries, requestData.Username, requestData.Password) if err != nil { return echo.NewHTTPError(http.StatusUnauthorized, err.Error()) } + user, err := queries.GetUserById(ctx, int32(userId)) + if err != nil { + return echo.NewHTTPError(http.StatusInternalServerError, err.Error()) + } + + jwt, err := auth.NewJWT(&user) + if err != nil { + return echo.NewHTTPError(http.StatusInternalServerError, err.Error()) + } + responseData := LoginResponseData{ - UserId: userId, + Token: jwt, } return c.JSON(http.StatusOK, responseData) diff --git a/backend/query.sql b/backend/query.sql index bdcd657..165c2c9 100644 --- a/backend/query.sql +++ b/backend/query.sql @@ -1,4 +1,10 @@ --- name: GetUserAuthFromUsername :one +-- name: GetUserById :one +SELECT * FROM users +WHERE users.user_id = $1 +LIMIT 1; + +-- name: GetUserAuthByUsername :one SELECT * FROM users JOIN user_auths ON users.user_id = user_auths.user_id -WHERE users.username = $1; +WHERE users.username = $1 +LIMIT 1; |
