@adminforth/user-soft-delete 1.0.0 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/build.log CHANGED
@@ -5,7 +5,8 @@
5
5
  sending incremental file list
6
6
  custom/
7
7
  custom/DisableButton.vue
8
+ custom/UserSoftDeleteFilterSetter.vue
8
9
  custom/tsconfig.json
9
10
 
10
- sent 3,102 bytes received 58 bytes 6,320.00 bytes/sec
11
- total size is 2,885 speedup is 0.91
11
+ sent 2,942 bytes received 77 bytes 6,038.00 bytes/sec
12
+ total size is 2,640 speedup is 0.87
@@ -1,7 +1,15 @@
1
1
  <template>
2
- <div class="flex items-end justify-start gap-2 cursor-pointer" :class="{'opacity-50': checkboxes.length !== 1}">
3
- <p class="text-justify max-h-[18px] truncate max-w-[60vw] md:max-w-none">Deactivate user</p>
4
- </div>
2
+ <Tooltip>
3
+ <button
4
+ @click="openDialog()"
5
+ >
6
+ <IconUserRemoveSolid class="w-5 h-5 me-2"/>
7
+ </button>
8
+
9
+ <template v-slot:tooltip>
10
+ {{ $t('Deactivate user') }}
11
+ </template>
12
+ </Tooltip>
5
13
  <Dialog
6
14
  ref="confirmDialog"
7
15
  class="w-96"
@@ -19,36 +27,16 @@
19
27
 
20
28
  <script lang="ts" setup>
21
29
  import { Dialog, Tooltip } from '@/afcl';
22
- import { ref, onMounted } from 'vue';
30
+ import { ref } from 'vue';
23
31
  import { AdminUser, type AdminForthResourceCommon } from '@/types';
24
32
  import adminforth from "@/adminforth"
25
33
  import { callAdminForthApi } from '@/utils';
26
- import { AdminForthFilterOperators } from '@/types/Common';
27
-
34
+ import { IconUserRemoveSolid } from '@iconify-prerendered/vue-flowbite';
28
35
 
29
36
  const confirmDialog = ref(null);
30
37
 
31
-
32
- onMounted(async () => {
33
- await new Promise((resolve) => setTimeout(resolve, 50));
34
-
35
- adminforth?.list?.updateFilter?.({
36
- field: props.meta.field,
37
- operator: AdminForthFilterOperators.EQ,
38
- value: true,
39
- });
40
- });
41
-
42
38
  function openDialog() {
43
- if ( props.checkboxes.length !== 1 ) {
44
- if (props.checkboxes.length > 1) {
45
- adminforth.alert({message: "Select only one account to deactivate", variant: "warning"})
46
- } else {
47
- adminforth.alert({message: "Select at least one account to deactivate", variant: "warning"})
48
- }
49
- } else {
50
- confirmDialog.value.open()
51
- }
39
+ confirmDialog.value.open();
52
40
  }
53
41
 
54
42
  async function deactivateUser() {
@@ -57,7 +45,7 @@ async function deactivateUser() {
57
45
  path: `/plugin/${props.meta.pluginInstanceId}/deactivateUser`,
58
46
  method: 'POST',
59
47
  body: {
60
- record: props.checkboxes[0],
48
+ record: props.record,
61
49
  },
62
50
  });
63
51
  if (!res || res.ok === false || res.error) {
@@ -66,33 +54,19 @@ async function deactivateUser() {
66
54
  }
67
55
  throw new Error("")
68
56
  }
69
- props.updateList();
57
+ props.updateRecords();
70
58
  } catch (e) {
71
59
  adminforth.alert({message: `Error deactivating user. ${e}`, variant: "warning"});
72
60
  }
73
61
  }
74
62
 
75
63
  const props = defineProps<{
76
- checkboxes: any,
77
64
  meta: any,
78
65
  resource: AdminForthResourceCommon,
79
66
  adminUser: AdminUser,
80
- updateList: {
81
- type: Function,
82
- required: true
83
- },
84
- clearCheckboxes: {
85
- type: Function
86
- }
67
+ record: any,
68
+ updateRecords: Function,
87
69
  }>();
88
70
 
89
- defineExpose({
90
- click
91
- });
92
-
93
- function click() {
94
- openDialog();
95
- }
96
-
97
71
 
98
72
  </script>
@@ -0,0 +1,20 @@
1
+ <template>
2
+
3
+ </template>
4
+
5
+ <script lang="ts" setup>
6
+ import { onMounted } from 'vue';
7
+ import { AdminForthFilterOperators } from '@/types/Common';
8
+ import adminforth from "@/adminforth"
9
+ onMounted(async () => {
10
+ await new Promise((resolve) => setTimeout(resolve, 50));
11
+ adminforth?.list?.updateFilter?.({
12
+ field: props.meta.field,
13
+ operator: AdminForthFilterOperators.EQ,
14
+ value: true,
15
+ });
16
+ });
17
+ const props = defineProps<{
18
+ meta: any
19
+ }>();
20
+ </script>
@@ -1,7 +1,15 @@
1
1
  <template>
