Compare commits

...

45 Commits

Author SHA1 Message Date
standardci
bb53e88a4e chore(release): publish new version
- @standardnotes/api-gateway@1.3.1
 - @standardnotes/auth-server@1.3.4
 - @standardnotes/files-server@1.1.8
 - @standardnotes/scheduler-server@1.2.3
 - @standardnotes/syncing-server@1.1.8
2022-06-28 12:20:39 +00:00
Karol Sójko
cfd04a5b39 Merge pull request #2 from standardnotes/create-pull-request/patch
chore(deps): upgrade snjs
2022-06-28 14:19:54 +02:00
standardci
e0f2d5e202 chore(release): publish new version
- @standardnotes/api-gateway@1.3.0
2022-06-28 12:11:19 +00:00
Karol Sójko
3035cbc5de feat: remove api metadata decorating html responses 2022-06-28 14:10:40 +02:00
standardci
7c271be310 chore(release): publish new version
- @standardnotes/auth-server@1.3.3
2022-06-28 10:09:14 +00:00
Karol Sójko
ba373ebc6b fix: change response type to html for muting marketing emails 2022-06-28 12:08:36 +02:00
Karol Sójko
2450d88a29 fix: install to be immutable 2022-06-28 11:13:06 +02:00
Karol Sójko
376a59c182 fix: add origin meta property to daily analytics event 2022-06-28 11:12:18 +02:00
standardci
d584ca57f1 chore(deps): upgrade snjs 2022-06-28 08:50:24 +00:00
Mo
c50662849b Merge pull request #4 from standardnotes/chore/pr-workflow
chore: add pr workflow
2022-06-27 17:12:23 -05:00
Mo
82da690139 chore: add pr workflow 2022-06-27 17:04:39 -05:00
standardci
b11a9b0eac chore(release): publish new version
- @standardnotes/auth-server@1.3.2
2022-06-27 22:02:46 +00:00
Mo
d7653474c3 Merge pull request #3 from standardnotes/chore/upgrade-features
chore: upgrade features package
2022-06-27 17:01:41 -05:00
Mo
ce2fd86ca3 chore: upgrade features package 2022-06-27 17:01:21 -05:00
standardci
c9c496c63f chore(release): publish new version
- @standardnotes/api-gateway@1.2.2
 - @standardnotes/auth-server@1.3.1
 - @standardnotes/files-server@1.1.7
 - @standardnotes/scheduler-server@1.2.2
 - @standardnotes/syncing-server@1.1.7
2022-06-27 21:57:06 +00:00
Mo
b1c9f8ca6e Merge pull request #1 from standardnotes/chore/snjs-workflow
chore: upgrade snjs event workflow
2022-06-27 16:56:33 -05:00
Mo
e84bd73a39 chore: add snjs workflow event handler 2022-06-27 16:53:57 -05:00
Mo
c69d1b02fb chore: add ini dep for ncu 2022-06-27 16:52:20 -05:00
Mo
b590d33b88 chore: ncu version 2022-06-27 16:48:02 -05:00
Mo
c1e7a3eb7e chore: add ncu to each package 2022-06-27 16:47:19 -05:00
Mo
fd743a9d5e chore: add npm-check-updates dev dep 2022-06-27 16:44:43 -05:00
standardci
4c40fd5186 chore(release): publish new version
- @standardnotes/api-gateway@1.2.1
2022-06-27 10:27:36 +00:00
Karol Sójko
2cb470b99e fix: issue with NaN error code responses 2022-06-27 12:27:00 +02:00
standardci
b6539f8795 chore(release): publish new version
- @standardnotes/auth-server@1.3.0
2022-06-27 10:18:23 +00:00
Karol Sójko
6d7de4a8da feat: add endpoint for muting marketing emails 2022-06-27 12:17:47 +02:00
standardci
41999f36f0 chore(release): publish new version
- @standardnotes/api-gateway@1.2.0
 - @standardnotes/auth-server@1.2.1
