Compare commits

...

16 Commits

Author SHA1 Message Date
standardci
b0baaf9ea6 chore(release): publish new version
- @standardnotes/analytics@2.21.3
 - @standardnotes/api-gateway@1.49.6
 - @standardnotes/auth-server@1.93.6
 - @standardnotes/event-store@1.7.5
 - @standardnotes/files-server@1.10.7
 - @standardnotes/revisions-server@1.12.9
 - @standardnotes/scheduler-server@1.17.7
 - @standardnotes/syncing-server@1.32.2
 - @standardnotes/websockets-server@1.6.8
2023-03-09 12:43:53 +00:00
Karol Sójko
b7c6dab3ad chore: upgrade node version to latest LTS 2023-03-09 13:30:16 +01:00
standardci
2daa145867 chore(release): publish new version
- @standardnotes/auth-server@1.93.5
2023-03-09 10:02:53 +00:00
Karol Sójko
4bd5fb22b4 fix(auth): remove migrate email settings procedure 2023-03-09 10:48:40 +01:00
standardci
78533a6045 chore(release): publish new version
- @standardnotes/auth-server@1.93.4
2023-03-09 06:25:32 +00:00
Karol Sójko
e1c533a15e fix(auth): change response from verifying authenticator registration 2023-03-09 07:09:43 +01:00
standardci
b6c2bb8023 chore(release): publish new version
- @standardnotes/auth-server@1.93.3
2023-03-09 05:59:55 +00:00
Karol Sójko
c45653a50a fix(auth): remove authenticator names from server 2023-03-09 06:46:35 +01:00
Karol Sójko
d827513b73 fix(auth): migrate encrypted sign in settings 2023-03-09 06:34:50 +01:00
standardci
ad183ca621 chore(release): publish new version
- @standardnotes/auth-server@1.93.2
2023-03-08 13:22:34 +00:00
Karol Sójko
1d11c5a186 fix(auth): authentication options 2023-03-08 14:08:40 +01:00
standardci
e84e78ec55 chore(release): publish new version
- @standardnotes/auth-server@1.93.1
2023-03-08 12:57:57 +00:00
Karol Sójko
f91e4316ff fix(auth): migrate muted email notifications settings 2023-03-08 13:42:45 +01:00
standardci
d54b812881 chore(release): publish new version
- @standardnotes/analytics@2.21.2
 - @standardnotes/api-gateway@1.49.5
 - @standardnotes/auth-server@1.93.0
 - @standardnotes/domain-core@1.12.0
 - @standardnotes/files-server@1.10.6
 - @standardnotes/revisions-server@1.12.8
 - @standardnotes/scheduler-server@1.17.6
 - @standardnotes/settings@1.20.1
 - @standardnotes/syncing-server@1.32.1
 - @standardnotes/websockets-server@1.6.7
