diff --git a/auth/auth.gen.go b/auth/auth.gen.go index 89a2168..1e8803e 100644 --- a/auth/auth.gen.go +++ b/auth/auth.gen.go @@ -19,9 +19,9 @@ const ( // GetImpersonationTokenJSONBody defines parameters for GetImpersonationToken. type GetImpersonationTokenJSONBody struct { - TgId *int64 `json:"tg_id,omitempty"` - UserId *int64 `json:"user_id,omitempty"` - union json.RawMessage + ExternalId *int64 `json:"external_id,omitempty"` + UserId *int64 `json:"user_id,omitempty"` + union json.RawMessage } // GetImpersonationTokenJSONBody0 defines parameters for GetImpersonationToken. diff --git a/auth/openapi-auth.yaml b/auth/openapi-auth.yaml index 93db937..803a4ae 100644 --- a/auth/openapi-auth.yaml +++ b/auth/openapi-auth.yaml @@ -94,12 +94,12 @@ paths: user_id: type: integer format: int64 - tg_id: + external_id: type: integer format: int64 oneOf: - required: ["user_id"] - - required: ["tg_id"] + - required: ["external_id"] responses: "200": description: Generated impersonation access token diff --git a/modules/auth/handlers/handlers.go b/modules/auth/handlers/handlers.go index 9138fa7..2a6518e 100644 --- a/modules/auth/handlers/handlers.go +++ b/modules/auth/handlers/handlers.go @@ -182,8 +182,33 @@ func (s Server) GetImpersonationToken(ctx context.Context, req auth.GetImpersona // TODO: check err and retyrn 400/500 } - // TODO: handle tgid - accessToken, err := s.generateImpersonationToken(fmt.Sprintf("%d", *req.Body.UserId), fmt.Sprintf("%d", ext_service.ID)) + var user_id string = "" + + 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 { log.Errorf("failed to generate impersonation token: %v", 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 } -// 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) { // valid := false // var userID *string diff --git a/modules/auth/queries.sql b/modules/auth/queries.sql index 363f07a..0b9b941 100644 --- a/modules/auth/queries.sql +++ b/modules/auth/queries.sql @@ -12,4 +12,10 @@ RETURNING id; -- name: GetExternalServiceByToken :one SELECT * FROM external_services -WHERE auth_token = sqlc.arg('auth_token'); \ No newline at end of file +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'); \ No newline at end of file diff --git a/sql/migrations/000001_init.up.sql b/sql/migrations/000001_init.up.sql index 9bf99dc..946fe7e 100644 --- a/sql/migrations/000001_init.up.sql +++ b/sql/migrations/000001_init.up.sql @@ -112,7 +112,7 @@ CREATE TABLE external_services ( CREATE TABLE external_ids ( 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 ); diff --git a/sql/models.go b/sql/models.go index 1395a19..c299609 100644 --- a/sql/models.go +++ b/sql/models.go @@ -188,7 +188,7 @@ func (ns NullUsertitleStatusT) Value() (driver.Value, error) { type ExternalID struct { UserID int64 `json:"user_id"` - ServiceID *int64 `json:"service_id"` + ServiceID int64 `json:"service_id"` ExternalID string `json:"external_id"` } diff --git a/sql/queries.sql.go b/sql/queries.sql.go index e12619e..2d4067d 100644 --- a/sql/queries.sql.go +++ b/sql/queries.sql.go @@ -251,6 +251,35 @@ func (q *Queries) GetTitleTags(ctx context.Context, titleID int64) ([]json.RawMe 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 SELECT t.id as id,