mirror of
https://github.com/wassname/talk.git
synced 2026-08-06 13:41:02 +08:00
[CORL-810] Custom Moderation Phases (#2901)
* feat: initial implementation
* feat: renamed fields from mutations
* fix: more renaming to streamline {Key,Secret}->SigningSecret
* feat: introduced WrappedInternalError
* feat: enhanced extern payload, more fetch options
- Added tenant.{id,domain} to extern payload
- Added site.id to the extern payload
- Added response size limit to fetch
- Added new SCRAPE_MAX_RESPONSE_SIZE env var for managing the size of
responses for scraping
* fix: fixed bug with scrape invocation
* feat: added more queries + mutations
- Added Query.externalModerationPhase
- Added Mutation.createExternalModerationPhase
- Added Mutation.updateExternalModerationPhase
- Added Mutation.enableExternalModerationPhase
- Added Mutation.disableExternalModerationPhase
- Added Mutation.deleteExternalModerationPhase
- Added Mutation.rotateExternalModerationPhaseSigningSecret
* feat: added secret management
* fix: linting
* fix: merge conflict fix
* feat: added UI
* fix: linting
* fix: linting
* fix: updated snapshots
* fix: improved docs
* fix: improved docs
* fix: added locales
* review: improve naming
* review: some review changes
- Switched /moderation/phase to /moderation/phases
- Fixed scrolling
- Fixed redirection
* fix: added scroll timeout for webhooks
This commit is contained in:
@@ -19,7 +19,7 @@ import { WebhookQueue } from "coral-server/queue/tasks/webhook";
|
||||
import { I18n } from "coral-server/services/i18n";
|
||||
import { JWTSigningConfig } from "coral-server/services/jwt";
|
||||
import { AugmentedRedis } from "coral-server/services/redis";
|
||||
import TenantCache from "coral-server/services/tenant/cache";
|
||||
import { TenantCache } from "coral-server/services/tenant/cache";
|
||||
import { Request } from "coral-server/types/express";
|
||||
|
||||
import loaders from "./loaders";
|
||||
|
||||
@@ -6,7 +6,7 @@ import { merge } from "lodash";
|
||||
import {
|
||||
CoralError,
|
||||
InternalDevelopmentError,
|
||||
InternalError,
|
||||
WrappedInternalError,
|
||||
} from "coral-server/errors";
|
||||
import GraphContext from "coral-server/graph/context";
|
||||
import { getOriginalError } from "./helpers";
|
||||
@@ -71,7 +71,7 @@ function getWrappedOriginalError(
|
||||
);
|
||||
}
|
||||
|
||||
return new InternalError(originalError, "wrapped internal error");
|
||||
return new WrappedInternalError(originalError, "wrapped internal error");
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import DataLoader from "dataloader";
|
||||
|
||||
import GraphContext from "coral-server/graph/context";
|
||||
import { retrieveLastUsedAtTenantSSOKeys } from "coral-server/models/tenant";
|
||||
import { retrieveLastUsedAtTenantSSOSigningSecrets } from "coral-server/models/tenant";
|
||||
import { discoverOIDCConfiguration } from "coral-server/services/tenant";
|
||||
|
||||
import { GQLDiscoveredOIDCConfiguration } from "coral-server/graph/schema/__generated__/types";
|
||||
@@ -19,7 +19,7 @@ export default (ctx: GraphContext) => ({
|
||||
cache: !ctx.disableCaching,
|
||||
}
|
||||
),
|
||||
retrieveSSOKeyLastUsedAt: new DataLoader((kids: string[]) =>
|
||||
retrieveLastUsedAtTenantSSOKeys(ctx.redis, ctx.tenant.id, kids)
|
||||
retrieveSSOSigningSecretLastUsedAt: new DataLoader((kids: string[]) =>
|
||||
retrieveLastUsedAtTenantSSOSigningSecrets(ctx.redis, ctx.tenant.id, kids)
|
||||
),
|
||||
});
|
||||
|
||||
@@ -211,12 +211,13 @@ export default (ctx: GraphContext) => ({
|
||||
// This typecast is needed because the custom `ms` format does not return
|
||||
// the desired `number` type even though that's the only type it can
|
||||
// output.
|
||||
scraper.scrape(
|
||||
scraper.scrape({
|
||||
url,
|
||||
(ctx.config.get("scrape_timeout") as unknown) as number,
|
||||
ctx.tenant.stories.scraping.customUserAgent,
|
||||
ctx.tenant.stories.scraping.proxyURL
|
||||
)
|
||||
timeout: (ctx.config.get("scrape_timeout") as unknown) as number,
|
||||
size: ctx.config.get("scrape_response_max_size"),
|
||||
customUserAgent: ctx.tenant.stories.scraping.customUserAgent,
|
||||
proxyURL: ctx.tenant.stories.scraping.proxyURL,
|
||||
})
|
||||
),
|
||||
{
|
||||
// Disable caching for the DataLoader if the Context is designed to be
|
||||
|
||||
@@ -2,34 +2,46 @@ import GraphContext from "coral-server/graph/context";
|
||||
import { Tenant } from "coral-server/models/tenant";
|
||||
import {
|
||||
createAnnouncement,
|
||||
createExternalModerationPhase,
|
||||
createWebhookEndpoint,
|
||||
deactivateSSOKey,
|
||||
deactivateSSOSigningSecret,
|
||||
deleteAnnouncement,
|
||||
deleteSSOKey,
|
||||
deleteExternalModerationPhase,
|
||||
deleteSSOSigningSecret,
|
||||
deleteWebhookEndpoint,
|
||||
disableExternalModerationPhase,
|
||||
disableFeatureFlag,
|
||||
disableWebhookEndpoint,
|
||||
enableExternalModerationPhase,
|
||||
enableFeatureFlag,
|
||||
enableWebhookEndpoint,
|
||||
regenerateSSOKey,
|
||||
rotateSSOKey,
|
||||
rotateWebhookEndpointSecret,
|
||||
rotateExternalModerationPhaseSigningSecret,
|
||||
rotateSSOSigningSecret,
|
||||
rotateWebhookEndpointSigningSecret,
|
||||
sendSMTPTest,
|
||||
update,
|
||||
updateExternalModerationPhase,
|
||||
updateWebhookEndpoint,
|
||||
} from "coral-server/services/tenant";
|
||||
|
||||
import {
|
||||
GQLCreateAnnouncementInput,
|
||||
GQLCreateExternalModerationPhaseInput,
|
||||
GQLCreateWebhookEndpointInput,
|
||||
GQLDeactivateSSOKeyInput,
|
||||
GQLDeleteSSOKeyInput,
|
||||
GQLDeactivateSSOSigningSecretInput,
|
||||
GQLDeleteExternalModerationPhaseInput,
|
||||
GQLDeleteSSOSigningSecretInput,
|
||||
GQLDeleteWebhookEndpointInput,
|
||||
GQLDisableExternalModerationPhaseInput,
|
||||
GQLDisableWebhookEndpointInput,
|
||||
GQLEnableExternalModerationPhaseInput,
|
||||
GQLEnableWebhookEndpointInput,
|
||||
GQLFEATURE_FLAG,
|
||||
GQLRotateSSOKeyInput,
|
||||
GQLRotateWebhookEndpointSecretInput,
|
||||
GQLRotateExternalModerationPhaseSigningSecretInput,
|
||||
GQLRotateSSOSigningSecretInput,
|
||||
GQLRotateWebhookEndpointSigningSecretInput,
|
||||
GQLUpdateExternalModerationPhaseInput,
|
||||
GQLUpdateSettingsInput,
|
||||
GQLUpdateWebhookEndpointInput,
|
||||
} from "coral-server/graph/schema/__generated__/types";
|
||||
@@ -50,20 +62,21 @@ export const Settings = ({
|
||||
input: WithoutMutationID<GQLUpdateSettingsInput>
|
||||
): Promise<Tenant | null> =>
|
||||
update(mongo, redis, tenantCache, config, tenant, input.settings),
|
||||
// DEPRECATED: deprecated in favour of `rotateSSOSigningSecret`, remove in 6.2.0.
|
||||
regenerateSSOKey: (): Promise<Tenant | null> =>
|
||||
regenerateSSOKey(mongo, redis, tenantCache, tenant, now),
|
||||
rotateSSOKey: ({ inactiveIn }: GQLRotateSSOKeyInput) =>
|
||||
rotateSSOKey(mongo, redis, tenantCache, tenant, inactiveIn, now),
|
||||
deactivateSSOKey: ({ kid }: GQLDeactivateSSOKeyInput) =>
|
||||
deactivateSSOKey(mongo, redis, tenantCache, tenant, kid, now),
|
||||
deleteSSOKey: ({ kid }: GQLDeleteSSOKeyInput) =>
|
||||
deleteSSOKey(mongo, redis, tenantCache, tenant, kid),
|
||||
rotateSSOSigningSecret: ({ inactiveIn }: GQLRotateSSOSigningSecretInput) =>
|
||||
rotateSSOSigningSecret(mongo, redis, tenantCache, tenant, inactiveIn, now),
|
||||
deleteSSOSigningSecret: ({ kid }: GQLDeleteSSOSigningSecretInput) =>
|
||||
deleteSSOSigningSecret(mongo, redis, tenantCache, tenant, kid),
|
||||
deactivateSSOSigningSecret: ({ kid }: GQLDeactivateSSOSigningSecretInput) =>
|
||||
deactivateSSOSigningSecret(mongo, redis, tenantCache, tenant, kid, now),
|
||||
enableFeatureFlag: (flag: GQLFEATURE_FLAG) =>
|
||||
enableFeatureFlag(mongo, redis, tenantCache, tenant, flag),
|
||||
disableFeatureFlag: (flag: GQLFEATURE_FLAG) =>
|
||||
disableFeatureFlag(mongo, redis, tenantCache, tenant, flag),
|
||||
createAnnouncement: (input: GQLCreateAnnouncementInput) =>
|
||||
createAnnouncement(mongo, redis, tenantCache, tenant, input, now),
|
||||
createAnnouncement(mongo, redis, tenantCache, tenant, input),
|
||||
deleteAnnouncement: () =>
|
||||
deleteAnnouncement(mongo, redis, tenantCache, tenant),
|
||||
createWebhookEndpoint: (
|
||||
@@ -92,10 +105,59 @@ export const Settings = ({
|
||||
deleteWebhookEndpoint: (
|
||||
input: WithoutMutationID<GQLDeleteWebhookEndpointInput>
|
||||
) => deleteWebhookEndpoint(mongo, redis, tenantCache, tenant, input.id),
|
||||
rotateWebhookEndpointSecret: (
|
||||
input: WithoutMutationID<GQLRotateWebhookEndpointSecretInput>
|
||||
rotateWebhookEndpointSigningSecret: (
|
||||
input: WithoutMutationID<GQLRotateWebhookEndpointSigningSecretInput>
|
||||
) =>
|
||||
rotateWebhookEndpointSecret(
|
||||
rotateWebhookEndpointSigningSecret(
|
||||
mongo,
|
||||
redis,
|
||||
tenantCache,
|
||||
tenant,
|
||||
input.id,
|
||||
input.inactiveIn,
|
||||
now
|
||||
),
|
||||
createExternalModerationPhase: (
|
||||
input: WithoutMutationID<GQLCreateExternalModerationPhaseInput>
|
||||
) =>
|
||||
createExternalModerationPhase(
|
||||
mongo,
|
||||
redis,
|
||||
config,
|
||||
tenantCache,
|
||||
tenant,
|
||||
input,
|
||||
now
|
||||
),
|
||||
updateExternalModerationPhase: ({
|
||||
id,
|
||||
...input
|
||||
}: WithoutMutationID<GQLUpdateExternalModerationPhaseInput>) =>
|
||||
updateExternalModerationPhase(
|
||||
mongo,
|
||||
redis,
|
||||
config,
|
||||
tenantCache,
|
||||
tenant,
|
||||
id,
|
||||
input
|
||||
),
|
||||
enableExternalModerationPhase: (
|
||||
input: WithoutMutationID<GQLEnableExternalModerationPhaseInput>
|
||||
) =>
|
||||
enableExternalModerationPhase(mongo, redis, tenantCache, tenant, input.id),
|
||||
disableExternalModerationPhase: (
|
||||
input: WithoutMutationID<GQLDisableExternalModerationPhaseInput>
|
||||
) =>
|
||||
disableExternalModerationPhase(mongo, redis, tenantCache, tenant, input.id),
|
||||
deleteExternalModerationPhase: (
|
||||
input: WithoutMutationID<GQLDeleteExternalModerationPhaseInput>
|
||||
) =>
|
||||
deleteExternalModerationPhase(mongo, redis, tenantCache, tenant, input.id),
|
||||
rotateExternalModerationPhaseSigningSecret: (
|
||||
input: WithoutMutationID<GQLRotateExternalModerationPhaseSigningSecretInput>
|
||||
) =>
|
||||
rotateExternalModerationPhaseSigningSecret(
|
||||
mongo,
|
||||
redis,
|
||||
tenantCache,
|
||||
|
||||
@@ -9,6 +9,7 @@ import {
|
||||
} from "coral-server/models/action/comment";
|
||||
import * as comment from "coral-server/models/comment";
|
||||
import {
|
||||
getDepth,
|
||||
getLatestRevision,
|
||||
hasAncestors,
|
||||
hasPublishedStatus,
|
||||
@@ -52,9 +53,9 @@ export const Comment: GQLCommentTypeResolver<comment.Comment> = {
|
||||
c.revisions.length > 0
|
||||
? { revision: getLatestRevision(c), comment: c }
|
||||
: null,
|
||||
deleted: ({ deletedAt }) => !!deletedAt,
|
||||
revisionHistory: (c) =>
|
||||
c.revisions.map((revision) => ({ revision, comment: c })),
|
||||
deleted: ({ deletedAt }) => !!deletedAt,
|
||||
editing: ({ revisions, createdAt }, input, ctx) => ({
|
||||
// When there is more than one body history, then the comment has been
|
||||
// edited.
|
||||
@@ -98,8 +99,8 @@ export const Comment: GQLCommentTypeResolver<comment.Comment> = {
|
||||
}),
|
||||
viewerActionPresence: (c, input, ctx) =>
|
||||
ctx.user ? ctx.loaders.Comments.retrieveMyActionPresence.load(c.id) : null,
|
||||
parentCount: (c) => (hasAncestors(c) ? c.ancestorIDs.length : 0),
|
||||
depth: (c) => (hasAncestors(c) ? c.ancestorIDs.length : 0),
|
||||
parentCount: (c) => getDepth(c),
|
||||
depth: (c) => getDepth(c),
|
||||
rootParent: (c, input, ctx, info) =>
|
||||
hasAncestors(c)
|
||||
? maybeLoadOnlyID(ctx, info, c.ancestorIDs[c.ancestorIDs.length - 1])
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
import * as settings from "coral-server/models/settings";
|
||||
|
||||
import { GQLExternalModerationPhaseTypeResolver } from "coral-server/graph/schema/__generated__/types";
|
||||
|
||||
export const ExternalModerationPhase: GQLExternalModerationPhaseTypeResolver<settings.ExternalModerationPhase> = {
|
||||
signingSecret: ({ signingSecrets }) =>
|
||||
signingSecrets[signingSecrets.length - 1],
|
||||
};
|
||||
@@ -75,20 +75,21 @@ export const Mutation: Required<GQLMutationTypeResolver<void>> = {
|
||||
comment: await ctx.mutators.Comments.unfeature(input),
|
||||
clientMutationId,
|
||||
}),
|
||||
// DEPRECATED: deprecated in favour of `rotateSSOSigningSecret`, remove in 6.2.0.
|
||||
regenerateSSOKey: async (source, { input }, ctx) => ({
|
||||
settings: await ctx.mutators.Settings.regenerateSSOKey(),
|
||||
clientMutationId: input.clientMutationId,
|
||||
}),
|
||||
rotateSSOKey: async (source, { input }, ctx) => ({
|
||||
settings: await ctx.mutators.Settings.rotateSSOKey(input),
|
||||
rotateSSOSigningSecret: async (source, { input }, ctx) => ({
|
||||
settings: await ctx.mutators.Settings.rotateSSOSigningSecret(input),
|
||||
clientMutationId: input.clientMutationId,
|
||||
}),
|
||||
deactivateSSOKey: async (source, { input }, ctx) => ({
|
||||
settings: await ctx.mutators.Settings.deactivateSSOKey(input),
|
||||
deactivateSSOSigningSecret: async (source, { input }, ctx) => ({
|
||||
settings: await ctx.mutators.Settings.deactivateSSOSigningSecret(input),
|
||||
clientMutationId: input.clientMutationId,
|
||||
}),
|
||||
deleteSSOKey: async (source, { input }, ctx) => ({
|
||||
settings: await ctx.mutators.Settings.deleteSSOKey(input),
|
||||
deleteSSOSigningSecret: async (source, { input }, ctx) => ({
|
||||
settings: await ctx.mutators.Settings.deleteSSOSigningSecret(input),
|
||||
clientMutationId: input.clientMutationId,
|
||||
}),
|
||||
createStory: async (source, { input }, ctx) => ({
|
||||
@@ -319,12 +320,64 @@ export const Mutation: Required<GQLMutationTypeResolver<void>> = {
|
||||
endpoint: await ctx.mutators.Settings.deleteWebhookEndpoint(input),
|
||||
clientMutationId,
|
||||
}),
|
||||
rotateWebhookEndpointSecret: async (
|
||||
rotateWebhookEndpointSigningSecret: async (
|
||||
source,
|
||||
{ input: { clientMutationId, ...input } },
|
||||
ctx
|
||||
) => ({
|
||||
endpoint: await ctx.mutators.Settings.rotateWebhookEndpointSecret(input),
|
||||
endpoint: await ctx.mutators.Settings.rotateWebhookEndpointSigningSecret(
|
||||
input
|
||||
),
|
||||
clientMutationId,
|
||||
}),
|
||||
createExternalModerationPhase: async (
|
||||
source,
|
||||
{ input: { clientMutationId, ...input } },
|
||||
ctx
|
||||
) => ({
|
||||
...(await ctx.mutators.Settings.createExternalModerationPhase(input)),
|
||||
clientMutationId,
|
||||
}),
|
||||
updateExternalModerationPhase: async (
|
||||
source,
|
||||
{ input: { clientMutationId, ...input } },
|
||||
ctx
|
||||
) => ({
|
||||
phase: await ctx.mutators.Settings.updateExternalModerationPhase(input),
|
||||
clientMutationId,
|
||||
}),
|
||||
disableExternalModerationPhase: async (
|
||||
source,
|
||||
{ input: { clientMutationId, ...input } },
|
||||
ctx
|
||||
) => ({
|
||||
phase: await ctx.mutators.Settings.disableExternalModerationPhase(input),
|
||||
clientMutationId,
|
||||
}),
|
||||
enableExternalModerationPhase: async (
|
||||
source,
|
||||
{ input: { clientMutationId, ...input } },
|
||||
ctx
|
||||
) => ({
|
||||
phase: await ctx.mutators.Settings.enableExternalModerationPhase(input),
|
||||
clientMutationId,
|
||||
}),
|
||||
deleteExternalModerationPhase: async (
|
||||
source,
|
||||
{ input: { clientMutationId, ...input } },
|
||||
ctx
|
||||
) => ({
|
||||
phase: await ctx.mutators.Settings.deleteExternalModerationPhase(input),
|
||||
clientMutationId,
|
||||
}),
|
||||
rotateExternalModerationPhaseSigningSecret: async (
|
||||
source,
|
||||
{ input: { clientMutationId, ...input } },
|
||||
ctx
|
||||
) => ({
|
||||
phase: await ctx.mutators.Settings.rotateExternalModerationPhaseSigningSecret(
|
||||
input
|
||||
),
|
||||
clientMutationId,
|
||||
}),
|
||||
testSMTP: async (source, { input: { clientMutationId } }, ctx) => {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { getExternalModerationPhase } from "coral-server/models/settings";
|
||||
import { getWebhookEndpoint } from "coral-server/models/tenant";
|
||||
|
||||
import { GQLQueryTypeResolver } from "coral-server/graph/schema/__generated__/types";
|
||||
@@ -29,4 +30,8 @@ export const Query: Required<GQLQueryTypeResolver<void>> = {
|
||||
site: (source, { id }, ctx) => (id ? ctx.loaders.Sites.site.load(id) : null),
|
||||
webhookEndpoint: (source, { id }, ctx) => getWebhookEndpoint(ctx.tenant, id),
|
||||
queues: () => ({}),
|
||||
externalModerationPhase: (source, { id }, ctx) =>
|
||||
ctx.tenant.integrations.external
|
||||
? getExternalModerationPhase(ctx.tenant.integrations.external, id)
|
||||
: null,
|
||||
};
|
||||
|
||||
@@ -1,25 +1,25 @@
|
||||
import * as settings from "coral-server/models/settings";
|
||||
|
||||
import { GQLSSOAuthIntegrationTypeResolver } from "coral-server/graph/schema/__generated__/types";
|
||||
import { filterFreshSigningSecrets } from "coral-server/models/settings";
|
||||
|
||||
function getActiveSSOKey(keys: settings.Secret[]) {
|
||||
// Any key that has been rotated cannot be the active key.
|
||||
return keys.find((key) => !key.rotatedAt);
|
||||
function getActiveSSOSigningSecret(keys: settings.SigningSecret[]) {
|
||||
return keys.find(filterFreshSigningSecrets());
|
||||
}
|
||||
|
||||
export const SSOAuthIntegration: GQLSSOAuthIntegrationTypeResolver<settings.SSOAuthIntegration> = {
|
||||
key: ({ keys }) => {
|
||||
const key = getActiveSSOKey(keys);
|
||||
if (key) {
|
||||
return key.secret;
|
||||
key: ({ signingSecrets }) => {
|
||||
const signingSecret = getActiveSSOSigningSecret(signingSecrets);
|
||||
if (signingSecret) {
|
||||
return signingSecret.secret;
|
||||
}
|
||||
|
||||
return null;
|
||||
},
|
||||
keyGeneratedAt: ({ keys }) => {
|
||||
const key = getActiveSSOKey(keys);
|
||||
if (key) {
|
||||
return key.createdAt;
|
||||
keyGeneratedAt: ({ signingSecrets }) => {
|
||||
const signingSecret = getActiveSSOSigningSecret(signingSecrets);
|
||||
if (signingSecret) {
|
||||
return signingSecret.createdAt;
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
import * as settings from "coral-server/models/settings";
|
||||
|
||||
import { GQLSecretTypeResolver } from "coral-server/graph/schema/__generated__/types";
|
||||
|
||||
export const Secret: GQLSecretTypeResolver<settings.Secret> = {
|
||||
lastUsedAt: async ({ kid }, args, ctx) =>
|
||||
ctx.loaders.Auth.retrieveSSOKeyLastUsedAt.load(kid),
|
||||
};
|
||||
@@ -0,0 +1,8 @@
|
||||
import * as settings from "coral-server/models/settings";
|
||||
|
||||
import { GQLSigningSecretTypeResolver } from "coral-server/graph/schema/__generated__/types";
|
||||
|
||||
export const SigningSecret: GQLSigningSecretTypeResolver<settings.SigningSecret> = {
|
||||
lastUsedAt: async ({ kid }, args, ctx) =>
|
||||
ctx.loaders.Auth.retrieveSSOSigningSecretLastUsedAt.load(kid),
|
||||
};
|
||||
@@ -20,6 +20,7 @@ import { CommentReplyCreatedPayload } from "./CommentReplyCreatedPayload";
|
||||
import { CommentRevision } from "./CommentRevision";
|
||||
import { CommentStatusUpdatedPayload } from "./CommentStatusUpdatedPayload";
|
||||
import { DisableCommenting } from "./DisableCommenting";
|
||||
import { ExternalModerationPhase } from "./ExternalModerationPhase";
|
||||
import { FacebookAuthIntegration } from "./FacebookAuthIntegration";
|
||||
import { FeatureCommentPayload } from "./FeatureCommentPayload";
|
||||
import { Flag } from "./Flag";
|
||||
@@ -39,8 +40,8 @@ import { Queue } from "./Queue";
|
||||
import { Queues } from "./Queues";
|
||||
import { RecentCommentHistory } from "./RecentCommentHistory";
|
||||
import { RejectCommentPayload } from "./RejectCommentPayload";
|
||||
import { Secret } from "./Secret";
|
||||
import { Settings } from "./Settings";
|
||||
import { SigningSecret } from "./SigningSecret";
|
||||
import { SlackConfiguration } from "./SlackConfiguration";
|
||||
import { SSOAuthIntegration } from "./SSOAuthIntegration";
|
||||
import { Story } from "./Story";
|
||||
@@ -73,6 +74,7 @@ const Resolvers: GQLResolver = {
|
||||
CommentStatusUpdatedPayload,
|
||||
Cursor,
|
||||
DisableCommenting,
|
||||
ExternalModerationPhase,
|
||||
FacebookAuthIntegration,
|
||||
FeatureCommentPayload,
|
||||
Flag,
|
||||
@@ -92,7 +94,7 @@ const Resolvers: GQLResolver = {
|
||||
RecentCommentHistory,
|
||||
RejectCommentPayload,
|
||||
SSOAuthIntegration,
|
||||
Secret,
|
||||
SigningSecret,
|
||||
Story,
|
||||
StorySettings,
|
||||
Subscription,
|
||||
|
||||
@@ -495,7 +495,7 @@ type LocalAuthIntegration {
|
||||
## SSOAuthIntegration
|
||||
##########################
|
||||
|
||||
type Secret {
|
||||
type SigningSecret {
|
||||
"""
|
||||
kid is the identifier for the key used when verifying tokens issued by the
|
||||
provider.
|
||||
@@ -551,23 +551,23 @@ type SSOAuthIntegration {
|
||||
targetFilter: AuthenticationTargetFilter!
|
||||
|
||||
"""
|
||||
keys are the different SSOKey's used by this Tenant.
|
||||
signingSecrets are the different SigningSecret's used by this Tenant.
|
||||
"""
|
||||
keys: [Secret!]! @auth(roles: [ADMIN])
|
||||
signingSecrets: [SigningSecret!]! @auth(roles: [ADMIN])
|
||||
|
||||
"""
|
||||
key is the secret that is used to sign tokens.
|
||||
"""
|
||||
key: String
|
||||
@auth(roles: [ADMIN])
|
||||
@deprecated(reason: "field is deprecated in favour of `keys`")
|
||||
@deprecated(reason: "field is deprecated in favour of `signingSecrets`")
|
||||
|
||||
"""
|
||||
keyGeneratedAt is the Time that the key was effective from.
|
||||
"""
|
||||
keyGeneratedAt: Time
|
||||
@auth(roles: [ADMIN])
|
||||
@deprecated(reason: "field is deprecated in favour of `keys`")
|
||||
@deprecated(reason: "field is deprecated in favour of `signingSecrets`")
|
||||
}
|
||||
|
||||
##########################
|
||||
@@ -908,6 +908,73 @@ type PerspectiveExternalIntegration {
|
||||
sendFeedback: Boolean @auth(roles: [ADMIN])
|
||||
}
|
||||
|
||||
"""
|
||||
COMMENT_BODY_FORMAT describes the various formats that a comment body can be
|
||||
provided in.
|
||||
"""
|
||||
enum COMMENT_BODY_FORMAT {
|
||||
"""
|
||||
HTML describes the format of the comment body using HTML.
|
||||
"""
|
||||
HTML
|
||||
|
||||
"""
|
||||
PLAIN_TEXT describes the format of the comment body with the HTML stripped.
|
||||
"""
|
||||
PLAIN_TEXT
|
||||
}
|
||||
|
||||
"""
|
||||
ExternalModerationPhase describes a phase use in the moderation pipeline that
|
||||
calls out to an external resource as defined by the provided URL.
|
||||
"""
|
||||
type ExternalModerationPhase {
|
||||
"""
|
||||
id identifies this particular External Moderation Phase.
|
||||
"""
|
||||
id: ID!
|
||||
|
||||
"""
|
||||
name is the name assigned to this ExternalModerationPhase for identification
|
||||
purposes.
|
||||
"""
|
||||
name: String!
|
||||
|
||||
"""
|
||||
enabled when true, will use this phase in the moderation pipeline.
|
||||
"""
|
||||
enabled: Boolean!
|
||||
|
||||
"""
|
||||
url is the actual URL that should be called.
|
||||
"""
|
||||
url: String!
|
||||
|
||||
"""
|
||||
format is the format of the comment body sent.
|
||||
"""
|
||||
format: COMMENT_BODY_FORMAT!
|
||||
|
||||
"""
|
||||
timeout is the number of milliseconds that this moderation is maximum expected
|
||||
to take before it is skipped.
|
||||
"""
|
||||
timeout: Int!
|
||||
|
||||
"""
|
||||
signingSecret is the secret used to sign outgoing requests to the url during
|
||||
the moderation pipeline.
|
||||
"""
|
||||
signingSecret: SigningSecret!
|
||||
}
|
||||
|
||||
type CustomExternalIntegration {
|
||||
"""
|
||||
phases is all the external moderation phases for this Tenant.
|
||||
"""
|
||||
phases: [ExternalModerationPhase!]!
|
||||
}
|
||||
|
||||
type ExternalIntegrations {
|
||||
"""
|
||||
akismet provides integration with the Akismet Spam detection service.
|
||||
@@ -919,6 +986,12 @@ type ExternalIntegrations {
|
||||
platform.
|
||||
"""
|
||||
perspective: PerspectiveExternalIntegration!
|
||||
|
||||
"""
|
||||
external provides integration details for external moderation phases that can be
|
||||
used in the moderation pipeline.
|
||||
"""
|
||||
external: CustomExternalIntegration
|
||||
}
|
||||
|
||||
################################################################################
|
||||
@@ -1318,7 +1391,7 @@ type WebhookEndpoint {
|
||||
"""
|
||||
signingSecret is the current secret used to sign the events sent out.
|
||||
"""
|
||||
signingSecret: Secret!
|
||||
signingSecret: SigningSecret!
|
||||
|
||||
"""
|
||||
deliveries store the deliveries for each event sent for the last 50 events.
|
||||
@@ -3183,6 +3256,13 @@ type Query {
|
||||
queues returns information on queues used in Coral to manage
|
||||
"""
|
||||
queues: Queues! @auth(roles: [ADMIN])
|
||||
|
||||
"""
|
||||
externalModerationPhase will return a specific ExternalModerationPhase if it
|
||||
exists.
|
||||
"""
|
||||
externalModerationPhase(id: ID!): ExternalModerationPhase
|
||||
@auth(roles: [ADMIN])
|
||||
}
|
||||
|
||||
################################################################################
|
||||
@@ -4369,7 +4449,7 @@ input RegenerateSSOKeyInput {
|
||||
|
||||
type RegenerateSSOKeyPayload {
|
||||
"""
|
||||
settings is the Settings that the SSO key was regenerated on.
|
||||
settings is the Settings that the SSO secret was regenerated on.
|
||||
"""
|
||||
settings: Settings
|
||||
|
||||
@@ -5158,10 +5238,10 @@ type UpdateWebhookEndpointPayload {
|
||||
}
|
||||
|
||||
##################
|
||||
# rotateWebhookEndpointSecret
|
||||
# rotateWebhookEndpointSigningSecret
|
||||
##################
|
||||
|
||||
input RotateWebhookEndpointSecretInput {
|
||||
input RotateWebhookEndpointSigningSecretInput {
|
||||
"""
|
||||
clientMutationId is required for Relay support.
|
||||
"""
|
||||
@@ -5179,7 +5259,7 @@ input RotateWebhookEndpointSecretInput {
|
||||
inactiveIn: Int!
|
||||
}
|
||||
|
||||
type RotateWebhookEndpointSecretPayload {
|
||||
type RotateWebhookEndpointSigningSecretPayload {
|
||||
"""
|
||||
clientMutationId is required for Relay support.
|
||||
"""
|
||||
@@ -5188,7 +5268,7 @@ type RotateWebhookEndpointSecretPayload {
|
||||
"""
|
||||
endpoint is the endpoint that we just updated.
|
||||
"""
|
||||
endpoint: WebhookEndpoint
|
||||
endpoint: WebhookEndpoint!
|
||||
}
|
||||
|
||||
##################
|
||||
@@ -5216,7 +5296,7 @@ type DisableWebhookEndpointPayload {
|
||||
"""
|
||||
endpoint is the endpoint that we just disabled.
|
||||
"""
|
||||
endpoint: WebhookEndpoint
|
||||
endpoint: WebhookEndpoint!
|
||||
}
|
||||
|
||||
##################
|
||||
@@ -5244,7 +5324,7 @@ type EnableWebhookEndpointPayload {
|
||||
"""
|
||||
endpoint is the endpoint that we just enabled.
|
||||
"""
|
||||
endpoint: WebhookEndpoint
|
||||
endpoint: WebhookEndpoint!
|
||||
}
|
||||
|
||||
##################
|
||||
@@ -5272,7 +5352,225 @@ type DeleteWebhookEndpointPayload {
|
||||
"""
|
||||
endpoint is the endpoint that we just deleted.
|
||||
"""
|
||||
endpoint: WebhookEndpoint
|
||||
endpoint: WebhookEndpoint!
|
||||
}
|
||||
|
||||
#################
|
||||
# createExternalModerationPhase
|
||||
##################
|
||||
|
||||
input CreateExternalModerationPhaseInput {
|
||||
"""
|
||||
clientMutationId is required for Relay support.
|
||||
"""
|
||||
clientMutationId: String!
|
||||
|
||||
"""
|
||||
name is the name assigned to this ExternalModerationPhase for identification
|
||||
purposes.
|
||||
"""
|
||||
name: String!
|
||||
|
||||
"""
|
||||
url is the URL that Coral will POST moderation queries to.
|
||||
"""
|
||||
url: String!
|
||||
|
||||
"""
|
||||
format is the format of the comment body sent.
|
||||
"""
|
||||
format: COMMENT_BODY_FORMAT!
|
||||
|
||||
"""
|
||||
timeout is the number of milliseconds that this moderation is maximum expected
|
||||
to take before it is skipped.
|
||||
"""
|
||||
timeout: Int!
|
||||
}
|
||||
|
||||
type CreateExternalModerationPhasePayload {
|
||||
"""
|
||||
clientMutationId is required for Relay support.
|
||||
"""
|
||||
clientMutationId: String!
|
||||
|
||||
"""
|
||||
phase is the ExternalModerationPhase that we just created.
|
||||
"""
|
||||
phase: ExternalModerationPhase!
|
||||
|
||||
"""
|
||||
settings is the updated settings also containing the new phase.
|
||||
"""
|
||||
settings: Settings!
|
||||
}
|
||||
|
||||
##################
|
||||
# updateExternalModerationPhase
|
||||
##################
|
||||
|
||||
input UpdateExternalModerationPhaseInput {
|
||||
"""
|
||||
clientMutationId is required for Relay support.
|
||||
"""
|
||||
clientMutationId: String!
|
||||
|
||||
"""
|
||||
id is the ID of the ExternalModerationPhase being updated.
|
||||
"""
|
||||
id: ID!
|
||||
|
||||
"""
|
||||
name is the name assigned to this ExternalModerationPhase for identification
|
||||
purposes.
|
||||
"""
|
||||
name: String
|
||||
|
||||
"""
|
||||
url is the URL that Coral will POST moderation queries to.
|
||||
"""
|
||||
url: String
|
||||
|
||||
"""
|
||||
format is the format of the comment body sent.
|
||||
"""
|
||||
format: COMMENT_BODY_FORMAT
|
||||
|
||||
"""
|
||||
timeout is the number of milliseconds that this moderation is maximum expected
|
||||
to take before it is skipped.
|
||||
"""
|
||||
timeout: Int
|
||||
}
|
||||
|
||||
type UpdateExternalModerationPhasePayload {
|
||||
"""
|
||||
clientMutationId is required for Relay support.
|
||||
"""
|
||||
clientMutationId: String!
|
||||
|
||||
"""
|
||||
phase is the ExternalModerationPhase that we just updated.
|
||||
"""
|
||||
phase: ExternalModerationPhase!
|
||||
}
|
||||
|
||||
##################
|
||||
# deleteExternalModerationPhase
|
||||
##################
|
||||
|
||||
input DeleteExternalModerationPhaseInput {
|
||||
"""
|
||||
clientMutationId is required for Relay support.
|
||||
"""
|
||||
clientMutationId: String!
|
||||
|
||||
"""
|
||||
id is the ID of the ExternalModerationPhase being deleted.
|
||||
"""
|
||||
id: ID!
|
||||
}
|
||||
|
||||
type DeleteExternalModerationPhasePayload {
|
||||
"""
|
||||
clientMutationId is required for Relay support.
|
||||
"""
|
||||
clientMutationId: String!
|
||||
|
||||
"""
|
||||
phase is the ExternalModerationPhase that we just deleted.
|
||||
"""
|
||||
phase: ExternalModerationPhase!
|
||||
}
|
||||
|
||||
##################
|
||||
# disableExternalModerationPhase
|
||||
##################
|
||||
|
||||
input DisableExternalModerationPhaseInput {
|
||||
"""
|
||||
clientMutationId is required for Relay support.
|
||||
"""
|
||||
clientMutationId: String!
|
||||
|
||||
"""
|
||||
id is the ID of the ExternalModerationPhase being disabled.
|
||||
"""
|
||||
id: ID!
|
||||
}
|
||||
|
||||
type DisableExternalModerationPhasePayload {
|
||||
"""
|
||||
clientMutationId is required for Relay support.
|
||||
"""
|
||||
clientMutationId: String!
|
||||
|
||||
"""
|
||||
phase is the ExternalModerationPhase that we just disabled.
|
||||
"""
|
||||
phase: ExternalModerationPhase!
|
||||
}
|
||||
|
||||
##################
|
||||
# enableExternalModerationPhase
|
||||
##################
|
||||
|
||||
input EnableExternalModerationPhaseInput {
|
||||
"""
|
||||
clientMutationId is required for Relay support.
|
||||
"""
|
||||
clientMutationId: String!
|
||||
|
||||
"""
|
||||
id is the ID of the ExternalModerationPhase being enabled.
|
||||
"""
|
||||
id: ID!
|
||||
}
|
||||
|
||||
type EnableExternalModerationPhasePayload {
|
||||
"""
|
||||
clientMutationId is required for Relay support.
|
||||
"""
|
||||
clientMutationId: String!
|
||||
|
||||
"""
|
||||
phase is the ExternalModerationPhase that we just enabled.
|
||||
"""
|
||||
phase: ExternalModerationPhase!
|
||||
}
|
||||
|
||||
##################
|
||||
# rotateExternalModerationPhaseSigningSecret
|
||||
##################
|
||||
|
||||
input RotateExternalModerationPhaseSigningSecretInput {
|
||||
"""
|
||||
clientMutationId is required for Relay support.
|
||||
"""
|
||||
clientMutationId: String!
|
||||
|
||||
"""
|
||||
id is the ID of the ExternalModerationPhase being updated.
|
||||
"""
|
||||
id: ID!
|
||||
|
||||
"""
|
||||
inactiveIn is the number of seconds that the current active Secret should be
|
||||
kept active.
|
||||
"""
|
||||
inactiveIn: Int!
|
||||
}
|
||||
|
||||
type RotateExternalModerationPhaseSigningSecretPayload {
|
||||
"""
|
||||
clientMutationId is required for Relay support.
|
||||
"""
|
||||
clientMutationId: String!
|
||||
|
||||
"""
|
||||
phase is the ExternalModerationPhase that we just updated.
|
||||
"""
|
||||
phase: ExternalModerationPhase!
|
||||
}
|
||||
|
||||
##################
|
||||
@@ -6001,87 +6299,87 @@ type EnableFeatureFlagPayload {
|
||||
}
|
||||
|
||||
#########################
|
||||
## rotateSSOKey
|
||||
## rotateSSOSigningSecret
|
||||
#########################
|
||||
|
||||
input RotateSSOKeyInput {
|
||||
input RotateSSOSigningSecretInput {
|
||||
"""
|
||||
clientMutationId is required for Relay support.
|
||||
"""
|
||||
clientMutationId: String!
|
||||
|
||||
"""
|
||||
inactiveIn is the number of seconds that the current active SSOKey should be
|
||||
kept active (allow signed tokens signed with this secret) before rejecting
|
||||
them.
|
||||
inactiveIn is the number of seconds that the current active SigningSecret
|
||||
should be kept active (allow signed tokens signed with this secret) before
|
||||
rejecting them.
|
||||
"""
|
||||
inactiveIn: Int!
|
||||
}
|
||||
|
||||
type RotateSSOKeyPayload {
|
||||
type RotateSSOSigningSecretPayload {
|
||||
"""
|
||||
clientMutationId is required for Relay support.
|
||||
"""
|
||||
clientMutationId: String!
|
||||
|
||||
"""
|
||||
settings is the Settings that the SSO key was regenerated on.
|
||||
settings is the Settings that the SSO secret was regenerated on.
|
||||
"""
|
||||
settings: Settings
|
||||
}
|
||||
|
||||
#########################
|
||||
## deactivateSSOKey
|
||||
## deactivateSSOSigningSecret
|
||||
#########################
|
||||
|
||||
input DeactivateSSOKeyInput {
|
||||
input DeactivateSSOSigningSecretInput {
|
||||
"""
|
||||
clientMutationId is required for Relay support.
|
||||
"""
|
||||
clientMutationId: String!
|
||||
|
||||
"""
|
||||
kid is the ID of the SSOKey being deactivated.
|
||||
kid is the ID of the SigningSecret being deactivated.
|
||||
"""
|
||||
kid: ID!
|
||||
}
|
||||
|
||||
type DeactivateSSOKeyPayload {
|
||||
type DeactivateSSOSigningSecretPayload {
|
||||
"""
|
||||
clientMutationId is required for Relay support.
|
||||
"""
|
||||
clientMutationId: String!
|
||||
|
||||
"""
|
||||
settings is the Settings that the SSO key was regenerated on.
|
||||
settings is the Settings that the SSO secret was regenerated on.
|
||||
"""
|
||||
settings: Settings
|
||||
}
|
||||
|
||||
#########################
|
||||
## deleteSSOKey
|
||||
## deleteSSOSigningSecret
|
||||
#########################
|
||||
|
||||
input DeleteSSOKeyInput {
|
||||
input DeleteSSOSigningSecretInput {
|
||||
"""
|
||||
clientMutationId is required for Relay support.
|
||||
"""
|
||||
clientMutationId: String!
|
||||
|
||||
"""
|
||||
kid is the ID of the SSOKey being deleted.
|
||||
kid is the ID of the SigningSecret being deleted.
|
||||
"""
|
||||
kid: ID!
|
||||
}
|
||||
|
||||
type DeleteSSOKeyPayload {
|
||||
type DeleteSSOSigningSecretPayload {
|
||||
"""
|
||||
clientMutationId is required for Relay support.
|
||||
"""
|
||||
clientMutationId: String!
|
||||
|
||||
"""
|
||||
settings is the Settings that the SSO key was regenerated on.
|
||||
settings is the Settings that the SSO secret was regenerated on.
|
||||
"""
|
||||
settings: Settings
|
||||
}
|
||||
@@ -6349,30 +6647,35 @@ type Mutation {
|
||||
@auth(roles: [ADMIN])
|
||||
|
||||
"""
|
||||
regenerateSSOKey will regenerate the SSO key used to sign secrets. This will
|
||||
regenerateSSOKey will regenerate the SSO secret used to sign secrets. This will
|
||||
invalidate any existing user sessions.
|
||||
|
||||
DEPRECATED: deprecated in favour of `rotateSSOSigningSecret`, remove in 6.2.0.
|
||||
"""
|
||||
regenerateSSOKey(input: RegenerateSSOKeyInput!): RegenerateSSOKeyPayload!
|
||||
@auth(roles: [ADMIN])
|
||||
@deprecated(reason: "deprecated in favour of `rotateSSOKey`")
|
||||
@deprecated(reason: "deprecated in favour of `rotateSSOSigningSecret`")
|
||||
|
||||
"""
|
||||
rotateSSOKey can be used to rotate a given active SSOKey.
|
||||
rotateSSOSigningSecret can be used to rotate a given active SigningSecret.
|
||||
"""
|
||||
rotateSSOKey(input: RotateSSOKeyInput!): RotateSSOKeyPayload!
|
||||
@auth(roles: [ADMIN])
|
||||
rotateSSOSigningSecret(
|
||||
input: RotateSSOSigningSecretInput!
|
||||
): RotateSSOSigningSecretPayload! @auth(roles: [ADMIN])
|
||||
|
||||
"""
|
||||
deactivateSSOKey will deactivate a given deactivated SSOKey.
|
||||
deactivateSSOSigningSecret will deactivate a given deactivated SigningSecret.
|
||||
"""
|
||||
deactivateSSOKey(input: DeactivateSSOKeyInput!): DeactivateSSOKeyPayload!
|
||||
@auth(roles: [ADMIN])
|
||||
deactivateSSOSigningSecret(
|
||||
input: DeactivateSSOSigningSecretInput!
|
||||
): DeactivateSSOSigningSecretPayload! @auth(roles: [ADMIN])
|
||||
|
||||
"""
|
||||
deleteSSOKey will delete a given inactive SSOKey.
|
||||
deleteSSOSigningSecret will delete a given inactive SigningSecret.
|
||||
"""
|
||||
deleteSSOKey(input: DeleteSSOKeyInput!): DeleteSSOKeyPayload!
|
||||
@auth(roles: [ADMIN])
|
||||
deleteSSOSigningSecret(
|
||||
input: DeleteSSOSigningSecretInput!
|
||||
): DeleteSSOSigningSecretPayload! @auth(roles: [ADMIN])
|
||||
|
||||
"""
|
||||
createCommentReaction will create a Reaction authored by the current logged in
|
||||
@@ -6762,11 +7065,56 @@ type Mutation {
|
||||
): DeleteWebhookEndpointPayload! @auth(roles: [ADMIN])
|
||||
|
||||
"""
|
||||
rotateWebhookEndpointSecret will roll the current active secret to a new key.
|
||||
rotateWebhookEndpointSigningSecret will roll the current active secret to a new key.
|
||||
"""
|
||||
rotateWebhookEndpointSecret(
|
||||
input: RotateWebhookEndpointSecretInput!
|
||||
): RotateWebhookEndpointSecretPayload! @auth(roles: [ADMIN])
|
||||
rotateWebhookEndpointSigningSecret(
|
||||
input: RotateWebhookEndpointSigningSecretInput!
|
||||
): RotateWebhookEndpointSigningSecretPayload! @auth(roles: [ADMIN])
|
||||
|
||||
"""
|
||||
createExternalModerationPhase will create a new ExternalModerationPhase.
|
||||
"""
|
||||
createExternalModerationPhase(
|
||||
input: CreateExternalModerationPhaseInput!
|
||||
): CreateExternalModerationPhasePayload! @auth(roles: [ADMIN])
|
||||
|
||||
"""
|
||||
updateExternalModerationPhase will update a ExternalModerationPhase.
|
||||
"""
|
||||
updateExternalModerationPhase(
|
||||
input: UpdateExternalModerationPhaseInput!
|
||||
): UpdateExternalModerationPhasePayload! @auth(roles: [ADMIN])
|
||||
|
||||
"""
|
||||
enableExternalModerationPhase will enable a ExternalModerationPhase to recieve
|
||||
new comments.
|
||||
"""
|
||||
enableExternalModerationPhase(
|
||||
input: EnableExternalModerationPhaseInput!
|
||||
): EnableExternalModerationPhasePayload! @auth(roles: [ADMIN])
|
||||
|
||||
"""
|
||||
disableExternalModerationPhase will disable a ExternalModerationPhase from
|
||||
recieving new comments.
|
||||
"""
|
||||
disableExternalModerationPhase(
|
||||
input: DisableExternalModerationPhaseInput!
|
||||
): DisableExternalModerationPhasePayload! @auth(roles: [ADMIN])
|
||||
|
||||
"""
|
||||
deleteExternalModerationPhase will delete a ExternalModerationPhase.
|
||||
"""
|
||||
deleteExternalModerationPhase(
|
||||
input: DeleteExternalModerationPhaseInput!
|
||||
): DeleteExternalModerationPhasePayload! @auth(roles: [ADMIN])
|
||||
|
||||
"""
|
||||
rotateExternalModerationPhaseSigningSecret will roll the current active secret
|
||||
to a new key.
|
||||
"""
|
||||
rotateExternalModerationPhaseSigningSecret(
|
||||
input: RotateExternalModerationPhaseSigningSecretInput!
|
||||
): RotateExternalModerationPhaseSigningSecretPayload! @auth(roles: [ADMIN])
|
||||
|
||||
"""
|
||||
updateStoryMode will set the story mode.
|
||||
|
||||
@@ -24,10 +24,10 @@ import {
|
||||
} from "coral-server/app/middleware/passport/strategies/jwt";
|
||||
import {
|
||||
CoralError,
|
||||
InternalError,
|
||||
LiveUpdatesDisabled,
|
||||
RawQueryNotAuthorized,
|
||||
TenantNotFoundError,
|
||||
WrappedInternalError,
|
||||
} from "coral-server/errors";
|
||||
import { enrichError, logError, logQuery } from "coral-server/graph/extensions";
|
||||
import { getOperationMetadata } from "coral-server/graph/extensions/helpers";
|
||||
@@ -151,7 +151,10 @@ export function onConnect(options: OnConnectOptions): OnConnectFn {
|
||||
|
||||
if (!(err instanceof CoralError)) {
|
||||
// eslint-disable-next-line no-ex-assign
|
||||
err = new InternalError(err, "could not setup websocket connection");
|
||||
err = new WrappedInternalError(
|
||||
err,
|
||||
"could not setup websocket connection"
|
||||
);
|
||||
}
|
||||
const { message } = err.serializeExtensions(
|
||||
options.i18n.getDefaultBundle()
|
||||
|
||||
Reference in New Issue
Block a user