2022-06-27 10:07:19 +00:00
Karol Sójko
fa2a8da17b feat: add endpoint to mute marketing emails 2022-06-27 12:06:33 +02:00
Karol Sójko
214684eae7 fix: add setting uuid to email requests 2022-06-27 12:06:33 +02:00
standardci
b3a92af04d chore(release): publish new version
- @standardnotes/auth-server@1.2.0
2022-06-27 09:57:22 +00:00
Karol Sójko
210a314c81 feat: add docker commands to start sending emails 2022-06-27 11:56:42 +02:00
standardci
46cba52bcb chore(release): publish new version
- @standardnotes/auth-server@1.1.7
2022-06-27 08:44:03 +00:00
Karol Sójko
bf14ec05f9 fix: add sending out email campaigns 2022-06-27 10:43:23 +02:00
standardci
6f88a96c3e chore(release): publish new version
- @standardnotes/scheduler-server@1.2.1
2022-06-27 07:42:47 +00:00
Karol Sójko
e12c9c47a7 fix: change subscription encouragement scheduled from 14 to 30 days 2022-06-27 09:42:08 +02:00
standardci
83085052f8 chore(release): publish new version
- @standardnotes/api-gateway@1.1.6
 - @standardnotes/auth-server@1.1.6
 - @standardnotes/files-server@1.1.6
 - @standardnotes/scheduler-server@1.2.0
 - @standardnotes/syncing-server@1.1.6
2022-06-27 07:25:46 +00:00
Karol Sójko
eda618d845 Merge branch 'main' of github.com:standardnotes/server 2022-06-27 09:25:04 +02:00
Karol Sójko
8d4280f4ca feat: add context for requesting email message 2022-06-27 09:24:43 +02:00
standardci
b57816bba4 chore(release): publish new version
- @standardnotes/api-gateway@1.1.5
 - @standardnotes/auth-server@1.1.5
 - @standardnotes/files-server@1.1.5
 - @standardnotes/scheduler-server@1.1.5
 - @standardnotes/syncing-server@1.1.5
2022-06-27 04:59:52 +00:00
Karol Sójko
b6db194a22 fix: upgrade sentry node sdk 2022-06-27 06:59:15 +02:00
standardci
8f708164cd chore(release): publish new version
- @standardnotes/api-gateway@1.1.4
 - @standardnotes/auth-server@1.1.4
 - @standardnotes/files-server@1.1.4
 - @standardnotes/scheduler-server@1.1.4
 - @standardnotes/syncing-server@1.1.4
2022-06-24 13:19:23 +00:00
Karol Sójko
ff09ae0a47 fix: newrelic deps and setup db and cache for local development purposes 2022-06-24 15:18:41 +02:00
Karol Sójko
d21d752029 fix: newrelic deploy markers on syncing-server 2022-06-23 19:42:23 +02:00
standardci
2ea077a7cd chore(release): publish new version
- @standardnotes/api-gateway@1.1.3
 - @standardnotes/auth-server@1.1.3
 - @standardnotes/files-server@1.1.3
 - @standardnotes/scheduler-server@1.1.3
 - @standardnotes/syncing-server@1.1.3
2022-06-23 17:23:35 +00:00
Karol Sójko
0d67c55e12 fix: curl in the final image 2022-06-23 19:22:52 +02:00
Karol Sójko
8837dca039 fix: pushing tags one by one on release 2022-06-23 18:55:55 +02:00
131 changed files with 2018 additions and 1093 deletions

6
.env.sample Normal file
View File

@@ -0,0 +1,6 @@
DB_PORT=3306
DB_USERNAME=std_notes_user
DB_PASSWORD=changeme123
DB_DATABASE=standard_notes_db
REDIS_PORT=6379

21
.github/workflows/pr.yml vendored Normal file
View File

@@ -0,0 +1,21 @@
name: Pull Request
on:
pull_request:
branches:
- main
jobs:
test:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Install dependencies
run: yarn install --immutable
- name: ESLint
run: yarn lint
- name: Build
run: yarn build
- name: Test
run: yarn test

View File

