feat(medusa): Prevent default channel from being deleted (#1835)

**What**
Prevent the default channel from being deleted

Fixes CORE-317
This commit is contained in:
Oliver Windall Juhl
2022-07-13 06:41:03 +00:00
committed by GitHub
parent e539bdc620
commit 4e375c2203
8 changed files with 272 additions and 57 deletions
@@ -1,5 +1,5 @@
import { MedusaError } from "medusa-core-utils"
import { NextFunction, Request, Response } from "express"
import { MedusaError } from "medusa-core-utils"
import { Logger } from "../../types/global"
const QUERY_RUNNER_RELEASED = "QueryRunnerAlreadyReleasedError"
@@ -1,28 +1,26 @@
import { IdMap } from "medusa-test-utils"
export const store = {
_id: IdMap.getId("store"),
id: "test-store",
name: "Test store",
currencies: ["DKK", "SEK", "GBP"],
}
export const StoreServiceMock = {
withTransaction: function () {
withTransaction: function() {
return this
},
create: jest.fn().mockImplementation(data => {
create: jest.fn().mockImplementation((data) => {
return Promise.resolve(data)
}),
addCurrency: jest.fn().mockImplementation(data => {
addCurrency: jest.fn().mockImplementation((data) => {
return Promise.resolve()
}),
removeCurrency: jest.fn().mockImplementation(data => {
removeCurrency: jest.fn().mockImplementation((data) => {
return Promise.resolve()
}),
update: jest.fn().mockImplementation(data => {
update: jest.fn().mockImplementation((data) => {
return Promise.resolve()
}),
retrieve: jest.fn().mockImplementation(data => {
retrieve: jest.fn().mockImplementation((data) => {
return Promise.resolve(store)
}),
}
@@ -1,10 +1,10 @@
import { IdMap, MockManager, MockRepository } from "medusa-test-utils"
import SalesChannelService from "../sales-channel"
import { EventBusServiceMock } from "../__mocks__/event-bus"
import { EventBusService, StoreService } from "../index"
import { FindConditions, FindOneOptions } from "typeorm"
import { SalesChannel } from "../../models"
import { store, StoreServiceMock } from "../__mocks__/store";
import { EventBusService, StoreService } from "../index"
import SalesChannelService from "../sales-channel"
import { EventBusServiceMock } from "../__mocks__/event-bus"
import { store, StoreServiceMock } from "../__mocks__/store"
describe("SalesChannelService", () => {
const salesChannelData = {
@@ -29,10 +29,11 @@ describe("SalesChannelService", () => {
}
),
create: jest.fn().mockImplementation((data) => data),
save: (salesChannel) => Promise.resolve({
id: IdMap.getId("sales_channel_1"),
...salesChannel
}),
save: (salesChannel) =>
Promise.resolve({
id: IdMap.getId("sales_channel_1"),
...salesChannel,
}),
softRemove: jest.fn().mockImplementation((id: string): any => {
return Promise.resolve()
}),
@@ -43,7 +44,7 @@ describe("SalesChannelService", () => {
manager: MockManager,
eventBusService: EventBusServiceMock as unknown as EventBusService,
salesChannelRepository: salesChannelRepositoryMock,
storeService: StoreServiceMock as unknown as StoreService
storeService: StoreServiceMock as unknown as StoreService,
})
beforeEach(() => {
@@ -75,10 +76,10 @@ describe("SalesChannelService", () => {
default_sales_channel: {
id: IdMap.getId("sales_channel_1"),
...salesChannelData,
}
},
})
})
} as any
}),
} as any,
})
const salesChannel = await localSalesChannelService.createDefault()
@@ -97,7 +98,7 @@ describe("SalesChannelService", () => {
manager: MockManager,
eventBusService: EventBusServiceMock as unknown as EventBusService,
salesChannelRepository: salesChannelRepositoryMock,
storeService: StoreServiceMock as unknown as StoreService
storeService: StoreServiceMock as unknown as StoreService,
})
beforeEach(() => {
@@ -127,7 +128,7 @@ describe("SalesChannelService", () => {
manager: MockManager,
eventBusService: EventBusServiceMock as unknown as EventBusService,
salesChannelRepository: salesChannelRepositoryMock,
storeService: StoreServiceMock as unknown as StoreService
storeService: StoreServiceMock as unknown as StoreService,
})
const update = {
@@ -162,35 +163,53 @@ describe("SalesChannelService", () => {
manager: MockManager,
eventBusService: EventBusServiceMock as unknown as EventBusService,
salesChannelRepository: salesChannelRepositoryMock,
storeService: StoreServiceMock as unknown as StoreService
storeService: {
...StoreServiceMock,
retrieve: jest.fn().mockImplementation(() => {
return Promise.resolve({
...store,
default_sales_channel_id: "default_channel",
default_sales_channel: {
id: "default_channel",
...salesChannelData,
},
})
}),
} as any,
})
beforeEach(() => {
jest.clearAllMocks()
})
it('should soft remove a sales channel', async () => {
it("should soft remove a sales channel", async () => {
const res = await salesChannelService.delete(
IdMap.getId("sales_channel_1")
)
expect(res).toBeUndefined()
expect(salesChannelRepositoryMock.softRemove)
.toHaveBeenCalledTimes(1)
expect(salesChannelRepositoryMock.softRemove)
.toHaveBeenLastCalledWith({
id: IdMap.getId("sales_channel_1"),
...salesChannelData
})
expect(salesChannelRepositoryMock.softRemove).toHaveBeenCalledTimes(1)
expect(salesChannelRepositoryMock.softRemove).toHaveBeenLastCalledWith({
id: IdMap.getId("sales_channel_1"),
...salesChannelData,
})
expect(EventBusServiceMock.emit)
.toHaveBeenCalledTimes(1)
expect(EventBusServiceMock.emit)
.toHaveBeenLastCalledWith(
SalesChannelService.Events.DELETED,
{ "id": IdMap.getId("sales_channel_1") }
expect(EventBusServiceMock.emit).toHaveBeenCalledTimes(1)
expect(EventBusServiceMock.emit).toHaveBeenLastCalledWith(
SalesChannelService.Events.DELETED,
{ id: IdMap.getId("sales_channel_1") }
)
})
it("should fail if delete of the default channel is attempted", async () => {
try {
await salesChannelService.delete("default_channel")
} catch (error) {
expect(error.message).toEqual(
"You cannot delete the default sales channel"
)
}
})
})
})
+12 -1
View File
@@ -9,8 +9,8 @@ import {
CreateSalesChannelInput,
UpdateSalesChannelInput,
} from "../types/sales-channels"
import EventBusService from "./event-bus"
import { buildQuery } from "../utils"
import EventBusService from "./event-bus"
import StoreService from "./store"
type InjectedDependencies = {
@@ -165,6 +165,17 @@ class SalesChannelService extends TransactionBaseService<SalesChannelService> {
return
}
const store = await this.storeService_.retrieve({
select: ["default_sales_channel_id"],
})
if (salesChannel.id === store?.default_sales_channel_id) {
throw new MedusaError(
MedusaError.Types.NOT_ALLOWED,
"You cannot delete the default sales channel"
)
}
await salesChannelRepo.softRemove(salesChannel)
await this.eventBusService_
+7 -8
View File
@@ -1,15 +1,14 @@
import { MedusaError } from "medusa-core-utils"
import { currencies, Currency } from "../utils/currencies"
import { EntityManager } from "typeorm"
import { StoreRepository } from "../repositories/store"
import { CurrencyRepository } from "../repositories/currency"
import EventBusService from "./event-bus"
import { Store } from "../models"
import { AdminPostStoreReq } from "../api/routes/admin/store"
import { FindConfig } from "../types/common"
import { TransactionBaseService } from "../interfaces"
import { buildQuery, setMetadata } from "../utils"
import { Store } from "../models"
import { CurrencyRepository } from "../repositories/currency"
import { StoreRepository } from "../repositories/store"
import { FindConfig } from "../types/common"
import { UpdateStoreInput } from "../types/store"
import { buildQuery, setMetadata } from "../utils"
import { currencies, Currency } from "../utils/currencies"
import EventBusService from "./event-bus"
type InjectedDependencies = {
manager: EntityManager