Skip to content

Commit

Permalink
Revert "chore: add sending of emails in production (#2009)"
Browse files Browse the repository at this point in the history
This reverts commit 5f7d945.
  • Loading branch information
tobiasdiez committed Jul 6, 2023
1 parent 5f7d945 commit 8fba0fb
Show file tree
Hide file tree
Showing 14 changed files with 66 additions and 233 deletions.
2 changes: 1 addition & 1 deletion .github/scripts/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash
sudo apt-get install python3 pip python3-venv
python3 -m venv .venv
source .venv/bin/activate
pip install azure-identity azure-mgmt-web azure-mgmt-storage azure-mgmt-applicationinsights azure-mgmt-redis azure-mgmt-communication
pip install azure-identity azure-mgmt-web azure-mgmt-storage azure-mgmt-applicationinsights azure-mgmt-redis
az login
export SUBSCRIPTION_ID=<...>
export DATABASE_URL=<...>
Expand Down
45 changes: 19 additions & 26 deletions .github/scripts/deploy.py
Original file line number Diff line number Diff line change
@@ -1,20 +1,19 @@
# type: ignore

import logging
import os
from argparse import ArgumentParser

from azure.identity import DefaultAzureCredential
from azure.mgmt.applicationinsights import ApplicationInsightsManagementClient
from azure.mgmt.communication import CommunicationServiceManagementClient
from azure.mgmt.redis import RedisManagementClient
from azure.mgmt.storage import StorageManagementClient
from azure.mgmt.web import WebSiteManagementClient
from azure.mgmt.web.models import (
StaticSiteUserProvidedFunctionAppARMResource,
Site,
SiteConfig,
StaticSiteUserProvidedFunctionAppARMResource,
)
from azure.mgmt.storage import StorageManagementClient
from azure.mgmt.applicationinsights import ApplicationInsightsManagementClient
from azure.mgmt.redis import RedisManagementClient
from argparse import ArgumentParser
import logging


def main(environment_name: str, verbose: bool = False):
Expand Down Expand Up @@ -56,9 +55,6 @@ def main(environment_name: str, verbose: bool = False):
redis_client = RedisManagementClient(
credential=DefaultAzureCredential(), subscription_id=SUBSCRIPTION_ID
)
email_client = CommunicationServiceManagementClient(
credential=DefaultAzureCredential(), subscription_id=SUBSCRIPTION_ID
)

# Get info for static site (only for debug)
# static_site = web_client.static_sites.get_static_site(
Expand All @@ -77,17 +73,15 @@ def main(environment_name: str, verbose: bool = False):
storage_connection_string = f"DefaultEndpointsProtocol=https;EndpointSuffix=core.windows.net;AccountName={STORAGE_ACCOUNT};AccountKey={storage_keys.keys[0].value}"
logger.debug(f"Storage connection string: {storage_connection_string}")

# Azure CLI equivalent: az communication list-key
email_connection_string = email_client.communication_services.list_keys(
resource_group_name=GROUP_NAME, communication_service_name="JabRefCommunication"
).primary_connection_string
logger.debug(f"Email connection string: {email_connection_string}")

appinsights = appinsights_client.components.get(GROUP_NAME, APP_INSIGHTS_NAME)
appinsights = appinsights_client.components.get(
GROUP_NAME, APP_INSIGHTS_NAME
)
logger.debug(
f"Application insights instrumentation key: {appinsights.instrumentation_key}"
)
redis = redis_client.redis.get(resource_group_name=GROUP_NAME, name=REDIS_NAME)
redis = redis_client.redis.get(
resource_group_name=GROUP_NAME, name=REDIS_NAME
)
logger.debug(f"Redis client: {redis}")
redis_keys = redis_client.redis.list_keys(
resource_group_name=GROUP_NAME, name=REDIS_NAME
Expand Down Expand Up @@ -121,7 +115,6 @@ def main(environment_name: str, verbose: bool = False):
"name": "WEBSITE_CONTENTAZUREFILECONNECTIONSTRING",
"value": storage_connection_string,
},
{"name": "EMAIL_CLIENT", "value": email_connection_string},
{"name": "DATABASE_URL", "value": DATABASE_URL},
{"name": "NODE_ENV", "value": "production"},
{
Expand Down Expand Up @@ -163,12 +156,10 @@ def main(environment_name: str, verbose: bool = False):
# print("Created function app slot:\n{}".format(function_app_slot))

# Detach already attached function apps
linked_function_apps = (
web_client.static_sites.get_user_provided_function_apps_for_static_site_build(
resource_group_name=GROUP_NAME,
name=STATIC_SITE,
environment_name=environment_name,
)
linked_function_apps = web_client.static_sites.get_user_provided_function_apps_for_static_site_build(
resource_group_name=GROUP_NAME,
name=STATIC_SITE,
environment_name=environment_name,
)
for app in linked_function_apps:
logger.info(f"Detaching function app {app.name}")
Expand All @@ -193,7 +184,9 @@ def main(environment_name: str, verbose: bool = False):
function_app_region=function_app.location,
),
)
logger.info(f"Linked function app {function_app_name} to {environment_name}")
logger.info(
f"Linked function app {function_app_name} to {environment_name}"
)
logger.debug(f"{poller_link.result()}")


Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ jobs:
- name: Create & Link Function App
run: |
pip install azure-identity azure-mgmt-web azure-mgmt-storage azure-mgmt-applicationinsights azure-mgmt-redis azure-mgmt-communication
pip install azure-identity azure-mgmt-web azure-mgmt-storage azure-mgmt-applicationinsights azure-mgmt-redis
python .github\scripts\deploy.py --env ${{ github.event.pull_request.number }}
env:
SUBSCRIPTION_ID: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
Expand Down Expand Up @@ -193,7 +193,7 @@ jobs:

