@nocobase/plugin-auth 0.10.0-alpha.5 → 0.10.1-alpha.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.
@@ -11,7 +11,6 @@ function _auth() {
11
11
  };
12
12
  return data;
13
13
  }
14
- var _preset = require("../preset");
15
14
  function _crypto() {
16
15
  const data = _interopRequireDefault(require("crypto"));
17
16
  _crypto = function _crypto() {
@@ -19,6 +18,7 @@ function _crypto() {
19
18
  };
20
19
  return data;
21
20
  }
21
+ var _preset = require("../preset");
22
22
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
23
23
  function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } }
24
24
  function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; }
@@ -47,7 +47,7 @@ class BasicAuth extends _auth().BaseAuth {
47
47
  ns: _preset.namespace
48
48
  }));
49
49
  }
50
- const user = yield _this.userCollection.repository.findOne({
50
+ const user = yield _this.userRepository.findOne({
51
51
  where: {
52
52
  [uniqueField]: values[uniqueField]
53
53
  }
@@ -96,7 +96,7 @@ class BasicAuth extends _auth().BaseAuth {
96
96
  ns: _preset.namespace
97
97
  }));
98
98
  }
99
- const user = yield _this3.userCollection.repository.findOne({
99
+ const user = yield _this3.userRepository.findOne({
100
100
  where: {
101
101
  email
102
102
  }
@@ -119,7 +119,7 @@ class BasicAuth extends _auth().BaseAuth {
119
119
  email = _ctx$action$params$va.email,
120
120
  password = _ctx$action$params$va.password,
121
121
  resetToken = _ctx$action$params$va.resetToken;
122
- const user = yield _this4.userCollection.repository.findOne({
122
+ const user = yield _this4.userRepository.findOne({
123
123
  where: {
124
124
  email,
125
125
  resetToken
@@ -140,7 +140,7 @@ class BasicAuth extends _auth().BaseAuth {
140
140
  return _asyncToGenerator(function* () {
141
141
  const ctx = _this5.ctx;
142
142
  const token = ctx.action.params.token;
143
- const user = yield _this5.userCollection.repository.findOne({
143
+ const user = yield _this5.userRepository.findOne({
144
144
  where: {
145
145
  resetToken: token
146
146
  }
@@ -162,7 +162,7 @@ class BasicAuth extends _auth().BaseAuth {
162
162
  if (!currentUser) {
163
163
  ctx.throw(401);
164
164
  }
165
- const user = yield _this6.userCollection.repository.findOne({
165
+ const user = yield _this6.userRepository.findOne({
166
166
  where: {
167
167
  email: currentUser.email
168
168
  }
@@ -0,0 +1,3 @@
1
+ import { CollectionOptions } from '@nocobase/client';
2
+ declare const _default: CollectionOptions;
3
+ export default _default;
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+ var _default = {
8
+ namespace: 'auth.token-black',
9
+ duplicator: 'optional',
10
+ name: 'tokenBlacklist',
11
+ model: 'TokenBlacklistModel',
12
+ fields: [{
13
+ type: 'string',
14
+ name: 'token',
15
+ index: true
16
+ }, {
17
+ type: 'date',
18
+ name: 'expiration'
19
+ }]
20
+ };
21
+ exports.default = _default;
@@ -4,8 +4,6 @@ export declare class AuthPlugin extends Plugin {
4
4
  beforeLoad(): Promise<void>;
5
5
  load(): Promise<void>;
6
6
  install(options?: InstallOptions): Promise<void>;
7
- afterEnable(): Promise<void>;
8
- afterDisable(): Promise<void>;
9
7
  remove(): Promise<void>;
10
8
  }
11
9
  export default AuthPlugin;
@@ -18,12 +18,13 @@ function _path() {
18
18
  };
19
19
  return data;
20
20
  }
21
- var _basicAuth = require("./basic-auth");
22
21
  var _preset = require("../preset");
23
22
  var _auth = _interopRequireDefault(require("./actions/auth"));
24
23
  var _authenticators = _interopRequireDefault(require("./actions/authenticators"));
24
+ var _basicAuth = require("./basic-auth");
25
25
  var _locale = require("./locale");
26
26
  var _authenticator = require("./model/authenticator");
27
+ var _tokenBlacklist = require("./token-blacklist");
27
28
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
28
29
  function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } }
29
30
  function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; }
@@ -72,6 +73,10 @@ class AuthPlugin extends _server().Plugin {
72
73
  return get;
73
74
  }()
74
75
  });
76
+ if (!_this2.app.authManager.jwt.blacklist) {
77
+ // If blacklist service is not set, should configure default blacklist service
78
+ _this2.app.authManager.setTokenBlacklistService(new _tokenBlacklist.TokenBlacklistService(_this2));
79
+ }
75
80
  _this2.app.authManager.registerTypes(_preset.presetAuthType, {
76
81
  auth: _basicAuth.BasicAuth
77
82
  });
@@ -115,12 +120,6 @@ class AuthPlugin extends _server().Plugin {
115
120
  });
116
121
  })();
117
122
  }
118
- afterEnable() {
119
- return _asyncToGenerator(function* () {})();
120
- }
121
- afterDisable() {
122
- return _asyncToGenerator(function* () {})();
123
- }
124
123
  remove() {
125
124
  return _asyncToGenerator(function* () {})();
126
125
  }
@@ -0,0 +1,15 @@
1
+ import { ITokenBlacklistService } from '@nocobase/auth';
2
+ import { Repository } from '@nocobase/database';
3
+ import { CronJob } from 'cron';
4
+ import AuthPlugin from './plugin';
5
+ export declare class TokenBlacklistService implements ITokenBlacklistService {
6
+ protected plugin: AuthPlugin;
7
+ repo: Repository;
8
+ cronJob: CronJob;
9
+ constructor(plugin: AuthPlugin);
10
+ get app(): import("@nocobase/server").default<import("@nocobase/server").DefaultState, import("@nocobase/server").DefaultContext>;
11
+ createCronJob(): CronJob;
12
+ has(token: string): Promise<boolean>;
13
+ add(values: any): Promise<[import("@nocobase/database").Model<any, any>, boolean]>;
14
+ deleteByExpiration(): Promise<any>;
15
+ }
@@ -0,0 +1,82 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.TokenBlacklistService = void 0;
7
+ function _cron() {
8
+ const data = require("cron");
9
+ _cron = function _cron() {
10
+ return data;
11
+ };
12
+ return data;
13
+ }
14
+ function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } }
15
+ function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; }
16
+ class TokenBlacklistService {
17
+ constructor(plugin) {
18
+ this.plugin = void 0;
19
+ this.repo = void 0;
20
+ this.cronJob = void 0;
21
+ this.plugin = plugin;
22
+ this.repo = plugin.db.getRepository('tokenBlacklist');
23
+ this.cronJob = this.createCronJob();
24
+ }
25
+ get app() {
26
+ return this.plugin.app;
27
+ }
28
+ createCronJob() {
29
+ var _this = this;
30
+ const cronJob = new (_cron().CronJob)(
31
+ // every day at 03:00
32
+ '0 3 * * *',
33
+ /*#__PURE__*/
34
+ //
35
+ _asyncToGenerator(function* () {
36
+ _this.app.logger.info(`${_this.plugin.name}: Start delete expired blacklist token`);
37
+ yield _this.deleteByExpiration();
38
+ _this.app.logger.info(`${_this.plugin.name}: End delete expired blacklist token`);
39
+ }), null);
40
+ this.app.once('beforeStart', () => {
41
+ cronJob.start();
42
+ });
43
+ this.app.once('beforeStop', () => {
44
+ cronJob.stop();
45
+ });
46
+ return cronJob;
47
+ }
48
+ has(token) {
49
+ var _this2 = this;
50
+ return _asyncToGenerator(function* () {
51
+ return !!(yield _this2.repo.findOne({
52
+ where: {
53
+ token
54
+ }
55
+ }));
56
+ })();
57
+ }
58
+ add(values) {
59
+ var _this3 = this;
60
+ return _asyncToGenerator(function* () {
61
+ return _this3.repo.model.findOrCreate({
62
+ defaults: values,
63
+ where: {
64
+ token: values.token
65
+ }
66
+ });
67
+ })();
68
+ }
69
+ deleteByExpiration() {
70
+ var _this4 = this;
71
+ return _asyncToGenerator(function* () {
72
+ return _this4.repo.destroy({
73
+ filter: {
74
+ expiration: {
75
+ $dateNotAfter: new Date()
76
+ }
77
+ }
78
+ });
79
+ })();
80
+ }
81
+ }
82
+ exports.TokenBlacklistService = TokenBlacklistService;
package/package.json CHANGED
@@ -1,17 +1,21 @@
1
1
  {
2
2
  "name": "@nocobase/plugin-auth",
3
- "version": "0.10.0-alpha.5",
3
+ "version": "0.10.1-alpha.1",
4
4
  "main": "lib/server/index.js",
5
5
  "devDependencies": {
6
- "@nocobase/actions": "0.10.0-alpha.5",
7
- "@nocobase/client": "0.10.0-alpha.5",
8
- "@nocobase/database": "0.10.0-alpha.5",
9
- "@nocobase/server": "0.10.0-alpha.5",
10
- "@nocobase/test": "0.10.0-alpha.5"
6
+ "@nocobase/test": "0.10.1-alpha.1",
7
+ "@types/cron": "^2.0.1"
8
+ },
9
+ "dependencies": {
10
+ "@nocobase/actions": "0.10.1-alpha.1",
11
+ "@nocobase/client": "0.10.1-alpha.1",
12
+ "@nocobase/database": "0.10.1-alpha.1",
13
+ "@nocobase/server": "0.10.1-alpha.1",
14
+ "cron": "^2.3.1"
11
15
  },
12
16
  "displayName": "Authentication",
13
17
  "displayName.zh-CN": "用户认证",
14
18
  "description": "Basic authentication and authenticator management.",
15
19
  "description.zh-CN": "提供基础认证功能和扩展认证器管理功能。",
16
- "gitHead": "1be8fcdad42688064460761cea22830cf392c7c0"
20
+ "gitHead": "8f415f5e0ee2e72d681f9ab16af5911b52c374a9"
17
21
  }
@@ -0,0 +1,73 @@
1
+ import Database, { Repository } from '@nocobase/database';
2
+ import { MockServer, mockServer } from '@nocobase/test';
3
+ import { TokenBlacklistService } from '../token-blacklist';
4
+
5
+ describe('token-blacklist', () => {
6
+ let app: MockServer;
7
+ let db: Database;
8
+ let repo: Repository;
9
+ let tokenBlacklist: TokenBlacklistService;
10
+
11
+ beforeAll(async () => {
12
+ app = mockServer({
13
+ plugins: ['auth'],
14
+ });
15
+ await app.loadAndInstall({ clean: true });
16
+ db = app.db;
17
+ repo = db.getRepository('tokenBlacklist');
18
+ tokenBlacklist = new TokenBlacklistService(app.getPlugin('auth'));
19
+ });
20
+
21
+ afterAll(async () => {
22
+ await db.close();
23
+ });
24
+
25
+ afterEach(async () => {
26
+ await repo.destroy({
27
+ truncate: true,
28
+ });
29
+ });
30
+
31
+ it('add and has correctly', async () => {
32
+ await tokenBlacklist.add({
33
+ token: 'test',
34
+ expiration: new Date(),
35
+ });
36
+
37
+ await tokenBlacklist.add({
38
+ token: 'test1',
39
+ expiration: new Date(),
40
+ });
41
+
42
+ expect(tokenBlacklist.has('test')).toBeTruthy();
43
+ expect(tokenBlacklist.has('test1')).toBeTruthy();
44
+ });
45
+
46
+ it('add same token correctly', async () => {
47
+ await tokenBlacklist.add({
48
+ token: 'test',
49
+ expiration: new Date(),
50
+ });
51
+
52
+ await tokenBlacklist.add({
53
+ token: 'test',
54
+ expiration: new Date(),
55
+ });
56
+
57
+ expect(tokenBlacklist.has('test')).toBeTruthy();
58
+ });
59
+
60
+ it('delete expired token correctly', async () => {
61
+ await tokenBlacklist.add({
62
+ token: 'should be deleted',
63
+ expiration: new Date('2020-01-01'),
64
+ });
65
+ await tokenBlacklist.add({
66
+ token: 'should not be deleted',
67
+ expiration: new Date('2100-01-01'),
68
+ });
69
+ await tokenBlacklist.deleteByExpiration();
70
+ expect(await tokenBlacklist.has('should be deleted')).not.toBeTruthy();
71
+ expect(await tokenBlacklist.has('should not be deleted')).toBeTruthy();
72
+ });
73
+ });
@@ -1,7 +1,7 @@
1
1
  import { AuthConfig, BaseAuth } from '@nocobase/auth';
2
- import { namespace } from '../preset';
3
2
  import { PasswordField } from '@nocobase/database';
4
3
  import crypto from 'crypto';
4
+ import { namespace } from '../preset';
5
5
 
6
6
  export class BasicAuth extends BaseAuth {
7
7
  constructor(config: AuthConfig) {
@@ -16,7 +16,7 @@ export class BasicAuth extends BaseAuth {
16
16
  if (!values[uniqueField]) {
17
17
  ctx.throw(400, ctx.t('Please fill in your email address', { ns: namespace }));
18
18
  }
19
- const user = await this.userCollection.repository.findOne({
19
+ const user = await this.userRepository.findOne({
20
20
  where: {
21
21
  [uniqueField]: values[uniqueField],
22
22
  },
@@ -54,7 +54,7 @@ export class BasicAuth extends BaseAuth {
54
54
  if (!email) {
55
55
  ctx.throw(400, ctx.t('Please fill in your email address', { ns: namespace }));
56
56
  }
57
- const user = await this.userCollection.repository.findOne({
57
+ const user = await this.userRepository.findOne({
58
58
  where: {
59
59
  email,
60
60
  },
@@ -72,7 +72,7 @@ export class BasicAuth extends BaseAuth {
72
72
  const {
73
73
  values: { email, password, resetToken },
74
74
  } = ctx.action.params;
75
- const user = await this.userCollection.repository.findOne({
75
+ const user = await this.userRepository.findOne({
76
76
  where: {
77
77
  email,
78
78
  resetToken,
@@ -91,7 +91,7 @@ export class BasicAuth extends BaseAuth {
91
91
  async getUserByResetToken() {
92
92
  const ctx = this.ctx;
93
93
  const { token } = ctx.action.params;
94
- const user = await this.userCollection.repository.findOne({
94
+ const user = await this.userRepository.findOne({
95
95
  where: {
96
96
  resetToken: token,
97
97
  },
@@ -111,7 +111,7 @@ export class BasicAuth extends BaseAuth {
111
111
  if (!currentUser) {
112
112
  ctx.throw(401);
113
113
  }
114
- const user = await this.userCollection.repository.findOne({
114
+ const user = await this.userRepository.findOne({
115
115
  where: {
116
116
  email: currentUser.email,
117
117
  },
@@ -0,0 +1,19 @@
1
+ import { CollectionOptions } from '@nocobase/client';
2
+
3
+ export default {
4
+ namespace: 'auth.token-black',
5
+ duplicator: 'optional',
6
+ name: 'tokenBlacklist',
7
+ model: 'TokenBlacklistModel',
8
+ fields: [
9
+ {
10
+ type: 'string',
11
+ name: 'token',
12
+ index: true,
13
+ },
14
+ {
15
+ type: 'date',
16
+ name: 'expiration',
17
+ },
18
+ ],
19
+ } as CollectionOptions;
@@ -1,17 +1,16 @@
1
+ import { Model } from '@nocobase/database';
1
2
  import { InstallOptions, Plugin } from '@nocobase/server';
2
3
  import { resolve } from 'path';
3
- import { BasicAuth } from './basic-auth';
4
- import { presetAuthType, presetAuthenticator } from '../preset';
4
+ import { namespace, presetAuthenticator, presetAuthType } from '../preset';
5
5
  import authActions from './actions/auth';
6
6
  import authenticatorsActions from './actions/authenticators';
7
+ import { BasicAuth } from './basic-auth';
7
8
  import { enUS, zhCN } from './locale';
8
- import { namespace } from '../preset';
9
9
  import { AuthModel } from './model/authenticator';
10
- import { Model } from '@nocobase/database';
10
+ import { TokenBlacklistService } from './token-blacklist';
11
11
 
12
12
  export class AuthPlugin extends Plugin {
13
13
  afterAdd() {}
14
-
15
14
  async beforeLoad() {
16
15
  this.app.i18n.addResources('zh-CN', namespace, zhCN);
17
16
  this.app.i18n.addResources('en-US', namespace, enUS);
@@ -40,6 +39,12 @@ export class AuthPlugin extends Plugin {
40
39
  return authenticator || authenticators[0];
41
40
  },
42
41
  });
42
+
43
+ if (!this.app.authManager.jwt.blacklist) {
44
+ // If blacklist service is not set, should configure default blacklist service
45
+ this.app.authManager.setTokenBlacklistService(new TokenBlacklistService(this));
46
+ }
47
+
43
48
  this.app.authManager.registerTypes(presetAuthType, {
44
49
  auth: BasicAuth,
45
50
  });
@@ -81,11 +86,6 @@ export class AuthPlugin extends Plugin {
81
86
  },
82
87
  });
83
88
  }
84
-
85
- async afterEnable() {}
86
-
87
- async afterDisable() {}
88
-
89
89
  async remove() {}
90
90
  }
91
91
 
@@ -0,0 +1,66 @@
1
+ import { ITokenBlacklistService } from '@nocobase/auth';
2
+ import { Repository } from '@nocobase/database';
3
+ import { CronJob } from 'cron';
4
+ import AuthPlugin from './plugin';
5
+
6
+ export class TokenBlacklistService implements ITokenBlacklistService {
7
+ repo: Repository;
8
+ cronJob: CronJob;
9
+
10
+ constructor(protected plugin: AuthPlugin) {
11
+ this.repo = plugin.db.getRepository('tokenBlacklist');
12
+ this.cronJob = this.createCronJob();
13
+ }
14
+
15
+ get app() {
16
+ return this.plugin.app;
17
+ }
18
+
19
+ createCronJob() {
20
+ const cronJob = new CronJob(
21
+ // every day at 03:00
22
+ '0 3 * * *', //
23
+ async () => {
24
+ this.app.logger.info(`${this.plugin.name}: Start delete expired blacklist token`);
25
+ await this.deleteByExpiration();
26
+ this.app.logger.info(`${this.plugin.name}: End delete expired blacklist token`);
27
+ },
28
+ null,
29
+ );
30
+
31
+ this.app.once('beforeStart', () => {
32
+ cronJob.start();
33
+ });
34
+
35
+ this.app.once('beforeStop', () => {
36
+ cronJob.stop();
37
+ });
38
+
39
+ return cronJob;
40
+ }
41
+
42
+ async has(token: string) {
43
+ return !!(await this.repo.findOne({
44
+ where: {
45
+ token,
46
+ },
47
+ }));
48
+ }
49
+ async add(values) {
50
+ return this.repo.model.findOrCreate({
51
+ defaults: values,
52
+ where: {
53
+ token: values.token,
54
+ },
55
+ });
56
+ }
57
+ async deleteByExpiration() {
58
+ return this.repo.destroy({
59
+ filter: {
60
+ expiration: {
61
+ $dateNotAfter: new Date(),
62
+ },
63
+ },
64
+ });
65
+ }
66
+ }