2026-01-06 16:23:17 +02:00
|
|
|
import { cloneDeep, differenceWith, flatten, get, isEqual, set } from 'lodash'
|
2026-06-09 13:11:21 +03:00
|
|
|
import { defineStore } from 'pinia'
|
2023-03-13 00:09:47 +02:00
|
|
|
|
|
|
|
|
export const defaultState = {
|
2023-03-29 00:58:07 +03:00
|
|
|
frontends: [],
|
2023-03-27 22:57:50 +03:00
|
|
|
loaded: false,
|
2023-03-13 00:09:47 +02:00
|
|
|
needsReboot: null,
|
|
|
|
|
config: null,
|
2023-03-19 21:27:07 +02:00
|
|
|
modifiedPaths: null,
|
2023-03-22 12:43:53 +02:00
|
|
|
descriptions: null,
|
2023-03-27 22:57:50 +03:00
|
|
|
draft: null,
|
2026-01-06 16:22:52 +02:00
|
|
|
dbConfigEnabled: null,
|
2023-03-13 00:09:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export const newUserFlags = {
|
2026-01-06 16:22:52 +02:00
|
|
|
...defaultState.flagStorage,
|
2023-03-13 00:09:47 +02:00
|
|
|
}
|
|
|
|
|
|
2026-06-09 13:11:21 +03:00
|
|
|
export const useAdminSettingsStore = defineStore('adminSettings', {
|
|
|
|
|
state: () => ({
|
2026-01-06 16:22:52 +02:00
|
|
|
...cloneDeep(defaultState),
|
2026-06-10 01:58:49 +03:00
|
|
|
backendInteractor: window.vuex.state.api.backendInteractor,
|
2026-06-09 13:11:21 +03:00
|
|
|
}),
|
|
|
|
|
actions: {
|
2026-06-10 01:58:49 +03:00
|
|
|
// Configuration Stuff
|
2026-06-09 13:11:21 +03:00
|
|
|
setInstanceAdminNoDbConfig() {
|
|
|
|
|
this.loaded = false
|
|
|
|
|
this.dbConfigEnabled = false
|
2023-03-27 22:57:50 +03:00
|
|
|
},
|
2026-06-09 13:11:21 +03:00
|
|
|
updateAdminSettings({ config, modifiedPaths }) {
|
|
|
|
|
this.loaded = true
|
|
|
|
|
this.dbConfigEnabled = true
|
|
|
|
|
this.config = config
|
|
|
|
|
this.modifiedPaths = modifiedPaths
|
2023-03-19 21:27:07 +02:00
|
|
|
},
|
2026-06-09 13:11:21 +03:00
|
|
|
updateAdminDescriptions({ descriptions }) {
|
|
|
|
|
this.descriptions = descriptions
|
2023-03-22 12:43:53 +02:00
|
|
|
},
|
2026-06-09 13:11:21 +03:00
|
|
|
updateAdminDraft({ path, value }) {
|
2023-03-22 12:43:53 +02:00
|
|
|
const [group, key, subkey] = path
|
|
|
|
|
const parent = [group, key, subkey]
|
|
|
|
|
|
2026-06-09 13:11:21 +03:00
|
|
|
set(this.draft, path, value)
|
2023-03-22 12:43:53 +02:00
|
|
|
|
|
|
|
|
// force-updating grouped draft to trigger refresh of group settings
|
|
|
|
|
if (path.length > parent.length) {
|
2026-06-09 13:11:21 +03:00
|
|
|
set(this.draft, parent, cloneDeep(get(this.draft, parent)))
|
2023-03-22 12:43:53 +02:00
|
|
|
}
|
|
|
|
|
},
|
2026-06-09 13:11:21 +03:00
|
|
|
resetAdminDraft() {
|
|
|
|
|
this.draft = cloneDeep(this.config)
|
2026-01-06 16:22:52 +02:00
|
|
|
},
|
2026-06-09 13:11:21 +03:00
|
|
|
|
|
|
|
|
loadAdminStuff() {
|
2026-06-10 01:58:49 +03:00
|
|
|
this.backendInteractor.fetchInstanceDBConfig().then((backendDbConfig) => {
|
|
|
|
|
if (backendDbConfig.error) {
|
|
|
|
|
if (backendDbConfig.error.status === 400) {
|
|
|
|
|
backendDbConfig.error.json().then((errorJson) => {
|
|
|
|
|
if (/configurable_from_database/.test(errorJson.error)) {
|
|
|
|
|
this.setInstanceAdminNoDbConfig()
|
|
|
|
|
}
|
|
|
|
|
})
|
2023-03-27 22:57:50 +03:00
|
|
|
}
|
2026-06-10 01:58:49 +03:00
|
|
|
} else {
|
|
|
|
|
this.setInstanceAdminSettings({ backendDbConfig })
|
|
|
|
|
}
|
|
|
|
|
})
|
2026-06-09 13:11:21 +03:00
|
|
|
if (this.descriptions === null) {
|
2026-06-10 01:58:49 +03:00
|
|
|
this.backendInteractor
|
2026-01-06 16:22:52 +02:00
|
|
|
.fetchInstanceConfigDescriptions()
|
|
|
|
|
.then((backendDescriptions) =>
|
2026-06-09 13:11:21 +03:00
|
|
|
this.setInstanceAdminDescriptions({ backendDescriptions }),
|
2026-01-06 16:22:52 +02:00
|
|
|
)
|
2023-03-27 22:57:50 +03:00
|
|
|
}
|
|
|
|
|
},
|
2026-06-09 13:11:21 +03:00
|
|
|
setInstanceAdminSettings({ backendDbConfig }) {
|
|
|
|
|
const config = this.config || {}
|
2023-03-22 18:57:23 +02:00
|
|
|
const modifiedPaths = new Set()
|
2025-12-09 13:21:46 +02:00
|
|
|
|
2026-01-06 16:22:52 +02:00
|
|
|
backendDbConfig.configs.forEach((c) => {
|
2023-03-20 23:36:47 +02:00
|
|
|
const path = [c.group, c.key]
|
2023-03-13 00:09:47 +02:00
|
|
|
if (c.db) {
|
2023-03-22 12:43:53 +02:00
|
|
|
// Path elements can contain dot, therefore we use ' -> ' as a separator instead
|
|
|
|
|
// Using strings for modified paths for easier searching
|
2026-01-06 16:22:52 +02:00
|
|
|
c.db.forEach((x) => modifiedPaths.add([...path, x].join(' -> ')))
|
2023-03-13 00:09:47 +02:00
|
|
|
}
|
2025-12-09 13:21:46 +02:00
|
|
|
|
|
|
|
|
// we need to preserve tuples on second level only, possibly third
|
|
|
|
|
// but it's not a case right now.
|
|
|
|
|
const convert = (value, preserveTuples, preserveTuplesLv2) => {
|
2023-03-13 00:09:47 +02:00
|
|
|
if (Array.isArray(value) && value.length > 0 && value[0].tuple) {
|
2025-12-09 13:21:46 +02:00
|
|
|
if (!preserveTuples) {
|
|
|
|
|
return value.reduce((acc, c) => {
|
2025-12-05 23:48:29 +01:00
|
|
|
if (c.tuple == null) {
|
|
|
|
|
return {
|
|
|
|
|
...acc,
|
|
|
|
|
[c]: c,
|
|
|
|
|
}
|
|
|
|
|
}
|
2026-01-06 16:22:52 +02:00
|
|
|
return {
|
|
|
|
|
...acc,
|
|
|
|
|
[c.tuple[0]]: convert(c.tuple[1], preserveTuplesLv2),
|
|
|
|
|
}
|
2025-12-09 13:21:46 +02:00
|
|
|
}, {})
|
|
|
|
|
} else {
|
2026-01-06 16:22:52 +02:00
|
|
|
return value.map((x) => x.tuple)
|
2025-12-09 13:21:46 +02:00
|
|
|
}
|
2023-03-13 00:09:47 +02:00
|
|
|
} else {
|
2025-12-09 13:21:46 +02:00
|
|
|
if (!preserveTuples) {
|
|
|
|
|
return value
|
|
|
|
|
} else {
|
|
|
|
|
return value.tuple
|
|
|
|
|
}
|
2023-03-13 00:09:47 +02:00
|
|
|
}
|
|
|
|
|
}
|
2025-12-09 13:21:46 +02:00
|
|
|
// for most stuff we want maps since those are more convenient
|
|
|
|
|
// however this doesn't allow for multiple values per same key
|
|
|
|
|
// so for those cases we want to preserve tuples as-is
|
|
|
|
|
// right now it's made exclusively for :pleroma.:rate_limit
|
|
|
|
|
// so it might not work properly elsewhere
|
2026-01-06 16:22:52 +02:00
|
|
|
const preserveTuples = path.find((x) => x === ':rate_limit')
|
2025-12-09 13:21:46 +02:00
|
|
|
set(config, path, convert(c.value, false, preserveTuples))
|
2023-03-13 00:09:47 +02:00
|
|
|
})
|
2025-12-08 13:50:08 +02:00
|
|
|
// patching http adapter config to be easier to handle
|
|
|
|
|
const adapter = config[':pleroma'][':http'][':adapter']
|
|
|
|
|
if (Array.isArray(adapter)) {
|
|
|
|
|
config[':pleroma'][':http'][':adapter'] = {
|
|
|
|
|
[':ssl_options']: {
|
2026-01-06 16:22:52 +02:00
|
|
|
[':versions']: [],
|
|
|
|
|
},
|
2025-12-08 13:50:08 +02:00
|
|
|
}
|
|
|
|
|
}
|
2026-06-09 13:11:21 +03:00
|
|
|
this.updateAdminSettings({ config, modifiedPaths })
|
|
|
|
|
this.resetAdminDraft()
|
2023-03-16 23:18:55 +02:00
|
|
|
},
|
2026-06-09 13:11:21 +03:00
|
|
|
setInstanceAdminDescriptions({ backendDescriptions }) {
|
2026-01-06 16:22:52 +02:00
|
|
|
const convert = (
|
|
|
|
|
{ children, description, label, key = '<ROOT>', group, suggestions },
|
|
|
|
|
path,
|
|
|
|
|
acc,
|
|
|
|
|
) => {
|
2023-03-20 23:36:47 +02:00
|
|
|
const newPath = group ? [group, key] : [key]
|
2023-03-19 21:27:07 +02:00
|
|
|
const obj = { description, label, suggestions }
|
|
|
|
|
if (Array.isArray(children)) {
|
2026-01-06 16:22:52 +02:00
|
|
|
children.forEach((c) => {
|
2023-03-20 23:36:47 +02:00
|
|
|
convert(c, newPath, obj)
|
2023-03-19 21:27:07 +02:00
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
set(acc, newPath, obj)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const descriptions = {}
|
2025-12-08 17:09:07 +02:00
|
|
|
|
2026-01-06 16:22:52 +02:00
|
|
|
backendDescriptions.forEach((d) => convert(d, '', descriptions))
|
2026-06-09 13:11:21 +03:00
|
|
|
this.updateAdminDescriptions({ descriptions })
|
2023-03-19 21:27:07 +02:00
|
|
|
},
|
2023-03-22 18:57:23 +02:00
|
|
|
|
|
|
|
|
// This action takes draft state, diffs it with live config state and then pushes
|
|
|
|
|
// only differences between the two. Difference detection only work up to subkey (third) level.
|
2026-06-09 13:11:21 +03:00
|
|
|
pushAdminDraft() {
|
2023-03-22 18:57:23 +02:00
|
|
|
// 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] }))
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Getting all group-keys used in config
|
|
|
|
|
const allGroupKeys = flatten(
|
2026-06-09 13:11:21 +03:00
|
|
|
Object.entries(this.config).map(([group, lv1data]) =>
|
2026-01-06 16:22:52 +02:00
|
|
|
Object.keys(lv1data).map((key) => ({ group, key })),
|
|
|
|
|
),
|
2023-03-22 18:57:23 +02:00
|
|
|
)
|
|
|
|
|
|
|
|
|
|
// Only using group-keys where there are changes detected
|
|
|
|
|
const changedGroupKeys = allGroupKeys.filter(({ group, key }) => {
|
2026-06-09 13:11:21 +03:00
|
|
|
return !isEqual(this.config[group][key], this.draft[group][key])
|
2023-03-22 18:57:23 +02:00
|
|
|
})
|
|
|
|
|
|
|
|
|
|
// Here we take all changed group-keys and get all changed subkeys
|
|
|
|
|
const changed = changedGroupKeys.map(({ group, key }) => {
|
2026-06-09 13:11:21 +03:00
|
|
|
const config = this.config[group][key]
|
|
|
|
|
const draft = this.draft[group][key]
|
2023-03-22 18:57:23 +02:00
|
|
|
|
|
|
|
|
// We convert group-key value into entries arrays
|
|
|
|
|
const eConfig = Object.entries(config)
|
|
|
|
|
const eDraft = Object.entries(draft)
|
|
|
|
|
|
|
|
|
|
// Then those entries array we diff so only changed subkey entries remain
|
|
|
|
|
// We use the diffed array to reconstruct the object and then shove it into convert()
|
2026-01-06 16:22:52 +02:00
|
|
|
return {
|
|
|
|
|
group,
|
|
|
|
|
key,
|
|
|
|
|
value: convert(
|
|
|
|
|
Object.fromEntries(differenceWith(eDraft, eConfig, isEqual)),
|
|
|
|
|
),
|
2023-03-22 18:57:23 +02:00
|
|
|
}
|
|
|
|
|
})
|
2026-01-06 16:22:52 +02:00
|
|
|
|
2026-06-09 13:11:21 +03:00
|
|
|
window.vuex.state.api.backendInteractor
|
2026-01-06 16:22:52 +02:00
|
|
|
.pushInstanceDBConfig({
|
|
|
|
|
payload: {
|
|
|
|
|
configs: changed,
|
|
|
|
|
},
|
|
|
|
|
})
|
2026-06-09 13:11:21 +03:00
|
|
|
.then(() =>
|
|
|
|
|
window.vuex.state.api.backendInteractor.fetchInstanceDBConfig(),
|
|
|
|
|
)
|
2026-01-06 16:22:52 +02:00
|
|
|
.then((backendDbConfig) =>
|
2026-06-09 13:11:21 +03:00
|
|
|
this.setInstanceAdminSettings({ backendDbConfig }),
|
2026-01-06 16:22:52 +02:00
|
|
|
)
|
2023-03-22 18:57:23 +02:00
|
|
|
},
|
2026-06-09 13:11:21 +03:00
|
|
|
pushAdminSetting({ path, value }) {
|
2026-01-06 16:22:52 +02:00
|
|
|
const [group, key, ...rest] = Array.isArray(path)
|
|
|
|
|
? path
|
|
|
|
|
: path.split(/\./g)
|
2023-03-16 23:18:55 +02:00
|
|
|
const clone = {} // not actually cloning the entire thing to avoid excessive writes
|
2023-03-20 23:36:47 +02:00
|
|
|
set(clone, rest, value)
|
2023-03-16 23:18:55 +02:00
|
|
|
|
|
|
|
|
// 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] }))
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-06-09 13:11:21 +03:00
|
|
|
window.vuex.state.api.backendInteractor
|
2026-01-06 16:22:52 +02:00
|
|
|
.pushInstanceDBConfig({
|
|
|
|
|
payload: {
|
|
|
|
|
configs: [
|
|
|
|
|
{
|
|
|
|
|
group,
|
|
|
|
|
key,
|
|
|
|
|
value: convert(clone),
|
|
|
|
|
},
|
|
|
|
|
],
|
|
|
|
|
},
|
|
|
|
|
})
|
2026-06-09 13:11:21 +03:00
|
|
|
.then(() =>
|
|
|
|
|
window.vuex.state.api.backendInteractor.fetchInstanceDBConfig(),
|
|
|
|
|
)
|
2026-01-06 16:22:52 +02:00
|
|
|
.then((backendDbConfig) =>
|
2026-06-09 13:11:21 +03:00
|
|
|
this.setInstanceAdminSettings({ backendDbConfig }),
|
2026-01-06 16:22:52 +02:00
|
|
|
)
|
2023-03-16 23:18:55 +02:00
|
|
|
},
|
2026-06-09 13:11:21 +03:00
|
|
|
resetAdminSetting({ path }) {
|
2026-01-06 16:22:52 +02:00
|
|
|
const [group, key, subkey] = Array.isArray(path)
|
|
|
|
|
? path
|
|
|
|
|
: path.split(/\./g)
|
2023-03-16 23:18:55 +02:00
|
|
|
|
2026-06-09 13:11:21 +03:00
|
|
|
this.modifiedPaths.delete(path)
|
2023-03-16 23:18:55 +02:00
|
|
|
|
2026-06-09 13:11:21 +03:00
|
|
|
return window.vuex.state.api.backendInteractor
|
2026-01-06 16:22:52 +02:00
|
|
|
.pushInstanceDBConfig({
|
|
|
|
|
payload: {
|
|
|
|
|
configs: [
|
|
|
|
|
{
|
|
|
|
|
group,
|
|
|
|
|
key,
|
|
|
|
|
delete: true,
|
|
|
|
|
subkeys: [subkey],
|
|
|
|
|
},
|
|
|
|
|
],
|
|
|
|
|
},
|
|
|
|
|
})
|
2026-06-09 13:11:21 +03:00
|
|
|
.then(() =>
|
|
|
|
|
window.vuex.state.api.backendInteractor.fetchInstanceDBConfig(),
|
|
|
|
|
)
|
2026-01-06 16:22:52 +02:00
|
|
|
.then((backendDbConfig) =>
|
2026-06-09 13:11:21 +03:00
|
|
|
this.setInstanceAdminSettings({ backendDbConfig }),
|
2026-01-06 16:22:52 +02:00
|
|
|
)
|
|
|
|
|
},
|
2026-06-10 01:58:49 +03:00
|
|
|
|
|
|
|
|
// Frontends Stuff
|
|
|
|
|
loadFrontendsStuff() {
|
|
|
|
|
this.backendInteractor
|
|
|
|
|
.fetchAvailableFrontends()
|
|
|
|
|
.then((frontends) => this.setAvailableFrontends({ frontends }))
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
setAvailableFrontends({ frontends }) {
|
|
|
|
|
this.frontends = frontends.map((f) => {
|
|
|
|
|
f.installedRefs = f.installed_refs
|
|
|
|
|
if (f.name === 'pleroma-fe') {
|
|
|
|
|
f.refs = ['master', 'develop']
|
|
|
|
|
} else {
|
|
|
|
|
f.refs = [f.ref]
|
|
|
|
|
}
|
|
|
|
|
return f
|
|
|
|
|
})
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
// Statuses stuff
|
|
|
|
|
listStatuses({ userId, opts }) {
|
|
|
|
|
return this.backendInteractor.adminListStatuses({
|
|
|
|
|
userId,
|
|
|
|
|
opts,
|
|
|
|
|
})
|
|
|
|
|
},
|
|
|
|
|
changeStatusScope({ opts }) {
|
|
|
|
|
return this.backendInteractor.adminChangeStatusScope({
|
|
|
|
|
opts,
|
|
|
|
|
})
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
// Users stuff
|
|
|
|
|
async fetchAdminUsers(opts) {
|
|
|
|
|
const adminData = await this.backendInteractor.adminListUsers({
|
|
|
|
|
opts,
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
adminData.users = await Promise.all(
|
|
|
|
|
adminData.users.map(
|
|
|
|
|
async (userAdminData) =>
|
|
|
|
|
await window.vuex.dispatch('updateUserAdminData', {
|
|
|
|
|
userAdminData,
|
|
|
|
|
}),
|
|
|
|
|
),
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
return adminData
|
|
|
|
|
},
|
|
|
|
|
async getUserData({ user }) {
|
|
|
|
|
const api = this.backendInteractor.adminGetUserData
|
|
|
|
|
const { screen_name } = user
|
|
|
|
|
|
|
|
|
|
const result = await api({ screen_name })
|
|
|
|
|
window.vuex.commit('updateUserAdminData', { user: result })
|
|
|
|
|
},
|
|
|
|
|
async deleteUsers({ users }) {
|
|
|
|
|
const screen_names = users.map((u) => u.screen_name)
|
|
|
|
|
const api = this.backendInteractor.adminDeleteAccounts
|
|
|
|
|
|
|
|
|
|
const resultUserIds = await api({ screen_names })
|
|
|
|
|
|
|
|
|
|
resultUserIds.forEach((userId) => {
|
|
|
|
|
window.vuex.dispatch(
|
|
|
|
|
'markStatusesAsDeleted',
|
|
|
|
|
(status) => userId === status.user.id,
|
|
|
|
|
)
|
|
|
|
|
// TODO when migrated to pinia, also remove user
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
return resultUserIds
|
|
|
|
|
},
|
|
|
|
|
resendConfirmationEmail({ users }) {
|
|
|
|
|
const screen_names = users.map((u) => u.screen_name)
|
|
|
|
|
|
|
|
|
|
return this.backendInteractor.adminResendConfirmationEmail({
|
|
|
|
|
screen_names,
|
|
|
|
|
})
|
|
|
|
|
},
|
|
|
|
|
requirePasswordChange({ users }) {
|
|
|
|
|
const screen_names = users.map((u) => u.screen_name)
|
|
|
|
|
|
|
|
|
|
return this.backendInteractor.adminRequirePasswordChange({
|
|
|
|
|
screen_names,
|
|
|
|
|
})
|
|
|
|
|
},
|
|
|
|
|
// Singular only!
|
|
|
|
|
disableMFA({ user }) {
|
|
|
|
|
return this.backendInteractor.adminDisableMFA(user)
|
|
|
|
|
},
|
|
|
|
|
async setUsersTags({ users, tags, value }) {
|
|
|
|
|
const screen_names = users.map((u) => u.screen_name)
|
|
|
|
|
const api = this.backendInteractor.adminSetUsersTags
|
|
|
|
|
|
|
|
|
|
await api({
|
|
|
|
|
screen_names,
|
|
|
|
|
tags,
|
|
|
|
|
value,
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
users.forEach((user) => {
|
|
|
|
|
this.getUserData({ user })
|
|
|
|
|
})
|
|
|
|
|
},
|
|
|
|
|
async setUsersRight({ users, right, value }) {
|
|
|
|
|
const screen_names = users.map((u) => u.screen_name)
|
|
|
|
|
const api = this.backendInteractor.adminSetUsersRight
|
|
|
|
|
|
|
|
|
|
await api({
|
|
|
|
|
screen_names,
|
|
|
|
|
right,
|
|
|
|
|
value,
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
users.forEach((user) => {
|
|
|
|
|
window.vuex.commit('updateRight', { user, right, value })
|
|
|
|
|
})
|
|
|
|
|
},
|
|
|
|
|
async setUsersActivationStatus({ users, value }) {
|
|
|
|
|
const screen_names = users.map((u) => u.screen_name)
|
|
|
|
|
const api = this.backendInteractor.adminSetUsersActivationStatus
|
|
|
|
|
|
|
|
|
|
const resultUsers = await api({
|
|
|
|
|
screen_names,
|
|
|
|
|
value,
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
resultUsers.forEach((user) => {
|
|
|
|
|
window.vuex.commit('updateUserAdminData', { user })
|
|
|
|
|
})
|
|
|
|
|
},
|
|
|
|
|
async setUsersSuggestionStatus({ users, value }) {
|
|
|
|
|
const screen_names = users.map((u) => u.screen_name)
|
|
|
|
|
const api = this.backendInteractor.adminSetUsersSuggestionStatus
|
|
|
|
|
|
|
|
|
|
const resultUsers = await api({
|
|
|
|
|
screen_names,
|
|
|
|
|
value,
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
resultUsers.forEach((user) => {
|
|
|
|
|
window.vuex.commit('updateUserAdminData', { user })
|
|
|
|
|
})
|
|
|
|
|
},
|
|
|
|
|
async setUsersConfirmationStatus({ users }) {
|
|
|
|
|
const screen_names = users.map((u) => u.screen_name)
|
|
|
|
|
const api = this.backendInteractor.adminSetUsersConfirmationStatus
|
|
|
|
|
|
|
|
|
|
await api({ screen_names })
|
|
|
|
|
|
|
|
|
|
users.forEach((user) => {
|
|
|
|
|
this.getUserData({ user })
|
|
|
|
|
})
|
|
|
|
|
},
|
|
|
|
|
async setUsersApprovalStatus({ users }) {
|
|
|
|
|
const screen_names = users.map((u) => u.screen_name)
|
|
|
|
|
const api = this.backendInteractor.adminSetUsersApprovalStatus
|
|
|
|
|
|
|
|
|
|
const resultUsers = await api({
|
|
|
|
|
screen_names,
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
resultUsers.forEach((user) => {
|
|
|
|
|
window.vuex.commit('updateUserAdminData', { user })
|
|
|
|
|
})
|
|
|
|
|
},
|
2026-01-06 16:22:52 +02:00
|
|
|
},
|
2026-06-09 13:11:21 +03:00
|
|
|
})
|