Merge branch 'dev' of ssh://meowgit.nekoea.red:22222/nihonium/nyanimedb into dev
This commit is contained in:
commit
e67c9a77ce
7 changed files with 293 additions and 134 deletions
115
auth/auth.gen.go
115
auth/auth.gen.go
|
|
@ -13,6 +13,23 @@ import (
|
||||||
strictgin "github.com/oapi-codegen/runtime/strictmiddleware/gin"
|
strictgin "github.com/oapi-codegen/runtime/strictmiddleware/gin"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
BearerAuthScopes = "bearerAuth.Scopes"
|
||||||
|
)
|
||||||
|
|
||||||
|
// GetImpersonationTokenJSONBody defines parameters for GetImpersonationToken.
|
||||||
|
type GetImpersonationTokenJSONBody struct {
|
||||||
|
ExternalId *int64 `json:"external_id,omitempty"`
|
||||||
|
UserId *int64 `json:"user_id,omitempty"`
|
||||||
|
union json.RawMessage
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetImpersonationTokenJSONBody0 defines parameters for GetImpersonationToken.
|
||||||
|
type GetImpersonationTokenJSONBody0 = interface{}
|
||||||
|
|
||||||
|
// GetImpersonationTokenJSONBody1 defines parameters for GetImpersonationToken.
|
||||||
|
type GetImpersonationTokenJSONBody1 = interface{}
|
||||||
|
|
||||||
// PostSignInJSONBody defines parameters for PostSignIn.
|
// PostSignInJSONBody defines parameters for PostSignIn.
|
||||||
type PostSignInJSONBody struct {
|
type PostSignInJSONBody struct {
|
||||||
Nickname string `json:"nickname"`
|
Nickname string `json:"nickname"`
|
||||||
|
|
@ -25,6 +42,9 @@ type PostSignUpJSONBody struct {
|
||||||
Pass string `json:"pass"`
|
Pass string `json:"pass"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetImpersonationTokenJSONRequestBody defines body for GetImpersonationToken for application/json ContentType.
|
||||||
|
type GetImpersonationTokenJSONRequestBody GetImpersonationTokenJSONBody
|
||||||
|
|
||||||
// PostSignInJSONRequestBody defines body for PostSignIn for application/json ContentType.
|
// PostSignInJSONRequestBody defines body for PostSignIn for application/json ContentType.
|
||||||
type PostSignInJSONRequestBody PostSignInJSONBody
|
type PostSignInJSONRequestBody PostSignInJSONBody
|
||||||
|
|
||||||
|
|
@ -33,6 +53,9 @@ type PostSignUpJSONRequestBody PostSignUpJSONBody
|
||||||
|
|
||||||
// ServerInterface represents all server handlers.
|
// ServerInterface represents all server handlers.
|
||||||
type ServerInterface interface {
|
type ServerInterface interface {
|
||||||
|
// Get service impersontaion token
|
||||||
|
// (POST /get-impersonation-token)
|
||||||
|
GetImpersonationToken(c *gin.Context)
|
||||||
// Sign in a user and return JWT
|
// Sign in a user and return JWT
|
||||||
// (POST /sign-in)
|
// (POST /sign-in)
|
||||||
PostSignIn(c *gin.Context)
|
PostSignIn(c *gin.Context)
|
||||||
|
|
@ -50,6 +73,21 @@ type ServerInterfaceWrapper struct {
|
||||||
|
|
||||||
type MiddlewareFunc func(c *gin.Context)
|
type MiddlewareFunc func(c *gin.Context)
|
||||||
|
|
||||||
|
// GetImpersonationToken operation middleware
|
||||||
|
func (siw *ServerInterfaceWrapper) GetImpersonationToken(c *gin.Context) {
|
||||||
|
|
||||||
|
c.Set(BearerAuthScopes, []string{})
|
||||||
|
|
||||||
|
for _, middleware := range siw.HandlerMiddlewares {
|
||||||
|
middleware(c)
|
||||||
|
if c.IsAborted() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
siw.Handler.GetImpersonationToken(c)
|
||||||
|
}
|
||||||
|
|
||||||
// PostSignIn operation middleware
|
// PostSignIn operation middleware
|
||||||
func (siw *ServerInterfaceWrapper) PostSignIn(c *gin.Context) {
|
func (siw *ServerInterfaceWrapper) PostSignIn(c *gin.Context) {
|
||||||
|
|
||||||
|
|
@ -103,10 +141,41 @@ func RegisterHandlersWithOptions(router gin.IRouter, si ServerInterface, options
|
||||||
ErrorHandler: errorHandler,
|
ErrorHandler: errorHandler,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
router.POST(options.BaseURL+"/get-impersonation-token", wrapper.GetImpersonationToken)
|
||||||
router.POST(options.BaseURL+"/sign-in", wrapper.PostSignIn)
|
router.POST(options.BaseURL+"/sign-in", wrapper.PostSignIn)
|
||||||
router.POST(options.BaseURL+"/sign-up", wrapper.PostSignUp)
|
router.POST(options.BaseURL+"/sign-up", wrapper.PostSignUp)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type UnauthorizedErrorResponse struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
type GetImpersonationTokenRequestObject struct {
|
||||||
|
Body *GetImpersonationTokenJSONRequestBody
|
||||||
|
}
|
||||||
|
|
||||||
|
type GetImpersonationTokenResponseObject interface {
|
||||||
|
VisitGetImpersonationTokenResponse(w http.ResponseWriter) error
|
||||||
|
}
|
||||||
|
|
||||||
|
type GetImpersonationToken200JSONResponse struct {
|
||||||
|
// AccessToken JWT access token
|
||||||
|
AccessToken string `json:"access_token"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (response GetImpersonationToken200JSONResponse) VisitGetImpersonationTokenResponse(w http.ResponseWriter) error {
|
||||||
|
w.Header().Set("Content-Type", "application/json")
|
||||||
|
w.WriteHeader(200)
|
||||||
|
|
||||||
|
return json.NewEncoder(w).Encode(response)
|
||||||
|
}
|
||||||
|
|
||||||
|
type GetImpersonationToken401Response = UnauthorizedErrorResponse
|
||||||
|
|
||||||
|
func (response GetImpersonationToken401Response) VisitGetImpersonationTokenResponse(w http.ResponseWriter) error {
|
||||||
|
w.WriteHeader(401)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
type PostSignInRequestObject struct {
|
type PostSignInRequestObject struct {
|
||||||
Body *PostSignInJSONRequestBody
|
Body *PostSignInJSONRequestBody
|
||||||
}
|
}
|
||||||
|
|
@ -127,15 +196,11 @@ func (response PostSignIn200JSONResponse) VisitPostSignInResponse(w http.Respons
|
||||||
return json.NewEncoder(w).Encode(response)
|
return json.NewEncoder(w).Encode(response)
|
||||||
}
|
}
|
||||||
|
|
||||||
type PostSignIn401JSONResponse struct {
|
type PostSignIn401Response = UnauthorizedErrorResponse
|
||||||
Error *string `json:"error,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (response PostSignIn401JSONResponse) VisitPostSignInResponse(w http.ResponseWriter) error {
|
func (response PostSignIn401Response) VisitPostSignInResponse(w http.ResponseWriter) error {
|
||||||
w.Header().Set("Content-Type", "application/json")
|
|
||||||
w.WriteHeader(401)
|
w.WriteHeader(401)
|
||||||
|
return nil
|
||||||
return json.NewEncoder(w).Encode(response)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type PostSignUpRequestObject struct {
|
type PostSignUpRequestObject struct {
|
||||||
|
|
@ -159,6 +224,9 @@ func (response PostSignUp200JSONResponse) VisitPostSignUpResponse(w http.Respons
|
||||||
|
|
||||||
// StrictServerInterface represents all server handlers.
|
// StrictServerInterface represents all server handlers.
|
||||||
type StrictServerInterface interface {
|
type StrictServerInterface interface {
|
||||||
|
// Get service impersontaion token
|
||||||
|
// (POST /get-impersonation-token)
|
||||||
|
GetImpersonationToken(ctx context.Context, request GetImpersonationTokenRequestObject) (GetImpersonationTokenResponseObject, error)
|
||||||
// Sign in a user and return JWT
|
// Sign in a user and return JWT
|
||||||
// (POST /sign-in)
|
// (POST /sign-in)
|
||||||
PostSignIn(ctx context.Context, request PostSignInRequestObject) (PostSignInResponseObject, error)
|
PostSignIn(ctx context.Context, request PostSignInRequestObject) (PostSignInResponseObject, error)
|
||||||
|
|
@ -179,6 +247,39 @@ type strictHandler struct {
|
||||||
middlewares []StrictMiddlewareFunc
|
middlewares []StrictMiddlewareFunc
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetImpersonationToken operation middleware
|
||||||
|
func (sh *strictHandler) GetImpersonationToken(ctx *gin.Context) {
|
||||||
|
var request GetImpersonationTokenRequestObject
|
||||||
|
|
||||||
|
var body GetImpersonationTokenJSONRequestBody
|
||||||
|
if err := ctx.ShouldBindJSON(&body); err != nil {
|
||||||
|
ctx.Status(http.StatusBadRequest)
|
||||||
|
ctx.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
request.Body = &body
|
||||||
|
|
||||||
|
handler := func(ctx *gin.Context, request interface{}) (interface{}, error) {
|
||||||
|
return sh.ssi.GetImpersonationToken(ctx, request.(GetImpersonationTokenRequestObject))
|
||||||
|
}
|
||||||
|
for _, middleware := range sh.middlewares {
|
||||||
|
handler = middleware(handler, "GetImpersonationToken")
|
||||||
|
}
|
||||||
|
|
||||||
|
response, err := handler(ctx, request)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
ctx.Error(err)
|
||||||
|
ctx.Status(http.StatusInternalServerError)
|
||||||
|
} else if validResponse, ok := response.(GetImpersonationTokenResponseObject); ok {
|
||||||
|
if err := validResponse.VisitGetImpersonationTokenResponse(ctx.Writer); err != nil {
|
||||||
|
ctx.Error(err)
|
||||||
|
}
|
||||||
|
} else if response != nil {
|
||||||
|
ctx.Error(fmt.Errorf("unexpected response type: %T", response))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// PostSignIn operation middleware
|
// PostSignIn operation middleware
|
||||||
func (sh *strictHandler) PostSignIn(ctx *gin.Context) {
|
func (sh *strictHandler) PostSignIn(ctx *gin.Context) {
|
||||||
var request PostSignInRequestObject
|
var request PostSignInRequestObject
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ paths:
|
||||||
/sign-up:
|
/sign-up:
|
||||||
post:
|
post:
|
||||||
summary: Sign up a new user
|
summary: Sign up a new user
|
||||||
|
operationId: postSignUp
|
||||||
tags: [Auth]
|
tags: [Auth]
|
||||||
requestBody:
|
requestBody:
|
||||||
required: true
|
required: true
|
||||||
|
|
@ -41,6 +42,7 @@ paths:
|
||||||
/sign-in:
|
/sign-in:
|
||||||
post:
|
post:
|
||||||
summary: Sign in a user and return JWT
|
summary: Sign in a user and return JWT
|
||||||
|
operationId: postSignIn
|
||||||
tags: [Auth]
|
tags: [Auth]
|
||||||
requestBody:
|
requestBody:
|
||||||
required: true
|
required: true
|
||||||
|
|
@ -73,88 +75,52 @@ paths:
|
||||||
user_name:
|
user_name:
|
||||||
type: string
|
type: string
|
||||||
"401":
|
"401":
|
||||||
description: Access denied due to invalid credentials
|
$ref: '#/components/responses/UnauthorizedError'
|
||||||
|
|
||||||
|
/get-impersonation-token:
|
||||||
|
post:
|
||||||
|
summary: Get service impersontaion token
|
||||||
|
operationId: getImpersonationToken
|
||||||
|
tags: [Auth]
|
||||||
|
security:
|
||||||
|
- bearerAuth: []
|
||||||
|
requestBody:
|
||||||
|
required: true
|
||||||
content:
|
content:
|
||||||
application/json:
|
application/json:
|
||||||
schema:
|
schema:
|
||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
error:
|
user_id:
|
||||||
|
type: integer
|
||||||
|
format: int64
|
||||||
|
external_id:
|
||||||
|
type: integer
|
||||||
|
format: int64
|
||||||
|
oneOf:
|
||||||
|
- required: ["user_id"]
|
||||||
|
- required: ["external_id"]
|
||||||
|
responses:
|
||||||
|
"200":
|
||||||
|
description: Generated impersonation access token
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
type: object
|
||||||
|
required:
|
||||||
|
- access_token
|
||||||
|
properties:
|
||||||
|
access_token:
|
||||||
type: string
|
type: string
|
||||||
example: "Access denied"
|
description: JWT access token
|
||||||
# /auth/verify-token:
|
"401":
|
||||||
# post:
|
$ref: '#/components/responses/UnauthorizedError'
|
||||||
# summary: Verify JWT validity
|
|
||||||
# tags: [Auth]
|
components:
|
||||||
# requestBody:
|
securitySchemes:
|
||||||
# required: true
|
bearerAuth:
|
||||||
# content:
|
type: http
|
||||||
# application/json:
|
scheme: bearer
|
||||||
# schema:
|
responses:
|
||||||
# type: object
|
UnauthorizedError:
|
||||||
# required: [token]
|
description: Access token is missing or invalid
|
||||||
# properties:
|
|
||||||
# token:
|
|
||||||
# type: string
|
|
||||||
# description: JWT token to validate
|
|
||||||
# responses:
|
|
||||||
# "200":
|
|
||||||
# description: Token validation result
|
|
||||||
# content:
|
|
||||||
# application/json:
|
|
||||||
# schema:
|
|
||||||
# type: object
|
|
||||||
# properties:
|
|
||||||
# valid:
|
|
||||||
# type: boolean
|
|
||||||
# description: True if token is valid
|
|
||||||
# user_id:
|
|
||||||
# type: string
|
|
||||||
# nullable: true
|
|
||||||
# description: User ID extracted from token if valid
|
|
||||||
# error:
|
|
||||||
# type: string
|
|
||||||
# nullable: true
|
|
||||||
# description: Error message if token is invalid
|
|
||||||
# /auth/refresh-token:
|
|
||||||
# post:
|
|
||||||
# summary: Refresh JWT using a refresh token
|
|
||||||
# tags: [Auth]
|
|
||||||
# requestBody:
|
|
||||||
# required: true
|
|
||||||
# content:
|
|
||||||
# application/json:
|
|
||||||
# schema:
|
|
||||||
# type: object
|
|
||||||
# required: [refresh_token]
|
|
||||||
# properties:
|
|
||||||
# refresh_token:
|
|
||||||
# type: string
|
|
||||||
# description: JWT refresh token obtained from sign-in
|
|
||||||
# responses:
|
|
||||||
# "200":
|
|
||||||
# description: New access (and optionally refresh) token
|
|
||||||
# content:
|
|
||||||
# application/json:
|
|
||||||
# schema:
|
|
||||||
# type: object
|
|
||||||
# properties:
|
|
||||||
# valid:
|
|
||||||
# type: boolean
|
|
||||||
# description: True if refresh token was valid
|
|
||||||
# user_id:
|
|
||||||
# type: string
|
|
||||||
# nullable: true
|
|
||||||
# description: User ID extracted from refresh token
|
|
||||||
# access_token:
|
|
||||||
# type: string
|
|
||||||
# description: New access token
|
|
||||||
# nullable: true
|
|
||||||
# refresh_token:
|
|
||||||
# type: string
|
|
||||||
# description: New refresh token (optional)
|
|
||||||
# nullable: true
|
|
||||||
# error:
|
|
||||||
# type: string
|
|
||||||
# nullable: true
|
|
||||||
# description: Error message if refresh token is invalid
|
|
||||||
|
|
@ -47,10 +47,28 @@ func CheckPassword(password, hash string) (bool, error) {
|
||||||
return argon2id.ComparePasswordAndHash(password, hash)
|
return argon2id.ComparePasswordAndHash(password, hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s Server) generateImpersonationToken(userID string, impersonated_by string) (accessToken string, err error) {
|
||||||
|
accessClaims := jwt.MapClaims{
|
||||||
|
"user_id": userID,
|
||||||
|
"exp": time.Now().Add(15 * time.Minute).Unix(),
|
||||||
|
"imp_id": impersonated_by,
|
||||||
|
}
|
||||||
|
|
||||||
|
at := jwt.NewWithClaims(jwt.SigningMethodHS256, accessClaims)
|
||||||
|
|
||||||
|
accessToken, err = at.SignedString([]byte(s.JwtPrivateKey))
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
return accessToken, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (s Server) generateTokens(userID string) (accessToken string, refreshToken string, csrfToken string, err error) {
|
func (s Server) generateTokens(userID string) (accessToken string, refreshToken string, csrfToken string, err error) {
|
||||||
accessClaims := jwt.MapClaims{
|
accessClaims := jwt.MapClaims{
|
||||||
"user_id": userID,
|
"user_id": userID,
|
||||||
"exp": time.Now().Add(15 * time.Minute).Unix(),
|
"exp": time.Now().Add(15 * time.Minute).Unix(),
|
||||||
|
//TODO: add created_at
|
||||||
}
|
}
|
||||||
at := jwt.NewWithClaims(jwt.SigningMethodHS256, accessClaims)
|
at := jwt.NewWithClaims(jwt.SigningMethodHS256, accessClaims)
|
||||||
accessToken, err = at.SignedString([]byte(s.JwtPrivateKey))
|
accessToken, err = at.SignedString([]byte(s.JwtPrivateKey))
|
||||||
|
|
@ -119,10 +137,7 @@ func (s Server) PostSignIn(ctx context.Context, req auth.PostSignInRequestObject
|
||||||
// TODO: return 500
|
// TODO: return 500
|
||||||
}
|
}
|
||||||
if !ok {
|
if !ok {
|
||||||
err_msg := "invalid credentials"
|
return auth.PostSignIn401Response{}, nil
|
||||||
return auth.PostSignIn401JSONResponse{
|
|
||||||
Error: &err_msg,
|
|
||||||
}, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
accessToken, refreshToken, csrfToken, err := s.generateTokens(req.Body.Nickname)
|
accessToken, refreshToken, csrfToken, err := s.generateTokens(req.Body.Nickname)
|
||||||
|
|
@ -144,47 +159,64 @@ func (s Server) PostSignIn(ctx context.Context, req auth.PostSignInRequestObject
|
||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// func (s Server) PostAuthVerifyToken(ctx context.Context, req auth.PostAuthVerifyTokenRequestObject) (auth.PostAuthVerifyTokenResponseObject, error) {
|
func (s Server) GetImpersonationToken(ctx context.Context, req auth.GetImpersonationTokenRequestObject) (auth.GetImpersonationTokenResponseObject, error) {
|
||||||
// valid := false
|
ginCtx, ok := ctx.Value(gin.ContextKey).(*gin.Context)
|
||||||
// var userID *string
|
if !ok {
|
||||||
// var errStr *string
|
log.Print("failed to get gin context")
|
||||||
|
// TODO: change to 500
|
||||||
|
return auth.GetImpersonationToken200JSONResponse{}, fmt.Errorf("failed to get gin.Context from context.Context")
|
||||||
|
}
|
||||||
|
|
||||||
// token, err := jwt.Parse(req.Body.Token, func(t *jwt.Token) (interface{}, error) {
|
token, err := ExtractBearerToken(ginCtx.Request.Header.Get("Authorization"))
|
||||||
// if _, ok := t.Method.(*jwt.SigningMethodHMAC); !ok {
|
if err != nil {
|
||||||
// return nil, fmt.Errorf("unexpected signing method")
|
// TODO: return 500
|
||||||
// }
|
log.Errorf("failed to extract bearer token: %v", err)
|
||||||
// return accessSecret, nil
|
return auth.GetImpersonationToken401Response{}, err
|
||||||
// })
|
}
|
||||||
|
log.Printf("got auth token: %s", token)
|
||||||
|
|
||||||
// if err != nil {
|
ext_service, err := s.db.GetExternalServiceByToken(context.Background(), &token)
|
||||||
// e := err.Error()
|
if err != nil {
|
||||||
// errStr = &e
|
log.Errorf("failed to get external service by token: %v", err)
|
||||||
// return auth.PostAuthVerifyToken200JSONResponse{
|
return auth.GetImpersonationToken401Response{}, err
|
||||||
// Valid: &valid,
|
// TODO: check err and retyrn 400/500
|
||||||
// UserId: userID,
|
}
|
||||||
// Error: errStr,
|
|
||||||
// }, nil
|
|
||||||
// }
|
|
||||||
|
|
||||||
// if claims, ok := token.Claims.(jwt.MapClaims); ok && token.Valid {
|
var user_id string = ""
|
||||||
// if uid, ok := claims["user_id"].(string); ok {
|
|
||||||
// valid = true
|
|
||||||
// userID = &uid
|
|
||||||
// } else {
|
|
||||||
// e := "user_id not found in token"
|
|
||||||
// errStr = &e
|
|
||||||
// }
|
|
||||||
// } else {
|
|
||||||
// e := "invalid token claims"
|
|
||||||
// errStr = &e
|
|
||||||
// }
|
|
||||||
|
|
||||||
// return auth.PostAuthVerifyToken200JSONResponse{
|
if req.Body.ExternalId != nil {
|
||||||
// Valid: &valid,
|
user, err := s.db.GetUserByExternalServiceId(context.Background(), sqlc.GetUserByExternalServiceIdParams{
|
||||||
// UserId: userID,
|
ExternalID: fmt.Sprintf("%d", *req.Body.ExternalId),
|
||||||
// Error: errStr,
|
ServiceID: ext_service.ID,
|
||||||
// }, nil
|
})
|
||||||
// }
|
if err != nil {
|
||||||
|
log.Errorf("failed to get user by external user id: %v", err)
|
||||||
|
return auth.GetImpersonationToken401Response{}, err
|
||||||
|
// TODO: check err and retyrn 400/500
|
||||||
|
}
|
||||||
|
|
||||||
|
user_id = fmt.Sprintf("%d", user.ID)
|
||||||
|
}
|
||||||
|
|
||||||
|
if req.Body.UserId != nil {
|
||||||
|
if user_id != "" && user_id != fmt.Sprintf("%d", *req.Body.UserId) {
|
||||||
|
log.Error("user_id and external_d are incorrect")
|
||||||
|
// TODO: 405
|
||||||
|
return auth.GetImpersonationToken401Response{}, nil
|
||||||
|
} else {
|
||||||
|
user_id = fmt.Sprintf("%d", *req.Body.UserId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
accessToken, err := s.generateImpersonationToken(user_id, fmt.Sprintf("%d", ext_service.ID))
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("failed to generate impersonation token: %v", err)
|
||||||
|
return auth.GetImpersonationToken401Response{}, err
|
||||||
|
// TODO: check err and retyrn 400/500
|
||||||
|
}
|
||||||
|
|
||||||
|
return auth.GetImpersonationToken200JSONResponse{AccessToken: accessToken}, nil
|
||||||
|
}
|
||||||
|
|
||||||
// func (s Server) PostAuthRefreshToken(ctx context.Context, req auth.PostAuthRefreshTokenRequestObject) (auth.PostAuthRefreshTokenResponseObject, error) {
|
// func (s Server) PostAuthRefreshToken(ctx context.Context, req auth.PostAuthRefreshTokenRequestObject) (auth.PostAuthRefreshTokenResponseObject, error) {
|
||||||
// valid := false
|
// valid := false
|
||||||
|
|
@ -236,3 +268,11 @@ func (s Server) PostSignIn(ctx context.Context, req auth.PostSignInRequestObject
|
||||||
// Error: errStr,
|
// Error: errStr,
|
||||||
// }, nil
|
// }, nil
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
func ExtractBearerToken(header string) (string, error) {
|
||||||
|
const prefix = "Bearer "
|
||||||
|
if len(header) <= len(prefix) || header[:len(prefix)] != prefix {
|
||||||
|
return "", fmt.Errorf("invalid bearer token format")
|
||||||
|
}
|
||||||
|
return header[len(prefix):], nil
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,3 +9,13 @@ INTO users (passhash, nickname)
|
||||||
VALUES (sqlc.arg(passhash), sqlc.arg(nickname))
|
VALUES (sqlc.arg(passhash), sqlc.arg(nickname))
|
||||||
RETURNING id;
|
RETURNING id;
|
||||||
|
|
||||||
|
-- name: GetExternalServiceByToken :one
|
||||||
|
SELECT *
|
||||||
|
FROM external_services
|
||||||
|
WHERE auth_token = sqlc.arg('auth_token');
|
||||||
|
|
||||||
|
-- name: GetUserByExternalServiceId :one
|
||||||
|
SELECT u.*
|
||||||
|
FROM users u
|
||||||
|
LEFT JOIN external_ids ei ON eu.user_id = u.id
|
||||||
|
WHERE ei.external_id = sqlc.arg('external_id') AND ei.service_id = sqlc.arg('service_id');
|
||||||
|
|
@ -33,8 +33,6 @@ CREATE TABLE users (
|
||||||
last_login timestamptz
|
last_login timestamptz
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
CREATE TABLE studios (
|
CREATE TABLE studios (
|
||||||
id bigint GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
|
id bigint GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
|
||||||
studio_name text NOT NULL UNIQUE,
|
studio_name text NOT NULL UNIQUE,
|
||||||
|
|
@ -108,12 +106,13 @@ CREATE TABLE signals (
|
||||||
|
|
||||||
CREATE TABLE external_services (
|
CREATE TABLE external_services (
|
||||||
id bigint GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
|
id bigint GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
|
||||||
name text UNIQUE NOT NULL
|
name text UNIQUE NOT NULL,
|
||||||
|
auth_token text
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE TABLE external_ids (
|
CREATE TABLE external_ids (
|
||||||
user_id bigint NOT NULL REFERENCES users (id),
|
user_id bigint NOT NULL REFERENCES users (id),
|
||||||
service_id bigint REFERENCES external_services (id),
|
service_id bigint NOT NULL REFERENCES external_services (id),
|
||||||
external_id text NOT NULL
|
external_id text NOT NULL
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -188,13 +188,14 @@ func (ns NullUsertitleStatusT) Value() (driver.Value, error) {
|
||||||
|
|
||||||
type ExternalID struct {
|
type ExternalID struct {
|
||||||
UserID int64 `json:"user_id"`
|
UserID int64 `json:"user_id"`
|
||||||
ServiceID *int64 `json:"service_id"`
|
ServiceID int64 `json:"service_id"`
|
||||||
ExternalID string `json:"external_id"`
|
ExternalID string `json:"external_id"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type ExternalService struct {
|
type ExternalService struct {
|
||||||
ID int64 `json:"id"`
|
ID int64 `json:"id"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
|
AuthToken *string `json:"auth_token"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type Image struct {
|
type Image struct {
|
||||||
|
|
|
||||||
|
|
@ -76,6 +76,19 @@ func (q *Queries) DeleteUserTitle(ctx context.Context, arg DeleteUserTitleParams
|
||||||
return i, err
|
return i, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const getExternalServiceByToken = `-- name: GetExternalServiceByToken :one
|
||||||
|
SELECT id, name, auth_token
|
||||||
|
FROM external_services
|
||||||
|
WHERE auth_token = $1
|
||||||
|
`
|
||||||
|
|
||||||
|
func (q *Queries) GetExternalServiceByToken(ctx context.Context, authToken *string) (ExternalService, error) {
|
||||||
|
row := q.db.QueryRow(ctx, getExternalServiceByToken, authToken)
|
||||||
|
var i ExternalService
|
||||||
|
err := row.Scan(&i.ID, &i.Name, &i.AuthToken)
|
||||||
|
return i, err
|
||||||
|
}
|
||||||
|
|
||||||
const getImageByID = `-- name: GetImageByID :one
|
const getImageByID = `-- name: GetImageByID :one
|
||||||
SELECT id, storage_type, image_path
|
SELECT id, storage_type, image_path
|
||||||
FROM images
|
FROM images
|
||||||
|
|
@ -240,6 +253,35 @@ func (q *Queries) GetTitleTags(ctx context.Context, titleID int64) ([]json.RawMe
|
||||||
return items, nil
|
return items, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const getUserByExternalServiceId = `-- name: GetUserByExternalServiceId :one
|
||||||
|
SELECT u.id, u.avatar_id, u.passhash, u.mail, u.nickname, u.disp_name, u.user_desc, u.creation_date, u.last_login
|
||||||
|
FROM users u
|
||||||
|
LEFT JOIN external_ids ei ON eu.user_id = u.id
|
||||||
|
WHERE ei.external_id = $1 AND ei.service_id = $2
|
||||||
|
`
|
||||||
|
|
||||||
|
type GetUserByExternalServiceIdParams struct {
|
||||||
|
ExternalID string `json:"external_id"`
|
||||||
|
ServiceID int64 `json:"service_id"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (q *Queries) GetUserByExternalServiceId(ctx context.Context, arg GetUserByExternalServiceIdParams) (User, error) {
|
||||||
|
row := q.db.QueryRow(ctx, getUserByExternalServiceId, arg.ExternalID, arg.ServiceID)
|
||||||
|
var i User
|
||||||
|
err := row.Scan(
|
||||||
|
&i.ID,
|
||||||
|
&i.AvatarID,
|
||||||
|
&i.Passhash,
|
||||||
|
&i.Mail,
|
||||||
|
&i.Nickname,
|
||||||
|
&i.DispName,
|
||||||
|
&i.UserDesc,
|
||||||
|
&i.CreationDate,
|
||||||
|
&i.LastLogin,
|
||||||
|
)
|
||||||
|
return i, err
|
||||||
|
}
|
||||||
|
|
||||||
const getUserByID = `-- name: GetUserByID :one
|
const getUserByID = `-- name: GetUserByID :one
|
||||||
SELECT
|
SELECT
|
||||||
t.id as id,
|
t.id as id,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue