feat: initial implementation (#2409)

This commit is contained in:
Wyatt Johnson
2019-07-23 17:20:40 +00:00
committed by GitHub
parent fc464bd7c9
commit b1732f8a00
24 changed files with 646 additions and 70 deletions
@@ -869,24 +869,27 @@ type DisableCommenting {
}
################################################################################
## Email
## EmailConfiguration
################################################################################
type Email {
type SMTP {
secure: Boolean
host: String
port: Int
authentication: Boolean
username: String
password: String
}
type EmailConfiguration {
"""
enabled when True, will enable the emailing functionality in Coral.
enabled when true, will enable the emailing functionality in Coral.
"""
enabled: Boolean!
"""
smtpURI is the SMTP connection url to send emails on.
"""
smtpURI: String @auth(roles: [ADMIN])
"""
fromAddress is the email address that will be used to send emails from.
"""
fromAddress: String
fromName: String
fromEmail: String
smtp: SMTP! @auth(roles: [ADMIN])
}
################################################################################
@@ -1148,7 +1151,7 @@ type Settings {
"""
email is the set of credentials and settings associated with the organization.
"""
email: Email! @auth(roles: [ADMIN, MODERATOR])
email: EmailConfiguration! @auth(roles: [ADMIN, MODERATOR])
"""
wordList will return a given list of words.
@@ -2599,21 +2602,23 @@ input SettingsOIDCAuthIntegrationInput {
issuer: String
}
input SettingsEmailInput {
input SettingsSMTPInput {
secure: Boolean
host: String
port: Int
authentication: Boolean
username: String
password: String
}
input SettingsEmailConfigurationInput {
"""
enabled when True, will enable the emailing functionality in Coral.
"""
enabled: Boolean
"""
smtpURI is the SMTP connection url to send emails on.
"""
smtpURI: String
"""
fromAddress is the email address that will be used to send emails from.
"""
fromAddress: String
smtp: SettingsSMTPInput
fromName: String
fromEmail: String
}
input SettingsWordListInput {
@@ -3048,7 +3053,7 @@ input SettingsInput {
"""
email is the set of credentials and settings associated with the organization.
"""
email: SettingsEmailInput
email: SettingsEmailConfigurationInput
"""
auth contains all the settings related to authentication and authorization.
-38
View File
@@ -1,38 +0,0 @@
import { LocalProfile, User } from "coral-server/models/user";
/**
* getLocalProfile will get the LocalProfile from the User if it exists.
*
* @param user the User to pull the LocalProfile out of
*/
export function getLocalProfile(
user: Pick<User, "profiles">
): LocalProfile | undefined {
return user.profiles.find(({ type }) => type === "local") as
| LocalProfile
| undefined;
}
/**
* hasLocalProfile will return true if the User has a LocalProfile, optionally
* checking the email on it as well.
*
* @param user the User to pull the LocalProfile out of
* @param withEmail when specified, will ensure that the LocalProfile has the
* specific email provided
*/
export function hasLocalProfile(
user: Pick<User, "profiles">,
withEmail?: string
): boolean {
const profile = getLocalProfile(user);
if (!profile) {
return false;
}
if (withEmail && profile.id !== withEmail) {
return false;
}
return true;
}
+9 -1
View File
@@ -1,6 +1,7 @@
import { Omit } from "coral-common/types";
import {
GQLAuth,
GQLEmailConfiguration,
GQLFacebookAuthIntegration,
GQLGoogleAuthIntegration,
GQLLiveConfiguration,
@@ -13,6 +14,8 @@ import {
export type LiveConfiguration = Omit<GQLLiveConfiguration, "configurable">;
export type EmailConfiguration = GQLEmailConfiguration;
export interface GlobalModerationSettings {
live: LiveConfiguration;
moderation: GQLMODERATION_MODE;
@@ -77,7 +80,6 @@ export type Settings = GlobalModerationSettings &
Pick<
GQLSettings,
| "charCount"
| "email"
| "karma"
| "wordList"
| "integrations"
@@ -93,6 +95,12 @@ export type Settings = GlobalModerationSettings &
*/
auth: Auth;
/**
* email is the set of credentials and settings associated with the
* organization.
*/
email: EmailConfiguration;
/**
* closeCommenting contains settings related to the automatic closing of commenting on
* Stories.
+1
View File
@@ -158,6 +158,7 @@ export async function createTenant(
},
email: {
enabled: false,
smtp: {},
},
karma: {
enabled: true,
@@ -6,9 +6,10 @@ import htmlToText from "html-to-text";
import Joi from "joi";
import { JSDOM } from "jsdom";
import { juiceResources } from "juice";
import { camelCase } from "lodash";
import { camelCase, isNil } from "lodash";
import { Db } from "mongodb";
import { createTransport } from "nodemailer";
import { Options } from "nodemailer/lib/smtp-connection";
import now from "performance-now";
import { LanguageCode } from "coral-common/helpers/i18n/locales";
@@ -202,24 +203,28 @@ export const createJobProcessor = (options: MailProcessorOptions) => {
return;
}
const { enabled, smtpURI, fromAddress } = tenant.email;
const { enabled, smtp, fromEmail, fromName } = tenant.email;
if (!enabled) {
log.error("not sending email, it was disabled");
return;
}
if (!smtpURI) {
log.error("email was enabled but the smtpURI configuration was missing");
// Check that we have enough to generate the smtp credentials.
if (isNil(smtp.secure) || isNil(smtp.host) || isNil(smtp.port)) {
log.error("email enabled, but configuration is incomplete");
return;
}
if (!fromAddress) {
if (!fromEmail) {
log.error(
"email was enabled but the fromAddress configuration was missing"
);
return;
}
// Construct the fromAddress.
const fromAddress = fromName ? `${fromName} <${fromEmail}>` : fromEmail;
const startTemplateGenerationTime = now();
// Get the message to send.
@@ -242,8 +247,24 @@ export const createJobProcessor = (options: MailProcessorOptions) => {
let transport = cache.get(tenantID);
if (!transport) {
try {
// Create the new transport options.
const opts: Options = {
host: smtp.host,
port: smtp.port,
secure: smtp.secure,
};
if (smtp.authentication && smtp.username && smtp.password) {
// If authentication details are provided, add them to the transport
// configuration.
opts.auth = {
type: "login",
user: smtp.username,
pass: smtp.password,
};
}
// Create the transport based on the smtp uri.
transport = createTransport(smtpURI);
transport = createTransport(opts);
} catch (err) {
throw new InternalError(err, "could not create email transport");
}