From 16e31a3bc5eedb0cdb7f17c7400c62825e52c65b Mon Sep 17 00:00:00 2001 From: Lautaro Petaccio Date: Wed, 1 Dec 2021 14:45:21 -0300 Subject: [PATCH] feat: Upsert items with the server's date --- src/Item/Item.router.spec.ts | 61 +++++++++++++++++++----------------- src/Item/Item.schema.ts | 4 --- src/Item/Item.service.ts | 3 ++ 3 files changed, 35 insertions(+), 33 deletions(-) diff --git a/src/Item/Item.router.spec.ts b/src/Item/Item.router.spec.ts index b10d01de..fc6009ce 100644 --- a/src/Item/Item.router.spec.ts +++ b/src/Item/Item.router.spec.ts @@ -1,6 +1,7 @@ import supertest from 'supertest' import { v4 as uuidv4 } from 'uuid' import { Wallet } from 'ethers' +import { omit } from 'decentraland-commons/dist/utils' import { createAuthHeaders, buildURL, @@ -318,16 +319,18 @@ describe('Item router', () => { jest.Mocked const mockUUID = '75e7da02-a727-48de-a4da-d0778395067b' + let itemToUpsert: Omit beforeEach(() => { url = `/items/${dbItem.id}` + itemToUpsert = omit(dbItem, ['created_at', 'updated_at']) }) describe('and the param id is different from payload id', () => { it('should fail with body and url ids do not match message', async () => { const response = await server .put(buildURL(url)) - .send({ item: { ...dbItem, id: mockUUID } }) + .send({ item: { ...itemToUpsert, id: mockUUID } }) .set(createAuthHeaders('put', url)) .expect(STATUS_CODES.badRequest) @@ -341,12 +344,12 @@ describe('Item router', () => { describe('and the user upserting is not authorized to do so', () => { beforeEach(() => { - mockOwnableCanUpsert(Item, dbItem.id, wallet.address, false) + mockOwnableCanUpsert(Item, itemToUpsert.id, wallet.address, false) }) it('should fail with unauthorized user message', async () => { const response = await server .put(buildURL(url)) - .send({ item: dbItem }) + .send({ item: itemToUpsert }) .set(createAuthHeaders('put', url)) .expect(STATUS_CODES.unauthorized) @@ -360,14 +363,14 @@ describe('Item router', () => { describe('and the collection provided in the payload does not exists in the db', () => { beforeEach(() => { - mockOwnableCanUpsert(Item, dbItem.id, wallet.address, true) + mockOwnableCanUpsert(Item, itemToUpsert.id, wallet.address, true) mockCollection.findOne.mockResolvedValueOnce(undefined) }) it('should fail with collection not found message', async () => { const response = await server .put(buildURL(url)) - .send({ item: dbItem }) + .send({ item: itemToUpsert }) .set(createAuthHeaders('put', url)) .expect(STATUS_CODES.notFound) @@ -382,7 +385,7 @@ describe('Item router', () => { describe('and the collection provided in the payload does not belong to the address making the request', () => { const differentEthAddress = '0xc6d2000a7a1ddca92941f4e2b41360fe4ee2abd8' beforeEach(() => { - mockOwnableCanUpsert(Item, dbItem.id, wallet.address, true) + mockOwnableCanUpsert(Item, itemToUpsert.id, wallet.address, true) mockCollection.findOne.mockResolvedValueOnce({ collection_id: dbItem.collection_id, eth_address: differentEthAddress, @@ -392,15 +395,15 @@ describe('Item router', () => { it('should fail with unauthorized user message', async () => { const response = await server .put(buildURL(url)) - .send({ item: dbItem }) + .send({ item: itemToUpsert }) .set(createAuthHeaders('put', url)) .expect(STATUS_CODES.unauthorized) expect(response.body).toEqual({ data: { - id: dbItem.id, + id: itemToUpsert.id, eth_address: wallet.address, - collection_id: dbItem.collection_id, + collection_id: itemToUpsert.collection_id, }, error: "The new collection for the item isn't owned by the same owner.", @@ -411,19 +414,19 @@ describe('Item router', () => { describe('and the collection of the item is being changed', () => { beforeEach(() => { - mockOwnableCanUpsert(Item, dbItem.id, wallet.address, true) + mockOwnableCanUpsert(Item, itemToUpsert.id, wallet.address, true) }) it('should fail with cant change item collection message', async () => { - mockItem.findOne.mockResolvedValueOnce(dbItem) + mockItem.findOne.mockResolvedValueOnce(itemToUpsert) mockCollection.findOne.mockResolvedValueOnce({ - collection_id: dbItem.collection_id, + collection_id: itemToUpsert.collection_id, eth_address: wallet.address, }) const response = await server .put(buildURL(url)) - .send({ item: { ...dbItem, collection_id: mockUUID } }) + .send({ item: { ...itemToUpsert, collection_id: mockUUID } }) .set(createAuthHeaders('put', url)) .expect(STATUS_CODES.unauthorized) @@ -437,9 +440,9 @@ describe('Item router', () => { describe('when the collection given for the item is locked', () => { beforeEach(() => { - mockOwnableCanUpsert(Item, dbItem.id, wallet.address, true) + mockOwnableCanUpsert(Item, itemToUpsert.id, wallet.address, true) mockCollection.findOne.mockResolvedValueOnce({ - collection_id: dbItem.collection_id, + collection_id: itemToUpsert.collection_id, eth_address: wallet.address, contract_address: Wallet.createRandom().address, lock: new Date(), @@ -455,13 +458,13 @@ describe('Item router', () => { it('should fail with can not update locked collection items message', async () => { const response = await server .put(buildURL(url)) - .send({ item: { ...dbItem, name: 'new name' } }) + .send({ item: { ...itemToUpsert, name: 'new name' } }) .set(createAuthHeaders('put', url)) .expect(STATUS_CODES.locked) expect(response.body).toEqual({ data: { - id: dbItem.id, + id: itemToUpsert.id, }, error: "The collection for the item is locked. The item can't be inserted or updated.", @@ -474,10 +477,10 @@ describe('Item router', () => { describe('when the collection given for the item is already published', () => { beforeEach(() => { dbItem.collection_id = collectionAttributesMock.id - mockOwnableCanUpsert(Item, dbItem.id, wallet.address, true) + mockOwnableCanUpsert(Item, itemToUpsert.id, wallet.address, true) mockCollection.findOne.mockResolvedValueOnce({ ...collectionAttributesMock, - collection_id: dbItem.collection_id, + collection_id: itemToUpsert.collection_id, eth_address: wallet.address, contract_address: Wallet.createRandom().address, }) @@ -492,12 +495,12 @@ describe('Item router', () => { it('should fail with can not add item to published collection message', async () => { const response = await server .put(buildURL(url)) - .send({ item: dbItem }) + .send({ item: itemToUpsert }) .set(createAuthHeaders('put', url)) .expect(STATUS_CODES.conflict) expect(response.body).toEqual({ - data: { id: dbItem.id }, + data: { id: itemToUpsert.id }, error: "The collection that contains this item has been already published. The item can't be inserted.", ok: false, @@ -507,18 +510,18 @@ describe('Item router', () => { describe('and the item is being removed from the collection', () => { beforeEach(() => { - mockItem.findOne.mockResolvedValueOnce(dbItem) + mockItem.findOne.mockResolvedValueOnce(itemToUpsert) }) it('should fail with can not remove item from published collection message', async () => { const response = await server .put(buildURL(url)) - .send({ item: { ...dbItem, collection_id: null } }) + .send({ item: { ...itemToUpsert, collection_id: null } }) .set(createAuthHeaders('put', url)) .expect(STATUS_CODES.conflict) expect(response.body).toEqual({ - data: { id: dbItem.id }, + data: { id: itemToUpsert.id }, error: "The collection that contains this item has been already published. The item can't be deleted.", ok: false, @@ -534,13 +537,13 @@ describe('Item router', () => { it('should fail with can not update items rarity message', async () => { const response = await server .put(buildURL(url)) - .send({ item: { ...dbItem, rarity: ItemRarity.EPIC } }) + .send({ item: { ...itemToUpsert, rarity: ItemRarity.EPIC } }) .set(createAuthHeaders('put', url)) .expect(STATUS_CODES.conflict) expect(response.body).toEqual({ data: { - id: dbItem.id, + id: itemToUpsert.id, }, error: "The collection that contains this item has been already published. The item can't be updated with a new rarity.", @@ -552,9 +555,9 @@ describe('Item router', () => { describe('and all the conditions for success are given', () => { beforeEach(() => { - mockOwnableCanUpsert(Item, dbItem.id, wallet.address, true) + mockOwnableCanUpsert(Item, itemToUpsert.id, wallet.address, true) mockCollection.findOne.mockResolvedValueOnce({ - collection_id: dbItem.collection_id, + collection_id: itemToUpsert.collection_id, eth_address: wallet.address, contract_address: Wallet.createRandom().address, }) @@ -566,7 +569,7 @@ describe('Item router', () => { it('should respond with the upserted item', async () => { const response = await server .put(buildURL(url)) - .send({ item: dbItem }) + .send({ item: itemToUpsert }) .set(createAuthHeaders('put', url)) .expect(STATUS_CODES.ok) diff --git a/src/Item/Item.schema.ts b/src/Item/Item.schema.ts index bedd7d74..1f867211 100644 --- a/src/Item/Item.schema.ts +++ b/src/Item/Item.schema.ts @@ -31,8 +31,6 @@ export const itemSchema = Object.freeze({ additionalProperties: true, }, content_hash: { type: ['string', 'null'] }, - created_at: { type: 'string' }, - updated_at: { type: 'string' }, }, additionalProperties: false, required: [ @@ -44,8 +42,6 @@ export const itemSchema = Object.freeze({ 'type', 'metrics', 'contents', - 'created_at', - 'updated_at', ], }) diff --git a/src/Item/Item.service.ts b/src/Item/Item.service.ts index 951743e1..8de4db61 100644 --- a/src/Item/Item.service.ts +++ b/src/Item/Item.service.ts @@ -138,7 +138,10 @@ export class ItemService { const dbItem = await Item.findOne(item.id) if (dbItem) { + item.updated_at = new Date() this.checkItemIsMovedToAnotherCollection(item, dbItem) + } else { + item.created_at = new Date() } const collectionId = item.collection_id || dbItem?.collection_id