2
- <div class="flex items-end justify-start gap-2 cursor-pointer" :class="{'opacity-50': checkboxes.length !== 1}">
3
- <p class="text-justify max-h-[18px] truncate max-w-[60vw] md:max-w-none">Deactivate user</p>
4
- </div>
2
+ <Tooltip>
3
+ <button
4
+ @click="openDialog()"
5
+ >
6
+ <IconUserRemoveSolid class="w-5 h-5 me-2"/>
7
+ </button>
8
+
9
+ <template v-slot:tooltip>
10
+ {{ $t('Deactivate user') }}
11
+ </template>
12
+ </Tooltip>
5
13
  <Dialog
6
14
  ref="confirmDialog"
7
15
  class="w-96"
@@ -19,36 +27,16 @@
19
27
 
20
28
  <script lang="ts" setup>
21
29
  import { Dialog, Tooltip } from '@/afcl';
22
- import { ref, onMounted } from 'vue';
30
+ import { ref } from 'vue';
23
31
  import { AdminUser, type AdminForthResourceCommon } from '@/types';
24
32
  import adminforth from "@/adminforth"
25
33
  import { callAdminForthApi } from '@/utils';
26
- import { AdminForthFilterOperators } from '@/types/Common';
27
-
34
+ import { IconUserRemoveSolid } from '@iconify-prerendered/vue-flowbite';
28
35
 
29
36
  const confirmDialog = ref(null);
30
37
 
31
-
32
- onMounted(async () => {
33
- await new Promise((resolve) => setTimeout(resolve, 50));
34
-
35
- adminforth?.list?.updateFilter?.({
36
- field: props.meta.field,
37
- operator: AdminForthFilterOperators.EQ,
38
- value: true,
39
- });
40
- });
41
-
42
38
  function openDialog() {
43
- if ( props.checkboxes.length !== 1 ) {
44
- if (props.checkboxes.length > 1) {
45
- adminforth.alert({message: "Select only one account to deactivate", variant: "warning"})
46
- } else {
47
- adminforth.alert({message: "Select at least one account to deactivate", variant: "warning"})
48
- }
49
- } else {
50
- confirmDialog.value.open()
51
- }
39
+ confirmDialog.value.open();
52
40
  }
53
41
 
54
42
  async function deactivateUser() {
@@ -57,7 +45,7 @@ async function deactivateUser() {
57
45
  path: `/plugin/${props.meta.pluginInstanceId}/deactivateUser`,
58
46
  method: 'POST',
59
47
  body: {
60
- record: props.checkboxes[0],
48
+ record: props.record,
61
49
  },
62
50
  });
63
51
  if (!res || res.ok === false || res.error) {
@@ -66,33 +54,19 @@ async function deactivateUser() {
66
54
  }
67
55
  throw new Error("")
68
56
  }
69
- props.updateList();
57
+ props.updateRecords();
70
58
  } catch (e) {
71
59
  adminforth.alert({message: `Error deactivating user. ${e}`, variant: "warning"});
72
60
  }
73
61
  }
74
62
 
75
63
  const props = defineProps<{
76
- checkboxes: any,
77
64
  meta: any,
78
65
  resource: AdminForthResourceCommon,
79
66
  adminUser: AdminUser,
80
- updateList: {
81
- type: Function,
82
- required: true
83
- },
84
- clearCheckboxes: {
85
- type: Function
86
- }
67
+ record: any,
68
+ updateRecords: Function,
87
69
  }>();
88
70
 
89
- defineExpose({
90
- click
91
- });
92
-
93
- function click() {
94
- openDialog();
95
- }
96
-
97
71
 
98
72
  </script>
@@ -0,0 +1,20 @@
1
+ <template>
2
+
3
+ </template>
4
+
5
+ <script lang="ts" setup>
6
+ import { onMounted } from 'vue';
7
+ import { AdminForthFilterOperators } from '@/types/Common';
8
+ import adminforth from "@/adminforth"
9
+ onMounted(async () => {
10
+ await new Promise((resolve) => setTimeout(resolve, 50));
11
+ adminforth?.list?.updateFilter?.({
12
+ field: props.meta.field,
13
+ operator: AdminForthFilterOperators.EQ,
14
+ value: true,
15
+ });
16
+ });
17
+ const props = defineProps<{
18
+ meta: any
19
+ }>();
20
+ </script>
package/dist/index.js CHANGED
@@ -48,16 +48,31 @@ export default class UserSoftDelete extends AdminForthPlugin {
48
48
  return rejectResult;
49
49
  }
