@vtecx/vtecxnext 2.1.3 → 2.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -5,10 +5,26 @@ import type { Readable } from 'node:stream';
5
5
  * Hello world.
6
6
  */
7
7
  export declare const hello: () => void;
8
- type StatusMessage = {
8
+ export type StatusMessage = {
9
9
  status: number;
10
10
  message: string;
11
11
  };
12
+ export type AdduserInfo = {
13
+ username?: string;
14
+ pswd?: string;
15
+ nickname?: string;
16
+ emailSubject?: string;
17
+ emailText?: string;
18
+ emailHtml?: string;
19
+ };
20
+ export type ChangepassByAdminInfo = {
21
+ uid: string;
22
+ pswd: string;
23
+ };
24
+ export type CreateGroupadminInfo = {
25
+ group: string;
26
+ uids: string[];
27
+ };
12
28
  export declare class VtecxNext {
13
29
  /** Request */
14
30
  readonly req: NextRequest;
@@ -47,6 +63,12 @@ export declare class VtecxNext {
47
63
  * @returns null、undefined、空文字の場合true
48
64
  */
49
65
  isBlank: (val: any) => boolean;
66
+ /**
67
+ * undefined、nullを空文字に変換
68
+ * @param val 文字列
69
+ * @returns 変換した文字列
70
+ */
71
+ null2blank: (val: string | undefined | null) => string;
50
72
  /**
51
73
  * X-Requested-With header check.
52
74
  * If not specified, set status 417 to the response.
@@ -538,13 +560,30 @@ export declare class VtecxNext {
538
560
  * @return feed
539
561
  */
540
562
  getMessageQueue: (channel: string) => Promise<any>;
563
+ /**
564
+ * add group
565
+ * (not yet joined)
566
+ * @param group group
567
+ * @param selfid hierarchical name under my group alias
568
+ * @return feed
569
+ */
570
+ addGroup: (group: string, selfid?: string) => Promise<any>;
571
+ /**
572
+ * add group by admin
573
+ * (not yet joined)
574
+ * @param uids uid list
575
+ * @param group group
576
+ * @param selfid hierarchical name under my group alias
577
+ * @return feed
578
+ */
579
+ addGroupByAdmin: (uids: string[], group: string, selfid?: string) => Promise<any>;
541
580
  /**
542
581
  * join to the group
543
582
  * @param group group
544
583
  * @param selfid hierarchical name under my group alias
545
584
  * @return feed
546
585
  */
547
- joinGroup: (group: string, selfid: string) => Promise<any>;
586
+ joinGroup: (group: string, selfid?: string) => Promise<any>;
548
587
  /**
549
588
  * leave from the group
550
589
  * @param group group
@@ -577,43 +616,58 @@ export declare class VtecxNext {
577
616
  isAdmin: () => Promise<boolean>;
578
617
  /**
579
618
  * add user
580
- * @param feed entry (JSON)
619
+ * @param adduserInfo adduser infomation
581
620
  * @param reCaptchaToken reCAPTCHA token
582
621
  * @return message feed
583
622
  */
584
- adduser: (feed: any, reCaptchaToken: string) => Promise<any>;
623
+ adduser: (adduserInfo: AdduserInfo, reCaptchaToken: string) => Promise<any>;
624
+ /**
625
+ * convert adduser info to argument entry
626
+ * @param adduserInfo adduser info
627
+ * @param isNoPswd パスワードを付加しない場合true(passresetの場合true)
628
+ * @returns entry
629
+ */
630
+ private convertAdduserInfoToEntry;
585
631
  /**
586
632
  * add user by user admin
587
633
  * @param feed entries (JSON)
588
- * @param reCaptchaToken reCAPTCHA token
589
634
  * @return message feed
590
635
  */
591
- adduserByAdmin: (feed: any) => Promise<any>;
636
+ adduserByAdmin: (adduserInfos: AdduserInfo[]) => Promise<any>;
637
+ /**
638
+ * add user by group admin
639
+ * @param feed entries (JSON)
640
+ * @param groupname group name
641
+ * @return message feed
642
+ */
643
+ adduserByGroupadmin: (adduserInfos: AdduserInfo[], groupname: string) => Promise<any>;
592
644
  /**
593
645
  * Send email for password reset
594
- * @param feed entry (JSON)
646
+ * @param adduserInfo mailaddress
595
647
  * @param reCaptchaToken reCAPTCHA token
596
648
  * @return message feed
597
649
  */
598
- passreset: (feed: any, reCaptchaToken?: string) => Promise<any>;
650
+ passreset: (adduserInfo: AdduserInfo, reCaptchaToken?: string) => Promise<any>;
599
651
  /**
600
652
  * change password
601
- * @param feed entry (JSON)
653
+ * @param newpswd new password
654
+ * @param oldpswd old password
655
+ * @param passresetToken password reset token
602
656
  * @return message feed
603
657
  */
604
- changepass: (feed: any) => Promise<any>;
658
+ changepass: (newpswd: string, oldpswd?: string, passresetToken?: string) => Promise<any>;
605
659
  /**
606
660
  * change password by user admin
607
- * @param feed entry (JSON)
661
+ * @param changepassByAdminInfos password change information (uid, password)
608
662
  * @return message feed
609
663
  */
610
- changepassByAdmin: (feed: any) => Promise<any>;
664
+ changepassByAdmin: (changepassByAdminInfos: ChangepassByAdminInfo[]) => Promise<any>;
611
665
  /**
612
666
  * change login user's account
613
- * @param feed entries (JSON)
667
+ * @param adduserInfo change user info
614
668
  * @return message feed
615
669
  */
616
- changeaccount: (feed: any) => Promise<any>;
670
+ changeaccount: (adduserInfo: AdduserInfo) => Promise<any>;
617
671
  /**
618
672
  * verify to change login user's account
619
673
  * @param verifyCode verify code
@@ -634,10 +688,11 @@ export declare class VtecxNext {
634
688
  revokeuser: (account: string) => Promise<any>;
635
689
  /**
636
690
  * revoke users
637
- * @param feed entries (JSON)
691
+ * @param accounts account list
692
+ * @param uids uid list
638
693
  * @return message feed
639
694
  */
640
- revokeusers: (feed: any) => Promise<any>;
695
+ revokeusers: (accounts?: string[], uids?: string[]) => Promise<any>;
641
696
  /**
642
697
  * activate user
643
698
  * @param account account
@@ -646,10 +701,11 @@ export declare class VtecxNext {
646
701
  activateuser: (account: string) => Promise<any>;
647
702
  /**
648
703
  * activate users
649
- * @param feed entries (JSON)
704
+ * @param accounts account list
705
+ * @param uids uid list
650
706
  * @return message feed
651
707
  */
652
- activateusers: (feed: any) => Promise<any>;
708
+ activateusers: (accounts?: string[], uids?: string[]) => Promise<any>;
653
709
  /**
654
710
  * cancel user.
655
711
  * @param account account
@@ -664,10 +720,11 @@ export declare class VtecxNext {
664
720
  deleteuser: (account: string) => Promise<any>;
665
721
  /**
666
722
  * revoke users
667
- * @param feed entries (JSON)
723
+ * @param accounts account list
724
+ * @param uids uid list
668
725
  * @return message feed
669
726
  */
670
- deleteusers: (feed: any) => Promise<any>;
727
+ deleteusers: (accounts?: string[], uids?: string[]) => Promise<any>;
671
728
  /**
672
729
  * add acl
673
730
  * @param feed entries
@@ -813,6 +870,12 @@ export declare class VtecxNext {
813
870
  * @return message feed
814
871
  */
815
872
  mergeOAuthUserLine: (rxid: string) => Promise<any>;
873
+ /**
874
+ * create group admin
875
+ * @param CreateGroupadminInfo group name and uid list
876
+ * @return message feed
877
+ */
878
+ createGroupadmin: (createGroupadminInfos: CreateGroupadminInfo[]) => Promise<any>;
816
879
  /**
817
880
  * vte.cxへリクエスト
818
881
  * @param method メソッド
@@ -894,4 +957,3 @@ export declare class VtecxNextError extends Error {
894
957
  export declare class FetchError extends VtecxNextError {
895
958
  constructor(message: string);
896
959
  }
897
- export {};
package/dist/vtecxnext.js CHANGED
@@ -109,6 +109,17 @@ class VtecxNext {
109
109
  isBlank = (val) => {
110
110
  return isBlank(val);
111
111
  };
112
+ /**
113
+ * undefined、nullを空文字に変換
114
+ * @param val 文字列
115
+ * @returns 変換した文字列
116
+ */
117
+ null2blank = (val) => {
118
+ if (val == undefined || val == null) {
119
+ return '';
120
+ }
121
+ return val;
122
+ };
112
123
  /**
113
124
  * X-Requested-With header check.
114
125
  * If not specified, set status 417 to the response.
@@ -2148,6 +2159,77 @@ class VtecxNext {
2148
2159
  // 戻り値
2149
2160
  return await getJson(response);
2150
2161
  };
2162
+ /**
2163
+ * add group
2164
+ * (not yet joined)
2165
+ * @param group group
2166
+ * @param selfid hierarchical name under my group alias
2167
+ * @return feed
2168
+ */
2169
+ addGroup = async (group, selfid) => {
2170
+ //console.log(`[vtecxnext addGroup] start. group=${group} selfid=${selfid} uids=${uids}`)
2171
+ // 入力チェック
2172
+ checkUri(group, 'group key');
2173
+ //checkNotNull(selfid, 'selfid (hierarchical name under my group alias)')
2174
+ // vte.cxへリクエスト
2175
+ const method = 'POST';
2176
+ const url = `${SERVLETPATH_PROVIDER}${group}?_addgroup${selfid ? '&_selfid=' + selfid : ''}`;
2177
+ let response;
2178
+ try {
2179
+ response = await this.requestVtecx(method, url);
2180
+ }
2181
+ catch (e) {
2182
+ throw newFetchError(e, true);
2183
+ }
2184
+ //console.log(`[vtecxnext addGroup] response. status=${response.status}`)
2185
+ // vte.cxからのset-cookieを転記
2186
+ this.setCookie(response);
2187
+ // レスポンスのエラーチェック
2188
+ await checkVtecxResponse(response);
2189
+ // 戻り値
2190
+ return await getJson(response);
2191
+ };
2192
+ /**
2193
+ * add group by admin
2194
+ * (not yet joined)
2195
+ * @param uids uid list
2196
+ * @param group group
2197
+ * @param selfid hierarchical name under my group alias
2198
+ * @return feed
2199
+ */
2200
+ addGroupByAdmin = async (uids, group, selfid) => {
2201
+ //console.log(`[vtecxnext addGroupByAdmin] start. group=${group} selfid=${selfid} uids=${uids}`)
2202
+ // 入力チェック
2203
+ checkUri(group, 'group key');
2204
+ //checkNotNull(selfid, 'selfid (hierarchical name under my group alias)')
2205
+ // vte.cxへリクエスト
2206
+ const method = 'POST';
2207
+ const url = `${SERVLETPATH_PROVIDER}${group}?_addgroupByAdmin${selfid ? '&_selfid=' + selfid : ''}`;
2208
+ let value;
2209
+ if (uids) {
2210
+ const feed = [];
2211
+ for (const uid of uids) {
2212
+ const entry = { 'link': [{ '___rel': 'self', '___href': `/_user/${uid}` }] };
2213
+ feed.push(entry);
2214
+ }
2215
+ value = JSON.stringify(feed);
2216
+ }
2217
+ checkNotNull(value, 'uid');
2218
+ let response;
2219
+ try {
2220
+ response = await this.requestVtecx(method, url, value);
2221
+ }
2222
+ catch (e) {
2223
+ throw newFetchError(e, true);
2224
+ }
2225
+ //console.log(`[vtecxnext addGroupByAdmin] response. status=${response.status}`)
2226
+ // vte.cxからのset-cookieを転記
2227
+ this.setCookie(response);
2228
+ // レスポンスのエラーチェック
2229
+ await checkVtecxResponse(response);
2230
+ // 戻り値
2231
+ return await getJson(response);
2232
+ };
2151
2233
  /**
2152
2234
  * join to the group
2153
2235
  * @param group group
@@ -2158,10 +2240,10 @@ class VtecxNext {
2158
2240
  //console.log(`[vtecxnext joinGroup] start. group=${group} selfid=${selfid}`)
2159
2241
  // 入力チェック
2160
2242
  checkUri(group);
2161
- checkNotNull(selfid, 'selfid (hierarchical name under my group alias)');
2243
+ //checkNotNull(selfid, 'selfid (hierarchical name under my group alias)')
2162
2244
  // vte.cxへリクエスト
2163
2245
  const method = 'PUT';
2164
- const url = `${SERVLETPATH_PROVIDER}${group}?_joingroup&_selfid=${selfid}`;
2246
+ const url = `${SERVLETPATH_PROVIDER}${group}?_joingroup${selfid ? '&_selfid=' + selfid : ''}`;
2165
2247
  let response;
2166
2248
  try {
2167
2249
  response = await this.requestVtecx(method, url);
@@ -2294,14 +2376,18 @@ class VtecxNext {
2294
2376
  };
2295
2377
  /**
2296
2378
  * add user
2297
- * @param feed entry (JSON)
2379
+ * @param adduserInfo adduser infomation
2298
2380
  * @param reCaptchaToken reCAPTCHA token
2299
2381
  * @return message feed
2300
2382
  */
2301
- adduser = async (feed, reCaptchaToken) => {
2383
+ adduser = async (adduserInfo, reCaptchaToken) => {
2302
2384
  //console.log(`[vtecxnext adduser] start. feed=${feed}`)
2303
2385
  // 入力チェック
2304
- checkNotNull(feed, 'Feed');
2386
+ checkNotNull(adduserInfo, 'username');
2387
+ checkNotNull(adduserInfo.username, 'username');
2388
+ checkNotNull(adduserInfo.pswd, 'pswd');
2389
+ const entry = this.convertAdduserInfoToEntry(adduserInfo);
2390
+ const feed = [entry];
2305
2391
  // vte.cxへリクエスト
2306
2392
  const method = 'POST';
2307
2393
  const param = reCaptchaToken ? `&g-recaptcha-token=${reCaptchaToken}` : '';
@@ -2320,16 +2406,38 @@ class VtecxNext {
2320
2406
  await checkVtecxResponse(response);
2321
2407
  return await getJson(response);
2322
2408
  };
2409
+ /**
2410
+ * convert adduser info to argument entry
2411
+ * @param adduserInfo adduser info
2412
+ * @param isNoPswd パスワードを付加しない場合true(passresetの場合true)
2413
+ * @returns entry
2414
+ */
2415
+ convertAdduserInfoToEntry = (adduserInfo, isNoPswd) => {
2416
+ return {
2417
+ 'contributor': [{
2418
+ 'uri': `urn:vte.cx:auth:${this.null2blank(adduserInfo.username)}${isNoPswd ? '' : ',' + this.null2blank(adduserInfo.pswd)}`,
2419
+ 'name': adduserInfo.nickname,
2420
+ }],
2421
+ 'title': adduserInfo.emailSubject,
2422
+ 'summary': adduserInfo.emailText,
2423
+ 'content': { '______text': adduserInfo.emailHtml }
2424
+ };
2425
+ };
2323
2426
  /**
2324
2427
  * add user by user admin
2325
2428
  * @param feed entries (JSON)
2326
- * @param reCaptchaToken reCAPTCHA token
2327
2429
  * @return message feed
2328
2430
  */
2329
- adduserByAdmin = async (feed) => {
2431
+ //adduserByAdmin = async (feed:any): Promise<any> => {
2432
+ adduserByAdmin = async (adduserInfos) => {
2330
2433
  //console.log(`[vtecxnext adduserByAdmin] start. feed=${feed}`)
2331
2434
  // 入力チェック
2332
- checkNotNull(feed, 'Feed');
2435
+ checkNotNull(adduserInfos, 'username');
2436
+ const feed = [];
2437
+ for (const adduserInfo of adduserInfos) {
2438
+ const entry = this.convertAdduserInfoToEntry(adduserInfo);
2439
+ feed.push(entry);
2440
+ }
2333
2441
  // vte.cxへリクエスト
2334
2442
  const method = 'POST';
2335
2443
  const url = `${SERVLETPATH_DATA}/?_adduserByAdmin`;
@@ -2347,16 +2455,51 @@ class VtecxNext {
2347
2455
  await checkVtecxResponse(response);
2348
2456
  return await getJson(response);
2349
2457
  };
2458
+ /**
2459
+ * add user by group admin
2460
+ * @param feed entries (JSON)
2461
+ * @param groupname group name
2462
+ * @return message feed
2463
+ */
2464
+ adduserByGroupadmin = async (adduserInfos, groupname) => {
2465
+ //console.log(`[vtecxnext adduserByGroupadmin] start. feed=${feed}`)
2466
+ // 入力チェック
2467
+ checkNotNull(adduserInfos, 'username');
2468
+ checkNotNull(groupname, 'group name');
2469
+ const feed = [];
2470
+ for (const adduserInfo of adduserInfos) {
2471
+ const entry = this.convertAdduserInfoToEntry(adduserInfo);
2472
+ feed.push(entry);
2473
+ }
2474
+ // vte.cxへリクエスト
2475
+ const method = 'POST';
2476
+ const url = `${SERVLETPATH_DATA}/?_adduserByGroupadmin=${groupname}`;
2477
+ let response;
2478
+ try {
2479
+ response = await this.requestVtecx(method, url, JSON.stringify(feed));
2480
+ }
2481
+ catch (e) {
2482
+ throw newFetchError(e, true);
2483
+ }
2484
+ //console.log(`[vtecxnext adduserByGroupadmin] response. status=${response.status}`)
2485
+ // vte.cxからのset-cookieを転記
2486
+ this.setCookie(response);
2487
+ // レスポンスのエラーチェック
2488
+ await checkVtecxResponse(response);
2489
+ return await getJson(response);
2490
+ };
2350
2491
  /**
2351
2492
  * Send email for password reset
2352
- * @param feed entry (JSON)
2493
+ * @param adduserInfo mailaddress
2353
2494
  * @param reCaptchaToken reCAPTCHA token
2354
2495
  * @return message feed
2355
2496
  */
2356
- passreset = async (feed, reCaptchaToken) => {
2497
+ passreset = async (adduserInfo, reCaptchaToken) => {
2357
2498
  //console.log(`[vtecxnext passreset] start. feed=${feed}`)
2358
2499
  // 入力チェック
2359
- checkNotNull(feed, 'Feed');
2500
+ checkNotNull(adduserInfo, 'email address');
2501
+ const entry = this.convertAdduserInfoToEntry(adduserInfo, true);
2502
+ const feed = [entry];
2360
2503
  // vte.cxへリクエスト
2361
2504
  const method = 'POST';
2362
2505
  const param = reCaptchaToken ? `&g-recaptcha-token=${reCaptchaToken}` : '';
@@ -2377,13 +2520,27 @@ class VtecxNext {
2377
2520
  };
2378
2521
  /**
2379
2522
  * change password
2380
- * @param feed entry (JSON)
2523
+ * @param newpswd new password
2524
+ * @param oldpswd old password
2525
+ * @param passresetToken password reset token
2381
2526
  * @return message feed
2382
2527
  */
2383
- changepass = async (feed) => {
2528
+ changepass = async (newpswd, oldpswd, passresetToken) => {
2384
2529
  //console.log(`[vtecxnext changepass] start. feed=${feed}`)
2385
2530
  // 入力チェック
2386
- checkNotNull(feed, 'Feed');
2531
+ checkNotNull(newpswd, 'new password');
2532
+ const contributors = [];
2533
+ const newPswdContributor = { 'uri': `urn:vte.cx:auth:,${newpswd}` };
2534
+ contributors.push(newPswdContributor);
2535
+ if (oldpswd) {
2536
+ const oldPswdContributor = { 'uri': `urn:vte.cx:oldphash:${oldpswd}` };
2537
+ contributors.push(oldPswdContributor);
2538
+ }
2539
+ if (passresetToken) {
2540
+ const passresetTokenContributor = { 'uri': `urn:vte.cx:passreset_token:${passresetToken}` };
2541
+ contributors.push(passresetTokenContributor);
2542
+ }
2543
+ const feed = [{ 'contributor': contributors }];
2387
2544
  // vte.cxへリクエスト
2388
2545
  const method = 'PUT';
2389
2546
  const url = `${SERVLETPATH_DATA}/?_changephash`;
@@ -2403,13 +2560,28 @@ class VtecxNext {
2403
2560
  };
2404
2561
  /**
2405
2562
  * change password by user admin
2406
- * @param feed entry (JSON)
2563
+ * @param changepassByAdminInfos password change information (uid, password)
2407
2564
  * @return message feed
2408
2565
  */
2409
- changepassByAdmin = async (feed) => {
2566
+ changepassByAdmin = async (changepassByAdminInfos) => {
2410
2567
  //console.log(`[vtecxnext changepassByAdmin] start. feed=${feed}`)
2411
2568
  // 入力チェック
2412
- checkNotNull(feed, 'Feed');
2569
+ checkNotNull(changepassByAdminInfos, 'password change information');
2570
+ const feed = [];
2571
+ for (const changepassByAdminInfo of changepassByAdminInfos) {
2572
+ // 入力チェック
2573
+ checkNotNull(changepassByAdminInfo.uid, 'password change information');
2574
+ checkNotNull(changepassByAdminInfo.pswd, 'password change information');
2575
+ const entry = {
2576
+ 'contributor': [
2577
+ { 'uri': `urn:vte.cx:auth:,${changepassByAdminInfo.pswd}` }
2578
+ ],
2579
+ 'link': [
2580
+ { '___rel': 'self', '___href': `/_user/${changepassByAdminInfo.uid}/auth` }
2581
+ ]
2582
+ };
2583
+ feed.push(entry);
2584
+ }
2413
2585
  // vte.cxへリクエスト
2414
2586
  const method = 'PUT';
2415
2587
  const url = `${SERVLETPATH_DATA}/?_changephashByAdmin`;
@@ -2429,13 +2601,15 @@ class VtecxNext {
2429
2601
  };
2430
2602
  /**
2431
2603
  * change login user's account
2432
- * @param feed entries (JSON)
2604
+ * @param adduserInfo change user info
2433
2605
  * @return message feed
2434
2606
  */
2435
- changeaccount = async (feed) => {
2607
+ changeaccount = async (adduserInfo) => {
2436
2608
  //console.log(`[vtecxnext changeaccount] start. feed=${feed}`)
2437
2609
  // 入力チェック
2438
- checkNotNull(feed, 'Feed');
2610
+ checkNotNull(adduserInfo, 'user info');
2611
+ const entry = this.convertAdduserInfoToEntry(adduserInfo);
2612
+ const feed = [entry];
2439
2613
  // vte.cxへリクエスト
2440
2614
  const method = 'PUT';
2441
2615
  const url = `${SERVLETPATH_DATA}/?_changeaccount`;
@@ -2534,13 +2708,29 @@ class VtecxNext {
2534
2708
  };
2535
2709
  /**
2536
2710
  * revoke users
2537
- * @param feed entries (JSON)
2711
+ * @param accounts account list
2712
+ * @param uids uid list
2538
2713
  * @return message feed
2539
2714
  */
2540
- revokeusers = async (feed) => {
2715
+ revokeusers = async (accounts, uids) => {
2541
2716
  //console.log(`[vtecxnext revokeusers] start. feed=${feed}`)
2542
2717
  // 入力チェック
2543
- checkNotNull(feed, 'Feed');
2718
+ if (isBlank(accounts) && isBlank(uids)) {
2719
+ throw new VtecxNextError(400, `account or uid is required.`);
2720
+ }
2721
+ const feed = [];
2722
+ if (accounts) {
2723
+ for (const account of accounts) {
2724
+ const entry = { 'title': account };
2725
+ feed.push(entry);
2726
+ }
2727
+ }
2728
+ if (uids) {
2729
+ for (const uid of uids) {
2730
+ const entry = { 'link': [{ '___rel': 'self', '___href': `/_user/${uid}` }] };
2731
+ feed.push(entry);
2732
+ }
2733
+ }
2544
2734
  // vte.cxへリクエスト
2545
2735
  const method = 'PUT';
2546
2736
  const url = `${SERVLETPATH_DATA}/?_revokeuser`;
@@ -2587,13 +2777,29 @@ class VtecxNext {
2587
2777
  };
2588
2778
  /**
2589
2779
  * activate users
2590
- * @param feed entries (JSON)
2780
+ * @param accounts account list
2781
+ * @param uids uid list
2591
2782
  * @return message feed
2592
2783
  */
2593
- activateusers = async (feed) => {
2784
+ activateusers = async (accounts, uids) => {
2594
2785
  //console.log(`[vtecxnext activateusers] start. feed=${feed}`)
2595
2786
  // 入力チェック
2596
- checkNotNull(feed, 'Feed');
2787
+ if (isBlank(accounts) && isBlank(uids)) {
2788
+ throw new VtecxNextError(400, `account or uid is required.`);
2789
+ }
2790
+ const feed = [];
2791
+ if (accounts) {
2792
+ for (const account of accounts) {
2793
+ const entry = { 'title': account };
2794
+ feed.push(entry);
2795
+ }
2796
+ }
2797
+ if (uids) {
2798
+ for (const uid of uids) {
2799
+ const entry = { 'link': [{ '___rel': 'self', '___href': `/_user/${uid}` }] };
2800
+ feed.push(entry);
2801
+ }
2802
+ }
2597
2803
  // vte.cxへリクエスト
2598
2804
  const method = 'PUT';
2599
2805
  const url = `${SERVLETPATH_DATA}/?_activateuser`;
@@ -2665,13 +2871,29 @@ class VtecxNext {
2665
2871
  };
2666
2872
  /**
2667
2873
  * revoke users
2668
- * @param feed entries (JSON)
2874
+ * @param accounts account list
2875
+ * @param uids uid list
2669
2876
  * @return message feed
2670
2877
  */
2671
- deleteusers = async (feed) => {
2878
+ deleteusers = async (accounts, uids) => {
2672
2879
  //console.log(`[vtecxnext deleteusers] start. feed=${feed}`)
2673
2880
  // 入力チェック
2674
- checkNotNull(feed, 'Feed');
2881
+ if (isBlank(accounts) && isBlank(uids)) {
2882
+ throw new VtecxNextError(400, `account or uid is required.`);
2883
+ }
2884
+ const feed = [];
2885
+ if (accounts) {
2886
+ for (const account of accounts) {
2887
+ const entry = { 'title': account };
2888
+ feed.push(entry);
2889
+ }
2890
+ }
2891
+ if (uids) {
2892
+ for (const uid of uids) {
2893
+ const entry = { 'link': [{ '___rel': 'self', '___href': `/_user/${uid}` }] };
2894
+ feed.push(entry);
2895
+ }
2896
+ }
2675
2897
  // vte.cxへリクエスト
2676
2898
  const method = 'DELETE';
2677
2899
  const url = `${SERVLETPATH_DATA}/?_deleteuser`;
@@ -3244,6 +3466,45 @@ class VtecxNext {
3244
3466
  //console.log(`[vtecxnext mergeOAuthUserLine] start. feed=${feed}`)
3245
3467
  return this.mergeOAuthUser('line', rxid);
3246
3468
  };
3469
+ /**
3470
+ * create group admin
3471
+ * @param CreateGroupadminInfo group name and uid list
3472
+ * @return message feed
3473
+ */
3474
+ createGroupadmin = async (createGroupadminInfos) => {
3475
+ //console.log(`[vtecxnext createGroupadmin] start. feed=${feed}`)
3476
+ // 入力チェック
3477
+ checkNotNull(createGroupadminInfos, 'group name');
3478
+ const feed = [];
3479
+ for (const createGroupadminInfo of createGroupadminInfos) {
3480
+ checkNotNull(createGroupadminInfo.group, 'group name');
3481
+ checkContainSlash(createGroupadminInfo.group, 'group name');
3482
+ checkNotNull(createGroupadminInfo.uids, 'uid');
3483
+ const links = [{ '___rel': 'self', '___href': `/_group/${createGroupadminInfo.group}` }];
3484
+ for (const uid of createGroupadminInfo.uids) {
3485
+ const link = { '___rel': 'via', '___title': uid };
3486
+ links.push(link);
3487
+ }
3488
+ const entry = { 'link': links };
3489
+ feed.push(entry);
3490
+ }
3491
+ // vte.cxへリクエスト
3492
+ const method = 'POST';
3493
+ const url = `${SERVLETPATH_DATA}/?_creategroupadmin`;
3494
+ let response;
3495
+ try {
3496
+ response = await this.requestVtecx(method, url, JSON.stringify(feed));
3497
+ }
3498
+ catch (e) {
3499
+ throw newFetchError(e, true);
3500
+ }
3501
+ //console.log(`[vtecxnext createGroupadmin] response. status=${response.status}`)
3502
+ // vte.cxからのset-cookieを転記
3503
+ this.setCookie(response);
3504
+ // レスポンスのエラーチェック
3505
+ await checkVtecxResponse(response);
3506
+ return await getJson(response);
3507
+ };
3247
3508
  //----------------------
3248
3509
  /**
3249
3510
  * vte.cxへリクエスト
@@ -3689,6 +3950,7 @@ const buffer = async (readable) => {
3689
3950
  };
3690
3951
  /**
3691
3952
  * null、undefined、空文字の判定
3953
+ * 配列で空の場合もtrueを返す。
3692
3954
  * @param val チェック値
3693
3955
  * @returns null、undefined、空文字の場合true
3694
3956
  */
@@ -3696,6 +3958,9 @@ const isBlank = (val) => {
3696
3958
  if (val === null || val === undefined || val === '') {
3697
3959
  return true;
3698
3960
  }
3961
+ if (Array.isArray(val) && val.length === 0) {
3962
+ return true;
3963
+ }
3699
3964
  return false;
3700
3965
  };
3701
3966
  /**
@@ -3734,6 +3999,17 @@ const checkNotNull = (val, name) => {
3734
3999
  throw new VtecxNextError(400, `${name ?? 'Key'} is required.`);
3735
4000
  }
3736
4001
  };
4002
+ /**
4003
+ * 文字列にスラッシュが含まれている場合エラー
4004
+ * エラーの場合 VtecxNextError をスローする。
4005
+ * @param val チェック文字列
4006
+ * @param name エラーの場合の項目名称
4007
+ */
4008
+ const checkContainSlash = (val, name) => {
4009
+ if (val.indexOf('/') > -1) {
4010
+ throw new VtecxNextError(400, `${name} cannot contain a slash : ${val}`);
4011
+ }
4012
+ };
3737
4013
  /**
3738
4014
  * キーチェック。
3739
4015
  * 入力チェックと、先頭が/で始まっているかどうかチェックする。
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vtecx/vtecxnext",
3
- "version": "2.1.3",
3
+ "version": "2.2.0",
4
4
  "description": "vte.cx Next.js api",
5
5
  "main": "dist/index.js",
6
6
  "files": [