Merge branch 'feature/add-missing-settings' into 'develop'

Add missing settings

Closes #132

See merge request pleroma/admin-fe!151
This commit is contained in:
Angelina Filippova 2020-08-13 11:51:04 +00:00
commit 37df2725ac
16 changed files with 295 additions and 74 deletions

View file

@ -18,7 +18,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- Add ability to disable multi-factor authentication for a user - Add ability to disable multi-factor authentication for a user
- Add ability to manually evict and ban URLs from the Pleroma MediaProxy cache - Add ability to manually evict and ban URLs from the Pleroma MediaProxy cache
- Add Invalidation settings on MediaProxy tab - Add Invalidation settings on MediaProxy tab
- Ability to configure S3 settings on Upload tab - Ability to configure S3 settings on Upload tab, Pleroma.Web.ApiSpec.CastAndValidate and :modules settings on Other tab, Pools, Connections pools and Hackney pools settings on Job Queue tab, :restrict_unauthenticated settings on Authentication tab, :favicons and :welcome settings on Instance tab, :frontends settings on Frontend tab
- Show number of open reports in Sidebar Menu - Show number of open reports in Sidebar Menu
- Add confirmation message when deleting a user - Add confirmation message when deleting a user
@ -31,7 +31,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- When rendering user's profile, statuses, reports and notes check if required properties exist - When rendering user's profile, statuses, reports and notes check if required properties exist
- Remove ability to moderate users that don't have valid nickname - Remove ability to moderate users that don't have valid nickname
- Displays both labels and description in the header of group of settiings - Displays both labels and description in the header of group of settiings
- Ability to add custom values in Pleroma.Upload.Filter.Mogrify setting - Ability to add custom values in Pleroma.Upload.Filter.Mogrify setting in the following format: '{"implode", "1"}'
- Change types of the following settings: ':groups', ':replace', ':federated_timeline_removal', ':reject', ':match_actor'. Update functions that parses and wraps settings data according to this change. - Change types of the following settings: ':groups', ':replace', ':federated_timeline_removal', ':reject', ':match_actor'. Update functions that parses and wraps settings data according to this change.
- Move rendering Crontab setting from a separate component to EditableKeyword component - Move rendering Crontab setting from a separate component to EditableKeyword component
- Show only those MRF settings that have been enabled in MRF Policies setting - Show only those MRF settings that have been enabled in MRF Policies setting
@ -42,6 +42,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- Send `true` and `false` as booleans if they are values of single selects on the Settings page - Send `true` and `false` as booleans if they are values of single selects on the Settings page
- Fix sorting users on Users page if there is an acount with missing nickname or ID - Fix sorting users on Users page if there is an acount with missing nickname or ID
- Add new type of settings: `['string', 'image']`. Render Image upload Input depending on the type of setting, not its key
## [2.0.3] - 2020-04-29 ## [2.0.3] - 2020-04-29

View file