50
50
  }));
51
+ const adminUserAuthorize = this.adminforth.config.auth.adminUserAuthorize;
52
+ const adminUserAuthorizeArray = Array.isArray(adminUserAuthorize) ? adminUserAuthorize : [adminUserAuthorize];
53
+ adminUserAuthorizeArray.unshift((_a) => __awaiter(this, [_a], void 0, function* ({ extra, adminUser }) {
54
+ const rejectResult = {
55
+ error: 'Your account is deactivated',
56
+ allowed: false,
57
+ };
58
+ if (adminUser.dbUser[this.options.activeFieldName] === false) {
59
+ return rejectResult;
60
+ }
61
+ }));
51
62
  if (!resourceConfig.options.pageInjections) {
52
63
  resourceConfig.options.pageInjections = {};
53
64
  }
54
65
  if (!resourceConfig.options.pageInjections.list) {
55
66
  resourceConfig.options.pageInjections.list = {};
56
67
  }
57
- if (!resourceConfig.options.pageInjections.list.threeDotsDropdownItems) {
58
- resourceConfig.options.pageInjections.list.threeDotsDropdownItems = [];
68
+ if (!resourceConfig.options.pageInjections.list.customActionIcons) {
69
+ resourceConfig.options.pageInjections.list.customActionIcons = [];
70
+ }
71
+ resourceConfig.options.pageInjections.list.customActionIcons.push({ file: this.componentPath('DisableButton.vue'), meta: { pluginInstanceId: this.pluginInstanceId, field: this.options.activeFieldName } });
72
+ if (!resourceConfig.options.pageInjections.list.afterBreadcrumbs) {
73
+ resourceConfig.options.pageInjections.list.afterBreadcrumbs = [];
59
74
  }
60
- resourceConfig.options.pageInjections.list.threeDotsDropdownItems.push({ file: this.componentPath('DisableButton.vue'), meta: { pluginInstanceId: this.pluginInstanceId, field: this.options.activeFieldName } });
75
+ resourceConfig.options.pageInjections.list.afterBreadcrumbs.push({ file: this.componentPath('UserSoftDeleteFilterSetter.vue'), meta: { pluginInstanceId: this.pluginInstanceId, field: this.options.activeFieldName } });
61
76
  // simply modify resourceConfig or adminforth.config. You can get access to plugin options via this.options;
62
77
  });
63
78
  }
