var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
import chaiAsPromised from 'chai-as-promised';
import chai, { expect } from 'chai';
import dexProtocolDefinition from '../vectors/protocol-definitions/dex.json' assert { type: 'json' };
import { DwnErrorCode } from '../../src/index.js';
import { Jws } from '../../src/utils/jws.js';
import { ProtocolsConfigure } from '../../src/interfaces/protocols-configure.js';
import { TestDataGenerator } from '../utils/test-data-generator.js';
import { Time } from '../../src/utils/time.js';
chai.use(chaiAsPromised);
describe('ProtocolsConfigure', () => {
    if (process.env.TESTSOFF === 'true') {
        return;
    }
    describe('create()', () => {
        it('should use `messageTimestamp` as is if given', () => __awaiter(void 0, void 0, void 0, function* () {
            const alice = yield TestDataGenerator.generatePersona();
            const currentTime = Time.getCurrentTimestamp();
            const definition = Object.assign({}, dexProtocolDefinition);
            const protocolsConfigure = yield ProtocolsConfigure.create({
                messageTimestamp: currentTime,
                definition,
                signer: Jws.createSigner(alice),
            });
            expect(protocolsConfigure.message.descriptor.messageTimestamp).to.equal(currentTime);
        }));
        it('should auto-normalize protocol URI', () => __awaiter(void 0, void 0, void 0, function* () {
            const alice = yield TestDataGenerator.generatePersona();
            const definition = Object.assign(Object.assign({}, dexProtocolDefinition), { protocol: 'example.com/' });
            const options = {
                recipient: alice.did,
                data: TestDataGenerator.randomBytes(10),
                dataFormat: 'application/json',
                signer: Jws.createSigner(alice),
                definition,
            };
            const protocolsConfig = yield ProtocolsConfigure.create(options);
            const message = protocolsConfig.message;
            expect(message.descriptor.definition.protocol).to.eq('http://example.com');
        }));
        it('should auto-normalize schema URIs', () => __awaiter(void 0, void 0, void 0, function* () {
            const alice = yield TestDataGenerator.generatePersona();
            const nonnormalizedDexProtocol = Object.assign({}, dexProtocolDefinition);
            nonnormalizedDexProtocol.types.ask.schema = 'ask';
            const options = {
                recipient: alice.did,
                data: TestDataGenerator.randomBytes(10),
                dataFormat: 'application/json',
                signer: Jws.createSigner(alice),
                protocol: 'example.com/',
                definition: nonnormalizedDexProtocol
            };
            const protocolsConfig = yield ProtocolsConfigure.create(options);
            const message = protocolsConfig.message;
            expect(message.descriptor.definition.types.ask.schema).to.eq('http://ask');
        }));
        describe('protocol definition validations', () => {
            it('allows `role` actions that have protocol path to valid $globalRole records', () => __awaiter(void 0, void 0, void 0, function* () {
                const definition = {
                    published: true,
                    protocol: 'http://example.com',
                    types: {
                        rootRole: {},
                        secondLevel: {},
                        otherRoot: {}
                    },
                    structure: {
                        rootRole: {
                            $globalRole: true,
                            secondLevel: {
                                $actions: [{
                                        role: 'rootRole',
                                        can: 'write'
                                    }]
                            }
                        },
                        otherRole: {
                            $actions: [{
                                    role: 'rootRole',
                                    can: 'write'
                                }]
                        }
                    }
                };
                const alice = yield TestDataGenerator.generatePersona();
                const protocolsConfigure = yield ProtocolsConfigure.create({
                    signer: Jws.createSigner(alice),
                    definition
                });
                expect(protocolsConfigure.message.descriptor.definition).not.to.be.undefined;
            }));
            it('allows `role` actions that have protocol path to valid $contextRole records', () => __awaiter(void 0, void 0, void 0, function* () {
                const definition = {
                    published: true,
                    protocol: 'http://example.com',
                    types: {
                        rootRole: {},
                        secondLevel: {},
                        otherRoot: {}
                    },
                    structure: {
                        thread: {
                            participant: {
                                $contextRole: true,
                            },
                            chat: {
                                $actions: [{
                                        role: 'thread/participant',
                                        can: 'write'
                                    }]
                            }
                        }
                    }
                };
                const alice = yield TestDataGenerator.generatePersona();
                const protocolsConfigure = yield ProtocolsConfigure.create({
                    signer: Jws.createSigner(alice),
                    definition
                });
                expect(protocolsConfigure.message.descriptor.definition).not.to.be.undefined;
            }));
            it('rejects protocol definitions with $globalRole at records that are not root records', () => __awaiter(void 0, void 0, void 0, function* () {
                const definition = {
                    published: true,
                    protocol: 'http://example.com',
                    types: {
                        root: {},
                        secondLevel: {}
                    },
                    structure: {
                        root: {
                            secondLevel: {
                                // $globalRole may only be set on root records, not nested records
                                $globalRole: true
                            }
                        }
                    }
                };
                const alice = yield TestDataGenerator.generatePersona();
                const createProtocolsConfigurePromise = ProtocolsConfigure.create({
                    signer: Jws.createSigner(alice),
                    definition
                });
                yield expect(createProtocolsConfigurePromise)
                    .to.be.rejectedWith(DwnErrorCode.ProtocolsConfigureGlobalRoleAtProhibitedProtocolPath);
            }));
            it('rejects protocol definitions with $contextRole at records that are not second-level records', () => __awaiter(void 0, void 0, void 0, function* () {
                const alice = yield TestDataGenerator.generatePersona();
                // it rejects context roles too high in the structure
                const definitionRootContextRole = {
                    published: true,
                    protocol: 'http://example.com',
                    types: {
                        root: {},
                        secondLevel: {}
                    },
                    structure: {
                        root: {
                            // $contextRole may only be set on second-level records, not root records
                            $contextRole: true,
                        }
                    }
                };
                const createProtocolsConfigurePromise = ProtocolsConfigure.create({
                    signer: Jws.createSigner(alice),
                    definition: definitionRootContextRole
                });
                yield expect(createProtocolsConfigurePromise)
                    .to.be.rejectedWith(DwnErrorCode.ProtocolsConfigureContextRoleAtProhibitedProtocolPath);
                // it rejects contextRoles too nested in the structure
                const definitionTooNestedContextRole = {
                    published: true,
                    protocol: 'http://example.com',
                    types: {
                        root: {},
                        secondLevel: {}
                    },
                    structure: {
                        root: {
                            secondLevel: {
                                thirdLevel: {
                                    // $contextRole may only be set on second-level records, not third-level or lower records
                                    $contextRole: true,
                                }
                            }
                        }
                    }
                };
                const createProtocolsConfigurePromise2 = ProtocolsConfigure.create({
                    signer: Jws.createSigner(alice),
                    definition: definitionTooNestedContextRole
                });
                yield expect(createProtocolsConfigurePromise2)
                    .to.be.rejectedWith(DwnErrorCode.ProtocolsConfigureContextRoleAtProhibitedProtocolPath);
            }));
            it('rejects protocol definitions with `role` actions that contain invalid roles', () => __awaiter(void 0, void 0, void 0, function* () {
                const definition = {
                    published: true,
                    protocol: 'http://example.com',
                    types: {
                        rootRole: {},
                        otherRoot: {},
                    },
                    structure: {
                        rootRole: {
                        // $globalRole: true // deliberated omitted
                        },
                        otherRoot: {
                            $actions: [{
                                    role: 'rootRole',
                                    can: 'read'
                                }]
                        }
                    }
                };
                const alice = yield TestDataGenerator.generatePersona();
                const createProtocolsConfigurePromise = ProtocolsConfigure.create({
                    signer: Jws.createSigner(alice),
                    definition
                });
                yield expect(createProtocolsConfigurePromise)
                    .to.be.rejectedWith(DwnErrorCode.ProtocolsConfigureInvalidRole);
            }));
            it('rejects protocol definitions with actions that contain `of` and  `who` is `anyone`', () => __awaiter(void 0, void 0, void 0, function* () {
                const definition = {
                    published: true,
                    protocol: 'http://example.com',
                    types: {
                        message: {},
                    },
                    structure: {
                        message: {
                            $actions: [{
                                    who: 'anyone',
                                    of: 'message',
                                    can: 'read'
                                }]
                        }
                    }
                };
                const alice = yield TestDataGenerator.generatePersona();
                const createProtocolsConfigurePromise = ProtocolsConfigure.create({
                    signer: Jws.createSigner(alice),
                    definition
                });
                yield expect(createProtocolsConfigurePromise)
                    .to.be.rejectedWith(DwnErrorCode.ProtocolsConfigureInvalidActionOfNotAllowed);
            }));
            it('rejects protocol definitions with actions that don\'t contain `of` and  `who` is `author` or `recipient`', () => __awaiter(void 0, void 0, void 0, function* () {
                const definition = {
                    published: true,
                    protocol: 'http://example.com',
                    types: {
                        message: {},
                    },
                    structure: {
                        message: {
                            $actions: [{
                                    who: 'author',
                                    // of : 'message', // Intentionally missing
                                    can: 'read'
                                }]
                        }
                    }
                };
                const alice = yield TestDataGenerator.generatePersona();
                const createProtocolsConfigurePromise = ProtocolsConfigure.create({
                    signer: Jws.createSigner(alice),
                    definition
                });
                yield expect(createProtocolsConfigurePromise)
                    .to.be.rejectedWith(DwnErrorCode.ProtocolsConfigureInvalidActionMissingOf);
            }));
            it('rejects protocol definitions with `can: query` in non-role rules', () => __awaiter(void 0, void 0, void 0, function* () {
                const definition = {
                    published: true,
                    protocol: 'http://example.com',
                    types: {
                        message: {},
                    },
                    structure: {
                        message: {
                            $actions: [{
                                    who: 'author',
                                    of: 'message',
                                    can: 'query'
                                }]
                        }
                    }
                };
                const alice = yield TestDataGenerator.generatePersona();
                const createProtocolsConfigurePromise = ProtocolsConfigure.create({
                    signer: Jws.createSigner(alice),
                    definition
                });
                yield expect(createProtocolsConfigurePromise)
                    .to.be.rejected;
            }));
        });
    });
});
//# sourceMappingURL=protocols-configure.spec.js.map