UBERF-9661:(staging) MAIL_URL env (#8274)

* UBERF-9661:(staging) MAIL_URL env

Signed-off-by: Artem Savchenko <armisav@gmail.com>

* UBERF-9661: Fix mail auth token

Signed-off-by: Artem Savchenko <armisav@gmail.com>

* UBERF-9661: Fix validation

Signed-off-by: Artem Savchenko <armisav@gmail.com>

---------

Signed-off-by: Artem Savchenko <armisav@gmail.com>
This commit is contained in:
Artyom Savchenko 2025-03-19 19:44:41 +07:00 committed by GitHub
parent e3ca5be15a
commit 2806ad5e72
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
12 changed files with 60 additions and 58 deletions

8
.vscode/launch.json vendored
View File

@ -147,7 +147,7 @@
"ACCOUNT_PORT": "3000",
"FRONT_URL": "http://localhost:8080",
"STATS_URL": "http://host.docker.internal:4900",
"SES_URL": "",
"MAIL_URL": "",
// "DB_NS": "account-2",
// "WS_LIVENESS_DAYS": "1",
"MINIO_ACCESS_KEY": "minioadmin",
@ -180,7 +180,7 @@
"ACCOUNT_PORT": "3003",
"FRONT_URL": "http://localhost:8083",
"STATS_URL": "http://host.docker.internal:4901",
"SES_URL": "",
"MAIL_URL": "",
// "DB_NS": "account-2",
// "WS_LIVENESS_DAYS": "1",
"MINIO_ACCESS_KEY": "minioadmin",
@ -228,7 +228,7 @@
"TRANSACTOR_URL": "ws://localhost:3333",
"ACCOUNTS_URL": "http://localhost:3000",
"FRONT_URL": "http://localhost:8080",
"SES_URL": "",
"MAIL_URL": "",
"MINIO_ACCESS_KEY": "minioadmin",
"MINIO_SECRET_KEY": "minioadmin",
"MINIO_ENDPOINT": "localhost",
@ -261,7 +261,7 @@
"TRANSACTOR_URL": "ws://localhost:3332",
"ACCOUNTS_URL": "http://localhost:3000",
"FRONT_URL": "http://localhost:8080",
"SES_URL": "",
"MAIL_URL": "",
"MINIO_ACCESS_KEY": "minioadmin",
"MINIO_SECRET_KEY": "minioadmin",
"MINIO_ENDPOINT": "localhost",

View File

@ -94,7 +94,7 @@ services:
- REGION_INFO=|Mongo;pg|Postgres;cockroach|CockroachDB
# - REGION_INFO=cockroach|CockroachDB
- TRANSACTOR_URL=ws://host.docker.internal:3333,ws://host.docker.internal:3331;;pg,ws://host.docker.internal:3332;;cockroach,
- SES_URL=
- MAIL_URL=
- STORAGE_CONFIG=${STORAGE_CONFIG}
- FRONT_URL=http://host.docker.internal:8087
- RESERVED_DB_NAMES=telegram,gmail,github
@ -132,7 +132,7 @@ services:
- SERVER_SECRET=secret
- DB_URL=${MONGO_URL}
- STATS_URL=http://host.docker.internal:4900
- SES_URL=
- MAIL_URL=
- STORAGE_CONFIG=${STORAGE_CONFIG}
- RESERVED_DB_NAMES=telegram,gmail,github
- MODEL_ENABLED=*
@ -158,7 +158,7 @@ services:
- SERVER_SECRET=secret
- DB_URL=postgresql://postgres:example@postgres:5432
- STATS_URL=http://host.docker.internal:4900
- SES_URL=
- MAIL_URL=
- REGION=pg
- STORAGE_CONFIG=${STORAGE_CONFIG}
- FRONT_URL=http://host.docker.internal:8087
@ -186,7 +186,7 @@ services:
- SERVER_SECRET=secret
- DB_URL=postgresql://root@host.docker.internal:26257/defaultdb?sslmode=disable
- STATS_URL=http://host.docker.internal:4900
- SES_URL=
- MAIL_URL=
- REGION=cockroach
- STORAGE_CONFIG=${STORAGE_CONFIG}
- RESERVED_DB_NAMES=telegram,gmail,github
@ -283,7 +283,7 @@ services:
- STORAGE_CONFIG=${STORAGE_CONFIG}
- FRONT_URL=http://host.docker.internal:8087
# - APM_SERVER_URL=http://apm-server:8200
- SES_URL=''
- MAIL_URL=''
- ACCOUNTS_URL=http://host.docker.internal:3000
- LAST_NAME_FIRST=true
- BRANDING_PATH=/var/cfg/branding.json
@ -319,7 +319,7 @@ services:
- STORAGE_CONFIG=${STORAGE_CONFIG}
- FRONT_URL=http://host.docker.internal:8087
# - APM_SERVER_URL=http://apm-server:8200
- SES_URL=''
- MAIL_URL=''
- ACCOUNTS_URL=http://host.docker.internal:3000
- LAST_NAME_FIRST=true
- BRANDING_PATH=/var/cfg/branding.json
@ -353,7 +353,7 @@ services:
- STORAGE_CONFIG=${STORAGE_CONFIG}
- FRONT_URL=http://host.docker.internal:8087
# - APM_SERVER_URL=http://apm-server:8200
- SES_URL=''
- MAIL_URL=''
- ACCOUNTS_URL=http://host.docker.internal:3000
- LAST_NAME_FIRST=true
- BRANDING_PATH=/var/cfg/branding.json

View File

@ -42,7 +42,7 @@ services:
- SERVER_SECRET=secret
- MONGO_URL=mongodb://host.docker.internal:27017?compressors=snappy
- TRANSACTOR_URL=ws://transactor:3333;ws://localhost:3333
- SES_URL=
- MAIL_URL=
- STORAGE_CONFIG=${STORAGE_CONFIG}
- FRONT_URL=http://localhost:8087
- RESERVED_DB_NAMES=telegram,gmail,github
@ -129,7 +129,7 @@ services:
- FRONT_URL=http://localhost:8087
- UPLOAD_URL=http://localhost:8087/files
# - APM_SERVER_URL=http://apm-server:8200
- SES_URL=''
- MAIL_URL=''
- ACCOUNTS_URL=http://account:3000
- LAST_NAME_FIRST=true
- ELASTIC_INDEX_NAME=local_storage_index

View File

@ -71,9 +71,9 @@ setMetadata(contactPlugin.metadata.LastNameFirst, lastNameFirst)
setMetadata(serverCore.metadata.FrontUrl, config.frontUrl)
setMetadata(serverCore.metadata.FilesUrl, config.filesUrl)
setMetadata(serverToken.metadata.Secret, config.serverSecret)
setMetadata(serverNotification.metadata.SesUrl, config.sesUrl ?? '')
setMetadata(serverNotification.metadata.SesAuthToken, config.sesAuthToken)
setMetadata(serverNotification.metadata.WebPushUrl, config.webPushUrl ?? config.sesUrl)
setMetadata(serverNotification.metadata.MailUrl, config.mailUrl ?? '')
setMetadata(serverNotification.metadata.MailAuthToken, config.mailAuthToken)
setMetadata(serverNotification.metadata.WebPushUrl, config.webPushUrl)
setMetadata(serverTelegram.metadata.BotUrl, process.env.TELEGRAM_BOT_URL)
setMetadata(serverAiBot.metadata.SupportWorkspaceId, process.env.SUPPORT_WORKSPACE)
setMetadata(serverAiBot.metadata.EndpointURL, process.env.AI_BOT_URL)

View File

@ -111,18 +111,18 @@ export async function sendEmailNotification (
receiver: string
): Promise<void> {
try {
const sesURL = getMetadata(serverNotification.metadata.SesUrl)
if (sesURL === undefined || sesURL === '') {
const mailURL = getMetadata(serverNotification.metadata.MailUrl)
if (mailURL === undefined || mailURL === '') {
ctx.error('Please provide email service url to enable email notifications.')
return
}
const sesAuth: string | undefined = getMetadata(serverNotification.metadata.SesAuthToken)
await fetch(concatLink(sesURL, '/send'), {
const mailAuth: string | undefined = getMetadata(serverNotification.metadata.MailAuthToken)
await fetch(concatLink(mailURL, '/send'), {
method: 'post',
keepalive: true,
headers: {
'Content-Type': 'application/json',
...(sesAuth != null ? { Authorization: `Bearer ${sesAuth}` } : {})
...(mailAuth != null ? { Authorization: `Bearer ${mailAuth}` } : {})
},
body: JSON.stringify({
text,

View File

@ -166,7 +166,7 @@ export async function createPushNotification (
): Promise<void> {
const pushURL: string | undefined = getMetadata(serverNotification.metadata.WebPushUrl)
// TODO: Remove auth token after migration to new services
const authToken: string | undefined = getMetadata(serverNotification.metadata.SesAuthToken)
const authToken: string | undefined = getMetadata(serverNotification.metadata.MailAuthToken)
if (pushURL === undefined || pushURL === '') return
const userSubscriptions = subscriptions.filter((it) => it.user === target)
const data: PushData = {
@ -199,7 +199,7 @@ export async function createPushNotification (
async function sendPushToSubscription (
pushURL: string,
sesAuth: string | undefined,
mailAuth: string | undefined,
control: TriggerControl,
targetUser: Ref<Account>,
subscriptions: PushSubscription[],
@ -213,7 +213,7 @@ async function sendPushToSubscription (
keepalive: true,
headers: {
'Content-Type': 'application/json',
...(sesAuth != null ? { Authorization: `Bearer ${sesAuth}` } : {})
...(mailAuth != null ? { Authorization: `Bearer ${mailAuth}` } : {})
},
body: JSON.stringify({
subscriptions,

View File

@ -150,8 +150,8 @@ export const PUSH_NOTIFICATION_TITLE_SIZE = 80
*/
export default plugin(serverNotificationId, {
metadata: {
SesUrl: '' as Metadata<string>,
SesAuthToken: '' as Metadata<string>,
MailUrl: '' as Metadata<string>,
MailAuthToken: '' as Metadata<string>,
WebPushUrl: '' as Metadata<string>,
InboxOnlyNotifications: '' as Metadata<boolean>
},

View File

@ -65,7 +65,8 @@ export function serveAccount (measureCtx: MeasureContext, brandings: BrandingMap
}
})
const ses = process.env.SES_URL
const mailUrl = process.env.MAIL_URL
const frontURL = process.env.FRONT_URL
const productName = process.env.PRODUCT_NAME
const lang = process.env.LANGUAGE ?? 'en'
@ -86,7 +87,8 @@ export function serveAccount (measureCtx: MeasureContext, brandings: BrandingMap
setMetadata(account.metadata.ProductName, productName)
setMetadata(account.metadata.OtpTimeToLiveSec, parseInt(process.env.OTP_TIME_TO_LIVE ?? '60'))
setMetadata(account.metadata.OtpRetryDelaySec, parseInt(process.env.OTP_RETRY_DELAY ?? '60'))
setMetadata(account.metadata.SES_URL, ses)
setMetadata(account.metadata.MAIL_URL, mailUrl)
setMetadata(account.metadata.FrontURL, frontURL)
setMetadata(account.metadata.WsLivenessDays, wsLivenessDays)

View File

@ -37,7 +37,7 @@ describe('server', () => {
let workspace: string = 'ws-' + randomBytes(8).toString('hex')
beforeAll(async () => {
setMetadata(accountPlugin.metadata.SES_URL, '')
setMetadata(accountPlugin.metadata.MAIL_URL, '')
conn = await MongoClient.connect(dbUri)
;[accountsDb, accountsDbClose] = await getAccountDB(dbUri, DB_NAME)
})

View File

@ -180,8 +180,8 @@ async function getAccountInfo (
}
async function sendOtpEmail (branding: Branding | null, otp: string, email: string): Promise<void> {
const sesURL = getMetadata(accountPlugin.metadata.SES_URL)
if (sesURL === undefined || sesURL === '') {
const mailURL = getMetadata(accountPlugin.metadata.MAIL_URL)
if (mailURL === undefined || mailURL === '') {
console.info('Please provide email service url to enable email otp.')
return
}
@ -194,7 +194,7 @@ async function sendOtpEmail (branding: Branding | null, otp: string, email: stri
const subject = await translate(accountPlugin.string.OtpSubject, { code: otp, app }, lang)
const to = email
await fetch(concatLink(sesURL, '/send'), {
await fetch(concatLink(mailURL, '/send'), {
method: 'POST',
headers: {
'Content-Type': 'application/json'
@ -649,8 +649,8 @@ export async function confirm (
}
async function sendConfirmation (branding: Branding | null, account: Account): Promise<void> {
const sesURL = getMetadata(accountPlugin.metadata.SES_URL)
if (sesURL === undefined || sesURL === '') {
const mailURL = getMetadata(accountPlugin.metadata.MAIL_URL)
if (mailURL === undefined || mailURL === '') {
console.info('Please provide email service url to enable email confirmations.')
return
}
@ -675,9 +675,9 @@ async function sendConfirmation (branding: Branding | null, account: Account): P
const html = await translate(accountPlugin.string.ConfirmationHTML, { name, link }, lang)
const subject = await translate(accountPlugin.string.ConfirmationSubject, { name }, lang)
if (sesURL !== undefined && sesURL !== '') {
if (mailURL !== undefined && mailURL !== '') {
const to = account.email
await fetch(concatLink(sesURL, '/send'), {
await fetch(concatLink(mailURL, '/send'), {
method: 'post',
headers: {
'Content-Type': 'application/json'
@ -709,7 +709,7 @@ export async function signUpJoin (
console.log(`signup join:${email} ${first} ${last}`)
const invite = await getInvite(db, inviteId)
const workspace = await checkInvite(ctx, invite, email)
const sesURL = getMetadata(accountPlugin.metadata.SES_URL)
const mailURL = getMetadata(accountPlugin.metadata.MAIL_URL)
await createAcc(
ctx,
db,
@ -718,7 +718,7 @@ export async function signUpJoin (
password,
first,
last,
invite?.emailMask === email || invite?.personId !== undefined || sesURL === undefined || sesURL === ''
invite?.emailMask === email || invite?.personId !== undefined || mailURL === undefined || mailURL === ''
)
const ws = await assignAccountToWs(
ctx,
@ -785,9 +785,9 @@ export async function createAcc (
if (newAccount === null) {
throw new PlatformError(new Status(Severity.ERROR, platform.status.AccountAlreadyExists, { account: email }))
}
const sesURL = getMetadata(accountPlugin.metadata.SES_URL)
const mailURL = getMetadata(accountPlugin.metadata.MAIL_URL)
if (!confirmed && shouldConfirm) {
if (sesURL !== undefined && sesURL !== '') {
if (mailURL !== undefined && mailURL !== '') {
await sendConfirmation(branding, newAccount)
} else {
ctx.info('Please provide email service url to enable email confirmations.')
@ -811,7 +811,7 @@ export async function createAccount (
last: string
): Promise<LoginInfo> {
const email = cleanEmail(_email)
const sesURL = getMetadata(accountPlugin.metadata.SES_URL)
const mailURL = getMetadata(accountPlugin.metadata.MAIL_URL)
const account = await createAcc(
ctx,
db,
@ -820,7 +820,7 @@ export async function createAccount (
password,
first,
last,
sesURL === undefined || sesURL === ''
mailURL === undefined || mailURL === ''
)
const result = {
@ -2275,8 +2275,8 @@ export async function requestPassword (
throw new PlatformError(new Status(Severity.ERROR, platform.status.AccountNotFound, { account: email }))
}
const sesURL = getMetadata(accountPlugin.metadata.SES_URL)
if (sesURL === undefined || sesURL === '') {
const mailURL = getMetadata(accountPlugin.metadata.MAIL_URL)
if (mailURL === undefined || mailURL === '') {
throw new Error('Please provide email service url')
}
const front = branding?.front ?? getMetadata(accountPlugin.metadata.FrontURL)
@ -2299,7 +2299,7 @@ export async function requestPassword (
const subject = await translate(accountPlugin.string.RecoverySubject, {}, lang)
const to = account.email
await fetch(concatLink(sesURL, '/send'), {
await fetch(concatLink(mailURL, '/send'), {
method: 'post',
headers: {
'Content-Type': 'application/json'
@ -2538,8 +2538,8 @@ export async function sendInvite (
}
await checkSendRateLimit(currentAccount, tokenData.workspace.name, db)
const sesURL = getMetadata(accountPlugin.metadata.SES_URL)
if (sesURL === undefined || sesURL === '') {
const mailURL = getMetadata(accountPlugin.metadata.MAIL_URL)
if (mailURL === undefined || mailURL === '') {
throw new Error('Please provide email service url')
}
const front = branding?.front ?? getMetadata(accountPlugin.metadata.FrontURL)
@ -2561,7 +2561,7 @@ export async function sendInvite (
const subject = await translate(accountPlugin.string.InviteSubject, { ws }, lang)
const to = email
await fetch(concatLink(sesURL, '/send'), {
await fetch(concatLink(mailURL, '/send'), {
method: 'post',
headers: {
'Content-Type': 'application/json'
@ -2628,8 +2628,8 @@ export async function resendInvite (
await checkSendRateLimit(currentAccount, workspace.name, db)
const sesURL = getMetadata(accountPlugin.metadata.SES_URL)
if (sesURL === undefined || sesURL === '') {
const mailURL = getMetadata(accountPlugin.metadata.MAIL_URL)
if (mailURL === undefined || mailURL === '') {
throw new Error('Please provide email service url')
}
const front = branding?.front ?? getMetadata(accountPlugin.metadata.FrontURL)
@ -2645,7 +2645,7 @@ export async function resendInvite (
const subject = await translate(accountPlugin.string.ResendInviteSubject, { ws }, lang)
const to = emailMask
await fetch(concatLink(sesURL, '/send'), {
await fetch(concatLink(mailURL, '/send'), {
method: 'post',
headers: {
'Content-Type': 'application/json'

View File

@ -11,7 +11,7 @@ export const accountId = 'account' as Plugin
export const accountPlugin = plugin(accountId, {
metadata: {
FrontURL: '' as Metadata<string>,
SES_URL: '' as Metadata<string>,
MAIL_URL: '' as Metadata<string>,
ProductName: '' as Metadata<string>,
Transactors: '' as Metadata<string>,
OtpTimeToLiveSec: '' as Metadata<number>,

View File

@ -5,8 +5,8 @@ export interface ServerEnv {
serverSecret: string
frontUrl: string
filesUrl: string | undefined
sesUrl: string | undefined
sesAuthToken: string | undefined
mailUrl: string | undefined
mailAuthToken: string | undefined
webPushUrl: string | undefined
accountsUrl: string
serverPort: number
@ -45,8 +45,8 @@ export function serverConfigFromEnv (): ServerEnv {
}
const filesUrl = process.env.FILES_URL
const sesUrl = process.env.SES_URL
const sesAuthToken = process.env.SES_AUTH_TOKEN
const mailUrl = process.env.MAIL_URL
const mailAuthToken = process.env.MAIL_AUTH_TOKEN
const webPushUrl = process.env.WEB_PUSH_URL
const accountsUrl = process.env.ACCOUNTS_URL
@ -64,8 +64,8 @@ export function serverConfigFromEnv (): ServerEnv {
serverSecret,
frontUrl,
filesUrl,
sesUrl,
sesAuthToken,
mailUrl,
mailAuthToken,
webPushUrl,
accountsUrl,
serverPort,