@vulkano/core 1.22.0 → 1.22.1

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/README.md CHANGED
@@ -116,7 +116,7 @@ GET /users/edit/1
116
116
 
117
117
  A controller method key is `<path tail>` on its own, or `'<verb> <path tail>'` when the verb isn't `GET`. The auto-router only reassigns the HTTP method when the key has a space-separated verb prefix — otherwise it defaults to **GET**.
118
118
 
119
- - A **custom action name with no verb prefix** (no space in the key) is still `GET`, e.g. `me(req, res)` on `AuthController` → `GET /auth/me`. Don't write `'get me'`; it's redundant.
119
+ - A **custom action name with no verb prefix** (no space in the key) is still `GET`, e.g. `me(req, res)` on `AuthController` → `GET /auth/current`. Don't write `'get current'`; it's redundant.
120
120
  - A **custom action that isn't `GET`** needs the verb spelled out, e.g. `'post login'` → `POST /auth/login`.
121
121
  - The path tail can carry arbitrary nested segments and multiple params:
122
122
 
@@ -134,8 +134,8 @@ module.exports = {
134
134
  // controllers/api/AuthController.js
135
135
  module.exports = {
136
136
 
137
- // GET /api/auth/me — no verb prefix needed, GET is the default
138
- me(req, res) { },
137
+ // GET /api/auth/current — no verb prefix needed, GET is the default
138
+ current(req, res) { },
139
139
 
140
140
  // POST /api/auth/login
141
141
  'post login': (req, res) => { },
@@ -304,6 +304,10 @@ module.exports = {
304
304
 
305
305
  NOTE: To find examples with the best practices for available methods ahd hooks, look in `examples/models` and read the file `Example.js`, and Scaffold Model API `ExampleWithScaffold.js`.
306
306
 
307
+ ### Vulkano models — don't hand-roll `createdAt` or `updatedAt`
308
+
309
+ `@vulkano/core`'s `database/mongodb.js` auto-injects `createdAt: Date` and `updatedAt: Date` attributes into every model schema if the model doesn't already define them (`if (!attributes.createdAt) { ... }`, same for `updatedAt`). Never add a manual timestamp field (`at`, `date`, `timestamp`, `createdAt`, `updatedAt`, etc.) to a model's `attributes` — they're already automatic in Vulkano, so a hand-rolled one is redundant, and if named anything other than `createdAt`/`updatedAt` it also fights the framework's own sort/index defaults (`database/scaffold.js` defaults `sort: 'createdAt|DESC'`). Use `createdAt` and `updatedAt` directly in indexes, sort strings, and business logic.
310
+
307
311
  ---
308
312
 
309
313
  ## Key conventions
@@ -0,0 +1,56 @@
1
+ /* global Auth, Jwt */
2
+
3
+ /**
4
+ * AuthController.js
5
+ */
6
+
7
+ module.exports = {
8
+
9
+ 'get current': (req, res) => {
10
+
11
+ const {
12
+ auth
13
+ } = req || {};
14
+
15
+ res.vsr(Auth.getCurrent(auth));
16
+
17
+ },
18
+
19
+ 'post login': (req, res) => {
20
+
21
+ Auth.login(req.body)
22
+ .then(({ user, token }) => {
23
+
24
+ const {
25
+ cookieName
26
+ } = Jwt.getConfig();
27
+
28
+ res.cookie(cookieName || 'token', token, {
29
+ httpOnly: true,
30
+ // secure: app.PRODUCTION,
31
+ // sameSite: 'lax',
32
+ maxAge: Auth.SESSION_MS,
33
+ });
34
+
35
+ res.vsr(Promise.resolve(user));
36
+
37
+ })
38
+ .catch((err) => {
39
+ res.vsr(Promise.reject(err));
40
+ });
41
+
42
+ },
43
+
44
+ 'post logout': (req, res) => {
45
+
46
+ const {
47
+ cookieName
48
+ } = Jwt.getConfig();
49
+
50
+ res.clearCookie(cookieName || 'token');
51
+
52
+ res.vsr(Promise.resolve({ success: true }));
53
+
54
+ }
55
+
56
+ };
@@ -0,0 +1,111 @@
1
+ /* global User, Auth, VSError */
2
+
3
+ const bcrypt = require('bcryptjs');
4
+
5
+ module.exports = {
6
+
7
+ SESSION_MS: 1000 * 60 * 60 * 24 * 365 * 10,
8
+
9
+ /**
10
+ * Verify a plain-text password against a stored hash.
11
+ * @param {String} plain
12
+ * @param {String} hash
13
+ * @returns {Boolean}
14
+ */
15
+ verifyPassword(plain, hash) {
16
+ return bcrypt.compareSync(`${process.env.SALT_KEY || ''}-${plain}`, hash);
17
+ },
18
+
19
+ /**
20
+ * Look up a user by email and verify their password. The only place in
21
+ * the model that explicitly loads the password hash.
22
+ * @param {String} email
23
+ * @param {String} password
24
+ * @returns {Promise<Object>} the authenticated User document
25
+ */
26
+ login({ email, password }) {
27
+
28
+ const normalizedEmail = String(email || '')
29
+ .toLowerCase()
30
+ .trim();
31
+
32
+ return User.findOne({ email: normalizedEmail, active: true })
33
+ .select('+password')
34
+ .then((user) => {
35
+
36
+ if (!user || !Auth.verifyPassword(password || '', user.password)) {
37
+ return VSError.reject('Invalid credentials', 401);
38
+ }
39
+
40
+ return Auth.setToken(user);
41
+ });
42
+
43
+ },
44
+
45
+ /**
46
+ * Generate token
47
+ * @param {Object} props
48
+ * @returns {Object}
49
+ */
50
+ setToken(u) {
51
+
52
+ const {
53
+ _id
54
+ } = u || {};
55
+
56
+ if (!_id) {
57
+ return VSError.reject('The user and/or password are incorrect', 400);
58
+ }
59
+
60
+ return Promise.resolve({
61
+
62
+ user: {
63
+ _id: u._id || '',
64
+ name: u.name || ''
65
+ },
66
+
67
+ token: Jwt.encode({
68
+ _id: u._id || '',
69
+ name: u.name || '',
70
+ email: u.email,
71
+ role: u.role || '',
72
+ expiration: Auth.SESSION_MS + Date.now()
73
+ })
74
+
75
+ });
76
+ },
77
+
78
+ /**
79
+ * Get current user logged
80
+ *
81
+ * @param {Object} auth
82
+ * @returns Promise
83
+ */
84
+ getCurrent(auth) {
85
+
86
+ const {
87
+ _id
88
+ } = auth || {};
89
+
90
+ if (!_id) {
91
+ return VSError.reject('Invalid token', 401);
92
+ }
93
+
94
+ return User
95
+ .getUser(_id)
96
+ .then( (u) => {
97
+
98
+ const {
99
+ active
100
+ } = u || {};
101
+
102
+ if (String(active || '') !== 'true' || !_id) {
103
+ return VSError.reject('Invalid ID. User not found', 401);
104
+ }
105
+
106
+ return u;
107
+
108
+ });
109
+
110
+ }
111
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vulkano/core",
3
- "version": "1.22.0",
3
+ "version": "1.22.1",
4
4
  "description": "A MVC framework using Express 4",
5
5
  "license": "MIT",
6
6
  "author": "Vulkano Team",
@@ -44,6 +44,7 @@
44
44
  "dependencies": {
45
45
  "@socket.io/mongo-adapter": "^0.4.0",
46
46
  "@socket.io/redis-adapter": "^8.3.0",
47
+ "bcryptjs": "^3.0.3",
47
48
  "compression": "^1.8.1",
48
49
  "connect-timeout": "^1.9.1",
49
50
  "cookie-parser": "^1.4.7",