@@ -0,0 +1,46 @@
name: Update SNJS Packages
on:
workflow_dispatch:
repository_dispatch:
types: [snjs-updated-event]
jobs:
SNJSUpdateEvent:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v3
with:
ref: main
token: ${{ secrets.CI_PAT_TOKEN }}
- uses: actions/setup-node@v3
with:
registry-url: 'https://registry.npmjs.org'
- name: Setup git config
run: |
git config --global user.name "standardci"
git config --global user.email "ci@standardnotes.com"
- name: Import GPG key
uses: crazy-max/ghaction-import-gpg@v4
with:
gpg_private_key: ${{ secrets.GPG_PRIVATE_KEY }}
passphrase: ${{ secrets.PASSPHRASE }}
git_user_signingkey: true
git_commit_gpgsign: true
- run: yarn install
- run: |
yarn upgrade:snjs
yarn install --no-immutable
- name: Create Pull Request
uses: peter-evans/create-pull-request@v4
with:
token: ${{ secrets.CI_PAT_TOKEN }}
title: "${{ 'chore(deps): upgrade snjs' }}"
body: Updates all packages prefixed with "@standardnotes/"
commit-message: "${{ 'chore(deps): upgrade snjs' }}"
delete-branch: true
committer: standardci <ci@standardnotes.com>
author: standardci <ci@standardnotes.com>

View File

@@ -185,25 +185,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: DEV - Create New Relic deployment marker for Web
uses: newrelic/deployment-marker-action@v1
with:
accountId: ${{ secrets.NEW_RELIC_ACCOUNT_ID }}
apiKey: ${{ secrets.NEW_RELIC_API_KEY }}
applicationId: ${{ secrets.NEW_RELIC_APPLICATION_ID_SYNCING_SERVER_WEB_DEV }}
revision: "${{ github.sha }}"
description: "Automated Deployment via Github Actions"
user: "${{ github.actor }}"
- name: DEV - Create New Relic deployment marker for Worker
uses: newrelic/deployment-marker-action@v1
with:
accountId: ${{ secrets.NEW_RELIC_ACCOUNT_ID }}
apiKey: ${{ secrets.NEW_RELIC_API_KEY }}
applicationId: ${{ secrets.NEW_RELIC_APPLICATION_ID_SYNCING_SERVER_WORKER_DEV }}
revision: "${{ github.sha }}"
description: "Automated Deployment via Github Actions"
user: "${{ github.actor }}"
- name: PROD - Create New Relic deployment marker for Web
- name: Create New Relic deployment marker for Web
uses: newrelic/deployment-marker-action@v1
with:
accountId: ${{ secrets.NEW_RELIC_ACCOUNT_ID }}
@@ -212,7 +194,7 @@ jobs:
revision: "${{ github.sha }}"
description: "Automated Deployment via Github Actions"
user: "${{ github.actor }}"
- name: PROD - Create New Relic deployment marker for Worker
- name: Create New Relic deployment marker for Worker
uses: newrelic/deployment-marker-action@v1
with:
accountId: ${{ secrets.NEW_RELIC_ACCOUNT_ID }}

3
.gitignore vendored
View File

