Skip to content

Commit

Permalink
Merge branch 'develop' into fix-ito-icon
Browse files Browse the repository at this point in the history
* develop:
  refactor: move backup code to backup-format package (#5922)
  fix: incorrect text (#6096)
  chore: change iOS idb fix
  chore: improve code style (#6090)
  refactor: cleanup code and add deprecations
  refactor: cleanup code
  feat: add transaction dialog in saving plugin (#6076)
  refactor: cleanup code
  refactor: cleanup post context (#6089)
  feat: add ECKeyIdentifier.publicKeyAsHex close GH-6082 (#6085)
  refactor: avoid prop drilling (#6083)
  chore: setup i18n in background (#6086)
  chore: improve eslint (#6084)
  fix: sprint2 ui issues  (#6042)
  refactor: rename createSubscriptionFromValueRef
  chore: update plugin template
  fix: incorrect plugin name (#6077)
  • Loading branch information
yanzhihong23 committed Apr 18, 2022
2 parents ec5eecf + 21d85c5 commit dc0f6b3
Show file tree
Hide file tree
Showing 166 changed files with 2,125 additions and 1,819 deletions.
3 changes: 2 additions & 1 deletion .eslintignore
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
*.d.ts
*.test.tsx
build/
dist/
dist
gun.js
e2e
package.json
packages/contracts
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,16 +47,16 @@
"lodash-unified": "1.0.2",
"react": "18.0.0",
"react-dom": "18.0.0",
"ses": "0.15.12",
"react-i18next": "^11.16.5",
"ses": "0.15.12",
"ts-results": "3.3.0",
"web3-core": "1.7.3",
"web3-core-method": "1.7.3"
},
"devDependencies": {
"@commitlint/cli": "^16.2.3",
"@commitlint/config-conventional": "^16.2.1",
"@dimensiondev/eslint-plugin": "^0.0.1-20220117062517-fd3cb01",
"@dimensiondev/eslint-plugin": "^0.0.2-20220414093950-7d54c58",
"@dimensiondev/patch-package": "^6.5.0",
"@jest/globals": "^28.0.0-alpha.8",
"@magic-works/i18n-codegen": "^0.1.0",
Expand Down
18 changes: 11 additions & 7 deletions packages/.eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -65,15 +65,19 @@
"unicorn/prefer-number-properties": "error",
"unicorn/relative-url-style": ["error", "always"],
"unicorn/throw-new-error": "error",
"@dimensiondev/no-jsx-template-literal": "error",
"@dimensiondev/no-locale-case": "error",
"@dimensiondev/array/no-implicit-sort": "error",
"@dimensiondev/browser/prefer-location-assign": "error",
"@dimensiondev/jsx/no-class-component": "error",
"@dimensiondev/jsx/no-template-literal": "error",
"@dimensiondev/no-number-constructor": "off",
"@dimensiondev/no-simple-string-interpolation": "off",
"@dimensiondev/no-simple-template-literal": "error",
"@dimensiondev/no-unneeded-to-string": "error",
"@dimensiondev/prefer-early-return": "error",
"@dimensiondev/prefer-location-assign": "error",
"@dimensiondev/unicode-specific-set": "error",
"@dimensiondev/string/no-interpolation": "off",
"@dimensiondev/string/no-locale-case": "error",
"@dimensiondev/string/no-simple-template-literal": "error",
"@dimensiondev/string/no-unneeded-to-string": "error",
"@dimensiondev/type/no-instanceof-wrapper": "error",
"@dimensiondev/type/no-wrapper-type-reference": "error",
"@dimensiondev/unicode/specific-set": "error",
"@typescript-eslint/await-thenable": "error",
"@typescript-eslint/no-base-to-string": "off",
"@typescript-eslint/no-for-in-array": "error",
Expand Down
1 change: 1 addition & 0 deletions packages/backup-format/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
"types": "./dist/index.d.ts",
"type": "module",
"dependencies": {
"@masknet/shared-base": "workspace:*",
"@msgpack/msgpack": "^2.7.2"
}
}
6 changes: 4 additions & 2 deletions packages/backup-format/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
export * from './v3-EncryptedJSON'
export * from './BackupErrors'
export { encryptBackup, decryptBackup } from './version-3'
export { BackupErrors } from './BackupErrors'
export { normalizeBackup, type NormalizedBackup, createEmptyNormalizedBackup, generateBackupRAW } from './normalize'
export { getBackupPreviewInfo, type BackupPreview } from './utils/backupPreview'
44 changes: 44 additions & 0 deletions packages/backup-format/src/normalize/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { ECKeyIdentifier, IdentifierMap, PostIVIdentifier, ProfileIdentifier } from '@masknet/shared-base'
import { None } from 'ts-results'
import { BackupErrors } from '../BackupErrors'
import { isBackupVersion0, normalizeBackupVersion0 } from '../version-0'
import { isBackupVersion1, normalizeBackupVersion1 } from '../version-1'
import { generateBackupVersion2, isBackupVersion2, normalizeBackupVersion2 } from '../version-2'
import type { NormalizedBackup } from './type'

export * from './type'
function __normalizeBackup(data: unknown): NormalizedBackup.Data {
if (isBackupVersion2(data)) return normalizeBackupVersion2(data)
if (isBackupVersion1(data)) return normalizeBackupVersion1(data)
if (isBackupVersion0(data)) return normalizeBackupVersion0(data)
throw new TypeError(BackupErrors.UnknownFormat)
}

export function normalizeBackup(data: unknown): NormalizedBackup.Data {
const normalized = __normalizeBackup(data)

// fix invalid URL
normalized.settings.grantedHostPermissions = normalized.settings.grantedHostPermissions.filter((url) =>
/^(http|<all_urls>)/.test(url),
)
return normalized
}

/** It will return the internal format. DO NOT rely on the detail of it! */
export function generateBackupRAW(data: NormalizedBackup.Data): unknown {
const result = generateBackupVersion2(data)
return result
}

export function createEmptyNormalizedBackup(): NormalizedBackup.Data {
return {
meta: { version: 2, createdAt: None, maskVersion: None },
personas: new IdentifierMap(new Map(), ECKeyIdentifier),
profiles: new IdentifierMap(new Map(), ProfileIdentifier),
posts: new IdentifierMap(new Map(), PostIVIdentifier),
relations: [],
settings: { grantedHostPermissions: [] },
wallets: [],
plugins: {},
}
}
99 changes: 99 additions & 0 deletions packages/backup-format/src/normalize/type.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
import type {
PersonaIdentifier,
EC_Private_JsonWebKey,
EC_Public_JsonWebKey,
AESJsonWebKey,
ProfileIdentifier,
RelationFavor,
PostIVIdentifier,
IdentifierMap,
} from '@masknet/shared-base'
import type { Option } from 'ts-results'

// All optional type in this file is marked by Option<T> because we don't want to miss any field.
export namespace NormalizedBackup {
export interface Data {
/** Meta about this backup */
meta: Meta
personas: IdentifierMap<PersonaIdentifier, PersonaBackup>
profiles: IdentifierMap<ProfileIdentifier, ProfileBackup>
relations: RelationBackup[]
posts: IdentifierMap<PostIVIdentifier, PostBackup>
wallets: WalletBackup[]
settings: SettingsBackup
plugins: Record<string, unknown>
}
export interface Meta {
/** Backup file version */
version: 0 | 1 | 2
/** Backup created by which Mask version */
maskVersion: Option<string>
createdAt: Option<Date>
}
export interface PersonaBackup {
identifier: PersonaIdentifier
mnemonic: Option<Mnemonic>
publicKey: EC_Public_JsonWebKey
privateKey: Option<EC_Private_JsonWebKey>
localKey: Option<AESJsonWebKey>
linkedProfiles: IdentifierMap<ProfileIdentifier, unknown>
nickname: Option<string>
createdAt: Option<Date>
updatedAt: Option<Date>
}
export interface Mnemonic {
words: string
path: string
hasPassword: boolean
}
export interface ProfileBackup {
identifier: ProfileIdentifier
nickname: Option<string>
localKey: Option<AESJsonWebKey>
linkedPersona: Option<PersonaIdentifier>
createdAt: Option<Date>
updatedAt: Option<Date>
}
export interface RelationBackup {
profile: ProfileIdentifier
persona: PersonaIdentifier
favor: RelationFavor
}
export interface PostBackup {
identifier: PostIVIdentifier
postBy: ProfileIdentifier
postCryptoKey: Option<AESJsonWebKey>
recipients: Option<PostReceiverPublic | PostReceiverE2E>
foundAt: Date
encryptBy: Option<PersonaIdentifier>
url: Option<string>
summary: Option<string>
interestedMeta: ReadonlyMap<string, unknown>
}
export interface PostReceiverPublic {
type: 'public'
}
export interface PostReceiverE2E {
type: 'e2e'
receivers: IdentifierMap<ProfileIdentifier, RecipientReason[]>
}
export interface RecipientReason {
type: 'auto-share' | 'direct' | 'group'
// We don't care about this field anymore. Do not wrap it with Option<T>
group?: unknown
at: Date
}
export interface WalletBackup {
address: string
name: string
passphrase: Option<string>
publicKey: Option<EC_Public_JsonWebKey>
privateKey: Option<EC_Private_JsonWebKey>
mnemonic: Option<Mnemonic>
createdAt: Date
updatedAt: Date
}
export interface SettingsBackup {
grantedHostPermissions: string[]
}
}
31 changes: 31 additions & 0 deletions packages/backup-format/src/utils/backupPreview.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import type { NormalizedBackup } from '@masknet/backup-format'

export interface BackupPreview {
personas: number
accounts: number
posts: number
contacts: number
relations: number
files: number
wallets: number
createdAt: number
}

export function getBackupPreviewInfo(json: NormalizedBackup.Data): BackupPreview {
let files = 0

try {
files = Number((json.plugins?.['com.maskbook.fileservice'] as any)?.length || 0)
} catch {}

return {
personas: json.personas.size,
accounts: [...json.personas.values()].reduce((a, b) => a + b.linkedProfiles.size, 0),
posts: json.posts.size,
contacts: json.profiles.size,
relations: json.relations.length,
files,
wallets: json.wallets.length,
createdAt: Number(json.meta.createdAt),
}
}
75 changes: 75 additions & 0 deletions packages/backup-format/src/version-0/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import {
AESJsonWebKey,
ECKeyIdentifierFromJsonWebKey,
EC_Private_JsonWebKey,
EC_Public_JsonWebKey,
IdentifierMap,
isAESJsonWebKey,
isEC_Private_JsonWebKey,
isEC_Public_JsonWebKey,
ProfileIdentifier,
} from '@masknet/shared-base'
import { isObjectLike } from 'lodash-unified'
import { None, Some } from 'ts-results'
import { createEmptyNormalizedBackup } from '../normalize'
import type { NormalizedBackup } from '../normalize/type'

export function isBackupVersion0(obj: unknown): obj is BackupJSONFileVersion0 {
if (!isObjectLike(obj)) return false
try {
const data: BackupJSONFileVersion0 = obj as any
if (!data.local || !data.key || !data.key.key || !data.key.key.privateKey || !data.key.key.publicKey)
return false
return true
} catch {
return false
}
}
export function normalizeBackupVersion0(file: BackupJSONFileVersion0): NormalizedBackup.Data {
const backup = createEmptyNormalizedBackup()
backup.meta.version = 0
backup.meta.maskVersion = Some('<=1.3.2')

const { local } = file
const { username, key } = file.key
const { publicKey, privateKey } = key

if (!isEC_Public_JsonWebKey(publicKey)) return backup

const persona: NormalizedBackup.PersonaBackup = {
identifier: ECKeyIdentifierFromJsonWebKey(publicKey),
publicKey,
linkedProfiles: new IdentifierMap<ProfileIdentifier, any>(new Map(), ProfileIdentifier),
localKey: isAESJsonWebKey(local) ? Some(local) : None,
privateKey: isEC_Private_JsonWebKey(privateKey) ? Some(privateKey) : None,
mnemonic: None,
nickname: None,
createdAt: None,
updatedAt: None,
}
backup.personas.set(persona.identifier, persona)

if (username && username !== '$unknown' && username !== '$local') {
const profile: NormalizedBackup.ProfileBackup = {
identifier: new ProfileIdentifier('facebook.com', username),
linkedPersona: Some(persona.identifier),
createdAt: None,
updatedAt: None,
localKey: isAESJsonWebKey(local) ? Some(local) : None,
nickname: None,
}
backup.profiles.set(profile.identifier, profile)
persona.linkedProfiles.set(profile.identifier, void 0)
}

return backup
}
interface BackupJSONFileVersion0 {
key: {
username: string
key: { publicKey: EC_Public_JsonWebKey; privateKey?: EC_Private_JsonWebKey }
algor: unknown
usages: string[]
}
local: AESJsonWebKey
}
Loading

0 comments on commit dc0f6b3

Please sign in to comment.