123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310 |
- import 'reflect-metadata'
- import { TokenEncoderInterface, CrossServiceTokenData } from '@standardnotes/security'
- import { ProjectorInterface } from '../../../Projection/ProjectorInterface'
- import { Session } from '../../Session/Session'
- import { User } from '../../User/User'
- import { Role } from '../../Role/Role'
- import { UserRepositoryInterface } from '../../User/UserRepositoryInterface'
- import { CreateCrossServiceToken } from './CreateCrossServiceToken'
- import { GetSetting } from '../GetSetting/GetSetting'
- import {
- Result,
- SharedVaultUser,
- SharedVaultUserPermission,
- Timestamps,
- TransitionStatus,
- Uuid,
- } from '@standardnotes/domain-core'
- import { TransitionStatusRepositoryInterface } from '../../Transition/TransitionStatusRepositoryInterface'
- import { SharedVaultUserRepositoryInterface } from '../../SharedVault/SharedVaultUserRepositoryInterface'
- describe('CreateCrossServiceToken', () => {
- let userProjector: ProjectorInterface<User>
- let sessionProjector: ProjectorInterface<Session>
- let roleProjector: ProjectorInterface<Role>
- let tokenEncoder: TokenEncoderInterface<CrossServiceTokenData>
- let userRepository: UserRepositoryInterface
- let getSettingUseCase: GetSetting
- let transitionStatusRepository: TransitionStatusRepositoryInterface
- let sharedVaultUserRepository: SharedVaultUserRepositoryInterface
- const jwtTTL = 60
- let session: Session
- let user: User
- let role: Role
- const createUseCase = () =>
- new CreateCrossServiceToken(
- userProjector,
- sessionProjector,
- roleProjector,
- tokenEncoder,
- userRepository,
- jwtTTL,
- getSettingUseCase,
- transitionStatusRepository,
- sharedVaultUserRepository,
- )
- beforeEach(() => {
- session = {} as jest.Mocked<Session>
- user = {
- uuid: '00000000-0000-0000-0000-000000000000',
- email: 'test@test.te',
- } as jest.Mocked<User>
- user.roles = Promise.resolve([role])
- userProjector = {} as jest.Mocked<ProjectorInterface<User>>
- userProjector.projectSimple = jest
- .fn()
- .mockReturnValue({ uuid: '00000000-0000-0000-0000-000000000000', email: 'test@test.te' })
- roleProjector = {} as jest.Mocked<ProjectorInterface<Role>>
- roleProjector.projectSimple = jest.fn().mockReturnValue({ name: 'role1', uuid: '1-3-4' })
- sessionProjector = {} as jest.Mocked<ProjectorInterface<Session>>
- sessionProjector.projectCustom = jest.fn().mockReturnValue({ foo: 'bar' })
- sessionProjector.projectSimple = jest.fn().mockReturnValue({ test: 'test' })
- tokenEncoder = {} as jest.Mocked<TokenEncoderInterface<CrossServiceTokenData>>
- tokenEncoder.encodeExpirableToken = jest.fn().mockReturnValue('foobar')
- userRepository = {} as jest.Mocked<UserRepositoryInterface>
- userRepository.findOneByUuid = jest.fn().mockReturnValue(user)
- getSettingUseCase = {} as jest.Mocked<GetSetting>
- getSettingUseCase.execute = jest.fn().mockReturnValue(Result.ok({ setting: { value: '100' } }))
- transitionStatusRepository = {} as jest.Mocked<TransitionStatusRepositoryInterface>
- transitionStatusRepository.getStatus = jest
- .fn()
- .mockReturnValue(TransitionStatus.create(TransitionStatus.STATUSES.Verified).getValue())
- sharedVaultUserRepository = {} as jest.Mocked<SharedVaultUserRepositoryInterface>
- sharedVaultUserRepository.findByUserUuid = jest.fn().mockReturnValue([
- SharedVaultUser.create({
- permission: SharedVaultUserPermission.create('read').getValue(),
- sharedVaultUuid: Uuid.create('00000000-0000-0000-0000-000000000000').getValue(),
- timestamps: Timestamps.create(123456789, 123456789).getValue(),
- userUuid: Uuid.create('00000000-0000-0000-0000-000000000000').getValue(),
- }).getValue(),
- ])
- })
- it('should create a cross service token for user', async () => {
- await createUseCase().execute({
- user,
- session,
- })
- expect(tokenEncoder.encodeExpirableToken).toHaveBeenCalledWith(
- {
- roles: [
- {
- name: 'role1',
- uuid: '1-3-4',
- },
- ],
- belongs_to_shared_vaults: [
- {
- shared_vault_uuid: '00000000-0000-0000-0000-000000000000',
- permission: 'read',
- },
- ],
- session: {
- test: 'test',
- },
- user: {
- email: 'test@test.te',
- uuid: '00000000-0000-0000-0000-000000000000',
- },
- ongoing_transition: false,
- ongoing_revisions_transition: false,
- },
- 60,
- )
- })
- it('should create a cross service token for user that has an ongoing transaction', async () => {
- transitionStatusRepository.getStatus = jest
- .fn()
- .mockReturnValue(TransitionStatus.create(TransitionStatus.STATUSES.InProgress).getValue())
- await createUseCase().execute({
- user,
- session,
- })
- expect(tokenEncoder.encodeExpirableToken).toHaveBeenCalledWith(
- {
- roles: [
- {
- name: 'role1',
- uuid: '1-3-4',
- },
- ],
- belongs_to_shared_vaults: [
- {
- shared_vault_uuid: '00000000-0000-0000-0000-000000000000',
- permission: 'read',
- },
- ],
- session: {
- test: 'test',
- },
- user: {
- email: 'test@test.te',
- uuid: '00000000-0000-0000-0000-000000000000',
- },
- ongoing_transition: true,
- ongoing_revisions_transition: true,
- },
- 60,
- )
- })
- it('should create a cross service token for user without a session', async () => {
- await createUseCase().execute({
- user,
- })
- expect(tokenEncoder.encodeExpirableToken).toHaveBeenCalledWith(
- {
- roles: [
- {
- name: 'role1',
- uuid: '1-3-4',
- },
- ],
- belongs_to_shared_vaults: [
- {
- shared_vault_uuid: '00000000-0000-0000-0000-000000000000',
- permission: 'read',
- },
- ],
- user: {
- email: 'test@test.te',
- uuid: '00000000-0000-0000-0000-000000000000',
- },
- ongoing_transition: false,
- ongoing_revisions_transition: false,
- },
- 60,
- )
- })
- it('should create a cross service token for user by user uuid', async () => {
- await createUseCase().execute({
- userUuid: '00000000-0000-0000-0000-000000000000',
- })
- expect(tokenEncoder.encodeExpirableToken).toHaveBeenCalledWith(
- {
- roles: [
- {
- name: 'role1',
- uuid: '1-3-4',
- },
- ],
- belongs_to_shared_vaults: [
- {
- shared_vault_uuid: '00000000-0000-0000-0000-000000000000',
- permission: 'read',
- },
- ],
- user: {
- email: 'test@test.te',
- uuid: '00000000-0000-0000-0000-000000000000',
- },
- ongoing_transition: false,
- ongoing_revisions_transition: false,
- },
- 60,
- )
- })
- it('should throw an error if user does not exist', async () => {
- userRepository.findOneByUuid = jest.fn().mockReturnValue(null)
- const result = await createUseCase().execute({
- userUuid: '00000000-0000-0000-0000-000000000000',
- })
- expect(result.isFailed()).toBeTruthy()
- })
- it('should throw an error if user uuid is invalid', async () => {
- const result = await createUseCase().execute({
- userUuid: 'invalid',
- })
- expect(result.isFailed()).toBeTruthy()
- })
- describe('shared vault context', () => {
- it('should add shared vault context if shared vault owner uuid is provided', async () => {
- await createUseCase().execute({
- user,
- session,
- sharedVaultOwnerContext: '00000000-0000-0000-0000-000000000000',
- })
- expect(tokenEncoder.encodeExpirableToken).toHaveBeenCalledWith(
- {
- roles: [
- {
- name: 'role1',
- uuid: '1-3-4',
- },
- ],
- belongs_to_shared_vaults: [
- {
- shared_vault_uuid: '00000000-0000-0000-0000-000000000000',
- permission: 'read',
- },
- ],
- session: {
- test: 'test',
- },
- shared_vault_owner_context: {
- upload_bytes_limit: 100,
- },
- user: {
- email: 'test@test.te',
- uuid: '00000000-0000-0000-0000-000000000000',
- },
- ongoing_revisions_transition: false,
- ongoing_transition: false,
- },
- 60,
- )
- })
- it('should throw an error if shared vault owner context is sensitive', async () => {
- getSettingUseCase.execute = jest.fn().mockReturnValue(Result.ok({ sensitive: true }))
- const result = await createUseCase().execute({
- user,
- session,
- sharedVaultOwnerContext: '00000000-0000-0000-0000-000000000000',
- })
- expect(result.isFailed()).toBeTruthy()
- })
- it('should throw an error if it fails to retrieve shared vault owner setting', async () => {
- getSettingUseCase.execute = jest.fn().mockReturnValue(Result.fail('Oops'))
- const result = await createUseCase().execute({
- user,
- session,
- sharedVaultOwnerContext: '00000000-0000-0000-0000-000000000000',
- })
- expect(result.isFailed()).toBeTruthy()
- })
- })
- })
|