mirror of
https://github.com/standardnotes/server
synced 2026-09-21 06:13:09 -04:00
wip: usecases
This commit is contained in:
@@ -0,0 +1,26 @@
|
||||
import { MigrationInterface, QueryRunner, TableColumn } from 'typeorm'
|
||||
|
||||
export class AddPkcFields1684172607219 implements MigrationInterface {
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.addColumn(
|
||||
'users',
|
||||
new TableColumn({
|
||||
name: 'public_key',
|
||||
type: 'text',
|
||||
}),
|
||||
)
|
||||
|
||||
await queryRunner.addColumn(
|
||||
'users',
|
||||
new TableColumn({
|
||||
name: 'encrypted_private_key',
|
||||
type: 'text',
|
||||
}),
|
||||
)
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.dropColumn('users', 'public_key')
|
||||
await queryRunner.dropColumn('users', 'encrypted_private_key')
|
||||
}
|
||||
}
|
||||
@@ -72,6 +72,8 @@ export class UsersController extends BaseHttpController {
|
||||
kpOrigination: request.body.origination,
|
||||
kpCreated: request.body.created,
|
||||
version: request.body.version,
|
||||
publicKey: request.body.public_key,
|
||||
encryptedPrivateKey: request.body.private_key,
|
||||
})
|
||||
|
||||
if (updateResult.success) {
|
||||
@@ -208,6 +210,8 @@ export class UsersController extends BaseHttpController {
|
||||
kpOrigination: request.body.origination,
|
||||
updatedWithUserAgent: <string>request.headers['user-agent'],
|
||||
protocolVersion: request.body.version,
|
||||
publicKey: request.body.new_public_key,
|
||||
encryptedPrivateKey: request.body.new_encrypted_private_key,
|
||||
})
|
||||
|
||||
if (!changeCredentialsResult.success) {
|
||||
|
||||
@@ -1,9 +1,5 @@
|
||||
import { ProtocolVersion } from '@standardnotes/common'
|
||||
import { SimpleUserProjection } from '../../Projection/SimpleUserProjection'
|
||||
|
||||
export interface AuthResponse {
|
||||
user: {
|
||||
uuid: string
|
||||
email: string
|
||||
protocolVersion: ProtocolVersion
|
||||
}
|
||||
user: SimpleUserProjection
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@ import {
|
||||
TokenEncoderInterface,
|
||||
} from '@standardnotes/security'
|
||||
import { DomainEventPublisherInterface } from '@standardnotes/domain-events'
|
||||
import { ProtocolVersion } from '@standardnotes/common'
|
||||
import { SessionBody } from '@standardnotes/responses'
|
||||
import { inject, injectable } from 'inversify'
|
||||
import { Logger } from 'winston'
|
||||
@@ -19,6 +18,7 @@ import { DomainEventFactoryInterface } from '../Event/DomainEventFactoryInterfac
|
||||
|
||||
import { AuthResponse20161215 } from './AuthResponse20161215'
|
||||
import { AuthResponse20200115 } from './AuthResponse20200115'
|
||||
import { SimpleUserProjection } from '../../Projection/SimpleUserProjection'
|
||||
|
||||
@injectable()
|
||||
export class AuthResponseFactory20200115 extends AuthResponseFactory20190520 {
|
||||
@@ -54,11 +54,7 @@ export class AuthResponseFactory20200115 extends AuthResponseFactory20190520 {
|
||||
return {
|
||||
session: sessionPayload,
|
||||
key_params: this.keyParamsFactory.create(dto.user, true),
|
||||
user: this.userProjector.projectSimple(dto.user) as {
|
||||
uuid: string
|
||||
email: string
|
||||
protocolVersion: ProtocolVersion
|
||||
},
|
||||
user: this.userProjector.projectSimple(dto.user) as SimpleUserProjection,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -62,6 +62,13 @@ export class ChangeCredentials implements UseCaseInterface {
|
||||
dto.user.email = newUsername.value
|
||||
}
|
||||
|
||||
if (dto.publicKey) {
|
||||
dto.user.publicKey = dto.publicKey
|
||||
}
|
||||
if (dto.encryptedPrivateKey) {
|
||||
dto.user.encryptedPrivateKey = dto.encryptedPrivateKey
|
||||
}
|
||||
|
||||
dto.user.pwNonce = dto.pwNonce
|
||||
if (dto.protocolVersion) {
|
||||
dto.user.version = dto.protocolVersion
|
||||
|
||||
@@ -11,4 +11,6 @@ export type ChangeCredentialsDTO = {
|
||||
protocolVersion?: string
|
||||
kpOrigination?: string
|
||||
kpCreated?: string
|
||||
publicKey?: string
|
||||
encryptedPrivateKey?: string
|
||||
}
|
||||
|
||||
@@ -71,6 +71,8 @@ export class Register implements UseCaseInterface {
|
||||
user.encryptedPassword = await bcrypt.hash(password, User.PASSWORD_HASH_COST)
|
||||
user.encryptedServerKey = await this.crypter.generateEncryptedUserServerKey()
|
||||
user.serverEncryptionVersion = User.DEFAULT_ENCRYPTION_VERSION
|
||||
user.publicKey = dto.publicKey ?? null
|
||||
user.encryptedPrivateKey = dto.encryptedPrivateKey ?? null
|
||||
|
||||
const defaultRole = await this.roleRepository.findOneByName(RoleName.NAMES.CoreUser)
|
||||
if (defaultRole) {
|
||||
|
||||
@@ -10,4 +10,6 @@ export type RegisterDTO = {
|
||||
kpOrigination?: string
|
||||
kpCreated?: string
|
||||
version?: string
|
||||
publicKey?: string
|
||||
encryptedPrivateKey?: string
|
||||
}
|
||||
|
||||
@@ -15,4 +15,6 @@ export type UpdateUserDTO = {
|
||||
kpOrigination?: string
|
||||
kpCreated?: Date
|
||||
version?: string
|
||||
publicKey?: string
|
||||
encryptedPrivateKey?: string
|
||||
}
|
||||
|
||||
@@ -42,6 +42,22 @@ export class User {
|
||||
})
|
||||
declare encryptedServerKey: string | null
|
||||
|
||||
@Column({
|
||||
name: 'public_key',
|
||||
length: 255,
|
||||
type: 'varchar',
|
||||
nullable: true,
|
||||
})
|
||||
declare publicKey: string | null
|
||||
|
||||
@Column({
|
||||
name: 'encrypted_private_key',
|
||||
length: 255,
|
||||
type: 'varchar',
|
||||
nullable: true,
|
||||
})
|
||||
declare encryptedPrivateKey: string | null
|
||||
|
||||
@Column({
|
||||
name: 'server_encryption_version',
|
||||
type: 'tinyint',
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
export type SimpleUserProjection = {
|
||||
uuid: string
|
||||
email: string
|
||||
protocolVersion: string
|
||||
publicKey?: string
|
||||
encryptedPrivateKey?: string
|
||||
}
|
||||
@@ -2,14 +2,17 @@ import { injectable } from 'inversify'
|
||||
|
||||
import { User } from '../Domain/User/User'
|
||||
import { ProjectorInterface } from './ProjectorInterface'
|
||||
import { SimpleUserProjection } from './SimpleUserProjection'
|
||||
|
||||
@injectable()
|
||||
export class UserProjector implements ProjectorInterface<User> {
|
||||
projectSimple(user: User): Record<string, unknown> {
|
||||
projectSimple(user: User): SimpleUserProjection {
|
||||
return {
|
||||
uuid: user.uuid,
|
||||
email: user.email,
|
||||
protocolVersion: user.version,
|
||||
publicKey: user.publicKey ?? undefined,
|
||||
encryptedPrivateKey: user.encryptedPrivateKey ?? undefined,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
import { MigrationInterface, QueryRunner, Table, TableColumn } from 'typeorm'
|
||||
|
||||
export class CreateGroup1684173017359 implements MigrationInterface {
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
const table = new Table({
|
||||
name: 'groups',
|
||||
columns: [
|
||||
new TableColumn({
|
||||
name: 'uuid',
|
||||
type: 'varchar',
|
||||
length: '36',
|
||||
isPrimary: true,
|
||||
}),
|
||||
new TableColumn({
|
||||
name: 'user_uuid',
|
||||
type: 'varchar',
|
||||
length: '36',
|
||||
isNullable: false,
|
||||
}),
|
||||
new TableColumn({
|
||||
name: 'created_at_timestamp',
|
||||
type: 'bigint',
|
||||
}),
|
||||
new TableColumn({
|
||||
name: 'updated_at_timestamp',
|
||||
type: 'bigint',
|
||||
}),
|
||||
],
|
||||
})
|
||||
|
||||
await queryRunner.createTable(table)
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.dropTable('groups')
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
import { MigrationInterface, QueryRunner, Table, TableColumn } from 'typeorm'
|
||||
|
||||
export class CreateGroupUser1684173023883 implements MigrationInterface {
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
const table = new Table({
|
||||
name: 'group_users',
|
||||
columns: [
|
||||
new TableColumn({
|
||||
name: 'uuid',
|
||||
type: 'varchar',
|
||||
length: '36',
|
||||
isPrimary: true,
|
||||
}),
|
||||
new TableColumn({
|
||||
name: 'group_uuid',
|
||||
type: 'varchar',
|
||||
length: '36',
|
||||
isNullable: false,
|
||||
}),
|
||||
new TableColumn({
|
||||
name: 'user_uuid',
|
||||
type: 'varchar',
|
||||
length: '36',
|
||||
isNullable: false,
|
||||
}),
|
||||
new TableColumn({
|
||||
name: 'encrypted_group_key',
|
||||
type: 'text',
|
||||
isNullable: false,
|
||||
}),
|
||||
new TableColumn({
|
||||
name: 'sender_public_key',
|
||||
type: 'text',
|
||||
isNullable: false,
|
||||
}),
|
||||
new TableColumn({
|
||||
name: 'created_at_timestamp',
|
||||
type: 'bigint',
|
||||
}),
|
||||
new TableColumn({
|
||||
name: 'updated_at_timestamp',
|
||||
type: 'bigint',
|
||||
}),
|
||||
],
|
||||
})
|
||||
|
||||
await queryRunner.createTable(table)
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.dropTable('group_users')
|
||||
}
|
||||
}
|
||||
@@ -2,10 +2,11 @@ import { GroupServiceInterface } from './../Domain/Group/Service/GroupServiceInt
|
||||
import { Request, Response } from 'express'
|
||||
import { BaseHttpController, controller, httpGet, httpPost, results } from 'inversify-express-utils'
|
||||
import TYPES from '../Bootstrap/Types'
|
||||
import { GroupUserServiceInterface } from '../Domain/GroupUser/Service/GroupUserService'
|
||||
|
||||
@controller('/groups')
|
||||
export class GroupsController extends BaseHttpController {
|
||||
constructor(private groupsService: GroupServiceInterface) {
|
||||
constructor(private groupsService: GroupServiceInterface, private groupUserService: GroupUserServiceInterface) {
|
||||
super()
|
||||
}
|
||||
|
||||
@@ -23,6 +24,20 @@ export class GroupsController extends BaseHttpController {
|
||||
return this.json({ group: result })
|
||||
}
|
||||
|
||||
@httpGet('/', TYPES.AuthMiddleware)
|
||||
public async getUserGroupKeys(
|
||||
_request: Request,
|
||||
response: Response,
|
||||
): Promise<results.NotFoundResult | results.JsonResult> {
|
||||
const result = await this.groupUserService.getUserGroupKeys({ userUuid: response.locals.user.uuid })
|
||||
|
||||
if (!result) {
|
||||
return this.errorResponse(500, 'Could not get user groups')
|
||||
}
|
||||
|
||||
return this.json({ groups: result })
|
||||
}
|
||||
|
||||
@httpPost('/:groupUuid/users', TYPES.AuthMiddleware)
|
||||
public async addUserToGroup(
|
||||
request: Request,
|
||||
@@ -31,8 +46,9 @@ export class GroupsController extends BaseHttpController {
|
||||
const result = await this.groupsService.addUserToGroup({
|
||||
groupUuid: request.params.groupUuid,
|
||||
ownerUuid: response.locals.user.uuid,
|
||||
inviteeUuid: request.body.inviteeUuid,
|
||||
encryptedGroupKey: request.body.encryptedGroupKey,
|
||||
inviteeUuid: request.body.invitee_uuid,
|
||||
encryptedGroupKey: request.body.encrypted_group_key,
|
||||
senderPublicKey: request.body.sender_public_key,
|
||||
})
|
||||
|
||||
if (!result) {
|
||||
@@ -42,20 +58,6 @@ export class GroupsController extends BaseHttpController {
|
||||
return this.json({ groupUser: result })
|
||||
}
|
||||
|
||||
@httpGet('/', TYPES.AuthMiddleware)
|
||||
public async getUserGroups(
|
||||
_request: Request,
|
||||
response: Response,
|
||||
): Promise<results.NotFoundResult | results.JsonResult> {
|
||||
const result = await this.groupsService.getUserGroups(response.locals.user.uuid)
|
||||
|
||||
if (!result) {
|
||||
return this.errorResponse(500, 'Could not get user groups')
|
||||
}
|
||||
|
||||
return this.json({ groups: result })
|
||||
}
|
||||
|
||||
private errorResponse(status: number, message?: string, tag?: string) {
|
||||
return this.json(
|
||||
{
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import { ItemHash } from './../../Item/ItemHash'
|
||||
import { GroupUser } from '../../GroupUser/Model/GroupUser'
|
||||
import { Group } from '../Model/Group'
|
||||
|
||||
@@ -10,20 +9,13 @@ import { TimerInterface } from '@standardnotes/time'
|
||||
import { GroupUserServiceInterface } from '../../GroupUser/Service/GroupUserService'
|
||||
|
||||
import { v4 as uuidv4 } from 'uuid'
|
||||
import { GetItem } from '../../UseCase/GetItem/GetItem'
|
||||
import { SaveItemUseCase } from '../../UseCase/SaveItem'
|
||||
import { ProjectorInterface } from '../../../Projection/ProjectorInterface'
|
||||
import { Item } from '../../Item/Item'
|
||||
import { ItemProjection } from '../../../Projection/ItemProjection'
|
||||
|
||||
export class GroupService implements GroupServiceInterface {
|
||||
constructor(
|
||||
private groupRepository: GroupsRepositoryInterface,
|
||||
private groupFactory: GroupFactoryInterface,
|
||||
private groupUserSerivce: GroupUserServiceInterface,
|
||||
private getItem: GetItem,
|
||||
private saveItem: SaveItemUseCase,
|
||||
private itemProjector: ProjectorInterface<Item, ItemProjection>,
|
||||
private groupUserService: GroupUserServiceInterface,
|
||||
|
||||
private timer: TimerInterface,
|
||||
) {}
|
||||
|
||||
@@ -48,45 +40,15 @@ export class GroupService implements GroupServiceInterface {
|
||||
ownerUuid: string
|
||||
inviteeUuid: string
|
||||
encryptedGroupKey: string
|
||||
senderPublicKey: string
|
||||
}): Promise<GroupUser | null> {
|
||||
const user = await this.groupUserSerivce.createGroupUser(dto.groupUuid, dto.inviteeUuid, dto.encryptedGroupKey)
|
||||
const user = await this.groupUserService.createGroupUser({
|
||||
groupUuid: dto.groupUuid,
|
||||
userUuid: dto.inviteeUuid,
|
||||
encryptedGroupKey: dto.encryptedGroupKey,
|
||||
senderPublicKey: dto.senderPublicKey,
|
||||
})
|
||||
|
||||
return user
|
||||
}
|
||||
|
||||
async addItemToGroup(dto: {
|
||||
groupUuid: string
|
||||
userUuid: string
|
||||
itemUuid: string
|
||||
apiVersion: string
|
||||
readOnlyAccess: boolean
|
||||
sessionUuid: string | null
|
||||
}): Promise<{ success: boolean }> {
|
||||
const getItemResult = await this.getItem.execute({ itemUuid: dto.itemUuid, userUuid: dto.userUuid })
|
||||
|
||||
if (!getItemResult.success) {
|
||||
return { success: false }
|
||||
}
|
||||
|
||||
const itemHash = await this.itemProjector.projectFull(getItemResult.item)
|
||||
itemHash.group_uuid = dto.groupUuid
|
||||
|
||||
const saveItemResult = await this.saveItem.execute({
|
||||
itemHash: <ItemHash>itemHash,
|
||||
userUuid: dto.userUuid,
|
||||
apiVersion: dto.apiVersion,
|
||||
readOnlyAccess: dto.readOnlyAccess,
|
||||
sessionUuid: dto.sessionUuid,
|
||||
})
|
||||
|
||||
return { success: saveItemResult.success }
|
||||
}
|
||||
|
||||
getGroup(groupUuid: string): Promise<Group | null> {
|
||||
return this.groupRepository.findByUuid(groupUuid)
|
||||
}
|
||||
|
||||
async getUserGroups(userUuid: string): Promise<Group[]> {
|
||||
return this.groupRepository.findAll({ userUuid })
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,18 +9,6 @@ export interface GroupServiceInterface {
|
||||
ownerUuid: string
|
||||
inviteeUuid: string
|
||||
encryptedGroupKey: string
|
||||
senderPublicKey: string
|
||||
}): Promise<GroupUser | null>
|
||||
|
||||
addItemToGroup(dto: {
|
||||
groupUuid: string
|
||||
userUuid: string
|
||||
itemUuid: string
|
||||
apiVersion: string
|
||||
readOnlyAccess: boolean
|
||||
sessionUuid: string | null
|
||||
}): Promise<{ success: boolean }>
|
||||
|
||||
getGroup(groupUuid: string): Promise<Group | null>
|
||||
|
||||
getUserGroups(userUuid: string): Promise<Group[]>
|
||||
}
|
||||
|
||||
@@ -22,6 +22,11 @@ export class GroupUser {
|
||||
})
|
||||
declare encryptedGroupKey: string
|
||||
|
||||
@Column({
|
||||
name: 'sender_public_key',
|
||||
})
|
||||
declare senderPublicKey: string
|
||||
|
||||
@Column({
|
||||
name: 'created_at_timestamp',
|
||||
type: 'bigint',
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
export interface GetUserGroupKeysDTO {
|
||||
userUuid: string
|
||||
syncToken?: string | null
|
||||
}
|
||||
@@ -1,12 +1,26 @@
|
||||
import { GetUserGroupKeysDTO } from './GetUserGroupKeysDTO'
|
||||
import { GroupUser } from '../Model/GroupUser'
|
||||
|
||||
export interface GroupUserServiceInterface {
|
||||
createGroupUser(groupUuid: string, userUuid: string, encryptedGroupKey: string): Promise<GroupUser>
|
||||
getGroupUsers(groupUuid: string): Promise<GroupUser[]>
|
||||
createGroupUser(dto: {
|
||||
groupUuid: string
|
||||
userUuid: string
|
||||
encryptedGroupKey: string
|
||||
senderPublicKey: string
|
||||
}): Promise<GroupUser>
|
||||
getUsersForGroup(groupUuid: string): Promise<GroupUser[]>
|
||||
getUserGroupKeys(dto: GetUserGroupKeysDTO): Promise<GroupUser[]>
|
||||
}
|
||||
|
||||
export class GroupUserService implements GroupUserServiceInterface {
|
||||
createGroupUser(groupUuid: string, userUuid: string, encryptedGroupKey: string): Promise<GroupUser> {}
|
||||
createGroupUser(dto: {
|
||||
groupUuid: string
|
||||
userUuid: string
|
||||
encryptedGroupKey: string
|
||||
senderPublicKey: string
|
||||
}): Promise<GroupUser> {}
|
||||
|
||||
getGroupUsers(groupUuid: string): Promise<GroupUser[]> {}
|
||||
getUsersForGroup(groupUuid: string): Promise<GroupUser[]> {}
|
||||
|
||||
getUserGroupKeys(dto: GetUserGroupKeysDTO): Promise<GroupUser[]> {}
|
||||
}
|
||||
|
||||
@@ -2,11 +2,10 @@ import { ItemSaveValidationDTO } from '../SaveValidator/ItemSaveValidationDTO'
|
||||
import { ItemSaveRuleResult } from './ItemSaveRuleResult'
|
||||
import { ItemSaveRuleInterface } from './ItemSaveRuleInterface'
|
||||
import { ConflictType } from '@standardnotes/responses'
|
||||
import { GetUserGroupsUseCase } from '../../UseCase/Groups/GetUserGroupsUseCase'
|
||||
import { GetGroupItemsUseCase } from '../../UseCase/Groups/GetGroupItemsUseCase'
|
||||
import { GetUserGroupKeysUseCase } from '../../UseCase/Groups/GetUserGroupKeysUseCase'
|
||||
|
||||
export class OwnershipFilter implements ItemSaveRuleInterface {
|
||||
constructor(private getUserGroupsUseCase: GetUserGroupsUseCase, private getGroupItemsUseCase: GetGroupItemsUseCase) {}
|
||||
constructor(private getUserGroupsUseCase: GetUserGroupKeysUseCase) {}
|
||||
|
||||
async check(dto: ItemSaveValidationDTO): Promise<ItemSaveRuleResult> {
|
||||
const itemBelongsToADifferentUser = dto.existingItem !== null && dto.existingItem.userUuid !== dto.userUuid
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { GroupUserProjection } from '../../../Projection/GroupUserProjection'
|
||||
import { ItemConflictProjection } from '../../../Projection/ItemConflictProjection'
|
||||
import { ItemProjection } from '../../../Projection/ItemProjection'
|
||||
import { SavedItemProjection } from '../../../Projection/SavedItemProjection'
|
||||
@@ -8,4 +9,5 @@ export type SyncResponse20200115 = {
|
||||
conflicts: Array<ItemConflictProjection>
|
||||
sync_token: string
|
||||
cursor_token?: string
|
||||
group_keys: Array<GroupUserProjection>
|
||||
}
|
||||
|
||||
@@ -7,12 +7,15 @@ import { ItemProjection } from '../../../Projection/ItemProjection'
|
||||
import { SyncResponse20200115 } from './SyncResponse20200115'
|
||||
import { SyncResponseFactoryInterface } from './SyncResponseFactoryInterface'
|
||||
import { SavedItemProjection } from '../../../Projection/SavedItemProjection'
|
||||
import { GroupUser } from '../../GroupUser/Model/GroupUser'
|
||||
import { GroupUserProjection } from '../../../Projection/GroupUserProjection'
|
||||
|
||||
export class SyncResponseFactory20200115 implements SyncResponseFactoryInterface {
|
||||
constructor(
|
||||
private itemProjector: ProjectorInterface<Item, ItemProjection>,
|
||||
private itemConflictProjector: ProjectorInterface<ItemConflict, ItemConflictProjection>,
|
||||
private savedItemProjector: ProjectorInterface<Item, SavedItemProjection>,
|
||||
private groupKeyProjector: ProjectorInterface<GroupUser, GroupUserProjection>,
|
||||
) {}
|
||||
|
||||
async createResponse(syncItemsResponse: SyncItemsResponse): Promise<SyncResponse20200115> {
|
||||
@@ -31,12 +34,18 @@ export class SyncResponseFactory20200115 implements SyncResponseFactoryInterface
|
||||
conflicts.push(<ItemConflictProjection>await this.itemConflictProjector.projectFull(itemConflict))
|
||||
}
|
||||
|
||||
const groupKeys = []
|
||||
for (const groupKey of syncItemsResponse.groupKeys) {
|
||||
groupKeys.push(<GroupUserProjection>await this.groupKeyProjector.projectFull(groupKey))
|
||||
}
|
||||
|
||||
return {
|
||||
retrieved_items: retrievedItems,
|
||||
saved_items: savedItems,
|
||||
conflicts,
|
||||
sync_token: syncItemsResponse.syncToken,
|
||||
cursor_token: syncItemsResponse.cursorToken,
|
||||
group_keys: groupKeys,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
import { GroupServiceInterface } from '../../Group/Service/GroupServiceInterface'
|
||||
import { UseCaseInterface } from '../UseCaseInterface'
|
||||
import { Group } from '../../Group/Model/Group'
|
||||
|
||||
export type GetGroupUseCaseResult =
|
||||
| {
|
||||
success: true
|
||||
group: Group
|
||||
}
|
||||
| {
|
||||
success: false
|
||||
message: string
|
||||
}
|
||||
|
||||
export class GetGroupUseCase implements UseCaseInterface {
|
||||
constructor(private groupService: GroupServiceInterface) {}
|
||||
|
||||
async execute(dto: { groupUuid: string }): Promise<GetGroupUseCaseResult> {
|
||||
const result = await this.groupService.getGroup(dto.groupUuid)
|
||||
|
||||
if (!result) {
|
||||
return {
|
||||
success: false,
|
||||
message: `Could not get group ${dto.groupUuid}`,
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
success: true,
|
||||
group: result,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
import { GetUserGroupKeysDTO } from './../../GroupUser/Service/GetUserGroupKeysDTO'
|
||||
import { UseCaseInterface } from '../UseCaseInterface'
|
||||
import { Group } from '../../Group/Model/Group'
|
||||
import { GroupUserServiceInterface } from '../../GroupUser/Service/GroupUserService'
|
||||
|
||||
export type GetUserGroupKeysUseCaseResult =
|
||||
| {
|
||||
success: true
|
||||
groups: Group[]
|
||||
}
|
||||
| {
|
||||
success: false
|
||||
message: string
|
||||
}
|
||||
|
||||
export class GetUserGroupKeysUseCase implements UseCaseInterface {
|
||||
constructor(private groupUserService: GroupUserServiceInterface) {}
|
||||
|
||||
async execute(dto: GetUserGroupKeysDTO): Promise<GetUserGroupKeysUseCaseResult> {
|
||||
const result = await this.groupUserService.getUserGroupKeys(dto)
|
||||
|
||||
if (!result) {
|
||||
return {
|
||||
success: false,
|
||||
message: `Could not get user groups for user ${dto.userUuid}`,
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
success: true,
|
||||
groups: result,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
import { GroupServiceInterface } from '../../Group/Service/GroupServiceInterface'
|
||||
import { UseCaseInterface } from '../UseCaseInterface'
|
||||
import { Group } from '../../Group/Model/Group'
|
||||
|
||||
export type GetUserGroupsUseCaseResult =
|
||||
| {
|
||||
success: true
|
||||
groups: Group[]
|
||||
}
|
||||
| {
|
||||
success: false
|
||||
message: string
|
||||
}
|
||||
|
||||
export class GetUserGroupsUseCase implements UseCaseInterface {
|
||||
constructor(private groupService: GroupServiceInterface) {}
|
||||
|
||||
async execute(dto: { userUuid: string }): Promise<GetUserGroupsUseCaseResult> {
|
||||
const result = await this.groupService.getUserGroups(dto.userUuid)
|
||||
|
||||
if (!result) {
|
||||
return {
|
||||
success: false,
|
||||
message: `Could not get user groups for user ${dto.userUuid}`,
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
success: true,
|
||||
groups: result,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
import { GroupUserServiceInterface } from '../GroupUser/Service/GroupUserService'
|
||||
import { Item } from '../Item/Item'
|
||||
import { ItemConflict } from '../Item/ItemConflict'
|
||||
import { ItemServiceInterface } from '../Item/ItemServiceInterface'
|
||||
@@ -6,7 +7,7 @@ import { SyncItemsResponse } from './SyncItemsResponse'
|
||||
import { UseCaseInterface } from './UseCaseInterface'
|
||||
|
||||
export class SyncItems implements UseCaseInterface {
|
||||
constructor(private itemService: ItemServiceInterface) {}
|
||||
constructor(private itemService: ItemServiceInterface, private groupUserService: GroupUserServiceInterface) {}
|
||||
|
||||
async execute(dto: SyncItemsDTO): Promise<SyncItemsResponse> {
|
||||
const getItemsResult = await this.itemService.getItems({
|
||||
@@ -30,12 +31,15 @@ export class SyncItems implements UseCaseInterface {
|
||||
retrievedItems = await this.itemService.frontLoadKeysItemsToTop(dto.userUuid, retrievedItems)
|
||||
}
|
||||
|
||||
const groupKeys = await this.groupUserService.getUserGroupKeys({ userUuid: dto.userUuid, syncToken: dto.syncToken })
|
||||
|
||||
const syncResponse: SyncItemsResponse = {
|
||||
retrievedItems,
|
||||
syncToken: saveItemsResult.syncToken,
|
||||
savedItems: saveItemsResult.savedItems,
|
||||
conflicts: saveItemsResult.conflicts,
|
||||
cursorToken: getItemsResult.cursorToken,
|
||||
groupKeys,
|
||||
}
|
||||
|
||||
return syncResponse
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { GroupUser } from './../GroupUser/Model/GroupUser'
|
||||
import { Item } from '../Item/Item'
|
||||
import { ItemConflict } from '../Item/ItemConflict'
|
||||
|
||||
@@ -5,6 +6,7 @@ export type SyncItemsResponse = {
|
||||
retrievedItems: Array<Item>
|
||||
savedItems: Array<Item>
|
||||
conflicts: Array<ItemConflict>
|
||||
groupKeys: Array<GroupUser>
|
||||
syncToken: string
|
||||
cursorToken?: string
|
||||
}
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
export type GroupUserProjection = {
|
||||
uuid: string
|
||||
group_uuid: string
|
||||
user_uuid: string
|
||||
encrypted_group_key: string
|
||||
sender_public_key: string
|
||||
created_at_timestamp: number
|
||||
updated_at_timestamp: number
|
||||
}
|
||||
Reference in New Issue
Block a user