mirror of
https://github.com/wassname/talk.git
synced 2026-08-13 12:40:11 +08:00
[CORL-645] Add Slack support for v5 (#2713)
* Create preliminary schema for setting Slack channels CORL-645 * Implement preliminary slack notification using tenant slack channels CORL-645 * Very preliminarily get data loading with FieldArray's for slack channels CORL-645 * Update settings input on schema to allow saving Slack settings to tenant CORL-645 * Filter off UNMODERATED queue events from slack channels We don't send these to slack through our filters, we only care about pending, reported, and featured CORL-645 * Include a moderation link in comments pushed to Slack CORL-645 * Hook up proper callback functions for adding/removing slack channels CORL-645 * Add missing translation for Slack navigation item CORL-645 * Update snapshots for preliminary Slack configuration changes CORL-645 * Add some FormField wrappers around slack config elements Makes the UI appear a little nicer CORL-645 * Set up slack config to only provide one slack channel We need to do this until we can get ArrayField's working in final-form. CORL-645 * Disable the other trigger checkboxes when "All Comments" is checked CORL-645 * Clean up the formatting of Slack messages CORL-645 * Add error handling around sending comments to Slack CORL-645 * Add links to external Slack setup documentation CORL-645 * Replace form state with wrapped field element CORL-645 * Clean up fetch request sending Slack notifications CORL-645 * Prefer global string replacement over RegEx CORL-645 * Use URL class to construct comment URL's CORL-645 * Require slack configuration in schema CORL-645 * Initialize Slack in fixtures Also fix up a flaky test that wasn't waiting on form submission and on-change events. CORL-645 * Preliminarily fix up styles to match other config pages CORL-645 * Create placeholder add/remove buttons * Convert SlackConfigContainer to FunctionalComponent CORL-645 * Add name field to slack channels CORL-645 * Disable inner fields on Slack channel when not enabled CORL-645 * Improve the delete channel button CORL-645 * Use pureMerge to extract slack channel settings CORL-645 * Do a bit of cleanup on the add channel button CORL-645
This commit is contained in:
@@ -12,6 +12,7 @@ import { MailerQueue } from "coral-server/queue/tasks/mailer";
|
||||
import { NotifierQueue } from "coral-server/queue/tasks/notifier";
|
||||
import { ScraperQueue } from "coral-server/queue/tasks/scraper";
|
||||
import { JWTSigningConfig } from "coral-server/services/jwt";
|
||||
import createSlackPublisher from "coral-server/services/slack/publisher";
|
||||
import TenantCache from "coral-server/services/tenant/cache";
|
||||
|
||||
import loaders from "./loaders";
|
||||
@@ -58,12 +59,13 @@ export default class TenantContext extends CommonContext {
|
||||
this.mailerQueue = options.mailerQueue;
|
||||
this.signingConfig = options.signingConfig;
|
||||
this.clientID = options.clientID;
|
||||
this.publisher = createPublisher(
|
||||
this.pubsub,
|
||||
this.publisher = createPublisher({
|
||||
pubsub: this.pubsub,
|
||||
slackPublisher: createSlackPublisher(this.mongo, this.tenant),
|
||||
notifierQueue,
|
||||
this.tenant.id,
|
||||
this.clientID
|
||||
);
|
||||
tenantID: this.tenant.id,
|
||||
clientID: this.clientID,
|
||||
});
|
||||
this.loaders = loaders(this);
|
||||
this.mutators = mutators(this);
|
||||
}
|
||||
|
||||
@@ -2,5 +2,5 @@ import { GQLSettingsTypeResolver } from "coral-server/graph/tenant/schema/__gene
|
||||
import { Tenant } from "coral-server/models/tenant";
|
||||
|
||||
export const Settings: GQLSettingsTypeResolver<Tenant> = {
|
||||
staticURI: (tenant, args, ctx) => ctx.config.get("static_uri") || null,
|
||||
slack: ({ slack = {} }) => slack,
|
||||
};
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
import {
|
||||
GQLSlackConfiguration,
|
||||
GQLSlackConfigurationTypeResolver,
|
||||
} from "coral-server/graph/tenant/schema/__generated__/types";
|
||||
|
||||
export const SlackConfiguration: GQLSlackConfigurationTypeResolver<
|
||||
GQLSlackConfiguration
|
||||
> = {
|
||||
// TODO: Remove this when we create a migration to generate slack channels on existing tenants
|
||||
channels: ({ channels = [] }) => channels,
|
||||
};
|
||||
@@ -37,6 +37,8 @@ import { Profile } from "./Profile";
|
||||
import { Query } from "./Query";
|
||||
import { RecentCommentHistory } from "./RecentCommentHistory";
|
||||
import { RejectCommentPayload } from "./RejectCommentPayload";
|
||||
import { Settings } from "./Settings";
|
||||
import { SlackConfiguration } from "./SlackConfiguration";
|
||||
import { SSOAuthIntegration } from "./SSOAuthIntegration";
|
||||
import { Story } from "./Story";
|
||||
import { StorySettings } from "./StorySettings";
|
||||
@@ -97,6 +99,8 @@ const Resolvers: GQLResolver = {
|
||||
UsernameHistory,
|
||||
UsernameStatus,
|
||||
UserStatus,
|
||||
Settings,
|
||||
SlackConfiguration,
|
||||
};
|
||||
|
||||
export default Resolvers;
|
||||
|
||||
@@ -936,6 +936,64 @@ type EmailConfiguration {
|
||||
smtp: SMTP! @auth(roles: [ADMIN])
|
||||
}
|
||||
|
||||
################################################################################
|
||||
## Slack Configuration
|
||||
################################################################################
|
||||
|
||||
type SlackConfiguration {
|
||||
"""
|
||||
channels is the set of Slack channels configured to receive comments
|
||||
"""
|
||||
channels: [SlackChannel!]!
|
||||
}
|
||||
|
||||
type SlackChannelTriggers {
|
||||
"""
|
||||
allComments is whether this channel will receive all comments entering moderation
|
||||
"""
|
||||
allComments: Boolean!
|
||||
|
||||
"""
|
||||
reportedComments is whether this channel will receive reported comments
|
||||
"""
|
||||
reportedComments: Boolean!
|
||||
|
||||
"""
|
||||
pendingComments is whether this channel will receive pending comments
|
||||
"""
|
||||
pendingComments: Boolean!
|
||||
|
||||
"""
|
||||
featuredComments is whether this channel will receive featured comments
|
||||
"""
|
||||
featuredComments: Boolean!
|
||||
|
||||
}
|
||||
|
||||
type SlackChannel {
|
||||
"""
|
||||
enabled is whether this Slack channel is enabled to send comments to its
|
||||
correlated web hook
|
||||
"""
|
||||
enabled: Boolean!
|
||||
|
||||
"""
|
||||
name is the name assigned to the Slack channel
|
||||
"""
|
||||
name: String
|
||||
|
||||
"""
|
||||
hookURL defines the URL that comments will be sent to
|
||||
"""
|
||||
hookURL: String
|
||||
|
||||
"""
|
||||
triggers are the filters of types of comments that will be sent to
|
||||
the correlated channel
|
||||
"""
|
||||
triggers: SlackChannelTriggers
|
||||
}
|
||||
|
||||
################################################################################
|
||||
## ReactionConfiguration
|
||||
################################################################################
|
||||
@@ -1217,6 +1275,11 @@ type Settings {
|
||||
"""
|
||||
email: EmailConfiguration! @auth(roles: [ADMIN, MODERATOR])
|
||||
|
||||
"""
|
||||
slack is the configuration for slack communication
|
||||
"""
|
||||
slack: SlackConfiguration! @auth(roles: [ADMIN, MODERATOR])
|
||||
|
||||
"""
|
||||
wordList will return a given list of words.
|
||||
"""
|
||||
@@ -3397,6 +3460,60 @@ input CommenterAccountFeaturesInput {
|
||||
deleteAccount: Boolean
|
||||
}
|
||||
|
||||
input SlackTriggersConfigurationInput {
|
||||
"""
|
||||
allComments is whether this channel will receive all comments entering moderation
|
||||
"""
|
||||
allComments: Boolean
|
||||
|
||||
"""
|
||||
reportedComments is whether this channel will receive reported comments
|
||||
"""
|
||||
reportedComments: Boolean
|
||||
|
||||
"""
|
||||
pendingComments is whether this channel will receive pending comments
|
||||
"""
|
||||
pendingComments: Boolean
|
||||
|
||||
"""
|
||||
featuredComments is whether this channel will receive featured comments
|
||||
"""
|
||||
featuredComments: Boolean
|
||||
|
||||
}
|
||||
|
||||
input SlackChannelConfigurationInput {
|
||||
"""
|
||||
enabled is whether this Slack channel is enabled to send comments to its
|
||||
correlated web hook
|
||||
"""
|
||||
enabled: Boolean
|
||||
|
||||
"""
|
||||
name is the name assigned to the Slack channel
|
||||
"""
|
||||
name: String
|
||||
|
||||
"""
|
||||
hookURL defines the URL that comments will be sent to
|
||||
"""
|
||||
hookURL: String
|
||||
|
||||
"""
|
||||
triggers are the filters of types of comments that will be sent to
|
||||
the correlated channel
|
||||
"""
|
||||
triggers: SlackTriggersConfigurationInput
|
||||
}
|
||||
|
||||
input SlackConfigurationInput {
|
||||
"""
|
||||
channels are the channels configured for Slack integration
|
||||
"""
|
||||
channels: [SlackChannelConfigurationInput!]
|
||||
}
|
||||
|
||||
"""
|
||||
SettingsInput is the partial type of the Settings type for performing mutations.
|
||||
"""
|
||||
@@ -3507,6 +3624,11 @@ input SettingsInput {
|
||||
"""
|
||||
accountFeatures: CommenterAccountFeaturesInput
|
||||
|
||||
"""
|
||||
slack specifies the configuration for Slack integration.
|
||||
"""
|
||||
slack: SlackConfigurationInput
|
||||
|
||||
"""
|
||||
locale specifies the locale for this Tenant.
|
||||
"""
|
||||
|
||||
@@ -4,24 +4,35 @@ import { createSubscriptionChannelName } from "coral-server/graph/tenant/resolve
|
||||
import { SUBSCRIPTION_INPUT } from "coral-server/graph/tenant/resolvers/Subscription/types";
|
||||
import logger from "coral-server/logger";
|
||||
import { NotifierQueue } from "coral-server/queue/tasks/notifier";
|
||||
import { SlackPublisher } from "coral-server/services/slack/publisher";
|
||||
|
||||
export type Publisher = (input: SUBSCRIPTION_INPUT) => Promise<void>;
|
||||
|
||||
export interface PublisherOptions {
|
||||
pubsub: RedisPubSub;
|
||||
slackPublisher: SlackPublisher;
|
||||
notifierQueue: NotifierQueue;
|
||||
tenantID: string;
|
||||
clientID?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* createPublisher will create a new Publisher that can be used to send events
|
||||
* over the pubsub broker to facilitate live updates and notifications.
|
||||
*
|
||||
* TODO: Update
|
||||
* @param pubsub the pubsub broker to be used to facilitate the publish action
|
||||
* @param notifier
|
||||
* @param tenantID the ID of the Tenant where the event will be published with
|
||||
* @param clientID the ID of the client to de-duplicate mutation responses
|
||||
*/
|
||||
export const createPublisher = (
|
||||
pubsub: RedisPubSub,
|
||||
notifier: NotifierQueue,
|
||||
tenantID: string,
|
||||
clientID?: string
|
||||
): Publisher => async input => {
|
||||
export const createPublisher = ({
|
||||
pubsub,
|
||||
slackPublisher,
|
||||
notifierQueue,
|
||||
tenantID,
|
||||
clientID,
|
||||
}: PublisherOptions): Publisher => async input => {
|
||||
const { channel, payload } = input;
|
||||
|
||||
logger.trace({ channel, tenantID, clientID }, "publishing event");
|
||||
@@ -33,8 +44,11 @@ export const createPublisher = (
|
||||
...payload,
|
||||
clientID,
|
||||
}),
|
||||
|
||||
slackPublisher(channel, payload),
|
||||
|
||||
// Notify the notifications queue so we can offload notification processing
|
||||
// to it.
|
||||
notifier.add({ tenantID, input }),
|
||||
notifierQueue.add({ tenantID, input }),
|
||||
]);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user