Compare commits

..

32 Commits

Author SHA1 Message Date
standardci
14794d1a5f chore(release): publish new version
- @standardnotes/proxy-server@1.1.3
2023-02-22 17:33:33 +00:00
Mo
6b130ef045 refactor: proxy improvements 2023-02-22 11:19:37 -06:00
standardci
25a6126ef4 chore(release): publish new version
- @standardnotes/proxy-server@1.1.2
2023-02-22 16:52:30 +00:00
Mo
a2df09fb5b refactor: proxy param 2023-02-22 10:38:18 -06:00
Mo
465b2741fb refactor: proxy server error handling 2023-02-22 10:35:33 -06:00
standardci
724dc5c86c chore(release): publish new version
- @standardnotes/proxy-server@1.1.1
2023-02-22 16:25:25 +00:00
Aman Harwara
f4208c19a7 refactor: proxy error response (#452) 2023-02-22 21:36:32 +05:30
Karol Sójko
6fed293716 chore: remove deploying worker workflow from proxy server 2023-02-22 13:40:30 +01:00
standardci
29ffaf04c4 chore(release): publish new version
- @standardnotes/api-gateway@1.49.0
 - @standardnotes/proxy-server@1.1.0
2023-02-22 12:33:59 +00:00
Karol Sójko
bc9182f214 fix(api-gateway): proxy endpoint for request passing 2023-02-22 13:19:17 +01:00
Karol Sójko
91c70a51a0 fix(proxy): prevent from passing auth tokens to proxy destination 2023-02-22 13:14:09 +01:00
Karol Sójko
dfe30d7f5e feat(proxy): add proxy server 2023-02-22 13:03:04 +01:00
mfridge
815d5460e7 Do not grant localstack access to host's docker.sock (#448)
* Do not grant localstack access to host's docker.sock

* Remove access to host's docker socket as requested by @karolsojko
2023-02-22 12:15:34 +01:00
standardci
8a63c6768b chore(release): publish new version
- @standardnotes/syncing-server@1.31.5
2023-02-22 11:06:01 +00:00
Karol Sójko
f7c29848f1 fix(syncing-server): numbering of the backup emails 2023-02-22 11:48:08 +01:00
standardci
78b9426c1c chore(release): publish new version
- @standardnotes/syncing-server@1.31.4
2023-02-21 11:08:01 +00:00
Karol Sójko
87b22ac684 fix(syncing-server): creating email backup attachment files 2023-02-21 11:45:54 +01:00
standardci
46c30d197a chore(release): publish new version
- @standardnotes/analytics@2.20.3
 - @standardnotes/api-gateway@1.48.3
 - @standardnotes/auth-server@1.88.3
 - @standardnotes/domain-events-infra@1.9.70
 - @standardnotes/domain-events@2.107.1
 - @standardnotes/event-store@1.7.2
 - @standardnotes/files-server@1.10.3
 - @standardnotes/revisions-server@1.12.4
 - @standardnotes/scheduler-server@1.17.3
 - @standardnotes/syncing-server@1.31.3
 - @standardnotes/websockets-server@1.6.3
 - @standardnotes/workspace-server@1.20.3
2023-02-21 10:03:46 +00:00
Karol Sójko
36b8354350 chore: remove unused revisions ownership event 2023-02-21 10:47:59 +01:00
Karol Sójko
b6702c7182 chore: remove unused content size recalculation event 2023-02-21 10:45:32 +01:00
standardci
09d7f608cd chore(release): publish new version
- @standardnotes/analytics@2.20.2
 - @standardnotes/api-gateway@1.48.2
 - @standardnotes/auth-server@1.88.2
 - @standardnotes/domain-events-infra@1.9.69
 - @standardnotes/domain-events@2.107.0
 - @standardnotes/event-store@1.7.1
 - @standardnotes/files-server@1.10.2
 - @standardnotes/revisions-server@1.12.3
 - @standardnotes/scheduler-server@1.17.2
 - @standardnotes/syncing-server@1.31.2
 - @standardnotes/websockets-server@1.6.2
 - @standardnotes/workspace-server@1.20.2
2023-02-20 06:31:30 +00:00
Karol Sójko
d023a27377 fix(event-store): add handling of email sent events 2023-02-20 07:14:24 +01:00
Karol Sójko
190595febf feat(domain-events): add email sent event 2023-02-20 07:13:23 +01:00
standardci
b25edec26c chore(release): publish new version
- @standardnotes/revisions-server@1.12.2
2023-02-17 10:18:28 +00:00
Karol Sójko
85d0c12dad fix(revisions): initial migration to check if user_uuid exists on table 2023-02-17 11:01:37 +01:00
Karol Sójko
25c98ef078 chore: fix path for syncing server revisions dumps 2023-02-16 15:17:00 +01:00
Karol Sójko
af51baea9a chore: fix upload volume path on example docker compose file 2023-02-16 15:06:31 +01:00
Karol Sójko
e97b16606c chore: fix db migrations path in self hosting setup 2023-02-16 13:26:51 +01:00
Karol Sójko
5ff9e43899 chore: fix default public files server url 2023-02-16 11:39:41 +01:00
Karol Sójko
d3a49e109c chore: change the localstack bootstrap path in the example docker compose file 2023-02-16 09:06:07 +01:00
Karol Sójko
e3dbff6996 chore: change the env file name in the example docker compose file 2023-02-16 09:04:18 +01:00
Karol Sójko
d9f5410afd chore: add mounted volume for file uploads 2023-02-15 17:37:25 +01:00
80 changed files with 630 additions and 309 deletions

View File

@@ -8,7 +8,6 @@ DB_USERNAME=std_notes_user
DB_PASSWORD=changeme123
DB_DATABASE=standard_notes_db
DB_DEBUG_LEVEL=all
DB_MIGRATIONS_PATH=dist/migrations/*.js
#########
# CACHE #

22
.github/workflows/proxy.yml vendored Normal file
View File

@@ -0,0 +1,22 @@
name: Proxy Server
concurrency:
group: proxy_server
cancel-in-progress: true
on:
push:
tags:
- '*standardnotes/proxy-server*'
workflow_dispatch:
jobs:
call_server_application_workflow:
name: Server Application
uses: standardnotes/server/.github/workflows/common-server-application.yml@main
with:
service_name: proxy
workspace_name: "@standardnotes/proxy-server"
deploy_worker: false
package_path: packages/proxy
secrets: inherit

53
.pnp.cjs generated
View File

@@ -53,6 +53,10 @@ const RAW_RUNTIME_STATE =
"name": "@standardnotes/predicates",\
"reference": "workspace:packages/predicates"\
},\
{\
"name": "@standardnotes/proxy-server",\
"reference": "workspace:packages/proxy"\
},\
{\
"name": "@standardnotes/revisions-server",\
"reference": "workspace:packages/revisions"\
@@ -103,6 +107,7 @@ const RAW_RUNTIME_STATE =
["@standardnotes/event-store", ["workspace:packages/event-store"]],\
["@standardnotes/files-server", ["workspace:packages/files"]],\
["@standardnotes/predicates", ["workspace:packages/predicates"]],\
["@standardnotes/proxy-server", ["workspace:packages/proxy"]],\
["@standardnotes/revisions-server", ["workspace:packages/revisions"]],\
["@standardnotes/scheduler-server", ["workspace:packages/scheduler"]],\
["@standardnotes/security", ["workspace:packages/security"]],\
@@ -4461,6 +4466,23 @@ const RAW_RUNTIME_STATE =
"linkType": "SOFT"\
}]\
]],\
["@standardnotes/proxy-server", [\
["workspace:packages/proxy", {\
"packageLocation": "./packages/proxy/",\
"packageDependencies": [\
["@standardnotes/proxy-server", "workspace:packages/proxy"],\
["@types/http-proxy", "npm:1.17.9"],\
["@types/newrelic", "npm:9.4.0"],\
["@typescript-eslint/eslint-plugin", "virtual:c66bf20e88479ada0172094776519a9f51acc4731d22079b60a295bcec7ea42d5545cbce58a77a50d932bf953298799135e99707486e343da6d99ba1d167bdbd#npm:5.48.2"],\
["eslint", "npm:8.32.0"],\
["eslint-plugin-prettier", "virtual:c66bf20e88479ada0172094776519a9f51acc4731d22079b60a295bcec7ea42d5545cbce58a77a50d932bf953298799135e99707486e343da6d99ba1d167bdbd#npm:4.2.1"],\
["http-proxy", "npm:1.18.1"],\
["newrelic", "npm:9.8.0"],\
["typescript", "patch:typescript@npm%3A4.8.4#optional!builtin<compat/typescript>::version=4.8.4&hash=701156"]\
],\
"linkType": "SOFT"\
}]\
]],\
["@standardnotes/responses", [\
["npm:1.13.4", {\
"packageLocation": "./.yarn/cache/@standardnotes-responses-npm-1.13.4-70cbd72561-4803ee14bd.zip/node_modules/@standardnotes/responses/",\
@@ -5076,6 +5098,16 @@ const RAW_RUNTIME_STATE =
"linkType": "HARD"\
}]\
]],\
["@types/http-proxy", [\
["npm:1.17.9", {\
"packageLocation": "./.yarn/cache/@types-http-proxy-npm-1.17.9-fa2f5ce316-3ee577db82.zip/node_modules/@types/http-proxy/",\
"packageDependencies": [\
["@types/http-proxy", "npm:1.17.9"],\
["@types/node", "npm:18.0.3"]\
],\
"linkType": "HARD"\
}]\
]],\
["@types/inversify-express-utils", [\
["npm:2.0.0", {\
"packageLocation": "./.yarn/cache/@types-inversify-express-utils-npm-2.0.0-e78182955d-9841bfddff.zip/node_modules/@types/inversify-express-utils/",\
@@ -9314,6 +9346,18 @@ const RAW_RUNTIME_STATE =
"linkType": "HARD"\
}]\
]],\
["http-proxy", [\
["npm:1.18.1", {\
"packageLocation": "./.yarn/cache/http-proxy-npm-1.18.1-a313c479c5-5d681e4231.zip/node_modules/http-proxy/",\
"packageDependencies": [\
["http-proxy", "npm:1.18.1"],\
["eventemitter3", "npm:4.0.7"],\
["follow-redirects", "virtual:4b63965ac1b2157b91a1875529bea3b0bbc3068d3676d1bef28bff5cf6689705374a86cc3832f95ba8d934037a93cc0e09c3662c13ca0e747800d7ca279a53c0#npm:1.15.2"],\
["requires-port", "npm:1.0.0"]\
],\
"linkType": "HARD"\
}]\
]],\
["http-proxy-agent", [\
["npm:5.0.0", {\
"packageLocation": "./.yarn/cache/http-proxy-agent-npm-5.0.0-7f1f121b83-b59a9b4bdd.zip/node_modules/http-proxy-agent/",\
@@ -13006,6 +13050,15 @@ const RAW_RUNTIME_STATE =
"linkType": "HARD"\
}]\
]],\
["requires-port", [\
["npm:1.0.0", {\
"packageLocation": "./.yarn/cache/requires-port-npm-1.0.0-fd036b488a-28a1064f04.zip/node_modules/requires-port/",\
"packageDependencies": [\
["requires-port", "npm:1.0.0"]\
],\
"linkType": "HARD"\
}]\
]],\
["resolve", [\
["patch:resolve@npm%3A1.22.1#optional!builtin<compat/resolve>::version=1.22.1&hash=07638b", {\
"packageLocation": "./.yarn/cache/resolve-patch-bc26c25fbb-a6f214b97d.zip/node_modules/resolve/",\

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -31,7 +31,8 @@ RUN mkdir -p \
/opt/bundled/auth \
/opt/bundled/files \
/opt/bundled/revisions \
/opt/bundled/api-gateway
/opt/bundled/api-gateway \
/opt/shared/uploads
RUN yarn workspace @standardnotes/syncing-server bundle --no-compress --output-directory /opt/bundled/syncing-server
RUN yarn workspace @standardnotes/auth-server bundle --no-compress --output-directory /opt/bundled/auth

View File

@@ -19,12 +19,10 @@ services:
restart: unless-stopped
environment:
- SERVICES=sns,sqs
- DOCKER_HOST=unix:///var/run/docker.sock
- HOSTNAME_EXTERNAL=localstack
- LS_LOG=warn
volumes:
- ./docker/localstack_bootstrap.sh:/etc/localstack/init/ready.d/localstack_bootstrap.sh
- /var/run/docker.sock:/var/run/docker.sock
networks:
- standardnotes_self_hosted

View File

@@ -1,13 +1,14 @@
services:
server:
image: standardnotes/server
env_file: .env.sample
env_file: .env
container_name: server_self_hosted
ports:
- 3000:3000
- 3125:3104
volumes:
- ./logs:/var/lib/server/logs
- ./uploads:/opt/bundled/files/packages/files/dist/uploads
networks:
- standardnotes_self_hosted
@@ -19,12 +20,10 @@ services:
restart: unless-stopped
environment:
- SERVICES=sns,sqs
- DOCKER_HOST=unix:///var/run/docker.sock
- HOSTNAME_EXTERNAL=localstack
- LS_LOG=warn
volumes:
- ./docker/localstack_bootstrap.sh:/etc/localstack/init/ready.d/localstack_bootstrap.sh
- /var/run/docker.sock:/var/run/docker.sock
- ./localstack_bootstrap.sh:/etc/localstack/init/ready.d/localstack_bootstrap.sh
networks:
- standardnotes_self_hosted

View File

@@ -44,9 +44,7 @@ fi
if [ -z "$DB_DEBUG_LEVEL" ]; then
export DB_DEBUG_LEVEL="all"
fi
if [ -z "$DB_MIGRATIONS_PATH" ]; then
export DB_MIGRATIONS_PATH="dist/migrations/*.js"
fi
export DB_MIGRATIONS_PATH="dist/migrations/*.js"
#########
# CACHE #
@@ -235,9 +233,7 @@ export SYNCING_SERVER_NEW_RELIC_ENABLED=false
export SYNCING_SERVER_NEW_RELIC_APP_NAME="Syncing Server JS"
export SYNCING_SERVER_NEW_RELIC_NO_CONFIG_FILE=true
if [ -z "$SYNCING_SERVER_FILE_UPLOAD_PATH" ]; then
export SYNCING_SERVER_FILE_UPLOAD_PATH="data/uploads"
fi
export SYNCING_SERVER_FILE_UPLOAD_PATH="/opt/shared/uploads"
printenv | grep SYNCING_SERVER_ | sed 's/SYNCING_SERVER_//g' > /opt/bundled/syncing-server/packages/syncing-server/.env
@@ -356,10 +352,9 @@ export API_GATEWAY_AUTH_SERVER_URL=http://localhost:$AUTH_SERVER_PORT
export API_GATEWAY_WORKSPACE_SERVER_URL=http://localhost:3004
export API_GATEWAY_REVISIONS_SERVER_URL=http://localhost:3005
if [ -z "$PUBLIC_FILES_SERVER_URL" ]; then
export API_GATEWAY_FILES_SERVER_URL=http://localhost:$FILES_SERVER_PORT
else
export API_GATEWAY_FILES_SERVER_URL=$PUBLIC_FILES_SERVER_URL
export PUBLIC_FILES_SERVER_URL=http://localhost:3125
fi
export API_GATEWAY_FILES_SERVER_URL=$PUBLIC_FILES_SERVER_URL
printenv | grep API_GATEWAY_ | sed 's/API_GATEWAY_//g' > /opt/bundled/api-gateway/packages/api-gateway/.env

View File

@@ -3,6 +3,14 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [2.20.3](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.20.2...@standardnotes/analytics@2.20.3) (2023-02-21)
**Note:** Version bump only for package @standardnotes/analytics
## [2.20.2](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.20.1...@standardnotes/analytics@2.20.2) (2023-02-20)
**Note:** Version bump only for package @standardnotes/analytics
## [2.20.1](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.20.0...@standardnotes/analytics@2.20.1) (2023-02-15)
**Note:** Version bump only for package @standardnotes/analytics

View File

@@ -1,6 +1,6 @@
{
"name": "@standardnotes/analytics",
"version": "2.20.1",
"version": "2.20.3",
"engines": {
"node": ">=18.0.0 <19.0.0"
},

View File

@@ -3,6 +3,24 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
# [1.49.0](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.48.3...@standardnotes/api-gateway@1.49.0) (2023-02-22)
### Bug Fixes
* **api-gateway:** proxy endpoint for request passing ([bc9182f](https://github.com/standardnotes/api-gateway/commit/bc9182f214c5386c5f1dd0bcbafbce34d413b6e8))
### Features
* **proxy:** add proxy server ([dfe30d7](https://github.com/standardnotes/api-gateway/commit/dfe30d7f5e8598ec1886db0e061b7d593cc27e29))
## [1.48.3](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.48.2...@standardnotes/api-gateway@1.48.3) (2023-02-21)
**Note:** Version bump only for package @standardnotes/api-gateway
## [1.48.2](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.48.1...@standardnotes/api-gateway@1.48.2) (2023-02-20)
**Note:** Version bump only for package @standardnotes/api-gateway
## [1.48.1](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.48.0...@standardnotes/api-gateway@1.48.1) (2023-02-15)
**Note:** Version bump only for package @standardnotes/api-gateway

View File

@@ -22,6 +22,7 @@ import '../src/Controller/v1/SubscriptionInvitesController'
import '../src/Controller/v1/WorkspacesController'
import '../src/Controller/v1/InvitesController'
import '../src/Controller/v1/AuthenticatorsController'
import '../src/Controller/v1/ProxyController'
import '../src/Controller/v2/PaymentsControllerV2'
import '../src/Controller/v2/ActionsControllerV2'

View File

@@ -1,6 +1,6 @@
{
"name": "@standardnotes/api-gateway",
"version": "1.48.1",
"version": "1.49.0",
"engines": {
"node": ">=18.0.0 <19.0.0"
},

View File

@@ -61,6 +61,7 @@ export class ContainerConfigLoader {
container.bind(TYPES.AUTH_JWT_SECRET).toConstantValue(env.get('AUTH_JWT_SECRET'))
container.bind(TYPES.WORKSPACE_SERVER_URL).toConstantValue(env.get('WORKSPACE_SERVER_URL', true))
container.bind(TYPES.WEB_SOCKET_SERVER_URL).toConstantValue(env.get('WEB_SOCKET_SERVER_URL', true))
container.bind(TYPES.PROXY_SERVER_URL).toConstantValue(env.get('PROXY_SERVER_URL', true))
container
.bind(TYPES.HTTP_CALL_TIMEOUT)
.toConstantValue(env.get('HTTP_CALL_TIMEOUT', true) ? +env.get('HTTP_CALL_TIMEOUT', true) : 60_000)

View File

@@ -11,6 +11,7 @@ const TYPES = {
EMAIL_SERVER_URL: Symbol.for('EMAIL_SERVER_URL'),
WORKSPACE_SERVER_URL: Symbol.for('WORKSPACE_SERVER_URL'),
WEB_SOCKET_SERVER_URL: Symbol.for('WEB_SOCKET_SERVER_URL'),
PROXY_SERVER_URL: Symbol.for('PROXY_SERVER_URL'),
AUTH_JWT_SECRET: Symbol.for('AUTH_JWT_SECRET'),
HTTP_CALL_TIMEOUT: Symbol.for('HTTP_CALL_TIMEOUT'),
VERSION: Symbol.for('VERSION'),

View File

@@ -0,0 +1,18 @@
import { Request, Response } from 'express'
import { inject } from 'inversify'
import { all, BaseHttpController, controller } from 'inversify-express-utils'
import TYPES from '../../Bootstrap/Types'
import { HttpServiceInterface } from '../../Service/Http/HttpServiceInterface'
@controller('/v1/proxy')
export class ProxyController extends BaseHttpController {
constructor(@inject(TYPES.HTTPService) private httpService: HttpServiceInterface) {
super()
}
@all('*', TYPES.AuthMiddleware)
async createToken(request: Request, response: Response): Promise<void> {
await this.httpService.callProxyServer(request, response, request.path.replace('/v1/proxy', ''), request.body)
}
}

View File

@@ -20,6 +20,7 @@ export class HttpService implements HttpServiceInterface {
@inject(TYPES.WEB_SOCKET_SERVER_URL) private webSocketServerUrl: string,
@inject(TYPES.REVISIONS_SERVER_URL) private revisionsServerUrl: string,
@inject(TYPES.EMAIL_SERVER_URL) private emailServerUrl: string,
@inject(TYPES.PROXY_SERVER_URL) private proxyServerUrl: string,
@inject(TYPES.HTTP_CALL_TIMEOUT) private httpCallTimeout: number,
@inject(TYPES.CrossServiceTokenCache) private crossServiceTokenCache: CrossServiceTokenCacheInterface,
@inject(TYPES.Logger) private logger: Logger,
@@ -111,6 +112,21 @@ export class HttpService implements HttpServiceInterface {
await this.callServer(this.webSocketServerUrl, request, response, endpoint, payload)
}
async callProxyServer(
request: Request,
response: Response,
endpoint: string,
payload?: Record<string, unknown> | string,
): Promise<void> {
if (!this.proxyServerUrl) {
this.logger.debug('Proxy Server URL not defined. Skipped request to Proxy.')
return
}
await this.callServer(this.proxyServerUrl, request, response, endpoint, payload)
}
async callPaymentsServer(
request: Request,
response: Response,

View File

@@ -55,4 +55,10 @@ export interface HttpServiceInterface {
endpoint: string,
payload?: Record<string, unknown> | string,
): Promise<void>
callProxyServer(
request: Request,
response: Response,
endpoint: string,
payload?: Record<string, unknown> | string,
): Promise<void>
}

View File

@@ -3,6 +3,14 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.88.3](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.88.2...@standardnotes/auth-server@1.88.3) (2023-02-21)
**Note:** Version bump only for package @standardnotes/auth-server
## [1.88.2](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.88.1...@standardnotes/auth-server@1.88.2) (2023-02-20)
**Note:** Version bump only for package @standardnotes/auth-server
## [1.88.1](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.88.0...@standardnotes/auth-server@1.88.1) (2023-02-15)
**Note:** Version bump only for package @standardnotes/auth-server

View File

@@ -1,74 +0,0 @@
import 'reflect-metadata'
import 'newrelic'
import { Logger } from 'winston'
import * as dayjs from 'dayjs'
import * as utc from 'dayjs/plugin/utc'
import { ContainerConfigLoader } from '../src/Bootstrap/Container'
import TYPES from '../src/Bootstrap/Types'
import { Env } from '../src/Bootstrap/Env'
import { DomainEventPublisherInterface } from '@standardnotes/domain-events'
import { DomainEventFactoryInterface } from '../src/Domain/Event/DomainEventFactoryInterface'
import { UserRepositoryInterface } from '../src/Domain/User/UserRepositoryInterface'
import { Stream } from 'stream'
const requestRecalculation = async (
userRepository: UserRepositoryInterface,
domainEventFactory: DomainEventFactoryInterface,
domainEventPublisher: DomainEventPublisherInterface,
logger: Logger,
): Promise<void> => {
const stream = await userRepository.streamAll()
return new Promise((resolve, reject) => {
stream
.pipe(
new Stream.Transform({
objectMode: true,
transform: async (rawUserData, _encoding, callback) => {
try {
await domainEventPublisher.publish(
domainEventFactory.createUserContentSizeRecalculationRequestedEvent(rawUserData.user_uuid),
)
} catch (error) {
logger.error(`Could not process user ${rawUserData.user_uuid}: ${(error as Error).message}`)
}
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 content size recalculation requests ...')
const userRepository: UserRepositoryInterface = container.get(TYPES.UserRepository)
const domainEventFactory: DomainEventFactoryInterface = container.get(TYPES.DomainEventFactory)
const domainEventPublisher: DomainEventPublisherInterface = container.get(TYPES.DomainEventPublisher)
Promise.resolve(requestRecalculation(userRepository, domainEventFactory, domainEventPublisher, logger))
.then(() => {
logger.info('content size recalculation requesting complete')
process.exit(0)
})
.catch((error) => {
logger.error(`Could not finish content size recalculation requesting : ${error.message}`)
process.exit(1)
})
})

View File

@@ -55,11 +55,6 @@ case "$COMMAND" in
node docker/entrypoint-backup.js one_drive daily
;;
'content-recalculation' )
echo "[Docker] Starting Content Size Recalculation..."
node docker/entrypoint-content.js
;;
* )
echo "[Docker] Unknown command"
;;

View File

@@ -1,6 +1,6 @@
{
"name": "@standardnotes/auth-server",
"version": "1.88.1",
"version": "1.88.3",
"engines": {
"node": ">=18.0.0 <19.0.0"
},

View File

@@ -16,7 +16,6 @@ import {
DomainEventService,
WebSocketMessageRequestedEvent,
ExitDiscountApplyRequestedEvent,
UserContentSizeRecalculationRequestedEvent,
MuteEmailsSettingChangedEvent,
EmailRequestedEvent,
StatisticPersistenceRequestedEvent,
@@ -70,23 +69,6 @@ export class DomainEventFactory implements DomainEventFactoryInterface {
}
}
createUserContentSizeRecalculationRequestedEvent(userUuid: string): UserContentSizeRecalculationRequestedEvent {
return {
type: 'USER_CONTENT_SIZE_RECALCULATION_REQUESTED',
createdAt: this.timer.getUTCDate(),
meta: {
correlation: {
userIdentifier: userUuid,
userIdentifierType: 'uuid',
},
origin: DomainEventService.Auth,
},
payload: {
userUuid,
},
}
}
createExitDiscountApplyRequestedEvent(dto: {
userEmail: string
discountCode: string

View File

@@ -14,7 +14,6 @@ import {
PredicateVerifiedEvent,
WebSocketMessageRequestedEvent,
ExitDiscountApplyRequestedEvent,
UserContentSizeRecalculationRequestedEvent,
MuteEmailsSettingChangedEvent,
EmailRequestedEvent,
StatisticPersistenceRequestedEvent,
@@ -22,7 +21,6 @@ import {
import { InviteeIdentifierType } from '../SharedSubscription/InviteeIdentifierType'
export interface DomainEventFactoryInterface {
createUserContentSizeRecalculationRequestedEvent(userUuid: string): UserContentSizeRecalculationRequestedEvent
createWebSocketMessageRequestedEvent(dto: { userUuid: string; message: JSONString }): WebSocketMessageRequestedEvent
createEmailRequestedEvent(dto: {
userEmail: string

View File

@@ -3,6 +3,14 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.9.70](https://github.com/standardnotes/server/compare/@standardnotes/domain-events-infra@1.9.69...@standardnotes/domain-events-infra@1.9.70) (2023-02-21)
**Note:** Version bump only for package @standardnotes/domain-events-infra
## [1.9.69](https://github.com/standardnotes/server/compare/@standardnotes/domain-events-infra@1.9.68...@standardnotes/domain-events-infra@1.9.69) (2023-02-20)
**Note:** Version bump only for package @standardnotes/domain-events-infra
## [1.9.68](https://github.com/standardnotes/server/compare/@standardnotes/domain-events-infra@1.9.67...@standardnotes/domain-events-infra@1.9.68) (2023-01-30)
**Note:** Version bump only for package @standardnotes/domain-events-infra

View File

@@ -1,6 +1,6 @@
{
"name": "@standardnotes/domain-events-infra",
"version": "1.9.68",
"version": "1.9.70",
"engines": {
"node": ">=18.0.0 <19.0.0"
},

View File

@@ -3,6 +3,16 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [2.107.1](https://github.com/standardnotes/server/compare/@standardnotes/domain-events@2.107.0...@standardnotes/domain-events@2.107.1) (2023-02-21)
**Note:** Version bump only for package @standardnotes/domain-events
# [2.107.0](https://github.com/standardnotes/server/compare/@standardnotes/domain-events@2.106.2...@standardnotes/domain-events@2.107.0) (2023-02-20)
### Features
* **domain-events:** add email sent event ([190595f](https://github.com/standardnotes/server/commit/190595febf935f0f47818a2d9f7926a5f351a458))
## [2.106.2](https://github.com/standardnotes/server/compare/@standardnotes/domain-events@2.106.1...@standardnotes/domain-events@2.106.2) (2023-01-20)
### Reverts

View File

@@ -1,6 +1,6 @@
{
"name": "@standardnotes/domain-events",
"version": "2.106.2",
"version": "2.107.1",
"engines": {
"node": ">=18.0.0 <19.0.0"
},

View File

@@ -0,0 +1,7 @@
import { DomainEventInterface } from './DomainEventInterface'
import { EmailSentEventPayload } from './EmailSentEventPayload'
export interface EmailSentEvent extends DomainEventInterface {
type: 'EMAIL_SENT'
payload: EmailSentEventPayload
}

View File

@@ -0,0 +1,15 @@
export interface EmailSentEventPayload {
userEmail: string
messageIdentifier: string
level: string
subject: string
body: string
sender?: string
additionalStyles?: string
attachments?: Array<{
filePath: string
fileName: string
attachmentFileName: string
attachmentContentType: string
}>
}

View File

@@ -1,7 +0,0 @@
import { DomainEventInterface } from './DomainEventInterface'
import { RevisionsOwnershipUpdateRequestedEventPayload } from './RevisionsOwnershipUpdateRequestedEventPayload'
export interface RevisionsOwnershipUpdateRequestedEvent extends DomainEventInterface {
type: 'REVISIONS_OWNERSHIP_UPDATE_REQUESTED'
payload: RevisionsOwnershipUpdateRequestedEventPayload
}

View File

@@ -1,4 +0,0 @@
export interface RevisionsOwnershipUpdateRequestedEventPayload {
itemUuid: string
userUuid: string
}

View File

@@ -1,7 +0,0 @@
import { DomainEventInterface } from './DomainEventInterface'
import { UserContentSizeRecalculationRequestedEventPayload } from './UserContentSizeRecalculationRequestedEventPayload'
export interface UserContentSizeRecalculationRequestedEvent extends DomainEventInterface {
type: 'USER_CONTENT_SIZE_RECALCULATION_REQUESTED'
payload: UserContentSizeRecalculationRequestedEventPayload
}

View File

@@ -1,3 +0,0 @@
export interface UserContentSizeRecalculationRequestedEventPayload {
userUuid: string
}

View File

@@ -14,6 +14,8 @@ export * from './Event/EmailBackupRequestedEvent'
export * from './Event/EmailBackupRequestedEventPayload'
export * from './Event/EmailRequestedEvent'
export * from './Event/EmailRequestedEventPayload'
export * from './Event/EmailSentEvent'
export * from './Event/EmailSentEventPayload'
export * from './Event/EmailSubscriptionUnsubscribedEvent'
export * from './Event/EmailSubscriptionUnsubscribedEventPayload'
export * from './Event/ExitDiscountAppliedEvent'
@@ -52,8 +54,6 @@ export * from './Event/RefundProcessedEvent'
export * from './Event/RefundProcessedEventPayload'
export * from './Event/RevisionsCopyRequestedEvent'
export * from './Event/RevisionsCopyRequestedEventPayload'
export * from './Event/RevisionsOwnershipUpdateRequestedEvent'
export * from './Event/RevisionsOwnershipUpdateRequestedEventPayload'
export * from './Event/SharedSubscriptionInvitationCanceledEvent'
export * from './Event/SharedSubscriptionInvitationCanceledEventPayload'
export * from './Event/SharedSubscriptionInvitationCreatedEvent'
@@ -78,8 +78,6 @@ export * from './Event/SubscriptionRevertRequestedEvent'
export * from './Event/SubscriptionRevertRequestedEventPayload'
export * from './Event/SubscriptionSyncRequestedEvent'
export * from './Event/SubscriptionSyncRequestedEventPayload'
export * from './Event/UserContentSizeRecalculationRequestedEvent'
export * from './Event/UserContentSizeRecalculationRequestedEventPayload'
export * from './Event/UserDisabledSessionUserAgentLoggingEvent'
export * from './Event/UserDisabledSessionUserAgentLoggingEventPayload'
export * from './Event/UserEmailChangedEvent'

View File

@@ -3,6 +3,16 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.7.2](https://github.com/standardnotes/server/compare/@standardnotes/event-store@1.7.1...@standardnotes/event-store@1.7.2) (2023-02-21)
**Note:** Version bump only for package @standardnotes/event-store
## [1.7.1](https://github.com/standardnotes/server/compare/@standardnotes/event-store@1.7.0...@standardnotes/event-store@1.7.1) (2023-02-20)
### Bug Fixes
* **event-store:** add handling of email sent events ([d023a27](https://github.com/standardnotes/server/commit/d023a2737772e01eca8dc2c848ddebe43bb58734))
# [1.7.0](https://github.com/standardnotes/server/compare/@standardnotes/event-store@1.6.68...@standardnotes/event-store@1.7.0) (2023-02-15)
### Features

View File

@@ -1,6 +1,6 @@
{
"name": "@standardnotes/event-store",
"version": "1.7.0",
"version": "1.7.2",
"description": "Event Store Service",
"private": true,
"main": "dist/src/index.js",

View File

@@ -81,6 +81,7 @@ export class ContainerConfigLoader {
['LISTED_ACCOUNT_CREATED', container.get(TYPES.EventHandler)],
['LISTED_ACCOUNT_DELETED', container.get(TYPES.EventHandler)],
['EMAIL_REQUESTED', container.get(TYPES.EventHandler)],
['EMAIL_SENT', container.get(TYPES.EventHandler)],
['SHARED_SUBSCRIPTION_INVITATION_CREATED', container.get(TYPES.EventHandler)],
['EMAIL_BACKUP_REQUESTED', container.get(TYPES.EventHandler)],
['PAYMENT_FAILED', container.get(TYPES.EventHandler)],

View File

@@ -3,6 +3,14 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.10.3](https://github.com/standardnotes/files/compare/@standardnotes/files-server@1.10.2...@standardnotes/files-server@1.10.3) (2023-02-21)
**Note:** Version bump only for package @standardnotes/files-server
## [1.10.2](https://github.com/standardnotes/files/compare/@standardnotes/files-server@1.10.1...@standardnotes/files-server@1.10.2) (2023-02-20)
**Note:** Version bump only for package @standardnotes/files-server
## [1.10.1](https://github.com/standardnotes/files/compare/@standardnotes/files-server@1.10.0...@standardnotes/files-server@1.10.1) (2023-02-15)
**Note:** Version bump only for package @standardnotes/files-server

View File

@@ -1,6 +1,6 @@
{
"name": "@standardnotes/files-server",
"version": "1.10.1",
"version": "1.10.3",
"engines": {
"node": ">=18.0.0 <19.0.0"
},

View File

@@ -0,0 +1 @@
dist

6
packages/proxy/.eslintrc Normal file
View File

@@ -0,0 +1,6 @@
{
"extends": "../../.eslintrc",
"parserOptions": {
"project": "./linter.tsconfig.json"
}
}

View File

@@ -0,0 +1,26 @@
# Change Log
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.1.3](https://github.com/standardnotes/server/compare/@standardnotes/proxy-server@1.1.2...@standardnotes/proxy-server@1.1.3) (2023-02-22)
**Note:** Version bump only for package @standardnotes/proxy-server
## [1.1.2](https://github.com/standardnotes/server/compare/@standardnotes/proxy-server@1.1.1...@standardnotes/proxy-server@1.1.2) (2023-02-22)
**Note:** Version bump only for package @standardnotes/proxy-server
## [1.1.1](https://github.com/standardnotes/server/compare/@standardnotes/proxy-server@1.1.0...@standardnotes/proxy-server@1.1.1) (2023-02-22)
**Note:** Version bump only for package @standardnotes/proxy-server
# 1.1.0 (2023-02-22)
### Bug Fixes
* **proxy:** prevent from passing auth tokens to proxy destination ([91c70a5](https://github.com/standardnotes/server/commit/91c70a51a067c606afc3570764367a6d60910ce3))
### Features
* **proxy:** add proxy server ([dfe30d7](https://github.com/standardnotes/server/commit/dfe30d7f5e8598ec1886db0e061b7d593cc27e29))

17
packages/proxy/Dockerfile Normal file
View File

@@ -0,0 +1,17 @@
FROM node:18.13.0-alpine
RUN apk add --update \
curl \
&& rm -rf /var/cache/apk/*
ENV NODE_ENV production
RUN corepack enable
COPY ./ /workspace
WORKDIR /workspace/packages/proxy
ENTRYPOINT [ "/workspace/packages/proxy/docker/entrypoint.sh" ]
CMD [ "start-web" ]

View File

@@ -0,0 +1,93 @@
import * as http from 'http'
import * as httpProxy from 'http-proxy'
import * as path from 'path'
const proxy = httpProxy.createProxyServer({
secure: true,
})
proxy.on('error', (error, req, res) => {
console.error(error.message)
;(res as http.ServerResponse).writeHead(500, {
'Content-Type': 'text/plain',
})
res.end(`Proxying failed for URL: ${req.url} Error: ${error.message}`)
})
// 10 MB in bytes
const MAX_IMAGE_SIZE = 10 * 1024 * 1024
proxy.on('proxyRes', (proxyRes, _req, res) => {
const contentLength = parseInt(proxyRes.headers['content-length'] as string)
if (contentLength > MAX_IMAGE_SIZE) {
res.writeHead(413, { 'Content-Type': 'text/plain' })
res.end(`Image size exceeds the limit of ${MAX_IMAGE_SIZE} bytes.`)
return
}
// validate response content type to be image
const contentType = proxyRes.headers['content-type'] as string
if (!contentType.startsWith('image/')) {
res.writeHead(400, { 'Content-Type': 'text/plain' })
res.end(`Invalid content type: ${contentType}`)
return
}
})
http
.createServer((req, res) => {
res.setHeader('Access-Control-Allow-Origin', '*')
res.setHeader('Access-Control-Request-Method', '*')
res.setHeader('Access-Control-Allow-Methods', 'OPTIONS, GET')
res.setHeader('Access-Control-Allow-Headers', '*')
if (req.method === 'OPTIONS') {
res.writeHead(200)
res.end()
return
}
if (req.url === '/healthcheck') {
res.writeHead(200)
res.end()
return
}
delete req.headers.authorization
delete req.headers['x-auth-token']
delete req.headers['x-auth-offline-token']
/** Remove / or // prefixes */
const target = (req.url as string).replace(/^\/+/, '')
try {
const url = new URL(target)
if (url.protocol !== 'http:' && url.protocol !== 'https:') {
throw new Error('Invalid URL protocol')
}
if (url.hostname === '') {
throw new Error('Invalid URL hostname')
}
const ext = path.extname(url.pathname)
if (!['.jpg', '.jpeg', '.png', '.gif'].includes(ext)) {
res.writeHead(400)
res.end('Only image files can be proxied')
return
}
req.url = url.href
proxy.web(req, res, {
target: target,
ignorePath: false,
prependPath: false,
toProxy: true,
})
} catch (error) {
res.writeHead(500)
res.end(`Invalid URL: ${target}`)
}
})
.listen(3000)

