UNPKG

@atproto/oauth-scopes

Version:

A library for manipulating and validating ATproto OAuth scopes in TypeScript.

268 lines (234 loc) 8.15 kB
import { ScopePermissions } from './scope-permissions.js' describe('ScopePermissions', () => { describe('allowsAccount', () => { it('should properly allow "account:email"', () => { const set = new ScopePermissions('account:email') expect(set.allowsAccount({ attr: 'email', action: 'read' })).toBe(true) expect(set.allowsAccount({ attr: 'email', action: 'manage' })).toBe(false) expect(set.allowsAccount({ attr: 'repo', action: 'read' })).toBe(false) expect(set.allowsAccount({ attr: 'repo', action: 'manage' })).toBe(false) expect(set.allowsAccount({ attr: 'status', action: 'read' })).toBe(false) expect(set.allowsAccount({ attr: 'status', action: 'manage' })).toBe( false, ) }) it('should ignore "transition:email"', () => { const set = new ScopePermissions('transition:email') expect(set.allowsAccount({ attr: 'email', action: 'read' })).toBe(false) expect(set.allowsAccount({ attr: 'email', action: 'manage' })).toBe(false) }) }) describe('allowsBlob', () => { it('should allow any mime with "blob:*/*"', () => { const set = new ScopePermissions('blob:*/*') expect(set.allowsBlob({ mime: 'image/png' })).toBe(true) expect(set.allowsBlob({ mime: 'application/json' })).toBe(true) }) it('should only allow images with "blob:image/*"', () => { const set = new ScopePermissions('blob:image/*') expect(set.allowsBlob({ mime: 'image/png' })).toBe(true) expect(set.allowsBlob({ mime: 'application/json' })).toBe(false) }) it('should ignore invalid scope "blob:*"', () => { const set = new ScopePermissions('blob:*') expect(set.allowsBlob({ mime: 'image/png' })).toBe(false) expect(set.allowsBlob({ mime: 'application/json' })).toBe(false) }) it('should ignore invalid scope "blob:/image"', () => { const set = new ScopePermissions('blob:/image') expect(set.allowsBlob({ mime: 'image/png' })).toBe(false) expect(set.allowsBlob({ mime: 'application/json' })).toBe(false) }) it('should ignore "transition:generic"', () => { const set = new ScopePermissions('transition:generic') expect(set.allowsBlob({ mime: 'image/png' })).toBe(false) expect(set.allowsBlob({ mime: 'application/json' })).toBe(false) }) }) describe('allowsRepo', () => { it('should allow any repo action with "repo:*"', () => { const set = new ScopePermissions('repo:*') expect( set.allowsRepo({ collection: 'com.example.foo', action: 'create' }), ).toBe(true) expect( set.allowsRepo({ collection: 'com.example.foo', action: 'update' }), ).toBe(true) expect( set.allowsRepo({ collection: 'app.bsky.feed.post', action: 'delete' }), ).toBe(true) }) it('should allow specific repo actions', () => { const set = new ScopePermissions('repo:*?action=create') expect( set.allowsRepo({ collection: 'com.example.foo', action: 'create' }), ).toBe(true) expect( set.allowsRepo({ collection: 'app.bsky.feed.post', action: 'create' }), ).toBe(true) // Control expect( set.allowsRepo({ collection: 'com.example.foo', action: 'update' }), ).toBe(false) expect( set.allowsRepo({ collection: 'app.bsky.feed.post', action: 'delete' }), ).toBe(false) }) it('should allow specific repo collection & actions', () => { const set = new ScopePermissions('repo:com.example.foo?action=create') expect( set.allowsRepo({ collection: 'com.example.foo', action: 'create' }), ).toBe(true) // Control expect( set.allowsRepo({ collection: 'com.example.foo', action: 'update' }), ).toBe(false) expect( set.allowsRepo({ collection: 'app.bsky.feed.post', action: 'delete' }), ).toBe(false) expect( set.allowsRepo({ collection: 'app.bsky.feed.post', action: 'create' }), ).toBe(false) }) it('should ignore transition:generic', () => { const set = new ScopePermissions('transition:generic') expect( set.allowsRepo({ collection: 'app.bsky.feed.post', action: 'create' }), ).toBe(false) expect( set.allowsRepo({ collection: 'app.bsky.feed.post', action: 'delete' }), ).toBe(false) expect( set.allowsRepo({ collection: 'com.example.foo', action: 'create' }), ).toBe(false) expect( set.allowsRepo({ collection: 'com.example.foo', action: 'update' }), ).toBe(false) }) }) describe('allowsRpc', () => { it('should ignore "rpc:*?lxm=*"', () => { const set = new ScopePermissions('rpc:*?lxm=*') expect( set.allowsRpc({ aud: 'did:web:example.com', lxm: 'com.example.method', }), ).toBe(false) expect( set.allowsRpc({ aud: 'did:web:example.com', lxm: 'app.bsky.feed.getFeed', }), ).toBe(false) }) it('should allow constraining "lxm"', () => { const set = new ScopePermissions('rpc:app.bsky.feed.getFeed?aud=*') expect( set.allowsRpc({ aud: 'did:web:example.com', lxm: 'app.bsky.feed.getFeed', }), ).toBe(true) expect( set.allowsRpc({ aud: 'did:plc:blahbla', lxm: 'app.bsky.feed.getFeed' }), ).toBe(true) // Control expect( set.allowsRpc({ aud: 'did:web:example.com', lxm: 'com.example.method', }), ).toBe(false) }) it('should allow constraining "aud"', () => { const set = new ScopePermissions('rpc:*?aud=did:web:example.com%23foo') expect( set.allowsRpc({ aud: 'did:web:example.com#foo', lxm: 'com.example.method', }), ).toBe(true) expect( set.allowsRpc({ aud: 'did:web:example.com#foo', lxm: 'app.bsky.feed.getFeed', }), ).toBe(true) // Control expect( set.allowsRpc({ aud: 'did:web:bar.com#foo', // invalid aud (wrong service id) lxm: 'com.example.method', }), ).toBe(false) expect( set.allowsRpc({ aud: 'did:web:example.com', // invalid aud (no service id) lxm: 'com.example.method', }), ).toBe(false) }) it('should allow constraining "lxm" and "aud"', () => { const set = new ScopePermissions( 'rpc:app.bsky.feed.getFeed?aud=did:web:example.com%23foo', ) expect( set.allowsRpc({ aud: 'did:web:example.com#foo', lxm: 'app.bsky.feed.getFeed', }), ).toBe(true) // Control expect( set.allowsRpc({ aud: 'did:web:example.com', lxm: 'com.example.method', }), ).toBe(false) expect( set.allowsRpc({ aud: 'did:plc:blahbla', lxm: 'app.bsky.feed.getFeed' }), ).toBe(false) }) it('should ignore "transition:generic"', () => { const set = new ScopePermissions('transition:generic') expect( set.allowsRpc({ aud: 'did:web:example.com', lxm: 'app.bsky.feed.getFeed', }), ).toBe(false) expect( set.allowsRpc({ aud: 'did:web:example.com', lxm: 'com.example.method', }), ).toBe(false) }) it('should ignore "transition:chat.bsky"', () => { const set = new ScopePermissions('transition:chat.bsky') expect( set.allowsRpc({ aud: 'did:web:example.com', lxm: 'chat.bsky.message.send', }), ).toBe(false) expect( set.allowsRpc({ aud: 'did:web:example.com', lxm: 'chat.bsky.conversation.get', }), ).toBe(false) // Control expect( set.allowsRpc({ aud: 'did:web:example.com', lxm: 'app.bsky.feed.post', }), ).toBe(false) expect( set.allowsRpc({ aud: 'did:web:example.com', lxm: 'com.example.foo' }), ).toBe(false) }) }) })