From b710a99ea58611bed441a2b04fe1955dcc67b8fd Mon Sep 17 00:00:00 2001 From: Taesu Date: Sat, 17 Oct 2026 05:52:59 +0900 Subject: [PATCH] fix(gitlab)!: type account locks and correct source references --- .changeset/gitlab-profile-types.md | 2 +- packages/core/src/social-providers/gitlab.test.ts | 10 ++++++++-- packages/core/src/social-providers/gitlab.ts | 5 +++-- 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/.changeset/gitlab-profile-types.md b/.changeset/gitlab-profile-types.md index d357b9ef93..3428c86307 100644 --- a/.changeset/gitlab-profile-types.md +++ b/.changeset/gitlab-profile-types.md @@ -2,4 +2,4 @@ "@better-auth/core": minor --- -GitLab profile callbacks now accept null profile details, including avatars and pronouns, and omitted conditional fields such as compute-minute limits. Missing avatars leave the local image unset and preserve existing user images when profile updates are enabled. Profile mappings must handle these null or missing values. +GitLab profile mappings now handle nullable details and omitted conditional fields, and expose the boolean account lock. Missing avatars preserve stored images when profile updates are enabled. diff --git a/packages/core/src/social-providers/gitlab.test.ts b/packages/core/src/social-providers/gitlab.test.ts index 7176842ba5..52eb3a27fa 100644 --- a/packages/core/src/social-providers/gitlab.test.ts +++ b/packages/core/src/social-providers/gitlab.test.ts @@ -1,5 +1,5 @@ import { betterFetch } from "@better-fetch/fetch"; -import { assertType, expect, it, vi } from "vitest"; +import { assertType, expect, expectTypeOf, it, vi } from "vitest"; import type { GitlabProfile } from "./gitlab"; import { gitlab } from "./gitlab"; @@ -8,7 +8,7 @@ vi.mock(import("@better-fetch/fetch"), () => ({ betterFetch: vi.fn() })); /** * @see https://docs.gitlab.com/api/users/#retrieve-the-current-user * @see https://github.com/gitlabhq/gitlabhq/blob/803abea42cb2e61278e3fe6a20e4fe4fb5046f43/lib/api/entities/user_public.rb#L5-L14 - * @see https://github.com/gitlabhq/gitlabhq/blob/a2042efa3487d2c5077cb265a6754727aa6f800d/db/structure.sql#L31231-L31243 + * @see https://github.com/gitlabhq/gitlabhq/blob/a2042efa3487d2c5077cb265a6754727aa6f800d/db/structure.sql#L33417-L33427 */ it("accepts nullable and conditional GitLab profile fields", () => { const profileFields = { @@ -49,6 +49,7 @@ it("preserves a missing GitLab avatar while leaving the local image unset", asyn name: "GitLab User", email: "user@example.com", state: "active", + locked: false, avatar_url: null, pronouns: null, }; @@ -60,3 +61,8 @@ it("preserves a missing GitLab avatar while leaving the local image unset", asyn expect(result?.user.image).toBeUndefined(); expect(result?.data).toEqual(profile); }); + +/** @see https://docs.gitlab.com/api/users/#retrieve-the-current-user */ +it("types the GitLab account lock", () => { + expectTypeOf().toEqualTypeOf(); +}); diff --git a/packages/core/src/social-providers/gitlab.ts b/packages/core/src/social-providers/gitlab.ts index 4400069866..e85ebeadb1 100644 --- a/packages/core/src/social-providers/gitlab.ts +++ b/packages/core/src/social-providers/gitlab.ts @@ -12,6 +12,7 @@ export interface GitlabProfile extends Record { email: string; name: string; state: string; + locked: boolean; avatar_url: string | null; web_url: string; created_at: string; @@ -139,8 +140,8 @@ export const gitlab = (options: GitlabOptions) => { return null; } const userMap = await options.mapProfileToUser?.(profile); - // GitLab may provide email_verified claim, but it's not guaranteed. - // We check for it first, then default to false for security consistency. + // GitLab does not document email_verified on /api/v4/user. + // Default to false unless an extension supplies the claim. return { user: { name: profile.name ?? profile.username ?? "",