UNPKG

jinaga

Version:

Data management for web and mobile applications.

233 lines (186 loc) 6.32 kB
import { AuthorizationRules, buildModel, Jinaga, JinagaTest, describeAuthorizationRules } from '../../src'; describe("Feedback authorization from specification", () => { describe("as a user", () => { let j: Jinaga; let site: Site; let content: Content; beforeEach(async () => { site = new Site(new User("Site creator"), "site identifier"); content = new Content(site, "/path/to/content"); j = JinagaTest.create({ model, authorization, user: new User("Logged in user"), initialState: [ site, content ] }); }); it("should allow a user", async () => { const creator = await j.fact(new User("Other user")); expect(creator.publicKey).toEqual("Other user"); }); it("should not allow site created by a different user", async () => { const creator = await j.fact(new User("Other user")); const promise = j.fact(new Site(creator, "site identifier")); await expect(promise).rejects.not.toBeNull(); }); it("should allow a site created by the logged in user", async () => { const creator = await j.fact(new User("Logged in user")); const site = await j.fact(new Site(creator, "site identifier")); expect(site.creator.publicKey).toEqual("Logged in user"); }); it("should not allow a comment from another user", async () => { const user = await j.fact(new User("Another user")); const promise = j.fact(new Comment("comment unique id", content, user)); await expect(promise).rejects.not.toBeNull(); }); it("should allow a comment from logged in user", async () => { const { userFact: user } = await j.login<User>(); const comment = await j.fact(new Comment("comment unique id", content, user)); expect(comment.author.publicKey).toEqual(user.publicKey); }); it("should not allow a post from another user", async () => { const promise = j.fact(new Content(site, "/path/to/new/content")); await expect(promise).rejects.not.toBeNull(); }); it("should not allow user to invite themselves", async () => { const { userFact: self } = await j.login<User>(); const promise = j.fact(new GuestBlogger(site, self)); await expect(promise).rejects.not.toBeNull(); }); }); describe("as a site creator", () => { let j: Jinaga; let site: Site; let content: Content; beforeEach(async () => { const siteCreator = new User("Site creator"); site = new Site(siteCreator, "site identifier"); content = new Content(site, "/path/to/content"); j = JinagaTest.create({ model, authorization, user: siteCreator, initialState: [ site, content ] }); }); it("should allow a post from the site creator", async () => { const newContent = await j.fact(new Content(site, "/path/to/new/content")); expect(j.hash(newContent.site)).toEqual(j.hash(site)); }); it("should allow an invitation to a guest blogger", async () => { const guest = await j.fact(new User("Guest blogger")); const guestBlogger = await j.fact(new GuestBlogger(site, guest)); expect(j.hash(guestBlogger.site)).toEqual(j.hash(site)); expect(j.hash(guestBlogger.guest)).toEqual(j.hash(guest)); }); }); describe("as a guest blogger", () => { let j: Jinaga; let site: Site; beforeEach(async () => { const siteCreator = new User("Site creator"); site = new Site(siteCreator, "site identifier"); const guestUser = new User("Guest user"); const guestBlogger = new GuestBlogger(site, guestUser); j = JinagaTest.create({ model, authorization, user: guestUser, initialState: [ site, guestBlogger ] }); }); it("should allow a post from the guest blogger", async () => { const newContent = await j.fact(new Content(site, "/path/to/new/content")); expect(j.hash(newContent.site)).toEqual(j.hash(site)); }); }); }); describe("Authorization rules description", () => { it("should be able to save authorization rules", () => { const description = describeAuthorizationRules(model, authorization); expect(description).not.toBeNull(); }); it("should be able to load authorization rules", () => { const description = describeAuthorizationRules(model, authorization); const loaded = AuthorizationRules.loadFromDescription(description); expect(loaded.hasRule(Content.Type)).toBeTruthy(); }); }); class User { static Type = "Jinaga.User" as const; type = User.Type; constructor ( public publicKey: string ) { } } class Site { static Type = "Feedback.Site" as const; type = Site.Type; constructor ( public creator: User, public identifier: string ) { } } class GuestBlogger { static Type = "Feedback.GuestBlogger" as const; type = GuestBlogger.Type; constructor ( public site: Site, public guest: User ) { } } class Content { static Type = "Feedback.Content" as const; type = Content.Type; constructor ( public site: Site, public path: string ) { } } class Comment { static Type = "Feedback.Comment" as const; type = Comment.Type; constructor ( public uniqueId: string, public content: Content, public author: User ) { } } const model = buildModel(b => b .type(User) .type(Site, f => f .predecessor("creator", User) ) .type(GuestBlogger, f => f .predecessor("site", Site) .predecessor("guest", User) ) .type(Content, f => f .predecessor("site", Site) ) .type(Comment, f => f .predecessor("content", Content) .predecessor("author", User) ) ); function authorization(a: AuthorizationRules) { return a .any(User) .type(Site, site => site.creator) .type(GuestBlogger, guestBlogger => guestBlogger.site.creator) .type(Content, content => content.site.creator) .type(Content, content => content.site.successors(GuestBlogger, guestBlogger => guestBlogger.site) .selectMany(guestBlogger => guestBlogger.guest.predecessor()) ) .type(Comment, comment => comment.author) ; }