Skip to content

Commit

Permalink
fix: Delete contact from cozy if it has been hidden from google (for …
Browse files Browse the repository at this point in the history
…first sync after migration)
  • Loading branch information
cedricmessiant committed Apr 4, 2019
1 parent f1c2aed commit 0e693ce
Show file tree
Hide file tree
Showing 6 changed files with 174 additions and 8 deletions.
14 changes: 14 additions & 0 deletions src/GoogleUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,20 @@ class GoogleUtils {
})
return response.data
}

async getContact(resourceName, personFields = ['names']) {
const peopleAPI = google.people({
version: 'v1',
auth: this.oAuth2Client
})

const response = await peopleAPI.people.get({
resourceName,
personFields
})

return response.data
}
}

module.exports = GoogleUtils
15 changes: 15 additions & 0 deletions src/GoogleUtils.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ describe('GoogleUtils', () => {
const peopleAPIMock = googleapis.google.people()
const googleCreateContactSpy = peopleAPIMock.people.createContact
const googleUpdateContactSpy = peopleAPIMock.people.updateContact
const googleGetContactSpy = peopleAPIMock.people.get

afterEach(() => {
jest.clearAllMocks()
Expand Down Expand Up @@ -103,4 +104,18 @@ describe('GoogleUtils', () => {
})
})
})

describe('getContact', () => {
it('should retrieve a contact on Google', async () => {
const result = await googleUtils.getContact('people/69042')
expect(result).toEqual({
resourceName: 'people/123456',
etag: '6f5f3948-375c-4b7f-8d6b-241ccb0fba8f'
})
expect(googleGetContactSpy).toHaveBeenCalledWith({
resourceName: 'people/69042',
personFields: ['names']
})
})
})
})
14 changes: 12 additions & 2 deletions src/__mocks__/googleapis.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,14 @@ const createContact = jest.fn(() =>
const updateContact = jest.fn(() =>
Promise.resolve({ data: 'The contact was updated' })
)
const get = jest.fn(() =>
Promise.resolve({
data: {
resourceName: 'people/123456',
etag: '6f5f3948-375c-4b7f-8d6b-241ccb0fba8f'
}
})
)

class FakeOAuth2 {}

Expand All @@ -16,14 +24,16 @@ googleapis.google.auth = {
googleapis.google.people = jest.fn(() => ({
people: {
createContact: createContact,
updateContact: updateContact
updateContact: updateContact,
get: get
}
}))

googleapis.spies = {
FakeOAuth2,
createContact,
updateContact
updateContact,
get
}

module.exports = googleapis
42 changes: 42 additions & 0 deletions src/__snapshots__/synchronizeContacts.spec.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,48 @@ Array [
]
`;

exports[`synchronizeContacts function should synchronize contacts: destroyHowellTowne 1`] = `
Array [
Object {
"_rev": "83152550-fe2b-42a4-a098-5d17c586d2bf",
"_type": "io.cozy.contacts",
"cozyMetadata": Object {
"createdAt": "2013-02-20T19:33:00.123Z",
"createdByApp": "Contacts",
"createdByAppVersion": "2.0.0",
"doctypeVersion": 2,
"sourceAccount": "45c49c15-4b00-48e8-8bfd-29f8177b89ff",
"sync": Object {
"45c49c15-4b00-48e8-8bfd-29f8177b89ff": Object {
"id": "people/1655899",
},
},
"updatedAt": "2017-01-12T12:12:01.222Z",
"updatedByApps": Array [
"konnector-google",
],
},
"email": Array [],
"id": "howell-towne-hidden",
"metadata": Object {
"google": Object {
"metadata": Object {
"sources": Array [
Object {
"etag": "67465901-d316-4dcd-b866-977ff95b056e",
},
],
},
},
},
"name": Object {
"familyName": "Towne",
"givenName": "Howell",
},
},
]
`;

exports[`synchronizeContacts function should synchronize contacts: destroyJohannaMoenInCozy 1`] = `
Array [
Object {
Expand Down
45 changes: 42 additions & 3 deletions src/synchronizeContacts.js
Original file line number Diff line number Diff line change
Expand Up @@ -347,10 +347,49 @@ const synchronizeContacts = async (
)
result.google.updated++
} catch (err) {
if (err.code !== 404) {
throw err
} else {
if (err.code === 404) {
log('info', `Entity not found on google: ${resourceName}`)
} else if (
err.message.includes(
'Request person.etag is different than the current person.etag'
)
) {
try {
// verify if the contact has not been deleted or hidden on Google
const googleContact = await googleUtils.getContact(resourceName)
const debugInfos = {
id: cozyContact.id,
resourceName: get(googleContact, 'resourceName'),
etag,
googleMetadata: get(googleContact, 'metadata'),
oldGoogleMetadata: get(
mergedContact,
'metadata.google.metadata'
),
cozyMetadata: get(mergedContact, 'cozyMetadata')
}
log(
'error',
'Google contact exists but etag is not valid: ' +
JSON.stringify(debugInfos)
)
throw new Error(
'Contact exists on Google but etag is not valid anymore!'
)
} catch (err) {
if (err.code === 404) {
log(
'info',
'Contact does not exist anymore on Google, remove it from cozy'
)
await cozyUtils.client.destroy(cozyContact)
result.cozy.deleted++
} else {
throw err
}
}
} else {
throw err
}
}
} else {
Expand Down
52 changes: 49 additions & 3 deletions src/synchronizeContacts.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,39 @@ const cozyContacts = [
}
}
}
},
// contact that has been hidden on Google before first sync after migration
{
id: 'howell-towne-hidden',
_type: 'io.cozy.contacts',
_rev: '83152550-fe2b-42a4-a098-5d17c586d2bf',
name: { givenName: 'Howell', familyName: 'Towne' },
email: [],
cozyMetadata: {
doctypeVersion: 2,
createdAt: '2013-02-20T19:33:00.123Z',
createdByApp: 'Contacts',
createdByAppVersion: '2.0.0',
updatedAt: '2017-01-12T12:12:01.222Z',
updatedByApps: ['konnector-google'],
sourceAccount: SOURCE_ACCOUNT_ID,
sync: {
[SOURCE_ACCOUNT_ID]: {
id: 'people/1655899'
}
}
},
metadata: {
google: {
metadata: {
sources: [
{
etag: '67465901-d316-4dcd-b866-977ff95b056e'
}
]
}
}
}
}
]

