@@ -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
4646async  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 or site-admin ` ) ; 
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+  */ 
164175export  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 }  ) ; 
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+  */ 
209231export  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+  */ 
232262export  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+  */ 
318351export  async  function  getAccount ( 
319352  user : string , 
320353) : Promise < 
0 commit comments