Skip to content

Commit 5c08a79

Browse files
Account Management API: Added new /api/v2/accounts/set-name API route to edit the first, last, and username for an account.
1 parent 70f8218 commit 5c08a79

File tree

2 files changed

+108
-0
lines changed

2 files changed

+108
-0
lines changed
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import { z } from "../../framework";
2+
3+
import {
4+
FailedAPIOperationSchema,
5+
SuccessfulAPIOperationSchema,
6+
} from "../common";
7+
8+
import { AccountIdSchema } from "./common";
9+
10+
// OpenAPI spec
11+
//
12+
export const SetAccountNameInputSchema = z
13+
.object({
14+
account_id: AccountIdSchema.optional().describe(
15+
`**Administrators only**. Optional account id to set name(s) for. If this field is
16+
not provided, it is assumed that this operation pertains to the account id of the
17+
user making the request.`,
18+
),
19+
username: z.string().describe("Unique username.").optional(),
20+
first_name: z.string().max(254).describe("First name").optional(),
21+
last_name: z.string().max(254).describe("Last name").optional(),
22+
})
23+
.describe(
24+
`Set the username, first name, and/or last name for a user account. Only non-empty
25+
field values are allowed; everything else will be omitted from the update query.`,
26+
);
27+
28+
export const SetAccountNameOutputSchema = z.union([
29+
FailedAPIOperationSchema,
30+
SuccessfulAPIOperationSchema,
31+
]);
32+
33+
export type SetAccountNameInput = z.infer<typeof SetAccountNameInputSchema>;
34+
export type SetAccountNameOutput = z.infer<typeof SetAccountNameOutputSchema>;
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
/*
2+
Set account {user/first/last} name.
3+
*/
4+
5+
import userQuery from "@cocalc/database/user-query";
6+
import userIsInGroup from "@cocalc/server/accounts/is-in-group";
7+
8+
import getAccountId from "lib/account/get-account";
9+
import getParams from "lib/api/get-params";
10+
11+
import { apiRoute, apiRouteOperation } from "lib/api";
12+
import {
13+
SetAccountNameInputSchema,
14+
SetAccountNameOutputSchema,
15+
} from "lib/api/schema/accounts/set-name";
16+
17+
async function handle(req, res) {
18+
try {
19+
res.json(await get(req));
20+
} catch (err) {
21+
res.json({ error: `${err.message ? err.message : err}` });
22+
return;
23+
}
24+
}
25+
26+
async function get(req) {
27+
const client_account_id = await getAccountId(req);
28+
29+
if (client_account_id == null) {
30+
throw Error("Must be signed in to edit account name.");
31+
}
32+
33+
const { username, first_name, last_name, account_id } = getParams(req);
34+
35+
// This user MUST be an admin:
36+
if (account_id && !(await userIsInGroup(client_account_id, "admin"))) {
37+
throw Error("Only admins are authorized to specify an account id.");
38+
}
39+
40+
return userQuery({
41+
account_id: account_id || client_account_id,
42+
query: {
43+
accounts: {
44+
// Any provided values must be non-empty in order for userQuery to SET values
45+
// instead of fetching them.
46+
//
47+
...(username && { name: username }),
48+
...(first_name && { first_name }),
49+
...(last_name && { last_name }),
50+
},
51+
},
52+
});
53+
}
54+
55+
export default apiRoute({
56+
setName: apiRouteOperation({
57+
method: "POST",
58+
openApiOperation: {
59+
tags: ["Accounts", "Admin"],
60+
},
61+
})
62+
.input({
63+
contentType: "application/json",
64+
body: SetAccountNameInputSchema,
65+
})
66+
.outputs([
67+
{
68+
status: 200,
69+
contentType: "application/json",
70+
body: SetAccountNameOutputSchema,
71+
},
72+
])
73+
.handler(handle),
74+
});

0 commit comments

Comments
 (0)