~ knotless Search/
↑↓ move↵ open⇧↵ all results

chadtmiller.com/pds.js

An atproto PDS in JavaScript, for Cloudflare Workers and Node

0
0
main
143 lines · 3.9 KB Raw History
// A space's policy goes out as a lexicon union and comes back as one. Both
// directions are here because the editor reads a policy into a form and writes
// the form back, and a mismatch between the two silently resets a field
// nobody meant to touch.

import { describe, expect, it } from 'vitest';
import {
  accessKind,
  allowedOf,
  isPublic,
  managingAppOf,
  policyKind,
  policyUnion,
  publishes,
} from '#/lib/policy.js';

describe('policyKind', () => {
  it('reads each baseline policy', () => {
    for (const kind of ['personalspace', 'memberspace', 'managedspace']) {
      expect(
        policyKind({ policy: { $type: `com.atproto.${kind}.policy` } }),
      ).toBe(kind);
    }
  });

  it('is null for a policy it does not know', () => {
    expect(policyKind({ policy: { $type: 'com.example.policy' } })).toBeNull();
    expect(policyKind({})).toBeNull();
  });
});

describe('reading a memberspace', () => {
  const config = {
    policy: {
      $type: 'com.atproto.memberspace.policy',
      publicRead: true,
      publicWrite: false,
      allowedApps: ['https://a.example/c.json', 7],
      publishMembers: true,
    },
  };

  it('reads its flags', () => {
    expect(isPublic(config, 'read')).toBe(true);
    expect(isPublic(config, 'write')).toBe(false);
    expect(publishes(config, 'publishMembers')).toBe(true);
    expect(publishes(config, 'publishPolicy')).toBe(false);
  });

  it('reads its allow list, keeping only strings', () => {
    expect(accessKind(config)).toBe('allowList');
    expect(allowedOf(config)).toEqual(['https://a.example/c.json']);
  });

  it('is open with no allow list', () => {
    expect(
      accessKind({ policy: { $type: 'com.atproto.memberspace.policy' } }),
    ).toBe('open');
  });

  it('reads no public access off another policy', () => {
    expect(
      isPublic(
        {
          policy: {
            $type: 'com.atproto.managedspace.policy',
            publicRead: true,
          },
        },
        'read',
      ),
    ).toBe(false);
  });
});

describe('managingAppOf', () => {
  it('reads the managing app of a managedspace', () => {
    expect(
      managingAppOf({
        policy: {
          $type: 'com.atproto.managedspace.policy',
          managingApp: 'did:web:app.example#forum',
        },
      }),
    ).toBe('did:web:app.example#forum');
    expect(managingAppOf({})).toBeNull();
  });
});

describe('policyUnion', () => {
  it('writes a memberspace with every field', () => {
    expect(
      policyUnion('memberspace', {
        publicRead: true,
        allowedApps: ['https://a.example/c.json'],
        managingApp: 'did:web:ignored.example',
      }),
    ).toEqual({
      $type: 'com.atproto.memberspace.policy',
      publicRead: true,
      publicWrite: false,
      allowedApps: ['https://a.example/c.json'],
      publishPolicy: false,
      publishMembers: false,
    });
  });

  it('leaves the allow list out to let any app read', () => {
    expect(
      policyUnion('memberspace', { allowedApps: null }),
    ).not.toHaveProperty('allowedApps');
  });

  it('writes a managedspace and a personalspace', () => {
    expect(
      policyUnion('managedspace', {
        managingApp: 'did:web:app.example#forum',
        publishPolicy: true,
      }),
    ).toEqual({
      $type: 'com.atproto.managedspace.policy',
      managingApp: 'did:web:app.example#forum',
      publishPolicy: true,
    });
    expect(policyUnion('personalspace', { publicRead: true })).toEqual({
      $type: 'com.atproto.personalspace.policy',
    });
  });

  it('round-trips through the readers', () => {
    const config = {
      policy: policyUnion('memberspace', {
        publicWrite: true,
        allowedApps: ['https://a.example/c.json'],
        publishPolicy: true,
      }),
    };
    expect(policyKind(config)).toBe('memberspace');
    expect(isPublic(config, 'write')).toBe(true);
    expect(allowedOf(config)).toEqual(['https://a.example/c.json']);
    expect(publishes(config, 'publishPolicy')).toBe(true);
  });
});