mirror of
https://github.com/the-draupnir-project/Draupnir.git
synced 2026-10-23 01:21:16 +00:00
Add a builder for protection descriptions.
https://github.com/the-draupnir-project/planning/issues/152
This commit is contained in:
3 files changed
+155
-21
No files matched your search
@@ -28,6 +28,121 @@ export interface ProjectionDescription<
|
||||
|
||||
export type AnyProjectionDescription = ProjectionDescription;
|
||||
|
||||
type ProjectionDescriptionRuntime<
|
||||
TName extends string,
|
||||
TPartitionKeys extends ProjectionPartitionKeys,
|
||||
> = {
|
||||
readonly name: TName;
|
||||
readonly partitionKeys: TPartitionKeys;
|
||||
};
|
||||
|
||||
export type ProjectionDescriptionBuilder<
|
||||
TName extends string,
|
||||
TPartitionKeys extends ProjectionPartitionKeys,
|
||||
TInputs extends readonly unknown[] = readonly unknown[],
|
||||
TDownstreamDeltaShape = unknown,
|
||||
TAccessMixin = Record<never, never>,
|
||||
> = {
|
||||
withInputs<
|
||||
TNextInputs extends readonly unknown[],
|
||||
>(): ProjectionDescriptionBuilder<
|
||||
TName,
|
||||
TPartitionKeys,
|
||||
TNextInputs,
|
||||
TDownstreamDeltaShape,
|
||||
TAccessMixin
|
||||
>;
|
||||
withDownstreamDeltaShape<
|
||||
TNextDownstreamDeltaShape,
|
||||
>(): ProjectionDescriptionBuilder<
|
||||
TName,
|
||||
TPartitionKeys,
|
||||
TInputs,
|
||||
TNextDownstreamDeltaShape,
|
||||
TAccessMixin
|
||||
>;
|
||||
withAccessMixin<TNextAccessMixin>(): ProjectionDescriptionBuilder<
|
||||
TName,
|
||||
TPartitionKeys,
|
||||
TInputs,
|
||||
TDownstreamDeltaShape,
|
||||
TNextAccessMixin
|
||||
>;
|
||||
build(): ProjectionDescription<
|
||||
TInputs,
|
||||
TDownstreamDeltaShape,
|
||||
TAccessMixin,
|
||||
TPartitionKeys
|
||||
> & {
|
||||
readonly name: TName;
|
||||
};
|
||||
};
|
||||
|
||||
function makeProjectionDescriptionBuilder<
|
||||
TName extends string,
|
||||
TPartitionKeys extends ProjectionPartitionKeys,
|
||||
TInputs extends readonly unknown[] = readonly unknown[],
|
||||
TDownstreamDeltaShape = unknown,
|
||||
TAccessMixin = Record<never, never>,
|
||||
>(
|
||||
description: ProjectionDescriptionRuntime<TName, TPartitionKeys>
|
||||
): ProjectionDescriptionBuilder<
|
||||
TName,
|
||||
TPartitionKeys,
|
||||
TInputs,
|
||||
TDownstreamDeltaShape,
|
||||
TAccessMixin
|
||||
> {
|
||||
return {
|
||||
withInputs<TNextInputs extends readonly unknown[]>() {
|
||||
return makeProjectionDescriptionBuilder<
|
||||
TName,
|
||||
TPartitionKeys,
|
||||
TNextInputs,
|
||||
TDownstreamDeltaShape,
|
||||
TAccessMixin
|
||||
>(description);
|
||||
},
|
||||
withDownstreamDeltaShape<TNextDownstreamDeltaShape>() {
|
||||
return makeProjectionDescriptionBuilder<
|
||||
TName,
|
||||
TPartitionKeys,
|
||||
TInputs,
|
||||
TNextDownstreamDeltaShape,
|
||||
TAccessMixin
|
||||
>(description);
|
||||
},
|
||||
withAccessMixin<TNextAccessMixin>() {
|
||||
return makeProjectionDescriptionBuilder<
|
||||
TName,
|
||||
TPartitionKeys,
|
||||
TInputs,
|
||||
TDownstreamDeltaShape,
|
||||
TNextAccessMixin
|
||||
>(description);
|
||||
},
|
||||
build() {
|
||||
return description;
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export function describeProjection<
|
||||
const TName extends string,
|
||||
const TPartitionKeys extends ProjectionPartitionKeys,
|
||||
>({
|
||||
name,
|
||||
partitionKeys,
|
||||
}: {
|
||||
readonly name: TName;
|
||||
readonly partitionKeys: TPartitionKeys;
|
||||
}): ProjectionDescriptionBuilder<TName, TPartitionKeys> {
|
||||
return makeProjectionDescriptionBuilder<TName, TPartitionKeys>({
|
||||
name,
|
||||
partitionKeys,
|
||||
});
|
||||
}
|
||||
|
||||
export type ExtractProjectionDescriptionInputs<
|
||||
TDescription extends AnyProjectionDescription,
|
||||
> =
|
||||
|
||||
+23
-12
@@ -12,7 +12,10 @@ import {
|
||||
ExtractInputDeltaShapes,
|
||||
ProjectionNode,
|
||||
} from "../../../Projection/ProjectionNode";
|
||||
import { ProjectionDescription } from "../../../Projection/ProjectionDescription";
|
||||
import {
|
||||
describeProjection,
|
||||
ProjectionDescription,
|
||||
} from "../../../Projection/ProjectionDescription";
|
||||
import {
|
||||
MemberPolicyMatches,
|
||||
MembershipPolicyRevision,
|
||||
@@ -50,6 +53,14 @@ type MemberBanIntentMap = PersistentMap<
|
||||
List<LiteralPolicyRule | GlobPolicyRule>
|
||||
>;
|
||||
|
||||
export type MemberBanIntentProjectionAccessMixin = {
|
||||
allMembersWithRules(): MemberPolicyMatches[];
|
||||
isMemberBanned(member: StringUserID): boolean;
|
||||
allRulesMatchingMember(
|
||||
member: StringUserID
|
||||
): (LiteralPolicyRule | GlobPolicyRule)[];
|
||||
};
|
||||
|
||||
function isPolicyRelevant(policy: LiteralPolicyRule | GlobPolicyRule): boolean {
|
||||
return (
|
||||
policy.recommendation === Recommendation.Ban ||
|
||||
@@ -57,17 +68,17 @@ function isPolicyRelevant(policy: LiteralPolicyRule | GlobPolicyRule): boolean {
|
||||
);
|
||||
}
|
||||
|
||||
export type MemberBanIntentProjectionDescription = ProjectionDescription<
|
||||
[MemberBanInputProjectionNode],
|
||||
MemberBanIntentProjectionDelta,
|
||||
{
|
||||
allMembersWithRules(): MemberPolicyMatches[];
|
||||
isMemberBanned(member: StringUserID): boolean;
|
||||
allRulesMatchingMember(
|
||||
member: StringUserID
|
||||
): (LiteralPolicyRule | GlobPolicyRule)[];
|
||||
}
|
||||
>;
|
||||
export const MemberBanIntentProjectionDescription = describeProjection({
|
||||
name: "MemberBanIntentProjection",
|
||||
partitionKeys: [],
|
||||
})
|
||||
.withInputs<[MemberBanInputProjectionNode]>()
|
||||
.withDownstreamDeltaShape<MemberBanIntentProjectionDelta>()
|
||||
.withAccessMixin<MemberBanIntentProjectionAccessMixin>()
|
||||
.build();
|
||||
|
||||
export type MemberBanIntentProjectionDescription =
|
||||
typeof MemberBanIntentProjectionDescription;
|
||||
|
||||
export type MemberBanIntentProjectionNode =
|
||||
ProjectionNode<MemberBanIntentProjectionDescription>;
|
||||
|
||||
+17
-9
@@ -8,7 +8,7 @@
|
||||
// </text>
|
||||
|
||||
import { StringServerName } from "@the-draupnir-project/matrix-basic-types";
|
||||
import { ProjectionDescription } from "../../../Projection/ProjectionDescription";
|
||||
import { describeProjection } from "../../../Projection/ProjectionDescription";
|
||||
import { ProjectionNode } from "../../../Projection/ProjectionNode";
|
||||
import { PolicyListBridgeProjectionNode } from "./PolicyListBridgeProjection";
|
||||
import {
|
||||
@@ -36,17 +36,25 @@ type ServerBanIntentMap = PersistentMap<
|
||||
List<LiteralPolicyRule | GlobPolicyRule>
|
||||
>;
|
||||
|
||||
export type ServerBanIntentProjectionAccessMixin = {
|
||||
deny: StringServerName[];
|
||||
isServerDenied(serverName: StringServerName): boolean;
|
||||
};
|
||||
|
||||
// is there a way that we can adapt this so that it can possibly be swapped
|
||||
// to a lazy ban style protection if acls become exhausted.
|
||||
// not withiout addressing the issues in the member protection tbh.
|
||||
export type ServerBanIntentProjectionDescription = ProjectionDescription<
|
||||
[PolicyListBridgeProjectionNode],
|
||||
ServerBanIntentProjectionDelta,
|
||||
{
|
||||
deny: StringServerName[];
|
||||
isServerDenied(serverName: StringServerName): boolean;
|
||||
}
|
||||
>;
|
||||
export const ServerBanIntentProjectionDescription = describeProjection({
|
||||
name: "ServerBanIntentProjection",
|
||||
partitionKeys: [],
|
||||
})
|
||||
.withInputs<[PolicyListBridgeProjectionNode]>()
|
||||
.withDownstreamDeltaShape<ServerBanIntentProjectionDelta>()
|
||||
.withAccessMixin<ServerBanIntentProjectionAccessMixin>()
|
||||
.build();
|
||||
|
||||
export type ServerBanIntentProjectionDescription =
|
||||
typeof ServerBanIntentProjectionDescription;
|
||||
|
||||
export type ServerBanIntentProjectionNode =
|
||||
ProjectionNode<ServerBanIntentProjectionDescription>;
|
||||
|
||||
Reference in new issue
Block a user