mirror of
https://github.com/the-draupnir-project/Draupnir.git
synced 2026-03-29 10:29:57 +00:00
This commit is contained in:
@@ -75,8 +75,9 @@ export class AccessControl {
|
|||||||
return MPSAccess.getAccessForUser(
|
return MPSAccess.getAccessForUser(
|
||||||
this.accessControlRevisionIssuer.currentRevision,
|
this.accessControlRevisionIssuer.currentRevision,
|
||||||
mxid,
|
mxid,
|
||||||
// Appservice provisioning should be gated by explicit user allow rules.
|
// Appservice provisioning is gated by explicit user allow rules only.
|
||||||
"CHECK_SERVER"
|
// Do not allow server-level rules to implicitly permit provisioning.
|
||||||
|
"IGNORE_SERVER"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -290,6 +290,14 @@ export class MjolnirAppService {
|
|||||||
`Failed to provision a draupnir for ${mxEvent.sender} after they invited ${this.bridge.botUserId}`,
|
`Failed to provision a draupnir for ${mxEvent.sender} after they invited ${this.bridge.botUserId}`,
|
||||||
result.error
|
result.error
|
||||||
);
|
);
|
||||||
|
await this.bridge
|
||||||
|
.getBot()
|
||||||
|
.getClient()
|
||||||
|
.sendText(
|
||||||
|
mxEvent.room_id,
|
||||||
|
"Please make sure you are allowed to provision a bot. Otherwise please notify the admin. The provisioning request was rejected."
|
||||||
|
);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
// Send a notice that the invite must be accepted
|
// Send a notice that the invite must be accepted
|
||||||
await this.bridge
|
await this.bridge
|
||||||
|
|||||||
@@ -34,6 +34,10 @@ export interface EntityAccess {
|
|||||||
readonly rule?: PolicyRule;
|
readonly rule?: PolicyRule;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type AllowRulesPolicy =
|
||||||
|
| "ALLOW_IF_NO_EXPLICIT_ALLOW_RULE"
|
||||||
|
| "REQUIRE_EXPLICIT_ALLOW_RULE";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This allows us to work out the access an entity has to some thing based on a set of watched/unwatched lists.
|
* This allows us to work out the access an entity has to some thing based on a set of watched/unwatched lists.
|
||||||
*/
|
*/
|
||||||
@@ -65,12 +69,17 @@ export class AccessControl {
|
|||||||
userID: StringUserID,
|
userID: StringUserID,
|
||||||
policy: "CHECK_SERVER" | "IGNORE_SERVER"
|
policy: "CHECK_SERVER" | "IGNORE_SERVER"
|
||||||
): EntityAccess {
|
): EntityAccess {
|
||||||
|
const allowRulesPolicy: AllowRulesPolicy =
|
||||||
|
policy === "IGNORE_SERVER"
|
||||||
|
? "REQUIRE_EXPLICIT_ALLOW_RULE"
|
||||||
|
: "ALLOW_IF_NO_EXPLICIT_ALLOW_RULE";
|
||||||
const userAccess = AccessControl.getAccessForEntity(
|
const userAccess = AccessControl.getAccessForEntity(
|
||||||
revision,
|
revision,
|
||||||
userID,
|
userID,
|
||||||
PolicyRuleType.User
|
PolicyRuleType.User,
|
||||||
|
allowRulesPolicy
|
||||||
);
|
);
|
||||||
if (policy === "IGNORE_SERVER" || userAccess.outcome === Access.Banned) {
|
if (policy === "IGNORE_SERVER" || userAccess.outcome !== Access.Allowed) {
|
||||||
return userAccess;
|
return userAccess;
|
||||||
} else {
|
} else {
|
||||||
const serverAccess = AccessControl.getAccessForEntity(
|
const serverAccess = AccessControl.getAccessForEntity(
|
||||||
@@ -78,21 +87,17 @@ export class AccessControl {
|
|||||||
userServerName(userID),
|
userServerName(userID),
|
||||||
PolicyRuleType.Server
|
PolicyRuleType.Server
|
||||||
);
|
);
|
||||||
if (
|
// CHECK_SERVER applies server bans while keeping explicit user allow as
|
||||||
userAccess.outcome === Access.Allowed &&
|
// the source of truth for who is allowed to provision.
|
||||||
serverAccess.outcome === Access.NotAllowed
|
return serverAccess.outcome === Access.Banned ? serverAccess : userAccess;
|
||||||
) {
|
|
||||||
return userAccess;
|
|
||||||
} else {
|
|
||||||
return serverAccess;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static getAccessForEntity(
|
public static getAccessForEntity(
|
||||||
revision: PolicyListRevision,
|
revision: PolicyListRevision,
|
||||||
entity: string,
|
entity: string,
|
||||||
entityType: PolicyRuleType
|
entityType: PolicyRuleType,
|
||||||
|
allowRulesPolicy: AllowRulesPolicy = "ALLOW_IF_NO_EXPLICIT_ALLOW_RULE"
|
||||||
): EntityAccess {
|
): EntityAccess {
|
||||||
// Check if the entity is explicitly allowed.
|
// Check if the entity is explicitly allowed.
|
||||||
// We have to infer that a rule exists for '*' if the allowCache is empty, otherwise you brick the ACL.
|
// We have to infer that a rule exists for '*' if the allowCache is empty, otherwise you brick the ACL.
|
||||||
@@ -101,10 +106,11 @@ export class AccessControl {
|
|||||||
recommendation: Recommendation.Allow,
|
recommendation: Recommendation.Allow,
|
||||||
searchHashedRules: false,
|
searchHashedRules: false,
|
||||||
});
|
});
|
||||||
|
const hasAllowRules =
|
||||||
|
revision.allRulesOfType(entityType, Recommendation.Allow).length !== 0;
|
||||||
if (
|
if (
|
||||||
allowRule === undefined &&
|
allowRule === undefined &&
|
||||||
// this is gonna be a pita resource wise.
|
(hasAllowRules || allowRulesPolicy === "REQUIRE_EXPLICIT_ALLOW_RULE")
|
||||||
!(revision.allRulesOfType(entityType, Recommendation.Allow).length === 0)
|
|
||||||
) {
|
) {
|
||||||
return { outcome: Access.NotAllowed };
|
return { outcome: Access.NotAllowed };
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user