diff --git a/lib/types/avatar-types.js b/lib/types/avatar-types.js index 2ecaee69b..e669f63bc 100644 --- a/lib/types/avatar-types.js +++ b/lib/types/avatar-types.js @@ -1,98 +1,105 @@ // @flow import t, { type TUnion, type TInterface } from 'tcomb'; import type { CreateUpdatesResult } from './update-types.js'; import { validHexColorRegex } from '../shared/account-utils.js'; import { onlyOneEmojiRegex } from '../shared/emojis.js'; import { tRegex, tShape, tString } from '../utils/validation-utils.js'; export type EmojiAvatarDBContent = { +type: 'emoji', +emoji: string, +color: string, // hex, without "#" or "0x" }; export const emojiAvatarDBContentValidator: TInterface = tShape({ type: tString('emoji'), emoji: tRegex(onlyOneEmojiRegex), color: tRegex(validHexColorRegex), }); export type ImageAvatarDBContent = { +type: 'image', +uploadID: string, }; export type EncryptedImageAvatarDBContent = { +type: 'encrypted_image', +uploadID: string, }; export type ENSAvatarDBContent = { +type: 'ens', }; export const ensAvatarDBContentValidator: TInterface = tShape({ type: tString('ens') }); export type AvatarDBContent = | EmojiAvatarDBContent | ImageAvatarDBContent | EncryptedImageAvatarDBContent | ENSAvatarDBContent; export type UpdateUserAvatarRemoveRequest = { +type: 'remove' }; export type UpdateUserAvatarRequest = | AvatarDBContent | UpdateUserAvatarRemoveRequest; export type ClientEmojiAvatar = EmojiAvatarDBContent; const clientEmojiAvatarValidator = emojiAvatarDBContentValidator; export type ClientImageAvatar = { +type: 'image', +uri: string, }; const clientImageAvatarValidator = tShape({ type: tString('image'), uri: t.String, }); export type ClientEncryptedImageAvatar = { +type: 'encrypted_image', +blobURI: string, +encryptionKey: string, +thumbHash: ?string, }; +const clientEncryptedImageAvatarValidator = tShape({ + type: tString('encrypted_image'), + blobURI: t.String, + encryptionKey: t.String, + thumbHash: t.maybe(t.String), +}); export type ClientENSAvatar = ENSAvatarDBContent; const clientENSAvatarValidator = ensAvatarDBContentValidator; export type ClientAvatar = | ClientEmojiAvatar | ClientImageAvatar | ClientEncryptedImageAvatar | ClientENSAvatar; export const clientAvatarValidator: TUnion = t.union([ clientEmojiAvatarValidator, clientImageAvatarValidator, clientENSAvatarValidator, + clientEncryptedImageAvatarValidator, ]); export type ResolvedClientAvatar = | ClientEmojiAvatar | ClientImageAvatar | ClientEncryptedImageAvatar; export type UpdateUserAvatarResponse = { +updates: CreateUpdatesResult, }; export type GenericUserInfoWithAvatar = { +username?: ?string, +avatar?: ?ClientAvatar, ... }; export type AvatarSize = 'XS' | 'S' | 'M' | 'L' | 'XL' | 'XXL'; diff --git a/lib/utils/avatar-utils.js b/lib/utils/avatar-utils.js index 1e1ada787..be56c1736 100644 --- a/lib/utils/avatar-utils.js +++ b/lib/utils/avatar-utils.js @@ -1,39 +1,47 @@ // @flow import t from 'tcomb'; import type { TUnion, TInterface } from 'tcomb'; import { tShape, tString, tID } from './validation-utils.js'; import { type ImageAvatarDBContent, type UpdateUserAvatarRemoveRequest, type UpdateUserAvatarRequest, emojiAvatarDBContentValidator, ensAvatarDBContentValidator, } from '../types/avatar-types.js'; const imageAvatarDBContentValidator: TInterface = tShape({ type: tString('image'), uploadID: tID, }); +const encryptedImageAvatarDBContentValidator: TInterface = + tShape({ + type: tString('encrypted_image'), + uploadID: tID, + }); + const updateUserAvatarRemoveRequestValidator: TInterface = tShape({ type: tString('remove'), }); const updateUserAvatarRequestValidator: TUnion = t.union([ emojiAvatarDBContentValidator, imageAvatarDBContentValidator, + encryptedImageAvatarDBContentValidator, ensAvatarDBContentValidator, updateUserAvatarRemoveRequestValidator, ]); export { emojiAvatarDBContentValidator, imageAvatarDBContentValidator, + encryptedImageAvatarDBContentValidator, ensAvatarDBContentValidator, updateUserAvatarRemoveRequestValidator, updateUserAvatarRequestValidator, }; diff --git a/lib/utils/avatar-utils.test.js b/lib/utils/avatar-utils.test.js index 8b9c51706..f5a7cc5c5 100644 --- a/lib/utils/avatar-utils.test.js +++ b/lib/utils/avatar-utils.test.js @@ -1,122 +1,152 @@ // @flow import { emojiAvatarDBContentValidator, ensAvatarDBContentValidator, imageAvatarDBContentValidator, + encryptedImageAvatarDBContentValidator, updateUserAvatarRequestValidator, } from './avatar-utils.js'; describe('emojiAvatarDBContentValidator', () => { it('should succeed for valid input', () => { expect( emojiAvatarDBContentValidator.is({ type: 'emoji', emoji: '👍', color: '4b87aa', }), ).toBe(true); }); it('should fail if type is incorrect', () => { expect( emojiAvatarDBContentValidator.is({ type: 'memoji', emoji: '👍', color: '4b87aa', }), ).toBe(false); }); it(`should fail if emoji isn't valid`, () => { expect( emojiAvatarDBContentValidator.is({ type: 'emoji', emoji: ':)', color: '4b87aa', }), ).toBe(false); }); it(`should fail if color isn't valid`, () => { expect( emojiAvatarDBContentValidator.is({ type: 'emoji', emoji: '👍', color: '#4b87aa', }), ).toBe(false); expect( emojiAvatarDBContentValidator.is({ type: 'emoji', emoji: '👍', color: '#4b87aa00', }), ).toBe(false); }); }); describe('imageAvatarDBContentValidator', () => { it('should succeed for valid input', () => { expect( imageAvatarDBContentValidator.is({ type: 'image', uploadID: '123456', }), ).toBe(true); }); it('should fail if type is incorrect', () => { expect( imageAvatarDBContentValidator.is({ type: 'emoji', uploadID: '123456', }), ).toBe(false); }); it('should fail if uploadID is incorrect type', () => { expect( imageAvatarDBContentValidator.is({ type: 'image', uploadID: 123456, }), ).toBe(false); }); }); +describe('encryptedImageAvatarDBContentValidator', () => { + it('should succeed for valid input', () => { + expect( + encryptedImageAvatarDBContentValidator.is({ + type: 'encrypted_image', + uploadID: '123456', + }), + ).toBe(true); + }); + + it('should fail if type is incorrect', () => { + expect( + encryptedImageAvatarDBContentValidator.is({ + type: 'emoji', + uploadID: '123456', + }), + ).toBe(false); + }); + + it('should fail if uploadID is incorrect type', () => { + expect( + encryptedImageAvatarDBContentValidator.is({ + type: 'encrypted_image', + uploadID: 123456, + }), + ).toBe(false); + }); +}); + describe('ensAvatarDBContentValidator', () => { it('should succeed for valid input', () => { expect( ensAvatarDBContentValidator.is({ type: 'ens', }), ).toBe(true); }); it('should fail for incorrect type', () => { expect( ensAvatarDBContentValidator.is({ type: 'emoji', }), ).toBe(false); }); }); describe('updateUserAvatarRemoveRequestValidator', () => { it('should succeed for valid input', () => { expect( updateUserAvatarRequestValidator.is({ type: 'remove', }), ).toBe(true); }); it('should fail for incorrect type', () => { expect( updateUserAvatarRequestValidator.is({ type: 'emoji', }), ).toBe(false); }); });