From 938328cd077d40b75e0834d56ff8d43ad035fd2b Mon Sep 17 00:00:00 2001 From: f0x52 Date: Thu, 29 Sep 2022 12:02:41 +0200 Subject: [frontend] Unified panels (#812) * settings panel restructuring * clean up old Gin handlers * colorscheme redesign, some other small css tweaks * basic router layout, error boundary * colorscheme redesign, some other small css tweaks * kebab-case consistency * superfluous padding on applist * remove unused consts * redux, whitespace changes.. * use .jsx extensions for components * login flow up till app registration * full redux oauth implementation, with basic error handling * split oauth api functions * oauth api revocation handling * basic profile change submission * move old dir * profile overview * fix keeping track of the wrong instance url (for different instance/api domains) * use redux state for profile form * delete old/index.js, old/basic.js, fully implemented * implement old/user/profile.js * implement password change * remove debug logging * support future api for removing files * customize profile css * remove unneeded wrapper components * restructure form fields * start on admin pages * admin panel settings * admin settings panel * remove old/admin files * add top-level redirect * refactor/cleanup forms * only do API checks on logged-in state * admin-status based routing * federation block routing * federation blocks * upgrade dependencies * react 18 changes * media cleanup * fix useEffect hooks * remove unused require * custom emoji base * emoji uploader * delete last old panel files * sidebar styling, remove unused page * refactor submit functions * fix sidebar boxshadow-border * fix old css variables * fix fake-toot avatar * fix non-square emoji * fix user settings redux keys * properly get admin account contact from instance response * Account.source default values * source.status_format key * mobile responsiveness * mobile element tweaks * proper redirect after removing block * add redirects for old setting panel urls * deletes * fix mobile overflow * clean up debug logging calls --- web/source/settings-panel/lib/api/admin.js | 192 +++++++++++++++++++++++++++++ 1 file changed, 192 insertions(+) create mode 100644 web/source/settings-panel/lib/api/admin.js (limited to 'web/source/settings-panel/lib/api/admin.js') diff --git a/web/source/settings-panel/lib/api/admin.js b/web/source/settings-panel/lib/api/admin.js new file mode 100644 index 000000000..1df47b693 --- /dev/null +++ b/web/source/settings-panel/lib/api/admin.js @@ -0,0 +1,192 @@ +/* + GoToSocial + Copyright (C) 2021-2022 GoToSocial Authors admin@gotosocial.org + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . +*/ + +"use strict"; + +const Promise = require("bluebird"); +const isValidDomain = require("is-valid-domain"); + +const instance = require("../../redux/reducers/instances").actions; +const admin = require("../../redux/reducers/admin").actions; + +module.exports = function ({ apiCall, getChanges }) { + const adminAPI = { + updateInstance: function updateInstance() { + return function (dispatch, getState) { + return Promise.try(() => { + const state = getState().instances.adminSettings; + + const update = getChanges(state, { + formKeys: ["title", "short_description", "description", "contact_account.username", "email", "terms"], + renamedKeys: {"contact_account.username": "contact_username"}, + // fileKeys: ["avatar", "header"] + }); + + return dispatch(apiCall("PATCH", "/api/v1/instance", update, "form")); + }).then((data) => { + return dispatch(instance.setInstanceInfo(data)); + }); + }; + }, + + fetchDomainBlocks: function fetchDomainBlocks() { + return function (dispatch, _getState) { + return Promise.try(() => { + return dispatch(apiCall("GET", "/api/v1/admin/domain_blocks")); + }).then((data) => { + return dispatch(admin.setBlockedInstances(data)); + }); + }; + }, + + updateDomainBlock: function updateDomainBlock(domain) { + return function (dispatch, getState) { + return Promise.try(() => { + const state = getState().admin.newInstanceBlocks[domain]; + const update = getChanges(state, { + formKeys: ["domain", "obfuscate", "public_comment", "private_comment"], + }); + + return dispatch(apiCall("POST", "/api/v1/admin/domain_blocks", update, "form")); + }).then((block) => { + return Promise.all([ + dispatch(admin.newDomainBlock([domain, block])), + dispatch(admin.setDomainBlock([domain, block])) + ]); + }); + }; + }, + + getEditableDomainBlock: function getEditableDomainBlock(domain) { + return function (dispatch, getState) { + let data = getState().admin.blockedInstances[domain]; + return dispatch(admin.newDomainBlock([domain, data])); + }; + }, + + bulkDomainBlock: function bulkDomainBlock() { + return function (dispatch, getState) { + let invalidDomains = []; + let success = 0; + + return Promise.try(() => { + const state = getState().admin.bulkBlock; + let list = state.list; + let domains; + + let fields = getChanges(state, { + formKeys: ["obfuscate", "public_comment", "private_comment"] + }); + + let defaultDate = new Date().toUTCString(); + + if (list[0] == "[") { + domains = JSON.parse(state.list); + } else { + domains = list.split("\n").map((line_) => { + let line = line_.trim(); + if (line.length == 0) { + return null; + } + + if (!isValidDomain(line, {wildcard: true, allowUnicode: true})) { + invalidDomains.push(line); + return null; + } + + return { + domain: line, + created_at: defaultDate, + ...fields + }; + }).filter((a) => a != null); + } + + if (domains.length == 0) { + return; + } + + const update = { + domains: new Blob([JSON.stringify(domains)], {type: "application/json"}) + }; + + return dispatch(apiCall("POST", "/api/v1/admin/domain_blocks?import=true", update, "form")); + }).then((blocks) => { + if (blocks != undefined) { + return Promise.each(blocks, (block) => { + success += 1; + return dispatch(admin.setDomainBlock([block.domain, block])); + }); + } + }).then(() => { + return { + success, + invalidDomains + }; + }); + }; + }, + + removeDomainBlock: function removeDomainBlock(domain) { + return function (dispatch, getState) { + return Promise.try(() => { + const id = getState().admin.blockedInstances[domain].id; + return dispatch(apiCall("DELETE", `/api/v1/admin/domain_blocks/${id}`)); + }).then((removed) => { + return dispatch(admin.removeDomainBlock(removed.domain)); + }); + }; + }, + + mediaCleanup: function mediaCleanup(days) { + return function (dispatch, _getState) { + return Promise.try(() => { + return dispatch(apiCall("POST", `/api/v1/admin/media_cleanup?remote_cache_days=${days}`)); + }); + }; + }, + + fetchCustomEmoji: function fetchCustomEmoji() { + return function (dispatch, _getState) { + return Promise.try(() => { + return dispatch(apiCall("GET", "/api/v1/custom_emojis")); + }).then((emoji) => { + return dispatch(admin.setEmoji(emoji)); + }); + }; + }, + + newEmoji: function newEmoji() { + return function (dispatch, getState) { + return Promise.try(() => { + const state = getState().admin.newEmoji; + + const update = getChanges(state, { + formKeys: ["shortcode"], + fileKeys: ["image"] + }); + + return dispatch(apiCall("POST", "/api/v1/admin/custom_emojis", update, "form")); + }).then((emoji) => { + return dispatch(admin.addEmoji(emoji)); + }); + }; + } + }; + return adminAPI; +}; \ No newline at end of file -- cgit v1.2.3