Merge branch 'auth' into dev
Some checks failed
Build and Deploy Go App / build (push) Has been cancelled
Build and Deploy Go App / deploy (push) Has been cancelled

This commit is contained in:
nihonium 2025-12-06 05:15:38 +03:00
commit 54c45ac3bc
Signed by: nihonium
GPG key ID: 0251623741027CFC
7 changed files with 70 additions and 52 deletions

View file

@ -19,7 +19,7 @@ const (
// GetImpersonationTokenJSONBody defines parameters for GetImpersonationToken. // GetImpersonationTokenJSONBody defines parameters for GetImpersonationToken.
type GetImpersonationTokenJSONBody struct { type GetImpersonationTokenJSONBody struct {
TgId *int64 `json:"tg_id,omitempty"` ExternalId *int64 `json:"external_id,omitempty"`
UserId *int64 `json:"user_id,omitempty"` UserId *int64 `json:"user_id,omitempty"`
union json.RawMessage union json.RawMessage
} }

View file

@ -94,12 +94,12 @@ paths:
user_id: user_id:
type: integer type: integer
format: int64 format: int64
tg_id: external_id:
type: integer type: integer
format: int64 format: int64
oneOf: oneOf:
- required: ["user_id"] - required: ["user_id"]
- required: ["tg_id"] - required: ["external_id"]
responses: responses:
"200": "200":
description: Generated impersonation access token description: Generated impersonation access token

View file

@ -182,8 +182,33 @@ func (s Server) GetImpersonationToken(ctx context.Context, req auth.GetImpersona
// TODO: check err and retyrn 400/500 // TODO: check err and retyrn 400/500
} }
// TODO: handle tgid var user_id string = ""
accessToken, err := s.generateImpersonationToken(fmt.Sprintf("%d", *req.Body.UserId), fmt.Sprintf("%d", ext_service.ID))
if req.Body.ExternalId != nil {
user, err := s.db.GetUserByExternalServiceId(context.Background(), sqlc.GetUserByExternalServiceIdParams{
ExternalID: fmt.Sprintf("%d", *req.Body.ExternalId),
ServiceID: ext_service.ID,
})
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 { if err != nil {
log.Errorf("failed to generate impersonation token: %v", err) log.Errorf("failed to generate impersonation token: %v", err)
return auth.GetImpersonationToken401Response{}, err return auth.GetImpersonationToken401Response{}, err
@ -193,48 +218,6 @@ func (s Server) GetImpersonationToken(ctx context.Context, req auth.GetImpersona
return auth.GetImpersonationToken200JSONResponse{AccessToken: accessToken}, nil return auth.GetImpersonationToken200JSONResponse{AccessToken: accessToken}, nil
} }
// func (s Server) PostAuthVerifyToken(ctx context.Context, req auth.PostAuthVerifyTokenRequestObject) (auth.PostAuthVerifyTokenResponseObject, error) {
// valid := false
// var userID *string
// var errStr *string
// token, err := jwt.Parse(req.Body.Token, func(t *jwt.Token) (interface{}, error) {
// if _, ok := t.Method.(*jwt.SigningMethodHMAC); !ok {
// return nil, fmt.Errorf("unexpected signing method")
// }
// return accessSecret, nil
// })
// if err != nil {
// e := err.Error()
// errStr = &e
// return auth.PostAuthVerifyToken200JSONResponse{
// Valid: &valid,
// UserId: userID,
// Error: errStr,
// }, nil
// }
// if claims, ok := token.Claims.(jwt.MapClaims); ok && token.Valid {
// 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{
// Valid: &valid,
// UserId: userID,
// Error: errStr,
// }, 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
// var userID *string // var userID *string

View file

@ -13,3 +13,9 @@ RETURNING id;
SELECT * SELECT *
FROM external_services FROM external_services
WHERE auth_token = sqlc.arg('auth_token'); 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');

View file

@ -112,7 +112,7 @@ CREATE TABLE external_services (
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
); );

View file

@ -188,7 +188,7 @@ 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"`
} }

View file

@ -251,6 +251,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,