@@ -88,14 +103,11 @@ export default class UserSoftDelete extends AdminForthPlugin {
88
103
  if (typeof this.allowDisableFunc === "function") {
89
104
  isAllowedToDeactivate = yield this.allowDisableFunc(adminUser);
90
105
  }
91
- else if (typeof this.allowDisableFunc === "boolean") {
92
- isAllowedToDeactivate = this.allowDisableFunc;
93
- }
94
106
  if (isAllowedToDeactivate === false) {
95
107
  return { ok: false, error: "Not allowed to deactivate user" };
96
108
  }
97
- const id = body.record;
98
109
  const primaryKeyColumn = this.resourceConfig.columns.find((col) => col.primaryKey);
110
+ const id = body.record[primaryKeyColumn.name];
99
111
  const oldUser = yield this.adminforth
100
112
  .resource(this.resourceConfig.resourceId)
101
113
  .get([Filters.EQ(primaryKeyColumn.name, id)]);
@@ -105,6 +117,9 @@ export default class UserSoftDelete extends AdminForthPlugin {
105
117
  if (oldUser[this.options.activeFieldName] === false) {
106
118
  return { ok: false, error: "User is already deactivated" };
107
119
  }
120
+ if (oldUser[primaryKeyColumn.name] === adminUser.dbUser[primaryKeyColumn.name]) {
121
+ return { ok: false, error: "You cannot deactivate your own account" };
122
+ }
108
123
  const newUser = Object.assign(Object.assign({}, oldUser), { [this.options.activeFieldName]: false });
109
124
  yield this.adminforth.updateResourceRecord({
110
125
  resource: this.resourceConfig,
package/index.ts CHANGED
@@ -44,19 +44,40 @@ export default class UserSoftDelete extends AdminForthPlugin {
44
44
  }
45
45
  );
46
46
 
47
+ const adminUserAuthorize = this.adminforth.config.auth.adminUserAuthorize;
48
+ const adminUserAuthorizeArray = Array.isArray(adminUserAuthorize) ? adminUserAuthorize : [adminUserAuthorize];
49
+ adminUserAuthorizeArray.unshift(
50
+ async({ extra, adminUser }: { adminUser: AdminUser, response: IAdminForthHttpResponse, extra?: any} )=> {
51
+ const rejectResult = {
52
+ error: 'Your account is deactivated',
53
+ allowed: false,
54
+ };
55
+ if (adminUser.dbUser[this.options.activeFieldName] === false) {
56
+ return rejectResult;
57
+ }
58
+ }
59
+ );
60
+
47
61
  if ( !resourceConfig.options.pageInjections ) {
48
62
  resourceConfig.options.pageInjections = {};
49
63
  }
50
64
  if ( !resourceConfig.options.pageInjections.list ) {
51
65
  resourceConfig.options.pageInjections.list = {};
52
66
  }
53
- if ( !resourceConfig.options.pageInjections.list.threeDotsDropdownItems ) {
54
- resourceConfig.options.pageInjections.list.threeDotsDropdownItems = [];
67
+ if ( !resourceConfig.options.pageInjections.list.customActionIcons ) {
68
+ resourceConfig.options.pageInjections.list.customActionIcons = [];
55
69
  }
56
- (resourceConfig.options.pageInjections.list.threeDotsDropdownItems as AdminForthComponentDeclaration[]).push(
70
+ (resourceConfig.options.pageInjections.list.customActionIcons as AdminForthComponentDeclaration[]).push(
57
71
  { file: this.componentPath('DisableButton.vue'), meta: { pluginInstanceId: this.pluginInstanceId, field: this.options.activeFieldName } }
58
72
  );
59
73
 
74
+ if ( !resourceConfig.options.pageInjections.list.afterBreadcrumbs ) {
75
+ resourceConfig.options.pageInjections.list.afterBreadcrumbs = [];
76
+ }
77
+ (resourceConfig.options.pageInjections.list.afterBreadcrumbs as AdminForthComponentDeclaration[]).push(
78
+ { file: this.componentPath('UserSoftDeleteFilterSetter.vue'), meta: { pluginInstanceId: this.pluginInstanceId, field: this.options.activeFieldName } }
79
+ );
80
+
60
81
  // simply modify resourceConfig or adminforth.config. You can get access to plugin options via this.options;
61
82
  }
62
83
 
@@ -88,14 +109,13 @@ export default class UserSoftDelete extends AdminForthPlugin {
88
109
  let isAllowedToDeactivate = false;
89
110
  if ( typeof this.allowDisableFunc === "function" ) {
90
111
  isAllowedToDeactivate = await this.allowDisableFunc(adminUser);
91
- } else if (typeof this.allowDisableFunc === "boolean") {
92
- isAllowedToDeactivate = this.allowDisableFunc;
93
112
  }
94
113
  if ( isAllowedToDeactivate === false ) {
95
114
  return {ok: false, error: "Not allowed to deactivate user"}
96
115
  }
97
- const id = body.record;
116
+
98
117
  const primaryKeyColumn = this.resourceConfig.columns.find((col) => col.primaryKey);
118
+ const id = body.record[primaryKeyColumn.name];
99
119
 
100
120
  const oldUser = await this.adminforth
101
121
  .resource(this.resourceConfig.resourceId)
@@ -108,6 +128,10 @@ export default class UserSoftDelete extends AdminForthPlugin {
108
128
  if (oldUser[this.options.activeFieldName] === false) {
109
129
  return {ok: false, error: "User is already deactivated"}
110
130
  }
131
+
132
+ if (oldUser[primaryKeyColumn.name] === adminUser.dbUser[primaryKeyColumn.name]) {
133
+ return {ok: false, error: "You cannot deactivate your own account"}
134
+ }
111
135
 
112
136
  const newUser = { ...oldUser, [this.options.activeFieldName]: false };
113
137
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adminforth/user-soft-delete",
3
- "version": "1.0.0",
3
+ "version": "1.2.0",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "type": "module",
@@ -16,12 +16,12 @@
16
16
  "description": "",
17
17
  "devDependencies": {
18
18
  "@types/node": "latest",
19
- "typescript": "^5.7.3",
20
19
  "semantic-release": "^24.2.1",
21
- "semantic-release-slack-bot": "^4.0.2"
20
+ "semantic-release-slack-bot": "^4.0.2",
21
+ "typescript": "^5.7.3"
22
22
  },
23
23
  "dependencies": {
24
- "adminforth": "^2.4.0-next.191"
24
+ "adminforth": "^2.4.0-next.227"
25
25
  },
26
26
  "release": {
27
27
  "plugins": [
package/types.ts CHANGED
@@ -2,5 +2,5 @@ import type { AdminUser } from "adminforth";
2
2
 
3
3
  export interface PluginOptions {
4
4
  activeFieldName: string;
5
- canDeactivate?: (adminUser: AdminUser) => Promise<boolean>;
5
+ canDeactivate: (adminUser: AdminUser) => Promise<boolean>;
6
6
  }