diff --git a/packages/api/src/services/save_email.ts b/packages/api/src/services/save_email.ts index dbb0a8ed5..306657c19 100644 --- a/packages/api/src/services/save_email.ts +++ b/packages/api/src/services/save_email.ts @@ -9,6 +9,7 @@ import { import normalizeUrl from 'normalize-url' import { kx } from '../datalayer/knex_config' import { UserArticleData } from '../datalayer/links/model' +import { setClaims } from '../datalayer/helpers' export type SaveContext = { pubsub: PubsubClient @@ -82,16 +83,21 @@ export const saveEmail = async ( if (matchedUserArticleRecord) { await ctx.pubsub.pageCreated(saverId, url, input.originalContent) - result = await ctx.models.userArticle.update(matchedUserArticleRecord.id, { - savedAt: new Date(), - archivedAt: null, + await kx.transaction(async (tx) => { + await setClaims(tx, saverId) + result = await ctx.models.userArticle.update( + matchedUserArticleRecord.id, + { + savedAt: new Date(), + archivedAt: null, + } + ) }) } else { await ctx.pubsub.pageCreated(saverId, url, input.originalContent) await kx.transaction(async (tx) => { const articleRecord = await ctx.models.article.create(articleToSave, tx) - result = await ctx.models.userArticle.create( { userId: saverId, diff --git a/packages/api/test/services/save_email.test.ts b/packages/api/test/services/save_email.test.ts new file mode 100644 index 000000000..586a60dab --- /dev/null +++ b/packages/api/test/services/save_email.test.ts @@ -0,0 +1,58 @@ +import 'mocha' +import { expect } from 'chai' +import 'chai/register-should' +import { + createTestUser, + deleteTestUser, +} from '../db' +import { SaveContext, saveEmail } from '../../src/services/save_email' +import { getRepository } from 'typeorm' +import { Link } from '../../src/entity/link' +import { initModels } from '../../src/server' +import { kx } from '../../src/datalayer/knex_config' +import { createPubSubClient } from '../../src/datalayer/pubsub' + +describe('saveEmail', () => { + const username = 'fakeUser' + after(async () => { + await deleteTestUser(username) + }) + + it('doesnt fail if saved twice', async () => { + const user = await createTestUser(username) + const ctx: SaveContext = { + models: initModels(kx, false), + pubsub: createPubSubClient(), + } + + await saveEmail(ctx, user.id, { + originalContent: 'fake content', + url: 'https://example.com', + title: 'fake title', + author: 'fake author', + }) + + // This ensures row level security doesnt prevent + // resaving the same URL + const secondResult = await saveEmail(ctx, user.id, { + originalContent: 'fake content', + url: 'https://example.com', + title: 'fake title', + author: 'fake author', + }) + expect(secondResult).to.not.be.undefined + + const links = await getRepository(Link).find({ + where: { + user: user, + }, + relations: ['page'], + }) + + expect(links.length).to.equal(1) + expect(links[0].page.url).to.equal('https://example.com') + expect(links[0].page.title).to.equal('fake title') + expect(links[0].page.author).to.equal('fake author') + expect(links[0].page.content).to.contain('fake content') + }).timeout(10000) +})