mirror of
https://github.com/h44z/wg-portal.git
synced 2026-01-08 21:16:18 +00:00
@@ -129,6 +129,11 @@
|
|||||||
"button-add-peers": "Mehrere Peers hinzufügen",
|
"button-add-peers": "Mehrere Peers hinzufügen",
|
||||||
"button-show-peer": "Peer anzeigen",
|
"button-show-peer": "Peer anzeigen",
|
||||||
"button-edit-peer": "Peer bearbeiten",
|
"button-edit-peer": "Peer bearbeiten",
|
||||||
|
"button-bulk-delete": "Ausgewählte Peers löschen",
|
||||||
|
"button-bulk-enable": "Ausgewählte Peers aktivieren",
|
||||||
|
"button-bulk-disable": "Ausgewählte Peers deaktivieren",
|
||||||
|
"confirm-bulk-delete": "Sind Sie sicher, dass Sie {count} Peers löschen möchten?",
|
||||||
|
"confirm-bulk-disable": "Sind Sie sicher, dass Sie {count} Peers deaktivieren möchten?",
|
||||||
"peer-disabled": "Peer ist deaktiviert, Grund:",
|
"peer-disabled": "Peer ist deaktiviert, Grund:",
|
||||||
"peer-expiring": "Peer läuft ab am",
|
"peer-expiring": "Peer läuft ab am",
|
||||||
"peer-connected": "Verbunden",
|
"peer-connected": "Verbunden",
|
||||||
@@ -153,6 +158,14 @@
|
|||||||
"button-add-user": "Benutzer hinzufügen",
|
"button-add-user": "Benutzer hinzufügen",
|
||||||
"button-show-user": "Benutzer anzeigen",
|
"button-show-user": "Benutzer anzeigen",
|
||||||
"button-edit-user": "Benutzer bearbeiten",
|
"button-edit-user": "Benutzer bearbeiten",
|
||||||
|
"button-bulk-delete": "Ausgewählte Benutzer löschen",
|
||||||
|
"button-bulk-enable": "Ausgewählte Benutzer aktivieren",
|
||||||
|
"button-bulk-disable": "Ausgewählte Benutzer deaktivieren",
|
||||||
|
"button-bulk-lock": "Ausgewählte Benutzer sperren",
|
||||||
|
"button-bulk-unlock": "Ausgewählte Benutzer entsperren",
|
||||||
|
"confirm-bulk-delete": "Sind Sie sicher, dass Sie {count} Benutzer löschen möchten?",
|
||||||
|
"confirm-bulk-disable": "Sind Sie sicher, dass Sie {count} Benutzer deaktivieren möchten?",
|
||||||
|
"confirm-bulk-lock": "Sind Sie sicher, dass Sie {count} Benutzer sperren möchten?",
|
||||||
"user-disabled": "Benutzer ist deaktiviert, Grund:",
|
"user-disabled": "Benutzer ist deaktiviert, Grund:",
|
||||||
"user-locked": "Konto ist gesperrt, Grund:",
|
"user-locked": "Konto ist gesperrt, Grund:",
|
||||||
"admin": "Benutzer hat Administratorrechte",
|
"admin": "Benutzer hat Administratorrechte",
|
||||||
|
|||||||
@@ -129,6 +129,11 @@
|
|||||||
"button-add-peers": "Add Multiple Peers",
|
"button-add-peers": "Add Multiple Peers",
|
||||||
"button-show-peer": "Show Peer",
|
"button-show-peer": "Show Peer",
|
||||||
"button-edit-peer": "Edit Peer",
|
"button-edit-peer": "Edit Peer",
|
||||||
|
"button-bulk-delete": "Delete selected peers",
|
||||||
|
"button-bulk-enable": "Enable selected peers",
|
||||||
|
"button-bulk-disable": "Disable selected peers",
|
||||||
|
"confirm-bulk-delete": "Are you sure you want to delete {count} peers?",
|
||||||
|
"confirm-bulk-disable": "Are you sure you want to disable {count} peers?",
|
||||||
"peer-disabled": "Peer is disabled, reason:",
|
"peer-disabled": "Peer is disabled, reason:",
|
||||||
"peer-expiring": "Peer is expiring at",
|
"peer-expiring": "Peer is expiring at",
|
||||||
"peer-connected": "Connected",
|
"peer-connected": "Connected",
|
||||||
@@ -153,6 +158,14 @@
|
|||||||
"button-add-user": "Add User",
|
"button-add-user": "Add User",
|
||||||
"button-show-user": "Show User",
|
"button-show-user": "Show User",
|
||||||
"button-edit-user": "Edit User",
|
"button-edit-user": "Edit User",
|
||||||
|
"button-bulk-delete": "Delete selected users",
|
||||||
|
"button-bulk-enable": "Enable selected users",
|
||||||
|
"button-bulk-disable": "Disable selected users",
|
||||||
|
"button-bulk-lock": "Lock selected users",
|
||||||
|
"button-bulk-unlock": "Unlock selected users",
|
||||||
|
"confirm-bulk-delete": "Are you sure you want to delete {count} users?",
|
||||||
|
"confirm-bulk-disable": "Are you sure you want to disable {count} users?",
|
||||||
|
"confirm-bulk-lock": "Are you sure you want to lock {count} users?",
|
||||||
"user-disabled": "User is disabled, reason:",
|
"user-disabled": "User is disabled, reason:",
|
||||||
"user-locked": "Account is locked, reason:",
|
"user-locked": "Account is locked, reason:",
|
||||||
"admin": "User has administrator privileges",
|
"admin": "User has administrator privileges",
|
||||||
|
|||||||
@@ -222,6 +222,73 @@ export const peerStore = defineStore('peers', {
|
|||||||
throw new Error(error)
|
throw new Error(error)
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
async BulkDelete(ids) {
|
||||||
|
this.fetching = true
|
||||||
|
return apiWrapper.post(`${baseUrl}/bulk-delete`, { Identifiers: ids })
|
||||||
|
.then(() => {
|
||||||
|
this.peers = this.peers.filter(p => !ids.includes(p.Identifier))
|
||||||
|
this.fetching = false
|
||||||
|
notify({
|
||||||
|
title: "Peers deleted",
|
||||||
|
text: "Selected peers have been deleted!",
|
||||||
|
type: 'success',
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
this.fetching = false
|
||||||
|
console.log("Failed to delete peers: ", error)
|
||||||
|
notify({
|
||||||
|
title: "Backend Connection Failure",
|
||||||
|
text: "Failed to delete selected peers!",
|
||||||
|
type: 'error',
|
||||||
|
})
|
||||||
|
throw new Error(error)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
async BulkEnable(ids) {
|
||||||
|
this.fetching = true
|
||||||
|
return apiWrapper.post(`${baseUrl}/bulk-enable`, { Identifiers: ids })
|
||||||
|
.then(async () => {
|
||||||
|
await this.LoadPeers()
|
||||||
|
notify({
|
||||||
|
title: "Peers enabled",
|
||||||
|
text: "Selected peers have been enabled!",
|
||||||
|
type: 'success',
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
this.fetching = false
|
||||||
|
console.log("Failed to enable peers: ", error)
|
||||||
|
notify({
|
||||||
|
title: "Backend Connection Failure",
|
||||||
|
text: "Failed to enable selected peers!",
|
||||||
|
type: 'error',
|
||||||
|
})
|
||||||
|
throw new Error(error)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
async BulkDisable(ids, reason) {
|
||||||
|
this.fetching = true
|
||||||
|
return apiWrapper.post(`${baseUrl}/bulk-disable`, { Identifiers: ids, Reason: reason })
|
||||||
|
.then(async () => {
|
||||||
|
await this.LoadPeers()
|
||||||
|
notify({
|
||||||
|
title: "Peers disabled",
|
||||||
|
text: "Selected peers have been disabled!",
|
||||||
|
type: 'success',
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
this.fetching = false
|
||||||
|
console.log("Failed to disable peers: ", error)
|
||||||
|
notify({
|
||||||
|
title: "Backend Connection Failure",
|
||||||
|
text: "Failed to disable selected peers!",
|
||||||
|
type: 'error',
|
||||||
|
})
|
||||||
|
throw new Error(error)
|
||||||
|
})
|
||||||
|
},
|
||||||
async UpdatePeer(id, formData) {
|
async UpdatePeer(id, formData) {
|
||||||
this.fetching = true
|
this.fetching = true
|
||||||
return apiWrapper.put(`${baseUrl}/${base64_url_encode(id)}`, formData)
|
return apiWrapper.put(`${baseUrl}/${base64_url_encode(id)}`, formData)
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import { defineStore } from 'pinia'
|
|||||||
import {apiWrapper} from "@/helpers/fetch-wrapper";
|
import {apiWrapper} from "@/helpers/fetch-wrapper";
|
||||||
import {notify} from "@kyvg/vue3-notification";
|
import {notify} from "@kyvg/vue3-notification";
|
||||||
import {authStore} from "@/stores/auth";
|
import {authStore} from "@/stores/auth";
|
||||||
|
import {peerStore} from "@/stores/peers";
|
||||||
import { base64_url_encode } from '@/helpers/encoding';
|
import { base64_url_encode } from '@/helpers/encoding';
|
||||||
import {freshStats} from "@/helpers/models";
|
import {freshStats} from "@/helpers/models";
|
||||||
import { ipToBigInt } from '@/helpers/utils';
|
import { ipToBigInt } from '@/helpers/utils';
|
||||||
@@ -218,5 +219,18 @@ export const profileStore = defineStore('profile', {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
async BulkDelete(ids) {
|
||||||
|
this.fetching = true
|
||||||
|
const peers = peerStore()
|
||||||
|
return peers.BulkDelete(ids)
|
||||||
|
.then(() => {
|
||||||
|
this.peers = this.peers.filter(p => !ids.includes(p.Identifier))
|
||||||
|
this.fetching = false
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
this.fetching = false
|
||||||
|
throw new Error(error)
|
||||||
|
})
|
||||||
|
},
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -142,5 +142,140 @@ export const userStore = defineStore('users', {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
async BulkDelete(ids) {
|
||||||
|
this.fetching = true
|
||||||
|
return apiWrapper.post(`${baseUrl}/bulk-delete`, { Identifiers: ids })
|
||||||
|
.then(() => {
|
||||||
|
this.users = this.users.filter(u => !ids.includes(u.Identifier))
|
||||||
|
this.fetching = false
|
||||||
|
notify({
|
||||||
|
title: "Users deleted",
|
||||||
|
text: "Selected users have been deleted!",
|
||||||
|
type: 'success',
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
this.fetching = false
|
||||||
|
console.log("Failed to delete users: ", error)
|
||||||
|
notify({
|
||||||
|
title: "Backend Connection Failure",
|
||||||
|
text: "Failed to delete selected users!",
|
||||||
|
type: 'error',
|
||||||
|
})
|
||||||
|
throw new Error(error)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
async BulkEnable(ids) {
|
||||||
|
this.fetching = true
|
||||||
|
return apiWrapper.post(`${baseUrl}/bulk-enable`, { Identifiers: ids })
|
||||||
|
.then(() => {
|
||||||
|
this.users.forEach(u => {
|
||||||
|
if (ids.includes(u.Identifier)) {
|
||||||
|
u.Disabled = false
|
||||||
|
u.DisabledReason = ""
|
||||||
|
}
|
||||||
|
})
|
||||||
|
this.fetching = false
|
||||||
|
notify({
|
||||||
|
title: "Users enabled",
|
||||||
|
text: "Selected users have been enabled!",
|
||||||
|
type: 'success',
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
this.fetching = false
|
||||||
|
console.log("Failed to enable users: ", error)
|
||||||
|
notify({
|
||||||
|
title: "Backend Connection Failure",
|
||||||
|
text: "Failed to enable selected users!",
|
||||||
|
type: 'error',
|
||||||
|
})
|
||||||
|
throw new Error(error)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
async BulkDisable(ids, reason) {
|
||||||
|
this.fetching = true
|
||||||
|
return apiWrapper.post(`${baseUrl}/bulk-disable`, { Identifiers: ids, Reason: reason })
|
||||||
|
.then(() => {
|
||||||
|
this.users.forEach(u => {
|
||||||
|
if (ids.includes(u.Identifier)) {
|
||||||
|
u.Disabled = true
|
||||||
|
u.DisabledReason = reason
|
||||||
|
}
|
||||||
|
})
|
||||||
|
this.fetching = false
|
||||||
|
notify({
|
||||||
|
title: "Users disabled",
|
||||||
|
text: "Selected users have been disabled!",
|
||||||
|
type: 'success',
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
this.fetching = false
|
||||||
|
console.log("Failed to disable users: ", error)
|
||||||
|
notify({
|
||||||
|
title: "Backend Connection Failure",
|
||||||
|
text: "Failed to disable selected users!",
|
||||||
|
type: 'error',
|
||||||
|
})
|
||||||
|
throw new Error(error)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
async BulkLock(ids, reason) {
|
||||||
|
this.fetching = true
|
||||||
|
return apiWrapper.post(`${baseUrl}/bulk-lock`, { Identifiers: ids, Reason: reason })
|
||||||
|
.then(() => {
|
||||||
|
this.users.forEach(u => {
|
||||||
|
if (ids.includes(u.Identifier)) {
|
||||||
|
u.Locked = true
|
||||||
|
u.LockedReason = reason
|
||||||
|
}
|
||||||
|
})
|
||||||
|
this.fetching = false
|
||||||
|
notify({
|
||||||
|
title: "Users locked",
|
||||||
|
text: "Selected users have been locked!",
|
||||||
|
type: 'success',
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
this.fetching = false
|
||||||
|
console.log("Failed to lock users: ", error)
|
||||||
|
notify({
|
||||||
|
title: "Backend Connection Failure",
|
||||||
|
text: "Failed to lock selected users!",
|
||||||
|
type: 'error',
|
||||||
|
})
|
||||||
|
throw new Error(error)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
async BulkUnlock(ids) {
|
||||||
|
this.fetching = true
|
||||||
|
return apiWrapper.post(`${baseUrl}/bulk-unlock`, { Identifiers: ids })
|
||||||
|
.then(() => {
|
||||||
|
this.users.forEach(u => {
|
||||||
|
if (ids.includes(u.Identifier)) {
|
||||||
|
u.Locked = false
|
||||||
|
u.LockedReason = ""
|
||||||
|
}
|
||||||
|
})
|
||||||
|
this.fetching = false
|
||||||
|
notify({
|
||||||
|
title: "Users unlocked",
|
||||||
|
text: "Selected users have been unlocked!",
|
||||||
|
type: 'success',
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
this.fetching = false
|
||||||
|
console.log("Failed to unlock users: ", error)
|
||||||
|
notify({
|
||||||
|
title: "Backend Connection Failure",
|
||||||
|
text: "Failed to unlock selected users!",
|
||||||
|
type: 'error',
|
||||||
|
})
|
||||||
|
throw new Error(error)
|
||||||
|
})
|
||||||
|
},
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -29,6 +29,10 @@ const sortKey = ref("")
|
|||||||
const sortOrder = ref(1)
|
const sortOrder = ref(1)
|
||||||
const selectAll = ref(false)
|
const selectAll = ref(false)
|
||||||
|
|
||||||
|
const selectedPeers = computed(() => {
|
||||||
|
return peers.All.filter(peer => peer.IsSelected).map(peer => peer.Identifier);
|
||||||
|
})
|
||||||
|
|
||||||
function sortBy(key) {
|
function sortBy(key) {
|
||||||
if (sortKey.value === key) {
|
if (sortKey.value === key) {
|
||||||
sortOrder.value = sortOrder.value * -1; // Toggle sort order
|
sortOrder.value = sortOrder.value * -1; // Toggle sort order
|
||||||
@@ -111,6 +115,39 @@ async function saveConfig() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function bulkDelete() {
|
||||||
|
if (confirm(t('interfaces.confirm-bulk-delete', {count: selectedPeers.value.length}))) {
|
||||||
|
try {
|
||||||
|
await peers.BulkDelete(selectedPeers.value)
|
||||||
|
selectAll.value = false // reset selection
|
||||||
|
} catch (e) {
|
||||||
|
// notification is handled in store
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function bulkEnable() {
|
||||||
|
try {
|
||||||
|
await peers.BulkEnable(selectedPeers.value)
|
||||||
|
selectAll.value = false
|
||||||
|
peers.All.forEach(p => p.IsSelected = false) // remove selection
|
||||||
|
} catch (e) {
|
||||||
|
// notification is handled in store
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function bulkDisable() {
|
||||||
|
if (confirm(t('interfaces.confirm-bulk-disable', {count: selectedPeers.value.length}))) {
|
||||||
|
try {
|
||||||
|
await peers.BulkDisable(selectedPeers.value)
|
||||||
|
selectAll.value = false
|
||||||
|
peers.All.forEach(p => p.IsSelected = false) // remove selection
|
||||||
|
} catch (e) {
|
||||||
|
// notification is handled in store
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function toggleSelectAll() {
|
function toggleSelectAll() {
|
||||||
peers.FilteredAndPaged.forEach(peer => {
|
peers.FilteredAndPaged.forEach(peer => {
|
||||||
peer.IsSelected = selectAll.value;
|
peer.IsSelected = selectAll.value;
|
||||||
@@ -353,6 +390,13 @@ onMounted(async () => {
|
|||||||
<a class="btn btn-primary ms-2" href="#" :title="$t('interfaces.button-add-peer')" @click.prevent="editPeerId='#NEW#'"><i class="fa fa-plus me-1"></i><i class="fa fa-user"></i></a>
|
<a class="btn btn-primary ms-2" href="#" :title="$t('interfaces.button-add-peer')" @click.prevent="editPeerId='#NEW#'"><i class="fa fa-plus me-1"></i><i class="fa fa-user"></i></a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="row" v-if="selectedPeers.length > 0">
|
||||||
|
<div class="col-12 text-lg-end">
|
||||||
|
<a class="btn btn-outline-primary btn-sm ms-2" href="#" :title="$t('interfaces.button-bulk-enable')" @click.prevent="bulkEnable"><i class="fa-regular fa-circle-check"></i></a>
|
||||||
|
<a class="btn btn-outline-primary btn-sm ms-2" href="#" :title="$t('interfaces.button-bulk-disable')" @click.prevent="bulkDisable"><i class="fa fa-ban"></i></a>
|
||||||
|
<a class="btn btn-outline-danger btn-sm ms-2" href="#" :title="$t('interfaces.button-bulk-delete')" @click.prevent="bulkDelete"><i class="fa fa-trash-can"></i></a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div v-if="interfaces.Count!==0" class="mt-2 table-responsive">
|
<div v-if="interfaces.Count!==0" class="mt-2 table-responsive">
|
||||||
<div v-if="peers.Count===0">
|
<div v-if="peers.Count===0">
|
||||||
<h4>{{ $t('interfaces.no-peer.headline') }}</h4>
|
<h4>{{ $t('interfaces.no-peer.headline') }}</h4>
|
||||||
|
|||||||
@@ -1,14 +1,19 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import PeerViewModal from "../components/PeerViewModal.vue";
|
import PeerViewModal from "../components/PeerViewModal.vue";
|
||||||
|
|
||||||
import { onMounted, ref } from "vue";
|
import { onMounted, ref, computed } from "vue";
|
||||||
|
import { useI18n } from "vue-i18n";
|
||||||
import { profileStore } from "@/stores/profile";
|
import { profileStore } from "@/stores/profile";
|
||||||
|
import { peerStore } from "@/stores/peers";
|
||||||
import UserPeerEditModal from "@/components/UserPeerEditModal.vue";
|
import UserPeerEditModal from "@/components/UserPeerEditModal.vue";
|
||||||
import { settingsStore } from "@/stores/settings";
|
import { settingsStore } from "@/stores/settings";
|
||||||
import { humanFileSize } from "@/helpers/utils";
|
import { humanFileSize } from "@/helpers/utils";
|
||||||
|
|
||||||
const settings = settingsStore()
|
const settings = settingsStore()
|
||||||
const profile = profileStore()
|
const profile = profileStore()
|
||||||
|
const peers = peerStore()
|
||||||
|
|
||||||
|
const { t } = useI18n()
|
||||||
|
|
||||||
const viewedPeerId = ref("")
|
const viewedPeerId = ref("")
|
||||||
const editPeerId = ref("")
|
const editPeerId = ref("")
|
||||||
@@ -17,6 +22,10 @@ const sortKey = ref("")
|
|||||||
const sortOrder = ref(1)
|
const sortOrder = ref(1)
|
||||||
const selectAll = ref(false)
|
const selectAll = ref(false)
|
||||||
|
|
||||||
|
const selectedPeers = computed(() => {
|
||||||
|
return profile.Peers.filter(peer => peer.IsSelected).map(peer => peer.Identifier);
|
||||||
|
})
|
||||||
|
|
||||||
function sortBy(key) {
|
function sortBy(key) {
|
||||||
if (sortKey.value === key) {
|
if (sortKey.value === key) {
|
||||||
sortOrder.value = sortOrder.value * -1; // Toggle sort order
|
sortOrder.value = sortOrder.value * -1; // Toggle sort order
|
||||||
@@ -35,6 +44,17 @@ function friendlyInterfaceName(id, name) {
|
|||||||
return id
|
return id
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function bulkDelete() {
|
||||||
|
if (confirm(t('interfaces.confirm-bulk-delete', {count: selectedPeers.value.length}))) {
|
||||||
|
try {
|
||||||
|
await profile.BulkDelete(selectedPeers.value)
|
||||||
|
selectAll.value = false // reset selection
|
||||||
|
} catch (e) {
|
||||||
|
// notification is handled in store
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function toggleSelectAll() {
|
function toggleSelectAll() {
|
||||||
profile.FilteredAndPagedPeers.forEach(peer => {
|
profile.FilteredAndPagedPeers.forEach(peer => {
|
||||||
peer.IsSelected = selectAll.value;
|
peer.IsSelected = selectAll.value;
|
||||||
@@ -84,6 +104,13 @@ onMounted(async () => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="row" v-if="selectedPeers.length > 0">
|
||||||
|
<div class="col-12 text-lg-end">
|
||||||
|
<button class="btn btn-outline-danger btn-sm" :title="$t('interfaces.button-bulk-delete')" @click.prevent="bulkDelete">
|
||||||
|
<i class="fa fa-trash-can"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="mt-2 table-responsive">
|
<div class="mt-2 table-responsive">
|
||||||
<div v-if="profile.CountPeers === 0">
|
<div v-if="profile.CountPeers === 0">
|
||||||
<h4>{{ $t('profile.no-peer.headline') }}</h4>
|
<h4>{{ $t('profile.no-peer.headline') }}</h4>
|
||||||
|
|||||||
@@ -1,16 +1,77 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import {userStore} from "@/stores/users";
|
import {userStore} from "@/stores/users";
|
||||||
import {ref,onMounted} from "vue";
|
import {ref, onMounted, computed} from "vue";
|
||||||
import UserEditModal from "../components/UserEditModal.vue";
|
import UserEditModal from "../components/UserEditModal.vue";
|
||||||
import UserViewModal from "../components/UserViewModal.vue";
|
import UserViewModal from "../components/UserViewModal.vue";
|
||||||
|
import {useI18n} from "vue-i18n";
|
||||||
|
|
||||||
const users = userStore()
|
const users = userStore()
|
||||||
|
const { t } = useI18n()
|
||||||
|
|
||||||
const editUserId = ref("")
|
const editUserId = ref("")
|
||||||
const viewedUserId = ref("")
|
const viewedUserId = ref("")
|
||||||
|
|
||||||
const selectAll = ref(false)
|
const selectAll = ref(false)
|
||||||
|
|
||||||
|
const selectedUsers = computed(() => {
|
||||||
|
return users.All.filter(user => user.IsSelected).map(user => user.Identifier);
|
||||||
|
})
|
||||||
|
|
||||||
|
async function bulkDelete() {
|
||||||
|
if (confirm(t('users.confirm-bulk-delete', {count: selectedUsers.value.length}))) {
|
||||||
|
try {
|
||||||
|
await users.BulkDelete(selectedUsers.value)
|
||||||
|
selectAll.value = false // reset selection
|
||||||
|
} catch (e) {
|
||||||
|
// notification is handled in store
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function bulkEnable() {
|
||||||
|
try {
|
||||||
|
await users.BulkEnable(selectedUsers.value)
|
||||||
|
selectAll.value = false
|
||||||
|
users.All.forEach(u => u.IsSelected = false) // remove selection
|
||||||
|
} catch (e) {
|
||||||
|
// notification is handled in store
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function bulkDisable() {
|
||||||
|
if (confirm(t('users.confirm-bulk-disable', {count: selectedUsers.value.length}))) {
|
||||||
|
try {
|
||||||
|
await users.BulkDisable(selectedUsers.value)
|
||||||
|
selectAll.value = false
|
||||||
|
users.All.forEach(u => u.IsSelected = false) // remove selection
|
||||||
|
} catch (e) {
|
||||||
|
// notification is handled in store
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function bulkLock() {
|
||||||
|
if (confirm(t('users.confirm-bulk-lock', {count: selectedUsers.value.length}))) {
|
||||||
|
try {
|
||||||
|
await users.BulkLock(selectedUsers.value)
|
||||||
|
selectAll.value = false
|
||||||
|
users.All.forEach(u => u.IsSelected = false) // remove selection
|
||||||
|
} catch (e) {
|
||||||
|
// notification is handled in store
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function bulkUnlock() {
|
||||||
|
try {
|
||||||
|
await users.BulkUnlock(selectedUsers.value)
|
||||||
|
selectAll.value = false
|
||||||
|
users.All.forEach(u => u.IsSelected = false) // remove selection
|
||||||
|
} catch (e) {
|
||||||
|
// notification is handled in store
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function toggleSelectAll() {
|
function toggleSelectAll() {
|
||||||
users.FilteredAndPaged.forEach(user => {
|
users.FilteredAndPaged.forEach(user => {
|
||||||
user.IsSelected = selectAll.value;
|
user.IsSelected = selectAll.value;
|
||||||
@@ -45,6 +106,15 @@ onMounted(() => {
|
|||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="row" v-if="selectedUsers.length > 0">
|
||||||
|
<div class="col-12 text-lg-end">
|
||||||
|
<a class="btn btn-outline-primary btn-sm ms-2" href="#" :title="$t('users.button-bulk-enable')" @click.prevent="bulkEnable"><i class="fa-regular fa-circle-check"></i></a>
|
||||||
|
<a class="btn btn-outline-primary btn-sm ms-2" href="#" :title="$t('users.button-bulk-disable')" @click.prevent="bulkDisable"><i class="fa fa-ban"></i></a>
|
||||||
|
<a class="btn btn-outline-primary btn-sm ms-2" href="#" :title="$t('users.button-bulk-unlock')" @click.prevent="bulkUnlock"><i class="fa-solid fa-lock-open"></i></a>
|
||||||
|
<a class="btn btn-outline-primary btn-sm ms-2" href="#" :title="$t('users.button-bulk-lock')" @click.prevent="bulkLock"><i class="fa-solid fa-lock"></i></a>
|
||||||
|
<a class="btn btn-outline-danger btn-sm ms-2" href="#" :title="$t('users.button-bulk-delete')" @click.prevent="bulkDelete"><i class="fa fa-trash-can"></i></a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="mt-2 table-responsive">
|
<div class="mt-2 table-responsive">
|
||||||
<div v-if="users.Count===0">
|
<div v-if="users.Count===0">
|
||||||
<h4>{{ $t('users.no-user.headline') }}</h4>
|
<h4>{{ $t('users.no-user.headline') }}</h4>
|
||||||
|
|||||||
@@ -800,6 +800,126 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"/peer/bulk-delete": {
|
||||||
|
"post": {
|
||||||
|
"produces": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"Peer"
|
||||||
|
],
|
||||||
|
"summary": "Bulk delete selected peers.",
|
||||||
|
"operationId": "peers_handleBulkDelete",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"description": "A list of peer identifiers to delete",
|
||||||
|
"name": "request",
|
||||||
|
"in": "body",
|
||||||
|
"required": true,
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/model.BulkPeerRequest"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"204": {
|
||||||
|
"description": "No content if deletion was successful"
|
||||||
|
},
|
||||||
|
"400": {
|
||||||
|
"description": "Bad Request",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/model.Error"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"500": {
|
||||||
|
"description": "Internal Server Error",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/model.Error"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/peer/bulk-disable": {
|
||||||
|
"post": {
|
||||||
|
"produces": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"Peer"
|
||||||
|
],
|
||||||
|
"summary": "Bulk disable selected peers.",
|
||||||
|
"operationId": "peers_handleBulkDisable",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"description": "A list of peer identifiers to disable",
|
||||||
|
"name": "request",
|
||||||
|
"in": "body",
|
||||||
|
"required": true,
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/model.BulkPeerRequest"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"204": {
|
||||||
|
"description": "No content if action was successful"
|
||||||
|
},
|
||||||
|
"400": {
|
||||||
|
"description": "Bad Request",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/model.Error"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"500": {
|
||||||
|
"description": "Internal Server Error",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/model.Error"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/peer/bulk-enable": {
|
||||||
|
"post": {
|
||||||
|
"produces": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"Peer"
|
||||||
|
],
|
||||||
|
"summary": "Bulk enable selected peers.",
|
||||||
|
"operationId": "peers_handleBulkEnable",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"description": "A list of peer identifiers to enable",
|
||||||
|
"name": "request",
|
||||||
|
"in": "body",
|
||||||
|
"required": true,
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/model.BulkPeerRequest"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"204": {
|
||||||
|
"description": "No content if action was successful"
|
||||||
|
},
|
||||||
|
"400": {
|
||||||
|
"description": "Bad Request",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/model.Error"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"500": {
|
||||||
|
"description": "Internal Server Error",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/model.Error"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"/peer/config-mail": {
|
"/peer/config-mail": {
|
||||||
"post": {
|
"post": {
|
||||||
"produces": [
|
"produces": [
|
||||||
@@ -1324,6 +1444,206 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"/user/bulk-delete": {
|
||||||
|
"post": {
|
||||||
|
"produces": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"Users"
|
||||||
|
],
|
||||||
|
"summary": "Bulk delete selected users.",
|
||||||
|
"operationId": "users_handleBulkDelete",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"description": "A list of user identifiers to delete",
|
||||||
|
"name": "request",
|
||||||
|
"in": "body",
|
||||||
|
"required": true,
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/model.BulkPeerRequest"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"204": {
|
||||||
|
"description": "No content if deletion was successful"
|
||||||
|
},
|
||||||
|
"400": {
|
||||||
|
"description": "Bad Request",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/model.Error"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"500": {
|
||||||
|
"description": "Internal Server Error",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/model.Error"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/user/bulk-disable": {
|
||||||
|
"post": {
|
||||||
|
"produces": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"Users"
|
||||||
|
],
|
||||||
|
"summary": "Bulk disable selected users.",
|
||||||
|
"operationId": "users_handleBulkDisable",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"description": "A list of user identifiers to disable",
|
||||||
|
"name": "request",
|
||||||
|
"in": "body",
|
||||||
|
"required": true,
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/model.BulkPeerRequest"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"204": {
|
||||||
|
"description": "No content if action was successful"
|
||||||
|
},
|
||||||
|
"400": {
|
||||||
|
"description": "Bad Request",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/model.Error"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"500": {
|
||||||
|
"description": "Internal Server Error",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/model.Error"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/user/bulk-enable": {
|
||||||
|
"post": {
|
||||||
|
"produces": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"Users"
|
||||||
|
],
|
||||||
|
"summary": "Bulk enable selected users.",
|
||||||
|
"operationId": "users_handleBulkEnable",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"description": "A list of user identifiers to enable",
|
||||||
|
"name": "request",
|
||||||
|
"in": "body",
|
||||||
|
"required": true,
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/model.BulkPeerRequest"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"204": {
|
||||||
|
"description": "No content if action was successful"
|
||||||
|
},
|
||||||
|
"400": {
|
||||||
|
"description": "Bad Request",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/model.Error"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"500": {
|
||||||
|
"description": "Internal Server Error",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/model.Error"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/user/bulk-lock": {
|
||||||
|
"post": {
|
||||||
|
"produces": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"Users"
|
||||||
|
],
|
||||||
|
"summary": "Bulk lock selected users.",
|
||||||
|
"operationId": "users_handleBulkLock",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"description": "A list of user identifiers to lock",
|
||||||
|
"name": "request",
|
||||||
|
"in": "body",
|
||||||
|
"required": true,
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/model.BulkPeerRequest"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"204": {
|
||||||
|
"description": "No content if action was successful"
|
||||||
|
},
|
||||||
|
"400": {
|
||||||
|
"description": "Bad Request",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/model.Error"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"500": {
|
||||||
|
"description": "Internal Server Error",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/model.Error"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/user/bulk-unlock": {
|
||||||
|
"post": {
|
||||||
|
"produces": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"Users"
|
||||||
|
],
|
||||||
|
"summary": "Bulk unlock selected users.",
|
||||||
|
"operationId": "users_handleBulkUnlock",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"description": "A list of user identifiers to unlock",
|
||||||
|
"name": "request",
|
||||||
|
"in": "body",
|
||||||
|
"required": true,
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/model.BulkPeerRequest"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"204": {
|
||||||
|
"description": "No content if action was successful"
|
||||||
|
},
|
||||||
|
"400": {
|
||||||
|
"description": "Bad Request",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/model.Error"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"500": {
|
||||||
|
"description": "Internal Server Error",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/model.Error"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"/user/new": {
|
"/user/new": {
|
||||||
"post": {
|
"post": {
|
||||||
"produces": [
|
"produces": [
|
||||||
@@ -1737,6 +2057,23 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"model.BulkPeerRequest": {
|
||||||
|
"type": "object",
|
||||||
|
"required": [
|
||||||
|
"Identifiers"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"Identifiers": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Reason": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"model.ConfigOption-array_string": {
|
"model.ConfigOption-array_string": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
|
|||||||
@@ -16,6 +16,17 @@ definitions:
|
|||||||
Timestamp:
|
Timestamp:
|
||||||
type: string
|
type: string
|
||||||
type: object
|
type: object
|
||||||
|
model.BulkPeerRequest:
|
||||||
|
properties:
|
||||||
|
Identifiers:
|
||||||
|
items:
|
||||||
|
type: string
|
||||||
|
type: array
|
||||||
|
Reason:
|
||||||
|
type: string
|
||||||
|
required:
|
||||||
|
- Identifiers
|
||||||
|
type: object
|
||||||
model.ConfigOption-array_string:
|
model.ConfigOption-array_string:
|
||||||
properties:
|
properties:
|
||||||
Overridable:
|
Overridable:
|
||||||
@@ -1080,6 +1091,84 @@ paths:
|
|||||||
summary: Update the given peer record.
|
summary: Update the given peer record.
|
||||||
tags:
|
tags:
|
||||||
- Peer
|
- Peer
|
||||||
|
/peer/bulk-delete:
|
||||||
|
post:
|
||||||
|
operationId: peers_handleBulkDelete
|
||||||
|
parameters:
|
||||||
|
- description: A list of peer identifiers to delete
|
||||||
|
in: body
|
||||||
|
name: request
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/model.BulkPeerRequest'
|
||||||
|
produces:
|
||||||
|
- application/json
|
||||||
|
responses:
|
||||||
|
"204":
|
||||||
|
description: No content if deletion was successful
|
||||||
|
"400":
|
||||||
|
description: Bad Request
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/model.Error'
|
||||||
|
"500":
|
||||||
|
description: Internal Server Error
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/model.Error'
|
||||||
|
summary: Bulk delete selected peers.
|
||||||
|
tags:
|
||||||
|
- Peer
|
||||||
|
/peer/bulk-disable:
|
||||||
|
post:
|
||||||
|
operationId: peers_handleBulkDisable
|
||||||
|
parameters:
|
||||||
|
- description: A list of peer identifiers to disable
|
||||||
|
in: body
|
||||||
|
name: request
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/model.BulkPeerRequest'
|
||||||
|
produces:
|
||||||
|
- application/json
|
||||||
|
responses:
|
||||||
|
"204":
|
||||||
|
description: No content if action was successful
|
||||||
|
"400":
|
||||||
|
description: Bad Request
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/model.Error'
|
||||||
|
"500":
|
||||||
|
description: Internal Server Error
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/model.Error'
|
||||||
|
summary: Bulk disable selected peers.
|
||||||
|
tags:
|
||||||
|
- Peer
|
||||||
|
/peer/bulk-enable:
|
||||||
|
post:
|
||||||
|
operationId: peers_handleBulkEnable
|
||||||
|
parameters:
|
||||||
|
- description: A list of peer identifiers to enable
|
||||||
|
in: body
|
||||||
|
name: request
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/model.BulkPeerRequest'
|
||||||
|
produces:
|
||||||
|
- application/json
|
||||||
|
responses:
|
||||||
|
"204":
|
||||||
|
description: No content if action was successful
|
||||||
|
"400":
|
||||||
|
description: Bad Request
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/model.Error'
|
||||||
|
"500":
|
||||||
|
description: Internal Server Error
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/model.Error'
|
||||||
|
summary: Bulk enable selected peers.
|
||||||
|
tags:
|
||||||
|
- Peer
|
||||||
/peer/config-mail:
|
/peer/config-mail:
|
||||||
post:
|
post:
|
||||||
operationId: peers_handleEmailPost
|
operationId: peers_handleEmailPost
|
||||||
@@ -1571,6 +1660,136 @@ paths:
|
|||||||
summary: Get all user records.
|
summary: Get all user records.
|
||||||
tags:
|
tags:
|
||||||
- Users
|
- Users
|
||||||
|
/user/bulk-delete:
|
||||||
|
post:
|
||||||
|
operationId: users_handleBulkDelete
|
||||||
|
parameters:
|
||||||
|
- description: A list of user identifiers to delete
|
||||||
|
in: body
|
||||||
|
name: request
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/model.BulkPeerRequest'
|
||||||
|
produces:
|
||||||
|
- application/json
|
||||||
|
responses:
|
||||||
|
"204":
|
||||||
|
description: No content if deletion was successful
|
||||||
|
"400":
|
||||||
|
description: Bad Request
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/model.Error'
|
||||||
|
"500":
|
||||||
|
description: Internal Server Error
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/model.Error'
|
||||||
|
summary: Bulk delete selected users.
|
||||||
|
tags:
|
||||||
|
- Users
|
||||||
|
/user/bulk-disable:
|
||||||
|
post:
|
||||||
|
operationId: users_handleBulkDisable
|
||||||
|
parameters:
|
||||||
|
- description: A list of user identifiers to disable
|
||||||
|
in: body
|
||||||
|
name: request
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/model.BulkPeerRequest'
|
||||||
|
produces:
|
||||||
|
- application/json
|
||||||
|
responses:
|
||||||
|
"204":
|
||||||
|
description: No content if action was successful
|
||||||
|
"400":
|
||||||
|
description: Bad Request
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/model.Error'
|
||||||
|
"500":
|
||||||
|
description: Internal Server Error
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/model.Error'
|
||||||
|
summary: Bulk disable selected users.
|
||||||
|
tags:
|
||||||
|
- Users
|
||||||
|
/user/bulk-enable:
|
||||||
|
post:
|
||||||
|
operationId: users_handleBulkEnable
|
||||||
|
parameters:
|
||||||
|
- description: A list of user identifiers to enable
|
||||||
|
in: body
|
||||||
|
name: request
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/model.BulkPeerRequest'
|
||||||
|
produces:
|
||||||
|
- application/json
|
||||||
|
responses:
|
||||||
|
"204":
|
||||||
|
description: No content if action was successful
|
||||||
|
"400":
|
||||||
|
description: Bad Request
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/model.Error'
|
||||||
|
"500":
|
||||||
|
description: Internal Server Error
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/model.Error'
|
||||||
|
summary: Bulk enable selected users.
|
||||||
|
tags:
|
||||||
|
- Users
|
||||||
|
/user/bulk-lock:
|
||||||
|
post:
|
||||||
|
operationId: users_handleBulkLock
|
||||||
|
parameters:
|
||||||
|
- description: A list of user identifiers to lock
|
||||||
|
in: body
|
||||||
|
name: request
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/model.BulkPeerRequest'
|
||||||
|
produces:
|
||||||
|
- application/json
|
||||||
|
responses:
|
||||||
|
"204":
|
||||||
|
description: No content if action was successful
|
||||||
|
"400":
|
||||||
|
description: Bad Request
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/model.Error'
|
||||||
|
"500":
|
||||||
|
description: Internal Server Error
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/model.Error'
|
||||||
|
summary: Bulk lock selected users.
|
||||||
|
tags:
|
||||||
|
- Users
|
||||||
|
/user/bulk-unlock:
|
||||||
|
post:
|
||||||
|
operationId: users_handleBulkUnlock
|
||||||
|
parameters:
|
||||||
|
- description: A list of user identifiers to unlock
|
||||||
|
in: body
|
||||||
|
name: request
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/model.BulkPeerRequest'
|
||||||
|
produces:
|
||||||
|
- application/json
|
||||||
|
responses:
|
||||||
|
"204":
|
||||||
|
description: No content if action was successful
|
||||||
|
"400":
|
||||||
|
description: Bad Request
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/model.Error'
|
||||||
|
"500":
|
||||||
|
description: Internal Server Error
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/model.Error'
|
||||||
|
summary: Bulk unlock selected users.
|
||||||
|
tags:
|
||||||
|
- Users
|
||||||
/user/new:
|
/user/new:
|
||||||
post:
|
post:
|
||||||
operationId: users_handleCreatePost
|
operationId: users_handleCreatePost
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package backend
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
"github.com/h44z/wg-portal/internal/config"
|
"github.com/h44z/wg-portal/internal/config"
|
||||||
@@ -118,3 +119,30 @@ func (p PeerService) SendPeerEmail(
|
|||||||
func (p PeerService) GetPeerStats(ctx context.Context, id domain.InterfaceIdentifier) ([]domain.PeerStatus, error) {
|
func (p PeerService) GetPeerStats(ctx context.Context, id domain.InterfaceIdentifier) ([]domain.PeerStatus, error) {
|
||||||
return p.peers.GetPeerStats(ctx, id)
|
return p.peers.GetPeerStats(ctx, id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p PeerService) BulkDelete(ctx context.Context, ids []domain.PeerIdentifier) error {
|
||||||
|
for _, id := range ids {
|
||||||
|
if err := p.peers.DeletePeer(ctx, id); err != nil {
|
||||||
|
return fmt.Errorf("failed to delete peer %s: %w", id, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p PeerService) BulkUpdate(ctx context.Context, ids []domain.PeerIdentifier, updateFn func(*domain.Peer)) error {
|
||||||
|
for _, id := range ids {
|
||||||
|
peer, err := p.peers.GetPeer(ctx, id)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to get peer %s: %w", id, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
updateFn(peer)
|
||||||
|
|
||||||
|
if _, err := p.peers.UpdatePeer(ctx, peer); err != nil {
|
||||||
|
return fmt.Errorf("failed to update peer %s: %w", id, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -72,7 +72,11 @@ func (u UserService) DeactivateApi(ctx context.Context, id domain.UserIdentifier
|
|||||||
return u.users.DeactivateApi(ctx, id)
|
return u.users.DeactivateApi(ctx, id)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u UserService) ChangePassword(ctx context.Context, id domain.UserIdentifier, oldPassword, newPassword string) (*domain.User, error) {
|
func (u UserService) ChangePassword(
|
||||||
|
ctx context.Context,
|
||||||
|
id domain.UserIdentifier,
|
||||||
|
oldPassword, newPassword string,
|
||||||
|
) (*domain.User, error) {
|
||||||
oldPassword = strings.TrimSpace(oldPassword)
|
oldPassword = strings.TrimSpace(oldPassword)
|
||||||
newPassword = strings.TrimSpace(newPassword)
|
newPassword = strings.TrimSpace(newPassword)
|
||||||
|
|
||||||
@@ -121,3 +125,30 @@ func (u UserService) GetUserPeerStats(ctx context.Context, id domain.UserIdentif
|
|||||||
func (u UserService) GetUserInterfaces(ctx context.Context, id domain.UserIdentifier) ([]domain.Interface, error) {
|
func (u UserService) GetUserInterfaces(ctx context.Context, id domain.UserIdentifier) ([]domain.Interface, error) {
|
||||||
return u.wg.GetUserInterfaces(ctx, id)
|
return u.wg.GetUserInterfaces(ctx, id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (u UserService) BulkDelete(ctx context.Context, ids []domain.UserIdentifier) error {
|
||||||
|
for _, id := range ids {
|
||||||
|
if err := u.users.DeleteUser(ctx, id); err != nil {
|
||||||
|
return fmt.Errorf("failed to delete user %s: %w", id, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u UserService) BulkUpdate(ctx context.Context, ids []domain.UserIdentifier, updateFn func(*domain.User)) error {
|
||||||
|
for _, id := range ids {
|
||||||
|
user, err := u.users.GetUser(ctx, id)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to get user %s: %w", id, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
updateFn(user)
|
||||||
|
|
||||||
|
if _, err := u.users.UpdateUser(ctx, user); err != nil {
|
||||||
|
return fmt.Errorf("failed to update user %s: %w", id, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/go-pkgz/routegroup"
|
"github.com/go-pkgz/routegroup"
|
||||||
|
|
||||||
@@ -41,6 +42,10 @@ type PeerService interface {
|
|||||||
SendPeerEmail(ctx context.Context, linkOnly bool, style string, peers ...domain.PeerIdentifier) error
|
SendPeerEmail(ctx context.Context, linkOnly bool, style string, peers ...domain.PeerIdentifier) error
|
||||||
// GetPeerStats returns the peer stats for the given interface.
|
// GetPeerStats returns the peer stats for the given interface.
|
||||||
GetPeerStats(ctx context.Context, id domain.InterfaceIdentifier) ([]domain.PeerStatus, error)
|
GetPeerStats(ctx context.Context, id domain.InterfaceIdentifier) ([]domain.PeerStatus, error)
|
||||||
|
// BulkDelete deletes multiple peers.
|
||||||
|
BulkDelete(context.Context, []domain.PeerIdentifier) error
|
||||||
|
// BulkUpdate modifies multiple peers.
|
||||||
|
BulkUpdate(context.Context, []domain.PeerIdentifier, func(*domain.Peer)) error
|
||||||
}
|
}
|
||||||
|
|
||||||
type PeerEndpoint struct {
|
type PeerEndpoint struct {
|
||||||
@@ -84,6 +89,9 @@ func (e PeerEndpoint) RegisterRoutes(g *routegroup.Bundle) {
|
|||||||
apiGroup.HandleFunc("GET /{id}", e.handleSingleGet())
|
apiGroup.HandleFunc("GET /{id}", e.handleSingleGet())
|
||||||
apiGroup.HandleFunc("PUT /{id}", e.handleUpdatePut())
|
apiGroup.HandleFunc("PUT /{id}", e.handleUpdatePut())
|
||||||
apiGroup.HandleFunc("DELETE /{id}", e.handleDelete())
|
apiGroup.HandleFunc("DELETE /{id}", e.handleDelete())
|
||||||
|
apiGroup.HandleFunc("POST /bulk-delete", e.handleBulkDelete())
|
||||||
|
apiGroup.HandleFunc("POST /bulk-enable", e.handleBulkEnable())
|
||||||
|
apiGroup.HandleFunc("POST /bulk-disable", e.handleBulkDisable())
|
||||||
}
|
}
|
||||||
|
|
||||||
// handleAllGet returns a gorm Handler function.
|
// handleAllGet returns a gorm Handler function.
|
||||||
@@ -521,3 +529,114 @@ func (e PeerEndpoint) getConfigStyle(r *http.Request) string {
|
|||||||
}
|
}
|
||||||
return configStyle
|
return configStyle
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// handleBulkDelete returns a gorm Handler function.
|
||||||
|
//
|
||||||
|
// @ID peers_handleBulkDelete
|
||||||
|
// @Tags Peer
|
||||||
|
// @Summary Bulk delete selected peers.
|
||||||
|
// @Produce json
|
||||||
|
// @Param request body model.BulkPeerRequest true "A list of peer identifiers to delete"
|
||||||
|
// @Success 204 "No content if deletion was successful"
|
||||||
|
// @Failure 400 {object} model.Error
|
||||||
|
// @Failure 500 {object} model.Error
|
||||||
|
// @Router /peer/bulk-delete [post]
|
||||||
|
func (e PeerEndpoint) handleBulkDelete() http.HandlerFunc {
|
||||||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
var req model.BulkPeerRequest
|
||||||
|
if err := request.BodyJson(r, &req); err != nil {
|
||||||
|
respond.JSON(w, http.StatusBadRequest, model.Error{Code: http.StatusBadRequest, Message: err.Error()})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
ids := make([]domain.PeerIdentifier, len(req.Identifiers))
|
||||||
|
for i, id := range req.Identifiers {
|
||||||
|
ids[i] = domain.PeerIdentifier(id)
|
||||||
|
}
|
||||||
|
|
||||||
|
err := e.peerService.BulkDelete(r.Context(), ids)
|
||||||
|
if err != nil {
|
||||||
|
respond.JSON(w, http.StatusInternalServerError,
|
||||||
|
model.Error{Code: http.StatusInternalServerError, Message: err.Error()})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
respond.Status(w, http.StatusNoContent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// handleBulkEnable returns a gorm Handler function.
|
||||||
|
//
|
||||||
|
// @ID peers_handleBulkEnable
|
||||||
|
// @Tags Peer
|
||||||
|
// @Summary Bulk enable selected peers.
|
||||||
|
// @Produce json
|
||||||
|
// @Param request body model.BulkPeerRequest true "A list of peer identifiers to enable"
|
||||||
|
// @Success 204 "No content if action was successful"
|
||||||
|
// @Failure 400 {object} model.Error
|
||||||
|
// @Failure 500 {object} model.Error
|
||||||
|
// @Router /peer/bulk-enable [post]
|
||||||
|
func (e PeerEndpoint) handleBulkEnable() http.HandlerFunc {
|
||||||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
var req model.BulkPeerRequest
|
||||||
|
if err := request.BodyJson(r, &req); err != nil {
|
||||||
|
respond.JSON(w, http.StatusBadRequest, model.Error{Code: http.StatusBadRequest, Message: err.Error()})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
ids := make([]domain.PeerIdentifier, len(req.Identifiers))
|
||||||
|
for i, id := range req.Identifiers {
|
||||||
|
ids[i] = domain.PeerIdentifier(id)
|
||||||
|
}
|
||||||
|
|
||||||
|
err := e.peerService.BulkUpdate(r.Context(), ids, func(p *domain.Peer) {
|
||||||
|
p.Disabled = nil
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
respond.JSON(w, http.StatusInternalServerError,
|
||||||
|
model.Error{Code: http.StatusInternalServerError, Message: err.Error()})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
respond.Status(w, http.StatusNoContent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// handleBulkDisable returns a gorm Handler function.
|
||||||
|
//
|
||||||
|
// @ID peers_handleBulkDisable
|
||||||
|
// @Tags Peer
|
||||||
|
// @Summary Bulk disable selected peers.
|
||||||
|
// @Produce json
|
||||||
|
// @Param request body model.BulkPeerRequest true "A list of peer identifiers to disable"
|
||||||
|
// @Success 204 "No content if action was successful"
|
||||||
|
// @Failure 400 {object} model.Error
|
||||||
|
// @Failure 500 {object} model.Error
|
||||||
|
// @Router /peer/bulk-disable [post]
|
||||||
|
func (e PeerEndpoint) handleBulkDisable() http.HandlerFunc {
|
||||||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
var req model.BulkPeerRequest
|
||||||
|
if err := request.BodyJson(r, &req); err != nil {
|
||||||
|
respond.JSON(w, http.StatusBadRequest, model.Error{Code: http.StatusBadRequest, Message: err.Error()})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
ids := make([]domain.PeerIdentifier, len(req.Identifiers))
|
||||||
|
for i, id := range req.Identifiers {
|
||||||
|
ids[i] = domain.PeerIdentifier(id)
|
||||||
|
}
|
||||||
|
|
||||||
|
now := time.Now()
|
||||||
|
err := e.peerService.BulkUpdate(r.Context(), ids, func(p *domain.Peer) {
|
||||||
|
p.Disabled = &now
|
||||||
|
p.DisabledReason = domain.DisabledReasonAdmin
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
respond.JSON(w, http.StatusInternalServerError,
|
||||||
|
model.Error{Code: http.StatusInternalServerError, Message: err.Error()})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
respond.Status(w, http.StatusNoContent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package handlers
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/go-pkgz/routegroup"
|
"github.com/go-pkgz/routegroup"
|
||||||
|
|
||||||
@@ -36,6 +37,10 @@ type UserService interface {
|
|||||||
GetUserPeerStats(ctx context.Context, id domain.UserIdentifier) ([]domain.PeerStatus, error)
|
GetUserPeerStats(ctx context.Context, id domain.UserIdentifier) ([]domain.PeerStatus, error)
|
||||||
// GetUserInterfaces returns all interfaces for the given user.
|
// GetUserInterfaces returns all interfaces for the given user.
|
||||||
GetUserInterfaces(ctx context.Context, id domain.UserIdentifier) ([]domain.Interface, error)
|
GetUserInterfaces(ctx context.Context, id domain.UserIdentifier) ([]domain.Interface, error)
|
||||||
|
// BulkDelete deletes multiple users.
|
||||||
|
BulkDelete(ctx context.Context, ids []domain.UserIdentifier) error
|
||||||
|
// BulkUpdate modifies multiple users.
|
||||||
|
BulkUpdate(ctx context.Context, ids []domain.UserIdentifier, updateFn func(*domain.User)) error
|
||||||
}
|
}
|
||||||
|
|
||||||
type UserEndpoint struct {
|
type UserEndpoint struct {
|
||||||
@@ -77,7 +82,13 @@ func (e UserEndpoint) RegisterRoutes(g *routegroup.Bundle) {
|
|||||||
apiGroup.With(e.authenticator.UserIdMatch("id")).HandleFunc("GET /{id}/interfaces", e.handleInterfacesGet())
|
apiGroup.With(e.authenticator.UserIdMatch("id")).HandleFunc("GET /{id}/interfaces", e.handleInterfacesGet())
|
||||||
apiGroup.With(e.authenticator.UserIdMatch("id")).HandleFunc("POST /{id}/api/enable", e.handleApiEnablePost())
|
apiGroup.With(e.authenticator.UserIdMatch("id")).HandleFunc("POST /{id}/api/enable", e.handleApiEnablePost())
|
||||||
apiGroup.With(e.authenticator.UserIdMatch("id")).HandleFunc("POST /{id}/api/disable", e.handleApiDisablePost())
|
apiGroup.With(e.authenticator.UserIdMatch("id")).HandleFunc("POST /{id}/api/disable", e.handleApiDisablePost())
|
||||||
apiGroup.With(e.authenticator.UserIdMatch("id")).HandleFunc("POST /{id}/change-password", e.handleChangePasswordPost())
|
apiGroup.With(e.authenticator.UserIdMatch("id")).HandleFunc("POST /{id}/change-password",
|
||||||
|
e.handleChangePasswordPost())
|
||||||
|
apiGroup.With(e.authenticator.LoggedIn(ScopeAdmin)).HandleFunc("POST /bulk-delete", e.handleBulkDelete())
|
||||||
|
apiGroup.With(e.authenticator.LoggedIn(ScopeAdmin)).HandleFunc("POST /bulk-enable", e.handleBulkEnable())
|
||||||
|
apiGroup.With(e.authenticator.LoggedIn(ScopeAdmin)).HandleFunc("POST /bulk-disable", e.handleBulkDisable())
|
||||||
|
apiGroup.With(e.authenticator.LoggedIn(ScopeAdmin)).HandleFunc("POST /bulk-lock", e.handleBulkLock())
|
||||||
|
apiGroup.With(e.authenticator.LoggedIn(ScopeAdmin)).HandleFunc("POST /bulk-unlock", e.handleBulkUnlock())
|
||||||
}
|
}
|
||||||
|
|
||||||
// handleAllGet returns a gorm Handler function.
|
// handleAllGet returns a gorm Handler function.
|
||||||
@@ -459,3 +470,190 @@ func (e UserEndpoint) handleChangePasswordPost() http.HandlerFunc {
|
|||||||
respond.JSON(w, http.StatusOK, model.NewUser(user, false))
|
respond.JSON(w, http.StatusOK, model.NewUser(user, false))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// handleBulkDelete returns a gorm Handler function.
|
||||||
|
//
|
||||||
|
// @ID users_handleBulkDelete
|
||||||
|
// @Tags Users
|
||||||
|
// @Summary Bulk delete selected users.
|
||||||
|
// @Produce json
|
||||||
|
// @Param request body model.BulkPeerRequest true "A list of user identifiers to delete"
|
||||||
|
// @Success 204 "No content if deletion was successful"
|
||||||
|
// @Failure 400 {object} model.Error
|
||||||
|
// @Failure 500 {object} model.Error
|
||||||
|
// @Router /user/bulk-delete [post]
|
||||||
|
func (e UserEndpoint) handleBulkDelete() http.HandlerFunc {
|
||||||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
var req model.BulkUserRequest
|
||||||
|
if err := request.BodyJson(r, &req); err != nil {
|
||||||
|
respond.JSON(w, http.StatusBadRequest, model.Error{Code: http.StatusBadRequest, Message: err.Error()})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
ids := make([]domain.UserIdentifier, len(req.Identifiers))
|
||||||
|
for i, id := range req.Identifiers {
|
||||||
|
ids[i] = domain.UserIdentifier(id)
|
||||||
|
}
|
||||||
|
|
||||||
|
err := e.userService.BulkDelete(r.Context(), ids)
|
||||||
|
if err != nil {
|
||||||
|
respond.JSON(w, http.StatusInternalServerError,
|
||||||
|
model.Error{Code: http.StatusInternalServerError, Message: err.Error()})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
respond.Status(w, http.StatusNoContent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// handleBulkEnable returns a gorm Handler function.
|
||||||
|
//
|
||||||
|
// @ID users_handleBulkEnable
|
||||||
|
// @Tags Users
|
||||||
|
// @Summary Bulk enable selected users.
|
||||||
|
// @Produce json
|
||||||
|
// @Param request body model.BulkPeerRequest true "A list of user identifiers to enable"
|
||||||
|
// @Success 204 "No content if action was successful"
|
||||||
|
// @Failure 400 {object} model.Error
|
||||||
|
// @Failure 500 {object} model.Error
|
||||||
|
// @Router /user/bulk-enable [post]
|
||||||
|
func (e UserEndpoint) handleBulkEnable() http.HandlerFunc {
|
||||||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
var req model.BulkUserRequest
|
||||||
|
if err := request.BodyJson(r, &req); err != nil {
|
||||||
|
respond.JSON(w, http.StatusBadRequest, model.Error{Code: http.StatusBadRequest, Message: err.Error()})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
ids := make([]domain.UserIdentifier, len(req.Identifiers))
|
||||||
|
for i, id := range req.Identifiers {
|
||||||
|
ids[i] = domain.UserIdentifier(id)
|
||||||
|
}
|
||||||
|
|
||||||
|
err := e.userService.BulkUpdate(r.Context(), ids, func(user *domain.User) {
|
||||||
|
user.Disabled = nil
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
respond.JSON(w, http.StatusInternalServerError,
|
||||||
|
model.Error{Code: http.StatusInternalServerError, Message: err.Error()})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
respond.Status(w, http.StatusNoContent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// handleBulkDisable returns a gorm Handler function.
|
||||||
|
//
|
||||||
|
// @ID users_handleBulkDisable
|
||||||
|
// @Tags Users
|
||||||
|
// @Summary Bulk disable selected users.
|
||||||
|
// @Produce json
|
||||||
|
// @Param request body model.BulkPeerRequest true "A list of user identifiers to disable"
|
||||||
|
// @Success 204 "No content if action was successful"
|
||||||
|
// @Failure 400 {object} model.Error
|
||||||
|
// @Failure 500 {object} model.Error
|
||||||
|
// @Router /user/bulk-disable [post]
|
||||||
|
func (e UserEndpoint) handleBulkDisable() http.HandlerFunc {
|
||||||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
var req model.BulkUserRequest
|
||||||
|
if err := request.BodyJson(r, &req); err != nil {
|
||||||
|
respond.JSON(w, http.StatusBadRequest, model.Error{Code: http.StatusBadRequest, Message: err.Error()})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
ids := make([]domain.UserIdentifier, len(req.Identifiers))
|
||||||
|
for i, id := range req.Identifiers {
|
||||||
|
ids[i] = domain.UserIdentifier(id)
|
||||||
|
}
|
||||||
|
|
||||||
|
now := time.Now()
|
||||||
|
err := e.userService.BulkUpdate(r.Context(), ids, func(user *domain.User) {
|
||||||
|
user.Disabled = &now
|
||||||
|
user.DisabledReason = domain.DisabledReasonAdmin
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
respond.JSON(w, http.StatusInternalServerError,
|
||||||
|
model.Error{Code: http.StatusInternalServerError, Message: err.Error()})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
respond.Status(w, http.StatusNoContent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// handleBulkLock returns a gorm Handler function.
|
||||||
|
//
|
||||||
|
// @ID users_handleBulkLock
|
||||||
|
// @Tags Users
|
||||||
|
// @Summary Bulk lock selected users.
|
||||||
|
// @Produce json
|
||||||
|
// @Param request body model.BulkPeerRequest true "A list of user identifiers to lock"
|
||||||
|
// @Success 204 "No content if action was successful"
|
||||||
|
// @Failure 400 {object} model.Error
|
||||||
|
// @Failure 500 {object} model.Error
|
||||||
|
// @Router /user/bulk-lock [post]
|
||||||
|
func (e UserEndpoint) handleBulkLock() http.HandlerFunc {
|
||||||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
var req model.BulkUserRequest
|
||||||
|
if err := request.BodyJson(r, &req); err != nil {
|
||||||
|
respond.JSON(w, http.StatusBadRequest, model.Error{Code: http.StatusBadRequest, Message: err.Error()})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
ids := make([]domain.UserIdentifier, len(req.Identifiers))
|
||||||
|
for i, id := range req.Identifiers {
|
||||||
|
ids[i] = domain.UserIdentifier(id)
|
||||||
|
}
|
||||||
|
|
||||||
|
now := time.Now()
|
||||||
|
err := e.userService.BulkUpdate(r.Context(), ids, func(user *domain.User) {
|
||||||
|
user.Locked = &now
|
||||||
|
user.LockedReason = domain.LockedReasonAdmin
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
respond.JSON(w, http.StatusInternalServerError,
|
||||||
|
model.Error{Code: http.StatusInternalServerError, Message: err.Error()})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
respond.Status(w, http.StatusNoContent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// handleBulkUnlock returns a gorm Handler function.
|
||||||
|
//
|
||||||
|
// @ID users_handleBulkUnlock
|
||||||
|
// @Tags Users
|
||||||
|
// @Summary Bulk unlock selected users.
|
||||||
|
// @Produce json
|
||||||
|
// @Param request body model.BulkPeerRequest true "A list of user identifiers to unlock"
|
||||||
|
// @Success 204 "No content if action was successful"
|
||||||
|
// @Failure 400 {object} model.Error
|
||||||
|
// @Failure 500 {object} model.Error
|
||||||
|
// @Router /user/bulk-unlock [post]
|
||||||
|
func (e UserEndpoint) handleBulkUnlock() http.HandlerFunc {
|
||||||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
var req model.BulkUserRequest
|
||||||
|
if err := request.BodyJson(r, &req); err != nil {
|
||||||
|
respond.JSON(w, http.StatusBadRequest, model.Error{Code: http.StatusBadRequest, Message: err.Error()})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
ids := make([]domain.UserIdentifier, len(req.Identifiers))
|
||||||
|
for i, id := range req.Identifiers {
|
||||||
|
ids[i] = domain.UserIdentifier(id)
|
||||||
|
}
|
||||||
|
|
||||||
|
err := e.userService.BulkUpdate(r.Context(), ids, func(user *domain.User) {
|
||||||
|
user.Locked = nil
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
respond.JSON(w, http.StatusInternalServerError,
|
||||||
|
model.Error{Code: http.StatusInternalServerError, Message: err.Error()})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
respond.Status(w, http.StatusNoContent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
10
internal/app/api/v0/model/models_bulk.go
Normal file
10
internal/app/api/v0/model/models_bulk.go
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
package model
|
||||||
|
|
||||||
|
type BulkPeerRequest struct {
|
||||||
|
Identifiers []string `json:"Identifiers" binding:"required"`
|
||||||
|
Reason string `json:"Reason"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type BulkUserRequest struct {
|
||||||
|
Identifiers []string `json:"Identifiers" binding:"required"`
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user