Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F85711973
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Award Token
Flag For Later
Size
18 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/src/components/settings_modal/admin_tabs/instance_tab.vue b/src/components/settings_modal/admin_tabs/instance_tab.vue
index ad27129343..ff784287cd 100644
--- a/src/components/settings_modal/admin_tabs/instance_tab.vue
+++ b/src/components/settings_modal/admin_tabs/instance_tab.vue
@@ -1,119 +1,170 @@
<template>
<div :label="$t('admin_dash.instance')">
<div class="setting-item">
<h2>{{ $t('admin_dash.instance') }}</h2>
<ul class="setting-list">
<li>
<StringSetting
source="admin"
path=":pleroma.:instance.:name"
draft-mode
>
NAME
</StringSetting>
</li>
<li>
<StringSetting
source="admin"
path=":pleroma.:instance.:email"
draft-mode
>
ADMIN EMAIL
</StringSetting>
</li>
<li>
<StringSetting
source="admin"
path=":pleroma.:instance.:description"
draft-mode
>
DESCRIPTION
</StringSetting>
</li>
<li>
<StringSetting
source="admin"
path=":pleroma.:instance.:short_description"
draft-mode
>
SHORT DESCRIPTION
</StringSetting>
</li>
<li>
<StringSetting
source="admin"
path=":pleroma.:instance.:instance_thumbnail"
draft-mode
>
INSTANCE THUMBNAIL
</StringSetting>
</li>
<li>
<StringSetting
source="admin"
path=":pleroma.:instance.:background_image"
draft-mode
>
BACKGROUND IMAGE
</StringSetting>
</li>
<li>
<BooleanSetting
source="admin"
path=":pleroma.:instance.:public"
draft-mode
>
PUBLIC
</BooleanSetting>
</li>
</ul>
</div>
<div class="setting-item">
<h2>{{ $t('admin_dash.registrations') }}</h2>
<ul class="setting-list">
<li>
<BooleanSetting
source="admin"
path=":pleroma.:instance.:registrations_open"
draft-mode
>
REGISTRATIONS OPEN
</BooleanSetting>
<ul class="setting-list suboptions">
<li>
<BooleanSetting
source="admin"
path=":pleroma.:instance.:invites_enabled"
parent-path=":pleroma.:instance.:registrations_open"
:parent-invert="true"
draft-mode
>
INVITES ENABLED
</BooleanSetting>
</li>
</ul>
</li>
<li>
<BooleanSetting
source="admin"
path=":pleroma.:instance.:account_activation_required"
draft-mode
>
ACTIVATION REQUIRED
</BooleanSetting>
</li>
<li>
<BooleanSetting
source="admin"
path=":pleroma.:instance.:account_approval_required"
draft-mode
>
APPROVAL REQUIRED
</BooleanSetting>
</li>
+ <li>
+ <h3>{{ $t('admin_dash.captcha.header') }}</h3>
+ </li>
+ <li>
+ <BooleanSetting
+ source="admin"
+ :path="[':pleroma', 'Pleroma.Captcha', ':enabled']"
+ draft-mode
+ >
+ CAPTCHA
+ </BooleanSetting>
+ <ul class="setting-list suboptions">
+ <li>
+ <ChoiceSetting
+ source="admin"
+ :path="[':pleroma', 'Pleroma.Captcha', ':method']"
+ :parent-path="[':pleroma', 'Pleroma.Captcha', ':enabled']"
+ :option-label-map="{
+ 'Pleroma.Captcha.Native': $t('admin_dash.captcha.native'),
+ 'Pleroma.Captcha.Kocaptcha': $t('admin_dash.captcha.kocaptcha')
+ }"
+ draft-mode
+ >
+ CAPTCHA TYPE
+ </ChoiceSetting>
+ <IntegerSetting
+ source="admin"
+ :path="[':pleroma', 'Pleroma.Captcha', ':seconds_valid']"
+ :parent-path="[':pleroma', 'Pleroma.Captcha', ':enabled']"
+ draft-mode
+ >
+ VALID
+ </IntegerSetting>
+ </li>
+ </ul>
+ <ul
+ v-if="adminConfig[':pleroma']['Pleroma.Captcha'][':enabled'] && adminConfig[':pleroma']['Pleroma.Captcha'][':method'] === 'Pleroma.Captcha.Kocaptcha'"
+ class="setting-list suboptions"
+ >
+ <h4>{{ $t('admin_dash.kocaptcha') }}</h4>
+ <li>
+ <StringSetting
+ source="admin"
+ :path="[':pleroma', 'Pleroma.Captcha.Kocaptcha', ':endpoint']"
+ draft-mode
+ >
+ cockAPTCHA ENDPOINT
+ </StringSetting>
+ </li>
+ </ul>
+ </li>
</ul>
</div>
</div>
</template>
<script src="./instance_tab.js"></script>
diff --git a/src/components/settings_modal/helpers/choice_setting.js b/src/components/settings_modal/helpers/choice_setting.js
index a3c3bf4432..3ff81bc904 100644
--- a/src/components/settings_modal/helpers/choice_setting.js
+++ b/src/components/settings_modal/helpers/choice_setting.js
@@ -1,17 +1,42 @@
import Select from 'src/components/select/select.vue'
import Setting from './setting.js'
export default {
...Setting,
components: {
...Setting.components,
Select
},
props: {
...Setting.props,
options: {
type: Array,
- required: true
+ required: false
+ },
+ optionLabelMap: {
+ type: Object,
+ required: false,
+ default: {}
+ }
+ },
+ computed: {
+ ...Setting.computed,
+ realOptions () {
+ if (this.source === 'admin') {
+ console.log(this.backendDescriptionSuggestions)
+ return this.backendDescriptionSuggestions.map(x => ({
+ key: x,
+ value: x,
+ label: this.optionLabelMap[x] || x
+ }))
+ }
+ return this.options
+ }
+ },
+ methods: {
+ ...Setting.methods,
+ getValue (e) {
+ return e
}
}
}
diff --git a/src/components/settings_modal/helpers/choice_setting.vue b/src/components/settings_modal/helpers/choice_setting.vue
index 4c4cdefec8..55f9a62ca9 100644
--- a/src/components/settings_modal/helpers/choice_setting.vue
+++ b/src/components/settings_modal/helpers/choice_setting.vue
@@ -1,30 +1,42 @@
<template>
<label
v-if="matchesExpertLevel"
class="ChoiceSetting"
>
- <slot />
+ <template v-if="backendDescription">
+ {{ backendDescriptionLabel }}
+ </template>
+ <template v-else>
+ <slot />
+ </template>
{{ ' ' }}
<Select
- :model-value="state"
+ :model-value="draftMode ? draft :state"
:disabled="disabled"
@update:modelValue="update"
>
<option
- v-for="option in options"
+ v-for="option in realOptions"
:key="option.key"
:value="option.value"
>
{{ option.label }}
{{ option.value === defaultState ? $t('settings.instance_default_simple') : '' }}
</option>
</Select>
<ModifiedIndicator
:changed="isChanged"
:onclick="reset"
/>
<ProfileSettingIndicator :is-profile="isProfileSetting" />
+ <DraftButtons />
+ <p
+ v-if="backendDescriptionDescription"
+ class="setting-description"
+ >
+ {{ backendDescriptionDescription + ' ' }}
+ </p>
</label>
</template>
<script src="./choice_setting.js"></script>
diff --git a/src/components/settings_modal/helpers/number_setting.vue b/src/components/settings_modal/helpers/number_setting.vue
index 813357622a..93a7a79ae8 100644
--- a/src/components/settings_modal/helpers/number_setting.vue
+++ b/src/components/settings_modal/helpers/number_setting.vue
@@ -1,27 +1,40 @@
<template>
<span
v-if="matchesExpertLevel"
class="NumberSetting"
>
<label :for="path">
- <slot />
+ <template v-if="backendDescription">
+ {{ backendDescriptionLabel + ' ' }}
+ </template>
+ <template v-else>
+ <slot />
+ </template>
</label>
<input
:id="path"
class="number-input"
type="number"
:step="step || 1"
:disabled="disabled"
:min="min || 0"
:value="draftMode ? draft :state"
@change="update"
>
{{ ' ' }}
<ModifiedIndicator
:changed="isChanged"
:onclick="reset"
/>
+ <ProfileSettingIndicator :is-profile="isProfileSetting" />
+ <DraftButtons />
+ <p
+ v-if="backendDescriptionDescription"
+ class="setting-description"
+ >
+ {{ backendDescriptionDescription + ' ' }}
+ </p>
</span>
</template>
<script src="./number_setting.js"></script>
diff --git a/src/components/settings_modal/helpers/setting.js b/src/components/settings_modal/helpers/setting.js
index 8c7074a57f..a6d35fb980 100644
--- a/src/components/settings_modal/helpers/setting.js
+++ b/src/components/settings_modal/helpers/setting.js
@@ -1,161 +1,164 @@
import Checkbox from 'src/components/checkbox/checkbox.vue'
import ModifiedIndicator from './modified_indicator.vue'
import ProfileSettingIndicator from './profile_setting_indicator.vue'
import DraftButtons from './draft_buttons.vue'
import { get, set } from 'lodash'
export default {
components: {
Checkbox,
ModifiedIndicator,
DraftButtons,
ProfileSettingIndicator
},
props: {
path: {
- type: String,
+ type: [String, Array],
required: true
},
disabled: {
type: Boolean,
default: false
},
parentPath: {
- type: String
+ type: [String, Array]
},
parentInvert: {
type: Boolean,
default: false
},
expert: {
type: [Number, String],
default: 0
},
source: {
type: String,
default: 'default'
},
draftMode: {
type: Boolean,
default: false
}
},
data () {
return {
draft: null
}
},
created () {
if (this.draftMode) {
this.draft = this.state
}
},
computed: {
state () {
const value = get(this.configSource, this.path)
if (value === undefined) {
return this.defaultState
} else {
return value
}
},
backendDescription () {
return get(this.$store.state.adminSettings.descriptions, this.path)
},
backendDescriptionLabel () {
return this.backendDescription?.label
},
backendDescriptionDescription () {
return this.backendDescription?.description
},
+ backendDescriptionSuggestions () {
+ return this.backendDescription?.suggestions
+ },
shouldBeDisabled () {
const parentValue = this.parentPath !== undefined ? get(this.configSource, this.parentPath) : null
return this.disabled || (parentValue !== null ? (this.parentInvert ? parentValue : !parentValue) : false)
},
configSource () {
switch (this.source) {
case 'profile':
return this.$store.state.profileConfig
case 'admin':
return this.$store.state.adminSettings.config
default:
return this.$store.getters.mergedConfig
}
},
configSink () {
switch (this.source) {
case 'profile':
return (k, v) => this.$store.dispatch('setProfileOption', { name: k, value: v })
case 'admin':
return (k, v) => this.$store.dispatch('pushAdminSetting', { path: k, value: v })
default:
return (k, v) => this.$store.dispatch('setOption', { name: k, value: v })
}
},
defaultState () {
switch (this.source) {
case 'profile':
return {}
default:
return get(this.$store.getters.defaultConfig, this.path)
}
},
isProfileSetting () {
return this.source === 'profile'
},
isChanged () {
switch (this.source) {
case 'profile':
case 'admin':
return false
default:
return this.state !== this.defaultState
}
},
isDirty () {
return this.draftMode && this.draft !== this.state
},
canHardReset () {
return this.source === 'admin' && this.$store.state.adminSettings.modifiedPaths.has(this.path)
},
matchesExpertLevel () {
return (this.expert || 0) <= this.$store.state.config.expertLevel > 0
}
},
methods: {
getValue (e) {
return e.target.value
},
update (e) {
if (this.draftMode) {
this.draft = this.getValue(e)
} else {
this.configSink(this.path, this.getValue(e))
}
},
commitDraft () {
if (this.draftMode) {
this.configSink(this.path, this.draft)
}
},
reset () {
console.log('reset')
if (this.draftMode) {
console.log(this.draft)
console.log(this.state)
this.draft = this.state
} else {
set(this.$store.getters.mergedConfig, this.path, this.defaultState)
}
},
hardReset () {
switch (this.source) {
case 'admin':
return this.$store.dispatch('resetAdminSetting', { path: this.path })
.then(() => { this.draft = this.state })
default:
console.warn('Hard reset not implemented yet!')
}
}
}
}
diff --git a/src/components/settings_modal/helpers/shared_computed_object.js b/src/components/settings_modal/helpers/shared_computed_object.js
index 912999ce7a..d02db542af 100644
--- a/src/components/settings_modal/helpers/shared_computed_object.js
+++ b/src/components/settings_modal/helpers/shared_computed_object.js
@@ -1,13 +1,16 @@
const SharedComputedObject = () => ({
user () {
return this.$store.state.users.currentUser
},
expertLevel () {
return this.$store.getters.mergedConfig.expertLevel > 0
},
mergedConfig () {
return this.$store.getters.mergedConfig
+ },
+ adminConfig () {
+ return this.$store.state.adminSettings.config
}
})
export default SharedComputedObject
diff --git a/src/modules/adminSettings.js b/src/modules/adminSettings.js
index 44a4d409e9..a84fadbf9e 100644
--- a/src/modules/adminSettings.js
+++ b/src/modules/adminSettings.js
@@ -1,115 +1,116 @@
import { set, cloneDeep } from 'lodash'
export const defaultState = {
needsReboot: null,
config: null,
modifiedPaths: null,
descriptions: null
}
export const newUserFlags = {
...defaultState.flagStorage
}
const adminSettingsStorage = {
state: {
...cloneDeep(defaultState)
},
mutations: {
updateAdminSettings (state, { config, modifiedPaths }) {
state.config = config
state.modifiedPaths = modifiedPaths
},
updateAdminDescriptions (state, { descriptions }) {
state.descriptions = descriptions
}
},
actions: {
setInstanceAdminSettings ({ state, commit, dispatch }, { backendDbConfig }) {
const config = state.config || {}
const modifiedPaths = state.modifiedPaths || new Set()
backendDbConfig.configs.forEach(c => {
- const path = c.group + '.' + c.key
+ const path = [c.group, c.key]
if (c.db) {
c.db.forEach(x => modifiedPaths.add(path + '.' + x))
}
const convert = (value) => {
if (Array.isArray(value) && value.length > 0 && value[0].tuple) {
return value.reduce((acc, c) => {
return { ...acc, [c.tuple[0]]: convert(c.tuple[1]) }
}, {})
} else {
return value
}
}
set(config, path, convert(c.value))
})
- console.log(config[':pleroma'][':welcome'])
+ console.log(config[':pleroma'])
commit('updateAdminSettings', { config, modifiedPaths })
},
setInstanceAdminDescriptions ({ state, commit, dispatch }, { backendDescriptions }) {
const convert = ({ children, description, label, key = '<ROOT>', group, suggestions }, path, acc) => {
- const newPath = group ? group + '.' + key : key
+ const newPath = group ? [group, key] : [key]
const obj = { description, label, suggestions }
if (Array.isArray(children)) {
children.forEach(c => {
- convert(c, '.' + newPath, obj)
+ convert(c, newPath, obj)
})
}
set(acc, newPath, obj)
}
const descriptions = {}
backendDescriptions.forEach(d => convert(d, '', descriptions))
+ console.log(descriptions[':pleroma']['Pleroma.Captcha'])
commit('updateAdminDescriptions', { descriptions })
},
pushAdminSetting ({ rootState, state, commit, dispatch }, { path, value }) {
- const [group, key, ...rest] = path.split(/\./g)
+ const [group, key, ...rest] = Array.isArray(path) ? path : path.split(/\./g)
const clone = {} // not actually cloning the entire thing to avoid excessive writes
- set(clone, rest.join('.'), value)
+ set(clone, rest, value)
// TODO cleanup paths in modifiedPaths
const convert = (value) => {
if (typeof value !== 'object') {
return value
} else if (Array.isArray(value)) {
return value.map(convert)
} else {
return Object.entries(value).map(([k, v]) => ({ tuple: [k, v] }))
}
}
rootState.api.backendInteractor.pushInstanceDBConfig({
payload: {
configs: [{
group,
key,
value: convert(clone)
}]
}
})
.then(() => rootState.api.backendInteractor.fetchInstanceDBConfig())
.then(backendDbConfig => dispatch('setInstanceAdminSettings', { backendDbConfig }))
},
resetAdminSetting ({ rootState, state, commit, dispatch }, { path }) {
const [group, key, subkey] = path.split(/\./g)
state.modifiedPaths.delete(path)
return rootState.api.backendInteractor.pushInstanceDBConfig({
payload: {
configs: [{
group,
key,
delete: true,
subkeys: [subkey]
}]
}
})
.then(() => rootState.api.backendInteractor.fetchInstanceDBConfig())
.then(backendDbConfig => dispatch('setInstanceAdminSettings', { backendDbConfig }))
}
}
}
export default adminSettingsStorage
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Sat, Sep 19, 8:24 AM (1 d, 18 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1769200
Default Alt Text
(18 KB)
Attached To
Mode
rPUFE pleroma-fe-upstream
Attached
Detach File
Event Timeline
Log In to Comment