pl-fe: fix simple policy mrf management

Signed-off-by: nicole mikołajczyk <git@mkljczk.pl>
This commit is contained in:
nicole mikołajczyk
2025-10-15 13:49:27 +02:00
parent 5316395ee9
commit 5bc3ef409e
7 changed files with 61 additions and 36 deletions

View File

@ -188,18 +188,36 @@ const pleromaSchema = coerceObject({
federation: coerceObject({
enabled: v.fallback(v.boolean(), true), // Assume true unless explicitly false
mrf_policies: v.fallback(v.optional(v.array(v.string())), undefined),
mrf_simple: coerceObject({
accept: v.fallback(v.array(v.string()), []),
avatar_removal: v.fallback(v.array(v.string()), []),
banner_removal: v.fallback(v.array(v.string()), []),
federated_timeline_removal: v.fallback(v.array(v.string()), []),
followers_only: v.fallback(v.array(v.string()), []),
media_nsfw: v.fallback(v.array(v.string()), []),
media_removal: v.fallback(v.array(v.string()), []),
reject: v.fallback(v.array(v.string()), []),
reject_deletes: v.fallback(v.array(v.string()), []),
report_removal: v.fallback(v.array(v.string()), []),
}),
mrf_simple: coerceObject(v.entriesFromList(
[
'accept',
'avatar_removal',
'banner_removal',
'federated_timeline_removal',
'followers_only',
'media_nsfw',
'media_removal',
'reject',
'reject_deletes',
'report_removal',
],
v.fallback(v.array(v.string()), []),
)),
mrf_simple_info: coerceObject(v.entriesFromList(
[
'accept',
'avatar_removal',
'banner_removal',
'federated_timeline_removal',
'followers_only',
'media_nsfw',
'media_removal',
'reject',
'reject_deletes',
'report_removal',
],
v.fallback(v.array(v.tuple([v.string(), v.string()])), []),
)),
}),
fields_limits: coerceObject({
max_fields: v.fallback(v.pipe(v.number(), v.integer(), v.minValue(0)), 4),

View File

@ -1,26 +1,33 @@
import { mrfSimpleSchema, type MRFSimple } from 'pl-fe/schemas/pleroma';
import ConfigDB from 'pl-fe/utils/config-db';
import { fetchConfig, updateConfig } from './admin';
import type { MRFSimple } from 'pl-fe/schemas/pleroma';
import type { AppDispatch, RootState } from 'pl-fe/store';
const simplePolicyMerge = (simplePolicy: MRFSimple, host: string, restrictions: Record<string, any>) => {
const simplePolicyMerge = (simplePolicy: Partial<MRFSimple>, host: string, restrictions: Record<string, any>): MRFSimple => {
const entries = Object.entries(simplePolicy).map(([key, hosts]) => {
const isRestricted = restrictions[key];
const set = new Set(hosts);
hosts = [...hosts];
if (isRestricted) {
set.add(host);
if (!hosts.some((tuple) => tuple[0] === host)) {
hosts.push([host, '']);
}
} else {
set.delete(host);
hosts = hosts.filter((tuple) => tuple[0] !== host);
}
return [key, [...set]];
return [key, hosts];
});
return Object.fromEntries(entries);
return Object.fromEntries([
...Object.keys(
(mrfSimpleSchema as any).wrapped.pipe[2].entries as typeof mrfSimpleSchema.entries,
).map((key) => [key, []]),
...entries,
]);
};
const updateMrf = (host: string, restrictions: Record<string, any>) =>

View File

@ -47,7 +47,7 @@ const FederationRestrictionsPage = () => {
<div className='pt-4'>
<ScrollableList emptyMessageText={emptyMessage}>
{hosts.map((host) => <RestrictedInstance key={host} host={host} />)}
{hosts.map(([host]) => <RestrictedInstance key={host} host={host} />)}
</ScrollableList>
</div>
</Column>

View File

@ -32,9 +32,8 @@ const getConfigValue = (instanceConfig: Array<any>, key: string) => {
const importConfigs = (state: State, configs: PleromaConfig['configs']) => {
// FIXME: This is pretty hacked together. Need to make a cleaner map.
const config = ConfigDB.find(configs, ':pleroma', ':instance');
const simplePolicy = ConfigDB.toSimplePolicy(configs);
if (!config && !simplePolicy) return state;
if (!config) return state;
if (config) {
const value = config.value || [];
@ -47,10 +46,6 @@ const importConfigs = (state: State, configs: PleromaConfig['configs']) => {
approval_required: approvalRequired ?? state.registrations.approval_required,
};
}
if (simplePolicy) {
state.pleroma.metadata.federation.mrf_simple = simplePolicy;
}
};
const handleAuthFetch = (state: State) => {

View File

@ -2,6 +2,11 @@ import * as v from 'valibot';
import { coerceObject } from './utils';
const mrfSimpleInstanceSchema = v.pipe(v.any(), v.transform((value) => {
if (typeof value === 'string') return [value, ''];
return value.tuple;
}), v.tuple([v.string(), v.string()]));
const mrfSimpleSchema = coerceObject(v.entriesFromList(
[
'accept',
@ -15,7 +20,7 @@ const mrfSimpleSchema = coerceObject(v.entriesFromList(
'reject_deletes',
'report_removal',
],
v.fallback(v.array(v.string()), []),
v.fallback(v.array(mrfSimpleInstanceSchema), []),
));
type MRFSimple = v.InferOutput<typeof mrfSimpleSchema>;

View File

@ -1,6 +1,5 @@
import { createSelector } from 'reselect';
// import { getLocale } from 'pl-fe/actions/settings';
import { Entities } from 'pl-fe/entity-store/entities';
import { useSettingsStore } from 'pl-fe/stores/settings';
import { getDomain } from 'pl-fe/utils/accounts';
@ -245,8 +244,8 @@ const makeGetOtherAccounts = () => createSelector([
const getSimplePolicy = createSelector([
(state: RootState) => state.admin.configs,
(state: RootState) => state.instance.pleroma.metadata.federation.mrf_simple,
], (configs, instancePolicy) => ({
(state: RootState) => state.instance.pleroma.metadata.federation.mrf_simple_info,
], (configs, instancePolicy): MRFSimple => ({
...instancePolicy,
...ConfigDB.toSimplePolicy(configs),
}));
@ -265,7 +264,7 @@ const getRemoteInstanceFederation = (state: RootState, host: string): HostFedera
const simplePolicy = getSimplePolicy(state);
return Object.fromEntries(
Object.entries(simplePolicy).map(([key, hosts]) => [key, hosts.includes(host)]),
Object.entries(simplePolicy).map(([key, hosts]) => [key, hosts.some(entry => entry[0] === host)]),
) as HostFederation;
};

View File

@ -1,7 +1,7 @@
import trimStart from 'lodash/trimStart';
import * as v from 'valibot';
import { mrfSimpleSchema } from 'pl-fe/schemas/pleroma';
import { mrfSimpleSchema, type MRFSimple } from 'pl-fe/schemas/pleroma';
import type { PleromaConfig } from 'pl-api';
@ -16,13 +16,14 @@ const find = (
config.group === group && config.key === key,
);
const toSimplePolicy = (configs: PleromaConfig['configs']) => {
const toSimplePolicy = (configs: PleromaConfig['configs']): Partial<MRFSimple> => {
const config = find(configs, ':pleroma', ':mrf_simple');
const reducer = (acc: Record<string, any>, curr: Record<string, any>) => {
const key = curr.tuple?.[0] as string;
const hosts = curr.tuple?.[1] as Array<string>;
return acc[trimStart(key, ':')] = hosts;
acc[trimStart(key, ':')] = hosts;
return acc;
};
if (config) {
@ -30,12 +31,12 @@ const toSimplePolicy = (configs: PleromaConfig['configs']) => {
const result = value.reduce(reducer, {});
return v.parse(mrfSimpleSchema, result);
} else {
return v.parse(mrfSimpleSchema, {});
return {};
}
};
const fromSimplePolicy = (simplePolicy: Policy) => {
const mapper = ([key, hosts]: [key: string, hosts: Array<string>]) => ({ tuple: [`:${key}`, hosts] });
const mapper = ([key, hosts]: [key: string, hosts: Array<[string, string]>]) => ({ tuple: [`:${key}`, hosts.map(host => ({ tuple: host }))] });
const value = Object.entries(simplePolicy).map(mapper);