@@ -18,3 +18,6 @@ newrelic_agent.log
packages/files/uploads/*
!packages/files/uploads/.gitkeep
data/*
!data/.gitkeep

1086
.pnp.cjs generated

File diff suppressed because it is too large Load Diff

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

0
data/.gitkeep Normal file
View File

24
docker-compose.yml Normal file
View File

@@ -0,0 +1,24 @@
version: '3.8'
services:
db:
image: mysql:5.6
environment:
MYSQL_DATABASE: '${DB_DATABASE}'
MYSQL_USER: '${DB_USERNAME}'
MYSQL_PASSWORD: '${DB_PASSWORD}'
MYSQL_ROOT_PASSWORD: '${DB_PASSWORD}'
expose:
- ${DB_PORT}:3306
restart: unless-stopped
command: --default-authentication-plugin=mysql_native_password --character-set-server=utf8 --collation-server=utf8_general_ci
volumes:
- ./data/mysql:/var/lib/mysql
- ./data/import:/docker-entrypoint-initdb.d
cache:
image: redis:6.0-alpine
volumes:
- ./data/redis/:/data
expose:
- ${REDIS_PORT}:6379
restart: unless-stopped

View File

@@ -23,7 +23,7 @@
"test:syncing-server": "yarn workspace @standardnotes/syncing-server test",
"test:files": "yarn workspace @standardnotes/files-server test",
"clean": "yarn workspaces foreach -p --verbose run clean",
"setup:env": "yarn workspaces foreach -p --verbose run setup:env",
"setup:env": "cp .env.sample .env && yarn workspaces foreach -p --verbose run setup:env",
"build": "yarn workspaces foreach -pt -j 10 --verbose run build",
"build:auth": "yarn workspace @standardnotes/auth-server build",
"build:scheduler": "yarn workspace @standardnotes/scheduler-server build",
@@ -38,7 +38,9 @@
"start:files": "yarn workspace @standardnotes/files-server start",
"start:files-worker": "yarn workspace @standardnotes/files-server worker",
"start:api-gateway": "yarn workspace @standardnotes/api-gateway start",
"release:prod": "lerna version --conventional-graduate --conventional-commits --yes -m \"chore(release): publish new version\""
"release:prod": "lerna version --conventional-graduate --conventional-commits --yes -m \"chore(release): publish new version\"",
"postversion": "./scripts/push-tags-one-by-one.sh",
"upgrade:snjs": "yarn workspaces foreach --verbose run upgrade:snjs"
},
"devDependencies": {
"@commitlint/cli": "^17.0.2",
@@ -47,13 +49,20 @@
"@lerna-lite/list": "^1.5.1",
"@lerna-lite/run": "^1.5.1",
"@types/jest": "^28.1.3",
"@types/newrelic": "^7.0.3",
"@types/node": "^18.0.0",
"@typescript-eslint/parser": "^5.29.0",
"eslint": "^8.17.0",
"eslint-config-prettier": "^8.5.0",
"ini": "^3.0.0",
"npm-check-updates": "^14.1.1",
"prettier": "^2.7.1",
"ts-node": "^10.8.1",
"typescript": "^4.7.4"
},
"packageManager": "yarn@3.2.1"
"packageManager": "yarn@3.2.1",
"dependencies": {
"@sentry/node": "^7.3.0",
"newrelic": "^8.14.1"
}
}

View File

@@ -3,6 +3,56 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.3.1](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.3.0...@standardnotes/api-gateway@1.3.1) (2022-06-28)
### Bug Fixes
* add origin meta property to daily analytics event ([376a59c](https://github.com/standardnotes/api-gateway/commit/376a59c1827411164a536157fc591a15e0a5b0b2))
# [1.3.0](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.2.2...@standardnotes/api-gateway@1.3.0) (2022-06-28)
### Features
* remove api metadata decorating html responses ([3035cbc](https://github.com/standardnotes/api-gateway/commit/3035cbc5ded1408bc4b8646563c4992ba5f27c75))
## [1.2.2](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.2.1...@standardnotes/api-gateway@1.2.2) (2022-06-27)
**Note:** Version bump only for package @standardnotes/api-gateway
## [1.2.1](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.2.0...@standardnotes/api-gateway@1.2.1) (2022-06-27)
### Bug Fixes
* issue with NaN error code responses ([2cb470b](https://github.com/standardnotes/api-gateway/commit/2cb470b99edc2fac8d5c38e4eb16201e55fe8753))
# [1.2.0](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.1.6...@standardnotes/api-gateway@1.2.0) (2022-06-27)
### Features
* add endpoint to mute marketing emails ([fa2a8da](https://github.com/standardnotes/api-gateway/commit/fa2a8da17bc6588021172adbbc4ecae5bd35f33a))
## [1.1.6](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.1.5...@standardnotes/api-gateway@1.1.6) (2022-06-27)
**Note:** Version bump only for package @standardnotes/api-gateway
## [1.1.5](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.1.4...@standardnotes/api-gateway@1.1.5) (2022-06-27)
### Bug Fixes
* upgrade sentry node sdk ([b6db194](https://github.com/standardnotes/api-gateway/commit/b6db194a22ff1d0afe96c291d545b408c0a5c373))
## [1.1.4](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.1.3...@standardnotes/api-gateway@1.1.4) (2022-06-24)
### Bug Fixes
* newrelic deps and setup db and cache for local development purposes ([ff09ae0](https://github.com/standardnotes/api-gateway/commit/ff09ae0a47747eaf7977ce5d3937ad385101eaeb))
## [1.1.3](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.1.2...@standardnotes/api-gateway@1.1.3) (2022-06-23)
### Bug Fixes
* curl in the final image ([0d67c55](https://github.com/standardnotes/api-gateway/commit/0d67c55e124eed08bca16824750152b895fceca7))
## [1.1.2](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.1.1...@standardnotes/api-gateway@1.1.2) (2022-06-23)
**Note:** Version bump only for package @standardnotes/api-gateway

View File

@@ -1,7 +1,7 @@
FROM node:16.15.1-alpine AS builder
# Install dependencies for building native libraries
RUN apk add --update git openssh-client curl python3 alpine-sdk
RUN apk add --update git openssh-client python3 alpine-sdk
WORKDIR /workspace
@@ -12,6 +12,8 @@ RUN yarn install --immutable
FROM node:16.15.1-alpine
RUN apk add --update curl
WORKDIR /workspace
# Copy the installed dependencies from the previous stage.

View File

@@ -7,7 +7,11 @@ import { Logger } from 'winston'
import { ContainerConfigLoader } from '../src/Bootstrap/Container'
import TYPES from '../src/Bootstrap/Types'
import { Env } from '../src/Bootstrap/Env'
import { DomainEventPublisherInterface, DailyAnalyticsReportGeneratedEvent } from '@standardnotes/domain-events'
import {
DomainEventPublisherInterface,
DailyAnalyticsReportGeneratedEvent,
DomainEventService,
} from '@standardnotes/domain-events'
import { AnalyticsActivity, AnalyticsStoreInterface, Period, StatisticsStoreInterface } from '@standardnotes/analytics'
const requestReport = async (
@@ -23,6 +27,7 @@ const requestReport = async (
userIdentifier: '',
userIdentifierType: 'uuid',
},
origin: DomainEventService.ApiGateway,
},
payload: {
applicationStatistics: await statisticsStore.getYesterdayApplicationUsage(),

View File

@@ -1,6 +1,6 @@
{
"name": "@standardnotes/api-gateway",
"version": "1.1.2",
"version": "1.3.1",
"engines": {
"node": ">=16.0.0 <17.0.0"
},
@@ -15,18 +15,19 @@
"prebuild": "yarn clean",
"build": "tsc --rootDir ./",
"lint": "eslint . --ext .ts",
"setup:env": "cp .env.sample .env",
"start": "yarn node dist/bin/server.js",
"report": "yarn node dist/bin/report.js"
"report": "yarn node dist/bin/report.js",
"upgrade:snjs": "yarn ncu -u '@standardnotes/*'"
},
"dependencies": {
"@newrelic/native-metrics": "7.0.2",
"@newrelic/winston-enricher": "^2.1.0",
"@sentry/node": "^6.16.1",
"@standardnotes/analytics": "^1.4.0",
"@standardnotes/auth": "3.19.2",
"@standardnotes/domain-events": "2.29.0",
"@standardnotes/domain-events-infra": "1.4.127",
"@standardnotes/time": "^1.7.0",
"@sentry/node": "^7.3.0",
"@standardnotes/analytics": "^1.6.0",
"@standardnotes/auth": "3.19.4",
"@standardnotes/domain-events": "2.32.5",
"@standardnotes/domain-events-infra": "1.5.5",
"@standardnotes/time": "^1.7.1",
"aws-sdk": "^2.1160.0",
"axios": "0.24.0",
"cors": "2.8.5",
@@ -37,7 +38,7 @@
"inversify-express-utils": "^6.4.3",
"ioredis": "^5.0.6",
"jsonwebtoken": "8.5.1",
"newrelic": "8.6.0",
"newrelic": "^8.14.1",
"prettyjson": "1.2.1",
"reflect-metadata": "0.1.13",
"winston": "3.3.3"
@@ -48,13 +49,14 @@
"@types/ioredis": "^4.28.10",
"@types/jest": "^28.1.3",
"@types/jsonwebtoken": "^8.5.0",
"@types/newrelic": "^7.0.1",
"@types/newrelic": "^7.0.3",
"@types/prettyjson": "^0.0.29",
"@typescript-eslint/eslint-plugin": "^5.29.0",
"eslint": "^8.14.0",
"eslint-plugin-prettier": "^4.0.0",
"jest": "^28.1.1",
"nodemon": "^2.0.16",
"npm-check-updates": "^14.1.1",
"ts-jest": "^28.0.1"
}
}

View File

@@ -99,7 +99,10 @@ export class AuthMiddleware extends BaseMiddleware {
response.setHeader('content-type', (error as AxiosError).response?.headers['content-type'] as string)
}
const errorCode = (error as AxiosError).isAxiosError ? +((error as AxiosError).code as string) : 500
const errorCode =
(error as AxiosError).isAxiosError && !isNaN(+((error as AxiosError).code as string))
? +((error as AxiosError).code as string)
: 500
response.status(errorCode).send(errorMessage)

View File

@@ -88,7 +88,10 @@ export class SubscriptionTokenAuthMiddleware extends BaseMiddleware {
response.setHeader('content-type', (error as AxiosError).response?.headers['content-type'] as string)
}
const errorCode = (error as AxiosError).isAxiosError ? +((error as AxiosError).code as string) : 500
const errorCode =
(error as AxiosError).isAxiosError && !isNaN(+((error as AxiosError).code as string))
? +((error as AxiosError).code as string)
: 500
response.status(errorCode).send(errorMessage)

View File

@@ -49,4 +49,14 @@ export class ActionsController extends BaseHttpController {
request.body,
)
}
@httpGet('/marketing-emails/mute/:settingUuid')
async muteMarketingEmails(request: Request, response: Response): Promise<void> {
await this.httpService.callAuthServer(
request,
response,
`internal/settings/marketing-emails/${request.params.settingUuid}/mute`,
request.body,
)
}
}

View File

@@ -133,7 +133,10 @@ export class HttpService implements HttpServiceInterface {
response.setHeader('content-type', (error as AxiosError).response?.headers['content-type'] as string)
}
const errorCode = (error as AxiosError).isAxiosError ? +((error as AxiosError).code as string) : 500
const errorCode =
(error as AxiosError).isAxiosError && !isNaN(+((error as AxiosError).code as string))
? +((error as AxiosError).code as string)
: 500
response.status(errorCode).send(errorMessage)
}
@@ -159,6 +162,12 @@ export class HttpService implements HttpServiceInterface {
this.applyResponseHeaders(serviceResponse, response)
if (this.responseShouldNotBeDecorated(serviceResponse)) {
response.status(serviceResponse.status).send(serviceResponse.data)
return
}
response.status(serviceResponse.status).send({
meta: {
auth: {
@@ -210,6 +219,10 @@ export class HttpService implements HttpServiceInterface {
return payload
}
private responseShouldNotBeDecorated(serviceResponse: AxiosResponse): boolean {
return serviceResponse.headers['content-type'].toLowerCase().includes('text/html')
}
private applyResponseHeaders(serviceResponse: AxiosResponse, response: Response): void {
const returnedHeadersFromUnderlyingService = [
'access-control-allow-methods',

View File

@@ -3,6 +3,70 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.3.4](https://github.com/standardnotes/auth/compare/@standardnotes/auth-server@1.3.3...@standardnotes/auth-server@1.3.4) (2022-06-28)
**Note:** Version bump only for package @standardnotes/auth-server
## [1.3.3](https://github.com/standardnotes/auth/compare/@standardnotes/auth-server@1.3.2...@standardnotes/auth-server@1.3.3) (2022-06-28)
### Bug Fixes
* change response type to html for muting marketing emails ([ba373eb](https://github.com/standardnotes/auth/commit/ba373ebc6b3038f7de2fab40f0429a655dbe2499))
## [1.3.2](https://github.com/standardnotes/auth/compare/@standardnotes/auth-server@1.3.1...@standardnotes/auth-server@1.3.2) (2022-06-27)
**Note:** Version bump only for package @standardnotes/auth-server
## [1.3.1](https://github.com/standardnotes/auth/compare/@standardnotes/auth-server@1.3.0...@standardnotes/auth-server@1.3.1) (2022-06-27)
**Note:** Version bump only for package @standardnotes/auth-server
# [1.3.0](https://github.com/standardnotes/auth/compare/@standardnotes/auth-server@1.2.1...@standardnotes/auth-server@1.3.0) (2022-06-27)
### Features
* add endpoint for muting marketing emails ([6d7de4a](https://github.com/standardnotes/auth/commit/6d7de4a8daaf7569b8f2e031854e8baaff64a469))
## [1.2.1](https://github.com/standardnotes/auth/compare/@standardnotes/auth-server@1.2.0...@standardnotes/auth-server@1.2.1) (2022-06-27)
### Bug Fixes
* add setting uuid to email requests ([214684e](https://github.com/standardnotes/auth/commit/214684eae733675b7cefa522202e53d9556e5279))
# [1.2.0](https://github.com/standardnotes/auth/compare/@standardnotes/auth-server@1.1.7...@standardnotes/auth-server@1.2.0) (2022-06-27)
### Features
* add docker commands to start sending emails ([210a314](https://github.com/standardnotes/auth/commit/210a314c8199e47e5b6a113bd60401c16bb95291))
## [1.1.7](https://github.com/standardnotes/auth/compare/@standardnotes/auth-server@1.1.6...@standardnotes/auth-server@1.1.7) (2022-06-27)
### Bug Fixes
* add sending out email campaigns ([bf14ec0](https://github.com/standardnotes/auth/commit/bf14ec05f92d893e7c74a4f29ef7e426bee9d768))
## [1.1.6](https://github.com/standardnotes/auth/compare/@standardnotes/auth-server@1.1.5...@standardnotes/auth-server@1.1.6) (2022-06-27)
**Note:** Version bump only for package @standardnotes/auth-server
## [1.1.5](https://github.com/standardnotes/auth/compare/@standardnotes/auth-server@1.1.4...@standardnotes/auth-server@1.1.5) (2022-06-27)
### Bug Fixes
* upgrade sentry node sdk ([b6db194](https://github.com/standardnotes/auth/commit/b6db194a22ff1d0afe96c291d545b408c0a5c373))
## [1.1.4](https://github.com/standardnotes/auth/compare/@standardnotes/auth-server@1.1.3...@standardnotes/auth-server@1.1.4) (2022-06-24)
### Bug Fixes
* newrelic deps and setup db and cache for local development purposes ([ff09ae0](https://github.com/standardnotes/auth/commit/ff09ae0a47747eaf7977ce5d3937ad385101eaeb))
## [1.1.3](https://github.com/standardnotes/auth/compare/@standardnotes/auth-server@1.1.2...@standardnotes/auth-server@1.1.3) (2022-06-23)
### Bug Fixes
* curl in the final image ([0d67c55](https://github.com/standardnotes/auth/commit/0d67c55e124eed08bca16824750152b895fceca7))
## [1.1.2](https://github.com/standardnotes/auth/compare/@standardnotes/auth-server@1.1.1...@standardnotes/auth-server@1.1.2) (2022-06-23)
**Note:** Version bump only for package @standardnotes/auth-server

View File

@@ -1,7 +1,7 @@
FROM node:16.15.1-alpine AS builder
# Install dependencies for building native libraries
RUN apk add --update git openssh-client curl python3 alpine-sdk
RUN apk add --update git openssh-client python3 alpine-sdk
WORKDIR /workspace
@@ -12,6 +12,8 @@ RUN yarn install --immutable
FROM node:16.15.1-alpine
RUN apk add --update curl
WORKDIR /workspace
# Copy the installed dependencies from the previous stage.

147
packages/auth/bin/email.ts Normal file
View File

@@ -0,0 +1,147 @@
import 'reflect-metadata'
import 'newrelic'
import { Stream } from 'stream'
import { Logger } from 'winston'
import * as dayjs from 'dayjs'
import * as utc from 'dayjs/plugin/utc'
import { UserRepositoryInterface } from '../src/Domain/User/UserRepositoryInterface'
import { ContainerConfigLoader } from '../src/Bootstrap/Container'
import TYPES from '../src/Bootstrap/Types'
import { Env } from '../src/Bootstrap/Env'
import { SettingServiceInterface } from '../src/Domain/Setting/SettingServiceInterface'
import { DomainEventFactoryInterface } from '../src/Domain/Event/DomainEventFactoryInterface'
import { UserSubscriptionRepositoryInterface } from '../src/Domain/Subscription/UserSubscriptionRepositoryInterface'
import { DomainEventPublisherInterface } from '@standardnotes/domain-events'
import { MuteMarketingEmailsOption, SettingName } from '@standardnotes/settings'
import { EmailMessageIdentifier } from '@standardnotes/common'
import { User } from '../src/Domain/User/User'
import { EncryptionVersion } from '../src/Domain/Encryption/EncryptionVersion'
import { TimerInterface } from '@standardnotes/time'
const inputArgs = process.argv.slice(2)
const emailMessageIdentifier = inputArgs[0]
const sendEmailCampaign = async (
userRepository: UserRepositoryInterface,
settingService: SettingServiceInterface,
userSubscriptionRepository: UserSubscriptionRepositoryInterface,
timer: TimerInterface,
domainEventFactory: DomainEventFactoryInterface,
domainEventPublisher: DomainEventPublisherInterface,
): Promise<void> => {
const stream = await userRepository.streamAll()
return new Promise((resolve, reject) => {
stream
.pipe(
new Stream.Transform({
objectMode: true,
transform: async (rawUserData, _encoding, callback) => {
let emailsMutedSetting = await settingService.findSettingWithDecryptedValue({
userUuid: rawUserData.user_uuid,
settingName: SettingName.MuteMarketingEmails,
})
if (emailsMutedSetting === null) {
const user = (await userRepository.findOneByUuid(rawUserData.user_uuid)) as User
const { setting } = await settingService.createOrReplace({
user,
props: {
name: SettingName.MuteMarketingEmails,
unencryptedValue: MuteMarketingEmailsOption.NotMuted,
serverEncryptionVersion: EncryptionVersion.Default,
sensitive: false,
},
})
emailsMutedSetting = setting
}
if (emailsMutedSetting.value === MuteMarketingEmailsOption.Muted) {
callback()
return
}
let activeSubscription = false
let subscriptionPlanName = null
const userSubscription = await userSubscriptionRepository.findOneByUserUuid(rawUserData.user_uuid)
if (userSubscription !== null) {
activeSubscription =
!userSubscription.cancelled && userSubscription.endsAt > timer.getTimestampInMicroseconds()
subscriptionPlanName = userSubscription.planName
}
await domainEventPublisher.publish(
domainEventFactory.createEmailMessageRequestedEvent({
userEmail: rawUserData.user_email,
messageIdentifier: emailMessageIdentifier as EmailMessageIdentifier,
context: {
activeSubscription,
subscriptionPlanName,
muteEmailsSettingUuid: emailsMutedSetting.uuid,
},
}),
)
callback()
},
}),
)
.on('finish', resolve)
.on('error', reject)
})
}
const container = new ContainerConfigLoader()
void container.load().then((container) => {
dayjs.extend(utc)
const env: Env = new Env()
env.load()
const logger: Logger = container.get(TYPES.Logger)
logger.info(`Starting email campaign for email ${emailMessageIdentifier} ...`)
if (!emailMessageIdentifier) {
logger.error('No email message identifier passed as argument. Skipped sending.')
process.exit(1)
}
const userRepository: UserRepositoryInterface = container.get(TYPES.UserRepository)
const settingService: SettingServiceInterface = container.get(TYPES.SettingService)
const userSubscriptionRepository: UserSubscriptionRepositoryInterface = container.get(
TYPES.UserSubscriptionRepository,
)
const timer: TimerInterface = container.get(TYPES.Timer)
const domainEventFactory: DomainEventFactoryInterface = container.get(TYPES.DomainEventFactory)
const domainEventPublisher: DomainEventPublisherInterface = container.get(TYPES.DomainEventPublisher)
Promise.resolve(
sendEmailCampaign(
userRepository,
settingService,
userSubscriptionRepository,
timer,
domainEventFactory,
domainEventPublisher,
),
)
.then(() => {
logger.info(`${emailMessageIdentifier} email campaign complete.`)
process.exit(0)
})
.catch((error) => {
logger.error(`Could not finish ${emailMessageIdentifier} email campaign: ${error.message}`)
process.exit(1)
})
})

View File

@@ -44,6 +44,12 @@ case "$COMMAND" in
yarn workspace @standardnotes/auth-server daily-backup:one_drive
;;
'email-campaign' )
echo "Starting Email Campaign Sending..."
MESSAGE_IDENTIFIER=$1 && shift 1
yarn workspace @standardnotes/auth-server email-campaign $MESSAGE_IDENTIFIER
;;
* )
echo "Unknown command"
;;

Some files were not shown because too many files have changed in this diff Show More