mirror of
https://github.com/standardnotes/server
synced 2026-05-11 21:57:17 -04:00
Compare commits
15 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 8070c70152 | |||
| c3ebb321cf | |||
| e54deb594a | |||
| 432d071ec8 | |||
| b9c06f1f5d | |||
| 52cc6462a6 | |||
| 35c2afef67 | |||
| 339c86fca0 | |||
| 0afd3de977 | |||
| e699569d46 | |||
| ced852d9db | |||
| a63612613e | |||
| c9ec7b492a | |||
| bf8ffc07ee | |||
| 73e1ea7f93 |
@@ -2506,6 +2506,7 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) {
|
|||||||
["@newrelic/winston-enricher", "virtual:04783e12400851b8a3d76e71495851cc94959db6e62f04cb0a31190080629440b182d8c8eb4d7f2b04e281912f2783a5fd4d2c3c6ab68d38b7097246c93f4c19#npm:4.0.0"],\
|
["@newrelic/winston-enricher", "virtual:04783e12400851b8a3d76e71495851cc94959db6e62f04cb0a31190080629440b182d8c8eb4d7f2b04e281912f2783a5fd4d2c3c6ab68d38b7097246c93f4c19#npm:4.0.0"],\
|
||||||
["@sentry/node", "npm:7.5.0"],\
|
["@sentry/node", "npm:7.5.0"],\
|
||||||
["@standardnotes/analytics", "workspace:packages/analytics"],\
|
["@standardnotes/analytics", "workspace:packages/analytics"],\
|
||||||
|
["@standardnotes/common", "workspace:packages/common"],\
|
||||||
["@standardnotes/domain-events", "workspace:packages/domain-events"],\
|
["@standardnotes/domain-events", "workspace:packages/domain-events"],\
|
||||||
["@standardnotes/domain-events-infra", "workspace:packages/domain-events-infra"],\
|
["@standardnotes/domain-events-infra", "workspace:packages/domain-events-infra"],\
|
||||||
["@standardnotes/security", "workspace:packages/security"],\
|
["@standardnotes/security", "workspace:packages/security"],\
|
||||||
|
|||||||
@@ -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.28.0](https://github.com/standardnotes/server/compare/@standardnotes/analytics@1.27.0...@standardnotes/analytics@1.28.0) (2022-09-09)
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **syncing-server:** add tracking files count in stats ([52cc646](https://github.com/standardnotes/server/commit/52cc6462a66dae3bd6c05f551d4ba661c8a9b8c8))
|
||||||
|
|
||||||
|
# [1.27.0](https://github.com/standardnotes/server/compare/@standardnotes/analytics@1.26.0...@standardnotes/analytics@1.27.0) (2022-09-09)
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **api-gateway:** add tracking general activity for free and paid users breakdown ([0afd3de](https://github.com/standardnotes/server/commit/0afd3de9779e2abe10deede24626a3cbe6b15e6c))
|
||||||
|
|
||||||
|
# [1.26.0](https://github.com/standardnotes/server/compare/@standardnotes/analytics@1.25.0...@standardnotes/analytics@1.26.0) (2022-09-09)
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **syncing-server:** add statistics for notes count for free and paid users ([c9ec7b4](https://github.com/standardnotes/server/commit/c9ec7b492aea1911e441ed8ad9a155f871be2ef7))
|
||||||
|
|
||||||
# [1.25.0](https://github.com/standardnotes/server/compare/@standardnotes/analytics@1.24.0...@standardnotes/analytics@1.25.0) (2022-09-07)
|
# [1.25.0](https://github.com/standardnotes/server/compare/@standardnotes/analytics@1.24.0...@standardnotes/analytics@1.25.0) (2022-09-07)
|
||||||
|
|
||||||
### Features
|
### Features
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@standardnotes/analytics",
|
"name": "@standardnotes/analytics",
|
||||||
"version": "1.25.0",
|
"version": "1.28.0",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=14.0.0 <17.0.0"
|
"node": ">=14.0.0 <17.0.0"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
export enum AnalyticsActivity {
|
export enum AnalyticsActivity {
|
||||||
GeneralActivity = 'general-activity',
|
GeneralActivity = 'general-activity',
|
||||||
|
GeneralActivityFreeUsers = 'general-activity-free-users',
|
||||||
|
GeneralActivityPaidUsers = 'general-activity-paid-users',
|
||||||
EditingItems = 'editing-items',
|
EditingItems = 'editing-items',
|
||||||
|
CheckingIntegrity = 'checking-integrity',
|
||||||
Login = 'login',
|
Login = 'login',
|
||||||
Register = 'register',
|
Register = 'register',
|
||||||
DeleteAccount = 'DeleteAccount',
|
DeleteAccount = 'DeleteAccount',
|
||||||
|
|||||||
@@ -4,4 +4,7 @@ export enum StatisticsMeasure {
|
|||||||
RegistrationLength = 'registration-length',
|
RegistrationLength = 'registration-length',
|
||||||
RegistrationToSubscriptionTime = 'registration-to-subscription-time',
|
RegistrationToSubscriptionTime = 'registration-to-subscription-time',
|
||||||
Refunds = 'refunds',
|
Refunds = 'refunds',
|
||||||
|
NotesCountFreeUsers = 'notes-count-free-users',
|
||||||
|
NotesCountPaidUsers = 'notes-count-paid-users',
|
||||||
|
FilesCount = 'files-count',
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,36 @@
|
|||||||
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.19.1](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.19.0...@standardnotes/api-gateway@1.19.1) (2022-09-09)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/api-gateway
|
||||||
|
|
||||||
|
# [1.19.0](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.18.0...@standardnotes/api-gateway@1.19.0) (2022-09-09)
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **syncing-server:** add tracking files count in stats ([52cc646](https://github.com/standardnotes/api-gateway/commit/52cc6462a66dae3bd6c05f551d4ba661c8a9b8c8))
|
||||||
|
|
||||||
|
# [1.18.0](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.17.4...@standardnotes/api-gateway@1.18.0) (2022-09-09)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **api-gateway:** add general activity breakdown to yesterdays report stats ([339c86f](https://github.com/standardnotes/api-gateway/commit/339c86fca073b02054260417b7519c08874e1e4e))
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **api-gateway:** add tracking general activity for free and paid users breakdown ([0afd3de](https://github.com/standardnotes/api-gateway/commit/0afd3de9779e2abe10deede24626a3cbe6b15e6c))
|
||||||
|
|
||||||
|
## [1.17.4](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.17.3...@standardnotes/api-gateway@1.17.4) (2022-09-09)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **api-gateway:** add notes count statistics to report ([ced852d](https://github.com/standardnotes/api-gateway/commit/ced852d9dbf8cab4c235b94a834968a5fc5e7d36))
|
||||||
|
|
||||||
|
## [1.17.3](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.17.2...@standardnotes/api-gateway@1.17.3) (2022-09-09)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/api-gateway
|
||||||
|
|
||||||
## [1.17.2](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.17.1...@standardnotes/api-gateway@1.17.2) (2022-09-08)
|
## [1.17.2](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.17.1...@standardnotes/api-gateway@1.17.2) (2022-09-08)
|
||||||
|
|
||||||
### Bug Fixes
|
### Bug Fixes
|
||||||
|
|||||||
@@ -70,6 +70,8 @@ const requestReport = async (
|
|||||||
const yesterdayActivityNames = [
|
const yesterdayActivityNames = [
|
||||||
AnalyticsActivity.LimitedDiscountOfferPurchased,
|
AnalyticsActivity.LimitedDiscountOfferPurchased,
|
||||||
AnalyticsActivity.GeneralActivity,
|
AnalyticsActivity.GeneralActivity,
|
||||||
|
AnalyticsActivity.GeneralActivityFreeUsers,
|
||||||
|
AnalyticsActivity.GeneralActivityPaidUsers,
|
||||||
AnalyticsActivity.PaymentFailed,
|
AnalyticsActivity.PaymentFailed,
|
||||||
AnalyticsActivity.PaymentSuccess,
|
AnalyticsActivity.PaymentSuccess,
|
||||||
]
|
]
|
||||||
@@ -92,6 +94,9 @@ const requestReport = async (
|
|||||||
StatisticsMeasure.RegistrationLength,
|
StatisticsMeasure.RegistrationLength,
|
||||||
StatisticsMeasure.SubscriptionLength,
|
StatisticsMeasure.SubscriptionLength,
|
||||||
StatisticsMeasure.RegistrationToSubscriptionTime,
|
StatisticsMeasure.RegistrationToSubscriptionTime,
|
||||||
|
StatisticsMeasure.NotesCountFreeUsers,
|
||||||
|
StatisticsMeasure.NotesCountPaidUsers,
|
||||||
|
StatisticsMeasure.FilesCount,
|
||||||
]
|
]
|
||||||
const statisticMeasures = []
|
const statisticMeasures = []
|
||||||
for (const statisticMeasureName of statisticMeasureNames) {
|
for (const statisticMeasureName of statisticMeasureNames) {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@standardnotes/api-gateway",
|
"name": "@standardnotes/api-gateway",
|
||||||
"version": "1.17.2",
|
"version": "1.19.1",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=16.0.0 <17.0.0"
|
"node": ">=16.0.0 <17.0.0"
|
||||||
},
|
},
|
||||||
@@ -25,6 +25,7 @@
|
|||||||
"@newrelic/winston-enricher": "^4.0.0",
|
"@newrelic/winston-enricher": "^4.0.0",
|
||||||
"@sentry/node": "^7.3.0",
|
"@sentry/node": "^7.3.0",
|
||||||
"@standardnotes/analytics": "workspace:*",
|
"@standardnotes/analytics": "workspace:*",
|
||||||
|
"@standardnotes/common": "workspace:^",
|
||||||
"@standardnotes/domain-events": "workspace:*",
|
"@standardnotes/domain-events": "workspace:*",
|
||||||
"@standardnotes/domain-events-infra": "workspace:*",
|
"@standardnotes/domain-events-infra": "workspace:*",
|
||||||
"@standardnotes/security": "workspace:*",
|
"@standardnotes/security": "workspace:*",
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { CrossServiceTokenData } from '@standardnotes/security'
|
import { CrossServiceTokenData } from '@standardnotes/security'
|
||||||
|
import { RoleName } from '@standardnotes/common'
|
||||||
import { AnalyticsActivity, AnalyticsStoreInterface, Period } from '@standardnotes/analytics'
|
import { AnalyticsActivity, AnalyticsStoreInterface, Period } from '@standardnotes/analytics'
|
||||||
import { TimerInterface } from '@standardnotes/time'
|
import { TimerInterface } from '@standardnotes/time'
|
||||||
import { NextFunction, Request, Response } from 'express'
|
import { NextFunction, Request, Response } from 'express'
|
||||||
@@ -75,9 +76,20 @@ export class AuthMiddleware extends BaseMiddleware {
|
|||||||
|
|
||||||
const decodedToken = <CrossServiceTokenData>verify(crossServiceToken, this.jwtSecret, { algorithms: ['HS256'] })
|
const decodedToken = <CrossServiceTokenData>verify(crossServiceToken, this.jwtSecret, { algorithms: ['HS256'] })
|
||||||
|
|
||||||
await this.analyticsStore.markActivity([AnalyticsActivity.GeneralActivity], decodedToken.analyticsId as number, [
|
response.locals.freeUser =
|
||||||
Period.Today,
|
decodedToken.roles.length === 1 &&
|
||||||
])
|
decodedToken.roles.find((role) => role.name === RoleName.CoreUser) !== undefined
|
||||||
|
|
||||||
|
await this.analyticsStore.markActivity(
|
||||||
|
[
|
||||||
|
AnalyticsActivity.GeneralActivity,
|
||||||
|
response.locals.freeUser
|
||||||
|
? AnalyticsActivity.GeneralActivityFreeUsers
|
||||||
|
: AnalyticsActivity.GeneralActivityPaidUsers,
|
||||||
|
],
|
||||||
|
decodedToken.analyticsId as number,
|
||||||
|
[Period.Today],
|
||||||
|
)
|
||||||
|
|
||||||
if (this.crossServiceTokenCacheTTL && !crossServiceTokenFetchedFromCache) {
|
if (this.crossServiceTokenCacheTTL && !crossServiceTokenFetchedFromCache) {
|
||||||
await this.crossServiceTokenCache.set({
|
await this.crossServiceTokenCache.set({
|
||||||
|
|||||||
@@ -3,6 +3,22 @@
|
|||||||
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.25.11](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.25.10...@standardnotes/auth-server@1.25.11) (2022-09-09)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/auth-server
|
||||||
|
|
||||||
|
## [1.25.10](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.25.9...@standardnotes/auth-server@1.25.10) (2022-09-09)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/auth-server
|
||||||
|
|
||||||
|
## [1.25.9](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.25.8...@standardnotes/auth-server@1.25.9) (2022-09-09)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/auth-server
|
||||||
|
|
||||||
|
## [1.25.8](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.25.7...@standardnotes/auth-server@1.25.8) (2022-09-09)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/auth-server
|
||||||
|
|
||||||
## [1.25.7](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.25.6...@standardnotes/auth-server@1.25.7) (2022-09-08)
|
## [1.25.7](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.25.6...@standardnotes/auth-server@1.25.7) (2022-09-08)
|
||||||
|
|
||||||
**Note:** Version bump only for package @standardnotes/auth-server
|
**Note:** Version bump only for package @standardnotes/auth-server
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@standardnotes/auth-server",
|
"name": "@standardnotes/auth-server",
|
||||||
"version": "1.25.7",
|
"version": "1.25.11",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=16.0.0 <17.0.0"
|
"node": ">=16.0.0 <17.0.0"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -3,6 +3,12 @@
|
|||||||
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.32.0](https://github.com/standardnotes/server/compare/@standardnotes/common@1.31.0...@standardnotes/common@1.32.0) (2022-09-09)
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **common:** add either and only types ([c3ebb32](https://github.com/standardnotes/server/commit/c3ebb321cfacd20769ebfd99413e283859b6e260))
|
||||||
|
|
||||||
# [1.31.0](https://github.com/standardnotes/server/compare/@standardnotes/common@1.30.0...@standardnotes/common@1.31.0) (2022-09-05)
|
# [1.31.0](https://github.com/standardnotes/server/compare/@standardnotes/common@1.30.0...@standardnotes/common@1.31.0) (2022-09-05)
|
||||||
|
|
||||||
### Features
|
### Features
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@standardnotes/common",
|
"name": "@standardnotes/common",
|
||||||
"version": "1.31.0",
|
"version": "1.32.0",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=16.0.0 <17.0.0"
|
"node": ">=16.0.0 <17.0.0"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
import { Only } from './Only'
|
||||||
|
|
||||||
|
export type Either<T, U> = Only<T, U> | Only<U, T>
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
export type Only<T, U> = {
|
||||||
|
[P in keyof T]: T[P]
|
||||||
|
} & {
|
||||||
|
[P in keyof U]?: never
|
||||||
|
}
|
||||||
@@ -18,3 +18,5 @@ export * from './Protocol/ProtocolVersion'
|
|||||||
export * from './Role/PaidRoles'
|
export * from './Role/PaidRoles'
|
||||||
export * from './Role/RoleName'
|
export * from './Role/RoleName'
|
||||||
export * from './Subscription/SubscriptionName'
|
export * from './Subscription/SubscriptionName'
|
||||||
|
export * from './Type/Either'
|
||||||
|
export * from './Type/Only'
|
||||||
|
|||||||
@@ -3,6 +3,10 @@
|
|||||||
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.8.9](https://github.com/standardnotes/server/compare/@standardnotes/domain-events-infra@1.8.8...@standardnotes/domain-events-infra@1.8.9) (2022-09-09)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/domain-events-infra
|
||||||
|
|
||||||
## [1.8.8](https://github.com/standardnotes/server/compare/@standardnotes/domain-events-infra@1.8.7...@standardnotes/domain-events-infra@1.8.8) (2022-09-08)
|
## [1.8.8](https://github.com/standardnotes/server/compare/@standardnotes/domain-events-infra@1.8.7...@standardnotes/domain-events-infra@1.8.8) (2022-09-08)
|
||||||
|
|
||||||
**Note:** Version bump only for package @standardnotes/domain-events-infra
|
**Note:** Version bump only for package @standardnotes/domain-events-infra
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@standardnotes/domain-events-infra",
|
"name": "@standardnotes/domain-events-infra",
|
||||||
"version": "1.8.8",
|
"version": "1.8.9",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=16.0.0 <17.0.0"
|
"node": ">=16.0.0 <17.0.0"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -3,6 +3,10 @@
|
|||||||
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.
|
||||||
|
|
||||||
|
## [2.60.3](https://github.com/standardnotes/server/compare/@standardnotes/domain-events@2.60.2...@standardnotes/domain-events@2.60.3) (2022-09-09)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/domain-events
|
||||||
|
|
||||||
## [2.60.2](https://github.com/standardnotes/server/compare/@standardnotes/domain-events@2.60.1...@standardnotes/domain-events@2.60.2) (2022-09-08)
|
## [2.60.2](https://github.com/standardnotes/server/compare/@standardnotes/domain-events@2.60.1...@standardnotes/domain-events@2.60.2) (2022-09-08)
|
||||||
|
|
||||||
### Bug Fixes
|
### Bug Fixes
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@standardnotes/domain-events",
|
"name": "@standardnotes/domain-events",
|
||||||
"version": "2.60.2",
|
"version": "2.60.3",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=16.0.0 <17.0.0"
|
"node": ">=16.0.0 <17.0.0"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -3,6 +3,22 @@
|
|||||||
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.3.14](https://github.com/standardnotes/server/compare/@standardnotes/event-store@1.3.13...@standardnotes/event-store@1.3.14) (2022-09-09)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/event-store
|
||||||
|
|
||||||
|
## [1.3.13](https://github.com/standardnotes/server/compare/@standardnotes/event-store@1.3.12...@standardnotes/event-store@1.3.13) (2022-09-09)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **event-store:** add missing event subscriptions ([432d071](https://github.com/standardnotes/server/commit/432d071ec88a49f90513be6c55a06005a471b174))
|
||||||
|
|
||||||
|
## [1.3.12](https://github.com/standardnotes/server/compare/@standardnotes/event-store@1.3.11...@standardnotes/event-store@1.3.12) (2022-09-08)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **event-store:** add listening to refund processed event ([73e1ea7](https://github.com/standardnotes/server/commit/73e1ea7f93b7d7956dd4a82298098e81ff9c85b1))
|
||||||
|
|
||||||
## [1.3.11](https://github.com/standardnotes/server/compare/@standardnotes/event-store@1.3.10...@standardnotes/event-store@1.3.11) (2022-09-08)
|
## [1.3.11](https://github.com/standardnotes/server/compare/@standardnotes/event-store@1.3.10...@standardnotes/event-store@1.3.11) (2022-09-08)
|
||||||
|
|
||||||
**Note:** Version bump only for package @standardnotes/event-store
|
**Note:** Version bump only for package @standardnotes/event-store
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@standardnotes/event-store",
|
"name": "@standardnotes/event-store",
|
||||||
"version": "1.3.11",
|
"version": "1.3.14",
|
||||||
"description": "Event Store Service",
|
"description": "Event Store Service",
|
||||||
"private": true,
|
"private": true,
|
||||||
"main": "dist/src/index.js",
|
"main": "dist/src/index.js",
|
||||||
|
|||||||
@@ -80,6 +80,12 @@ export class ContainerConfigLoader {
|
|||||||
['PAYMENT_SUCCESS', container.get(TYPES.EventHandler)],
|
['PAYMENT_SUCCESS', container.get(TYPES.EventHandler)],
|
||||||
['ACCOUNT_CLAIM_REQUESTED', container.get(TYPES.EventHandler)],
|
['ACCOUNT_CLAIM_REQUESTED', container.get(TYPES.EventHandler)],
|
||||||
['SUBSCRIPTION_REVERT_REQUESTED', container.get(TYPES.EventHandler)],
|
['SUBSCRIPTION_REVERT_REQUESTED', container.get(TYPES.EventHandler)],
|
||||||
|
['REFUND_PROCESSED', container.get(TYPES.EventHandler)],
|
||||||
|
['ACCOUNT_RESET_REQUESTED', container.get(TYPES.EventHandler)],
|
||||||
|
['DISCOUNT_APPLIED', container.get(TYPES.EventHandler)],
|
||||||
|
['SUBSCRIPTION_RATE_ADJUSTED', container.get(TYPES.EventHandler)],
|
||||||
|
['REFUND_REQUESTED', container.get(TYPES.EventHandler)],
|
||||||
|
['INVOICE_GENERATED', container.get(TYPES.EventHandler)],
|
||||||
])
|
])
|
||||||
|
|
||||||
container
|
container
|
||||||
|
|||||||
@@ -3,6 +3,10 @@
|
|||||||
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.5.51](https://github.com/standardnotes/files/compare/@standardnotes/files-server@1.5.50...@standardnotes/files-server@1.5.51) (2022-09-09)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/files-server
|
||||||
|
|
||||||
## [1.5.50](https://github.com/standardnotes/files/compare/@standardnotes/files-server@1.5.49...@standardnotes/files-server@1.5.50) (2022-09-08)
|
## [1.5.50](https://github.com/standardnotes/files/compare/@standardnotes/files-server@1.5.49...@standardnotes/files-server@1.5.50) (2022-09-08)
|
||||||
|
|
||||||
**Note:** Version bump only for package @standardnotes/files-server
|
**Note:** Version bump only for package @standardnotes/files-server
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@standardnotes/files-server",
|
"name": "@standardnotes/files-server",
|
||||||
"version": "1.5.50",
|
"version": "1.5.51",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=16.0.0 <17.0.0"
|
"node": ">=16.0.0 <17.0.0"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -3,6 +3,10 @@
|
|||||||
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.4.1](https://github.com/standardnotes/server/compare/@standardnotes/predicates@1.4.0...@standardnotes/predicates@1.4.1) (2022-09-09)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/predicates
|
||||||
|
|
||||||
# [1.4.0](https://github.com/standardnotes/server/compare/@standardnotes/predicates@1.3.0...@standardnotes/predicates@1.4.0) (2022-09-05)
|
# [1.4.0](https://github.com/standardnotes/server/compare/@standardnotes/predicates@1.3.0...@standardnotes/predicates@1.4.0) (2022-09-05)
|
||||||
|
|
||||||
### Features
|
### Features
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@standardnotes/predicates",
|
"name": "@standardnotes/predicates",
|
||||||
"version": "1.4.0",
|
"version": "1.4.1",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=16.0.0 <17.0.0"
|
"node": ">=16.0.0 <17.0.0"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -3,6 +3,10 @@
|
|||||||
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.10.28](https://github.com/standardnotes/server/compare/@standardnotes/scheduler-server@1.10.27...@standardnotes/scheduler-server@1.10.28) (2022-09-09)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/scheduler-server
|
||||||
|
|
||||||
## [1.10.27](https://github.com/standardnotes/server/compare/@standardnotes/scheduler-server@1.10.26...@standardnotes/scheduler-server@1.10.27) (2022-09-08)
|
## [1.10.27](https://github.com/standardnotes/server/compare/@standardnotes/scheduler-server@1.10.26...@standardnotes/scheduler-server@1.10.27) (2022-09-08)
|
||||||
|
|
||||||
**Note:** Version bump only for package @standardnotes/scheduler-server
|
**Note:** Version bump only for package @standardnotes/scheduler-server
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@standardnotes/scheduler-server",
|
"name": "@standardnotes/scheduler-server",
|
||||||
"version": "1.10.27",
|
"version": "1.10.28",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=16.0.0 <17.0.0"
|
"node": ">=16.0.0 <17.0.0"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -3,6 +3,10 @@
|
|||||||
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.3.1](https://github.com/standardnotes/server/compare/@standardnotes/security@1.3.0...@standardnotes/security@1.3.1) (2022-09-09)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/security
|
||||||
|
|
||||||
# [1.3.0](https://github.com/standardnotes/server/compare/@standardnotes/security@1.2.6...@standardnotes/security@1.3.0) (2022-09-05)
|
# [1.3.0](https://github.com/standardnotes/server/compare/@standardnotes/security@1.2.6...@standardnotes/security@1.3.0) (2022-09-05)
|
||||||
|
|
||||||
### Features
|
### Features
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@standardnotes/security",
|
"name": "@standardnotes/security",
|
||||||
"version": "1.3.0",
|
"version": "1.3.1",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=16.0.0 <17.0.0"
|
"node": ">=16.0.0 <17.0.0"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -3,6 +3,26 @@
|
|||||||
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.8.1](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.8.0...@standardnotes/syncing-server@1.8.1) (2022-09-09)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/syncing-server
|
||||||
|
|
||||||
|
# [1.8.0](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.7.1...@standardnotes/syncing-server@1.8.0) (2022-09-09)
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **syncing-server:** add tracking files count in stats ([52cc646](https://github.com/standardnotes/syncing-server-js/commit/52cc6462a66dae3bd6c05f551d4ba661c8a9b8c8))
|
||||||
|
|
||||||
|
## [1.7.1](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.7.0...@standardnotes/syncing-server@1.7.1) (2022-09-09)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/syncing-server
|
||||||
|
|
||||||
|
# [1.7.0](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.6.70...@standardnotes/syncing-server@1.7.0) (2022-09-09)
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **syncing-server:** add statistics for notes count for free and paid users ([c9ec7b4](https://github.com/standardnotes/syncing-server-js/commit/c9ec7b492aea1911e441ed8ad9a155f871be2ef7))
|
||||||
|
|
||||||
## [1.6.70](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.6.69...@standardnotes/syncing-server@1.6.70) (2022-09-08)
|
## [1.6.70](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.6.69...@standardnotes/syncing-server@1.6.70) (2022-09-08)
|
||||||
|
|
||||||
**Note:** Version bump only for package @standardnotes/syncing-server
|
**Note:** Version bump only for package @standardnotes/syncing-server
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@standardnotes/syncing-server",
|
"name": "@standardnotes/syncing-server",
|
||||||
"version": "1.6.70",
|
"version": "1.8.1",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=16.0.0 <17.0.0"
|
"node": ">=16.0.0 <17.0.0"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ describe('AuthMiddleware', () => {
|
|||||||
next = jest.fn()
|
next = jest.fn()
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should authorize user from an auth JWT token if present', async () => {
|
it('should authorize a paid user from an auth JWT token if present', async () => {
|
||||||
const authToken = sign(
|
const authToken = sign(
|
||||||
{
|
{
|
||||||
user: { uuid: '123' },
|
user: { uuid: '123' },
|
||||||
@@ -66,6 +66,34 @@ describe('AuthMiddleware', () => {
|
|||||||
expect(response.locals.session).toEqual({ uuid: '234' })
|
expect(response.locals.session).toEqual({ uuid: '234' })
|
||||||
expect(response.locals.readOnlyAccess).toBeFalsy()
|
expect(response.locals.readOnlyAccess).toBeFalsy()
|
||||||
expect(response.locals.analyticsId).toEqual(123)
|
expect(response.locals.analyticsId).toEqual(123)
|
||||||
|
expect(response.locals.freeUser).toEqual(false)
|
||||||
|
|
||||||
|
expect(next).toHaveBeenCalled()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should authorize a free user from an auth JWT token if present', async () => {
|
||||||
|
const authToken = sign(
|
||||||
|
{
|
||||||
|
user: { uuid: '123' },
|
||||||
|
session: { uuid: '234' },
|
||||||
|
roles: [
|
||||||
|
{
|
||||||
|
uuid: '1-2-3',
|
||||||
|
name: RoleName.CoreUser,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
analyticsId: 123,
|
||||||
|
permissions: [],
|
||||||
|
},
|
||||||
|
jwtSecret,
|
||||||
|
{ algorithm: 'HS256' },
|
||||||
|
)
|
||||||
|
|
||||||
|
request.header = jest.fn().mockReturnValue(authToken)
|
||||||
|
|
||||||
|
await createMiddleware().handler(request, response, next)
|
||||||
|
|
||||||
|
expect(response.locals.freeUser).toEqual(true)
|
||||||
|
|
||||||
expect(next).toHaveBeenCalled()
|
expect(next).toHaveBeenCalled()
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import { verify } from 'jsonwebtoken'
|
|||||||
import { CrossServiceTokenData } from '@standardnotes/security'
|
import { CrossServiceTokenData } from '@standardnotes/security'
|
||||||
import * as winston from 'winston'
|
import * as winston from 'winston'
|
||||||
import TYPES from '../Bootstrap/Types'
|
import TYPES from '../Bootstrap/Types'
|
||||||
|
import { RoleName } from '@standardnotes/common'
|
||||||
|
|
||||||
@injectable()
|
@injectable()
|
||||||
export class AuthMiddleware extends BaseMiddleware {
|
export class AuthMiddleware extends BaseMiddleware {
|
||||||
@@ -27,6 +28,8 @@ export class AuthMiddleware extends BaseMiddleware {
|
|||||||
|
|
||||||
response.locals.user = decodedToken.user
|
response.locals.user = decodedToken.user
|
||||||
response.locals.roleNames = decodedToken.roles.map((role) => role.name)
|
response.locals.roleNames = decodedToken.roles.map((role) => role.name)
|
||||||
|
response.locals.freeUser =
|
||||||
|
response.locals.roleNames.length === 1 && response.locals.roleNames[0] === RoleName.CoreUser
|
||||||
response.locals.session = decodedToken.session
|
response.locals.session = decodedToken.session
|
||||||
response.locals.readOnlyAccess = decodedToken.session?.readonly_access ?? false
|
response.locals.readOnlyAccess = decodedToken.session?.readonly_access ?? false
|
||||||
response.locals.analyticsId = decodedToken.analyticsId
|
response.locals.analyticsId = decodedToken.analyticsId
|
||||||
|
|||||||
@@ -75,6 +75,7 @@ describe('ItemsController', () => {
|
|||||||
uuid: '123',
|
uuid: '123',
|
||||||
}
|
}
|
||||||
response.locals.analyticsId = 123
|
response.locals.analyticsId = 123
|
||||||
|
response.locals.freeUser = false
|
||||||
|
|
||||||
syncResponse = {} as jest.Mocked<SyncResponse20200115>
|
syncResponse = {} as jest.Mocked<SyncResponse20200115>
|
||||||
|
|
||||||
@@ -132,6 +133,8 @@ describe('ItemsController', () => {
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
userUuid: '123',
|
userUuid: '123',
|
||||||
|
analyticsId: 123,
|
||||||
|
freeUser: false,
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(result.statusCode).toEqual(200)
|
expect(result.statusCode).toEqual(200)
|
||||||
@@ -147,6 +150,8 @@ describe('ItemsController', () => {
|
|||||||
expect(checkIntegrity.execute).toHaveBeenCalledWith({
|
expect(checkIntegrity.execute).toHaveBeenCalledWith({
|
||||||
integrityPayloads: [],
|
integrityPayloads: [],
|
||||||
userUuid: '123',
|
userUuid: '123',
|
||||||
|
analyticsId: 123,
|
||||||
|
freeUser: false,
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(result.statusCode).toEqual(200)
|
expect(result.statusCode).toEqual(200)
|
||||||
|
|||||||
@@ -62,6 +62,8 @@ export class ItemsController extends BaseHttpController {
|
|||||||
const result = await this.checkIntegrity.execute({
|
const result = await this.checkIntegrity.execute({
|
||||||
userUuid: response.locals.user.uuid,
|
userUuid: response.locals.user.uuid,
|
||||||
integrityPayloads,
|
integrityPayloads,
|
||||||
|
analyticsId: response.locals.analyticsId,
|
||||||
|
freeUser: response.locals.freeUser,
|
||||||
})
|
})
|
||||||
|
|
||||||
return this.json(result)
|
return this.json(result)
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import 'reflect-metadata'
|
import 'reflect-metadata'
|
||||||
|
|
||||||
import { StatisticsStoreInterface } from '@standardnotes/analytics'
|
import { AnalyticsStoreInterface, Period, StatisticsStoreInterface } from '@standardnotes/analytics'
|
||||||
|
|
||||||
import { ItemRepositoryInterface } from '../../Item/ItemRepositoryInterface'
|
import { ItemRepositoryInterface } from '../../Item/ItemRepositoryInterface'
|
||||||
|
|
||||||
@@ -10,8 +10,9 @@ import { ContentType } from '@standardnotes/common'
|
|||||||
describe('CheckIntegrity', () => {
|
describe('CheckIntegrity', () => {
|
||||||
let itemRepository: ItemRepositoryInterface
|
let itemRepository: ItemRepositoryInterface
|
||||||
let statisticsStore: StatisticsStoreInterface
|
let statisticsStore: StatisticsStoreInterface
|
||||||
|
let analyticsStore: AnalyticsStoreInterface
|
||||||
|
|
||||||
const createUseCase = () => new CheckIntegrity(itemRepository, statisticsStore)
|
const createUseCase = () => new CheckIntegrity(itemRepository, statisticsStore, analyticsStore)
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
itemRepository = {} as jest.Mocked<ItemRepositoryInterface>
|
itemRepository = {} as jest.Mocked<ItemRepositoryInterface>
|
||||||
@@ -36,16 +37,28 @@ describe('CheckIntegrity', () => {
|
|||||||
updated_at_timestamp: 4,
|
updated_at_timestamp: 4,
|
||||||
content_type: ContentType.ItemsKey,
|
content_type: ContentType.ItemsKey,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
uuid: '5-6-7',
|
||||||
|
updated_at_timestamp: 5,
|
||||||
|
content_type: ContentType.File,
|
||||||
|
},
|
||||||
])
|
])
|
||||||
|
|
||||||
statisticsStore = {} as jest.Mocked<StatisticsStoreInterface>
|
statisticsStore = {} as jest.Mocked<StatisticsStoreInterface>
|
||||||
statisticsStore.incrementOutOfSyncIncidents = jest.fn()
|
statisticsStore.incrementOutOfSyncIncidents = jest.fn()
|
||||||
|
statisticsStore.incrementMeasure = jest.fn()
|
||||||
|
|
||||||
|
analyticsStore = {} as jest.Mocked<AnalyticsStoreInterface>
|
||||||
|
analyticsStore.wasActivityDone = jest.fn().mockReturnValue(false)
|
||||||
|
analyticsStore.markActivity = jest.fn()
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should return an empty result if there are no integrity mismatches', async () => {
|
it('should return an empty result if there are no integrity mismatches', async () => {
|
||||||
expect(
|
expect(
|
||||||
await createUseCase().execute({
|
await createUseCase().execute({
|
||||||
userUuid: '1-2-3',
|
userUuid: '1-2-3',
|
||||||
|
analyticsId: 1,
|
||||||
|
freeUser: false,
|
||||||
integrityPayloads: [
|
integrityPayloads: [
|
||||||
{
|
{
|
||||||
uuid: '1-2-3',
|
uuid: '1-2-3',
|
||||||
@@ -59,6 +72,10 @@ describe('CheckIntegrity', () => {
|
|||||||
uuid: '3-4-5',
|
uuid: '3-4-5',
|
||||||
updated_at_timestamp: 3,
|
updated_at_timestamp: 3,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
uuid: '5-6-7',
|
||||||
|
updated_at_timestamp: 5,
|
||||||
|
},
|
||||||
],
|
],
|
||||||
}),
|
}),
|
||||||
).toEqual({
|
).toEqual({
|
||||||
@@ -70,6 +87,8 @@ describe('CheckIntegrity', () => {
|
|||||||
expect(
|
expect(
|
||||||
await createUseCase().execute({
|
await createUseCase().execute({
|
||||||
userUuid: '1-2-3',
|
userUuid: '1-2-3',
|
||||||
|
analyticsId: 1,
|
||||||
|
freeUser: false,
|
||||||
integrityPayloads: [
|
integrityPayloads: [
|
||||||
{
|
{
|
||||||
uuid: '1-2-3',
|
uuid: '1-2-3',
|
||||||
@@ -83,6 +102,10 @@ describe('CheckIntegrity', () => {
|
|||||||
uuid: '3-4-5',
|
uuid: '3-4-5',
|
||||||
updated_at_timestamp: 3,
|
updated_at_timestamp: 3,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
uuid: '5-6-7',
|
||||||
|
updated_at_timestamp: 5,
|
||||||
|
},
|
||||||
],
|
],
|
||||||
}),
|
}),
|
||||||
).toEqual({
|
).toEqual({
|
||||||
@@ -101,6 +124,8 @@ describe('CheckIntegrity', () => {
|
|||||||
expect(
|
expect(
|
||||||
await createUseCase().execute({
|
await createUseCase().execute({
|
||||||
userUuid: '1-2-3',
|
userUuid: '1-2-3',
|
||||||
|
analyticsId: 1,
|
||||||
|
freeUser: false,
|
||||||
integrityPayloads: [
|
integrityPayloads: [
|
||||||
{
|
{
|
||||||
uuid: '1-2-3',
|
uuid: '1-2-3',
|
||||||
@@ -110,6 +135,10 @@ describe('CheckIntegrity', () => {
|
|||||||
uuid: '2-3-4',
|
uuid: '2-3-4',
|
||||||
updated_at_timestamp: 2,
|
updated_at_timestamp: 2,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
uuid: '5-6-7',
|
||||||
|
updated_at_timestamp: 5,
|
||||||
|
},
|
||||||
],
|
],
|
||||||
}),
|
}),
|
||||||
).toEqual({
|
).toEqual({
|
||||||
@@ -121,4 +150,87 @@ describe('CheckIntegrity', () => {
|
|||||||
],
|
],
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('should count notes for statistics of free users', async () => {
|
||||||
|
await createUseCase().execute({
|
||||||
|
userUuid: '1-2-3',
|
||||||
|
analyticsId: 1,
|
||||||
|
freeUser: true,
|
||||||
|
integrityPayloads: [
|
||||||
|
{
|
||||||
|
uuid: '1-2-3',
|
||||||
|
updated_at_timestamp: 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
uuid: '2-3-4',
|
||||||
|
updated_at_timestamp: 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
uuid: '3-4-5',
|
||||||
|
updated_at_timestamp: 3,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(statisticsStore.incrementMeasure).toHaveBeenCalledWith('notes-count-free-users', 3, [
|
||||||
|
Period.Today,
|
||||||
|
Period.ThisMonth,
|
||||||
|
])
|
||||||
|
expect(analyticsStore.markActivity).toHaveBeenCalledWith(['checking-integrity'], 1, [Period.Today])
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should count notes for statistics of paid users', async () => {
|
||||||
|
await createUseCase().execute({
|
||||||
|
userUuid: '1-2-3',
|
||||||
|
analyticsId: 1,
|
||||||
|
freeUser: false,
|
||||||
|
integrityPayloads: [
|
||||||
|
{
|
||||||
|
uuid: '1-2-3',
|
||||||
|
updated_at_timestamp: 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
uuid: '2-3-4',
|
||||||
|
updated_at_timestamp: 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
uuid: '3-4-5',
|
||||||
|
updated_at_timestamp: 3,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(statisticsStore.incrementMeasure).toHaveBeenCalledWith('notes-count-paid-users', 3, [
|
||||||
|
Period.Today,
|
||||||
|
Period.ThisMonth,
|
||||||
|
])
|
||||||
|
expect(analyticsStore.markActivity).toHaveBeenCalledWith(['checking-integrity'], 1, [Period.Today])
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should not count notes for statistics if they were already counted today', async () => {
|
||||||
|
analyticsStore.wasActivityDone = jest.fn().mockReturnValue(true)
|
||||||
|
|
||||||
|
await createUseCase().execute({
|
||||||
|
userUuid: '1-2-3',
|
||||||
|
analyticsId: 1,
|
||||||
|
freeUser: false,
|
||||||
|
integrityPayloads: [
|
||||||
|
{
|
||||||
|
uuid: '1-2-3',
|
||||||
|
updated_at_timestamp: 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
uuid: '2-3-4',
|
||||||
|
updated_at_timestamp: 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
uuid: '3-4-5',
|
||||||
|
updated_at_timestamp: 3,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(statisticsStore.incrementMeasure).not.toHaveBeenCalled()
|
||||||
|
expect(analyticsStore.markActivity).not.toHaveBeenCalled()
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,6 +1,12 @@
|
|||||||
import { inject, injectable } from 'inversify'
|
import { inject, injectable } from 'inversify'
|
||||||
import { IntegrityPayload } from '@standardnotes/payloads'
|
import { IntegrityPayload } from '@standardnotes/payloads'
|
||||||
import { StatisticsStoreInterface } from '@standardnotes/analytics'
|
import {
|
||||||
|
AnalyticsActivity,
|
||||||
|
AnalyticsStoreInterface,
|
||||||
|
Period,
|
||||||
|
StatisticsMeasure,
|
||||||
|
StatisticsStoreInterface,
|
||||||
|
} from '@standardnotes/analytics'
|
||||||
|
|
||||||
import TYPES from '../../../Bootstrap/Types'
|
import TYPES from '../../../Bootstrap/Types'
|
||||||
import { ItemRepositoryInterface } from '../../Item/ItemRepositoryInterface'
|
import { ItemRepositoryInterface } from '../../Item/ItemRepositoryInterface'
|
||||||
@@ -15,16 +21,27 @@ export class CheckIntegrity implements UseCaseInterface {
|
|||||||
constructor(
|
constructor(
|
||||||
@inject(TYPES.ItemRepository) private itemRepository: ItemRepositoryInterface,
|
@inject(TYPES.ItemRepository) private itemRepository: ItemRepositoryInterface,
|
||||||
@inject(TYPES.StatisticsStore) private statisticsStore: StatisticsStoreInterface,
|
@inject(TYPES.StatisticsStore) private statisticsStore: StatisticsStoreInterface,
|
||||||
|
@inject(TYPES.AnalyticsStore) private analyticsStore: AnalyticsStoreInterface,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
async execute(dto: CheckIntegrityDTO): Promise<CheckIntegrityResponse> {
|
async execute(dto: CheckIntegrityDTO): Promise<CheckIntegrityResponse> {
|
||||||
const serverItemIntegrityPayloads = await this.itemRepository.findItemsForComputingIntegrityPayloads(dto.userUuid)
|
const serverItemIntegrityPayloads = await this.itemRepository.findItemsForComputingIntegrityPayloads(dto.userUuid)
|
||||||
|
|
||||||
|
let notesCount = 0
|
||||||
|
let filesCount = 0
|
||||||
const serverItemIntegrityPayloadsMap = new Map<string, ExtendedIntegrityPayload>()
|
const serverItemIntegrityPayloadsMap = new Map<string, ExtendedIntegrityPayload>()
|
||||||
for (const serverItemIntegrityPayload of serverItemIntegrityPayloads) {
|
for (const serverItemIntegrityPayload of serverItemIntegrityPayloads) {
|
||||||
serverItemIntegrityPayloadsMap.set(serverItemIntegrityPayload.uuid, serverItemIntegrityPayload)
|
serverItemIntegrityPayloadsMap.set(serverItemIntegrityPayload.uuid, serverItemIntegrityPayload)
|
||||||
|
if (serverItemIntegrityPayload.content_type === ContentType.Note) {
|
||||||
|
notesCount++
|
||||||
|
}
|
||||||
|
if (serverItemIntegrityPayload.content_type === ContentType.File) {
|
||||||
|
filesCount++
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await this.saveNotesCountStatistics(dto.freeUser, dto.analyticsId, { notes: notesCount, files: filesCount })
|
||||||
|
|
||||||
const clientItemIntegrityPayloadsMap = new Map<string, number>()
|
const clientItemIntegrityPayloadsMap = new Map<string, number>()
|
||||||
for (const clientItemIntegrityPayload of dto.integrityPayloads) {
|
for (const clientItemIntegrityPayload of dto.integrityPayloads) {
|
||||||
clientItemIntegrityPayloadsMap.set(
|
clientItemIntegrityPayloadsMap.set(
|
||||||
@@ -74,4 +91,31 @@ export class CheckIntegrity implements UseCaseInterface {
|
|||||||
mismatches,
|
mismatches,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async saveNotesCountStatistics(
|
||||||
|
freeUser: boolean,
|
||||||
|
analyticsId: number,
|
||||||
|
counts: { notes: number; files: number },
|
||||||
|
) {
|
||||||
|
const integrityWasCheckedToday = await this.analyticsStore.wasActivityDone(
|
||||||
|
AnalyticsActivity.CheckingIntegrity,
|
||||||
|
analyticsId,
|
||||||
|
Period.Today,
|
||||||
|
)
|
||||||
|
|
||||||
|
if (!integrityWasCheckedToday) {
|
||||||
|
await this.analyticsStore.markActivity([AnalyticsActivity.CheckingIntegrity], analyticsId, [Period.Today])
|
||||||
|
|
||||||
|
await this.statisticsStore.incrementMeasure(
|
||||||
|
freeUser ? StatisticsMeasure.NotesCountFreeUsers : StatisticsMeasure.NotesCountPaidUsers,
|
||||||
|
counts.notes,
|
||||||
|
[Period.Today, Period.ThisMonth],
|
||||||
|
)
|
||||||
|
|
||||||
|
await this.statisticsStore.incrementMeasure(StatisticsMeasure.FilesCount, counts.files, [
|
||||||
|
Period.Today,
|
||||||
|
Period.ThisMonth,
|
||||||
|
])
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,4 +4,6 @@ import { IntegrityPayload } from '@standardnotes/payloads'
|
|||||||
export type CheckIntegrityDTO = {
|
export type CheckIntegrityDTO = {
|
||||||
userUuid: Uuid
|
userUuid: Uuid
|
||||||
integrityPayloads: IntegrityPayload[]
|
integrityPayloads: IntegrityPayload[]
|
||||||
|
freeUser: boolean
|
||||||
|
analyticsId: number
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1767,6 +1767,7 @@ __metadata:
|
|||||||
"@newrelic/winston-enricher": ^4.0.0
|
"@newrelic/winston-enricher": ^4.0.0
|
||||||
"@sentry/node": ^7.3.0
|
"@sentry/node": ^7.3.0
|
||||||
"@standardnotes/analytics": "workspace:*"
|
"@standardnotes/analytics": "workspace:*"
|
||||||
|
"@standardnotes/common": "workspace:^"
|
||||||
"@standardnotes/domain-events": "workspace:*"
|
"@standardnotes/domain-events": "workspace:*"
|
||||||
"@standardnotes/domain-events-infra": "workspace:*"
|
"@standardnotes/domain-events-infra": "workspace:*"
|
||||||
"@standardnotes/security": "workspace:*"
|
"@standardnotes/security": "workspace:*"
|
||||||
@@ -1884,7 +1885,7 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"@standardnotes/common@^1.19.1, @standardnotes/common@^1.23.1, @standardnotes/common@workspace:*, @standardnotes/common@workspace:packages/common":
|
"@standardnotes/common@^1.19.1, @standardnotes/common@^1.23.1, @standardnotes/common@workspace:*, @standardnotes/common@workspace:^, @standardnotes/common@workspace:packages/common":
|
||||||
version: 0.0.0-use.local
|
version: 0.0.0-use.local
|
||||||
resolution: "@standardnotes/common@workspace:packages/common"
|
resolution: "@standardnotes/common@workspace:packages/common"
|
||||||
dependencies:
|
dependencies:
|
||||||
|
|||||||
Reference in New Issue
Block a user