View File

@@ -4,7 +4,7 @@ const path = require('path')
const pnp = require(path.normalize(path.resolve(__dirname, '../../..', '.pnp.cjs'))).setup()
const index = require(path.normalize(path.resolve(__dirname, '../dist/bin/content.js')))
const index = require(path.normalize(path.resolve(__dirname, '../dist/bin/server.js')))
Object.defineProperty(exports, '__esModule', { value: true })

View File

@@ -0,0 +1,17 @@
#!/bin/sh
set -e
COMMAND=$1 && shift 1
case "$COMMAND" in
'start-web' )
echo "[Docker] Starting Web..."
node docker/entrypoint-server.js
;;
* )
echo "Unknown command"
;;
esac
exec "$@"

View File

@@ -0,0 +1,4 @@
{
"extends": "./tsconfig.json",
"exclude": ["dist"]
}

View File

@@ -0,0 +1,33 @@
{
"name": "@standardnotes/proxy-server",
"version": "1.1.3",
"engines": {
"node": ">=18.0.0 <19.0.0"
},
"private": true,
"description": "Proxy Server",
"main": "dist/src/index.js",
"typings": "dist/src/index.d.ts",
"repository": "git@github.com:standardnotes/server.git",
"author": "Karol Sójko <karolsojko@standardnotes.com>",
"license": "AGPL-3.0-or-later",
"scripts": {
"clean": "rm -fr dist",
"build": "tsc --build",
"lint": "eslint . --ext .ts",
"lint:fix": "eslint . --ext .ts --fix",
"start": "yarn node dist/bin/server.js"
},
"dependencies": {
"@types/http-proxy": "^1.17.9",
"http-proxy": "^1.18.1",
"newrelic": "^9.8.0"
},
"devDependencies": {
"@types/newrelic": "^9.4.0",
"@typescript-eslint/eslint-plugin": "^5.48.2",
"eslint": "^8.32.0",
"eslint-plugin-prettier": "^4.0.0",
"typescript": "^4.8.4"
}
}

