Merge branch 'mrf-config-updates' into 'develop'
EditFederationModal: use ConfigDB directly instead of /api/v1/instance See merge request soapbox-pub/soapbox-fe!649
This commit is contained in:
commit
67d68b7efb
|
@ -82,10 +82,10 @@ export function updateConfig(configs) {
|
||||||
dispatch({ type: ADMIN_CONFIG_UPDATE_REQUEST, configs });
|
dispatch({ type: ADMIN_CONFIG_UPDATE_REQUEST, configs });
|
||||||
return api(getState)
|
return api(getState)
|
||||||
.post('/api/pleroma/admin/config', { configs })
|
.post('/api/pleroma/admin/config', { configs })
|
||||||
.then(({ data: { configs } }) => {
|
.then(({ data }) => {
|
||||||
dispatch({ type: ADMIN_CONFIG_UPDATE_SUCCESS, configs });
|
dispatch({ type: ADMIN_CONFIG_UPDATE_SUCCESS, configs: data.configs, needsReboot: data.need_reboot });
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
dispatch({ type: ADMIN_CONFIG_UPDATE_FAIL, error });
|
dispatch({ type: ADMIN_CONFIG_UPDATE_FAIL, error, configs });
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { fetchInstance } from './instance';
|
import { fetchConfig, updateConfig } from './admin';
|
||||||
import { updateConfig } from './admin';
|
|
||||||
import { Set as ImmutableSet } from 'immutable';
|
import { Set as ImmutableSet } from 'immutable';
|
||||||
|
import ConfigDB from 'soapbox/utils/config_db';
|
||||||
|
|
||||||
const simplePolicyMerge = (simplePolicy, host, restrictions) => {
|
const simplePolicyMerge = (simplePolicy, host, restrictions) => {
|
||||||
return simplePolicy.map((hosts, key) => {
|
return simplePolicy.map((hosts, key) => {
|
||||||
|
@ -14,31 +14,15 @@ const simplePolicyMerge = (simplePolicy, host, restrictions) => {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const simplePolicyToConfig = simplePolicy => {
|
|
||||||
const value = simplePolicy.map((hosts, key) => (
|
|
||||||
{ tuple: [`:${key}`, hosts.toJS()] }
|
|
||||||
)).toList();
|
|
||||||
|
|
||||||
return [{
|
|
||||||
group: ':pleroma',
|
|
||||||
key: ':mrf_simple',
|
|
||||||
value,
|
|
||||||
}];
|
|
||||||
};
|
|
||||||
|
|
||||||
export function updateMrf(host, restrictions) {
|
export function updateMrf(host, restrictions) {
|
||||||
return (dispatch, getState) => {
|
return (dispatch, getState) => {
|
||||||
return dispatch(fetchInstance())
|
return dispatch(fetchConfig())
|
||||||
.then(() => {
|
.then(() => {
|
||||||
const simplePolicy = getState().getIn(['instance', 'pleroma', 'metadata', 'federation', 'mrf_simple']);
|
const configs = getState().getIn(['admin', 'configs']);
|
||||||
|
const simplePolicy = ConfigDB.toSimplePolicy(configs);
|
||||||
const merged = simplePolicyMerge(simplePolicy, host, restrictions);
|
const merged = simplePolicyMerge(simplePolicy, host, restrictions);
|
||||||
const config = simplePolicyToConfig(merged);
|
const config = ConfigDB.fromSimplePolicy(merged);
|
||||||
dispatch(updateConfig(config));
|
dispatch(updateConfig(config));
|
||||||
|
|
||||||
// TODO: Make this less insane
|
|
||||||
setTimeout(() => {
|
|
||||||
dispatch(fetchInstance());
|
|
||||||
}, 1000);
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,21 +4,11 @@ import { defineMessages, injectIntl } from 'react-intl';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||||
import Column from '../ui/components/column';
|
import Column from '../ui/components/column';
|
||||||
import { createSelector } from 'reselect';
|
|
||||||
import { Map as ImmutableMap, OrderedSet as ImmutableOrderedSet } from 'immutable';
|
|
||||||
import RestrictedInstance from './components/restricted_instance';
|
import RestrictedInstance from './components/restricted_instance';
|
||||||
import Accordion from 'soapbox/features/ui/components/accordion';
|
import Accordion from 'soapbox/features/ui/components/accordion';
|
||||||
import ScrollableList from 'soapbox/components/scrollable_list';
|
import ScrollableList from 'soapbox/components/scrollable_list';
|
||||||
import { federationRestrictionsDisclosed } from 'soapbox/utils/state';
|
import { federationRestrictionsDisclosed } from 'soapbox/utils/state';
|
||||||
|
import { makeGetHosts } from 'soapbox/selectors';
|
||||||
const getHosts = createSelector([
|
|
||||||
state => state.getIn(['instance', 'pleroma', 'metadata', 'federation', 'mrf_simple'], ImmutableMap()),
|
|
||||||
], (simplePolicy) => {
|
|
||||||
return simplePolicy
|
|
||||||
.deleteAll(['accept', 'reject_deletes', 'report_removal'])
|
|
||||||
.reduce((acc, hosts) => acc.union(hosts), ImmutableOrderedSet())
|
|
||||||
.sort();
|
|
||||||
});
|
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
heading: { id: 'column.federation_restrictions', defaultMessage: 'Federation Restrictions' },
|
heading: { id: 'column.federation_restrictions', defaultMessage: 'Federation Restrictions' },
|
||||||
|
@ -28,6 +18,8 @@ const messages = defineMessages({
|
||||||
notDisclosed: { id: 'federation_restrictions.not_disclosed_message', defaultMessage: '{siteTitle} does not disclose federation restrictions through the API.' },
|
notDisclosed: { id: 'federation_restrictions.not_disclosed_message', defaultMessage: '{siteTitle} does not disclose federation restrictions through the API.' },
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const getHosts = makeGetHosts();
|
||||||
|
|
||||||
const mapStateToProps = state => ({
|
const mapStateToProps = state => ({
|
||||||
siteTitle: state.getIn(['instance', 'title']),
|
siteTitle: state.getIn(['instance', 'title']),
|
||||||
hosts: getHosts(state),
|
hosts: getHosts(state),
|
||||||
|
|
|
@ -6,7 +6,7 @@ import { connect } from 'react-redux';
|
||||||
import { defineMessages, injectIntl } from 'react-intl';
|
import { defineMessages, injectIntl } from 'react-intl';
|
||||||
import { SimpleForm, Checkbox } from 'soapbox/features/forms';
|
import { SimpleForm, Checkbox } from 'soapbox/features/forms';
|
||||||
import { makeGetRemoteInstance } from 'soapbox/selectors';
|
import { makeGetRemoteInstance } from 'soapbox/selectors';
|
||||||
import { Map as ImmutableMap } from 'immutable';
|
import { Map as ImmutableMap, is } from 'immutable';
|
||||||
import { updateMrf } from 'soapbox/actions/mrf';
|
import { updateMrf } from 'soapbox/actions/mrf';
|
||||||
import snackbar from 'soapbox/actions/snackbar';
|
import snackbar from 'soapbox/actions/snackbar';
|
||||||
|
|
||||||
|
@ -41,11 +41,23 @@ class EditFederationModal extends ImmutablePureComponent {
|
||||||
data: ImmutableMap(),
|
data: ImmutableMap(),
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
hydrateState = () => {
|
||||||
const { remoteInstance } = this.props;
|
const { remoteInstance } = this.props;
|
||||||
this.setState({ data: remoteInstance.get('federation') });
|
this.setState({ data: remoteInstance.get('federation') });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
this.hydrateState();
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidUpdate(prevProps) {
|
||||||
|
const { remoteInstance } = this.props;
|
||||||
|
|
||||||
|
if (!is(prevProps.remoteInstance, remoteInstance)) {
|
||||||
|
this.hydrateState();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
handleDataChange = key => {
|
handleDataChange = key => {
|
||||||
return ({ target }) => {
|
return ({ target }) => {
|
||||||
const { data } = this.state;
|
const { data } = this.state;
|
||||||
|
|
|
@ -9,9 +9,11 @@ import LinkFooter from 'soapbox/features/ui/components/link_footer';
|
||||||
import { getFeatures } from 'soapbox/utils/features';
|
import { getFeatures } from 'soapbox/utils/features';
|
||||||
import InstanceInfoPanel from 'soapbox/features/ui/components/instance_info_panel';
|
import InstanceInfoPanel from 'soapbox/features/ui/components/instance_info_panel';
|
||||||
import { federationRestrictionsDisclosed } from 'soapbox/utils/state';
|
import { federationRestrictionsDisclosed } from 'soapbox/utils/state';
|
||||||
|
import { isAdmin } from 'soapbox/utils/accounts';
|
||||||
|
|
||||||
const mapStateToProps = state => {
|
const mapStateToProps = state => {
|
||||||
const me = state.get('me');
|
const me = state.get('me');
|
||||||
|
const account = state.getIn(['accounts', me]);
|
||||||
const features = getFeatures(state.get('instance'));
|
const features = getFeatures(state.get('instance'));
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
@ -19,6 +21,7 @@ const mapStateToProps = state => {
|
||||||
showTrendsPanel: features.trends,
|
showTrendsPanel: features.trends,
|
||||||
showWhoToFollowPanel: features.suggestions,
|
showWhoToFollowPanel: features.suggestions,
|
||||||
disclosed: federationRestrictionsDisclosed(state),
|
disclosed: federationRestrictionsDisclosed(state),
|
||||||
|
isAdmin: isAdmin(account),
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -26,7 +29,7 @@ export default @connect(mapStateToProps)
|
||||||
class RemoteInstancePage extends ImmutablePureComponent {
|
class RemoteInstancePage extends ImmutablePureComponent {
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { me, children, showTrendsPanel, showWhoToFollowPanel, params: { instance: host }, disclosed } = this.props;
|
const { me, children, showTrendsPanel, showWhoToFollowPanel, params: { instance: host }, disclosed, isAdmin } = this.props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='page'>
|
<div className='page'>
|
||||||
|
@ -35,7 +38,7 @@ class RemoteInstancePage extends ImmutablePureComponent {
|
||||||
|
|
||||||
<div className='columns-area__panels__pane columns-area__panels__pane--left'>
|
<div className='columns-area__panels__pane columns-area__panels__pane--left'>
|
||||||
<div className='columns-area__panels__pane__inner'>
|
<div className='columns-area__panels__pane__inner'>
|
||||||
{disclosed && <InstanceInfoPanel host={host} />}
|
{(disclosed || isAdmin) && <InstanceInfoPanel host={host} />}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import {
|
import {
|
||||||
ADMIN_CONFIG_FETCH_SUCCESS,
|
ADMIN_CONFIG_FETCH_SUCCESS,
|
||||||
|
ADMIN_CONFIG_UPDATE_SUCCESS,
|
||||||
ADMIN_REPORTS_FETCH_SUCCESS,
|
ADMIN_REPORTS_FETCH_SUCCESS,
|
||||||
ADMIN_REPORTS_PATCH_REQUEST,
|
ADMIN_REPORTS_PATCH_REQUEST,
|
||||||
ADMIN_REPORTS_PATCH_SUCCESS,
|
ADMIN_REPORTS_PATCH_SUCCESS,
|
||||||
|
@ -127,6 +128,7 @@ function handleReportDiffs(state, reports) {
|
||||||
export default function admin(state = initialState, action) {
|
export default function admin(state = initialState, action) {
|
||||||
switch(action.type) {
|
switch(action.type) {
|
||||||
case ADMIN_CONFIG_FETCH_SUCCESS:
|
case ADMIN_CONFIG_FETCH_SUCCESS:
|
||||||
|
case ADMIN_CONFIG_UPDATE_SUCCESS:
|
||||||
return state.set('configs', fromJS(action.configs));
|
return state.set('configs', fromJS(action.configs));
|
||||||
case ADMIN_REPORTS_FETCH_SUCCESS:
|
case ADMIN_REPORTS_FETCH_SUCCESS:
|
||||||
return importReports(state, action.reports);
|
return importReports(state, action.reports);
|
||||||
|
|
|
@ -51,15 +51,23 @@ const getConfigValue = (instanceConfig, key) => {
|
||||||
const importConfigs = (state, configs) => {
|
const importConfigs = (state, configs) => {
|
||||||
// FIXME: This is pretty hacked together. Need to make a cleaner map.
|
// FIXME: This is pretty hacked together. Need to make a cleaner map.
|
||||||
const config = ConfigDB.find(configs, ':pleroma', ':instance');
|
const config = ConfigDB.find(configs, ':pleroma', ':instance');
|
||||||
if (!config) return state;
|
const simplePolicy = ConfigDB.toSimplePolicy(configs);
|
||||||
const value = config.get('value', ImmutableList());
|
|
||||||
|
if (!config && !simplePolicy) return state;
|
||||||
|
|
||||||
return state.withMutations(state => {
|
return state.withMutations(state => {
|
||||||
const registrationsOpen = getConfigValue(value, ':registrations_open');
|
if (config) {
|
||||||
const approvalRequired = getConfigValue(value, ':account_approval_required');
|
const value = config.get('value', ImmutableList());
|
||||||
|
const registrationsOpen = getConfigValue(value, ':registrations_open');
|
||||||
|
const approvalRequired = getConfigValue(value, ':account_approval_required');
|
||||||
|
|
||||||
state.update('registrations', c => typeof registrationsOpen === 'boolean' ? registrationsOpen : c);
|
state.update('registrations', c => typeof registrationsOpen === 'boolean' ? registrationsOpen : c);
|
||||||
state.update('approval_required', c => typeof approvalRequired === 'boolean' ? approvalRequired : c);
|
state.update('approval_required', c => typeof approvalRequired === 'boolean' ? approvalRequired : c);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (simplePolicy) {
|
||||||
|
state.setIn(['pleroma', 'metadata', 'federation', 'mrf_simple'], simplePolicy);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,11 @@
|
||||||
import { createSelector } from 'reselect';
|
import { createSelector } from 'reselect';
|
||||||
import { Map as ImmutableMap, List as ImmutableList } from 'immutable';
|
import {
|
||||||
|
Map as ImmutableMap,
|
||||||
|
List as ImmutableList,
|
||||||
|
OrderedSet as ImmutableOrderedSet,
|
||||||
|
} from 'immutable';
|
||||||
import { getDomain } from 'soapbox/utils/accounts';
|
import { getDomain } from 'soapbox/utils/accounts';
|
||||||
|
import ConfigDB from 'soapbox/utils/config_db';
|
||||||
|
|
||||||
const getAccountBase = (state, id) => state.getIn(['accounts', id], null);
|
const getAccountBase = (state, id) => state.getIn(['accounts', id], null);
|
||||||
const getAccountCounters = (state, id) => state.getIn(['accounts_counters', id], null);
|
const getAccountCounters = (state, id) => state.getIn(['accounts_counters', id], null);
|
||||||
|
@ -217,22 +222,38 @@ export const makeGetOtherAccounts = () => {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const getSimplePolicy = createSelector([
|
||||||
|
state => state.getIn(['admin', 'configs'], ImmutableMap()),
|
||||||
|
state => state.getIn(['instance', 'pleroma', 'metadata', 'federation', 'mrf_simple'], ImmutableMap()),
|
||||||
|
], (configs, instancePolicy) => {
|
||||||
|
return instancePolicy.merge(ConfigDB.toSimplePolicy(configs));
|
||||||
|
});
|
||||||
|
|
||||||
const getRemoteInstanceFavicon = (state, host) => (
|
const getRemoteInstanceFavicon = (state, host) => (
|
||||||
state.get('accounts')
|
state.get('accounts')
|
||||||
.find(account => getDomain(account) === host, null, ImmutableMap())
|
.find(account => getDomain(account) === host, null, ImmutableMap())
|
||||||
.getIn(['pleroma', 'favicon'])
|
.getIn(['pleroma', 'favicon'])
|
||||||
);
|
);
|
||||||
|
|
||||||
const getSimplePolicy = (state, host) => (
|
const getRemoteInstanceFederation = (state, host) => (
|
||||||
state.getIn(['instance', 'pleroma', 'metadata', 'federation', 'mrf_simple'], ImmutableMap())
|
getSimplePolicy(state)
|
||||||
.map(hosts => hosts.includes(host))
|
.map(hosts => hosts.includes(host))
|
||||||
);
|
);
|
||||||
|
|
||||||
|
export const makeGetHosts = () => {
|
||||||
|
return createSelector([getSimplePolicy], (simplePolicy) => {
|
||||||
|
return simplePolicy
|
||||||
|
.deleteAll(['accept', 'reject_deletes', 'report_removal'])
|
||||||
|
.reduce((acc, hosts) => acc.union(hosts), ImmutableOrderedSet())
|
||||||
|
.sort();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
export const makeGetRemoteInstance = () => {
|
export const makeGetRemoteInstance = () => {
|
||||||
return createSelector([
|
return createSelector([
|
||||||
(state, host) => host,
|
(state, host) => host,
|
||||||
getRemoteInstanceFavicon,
|
getRemoteInstanceFavicon,
|
||||||
getSimplePolicy,
|
getRemoteInstanceFederation,
|
||||||
], (host, favicon, federation) => {
|
], (host, favicon, federation) => {
|
||||||
return ImmutableMap({
|
return ImmutableMap({
|
||||||
host,
|
host,
|
||||||
|
|
|
@ -1,9 +1,50 @@
|
||||||
|
import {
|
||||||
|
Map as ImmutableMap,
|
||||||
|
List as ImmutableList,
|
||||||
|
Set as ImmutableSet,
|
||||||
|
fromJS,
|
||||||
|
} from 'immutable';
|
||||||
|
import { trimStart } from 'lodash';
|
||||||
|
|
||||||
|
const find = (configs, group, key) => {
|
||||||
|
return configs.find(config =>
|
||||||
|
config.isSuperset({ group, key }),
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const toSimplePolicy = configs => {
|
||||||
|
const config = find(configs, ':pleroma', ':mrf_simple');
|
||||||
|
|
||||||
|
const reducer = (acc, curr) => {
|
||||||
|
const { tuple: [key, hosts] } = curr.toJS();
|
||||||
|
return acc.set(trimStart(key, ':'), ImmutableSet(hosts));
|
||||||
|
};
|
||||||
|
|
||||||
|
if (config && config.get) {
|
||||||
|
const value = config.get('value', ImmutableList());
|
||||||
|
return value.reduce(reducer, ImmutableMap());
|
||||||
|
} else {
|
||||||
|
return ImmutableMap();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const fromSimplePolicy = simplePolicy => {
|
||||||
|
const mapper = (hosts, key) => fromJS({ tuple: [`:${key}`, hosts.toJS()] });
|
||||||
|
const value = simplePolicy.map(mapper).toList();
|
||||||
|
|
||||||
|
return ImmutableList([
|
||||||
|
ImmutableMap({
|
||||||
|
group: ':pleroma',
|
||||||
|
key: ':mrf_simple',
|
||||||
|
value,
|
||||||
|
}),
|
||||||
|
]);
|
||||||
|
};
|
||||||
|
|
||||||
export const ConfigDB = {
|
export const ConfigDB = {
|
||||||
find: (configs, group, key) => {
|
find,
|
||||||
return configs.find(config =>
|
toSimplePolicy,
|
||||||
config.isSuperset({ group, key }),
|
fromSimplePolicy,
|
||||||
);
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default ConfigDB;
|
export default ConfigDB;
|
||||||
|
|
Loading…
Reference in New Issue