diff --git a/CHANGES b/CHANGES
index 6f5dc729a..e1c8ed921 100644
--- a/CHANGES
+++ b/CHANGES
@@ -3016,3 +3016,6 @@
* display backup duration
* add hetznercloud DNS provider
+[9.0.5]
+* access control/operators: remove deleted users and groups
+
diff --git a/dashboard/src/components/AccessControl.vue b/dashboard/src/components/AccessControl.vue
index 27179fe8e..fb02fd30a 100644
--- a/dashboard/src/components/AccessControl.vue
+++ b/dashboard/src/components/AccessControl.vue
@@ -1,33 +1,18 @@
diff --git a/dashboard/src/components/OperatorAccessControl.vue b/dashboard/src/components/OperatorAccessControl.vue
index 9d158728f..ae91405c4 100644
--- a/dashboard/src/components/OperatorAccessControl.vue
+++ b/dashboard/src/components/OperatorAccessControl.vue
@@ -1,29 +1,13 @@
diff --git a/dashboard/src/components/app/Access.vue b/dashboard/src/components/app/Access.vue
index 3eab900fe..538276bab 100644
--- a/dashboard/src/components/app/Access.vue
+++ b/dashboard/src/components/app/Access.vue
@@ -6,39 +6,64 @@ import AccessControl from '../AccessControl.vue';
import OperatorAccessControl from '../OperatorAccessControl.vue';
import AppsModel from '../../models/AppsModel.js';
import { ACL_OPTIONS } from '../../constants.js';
+import UsersModel from '../../models/UsersModel.js';
+import GroupsModel from '../../models/GroupsModel.js';
const props = defineProps([ 'app' ]);
const appsModel = AppsModel.create();
+const usersModel = UsersModel.create();
+const groupsModel = GroupsModel.create();
-const busy = ref(false);
+const users = ref([]);
+const groups = ref([]);
+
+const loading = ref(false);
+const submitBusy = ref(false);
const errorMessage = ref('');
const accessRestrictionOption = ref(ACL_OPTIONS.ANY);
const accessRestrictionAcl = ref({ users: [], groups: [] });
const operatorAcl = ref({ users: [], groups: [] });
async function onSubmit() {
- busy.value = true;
+ submitBusy.value = true;
errorMessage.value = '';
let [error] = await appsModel.configure(props.app.id, 'access_restriction', { accessRestriction: accessRestrictionOption.value === ACL_OPTIONS.ANY ? null : (accessRestrictionOption.value === ACL_OPTIONS.NOSSO ? false : accessRestrictionAcl.value) });
if (error) {
errorMessage.value = error.body ? error.body.message : 'Internal error';
- busy.value = false;
+ submitBusy.value = false;
return console.error(error);
}
[error] = await appsModel.configure(props.app.id, 'operators', { operators: (operatorAcl.value.users.length || operatorAcl.value.groups.length) ? operatorAcl.value : null});
if (error) {
errorMessage.value = error.body ? error.body.message : 'Internal error';
- busy.value = false;
+ submitBusy.value = false;
return console.error(error);
}
- busy.value = false;
+ submitBusy.value = false;
}
-onMounted(() => {
+onMounted(async () => {
+ loading.value = true;
+
+ let [error, result] = await usersModel.list();
+ if (error) return console.error(error);
+ const userIds = new Set();
+ for (const u of result) {
+ u.username = u.username || u.email; // ensure username
+ userIds.add(u.id);
+ }
+ users.value = result;
+
+ [error, result] = await groupsModel.list();
+ if (error) return console.error(error);
+ groups.value = result;
+ const groupIds = new Set();
+ for (const g of result) groupIds.add(g.id);
+
if (props.app.accessRestriction === null) {
accessRestrictionOption.value = ACL_OPTIONS.ANY;
accessRestrictionAcl.value = { users: [], groups: [] };
@@ -47,26 +72,31 @@ onMounted(() => {
accessRestrictionAcl.value = { users: [], groups: [] };
} else {
accessRestrictionOption.value = ACL_OPTIONS.RESTRICTED;
- accessRestrictionAcl.value = props.app.accessRestriction;
+ accessRestrictionAcl.value = JSON.parse(JSON.stringify(props.app.accessRestriction)); // make a copy
+ accessRestrictionAcl.value.users = accessRestrictionAcl.value.users.filter(uid => userIds.has(uid)); // remove deleted users
+ accessRestrictionAcl.value.groups = accessRestrictionAcl.value.groups.filter(gid => groupIds.has(gid)); // remove deleted groups
}
operatorAcl.value = { users: [], groups: [] };
if (props.app.operators) {
- operatorAcl.value.users = props.app.operators.users;
- operatorAcl.value.groups = props.app.operators.groups;
+ operatorAcl.value = JSON.parse(JSON.stringify(props.app.operators)); // make a copy
+ operatorAcl.value.users = operatorAcl.value.users.filter(uid => userIds.has(uid)); // remove deleted users
+ operatorAcl.value.groups = operatorAcl.value.groups.filter(gid => groupIds.has(gid)); // remove deleted groups
}
+
+ loading.value = false;
});
-
+
{{ errorMessage }}
-
+
-
+
-
+