@@ -41,6 +41,7 @@ import {
4141 ValidateAccessTokenResponse_Status ,
4242 InviteUserToTeamRequest ,
4343 InviteUserToTeamResponse ,
44+ UpdateTeamRequest ,
4445} from './protoTypes/authentication.js' ;
4546import { Empty } from './protoTypes/google/protobuf/empty.js' ;
4647import { runMigrations } from './migrations/index.js' ;
@@ -83,6 +84,7 @@ export default class Authentication extends ManagedModule<Config> {
8384 removeTeamMembers : this . removeTeamMembers . bind ( this ) ,
8485 invitationDelete : this . invitationDelete . bind ( this ) ,
8586 inviteUserToTeam : this . inviteUserToTeam . bind ( this ) ,
87+ updateTeam : this . updateTeam . bind ( this ) ,
8688 } ,
8789 } ;
8890 protected metricsSchema = metricsSchema ;
@@ -744,6 +746,95 @@ export default class Authentication extends ManagedModule<Config> {
744746 }
745747 }
746748
749+ async updateTeam (
750+ call : GrpcRequest < UpdateTeamRequest > ,
751+ callback : GrpcCallback < GrpcTeam > ,
752+ ) {
753+ const { teamId, name, newParentTeamId } = call . request ;
754+
755+ try {
756+ if ( ! name && ! newParentTeamId ) {
757+ return callback ( {
758+ code : status . INVALID_ARGUMENT ,
759+ message : 'At least one of name or newParentTeamId must be provided' ,
760+ } ) ;
761+ }
762+
763+ const team = await models . Team . getInstance ( ) . findOne ( { _id : teamId } ) ;
764+ if ( ! team ) {
765+ return callback ( { code : status . NOT_FOUND , message : 'Team not found' } ) ;
766+ }
767+
768+ const updateFields : { name ?: string ; parentTeam ?: string } = {
769+ ...( name && { name } ) ,
770+ } ;
771+
772+ if ( newParentTeamId ) {
773+ const newParentTeam = await models . Team . getInstance ( ) . findOne ( {
774+ _id : newParentTeamId ,
775+ } ) ;
776+ if ( ! newParentTeam ) {
777+ return callback ( {
778+ code : status . NOT_FOUND ,
779+ message : 'New parent team not found' ,
780+ } ) ;
781+ }
782+
783+ const oldParentTeamId = team . parentTeam ;
784+
785+ if ( oldParentTeamId ) {
786+ try {
787+ await this . grpcSdk . authorization ! . deleteRelation ( {
788+ subject : 'Team:' + oldParentTeamId ,
789+ relation : 'owner' ,
790+ resource : 'Team:' + teamId ,
791+ } ) ;
792+ } catch ( e ) {
793+ ConduitGrpcSdk . Logger . warn (
794+ `Failed to delete old parent relation: ${ ( e as Error ) . message } ` ,
795+ ) ;
796+ }
797+ }
798+
799+ await this . grpcSdk . authorization ! . createRelation ( {
800+ subject : 'Team:' + newParentTeamId ,
801+ relation : 'owner' ,
802+ resource : 'Team:' + teamId ,
803+ } ) ;
804+
805+ updateFields . parentTeam = newParentTeamId ;
806+
807+ ConduitGrpcSdk . Logger . info (
808+ `Team ${ teamId } parent switched from ${
809+ oldParentTeamId ?? 'none'
810+ } to ${ newParentTeamId } `,
811+ ) ;
812+ }
813+
814+ const updatedTeam = await models . Team . getInstance ( ) . findByIdAndUpdate (
815+ teamId ,
816+ updateFields ,
817+ ) ;
818+
819+ if ( ! updatedTeam ) {
820+ return callback ( { code : status . INTERNAL , message : 'Failed to update team' } ) ;
821+ }
822+
823+ if ( name ) {
824+ ConduitGrpcSdk . Logger . info ( `Team ${ teamId } name updated to ${ name } ` ) ;
825+ }
826+
827+ return callback ( null , {
828+ id : updatedTeam . _id ,
829+ name : updatedTeam . name ,
830+ parentTeam : updatedTeam . parentTeam ,
831+ isDefault : updatedTeam . isDefault ,
832+ } ) ;
833+ } catch ( e ) {
834+ return callback ( { code : status . INTERNAL , message : ( e as Error ) . message } ) ;
835+ }
836+ }
837+
747838 protected registerSchemas ( ) {
748839 const promises = Object . values ( models ) . map ( model => {
749840 const modelInstance = model . getInstance ( this . database ) ;
0 commit comments