Skip to content

Commit d87a26b

Browse files
committed
server/organizations logic: only allow site-admins to promote users to be admins or add existing users to orgs. Org-admins can create new users inside an org, though.
1 parent b824e3f commit d87a26b

File tree

1 file changed

+48
-15
lines changed
  • src/packages/server/conat/api

1 file changed

+48
-15
lines changed

src/packages/server/conat/api/org.ts

Lines changed: 48 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -36,16 +36,16 @@ async function isAllowed({
3636
account_id?: string;
3737
name: string;
3838
}): Promise<boolean> {
39+
if (!account_id) return false;
3940
return (
40-
!!account_id &&
41-
((await isOrganizationAdmin({ account_id, name })) ||
42-
(await isAdmin(account_id)))
41+
(await isOrganizationAdmin({ account_id, name })) ||
42+
(await isAdmin(account_id))
4343
);
4444
}
4545

4646
async function assertAllowed(opts) {
4747
if (!(await isAllowed(opts))) {
48-
throw Error(`user must an admin of the organization`);
48+
throw Error(`user must be an admin of the organization`);
4949
}
5050
}
5151

@@ -161,6 +161,17 @@ export async function set(opts: {
161161
]);
162162
}
163163

164+
/**
165+
* Promote an existing user to organization admin: adding them to the admin_account_ids list and adding them to be member of the organization.
166+
* Only site-level admins can perform this operation to prevent privilege escalation.
167+
* Organization-level admins cannot promote other users to admin status.
168+
*
169+
* NOTE: this prevents moving a user from another org to the @name org. Use addUser first, to move a user from one org to another one.
170+
*
171+
* @param account_id - The site admin performing the operation
172+
* @param name - The organization name
173+
* @param user - The account_id or email address of the user to promote
174+
*/
164175
export async function addAdmin({
165176
account_id,
166177
name,
@@ -170,21 +181,23 @@ export async function addAdmin({
170181
name: string;
171182
user: string;
172183
}): Promise<void> {
173-
const { name: currentOrgName, account_id: admin_account_id } =
174-
await getAccount(user);
184+
const { name: usersOrgName, account_id: admin_account_id } = await getAccount(
185+
user,
186+
);
175187
if (!admin_account_id) {
176188
throw Error(`no such account '${user}'`);
177189
}
178-
if (currentOrgName == name) {
179-
// already an admin of the org
180-
return;
190+
if (usersOrgName != null && usersOrgName !== name) {
191+
throw new Error(`User '${user}' is already member of another organization`);
192+
}
193+
// await assertAllowed({ account_id, name });
194+
if (!(await isAdmin(account_id))) {
195+
throw Error(
196+
"only site admins can make a user an organization admin right now",
197+
);
181198
}
182-
await assertAllowed({
183-
account_id,
184-
name,
185-
});
186199
const pool = getPool();
187-
// query below takes care to ensure no dups and work in case of null.
200+
// query below takes care to ensure no dups and works in case of null.
188201
await pool.query(
189202
`
190203
UPDATE organizations
@@ -206,6 +219,15 @@ export async function addAdmin({
206219
});
207220
}
208221

222+
/**
223+
* Add an existing CoCalc user to an organization by setting their org field.
224+
* Only site-level admins can perform this operation.
225+
* NOTE: this could move a user from an existing org to another org!
226+
*
227+
* @param account_id - The site admin performing the operation
228+
* @param name - The organization name
229+
* @param user - The account_id or email address of the user to add
230+
*/
209231
export async function addUser({
210232
account_id,
211233
name,
@@ -216,7 +238,7 @@ export async function addUser({
216238
user: string;
217239
}): Promise<void> {
218240
if (!(await isAdmin(account_id))) {
219-
throw Error("only site admins can move user to an org right now");
241+
throw Error("only site admins can add/move a user to an org right now");
220242
}
221243
const { account_id: user_account_id } = await getAccount(user);
222244
if (!user_account_id) {
@@ -229,6 +251,14 @@ export async function addUser({
229251
]);
230252
}
231253

254+
/**
255+
* Create a new CoCalc account and add it to an organization.
256+
* Allowed for both site-level admins and organization admins.
257+
*
258+
* @param account_id - The admin (site or org) performing the operation
259+
* @param name - The organization name
260+
* @returns The account_id of the newly created account
261+
*/
232262
export async function createUser({
233263
account_id,
234264
name,
@@ -315,6 +345,9 @@ export async function removeAdmin({
315345
);
316346
}
317347

348+
/**
349+
* @param user and account_id or email_address in the accounts table
350+
*/
318351
export async function getAccount(
319352
user: string,
320353
): Promise<

0 commit comments

Comments
 (0)