ace-auth 1.2.1 → 1.2.4
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/dist/adapters/MongoStore.d.ts +4 -4
- package/dist/adapters/MongoStore.js +29 -18
- package/dist/adapters/PostgressStore.d.ts +14 -10
- package/dist/adapters/PostgressStore.js +53 -45
- package/dist/index.d.ts +1 -0
- package/dist/index.js +3 -1
- package/package.json +1 -1
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { IStore } from "../interfaces/IStore";
|
|
2
2
|
export declare class MongoStore implements IStore {
|
|
3
3
|
private model;
|
|
4
|
-
constructor(
|
|
5
|
-
findAllByUser(userId: string): Promise<string[]>;
|
|
6
|
-
deleteByUser(userId: string): Promise<void>;
|
|
4
|
+
constructor(mongooseCollection: any);
|
|
7
5
|
set(key: string, value: string, ttlSeconds: number): Promise<void>;
|
|
8
6
|
get(key: string): Promise<string | null>;
|
|
9
|
-
delete(key: string): Promise<void>;
|
|
10
7
|
touch(key: string, ttlSeconds: number): Promise<void>;
|
|
8
|
+
delete(key: string): Promise<void>;
|
|
9
|
+
findAllByUser(userId: string): Promise<string[]>;
|
|
10
|
+
deleteByUser(userId: string): Promise<void>;
|
|
11
11
|
}
|
|
@@ -2,40 +2,51 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.MongoStore = void 0;
|
|
4
4
|
class MongoStore {
|
|
5
|
-
constructor(
|
|
6
|
-
this.model =
|
|
7
|
-
}
|
|
8
|
-
async findAllByUser(userId) {
|
|
9
|
-
const docs = await this.model.findOne({ userId });
|
|
10
|
-
if (!docs)
|
|
11
|
-
return [];
|
|
12
|
-
return docs.map((doc) => doc.data);
|
|
13
|
-
}
|
|
14
|
-
async deleteByUser(userId) {
|
|
15
|
-
await this.model.deleteOne({ userId });
|
|
5
|
+
constructor(mongooseCollection) {
|
|
6
|
+
this.model = mongooseCollection;
|
|
16
7
|
}
|
|
8
|
+
// ==============================
|
|
9
|
+
// REQUIRED BY AceAuth
|
|
10
|
+
// ==============================
|
|
17
11
|
async set(key, value, ttlSeconds) {
|
|
18
12
|
const expiresAt = new Date(Date.now() + ttlSeconds * 1000);
|
|
19
|
-
|
|
20
|
-
await this.model.updateOne({ _id: key }, {
|
|
13
|
+
const parsed = JSON.parse(value);
|
|
14
|
+
await this.model.updateOne({ _id: key }, {
|
|
15
|
+
$set: {
|
|
16
|
+
_id: key,
|
|
17
|
+
data: value,
|
|
18
|
+
userId: parsed.id, // 🔥 REQUIRED for logoutAll / devices
|
|
19
|
+
expiresAt
|
|
20
|
+
}
|
|
21
|
+
}, { upsert: true });
|
|
21
22
|
}
|
|
22
23
|
async get(key) {
|
|
23
24
|
const doc = await this.model.findOne({ _id: key });
|
|
24
25
|
if (!doc)
|
|
25
26
|
return null;
|
|
26
|
-
// MongoDB TTL indexes usually handle cleanup, but we double-check here
|
|
27
27
|
if (new Date() > doc.expiresAt) {
|
|
28
|
+
// Clean up expired session eagerly
|
|
29
|
+
await this.delete(key);
|
|
28
30
|
return null;
|
|
29
31
|
}
|
|
30
32
|
return doc.data;
|
|
31
33
|
}
|
|
32
|
-
async delete(key) {
|
|
33
|
-
await this.model.deleteOne({ _id: key });
|
|
34
|
-
}
|
|
35
34
|
async touch(key, ttlSeconds) {
|
|
36
35
|
const expiresAt = new Date(Date.now() + ttlSeconds * 1000);
|
|
37
|
-
// The "Slide": Just update the date
|
|
38
36
|
await this.model.updateOne({ _id: key }, { $set: { expiresAt } });
|
|
39
37
|
}
|
|
38
|
+
async delete(key) {
|
|
39
|
+
await this.model.deleteOne({ _id: key });
|
|
40
|
+
}
|
|
41
|
+
// ==============================
|
|
42
|
+
// DEVICE / USER MANAGEMENT
|
|
43
|
+
// ==============================
|
|
44
|
+
async findAllByUser(userId) {
|
|
45
|
+
const docs = await this.model.find({ userId });
|
|
46
|
+
return docs.map(doc => doc.data);
|
|
47
|
+
}
|
|
48
|
+
async deleteByUser(userId) {
|
|
49
|
+
await this.model.deleteMany({ userId });
|
|
50
|
+
}
|
|
40
51
|
}
|
|
41
52
|
exports.MongoStore = MongoStore;
|
|
@@ -1,25 +1,29 @@
|
|
|
1
1
|
import { IStore } from '../interfaces/IStore';
|
|
2
2
|
/**
|
|
3
|
-
* SQL SCHEMA
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
3
|
+
* REQUIRED SQL SCHEMA:
|
|
4
|
+
*
|
|
5
|
+
* CREATE TABLE auth_sessions (
|
|
6
|
+
* sid TEXT PRIMARY KEY,
|
|
7
|
+
* sess JSONB NOT NULL,
|
|
8
|
+
* user_id TEXT NOT NULL,
|
|
9
|
+
* expired_at TIMESTAMPTZ NOT NULL
|
|
8
10
|
* );
|
|
9
|
-
*
|
|
11
|
+
*
|
|
12
|
+
* CREATE INDEX idx_auth_sessions_user_id ON auth_sessions(user_id);
|
|
13
|
+
* CREATE INDEX idx_auth_sessions_expired_at ON auth_sessions(expired_at);
|
|
10
14
|
*/
|
|
11
15
|
interface PgPool {
|
|
12
16
|
query(text: string, params?: any[]): Promise<any>;
|
|
13
17
|
}
|
|
14
18
|
export declare class PostgresStore implements IStore {
|
|
15
19
|
private pool;
|
|
16
|
-
private
|
|
20
|
+
private table;
|
|
17
21
|
constructor(pool: PgPool, tableName?: string);
|
|
18
|
-
findAllByUser(userId: string): Promise<string[]>;
|
|
19
|
-
deleteByUser(userId: string): Promise<void>;
|
|
20
22
|
set(key: string, value: string, ttlSeconds: number): Promise<void>;
|
|
21
23
|
get(key: string): Promise<string | null>;
|
|
22
|
-
delete(key: string): Promise<void>;
|
|
23
24
|
touch(key: string, ttlSeconds: number): Promise<void>;
|
|
25
|
+
delete(key: string): Promise<void>;
|
|
26
|
+
findAllByUser(userId: string): Promise<string[]>;
|
|
27
|
+
deleteByUser(userId: string): Promise<void>;
|
|
24
28
|
}
|
|
25
29
|
export {};
|
|
@@ -2,71 +2,79 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.PostgresStore = void 0;
|
|
4
4
|
class PostgresStore {
|
|
5
|
-
// Allow user to customize table name
|
|
6
5
|
constructor(pool, tableName = 'auth_sessions') {
|
|
7
6
|
this.pool = pool;
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
WHERE sess->>'userId' = $1 AND expired_at > NOW()
|
|
14
|
-
`;
|
|
15
|
-
const result = await this.pool.query(query, [userId]);
|
|
16
|
-
// Extract sessions and return them as an array of strings
|
|
17
|
-
return result.rows.map((row) => {
|
|
18
|
-
const data = row.sess;
|
|
19
|
-
return typeof data === 'string' ? data : JSON.stringify(data);
|
|
20
|
-
});
|
|
21
|
-
}
|
|
22
|
-
async deleteByUser(userId) {
|
|
23
|
-
const query = `
|
|
24
|
-
DELETE FROM ${this.tableName}
|
|
25
|
-
WHERE sess->>'userId' = $1
|
|
26
|
-
`;
|
|
27
|
-
await this.pool.query(query, [userId]);
|
|
7
|
+
// 🛡️ Prevent SQL injection via table name
|
|
8
|
+
if (!/^[a-zA-Z_]+$/.test(tableName)) {
|
|
9
|
+
throw new Error('Invalid table name');
|
|
10
|
+
}
|
|
11
|
+
this.table = tableName;
|
|
28
12
|
}
|
|
13
|
+
// ==============================
|
|
14
|
+
// CORE SESSION OPERATIONS
|
|
15
|
+
// ==============================
|
|
29
16
|
async set(key, value, ttlSeconds) {
|
|
30
17
|
const expiresAt = new Date(Date.now() + ttlSeconds * 1000);
|
|
31
|
-
|
|
18
|
+
const parsed = JSON.parse(value);
|
|
32
19
|
const query = `
|
|
33
|
-
INSERT INTO ${this.
|
|
34
|
-
VALUES ($1, $2, $3)
|
|
35
|
-
ON CONFLICT (sid)
|
|
36
|
-
DO UPDATE SET
|
|
20
|
+
INSERT INTO ${this.table} (sid, sess, user_id, expired_at)
|
|
21
|
+
VALUES ($1, $2, $3, $4)
|
|
22
|
+
ON CONFLICT (sid)
|
|
23
|
+
DO UPDATE SET
|
|
24
|
+
sess = EXCLUDED.sess,
|
|
25
|
+
user_id = EXCLUDED.user_id,
|
|
26
|
+
expired_at = EXCLUDED.expired_at
|
|
37
27
|
`;
|
|
38
|
-
await this.pool.query(query, [
|
|
28
|
+
await this.pool.query(query, [
|
|
29
|
+
key,
|
|
30
|
+
parsed,
|
|
31
|
+
parsed.id, // 🔥 REQUIRED for logoutAll & device management
|
|
32
|
+
expiresAt
|
|
33
|
+
]);
|
|
39
34
|
}
|
|
40
35
|
async get(key) {
|
|
41
|
-
// We perform a "Lazy Delete" check here.
|
|
42
|
-
// Even if the row exists, if it's expired, we treat it as null.
|
|
43
36
|
const query = `
|
|
44
|
-
SELECT sess
|
|
45
|
-
|
|
37
|
+
SELECT sess, expired_at
|
|
38
|
+
FROM ${this.table}
|
|
39
|
+
WHERE sid = $1
|
|
46
40
|
`;
|
|
47
41
|
const result = await this.pool.query(query, [key]);
|
|
48
|
-
if (result.rows
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
42
|
+
if (!result.rows.length)
|
|
43
|
+
return null;
|
|
44
|
+
const { sess, expired_at } = result.rows[0];
|
|
45
|
+
if (new Date() > expired_at) {
|
|
46
|
+
// Lazy cleanup
|
|
47
|
+
await this.delete(key);
|
|
48
|
+
return null;
|
|
54
49
|
}
|
|
55
|
-
return
|
|
56
|
-
}
|
|
57
|
-
async delete(key) {
|
|
58
|
-
const query = `DELETE FROM ${this.tableName} WHERE sid = $1`;
|
|
59
|
-
await this.pool.query(query, [key]);
|
|
50
|
+
return JSON.stringify(sess);
|
|
60
51
|
}
|
|
61
52
|
async touch(key, ttlSeconds) {
|
|
62
53
|
const expiresAt = new Date(Date.now() + ttlSeconds * 1000);
|
|
63
|
-
// Just update the timestamp to keep the session alive
|
|
64
54
|
const query = `
|
|
65
|
-
UPDATE ${this.
|
|
66
|
-
SET expired_at = $1
|
|
55
|
+
UPDATE ${this.table}
|
|
56
|
+
SET expired_at = $1
|
|
67
57
|
WHERE sid = $2
|
|
68
58
|
`;
|
|
69
59
|
await this.pool.query(query, [expiresAt, key]);
|
|
70
60
|
}
|
|
61
|
+
async delete(key) {
|
|
62
|
+
await this.pool.query(`DELETE FROM ${this.table} WHERE sid = $1`, [key]);
|
|
63
|
+
}
|
|
64
|
+
// ==============================
|
|
65
|
+
// USER / DEVICE MANAGEMENT
|
|
66
|
+
// ==============================
|
|
67
|
+
async findAllByUser(userId) {
|
|
68
|
+
const query = `
|
|
69
|
+
SELECT sess
|
|
70
|
+
FROM ${this.table}
|
|
71
|
+
WHERE user_id = $1 AND expired_at > NOW()
|
|
72
|
+
`;
|
|
73
|
+
const result = await this.pool.query(query, [userId]);
|
|
74
|
+
return result.rows.map((row) => JSON.stringify(row.sess));
|
|
75
|
+
}
|
|
76
|
+
async deleteByUser(userId) {
|
|
77
|
+
await this.pool.query(`DELETE FROM ${this.table} WHERE user_id = $1`, [userId]);
|
|
78
|
+
}
|
|
71
79
|
}
|
|
72
80
|
exports.PostgresStore = PostgresStore;
|
package/dist/index.d.ts
CHANGED
|
@@ -4,3 +4,4 @@ export { MemoryStore } from './adapters/MemoryStore';
|
|
|
4
4
|
export { MongoStore } from './adapters/MongoStore';
|
|
5
5
|
export { RedisStore } from './adapters/RedisStore';
|
|
6
6
|
export { PostgresStore } from './adapters/PostgressStore';
|
|
7
|
+
export { gatekeeper } from './middleware/gatekeeper';
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
// src/index.ts
|
|
3
3
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
-
exports.PostgresStore = exports.RedisStore = exports.MongoStore = exports.MemoryStore = exports.AceAuth = void 0;
|
|
4
|
+
exports.gatekeeper = exports.PostgresStore = exports.RedisStore = exports.MongoStore = exports.MemoryStore = exports.AceAuth = void 0;
|
|
5
5
|
// Export Core
|
|
6
6
|
var AceAuth_1 = require("./core/AceAuth");
|
|
7
7
|
Object.defineProperty(exports, "AceAuth", { enumerable: true, get: function () { return AceAuth_1.AceAuth; } });
|
|
@@ -14,3 +14,5 @@ var RedisStore_1 = require("./adapters/RedisStore");
|
|
|
14
14
|
Object.defineProperty(exports, "RedisStore", { enumerable: true, get: function () { return RedisStore_1.RedisStore; } });
|
|
15
15
|
var PostgressStore_1 = require("./adapters/PostgressStore");
|
|
16
16
|
Object.defineProperty(exports, "PostgresStore", { enumerable: true, get: function () { return PostgressStore_1.PostgresStore; } });
|
|
17
|
+
var gatekeeper_1 = require("./middleware/gatekeeper");
|
|
18
|
+
Object.defineProperty(exports, "gatekeeper", { enumerable: true, get: function () { return gatekeeper_1.gatekeeper; } });
|