@drax/identity-vue 0.36.0 → 0.37.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/package.json +8 -8
- package/src/components/IdentityUserGroupBy/IdentityUserGroupBy.vue +132 -0
- package/src/cruds/UserLoginFailCrud.ts +171 -0
- package/src/cruds/UserSessionCrud.ts +174 -0
- package/src/cruds/role-crud/RoleCrud.ts +3 -1
- package/src/cruds/role-crud/RoleForm.vue +5 -1
- package/src/cruds/user-crud/UserCrud.ts +8 -3
- package/src/i18n/UserLoginFail-i18n.ts +46 -0
- package/src/i18n/UserSession-i18n.ts +48 -0
- package/src/index.ts +7 -0
- package/src/pages/crud/UserCrudPage.vue +18 -2
- package/src/pages/crud/UserLoginFailCrudPage.vue +19 -0
- package/src/pages/crud/UserSessionCrudPage.vue +19 -0
- package/src/routes/IdentityRoutes.ts +4 -0
- package/src/routes/UserLoginFailCrudRoute.ts +18 -0
- package/src/routes/UserSessionCrudRoute.ts +18 -0
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"publishConfig": {
|
|
4
4
|
"access": "public"
|
|
5
5
|
},
|
|
6
|
-
"version": "0.
|
|
6
|
+
"version": "0.37.0",
|
|
7
7
|
"type": "module",
|
|
8
8
|
"main": "./src/index.ts",
|
|
9
9
|
"module": "./src/index.ts",
|
|
@@ -24,12 +24,12 @@
|
|
|
24
24
|
"format": "prettier --write src/"
|
|
25
25
|
},
|
|
26
26
|
"dependencies": {
|
|
27
|
-
"@drax/common-front": "^0.
|
|
28
|
-
"@drax/common-vue": "^0.
|
|
29
|
-
"@drax/crud-front": "^0.
|
|
30
|
-
"@drax/crud-share": "^0.
|
|
31
|
-
"@drax/crud-vue": "^0.
|
|
32
|
-
"@drax/identity-share": "^0.
|
|
27
|
+
"@drax/common-front": "^0.37.0",
|
|
28
|
+
"@drax/common-vue": "^0.37.0",
|
|
29
|
+
"@drax/crud-front": "^0.37.0",
|
|
30
|
+
"@drax/crud-share": "^0.37.0",
|
|
31
|
+
"@drax/crud-vue": "^0.37.0",
|
|
32
|
+
"@drax/identity-share": "^0.37.0"
|
|
33
33
|
},
|
|
34
34
|
"peerDependencies": {
|
|
35
35
|
"pinia": "^2.2.2",
|
|
@@ -66,5 +66,5 @@
|
|
|
66
66
|
"vue-tsc": "^2.1.6",
|
|
67
67
|
"vuetify": "^3.7.1"
|
|
68
68
|
},
|
|
69
|
-
"gitHead": "
|
|
69
|
+
"gitHead": "0bca48d4b686fd9536a78d84f5befe6801238000"
|
|
70
70
|
}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { ref, onMounted } from 'vue'
|
|
3
|
+
import { UserSystemFactory } from '@drax/identity-front'
|
|
4
|
+
|
|
5
|
+
interface RoleGroup {
|
|
6
|
+
_id: string
|
|
7
|
+
count: number
|
|
8
|
+
name?: string
|
|
9
|
+
icon?: string
|
|
10
|
+
color?: string
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const userSystem = UserSystemFactory.getInstance()
|
|
14
|
+
const roleGroups = ref<RoleGroup[]>([])
|
|
15
|
+
const loading = ref(false)
|
|
16
|
+
const error = ref<string | null>(null)
|
|
17
|
+
|
|
18
|
+
const loadUsersByRole = async () => {
|
|
19
|
+
loading.value = true
|
|
20
|
+
error.value = null
|
|
21
|
+
|
|
22
|
+
try {
|
|
23
|
+
const result = await userSystem.groupBy({fields: ['role']})
|
|
24
|
+
roleGroups.value = result.map((group: any) => ({
|
|
25
|
+
_id: group._id,
|
|
26
|
+
count: group.count,
|
|
27
|
+
name: group?.role?.name || 'Sin rol',
|
|
28
|
+
icon: group?.role?.icon || 'mdi-account-group',
|
|
29
|
+
color: group?.role?.color || 'primary'
|
|
30
|
+
}))
|
|
31
|
+
} catch (e) {
|
|
32
|
+
console.error('Error loading users by role:', e)
|
|
33
|
+
error.value = 'Error al cargar los datos de usuarios'
|
|
34
|
+
} finally {
|
|
35
|
+
loading.value = false
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
onMounted(() => {
|
|
40
|
+
loadUsersByRole()
|
|
41
|
+
})
|
|
42
|
+
</script>
|
|
43
|
+
|
|
44
|
+
<template>
|
|
45
|
+
<v-card variant="text" class="rounded-xl ma-4">
|
|
46
|
+
<v-card-text class="pa-2">
|
|
47
|
+
<v-row v-if="loading" justify="center">
|
|
48
|
+
<v-col cols="12" class="text-center py-4">
|
|
49
|
+
<v-progress-circular
|
|
50
|
+
indeterminate
|
|
51
|
+
color="primary"
|
|
52
|
+
size="48"
|
|
53
|
+
></v-progress-circular>
|
|
54
|
+
<p class="text-body-2 mt-2">Cargando...</p>
|
|
55
|
+
</v-col>
|
|
56
|
+
</v-row>
|
|
57
|
+
|
|
58
|
+
<v-row v-else-if="error" justify="center">
|
|
59
|
+
<v-col cols="12" md="6" class="py-2">
|
|
60
|
+
<v-alert
|
|
61
|
+
type="error"
|
|
62
|
+
variant="tonal"
|
|
63
|
+
density="compact"
|
|
64
|
+
closable
|
|
65
|
+
@click:close="error = null"
|
|
66
|
+
>
|
|
67
|
+
{{ error }}
|
|
68
|
+
</v-alert>
|
|
69
|
+
<div class="text-center mt-2">
|
|
70
|
+
<v-btn
|
|
71
|
+
color="primary"
|
|
72
|
+
variant="elevated"
|
|
73
|
+
size="small"
|
|
74
|
+
@click="loadUsersByRole"
|
|
75
|
+
>
|
|
76
|
+
Reintentar
|
|
77
|
+
</v-btn>
|
|
78
|
+
</div>
|
|
79
|
+
</v-col>
|
|
80
|
+
</v-row>
|
|
81
|
+
|
|
82
|
+
<v-row v-else dense>
|
|
83
|
+
<v-col
|
|
84
|
+
v-for="group in roleGroups"
|
|
85
|
+
:key="group._id"
|
|
86
|
+
cols="6"
|
|
87
|
+
sm="3"
|
|
88
|
+
md="3"
|
|
89
|
+
lg="2"
|
|
90
|
+
>
|
|
91
|
+
<v-card
|
|
92
|
+
elevation="1"
|
|
93
|
+
hover
|
|
94
|
+
class="role-card"
|
|
95
|
+
:class="`role-card--${group.color}`"
|
|
96
|
+
>
|
|
97
|
+
<v-card-text class="pa-3">
|
|
98
|
+
<div class="d-flex align-center mb-2">
|
|
99
|
+
<v-icon
|
|
100
|
+
:color="group.color"
|
|
101
|
+
size="28"
|
|
102
|
+
class="mr-2"
|
|
103
|
+
>
|
|
104
|
+
{{ group.icon }}
|
|
105
|
+
</v-icon>
|
|
106
|
+
<div :class="`text-subtitle-1 font-weight-bold text-truncate text-${group.color}`" :title="group.name">
|
|
107
|
+
{{ group.name }}
|
|
108
|
+
</div>
|
|
109
|
+
</div>
|
|
110
|
+
<div class="text-center">
|
|
111
|
+
<div :class="`text-h4 font-weight-bold ${group.color}--text`">
|
|
112
|
+
{{ group.count }}
|
|
113
|
+
</div>
|
|
114
|
+
</div>
|
|
115
|
+
</v-card-text>
|
|
116
|
+
</v-card>
|
|
117
|
+
</v-col>
|
|
118
|
+
</v-row>
|
|
119
|
+
</v-card-text>
|
|
120
|
+
</v-card>
|
|
121
|
+
</template>
|
|
122
|
+
|
|
123
|
+
<style scoped>
|
|
124
|
+
.role-card {
|
|
125
|
+
transition: transform 0.2s ease-in-out, box-shadow 0.2s ease-in-out;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
.role-card:hover {
|
|
129
|
+
transform: translateY(-2px);
|
|
130
|
+
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.12) !important;
|
|
131
|
+
}
|
|
132
|
+
</style>
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
import {EntityCrud} from "@drax/crud-vue";
|
|
2
|
+
import type {
|
|
3
|
+
IDraxCrudProvider,
|
|
4
|
+
IEntityCrud,
|
|
5
|
+
IEntityCrudField,
|
|
6
|
+
IEntityCrudFilter,
|
|
7
|
+
IEntityCrudHeader,
|
|
8
|
+
IEntityCrudPermissions,
|
|
9
|
+
IEntityCrudRefs,
|
|
10
|
+
IEntityCrudRules
|
|
11
|
+
} from "@drax/crud-share";
|
|
12
|
+
import {UserLoginFailSystemFactory} from "@drax/identity-front";
|
|
13
|
+
|
|
14
|
+
//Import EntityCrud Refs
|
|
15
|
+
import {UserCrud} from "@drax/identity-vue"
|
|
16
|
+
|
|
17
|
+
class UserLoginFailCrud extends EntityCrud implements IEntityCrud {
|
|
18
|
+
|
|
19
|
+
static singleton: UserLoginFailCrud
|
|
20
|
+
|
|
21
|
+
constructor() {
|
|
22
|
+
super();
|
|
23
|
+
this.name = 'UserLoginFail'
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
static get instance(): UserLoginFailCrud {
|
|
27
|
+
if (!UserLoginFailCrud.singleton) {
|
|
28
|
+
UserLoginFailCrud.singleton = new UserLoginFailCrud()
|
|
29
|
+
}
|
|
30
|
+
return UserLoginFailCrud.singleton
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
get permissions(): IEntityCrudPermissions {
|
|
34
|
+
return {
|
|
35
|
+
manage: 'userloginfail:manage',
|
|
36
|
+
view: 'userloginfail:view',
|
|
37
|
+
create: 'userloginfail:create',
|
|
38
|
+
update: 'userloginfail:update',
|
|
39
|
+
delete: 'userloginfail:delete'
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
get headers(): IEntityCrudHeader[] {
|
|
44
|
+
return [
|
|
45
|
+
{title: 'username', key: 'username', align: 'start'},
|
|
46
|
+
{title: 'userAgent', key: 'userAgent', align: 'start'},
|
|
47
|
+
{title: 'ip', key: 'ip', align: 'start'},
|
|
48
|
+
{title: 'createdAt', key: 'createdAt', align: 'start'}
|
|
49
|
+
]
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
get selectedHeaders(): string[] {
|
|
53
|
+
return this.headers.map(header => header.key)
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
get actionHeaders(): IEntityCrudHeader[] {
|
|
57
|
+
return [
|
|
58
|
+
{
|
|
59
|
+
title: 'action.actions',
|
|
60
|
+
key: 'actions',
|
|
61
|
+
sortable: false,
|
|
62
|
+
align: 'center',
|
|
63
|
+
minWidth: '190px'
|
|
64
|
+
},
|
|
65
|
+
]
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
get provider(): IDraxCrudProvider<any, any, any> {
|
|
69
|
+
return UserLoginFailSystemFactory.getInstance()
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
get refs(): IEntityCrudRefs {
|
|
73
|
+
return {
|
|
74
|
+
User: UserCrud.instance
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
get rules(): IEntityCrudRules {
|
|
79
|
+
return {
|
|
80
|
+
user: [(v: any) => !!v || 'validation.required'],
|
|
81
|
+
agent: [],
|
|
82
|
+
ip: [],
|
|
83
|
+
createdAt: []
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
get fields(): IEntityCrudField[] {
|
|
88
|
+
return [
|
|
89
|
+
{name: 'username', type: 'string', label: 'username', default: null},
|
|
90
|
+
{name: 'userAgent', type: 'string', label: 'userAgent', default: ''},
|
|
91
|
+
{name: 'ip', type: 'string', label: 'ip', default: ''},
|
|
92
|
+
{name: 'createdAt', type: 'date', label: 'createdAt', default: null}
|
|
93
|
+
]
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
get filters(): IEntityCrudFilter[] {
|
|
97
|
+
return [
|
|
98
|
+
{name: 'createdAt', type: 'date', label: 'createdAt', default: '', operator: 'gte' },
|
|
99
|
+
{name: 'createdAt', type: 'date', label: 'createdAt', default: '', operator: 'lte' },
|
|
100
|
+
{name: 'username', type: 'string', label: 'username', default: '', operator: 'eq' },
|
|
101
|
+
{name: 'userAgent', type: 'string', label: 'userAgent', default: '', operator: 'eq' },
|
|
102
|
+
{name: 'ip', type: 'string', label: 'ip', default: '', operator: 'eq' },
|
|
103
|
+
|
|
104
|
+
]
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
get searchEnable(){
|
|
108
|
+
return false
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
get isViewable() {
|
|
112
|
+
return true
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
get isEditable() {
|
|
116
|
+
return false
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
get isCreatable() {
|
|
120
|
+
return false
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
get isDeletable() {
|
|
124
|
+
return false
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
get isExportable() {
|
|
128
|
+
return true
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
get exportFormats() {
|
|
132
|
+
return ['CSV', 'JSON']
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
get exportHeaders() {
|
|
136
|
+
return ['_id','username','createdAt','userAgent','ip']
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
get isImportable() {
|
|
140
|
+
return false
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
get isColumnSelectable() {
|
|
144
|
+
return true
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
get isGroupable() {
|
|
148
|
+
return true
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
get importFormats() {
|
|
152
|
+
return ['CSV', 'JSON']
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
get dialogFullscreen() {
|
|
156
|
+
return false
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
get tabs() {
|
|
160
|
+
return []
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
get menus() {
|
|
164
|
+
return []
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
export default UserLoginFailCrud
|
|
171
|
+
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
import {EntityCrud} from "@drax/crud-vue";
|
|
2
|
+
import type {
|
|
3
|
+
IDraxCrudProvider,
|
|
4
|
+
IEntityCrud,
|
|
5
|
+
IEntityCrudField,
|
|
6
|
+
IEntityCrudFilter,
|
|
7
|
+
IEntityCrudHeader,
|
|
8
|
+
IEntityCrudPermissions,
|
|
9
|
+
IEntityCrudRefs,
|
|
10
|
+
IEntityCrudRules
|
|
11
|
+
} from "@drax/crud-share";
|
|
12
|
+
import {UserSessionSystemFactory} from "@drax/identity-front";
|
|
13
|
+
|
|
14
|
+
//Import EntityCrud Refs
|
|
15
|
+
import {UserCrud} from "@drax/identity-vue"
|
|
16
|
+
|
|
17
|
+
class UserSessionCrud extends EntityCrud implements IEntityCrud {
|
|
18
|
+
|
|
19
|
+
static singleton: UserSessionCrud
|
|
20
|
+
|
|
21
|
+
constructor() {
|
|
22
|
+
super();
|
|
23
|
+
this.name = 'UserSession'
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
static get instance(): UserSessionCrud {
|
|
27
|
+
if (!UserSessionCrud.singleton) {
|
|
28
|
+
UserSessionCrud.singleton = new UserSessionCrud()
|
|
29
|
+
}
|
|
30
|
+
return UserSessionCrud.singleton
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
get permissions(): IEntityCrudPermissions {
|
|
34
|
+
return {
|
|
35
|
+
manage: 'usersession:manage',
|
|
36
|
+
view: 'usersession:view',
|
|
37
|
+
create: 'usersession:create',
|
|
38
|
+
update: 'usersession:update',
|
|
39
|
+
delete: 'usersession:delete'
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
get headers(): IEntityCrudHeader[] {
|
|
44
|
+
return [
|
|
45
|
+
{title: 'uuid', key: 'uuid', align: 'start'},
|
|
46
|
+
{title: 'user', key: 'user', align: 'start'},
|
|
47
|
+
{title: 'agent', key: 'agent', align: 'start'},
|
|
48
|
+
{title: 'ip', key: 'ip', align: 'start'},
|
|
49
|
+
{title: 'createdAt', key: 'createdAt', align: 'start'}
|
|
50
|
+
]
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
get selectedHeaders(): string[] {
|
|
54
|
+
return this.headers.map(header => header.key)
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
get actionHeaders(): IEntityCrudHeader[] {
|
|
58
|
+
return [
|
|
59
|
+
{
|
|
60
|
+
title: 'action.actions',
|
|
61
|
+
key: 'actions',
|
|
62
|
+
sortable: false,
|
|
63
|
+
align: 'center',
|
|
64
|
+
minWidth: '190px'
|
|
65
|
+
},
|
|
66
|
+
]
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
get provider(): IDraxCrudProvider<any, any, any> {
|
|
70
|
+
return UserSessionSystemFactory.getInstance()
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
get refs(): IEntityCrudRefs {
|
|
74
|
+
return {
|
|
75
|
+
User: UserCrud.instance
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
get rules(): IEntityCrudRules {
|
|
80
|
+
return {
|
|
81
|
+
uuid: [(v: any) => !!v || 'validation.required'],
|
|
82
|
+
user: [(v: any) => !!v || 'validation.required'],
|
|
83
|
+
agent: [],
|
|
84
|
+
ip: [],
|
|
85
|
+
createdAt: []
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
get fields(): IEntityCrudField[] {
|
|
90
|
+
return [
|
|
91
|
+
{name: 'uuid', type: 'string', label: 'uuid', default: ''},
|
|
92
|
+
{name: 'user', type: 'ref', label: 'user', default: null, ref: 'User', refDisplay: 'username'},
|
|
93
|
+
{name: 'agent', type: 'string', label: 'agent', default: ''},
|
|
94
|
+
{name: 'ip', type: 'string', label: 'ip', default: ''},
|
|
95
|
+
{name: 'createdAt', type: 'date', label: 'createdAt', default: null}
|
|
96
|
+
]
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
get filters(): IEntityCrudFilter[] {
|
|
100
|
+
return [
|
|
101
|
+
{name: 'createdAt', type: 'date', label: 'createdAt', default: '', operator: 'gte' },
|
|
102
|
+
{name: 'createdAt', type: 'date', label: 'createdAt', default: '', operator: 'lte' },
|
|
103
|
+
{name: 'user', type: 'ref', ref: 'User', refDisplay:"username", label: 'User', default: '', operator: 'eq' },
|
|
104
|
+
{name: 'userAgent', type: 'string', label: 'userAgent', default: '', operator: 'eq' },
|
|
105
|
+
{name: 'ip', type: 'string', label: 'ip', default: '', operator: 'eq' },
|
|
106
|
+
|
|
107
|
+
]
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
get searchEnable(){
|
|
111
|
+
return false
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
get isViewable() {
|
|
115
|
+
return true
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
get isEditable() {
|
|
119
|
+
return false
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
get isCreatable() {
|
|
123
|
+
return false
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
get isDeletable() {
|
|
127
|
+
return false
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
get isExportable() {
|
|
131
|
+
return true
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
get exportFormats() {
|
|
135
|
+
return ['CSV', 'JSON']
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
get exportHeaders() {
|
|
139
|
+
return ['_id','user','createdAt','userAgent','ip']
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
get isImportable() {
|
|
143
|
+
return false
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
get isColumnSelectable() {
|
|
147
|
+
return true
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
get isGroupable() {
|
|
151
|
+
return true
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
get importFormats() {
|
|
155
|
+
return ['CSV', 'JSON']
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
get dialogFullscreen() {
|
|
159
|
+
return false
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
get tabs() {
|
|
163
|
+
return []
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
get menus() {
|
|
167
|
+
return []
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
export default UserSessionCrud
|
|
174
|
+
|
|
@@ -59,6 +59,8 @@ class RoleCrud extends EntityCrud implements IEntityCrud {
|
|
|
59
59
|
get fields(): IEntityCrudField[]{
|
|
60
60
|
return [
|
|
61
61
|
{name: 'name', type: 'string', label: 'name', default:'', prependInnerIcon:'mdi-text-short' },
|
|
62
|
+
{name: 'icon', type: 'string', label: 'icon', default:'', prependInnerIcon:'mdi-simple-icons' },
|
|
63
|
+
{name: 'color', type: 'string', label: 'color', default:'', prependInnerIcon:'mdi-palette' },
|
|
62
64
|
{name: 'childRoles', type: 'array.ref', ref:'Role', refDisplay: 'name', label: 'childRoles', default:[], prependInnerIcon:'mdi-text-short' },
|
|
63
65
|
{name: 'permissions', type: 'array.string', label: 'childRoles', default:[], prependInnerIcon:'mdi-text-short' }
|
|
64
66
|
]
|
|
@@ -75,7 +77,7 @@ class RoleCrud extends EntityCrud implements IEntityCrud {
|
|
|
75
77
|
}
|
|
76
78
|
|
|
77
79
|
get exportHeaders(){
|
|
78
|
-
return ['id', 'name','permissions','childRoles','readonly']
|
|
80
|
+
return ['id', 'name','icon','color','permissions','childRoles','readonly']
|
|
79
81
|
}
|
|
80
82
|
|
|
81
83
|
get isExportable(){
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import {useFormUtils, useCrudStore} from "@drax/crud-vue";
|
|
3
3
|
import {computed, defineEmits, defineModel, ref} from "vue";
|
|
4
|
-
import {useI18nValidation} from "@drax/common-vue";
|
|
4
|
+
import {useI18nValidation, IconCombobox, ColorCombobox} from "@drax/common-vue";
|
|
5
5
|
import PermissionSelector from "../../components/PermissionSelector/PermissionSelector.vue";
|
|
6
6
|
import RoleCombobox from "../../combobox/RoleCombobox.vue";
|
|
7
7
|
import {useIdentityCrudStore} from "../../stores/IdentityCrudStore";
|
|
@@ -89,6 +89,10 @@ const {
|
|
|
89
89
|
:clearable="false"
|
|
90
90
|
></v-text-field>
|
|
91
91
|
|
|
92
|
+
|
|
93
|
+
<icon-combobox v-model="valueModel.icon"></icon-combobox>
|
|
94
|
+
<color-combobox v-model="valueModel.color"></color-combobox>
|
|
95
|
+
|
|
92
96
|
<RoleCombobox
|
|
93
97
|
v-model="valueModel.childRoles"
|
|
94
98
|
label="role.field.childRoles"
|
|
@@ -42,12 +42,14 @@ class UserCrud extends EntityCrud implements IEntityCrud {
|
|
|
42
42
|
return import.meta.env.VITE_DRAX_TENANT === 'ENABLE'
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
+
|
|
45
46
|
get headers():IEntityCrudHeader[] {
|
|
46
47
|
return [
|
|
48
|
+
{ title: '', key: 'avatar', align: 'start', width:'50px' },
|
|
47
49
|
{ title: 'name', key: 'name', align: 'start' },
|
|
48
50
|
{ title: 'username', key: 'username', align: 'start' },
|
|
49
51
|
{ title: 'email', key: 'email', align: 'start' },
|
|
50
|
-
{ title: 'role', key: 'role
|
|
52
|
+
{ title: 'role', key: 'role', align: 'start' },
|
|
51
53
|
...(this.isTenantEnabled ? [{ title: 'tenant', key: 'tenant.name', align: 'start' as const }] : []),
|
|
52
54
|
{ title: 'active', key: 'active', align: 'start' },
|
|
53
55
|
]
|
|
@@ -76,8 +78,8 @@ class UserCrud extends EntityCrud implements IEntityCrud {
|
|
|
76
78
|
{name: 'username', type: 'string', label: 'username', default:'' },
|
|
77
79
|
{name: 'email', type: 'string', label: 'email', default:'' },
|
|
78
80
|
{name: 'phone', type: 'string', label: 'phone', default:'' },
|
|
79
|
-
{name: 'role', type: 'ref', ref: 'role', label: 'role', default:null },
|
|
80
|
-
{name: 'tenant', type: 'ref', ref: 'tenant', label: 'tenant', default:null, permission: 'tenant:manage' },
|
|
81
|
+
{name: 'role', type: 'ref', ref: 'role', refDisplay:'name', label: 'role', default:null },
|
|
82
|
+
{name: 'tenant', type: 'ref', ref: 'tenant', refDisplay:'name', label: 'tenant', default:null, permission: 'tenant:manage' },
|
|
81
83
|
{name: 'active', type: 'boolean', label: 'active', default:true },
|
|
82
84
|
|
|
83
85
|
]
|
|
@@ -139,6 +141,9 @@ class UserCrud extends EntityCrud implements IEntityCrud {
|
|
|
139
141
|
return false
|
|
140
142
|
}
|
|
141
143
|
|
|
144
|
+
get containerFluid(): boolean{
|
|
145
|
+
return true
|
|
146
|
+
}
|
|
142
147
|
}
|
|
143
148
|
|
|
144
149
|
export default UserCrud
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
|
|
2
|
+
const messages = {
|
|
3
|
+
en: {
|
|
4
|
+
|
|
5
|
+
userloginfail: {
|
|
6
|
+
entity: 'UserLoginFail',
|
|
7
|
+
menu: 'UserLoginFail',
|
|
8
|
+
crud: 'Manage UserLoginFail',
|
|
9
|
+
field:{
|
|
10
|
+
user:'user',
|
|
11
|
+
agent:'agent',
|
|
12
|
+
ip:'ip',
|
|
13
|
+
createdAt:'createdAt'
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
permission: {
|
|
17
|
+
'userloginfail:view': 'View UserLoginFail',
|
|
18
|
+
'userloginfail:create': 'Create UserLoginFail',
|
|
19
|
+
'userloginfail:update': 'Edit UserLoginFail',
|
|
20
|
+
'userloginfail:delete': 'Delete UserLoginFail',
|
|
21
|
+
'userloginfail:manage': 'Manage UserLoginFail',
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
es: {
|
|
25
|
+
userloginfail: {
|
|
26
|
+
entity: 'UserLoginFail',
|
|
27
|
+
menu: 'UserLoginFail',
|
|
28
|
+
crud: 'Gestionar UserLoginFail',
|
|
29
|
+
field:{
|
|
30
|
+
user:'user',
|
|
31
|
+
agent:'agent',
|
|
32
|
+
ip:'ip',
|
|
33
|
+
createdAt:'createdAt'
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
permission: {
|
|
37
|
+
'userloginfail:view': 'Ver UserLoginFail',
|
|
38
|
+
'userloginfail:create': 'Crear UserLoginFail',
|
|
39
|
+
'userloginfail:update': 'Editar UserLoginFail',
|
|
40
|
+
'userloginfail:delete': 'Eliminar UserLoginFail',
|
|
41
|
+
'userloginfail:manage': 'Gestionar UserLoginFail',
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export default messages;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
|
|
2
|
+
const messages = {
|
|
3
|
+
en: {
|
|
4
|
+
|
|
5
|
+
usersession: {
|
|
6
|
+
entity: 'UserSession',
|
|
7
|
+
menu: 'UserSession',
|
|
8
|
+
crud: 'Manage UserSession',
|
|
9
|
+
field:{
|
|
10
|
+
uuid:'uuid',
|
|
11
|
+
user:'user',
|
|
12
|
+
agent:'agent',
|
|
13
|
+
ip:'ip',
|
|
14
|
+
createdAt:'createdAt'
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
permission: {
|
|
18
|
+
'usersession:view': 'View UserSession',
|
|
19
|
+
'usersession:create': 'Create UserSession',
|
|
20
|
+
'usersession:update': 'Edit UserSession',
|
|
21
|
+
'usersession:delete': 'Delete UserSession',
|
|
22
|
+
'usersession:manage': 'Manage UserSession',
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
es: {
|
|
26
|
+
usersession: {
|
|
27
|
+
entity: 'UserSession',
|
|
28
|
+
menu: 'UserSession',
|
|
29
|
+
crud: 'Gestionar UserSession',
|
|
30
|
+
field:{
|
|
31
|
+
uuid:'uuid',
|
|
32
|
+
user:'user',
|
|
33
|
+
agent:'agent',
|
|
34
|
+
ip:'ip',
|
|
35
|
+
createdAt:'createdAt'
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
permission: {
|
|
39
|
+
'usersession:view': 'Ver UserSession',
|
|
40
|
+
'usersession:create': 'Crear UserSession',
|
|
41
|
+
'usersession:update': 'Editar UserSession',
|
|
42
|
+
'usersession:delete': 'Eliminar UserSession',
|
|
43
|
+
'usersession:manage': 'Gestionar UserSession',
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export default messages;
|
package/src/index.ts
CHANGED
|
@@ -26,6 +26,10 @@ import UserApiKeyCreated from "./cruds/user-api-key-crud/UserApiKeyCreated.vue";
|
|
|
26
26
|
import UserApiKeyView from "./views/UserApiKeyView.vue";
|
|
27
27
|
import UserApiKeyCrudPage from "./pages/crud/UserApiKeyCrudPage.vue";
|
|
28
28
|
|
|
29
|
+
|
|
30
|
+
import UserLoginFailCrudPage from "./pages/crud/UserLoginFailCrudPage.vue";
|
|
31
|
+
import UserSessionCrudPage from "./pages/crud/UserSessionCrudPage.vue";
|
|
32
|
+
|
|
29
33
|
import {useAuth} from "./composables/useAuth.js";
|
|
30
34
|
import {useUser} from "./composables/useUser.js";
|
|
31
35
|
import {useRole} from "./composables/useRole.js";
|
|
@@ -65,6 +69,9 @@ export {
|
|
|
65
69
|
ProfilePage,
|
|
66
70
|
PasswordPage,
|
|
67
71
|
|
|
72
|
+
UserLoginFailCrudPage,
|
|
73
|
+
UserSessionCrudPage,
|
|
74
|
+
|
|
68
75
|
//User
|
|
69
76
|
UserView,
|
|
70
77
|
UserForm,
|
|
@@ -8,6 +8,7 @@ import PasswordUpdateButton from "../../cruds/user-crud/PasswordUpdateButton.vue
|
|
|
8
8
|
import UserPasswordDialog from "../../cruds/user-crud/UserPasswordDialog.vue";
|
|
9
9
|
import type {IUser} from "@drax/identity-share";
|
|
10
10
|
import {useIdentityCrudStore} from "../../stores/IdentityCrudStore"
|
|
11
|
+
import IdentityUserGroupBy from "../../components/IdentityUserGroupBy/IdentityUserGroupBy.vue";
|
|
11
12
|
|
|
12
13
|
const identityCrudStore = useIdentityCrudStore();
|
|
13
14
|
|
|
@@ -24,16 +25,20 @@ function onChangePassword(user:IUser){
|
|
|
24
25
|
dialogPassword.value = true;
|
|
25
26
|
}
|
|
26
27
|
|
|
28
|
+
const roleDashboard = import.meta.env.VITE_DRAX_USER_ROLE_DASHBOARD === 'ENABLE'
|
|
29
|
+
|
|
27
30
|
</script>
|
|
28
31
|
|
|
29
32
|
<template>
|
|
30
|
-
<
|
|
33
|
+
<v-container fluid>
|
|
31
34
|
<user-password-dialog
|
|
32
35
|
v-if="dialogPassword && userSelected"
|
|
33
36
|
v-model="dialogPassword"
|
|
34
37
|
:user="userSelected"
|
|
35
38
|
/>
|
|
36
39
|
|
|
40
|
+
<identity-user-group-by v-if="roleDashboard"></identity-user-group-by>
|
|
41
|
+
|
|
37
42
|
<crud :entity="identityCrudStore.userCrud">
|
|
38
43
|
|
|
39
44
|
<template v-slot:form>
|
|
@@ -44,6 +49,17 @@ function onChangePassword(user:IUser){
|
|
|
44
49
|
/>
|
|
45
50
|
</template>
|
|
46
51
|
|
|
52
|
+
<template v-slot:item.avatar="{ item }">
|
|
53
|
+
<v-avatar>
|
|
54
|
+
<v-img v-if="item.avatar" :src="item.avatar"></v-img>
|
|
55
|
+
<v-icon v-else size="50">mdi-account-circle</v-icon>
|
|
56
|
+
</v-avatar>
|
|
57
|
+
</template>
|
|
58
|
+
|
|
59
|
+
<template v-slot:item.role="{ item }">
|
|
60
|
+
<v-chip variant="outlined" :color="item.role.color"> <v-icon v-if="item.role.icon" start>{{item.role.icon}}</v-icon>{{item.role.name}}</v-chip>
|
|
61
|
+
</template>
|
|
62
|
+
|
|
47
63
|
|
|
48
64
|
|
|
49
65
|
<template v-slot:item.actions="{ item }">
|
|
@@ -59,7 +75,7 @@ function onChangePassword(user:IUser){
|
|
|
59
75
|
</v-chip>
|
|
60
76
|
</template>
|
|
61
77
|
</crud>
|
|
62
|
-
</
|
|
78
|
+
</v-container>
|
|
63
79
|
|
|
64
80
|
</template>
|
|
65
81
|
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
|
|
2
|
+
<script setup lang="ts">
|
|
3
|
+
import UserLoginFailCrud from '../../cruds/UserLoginFailCrud'
|
|
4
|
+
import {Crud} from "@drax/crud-vue";
|
|
5
|
+
import {formatDateTime} from "@drax/common-front"
|
|
6
|
+
|
|
7
|
+
</script>
|
|
8
|
+
|
|
9
|
+
<template>
|
|
10
|
+
<crud :entity="UserLoginFailCrud.instance">
|
|
11
|
+
<template v-slot:item.user="{value}">{{value?.username}}</template>
|
|
12
|
+
<template v-slot:item.createdAt="{value}">{{formatDateTime(value)}}</template>
|
|
13
|
+
</crud>
|
|
14
|
+
</template>
|
|
15
|
+
|
|
16
|
+
<style scoped>
|
|
17
|
+
|
|
18
|
+
</style>
|
|
19
|
+
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
|
|
2
|
+
<script setup lang="ts">
|
|
3
|
+
import UserSessionCrud from '../../cruds/UserSessionCrud'
|
|
4
|
+
import {Crud} from "@drax/crud-vue";
|
|
5
|
+
import {formatDateTime} from "@drax/common-front"
|
|
6
|
+
|
|
7
|
+
</script>
|
|
8
|
+
|
|
9
|
+
<template>
|
|
10
|
+
<crud :entity="UserSessionCrud.instance">
|
|
11
|
+
<template v-slot:item.user="{value}">{{value?.username}}</template>
|
|
12
|
+
<template v-slot:item.createdAt="{value}">{{formatDateTime(value)}}</template>
|
|
13
|
+
</crud>
|
|
14
|
+
</template>
|
|
15
|
+
|
|
16
|
+
<style scoped>
|
|
17
|
+
|
|
18
|
+
</style>
|
|
19
|
+
|
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
import IdentityCrudRoutes from './IdentityCrudRoutes'
|
|
2
2
|
import IdentityAuthRoutes from './IdentityAuthRoutes'
|
|
3
|
+
import UserLoginFailCrudRoute from './UserLoginFailCrudRoute'
|
|
4
|
+
import UserSessionCrudRoute from './UserSessionCrudRoute'
|
|
3
5
|
|
|
4
6
|
|
|
5
7
|
const routes = [
|
|
6
8
|
...IdentityAuthRoutes,
|
|
7
9
|
...IdentityCrudRoutes,
|
|
10
|
+
...UserLoginFailCrudRoute,
|
|
11
|
+
...UserSessionCrudRoute
|
|
8
12
|
]
|
|
9
13
|
|
|
10
14
|
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
|
|
2
|
+
import UserLoginFailCrudPage from "../pages/crud/UserLoginFailCrudPage.vue";
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
const UserLoginFailCrudRoute = [
|
|
6
|
+
{
|
|
7
|
+
name: 'UserLoginFailCrudPage',
|
|
8
|
+
path: '/identity/user-login-fail',
|
|
9
|
+
component: UserLoginFailCrudPage,
|
|
10
|
+
meta: {
|
|
11
|
+
auth: true,
|
|
12
|
+
permission: 'userloginfail:manage',
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
]
|
|
16
|
+
|
|
17
|
+
export default UserLoginFailCrudRoute
|
|
18
|
+
export { UserLoginFailCrudRoute }
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
|
|
2
|
+
import UserSessionCrudPage from "../pages/crud/UserSessionCrudPage.vue";
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
const UserSessionCrudRoute = [
|
|
6
|
+
{
|
|
7
|
+
name: 'UserSessionCrudPage',
|
|
8
|
+
path: '/identity/user-session',
|
|
9
|
+
component: UserSessionCrudPage,
|
|
10
|
+
meta: {
|
|
11
|
+
auth: true,
|
|
12
|
+
permission: 'usersession:manage',
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
]
|
|
16
|
+
|
|
17
|
+
export default UserSessionCrudRoute
|
|
18
|
+
export { UserSessionCrudRoute }
|