Implement user deletion

This commit is contained in:
Johannes Zellner
2025-02-12 15:18:45 +01:00
parent bd44bb4534
commit c9d875e3fa
4 changed files with 69 additions and 40 deletions

View File

@@ -229,6 +229,7 @@ onMounted(async () => {
:confirm-busy="editBusy"
:confirm-active="!editBusy && isValid"
:reject-label="$t('main.dialog.cancel')"
reject-style="secondary"
@confirm="onSubmit()"
>
<p class="has-error text-center" v-show="editError.generic">{{ editError.generic }}</p>

View File

@@ -7,14 +7,14 @@ function create() {
return {
async getIpv4Config() {
let error, result;
let result;
try {
result = await fetcher.get(`${origin}/api/v1/network/ipv4_config`, { access_token: accessToken });
} catch (e) {
error = e;
return [e];
}
if (error || result.status !== 200) return [error || result];
if (result.status !== 200) return [result];
return [null, result.body];
},
async setIpv4Config(provider, ip, ifname) {
@@ -23,36 +23,36 @@ function create() {
if (provider === 'fixed') data.ip = ip;
else if (provider === 'network-interface') data.ifname = ifname;
let error, result;
let result;
try {
result = await fetcher.post(`${origin}/api/v1/network/ipv4_config`, data, { access_token: accessToken });
} catch (e) {
error = e;
return [e];
}
if (error || result.status !== 200) return [error || result];
if (result.status !== 200) return [result];
return [null];
},
async getIpv4() {
let error, result;
let result;
try {
result = await fetcher.get(`${origin}/api/v1/network/ipv4`, { access_token: accessToken });
} catch (e) {
error = e;
return [e];
}
if (error || result.status !== 200) return [error || result];
if (result.status !== 200) return [result];
return [null, result.body.ip];
},
async getIpv6Config() {
let error, result;
let result;
try {
result = await fetcher.get(`${origin}/api/v1/network/ipv6_config`, { access_token: accessToken });
} catch (e) {
error = e;
return [e];
}
if (error || result.status !== 200) return [error || result];
if (result.status !== 200) return [result];
return [null, result.body];
},
async setIpv6Config(provider, ip, ifname) {
@@ -61,91 +61,91 @@ function create() {
if (provider === 'fixed') data.ip = ip;
else if (provider === 'network-interface') data.ifname = ifname;
let error, result;
let result;
try {
result = await fetcher.post(`${origin}/api/v1/network/ipv6_config`, data, { access_token: accessToken });
} catch (e) {
error = e;
return [e];
}
if (error || result.status !== 200) return [error || result];
if (result.status !== 200) return [result];
return [null];
},
async getIpv6() {
let error, result;
let result;
try {
result = await fetcher.get(`${origin}/api/v1/network/ipv6`, { access_token: accessToken });
} catch (e) {
error = e;
return [e];
}
if (error || result.status !== 200) return [error || result];
if (result.status !== 200) return [result];
return [null, result.body.ip];
},
async getDynDnsConfig() {
let error, result;
let result;
try {
result = await fetcher.get(`${origin}/api/v1/network/dynamic_dns`, { access_token: accessToken });
} catch (e) {
error = e;
return [e];
}
if (error || result.status !== 200) return [error || result];
if (result.status !== 200) return [result];
return [null, result.body];
},
async setDynDnsConfig(enabled) {
let error, result;
let result;
try {
result = await fetcher.post(`${origin}/api/v1/network/dynamic_dns`, { enabled }, { access_token: accessToken });
} catch (e) {
error = e;
return [e];
}
if (error || result.status !== 200) return [error || result];
if (result.status !== 200) return [result];
return [null];
},
async getBlocklist() {
let error, result;
let result;
try {
result = await fetcher.get(`${origin}/api/v1/network/blocklist`, { access_token: accessToken });
} catch (e) {
error = e;
return [e];
}
if (error || result.status !== 200) return [error || result];
if (result.status !== 200) return [result];
return [null, result.body.blocklist];
},
async setBlocklist(blocklist) {
let error, result;
let result;
try {
result = await fetcher.post(`${origin}/api/v1/network/blocklist`, { blocklist }, { access_token: accessToken });
} catch (e) {
error = e;
return [e];
}
if (error || result.status !== 200) return [error || result];
if (result.status !== 200) return [result];
return [null];
},
async getTrustedIps() {
let error, result;
let result;
try {
result = await fetcher.get(`${origin}/api/v1/reverseproxy/trusted_ips`, { access_token: accessToken });
} catch (e) {
error = e;
return [e];
}
if (error || result.status !== 200) return [error || result];
if (result.status !== 200) return [result];
return [null, result.body.trustedIps];
},
async setTrustedIps(trustedIps) {
let error, result;
let result;
try {
result = await fetcher.post(`${origin}/api/v1/reverseproxy/trusted_ips`, { trustedIps }, { access_token: accessToken });
} catch (e) {
error = e;
return [e];
}
if (error || result.status !== 200) return [error || result];
if (result.status !== 200) return [result];
return [null];
},
};

View File

@@ -13,14 +13,14 @@ function create() {
let users = [];
while (true) {
let error, result;
let result;
try {
result = await fetcher.get(`${origin}/api/v1/users`, { page, per_page: perPage, access_token: accessToken });
} catch (e) {
error = e;
return [e];
}
if (error || result.status !== 200) return [error || result];
if (result.status !== 200) return [result];
users = users.concat(result.body.users);
@@ -31,6 +31,17 @@ function create() {
return [null, users];
},
async remove(id) {
let result;
try {
result = await fetcher.del(`${origin}/api/v1/users/${id}`, { access_token: accessToken });
} catch (e) {
return [e];
}
if (result.status !== 204) return [result];
return [null];
},
};
}

View File

@@ -134,6 +134,23 @@ async function onRemoveGroup(group) {
await refreshGroups();
}
async function onRemoveUser(user) {
const yes = await inputDialog.value.confirm({
title: t('users.deleteUserDialog.title', { username: (user.username || user.email) }),
message: t('users.deleteUserDialog.description'),
confirmStyle: 'danger',
confirmLabel: t('users.deleteUserDialog.deleteAction'),
rejectLabel: t('main.dialog.cancel')
});
if (!yes) return;
const [error] = await usersModel.remove(user.id);
if (error) console.error(error);
await refreshUsers();
}
onMounted(async () => {
const [error, result] = await profileModel.get();
if (error) return console.error(error);
@@ -193,7 +210,7 @@ onMounted(async () => {
<Button small tool secondary :disabled="!canImpersonate(user)" @click="setGhost.show(user)" v-tooltip="$t('users.users.setGhostTooltip')" icon="fa-solid fa-user-secret" />
<Button small tool secondary :disabled="!canEdit(user)" @click="userEdit.show(user)" v-tooltip="$t('users.users.editUserTooltip')" icon="fa fa-pencil-alt" />
</ButtonGroup>
<Button small tool danger :disabled="!canEdit(user) || isMe(user)" @click="userRemove.show(user)" v-tooltip="$t('users.users.removeUserTooltip')" icon="far fa-trash-alt" />
<Button small tool danger :disabled="!canEdit(user) || isMe(user)" @click="onRemoveUser(user)" v-tooltip="$t('users.users.removeUserTooltip')" icon="far fa-trash-alt" />
</div>
</template>
</TableView>