SettingService.spec.ts 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. import 'reflect-metadata'
  2. import { LogSessionUserAgentOption, MuteSignInEmailsOption, SettingName } from '@standardnotes/settings'
  3. import { Logger } from 'winston'
  4. import { EncryptionVersion } from '../Encryption/EncryptionVersion'
  5. import { User } from '../User/User'
  6. import { Setting } from './Setting'
  7. import { SettingRepositoryInterface } from './SettingRepositoryInterface'
  8. import { SettingService } from './SettingService'
  9. import { SettingsAssociationServiceInterface } from './SettingsAssociationServiceInterface'
  10. import { SettingInterpreterInterface } from './SettingInterpreterInterface'
  11. import { SettingDecrypterInterface } from './SettingDecrypterInterface'
  12. import { SettingFactoryInterface } from './SettingFactoryInterface'
  13. describe('SettingService', () => {
  14. let setting: Setting
  15. let user: User
  16. let factory: SettingFactoryInterface
  17. let settingRepository: SettingRepositoryInterface
  18. let settingsAssociationService: SettingsAssociationServiceInterface
  19. let settingInterpreter: SettingInterpreterInterface
  20. let settingDecrypter: SettingDecrypterInterface
  21. let logger: Logger
  22. const createService = () =>
  23. new SettingService(
  24. factory,
  25. settingRepository,
  26. settingsAssociationService,
  27. settingInterpreter,
  28. settingDecrypter,
  29. logger,
  30. )
  31. beforeEach(() => {
  32. user = {
  33. uuid: '4-5-6',
  34. } as jest.Mocked<User>
  35. user.isPotentiallyAPrivateUsernameAccount = jest.fn().mockReturnValue(false)
  36. setting = {
  37. name: SettingName.NAMES.DropboxBackupToken,
  38. } as jest.Mocked<Setting>
  39. factory = {} as jest.Mocked<SettingFactoryInterface>
  40. factory.create = jest.fn().mockReturnValue(setting)
  41. factory.createReplacement = jest.fn().mockReturnValue(setting)
  42. settingRepository = {} as jest.Mocked<SettingRepositoryInterface>
  43. settingRepository.findLastByNameAndUserUuid = jest.fn().mockReturnValue(null)
  44. settingRepository.findOneByNameAndUserUuid = jest.fn().mockReturnValue(null)
  45. settingRepository.save = jest.fn().mockImplementation((setting) => setting)
  46. settingsAssociationService = {} as jest.Mocked<SettingsAssociationServiceInterface>
  47. settingsAssociationService.getDefaultSettingsAndValuesForNewUser = jest.fn().mockReturnValue(
  48. new Map([
  49. [
  50. SettingName.NAMES.MuteSignInEmails,
  51. {
  52. value: MuteSignInEmailsOption.NotMuted,
  53. sensitive: 0,
  54. serverEncryptionVersion: EncryptionVersion.Unencrypted,
  55. },
  56. ],
  57. ]),
  58. )
  59. settingsAssociationService.getDefaultSettingsAndValuesForNewPrivateUsernameAccount = jest.fn().mockReturnValue(
  60. new Map([
  61. [
  62. SettingName.NAMES.LogSessionUserAgent,
  63. {
  64. sensitive: false,
  65. serverEncryptionVersion: EncryptionVersion.Unencrypted,
  66. value: LogSessionUserAgentOption.Disabled,
  67. },
  68. ],
  69. ]),
  70. )
  71. settingInterpreter = {} as jest.Mocked<SettingInterpreterInterface>
  72. settingInterpreter.interpretSettingUpdated = jest.fn()
  73. settingDecrypter = {} as jest.Mocked<SettingDecrypterInterface>
  74. settingDecrypter.decryptSettingValue = jest.fn().mockReturnValue('decrypted')
  75. logger = {} as jest.Mocked<Logger>
  76. logger.debug = jest.fn()
  77. logger.warn = jest.fn()
  78. logger.error = jest.fn()
  79. })
  80. it('should create default settings for a newly registered user', async () => {
  81. await createService().applyDefaultSettingsUponRegistration(user)
  82. expect(settingRepository.save).toHaveBeenCalledWith(setting)
  83. })
  84. it('should create default settings for a newly registered vault account', async () => {
  85. user.isPotentiallyAPrivateUsernameAccount = jest.fn().mockReturnValue(true)
  86. await createService().applyDefaultSettingsUponRegistration(user)
  87. expect(settingRepository.save).toHaveBeenCalledWith(setting)
  88. })
  89. it("should create setting if it doesn't exist", async () => {
  90. const result = await createService().createOrReplace({
  91. user,
  92. props: {
  93. name: SettingName.NAMES.MuteFailedBackupsEmails,
  94. unencryptedValue: 'value',
  95. serverEncryptionVersion: 1,
  96. sensitive: false,
  97. },
  98. })
  99. expect(result.status).toEqual('created')
  100. })
  101. it('should throw error if setting name is not valid', async () => {
  102. await expect(
  103. createService().createOrReplace({
  104. user,
  105. props: {
  106. name: 'invalid',
  107. unencryptedValue: 'value',
  108. serverEncryptionVersion: 1,
  109. sensitive: false,
  110. },
  111. }),
  112. ).rejects.toThrowError('Invalid setting name: invalid')
  113. })
  114. it('should create setting with a given uuid if it does not exist', async () => {
  115. settingRepository.findOneByUuid = jest.fn().mockReturnValue(null)
  116. const result = await createService().createOrReplace({
  117. user,
  118. props: {
  119. uuid: '1-2-3',
  120. name: SettingName.NAMES.MuteFailedBackupsEmails,
  121. unencryptedValue: 'value',
  122. serverEncryptionVersion: 1,
  123. sensitive: false,
  124. },
  125. })
  126. expect(result.status).toEqual('created')
  127. })
  128. it('should replace setting if it does exist', async () => {
  129. settingRepository.findLastByNameAndUserUuid = jest.fn().mockReturnValue(setting)
  130. const result = await createService().createOrReplace({
  131. user: user,
  132. props: {
  133. ...setting,
  134. unencryptedValue: 'value',
  135. serverEncryptionVersion: 1,
  136. },
  137. })
  138. expect(result.status).toEqual('replaced')
  139. })
  140. it('should replace setting with a given uuid if it does exist', async () => {
  141. settingRepository.findOneByUuid = jest.fn().mockReturnValue(setting)
  142. const result = await createService().createOrReplace({
  143. user: user,
  144. props: {
  145. ...setting,
  146. uuid: '1-2-3',
  147. unencryptedValue: 'value',
  148. serverEncryptionVersion: 1,
  149. },
  150. })
  151. expect(result.status).toEqual('replaced')
  152. })
  153. it('should find and decrypt the value of a setting for user', async () => {
  154. setting = {
  155. value: 'encrypted',
  156. serverEncryptionVersion: EncryptionVersion.Default,
  157. } as jest.Mocked<Setting>
  158. settingRepository.findLastByNameAndUserUuid = jest.fn().mockReturnValue(setting)
  159. expect(
  160. await createService().findSettingWithDecryptedValue({
  161. userUuid: '1-2-3',
  162. settingName: SettingName.create(SettingName.NAMES.LogSessionUserAgent).getValue(),
  163. }),
  164. ).toEqual({
  165. serverEncryptionVersion: 1,
  166. value: 'decrypted',
  167. })
  168. })
  169. })