mirror of
https://github.com/standardnotes/server
synced 2026-07-14 00:01:54 -04:00
fix: functionality
This commit is contained in:
@@ -10,8 +10,8 @@ export class ItemSharesController extends BaseHttpController {
|
||||
super()
|
||||
}
|
||||
|
||||
@all('(/*)?')
|
||||
@all('*')
|
||||
async subscriptions(request: Request, response: Response): Promise<void> {
|
||||
await this.httpService.callSyncingServer(request, response, request.path, request.body)
|
||||
await this.httpService.callSyncingServer(request, response, request.path.replace('/v1/', ''), request.body)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import 'newrelic'
|
||||
|
||||
import '../src/Controller/HealthCheckController'
|
||||
import '../src/Controller/ItemsController'
|
||||
import '../src/Controller/ItemSharesController'
|
||||
|
||||
import helmet from 'helmet'
|
||||
import * as cors from 'cors'
|
||||
|
||||
@@ -9,9 +9,19 @@ export class CreateItemShare1683714734321 implements MigrationInterface {
|
||||
columns: [
|
||||
new TableColumn({
|
||||
name: 'uuid',
|
||||
type: 'uuid',
|
||||
type: 'varchar',
|
||||
length: '36',
|
||||
isPrimary: true,
|
||||
default: 'gen_random_uuid()',
|
||||
}),
|
||||
new TableColumn({
|
||||
name: 'user_uuid',
|
||||
type: 'varchar',
|
||||
length: '36',
|
||||
}),
|
||||
new TableColumn({
|
||||
name: 'item_uuid',
|
||||
type: 'varchar',
|
||||
length: '36',
|
||||
}),
|
||||
new TableColumn({
|
||||
name: 'share_token',
|
||||
@@ -35,16 +45,6 @@ export class CreateItemShare1683714734321 implements MigrationInterface {
|
||||
type: 'text',
|
||||
isNullable: true,
|
||||
}),
|
||||
new TableColumn({
|
||||
name: 'user_uuid',
|
||||
type: 'varchar',
|
||||
length: '36',
|
||||
}),
|
||||
new TableColumn({
|
||||
name: 'item_uuid',
|
||||
type: 'varchar',
|
||||
length: '36',
|
||||
}),
|
||||
new TableColumn({
|
||||
name: 'expired',
|
||||
type: 'tinyint',
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { ItemShare } from './../Domain/ItemShare/ItemShare'
|
||||
import { TypeORMItemShareRepository } from './../Infra/TypeORM/TypeORMItemShareRepository'
|
||||
import * as winston from 'winston'
|
||||
import { Container, interfaces } from 'inversify'
|
||||
|
||||
@@ -19,7 +21,6 @@ import { Timer, TimerInterface } from '@standardnotes/time'
|
||||
import { ItemTransferCalculatorInterface } from '../Domain/Item/ItemTransferCalculatorInterface'
|
||||
import { ItemTransferCalculator } from '../Domain/Item/ItemTransferCalculator'
|
||||
import { ItemShareRepositoryInterface } from '../Domain/ItemShare/ItemShareRepositoryInterface'
|
||||
import { TypeORMItemShareRepository } from '../Infra/TypeORM/TypeORMItemShareRepository'
|
||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||
const newrelicFormatter = require('@newrelic/winston-enricher')
|
||||
|
||||
@@ -81,11 +82,14 @@ export class CommonContainerConfigLoader {
|
||||
container
|
||||
.bind<ItemShareRepositoryInterface>(TYPES.ItemShareRepository)
|
||||
.toDynamicValue((context: interfaces.Context) => {
|
||||
return new TypeORMItemShareRepository(context.container.get(TYPES.ORMItemRepository))
|
||||
return new TypeORMItemShareRepository(context.container.get(TYPES.ORMItemShareRepository))
|
||||
})
|
||||
|
||||
// ORM
|
||||
container.bind<Repository<Item>>(TYPES.ORMItemRepository).toDynamicValue(() => AppDataSource.getRepository(Item))
|
||||
container
|
||||
.bind<Repository<ItemShare>>(TYPES.ORMItemShareRepository)
|
||||
.toDynamicValue(() => AppDataSource.getRepository(ItemShare))
|
||||
|
||||
// Projectors
|
||||
container
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { ItemShare } from './../Domain/ItemShare/ItemShare'
|
||||
import { DataSource, LoggerOptions } from 'typeorm'
|
||||
import { MysqlConnectionOptions } from 'typeorm/driver/mysql/MysqlConnectionOptions'
|
||||
import { Item } from '../Domain/Item/Item'
|
||||
@@ -38,7 +39,7 @@ const replicationConfig = {
|
||||
|
||||
const commonDataSourceOptions = {
|
||||
maxQueryExecutionTime,
|
||||
entities: [Item],
|
||||
entities: [Item, ItemShare],
|
||||
migrations: [`dist/migrations/${isConfiguredForMySQL ? 'mysql' : 'sqlite'}/*.js`],
|
||||
migrationsRun: true,
|
||||
logging: <LoggerOptions>env.get('DB_DEBUG_LEVEL'),
|
||||
|
||||
@@ -36,6 +36,7 @@ import { ItemShareService } from '../Domain/ItemShare/ItemShareService'
|
||||
import { ItemShareFactoryInterface } from '../Domain/ItemShare/ItemShareFactoryInterface'
|
||||
import { ItemShareFactory } from '../Domain/ItemShare/ItemShareFactory'
|
||||
import { ShareItemUseCase } from '../Domain/UseCase/ItemShare/ShareItemUseCase'
|
||||
import { GetUserItemSharesUseCase } from '../Domain/UseCase/ItemShare/GetUserItemSharesUseCase'
|
||||
|
||||
export class ServerContainerConfigLoader extends CommonContainerConfigLoader {
|
||||
private readonly DEFAULT_CONTENT_SIZE_TRANSFER_LIMIT = 10_000_000
|
||||
@@ -100,6 +101,9 @@ export class ServerContainerConfigLoader extends CommonContainerConfigLoader {
|
||||
container.bind<UpdateSharedItemUseCase>(TYPES.UpdateSharedItem).toDynamicValue((context: interfaces.Context) => {
|
||||
return new UpdateSharedItemUseCase(context.container.get(TYPES.ItemShareService))
|
||||
})
|
||||
container.bind<GetUserItemSharesUseCase>(TYPES.GetUserItemShares).toDynamicValue((context: interfaces.Context) => {
|
||||
return new GetUserItemSharesUseCase(context.container.get(TYPES.ItemShareService))
|
||||
})
|
||||
|
||||
// Services
|
||||
container.bind<ItemServiceInterface>(TYPES.ItemService).toDynamicValue((context: interfaces.Context) => {
|
||||
@@ -119,7 +123,7 @@ export class ServerContainerConfigLoader extends CommonContainerConfigLoader {
|
||||
)
|
||||
})
|
||||
// Services
|
||||
container.bind<ItemShareServiceInterface>(TYPES.ItemService).toDynamicValue((context: interfaces.Context) => {
|
||||
container.bind<ItemShareServiceInterface>(TYPES.ItemShareService).toDynamicValue((context: interfaces.Context) => {
|
||||
return new ItemShareService(
|
||||
context.container.get(TYPES.ItemShareRepository),
|
||||
context.container.get(TYPES.ItemShareFactory),
|
||||
@@ -152,7 +156,7 @@ export class ServerContainerConfigLoader extends CommonContainerConfigLoader {
|
||||
container.bind<ItemFactoryInterface>(TYPES.ItemFactory).toDynamicValue((context: interfaces.Context) => {
|
||||
return new ItemFactory(context.container.get(TYPES.Timer), context.container.get(TYPES.ItemProjector))
|
||||
})
|
||||
container.bind<ItemShareFactoryInterface>(TYPES.ItemFactory).toDynamicValue((context: interfaces.Context) => {
|
||||
container.bind<ItemShareFactoryInterface>(TYPES.ItemShareFactory).toDynamicValue((context: interfaces.Context) => {
|
||||
return new ItemShareFactory(context.container.get(TYPES.Timer))
|
||||
})
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ const TYPES = {
|
||||
ItemShareRepository: Symbol.for('ItemShareRepository'),
|
||||
// ORM
|
||||
ORMItemRepository: Symbol.for('ORMItemRepository'),
|
||||
ORMItemShareRepository: Symbol.for('ORMItemShareRepository'),
|
||||
// Middleware
|
||||
AuthMiddleware: Symbol.for('AuthMiddleware'),
|
||||
// Projectors
|
||||
@@ -42,6 +43,7 @@ const TYPES = {
|
||||
ShareItem: Symbol.for('ShareItem'),
|
||||
GetSharedItem: Symbol.for('GetSharedItem'),
|
||||
UpdateSharedItem: Symbol.for('UpdateSharedItem'),
|
||||
GetUserItemShares: Symbol.for('GetUserItemShares'),
|
||||
// Handlers
|
||||
AccountDeletionRequestedEventHandler: Symbol.for('AccountDeletionRequestedEventHandler'),
|
||||
DuplicateItemSyncedEventHandler: Symbol.for('DuplicateItemSyncedEventHandler'),
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { GetUserItemSharesUseCase } from './../Domain/UseCase/ItemShare/GetUserItemSharesUseCase'
|
||||
import { UpdateSharedItemUseCase } from './../Domain/UseCase/ItemShare/UpdateSharedItemUseCase'
|
||||
import { GetSharedItemUseCase } from './../Domain/UseCase/ItemShare/GetSharedItemUseCase'
|
||||
import { Request, Response } from 'express'
|
||||
@@ -12,6 +13,7 @@ export class ItemSharesController extends BaseHttpController {
|
||||
@inject(TYPES.ShareItem) private shareItem: ShareItemUseCase,
|
||||
@inject(TYPES.GetSharedItem) private getSharedItem: GetSharedItemUseCase,
|
||||
@inject(TYPES.UpdateSharedItem) private updateSharedItem: UpdateSharedItemUseCase,
|
||||
@inject(TYPES.GetUserItemShares) private getItemShares: GetUserItemSharesUseCase,
|
||||
) {
|
||||
super()
|
||||
}
|
||||
@@ -19,11 +21,11 @@ export class ItemSharesController extends BaseHttpController {
|
||||
@httpPost('/')
|
||||
public async share(request: Request, response: Response): Promise<results.JsonResult> {
|
||||
const result = await this.shareItem.execute({
|
||||
itemUuid: request.body.item_uuid,
|
||||
itemUuid: request.body.itemUuid,
|
||||
userUuid: response.locals.user.uuid,
|
||||
publicKey: request.body.public_key,
|
||||
encryptedContentKey: request.body.encrypted_content_key,
|
||||
contentType: request.body.content_type,
|
||||
publicKey: request.body.publicKey,
|
||||
encryptedContentKey: request.body.encryptedContentKey,
|
||||
contentType: request.body.contentType,
|
||||
})
|
||||
|
||||
return this.json(result)
|
||||
@@ -32,8 +34,8 @@ export class ItemSharesController extends BaseHttpController {
|
||||
@httpPatch('/')
|
||||
public async updateSharedItemRequest(request: Request): Promise<results.JsonResult> {
|
||||
const result = await this.updateSharedItem.execute({
|
||||
shareToken: request.body.share_token,
|
||||
encryptedContentKey: request.body.encrypted_content_key,
|
||||
shareToken: request.body.shareToken,
|
||||
encryptedContentKey: request.body.encryptedContentKey,
|
||||
})
|
||||
|
||||
return this.json(result)
|
||||
@@ -42,26 +44,29 @@ export class ItemSharesController extends BaseHttpController {
|
||||
@httpGet('/item/:shareToken')
|
||||
public async getItemForShareToken(request: Request): Promise<results.NotFoundResult | results.JsonResult> {
|
||||
const result = await this.getSharedItem.execute({
|
||||
shareToken: request.body.share_token,
|
||||
shareToken: request.params.shareToken,
|
||||
})
|
||||
|
||||
if (result.success === false) {
|
||||
return this.notFound()
|
||||
}
|
||||
|
||||
return this.json(result.item)
|
||||
return this.json(result)
|
||||
}
|
||||
|
||||
@httpGet('/')
|
||||
public async getItemSharesForUser(request: Request): Promise<results.NotFoundResult | results.JsonResult> {
|
||||
const result = await this.getSharedItem.execute({
|
||||
shareToken: request.body.share_token,
|
||||
public async getItemSharesForUser(
|
||||
_request: Request,
|
||||
response: Response,
|
||||
): Promise<results.NotFoundResult | results.JsonResult> {
|
||||
const result = await this.getItemShares.execute({
|
||||
userUuid: response.locals.user.uuid,
|
||||
})
|
||||
|
||||
if (result.success === false) {
|
||||
return this.notFound()
|
||||
}
|
||||
|
||||
return this.json(result.item)
|
||||
return this.json(result)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,9 +11,9 @@ export class ItemShare {
|
||||
type: 'varchar',
|
||||
name: 'share_token',
|
||||
length: 36,
|
||||
nullable: true,
|
||||
nullable: false,
|
||||
})
|
||||
declare shareToken: string | null
|
||||
declare shareToken: string
|
||||
|
||||
@Column({
|
||||
name: 'content_type',
|
||||
|
||||
@@ -8,6 +8,8 @@ export class ItemShareFactory implements ItemShareFactoryInterface {
|
||||
create(dto: { userUuid: string; itemShareHash: ItemShareHash }): ItemShare {
|
||||
const newItemShare = new ItemShare()
|
||||
newItemShare.uuid = dto.itemShareHash.uuid
|
||||
newItemShare.userUuid = dto.userUuid
|
||||
newItemShare.itemUuid = dto.itemShareHash.item_uuid
|
||||
newItemShare.shareToken = dto.itemShareHash.share_token
|
||||
newItemShare.encryptedContentKey = dto.itemShareHash.encrypted_content_key
|
||||
newItemShare.publicKey = dto.itemShareHash.public_key
|
||||
|
||||
@@ -3,6 +3,7 @@ import { ItemShare } from './ItemShare'
|
||||
|
||||
export type ItemShareHash = {
|
||||
uuid: string
|
||||
item_uuid: string
|
||||
share_token: string
|
||||
public_key: string
|
||||
encrypted_content_key: string
|
||||
|
||||
@@ -12,7 +12,7 @@ export type UserItemSharesQuery = {
|
||||
export interface ItemShareRepositoryInterface {
|
||||
create(itemShare: ItemShare): Promise<ItemShare>
|
||||
remove(itemShare: ItemShare): Promise<ItemShare>
|
||||
updateEncryptedContentKey(shareToken: string, encryptedContentKey: string): Promise<void>
|
||||
updateEncryptedContentKey(dto: { shareToken: string; encryptedContentKey: string }): Promise<void>
|
||||
deleteByShareToken(shareToken: string): Promise<void>
|
||||
findByShareToken(shareToken: string): Promise<ItemShare | null>
|
||||
findAll(query: UserItemSharesQuery): Promise<ItemShare[]>
|
||||
|
||||
@@ -44,6 +44,7 @@ export class ItemShareService implements ItemShareServiceInterface {
|
||||
userUuid: dto.userUuid,
|
||||
itemShareHash: {
|
||||
uuid,
|
||||
item_uuid: dto.itemUuid,
|
||||
share_token: shareToken,
|
||||
public_key: dto.publicKey,
|
||||
encrypted_content_key: dto.encryptedContentKey,
|
||||
@@ -62,7 +63,10 @@ export class ItemShareService implements ItemShareServiceInterface {
|
||||
return false
|
||||
}
|
||||
|
||||
await this.itemShareRepository.updateEncryptedContentKey(itemShareItem.uuid, dto.encryptedContentKey)
|
||||
await this.itemShareRepository.updateEncryptedContentKey({
|
||||
shareToken: itemShareItem.shareToken,
|
||||
encryptedContentKey: dto.encryptedContentKey,
|
||||
})
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
+3
-3
@@ -2,7 +2,7 @@ import { ItemShare } from '../../ItemShare/ItemShare'
|
||||
import { ItemShareServiceInterface } from '../../ItemShare/ItemShareServiceInterface'
|
||||
import { UseCaseInterface } from '../UseCaseInterface'
|
||||
|
||||
export type GetItemSharesResponse =
|
||||
export type GetUserItemSharesResponse =
|
||||
| {
|
||||
success: true
|
||||
itemShares: ItemShare[]
|
||||
@@ -12,10 +12,10 @@ export type GetItemSharesResponse =
|
||||
message: string
|
||||
}
|
||||
|
||||
export class GetItemSharesUseCase implements UseCaseInterface {
|
||||
export class GetUserItemSharesUseCase implements UseCaseInterface {
|
||||
constructor(private itemShareService: ItemShareServiceInterface) {}
|
||||
|
||||
async execute(dto: { userUuid: string }): Promise<GetItemSharesResponse> {
|
||||
async execute(dto: { userUuid: string }): Promise<GetUserItemSharesResponse> {
|
||||
const result = await this.itemShareService.getUserItemShares(dto.userUuid)
|
||||
|
||||
if (result === null) {
|
||||
@@ -13,15 +13,15 @@ export class TypeORMItemShareRepository implements ItemShareRepositoryInterface
|
||||
return this.ormRepository.remove(itemShare)
|
||||
}
|
||||
|
||||
async updateEncryptedContentKey(shareToken: string, encryptedContentKey: string): Promise<void> {
|
||||
async updateEncryptedContentKey(dto: { shareToken: string; encryptedContentKey: string }): Promise<void> {
|
||||
await this.ormRepository
|
||||
.createQueryBuilder('item_share')
|
||||
.update()
|
||||
.set({
|
||||
encryptedContentKey,
|
||||
encryptedContentKey: dto.encryptedContentKey,
|
||||
})
|
||||
.where('share_token = :shareToken', {
|
||||
shareToken,
|
||||
shareToken: dto.shareToken,
|
||||
})
|
||||
.execute()
|
||||
}
|
||||
@@ -38,7 +38,7 @@ export class TypeORMItemShareRepository implements ItemShareRepositoryInterface
|
||||
async findByShareToken(shareToken: string): Promise<ItemShare | null> {
|
||||
return this.ormRepository
|
||||
.createQueryBuilder('item_share')
|
||||
.where('item.share_token = :shareToken', {
|
||||
.where('item_share.share_token = :shareToken', {
|
||||
shareToken,
|
||||
})
|
||||
.getOne()
|
||||
|
||||
Reference in New Issue
Block a user