Skip to content

Commit

Permalink
Merge pull request #171 from joincivil/ritave/sign-revision
Browse files Browse the repository at this point in the history
Added ability to add author back in later
  • Loading branch information
walfly authored May 18, 2018
2 parents 5edf30d + 2a67618 commit 575d52f
Show file tree
Hide file tree
Showing 2 changed files with 122 additions and 1 deletion.
30 changes: 29 additions & 1 deletion packages/contracts/contracts/newsroom/Newsroom.sol
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,7 @@ contract Newsroom is ACL {
uint contentId = contentCount;
contentCount++;

require((author == 0x0 && signature.length == 0) || (author != 0x0 && signature.length != 0));
contents[contentId].author = author;
pushRevision(contentId, contentUri, contentHash, signature);

Expand All @@ -166,8 +167,35 @@ contract Newsroom is ACL {
pushRevision(contentId, contentUri, contentHash, signature);
}

/**
@notice Allows to backsign a revision by the author. This is indented when an author didn't have time to access
to their private key but after time they do.
The author must be the same as the one during publishing.
If there was no author during publishing this functions allows to update the 0x0 author to a real one.
Once done, the author can't be changed afterwards
@dev Emits `RevisionSigned` event
*/
function signRevision(uint contentId, uint revisionId, address author, bytes signature) external requireRole(ROLE_EDITOR) {
require(contentId < contentCount);

Content storage content = contents[contentId];

require(content.author == 0x0 || content.author == author);
require(content.revisions.length > revisionId);

content.author = author;

Revision storage revision = content.revisions[revisionId];
revision.signature = signature;

require(verifyRevisionSignature(author, revision));

emit RevisionSigned(contentId, revisionId, author);
}

function verifyRevisionSignature(address author, Revision storage revision) view internal returns (bool isSigned) {
if (author == 0x0) {
if (author == 0x0 || revision.signature.length == 0) {
require(revision.signature.length == 0);
return false;
} else {
Expand Down
93 changes: 93 additions & 0 deletions packages/contracts/test/newsroom/newsroom.ts
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,16 @@ contract("Newsroom", (accounts: string[]) => {
newsroom.updateRevision(contentId, SOME_URI, SOME_HASH, editorSignature),
).to.eventually.be.rejectedWith(REVERTED);
});

it("allows unsigned revisions", async () => {
expect(await newsroom.isContentSigned(contentId)).to.be.true();

await expect(newsroom.updateRevision(contentId, SOME_URI, SOME_HASH, ""));

expect(await newsroom.isContentSigned(contentId)).to.be.false();
expect(await newsroom.isRevisionSigned(contentId, 0)).to.be.true();
});

it("doesn't allow signing if the first revision was unsigned", async () => {
const receipt = await newsroom.publishContent(SOME_URI, SOME_HASH, "", "", { from: editor });
const event = findEvent(receipt, events.NEWSROOM_PUBLISHED);
Expand Down Expand Up @@ -435,4 +445,87 @@ contract("Newsroom", (accounts: string[]) => {
await expect(newsroom.getRevision(contentId, 999)).to.eventually.be.rejectedWith(REVERTED);
});
});

describe("signRevision", () => {
let contentId: BigNumber;
let MESSAGE: string;
let SIGNATURE: string;

beforeEach(async () => {
MESSAGE = prepareNewsroomMessage(newsroom.address, SOME_HASH);
SIGNATURE = await signAsync(author, MESSAGE);
await newsroom.addRole(editor, NEWSROOM_ROLE_EDITOR);
});

describe("with no publishing author", () => {
beforeEach(async () => {
const receipt = await newsroom.publishContent(SOME_URI, SOME_HASH, "", "", { from: editor });
const event = findEvent(receipt, events.NEWSROOM_PUBLISHED);
expect(event).to.not.be.null();
contentId = event!.args.contentId;
});

it("doesn't allow to add signature with 0x0 author", async () => {
await expect(newsroom.signRevision(contentId, 0, "", SIGNATURE)).to.be.eventually.rejectedWith(REVERTED);
});

it("allows to update author", async () => {
const receipt = await newsroom.signRevision(contentId, 0, author, SIGNATURE);
const event = findEvent(receipt, events.NEWSROOM_SIGNED);

const [, , , newAuthor] = await newsroom.getContent(contentId);

expect(event).to.not.be.null();
expect(event!.args.contentId).to.be.bignumber.equal(contentId);
expect(event!.args.revisionId).to.be.bignumber.equal(0);
expect(event!.args.author).to.be.equal(author);

expect(newAuthor).to.be.equal(author);
});

it("requires proper signature", async () => {
const wrongSignature = await signAsync(editor, MESSAGE);

await expect(newsroom.signRevision(contentId, 0, author, wrongSignature)).to.eventually.be.rejectedWith(
REVERTED,
);
});

it("requires editor role", async () => {
await expect(
newsroom.signRevision(contentId, 0, author, SIGNATURE, { from: author }),
).to.eventually.be.rejectedWith(REVERTED);
});
});

describe("with an existing author", () => {
beforeEach(async () => {
const receipt = await newsroom.publishContent(SOME_URI, SOME_HASH, author, SIGNATURE, { from: editor });
const event = findEvent(receipt, events.NEWSROOM_PUBLISHED);
expect(event).to.not.be.null();
contentId = event!.args.contentId;
});

it("doesn't allow to add 0x0 author", async () => {
await expect(newsroom.signRevision(contentId, 0, "0x0", SIGNATURE)).to.eventually.be.rejectedWith(REVERTED);
});

it("doesn't allow to unsign revision", async () => {
await expect(newsroom.signRevision(contentId, 0, "0x0", "")).to.eventually.be.rejectedWith(REVERTED);
});

it("allows to backsign an unsigned revisision", async () => {
console.log("hehehe");
await newsroom.updateRevision(contentId, SOME_URI, SOME_HASH, "", { from: editor });

expect(await newsroom.isContentSigned(contentId)).to.be.false();

console.log("hehe");

await newsroom.signRevision(contentId, 1, author, SIGNATURE);

expect(await newsroom.isContentSigned(contentId)).to.be.true();
});
});
});
});

0 comments on commit 575d52f

Please sign in to comment.