正在显示
21 个修改的文件
包含
580 行增加
和
0 行删除
.autod.conf.js
0 → 100644
1 | +'use strict'; | |
2 | + | |
3 | +module.exports = { | |
4 | + write: true, | |
5 | + prefix: '^', | |
6 | + plugin: 'autod-egg', | |
7 | + test: [ | |
8 | + 'test', | |
9 | + 'benchmark', | |
10 | + ], | |
11 | + devdep: [ | |
12 | + 'egg', | |
13 | + 'egg-ci', | |
14 | + 'egg-bin', | |
15 | + 'autod', | |
16 | + 'autod-egg', | |
17 | + 'eslint', | |
18 | + 'eslint-config-egg', | |
19 | + ], | |
20 | + exclude: [ | |
21 | + './test/fixtures', | |
22 | + './docs', | |
23 | + './coverage', | |
24 | + ], | |
25 | +}; | ... | ... |
.eslintignore
0 → 100644
1 | +coverage | ... | ... |
.github/PULL_REQUEST_TEMPLATE.md
0 → 100644
1 | +<!-- | |
2 | +Thank you for your pull request. Please review below requirements. | |
3 | +Bug fixes and new features should include tests and possibly benchmarks. | |
4 | +Contributors guide: https://github.com/eggjs/egg/blob/master/CONTRIBUTING.md | |
5 | + | |
6 | +感谢您贡献代码。请确认下列 checklist 的完成情况。 | |
7 | +Bug 修复和新功能必须包含测试,必要时请附上性能测试。 | |
8 | +Contributors guide: https://github.com/eggjs/egg/blob/master/CONTRIBUTING.md | |
9 | +--> | |
10 | + | |
11 | +##### Checklist | |
12 | +<!-- Remove items that do not apply. For completed items, change [ ] to [x]. --> | |
13 | + | |
14 | +- [ ] `npm test` passes | |
15 | +- [ ] tests and/or benchmarks are included | |
16 | +- [ ] documentation is changed or added | |
17 | +- [ ] commit message follows commit guidelines | |
18 | + | |
19 | +##### Affected core subsystem(s) | |
20 | +<!-- Provide affected core subsystem(s). --> | |
21 | + | |
22 | + | |
23 | +##### Description of change | |
24 | +<!-- Provide a description of the change below this comment. --> | ... | ... |
.github/workflows/nodejs.yml
0 → 100644
1 | +# This workflow will do a clean install of node dependencies, build the source code and run tests across different versions of node | |
2 | +# For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions | |
3 | + | |
4 | +name: Node.js CI | |
5 | + | |
6 | +on: | |
7 | + push: | |
8 | + branches: | |
9 | + - main | |
10 | + - master | |
11 | + pull_request: | |
12 | + branches: | |
13 | + - main | |
14 | + - master | |
15 | + schedule: | |
16 | + - cron: '0 2 * * *' | |
17 | + | |
18 | +jobs: | |
19 | + build: | |
20 | + runs-on: ${{ matrix.os }} | |
21 | + | |
22 | + strategy: | |
23 | + fail-fast: false | |
24 | + matrix: | |
25 | + node-version: [8, 10] | |
26 | + os: [ubuntu-latest, windows-latest, macos-latest] | |
27 | + | |
28 | + steps: | |
29 | + - name: Checkout Git Source | |
30 | + uses: actions/checkout@v2 | |
31 | + | |
32 | + - name: Use Node.js ${{ matrix.node-version }} | |
33 | + uses: actions/setup-node@v1 | |
34 | + with: | |
35 | + node-version: ${{ matrix.node-version }} | |
36 | + | |
37 | + - name: Install Dependencies | |
38 | + run: npm i -g npminstall && npminstall | |
39 | + | |
40 | + - name: Continuous Integration | |
41 | + run: npm run ci | |
42 | + | |
43 | + - name: Code Coverage | |
44 | + uses: codecov/codecov-action@v1 | |
45 | + with: | |
46 | + token: ${{ secrets.CODECOV_TOKEN }} | ... | ... |
.gitignore
0 → 100644
.travis.yml
0 → 100644
LICENSE
0 → 100644
1 | +The MIT License (MIT) | |
2 | + | |
3 | +Copyright (c) 2019-present Alibaba Group Holding Limited and other contributors. | |
4 | + | |
5 | +Permission is hereby granted, free of charge, to any person obtaining a copy | |
6 | +of this software and associated documentation files (the "Software"), to deal | |
7 | +in the Software without restriction, including without limitation the rights | |
8 | +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
9 | +copies of the Software, and to permit persons to whom the Software is | |
10 | +furnished to do so, subject to the following conditions: | |
11 | + | |
12 | +The above copyright notice and this permission notice shall be included in all | |
13 | +copies or substantial portions of the Software. | |
14 | + | |
15 | +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
16 | +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
17 | +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
18 | +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
19 | +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
20 | +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |
21 | +SOFTWARE. | ... | ... |
README.md
0 → 100644
1 | +# egg-ldapjs | |
2 | + | |
3 | +[![NPM version][npm-image]][npm-url] | |
4 | +[![build status][travis-image]][travis-url] | |
5 | +[![Test coverage][codecov-image]][codecov-url] | |
6 | +[![David deps][david-image]][david-url] | |
7 | +[![Known Vulnerabilities][snyk-image]][snyk-url] | |
8 | +[![npm download][download-image]][download-url] | |
9 | + | |
10 | +[npm-image]: https://img.shields.io/npm/v/egg-ldapjs.svg?style=flat-square | |
11 | +[npm-url]: https://npmjs.org/package/egg-ldapjs | |
12 | +[travis-image]: https://img.shields.io/travis/eggjs/egg-ldapjs.svg?style=flat-square | |
13 | +[travis-url]: https://travis-ci.org/eggjs/egg-ldapjs | |
14 | +[codecov-image]: https://img.shields.io/codecov/c/github/eggjs/egg-ldapjs.svg?style=flat-square | |
15 | +[codecov-url]: https://codecov.io/github/eggjs/egg-ldapjs?branch=master | |
16 | +[david-image]: https://img.shields.io/david/eggjs/egg-ldapjs.svg?style=flat-square | |
17 | +[david-url]: https://david-dm.org/eggjs/egg-ldapjs | |
18 | +[snyk-image]: https://snyk.io/test/npm/egg-ldapjs/badge.svg?style=flat-square | |
19 | +[snyk-url]: https://snyk.io/test/npm/egg-ldapjs | |
20 | +[download-image]: https://img.shields.io/npm/dm/egg-ldapjs.svg?style=flat-square | |
21 | +[download-url]: https://npmjs.org/package/egg-ldapjs | |
22 | + | |
23 | +<!-- | |
24 | +Description here. | |
25 | +--> | |
26 | + | |
27 | +## Install | |
28 | + | |
29 | +```bash | |
30 | +$ npm i egg-ldapjs --save | |
31 | +``` | |
32 | + | |
33 | +## Usage | |
34 | + | |
35 | +```js | |
36 | +// {app_root}/config/plugin.js | |
37 | +exports.ldapjs = { | |
38 | + enable: true, | |
39 | + package: 'egg-ldapjs', | |
40 | +}; | |
41 | +``` | |
42 | + | |
43 | +## Configuration | |
44 | + | |
45 | +```js | |
46 | +// {app_root}/config/config.default.js | |
47 | +exports.ldapjs = { | |
48 | +}; | |
49 | +``` | |
50 | + | |
51 | +see [config/config.default.js](config/config.default.js) for more detail. | |
52 | + | |
53 | +## Example | |
54 | + | |
55 | +<!-- example here --> | |
56 | + | |
57 | +## Questions & Suggestions | |
58 | + | |
59 | +Please open an issue [here](https://github.com/eggjs/egg/issues). | |
60 | + | |
61 | +## License | |
62 | + | |
63 | +[MIT](LICENSE) | ... | ... |
README.zh_CN.md
0 → 100644
1 | +# egg-ldapjs | |
2 | + | |
3 | +[![NPM version][npm-image]][npm-url] | |
4 | +[![build status][travis-image]][travis-url] | |
5 | +[![Test coverage][codecov-image]][codecov-url] | |
6 | +[![David deps][david-image]][david-url] | |
7 | +[![Known Vulnerabilities][snyk-image]][snyk-url] | |
8 | +[![npm download][download-image]][download-url] | |
9 | + | |
10 | +[npm-image]: https://img.shields.io/npm/v/egg-ldapjs.svg?style=flat-square | |
11 | +[npm-url]: https://npmjs.org/package/egg-ldapjs | |
12 | +[travis-image]: https://img.shields.io/travis/eggjs/egg-ldapjs.svg?style=flat-square | |
13 | +[travis-url]: https://travis-ci.org/eggjs/egg-ldapjs | |
14 | +[codecov-image]: https://img.shields.io/codecov/c/github/eggjs/egg-ldapjs.svg?style=flat-square | |
15 | +[codecov-url]: https://codecov.io/github/eggjs/egg-ldapjs?branch=master | |
16 | +[david-image]: https://img.shields.io/david/eggjs/egg-ldapjs.svg?style=flat-square | |
17 | +[david-url]: https://david-dm.org/eggjs/egg-ldapjs | |
18 | +[snyk-image]: https://snyk.io/test/npm/egg-ldapjs/badge.svg?style=flat-square | |
19 | +[snyk-url]: https://snyk.io/test/npm/egg-ldapjs | |
20 | +[download-image]: https://img.shields.io/npm/dm/egg-ldapjs.svg?style=flat-square | |
21 | +[download-url]: https://npmjs.org/package/egg-ldapjs | |
22 | + | |
23 | +<!-- | |
24 | +Description here. | |
25 | +--> | |
26 | + | |
27 | +## 依赖说明 | |
28 | + | |
29 | +### 依赖的 egg 版本 | |
30 | + | |
31 | +egg-ldapjs 版本 | egg 1.x | |
32 | +--- | --- | |
33 | +1.x | 😁 | |
34 | +0.x | ❌ | |
35 | + | |
36 | +### 依赖的插件 | |
37 | +<!-- | |
38 | + | |
39 | +如果有依赖其它插件,请在这里特别说明。如 | |
40 | + | |
41 | +- security | |
42 | +- multipart | |
43 | + | |
44 | +--> | |
45 | + | |
46 | +## 开启插件 | |
47 | + | |
48 | +```js | |
49 | +// config/plugin.js | |
50 | +exports.ldapjs = { | |
51 | + enable: true, | |
52 | + package: 'egg-ldapjs', | |
53 | +}; | |
54 | +``` | |
55 | + | |
56 | +## 使用场景 | |
57 | + | |
58 | +- Why and What: 描述为什么会有这个插件,它主要在完成一件什么事情。 | |
59 | +尽可能描述详细。 | |
60 | +- How: 描述这个插件是怎样使用的,具体的示例代码,甚至提供一个完整的示例,并给出链接。 | |
61 | + | |
62 | +## 详细配置 | |
63 | + | |
64 | +请到 [config/config.default.js](config/config.default.js) 查看详细配置项说明。 | |
65 | + | |
66 | +## 单元测试 | |
67 | + | |
68 | +<!-- 描述如何在单元测试中使用此插件,例如 schedule 如何触发。无则省略。--> | |
69 | + | |
70 | +## 提问交流 | |
71 | + | |
72 | +请到 [egg issues](https://github.com/eggjs/egg/issues) 异步交流。 | |
73 | + | |
74 | +## License | |
75 | + | |
76 | +[MIT](LICENSE) | ... | ... |
app.js
0 → 100644
appveyor.yml
0 → 100644
1 | +environment: | |
2 | + matrix: | |
3 | + - nodejs_version: '8' | |
4 | + - nodejs_version: '10' | |
5 | + | |
6 | +install: | |
7 | + - ps: Install-Product node $env:nodejs_version | |
8 | + - npm i npminstall && node_modules\.bin\npminstall | |
9 | + | |
10 | +test_script: | |
11 | + - node --version | |
12 | + - npm --version | |
13 | + - npm run test | |
14 | + | |
15 | +build: off | ... | ... |
config/config.default.js
0 → 100644
lib/ldap.js
0 → 100644
1 | +'use strict'; | |
2 | +const assert = require('assert'); | |
3 | +const Promise = require('any-promise'); | |
4 | +const ldap = require('ldapjs'); | |
5 | + | |
6 | +let count = 0; | |
7 | + | |
8 | +module.exports = app => { | |
9 | + app.addSingleton('ldapjs', createClient); | |
10 | +}; | |
11 | + | |
12 | +function createClient(config, app) { | |
13 | + assert(config.url && config.dn && config.password, | |
14 | + `[egg-ldapjs] 'url: ${config.url}', 'dn: ${config.dn}', 'password: ${config.password}' are required on config`); | |
15 | + | |
16 | + app.coreLogger.info('[egg-ldapjs] connecting %s@%s:%s/%s', | |
17 | + config.dn, config.url); | |
18 | + | |
19 | + const LdapClient = options => { | |
20 | + this.client = ldap.createClient(options); | |
21 | + }; | |
22 | + function promisify(fn) { | |
23 | + return function() { | |
24 | + const client = this.client; | |
25 | + const args = Array.prototype.slice.call(arguments); | |
26 | + | |
27 | + return new Promise(function(resolve, reject) { | |
28 | + args.push(function(err, result) { | |
29 | + if (err) reject(err); | |
30 | + else resolve(result); | |
31 | + }); | |
32 | + | |
33 | + client[fn].apply(client, args); | |
34 | + }); | |
35 | + }; | |
36 | + } | |
37 | + | |
38 | + [ 'bind', 'add', 'compare', 'del', 'exop', 'modify', 'modifyDN', 'unbind' ].forEach(function(fn) { | |
39 | + LdapClient.prototype[fn] = promisify(fn); | |
40 | + }); | |
41 | + | |
42 | + LdapClient.prototype.destroy = function() { this.client.destroy(); }; | |
43 | + LdapClient.prototype._search = promisify('search'); | |
44 | + | |
45 | + | |
46 | + LdapClient.prototype.search = function(base, options, controls) { | |
47 | + const client = this.client; | |
48 | + | |
49 | + return new Promise(function(resolve, reject) { | |
50 | + const searchCallback = function(err, result) { | |
51 | + const r = { | |
52 | + entries: [], | |
53 | + references: [], | |
54 | + }; | |
55 | + | |
56 | + result.on('searchEntry', function(entry) { | |
57 | + r.entries.push(entry); | |
58 | + }); | |
59 | + | |
60 | + result.on('searchReference', function(reference) { | |
61 | + r.references.push(reference); | |
62 | + }); | |
63 | + | |
64 | + result.on('error', function(err) { | |
65 | + reject(err); | |
66 | + }); | |
67 | + | |
68 | + result.on('end', function(result) { | |
69 | + if (result.status === 0) { | |
70 | + resolve(r); | |
71 | + } else { | |
72 | + reject(new Error('non-zero status code: ' + result.status)); | |
73 | + } | |
74 | + }); | |
75 | + }; | |
76 | + | |
77 | + const args = ([ base, options, controls, searchCallback ]) | |
78 | + .filter(function(x) { return typeof x !== 'undefined'; }); | |
79 | + | |
80 | + client.search.apply(client, args); | |
81 | + }); | |
82 | + }; | |
83 | + | |
84 | + | |
85 | + LdapClient.prototype.authenticate = function(base, cn, password) { | |
86 | + const _this = this; | |
87 | + | |
88 | + return _this.bind('CN=' + cn + ',' + base, password).then( | |
89 | + function() { | |
90 | + return _this.search(base, { scope: 'sub', filter: '(cn=' + cn + ')' }).then(function(result) { | |
91 | + return result.entries[0].object; | |
92 | + }); | |
93 | + }, | |
94 | + function(err) { | |
95 | + if (err.name === 'InvalidCredentialsError') { | |
96 | + return null; | |
97 | + } | |
98 | + throw err; | |
99 | + | |
100 | + } | |
101 | + ); | |
102 | + }; | |
103 | + | |
104 | + | |
105 | + LdapClient.prototype.authenticateUser = function(base, cn, password) { | |
106 | + const dnRegex = new RegExp('^CN=([^,]+),' + base + '$'); | |
107 | + | |
108 | + return this.authenticate(base, cn, password).then(function(result) { | |
109 | + if (result) { | |
110 | + let groups = []; | |
111 | + | |
112 | + if (result.memberOf) { | |
113 | + groups = result.memberOf | |
114 | + .map(function(x) { return (x.match(dnRegex) || [])[1]; }) | |
115 | + .filter(function(x) { return typeof x !== 'undefined'; }); | |
116 | + } | |
117 | + | |
118 | + return { | |
119 | + email: result.userPrincipalName, | |
120 | + name: result.displayName, | |
121 | + groups, | |
122 | + }; | |
123 | + | |
124 | + } | |
125 | + return null; | |
126 | + | |
127 | + }); | |
128 | + }; | |
129 | + | |
130 | + | |
131 | + const client = new LdapClient({ url: config.url }); | |
132 | + | |
133 | + app.beforeStart(async () => { | |
134 | + const result = await client.bind(config.dn, config.password); | |
135 | + const index = count++; | |
136 | + app.coreLogger.info(`[egg-ldapjs] instance[${index}] status OK, client ready ${result}`); | |
137 | + }); | |
138 | + return client; | |
139 | +} | ... | ... |
package-lock.json
0 → 100644
此 diff 太大无法显示。
package.json
0 → 100644
1 | +{ | |
2 | + "name": "egg-ldapjs", | |
3 | + "version": "1.0.0", | |
4 | + "description": "openldap ldap", | |
5 | + "eggPlugin": { | |
6 | + "name": "ldapjs" | |
7 | + }, | |
8 | + "keywords": [ | |
9 | + "egg", | |
10 | + "eggPlugin", | |
11 | + "egg-plugin", | |
12 | + "ldap", | |
13 | + "ldapjs" | |
14 | + ], | |
15 | + "dependencies": { | |
16 | + "any-promise": "^1.3.0", | |
17 | + "ldapjs": "^2.3.2" | |
18 | + }, | |
19 | + "devDependencies": { | |
20 | + "autod": "^3.0.1", | |
21 | + "autod-egg": "^1.1.0", | |
22 | + "egg": "^2.16.0", | |
23 | + "egg-bin": "^4.11.0", | |
24 | + "egg-ci": "^1.11.0", | |
25 | + "egg-mock": "^3.21.0", | |
26 | + "eslint": "^5.13.0", | |
27 | + "eslint-config-egg": "^7.1.0" | |
28 | + }, | |
29 | + "engines": { | |
30 | + "node": ">=8.0.0" | |
31 | + }, | |
32 | + "scripts": { | |
33 | + "test": "npm run lint -- --fix && egg-bin pkgfiles && npm run test-local", | |
34 | + "test-local": "egg-bin test", | |
35 | + "cov": "egg-bin cov", | |
36 | + "lint": "eslint .", | |
37 | + "ci": "egg-bin pkgfiles --check && npm run lint && npm run cov", | |
38 | + "pkgfiles": "egg-bin pkgfiles", | |
39 | + "autod": "autod" | |
40 | + }, | |
41 | + "files": [ | |
42 | + "config", | |
43 | + "app.js", | |
44 | + "lib" | |
45 | + ], | |
46 | + "ci": { | |
47 | + "version": "8, 10" | |
48 | + }, | |
49 | + "repository": { | |
50 | + "type": "git", | |
51 | + "url": "git+https://github.com/eggjs/egg-ldapjs.git" | |
52 | + }, | |
53 | + "bugs": { | |
54 | + "url": "https://github.com/eggjs/egg/issues" | |
55 | + }, | |
56 | + "homepage": "https://github.com/eggjs/egg-ldapjs#readme", | |
57 | + "author": "fan", | |
58 | + "license": "MIT" | |
59 | +} | ... | ... |
1 | +'use strict'; | |
2 | + | |
3 | +const Controller = require('egg').Controller; | |
4 | + | |
5 | +class HomeController extends Controller { | |
6 | + async index() { | |
7 | + this.ctx.body = 'hi, ' + this.app.plugins.ldapjs.name; | |
8 | + const opts = { | |
9 | + filter: '(objectclass=organizationalUnit)', | |
10 | + scope: 'sub', | |
11 | + attributes: [ 'dn', 'sn', 'cn', 'ou' ], | |
12 | + }; | |
13 | + console.log(this.app.ldapjs); | |
14 | + const result = await this.app.ldapjs.search('dc=dodokeroro,dc=cn', opts); | |
15 | + console.log('result::::', result); | |
16 | + } | |
17 | +} | |
18 | + | |
19 | +module.exports = HomeController; | ... | ... |
test/fixtures/apps/ldapjs-test/app/router.js
0 → 100644
1 | +'use strict'; | |
2 | + | |
3 | +/** | |
4 | + * egg-ldapjs default config | |
5 | + * @member Config#ldapjs | |
6 | + * @property {String} SOME_KEY - some description | |
7 | + */ | |
8 | +exports.ldapjs = { | |
9 | + url: 'ldap://test.dodokeroro.cn:30007', | |
10 | + dn: 'cn=admin,dc=dodokeroro,dc=cn', | |
11 | + password: 'workai123', | |
12 | +}; | |
13 | + | |
14 | +exports.keys = '123456'; | ... | ... |
test/fixtures/apps/ldapjs-test/package.json
0 → 100644
test/ldapjs.test.js
0 → 100644
1 | +'use strict'; | |
2 | + | |
3 | +const mock = require('egg-mock'); | |
4 | + | |
5 | +describe('test/ldapjs.test.js', () => { | |
6 | + let app; | |
7 | + before(() => { | |
8 | + app = mock.app({ | |
9 | + baseDir: 'apps/ldapjs-test', | |
10 | + }); | |
11 | + return app.ready(); | |
12 | + }); | |
13 | + | |
14 | + after(() => app.close()); | |
15 | + afterEach(mock.restore); | |
16 | + | |
17 | + it('should GET /', () => { | |
18 | + return app.httpRequest() | |
19 | + .get('/') | |
20 | + .expect('hi, ldapjs') | |
21 | + .expect(200); | |
22 | + }); | |
23 | +}); | ... | ... |
请
注册
或
登录
后发表评论