evont-software.com
On client side for CSOM we have already a solution for adding managers or contributors for term groups. You can have a look here for the original article.
1ClientContext clientContext = GetClientContext();23var taxonomySession = TaxonomySession.GetTaxonomySession(clientContext);45var termStore = taxonomySession.GetDefaultSiteCollectionTermStore();67var myTermGroup = termStore.Groups.GetByName("My Custom Terms Group");89//Add Group Managers10myTermGroup.AddGroupManager("i:0#.f|membership|...@tenant.onmicrosoft.com");1112//Add Group Contributors13myTermGroup.AddContributor("i:0#.f|membership|...@tenant.onmicrosoft.com");14myTermGroup.AddContributor("i:0#.f|membership|...@tenant.onmicrosoft.com");1516clientContext.Load(myTermGroup, group => group.GroupManagerPrincipalNames, group => group.ContributorPrincipalNames);17clientContext.ExecuteQuery();1819Console.WriteLine("Group Managers: ");20foreach (var manager in myTermGroup.GroupManagerPrincipalNames)21{22 Console.WriteLine(manager);23}2425Console.WriteLine("Group Contributors: ");26foreach (var contributors in myTermGroup.ContributorPrincipalNames)27{28 Console.WriteLine(contributors);29}
I extracted the methods for the special case of site collection term group managers and contributors, you can find here a working version with pure typescript. Your class should also have a property for spHttpClient and absoluteWebUrl from pnp js.
1/**2 * Add manager (creates site term group if not exists, allowed to run multiple times for same user)3 * @param principalName name of user contoso\login or Everyone4 */5 public async addSiteGroupManager(principalName: string): Promise<void> {6 const requestBody = `<?xml version="1.0" encoding="UTF-8"?>7 <Request xmlns="http://schemas.microsoft.com/sharepoint/clientquery/2009" SchemaVersion="15.0.0.0" LibraryVersion="16.0.0.0" ApplicationName="Javascript Library">8 <Actions>9 <ObjectPath Id="1" ObjectPathId="0" />10 <ObjectIdentityQuery Id="2" ObjectPathId="0" />11 <ObjectPath Id="4" ObjectPathId="3" />12 <ObjectIdentityQuery Id="5" ObjectPathId="3" />13 <ObjectPath Id="7" ObjectPathId="6" />14 <ObjectPath Id="9" ObjectPathId="8" />15 <ObjectPath Id="11" ObjectPathId="10" />16 <ObjectIdentityQuery Id="12" ObjectPathId="10" />17 <Method Name="AddGroupManager" Id="13" ObjectPathId="10">18 <Parameters>19 <Parameter Type="String">${principalName}</Parameter>20 </Parameters>21 </Method>22 </Actions>23 <ObjectPaths>24 <StaticMethod Id="0" Name="GetTaxonomySession" TypeId="{981cbc68-9edc-4f8d-872f-71146fcbb84f}" />25 <Method Id="3" ParentId="0" Name="GetDefaultSiteCollectionTermStore" />26 <StaticProperty Id="6" TypeId="{3747adcd-a3c3-41b9-bfab-4a64dd2f1e0a}" Name="Current" />27 <Property Id="8" ParentId="6" Name="Site" />28 <Method Id="10" ParentId="3" Name="GetSiteCollectionGroup">29 <Parameters>30 <Parameter ObjectPathId="8" />31 <Parameter Type="Boolean">true</Parameter>32 </Parameters>33 </Method>34 </ObjectPaths>35 </Request>`;3637 return await this.postcsom(requestBody).then((result) => {38 if (result[0].ErrorInfo !== null) {39 throw new Error(JSON.stringify(result[0].ErrorInfo));40 }41 return;42 });43 }4445 /**46 * Add contributor (creates site term group if not exists, allowed to run multiple times for same user)47 * @param principalName name of user contoso\login or Everyone48 */49 public async addSiteGroupContributor(principalName: string): Promise<void> {50 const requestBody = `<?xml version="1.0" encoding="UTF-8"?>51 <Request xmlns="http://schemas.microsoft.com/sharepoint/clientquery/2009" SchemaVersion="15.0.0.0" LibraryVersion="16.0.0.0" ApplicationName="Javascript Library">52 <Actions>53 <ObjectPath Id="1" ObjectPathId="0" />54 <ObjectIdentityQuery Id="2" ObjectPathId="0" />55 <ObjectPath Id="4" ObjectPathId="3" />56 <ObjectIdentityQuery Id="5" ObjectPathId="3" />57 <ObjectPath Id="7" ObjectPathId="6" />58 <ObjectPath Id="9" ObjectPathId="8" />59 <ObjectPath Id="11" ObjectPathId="10" />60 <ObjectIdentityQuery Id="12" ObjectPathId="10" />61 <Method Name="AddContributor" Id="13" ObjectPathId="10">62 <Parameters>63 <Parameter Type="String">${principalName}</Parameter>64 </Parameters>65 </Method>66 </Actions>67 <ObjectPaths>68 <StaticMethod Id="0" Name="GetTaxonomySession" TypeId="{981cbc68-9edc-4f8d-872f-71146fcbb84f}" />69 <Method Id="3" ParentId="0" Name="GetDefaultSiteCollectionTermStore" />70 <StaticProperty Id="6" TypeId="{3747adcd-a3c3-41b9-bfab-4a64dd2f1e0a}" Name="Current" />71 <Property Id="8" ParentId="6" Name="Site" />72 <Method Id="10" ParentId="3" Name="GetSiteCollectionGroup">73 <Parameters>74 <Parameter ObjectPathId="8" />75 <Parameter Type="Boolean">true</Parameter>76 </Parameters>77 </Method>78 </ObjectPaths>79 </Request>`;80 return await this.postcsom(requestBody).then((result) => {81 if (result[0].ErrorInfo !== null) {82 throw new Error(JSON.stringify(result[0].ErrorInfo));83 }84 return;85 });86 }878889/**90 * sends a request to client svc91 * @param data request data92 */93 // eslint-disable-next-line @typescript-eslint/no-explicit-any94 private async postcsom(data: string): Promise<any> {95 const clientServiceUrl = this.absoluteWebUrl + '/_vti_bin/client.svc/ProcessQuery';9697 const formDigest = await this.getFormDigest();9899 const requestHeaders: Headers = new Headers();100 requestHeaders.append('Accept', 'application/json');101 requestHeaders.append('Content-Type', 'text/xml');102 requestHeaders.append('X-RequestDigest', formDigest);103104 const httpPostOptions: IHttpClientOptions = {105 headers: requestHeaders,106 body: data107 };108109 const serviceResponse: IResponse = await this.spHttpClient.post(clientServiceUrl,SPHttpClient.configurations.v1, httpPostOptions);110 const serviceJSONResponse = await serviceResponse.json();111 if (serviceResponse.ok) {112 return serviceJSONResponse;113 }114 return null;115 }116117 /**118 * digest is needed for post requests119 */120 private async getFormDigest(): Promise<string> {121 if (this.cachedDigest && !this.isDigestDateInvalid()) return this.cachedDigest;122 this.cachedDigestDate = new Date();123 const contextInfoUrl = this.absoluteWebUrl + '/_api/contextinfo';124125 const requestHeaders: Headers = new Headers();126 requestHeaders.append('Accept', 'application/json');127 requestHeaders.append('Content-Type', 'text/xml');128129 const httpPostOptions: IHttpClientOptions = {130 headers: requestHeaders131 };132 const contextInfoResponse: IResponse = await this.spHttpClient.post(contextInfoUrl, httpPostOptions);133 const contextInfoJsonResponse = await contextInfoResponse.json();134 const formDigest: string = contextInfoJsonResponse.FormDigestValue;135 this.cachedDigest = formDigest;136 return formDigest;137 }138139 private isDigestDateInvalid(): boolean {140 const today = new Date().getTime();141 const cachedtime = this.cachedDigestDate.getTime();142 const difference = Math.abs(cachedtime - today);143 const seconds = (difference / 1000) % 60;144 return seconds > 60;145 }
The easy usage is:
addSiteGroupContributor('Everyone')