Compare commits

..

24 Commits

Author SHA1 Message Date
standardci 2237e0f5df chore(release): publish new version
- @standardnotes/api-gateway@1.64.2
 - @standardnotes/auth-server@1.119.3
 - @standardnotes/files-server@1.18.3
 - @standardnotes/home-server@1.11.8
 - @standardnotes/revisions-server@1.23.2
 - @standardnotes/syncing-server@1.44.2
2023-06-22 10:05:28 +00:00
Karol Sójko 0df471585f fix(home-server): add debug logs about container initalizations 2023-06-22 11:50:59 +02:00
standardci 95aac1a7bf chore(release): publish new version
- @standardnotes/home-server@1.11.7
2023-06-22 08:23:45 +00:00
Karol Sójko c078bc958d fix(home-server): add default log level to overrides 2023-06-22 10:06:54 +02:00
Karol Sójko 49c27924ea fix(home-server): add log leve information to starting the home server information 2023-06-22 09:08:37 +02:00
standardci c9dd8e7338 chore(release): publish new version
- @standardnotes/home-server@1.11.6
2023-06-16 09:44:09 +00:00
Karol Sójko 5ef90cc75b fix(home-server): unref the server instance when stopping the home server 2023-06-16 11:30:04 +02:00
standardci 063c61d96c chore(release): publish new version
- @standardnotes/auth-server@1.119.2
 - @standardnotes/home-server@1.11.5
 - @standardnotes/revisions-server@1.23.1
 - @standardnotes/syncing-server@1.44.1
