84 lines
3.7 KiB
TypeScript
84 lines
3.7 KiB
TypeScript
import {
|
|
$claimNick,
|
|
$joinedUser,
|
|
$says,
|
|
$user,
|
|
Join,
|
|
NickConflict,
|
|
UserId,
|
|
UserInfo,
|
|
fromJoin,
|
|
fromNickConflict,
|
|
fromUserInfo,
|
|
} from "../gen/secureChatProtocol.js";
|
|
import { Assertion, Handle, Ref, Turn } from "../runtime/actor.js";
|
|
import { observe, during, $Observe, Dataspace, P, $rec, $compound } from "../runtime/dataspace.js";
|
|
import { attenuate, rfilter, pRec, pEmbedded, pString, pLit, pDiscard } from "../runtime/rewrite.js";
|
|
import { attenuate as sturdyAttenuate, KEY_LENGTH, sturdyEncode, fromSturdyRef, mint } from "../transport/sturdy.js";
|
|
import { Bind, fromBind } from "../gen/gatekeeper.js";
|
|
import { Bytes, Embedded } from "@preserves/core";
|
|
|
|
export default function (t: Turn, gatekeeperDs_ptr: Embedded<Ref>) {
|
|
const gatekeeperDs = gatekeeperDs_ptr.embeddedValue;
|
|
|
|
const ds = t.ref(new Dataspace());
|
|
|
|
const chatOid = 'chat';
|
|
const chatKey = new Bytes(KEY_LENGTH);
|
|
t.assert(gatekeeperDs, fromBind(Bind({ oid: chatOid, key: chatKey, target: ds })));
|
|
mint(chatOid, chatKey).then(async r => {
|
|
r = await sturdyAttenuate(r, rfilter(pRec($Observe,
|
|
pRec($compound,
|
|
pRec($rec, pLit($joinedUser), pLit(2)),
|
|
pDiscard()),
|
|
pEmbedded())));
|
|
console.log(fromSturdyRef(r).asPreservesText());
|
|
console.log(sturdyEncode(fromSturdyRef(r)).toHex());
|
|
});
|
|
|
|
const nicks = new Map<string, UserId>();
|
|
|
|
let nextUserId: UserId = 0;
|
|
observe(t, ds, P.rec($Observe,
|
|
P.rec($compound,
|
|
P.rec($rec, P.lit($joinedUser), P.lit(2)),
|
|
P.discard()),
|
|
P.bind('observer', P.discard())),
|
|
during(async (t, bindings) => {
|
|
const [embeddedObserver] = bindings as [Embedded<Ref>];
|
|
const observer = embeddedObserver.embeddedValue;
|
|
|
|
const uid: UserId = nextUserId++;
|
|
const f = t.facet(t => {
|
|
t.assert(observer, fromJoin(Join({
|
|
uid,
|
|
handle: attenuate(ds, rfilter(
|
|
pRec($Observe, pLit($user), pEmbedded()),
|
|
pRec($Observe, pLit($says), pEmbedded()),
|
|
pRec($claimNick, pLit(uid), pString(), pEmbedded()),
|
|
pRec($says, pLit(uid), pString()))),
|
|
})));
|
|
let infoHandle: Handle | undefined;
|
|
let nick: string | undefined;
|
|
observe(t, ds, P.rec($claimNick, P.lit(uid), P.bind('name'), P.bind('k')), {
|
|
assert(t: Turn, bindings: Assertion): void {
|
|
const [name, embeddedK] = bindings as [string, Embedded<Ref>];
|
|
const k = embeddedK.embeddedValue;
|
|
if (nicks.has(name)) {
|
|
t.message(k, fromNickConflict(NickConflict()));
|
|
} else {
|
|
t.message(k, true);
|
|
if (nick !== void 0) nicks.delete(nick);
|
|
infoHandle = t.replace(ds, infoHandle,
|
|
fromUserInfo(UserInfo({ uid, name })));
|
|
nick = name;
|
|
nicks.set(nick, uid);
|
|
}
|
|
}
|
|
});
|
|
});
|
|
|
|
return t => t.stop(f);
|
|
}));
|
|
}
|