@ -50,12 +50,7 @@ export const parseNonTuples = (key, value) => {
return updated return updated
} }
if (key === ':args') { if (key === ':args') {
if (typeof value === 'string') { return typeof value === 'string' ? [value] : value
return [value]
}
const index = value.findIndex(el => typeof el === 'object' && el.tuple.includes('implode'))
const updated = value.map((el, i) => i === index ? 'implode' : el)
return updated
} }
return value return value
} }
@ -89,8 +84,8 @@ export const parseTuples = (tuples, key) => {
}, []) }, [])
} else if (item.tuple[0] === ':prune') { } else if (item.tuple[0] === ':prune') {
accum[item.tuple[0]] = item.tuple[1] === ':disabled' ? [item.tuple[1]] : item.tuple[1].tuple accum[item.tuple[0]] = item.tuple[1] === ':disabled' ? [item.tuple[1]] : item.tuple[1].tuple
} else if (item.tuple[0] === ':proxy_url') { } else if (item.tuple[0] === ':proxy_url' || item.tuple[0] === ':sender') {
accum[item.tuple[0]] = parseProxyUrl(item.tuple[1]) accum[item.tuple[0]] = parseStringOrTupleValue(item.tuple[0], item.tuple[1])
} else if (item.tuple[0] === ':args') { } else if (item.tuple[0] === ':args') {
accum[item.tuple[0]] = parseNonTuples(item.tuple[0], item.tuple[1]) accum[item.tuple[0]] = parseNonTuples(item.tuple[0], item.tuple[1])
} else if (Array.isArray(item.tuple[1]) && } else if (Array.isArray(item.tuple[1]) &&
@ -122,18 +117,29 @@ const parseObject = object => {
}, {}) }, {})
} }
const parseProxyUrl = value => { const parseStringOrTupleValue = (key, value) => {
if (value && !Array.isArray(value) && if (key === ':proxy_url') {
typeof value === 'object' && if (value && !Array.isArray(value) &&
value.tuple.length === 3 && typeof value === 'object' &&
value.tuple[0] === ':socks5') { value.tuple.length === 3 &&
const [, host, port] = value.tuple value.tuple[0] === ':socks5') {
return { socks5: true, host, port } const [, host, port] = value.tuple
} else if (typeof value === 'string') { return { socks5: true, host, port }
const [host, port] = value.split(':') } else if (typeof value === 'string') {
return { socks5: false, host, port } const [host, port] = value.split(':')
return { socks5: false, host, port }
}
return { socks5: false, host: null, port: null }
} else if (key === ':sender') {
if (typeof value === 'string') {
return { email: value }
} else if (value &&
typeof value === 'object' &&
value.tuple.length === 2) {
const [nickname, email] = value.tuple
return { nickname, email }
}
} }
return { socks5: false, host: null, port: null }
} }
const prependWithСolon = (type, value) => { const prependWithСolon = (type, value) => {
@ -248,13 +254,6 @@ const wrapValues = (settings, currentState) => {
} else if (setting === ':ip') { } else if (setting === ':ip') {
const ip = value.split('.').map(s => parseInt(s, 10)) const ip = value.split('.').map(s => parseInt(s, 10))
return { 'tuple': [setting, { 'tuple': ip }] } return { 'tuple': [setting, { 'tuple': ip }] }
} else if (setting === ':args') {
const index = value.findIndex(el => el === 'implode')
const updatedArray = value.slice()
if (index !== -1) {
updatedArray[index] = { 'tuple': ['implode', '1'] }
}
return { 'tuple': [setting, updatedArray] }
} else { } else {
return { 'tuple': [setting, value] } return { 'tuple': [setting, value] }
} }

View file

@ -11,10 +11,14 @@
<el-form :model="ldapData" :label-position="labelPosition" :label-width="labelWidth"> <el-form :model="ldapData" :label-position="labelPosition" :label-width="labelWidth">
<setting :setting-group="ldap" :data="ldapData"/> <setting :setting-group="ldap" :data="ldapData"/>
</el-form> </el-form>
<el-divider v-if="oauth2" class="divider thick-line"/> <el-divider v-if="ldap" class="divider thick-line"/>
<el-form :model="oauth2Data" :label-position="labelPosition" :label-width="labelWidth"> <el-form :model="oauth2Data" :label-position="labelPosition" :label-width="labelWidth">
<setting :setting-group="oauth2" :data="oauth2Data"/> <setting :setting-group="oauth2" :data="oauth2Data"/>
</el-form> </el-form>
<el-divider v-if="oauth2" class="divider thick-line"/>
<el-form :model="restrictUnauthenticatedData" :label-position="labelPosition" :label-width="labelWidth">
<setting :setting-group="restrictUnauthenticated" :data="restrictUnauthenticatedData"/>
</el-form>
<div class="submit-button-container"> <div class="submit-button-container">
<el-button class="submit-button" type="primary" @click="onSubmit">Submit</el-button> <el-button class="submit-button" type="primary" @click="onSubmit">Submit</el-button>
</div> </div>
@ -81,6 +85,12 @@ export default {
}, },
pleromaAuthenticatorData() { pleromaAuthenticatorData() {
return _.get(this.settings.settings, [':pleroma', 'Pleroma.Web.Auth.Authenticator']) || {} return _.get(this.settings.settings, [':pleroma', 'Pleroma.Web.Auth.Authenticator']) || {}
},
restrictUnauthenticated() {
return this.settings.description.find(setting => setting.key === ':restrict_unauthenticated')
},
restrictUnauthenticatedData() {
return _.get(this.settings.settings, [':pleroma', ':restrict_unauthenticated']) || {}
} }
}, },
methods: { methods: {

View file

@ -8,6 +8,10 @@
<setting :setting-group="staticFe" :data="staticFeData"/> <setting :setting-group="staticFe" :data="staticFeData"/>
</el-form> </el-form>
<el-divider v-if="staticFe" class="divider thick-line"/> <el-divider v-if="staticFe" class="divider thick-line"/>
<el-form :model="frontendsData" :label-position="labelPosition" :label-width="labelWidth">
<setting :setting-group="frontends" :data="frontendsData"/>
</el-form>
<el-divider v-if="frontends" class="divider thick-line"/>
<el-form :model="assetsData" :label-position="labelPosition" :label-width="labelWidth"> <el-form :model="assetsData" :label-position="labelPosition" :label-width="labelWidth">
<setting :setting-group="assets" :data="assetsData"/> <setting :setting-group="assets" :data="assetsData"/>
</el-form> </el-form>
@ -66,6 +70,12 @@ export default {
frontendData() { frontendData() {
return _.get(this.settings.settings, [':pleroma', ':frontend_configurations']) || {} return _.get(this.settings.settings, [':pleroma', ':frontend_configurations']) || {}
}, },
frontends() {
return this.settings.description.find(setting => setting.key === ':frontends')
},
frontendsData() {
return _.get(this.settings.settings, [':pleroma', ':frontends']) || {}
},
isMobile() { isMobile() {
return this.$store.state.app.device === 'mobile' return this.$store.state.app.device === 'mobile'
}, },

View file

@ -112,6 +112,7 @@
<reg-invites-input v-if="[':registrations_open', ':invites_enabled'].includes(setting.key)" :data="data" :setting-group="settingGroup" :setting="setting"/> <reg-invites-input v-if="[':registrations_open', ':invites_enabled'].includes(setting.key)" :data="data" :setting-group="settingGroup" :setting="setting"/>
<select-input-with-reduced-labels v-if="reducedSelects" :data="data" :setting-group="settingGroup" :setting="setting"/> <select-input-with-reduced-labels v-if="reducedSelects" :data="data" :setting-group="settingGroup" :setting="setting"/>
<specific-multiple-select v-if="setting.key === ':backends' || setting.key === ':args'" :data="data" :setting-group="settingGroup" :setting="setting"/> <specific-multiple-select v-if="setting.key === ':backends' || setting.key === ':args'" :data="data" :setting-group="settingGroup" :setting="setting"/>
<sender-input v-if="senderInput(setting)" :data="data[setting.key]" :setting-group="settingGroup" :setting="setting" :parents="settingParent"/>
<!--------------------> <!-------------------->
<el-tooltip v-if="canBeDeleted && isTablet" :content="$t('settings.removeFromDB')" placement="bottom-end" class="delete-setting-button-container"> <el-tooltip v-if="canBeDeleted && isTablet" :content="$t('settings.removeFromDB')" placement="bottom-end" class="delete-setting-button-container">
<el-button icon="el-icon-delete" circle size="mini" class="delete-setting-button" @click="removeSetting"/> <el-button icon="el-icon-delete" circle size="mini" class="delete-setting-button" @click="removeSetting"/>
@ -138,6 +139,7 @@ import {
RateLimitInput, RateLimitInput,
RegInvitesInput, RegInvitesInput,
SelectInputWithReducedLabels, SelectInputWithReducedLabels,
SenderInput,
SpecificMultipleSelect } from './inputComponents' SpecificMultipleSelect } from './inputComponents'
import { getBooleanValue, processNested } from '@/store/modules/normalizers' import { getBooleanValue, processNested } from '@/store/modules/normalizers'
import _ from 'lodash' import _ from 'lodash'
@ -156,6 +158,7 @@ export default {
RateLimitInput, RateLimitInput,
RegInvitesInput, RegInvitesInput,
SelectInputWithReducedLabels, SelectInputWithReducedLabels,
SenderInput,
SpecificMultipleSelect SpecificMultipleSelect
}, },
props: { props: {
@ -292,7 +295,7 @@ export default {
return this.$store.state.settings.updatedSettings return this.$store.state.settings.updatedSettings
}, },
isImageUrl() { isImageUrl() {
return [':background', ':logo', ':nsfwCensorImage', ':default_user_avatar', ':instance_thumbnail'].includes(this.setting.key) return Array.isArray(this.setting.type) && this.setting.type.includes('image')
} }
}, },
methods: { methods: {
@ -357,6 +360,9 @@ export default {
renderSingleSelect(type) { renderSingleSelect(type) {
return !this.reducedSelects && (type === 'module' || (type.includes('atom') && type.includes('dropdown'))) return !this.reducedSelects && (type === 'module' || (type.includes('atom') && type.includes('dropdown')))
}, },
senderInput({ key, type }) {
return Array.isArray(type) && type.includes('string') && type.includes('tuple') && key === ':sender'
},
update(value, group, key, parents, input, type, nested) { update(value, group, key, parents, input, type, nested) {
const updatedValue = this.renderSingleSelect(type) ? getBooleanValue(value) : value const updatedValue = this.renderSingleSelect(type) ? getBooleanValue(value) : value
nested nested

View file

@ -8,6 +8,10 @@
<setting :setting-group="adminToken" :data="adminTokenData"/> <setting :setting-group="adminToken" :data="adminTokenData"/>
</el-form> </el-form>
<el-divider v-if="adminToken" class="divider thick-line"/> <el-divider v-if="adminToken" class="divider thick-line"/>
<el-form :model="welcomeData" :label-position="labelPosition" :label-width="labelWidth">
<setting :setting-group="welcome" :data="welcomeData"/>
</el-form>
<el-divider v-if="welcome" class="divider thick-line"/>
<el-form :model="scheduledActivityData" :label-position="labelPosition" :label-width="labelWidth"> <el-form :model="scheduledActivityData" :label-position="labelPosition" :label-width="labelWidth">
<setting :setting-group="scheduledActivity" :data="scheduledActivityData"/> <setting :setting-group="scheduledActivity" :data="scheduledActivityData"/>
</el-form> </el-form>
@ -20,6 +24,10 @@
<setting :setting-group="pleromaUser" :data="pleromaUserData"/> <setting :setting-group="pleromaUser" :data="pleromaUserData"/>
</el-form> </el-form>
<el-divider v-if="pleromaUser" class="divider thick-line"/> <el-divider v-if="pleromaUser" class="divider thick-line"/>
<el-form :model="faviconsData" :label-position="labelPosition" :label-width="labelWidth">
<setting :setting-group="favicons" :data="faviconsData"/>
</el-form>
<el-divider v-if="favicons" class="divider thick-line"/>
<el-form :model="uriSchemesData" :label-position="labelPosition" :label-width="labelWidth"> <el-form :model="uriSchemesData" :label-position="labelPosition" :label-width="labelWidth">
<setting :setting-group="uriSchemes" :data="uriSchemesData"/> <setting :setting-group="uriSchemes" :data="uriSchemesData"/>
</el-form> </el-form>
@ -27,7 +35,7 @@
<el-form :model="feedData" :label-position="labelPosition" :label-width="labelWidth"> <el-form :model="feedData" :label-position="labelPosition" :label-width="labelWidth">
<setting :setting-group="feed" :data="feedData"/> <setting :setting-group="feed" :data="feedData"/>
</el-form> </el-form>
<el-divider v-if="uriSchemes" class="divider thick-line"/> <el-divider v-if="feed" class="divider thick-line"/>
<el-form :model="streamerData" :label-position="labelPosition" :label-width="labelWidth"> <el-form :model="streamerData" :label-position="labelPosition" :label-width="labelWidth">
<setting :setting-group="streamer" :data="streamerData"/> <setting :setting-group="streamer" :data="streamerData"/>
</el-form> </el-form>
@ -58,6 +66,12 @@ export default {
adminTokenData() { adminTokenData() {
return _.get(this.settings.settings, [':pleroma', ':admin_token']) || {} return _.get(this.settings.settings, [':pleroma', ':admin_token']) || {}
}, },
favicons() {
return this.settings.description.find(setting => setting.key === ':instances_favicons')
},
faviconsData() {
return _.get(this.settings.settings, [':pleroma', ':instances_favicons']) || {}
},
feed() { feed() {
return this.settings.description.find(setting => setting.key === ':feed') return this.settings.description.find(setting => setting.key === ':feed')
}, },
@ -123,6 +137,12 @@ export default {
}, },
uriSchemesData() { uriSchemesData() {
return _.get(this.settings.settings, [':pleroma', ':uri_schemes']) || {} return _.get(this.settings.settings, [':pleroma', ':uri_schemes']) || {}
},
welcome() {
return this.settings.description.find(setting => setting.key === ':welcome')
},
welcomeData() {
return _.get(this.settings.settings, [':pleroma', ':welcome']) || {}
} }
}, },
methods: { methods: {

View file

@ -11,6 +11,18 @@
<el-form :model="activityExpirationData" :label-position="labelPosition" :label-width="labelWidth"> <el-form :model="activityExpirationData" :label-position="labelPosition" :label-width="labelWidth">
<setting :setting-group="activityExpiration" :data="activityExpirationData"/> <setting :setting-group="activityExpiration" :data="activityExpirationData"/>
</el-form> </el-form>
<el-divider v-if="activityExpiration" class="divider thick-line"/>
<el-form :model="connectionsPoolsData" :label-position="labelPosition" :label-width="labelWidth">
<setting :setting-group="connectionsPools" :data="connectionsPoolsData"/>
</el-form>
<el-divider v-if="connectionsPools" class="divider thick-line"/>
<el-form :model="poolsData" :label-position="labelPosition" :label-width="labelWidth">
<setting :setting-group="pools" :data="poolsData"/>
</el-form>
<el-divider v-if="pools" class="divider thick-line"/>
<el-form :model="hackneyPoolsData" :label-position="labelPosition" :label-width="labelWidth">
<setting :setting-group="hackneyPools" :data="hackneyPoolsData"/>
</el-form>
<div class="submit-button-container"> <div class="submit-button-container">
<el-button class="submit-button" type="primary" @click="onSubmit">Submit</el-button> <el-button class="submit-button" type="primary" @click="onSubmit">Submit</el-button>
</div> </div>
@ -36,6 +48,18 @@ export default {
activityExpirationData() { activityExpirationData() {
return _.get(this.settings.settings, [':pleroma', 'Pleroma.ActivityExpiration']) || {} return _.get(this.settings.settings, [':pleroma', 'Pleroma.ActivityExpiration']) || {}
}, },
connectionsPools() {
return this.settings.description.find(setting => setting.key === ':connections_pool')
},
connectionsPoolsData() {
return _.get(this.settings.settings, [':pleroma', ':connections_pool']) || {}
},
hackneyPools() {
return this.settings.description.find(setting => setting.key === ':hackney_pools')
},
hackneyPoolsData() {
return _.get(this.settings.settings, [':pleroma', ':hackney_pools']) || {}
},
isMobile() { isMobile() {
return this.$store.state.app.device === 'mobile' return this.$store.state.app.device === 'mobile'
}, },
@ -66,6 +90,12 @@ export default {
obanQueuesData() { obanQueuesData() {
return _.get(this.settings.settings, [':pleroma', 'Oban']) || {} return _.get(this.settings.settings, [':pleroma', 'Oban']) || {}
}, },
pools() {
return this.settings.description.find(setting => setting.key === ':pools')
},
poolsData() {
return _.get(this.settings.settings, [':pleroma', ':pools']) || {}
},
workers() { workers() {
return this.settings.description.find(setting => setting.key === ':workers') return this.settings.description.find(setting => setting.key === ':workers')
}, },

View file

@ -49,9 +49,6 @@ export default {
loading() { loading() {
return this.settings.loading return this.settings.loading
}, },
modules() {
return this.settings.description.find(setting => setting.key === ':modules')
},
mrfSettings() { mrfSettings() {
return this.settings.description.filter(el => el.tab === 'mrf') return this.settings.description.filter(el => el.tab === 'mrf')
} }

View file

@ -7,6 +7,14 @@
<el-form :model="remoteIpData" :label-position="labelPosition" :label-width="labelWidth"> <el-form :model="remoteIpData" :label-position="labelPosition" :label-width="labelWidth">
<setting :setting-group="remoteIp" :data="remoteIpData"/> <setting :setting-group="remoteIp" :data="remoteIpData"/>
</el-form> </el-form>
<el-divider v-if="remoteIpData" class="divider thick-line"/>
<el-form :model="modulesData" :label-position="labelPosition" :label-width="labelWidth">
<setting :setting-group="modules" :data="modulesData"/>
</el-form>
<el-divider v-if="castAndValidate" class="divider thick-line"/>
<el-form :model="castAndValidateData" :label-position="labelPosition" :label-width="labelWidth">
<setting :setting-group="castAndValidate" :data="castAndValidateData"/>
</el-form>
<div class="submit-button-container"> <div class="submit-button-container">
<el-button class="submit-button" type="primary" @click="onSubmit">Submit</el-button> <el-button class="submit-button" type="primary" @click="onSubmit">Submit</el-button>
</div> </div>
@ -26,6 +34,12 @@ export default {
...mapGetters([ ...mapGetters([
'settings' 'settings'
]), ]),
castAndValidate() {
return this.settings.description.find(setting => setting.key === 'Pleroma.Web.ApiSpec.CastAndValidate')
},
castAndValidateData() {
return _.get(this.settings.settings, [':pleroma', 'Pleroma.Web.ApiSpec.CastAndValidate']) || {}
},
isMobile() { isMobile() {
return this.$store.state.app.device === 'mobile' return this.$store.state.app.device === 'mobile'
}, },
@ -56,6 +70,12 @@ export default {
mimeTypesData() { mimeTypesData() {
return _.get(this.settings.settings, [':mime']) || {} return _.get(this.settings.settings, [':mime']) || {}
}, },
modules() {
return this.settings.description.find(setting => setting.key === ':modules')
},
modulesData() {
return _.get(this.settings.settings, [':pleroma', ':modules']) || {}
},
remoteIp() { remoteIp() {
return this.settings.description.find(setting => setting.key === 'Pleroma.Plugs.RemoteIp') return this.settings.description.find(setting => setting.key === 'Pleroma.Plugs.RemoteIp')
}, },

View file

@ -0,0 +1,98 @@
<template>
<div :data-search="setting.key || setting.group" class="sender-input">
<el-input
:value="sender.email"
placeholder="email address"
class="email-address-input"
@input="updateSender($event, 'email')"/>
<el-input
:value="sender.nickname"
placeholder="nickname"
class="nickname-input"
@input="updateSender($event, 'nickname')"/>
</div>
</template>
<script>
import { processNested } from '@/store/modules/normalizers'
export default {
name: 'SenderInput',
props: {
data: {
type: [Object, Array],
default: function() {
return {}
}
},
parents: {
type: Array,
default: function() {
return []
},
required: false
},
setting: {
type: Object,
default: function() {
return {}
}
},
settingGroup: {
type: Object,
default: function() {
return {}
}
}
},
computed: {
isDesktop() {
return this.$store.state.app.device === 'desktop'
},
settings() {
return this.$store.state.settings.settings
},
updatedSettings() {
return this.$store.state.settings.updatedSettings
},
sender() {
return Object.keys(this.data).length === 0 ? { email: null, nickname: null } : this.data
}
},
methods: {
updateSender(value, inputType) {
let data
if (inputType === 'email') {
data = { ...this.sender, email: value }
} else {
data = { ...this.sender, nickname: value }
}
this.updateSetting(data, this.settingGroup.group, this.settingGroup.key, this.setting.key, this.setting.type)
},
updateSetting(value, group, key, input, type) {
const assembledData = value.nickname
? [value.nickname, value.email]
: value.email
if (this.parents.length > 0) {
const { valueForState,
valueForUpdatedSettings,
setting } = processNested(value, assembledData, group, key, this.parents.reverse(), this.settings, this.updatedSettings)
this.$store.dispatch('UpdateSettings',
{ group, key, input: setting.key, value: valueForUpdatedSettings, type: setting.type })
this.$store.dispatch('UpdateState',
{ group, key, input: setting.key, value: valueForState })
} else {
this.$store.dispatch('UpdateSettings', { group, key, input, value: assembledData, type })
this.$store.dispatch('UpdateState', { group, key, input, value })
}
}
}
}
</script>
<style rel='stylesheet/scss' lang='scss'>
@import '../../styles/main';
@include settings
</style>

View file

@ -20,9 +20,11 @@
allow-create allow-create
class="input" class="input"
@change="updateSetting($event, settingGroup.group, settingGroup.key, setting.key, setting.type)"> @change="updateSetting($event, settingGroup.group, settingGroup.key, setting.key, setting.type)">
<el-option value="strip" label="strip"/> <el-option value="strip"/>
<el-option value="auto-orient" label="auto-orient"/> <el-option value="auto-orient"/>
<el-option value="implode" label="implode"/> <!-- eslint-disable -->
<el-option value='{"implode", "1"}'/>
<!-- eslint-enable -->
</el-select> </el-select>
</div> </div>
</template> </template>

View file

@ -8,4 +8,5 @@ export { default as PruneInput } from './PruneInput'
export { default as RateLimitInput } from './RateLimitInput' export { default as RateLimitInput } from './RateLimitInput'
export { default as RegInvitesInput } from './RegInvitesInput' export { default as RegInvitesInput } from './RegInvitesInput'
export { default as SelectInputWithReducedLabels } from './SelectInputWithReducedLabels' export { default as SelectInputWithReducedLabels } from './SelectInputWithReducedLabels'
export { default as SenderInput } from './SenderInput'
export { default as SpecificMultipleSelect } from './SpecificMultipleSelect' export { default as SpecificMultipleSelect } from './SpecificMultipleSelect'

View file

@ -6,11 +6,7 @@ export const tabs = description => {
}, },
'authentication': { 'authentication': {
label: 'settings.auth', label: 'settings.auth',
settings: [':auth', ':ldap', ':oauth2', 'Pleroma.Web.Auth.Authenticator'] settings: [':auth', ':ldap', ':oauth2', 'Pleroma.Web.Auth.Authenticator', ':restrict_unauthenticated']
},
'auto-linker': {
label: 'settings.autoLinker',
settings: [':opts']
}, },
'esshd': { 'esshd': {
label: 'settings.esshd', label: 'settings.esshd',
@ -22,7 +18,7 @@ export const tabs = description => {
}, },
'frontend': { 'frontend': {
label: 'settings.frontend', label: 'settings.frontend',
settings: [':assets', ':chat', ':emoji', ':frontend_configurations', ':markup', ':static_fe'] settings: [':assets', ':chat', ':frontends', ':emoji', ':frontend_configurations', ':markup', ':static_fe']
}, },
'gopher': { 'gopher': {
label: 'settings.gopher', label: 'settings.gopher',
@ -34,11 +30,15 @@ export const tabs = description => {
}, },
'instance': { 'instance': {
label: 'settings.instance', label: 'settings.instance',
settings: [':admin_token', ':instance', ':manifest', 'Pleroma.User', 'Pleroma.ScheduledActivity', ':uri_schemes', ':feed', ':streamer'] settings: [':admin_token', ':instance', ':instances_favicons', ':welcome', ':manifest', 'Pleroma.User', 'Pleroma.ScheduledActivity', ':uri_schemes', ':feed', ':streamer']
}, },
'job-queue': { 'job-queue': {
label: 'settings.jobQueue', label: 'settings.jobQueue',
settings: ['Pleroma.ActivityExpiration', 'Oban', ':workers'] settings: ['Pleroma.ActivityExpiration', ':connections_pool', ':hackney_pools', 'Oban', ':pools', ':workers']
},
'link-formatter': {
label: 'settings.linkFormatter',
settings: ['Pleroma.Formatter']
}, },
'logger': { 'logger': {
label: 'settings.logger', label: 'settings.logger',
@ -78,7 +78,7 @@ export const tabs = description => {
}, },
'other': { 'other': {
label: 'settings.other', label: 'settings.other',
settings: [':mime', 'Pleroma.Plugs.RemoteIp'] settings: [':mime', 'Pleroma.Plugs.RemoteIp', ':modules', 'Pleroma.Web.ApiSpec.CastAndValidate']
} }
} }
} }

View file

@ -46,6 +46,10 @@
.el-tabs__header { .el-tabs__header {
z-index: 2002; z-index: 2002;
} }
.email-address-input {
width: 50%;
margin-right: 10px;
}
.esshd-list { .esshd-list {
margin: 0; margin: 0;
} }
@ -175,6 +179,9 @@
width: 30%; width: 30%;
margin-right: 8px margin-right: 8px
} }
.nickname-input {
width: 50%;
}
.no-top-margin { .no-top-margin {
margin-top: 0; margin-top: 0;
p { p {
@ -254,6 +261,12 @@
margin-left: 8px; margin-left: 8px;
margin-right: 10px margin-right: 10px
} }
.sender-input {
display: flex;
align-items: center;
margin-bottom: 10px;
width: 100%;
}
.scale-input { .scale-input {
width: 47%; width: 47%;
margin: 0 1% 5px 0 margin: 0 1% 5px 0

View file

@ -223,10 +223,10 @@ describe('Parse tuples', () => {
}) })
it('parses match_actor setting in mrf_subchain group', () => { it('parses match_actor setting in mrf_subchain group', () => {
const tuples = [{ tuple: [":match_actor", const tuples = [{ tuple: [':match_actor',
{ '~r/https:\/\/example.com/s': ["Elixir.Pleroma.Web.ActivityPub.MRF.DropPolicy"]}]}] { '~r/https:\/\/example.com/s': ['Elixir.Pleroma.Web.ActivityPub.MRF.DropPolicy']}]}]
const expectedResult = { ":match_actor": const expectedResult = { ':match_actor':
[{ '~r/https:\/\/example.com/s': { value: ["Elixir.Pleroma.Web.ActivityPub.MRF.DropPolicy"] }}]} [{ '~r/https:\/\/example.com/s': { value: ['Elixir.Pleroma.Web.ActivityPub.MRF.DropPolicy'] }}]}
const parsed = parseTuples(tuples, ':mrf_subchain') const parsed = parseTuples(tuples, ':mrf_subchain')
@ -241,7 +241,7 @@ describe('Parse tuples', () => {
}) })
it('parses options setting in MediaProxy.Invalidation.Http group', () => { it('parses options setting in MediaProxy.Invalidation.Http group', () => {
const tuples = [{ tuple: [":options", [{ tuple: [":params", { xxx: "zzz", aaa: "bbb" }]}]]}] const tuples = [{ tuple: [':options', [{ tuple: [':params', { xxx: 'zzz', aaa: 'bbb' }]}]]}]
const expectedResult = { ':options': { ':params': const expectedResult = { ':options': { ':params':
[ { xxx: { value: 'zzz' }}, { aaa: { value: 'bbb' }}] [ { xxx: { value: 'zzz' }}, { aaa: { value: 'bbb' }}]
}} }}
@ -260,14 +260,28 @@ describe('Parse tuples', () => {
expect(_.isEqual(expectedResult, parsed)).toBeTruthy() expect(_.isEqual(expectedResult, parsed)).toBeTruthy()
}) })
it('parses proxy_url', () => { it('parses sender setting in :welcome', () => {
const proxyUrlNull = [{ tuple: [":proxy_url", null] }] const senderEmpty = [{ tuple: [':sender', ''] }]
const proxyUrlTuple = [{ tuple: [":proxy_url", { tuple: [":socks5", ":localhost", 3090] }]}] const senderTuple = [{ tuple: [':sender', { tuple: ['test', 'test@email.com'] }]}]
const proxyUrlString = [{ tuple: [":proxy_url", 'localhost:9020'] }] const senderString = [{ tuple: [':sender', 'test@email.com'] }]
const expectedProxyUrlNull = { ":proxy_url": { socks5: false, host: null, port: null }} const expectedSenderEmpty = { ':sender': { email: '' }}
const expectedProxyUrlTuple = { ":proxy_url": { socks5: true, host: ":localhost", port: 3090 }} const expectedSenderTuple = { ':sender': { email: 'test@email.com', nickname: 'test' }}
const expectedProxyUrlString = { ":proxy_url": { socks5: false, host: 'localhost', port: '9020' }} const expectedSenderString = { ':sender': { email: 'test@email.com' }}
expect(_.isEqual(expectedSenderEmpty, parseTuples(senderEmpty, ':welcome'))).toBeTruthy()
expect(_.isEqual(expectedSenderTuple, parseTuples(senderTuple, ':welcome'))).toBeTruthy()
expect(_.isEqual(expectedSenderString, parseTuples(senderString, ':welcome'))).toBeTruthy()
})
it('parses proxy_url', () => {
const proxyUrlNull = [{ tuple: [':proxy_url', null] }]
const proxyUrlTuple = [{ tuple: [':proxy_url', { tuple: [':socks5', ':localhost', 3090] }]}]
const proxyUrlString = [{ tuple: [':proxy_url', 'localhost:9020'] }]
const expectedProxyUrlNull = { ':proxy_url': { socks5: false, host: null, port: null }}
const expectedProxyUrlTuple = { ':proxy_url': { socks5: true, host: ':localhost', port: 3090 }}
const expectedProxyUrlString = { ':proxy_url': { socks5: false, host: 'localhost', port: '9020' }}
expect(_.isEqual(expectedProxyUrlNull, parseTuples(proxyUrlNull, ':http'))).toBeTruthy() expect(_.isEqual(expectedProxyUrlNull, parseTuples(proxyUrlNull, ':http'))).toBeTruthy()
expect(_.isEqual(expectedProxyUrlTuple, parseTuples(proxyUrlTuple, ':http'))).toBeTruthy() expect(_.isEqual(expectedProxyUrlTuple, parseTuples(proxyUrlTuple, ':http'))).toBeTruthy()
@ -275,8 +289,8 @@ describe('Parse tuples', () => {
}) })
it('parses args setting in Pleroma.Upload.Filter.Mogrify', () => { it('parses args setting in Pleroma.Upload.Filter.Mogrify', () => {
const tuples = [{ tuple: [":args", ["strip", { tuple: ["implode", "1"] }]]}] const tuples = [{ tuple: [':args', ['strip', '{ "implode", "1" }']]}]
const expectedResult = { ":args": ["strip", "implode"] } const expectedResult = { ':args': ['strip', '{ "implode", "1" }'] }
const result = parseTuples(tuples, 'Pleroma.Upload.Filter.Mogrify') const result = parseTuples(tuples, 'Pleroma.Upload.Filter.Mogrify')
expect(_.isEqual(expectedResult, result)).toBeTruthy() expect(_.isEqual(expectedResult, result)).toBeTruthy()
@ -284,19 +298,19 @@ describe('Parse tuples', () => {
it('parses nested tuples', () => { it('parses nested tuples', () => {
const tuples = [{ tuple: [':proxy_opts', [ const tuples = [{ tuple: [':proxy_opts', [
{ tuple: [":redirect_on_failure", false] }, { tuple: [':redirect_on_failure', false] },
{ tuple: [":max_body_length", 26214400] }, { tuple: [':max_body_length', 26214400] },
{ tuple: [":http", [ { tuple: [':http', [
{ tuple: [":follow_redirect", true] }, { tuple: [':follow_redirect', true] },
{ tuple: [":pool", ":media"] } { tuple: [':pool', ':media'] }
]]}, ]]},
]]}] ]]}]
const expectedResult = { ':proxy_opts': { const expectedResult = { ':proxy_opts': {
":redirect_on_failure": false, ':redirect_on_failure': false,
":max_body_length": 26214400, ':max_body_length': 26214400,
":http": { ':http': {
":follow_redirect": true, ':follow_redirect': true,
":pool": ":media" ':pool': ':media'
} }
}} }}
const result = parseTuples(tuples, ':media_proxy') const result = parseTuples(tuples, ':media_proxy')
@ -304,8 +318,8 @@ describe('Parse tuples', () => {
}) })
it('parses tuples with arrays', () => { it('parses tuples with arrays', () => {
const tuples = [{ tuple: [":ignore_hosts", []]}, { tuple: [":ignore_tld", ["local", "localdomain", "lan"]]}] const tuples = [{ tuple: [':ignore_hosts', []]}, { tuple: [':ignore_tld', ['local', 'localdomain', 'lan']]}]
const expectedResult = { ":ignore_hosts": [], ":ignore_tld": ["local", "localdomain", "lan"] } const expectedResult = { ':ignore_hosts': [], ':ignore_tld': ['local', 'localdomain', 'lan'] }
const result = parseTuples(tuples, ':rich_media') const result = parseTuples(tuples, ':rich_media')
expect(_.isEqual(expectedResult, result)).toBeTruthy() expect(_.isEqual(expectedResult, result)).toBeTruthy()

View file

@ -357,14 +357,14 @@ describe('Wrap settings', () => {
it('wraps args setting in Pleroma.Upload.Filter.Mogrify group', () => { it('wraps args setting in Pleroma.Upload.Filter.Mogrify group', () => {
const settings = { 'Pleroma.Upload.Filter.Mogrify': { ':args': [ const settings = { 'Pleroma.Upload.Filter.Mogrify': { ':args': [
['string', ['list', 'string'], ['list', 'tuple']], ['string', ['list', 'string'], ['list', 'tuple']],
['strip', 'implode'] ['strip', '{ "implode", "1"]}']
]}} ]}}
const state = { ':pleroma': { 'Pleroma.Upload.Filter.Mogrify': {}}} const state = { ':pleroma': { 'Pleroma.Upload.Filter.Mogrify': {}}}
const result = wrapUpdatedSettings(':pleroma', settings, state) const result = wrapUpdatedSettings(':pleroma', settings, state)
const expectedResult = [{ const expectedResult = [{
group: ':pleroma', group: ':pleroma',
key: 'Pleroma.Upload.Filter.Mogrify', key: 'Pleroma.Upload.Filter.Mogrify',
value: [{tuple: [':args', ['strip', {tuple: ['implode', '1']}]]}] value: [{tuple: [':args', ['strip', '{ "implode", "1"]}']]}]
}] }]
expect(_.isEqual(result, expectedResult)).toBeTruthy() expect(_.isEqual(result, expectedResult)).toBeTruthy()