Skip to content

Commit 1807de5

Browse files
committed
fix(gateway): profiles CI conformance — bindings, lint, knip, sql boundary
1 parent 4e9f603 commit 1807de5

3 files changed

Lines changed: 29 additions & 18 deletions

File tree

apps/android/app/src/main/java/ai/openclaw/app/gateway/GatewayProtocol.kt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,10 @@ enum class GatewayMethod(
238238
BoardEvent("board.event"),
239239
AuditList("audit.list"),
240240
AuditActivityList("audit.activity.list"),
241+
UsersList("users.list"),
242+
UsersLinkEmail("users.linkEmail"),
243+
UsersSetDisplayName("users.setDisplayName"),
244+
UsersSetAvatar("users.setAvatar"),
241245
TasksList("tasks.list"),
242246
TasksGet("tasks.get"),
243247
TasksCancel("tasks.cancel"),

src/gateway/user-profiles-http.test.ts

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,14 @@ vi.mock("../state/user-profiles.js", () => ({
1616
}));
1717

1818
function response() {
19+
const end = vi.fn();
20+
const setHeader = vi.fn();
21+
const writeHead = vi.fn();
1922
return {
20-
end: vi.fn(),
21-
setHeader: vi.fn(),
22-
writeHead: vi.fn(),
23-
} as unknown as ServerResponse;
23+
end,
24+
response: { end, setHeader, writeHead } as unknown as ServerResponse,
25+
writeHead,
26+
};
2427
}
2528

2629
function request(path: string, headers: Record<string, string> = {}) {
@@ -45,7 +48,7 @@ describe("profile avatar HTTP endpoint", () => {
4548

4649
await handleUserProfileAvatarHttpRequest(
4750
request("/ignored-by-handler"),
48-
res,
51+
res.response,
4952
"/api/users/profile-1/avatar",
5053
{ auth: {} as never },
5154
);
@@ -71,7 +74,7 @@ describe("profile avatar HTTP endpoint", () => {
7174

7275
await handleUserProfileAvatarHttpRequest(
7376
request("/ignored-by-handler", { "if-none-match": '"current-hash-png"' }),
74-
res,
77+
res.response,
7578
"/api/users/profile-1/avatar",
7679
{ auth: {} as never },
7780
);
@@ -90,7 +93,7 @@ describe("profile avatar HTTP endpoint", () => {
9093

9194
await handleUserProfileAvatarHttpRequest(
9295
request("/ignored-by-handler"),
93-
response(),
96+
response().response,
9497
"/api/users/profile%2D1/avatar",
9598
{ auth: {} as never },
9699
);
@@ -109,7 +112,7 @@ describe("profile avatar HTTP endpoint", () => {
109112

110113
await handleUserProfileAvatarHttpRequest(
111114
{ method: "HEAD", url: "/ignored-by-handler", headers: {} } as unknown as IncomingMessage,
112-
res,
115+
res.response,
113116
"/api/users/profile-1/avatar",
114117
{ auth: {} as never },
115118
);
@@ -134,7 +137,7 @@ describe("profile avatar HTTP endpoint", () => {
134137

135138
await handleUserProfileAvatarHttpRequest(
136139
request("/ignored-by-handler", { "if-none-match": header }),
137-
res,
140+
res.response,
138141
"/api/users/profile-1/avatar",
139142
{ auth: {} as never },
140143
);

src/state/user-profiles.ts

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,11 @@ import {
1818
import { USER_PROFILES_SCHEMA_SQL } from "./user-profiles-schema.js";
1919

2020
export const MAX_USER_PROFILE_AVATAR_BYTES = 512 * 1024;
21-
export const USER_PROFILE_AVATAR_MIME_TYPES = ["image/png", "image/jpeg", "image/webp"] as const;
21+
const USER_PROFILE_AVATAR_MIME_TYPES = ["image/png", "image/jpeg", "image/webp"] as const;
2222

23-
export type UserProfileAvatarMime = (typeof USER_PROFILE_AVATAR_MIME_TYPES)[number];
23+
type UserProfileAvatarMime = (typeof USER_PROFILE_AVATAR_MIME_TYPES)[number];
2424

25-
export type UserProfile = {
25+
type UserProfile = {
2626
id: string;
2727
displayName: string | null;
2828
avatarMime: UserProfileAvatarMime | null;
@@ -31,19 +31,19 @@ export type UserProfile = {
3131
updatedAt: number;
3232
};
3333

34-
export type UserProfileListItem = UserProfile & {
34+
type UserProfileListItem = UserProfile & {
3535
emails: string[];
3636
hasAvatar: boolean;
3737
};
3838

39-
export type UserProfileAvatar = {
39+
type UserProfileAvatar = {
4040
bytes: Uint8Array;
4141
mime: UserProfileAvatarMime;
4242
sha256: string;
4343
updatedAt: number;
4444
};
4545

46-
export type UserProfileAvatarError =
46+
type UserProfileAvatarError =
4747
| { code: "avatar_too_large"; maxBytes: number }
4848
| { code: "unsupported_avatar_mime"; mime: string };
4949

@@ -81,7 +81,7 @@ type UserProfileListRow = Pick<
8181
UserProfileRow,
8282
"id" | "display_name" | "avatar_mime" | "merged_into" | "created_at" | "updated_at"
8383
> & {
84-
has_avatar: number;
84+
has_avatar: unknown;
8585
};
8686

8787
const ensuredDatabases = new WeakSet<DatabaseSync>();
@@ -146,6 +146,10 @@ function toUserProfileListItem(row: UserProfileListRow, emails: string[]): UserP
146146
};
147147
}
148148

149+
function hasAvatarColumn() {
150+
return sql`CASE WHEN avatar IS NULL THEN 0 ELSE 1 END`.as("has_avatar");
151+
}
152+
149153
function selectUserProfileListItemById(db: DatabaseSync, profileId: string): UserProfileListItem {
150154
const kysely = profileDb(db);
151155
const profile = executeSqliteQueryTakeFirstSync(
@@ -159,7 +163,7 @@ function selectUserProfileListItemById(db: DatabaseSync, profileId: string): Use
159163
"merged_into",
160164
"created_at",
161165
"updated_at",
162-
sql<number>`CASE WHEN avatar IS NULL THEN 0 ELSE 1 END`.as("has_avatar"),
166+
hasAvatarColumn(),
163167
])
164168
.where("id", "=", profileId),
165169
);
@@ -461,7 +465,7 @@ export function listProfiles(options: OpenClawStateDatabaseOptions = {}): UserPr
461465
"merged_into",
462466
"created_at",
463467
"updated_at",
464-
sql<number>`CASE WHEN avatar IS NULL THEN 0 ELSE 1 END`.as("has_avatar"),
468+
hasAvatarColumn(),
465469
])
466470
.orderBy("created_at", "asc")
467471
.orderBy("id", "asc"),

0 commit comments

Comments
 (0)