2023-06-14 06:19:56 +00:00
Karol Sójko 0cb5e36b20 fix(home-server): env var determining the sqlite database location (#626) 2023-06-14 08:05:48 +02:00
standardci 319bab5b34 chore(release): publish new version
- @standardnotes/home-server@1.11.4
2023-06-13 12:19:56 +00:00
Karol Sójko 90a4f2111f fix(home-server): encapsulate starting the server with a result return 2023-06-13 14:03:39 +02:00
standardci 3aba202970 chore(release): publish new version
- @standardnotes/files-server@1.18.2
 - @standardnotes/home-server@1.11.3
2023-06-12 10:09:28 +00:00
Karol Sójko c8974b7fa2 fix(home-server): accept application/octet-stream requests for files (#625)
* fix(home-server): accept application/octet-stream requests for files

* fix(files): check for empty chunks
2023-06-12 11:55:18 +02:00
standardci 3654a19586 chore(release): publish new version
- @standardnotes/files-server@1.18.1
 - @standardnotes/home-server@1.11.2
2023-06-09 11:51:44 +00:00
Karol Sójko 5f0929c1aa fix(files): add debug logs for checking chunks upon finishing upload session 2023-06-09 13:37:30 +02:00
standardci c0fa83bce6 chore(release): publish new version
- @standardnotes/api-gateway@1.64.1
 - @standardnotes/auth-server@1.119.1
 - @standardnotes/home-server@1.11.1
2023-06-09 11:14:28 +00:00
Karol Sójko c201ee42a0 fix(home-server): add default value for valet token ttl 2023-06-09 12:56:57 +02:00
Karol Sójko e6a4cc3098 fix(api-gateway): direct call service proxy to return 400 responses instead of throwing errors 2023-06-09 12:52:58 +02:00
standardci 39f2fe2ba1 chore(release): publish new version
- @standardnotes/auth-server@1.119.0
 - @standardnotes/home-server@1.11.0
2023-06-09 06:13:41 +00:00
Karol Sójko 72ce190996 feat(home-server): add activating premium features (#624) 2023-06-09 07:59:07 +02:00
standardci 527dd1b61b chore(release): publish new version
- @standardnotes/auth-server@1.118.0
 - @standardnotes/home-server@1.10.0
 - @standardnotes/revisions-server@1.23.0
 - @standardnotes/syncing-server@1.44.0
2023-06-07 08:53:34 +00:00
Karol Sójko af8feaadfe feat: configurable path for uploads and db (#623)
* fix(home-server): passing the database path

* fix(home-server): passing the file upload path
2023-06-07 10:39:33 +02:00
standardci 3164f76662 chore(release): publish new version
- @standardnotes/api-gateway@1.64.0
 - @standardnotes/auth-server@1.117.0
 - @standardnotes/files-server@1.18.0
 - @standardnotes/home-server@1.9.0
 - @standardnotes/revisions-server@1.22.0
 - @standardnotes/syncing-server@1.43.0
2023-06-05 10:01:28 +00:00
Karol Sójko d6e531d4b6 feat(home-server): allow running the home server with a mysql and redis configuration (#622)
* feat(home-server): allow running the home server with a mysql and redis configuration

* fix(files): config for file uploader

* fix(files): if condition on fs file uploader bootstrap
2023-06-05 11:47:10 +02:00
42 changed files with 716 additions and 206 deletions
+1
View File
@@ -4,6 +4,7 @@ DB_USERNAME=std_notes_user
DB_PASSWORD=changeme123 DB_PASSWORD=changeme123
DB_DATABASE=standard_notes_db DB_DATABASE=standard_notes_db
DB_PORT=3306 DB_PORT=3306
DB_SQLITE_DATABASE_PATH=standard_notes_db
REDIS_PORT=6379 REDIS_PORT=6379
REDIS_HOST=cache REDIS_HOST=cache
AUTH_SERVER_ACCESS_TOKEN_AGE=4 AUTH_SERVER_ACCESS_TOKEN_AGE=4
+25
View File
@@ -54,6 +54,11 @@ jobs:
e2e-home-server: e2e-home-server:
name: (Home Server) E2E Test Suite name: (Home Server) E2E Test Suite
strategy:
matrix:
db_type: [mysql, sqlite]
cache_type: [redis, memory]
runs-on: ubuntu-latest runs-on: ubuntu-latest
services: services:
@@ -61,6 +66,19 @@ jobs:
image: standardnotes/snjs:${{ inputs.snjs_image_tag }} image: standardnotes/snjs:${{ inputs.snjs_image_tag }}
ports: ports:
- 9001:9001 - 9001:9001
cache:
image: redis
ports:
- 6379:6379
db:
image: mysql
ports:
- 3306:3306
env:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: standardnotes
MYSQL_USER: standardnotes
MYSQL_PASSWORD: standardnotes
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
@@ -90,6 +108,13 @@ jobs:
echo "ACCESS_TOKEN_AGE=4" >> packages/home-server/.env echo "ACCESS_TOKEN_AGE=4" >> packages/home-server/.env
echo "REFRESH_TOKEN_AGE=7" >> packages/home-server/.env echo "REFRESH_TOKEN_AGE=7" >> packages/home-server/.env
echo "REVISIONS_FREQUENCY=5" >> packages/home-server/.env echo "REVISIONS_FREQUENCY=5" >> packages/home-server/.env
echo "DB_HOST=db" >> packages/home-server/.env
echo "DB_PORT=3306" >> packages/home-server/.env
echo "DB_USERNAME=standardnotes" >> packages/home-server/.env
echo "DB_PASSWORD=standardnotes" >> packages/home-server/.env
echo "DB_TYPE=${{ matrix.db_type }}" >> packages/home-server/.env
echo "REDIS_URL=redis://cache" >> packages/home-server/.env
echo "CACHE_TYPE=${{ matrix.cache_type }}" >> packages/home-server/.env
- name: Run Server - name: Run Server
run: nohup yarn workspace @standardnotes/home-server start & run: nohup yarn workspace @standardnotes/home-server start &
+1
View File
@@ -1,3 +1,4 @@
MODE=microservice # microservice | home-server
LOG_LEVEL=debug LOG_LEVEL=debug
NODE_ENV=development NODE_ENV=development
VERSION=development VERSION=development
+18
View File
@@ -3,6 +3,24 @@
All notable changes to this project will be documented in this file. All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.64.2](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.64.1...@standardnotes/api-gateway@1.64.2) (2023-06-22)
### Bug Fixes
* **home-server:** add debug logs about container initalizations ([0df4715](https://github.com/standardnotes/api-gateway/commit/0df471585fd5b4626ec2972f3b9a3e33b2830e65))
## [1.64.1](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.64.0...@standardnotes/api-gateway@1.64.1) (2023-06-09)
### Bug Fixes
* **api-gateway:** direct call service proxy to return 400 responses instead of throwing errors ([e6a4cc3](https://github.com/standardnotes/api-gateway/commit/e6a4cc3098bdf84fc9d48ed0d9098ebb52afb0e7))
# [1.64.0](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.63.2...@standardnotes/api-gateway@1.64.0) (2023-06-05)
### Features
* **home-server:** allow running the home server with a mysql and redis configuration ([#622](https://github.com/standardnotes/api-gateway/issues/622)) ([d6e531d](https://github.com/standardnotes/api-gateway/commit/d6e531d4b6c1c80a894f6d7ec93632595268dd64))
## [1.63.2](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.63.1...@standardnotes/api-gateway@1.63.2) (2023-06-02) ## [1.63.2](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.63.1...@standardnotes/api-gateway@1.63.2) (2023-06-02)
### Bug Fixes ### Bug Fixes
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "@standardnotes/api-gateway", "name": "@standardnotes/api-gateway",
"version": "1.63.2", "version": "1.64.2",
"engines": { "engines": {
"node": ">=18.0.0 <21.0.0" "node": ">=18.0.0 <21.0.0"
}, },
@@ -34,7 +34,8 @@ export class ContainerConfigLoader {
const container = new Container() const container = new Container()
const isConfiguredForHomeServer = env.get('CACHE_TYPE') === 'memory' const isConfiguredForHomeServer = env.get('MODE', true) === 'home-server'
const isConfiguredForInMemoryCache = env.get('CACHE_TYPE', true) === 'memory'
const winstonFormatters = [winston.format.splat(), winston.format.json()] const winstonFormatters = [winston.format.splat(), winston.format.json()]
if (env.get('NEW_RELIC_ENABLED', true) === 'true') { if (env.get('NEW_RELIC_ENABLED', true) === 'true') {
@@ -45,19 +46,20 @@ export class ContainerConfigLoader {
winstonFormatters.push(newrelicWinstonFormatter()) winstonFormatters.push(newrelicWinstonFormatter())
} }
let logger: winston.Logger
if (configuration?.logger) { if (configuration?.logger) {
container.bind<winston.Logger>(TYPES.Logger).toConstantValue(configuration.logger as winston.Logger) logger = configuration.logger as winston.Logger
} else { } else {
const logger = winston.createLogger({ logger = winston.createLogger({
level: env.get('LOG_LEVEL', true) || 'info', level: env.get('LOG_LEVEL', true) || 'info',
format: winston.format.combine(...winstonFormatters), format: winston.format.combine(...winstonFormatters),
transports: [new winston.transports.Console({ level: env.get('LOG_LEVEL', true) || 'info' })], transports: [new winston.transports.Console({ level: env.get('LOG_LEVEL', true) || 'info' })],
defaultMeta: { service: 'api-gateway' }, defaultMeta: { service: 'api-gateway' },
}) })
container.bind<winston.Logger>(TYPES.Logger).toConstantValue(logger)
} }
container.bind<winston.Logger>(TYPES.Logger).toConstantValue(logger)
if (!isConfiguredForHomeServer) { if (!isConfiguredForInMemoryCache) {
const redisUrl = env.get('REDIS_URL') const redisUrl = env.get('REDIS_URL')
const isRedisInClusterMode = redisUrl.indexOf(',') > 0 const isRedisInClusterMode = redisUrl.indexOf(',') > 0
let redis let redis
@@ -124,6 +126,8 @@ export class ContainerConfigLoader {
.bind<EndpointResolverInterface>(TYPES.EndpointResolver) .bind<EndpointResolverInterface>(TYPES.EndpointResolver)
.toConstantValue(new EndpointResolver(isConfiguredForHomeServer)) .toConstantValue(new EndpointResolver(isConfiguredForHomeServer))
logger.debug('Configuration complete')
return container return container
} }
} }
@@ -1,7 +1,7 @@
import { Request, Response } from 'express' import { Request, Response } from 'express'
import { ServiceContainerInterface, ServiceIdentifier } from '@standardnotes/domain-core'
import { ServiceProxyInterface } from '../Http/ServiceProxyInterface' import { ServiceProxyInterface } from '../Http/ServiceProxyInterface'
import { ServiceContainerInterface, ServiceIdentifier } from '@standardnotes/domain-core'
export class DirectCallServiceProxy implements ServiceProxyInterface { export class DirectCallServiceProxy implements ServiceProxyInterface {
constructor(private serviceContainer: ServiceContainerInterface, private filesServerUrl: string) {} constructor(private serviceContainer: ServiceContainerInterface, private filesServerUrl: string) {}
@@ -34,8 +34,12 @@ export class DirectCallServiceProxy implements ServiceProxyInterface {
} }
} }
async callEmailServer(_request: Request, _response: Response, _endpointOrMethodIdentifier: string): Promise<void> { async callEmailServer(_request: Request, response: Response, _endpointOrMethodIdentifier: string): Promise<void> {
throw new Error('Email server is not available.') response.status(400).send({
error: {
message: 'Email server is not available.',
},
})
} }
async callAuthServer(request: never, response: never, endpointOrMethodIdentifier: string): Promise<void> { async callAuthServer(request: never, response: never, endpointOrMethodIdentifier: string): Promise<void> {
@@ -54,10 +58,14 @@ export class DirectCallServiceProxy implements ServiceProxyInterface {
async callAuthServerWithLegacyFormat( async callAuthServerWithLegacyFormat(
_request: Request, _request: Request,
_response: Response, response: Response,
_endpointOrMethodIdentifier: string, _endpointOrMethodIdentifier: string,
): Promise<void> { ): Promise<void> {
throw new Error('Legacy auth endpoints are no longer available.') response.status(400).send({
error: {
message: 'Legacy auth endpoints are no longer available.',
},
})
} }
async callRevisionsServer(request: never, response: never, endpointOrMethodIdentifier: string): Promise<void> { async callRevisionsServer(request: never, response: never, endpointOrMethodIdentifier: string): Promise<void> {
@@ -92,22 +100,30 @@ export class DirectCallServiceProxy implements ServiceProxyInterface {
async callLegacySyncingServer( async callLegacySyncingServer(
_request: Request, _request: Request,
_response: Response, response: Response,
_endpointOrMethodIdentifier: string, _endpointOrMethodIdentifier: string,
): Promise<void> { ): Promise<void> {
throw new Error('Legacy syncing server endpoints are no longer available.') response.status(400).send({
error: {
message: 'Legacy syncing server endpoints are no longer available.',
},
})
} }
async callPaymentsServer(_request: Request, _response: Response, _endpointOrMethodIdentifier: string): Promise<void> { async callPaymentsServer(_request: Request, response: Response, _endpointOrMethodIdentifier: string): Promise<void> {
throw new Error('Payments server is not available.') response.status(400).send({
error: {
message: 'Payments server is not available.',
},
})
} }
async callWebSocketServer( async callWebSocketServer(_request: Request, response: Response, _endpointOrMethodIdentifier: string): Promise<void> {
_request: Request, response.status(400).send({
_response: Response, error: {
_endpointOrMethodIdentifier: string, message: 'Websockets server is not available.',
): Promise<void> { },
throw new Error('Websockets server is not available.') })
} }
private sendDecoratedResponse( private sendDecoratedResponse(
+3
View File
@@ -1,3 +1,4 @@
MODE=microservice # microservice | home-server
LOG_LEVEL=debug LOG_LEVEL=debug
NODE_ENV=development NODE_ENV=development
VERSION=development VERSION=development
@@ -20,8 +21,10 @@ DB_USERNAME=auth
DB_PASSWORD=changeme123 DB_PASSWORD=changeme123
DB_DATABASE=auth DB_DATABASE=auth
DB_DEBUG_LEVEL=all # "all" | "query" | "schema" | "error" | "warn" | "info" | "log" | "migration" DB_DEBUG_LEVEL=all # "all" | "query" | "schema" | "error" | "warn" | "info" | "log" | "migration"
DB_TYPE=mysql
REDIS_URL=redis://cache REDIS_URL=redis://cache
CACHE_TYPE=redis
DISABLE_USER_REGISTRATION=false DISABLE_USER_REGISTRATION=false
+36
View File
@@ -3,6 +3,42 @@
All notable changes to this project will be documented in this file. All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.119.3](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.119.2...@standardnotes/auth-server@1.119.3) (2023-06-22)
### Bug Fixes
* **home-server:** add debug logs about container initalizations ([0df4715](https://github.com/standardnotes/server/commit/0df471585fd5b4626ec2972f3b9a3e33b2830e65))
## [1.119.2](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.119.1...@standardnotes/auth-server@1.119.2) (2023-06-14)
### Bug Fixes
* **home-server:** env var determining the sqlite database location ([#626](https://github.com/standardnotes/server/issues/626)) ([0cb5e36](https://github.com/standardnotes/server/commit/0cb5e36b20d9b095ea0edbcd877387e6c0069856))
## [1.119.1](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.119.0...@standardnotes/auth-server@1.119.1) (2023-06-09)
### Bug Fixes
* **home-server:** add default value for valet token ttl ([c201ee4](https://github.com/standardnotes/server/commit/c201ee42a00d9e5402afea2f2c5848a362c1529e))
# [1.119.0](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.118.0...@standardnotes/auth-server@1.119.0) (2023-06-09)
### Features
* **home-server:** add activating premium features ([#624](https://github.com/standardnotes/server/issues/624)) ([72ce190](https://github.com/standardnotes/server/commit/72ce1909960fbd2ec6a47b8dbdfbe53a4f10e776))
# [1.118.0](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.117.0...@standardnotes/auth-server@1.118.0) (2023-06-07)
### Features
* configurable path for uploads and db ([#623](https://github.com/standardnotes/server/issues/623)) ([af8feaa](https://github.com/standardnotes/server/commit/af8feaadfe2dd58baab4cca217d6307b4a221326))
# [1.117.0](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.116.2...@standardnotes/auth-server@1.117.0) (2023-06-05)
### Features
* **home-server:** allow running the home server with a mysql and redis configuration ([#622](https://github.com/standardnotes/server/issues/622)) ([d6e531d](https://github.com/standardnotes/server/commit/d6e531d4b6c1c80a894f6d7ec93632595268dd64))
## [1.116.2](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.116.1...@standardnotes/auth-server@1.116.2) (2023-06-02) ## [1.116.2](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.116.1...@standardnotes/auth-server@1.116.2) (2023-06-02)
### Bug Fixes ### Bug Fixes
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "@standardnotes/auth-server", "name": "@standardnotes/auth-server",
"version": "1.116.2", "version": "1.119.3",
"engines": { "engines": {
"node": ">=18.0.0 <21.0.0" "node": ">=18.0.0 <21.0.0"
}, },
@@ -0,0 +1,5 @@
import { Result, ServiceInterface } from '@standardnotes/domain-core'
export interface AuthServiceInterface extends ServiceInterface {
activatePremiumFeatures(username: string): Promise<Result<string>>
}
+53 -34
View File
@@ -251,6 +251,7 @@ import { HomeServerValetTokenController } from '../Infra/InversifyExpressUtils/H
import { HomeServerWebSocketsController } from '../Infra/InversifyExpressUtils/HomeServer/HomeServerWebSocketsController' import { HomeServerWebSocketsController } from '../Infra/InversifyExpressUtils/HomeServer/HomeServerWebSocketsController'
import { HomeServerSessionsController } from '../Infra/InversifyExpressUtils/HomeServer/HomeServerSessionsController' import { HomeServerSessionsController } from '../Infra/InversifyExpressUtils/HomeServer/HomeServerSessionsController'
import { Transform } from 'stream' import { Transform } from 'stream'
import { ActivatePremiumFeatures } from '../Domain/UseCase/ActivatePremiumFeatures/ActivatePremiumFeatures'
export class ContainerConfigLoader { export class ContainerConfigLoader {
async load(configuration?: { async load(configuration?: {
@@ -267,12 +268,37 @@ export class ContainerConfigLoader {
const container = new Container() const container = new Container()
const winstonFormatters = [winston.format.splat(), winston.format.json()]
if (env.get('NEW_RELIC_ENABLED', true) === 'true') {
await import('newrelic')
// eslint-disable-next-line @typescript-eslint/no-var-requires
const newrelicFormatter = require('@newrelic/winston-enricher')
const newrelicWinstonFormatter = newrelicFormatter(winston)
winstonFormatters.push(newrelicWinstonFormatter())
}
let logger: winston.Logger
if (configuration?.logger) {
logger = configuration.logger as winston.Logger
} else {
logger = winston.createLogger({
level: env.get('LOG_LEVEL', true) || 'info',
format: winston.format.combine(...winstonFormatters),
transports: [new winston.transports.Console({ level: env.get('LOG_LEVEL', true) || 'info' })],
defaultMeta: { service: 'auth' },
})
}
container.bind<winston.Logger>(TYPES.Auth_Logger).toConstantValue(logger)
const appDataSource = new AppDataSource(env) const appDataSource = new AppDataSource(env)
await appDataSource.initialize() await appDataSource.initialize()
const isConfiguredForHomeServer = env.get('DB_TYPE') === 'sqlite' logger.debug('Database initialized')
if (!isConfiguredForHomeServer) { const isConfiguredForHomeServer = env.get('MODE', true) === 'home-server'
const isConfiguredForInMemoryCache = env.get('CACHE_TYPE', true) === 'memory'
if (!isConfiguredForInMemoryCache) {
const redisUrl = env.get('REDIS_URL') const redisUrl = env.get('REDIS_URL')
const isRedisInClusterMode = redisUrl.indexOf(',') > 0 const isRedisInClusterMode = redisUrl.indexOf(',') > 0
let redis let redis
@@ -285,27 +311,6 @@ export class ContainerConfigLoader {
container.bind(TYPES.Auth_Redis).toConstantValue(redis) container.bind(TYPES.Auth_Redis).toConstantValue(redis)
} }
const winstonFormatters = [winston.format.splat(), winston.format.json()]
if (env.get('NEW_RELIC_ENABLED', true) === 'true') {
await import('newrelic')
// eslint-disable-next-line @typescript-eslint/no-var-requires
const newrelicFormatter = require('@newrelic/winston-enricher')
const newrelicWinstonFormatter = newrelicFormatter(winston)
winstonFormatters.push(newrelicWinstonFormatter())
}
if (configuration?.logger) {
container.bind<winston.Logger>(TYPES.Auth_Logger).toConstantValue(configuration.logger as winston.Logger)
} else {
const logger = winston.createLogger({
level: env.get('LOG_LEVEL', true) || 'info',
format: winston.format.combine(...winstonFormatters),
transports: [new winston.transports.Console({ level: env.get('LOG_LEVEL', true) || 'info' })],
defaultMeta: { service: 'auth' },
})
container.bind<winston.Logger>(TYPES.Auth_Logger).toConstantValue(logger)
}
container.bind<TimerInterface>(TYPES.Auth_Timer).toConstantValue(new Timer()) container.bind<TimerInterface>(TYPES.Auth_Timer).toConstantValue(new Timer())
if (!isConfiguredForHomeServer) { if (!isConfiguredForHomeServer) {
@@ -488,7 +493,9 @@ export class ContainerConfigLoader {
.bind(TYPES.Auth_AUTH_JWT_TTL) .bind(TYPES.Auth_AUTH_JWT_TTL)
.toConstantValue(env.get('AUTH_JWT_TTL', true) ? +env.get('AUTH_JWT_TTL') : 60_000) .toConstantValue(env.get('AUTH_JWT_TTL', true) ? +env.get('AUTH_JWT_TTL') : 60_000)
container.bind(TYPES.Auth_VALET_TOKEN_SECRET).toConstantValue(env.get('VALET_TOKEN_SECRET', true)) container.bind(TYPES.Auth_VALET_TOKEN_SECRET).toConstantValue(env.get('VALET_TOKEN_SECRET', true))
container.bind(TYPES.Auth_VALET_TOKEN_TTL).toConstantValue(+env.get('VALET_TOKEN_TTL', true)) container
.bind(TYPES.Auth_VALET_TOKEN_TTL)
.toConstantValue(env.get('VALET_TOKEN_TTL', true) ? +env.get('VALET_TOKEN_TTL', true) : 7200)
container container
.bind(TYPES.Auth_WEB_SOCKET_CONNECTION_TOKEN_SECRET) .bind(TYPES.Auth_WEB_SOCKET_CONNECTION_TOKEN_SECRET)
.toConstantValue(env.get('WEB_SOCKET_CONNECTION_TOKEN_SECRET', true)) .toConstantValue(env.get('WEB_SOCKET_CONNECTION_TOKEN_SECRET', true))
@@ -550,7 +557,16 @@ export class ContainerConfigLoader {
.bind(TYPES.Auth_READONLY_USERS) .bind(TYPES.Auth_READONLY_USERS)
.toConstantValue(env.get('READONLY_USERS', true) ? env.get('READONLY_USERS', true).split(',') : []) .toConstantValue(env.get('READONLY_USERS', true) ? env.get('READONLY_USERS', true).split(',') : [])
if (isConfiguredForHomeServer) { if (isConfiguredForInMemoryCache) {
container
.bind<PKCERepositoryInterface>(TYPES.Auth_PKCERepository)
.toConstantValue(
new TypeORMPKCERepository(
container.get(TYPES.Auth_CacheEntryRepository),
container.get(TYPES.Auth_Logger),
container.get(TYPES.Auth_Timer),
),
)
container container
.bind<LockRepositoryInterface>(TYPES.Auth_LockRepository) .bind<LockRepositoryInterface>(TYPES.Auth_LockRepository)
.toConstantValue( .toConstantValue(
@@ -578,15 +594,6 @@ export class ContainerConfigLoader {
container.get(TYPES.Auth_Timer), container.get(TYPES.Auth_Timer),
), ),
) )
container
.bind<PKCERepositoryInterface>(TYPES.Auth_PKCERepository)
.toConstantValue(
new TypeORMPKCERepository(
container.get(TYPES.Auth_CacheEntryRepository),
container.get(TYPES.Auth_Logger),
container.get(TYPES.Auth_Timer),
),
)
container container
.bind<SubscriptionTokenRepositoryInterface>(TYPES.Auth_SubscriptionTokenRepository) .bind<SubscriptionTokenRepositoryInterface>(TYPES.Auth_SubscriptionTokenRepository)
.toConstantValue( .toConstantValue(
@@ -780,6 +787,16 @@ export class ContainerConfigLoader {
container.get(TYPES.Auth_CryptoNode), container.get(TYPES.Auth_CryptoNode),
), ),
) )
container
.bind<ActivatePremiumFeatures>(TYPES.Auth_ActivatePremiumFeatures)
.toConstantValue(
new ActivatePremiumFeatures(
container.get(TYPES.Auth_UserRepository),
container.get(TYPES.Auth_UserSubscriptionRepository),
container.get(TYPES.Auth_RoleService),
container.get(TYPES.Auth_Timer),
),
)
container container
.bind<CleanupSessionTraces>(TYPES.Auth_CleanupSessionTraces) .bind<CleanupSessionTraces>(TYPES.Auth_CleanupSessionTraces)
@@ -1187,6 +1204,8 @@ export class ContainerConfigLoader {
) )
} }
logger.debug('Configuration complete')
return container return container
} }
} }
+1 -1
View File
@@ -109,7 +109,7 @@ export class AppDataSource {
const sqliteDataSourceOptions: SqliteConnectionOptions = { const sqliteDataSourceOptions: SqliteConnectionOptions = {
...commonDataSourceOptions, ...commonDataSourceOptions,
type: 'sqlite', type: 'sqlite',
database: `data/${this.env.get('DB_DATABASE')}.sqlite`, database: this.env.get('DB_SQLITE_DATABASE_PATH'),
} }
this.dataSource = new DataSource(sqliteDataSourceOptions) this.dataSource = new DataSource(sqliteDataSourceOptions)
+23 -3
View File
@@ -1,15 +1,21 @@
import { import {
ControllerContainerInterface, ControllerContainerInterface,
Result,
ServiceConfiguration, ServiceConfiguration,
ServiceContainerInterface, ServiceContainerInterface,
ServiceIdentifier, ServiceIdentifier,
ServiceInterface,
} from '@standardnotes/domain-core' } from '@standardnotes/domain-core'
import { ContainerConfigLoader } from './Container' import { ContainerConfigLoader } from './Container'
import { DirectCallDomainEventPublisher } from '@standardnotes/domain-events-infra' import { DirectCallDomainEventPublisher } from '@standardnotes/domain-events-infra'
import TYPES from './Types'
import { Container } from 'inversify'
import { ActivatePremiumFeatures } from '../Domain/UseCase/ActivatePremiumFeatures/ActivatePremiumFeatures'
import { AuthServiceInterface } from './AuthServiceInterface'
export class Service implements AuthServiceInterface {
private container: Container | undefined
export class Service implements ServiceInterface {
constructor( constructor(
private serviceContainer: ServiceContainerInterface, private serviceContainer: ServiceContainerInterface,
private controllerContainer: ControllerContainerInterface, private controllerContainer: ControllerContainerInterface,
@@ -18,6 +24,16 @@ export class Service implements ServiceInterface {
this.serviceContainer.register(this.getId(), this) this.serviceContainer.register(this.getId(), this)
} }
async activatePremiumFeatures(username: string): Promise<Result<string>> {
if (!this.container) {
return Result.fail('Container not initialized')
}
const activatePremiumFeatures = this.container.get(TYPES.Auth_ActivatePremiumFeatures) as ActivatePremiumFeatures
return activatePremiumFeatures.execute({ username })
}
async handleRequest(request: never, response: never, endpointOrMethodIdentifier: string): Promise<unknown> { async handleRequest(request: never, response: never, endpointOrMethodIdentifier: string): Promise<unknown> {
const method = this.controllerContainer.get(endpointOrMethodIdentifier) const method = this.controllerContainer.get(endpointOrMethodIdentifier)
@@ -31,12 +47,16 @@ export class Service implements ServiceInterface {
async getContainer(configuration?: ServiceConfiguration): Promise<unknown> { async getContainer(configuration?: ServiceConfiguration): Promise<unknown> {
const config = new ContainerConfigLoader() const config = new ContainerConfigLoader()
return config.load({ const container = await config.load({
controllerConatiner: this.controllerContainer, controllerConatiner: this.controllerContainer,
directCallDomainEventPublisher: this.directCallDomainEventPublisher, directCallDomainEventPublisher: this.directCallDomainEventPublisher,
logger: configuration?.logger, logger: configuration?.logger,
environmentOverrides: configuration?.environmentOverrides, environmentOverrides: configuration?.environmentOverrides,
}) })
this.container = container
return container
} }
getId(): ServiceIdentifier { getId(): ServiceIdentifier {
+1
View File
@@ -149,6 +149,7 @@ const TYPES = {
Auth_ListAuthenticators: Symbol.for('Auth_ListAuthenticators'), Auth_ListAuthenticators: Symbol.for('Auth_ListAuthenticators'),
Auth_DeleteAuthenticator: Symbol.for('Auth_DeleteAuthenticator'), Auth_DeleteAuthenticator: Symbol.for('Auth_DeleteAuthenticator'),
Auth_GenerateRecoveryCodes: Symbol.for('Auth_GenerateRecoveryCodes'), Auth_GenerateRecoveryCodes: Symbol.for('Auth_GenerateRecoveryCodes'),
Auth_ActivatePremiumFeatures: Symbol.for('Auth_ActivatePremiumFeatures'),
Auth_SignInWithRecoveryCodes: Symbol.for('Auth_SignInWithRecoveryCodes'), Auth_SignInWithRecoveryCodes: Symbol.for('Auth_SignInWithRecoveryCodes'),
Auth_GetUserKeyParamsRecovery: Symbol.for('Auth_GetUserKeyParamsRecovery'), Auth_GetUserKeyParamsRecovery: Symbol.for('Auth_GetUserKeyParamsRecovery'),
// Handlers // Handlers
+1
View File
@@ -1 +1,2 @@
export * from './AuthServiceInterface'
export * from './Service' export * from './Service'
@@ -0,0 +1,67 @@
import { TimerInterface } from '@standardnotes/time'
import { RoleServiceInterface } from '../../Role/RoleServiceInterface'
import { UserSubscriptionRepositoryInterface } from '../../Subscription/UserSubscriptionRepositoryInterface'
import { UserRepositoryInterface } from '../../User/UserRepositoryInterface'
import { ActivatePremiumFeatures } from './ActivatePremiumFeatures'
import { User } from '../../User/User'
describe('ActivatePremiumFeatures', () => {
let userRepository: UserRepositoryInterface
let userSubscriptionRepository: UserSubscriptionRepositoryInterface
let roleService: RoleServiceInterface
let timer: TimerInterface
let user: User
const createUseCase = () =>
new ActivatePremiumFeatures(userRepository, userSubscriptionRepository, roleService, timer)
beforeEach(() => {
user = {} as jest.Mocked<User>
userRepository = {} as jest.Mocked<UserRepositoryInterface>
userRepository.findOneByUsernameOrEmail = jest.fn().mockResolvedValue(user)
userSubscriptionRepository = {} as jest.Mocked<UserSubscriptionRepositoryInterface>
userSubscriptionRepository.save = jest.fn()
roleService = {} as jest.Mocked<RoleServiceInterface>
roleService.addUserRole = jest.fn()
timer = {} as jest.Mocked<TimerInterface>
timer.getTimestampInMicroseconds = jest.fn().mockReturnValue(123456789)
timer.convertDateToMicroseconds = jest.fn().mockReturnValue(123456789)
timer.getUTCDateNDaysAhead = jest.fn().mockReturnValue(new Date('2024-01-01T00:00:00.000Z'))
})
it('should return error when username is invalid', async () => {
const useCase = createUseCase()
const result = await useCase.execute({ username: '' })
expect(result.isFailed()).toBe(true)
expect(result.getError()).toBe('Username cannot be empty')
})
it('should return error when user is not found', async () => {
userRepository.findOneByUsernameOrEmail = jest.fn().mockResolvedValue(null)
const useCase = createUseCase()
const result = await useCase.execute({ username: 'test@test.te' })
expect(result.isFailed()).toBe(true)
expect(result.getError()).toBe('User not found with username: test@test.te')
})
it('should save a subscription and add role to user', async () => {
const useCase = createUseCase()
const result = await useCase.execute({ username: 'test@test.te' })
expect(result.isFailed()).toBe(false)
expect(userSubscriptionRepository.save).toHaveBeenCalled()
expect(roleService.addUserRole).toHaveBeenCalled()
})
})
@@ -0,0 +1,49 @@
import { Result, SubscriptionPlanName, UseCaseInterface, Username } from '@standardnotes/domain-core'
import { TimerInterface } from '@standardnotes/time'
import { RoleServiceInterface } from '../../Role/RoleServiceInterface'
import { UserSubscriptionRepositoryInterface } from '../../Subscription/UserSubscriptionRepositoryInterface'
import { UserRepositoryInterface } from '../../User/UserRepositoryInterface'
import { UserSubscription } from '../../Subscription/UserSubscription'
import { UserSubscriptionType } from '../../Subscription/UserSubscriptionType'
import { ActivatePremiumFeaturesDTO } from './ActivatePremiumFeaturesDTO'
export class ActivatePremiumFeatures implements UseCaseInterface<string> {
constructor(
private userRepository: UserRepositoryInterface,
private userSubscriptionRepository: UserSubscriptionRepositoryInterface,
private roleService: RoleServiceInterface,
private timer: TimerInterface,
) {}
async execute(dto: ActivatePremiumFeaturesDTO): Promise<Result<string>> {
const usernameOrError = Username.create(dto.username)
if (usernameOrError.isFailed()) {
return Result.fail(usernameOrError.getError())
}
const username = usernameOrError.getValue()
const user = await this.userRepository.findOneByUsernameOrEmail(username)
if (user === null) {
return Result.fail(`User not found with username: ${username.value}`)
}
const timestamp = this.timer.getTimestampInMicroseconds()
const subscription = new UserSubscription()
subscription.planName = SubscriptionPlanName.NAMES.ProPlan
subscription.user = Promise.resolve(user)
subscription.createdAt = timestamp
subscription.updatedAt = timestamp
subscription.endsAt = this.timer.convertDateToMicroseconds(this.timer.getUTCDateNDaysAhead(365))
subscription.cancelled = false
subscription.subscriptionId = 1
subscription.subscriptionType = UserSubscriptionType.Regular
await this.userSubscriptionRepository.save(subscription)
await this.roleService.addUserRole(user, SubscriptionPlanName.NAMES.ProPlan)
return Result.ok('Premium features activated.')
}
}
@@ -0,0 +1,3 @@
export interface ActivatePremiumFeaturesDTO {
username: string
}
+1
View File
@@ -1,3 +1,4 @@
MODE=microservice # microservice | home-server
LOG_LEVEL=debug LOG_LEVEL=debug
NODE_ENV=development NODE_ENV=development
VERSION=development VERSION=development
+24
View File
@@ -3,6 +3,30 @@
All notable changes to this project will be documented in this file. All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.18.3](https://github.com/standardnotes/files/compare/@standardnotes/files-server@1.18.2...@standardnotes/files-server@1.18.3) (2023-06-22)
### Bug Fixes
* **home-server:** add debug logs about container initalizations ([0df4715](https://github.com/standardnotes/files/commit/0df471585fd5b4626ec2972f3b9a3e33b2830e65))
## [1.18.2](https://github.com/standardnotes/files/compare/@standardnotes/files-server@1.18.1...@standardnotes/files-server@1.18.2) (2023-06-12)
### Bug Fixes
* **home-server:** accept application/octet-stream requests for files ([#625](https://github.com/standardnotes/files/issues/625)) ([c8974b7](https://github.com/standardnotes/files/commit/c8974b7fa229ff4f1e026e1ebff50d1081cc5f8b))
## [1.18.1](https://github.com/standardnotes/files/compare/@standardnotes/files-server@1.18.0...@standardnotes/files-server@1.18.1) (2023-06-09)
### Bug Fixes
* **files:** add debug logs for checking chunks upon finishing upload session ([5f0929c](https://github.com/standardnotes/files/commit/5f0929c1aa7b83661fb102bad34644db69ddf7eb))
# [1.18.0](https://github.com/standardnotes/files/compare/@standardnotes/files-server@1.17.1...@standardnotes/files-server@1.18.0) (2023-06-05)
### Features
* **home-server:** allow running the home server with a mysql and redis configuration ([#622](https://github.com/standardnotes/files/issues/622)) ([d6e531d](https://github.com/standardnotes/files/commit/d6e531d4b6c1c80a894f6d7ec93632595268dd64))
## [1.17.1](https://github.com/standardnotes/files/compare/@standardnotes/files-server@1.17.0...@standardnotes/files-server@1.17.1) (2023-06-02) ## [1.17.1](https://github.com/standardnotes/files/compare/@standardnotes/files-server@1.17.0...@standardnotes/files-server@1.17.1) (2023-06-02)
### Bug Fixes ### Bug Fixes
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "@standardnotes/files-server", "name": "@standardnotes/files-server",
"version": "1.17.1", "version": "1.18.3",
"engines": { "engines": {
"node": ">=18.0.0 <21.0.0" "node": ">=18.0.0 <21.0.0"
}, },
+24 -16
View File
@@ -67,30 +67,24 @@ export class ContainerConfigLoader {
await import('newrelic') await import('newrelic')
} }
const isConfiguredForHomeServer = env.get('CACHE_TYPE') === 'memory' const isConfiguredForHomeServer = env.get('MODE', true) === 'home-server'
const isConfiguredForInMemoryCache = env.get('CACHE_TYPE', true) === 'memory'
let logger: winston.Logger
if (configuration?.logger) { if (configuration?.logger) {
container.bind<winston.Logger>(TYPES.Files_Logger).toConstantValue(configuration.logger as winston.Logger) logger = configuration.logger as winston.Logger
} else { } else {
container.bind<winston.Logger>(TYPES.Files_Logger).toConstantValue(this.createLogger({ env })) logger = this.createLogger({ env })
} }
container.bind<winston.Logger>(TYPES.Files_Logger).toConstantValue(logger)
container.bind<TimerInterface>(TYPES.Files_Timer).toConstantValue(new Timer()) container.bind<TimerInterface>(TYPES.Files_Timer).toConstantValue(new Timer())
if (isConfiguredForHomeServer) { if (isConfiguredForInMemoryCache) {
container container
.bind<UploadRepositoryInterface>(TYPES.Files_UploadRepository) .bind<UploadRepositoryInterface>(TYPES.Files_UploadRepository)
.toConstantValue(new InMemoryUploadRepository(container.get(TYPES.Files_Timer))) .toConstantValue(new InMemoryUploadRepository(container.get(TYPES.Files_Timer)))
container
.bind<DomainEventPublisherInterface>(TYPES.Files_DomainEventPublisher)
.toConstantValue(directCallDomainEventPublisher)
} else { } else {
container.bind(TYPES.Files_S3_BUCKET_NAME).toConstantValue(env.get('S3_BUCKET_NAME', true))
container.bind(TYPES.Files_S3_AWS_REGION).toConstantValue(env.get('S3_AWS_REGION', true))
container.bind(TYPES.Files_SNS_TOPIC_ARN).toConstantValue(env.get('SNS_TOPIC_ARN'))
container.bind(TYPES.Files_SNS_AWS_REGION).toConstantValue(env.get('SNS_AWS_REGION', true))
container.bind(TYPES.Files_SQS_QUEUE_URL).toConstantValue(env.get('SQS_QUEUE_URL'))
container.bind(TYPES.Files_REDIS_URL).toConstantValue(env.get('REDIS_URL')) container.bind(TYPES.Files_REDIS_URL).toConstantValue(env.get('REDIS_URL'))
const redisUrl = container.get(TYPES.Files_REDIS_URL) as string const redisUrl = container.get(TYPES.Files_REDIS_URL) as string
@@ -104,6 +98,20 @@ export class ContainerConfigLoader {
container.bind(TYPES.Files_Redis).toConstantValue(redis) container.bind(TYPES.Files_Redis).toConstantValue(redis)
container.bind<UploadRepositoryInterface>(TYPES.Files_UploadRepository).to(RedisUploadRepository)
}
if (isConfiguredForHomeServer) {
container
.bind<DomainEventPublisherInterface>(TYPES.Files_DomainEventPublisher)
.toConstantValue(directCallDomainEventPublisher)
} else {
container.bind(TYPES.Files_S3_BUCKET_NAME).toConstantValue(env.get('S3_BUCKET_NAME', true))
container.bind(TYPES.Files_S3_AWS_REGION).toConstantValue(env.get('S3_AWS_REGION', true))
container.bind(TYPES.Files_SNS_TOPIC_ARN).toConstantValue(env.get('SNS_TOPIC_ARN'))
container.bind(TYPES.Files_SNS_AWS_REGION).toConstantValue(env.get('SNS_AWS_REGION', true))
container.bind(TYPES.Files_SQS_QUEUE_URL).toConstantValue(env.get('SQS_QUEUE_URL'))
if (env.get('SNS_TOPIC_ARN', true)) { if (env.get('SNS_TOPIC_ARN', true)) {
const snsConfig: SNSClientConfig = { const snsConfig: SNSClientConfig = {
apiVersion: 'latest', apiVersion: 'latest',
@@ -137,8 +145,6 @@ export class ContainerConfigLoader {
container.bind<SQSClient>(TYPES.Files_SQS).toConstantValue(new SQSClient(sqsConfig)) container.bind<SQSClient>(TYPES.Files_SQS).toConstantValue(new SQSClient(sqsConfig))
} }
container.bind<UploadRepositoryInterface>(TYPES.Files_UploadRepository).to(RedisUploadRepository)
container container
.bind<DomainEventPublisherInterface>(TYPES.Files_DomainEventPublisher) .bind<DomainEventPublisherInterface>(TYPES.Files_DomainEventPublisher)
.toConstantValue( .toConstantValue(
@@ -156,7 +162,7 @@ export class ContainerConfigLoader {
.bind(TYPES.Files_FILE_UPLOAD_PATH) .bind(TYPES.Files_FILE_UPLOAD_PATH)
.toConstantValue(env.get('FILE_UPLOAD_PATH', true) ?? `${__dirname}/../../uploads`) .toConstantValue(env.get('FILE_UPLOAD_PATH', true) ?? `${__dirname}/../../uploads`)
if (env.get('S3_AWS_REGION', true) || env.get('S3_ENDPOINT', true)) { if (!isConfiguredForHomeServer && (env.get('S3_AWS_REGION', true) || env.get('S3_ENDPOINT', true))) {
const s3Opts: S3ClientConfig = { const s3Opts: S3ClientConfig = {
apiVersion: 'latest', apiVersion: 'latest',
} }
@@ -245,6 +251,8 @@ export class ContainerConfigLoader {
) )
} }
logger.debug('Configuration complete')
return container return container
} }
@@ -26,6 +26,24 @@ describe('UploadFileChunk', () => {
logger.warn = jest.fn() logger.warn = jest.fn()
}) })
it('should not upload a data chunk with 0 bytes', async () => {
expect(
await createUseCase().execute({
chunkId: 2,
data: new Uint8Array([]),
resourceRemoteIdentifier: '2-3-4',
resourceUnencryptedFileSize: 123,
userUuid: '1-2-3',
}),
).toEqual({
success: false,
message: 'Empty file chunk',
})
expect(fileUploader.uploadFileChunk).not.toHaveBeenCalled()
expect(uploadRepository.storeUploadChunkResult).not.toHaveBeenCalled()
})
it('should not upload a data chunk to a non existing file upload session', async () => { it('should not upload a data chunk to a non existing file upload session', async () => {
uploadRepository.retrieveUploadSessionId = jest.fn().mockReturnValue(undefined) uploadRepository.retrieveUploadSessionId = jest.fn().mockReturnValue(undefined)
@@ -18,6 +18,17 @@ export class UploadFileChunk implements UseCaseInterface {
async execute(dto: UploadFileChunkDTO): Promise<UploadFileChunkResponse> { async execute(dto: UploadFileChunkDTO): Promise<UploadFileChunkResponse> {
try { try {
if (!dto.data.byteLength || dto.data.byteLength === 0) {
this.logger.debug(
`Skipping upload file chunk ${dto.chunkId} with 0 bytes for resource: ${dto.resourceRemoteIdentifier}`,
)
return {
success: false,
message: 'Empty file chunk',
}
}
this.logger.debug( this.logger.debug(
`Starting upload file chunk ${dto.chunkId} with ${dto.data.byteLength} bytes for resource: ${dto.resourceRemoteIdentifier}`, `Starting upload file chunk ${dto.chunkId} with ${dto.data.byteLength} bytes for resource: ${dto.resourceRemoteIdentifier}`,
) )
+11 -2
View File
@@ -39,7 +39,9 @@ export class FSFileUploader implements FileUploaderInterface {
) )
} }
this.logger.debug(`FS storing file chunk ${dto.chunkId} in memory for ${dto.uploadId}`) this.logger.debug(
`FS storing file chunk ${dto.chunkId} in memory for ${dto.uploadId}: ${dto.data}, ${dto.data.byteLength}`,
)
fileChunks.set(dto.chunkId, dto.data) fileChunks.set(dto.chunkId, dto.data)
@@ -60,7 +62,14 @@ export class FSFileUploader implements FileUploaderInterface {
const orderedKeys = [...fileChunks.keys()].sort((a, b) => a - b) const orderedKeys = [...fileChunks.keys()].sort((a, b) => a - b)
for (const orderedKey of orderedKeys) { for (const orderedKey of orderedKeys) {
await promises.appendFile(`${this.fileUploadPath}/${filePath}`, fileChunks.get(orderedKey) as Uint8Array) const chunk = fileChunks.get(orderedKey)
if (!chunk || chunk.byteLength === 0) {
throw new Error(`Could not find chunk ${orderedKey} for upload ${uploadId}`)
}
this.logger.debug(`FS writing chunk ${orderedKey} for ${uploadId}: ${chunk.toString()} ${chunk.byteLength}}`)
await promises.appendFile(`${this.fileUploadPath}/${filePath}`, chunk)
} }
this.inMemoryChunks.delete(uploadId) this.inMemoryChunks.delete(uploadId)
+63
View File
@@ -3,6 +3,69 @@
All notable changes to this project will be documented in this file. All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.11.8](https://github.com/standardnotes/server/compare/@standardnotes/home-server@1.11.7...@standardnotes/home-server@1.11.8) (2023-06-22)
### Bug Fixes
* **home-server:** add debug logs about container initalizations ([0df4715](https://github.com/standardnotes/server/commit/0df471585fd5b4626ec2972f3b9a3e33b2830e65))
## [1.11.7](https://github.com/standardnotes/server/compare/@standardnotes/home-server@1.11.6...@standardnotes/home-server@1.11.7) (2023-06-22)
### Bug Fixes
* **home-server:** add default log level to overrides ([c078bc9](https://github.com/standardnotes/server/commit/c078bc958d96e856f6e607406d5d817d422572fb))
* **home-server:** add log leve information to starting the home server information ([49c2792](https://github.com/standardnotes/server/commit/49c27924eafa50c164854946053fd95e6429df9e))
## [1.11.6](https://github.com/standardnotes/server/compare/@standardnotes/home-server@1.11.5...@standardnotes/home-server@1.11.6) (2023-06-16)
### Bug Fixes
* **home-server:** unref the server instance when stopping the home server ([5ef90cc](https://github.com/standardnotes/server/commit/5ef90cc75b44133bf8065ce16f36d5b347c68122))
## [1.11.5](https://github.com/standardnotes/server/compare/@standardnotes/home-server@1.11.4...@standardnotes/home-server@1.11.5) (2023-06-14)
### Bug Fixes
* **home-server:** env var determining the sqlite database location ([#626](https://github.com/standardnotes/server/issues/626)) ([0cb5e36](https://github.com/standardnotes/server/commit/0cb5e36b20d9b095ea0edbcd877387e6c0069856))
## [1.11.4](https://github.com/standardnotes/server/compare/@standardnotes/home-server@1.11.3...@standardnotes/home-server@1.11.4) (2023-06-13)
### Bug Fixes
* **home-server:** encapsulate starting the server with a result return ([90a4f21](https://github.com/standardnotes/server/commit/90a4f2111f9e050e5fb500261c3e43eacc5622e4))
## [1.11.3](https://github.com/standardnotes/server/compare/@standardnotes/home-server@1.11.2...@standardnotes/home-server@1.11.3) (2023-06-12)
### Bug Fixes
* **home-server:** accept application/octet-stream requests for files ([#625](https://github.com/standardnotes/server/issues/625)) ([c8974b7](https://github.com/standardnotes/server/commit/c8974b7fa229ff4f1e026e1ebff50d1081cc5f8b))
## [1.11.2](https://github.com/standardnotes/server/compare/@standardnotes/home-server@1.11.1...@standardnotes/home-server@1.11.2) (2023-06-09)
**Note:** Version bump only for package @standardnotes/home-server
## [1.11.1](https://github.com/standardnotes/server/compare/@standardnotes/home-server@1.11.0...@standardnotes/home-server@1.11.1) (2023-06-09)
**Note:** Version bump only for package @standardnotes/home-server
# [1.11.0](https://github.com/standardnotes/server/compare/@standardnotes/home-server@1.10.0...@standardnotes/home-server@1.11.0) (2023-06-09)
### Features
* **home-server:** add activating premium features ([#624](https://github.com/standardnotes/server/issues/624)) ([72ce190](https://github.com/standardnotes/server/commit/72ce1909960fbd2ec6a47b8dbdfbe53a4f10e776))
# [1.10.0](https://github.com/standardnotes/server/compare/@standardnotes/home-server@1.9.0...@standardnotes/home-server@1.10.0) (2023-06-07)
### Features
* configurable path for uploads and db ([#623](https://github.com/standardnotes/server/issues/623)) ([af8feaa](https://github.com/standardnotes/server/commit/af8feaadfe2dd58baab4cca217d6307b4a221326))
# [1.9.0](https://github.com/standardnotes/server/compare/@standardnotes/home-server@1.8.5...@standardnotes/home-server@1.9.0) (2023-06-05)
### Features
* **home-server:** allow running the home server with a mysql and redis configuration ([#622](https://github.com/standardnotes/server/issues/622)) ([d6e531d](https://github.com/standardnotes/server/commit/d6e531d4b6c1c80a894f6d7ec93632595268dd64))
## [1.8.5](https://github.com/standardnotes/server/compare/@standardnotes/home-server@1.8.4...@standardnotes/home-server@1.8.5) (2023-06-02) ## [1.8.5](https://github.com/standardnotes/server/compare/@standardnotes/home-server@1.8.4...@standardnotes/home-server@1.8.5) (2023-06-02)
### Bug Fixes ### Bug Fixes
+1 -1
View File
@@ -2,7 +2,7 @@ import { HomeServer } from '../src/Server/HomeServer'
const homeServer = new HomeServer() const homeServer = new HomeServer()
Promise.resolve(homeServer.start()) Promise.resolve(homeServer.start({ dataDirectoryPath: `${__dirname}/../data` }))
.then(() => { .then(() => {
const logStream = homeServer.logs() const logStream = homeServer.logs()
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "@standardnotes/home-server", "name": "@standardnotes/home-server",
"version": "1.8.5", "version": "1.11.8",
"engines": { "engines": {
"node": ">=18.0.0 <21.0.0" "node": ">=18.0.0 <21.0.0"
}, },
+139 -97
View File
@@ -1,10 +1,10 @@
import 'reflect-metadata' import 'reflect-metadata'
import { ControllerContainer, ServiceContainer } from '@standardnotes/domain-core' import { ControllerContainer, Result, ServiceContainer } from '@standardnotes/domain-core'
import { Service as ApiGatewayService } from '@standardnotes/api-gateway' import { Service as ApiGatewayService } from '@standardnotes/api-gateway'
import { Service as FilesService } from '@standardnotes/files-server' import { Service as FilesService } from '@standardnotes/files-server'
import { DirectCallDomainEventPublisher } from '@standardnotes/domain-events-infra' import { DirectCallDomainEventPublisher } from '@standardnotes/domain-events-infra'
import { Service as AuthService } from '@standardnotes/auth-server' import { Service as AuthService, AuthServiceInterface } from '@standardnotes/auth-server'
import { Service as SyncingService } from '@standardnotes/syncing-server' import { Service as SyncingService } from '@standardnotes/syncing-server'
import { Service as RevisionsService } from '@standardnotes/revisions-server' import { Service as RevisionsService } from '@standardnotes/revisions-server'
import { Container } from 'inversify' import { Container } from 'inversify'
@@ -12,7 +12,7 @@ import { InversifyExpressServer } from 'inversify-express-utils'
import helmet from 'helmet' import helmet from 'helmet'
import * as cors from 'cors' import * as cors from 'cors'
import * as http from 'http' import * as http from 'http'
import { text, json, Request, Response, NextFunction } from 'express' import { text, json, Request, Response, NextFunction, raw } from 'express'
import * as winston from 'winston' import * as winston from 'winston'
import { PassThrough } from 'stream' import { PassThrough } from 'stream'
// eslint-disable-next-line @typescript-eslint/no-var-requires // eslint-disable-next-line @typescript-eslint/no-var-requires
@@ -24,121 +24,155 @@ import { HomeServerConfiguration } from './HomeServerConfiguration'
export class HomeServer implements HomeServerInterface { export class HomeServer implements HomeServerInterface {
private serverInstance: http.Server | undefined private serverInstance: http.Server | undefined
private authService: AuthServiceInterface | undefined
private logStream: PassThrough = new PassThrough() private logStream: PassThrough = new PassThrough()
async start(configuration?: HomeServerConfiguration): Promise<void> { async start(configuration: HomeServerConfiguration): Promise<Result<string>> {
const controllerContainer = new ControllerContainer() try {
const serviceContainer = new ServiceContainer() const controllerContainer = new ControllerContainer()
const directCallDomainEventPublisher = new DirectCallDomainEventPublisher() const serviceContainer = new ServiceContainer()
const directCallDomainEventPublisher = new DirectCallDomainEventPublisher()
const environmentOverrides = { const environmentOverrides = {
...configuration?.environment, DB_TYPE: 'sqlite',
NEW_RELIC_ENABLED: 'false', CACHE_TYPE: 'memory',
NEW_RELIC_APP_NAME: 'Home Server', DB_SQLITE_DATABASE_PATH: `${configuration.dataDirectoryPath}/database/home_server.sqlite`,
CACHE_TYPE: 'memory', FILE_UPLOAD_PATH: `${configuration.dataDirectoryPath}/uploads`,
DB_TYPE: 'sqlite', ...configuration.environment,
DB_DATABASE: 'home_server', MODE: 'home-server',
} NEW_RELIC_ENABLED: 'false',
NEW_RELIC_APP_NAME: 'Home Server',
}
const env: Env = new Env(environmentOverrides) const env: Env = new Env(environmentOverrides)
env.load() env.load()
this.configureLoggers(env) this.configureLoggers(env)
const apiGatewayService = new ApiGatewayService(serviceContainer) const apiGatewayService = new ApiGatewayService(serviceContainer)
const authService = new AuthService(serviceContainer, controllerContainer, directCallDomainEventPublisher) const authService = new AuthService(serviceContainer, controllerContainer, directCallDomainEventPublisher)
const syncingService = new SyncingService(serviceContainer, controllerContainer, directCallDomainEventPublisher) this.authService = authService
const revisionsService = new RevisionsService(serviceContainer, controllerContainer, directCallDomainEventPublisher) const syncingService = new SyncingService(serviceContainer, controllerContainer, directCallDomainEventPublisher)
const filesService = new FilesService(serviceContainer, directCallDomainEventPublisher) const revisionsService = new RevisionsService(
serviceContainer,
controllerContainer,
directCallDomainEventPublisher,
)
const filesService = new FilesService(serviceContainer, directCallDomainEventPublisher)
const container = Container.merge( const container = Container.merge(
(await apiGatewayService.getContainer({ (await apiGatewayService.getContainer({
logger: winston.loggers.get('api-gateway'), logger: winston.loggers.get('api-gateway'),
environmentOverrides, environmentOverrides,
})) as Container, })) as Container,
(await authService.getContainer({ (await authService.getContainer({
logger: winston.loggers.get('auth-server'), logger: winston.loggers.get('auth-server'),
environmentOverrides, environmentOverrides,
})) as Container, })) as Container,
(await syncingService.getContainer({ (await syncingService.getContainer({
logger: winston.loggers.get('syncing-server'), logger: winston.loggers.get('syncing-server'),
environmentOverrides, environmentOverrides,
})) as Container, })) as Container,
(await revisionsService.getContainer({ (await revisionsService.getContainer({
logger: winston.loggers.get('revisions-server'), logger: winston.loggers.get('revisions-server'),
environmentOverrides, environmentOverrides,
})) as Container, })) as Container,
(await filesService.getContainer({ (await filesService.getContainer({
logger: winston.loggers.get('files-server'), logger: winston.loggers.get('files-server'),
environmentOverrides, environmentOverrides,
})) as Container, })) as Container,
) )
const server = new InversifyExpressServer(container) const server = new InversifyExpressServer(container)
server.setConfig((app) => { server.setConfig((app) => {
/* eslint-disable */ /* eslint-disable */
app.use(helmet({ app.use(helmet({
contentSecurityPolicy: { contentSecurityPolicy: {
directives: { directives: {
defaultSrc: ["https: 'self'"], defaultSrc: ["https: 'self'"],
baseUri: ["'self'"], baseUri: ["'self'"],
childSrc: ["*", "blob:"], childSrc: ["*", "blob:"],
connectSrc: ["*"], connectSrc: ["*"],
fontSrc: ["*", "'self'"], fontSrc: ["*", "'self'"],
formAction: ["'self'"], formAction: ["'self'"],
frameAncestors: ["*", "*.standardnotes.org", "*.standardnotes.com"], frameAncestors: ["*", "*.standardnotes.org", "*.standardnotes.com"],
frameSrc: ["*", "blob:"], frameSrc: ["*", "blob:"],
imgSrc: ["'self'", "*", "data:"], imgSrc: ["'self'", "*", "data:"],
manifestSrc: ["'self'"], manifestSrc: ["'self'"],
mediaSrc: ["'self'"], mediaSrc: ["'self'"],
objectSrc: ["'self'"], objectSrc: ["'self'"],
scriptSrc: ["'self'"], scriptSrc: ["'self'"],
styleSrc: ["'self'"] styleSrc: ["'self'"]
}
} }
} }))
})) /* eslint-enable */
/* eslint-enable */ app.use(json({ limit: '50mb' }))
app.use(json({ limit: '50mb' })) app.use(raw({ limit: '50mb', type: 'application/octet-stream' }))
app.use( app.use(
text({ text({
type: ['text/plain', 'application/x-www-form-urlencoded', 'application/x-www-form-urlencoded; charset=utf-8'], type: [
}), 'text/plain',
) 'application/x-www-form-urlencoded',
app.use(cors()) 'application/x-www-form-urlencoded; charset=utf-8',
app.use( ],
robots({ }),
UserAgent: '*', )
Disallow: '/', app.use(
}), cors({
) exposedHeaders: ['Content-Range', 'Accept-Ranges'],
}) }),
)
app.use(
robots({
UserAgent: '*',
Disallow: '/',
}),
)
})
const logger: winston.Logger = winston.loggers.get('home-server') const logger: winston.Logger = winston.loggers.get('home-server')
server.setErrorConfig((app) => { server.setErrorConfig((app) => {
app.use((error: Record<string, unknown>, _request: Request, response: Response, _next: NextFunction) => { app.use((error: Record<string, unknown>, _request: Request, response: Response, _next: NextFunction) => {
logger.error(error.stack) logger.error(error.stack)
response.status(500).send({ response.status(500).send({
error: { error: {
message: message:
"Unfortunately, we couldn't handle your request. Please try again or contact our support if the error persists.", "Unfortunately, we couldn't handle your request. Please try again or contact our support if the error persists.",
}, },
})
}) })
}) })
})
const port = env.get('PORT', true) ? +env.get('PORT', true) : 3000 const port = env.get('PORT', true) ? +env.get('PORT', true) : 3000
this.serverInstance = server.build().listen(port) this.serverInstance = server.build().listen(port)
logger.info(`Server started on port ${port}`) logger.info(`Server started on port ${port}. Log level: ${env.get('LOG_LEVEL', true)}.`)
return Result.ok('Server started.')
} catch (error) {
return Result.fail((error as Error).message)
}
} }
async stop(): Promise<void> { async stop(): Promise<Result<string>> {
if (this.serverInstance) { try {
if (!this.serverInstance) {
return Result.fail('Home server is not running.')
}
this.serverInstance.close() this.serverInstance.close()
this.serverInstance.unref()
this.serverInstance = undefined
return Result.ok('Server stopped.')
} catch (error) {
return Result.fail((error as Error).message)
} }
} }
@@ -150,6 +184,14 @@ export class HomeServer implements HomeServerInterface {
return this.serverInstance.address() !== null return this.serverInstance.address() !== null
} }
async activatePremiumFeatures(username: string): Promise<Result<string>> {
if (!this.isRunning() || !this.authService) {
return Result.fail('Home server is not running.')
}
return this.authService.activatePremiumFeatures(username)
}
logs(): NodeJS.ReadableStream { logs(): NodeJS.ReadableStream {
return this.logStream return this.logStream
} }
@@ -1,3 +1,4 @@
export interface HomeServerConfiguration { export interface HomeServerConfiguration {
environment: { [name: string]: string } dataDirectoryPath: string
environment?: { [name: string]: string }
} }
@@ -1,8 +1,10 @@
import { Result } from '@standardnotes/domain-core'
import { HomeServerConfiguration } from './HomeServerConfiguration' import { HomeServerConfiguration } from './HomeServerConfiguration'
export interface HomeServerInterface { export interface HomeServerInterface {
start(configuration?: HomeServerConfiguration): Promise<void> start(configuration?: HomeServerConfiguration): Promise<Result<string>>
stop(): Promise<void> activatePremiumFeatures(username: string): Promise<Result<string>>
stop(): Promise<Result<string>>
isRunning(): Promise<boolean> isRunning(): Promise<boolean>
logs(): NodeJS.ReadableStream logs(): NodeJS.ReadableStream
} }
+3
View File
@@ -1,3 +1,4 @@
MODE=microservice # microservice | home-server
LOG_LEVEL=info LOG_LEVEL=info
NODE_ENV=development NODE_ENV=development
VERSION=development VERSION=development
@@ -14,8 +15,10 @@ DB_PASSWORD=revisionspassword
DB_DATABASE=revisions DB_DATABASE=revisions
DB_DEBUG_LEVEL=all # "all" | "query" | "schema" | "error" | "warn" | "info" | "log" | "migration" DB_DEBUG_LEVEL=all # "all" | "query" | "schema" | "error" | "warn" | "info" | "log" | "migration"
DB_MIGRATIONS_PATH=dist/migrations/*.js DB_MIGRATIONS_PATH=dist/migrations/*.js
DB_TYPE=mysql
REDIS_URL=redis://cache REDIS_URL=redis://cache
CACHE_TYPE=redis
SQS_QUEUE_URL= SQS_QUEUE_URL=
SQS_AWS_REGION= SQS_AWS_REGION=
+24
View File
@@ -3,6 +3,30 @@
All notable changes to this project will be documented in this file. All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.23.2](https://github.com/standardnotes/server/compare/@standardnotes/revisions-server@1.23.1...@standardnotes/revisions-server@1.23.2) (2023-06-22)
### Bug Fixes
* **home-server:** add debug logs about container initalizations ([0df4715](https://github.com/standardnotes/server/commit/0df471585fd5b4626ec2972f3b9a3e33b2830e65))
## [1.23.1](https://github.com/standardnotes/server/compare/@standardnotes/revisions-server@1.23.0...@standardnotes/revisions-server@1.23.1) (2023-06-14)
### Bug Fixes
* **home-server:** env var determining the sqlite database location ([#626](https://github.com/standardnotes/server/issues/626)) ([0cb5e36](https://github.com/standardnotes/server/commit/0cb5e36b20d9b095ea0edbcd877387e6c0069856))
# [1.23.0](https://github.com/standardnotes/server/compare/@standardnotes/revisions-server@1.22.0...@standardnotes/revisions-server@1.23.0) (2023-06-07)
### Features
* configurable path for uploads and db ([#623](https://github.com/standardnotes/server/issues/623)) ([af8feaa](https://github.com/standardnotes/server/commit/af8feaadfe2dd58baab4cca217d6307b4a221326))
# [1.22.0](https://github.com/standardnotes/server/compare/@standardnotes/revisions-server@1.21.3...@standardnotes/revisions-server@1.22.0) (2023-06-05)
### Features
* **home-server:** allow running the home server with a mysql and redis configuration ([#622](https://github.com/standardnotes/server/issues/622)) ([d6e531d](https://github.com/standardnotes/server/commit/d6e531d4b6c1c80a894f6d7ec93632595268dd64))
## [1.21.3](https://github.com/standardnotes/server/compare/@standardnotes/revisions-server@1.21.2...@standardnotes/revisions-server@1.21.3) (2023-06-02) ## [1.21.3](https://github.com/standardnotes/server/compare/@standardnotes/revisions-server@1.21.2...@standardnotes/revisions-server@1.21.3) (2023-06-02)
### Bug Fixes ### Bug Fixes
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "@standardnotes/revisions-server", "name": "@standardnotes/revisions-server",
"version": "1.21.3", "version": "1.23.2",
"engines": { "engines": {
"node": ">=18.0.0 <21.0.0" "node": ">=18.0.0 <21.0.0"
}, },
+14 -10
View File
@@ -61,19 +61,15 @@ export class ContainerConfigLoader {
const env: Env = new Env(configuration?.environmentOverrides) const env: Env = new Env(configuration?.environmentOverrides)
env.load() env.load()
const isConfiguredForHomeServer = env.get('DB_TYPE') === 'sqlite' const isConfiguredForHomeServer = env.get('MODE', true) === 'home-server'
const container = new Container({ const container = new Container({
defaultScope: 'Singleton', defaultScope: 'Singleton',
}) })
const appDataSource = new AppDataSource(env) let logger: winston.Logger
await appDataSource.initialize()
container.bind<Env>(TYPES.Revisions_Env).toConstantValue(env)
if (configuration?.logger) { if (configuration?.logger) {
container.bind<winston.Logger>(TYPES.Revisions_Logger).toConstantValue(configuration.logger as winston.Logger) logger = configuration.logger as winston.Logger
} else { } else {
const winstonFormatters = [winston.format.splat(), winston.format.json()] const winstonFormatters = [winston.format.splat(), winston.format.json()]
if (env.get('NEW_RELIC_ENABLED', true) === 'true') { if (env.get('NEW_RELIC_ENABLED', true) === 'true') {
@@ -84,15 +80,21 @@ export class ContainerConfigLoader {
winstonFormatters.push(newrelicWinstonFormatter()) winstonFormatters.push(newrelicWinstonFormatter())
} }
const logger = winston.createLogger({ logger = winston.createLogger({
level: env.get('LOG_LEVEL', true) || 'info', level: env.get('LOG_LEVEL', true) || 'info',
format: winston.format.combine(...winstonFormatters), format: winston.format.combine(...winstonFormatters),
transports: [new winston.transports.Console({ level: env.get('LOG_LEVEL', true) || 'info' })], transports: [new winston.transports.Console({ level: env.get('LOG_LEVEL', true) || 'info' })],
defaultMeta: { service: 'revisions' }, defaultMeta: { service: 'revisions' },
}) })
container.bind<winston.Logger>(TYPES.Revisions_Logger).toConstantValue(logger)
} }
container.bind<winston.Logger>(TYPES.Revisions_Logger).toConstantValue(logger)
const appDataSource = new AppDataSource(env)
await appDataSource.initialize()
logger.debug('Database initialized')
container.bind<Env>(TYPES.Revisions_Env).toConstantValue(env)
container.bind(TYPES.Revisions_NEW_RELIC_ENABLED).toConstantValue(env.get('NEW_RELIC_ENABLED', true)) container.bind(TYPES.Revisions_NEW_RELIC_ENABLED).toConstantValue(env.get('NEW_RELIC_ENABLED', true))
container.bind(TYPES.Revisions_VERSION).toConstantValue(env.get('VERSION', true) ?? 'development') container.bind(TYPES.Revisions_VERSION).toConstantValue(env.get('VERSION', true) ?? 'development')
@@ -350,6 +352,8 @@ export class ContainerConfigLoader {
) )
} }
logger.debug('Configuration complete')
return container return container
} }
} }
@@ -79,7 +79,7 @@ export class AppDataSource {
const sqliteDataSourceOptions: SqliteConnectionOptions = { const sqliteDataSourceOptions: SqliteConnectionOptions = {
...commonDataSourceOptions, ...commonDataSourceOptions,
type: 'sqlite', type: 'sqlite',
database: `data/${this.env.get('DB_DATABASE')}.sqlite`, database: this.env.get('DB_SQLITE_DATABASE_PATH'),
} }
this.dataSource = new DataSource(sqliteDataSourceOptions) this.dataSource = new DataSource(sqliteDataSourceOptions)
+3
View File
@@ -1,3 +1,4 @@
MODE=microservice # microservice | home-server
LOG_LEVEL=info LOG_LEVEL=info
NODE_ENV=development NODE_ENV=development
VERSION=development VERSION=development
@@ -14,8 +15,10 @@ DB_PASSWORD=changeme123
DB_DATABASE=standard_notes_db DB_DATABASE=standard_notes_db
DB_DEBUG_LEVEL=all # "all" | "query" | "schema" | "error" | "warn" | "info" | "log" | "migration" DB_DEBUG_LEVEL=all # "all" | "query" | "schema" | "error" | "warn" | "info" | "log" | "migration"
DB_MIGRATIONS_PATH=dist/migrations/*.js DB_MIGRATIONS_PATH=dist/migrations/*.js
DB_TYPE=mysql
REDIS_URL=redis://cache REDIS_URL=redis://cache
CACHE_TYPE=redis
SNS_TOPIC_ARN= SNS_TOPIC_ARN=
SNS_AWS_REGION= SNS_AWS_REGION=
+24
View File
@@ -3,6 +3,30 @@
All notable changes to this project will be documented in this file. All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.44.2](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.44.1...@standardnotes/syncing-server@1.44.2) (2023-06-22)
### Bug Fixes
* **home-server:** add debug logs about container initalizations ([0df4715](https://github.com/standardnotes/syncing-server-js/commit/0df471585fd5b4626ec2972f3b9a3e33b2830e65))
## [1.44.1](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.44.0...@standardnotes/syncing-server@1.44.1) (2023-06-14)
### Bug Fixes
* **home-server:** env var determining the sqlite database location ([#626](https://github.com/standardnotes/syncing-server-js/issues/626)) ([0cb5e36](https://github.com/standardnotes/syncing-server-js/commit/0cb5e36b20d9b095ea0edbcd877387e6c0069856))
# [1.44.0](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.43.0...@standardnotes/syncing-server@1.44.0) (2023-06-07)
### Features
* configurable path for uploads and db ([#623](https://github.com/standardnotes/syncing-server-js/issues/623)) ([af8feaa](https://github.com/standardnotes/syncing-server-js/commit/af8feaadfe2dd58baab4cca217d6307b4a221326))
# [1.43.0](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.42.2...@standardnotes/syncing-server@1.43.0) (2023-06-05)
### Features
* **home-server:** allow running the home server with a mysql and redis configuration ([#622](https://github.com/standardnotes/syncing-server-js/issues/622)) ([d6e531d](https://github.com/standardnotes/syncing-server-js/commit/d6e531d4b6c1c80a894f6d7ec93632595268dd64))
## [1.42.2](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.42.1...@standardnotes/syncing-server@1.42.2) (2023-06-02) ## [1.42.2](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.42.1...@standardnotes/syncing-server@1.42.2) (2023-06-02)
### Bug Fixes ### Bug Fixes
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "@standardnotes/syncing-server", "name": "@standardnotes/syncing-server",
"version": "1.42.2", "version": "1.44.2",
"engines": { "engines": {
"node": ">=18.0.0 <21.0.0" "node": ">=18.0.0 <21.0.0"
}, },
@@ -95,15 +95,9 @@ export class ContainerConfigLoader {
defaultScope: 'Singleton', defaultScope: 'Singleton',
}) })
const appDataSource = new AppDataSource(env) let logger: winston.Logger
await appDataSource.initialize()
const isConfiguredForHomeServer = env.get('DB_TYPE') === 'sqlite'
container.bind<Env>(TYPES.Sync_Env).toConstantValue(env)
if (configuration?.logger) { if (configuration?.logger) {
container.bind<winston.Logger>(TYPES.Sync_Logger).toConstantValue(configuration.logger as winston.Logger) logger = configuration.logger as winston.Logger
} else { } else {
const winstonFormatters = [winston.format.splat(), winston.format.json()] const winstonFormatters = [winston.format.splat(), winston.format.json()]
if (env.get('NEW_RELIC_ENABLED', true) === 'true') { if (env.get('NEW_RELIC_ENABLED', true) === 'true') {
@@ -114,15 +108,23 @@ export class ContainerConfigLoader {
winstonFormatters.push(newrelicWinstonFormatter()) winstonFormatters.push(newrelicWinstonFormatter())
} }
const logger = winston.createLogger({ logger = winston.createLogger({
level: env.get('LOG_LEVEL', true) || 'info', level: env.get('LOG_LEVEL', true) || 'info',
format: winston.format.combine(...winstonFormatters), format: winston.format.combine(...winstonFormatters),
transports: [new winston.transports.Console({ level: env.get('LOG_LEVEL', true) || 'info' })], transports: [new winston.transports.Console({ level: env.get('LOG_LEVEL', true) || 'info' })],
defaultMeta: { service: 'syncing-server' }, defaultMeta: { service: 'syncing-server' },
}) })
container.bind<winston.Logger>(TYPES.Sync_Logger).toConstantValue(logger)
} }
container.bind<winston.Logger>(TYPES.Sync_Logger).toConstantValue(logger)
const appDataSource = new AppDataSource(env)
await appDataSource.initialize()
logger.debug('Database initialized')
const isConfiguredForHomeServer = env.get('MODE', true) === 'home-server'
container.bind<Env>(TYPES.Sync_Env).toConstantValue(env)
if (isConfiguredForHomeServer) { if (isConfiguredForHomeServer) {
container container
@@ -517,6 +519,8 @@ export class ContainerConfigLoader {
) )
} }
logger.debug('Configuration complete')
return container return container
} }
} }
@@ -77,7 +77,7 @@ export class AppDataSource {
const sqliteDataSourceOptions: SqliteConnectionOptions = { const sqliteDataSourceOptions: SqliteConnectionOptions = {
...commonDataSourceOptions, ...commonDataSourceOptions,
type: 'sqlite', type: 'sqlite',
database: `data/${this.env.get('DB_DATABASE')}.sqlite`, database: this.env.get('DB_SQLITE_DATABASE_PATH'),
} }
this.dataSource = new DataSource(sqliteDataSourceOptions) this.dataSource = new DataSource(sqliteDataSourceOptions)