Skip to content

Commit

Permalink
feat: Allow to send Pouch databases through email for debug purpose
Browse files Browse the repository at this point in the history
  • Loading branch information
Ldoppea committed Jul 26, 2024
1 parent cb3bb8a commit 21dbcff
Show file tree
Hide file tree
Showing 4 changed files with 141 additions and 0 deletions.
5 changes: 5 additions & 0 deletions src/hooks/useAppBootstrap.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { useEffect, useState } from 'react'
import { deconstructCozyWebLinkWithSlug } from 'cozy-client'

import { handleLogsDeepLink } from '/app/domain/logger/deeplinkHandler'
import { handleDbDeepLink } from '/pouchdb/deeplinkHandler'
import { SentryCustomTags, setSentryTag } from '/libs/monitoring/Sentry'
import { manageIconCache } from '/libs/functions/iconTable'
import { getDefaultIconParams } from '/libs/functions/openApp'
Expand Down Expand Up @@ -160,6 +161,10 @@ export const useAppBootstrap = client => {
return
}

if (handleDbDeepLink(url, client)) {
return
}

if (!client) {
const action = parseOnboardLink(url)

Expand Down
1 change: 1 addition & 0 deletions src/hooks/useAppBootstrap.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ jest.mock('/libs/RootNavigation', () => ({
jest.mock('./useSplashScreen', () => ({
useSplashScreen: () => ({ hideSplashScreen: mockHideSplashScreen })
}))
jest.mock('/app/theme/SplashScreenService', () => ({}))

jest.mock('/libs/functions/openApp', () => ({
getDefaultIconParams: jest.fn().mockReturnValue({})
Expand Down
23 changes: 23 additions & 0 deletions src/pouchdb/deeplinkHandler.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import CozyClient from 'cozy-client'

import strings from '/constants/strings.json'
import { sendDbByEmail } from '/pouchdb/sendDbByEmail'

export const handleDbDeepLink = (url: string, client?: CozyClient): boolean => {
if (isSendDbDeepLink(url)) {
void sendDbByEmail(client)

return true
}

return false
}

const isSendDbDeepLink = (url: string): boolean => {
const deepLinks = [
`${strings.COZY_SCHEME}senddb`,
`${strings.UNIVERSAL_LINK_BASE}/senddb`
]

return deepLinks.includes(url.toLowerCase())
}
112 changes: 112 additions & 0 deletions src/pouchdb/sendDbByEmail.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
import { Alert, PermissionsAndroid } from 'react-native'
import Mailer from 'react-native-mail'
import RNFS from 'react-native-fs'
import RNFetchBlob from 'rn-fetch-blob'
import DeviceInfo from 'react-native-device-info'

import type CozyClient from 'cozy-client'
import Minilog from 'cozy-minilog'

import { fetchSupportMail } from '/app/domain/logger/supportEmail'
import {
hideSplashScreen,
showSplashScreen,
splashScreens
} from '/app/theme/SplashScreenService'
import { getInstanceAndFqdnFromClient } from '/libs/client'

const log = Minilog('🗒️ DB Mailer')

export const sendDbByEmail = async (client?: CozyClient): Promise<void> => {
log.info('Send DB by email')

if (!client) {
log.info('SendDbByEmail called with no client, return')
return
}
try {

Check failure on line 28 in src/pouchdb/sendDbByEmail.ts

View workflow job for this annotation

GitHub Actions / Quality Checks

Replace `⏎` with `··`
const permission = PermissionsAndroid.PERMISSIONS.WRITE_EXTERNAL_STORAGE
await PermissionsAndroid.request(permission)

Check failure on line 30 in src/pouchdb/sendDbByEmail.ts

View workflow job for this annotation

GitHub Actions / Quality Checks

Insert `··`

const supportEmail = await fetchSupportMail(client)

Check failure on line 32 in src/pouchdb/sendDbByEmail.ts

View workflow job for this annotation

GitHub Actions / Quality Checks

Insert `··`

const { fqdn } = getInstanceAndFqdnFromClient(client)

Check failure on line 34 in src/pouchdb/sendDbByEmail.ts

View workflow job for this annotation

GitHub Actions / Quality Checks

Insert `··`

const instance = client.getStackClient().uri ?? 'not logged app'

Check failure on line 36 in src/pouchdb/sendDbByEmail.ts

View workflow job for this annotation

GitHub Actions / Quality Checks

Insert `··`

const subject = `DB file for ${instance}`

const files = await RNFS.readDir(RNFS.DocumentDirectoryPath)

const dbFiles = files.filter(f => f.name.startsWith(`${fqdn}_`))

const externalFiles = []
for (const dbFile of dbFiles) {
const dirs = RNFetchBlob.fs.dirs

const internalPath = dbFile.path

const date = Number(new Date())
const externalPath = `${dirs.DCIMDir}/DbFile_${dbFile.name}${date}.sqlite`

await RNFS.copyFile(internalPath, externalPath)

externalFiles.push({
path: externalPath
})
}

await showSplashScreen(splashScreens.SEND_LOG_EMAIL)
log.info('Start email intent')
Mailer.mail(
{
subject: subject,
recipients: [supportEmail],
body: buildMessageBody(),
customChooserTitle: 'This is my new title', // Android only (defaults to "Send Mail")
isHTML: true,
attachments: externalFiles
},
(error, event) => {
Alert.alert(
error,
event,
[
{
text: 'Ok',
onPress: (): void => log.debug('OK: Email Error Response')
},
{
text: 'Cancel',
onPress: (): void => log.debug('CANCEL: Email Error Response')
}
],
{ cancelable: true }
)
}
)
log.info('Did finish email intent')
await hideSplashScreen(splashScreens.SEND_LOG_EMAIL)

}
catch (err) {
console.log('🍎 ERORR WHILE EMAIL', err.message)
}
}

const buildMessageBody = (): string => {
const appVersion = DeviceInfo.getVersion()
const appBuild = DeviceInfo.getBuildNumber()
const bundle = DeviceInfo.getBundleId()
const deviceBrand = DeviceInfo.getBrand()
const deviceModel = DeviceInfo.getModel()
const os = DeviceInfo.getSystemName()
const version = DeviceInfo.getSystemVersion()

const appInfo = `App info: ${appVersion} (${appBuild})`
const bundleInfo = `App bundle: ${bundle}`
const deviceInfo = `Device info: ${deviceBrand} ${deviceModel} ${os} ${version}`

return `${appInfo}\n${bundleInfo}\n${deviceInfo}`
}

0 comments on commit 21dbcff

Please sign in to comment.