Expand Down Expand Up @@ -369,10 +402,19 @@ describe('synchronizeContacts function', () => {
etag: '7087f1a4-d4b9-4771-86a8-86a04713712d',
resourceName: 'people/1655899' // coleman-hintz-noetag
}) // no etag
googleUtils.updateContact.mockRejectedValueOnce({
code: 400,
message:
'Request person.etag is different than the current person.etag. Clear local cache and get the latest person.' // howell-towne-hidden
}) // hidden contact
googleUtils.deleteContact.mockResolvedValueOnce({
etag: '440922abef-c9b8-4865-bdbd-85561aa7b',
resourceName: 'people/924609' // fabiola-grozdana-deleted-in-cozy
})
googleUtils.getContact.mockRejectedValue({
code: 404,
message: 'Entity not found'
})

fakeCozyClient.save = jest
.fn(contact =>
Expand Down Expand Up @@ -414,7 +456,7 @@ describe('synchronizeContacts function', () => {
expect(result).toEqual({
cozy: {
created: 2,
deleted: 4,
deleted: 5,
updated: 2
},
google: {
Expand Down Expand Up @@ -448,7 +490,7 @@ describe('synchronizeContacts function', () => {
)
expect(fakeCozyClient.save.mock.calls[6]).toMatchSnapshot('johnDoeInCozy')

expect(fakeCozyClient.destroy).toHaveBeenCalledTimes(4)
expect(fakeCozyClient.destroy).toHaveBeenCalledTimes(5)

expect(fakeCozyClient.destroy.mock.calls[0]).toMatchSnapshot(
'destroyAureliaHayesInCozy'
Expand All @@ -466,6 +508,10 @@ describe('synchronizeContacts function', () => {
'destroyFabiolaGrozdanaInCozy'
)

expect(fakeCozyClient.destroy.mock.calls[4]).toMatchSnapshot(
'destroyHowellTowne'
)

expect(googleUtils.createContact).toHaveBeenCalledTimes(2)
expect(googleUtils.createContact.mock.calls[0]).toMatchSnapshot(
'reinholdJenkinsInGoogle'
Expand All @@ -474,7 +520,7 @@ describe('synchronizeContacts function', () => {
'larueCreminInGoogle'
)

expect(googleUtils.updateContact).toHaveBeenCalledTimes(2)
expect(googleUtils.updateContact).toHaveBeenCalledTimes(3)
expect(googleUtils.updateContact.mock.calls[0]).toMatchSnapshot(
'johnDoeInGoogle'
)
Expand Down

0 comments on commit 0e693ce

Please sign in to comment.