2023-03-08 10:09:09 +00:00
Karol Sójko
28dc5ba2a4 fix(auth): setting name value objects in typeorm queries 2023-03-08 10:54:48 +01:00
Karol Sójko
979a320ca6 feat(domain-core): add internal team user role (#473)
* feat(domain-core): add internal team user role

* feat(auth): add internal team user role

* chore: upgrade @standardnotes/features

---------

Co-authored-by: Karol Sójko <karolsojko@protonmail.com>
2023-03-08 10:45:50 +01:00
66 changed files with 241 additions and 273 deletions

2
.nvmrc
View File

@@ -1 +1 @@
18.13.0
18.15.0

14
.pnp.cjs generated
View File

@@ -4163,7 +4163,7 @@ const RAW_RUNTIME_STATE =
["@standardnotes/domain-core", "workspace:packages/domain-core"],\
["@standardnotes/domain-events", "workspace:packages/domain-events"],\
["@standardnotes/domain-events-infra", "workspace:packages/domain-events-infra"],\
["@standardnotes/features", "npm:1.58.4"],\
["@standardnotes/features", "npm:1.58.9"],\
["@standardnotes/predicates", "workspace:packages/predicates"],\
["@standardnotes/responses", "npm:1.13.9"],\
["@standardnotes/security", "workspace:packages/security"],\
@@ -4348,10 +4348,10 @@ const RAW_RUNTIME_STATE =
}]\
]],\
["@standardnotes/features", [\
["npm:1.58.4", {\
"packageLocation": "./.yarn/cache/@standardnotes-features-npm-1.58.4-a84962d125-a39afc145a.zip/node_modules/@standardnotes/features/",\
["npm:1.58.8", {\
"packageLocation": "./.yarn/cache/@standardnotes-features-npm-1.58.8-d97ff2aae1-77bac7d0a0.zip/node_modules/@standardnotes/features/",\
"packageDependencies": [\
["@standardnotes/features", "npm:1.58.4"],\
["@standardnotes/features", "npm:1.58.8"],\
["@standardnotes/common", "workspace:packages/common"],\
["@standardnotes/domain-core", "workspace:packages/domain-core"],\
["@standardnotes/security", "workspace:packages/security"],\
@@ -4359,10 +4359,10 @@ const RAW_RUNTIME_STATE =
],\
"linkType": "HARD"\
}],\
["npm:1.58.8", {\
"packageLocation": "./.yarn/cache/@standardnotes-features-npm-1.58.8-d97ff2aae1-77bac7d0a0.zip/node_modules/@standardnotes/features/",\
["npm:1.58.9", {\
"packageLocation": "./.yarn/cache/@standardnotes-features-npm-1.58.9-c278f712cd-218350ee55.zip/node_modules/@standardnotes/features/",\
"packageDependencies": [\
["@standardnotes/features", "npm:1.58.8"],\
["@standardnotes/features", "npm:1.58.9"],\
["@standardnotes/common", "workspace:packages/common"],\
["@standardnotes/domain-core", "workspace:packages/domain-core"],\
["@standardnotes/security", "workspace:packages/security"],\

View File

@@ -1,4 +1,4 @@
FROM node:18.13.0-alpine
FROM node:18.15.0-alpine
ENV NODE_ENV production

View File

@@ -3,6 +3,14 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [2.21.3](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.21.2...@standardnotes/analytics@2.21.3) (2023-03-09)
**Note:** Version bump only for package @standardnotes/analytics
## [2.21.2](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.21.1...@standardnotes/analytics@2.21.2) (2023-03-08)
**Note:** Version bump only for package @standardnotes/analytics
## [2.21.1](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.21.0...@standardnotes/analytics@2.21.1) (2023-02-23)
### Bug Fixes

View File

@@ -1,4 +1,4 @@
FROM node:18.13.0-alpine
FROM node:18.15.0-alpine
RUN apk add --update \
curl \

View File

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

View File

@@ -3,6 +3,14 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.49.6](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.49.5...@standardnotes/api-gateway@1.49.6) (2023-03-09)
**Note:** Version bump only for package @standardnotes/api-gateway
## [1.49.5](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.49.4...@standardnotes/api-gateway@1.49.5) (2023-03-08)
**Note:** Version bump only for package @standardnotes/api-gateway
## [1.49.4](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.49.3...@standardnotes/api-gateway@1.49.4) (2023-02-25)
**Note:** Version bump only for package @standardnotes/api-gateway

View File

@@ -1,4 +1,4 @@
FROM node:18.13.0-alpine
FROM node:18.15.0-alpine
RUN apk add --update \
curl \

View File

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

View File

@@ -3,6 +3,51 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.93.6](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.93.5...@standardnotes/auth-server@1.93.6) (2023-03-09)
**Note:** Version bump only for package @standardnotes/auth-server
## [1.93.5](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.93.4...@standardnotes/auth-server@1.93.5) (2023-03-09)
### Bug Fixes
* **auth:** remove migrate email settings procedure ([4bd5fb2](https://github.com/standardnotes/server/commit/4bd5fb22b447b0e0fdb136aa46ddc812c8b272cd))
## [1.93.4](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.93.3...@standardnotes/auth-server@1.93.4) (2023-03-09)
### Bug Fixes
* **auth:** change response from verifying authenticator registration ([e1c533a](https://github.com/standardnotes/server/commit/e1c533a15e33e215e90fbe15d2d4994605eaa1bd))
## [1.93.3](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.93.2...@standardnotes/auth-server@1.93.3) (2023-03-09)
### Bug Fixes
* **auth:** migrate encrypted sign in settings ([d827513](https://github.com/standardnotes/server/commit/d827513b73a57fbdb72c3112f32dc2a296103450))
* **auth:** remove authenticator names from server ([c45653a](https://github.com/standardnotes/server/commit/c45653a50a9d25de1e0fc86127ff6931dc98406d))
## [1.93.2](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.93.1...@standardnotes/auth-server@1.93.2) (2023-03-08)
### Bug Fixes
* **auth:** authentication options ([1d11c5a](https://github.com/standardnotes/server/commit/1d11c5a1865f81ca57d0ad4313cc3df497b4c445))
## [1.93.1](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.93.0...@standardnotes/auth-server@1.93.1) (2023-03-08)
### Bug Fixes
* **auth:** migrate muted email notifications settings ([f91e431](https://github.com/standardnotes/server/commit/f91e4316ff4993d032c016bb233b93a9f3356cf3))
# [1.93.0](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.92.0...@standardnotes/auth-server@1.93.0) (2023-03-08)
### Bug Fixes
* **auth:** setting name value objects in typeorm queries ([28dc5ba](https://github.com/standardnotes/server/commit/28dc5ba2a4e946b7aed86432da160c0be76f839d))
### Features
* **domain-core:** add internal team user role ([#473](https://github.com/standardnotes/server/issues/473)) ([979a320](https://github.com/standardnotes/server/commit/979a320ca666991ad2b023436f58c59ae168c768))
# [1.92.0](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.91.2...@standardnotes/auth-server@1.92.0) (2023-03-08)
### Features

View File

@@ -1,4 +1,4 @@
FROM node:18.13.0-alpine
FROM node:18.15.0-alpine
RUN apk add --update \
curl \

View File

@@ -1,137 +0,0 @@
import 'reflect-metadata'
import 'newrelic'
import { Stream } from 'stream'
import { Logger } from 'winston'
import * as dayjs from 'dayjs'
import * as utc from 'dayjs/plugin/utc'
import { ContainerConfigLoader } from '../src/Bootstrap/Container'
import TYPES from '../src/Bootstrap/Types'
import { Env } from '../src/Bootstrap/Env'
import { DomainEventPublisherInterface } from '@standardnotes/domain-events'
import { DomainEventFactoryInterface } from '../src/Domain/Event/DomainEventFactoryInterface'
import { SettingRepositoryInterface } from '../src/Domain/Setting/SettingRepositoryInterface'
import { SettingName } from '@standardnotes/settings'
import { EmailLevel } from '@standardnotes/domain-core'
import { UserSubscriptionServiceInterface } from '../src/Domain/Subscription/UserSubscriptionServiceInterface'
import { UserRepositoryInterface } from '../src/Domain/User/UserRepositoryInterface'
import { SubscriptionSettingServiceInterface } from '../src/Domain/Setting/SubscriptionSettingServiceInterface'
import { EncryptionVersion } from '../src/Domain/Encryption/EncryptionVersion'
const requestSettingMigration = async (
settingRepository: SettingRepositoryInterface,
subscriptionSettingService: SubscriptionSettingServiceInterface,
userRepository: UserRepositoryInterface,
userSubscriptionService: UserSubscriptionServiceInterface,
domainEventFactory: DomainEventFactoryInterface,
domainEventPublisher: DomainEventPublisherInterface,
): Promise<void> => {
const stream = await settingRepository.streamAllByNameAndValue(
SettingName.create(SettingName.NAMES.MuteSignInEmails).getValue(),
'not_muted',
)
return new Promise((resolve, reject) => {
stream
.pipe(
new Stream.Transform({
objectMode: true,
transform: async (setting, _encoding, callback) => {
const user = await userRepository.findOneByUuid(setting.setting_user_uuid)
if (!user) {
callback()
return
}
const { regularSubscription, sharedSubscription } =
await userSubscriptionService.findRegularSubscriptionForUserUuid(user.uuid)
const subscription = sharedSubscription ?? regularSubscription
if (!subscription) {
await domainEventPublisher.publish(
domainEventFactory.createMuteEmailsSettingChangedEvent({
username: user.email,
mute: true,
emailSubscriptionRejectionLevel: EmailLevel.LEVELS.SignIn,
}),
)
await settingRepository.deleteByUserUuid({
userUuid: user.uuid,
settingName: SettingName.NAMES.MuteSignInEmails,
})
callback()
return
}
await subscriptionSettingService.createOrReplace({
userSubscription: subscription,
props: {
name: SettingName.NAMES.MuteSignInEmails,
sensitive: false,
serverEncryptionVersion: EncryptionVersion.Unencrypted,
unencryptedValue: 'not_muted',
},
})
await settingRepository.deleteByUserUuid({
userUuid: user.uuid,
settingName: SettingName.NAMES.MuteSignInEmails,
})
callback()
},
}),
)
.on('finish', resolve)
.on('error', reject)
})
}
const container = new ContainerConfigLoader()
void container.load().then((container) => {
dayjs.extend(utc)
const env: Env = new Env()
env.load()
const logger: Logger = container.get(TYPES.Logger)
logger.info('Starting migration of mute sign in emails settings to subscription settings...')
const settingRepository: SettingRepositoryInterface = container.get(TYPES.SettingRepository)
const domainEventFactory: DomainEventFactoryInterface = container.get(TYPES.DomainEventFactory)
const domainEventPublisher: DomainEventPublisherInterface = container.get(TYPES.DomainEventPublisher)
const subscriptionSettingService: SubscriptionSettingServiceInterface = container.get(
TYPES.SubscriptionSettingService,
)
const userRepository: UserRepositoryInterface = container.get(TYPES.UserRepository)
const userSubscriptionService: UserSubscriptionServiceInterface = container.get(TYPES.UserSubscriptionService)
Promise.resolve(
requestSettingMigration(
settingRepository,
subscriptionSettingService,
userRepository,
userSubscriptionService,
domainEventFactory,
domainEventPublisher,
),
)
.then(() => {
logger.info('Migration of mute sign in emails settings to subscription settings finished successfully.')
process.exit(0)
})
.catch((error) => {
logger.error(`Migration of mute sign in emails settings to subscription settings failed: ${error.message}`)
process.exit(1)
})
})

View File

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

View File

@@ -40,11 +40,6 @@ case "$COMMAND" in
node docker/entrypoint-user-email-backup.js $EMAIL
;;
'migrate-email-settings' )
echo "[Docker] Starting Email Settings Migration..."
node docker/entrypoint-migrate-email-settings.js
;;
'dropbox-daily-backup' )
echo "[Docker] Starting Dropbox Daily Backup..."
node docker/entrypoint-backup.js dropbox daily

View File

@@ -0,0 +1,26 @@
import { MigrationInterface, QueryRunner } from 'typeorm'
export class addInternalTeamUserRole1678266947362 implements MigrationInterface {
public async up(queryRunner: QueryRunner): Promise<void> {
// remove beta files user role and permission
await queryRunner.query('DELETE FROM `role_permissions` WHERE role_uuid="1cd9ee6e-bc95-4f32-957c-d8c41f94d4ef"')
await queryRunner.query('DELETE FROM `user_roles` WHERE role_uuid="1cd9ee6e-bc95-4f32-957c-d8c41f94d4ef"')
await queryRunner.query('DELETE FROM `roles` WHERE name="FILES_BETA_USER"')
await queryRunner.query('DELETE FROM `permissions` WHERE name="app:files-beta"')
// add internal team user role and permission
await queryRunner.query(
'INSERT INTO `roles` (uuid, name, version) VALUES ("9f8d2313-e8d0-48ad-b19c-026601d0ddf4", "INTERNAL_TEAM_USER", 1)',
)
await queryRunner.query(
'INSERT INTO `permissions` (uuid, name) VALUES ("fb13e7d3-936f-4ded-a543-e1650cc99dfd", "server:universal-second-factor")',
)
await queryRunner.query(
'INSERT INTO `role_permissions` (role_uuid, permission_uuid) VALUES ("9f8d2313-e8d0-48ad-b19c-026601d0ddf4", "fb13e7d3-936f-4ded-a543-e1650cc99dfd")',
)
}
public async down(): Promise<void> {
return
}
}

View File

@@ -0,0 +1,13 @@
import { MigrationInterface, QueryRunner } from 'typeorm'
export class removeAuthenticatorNamesFromServer1678340701766 implements MigrationInterface {
name = 'removeAuthenticatorNamesFromServer1678340701766'
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query('ALTER TABLE `authenticators` DROP COLUMN `name`')
}
public async down(): Promise<void> {
return
}
}

View File

@@ -1,6 +1,6 @@
{
"name": "@standardnotes/auth-server",
"version": "1.92.0",
"version": "1.93.6",
"engines": {
"node": ">=18.0.0 <19.0.0"
},
@@ -45,7 +45,7 @@
"@standardnotes/domain-core": "workspace:^",
"@standardnotes/domain-events": "workspace:*",
"@standardnotes/domain-events-infra": "workspace:*",
"@standardnotes/features": "^1.58.4",
"@standardnotes/features": "^1.58.9",
"@standardnotes/predicates": "workspace:*",
"@standardnotes/responses": "^1.13.9",
"@standardnotes/security": "workspace:*",

View File

@@ -88,7 +88,6 @@ export class AuthenticatorsController {
): Promise<HttpResponse<VerifyAuthenticatorRegistrationResponseResponseBody>> {
const result = await this.verifyAuthenticatorRegistrationResponse.execute({
userUuid: params.userUuid,
name: params.name,
attestationResponse: params.attestationResponse,
})
@@ -105,7 +104,7 @@ export class AuthenticatorsController {
return {
status: HttpStatusCode.Success,
data: { success: result.getValue() },
data: { id: result.getValue().toString() },
}
}

View File

@@ -6,7 +6,6 @@ describe('Authenticator', () => {
it('should create an entity', () => {
const entityOrError = Authenticator.create({
counter: 1,
name: 'my-key',
credentialBackedUp: true,
credentialDeviceType: 'singleDevice',
credentialId: Buffer.from('credentialId'),

View File

@@ -1,7 +1,6 @@
import { Dates, Uuid } from '@standardnotes/domain-core'
export interface AuthenticatorProps {
name: string
userUuid: Uuid
credentialId: Uint8Array
credentialPublicKey: Uint8Array

View File

@@ -343,7 +343,7 @@ describe('FeatureService', () => {
])
const nonSubscriptionRole = {
name: RoleName.NAMES.FilesBetaUser,
name: RoleName.NAMES.InternalTeamUser,
uuid: 'role-files-beta',
permissions: Promise.resolve([nonSubscriptionPermission]),
} as jest.Mocked<Role>

View File

@@ -27,7 +27,7 @@ describe('RoleToSubscriptionMap', () => {
name: RoleName.NAMES.CoreUser,
} as jest.Mocked<Role>,
{
name: RoleName.NAMES.FilesBetaUser,
name: RoleName.NAMES.InternalTeamUser,
} as jest.Mocked<Role>,
{
name: RoleName.NAMES.PlusUser,
@@ -38,7 +38,7 @@ describe('RoleToSubscriptionMap', () => {
name: RoleName.NAMES.CoreUser,
},
{
name: RoleName.NAMES.FilesBetaUser,
name: RoleName.NAMES.InternalTeamUser,
},
])
})
@@ -49,7 +49,7 @@ describe('RoleToSubscriptionMap', () => {
name: RoleName.NAMES.CoreUser,
} as jest.Mocked<Role>,
{
name: RoleName.NAMES.FilesBetaUser,
name: RoleName.NAMES.InternalTeamUser,
} as jest.Mocked<Role>,
{
name: RoleName.NAMES.PlusUser,

View File

@@ -12,7 +12,7 @@ export class RoleToSubscriptionMap implements RoleToSubscriptionMapInterface {
[RoleName.NAMES.ProUser, SubscriptionName.ProPlan],
])
private readonly nonSubscriptionRoles = [RoleName.NAMES.CoreUser, RoleName.NAMES.FilesBetaUser]
private readonly nonSubscriptionRoles = [RoleName.NAMES.CoreUser, RoleName.NAMES.InternalTeamUser]
filterNonSubscriptionRoles(roles: Role[]): Array<Role> {
return roles.filter((role) => this.nonSubscriptionRoles.includes(role.name))

View File

@@ -11,6 +11,7 @@ export interface SettingRepositoryInterface {
findLastByNameAndUserUuid(name: string, userUuid: string): Promise<Setting | null>
findAllByUserUuid(userUuid: string): Promise<Setting[]>
streamAllByNameAndValue(name: SettingName, value: string): Promise<ReadStream>
streamAllByName(name: SettingName): Promise<ReadStream>
deleteByUserUuid(dto: DeleteSettingDto): Promise<void>
save(setting: Setting): Promise<Setting>
}

View File

@@ -12,7 +12,6 @@ describe('DeleteAuthenticator', () => {
beforeEach(() => {
authenticator = Authenticator.create({
counter: 1,
name: 'my-key',
credentialBackedUp: true,
credentialDeviceType: 'singleDevice',
credentialId: Buffer.from('credentialId'),

View File

@@ -24,7 +24,6 @@ describe('GenerateAuthenticatorAuthenticationOptions', () => {
beforeEach(() => {
const authenticator = Authenticator.create({
counter: 1,
name: 'my-key',
credentialBackedUp: true,
credentialDeviceType: 'singleDevice',
credentialId: Buffer.from('credentialId'),
@@ -54,7 +53,7 @@ describe('GenerateAuthenticatorAuthenticationOptions', () => {
})
expect(result.isFailed()).toBe(true)
expect(result.getError()).toBe('Could not generate authenticator registration options: Username cannot be empty')
expect(result.getError()).toBe('Could not generate authenticator authentication options: Username cannot be empty')
})
it('should return error if user uuid is not valid', async () => {
@@ -70,7 +69,7 @@ describe('GenerateAuthenticatorAuthenticationOptions', () => {
expect(result.isFailed()).toBe(true)
expect(result.getError()).toBe(
'Could not generate authenticator registration options: Given value is not a valid uuid: invalid',
'Could not generate authenticator authentication options: Given value is not a valid uuid: invalid',
)
})
@@ -97,7 +96,7 @@ describe('GenerateAuthenticatorAuthenticationOptions', () => {
})
expect(result.isFailed()).toBe(true)
expect(result.getError()).toBe('Could not generate authenticator registration options: Oops')
expect(result.getError()).toBe('Could not generate authenticator authentication options: Oops')
mock.mockRestore()
})

View File

@@ -19,7 +19,7 @@ export class GenerateAuthenticatorAuthenticationOptions implements UseCaseInterf
async execute(dto: GenerateAuthenticatorAuthenticationOptionsDTO): Promise<Result<Record<string, unknown>>> {
const usernameOrError = Username.create(dto.username)
if (usernameOrError.isFailed()) {
return Result.fail(`Could not generate authenticator registration options: ${usernameOrError.getError()}`)
return Result.fail(`Could not generate authenticator authentication options: ${usernameOrError.getError()}`)
}
const username = usernameOrError.getValue()
@@ -46,7 +46,7 @@ export class GenerateAuthenticatorAuthenticationOptions implements UseCaseInterf
const userUuidOrError = Uuid.create(user.uuid)
if (userUuidOrError.isFailed()) {
return Result.fail(`Could not generate authenticator registration options: ${userUuidOrError.getError()}`)
return Result.fail(`Could not generate authenticator authentication options: ${userUuidOrError.getError()}`)
}
const userUuid = userUuidOrError.getValue()
@@ -67,7 +67,7 @@ export class GenerateAuthenticatorAuthenticationOptions implements UseCaseInterf
})
if (authenticatorChallengeOrError.isFailed()) {
return Result.fail(
`Could not generate authenticator registration options: ${authenticatorChallengeOrError.getError()}`,
`Could not generate authenticator authentication options: ${authenticatorChallengeOrError.getError()}`,
)
}
const authenticatorChallenge = authenticatorChallengeOrError.getValue()

View File

@@ -21,7 +21,6 @@ describe('GenerateAuthenticatorRegistrationOptions', () => {
beforeEach(() => {
const authenticator = Authenticator.create({
counter: 1,
name: 'my-key',
credentialBackedUp: true,
credentialDeviceType: 'singleDevice',
credentialId: Buffer.from('credentialId'),

View File

@@ -24,7 +24,6 @@ describe('VerifyAuthenticatorAuthenticationResponse', () => {
beforeEach(() => {
const authenticator = Authenticator.create({
counter: 1,
name: 'my-key',
credentialBackedUp: true,
credentialDeviceType: 'singleDevice',
credentialId: Buffer.from('credentialId'),

View File

@@ -38,7 +38,6 @@ describe('VerifyAuthenticatorRegistrationResponse', () => {
const result = await useCase.execute({
userUuid: 'invalid',
name: 'name',
attestationResponse: {
id: Buffer.from('id'),
rawId: Buffer.from('rawId'),
@@ -56,27 +55,6 @@ describe('VerifyAuthenticatorRegistrationResponse', () => {
)
})
it('should return error if name is invalid', async () => {
const useCase = createUseCase()
const result = await useCase.execute({
userUuid: '00000000-0000-0000-0000-000000000000',
name: '',
attestationResponse: {
id: Buffer.from('id'),
rawId: Buffer.from('rawId'),
response: {
attestationObject: Buffer.from('attestationObject'),
clientDataJSON: Buffer.from('clientDataJSON'),
},
type: 'type',
},
})
expect(result.isFailed()).toBeTruthy()
expect(result.getError()).toEqual('Could not verify authenticator registration response: Given value is empty: ')
})
it('should return error if challenge is not found', async () => {
authenticatorChallengeRepository.findByUserUuid = jest.fn().mockReturnValue(null)
@@ -84,7 +62,6 @@ describe('VerifyAuthenticatorRegistrationResponse', () => {
const result = await useCase.execute({
userUuid: '00000000-0000-0000-0000-000000000000',
name: 'name',
attestationResponse: {
id: Buffer.from('id'),
rawId: Buffer.from('rawId'),
@@ -125,7 +102,6 @@ describe('VerifyAuthenticatorRegistrationResponse', () => {
const result = await useCase.execute({
userUuid: '00000000-0000-0000-0000-000000000000',
name: 'name',
attestationResponse: {
id: Buffer.from('id'),
rawId: Buffer.from('rawId'),
@@ -159,7 +135,6 @@ describe('VerifyAuthenticatorRegistrationResponse', () => {
const result = await useCase.execute({
userUuid: '00000000-0000-0000-0000-000000000000',
name: 'name',
attestationResponse: {
id: Buffer.from('id'),
rawId: Buffer.from('rawId'),
@@ -195,7 +170,6 @@ describe('VerifyAuthenticatorRegistrationResponse', () => {
const result = await useCase.execute({
userUuid: '00000000-0000-0000-0000-000000000000',
name: 'name',
attestationResponse: {
id: Buffer.from('id'),
rawId: Buffer.from('rawId'),
@@ -245,7 +219,6 @@ describe('VerifyAuthenticatorRegistrationResponse', () => {
const result = await useCase.execute({
userUuid: '00000000-0000-0000-0000-000000000000',
name: 'name',
attestationResponse: {
id: Buffer.from('id'),
rawId: Buffer.from('rawId'),
@@ -289,7 +262,6 @@ describe('VerifyAuthenticatorRegistrationResponse', () => {
const result = await useCase.execute({
userUuid: '00000000-0000-0000-0000-000000000000',
name: 'name',
attestationResponse: {
id: Buffer.from('id'),
rawId: Buffer.from('rawId'),

View File

@@ -1,4 +1,4 @@
import { Dates, Result, UseCaseInterface, Uuid, Validator } from '@standardnotes/domain-core'
import { Dates, Result, UniqueEntityId, UseCaseInterface, Uuid } from '@standardnotes/domain-core'
import { VerifiedRegistrationResponse, verifyRegistrationResponse } from '@simplewebauthn/server'
import { AuthenticatorChallengeRepositoryInterface } from '../../Authenticator/AuthenticatorChallengeRepositoryInterface'
@@ -6,7 +6,7 @@ import { AuthenticatorRepositoryInterface } from '../../Authenticator/Authentica
import { Authenticator } from '../../Authenticator/Authenticator'
import { VerifyAuthenticatorRegistrationResponseDTO } from './VerifyAuthenticatorRegistrationResponseDTO'
export class VerifyAuthenticatorRegistrationResponse implements UseCaseInterface<boolean> {
export class VerifyAuthenticatorRegistrationResponse implements UseCaseInterface<UniqueEntityId> {
constructor(
private authenticatorRepository: AuthenticatorRepositoryInterface,
private authenticatorChallengeRepository: AuthenticatorChallengeRepositoryInterface,
@@ -15,18 +15,13 @@ export class VerifyAuthenticatorRegistrationResponse implements UseCaseInterface
private requireUserVerification: boolean,
) {}
async execute(dto: VerifyAuthenticatorRegistrationResponseDTO): Promise<Result<boolean>> {
async execute(dto: VerifyAuthenticatorRegistrationResponseDTO): Promise<Result<UniqueEntityId>> {
const userUuidOrError = Uuid.create(dto.userUuid)
if (userUuidOrError.isFailed()) {
return Result.fail(`Could not verify authenticator registration response: ${userUuidOrError.getError()}`)
}
const userUuid = userUuidOrError.getValue()
const nameValidation = Validator.isNotEmpty(dto.name)
if (nameValidation.isFailed()) {
return Result.fail(`Could not verify authenticator registration response: ${nameValidation.getError()}`)
}
const authenticatorChallenge = await this.authenticatorChallengeRepository.findByUserUuid(userUuid)
if (!authenticatorChallenge) {
return Result.fail('Could not verify authenticator registration response: challenge not found')
@@ -55,7 +50,6 @@ export class VerifyAuthenticatorRegistrationResponse implements UseCaseInterface
const authenticatorOrError = Authenticator.create({
userUuid,
name: dto.name,
counter: verification.registrationInfo.counter,
credentialBackedUp: verification.registrationInfo.credentialBackedUp,
credentialDeviceType: verification.registrationInfo.credentialDeviceType,
@@ -71,6 +65,6 @@ export class VerifyAuthenticatorRegistrationResponse implements UseCaseInterface
await this.authenticatorRepository.save(authenticator)
return Result.ok(true)
return Result.ok(authenticator.id)
}
}

View File

@@ -1,5 +1,4 @@
export interface VerifyAuthenticatorRegistrationResponseDTO {
userUuid: string
name: string
attestationResponse: Record<string, unknown>
}

View File

@@ -1,4 +1,3 @@
export interface AuthenticatorHttpProjection {
id: string
name: string
}

View File

@@ -1,5 +1,4 @@
export interface VerifyAuthenticatorRegistrationResponseRequestParams {
userUuid: string
name: string
attestationResponse: Record<string, unknown>
}

View File

@@ -1,3 +1,3 @@
export interface VerifyAuthenticatorRegistrationResponseResponseBody {
success: boolean
id: string
}

View File

@@ -52,7 +52,6 @@ export class InversifyExpressAuthenticatorsController extends BaseHttpController
const result = await this.authenticatorsController.verifyRegistrationResponse({
userUuid: response.locals.user.uuid,
attestationResponse: request.body.attestationResponse,
name: request.body.name,
})
return this.json(result.data, result.status)

View File

@@ -19,20 +19,31 @@ export class MySQLSettingRepository implements SettingRepositoryInterface {
}
async findOneByUuidAndNames(uuid: string, names: SettingName[]): Promise<Setting | null> {
const nameValues = names.map((name) => name.value)
return this.ormRepository
.createQueryBuilder('setting')
.where('setting.uuid = :uuid AND setting.name IN (:...names)', {
names,
names: nameValues,
uuid,
})
.getOne()
}
async streamAllByName(name: SettingName): Promise<ReadStream> {
return this.ormRepository
.createQueryBuilder('setting')
.where('setting.name = :name', {
name: name.value,
})
.orderBy('updated_at', 'ASC')
.stream()
}
async streamAllByNameAndValue(name: SettingName, value: string): Promise<ReadStream> {
return this.ormRepository
.createQueryBuilder('setting')
.where('setting.name = :name AND setting.value = :value', {
name,
name: name.value,
value,
})
.orderBy('updated_at', 'ASC')

View File

@@ -11,13 +11,6 @@ export class TypeORMAuthenticator {
})
declare userUuid: string
@Column({
name: 'name',
type: 'varchar',
length: 255,
})
declare name: string
@Column({
name: 'credential_id',
type: 'text',

View File

@@ -11,7 +11,6 @@ export class AuthenticatorHttpMapper implements MapperInterface<Authenticator, A
toProjection(domain: Authenticator): AuthenticatorHttpProjection {
return {
id: domain.id.toString(),
name: domain.props.name,
}
}
}

View File

@@ -20,7 +20,6 @@ export class AuthenticatorPersistenceMapper implements MapperInterface<Authentic
const authenticatorOrError = Authenticator.create(
{
userUuid,
name: projection.name,
counter: projection.counter,
credentialBackedUp: projection.credentialBackedUp,
credentialDeviceType: projection.credentialDeviceType,
@@ -43,7 +42,6 @@ export class AuthenticatorPersistenceMapper implements MapperInterface<Authentic
const typeorm = new TypeORMAuthenticator()
typeorm.uuid = domain.id.toString()
typeorm.name = domain.props.name
typeorm.userUuid = domain.props.userUuid.value
typeorm.credentialId = Buffer.from(domain.props.credentialId).toString('base64url')
typeorm.credentialPublicKey = Buffer.from(domain.props.credentialPublicKey.buffer)

View File

@@ -3,6 +3,12 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
# [1.12.0](https://github.com/standardnotes/server/compare/@standardnotes/domain-core@1.11.3...@standardnotes/domain-core@1.12.0) (2023-03-08)
### Features
* **domain-core:** add internal team user role ([#473](https://github.com/standardnotes/server/issues/473)) ([979a320](https://github.com/standardnotes/server/commit/979a320ca666991ad2b023436f58c59ae168c768))
## [1.11.3](https://github.com/standardnotes/server/compare/@standardnotes/domain-core@1.11.2...@standardnotes/domain-core@1.11.3) (2023-02-15)
### Bug Fixes

View File

@@ -1,6 +1,6 @@
{
"name": "@standardnotes/domain-core",
"version": "1.11.3",
"version": "1.12.0",
"engines": {
"node": ">=18.0.0 <19.0.0"
},

View File

@@ -20,19 +20,26 @@ describe('RoleName', () => {
const proUserRole = RoleName.create(RoleName.NAMES.ProUser).getValue()
const plusUserRole = RoleName.create(RoleName.NAMES.PlusUser).getValue()
const coreUser = RoleName.create(RoleName.NAMES.CoreUser).getValue()
const internalTeamUser = RoleName.create(RoleName.NAMES.InternalTeamUser).getValue()
expect(internalTeamUser.hasMoreOrEqualPowerTo(proUserRole)).toBeTruthy()
expect(internalTeamUser.hasMoreOrEqualPowerTo(proUserRole)).toBeTruthy()
expect(internalTeamUser.hasMoreOrEqualPowerTo(plusUserRole)).toBeTruthy()
expect(internalTeamUser.hasMoreOrEqualPowerTo(coreUser)).toBeTruthy()
expect(proUserRole.hasMoreOrEqualPowerTo(internalTeamUser)).toBeFalsy()
expect(proUserRole.hasMoreOrEqualPowerTo(proUserRole)).toBeTruthy()
expect(proUserRole.hasMoreOrEqualPowerTo(plusUserRole)).toBeTruthy()
expect(proUserRole.hasMoreOrEqualPowerTo(coreUser)).toBeTruthy()
expect(plusUserRole.hasMoreOrEqualPowerTo(internalTeamUser)).toBeFalsy()
expect(plusUserRole.hasMoreOrEqualPowerTo(proUserRole)).toBeFalsy()
expect(plusUserRole.hasMoreOrEqualPowerTo(plusUserRole)).toBeTruthy()
expect(plusUserRole.hasMoreOrEqualPowerTo(coreUser)).toBeTruthy()
expect(coreUser.hasMoreOrEqualPowerTo(internalTeamUser)).toBeFalsy()
expect(coreUser.hasMoreOrEqualPowerTo(proUserRole)).toBeFalsy()
expect(coreUser.hasMoreOrEqualPowerTo(plusUserRole)).toBeFalsy()
expect(coreUser.hasMoreOrEqualPowerTo(coreUser)).toBeTruthy()
expect(RoleName.create(RoleName.NAMES.FilesBetaUser).getValue().hasMoreOrEqualPowerTo(coreUser)).toBeFalsy()
})
})

View File

@@ -7,7 +7,7 @@ export class RoleName extends ValueObject<RoleNameProps> {
CoreUser: 'CORE_USER',
PlusUser: 'PLUS_USER',
ProUser: 'PRO_USER',
FilesBetaUser: 'FILES_BETA_USER',
InternalTeamUser: 'INTERNAL_TEAM_USER',
}
get value(): string {
@@ -16,14 +16,17 @@ export class RoleName extends ValueObject<RoleNameProps> {
hasMoreOrEqualPowerTo(roleName: RoleName): boolean {
switch (this.value) {
case RoleName.NAMES.ProUser:
case RoleName.NAMES.InternalTeamUser:
return true
case RoleName.NAMES.ProUser:
return [RoleName.NAMES.CoreUser, RoleName.NAMES.PlusUser, RoleName.NAMES.ProUser].includes(roleName.value)
case RoleName.NAMES.PlusUser:
return [RoleName.NAMES.CoreUser, RoleName.NAMES.PlusUser].includes(roleName.value)
case RoleName.NAMES.CoreUser:
return [RoleName.NAMES.CoreUser].includes(roleName.value)
/*istanbul ignore next*/
default:
return false
throw new Error(`Invalid role name: ${this.value}`)
}
}

View File

@@ -3,6 +3,10 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.7.5](https://github.com/standardnotes/server/compare/@standardnotes/event-store@1.7.4...@standardnotes/event-store@1.7.5) (2023-03-09)
**Note:** Version bump only for package @standardnotes/event-store
## [1.7.4](https://github.com/standardnotes/server/compare/@standardnotes/event-store@1.7.3...@standardnotes/event-store@1.7.4) (2023-02-23)
**Note:** Version bump only for package @standardnotes/event-store

View File

@@ -1,4 +1,4 @@
FROM node:18.13.0-alpine
FROM node:18.15.0-alpine
RUN apk add --update \
curl \

View File

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

View File

@@ -3,6 +3,14 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.10.7](https://github.com/standardnotes/files/compare/@standardnotes/files-server@1.10.6...@standardnotes/files-server@1.10.7) (2023-03-09)
**Note:** Version bump only for package @standardnotes/files-server
## [1.10.6](https://github.com/standardnotes/files/compare/@standardnotes/files-server@1.10.5...@standardnotes/files-server@1.10.6) (2023-03-08)
**Note:** Version bump only for package @standardnotes/files-server
## [1.10.5](https://github.com/standardnotes/files/compare/@standardnotes/files-server@1.10.4...@standardnotes/files-server@1.10.5) (2023-02-23)
**Note:** Version bump only for package @standardnotes/files-server

View File

@@ -1,4 +1,4 @@
FROM node:18.13.0-alpine
FROM node:18.15.0-alpine
RUN apk add --update \
curl \

View File

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

View File

@@ -3,6 +3,14 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.12.9](https://github.com/standardnotes/server/compare/@standardnotes/revisions-server@1.12.8...@standardnotes/revisions-server@1.12.9) (2023-03-09)
**Note:** Version bump only for package @standardnotes/revisions-server
## [1.12.8](https://github.com/standardnotes/server/compare/@standardnotes/revisions-server@1.12.7...@standardnotes/revisions-server@1.12.8) (2023-03-08)
**Note:** Version bump only for package @standardnotes/revisions-server
## [1.12.7](https://github.com/standardnotes/server/compare/@standardnotes/revisions-server@1.12.6...@standardnotes/revisions-server@1.12.7) (2023-03-01)
**Note:** Version bump only for package @standardnotes/revisions-server

View File

@@ -1,4 +1,4 @@
FROM node:18.13.0-alpine
FROM node:18.15.0-alpine
RUN apk add --update \
curl \

View File

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

View File

@@ -3,6 +3,14 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.17.7](https://github.com/standardnotes/server/compare/@standardnotes/scheduler-server@1.17.6...@standardnotes/scheduler-server@1.17.7) (2023-03-09)
**Note:** Version bump only for package @standardnotes/scheduler-server
## [1.17.6](https://github.com/standardnotes/server/compare/@standardnotes/scheduler-server@1.17.5...@standardnotes/scheduler-server@1.17.6) (2023-03-08)
**Note:** Version bump only for package @standardnotes/scheduler-server
## [1.17.5](https://github.com/standardnotes/server/compare/@standardnotes/scheduler-server@1.17.4...@standardnotes/scheduler-server@1.17.5) (2023-02-23)
**Note:** Version bump only for package @standardnotes/scheduler-server

View File

@@ -1,4 +1,4 @@
FROM node:18.13.0-alpine
FROM node:18.15.0-alpine
RUN apk add --update \
curl \

View File

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

View File

@@ -3,6 +3,10 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.20.1](https://github.com/standardnotes/server/compare/@standardnotes/settings@1.20.0...@standardnotes/settings@1.20.1) (2023-03-08)
**Note:** Version bump only for package @standardnotes/settings
# [1.20.0](https://github.com/standardnotes/server/compare/@standardnotes/settings@1.19.1...@standardnotes/settings@1.20.0) (2023-03-08)
### Features

View File

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

View File

@@ -3,6 +3,14 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.32.2](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.32.1...@standardnotes/syncing-server@1.32.2) (2023-03-09)
**Note:** Version bump only for package @standardnotes/syncing-server
## [1.32.1](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.32.0...@standardnotes/syncing-server@1.32.1) (2023-03-08)
**Note:** Version bump only for package @standardnotes/syncing-server
# [1.32.0](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.31.8...@standardnotes/syncing-server@1.32.0) (2023-03-08)
### Features

View File

@@ -1,4 +1,4 @@
FROM node:18.13.0-alpine
FROM node:18.15.0-alpine
RUN apk add --update \
curl \

View File

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

View File

@@ -3,6 +3,14 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.6.8](https://github.com/standardnotes/server/compare/@standardnotes/websockets-server@1.6.7...@standardnotes/websockets-server@1.6.8) (2023-03-09)
**Note:** Version bump only for package @standardnotes/websockets-server
## [1.6.7](https://github.com/standardnotes/server/compare/@standardnotes/websockets-server@1.6.6...@standardnotes/websockets-server@1.6.7) (2023-03-08)
**Note:** Version bump only for package @standardnotes/websockets-server
## [1.6.6](https://github.com/standardnotes/server/compare/@standardnotes/websockets-server@1.6.5...@standardnotes/websockets-server@1.6.6) (2023-03-01)
**Note:** Version bump only for package @standardnotes/websockets-server

View File

@@ -1,4 +1,4 @@
FROM node:18.13.0-alpine
FROM node:18.15.0-alpine
RUN apk add --update \
curl \

View File

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

View File

@@ -3284,7 +3284,7 @@ __metadata:
"@standardnotes/domain-core": "workspace:^"
"@standardnotes/domain-events": "workspace:*"
"@standardnotes/domain-events-infra": "workspace:*"
"@standardnotes/features": "npm:^1.58.4"
"@standardnotes/features": "npm:^1.58.9"
"@standardnotes/predicates": "workspace:*"
"@standardnotes/responses": "npm:^1.13.9"
"@standardnotes/security": "workspace:*"
@@ -3331,7 +3331,7 @@ __metadata:
languageName: unknown
linkType: soft
"@standardnotes/common@npm:^1.46.4, @standardnotes/common@workspace:*, @standardnotes/common@workspace:^, @standardnotes/common@workspace:packages/common":
"@standardnotes/common@npm:^1.46.4, @standardnotes/common@npm:^1.46.6, @standardnotes/common@workspace:*, @standardnotes/common@workspace:^, @standardnotes/common@workspace:packages/common":
version: 0.0.0-use.local
resolution: "@standardnotes/common@workspace:packages/common"
dependencies:
@@ -3359,7 +3359,7 @@ __metadata:
languageName: node
linkType: hard
"@standardnotes/domain-core@npm:^1.11.1, @standardnotes/domain-core@npm:^1.11.3, @standardnotes/domain-core@workspace:^, @standardnotes/domain-core@workspace:packages/domain-core":
"@standardnotes/domain-core@npm:^1.11.3, @standardnotes/domain-core@workspace:^, @standardnotes/domain-core@workspace:packages/domain-core":
version: 0.0.0-use.local
resolution: "@standardnotes/domain-core@workspace:packages/domain-core"
dependencies:
@@ -3467,15 +3467,15 @@ __metadata:
languageName: node
linkType: hard
"@standardnotes/features@npm:^1.58.4":
version: 1.58.4
resolution: "@standardnotes/features@npm:1.58.4"
"@standardnotes/features@npm:^1.58.9":
version: 1.58.9
resolution: "@standardnotes/features@npm:1.58.9"
dependencies:
"@standardnotes/common": "npm:^1.46.4"
"@standardnotes/domain-core": "npm:^1.11.1"
"@standardnotes/security": "npm:^1.7.5"
"@standardnotes/common": "npm:^1.46.6"
"@standardnotes/domain-core": "npm:^1.11.3"
"@standardnotes/security": "npm:^1.7.6"
reflect-metadata: "npm:^0.1.13"
checksum: a39afc145a158985d46a4332aaa450722cffd0978391958536ed37ba9d465616ea59c0e7df70490634cb3849fc41443334cfa4e3bb321dea903dc88198c84ec1
checksum: 218350ee55d2f920e26c4041e1e307655cf9e755b83c7fd2165be2222d95b40154c0d325a362cc84ce960ccf8c07c6d95c6a8558ddabf6ee335462cf6bd22508
languageName: node
linkType: hard
@@ -3649,7 +3649,7 @@ __metadata:
languageName: unknown
linkType: soft
"@standardnotes/security@npm:^1.7.5, @standardnotes/security@workspace:*, @standardnotes/security@workspace:^, @standardnotes/security@workspace:packages/security":
"@standardnotes/security@npm:^1.7.5, @standardnotes/security@npm:^1.7.6, @standardnotes/security@workspace:*, @standardnotes/security@workspace:^, @standardnotes/security@workspace:packages/security":
version: 0.0.0-use.local
resolution: "@standardnotes/security@workspace:packages/security"
dependencies: