@helyx/module-account-gate 2.1.2 → 2.1.3

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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,12 @@
1
1
  # Changelog
2
2
 
3
+ ## 2.1.3
4
+
5
+ ### Patch Changes
6
+
7
+ - Respect status filters and bounded cursor paging for Access Control gate panels shown in Server Overview. Reuse canonical managed-resource permissions and detail views.
8
+ - Exclude bot and unconfirmed account types from member tables, searches and direct member details while preserving retained summaries.
9
+
3
10
  ## 2.1.2
4
11
 
5
12
  ### Patch Changes
@@ -2,7 +2,7 @@ export declare const ACCOUNT_GATE_IDENTITY: {
2
2
  readonly packageName: "@helyx/module-account-gate";
3
3
  readonly moduleId: "helyx.account-gate";
4
4
  readonly name: "Access Control";
5
- readonly version: "2.1.2";
5
+ readonly version: "2.1.3";
6
6
  readonly releaseStatus: "live";
7
7
  readonly category: "safety";
8
8
  readonly icon: "shield-check";
package/dist/contracts.js CHANGED
@@ -2,7 +2,7 @@ export const ACCOUNT_GATE_IDENTITY = {
2
2
  packageName: "@helyx/module-account-gate",
3
3
  moduleId: "helyx.account-gate",
4
4
  name: "Access Control",
5
- version: "2.1.2",
5
+ version: "2.1.3",
6
6
  releaseStatus: "live",
7
7
  category: "safety",
8
8
  icon: "shield-check",
@@ -31,7 +31,9 @@ export const accountGateMemberResource = {
31
31
  });
32
32
  const identities = await resolveLiveIdentities(context, page.records.map((row) => stringValue(row.member_user_id)));
33
33
  return {
34
- items: page.records.map((row) => memberSummary(row, identities.get(stringValue(row.member_user_id)))),
34
+ items: page.records
35
+ .filter((row) => identities.has(stringValue(row.member_user_id)))
36
+ .map((row) => memberSummary(row, identities.get(stringValue(row.member_user_id)))),
35
37
  ...(page.nextCursor
36
38
  ? {
37
39
  nextCursor: encodeRecordCursor(context.guildId, stringValue(page.nextCursor[1])),
@@ -45,6 +47,8 @@ export const accountGateMemberResource = {
45
47
  if (!row)
46
48
  return null;
47
49
  const identities = await resolveLiveIdentities(context, [resourceId]);
50
+ if (!identities.has(resourceId))
51
+ return null;
48
52
  return memberDetail(row, identities.get(resourceId));
49
53
  },
50
54
  preview() {
@@ -104,6 +108,8 @@ async function searchKnownMembers(context, search, cursor) {
104
108
  if (!row)
105
109
  return { items: [] };
106
110
  const identities = await resolveLiveIdentities(context, [search]);
111
+ if (!identities.has(search))
112
+ return { items: [] };
107
113
  return { items: [memberSummary(row, identities.get(search))] };
108
114
  }
109
115
  const offset = cursor ? decodeSearchCursor(cursor, search) : 0;
@@ -113,7 +119,7 @@ async function searchKnownMembers(context, search, cursor) {
113
119
  limit: SEARCH_RESULT_LIMIT,
114
120
  });
115
121
  const known = (await Promise.all(matches
116
- .filter(({ isBot }) => !isBot)
122
+ .filter(({ isBot }) => isBot === false)
117
123
  .map(async (identity) => ({
118
124
  identity: {
119
125
  userId: identity.userId,
@@ -138,7 +144,7 @@ async function resolveLiveIdentities(context, userIds) {
138
144
  guildId: context.guildId,
139
145
  userIds,
140
146
  });
141
- return new Map(resolved.flatMap((member) => member.displayName === null
147
+ return new Map(resolved.flatMap((member) => member.isBot !== false
142
148
  ? []
143
149
  : [
144
150
  [
@@ -165,8 +171,8 @@ function memberSummary(row, identity) {
165
171
  attributes: {
166
172
  memberUserId,
167
173
  displayName: identity?.displayName ?? null,
168
- avatarUrl: identity?.avatarUrl ?? null,
169
- memberPresent: identity !== undefined,
174
+ avatarUrl: identity?.avatarUrl || null,
175
+ memberPresent: identity?.displayName != null,
170
176
  completedAt: completedAt?.toISOString() ?? null,
171
177
  },
172
178
  updatedAt: updatedAt.toISOString(),
@@ -178,7 +184,7 @@ function memberDetail(row, identity) {
178
184
  ...summary,
179
185
  value: {
180
186
  memberUserId: summary.id,
181
- memberPresent: identity !== undefined,
187
+ memberPresent: identity?.displayName != null,
182
188
  },
183
189
  };
184
190
  }
@@ -33,7 +33,7 @@ export declare function summaryValues(input: {
33
33
  pending_reason: "none" | "account_too_new";
34
34
  last_failure_terminal_id: string;
35
35
  left_at: Date;
36
- last_decision: "passed" | "failed" | "review" | "kicked" | "pending" | "finalizing" | "kick_pending" | "dismissed" | "revoked";
36
+ last_decision: "pending" | "passed" | "review" | "failed" | "revoked" | "finalizing" | "kicked" | "kick_pending" | "dismissed";
37
37
  revision: number;
38
38
  retention_until: Date;
39
39
  created_at: Date;
@@ -13,12 +13,19 @@ const MAX_GATE_PANELS = 10;
13
13
  export const gatePanelResource = {
14
14
  id: "gate-panel",
15
15
  availableWhileDisabled: true,
16
- async list(context) {
16
+ async list(context, input) {
17
+ const offset = Number(input.cursor ?? "0");
18
+ if (!Number.isSafeInteger(offset) || offset < 0 || offset > MAX_GATE_PANELS)
19
+ throw new DashboardActionValidationError("Invalid panel cursor. Reload the list.");
20
+ const limit = Math.min(MAX_GATE_PANELS, Math.max(1, input.limit));
17
21
  const page = await records(context).findMany({
18
22
  moduleId: ACCOUNT_GATE_IDENTITY.moduleId,
19
23
  collection: "gate_panels",
20
24
  select: accountGateRecords.gate_panels.readableFields,
21
- where: { guild_id: context.guildId },
25
+ where: {
26
+ guild_id: context.guildId,
27
+ ...(input.filters?.status ? { status: input.filters.status } : {}),
28
+ },
22
29
  orderBy: [
23
30
  { field: "guild_id", direction: "asc" },
24
31
  { field: "created_at", direction: "asc" },
@@ -26,8 +33,15 @@ export const gatePanelResource = {
26
33
  ],
27
34
  limit: MAX_GATE_PANELS,
28
35
  });
29
- const details = await Promise.all(page.records.map((row) => inspectedDetail(context, row)));
30
- return { items: details.map(managedResourceSummary) };
36
+ const details = await Promise.all(page.records
37
+ .slice(offset, offset + limit)
38
+ .map((row) => inspectedDetail(context, row)));
39
+ return {
40
+ items: details.map(managedResourceSummary),
41
+ ...(offset + details.length < page.records.length
42
+ ? { nextCursor: String(offset + details.length) }
43
+ : {}),
44
+ };
31
45
  },
32
46
  async read(context, resourceId) {
33
47
  const row = await records(context).findOne({
package/manifest.json CHANGED
@@ -11,7 +11,7 @@
11
11
  "healthExposure": "direct",
12
12
  "id": "helyx.account-gate",
13
13
  "name": "Access Control",
14
- "version": "2.1.2",
14
+ "version": "2.1.3",
15
15
  "description": "Require new members to complete configurable Discord interaction checks before gaining access.",
16
16
  "entry": "./dist/index.js",
17
17
  "framework": "^0.2.0",
@@ -618,7 +618,26 @@
618
618
  "equals": "password"
619
619
  }
620
620
  }
621
- ]
621
+ ],
622
+ "query": {
623
+ "filters": [
624
+ {
625
+ "key": "status",
626
+ "label": "State",
627
+ "type": "select",
628
+ "options": [
629
+ {
630
+ "value": "posted",
631
+ "label": "Posted"
632
+ },
633
+ {
634
+ "value": "missing",
635
+ "label": "Missing"
636
+ }
637
+ ]
638
+ }
639
+ ]
640
+ }
622
641
  },
623
642
  {
624
643
  "id": "members",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@helyx/module-account-gate",
3
- "version": "2.1.2",
3
+ "version": "2.1.3",
4
4
  "description": "Require configurable Discord interaction checks before new members gain access.",
5
5
  "keywords": [
6
6
  "helyx",
@@ -51,6 +51,6 @@
51
51
  },
52
52
  "dependencies": {
53
53
  "@helyx/module-manifest": ">=0.14.0 <0.15.0",
54
- "@helyx/sdk": ">=0.17.0 <0.18.0"
54
+ "@helyx/sdk": ">=0.17.1 <0.18.0"
55
55
  }
56
56
  }