View File

@@ -0,0 +1,11 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"composite": true,
"outDir": "./dist",
},
"include": [
"bin/**/*",
],
"references": []
}

View File

@@ -3,6 +3,20 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.12.4](https://github.com/standardnotes/server/compare/@standardnotes/revisions-server@1.12.3...@standardnotes/revisions-server@1.12.4) (2023-02-21)
**Note:** Version bump only for package @standardnotes/revisions-server
## [1.12.3](https://github.com/standardnotes/server/compare/@standardnotes/revisions-server@1.12.2...@standardnotes/revisions-server@1.12.3) (2023-02-20)
**Note:** Version bump only for package @standardnotes/revisions-server
## [1.12.2](https://github.com/standardnotes/server/compare/@standardnotes/revisions-server@1.12.1...@standardnotes/revisions-server@1.12.2) (2023-02-17)
### Bug Fixes
* **revisions:** initial migration to check if user_uuid exists on table ([85d0c12](https://github.com/standardnotes/server/commit/85d0c12dadffe3ed7b8c0717725813e168e20b6c))
## [1.12.1](https://github.com/standardnotes/server/compare/@standardnotes/revisions-server@1.12.0...@standardnotes/revisions-server@1.12.1) (2023-02-15)
**Note:** Version bump only for package @standardnotes/revisions-server

View File

@@ -28,6 +28,14 @@ export class init1669113322388 implements MigrationInterface {
return
}
const revisionsTableHasUserUuidColumnQueryResult = await queryRunner.manager.query(
'SELECT COUNT(*) as count FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name = "revisions" AND column_name = "user_uuid"',
)
const revisionsTableHasUserUuidColumn = revisionsTableHasUserUuidColumnQueryResult[0].count === 1
if (revisionsTableHasUserUuidColumn) {
return
}
await queryRunner.query('ALTER TABLE `revisions` ADD COLUMN `user_uuid` varchar(36) NULL')
}
}

View File

@@ -1,6 +1,6 @@
{
"name": "@standardnotes/revisions-server",
"version": "1.12.1",
"version": "1.12.4",
"engines": {
"node": ">=18.0.0 <19.0.0"
},

View File

@@ -36,7 +36,6 @@ const TYPES = {
ItemDumpedEventHandler: Symbol.for('ItemDumpedEventHandler'),
AccountDeletionRequestedEventHandler: Symbol.for('AccountDeletionRequestedEventHandler'),
RevisionsCopyRequestedEventHandler: Symbol.for('RevisionsCopyRequestedEventHandler'),
RevisionsOwnershipUpdateRequestedEventHandler: Symbol.for('RevisionsOwnershipUpdateRequestedEventHandler'),
// Services
CrossServiceTokenDecoder: Symbol.for('CrossServiceTokenDecoder'),
DomainEventSubscriberFactory: Symbol.for('DomainEventSubscriberFactory'),

View File

@@ -23,7 +23,6 @@ import { FSDumpRepository } from '../Infra/FS/FSDumpRepository'
import { AccountDeletionRequestedEventHandler } from '../Domain/Handler/AccountDeletionRequestedEventHandler'
import { RevisionsCopyRequestedEventHandler } from '../Domain/Handler/RevisionsCopyRequestedEventHandler'
import { CopyRevisions } from '../Domain/UseCase/CopyRevisions/CopyRevisions'
import { RevisionsOwnershipUpdateRequestedEventHandler } from '../Domain/Handler/RevisionsOwnershipUpdateRequestedEventHandler'
import { CommonContainerConfigLoader } from './CommonContainerConfigLoader'
import { Env } from './Env'
@@ -120,11 +119,6 @@ export class WorkerContainerConfigLoader extends CommonContainerConfigLoader {
context.container.get(TYPES.Logger),
)
})
container
.bind<RevisionsOwnershipUpdateRequestedEventHandler>(TYPES.RevisionsOwnershipUpdateRequestedEventHandler)
.toDynamicValue((context: interfaces.Context) => {
return new RevisionsOwnershipUpdateRequestedEventHandler(context.container.get(TYPES.RevisionRepository))
})
container
.bind<DomainEventMessageHandlerInterface>(TYPES.DomainEventMessageHandler)
@@ -135,10 +129,6 @@ export class WorkerContainerConfigLoader extends CommonContainerConfigLoader {
['ITEM_DUMPED', context.container.get(TYPES.ItemDumpedEventHandler)],
['ACCOUNT_DELETION_REQUESTED', context.container.get(TYPES.AccountDeletionRequestedEventHandler)],
['REVISIONS_COPY_REQUESTED', context.container.get(TYPES.RevisionsCopyRequestedEventHandler)],
[
'REVISIONS_OWNERSHIP_UPDATE_REQUESTED',
context.container.get(TYPES.RevisionsOwnershipUpdateRequestedEventHandler),
],
])
const handler =

