nuxt-users 1.23.1 → 1.25.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/CHANGELOG.md +41 -0
- package/dist/module.d.mts +1 -1
- package/dist/module.d.ts +1 -1
- package/dist/module.json +1 -1
- package/dist/module.mjs +4 -2
- package/dist/runtime/assets/nuxt-users.css +1 -1
- package/dist/runtime/components/NUsersList.vue +12 -4
- package/dist/runtime/components/NUsersList.vue.d.ts +6 -6
- package/dist/runtime/server/api/nuxt-users/me.patch.js +3 -0
- package/dist/runtime/server/utils/user.d.ts +3 -0
- package/dist/runtime/server/utils/user.js +9 -3
- package/dist/shared/{nuxt-users.CqP-FK1T.d.mts → nuxt-users.CydOpwYH.d.mts} +8 -0
- package/dist/shared/{nuxt-users.CqP-FK1T.d.ts → nuxt-users.CydOpwYH.d.ts} +8 -0
- package/dist/utils.d.mts +1 -1
- package/dist/utils.d.ts +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,47 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
3
|
|
|
4
|
+
## v1.25.0
|
|
5
|
+
|
|
6
|
+
[compare changes](https://github.com/rrd108/nuxt-users/compare/v1.24.0...v1.25.0)
|
|
7
|
+
|
|
8
|
+
### 🚀 Enhancements
|
|
9
|
+
|
|
10
|
+
- Remove user form view on deletion ([2066238](https://github.com/rrd108/nuxt-users/commit/2066238))
|
|
11
|
+
- Use soft delete by default ([5c9f0da](https://github.com/rrd108/nuxt-users/commit/5c9f0da))
|
|
12
|
+
|
|
13
|
+
### 🏡 Chore
|
|
14
|
+
|
|
15
|
+
- **release:** V1.24.0 ([ca9ee73](https://github.com/rrd108/nuxt-users/commit/ca9ee73))
|
|
16
|
+
|
|
17
|
+
### ❤️ Contributors
|
|
18
|
+
|
|
19
|
+
- Rrd108 ([@rrd108](https://github.com/rrd108))
|
|
20
|
+
|
|
21
|
+
## v1.24.0
|
|
22
|
+
|
|
23
|
+
[compare changes](https://github.com/rrd108/nuxt-users/compare/v1.23.1...v1.24.0)
|
|
24
|
+
|
|
25
|
+
### 🚀 Enhancements
|
|
26
|
+
|
|
27
|
+
- Remove user form view on deletion ([2066238](https://github.com/rrd108/nuxt-users/commit/2066238))
|
|
28
|
+
|
|
29
|
+
### 🩹 Fixes
|
|
30
|
+
|
|
31
|
+
- User patch sql error ([aa506dd](https://github.com/rrd108/nuxt-users/commit/aa506dd))
|
|
32
|
+
|
|
33
|
+
### 🏡 Chore
|
|
34
|
+
|
|
35
|
+
- **release:** V1.23.1 ([9b2ed06](https://github.com/rrd108/nuxt-users/commit/9b2ed06))
|
|
36
|
+
|
|
37
|
+
### ✅ Tests
|
|
38
|
+
|
|
39
|
+
- New test script added ([618b8dc](https://github.com/rrd108/nuxt-users/commit/618b8dc))
|
|
40
|
+
|
|
41
|
+
### ❤️ Contributors
|
|
42
|
+
|
|
43
|
+
- Rrd108 ([@rrd108](https://github.com/rrd108))
|
|
44
|
+
|
|
4
45
|
## v1.23.1
|
|
5
46
|
|
|
6
47
|
[compare changes](https://github.com/rrd108/nuxt-users/compare/v1.23.0...v1.23.1)
|
package/dist/module.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as _nuxt_schema from '@nuxt/schema';
|
|
2
|
-
import { R as RuntimeModuleOptions, M as ModuleOptions } from './shared/nuxt-users.
|
|
2
|
+
import { R as RuntimeModuleOptions, M as ModuleOptions } from './shared/nuxt-users.CydOpwYH.mjs';
|
|
3
3
|
export * from '../dist/runtime/server/internal/index.js';
|
|
4
4
|
|
|
5
5
|
declare const defaultOptions: ModuleOptions;
|
package/dist/module.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as _nuxt_schema from '@nuxt/schema';
|
|
2
|
-
import { R as RuntimeModuleOptions, M as ModuleOptions } from './shared/nuxt-users.
|
|
2
|
+
import { R as RuntimeModuleOptions, M as ModuleOptions } from './shared/nuxt-users.CydOpwYH.js';
|
|
3
3
|
export * from '../dist/runtime/server/internal/index.js';
|
|
4
4
|
|
|
5
5
|
declare const defaultOptions: ModuleOptions;
|
package/dist/module.json
CHANGED
package/dist/module.mjs
CHANGED
|
@@ -46,7 +46,8 @@ const defaultOptions = {
|
|
|
46
46
|
requireNumbers: true,
|
|
47
47
|
requireSpecialChars: true,
|
|
48
48
|
preventCommonPasswords: true
|
|
49
|
-
}
|
|
49
|
+
},
|
|
50
|
+
hardDelete: false
|
|
50
51
|
};
|
|
51
52
|
const module = defineNuxtModule({
|
|
52
53
|
meta: {
|
|
@@ -72,7 +73,8 @@ const module = defineNuxtModule({
|
|
|
72
73
|
whitelist: [...defaultOptions.auth?.whitelist || [], ...options.auth?.whitelist || []],
|
|
73
74
|
tokenExpiration: options.auth?.tokenExpiration || defaultOptions.auth.tokenExpiration,
|
|
74
75
|
permissions: options.auth?.permissions || defaultOptions.auth.permissions
|
|
75
|
-
}
|
|
76
|
+
},
|
|
77
|
+
hardDelete: options.hardDelete ?? defaultOptions.hardDelete
|
|
76
78
|
};
|
|
77
79
|
nuxt.options.runtimeConfig.public = nuxt.options.runtimeConfig.public || {};
|
|
78
80
|
nuxt.options.runtimeConfig.public.nuxtUsers = {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
:root{--nu-color-primary:#3b82f6;--nu-color-primary-dark:#2563eb;--nu-color-primary-light:#60a5fa;--nu-color-white:#fff;--nu-color-gray-50:#f9fafb;--nu-color-gray-500:#6b7280;--nu-color-gray-600:#4b5563;--nu-color-gray-700:#374151;--nu-color-gray-900:#111827;--nu-color-success:#059669;--nu-color-success-light:#f0fdf4;--nu-color-success-border:#9ae6b4;--nu-color-error:#dc2626;--nu-color-error-light:#fef2f2;--nu-color-error-border:#fecaca;--nu-color-error-alt:#db5050;--nu-color-error-dark:#b91c1c;--nu-color-border:#e5e7eb;--nu-color-border-light:#d1d5db;--nu-color-border-dark:#ccc;--nu-color-bg-primary:#fff;--nu-color-bg-secondary:#f9fafb;--nu-color-bg-tertiary:#f3f4f6;--nu-color-text-primary:#000;--nu-color-text-secondary:#6b7280;--nu-color-strength-bg:#e9ecef;--nu-color-validation-passed:#28a745;--nu-color-validation-failed:#dc3545;--nu-color-validation-hint:#6c757d}.dark :root{--nu-color-primary:#60a5fa;--nu-color-primary-dark:#3b82f6;--nu-color-primary-light:#93c5fd;--nu-color-white:#000;--nu-color-gray-50:#111827;--nu-color-gray-500:#9ca3af;--nu-color-gray-600:#d1d5db;--nu-color-gray-700:#e5e7eb;--nu-color-gray-900:#f9fafb;--nu-color-success:#10b981;--nu-color-success-light:#064e3b;--nu-color-success-border:#065f46;--nu-color-error:#ef4444;--nu-color-error-light:#450a0a;--nu-color-error-border:#7f1d1d;--nu-color-error-alt:#f87171;--nu-color-error-dark:#dc2626;--nu-color-border:#374151;--nu-color-border-light:#4b5563;--nu-color-border-dark:#6b7280;--nu-color-bg-primary:#111827;--nu-color-bg-secondary:#1f2937;--nu-color-bg-tertiary:#374151;--nu-color-text-primary:#fff;--nu-color-text-secondary:#9ca3af;--nu-color-strength-bg:#374151;--nu-color-validation-passed:#22c55e;--nu-color-validation-failed:#ef4444;--nu-color-validation-hint:#9ca3af}.n-users-form-group{display:flex;flex-direction:column;gap:.5rem;margin-bottom:1rem;width:100%}.n-users-form-group.n-users-form-group-narrow{width:90%}.n-users-form-group label,.n-users-form-label{color:var(--nu-color-text-primary,#000);display:block;font-size:1rem;font-weight:500;margin-bottom:.5rem}.n-users-form-group input,.n-users-form-group select,.n-users-form-input{border:1px solid var(--nu-color-border,#ccc);border-radius:.25rem;font-size:1rem;padding:.5rem;transition:border-color .2s,box-shadow .2s;width:100%}.n-users-form-group input:focus,.n-users-form-group select:focus,.n-users-form-input:focus{border-color:var(--nu-color-primary);box-shadow:0 0 0 .1rem rgba(59,130,246,.1);outline:none}.n-users-form-group input:disabled,.n-users-form-input:disabled{background-color:var(--nu-color-bg-secondary,#f9fafb);cursor:not-allowed}.n-users-form-group input.error,.n-users-form-input.error{border-color:var(--nu-color-error,#dc3545)}.n-users-form-group input[type=email],.n-users-form-group input[type=password],.n-users-form-group input[type=text]{background-color:var(--nu-color-bg-secondary);border:1px solid var(--nu-color-border-light);border-radius:.5em;box-sizing:border-box;color:var(--nu-color-gray-700);font-size:.875rem;padding:.75em 1em;transition:all .2s ease-in-out;width:100%}.n-users-form-group input[type=email]:focus,.n-users-form-group input[type=password]:focus,.n-users-form-group input[type=text]:focus{background-color:var(--nu-color-bg-primary);border-color:var(--nu-color-primary);box-shadow:0 0 0 3px rgba(59,130,246,.1);outline:none}.n-users-form-group input[type=checkbox]{margin:0;width:auto}.n-users-btn,.n-users-cancel-btn,.n-users-delete-btn,.n-users-edit-btn,.n-users-submit-btn{align-self:flex-start;border:none;border-radius:.25rem;cursor:pointer;display:inline-block;font-size:1rem;font-weight:500;padding:.5rem 1rem;text-decoration:none;transition:background-color .2s,transform .1s}.n-users-btn:hover,.n-users-edit-btn:hover,.n-users-submit-btn:hover{background-color:var(--nu-color-primary-dark,#2563eb);transform:translateY(-1px)}.n-users-btn:disabled,.n-users-submit-btn:disabled{cursor:not-allowed;opacity:.6;transform:none}.n-users-btn-primary,.n-users-edit-btn,.n-users-submit-btn{background-color:var(--nu-color-primary,#3b82f6);color:#fff}.n-users-btn-secondary,.n-users-cancel-btn{background-color:var(--nu-color-gray-500,#6b7280);color:#fff}.n-users-cancel-btn:hover{background-color:var(--nu-color-gray-600,#4b5563)}.n-users-delete-btn{background-color:var(--nu-color-error,#ef4444);color:#fff}.n-users-delete-btn:hover{background-color:var(--nu-color-error-alt,#dc2626)}button[type=submit]{align-items:center;background-color:var(--nu-color-primary);border:1px solid var(--nu-color-primary);border-radius:.5em;color:var(--nu-color-white);cursor:pointer;display:flex;font-size:.875rem;font-weight:500;gap:.5rem;justify-content:center;min-height:44px;padding:.75em 1em;transition:all .2s ease-in-out;width:100%}button[type=submit]:hover:not(:disabled){background-color:var(--nu-color-primary-dark);border-color:var(--nu-color-primary-dark)}button[type=submit]:disabled{cursor:not-allowed;opacity:.6}.n-users-error-message,.n-users-error-text{background-color:var(--nu-color-error-light,#fef2f2);border:1px solid var(--nu-color-error-border,#fecaca);border-radius:.5rem;color:var(--nu-color-error,#dc3545);font-size:.875rem;margin-top:.5rem;padding:.75rem 1rem}.n-users-success-message{background-color:var(--nu-color-success-light,#f0fff4);border:1px solid var(--nu-color-success-border,#9ae6b4);border-radius:.5rem;color:var(--nu-color-success,#10b981);font-size:.875rem;margin-top:.5rem;padding:.75rem 1rem}.n-users-grid{display:grid;gap:1rem}.n-users-grid-2{grid-template-columns:1fr 5fr}.n-users-grid-auto{grid-template-columns:repeat(auto-fill,minmax(12em,1fr))}.n-users-form-actions{align-items:center;display:flex;gap:1rem;margin-top:1.5rem}.n-users-loading-spinner{animation:n-users-spin 1s linear infinite;border:2px solid var(--nu-color-white,#fff);border-radius:50%;border-top:2px solid transparent;height:16px;width:16px}@keyframes n-users-spin{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}.n-users-card{background-color:var(--nu-color-bg-primary,#fff);border:1px solid var(--nu-color-border,#e5e7eb);border-radius:.5rem;padding:1rem}.n-users-section{margin:0 auto;max-width:42em;padding:1em}.n-users-section-header{border-bottom:.1em solid var(--nu-color-border,#e5e7eb);margin-bottom:1rem;padding-bottom:.5rem}.n-users-form-help{color:var(--nu-color-text-secondary,#6b7280);font-size:.75rem;margin-top:.25rem}.n-users-strength-bar{background-color:var(--nu-color-strength-bg,#e9ecef);border-radius:2px;height:4px;margin-bottom:4px;overflow:hidden;width:100%}.n-users-strength-fill{height:100%;transition:width .3s ease,background-color .3s ease}.n-users-strength-text{font-size:.75rem;font-weight:500}.n-users-validation-container{background-color:#f8f9fa;border:1px solid #e9ecef;border-radius:4px;margin-top:12px;padding:12px}.n-users-container-title{color:#495057;font-size:.875rem;font-weight:600;margin-bottom:8px}.n-users-list-unstyled{list-style:none;margin:0;padding-left:0}.n-users-list-item{align-items:center;display:flex;font-size:.875rem;margin-bottom:6px;transition:color .2s ease}.n-users-list-item:last-child{margin-bottom:0}.n-users-icon{font-weight:700;margin-right:8px;min-width:16px;text-align:center}.n-users-text{flex:1}.n-users-list ul{list-style:none}form{display:flex;flex-direction:column;gap:1.5rem}.n-users-login-section{background:linear-gradient(135deg,var(--nu-color-bg-primary) 0,var(--nu-color-bg-secondary) 100%);border:1px solid var(--nu-color-border);border-radius:.75em;box-shadow:0 4px 6px -1px rgba(0,0,0,.1),0 2px 4px -1px rgba(0,0,0,.06);max-width:25rem}.n-users-login-header{margin-bottom:1em;text-align:center}.n-users-login-title{color:var(--nu-color-gray-700);font-size:1.875rem;font-weight:700;line-height:1.2;margin:0 0 .5em}.n-users-login-subtitle{color:var(--nu-color-gray-700);font-size:.875rem;line-height:1.5;margin:0}.n-users-remember-me{align-items:center;display:flex;gap:.5rem}.n-users-remember-me label{color:var(--nu-color-gray-700);font-size:.875rem;margin:0}.n-users-login-footer{margin-top:1em;text-align:center}.n-users-forgot-password{margin:0}.n-users-forgot-link{align-items:center;color:var(--nu-color-primary);display:inline-flex;font-size:.875rem;gap:.5rem;text-decoration:none;transition:color .2s ease-in-out}.n-users-forgot-link:hover:not(.loading){color:var(--nu-color-primary-dark);text-decoration:underline}.n-users-forgot-link.loading{cursor:not-allowed;opacity:.6;pointer-events:none}.n-users-password-strength{margin-top:8px}.n-users-validation-rules{margin-top:12px}.n-users-rules-title{margin-bottom:8px}.n-users-rules-list{padding-left:0}.n-users-rule-item{margin-bottom:6px}.n-users-rule-item:last-child{margin-bottom:0}.n-users-rule-passed{color:var(--nu-color-validation-passed,#28a745)}.n-users-rule-failed{color:var(--nu-color-validation-failed,#dc3545)}.n-users-rule-icon{margin-right:8px}.n-users-rule-text{flex:1}.n-users-validation-errors{margin-top:8px}.n-users-error-text:last-child{margin-bottom:0}.n-users-password-hints{margin-top:8px}.n-users-hint-title{margin-bottom:8px}.n-users-hint-list{padding-left:16px}.n-users-hint-item{color:var(--nu-color-validation-hint,#6c757d);margin-bottom:4px}.n-users-hint-item:last-child{margin-bottom:0}.n-users-logout-link{background:var(--nu-color-error);border:2px solid transparent;border-color:var(--nu-color-error-dark);border-radius:.5em;color:#fff;padding:.5em 1em;text-decoration:none}.n-users-logout-link:hover{border-color:var(--nu-color-primary)}.n-users-user-card dd{margin:0}.n-users-user-card-actions{display:flex;gap:.5rem;margin-top:1rem}.n-users-user-form{margin:0 auto;max-width:500px}.n-users-form-group input.error{border-color:#dc3545}.n-users-profile-info{background-color:var(--nu-color-bg-primary);border-top-left-radius:.5em;border-top-right-radius:.5em}.n-users-profile-details{font-size:1rem;list-style:none;margin:0;padding:0}.n-users-reset-password-container{background-color:var(--nu-color-bg-primary);border-bottom-left-radius:.5em;border-bottom-right-radius:.5em}@media (max-width:480px){.n-users-login-title{font-size:1.5rem}}
|
|
1
|
+
:root{--nu-color-primary:#3b82f6;--nu-color-primary-dark:#2563eb;--nu-color-primary-light:#60a5fa;--nu-color-white:#fff;--nu-color-gray-50:#f9fafb;--nu-color-gray-500:#6b7280;--nu-color-gray-600:#4b5563;--nu-color-gray-700:#374151;--nu-color-gray-900:#111827;--nu-color-success:#059669;--nu-color-success-light:#f0fdf4;--nu-color-success-border:#9ae6b4;--nu-color-error:#dc2626;--nu-color-error-light:#fef2f2;--nu-color-error-border:#fecaca;--nu-color-error-alt:#db5050;--nu-color-error-dark:#b91c1c;--nu-color-border:#e5e7eb;--nu-color-border-light:#d1d5db;--nu-color-border-dark:#ccc;--nu-color-bg-primary:#fff;--nu-color-bg-secondary:#f9fafb;--nu-color-bg-tertiary:#f3f4f6;--nu-color-text-primary:#000;--nu-color-text-secondary:#6b7280;--nu-color-strength-bg:#e9ecef;--nu-color-validation-passed:#28a745;--nu-color-validation-failed:#dc3545;--nu-color-validation-hint:#6c757d}.dark :root{--nu-color-primary:#60a5fa;--nu-color-primary-dark:#3b82f6;--nu-color-primary-light:#93c5fd;--nu-color-white:#000;--nu-color-gray-50:#111827;--nu-color-gray-500:#9ca3af;--nu-color-gray-600:#d1d5db;--nu-color-gray-700:#e5e7eb;--nu-color-gray-900:#f9fafb;--nu-color-success:#10b981;--nu-color-success-light:#064e3b;--nu-color-success-border:#065f46;--nu-color-error:#ef4444;--nu-color-error-light:#450a0a;--nu-color-error-border:#7f1d1d;--nu-color-error-alt:#f87171;--nu-color-error-dark:#dc2626;--nu-color-border:#374151;--nu-color-border-light:#4b5563;--nu-color-border-dark:#6b7280;--nu-color-bg-primary:#111827;--nu-color-bg-secondary:#1f2937;--nu-color-bg-tertiary:#374151;--nu-color-text-primary:#fff;--nu-color-text-secondary:#9ca3af;--nu-color-strength-bg:#374151;--nu-color-validation-passed:#22c55e;--nu-color-validation-failed:#ef4444;--nu-color-validation-hint:#9ca3af}.n-users-form-group{display:flex;flex-direction:column;gap:.5rem;margin-bottom:1rem;width:100%}.n-users-form-group.n-users-form-group-narrow{width:90%}.n-users-form-group label,.n-users-form-label{color:var(--nu-color-text-primary,#000);display:block;font-size:1rem;font-weight:500;margin-bottom:.5rem}.n-users-form-group input,.n-users-form-group select,.n-users-form-input{border:1px solid var(--nu-color-border,#ccc);border-radius:.25rem;font-size:1rem;padding:.5rem;transition:border-color .2s,box-shadow .2s;width:100%}.n-users-form-group input:focus,.n-users-form-group select:focus,.n-users-form-input:focus{border-color:var(--nu-color-primary);box-shadow:0 0 0 .1rem rgba(59,130,246,.1);outline:none}.n-users-form-group input:disabled,.n-users-form-input:disabled{background-color:var(--nu-color-bg-secondary,#f9fafb);cursor:not-allowed}.n-users-form-group input.error,.n-users-form-input.error{border-color:var(--nu-color-error,#dc3545)}.n-users-form-group input[type=email],.n-users-form-group input[type=password],.n-users-form-group input[type=text]{background-color:var(--nu-color-bg-secondary);border:1px solid var(--nu-color-border-light);border-radius:.5em;box-sizing:border-box;color:var(--nu-color-gray-700);font-size:.875rem;padding:.75em 1em;transition:all .2s ease-in-out;width:100%}.n-users-form-group input[type=email]:focus,.n-users-form-group input[type=password]:focus,.n-users-form-group input[type=text]:focus{background-color:var(--nu-color-bg-primary);border-color:var(--nu-color-primary);box-shadow:0 0 0 3px rgba(59,130,246,.1);outline:none}.n-users-form-group input[type=checkbox]{margin:0;width:auto}.n-users-btn,.n-users-cancel-btn,.n-users-delete-btn,.n-users-edit-btn,.n-users-submit-btn{align-self:flex-start;border:none;border-radius:.25rem;cursor:pointer;display:inline-block;font-size:1rem;font-weight:500;padding:.5rem 1rem;text-decoration:none;transition:background-color .2s,transform .1s}.n-users-btn:hover,.n-users-edit-btn:hover,.n-users-submit-btn:hover{background-color:var(--nu-color-primary-dark,#2563eb);transform:translateY(-1px)}.n-users-btn:disabled,.n-users-submit-btn:disabled{cursor:not-allowed;opacity:.6;transform:none}.n-users-btn-primary,.n-users-edit-btn,.n-users-submit-btn{background-color:var(--nu-color-primary,#3b82f6);color:#fff}.n-users-btn-secondary,.n-users-cancel-btn{background-color:var(--nu-color-gray-500,#6b7280);color:#fff}.n-users-cancel-btn:hover{background-color:var(--nu-color-gray-600,#4b5563)}.n-users-delete-btn{background-color:var(--nu-color-error,#ef4444);color:#fff}.n-users-delete-btn:hover{background-color:var(--nu-color-error-alt,#dc2626)}button[type=submit]{align-items:center;background-color:var(--nu-color-primary);border:1px solid var(--nu-color-primary);border-radius:.5em;color:var(--nu-color-white);cursor:pointer;display:flex;font-size:.875rem;font-weight:500;gap:.5rem;justify-content:center;min-height:44px;padding:.75em 1em;transition:all .2s ease-in-out;width:100%}button[type=submit]:hover:not(:disabled){background-color:var(--nu-color-primary-dark);border-color:var(--nu-color-primary-dark)}button[type=submit]:disabled{cursor:not-allowed;opacity:.6}.n-users-error-message,.n-users-error-text{background-color:var(--nu-color-error-light,#fef2f2);border:1px solid var(--nu-color-error-border,#fecaca);border-radius:.5rem;color:var(--nu-color-error,#dc3545);font-size:.875rem;margin-top:.5rem;padding:.75rem 1rem}.n-users-success-message{background-color:var(--nu-color-success-light,#f0fff4);border:1px solid var(--nu-color-success-border,#9ae6b4);border-radius:.5rem;color:var(--nu-color-success,#10b981);font-size:.875rem;margin-top:.5rem;padding:.75rem 1rem}.n-users-grid{display:grid;gap:1rem}.n-users-grid-2{grid-template-columns:1fr 5fr}.n-users-grid-auto{grid-template-columns:repeat(auto-fill,minmax(12em,1fr))}.n-users-form-actions{align-items:center;display:flex;gap:1rem;margin-top:1.5rem}.n-users-loading-spinner{animation:n-users-spin 1s linear infinite;border:2px solid var(--nu-color-white,#fff);border-radius:50%;border-top:2px solid transparent;height:16px;width:16px}@keyframes n-users-spin{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}.n-users-card{background-color:var(--nu-color-bg-primary,#fff);border:1px solid var(--nu-color-border,#e5e7eb);border-radius:.5rem;padding:1rem}.n-users-section{margin:0 auto;max-width:42em;padding:1em}.n-users-section-header{border-bottom:.1em solid var(--nu-color-border,#e5e7eb);margin-bottom:1rem;padding-bottom:.5rem}.n-users-form-help{color:var(--nu-color-text-secondary,#6b7280);font-size:.75rem;margin-top:.25rem}.n-users-strength-bar{background-color:var(--nu-color-strength-bg,#e9ecef);border-radius:2px;height:4px;margin-bottom:4px;overflow:hidden;width:100%}.n-users-strength-fill{height:100%;transition:width .3s ease,background-color .3s ease}.n-users-strength-text{font-size:.75rem;font-weight:500}.n-users-validation-container{background-color:#f8f9fa;border:1px solid #e9ecef;border-radius:4px;margin-top:12px;padding:12px}.n-users-container-title{color:#495057;font-size:.875rem;font-weight:600;margin-bottom:8px}.n-users-list-unstyled{list-style:none;margin:0;padding-left:0}.n-users-list-item{align-items:center;display:flex;font-size:.875rem;margin-bottom:6px;transition:color .2s ease}.n-users-list-item:last-child{margin-bottom:0}.n-users-icon{font-weight:700;margin-right:8px;min-width:16px;text-align:center}.n-users-text{flex:1}.n-users-list ul{list-style:none}form{display:flex;flex-direction:column;gap:1.5rem}.n-users-login-section{background:linear-gradient(135deg,var(--nu-color-bg-primary) 0,var(--nu-color-bg-secondary) 100%);border:1px solid var(--nu-color-border);border-radius:.75em;box-shadow:0 4px 6px -1px rgba(0,0,0,.1),0 2px 4px -1px rgba(0,0,0,.06);max-width:25rem}.n-users-login-header{margin-bottom:1em;text-align:center}.n-users-login-title{color:var(--nu-color-gray-700);font-size:1.875rem;font-weight:700;line-height:1.2;margin:0 0 .5em}.n-users-login-subtitle{color:var(--nu-color-gray-700);font-size:.875rem;line-height:1.5;margin:0}.n-users-remember-me{align-items:center;display:flex;gap:.5rem}.n-users-remember-me label{color:var(--nu-color-gray-700);font-size:.875rem;margin:0}.n-users-login-footer{margin-top:1em;text-align:center}.n-users-forgot-password{margin:0}.n-users-forgot-link{align-items:center;color:var(--nu-color-primary);display:inline-flex;font-size:.875rem;gap:.5rem;text-decoration:none;transition:color .2s ease-in-out}.n-users-forgot-link:hover:not(.loading){color:var(--nu-color-primary-dark);text-decoration:underline}.n-users-forgot-link.loading{cursor:not-allowed;opacity:.6;pointer-events:none}.n-users-password-strength{margin-top:8px}.n-users-validation-rules{margin-top:12px}.n-users-rules-title{margin-bottom:8px}.n-users-rules-list{padding-left:0}.n-users-rule-item{margin-bottom:6px}.n-users-rule-item:last-child{margin-bottom:0}.n-users-rule-passed{color:var(--nu-color-validation-passed,#28a745)}.n-users-rule-failed{color:var(--nu-color-validation-failed,#dc3545)}.n-users-rule-icon{margin-right:8px}.n-users-rule-text{flex:1}.n-users-validation-errors{margin-top:8px}.n-users-error-text:last-child{margin-bottom:0}.n-users-password-hints{margin-top:8px}.n-users-hint-title{margin-bottom:8px}.n-users-hint-list{padding-left:16px}.n-users-hint-item{color:var(--nu-color-validation-hint,#6c757d);margin-bottom:4px}.n-users-hint-item:last-child{margin-bottom:0}.n-users-logout-link{background:var(--nu-color-error);border:2px solid transparent;border-color:var(--nu-color-error-dark);border-radius:.5em;color:#fff;padding:.5em 1em;text-decoration:none}.n-users-logout-link:hover{border-color:var(--nu-color-primary)}.n-users-user-card dd{margin:0}.n-users-user-card-actions{display:flex;gap:.5rem;margin-top:1rem}.n-users-user-form{margin:0 auto;max-width:500px}.n-users-form-group input.error{border-color:#dc3545}.n-users-profile-info{background-color:var(--nu-color-bg-primary);border-top-left-radius:.5em;border-top-right-radius:.5em}.n-users-profile-details{font-size:1rem;list-style:none;margin:0;padding:0}.n-users-reset-password-container{background-color:var(--nu-color-bg-primary);border-bottom-left-radius:.5em;border-bottom-right-radius:.5em}@media (max-width:480px){.n-users-login-title{font-size:1.5rem}}.n-users-list-enter-active,.n-users-list-leave-active,.n-users-list-move{transition:all .3s ease}.n-users-list-enter-from,.n-users-list-leave-to{opacity:0;transform:translateX(2rem)}.n-users-list-leave-active{position:absolute}.n-users-list-move{transition-timing-function:ease}
|
|
@@ -6,7 +6,7 @@ defineProps({
|
|
|
6
6
|
displayFields: { type: Array, required: false, default: () => defaultDisplayFields },
|
|
7
7
|
fieldLabels: { type: Object, required: false, default: () => defaultFieldLabels }
|
|
8
8
|
});
|
|
9
|
-
defineEmits(["editClick", "delete"]);
|
|
9
|
+
const emit = defineEmits(["editClick", "delete"]);
|
|
10
10
|
const { public: { nuxtUsers } } = useRuntimeConfig();
|
|
11
11
|
const users = ref([]);
|
|
12
12
|
const pagination = ref(null);
|
|
@@ -34,6 +34,10 @@ defineExpose({
|
|
|
34
34
|
onMounted(() => {
|
|
35
35
|
fetchUsers();
|
|
36
36
|
});
|
|
37
|
+
const handleDelete = (user) => {
|
|
38
|
+
users.value = users.value.filter((u) => u.id !== user.id);
|
|
39
|
+
emit("delete", user);
|
|
40
|
+
};
|
|
37
41
|
</script>
|
|
38
42
|
|
|
39
43
|
<template>
|
|
@@ -70,7 +74,11 @@ onMounted(() => {
|
|
|
70
74
|
|
|
71
75
|
<div v-if="users.length">
|
|
72
76
|
<slot name="usersList">
|
|
73
|
-
<
|
|
77
|
+
<TransitionGroup
|
|
78
|
+
name="n-users-list"
|
|
79
|
+
tag="ul"
|
|
80
|
+
class="n-users-grid n-users-grid-auto"
|
|
81
|
+
>
|
|
74
82
|
<li
|
|
75
83
|
v-for="(user, index) in users"
|
|
76
84
|
:key="user.id"
|
|
@@ -86,11 +94,11 @@ onMounted(() => {
|
|
|
86
94
|
:display-fields="displayFields"
|
|
87
95
|
:field-labels="fieldLabels"
|
|
88
96
|
@edit-click="$emit('editClick', user)"
|
|
89
|
-
@delete="
|
|
97
|
+
@delete="handleDelete(user)"
|
|
90
98
|
/>
|
|
91
99
|
</slot>
|
|
92
100
|
</li>
|
|
93
|
-
</
|
|
101
|
+
</TransitionGroup>
|
|
94
102
|
</slot>
|
|
95
103
|
|
|
96
104
|
<slot
|
|
@@ -6,10 +6,10 @@ declare var __VLS_1: {}, __VLS_3: {
|
|
|
6
6
|
loading: boolean;
|
|
7
7
|
}, __VLS_5: {
|
|
8
8
|
error: string | null;
|
|
9
|
-
}, __VLS_7: {}, __VLS_9: {},
|
|
9
|
+
}, __VLS_7: {}, __VLS_9: {}, __VLS_16: {
|
|
10
10
|
user: any;
|
|
11
11
|
index: number;
|
|
12
|
-
},
|
|
12
|
+
}, __VLS_27: {
|
|
13
13
|
pagination: {
|
|
14
14
|
page: number;
|
|
15
15
|
limit: number;
|
|
@@ -18,7 +18,7 @@ declare var __VLS_1: {}, __VLS_3: {
|
|
|
18
18
|
hasNext: boolean;
|
|
19
19
|
hasPrev: boolean;
|
|
20
20
|
} | null;
|
|
21
|
-
},
|
|
21
|
+
}, __VLS_29: {
|
|
22
22
|
pagination: {
|
|
23
23
|
page: number;
|
|
24
24
|
limit: number;
|
|
@@ -41,11 +41,11 @@ type __VLS_Slots = {} & {
|
|
|
41
41
|
} & {
|
|
42
42
|
usersList?: (props: typeof __VLS_9) => any;
|
|
43
43
|
} & {
|
|
44
|
-
user?: (props: typeof
|
|
44
|
+
user?: (props: typeof __VLS_16) => any;
|
|
45
45
|
} & {
|
|
46
|
-
paginationInfo?: (props: typeof
|
|
46
|
+
paginationInfo?: (props: typeof __VLS_27) => any;
|
|
47
47
|
} & {
|
|
48
|
-
pagination?: (props: typeof
|
|
48
|
+
pagination?: (props: typeof __VLS_29) => any;
|
|
49
49
|
};
|
|
50
50
|
declare const __VLS_component: import("vue").DefineComponent<Props, {
|
|
51
51
|
refresh: () => void;
|
|
@@ -25,6 +25,9 @@ export declare const findUserById: <T extends boolean = false>(id: number, optio
|
|
|
25
25
|
export declare const updateUser: (id: number, userData: Partial<User>, options: ModuleOptions) => Promise<UserWithoutPassword>;
|
|
26
26
|
/**
|
|
27
27
|
* Deletes a user by their ID.
|
|
28
|
+
* By default performs soft delete (sets active to false).
|
|
29
|
+
* If hardDelete option is true, performs hard delete (removes from database).
|
|
30
|
+
* In both cases, user tokens are revoked.
|
|
28
31
|
*/
|
|
29
32
|
export declare const deleteUser: (id: number, options: ModuleOptions) => Promise<void>;
|
|
30
33
|
/**
|
|
@@ -96,10 +96,16 @@ export const updateUser = async (id, userData, options) => {
|
|
|
96
96
|
export const deleteUser = async (id, options) => {
|
|
97
97
|
const db = await useDb(options);
|
|
98
98
|
const usersTable = options.tables.users;
|
|
99
|
-
const
|
|
100
|
-
if (
|
|
101
|
-
throw new Error("User not found
|
|
99
|
+
const userExists = await db.sql`SELECT id FROM {${usersTable}} WHERE id = ${id}`;
|
|
100
|
+
if (userExists.rows.length === 0) {
|
|
101
|
+
throw new Error("User not found.");
|
|
102
102
|
}
|
|
103
|
+
await revokeUserTokens(id, options);
|
|
104
|
+
if (options.hardDelete) {
|
|
105
|
+
await db.sql`DELETE FROM {${usersTable}} WHERE id = ${id}`;
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
await db.sql`UPDATE {${usersTable}} SET active = false, updated_at = CURRENT_TIMESTAMP WHERE id = ${id}`;
|
|
103
109
|
};
|
|
104
110
|
export const updateUserPassword = async (email, newPassword, options) => {
|
|
105
111
|
const db = await useDb(options);
|
|
@@ -100,6 +100,13 @@ interface RuntimeModuleOptions {
|
|
|
100
100
|
*/
|
|
101
101
|
preventCommonPasswords?: boolean;
|
|
102
102
|
};
|
|
103
|
+
/**
|
|
104
|
+
* Enable hard delete for user deletion
|
|
105
|
+
* When false (default), users are soft deleted (active set to false)
|
|
106
|
+
* When true, users are permanently deleted from database
|
|
107
|
+
* @default false
|
|
108
|
+
*/
|
|
109
|
+
hardDelete?: boolean;
|
|
103
110
|
}
|
|
104
111
|
interface ModuleOptions {
|
|
105
112
|
connector: {
|
|
@@ -128,6 +135,7 @@ interface ModuleOptions {
|
|
|
128
135
|
requireSpecialChars: boolean;
|
|
129
136
|
preventCommonPasswords: boolean;
|
|
130
137
|
};
|
|
138
|
+
hardDelete: boolean;
|
|
131
139
|
}
|
|
132
140
|
interface MailerOptions {
|
|
133
141
|
host: string;
|
|
@@ -100,6 +100,13 @@ interface RuntimeModuleOptions {
|
|
|
100
100
|
*/
|
|
101
101
|
preventCommonPasswords?: boolean;
|
|
102
102
|
};
|
|
103
|
+
/**
|
|
104
|
+
* Enable hard delete for user deletion
|
|
105
|
+
* When false (default), users are soft deleted (active set to false)
|
|
106
|
+
* When true, users are permanently deleted from database
|
|
107
|
+
* @default false
|
|
108
|
+
*/
|
|
109
|
+
hardDelete?: boolean;
|
|
103
110
|
}
|
|
104
111
|
interface ModuleOptions {
|
|
105
112
|
connector: {
|
|
@@ -128,6 +135,7 @@ interface ModuleOptions {
|
|
|
128
135
|
requireSpecialChars: boolean;
|
|
129
136
|
preventCommonPasswords: boolean;
|
|
130
137
|
};
|
|
138
|
+
hardDelete: boolean;
|
|
131
139
|
}
|
|
132
140
|
interface MailerOptions {
|
|
133
141
|
host: string;
|
package/dist/utils.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { g as DatabaseConfig, f as DatabaseType, D as DisplayFieldsProps, L as LoginFormData, c as LoginFormProps, M as ModuleOptions, b as PasswordResetToken, e as Permission, P as PersonalAccessToken, d as ResetPasswordFormProps, R as RuntimeModuleOptions, U as User, a as UserWithoutPassword, h as defaultDisplayFields, i as defaultFieldLabels } from './shared/nuxt-users.
|
|
1
|
+
export { g as DatabaseConfig, f as DatabaseType, D as DisplayFieldsProps, L as LoginFormData, c as LoginFormProps, M as ModuleOptions, b as PasswordResetToken, e as Permission, P as PersonalAccessToken, d as ResetPasswordFormProps, R as RuntimeModuleOptions, U as User, a as UserWithoutPassword, h as defaultDisplayFields, i as defaultFieldLabels } from './shared/nuxt-users.CydOpwYH.mjs';
|
|
2
2
|
|
|
3
3
|
interface PasswordValidationResult {
|
|
4
4
|
isValid: boolean;
|
package/dist/utils.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { g as DatabaseConfig, f as DatabaseType, D as DisplayFieldsProps, L as LoginFormData, c as LoginFormProps, M as ModuleOptions, b as PasswordResetToken, e as Permission, P as PersonalAccessToken, d as ResetPasswordFormProps, R as RuntimeModuleOptions, U as User, a as UserWithoutPassword, h as defaultDisplayFields, i as defaultFieldLabels } from './shared/nuxt-users.
|
|
1
|
+
export { g as DatabaseConfig, f as DatabaseType, D as DisplayFieldsProps, L as LoginFormData, c as LoginFormProps, M as ModuleOptions, b as PasswordResetToken, e as Permission, P as PersonalAccessToken, d as ResetPasswordFormProps, R as RuntimeModuleOptions, U as User, a as UserWithoutPassword, h as defaultDisplayFields, i as defaultFieldLabels } from './shared/nuxt-users.CydOpwYH.js';
|
|
2
2
|
|
|
3
3
|
interface PasswordValidationResult {
|
|
4
4
|
isValid: boolean;
|
package/package.json
CHANGED