@@ -39,6 +39,16 @@ export class NamespacesService {
3939 private readonly i18n : I18nService ,
4040 ) { }
4141
42+ private async hasOwner (
43+ namespaceId : string ,
44+ entityManager : EntityManager ,
45+ ) : Promise < boolean > {
46+ const count = await entityManager . count ( NamespaceMember , {
47+ where : { namespaceId, role : NamespaceRole . OWNER } ,
48+ } ) ;
49+ return count > 0 ;
50+ }
51+
4252 async getPrivateRootId ( userId : string , namespaceId : string ) : Promise < string > {
4353 const member = await this . namespaceMemberRepository . findOne ( {
4454 where : {
@@ -307,10 +317,17 @@ export class NamespacesService {
307317 userId : string ,
308318 role : NamespaceRole ,
309319 ) {
310- await this . namespaceMemberRepository . update (
311- { namespaceId, userId } ,
312- { role } ,
313- ) ;
320+ await this . dataSource . transaction ( async ( manager ) => {
321+ await manager . update ( NamespaceMember , { namespaceId, userId } , { role } ) ;
322+ const hasOwner = await this . hasOwner ( namespaceId , manager ) ;
323+ if ( ! hasOwner ) {
324+ throw new AppException (
325+ this . i18n . t ( 'namespace.errors.noOwnerAfterwards' ) ,
326+ 'NO_OWNER_AFTERWARDS' ,
327+ HttpStatus . UNPROCESSABLE_ENTITY ,
328+ ) ;
329+ }
330+ } ) ;
314331 }
315332
316333 async listNamespaces ( userId : string ) : Promise < Namespace [ ] > {
@@ -329,6 +346,10 @@ export class NamespacesService {
329346 } ) ;
330347 }
331348
349+ async countMembers ( namespaceId : string ) : Promise < number > {
350+ return await this . namespaceMemberRepository . countBy ( { namespaceId } ) ;
351+ }
352+
332353 async listMembers ( namespaceId : string ) : Promise < NamespaceMemberDto [ ] > {
333354 const members = await this . namespaceMemberRepository . find ( {
334355 where : { namespaceId } ,
@@ -399,6 +420,14 @@ export class NamespacesService {
399420 } ) ;
400421 // Delete namespace member record
401422 await manager . softDelete ( NamespaceMember , { id : member . id } ) ;
423+ const hasOwner = await this . hasOwner ( namespaceId , manager ) ;
424+ if ( ! hasOwner ) {
425+ throw new AppException (
426+ this . i18n . t ( 'namespace.errors.noOwnerAfterwards' ) ,
427+ 'NO_OWNER_AFTERWARDS' ,
428+ HttpStatus . UNPROCESSABLE_ENTITY ,
429+ ) ;
430+ }
402431 } ) ;
403432 }
404433
0 commit comments