- name: Create & Link Function App
run: |
pip install azure-identity azure-mgmt-web azure-mgmt-storage azure-mgmt-applicationinsights azure-mgmt-redis azure-mgmt-communication
pip install azure-identity azure-mgmt-web azure-mgmt-storage azure-mgmt-applicationinsights azure-mgmt-redis
python .github\scripts\deploy.py --env ${{ matrix.deployment_environment }}
env:
SUBSCRIPTION_ID: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
Expand Down
2 changes: 0 additions & 2 deletions config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,6 @@ export interface Config {
host: string
password: string
}
emailClient?: string
session: {
primarySecret: string
secondarySecret: string
Expand All @@ -79,7 +78,6 @@ export function constructConfig(): Config {
host: process.env.REDIS_HOST || 'localhost',
password: process.env.REDIS_PASSWORD || 'jabref',
},
emailClient: process.env.EMAIL_CLIENT,
session: {
primarySecret: process.env.SESSION_SECRET_PRIMARY || 'session_secret',
secondarySecret: process.env.SESSION_SECRET_SECONDARY || 'session_secret',
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@
"@apollo/client": "^3.7.15",
"@apollo/server": "^4.7.0",
"@as-integrations/h3": "^1.1.5",
"@azure/communication-email": "^1.0.0",
"@graphql-tools/schema": "^9.0.12",
"@he-tree/vue": "^2.4.0",
"@nozomuikuta/h3-cors": "^0.2.2",
Expand All @@ -68,6 +67,7 @@
"graphql-passport": "^0.6.5",
"graphql-scalars": "^1.22.2",
"lodash": "^4.17.21",
"nodemailer": "^6.8.0",
"passport": "^0.6.0",
"pinia": "^2.0.35",
"redis": "^4.6.7",
Expand Down
14 changes: 7 additions & 7 deletions pages/user/forgot-password.vue
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,13 @@
<h2 class="mb-7 text-center text-5xl font-extrabold text-gray-900">
Reset Password
</h2>
<p
v-if="called"
class="text-base"
>
An email with instructions on how to reset your password has been sent
to {{ email }}.
</p>
<div v-if="called">
<h2>Email Sent</h2>
<p>
An email with instructions on how to reset your password has been sent
to {{ email }}.
</p>
</div>
<form
v-else
@submit.prevent="forgotPassword()"
Expand Down
2 changes: 0 additions & 2 deletions server/tsyringe.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import { instanceCachingFactory, register } from './tsyringe'
import { AuthService } from './user/auth.service'
import PassportInitializer from './user/passport-initializer'
import * as UserResolvers from './user/resolvers'
import { createEmailService } from './utils/email.service'
import { createRedisClient } from './utils/services.factory'

const { PrismaClient } = prisma
Expand All @@ -23,7 +22,6 @@ export async function configure(): Promise<void> {
register('RedisClient', {
useValue: await createRedisClient(config),
})
register('EmailService', { useValue: createEmailService() })
registerClasses()
}

Expand Down
2 changes: 0 additions & 2 deletions server/tsyringe.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ import type { GroupService } from './groups/service'
import type { AuthService } from './user/auth.service'
import type PassportInitializer from './user/passport-initializer'
import type * as UserResolvers from './user/resolvers'
import { EmailService } from './utils/email.service'
import { RedisClient } from './utils/services.factory'

export { injectable, instanceCachingFactory } from 'tsyringe'
Expand Down Expand Up @@ -48,7 +47,6 @@ export const InjectionSymbols = {
...injectSymbol('PrismaClient')<typeof PrismaClient>(),
...injectSymbol('RedisClient')<RedisClient>(),
...injectSymbol('PassportInitializer')<typeof PassportInitializer>(),
...injectSymbol('EmailService')<EmailService>(),
// Services
...injectSymbol('UserDocumentService')<typeof UserDocumentService>(),
...injectSymbol('AuthService')<typeof AuthService>(),
Expand Down
21 changes: 4 additions & 17 deletions server/user/auth.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,8 @@ import type { PrismaClient, User } from '@prisma/client'
import { ResolversTypes } from '#graphql/resolver'
import { v4 as generateToken } from 'uuid'
import { hash, verifyHash } from '../utils/crypto'
import { EmailService } from '../utils/email.service'
import {
resetPasswordTemplate,
resetPasswordUserNotFoundTemplate,
} from '../utils/resetPasswordTemplate'
import { resetPasswordTemplate } from '../utils/resetPasswordTemplate'
import { sendEmail } from '../utils/sendEmail'
import { RedisClient } from '../utils/services.factory'
import { inject, injectable } from './../tsyringe'

Expand All @@ -28,8 +25,7 @@ export type LoginPayload = ResolversTypes['LoginPayload']
export class AuthService {
constructor(
@inject('PrismaClient') private prisma: PrismaClient,
@inject('RedisClient') private redisClient: RedisClient,
@inject('EmailService') private emailService: EmailService
@inject('RedisClient') private redisClient: RedisClient
) {}

async getUsers(): Promise<User[]> {
Expand Down Expand Up @@ -65,23 +61,14 @@ export class AuthService {
async resetPassword(email: string): Promise<boolean> {
const user = await this.getUserByEmail(email)
if (!user) {
await this.emailService.sendEmail(
{ address: email },
'Password reset on JabRef',
resetPasswordUserNotFoundTemplate()
)
return true
}
const PREFIX = process.env.PREFIX || 'forgot-password'
const key = PREFIX + user.id
const token = generateToken()
const hashedToken = await hash(token)
await this.redisClient.set(key, hashedToken, { EX: 1000 * 60 * 60 * 24 }) // VALID FOR ONE DAY
await this.emailService.sendEmail(
{ address: email },
'Password reset on JabRef',
resetPasswordTemplate(user.id, token)
)
await sendEmail(email, resetPasswordTemplate(user.id, token))
return true
}

Expand Down
90 changes: 0 additions & 90 deletions server/utils/email.service.ts

This file was deleted.

26 changes: 0 additions & 26 deletions server/utils/resetPasswordTemplate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,29 +65,3 @@ export function resetPasswordTemplate(id: string, token: string): string {
</html>`
}

export function resetPasswordUserNotFoundTemplate(): string {
return `
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Password Reset Request - Email Address Not Found</title>
</head>
<body>
<h2>Password Reset Request - Email Address Not Found</h2>
<p>Dear user,</p>
<p>We received your password reset request; however, we couldn't locate an account associated with the provided email address. Here are a few suggestions:</p>
<ol>
<li>Double-check the email: Please ensure that you entered the correct email address when requesting the password reset.</li>
<li>Create a new account: If you don't have an account with us yet, we invite you to <a href="https://www.jabref.org/user/register">create one</a> on our registration page.</li>
<li>Contact support: For further assistance or if you suspect an issue, please reach out to our support team, who will be happy to help.</li>
</ol>
<p>We apologize for any inconvenience caused. To protect user privacy, we can't disclose whether an email address is registered in our system.</p>
<p>If you didn't initiate the password reset request or have concerns, please contact us immediately. We'll investigate promptly and take necessary actions to ensure account security.</p>
<p>Best regards,</p>
<p>JabRef Team</p>
</body>
</html>
`
}
20 changes: 20 additions & 0 deletions server/utils/sendEmail.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { createTestAccount, createTransport } from 'nodemailer'

export async function sendEmail(to: string, html: string): Promise<void> {
const testAccount = await createTestAccount()
const transporter = createTransport({
host: 'smtp.ethereal.email',
port: 587,
secure: false, // true for 465, false for other ports
auth: {
user: testAccount.user, // generated ethereal user
pass: testAccount.pass, // generated ethereal password
},
})
await transporter.sendMail({
from: '"Jabref" <[email protected]>', // sender address
to, // list of receivers
subject: 'Reset your password', // Subject line
html, // plain text body
})
}
Loading

0 comments on commit 8fba0fb

Please sign in to comment.