View File

@@ -1,25 +0,0 @@
/* istanbul ignore file */
import { Uuid } from '@standardnotes/domain-core'
import { DomainEventHandlerInterface, RevisionsOwnershipUpdateRequestedEvent } from '@standardnotes/domain-events'
import { RevisionRepositoryInterface } from '../Revision/RevisionRepositoryInterface'
export class RevisionsOwnershipUpdateRequestedEventHandler implements DomainEventHandlerInterface {
constructor(private revisionRepository: RevisionRepositoryInterface) {}
async handle(event: RevisionsOwnershipUpdateRequestedEvent): Promise<void> {
const userUuidOrError = Uuid.create(event.payload.userUuid)
if (userUuidOrError.isFailed()) {
return
}
const userUuid = userUuidOrError.getValue()
const itemUuidOrError = Uuid.create(event.payload.itemUuid)
if (itemUuidOrError.isFailed()) {
return
}
const itemUuid = itemUuidOrError.getValue()
await this.revisionRepository.updateUserUuid(itemUuid, userUuid)
}
}

View File

@@ -3,6 +3,14 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.17.3](https://github.com/standardnotes/server/compare/@standardnotes/scheduler-server@1.17.2...@standardnotes/scheduler-server@1.17.3) (2023-02-21)
**Note:** Version bump only for package @standardnotes/scheduler-server
## [1.17.2](https://github.com/standardnotes/server/compare/@standardnotes/scheduler-server@1.17.1...@standardnotes/scheduler-server@1.17.2) (2023-02-20)
**Note:** Version bump only for package @standardnotes/scheduler-server
## [1.17.1](https://github.com/standardnotes/server/compare/@standardnotes/scheduler-server@1.17.0...@standardnotes/scheduler-server@1.17.1) (2023-02-15)
**Note:** Version bump only for package @standardnotes/scheduler-server

View File

@@ -1,6 +1,6 @@
{
"name": "@standardnotes/scheduler-server",
"version": "1.17.1",
"version": "1.17.3",
"engines": {
"node": ">=18.0.0 <19.0.0"
},

View File

@@ -3,6 +3,26 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.31.5](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.31.4...@standardnotes/syncing-server@1.31.5) (2023-02-22)
### Bug Fixes
* **syncing-server:** numbering of the backup emails ([f7c2984](https://github.com/standardnotes/syncing-server-js/commit/f7c29848f1b1bc8a1f39a5b7f246c52f242ed60a))
## [1.31.4](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.31.3...@standardnotes/syncing-server@1.31.4) (2023-02-21)
### Bug Fixes
* **syncing-server:** creating email backup attachment files ([87b22ac](https://github.com/standardnotes/syncing-server-js/commit/87b22ac684732feaf3aef49496b25fbcda5bd888))
## [1.31.3](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.31.2...@standardnotes/syncing-server@1.31.3) (2023-02-21)
**Note:** Version bump only for package @standardnotes/syncing-server
## [1.31.2](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.31.1...@standardnotes/syncing-server@1.31.2) (2023-02-20)
**Note:** Version bump only for package @standardnotes/syncing-server
## [1.31.1](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.31.0...@standardnotes/syncing-server@1.31.1) (2023-02-15)
**Note:** Version bump only for package @standardnotes/syncing-server

View File

@@ -1,52 +0,0 @@
import 'reflect-metadata'
import 'newrelic'
import { Logger } from 'winston'
import TYPES from '../src/Bootstrap/Types'
import { Env } from '../src/Bootstrap/Env'
import { DomainEventFactoryInterface } from '../src/Domain/Event/DomainEventFactoryInterface'
import { DomainEventPublisherInterface } from '@standardnotes/domain-events'
import { WorkerContainerConfigLoader } from '../src/Bootstrap/WorkerContainerConfigLoader'
const inputArgs = process.argv.slice(2)
const userUuid = inputArgs[0]
const fixContentSize = async (
domainEventFactory: DomainEventFactoryInterface,
domainEventPublisher: DomainEventPublisherInterface,
): Promise<void> => {
await domainEventPublisher.publish(domainEventFactory.createUserContentSizeRecalculationRequestedEvent(userUuid))
}
const container = new WorkerContainerConfigLoader()
void container.load().then((container) => {
const env: Env = new Env()
env.load()
const logger: Logger = container.get(TYPES.Logger)
logger.info(`Starting content size fixing for user ${userUuid} ...`)
if (!userUuid) {
logger.error('No user uuid passed as argument. Skipped.')
process.exit(1)
}
const domainEventFactory: DomainEventFactoryInterface = container.get(TYPES.DomainEventFactory)
const domainEventPublisher: DomainEventPublisherInterface = container.get(TYPES.DomainEventPublisher)
Promise.resolve(fixContentSize(domainEventFactory, domainEventPublisher))
.then(() => {
logger.info('Content size fix complete.')
process.exit(0)
})
.catch((error) => {
logger.error(`Could not finish content size fix: ${error.message}`)
process.exit(1)
})
})

View File

@@ -1,11 +0,0 @@
'use strict'
const path = require('path')
const pnp = require(path.normalize(path.resolve(__dirname, '../../..', '.pnp.cjs'))).setup()
const index = require(path.normalize(path.resolve(__dirname, '../dist/bin/content.js')))
Object.defineProperty(exports, '__esModule', { value: true })
exports.default = index

View File

@@ -14,12 +14,6 @@ case "$COMMAND" in
node docker/entrypoint-worker.js
;;
'content-size-recalculate' )
echo "[Docker] Starting Content Size Recalculation..."
USER_UUID=$1 && shift 1
node docker/entrypoint-content.js $USER_UUID
;;
* )
echo "[Docker] Unknown command"
;;

View File

@@ -1,6 +1,6 @@
{
"name": "@standardnotes/syncing-server",
"version": "1.31.1",
"version": "1.31.5",
"engines": {
"node": ">=18.0.0 <19.0.0"
},

View File

@@ -6,7 +6,6 @@ import {
ItemDumpedEvent,
ItemRevisionCreationRequestedEvent,
RevisionsCopyRequestedEvent,
UserContentSizeRecalculationRequestedEvent,
} from '@standardnotes/domain-events'
import { TimerInterface } from '@standardnotes/time'
import { DomainEventFactoryInterface } from './DomainEventFactoryInterface'
@@ -69,23 +68,6 @@ export class DomainEventFactory implements DomainEventFactoryInterface {
}
}
createUserContentSizeRecalculationRequestedEvent(userUuid: string): UserContentSizeRecalculationRequestedEvent {
return {
type: 'USER_CONTENT_SIZE_RECALCULATION_REQUESTED',
createdAt: this.timer.getUTCDate(),
meta: {
correlation: {
userIdentifier: userUuid,
userIdentifierType: 'uuid',
},
origin: DomainEventService.SyncingServer,
},
payload: {
userUuid,
},
}
}
createDuplicateItemSyncedEvent(itemUuid: string, userUuid: string): DuplicateItemSyncedEvent {
return {
type: 'DUPLICATE_ITEM_SYNCED',

View File

@@ -4,11 +4,9 @@ import {
ItemDumpedEvent,
ItemRevisionCreationRequestedEvent,
RevisionsCopyRequestedEvent,
UserContentSizeRecalculationRequestedEvent,
} from '@standardnotes/domain-events'
export interface DomainEventFactoryInterface {
createUserContentSizeRecalculationRequestedEvent(userUuid: string): UserContentSizeRecalculationRequestedEvent
createEmailRequestedEvent(dto: {
userEmail: string
messageIdentifier: string

View File

@@ -53,7 +53,7 @@ describe('CloudBackupRequestedEventHandler', () => {
}
itemBackupService = {} as jest.Mocked<ItemBackupServiceInterface>
itemBackupService.backup = jest.fn().mockReturnValue('backup-file-name')
itemBackupService.backup = jest.fn().mockReturnValue(['backup-file-name'])
logger = {} as jest.Mocked<Logger>
logger.debug = jest.fn()
@@ -133,6 +133,14 @@ describe('CloudBackupRequestedEventHandler', () => {
expect(expectedError).not.toBeNull()
})
it('should not trigger cloud backup if backup filename is not returned', async () => {
itemBackupService.backup = jest.fn().mockReturnValue([])
await createHandler().handle(event)
expect(extensionsHttpService.triggerCloudBackupOnExtensionsServer).not.toHaveBeenCalled()
})
it('should trigger cloud backup on extensions server with muted emails', async () => {
event.payload.userHasEmailsMuted = true

View File

@@ -34,14 +34,19 @@ export class CloudBackupRequestedEventHandler implements DomainEventHandlerInter
return
}
const backupFilename = await this.itemBackupService.backup(items, authParams)
const backupFilenames = await this.itemBackupService.backup(items, authParams)
if (backupFilenames.length === 0) {
this.logger.warn(`No backup files created for user ${event.payload.userUuid}`)
return
}
this.logger.debug(`Sending ${items.length} items to extensions server for user ${event.payload.userUuid}`)
await this.extensionsHttpService.triggerCloudBackupOnExtensionsServer({
cloudProvider: event.payload.cloudProvider,
authParams,
backupFilename,
backupFilename: backupFilenames[0],
forceMute: event.payload.userHasEmailsMuted,
muteEmailsSettingUuid: event.payload.muteEmailsSettingUuid,
extensionsServerUrl: this.getExtensionsServerUrl(event),

View File

@@ -57,7 +57,7 @@ describe('EmailBackupRequestedEventHandler', () => {
}
itemBackupService = {} as jest.Mocked<ItemBackupServiceInterface>
itemBackupService.backup = jest.fn().mockReturnValue('backup-file-name')
itemBackupService.backup = jest.fn().mockReturnValue(['backup-file-name'])
domainEventPublisher = {} as jest.Mocked<DomainEventPublisherInterface>
domainEventPublisher.publish = jest.fn()
@@ -84,14 +84,14 @@ describe('EmailBackupRequestedEventHandler', () => {
it('should inform that multipart backup attachment for email was created', async () => {
itemBackupService.backup = jest
.fn()
.mockReturnValueOnce('backup-file-name-1')
.mockReturnValueOnce('backup-file-name-2')
.mockReturnValueOnce(['backup-file-name-1'])
.mockReturnValueOnce(['backup-file-name-2', 'backup-file-name-3'])
itemTransferCalculator.computeItemUuidBundlesToFetch = jest.fn().mockReturnValue([['1-2-3'], ['2-3-4']])
await createHandler().handle(event)
expect(domainEventPublisher.publish).toHaveBeenCalledTimes(2)
expect(domainEventFactory.createEmailRequestedEvent).toHaveBeenCalledTimes(2)
expect(domainEventPublisher.publish).toHaveBeenCalledTimes(3)
expect(domainEventFactory.createEmailRequestedEvent).toHaveBeenCalledTimes(3)
})
it('should not inform that backup attachment for email was created if user key params cannot be obtained', async () => {

View File

@@ -51,7 +51,7 @@ export class EmailBackupRequestedEventHandler implements DomainEventHandlerInter
this.emailAttachmentMaxByteSize,
)
let bundleIndex = 1
const backupFileNames: string[] = []
for (const itemUuidBundle of itemUuidBundles) {
const items = await this.itemRepository.findAll({
uuids: itemUuidBundle,
@@ -59,23 +59,25 @@ export class EmailBackupRequestedEventHandler implements DomainEventHandlerInter
sortOrder: 'ASC',
})
const backupFileName = await this.itemBackupService.backup(items, authParams)
const bundleBackupFileNames = await this.itemBackupService.backup(
items,
authParams,
this.emailAttachmentMaxByteSize,
)
this.logger.debug(`Data backed up into: ${backupFileName}`)
backupFileNames.push(...bundleBackupFileNames)
}
if (backupFileName.length === 0) {
this.logger.error(`Could not create a backup file for user ${event.payload.userUuid}`)
return
}
const dateOnly = new Date().toISOString().substring(0, 10)
const dateOnly = new Date().toISOString().substring(0, 10)
let bundleIndex = 1
for (const backupFileName of backupFileNames) {
await this.domainEventPublisher.publish(
this.domainEventFactory.createEmailRequestedEvent({
body: getBody(authParams.identifier as string),
level: EmailLevel.LEVELS.System,
messageIdentifier: 'DATA_BACKUP',
subject: getSubject(bundleIndex++, itemUuidBundles.length, dateOnly),
subject: getSubject(bundleIndex++, backupFileNames.length, dateOnly),
userEmail: authParams.identifier as string,
sender: 'backups@standardnotes.org',
attachments: [

View File

@@ -2,6 +2,6 @@ import { KeyParamsData } from '@standardnotes/responses'
import { Item } from './Item'
export interface ItemBackupServiceInterface {
backup(items: Array<Item>, authParams: KeyParamsData): Promise<string>
backup(items: Array<Item>, authParams: KeyParamsData, contentSizeLimit?: number): Promise<string[]>
dump(item: Item): Promise<string>
}

View File

@@ -16,7 +16,7 @@ export class FSItemBackupService implements ItemBackupServiceInterface {
private logger: Logger,
) {}
async backup(_items: Item[], _authParams: KeyParamsData): Promise<string> {
async backup(_items: Item[], _authParams: KeyParamsData, _contentSizeLimit?: number): Promise<string[]> {
throw new Error('Method not implemented.')
}

View File

@@ -37,21 +37,52 @@ export class S3ItemBackupService implements ItemBackupServiceInterface {
return s3Key
}
async backup(items: Item[], authParams: KeyParamsData): Promise<string> {
async backup(items: Item[], authParams: KeyParamsData, contentSizeLimit?: number): Promise<string[]> {
if (!this.s3BackupBucketName || this.s3Client === undefined) {
this.logger.warn('S3 backup not configured')
return ''
return []
}
const fileNames = []
let itemProjections: Array<ItemProjection> = []
let contentSizeCounter = 0
for (const item of items) {
const itemProjection = await this.itemProjector.projectFull(item)
if (contentSizeLimit === undefined) {
itemProjections.push(itemProjection)
continue
}
const itemContentSize = Buffer.byteLength(JSON.stringify(itemProjection))
if (contentSizeCounter + itemContentSize <= contentSizeLimit) {
itemProjections.push(itemProjection)
contentSizeCounter += itemContentSize
} else {
const backupFileName = await this.createBackupFile(itemProjections, authParams)
fileNames.push(backupFileName)
itemProjections = [itemProjection]
contentSizeCounter = itemContentSize
}
}
if (itemProjections.length > 0) {
const backupFileName = await this.createBackupFile(itemProjections, authParams)
fileNames.push(backupFileName)
}
return fileNames
}
private async createBackupFile(itemProjections: ItemProjection[], authParams: KeyParamsData): Promise<string> {
const fileName = uuid.v4()
const itemProjections = []
for (const item of items) {
itemProjections.push(await this.itemProjector.projectFull(item))
}
await this.s3Client.send(
await (this.s3Client as S3Client).send(
new PutObjectCommand({
Bucket: this.s3BackupBucketName,
Key: fileName,

View File

@@ -3,6 +3,14 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.6.3](https://github.com/standardnotes/server/compare/@standardnotes/websockets-server@1.6.2...@standardnotes/websockets-server@1.6.3) (2023-02-21)
**Note:** Version bump only for package @standardnotes/websockets-server
## [1.6.2](https://github.com/standardnotes/server/compare/@standardnotes/websockets-server@1.6.1...@standardnotes/websockets-server@1.6.2) (2023-02-20)
**Note:** Version bump only for package @standardnotes/websockets-server
## [1.6.1](https://github.com/standardnotes/server/compare/@standardnotes/websockets-server@1.6.0...@standardnotes/websockets-server@1.6.1) (2023-02-15)
**Note:** Version bump only for package @standardnotes/websockets-server

View File

@@ -1,6 +1,6 @@
{
"name": "@standardnotes/websockets-server",
"version": "1.6.1",
"version": "1.6.3",
"engines": {
"node": ">=18.0.0 <19.0.0"
},

View File

@@ -3,6 +3,14 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.20.3](https://github.com/standardnotes/server/compare/@standardnotes/workspace-server@1.20.2...@standardnotes/workspace-server@1.20.3) (2023-02-21)
**Note:** Version bump only for package @standardnotes/workspace-server
## [1.20.2](https://github.com/standardnotes/server/compare/@standardnotes/workspace-server@1.20.1...@standardnotes/workspace-server@1.20.2) (2023-02-20)
**Note:** Version bump only for package @standardnotes/workspace-server
## [1.20.1](https://github.com/standardnotes/server/compare/@standardnotes/workspace-server@1.20.0...@standardnotes/workspace-server@1.20.1) (2023-02-15)
**Note:** Version bump only for package @standardnotes/workspace-server

View File

@@ -1,6 +1,6 @@
{
"name": "@standardnotes/workspace-server",
"version": "1.20.1",
"version": "1.20.3",
"engines": {
"node": ">=18.0.0 <19.0.0"
},

View File

@@ -53,6 +53,9 @@
{
"path": "./packages/predicates"
},
{
"path": "./packages/proxy"
},
{
"path": "./packages/revisions"
},

View File

@@ -3559,6 +3559,21 @@ __metadata:
languageName: unknown
linkType: soft
"@standardnotes/proxy-server@workspace:packages/proxy":
version: 0.0.0-use.local
resolution: "@standardnotes/proxy-server@workspace:packages/proxy"
dependencies:
"@types/http-proxy": "npm:^1.17.9"
"@types/newrelic": "npm:^9.4.0"
"@typescript-eslint/eslint-plugin": "npm:^5.48.2"
eslint: "npm:^8.32.0"
eslint-plugin-prettier: "npm:^4.0.0"
http-proxy: "npm:^1.18.1"
newrelic: "npm:^9.8.0"
typescript: "npm:^4.8.4"
languageName: unknown
linkType: soft
"@standardnotes/responses@npm:1.13.6":
version: 1.13.6
resolution: "@standardnotes/responses@npm:1.13.6"
@@ -4124,6 +4139,15 @@ __metadata:
languageName: node
linkType: hard
"@types/http-proxy@npm:^1.17.9":
version: 1.17.9
resolution: "@types/http-proxy@npm:1.17.9"
dependencies:
"@types/node": "npm:*"
checksum: 3ee577db823f0beb7d0a7eb8b21b0d488b43afb008161d7f4f714c5c53bea2d648b1ed5123c7f58136bc3881f4d2dfc31b5bc0b047c6b7cdb17865bc0b831499
languageName: node
linkType: hard
"@types/inversify-express-utils@npm:^2.0.0":
version: 2.0.0
resolution: "@types/inversify-express-utils@npm:2.0.0"
@@ -6671,7 +6695,7 @@ __metadata:
languageName: node
linkType: hard
"eventemitter3@npm:^4.0.4":
"eventemitter3@npm:^4.0.0, eventemitter3@npm:^4.0.4":
version: 4.0.7
resolution: "eventemitter3@npm:4.0.7"
checksum: e6ecb1ac2fee59b0ba0e778564cec0a1fe0631f28a50f24aa0e7ba367e718c5f9b23156fb2c1d238bcebe7923dfff37a63c39b519121a47c7bf78c38c96febd8
@@ -6972,7 +6996,7 @@ __metadata:
languageName: node
linkType: hard
"follow-redirects@npm:^1.15.0":
"follow-redirects@npm:^1.0.0, follow-redirects@npm:^1.15.0":
version: 1.15.2
resolution: "follow-redirects@npm:1.15.2"
peerDependenciesMeta:
@@ -7507,6 +7531,17 @@ __metadata:
languageName: node
linkType: hard
"http-proxy@npm:^1.18.1":
version: 1.18.1
resolution: "http-proxy@npm:1.18.1"
dependencies:
eventemitter3: "npm:^4.0.0"
follow-redirects: "npm:^1.0.0"
requires-port: "npm:^1.0.0"
checksum: 5d681e4231e3de09359e6fb14c2cc3fb79536b4b465cb0c2af4616e6754af0a6f1e33baccd83038f39a377dbb1e0b16b02c3a41458685e1754e3611b6dd10d64
languageName: node
linkType: hard
"http-status-codes@npm:^2.1.4":
version: 2.2.0
resolution: "http-status-codes@npm:2.2.0"
@@ -10757,6 +10792,13 @@ __metadata:
languageName: node
linkType: hard
"requires-port@npm:^1.0.0":
version: 1.0.0
resolution: "requires-port@npm:1.0.0"
checksum: 28a1064f043588514802bff52dacac500c43b642383109145c55ff8bac26b3cf1ca951abc824446c773309c45dd049608986c1e15142ae7e336b9926065a1830
languageName: node
linkType: hard
"resolve-alpn@npm:^1.2.0":
version: 1.2.1
resolution: "resolve-alpn@npm:1.2.1"