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:
@@ -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"
|
||||
)
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -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_
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user