diff --git a/chain-cli/chaincode-template/e2e/__snapshots__/api.spec.ts.snap b/chain-cli/chaincode-template/e2e/__snapshots__/api.spec.ts.snap index 70df2ebc52..fb692717d7 100644 --- a/chain-cli/chaincode-template/e2e/__snapshots__/api.spec.ts.snap +++ b/chain-cli/chaincode-template/e2e/__snapshots__/api.spec.ts.snap @@ -201,7 +201,7 @@ The key is generated by the caller and should be unique for each DTO. You can us }, }, { - "description": "Submit a batch of transactions Transaction updates the chain (submit). Allowed roles: SUBMIT. Allowed orgs: CuratorOrg.", + "description": "Submit a batch of transactions Transaction updates the chain (submit). Allowed roles: SUBMIT.", "dtoSchema": { "properties": { "dtoExpiresAt": { @@ -1661,7 +1661,7 @@ The key is generated by the caller and should be unique for each DTO. You can us }, }, { - "description": "Submit a batch of transactions Transaction updates the chain (submit). Allowed roles: SUBMIT. Allowed orgs: CuratorOrg.", + "description": "Submit a batch of transactions Transaction updates the chain (submit). Allowed roles: SUBMIT.", "dtoSchema": { "properties": { "dtoExpiresAt": { @@ -10424,7 +10424,7 @@ The key is generated by the caller and should be unique for each DTO. You can us }, }, { - "description": "Submit a batch of transactions Transaction updates the chain (submit). Allowed roles: SUBMIT. Allowed orgs: CuratorOrg.", + "description": "Submit a batch of transactions Transaction updates the chain (submit). Allowed roles: SUBMIT.", "dtoSchema": { "properties": { "dtoExpiresAt": { diff --git a/chain-cli/chaincode-template/src/apples/__snapshots__/api.spec.ts.snap b/chain-cli/chaincode-template/src/apples/__snapshots__/api.spec.ts.snap index 49775e4037..23c16ef8e7 100644 --- a/chain-cli/chaincode-template/src/apples/__snapshots__/api.spec.ts.snap +++ b/chain-cli/chaincode-template/src/apples/__snapshots__/api.spec.ts.snap @@ -201,7 +201,7 @@ The key is generated by the caller and should be unique for each DTO. You can us }, }, { - "description": "Submit a batch of transactions Transaction updates the chain (submit). Allowed roles: SUBMIT. Allowed orgs: CuratorOrg.", + "description": "Submit a batch of transactions Transaction updates the chain (submit). Allowed roles: SUBMIT.", "dtoSchema": { "properties": { "dtoExpiresAt": { diff --git a/chain-cli/chaincode-template/src/pk/__snapshots__/api.spec.ts.snap b/chain-cli/chaincode-template/src/pk/__snapshots__/api.spec.ts.snap index aaddcfb83f..6605dbd98c 100644 --- a/chain-cli/chaincode-template/src/pk/__snapshots__/api.spec.ts.snap +++ b/chain-cli/chaincode-template/src/pk/__snapshots__/api.spec.ts.snap @@ -282,7 +282,7 @@ The key is generated by the caller and should be unique for each DTO. You can us }, }, { - "description": "Submit a batch of transactions Transaction updates the chain (submit). Allowed roles: SUBMIT. Allowed orgs: CuratorOrg.", + "description": "Submit a batch of transactions Transaction updates the chain (submit). Allowed roles: SUBMIT.", "dtoSchema": { "properties": { "dtoExpiresAt": { diff --git a/chain-cli/chaincode-template/src/token/__snapshots__/api.spec.ts.snap b/chain-cli/chaincode-template/src/token/__snapshots__/api.spec.ts.snap index f8e1205495..83d7177f60 100644 --- a/chain-cli/chaincode-template/src/token/__snapshots__/api.spec.ts.snap +++ b/chain-cli/chaincode-template/src/token/__snapshots__/api.spec.ts.snap @@ -494,7 +494,7 @@ The key is generated by the caller and should be unique for each DTO. You can us }, }, { - "description": "Submit a batch of transactions Transaction updates the chain (submit). Allowed roles: SUBMIT. Allowed orgs: CuratorOrg.", + "description": "Submit a batch of transactions Transaction updates the chain (submit). Allowed roles: SUBMIT.", "dtoSchema": { "properties": { "dtoExpiresAt": { diff --git a/chaincode/src/contracts/GalaContract.ts b/chaincode/src/contracts/GalaContract.ts index a9cdb789cb..8d05355bce 100644 --- a/chaincode/src/contracts/GalaContract.ts +++ b/chaincode/src/contracts/GalaContract.ts @@ -25,7 +25,6 @@ import { GalaChainResponseType, GetObjectDto, GetObjectHistoryDto, - NotFoundError, UserProfile, ValidationFailedError, createValidDTO, @@ -223,8 +222,7 @@ export abstract class GalaContract extends Contract { in: BatchDto, out: "object", enforceUniqueKey: true, - description: "Submit a batch of transactions", - allowedOrgs: [process.env.CURATOR_ORG_MSP ?? "CuratorOrg"] + description: "Submit a batch of transactions" }) public async BatchSubmit(ctx: GalaChainContext, batchDto: BatchDto): Promise[]> { const responses: GalaChainResponse[] = []; diff --git a/chaincode/src/contracts/GalaTransaction.ts b/chaincode/src/contracts/GalaTransaction.ts index edcd7e83de..3fbdb49863 100644 --- a/chaincode/src/contracts/GalaTransaction.ts +++ b/chaincode/src/contracts/GalaTransaction.ts @@ -138,8 +138,11 @@ function GalaTransaction( } if (options.type === SUBMIT && !options.verifySignature && !options.allowedOrgs?.length) { - const message = `SUBMIT transaction '${propertyKey}' must have either verifySignature or allowedOrgs defined`; - throw new NotImplementedError(message); + // Edge case: we allow BatchSubmit without verifySignature or allowedOrgs + if (propertyKey !== "BatchSubmit") { + const message = `SUBMIT transaction '${propertyKey}' must have either verifySignature or allowedOrgs defined`; + throw new NotImplementedError(message); + } } if (options.allowedRoles !== undefined && options.allowedOrgs !== undefined) { diff --git a/chaincode/src/contracts/__snapshots__/PublicKeyContract.spec.ts.snap b/chaincode/src/contracts/__snapshots__/PublicKeyContract.spec.ts.snap index db0c8e6cf9..e01c5cc8d4 100644 --- a/chaincode/src/contracts/__snapshots__/PublicKeyContract.spec.ts.snap +++ b/chaincode/src/contracts/__snapshots__/PublicKeyContract.spec.ts.snap @@ -283,7 +283,7 @@ The key is generated by the caller and should be unique for each DTO. You can us }, }, { - "description": "Submit a batch of transactions Transaction updates the chain (submit). Allowed roles: SUBMIT. Allowed orgs: CuratorOrg.", + "description": "Submit a batch of transactions Transaction updates the chain (submit). Allowed roles: SUBMIT.", "dtoSchema": { "properties": { "dtoExpiresAt": { diff --git a/chaincode/src/contracts/authorize.ts b/chaincode/src/contracts/authorize.ts index 932478c47e..dd91f4f38f 100644 --- a/chaincode/src/contracts/authorize.ts +++ b/chaincode/src/contracts/authorize.ts @@ -12,7 +12,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { ChainCallDTO, ForbiddenError, UnauthorizedError, UserRole } from "@gala-chain/api"; +import { BatchDto, ChainCallDTO, ForbiddenError, UnauthorizedError, UserRole } from "@gala-chain/api"; import { GalaChainContext } from "../types"; @@ -100,6 +100,13 @@ export function ensureChaincodeIsAllowed(chaincode: string, allowedChaincodes: s } } +function isBatchOperation(ctx: GalaChainContext, dto: ChainCallDTO | undefined) { + const methodName = ctx.operationCtx.methodName; + const isBatchMethod = methodName === "BatchSubmit" || methodName.endsWith(":BatchSubmit"); + const isBatchDto = (dto as BatchDto | undefined)?.operations?.some((o) => o.method.length > 0); + return isBatchMethod || isBatchDto; +} + export interface AuthorizeOptions { allowedOrgs?: string[]; allowedRoles?: string[]; @@ -112,6 +119,11 @@ export async function authorize( options: AuthorizeOptions, dto: ChainCallDTO | undefined ) { + // For batch operations authorization happens for each operation in the batch + if (isBatchOperation(ctx, dto)) { + return; + } + if (options.allowedOriginChaincodes && ctx.callingUser.startsWith("service|")) { const callingChaincode = ctx.callingUser.slice(8); ensureChaincodeIsAllowed(callingChaincode, options.allowedOriginChaincodes);