Showing
53 changed files
with
2807 additions
and
6 deletions
... | @@ -9,6 +9,7 @@ var index = require('./routes/index'); | ... | @@ -9,6 +9,7 @@ var index = require('./routes/index'); |
9 | var users = require('./routes/users'); | 9 | var users = require('./routes/users'); |
10 | var calendar = require('./routes/calendar'); | 10 | var calendar = require('./routes/calendar'); |
11 | var events = require('./routes/events'); | 11 | var events = require('./routes/events'); |
12 | +var login = require('./routes/login') | ||
12 | 13 | ||
13 | passport.serializeUser(function(user,done) { | 14 | passport.serializeUser(function(user,done) { |
14 | console.log('serialized'); | 15 | console.log('serialized'); |
... | @@ -44,6 +45,7 @@ app.use('/', index); | ... | @@ -44,6 +45,7 @@ app.use('/', index); |
44 | app.use('/users', users); | 45 | app.use('/users', users); |
45 | app.use('/calendar',calendar); | 46 | app.use('/calendar',calendar); |
46 | app.use('/events',events); | 47 | app.use('/events',events); |
48 | +app.use('/login',login); | ||
47 | 49 | ||
48 | // catch 404 and forward to error handler | 50 | // catch 404 and forward to error handler |
49 | app.use(function(req, res, next) { | 51 | app.use(function(req, res, next) { | ... | ... |
node_modules/passport-kakao/.prettierrc
0 → 100644
node_modules/passport-kakao/.travis.yml
0 → 100644
node_modules/passport-kakao/README.md
0 → 100644
1 | +# passport-kakao | ||
2 | + | ||
3 | +kakao oauth2 로그인과 passport 모듈 연결체. | ||
4 | + | ||
5 | +## install | ||
6 | + | ||
7 | +```sh | ||
8 | +npm install passport-kakao | ||
9 | +``` | ||
10 | + | ||
11 | +## how to use | ||
12 | + | ||
13 | +- https://developers.kakao.com/ 에서 애플리케이션을 등록한다. | ||
14 | +- 방금 추가한 애플리케이션의 설정 - 사용자 관리에 들어가서 사용을 ON으로 한 뒤 저장한다. | ||
15 | +- 설정 - 일반에서, 플랫폼 추가를 누른 후 웹 플랫폼을 추가한다. | ||
16 | +- 웹 플랫폼 설정의 사이트 도메인에 자신의 사이트 도메인을 추가한다. (ex : http://localhost:3000) | ||
17 | +- 프로그램 상에서는 아래와 같이 사용한다. | ||
18 | + | ||
19 | +> clientSecret을 활성화 한 경우 해당 파라메터를 같이 넘겨줘야한다. | ||
20 | + | ||
21 | +```javascript | ||
22 | +const passport = require('passport') | ||
23 | +const KakaoStrategy = require('passport-kakao').Strategy | ||
24 | + | ||
25 | +passport.use(new KakaoStrategy({ | ||
26 | + clientID : clientID, | ||
27 | + clientSecret: clientSecret, // clientSecret을 사용하지 않는다면 넘기지 말거나 빈 스트링을 넘길 것 | ||
28 | + callbackURL : callbackURL | ||
29 | + }, | ||
30 | + (accessToken, refreshToken, profile, done) => { | ||
31 | + // 사용자의 정보는 profile에 들어있다. | ||
32 | + User.findOrCreate(..., (err, user) => { | ||
33 | + if (err) { return done(err) } | ||
34 | + return done(null, user) | ||
35 | + }) | ||
36 | + } | ||
37 | +)) | ||
38 | +``` | ||
39 | + | ||
40 | +> 기본 callbackPath는 `/oauth` 이고 https://developers.kakao.com 에서 수정할 수 있다. 하지만 callbackURL은 `사이트 도메인/oauth` 로 설정하는 것을 권장함. (ex : http://myhomepage.com:3000/oauth ) | ||
41 | + | ||
42 | +## | ||
43 | + | ||
44 | +## profile property | ||
45 | + | ||
46 | +profile에는 아래의 property들이 설정되어 넘겨진다. | ||
47 | + | ||
48 | +| key | value | 비고 | | ||
49 | +| -------- | ------ | ------------------------------------------ | | ||
50 | +| provider | String | kakao 고정 | | ||
51 | +| id | Number | 사용자의 kakao id | | ||
52 | +| \_raw | String | 사용자 정보 조회로 얻어진 json string | | ||
53 | +| \_json | Object | 사용자 정보 조회로 얻어진 json 원본 데이터 | | ||
54 | + | ||
55 | +## simple sample | ||
56 | + | ||
57 | +### 설치 & 실행 | ||
58 | + | ||
59 | +1. `./sample/sample.js` 의 `appKey` 를 https://developers.kakao.com 에서 발급받은 JS appKey 값으로 셋팅. | ||
60 | +2. command line 에서 아래의 커맨드 실행 | ||
61 | +3. 브라우져를 열고 `127.0.0.1:3000/login` 을 입력 후 이후 과정을 진행한다. | ||
62 | + | ||
63 | +``` | ||
64 | +cd ./sample | ||
65 | +npm install | ||
66 | +node app | ||
67 | +``` | ||
68 | + | ||
69 | +## mean.io 와 쉽게 연동하기 | ||
70 | + | ||
71 | +수정해야하는 파일들은 아래와 같다. | ||
72 | + | ||
73 | +| file path | 설명 | | ||
74 | +| -------------------------------- | ------------------------------ | | ||
75 | +| server/config/env/development.js | 개발환경 설정파일 | | ||
76 | +| server/config/env/production.js | 운영환경 설정파일 | | ||
77 | +| server/config/models/user.js | 사용자 모델 | | ||
78 | +| server/config/passport.js | passport script | | ||
79 | +| server/routes/users.js | 사용자 로그인 관련 routes file | | ||
80 | +| public/auth/views/index.html | 로그인 화면 | | ||
81 | + | ||
82 | +(1) **mean.io app을 생성** 한다. (ex : mean init kakaoTest) | ||
83 | + | ||
84 | +(2) 해당 모듈을 연동할 mean.io app에 설치한다.(npm install passport-kakao --save) | ||
85 | + | ||
86 | +(3) **server/config/env/development.js** 와 **production.js** 에 kakao 관련 설정을 아래와 같이 추가한다. | ||
87 | + | ||
88 | +```javascript | ||
89 | +'use strict' | ||
90 | + | ||
91 | +module.exports = { | ||
92 | + db: 'mongodb', | ||
93 | + app: { | ||
94 | + name: 'passport-kakao', | ||
95 | + }, | ||
96 | + // 그외 설정들...., | ||
97 | + kakao: { | ||
98 | + clientID: 'kakao app rest api key', | ||
99 | + callbackURL: 'http://localhost:3000/oauth', | ||
100 | + }, | ||
101 | +} | ||
102 | +``` | ||
103 | + | ||
104 | +(4) **server/config/models/users.js** 의 사용자 스키마 정의에 **kakao: {}** 를 추가한다. | ||
105 | + | ||
106 | +(5) **server/config/passport.js** 파일에 아래 구문을 추가한다. | ||
107 | + | ||
108 | +```javascript | ||
109 | +// 최상단 require되는 구문에 추가 | ||
110 | +var KakaoStrategy = require('passport-kakao').Strategy | ||
111 | + | ||
112 | +passport.use( | ||
113 | + new KakaoStrategy( | ||
114 | + { | ||
115 | + clientID: config.kakao.clientID, | ||
116 | + callbackURL: config.kakao.callbackURL, | ||
117 | + }, | ||
118 | + function(accessToken, refreshToken, profile, done) { | ||
119 | + User.findOne( | ||
120 | + { | ||
121 | + 'kakao.id': profile.id, | ||
122 | + }, | ||
123 | + function(err, user) { | ||
124 | + if (err) { | ||
125 | + return done(err) | ||
126 | + } | ||
127 | + if (!user) { | ||
128 | + user = new User({ | ||
129 | + name: profile.username, | ||
130 | + username: profile.id, | ||
131 | + roles: ['authenticated'], | ||
132 | + provider: 'kakao', | ||
133 | + kakao: profile._json, | ||
134 | + }) | ||
135 | + | ||
136 | + user.save(function(err) { | ||
137 | + if (err) { | ||
138 | + console.log(err) | ||
139 | + } | ||
140 | + return done(err, user) | ||
141 | + }) | ||
142 | + } else { | ||
143 | + return done(err, user) | ||
144 | + } | ||
145 | + } | ||
146 | + ) | ||
147 | + } | ||
148 | + ) | ||
149 | +) | ||
150 | +``` | ||
151 | + | ||
152 | +(6) **server/routes/users.js** 에 아래와 같은 구문을 추가한다. | ||
153 | + | ||
154 | +```javascript | ||
155 | +app.get( | ||
156 | + '/auth/kakao', | ||
157 | + passport.authenticate('kakao', { | ||
158 | + failureRedirect: '#!/login', | ||
159 | + }), | ||
160 | + users.signin | ||
161 | +) | ||
162 | + | ||
163 | +app.get( | ||
164 | + '/oauth', | ||
165 | + passport.authenticate('kakao', { | ||
166 | + failureRedirect: '#!/login', | ||
167 | + }), | ||
168 | + users.authCallback | ||
169 | +) | ||
170 | +``` | ||
171 | + | ||
172 | +(7) **public/auth/views/index.html** 에 kakao login을 연결한다. | ||
173 | + | ||
174 | +```html | ||
175 | +<!-- 아래는 예시 --> | ||
176 | +<div> | ||
177 | + <div class="row"> | ||
178 | + <div class="col-md-offset-1 col-md-5"> | ||
179 | + <a href="/auth/facebook"> | ||
180 | + <img src="/public/auth/assets/img/icons/facebook.png" /> | ||
181 | + </a> | ||
182 | + <a href="/auth/twitter"> | ||
183 | + <img src="/public/auth/assets/img/icons/twitter.png" /> | ||
184 | + </a> | ||
185 | + | ||
186 | + <!-- kakao login --> | ||
187 | + <a href="/auth/kakao"> | ||
188 | + <img | ||
189 | + src="https://developers.kakao.com/assets/img/about/logos/kakaolink/kakaolink_btn_medium.png" | ||
190 | + /> | ||
191 | + </a> | ||
192 | + </div> | ||
193 | + </div> | ||
194 | + <div class="col-md-6"> | ||
195 | + <div ui-view></div> | ||
196 | + </div> | ||
197 | +</div> | ||
198 | +``` | ||
199 | + | ||
200 | +(8) grunt로 mean.io app 실행 후, 실제 로그인 연동 테스트를 해본다. | ||
201 | + | ||
202 | +## 기타 | ||
203 | + | ||
204 | +passport-oauth 모듈과 passport-facebook 모듈을 참고함. |
node_modules/passport-kakao/dist/Strategy.js
0 → 100644
1 | +"use strict"; | ||
2 | +var __importDefault = (this && this.__importDefault) || function (mod) { | ||
3 | + return (mod && mod.__esModule) ? mod : { "default": mod }; | ||
4 | +}; | ||
5 | +Object.defineProperty(exports, "__esModule", { value: true }); | ||
6 | +var util_1 = require("util"); | ||
7 | +var passport_oauth2_1 = __importDefault(require("passport-oauth2")); | ||
8 | +var DEFAULT_CLIENT_SECRET = 'kakao'; | ||
9 | +var OAUTH_HOST = 'https://kauth.kakao.com'; | ||
10 | +var USER_PROFILE_URL = 'https://kapi.kakao.com/v2/user/me'; | ||
11 | +exports.buildOptions = function (options) { | ||
12 | + options.authorizationURL = OAUTH_HOST + "/oauth/authorize"; | ||
13 | + options.tokenURL = OAUTH_HOST + "/oauth/token"; | ||
14 | + if (!options.clientSecret) { | ||
15 | + options.clientSecret = DEFAULT_CLIENT_SECRET; | ||
16 | + } | ||
17 | + options.scopeSeparator = options.scopeSeparator || ','; | ||
18 | + options.customHeaders = options.customHeaders || {}; | ||
19 | + if (!options.customHeaders['User-Agent']) { | ||
20 | + options.customHeaders['User-Agent'] = options.userAgent || 'passport-kakao'; | ||
21 | + } | ||
22 | + return options; | ||
23 | +}; | ||
24 | +/** | ||
25 | + * KaKaoStrategy 생성자 함수.<br/> | ||
26 | + * @param options.clientID 필수. kakao rest app key. | ||
27 | + * @param options.callbackURL 필수. 로그인 처리 후 호출할 URL | ||
28 | + * @param verify | ||
29 | + * @constructor | ||
30 | + */ | ||
31 | +function Strategy(options, verify) { | ||
32 | + if (options === void 0) { options = {}; } | ||
33 | + passport_oauth2_1.default.call(this, exports.buildOptions(options), verify); | ||
34 | + this.name = 'kakao'; | ||
35 | + this._userProfileURL = USER_PROFILE_URL; | ||
36 | +} | ||
37 | +/** | ||
38 | + * `OAuth2Stragegy`를 상속 받는다. | ||
39 | + */ | ||
40 | +util_1.inherits(Strategy, passport_oauth2_1.default); | ||
41 | +/** | ||
42 | + * kakao 사용자 정보를 얻는다.<br/> | ||
43 | + * 사용자 정보를 성공적으로 조회하면 아래의 object가 done 콜백함수 호출과 함꼐 넘어간다. | ||
44 | + * | ||
45 | + * - `provider` kakao 고정 | ||
46 | + * - `id` kakao user id number | ||
47 | + * - `username` 사용자의 kakao nickname | ||
48 | + * - `_raw` json string 원문 | ||
49 | + * _ `_json` json 원 데이터 | ||
50 | + * | ||
51 | + * @param {String} accessToken | ||
52 | + * @param {Function} done | ||
53 | + */ | ||
54 | +Strategy.prototype.userProfile = function (accessToken, done) { | ||
55 | + this._oauth2.get(this._userProfileURL, accessToken, function (err, body) { | ||
56 | + if (err) { | ||
57 | + return done(err); | ||
58 | + } | ||
59 | + try { | ||
60 | + var json = JSON.parse(body); | ||
61 | + // 카카오톡이나 카카오스토리에 연동한 적이 없는 계정의 경우 | ||
62 | + // properties가 비어있다고 한다. 없을 경우의 처리 | ||
63 | + var properties = json.properties || { | ||
64 | + nickname: '미연동 계정', | ||
65 | + }; | ||
66 | + var profile = { | ||
67 | + provider: 'kakao', | ||
68 | + id: json.id, | ||
69 | + username: properties.nickname, | ||
70 | + displayName: properties.nickname, | ||
71 | + _raw: body, | ||
72 | + _json: json, | ||
73 | + }; | ||
74 | + return done(null, profile); | ||
75 | + } | ||
76 | + catch (e) { | ||
77 | + return done(e); | ||
78 | + } | ||
79 | + }); | ||
80 | +}; | ||
81 | +exports.default = Strategy; |
1 | +"use strict"; | ||
2 | +var __importDefault = (this && this.__importDefault) || function (mod) { | ||
3 | + return (mod && mod.__esModule) ? mod : { "default": mod }; | ||
4 | +}; | ||
5 | +Object.defineProperty(exports, "__esModule", { value: true }); | ||
6 | +var Strategy_1 = __importDefault(require("./Strategy")); | ||
7 | +exports.Strategy = Strategy_1.default; | ||
8 | +exports.default = Strategy_1.default; |
1 | +"use strict"; | ||
2 | +var __importDefault = (this && this.__importDefault) || function (mod) { | ||
3 | + return (mod && mod.__esModule) ? mod : { "default": mod }; | ||
4 | +}; | ||
5 | +Object.defineProperty(exports, "__esModule", { value: true }); | ||
6 | +var util_1 = require("util"); | ||
7 | +var passport_oauth2_1 = __importDefault(require("passport-oauth2")); | ||
8 | +var DEFAULT_CLIENT_SECRET = 'kakao'; | ||
9 | +var OAUTH_HOST = 'https://kauth.kakao.com'; | ||
10 | +var USER_PROFILE_URL = 'https://kapi.kakao.com/v2/user/me'; | ||
11 | +exports.buildOptions = function (options) { | ||
12 | + options.authorizationURL = OAUTH_HOST + "/oauth/authorize"; | ||
13 | + options.tokenURL = OAUTH_HOST + "/oauth/token"; | ||
14 | + if (!options.clientSecret) { | ||
15 | + options.clientSecret = DEFAULT_CLIENT_SECRET; | ||
16 | + } | ||
17 | + options.scopeSeparator = options.scopeSeparator || ','; | ||
18 | + options.customHeaders = options.customHeaders || {}; | ||
19 | + if (!options.customHeaders['User-Agent']) { | ||
20 | + options.customHeaders['User-Agent'] = options.userAgent || 'passport-kakao'; | ||
21 | + } | ||
22 | + return options; | ||
23 | +}; | ||
24 | +/** | ||
25 | + * KaKaoStrategy 생성자 함수.<br/> | ||
26 | + * @param options.clientID 필수. kakao rest app key. | ||
27 | + * @param options.callbackURL 필수. 로그인 처리 후 호출할 URL | ||
28 | + * @param verify | ||
29 | + * @constructor | ||
30 | + */ | ||
31 | +function Strategy(options, verify) { | ||
32 | + if (options === void 0) { options = {}; } | ||
33 | + passport_oauth2_1.default.call(this, exports.buildOptions(options), verify); | ||
34 | + this.name = 'kakao'; | ||
35 | + this._userProfileURL = USER_PROFILE_URL; | ||
36 | +} | ||
37 | +/** | ||
38 | + * `OAuth2Stragegy`를 상속 받는다. | ||
39 | + */ | ||
40 | +util_1.inherits(Strategy, passport_oauth2_1.default); | ||
41 | +/** | ||
42 | + * kakao 사용자 정보를 얻는다.<br/> | ||
43 | + * 사용자 정보를 성공적으로 조회하면 아래의 object가 done 콜백함수 호출과 함꼐 넘어간다. | ||
44 | + * | ||
45 | + * - `provider` kakao 고정 | ||
46 | + * - `id` kakao user id number | ||
47 | + * - `username` 사용자의 kakao nickname | ||
48 | + * - `_raw` json string 원문 | ||
49 | + * _ `_json` json 원 데이터 | ||
50 | + * | ||
51 | + * @param {String} accessToken | ||
52 | + * @param {Function} done | ||
53 | + */ | ||
54 | +Strategy.prototype.userProfile = function (accessToken, done) { | ||
55 | + this._oauth2.get(this._userProfileURL, accessToken, function (err, body) { | ||
56 | + if (err) { | ||
57 | + return done(err); | ||
58 | + } | ||
59 | + try { | ||
60 | + var json = JSON.parse(body); | ||
61 | + // 카카오톡이나 카카오스토리에 연동한 적이 없는 계정의 경우 | ||
62 | + // properties가 비어있다고 한다. 없을 경우의 처리 | ||
63 | + var properties = json.properties || { | ||
64 | + nickname: '미연동 계정', | ||
65 | + }; | ||
66 | + var profile = { | ||
67 | + provider: 'kakao', | ||
68 | + id: json.id, | ||
69 | + username: properties.nickname, | ||
70 | + displayName: properties.nickname, | ||
71 | + _raw: body, | ||
72 | + _json: json, | ||
73 | + }; | ||
74 | + return done(null, profile); | ||
75 | + } | ||
76 | + catch (e) { | ||
77 | + return done(e); | ||
78 | + } | ||
79 | + }); | ||
80 | +}; | ||
81 | +exports.default = Strategy; |
1 | +"use strict"; | ||
2 | +var __importDefault = (this && this.__importDefault) || function (mod) { | ||
3 | + return (mod && mod.__esModule) ? mod : { "default": mod }; | ||
4 | +}; | ||
5 | +Object.defineProperty(exports, "__esModule", { value: true }); | ||
6 | +var Strategy_1 = __importDefault(require("./Strategy")); | ||
7 | +exports.Strategy = Strategy_1.default; | ||
8 | +exports.default = Strategy_1.default; |
1 | +"use strict"; | ||
2 | +var __importStar = (this && this.__importStar) || function (mod) { | ||
3 | + if (mod && mod.__esModule) return mod; | ||
4 | + var result = {}; | ||
5 | + if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k]; | ||
6 | + result["default"] = mod; | ||
7 | + return result; | ||
8 | +}; | ||
9 | +Object.defineProperty(exports, "__esModule", { value: true }); | ||
10 | +var chai_1 = require("chai"); | ||
11 | +var Strategy_1 = __importStar(require("../src/Strategy")); | ||
12 | +describe('passport-kakao', function () { | ||
13 | + it('passport-kakao 객체가 제대로 생성이 되어 있어야 한다.', function () { | ||
14 | + chai_1.expect(Strategy_1.default).to.not.equals(null); | ||
15 | + }); | ||
16 | + it('Strategy option의 clientSecret 값이 없을 경우 default 값이 설정되어야 한다.', function () { | ||
17 | + var options = Strategy_1.buildOptions({}); | ||
18 | + chai_1.expect(options).to.not.equals(null); | ||
19 | + chai_1.expect(options.clientSecret).to.be.equals('kakao'); | ||
20 | + chai_1.expect(options.scopeSeparator).to.be.equals(','); | ||
21 | + chai_1.expect(options.customHeaders['User-Agent']).to.be.equals('passport-kakao'); | ||
22 | + }); | ||
23 | + it('Strategy option의 User-Agent값이 있을 경우 customHeaders의 User-Agent가 해당 값으로 설정되어야 한다.', function () { | ||
24 | + var options = Strategy_1.buildOptions({ | ||
25 | + customHeaders: { | ||
26 | + 'User-Agent': 'HELLO ROTO', | ||
27 | + }, | ||
28 | + }); | ||
29 | + chai_1.expect(options.customHeaders['User-Agent']).to.be.equals('HELLO ROTO'); | ||
30 | + }); | ||
31 | +}); |
1 | +(The MIT License) | ||
2 | + | ||
3 | +Copyright (c) 2011-2014 Jared Hanson | ||
4 | + | ||
5 | +Permission is hereby granted, free of charge, to any person obtaining a copy of | ||
6 | +this software and associated documentation files (the "Software"), to deal in | ||
7 | +the Software without restriction, including without limitation the rights to | ||
8 | +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of | ||
9 | +the Software, and to permit persons to whom the Software is furnished to do so, | ||
10 | +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, FITNESS | ||
17 | +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR | ||
18 | +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER | ||
19 | +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | ||
20 | +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
1 | +# passport-oauth2 | ||
2 | + | ||
3 | +[![Build](https://travis-ci.org/jaredhanson/passport-oauth2.png)](https://travis-ci.org/jaredhanson/passport-oauth2) | ||
4 | +[![Coverage](https://coveralls.io/repos/jaredhanson/passport-oauth2/badge.png)](https://coveralls.io/r/jaredhanson/passport-oauth2) | ||
5 | +[![Quality](https://codeclimate.com/github/jaredhanson/passport-oauth2.png)](https://codeclimate.com/github/jaredhanson/passport-oauth2) | ||
6 | +[![Dependencies](https://david-dm.org/jaredhanson/passport-oauth2.png)](https://david-dm.org/jaredhanson/passport-oauth2) | ||
7 | +[![Tips](http://img.shields.io/gittip/jaredhanson.png)](https://www.gittip.com/jaredhanson/) | ||
8 | + | ||
9 | +General-purpose OAuth 2.0 authentication strategy for [Passport](http://passportjs.org/). | ||
10 | + | ||
11 | +This module lets you authenticate using OAuth 2.0 in your Node.js applications. | ||
12 | +By plugging into Passport, OAuth 2.0 authentication can be easily and | ||
13 | +unobtrusively integrated into any application or framework that supports | ||
14 | +[Connect](http://www.senchalabs.org/connect/)-style middleware, including | ||
15 | +[Express](http://expressjs.com/). | ||
16 | + | ||
17 | +Note that this strategy provides generic OAuth 2.0 support. In many cases, a | ||
18 | +provider-specific strategy can be used instead, which cuts down on unnecessary | ||
19 | +configuration, and accommodates any provider-specific quirks. See the | ||
20 | +[list](https://github.com/jaredhanson/passport/wiki/Strategies) for supported | ||
21 | +providers. | ||
22 | + | ||
23 | +Developers who need to implement authentication against an OAuth 2.0 provider | ||
24 | +that is not already supported are encouraged to sub-class this strategy. If you | ||
25 | +choose to open source the new provider-specific strategy, please add it to the | ||
26 | +list so other people can find it. | ||
27 | + | ||
28 | +## Install | ||
29 | + | ||
30 | + $ npm install passport-oauth2 | ||
31 | + | ||
32 | +## Usage | ||
33 | + | ||
34 | +#### Configure Strategy | ||
35 | + | ||
36 | +The OAuth 2.0 authentication strategy authenticates users using a third-party | ||
37 | +account and OAuth 2.0 tokens. The provider's OAuth 2.0 endpoints, as well as | ||
38 | +the client identifer and secret, are specified as options. The strategy | ||
39 | +requires a `verify` callback, which receives an access token and profile, | ||
40 | +and calls `done` providing a user. | ||
41 | + | ||
42 | + passport.use(new OAuth2Strategy({ | ||
43 | + authorizationURL: 'https://www.example.com/oauth2/authorize', | ||
44 | + tokenURL: 'https://www.example.com/oauth2/token', | ||
45 | + clientID: EXAMPLE_CLIENT_ID, | ||
46 | + clientSecret: EXAMPLE_CLIENT_SECRET, | ||
47 | + callbackURL: "http://localhost:3000/auth/example/callback" | ||
48 | + }, | ||
49 | + function(accessToken, refreshToken, profile, done) { | ||
50 | + User.findOrCreate({ exampleId: profile.id }, function (err, user) { | ||
51 | + return done(err, user); | ||
52 | + }); | ||
53 | + } | ||
54 | + )); | ||
55 | + | ||
56 | +#### Authenticate Requests | ||
57 | + | ||
58 | +Use `passport.authenticate()`, specifying the `'oauth2'` strategy, to | ||
59 | +authenticate requests. | ||
60 | + | ||
61 | +For example, as route middleware in an [Express](http://expressjs.com/) | ||
62 | +application: | ||
63 | + | ||
64 | + app.get('/auth/example', | ||
65 | + passport.authenticate('oauth2')); | ||
66 | + | ||
67 | + app.get('/auth/example/callback', | ||
68 | + passport.authenticate('oauth2', { failureRedirect: '/login' }), | ||
69 | + function(req, res) { | ||
70 | + // Successful authentication, redirect home. | ||
71 | + res.redirect('/'); | ||
72 | + }); | ||
73 | + | ||
74 | +## Related Modules | ||
75 | + | ||
76 | +- [passport-oauth1](https://github.com/jaredhanson/passport-oauth1) — OAuth 1.0 authentication strategy | ||
77 | +- [passport-http-bearer](https://github.com/jaredhanson/passport-http-bearer) — Bearer token authentication strategy for APIs | ||
78 | +- [OAuth2orize](https://github.com/jaredhanson/oauth2orize) — OAuth 2.0 authorization server toolkit | ||
79 | + | ||
80 | +## Tests | ||
81 | + | ||
82 | + $ npm install | ||
83 | + $ npm test | ||
84 | + | ||
85 | +## Credits | ||
86 | + | ||
87 | + - [Jared Hanson](http://github.com/jaredhanson) | ||
88 | + | ||
89 | +## License | ||
90 | + | ||
91 | +[The MIT License](http://opensource.org/licenses/MIT) | ||
92 | + | ||
93 | +Copyright (c) 2011-2014 Jared Hanson <[http://jaredhanson.net/](http://jaredhanson.net/)> |
node_modules/passport-kakao/node_modules/passport-oauth2/lib/errors/authorizationerror.js
0 → 100644
1 | +/** | ||
2 | + * `AuthorizationError` error. | ||
3 | + * | ||
4 | + * AuthorizationError represents an error in response to an authorization | ||
5 | + * request. For details, refer to RFC 6749, section 4.1.2.1. | ||
6 | + * | ||
7 | + * References: | ||
8 | + * - [The OAuth 2.0 Authorization Framework](http://tools.ietf.org/html/rfc6749) | ||
9 | + * | ||
10 | + * @constructor | ||
11 | + * @param {String} [message] | ||
12 | + * @param {String} [code] | ||
13 | + * @param {String} [uri] | ||
14 | + * @param {Number} [status] | ||
15 | + * @api public | ||
16 | + */ | ||
17 | +function AuthorizationError(message, code, uri, status) { | ||
18 | + if (!status) { | ||
19 | + switch (code) { | ||
20 | + case 'access_denied': status = 403; break; | ||
21 | + case 'server_error': status = 502; break; | ||
22 | + case 'temporarily_unavailable': status = 503; break; | ||
23 | + } | ||
24 | + } | ||
25 | + | ||
26 | + Error.call(this); | ||
27 | + Error.captureStackTrace(this, arguments.callee); | ||
28 | + this.name = 'AuthorizationError'; | ||
29 | + this.message = message; | ||
30 | + this.code = code || 'server_error'; | ||
31 | + this.uri = uri; | ||
32 | + this.status = status || 500; | ||
33 | +} | ||
34 | + | ||
35 | +/** | ||
36 | + * Inherit from `Error`. | ||
37 | + */ | ||
38 | +AuthorizationError.prototype.__proto__ = Error.prototype; | ||
39 | + | ||
40 | + | ||
41 | +/** | ||
42 | + * Expose `AuthorizationError`. | ||
43 | + */ | ||
44 | +module.exports = AuthorizationError; |
node_modules/passport-kakao/node_modules/passport-oauth2/lib/errors/internaloautherror.js
0 → 100644
1 | +/** | ||
2 | + * `InternalOAuthError` error. | ||
3 | + * | ||
4 | + * InternalOAuthError wraps errors generated by node-oauth. By wrapping these | ||
5 | + * objects, error messages can be formatted in a manner that aids in debugging | ||
6 | + * OAuth issues. | ||
7 | + * | ||
8 | + * @constructor | ||
9 | + * @param {String} [message] | ||
10 | + * @param {Object|Error} [err] | ||
11 | + * @api public | ||
12 | + */ | ||
13 | +function InternalOAuthError(message, err) { | ||
14 | + Error.call(this); | ||
15 | + Error.captureStackTrace(this, arguments.callee); | ||
16 | + this.name = 'InternalOAuthError'; | ||
17 | + this.message = message; | ||
18 | + this.oauthError = err; | ||
19 | +} | ||
20 | + | ||
21 | +/** | ||
22 | + * Inherit from `Error`. | ||
23 | + */ | ||
24 | +InternalOAuthError.prototype.__proto__ = Error.prototype; | ||
25 | + | ||
26 | +/** | ||
27 | + * Returns a string representing the error. | ||
28 | + * | ||
29 | + * @return {String} | ||
30 | + * @api public | ||
31 | + */ | ||
32 | +InternalOAuthError.prototype.toString = function() { | ||
33 | + var m = this.name; | ||
34 | + if (this.message) { m += ': ' + this.message; } | ||
35 | + if (this.oauthError) { | ||
36 | + if (this.oauthError instanceof Error) { | ||
37 | + m = this.oauthError.toString(); | ||
38 | + } else if (this.oauthError.statusCode && this.oauthError.data) { | ||
39 | + m += ' (status: ' + this.oauthError.statusCode + ' data: ' + this.oauthError.data + ')'; | ||
40 | + } | ||
41 | + } | ||
42 | + return m; | ||
43 | +}; | ||
44 | + | ||
45 | + | ||
46 | +/** | ||
47 | + * Expose `InternalOAuthError`. | ||
48 | + */ | ||
49 | +module.exports = InternalOAuthError; |
1 | +/** | ||
2 | + * `TokenError` error. | ||
3 | + * | ||
4 | + * TokenError represents an error received from a token endpoint. For details, | ||
5 | + * refer to RFC 6749, section 5.2. | ||
6 | + * | ||
7 | + * References: | ||
8 | + * - [The OAuth 2.0 Authorization Framework](http://tools.ietf.org/html/rfc6749) | ||
9 | + * | ||
10 | + * @constructor | ||
11 | + * @param {String} [message] | ||
12 | + * @param {String} [code] | ||
13 | + * @param {String} [uri] | ||
14 | + * @param {Number} [status] | ||
15 | + * @api public | ||
16 | + */ | ||
17 | +function TokenError(message, code, uri, status) { | ||
18 | + Error.call(this); | ||
19 | + Error.captureStackTrace(this, arguments.callee); | ||
20 | + this.name = 'TokenError'; | ||
21 | + this.message = message; | ||
22 | + this.code = code || 'invalid_request'; | ||
23 | + this.uri = uri; | ||
24 | + this.status = status || 500; | ||
25 | +} | ||
26 | + | ||
27 | +/** | ||
28 | + * Inherit from `Error`. | ||
29 | + */ | ||
30 | +TokenError.prototype.__proto__ = Error.prototype; | ||
31 | + | ||
32 | + | ||
33 | +/** | ||
34 | + * Expose `TokenError`. | ||
35 | + */ | ||
36 | +module.exports = TokenError; |
1 | +/** | ||
2 | + * Module dependencies. | ||
3 | + */ | ||
4 | +var Strategy = require('./strategy') | ||
5 | + , AuthorizationError = require('./errors/authorizationerror') | ||
6 | + , TokenError = require('./errors/tokenerror') | ||
7 | + , InternalOAuthError = require('./errors/internaloautherror'); | ||
8 | + | ||
9 | + | ||
10 | +/** | ||
11 | + * Expose `Strategy` directly from package. | ||
12 | + */ | ||
13 | +exports = module.exports = Strategy; | ||
14 | + | ||
15 | +/** | ||
16 | + * Export constructors. | ||
17 | + */ | ||
18 | +exports.Strategy = Strategy; | ||
19 | + | ||
20 | +/** | ||
21 | + * Export errors. | ||
22 | + */ | ||
23 | +exports.AuthorizationError = AuthorizationError; | ||
24 | +exports.TokenError = TokenError; | ||
25 | +exports.InternalOAuthError = InternalOAuthError; |
1 | +/** | ||
2 | + * Module dependencies. | ||
3 | + */ | ||
4 | +var passport = require('passport-strategy') | ||
5 | + , url = require('url') | ||
6 | + , uid = require('uid2') | ||
7 | + , util = require('util') | ||
8 | + , utils = require('./utils') | ||
9 | + , OAuth2 = require('oauth').OAuth2 | ||
10 | + , AuthorizationError = require('./errors/authorizationerror') | ||
11 | + , TokenError = require('./errors/tokenerror') | ||
12 | + , InternalOAuthError = require('./errors/internaloautherror'); | ||
13 | + | ||
14 | + | ||
15 | +/** | ||
16 | + * Creates an instance of `OAuth2Strategy`. | ||
17 | + * | ||
18 | + * The OAuth 2.0 authentication strategy authenticates requests using the OAuth | ||
19 | + * 2.0 framework. | ||
20 | + * | ||
21 | + * OAuth 2.0 provides a facility for delegated authentication, whereby users can | ||
22 | + * authenticate using a third-party service such as Facebook. Delegating in | ||
23 | + * this manner involves a sequence of events, including redirecting the user to | ||
24 | + * the third-party service for authorization. Once authorization has been | ||
25 | + * granted, the user is redirected back to the application and an authorization | ||
26 | + * code can be used to obtain credentials. | ||
27 | + * | ||
28 | + * Applications must supply a `verify` callback, for which the function | ||
29 | + * signature is: | ||
30 | + * | ||
31 | + * function(accessToken, refreshToken, profile, done) { ... } | ||
32 | + * | ||
33 | + * The verify callback is responsible for finding or creating the user, and | ||
34 | + * invoking `done` with the following arguments: | ||
35 | + * | ||
36 | + * done(err, user, info); | ||
37 | + * | ||
38 | + * `user` should be set to `false` to indicate an authentication failure. | ||
39 | + * Additional `info` can optionally be passed as a third argument, typically | ||
40 | + * used to display informational messages. If an exception occured, `err` | ||
41 | + * should be set. | ||
42 | + * | ||
43 | + * Options: | ||
44 | + * | ||
45 | + * - `authorizationURL` URL used to obtain an authorization grant | ||
46 | + * - `tokenURL` URL used to obtain an access token | ||
47 | + * - `clientID` identifies client to service provider | ||
48 | + * - `clientSecret` secret used to establish ownership of the client identifer | ||
49 | + * - `callbackURL` URL to which the service provider will redirect the user after obtaining authorization | ||
50 | + * - `passReqToCallback` when `true`, `req` is the first argument to the verify callback (default: `false`) | ||
51 | + * | ||
52 | + * Examples: | ||
53 | + * | ||
54 | + * passport.use(new OAuth2Strategy({ | ||
55 | + * authorizationURL: 'https://www.example.com/oauth2/authorize', | ||
56 | + * tokenURL: 'https://www.example.com/oauth2/token', | ||
57 | + * clientID: '123-456-789', | ||
58 | + * clientSecret: 'shhh-its-a-secret' | ||
59 | + * callbackURL: 'https://www.example.net/auth/example/callback' | ||
60 | + * }, | ||
61 | + * function(accessToken, refreshToken, profile, done) { | ||
62 | + * User.findOrCreate(..., function (err, user) { | ||
63 | + * done(err, user); | ||
64 | + * }); | ||
65 | + * } | ||
66 | + * )); | ||
67 | + * | ||
68 | + * @constructor | ||
69 | + * @param {Object} options | ||
70 | + * @param {Function} verify | ||
71 | + * @api public | ||
72 | + */ | ||
73 | +function OAuth2Strategy(options, verify) { | ||
74 | + if (typeof options == 'function') { | ||
75 | + verify = options; | ||
76 | + options = undefined; | ||
77 | + } | ||
78 | + options = options || {}; | ||
79 | + | ||
80 | + if (!verify) { throw new TypeError('OAuth2Strategy requires a verify callback'); } | ||
81 | + if (!options.authorizationURL) { throw new TypeError('OAuth2Strategy requires a authorizationURL option'); } | ||
82 | + if (!options.tokenURL) { throw new TypeError('OAuth2Strategy requires a tokenURL option'); } | ||
83 | + if (!options.clientID) { throw new TypeError('OAuth2Strategy requires a clientID option'); } | ||
84 | + if (!options.clientSecret) { throw new TypeError('OAuth2Strategy requires a clientSecret option'); } | ||
85 | + | ||
86 | + passport.Strategy.call(this); | ||
87 | + this.name = 'oauth2'; | ||
88 | + this._verify = verify; | ||
89 | + | ||
90 | + // NOTE: The _oauth2 property is considered "protected". Subclasses are | ||
91 | + // allowed to use it when making protected resource requests to retrieve | ||
92 | + // the user profile. | ||
93 | + this._oauth2 = new OAuth2(options.clientID, options.clientSecret, | ||
94 | + '', options.authorizationURL, options.tokenURL, options.customHeaders); | ||
95 | + | ||
96 | + this._callbackURL = options.callbackURL; | ||
97 | + this._scope = options.scope; | ||
98 | + this._scopeSeparator = options.scopeSeparator || ' '; | ||
99 | + this._state = options.state; | ||
100 | + this._key = options.sessionKey || ('oauth2:' + url.parse(options.authorizationURL).hostname); | ||
101 | + this._trustProxy = options.proxy; | ||
102 | + this._passReqToCallback = options.passReqToCallback; | ||
103 | + this._skipUserProfile = (options.skipUserProfile === undefined) ? false : options.skipUserProfile; | ||
104 | +} | ||
105 | + | ||
106 | +/** | ||
107 | + * Inherit from `passport.Strategy`. | ||
108 | + */ | ||
109 | +util.inherits(OAuth2Strategy, passport.Strategy); | ||
110 | + | ||
111 | + | ||
112 | +/** | ||
113 | + * Authenticate request by delegating to a service provider using OAuth 2.0. | ||
114 | + * | ||
115 | + * @param {Object} req | ||
116 | + * @api protected | ||
117 | + */ | ||
118 | +OAuth2Strategy.prototype.authenticate = function(req, options) { | ||
119 | + options = options || {}; | ||
120 | + var self = this; | ||
121 | + | ||
122 | + if (req.query && req.query.error) { | ||
123 | + if (req.query.error == 'access_denied') { | ||
124 | + return this.fail({ message: req.query.error_description }); | ||
125 | + } else { | ||
126 | + return this.error(new AuthorizationError(req.query.error_description, req.query.error, req.query.error_uri)); | ||
127 | + } | ||
128 | + } | ||
129 | + | ||
130 | + var callbackURL = options.callbackURL || this._callbackURL; | ||
131 | + if (callbackURL) { | ||
132 | + var parsed = url.parse(callbackURL); | ||
133 | + if (!parsed.protocol) { | ||
134 | + // The callback URL is relative, resolve a fully qualified URL from the | ||
135 | + // URL of the originating request. | ||
136 | + callbackURL = url.resolve(utils.originalURL(req, { proxy: this._trustProxy }), callbackURL); | ||
137 | + } | ||
138 | + } | ||
139 | + | ||
140 | + if (req.query && req.query.code) { | ||
141 | + var code = req.query.code; | ||
142 | + | ||
143 | + if (this._state) { | ||
144 | + if (!req.session) { return this.error(new Error('OAuth2Strategy requires session support when using state. Did you forget app.use(express.session(...))?')); } | ||
145 | + | ||
146 | + var key = this._key; | ||
147 | + if (!req.session[key]) { | ||
148 | + return this.fail({ message: 'Unable to verify authorization request state.' }, 403); | ||
149 | + } | ||
150 | + var state = req.session[key].state; | ||
151 | + if (!state) { | ||
152 | + return this.fail({ message: 'Unable to verify authorization request state.' }, 403); | ||
153 | + } | ||
154 | + | ||
155 | + delete req.session[key].state; | ||
156 | + if (Object.keys(req.session[key]).length === 0) { | ||
157 | + delete req.session[key]; | ||
158 | + } | ||
159 | + | ||
160 | + if (state !== req.query.state) { | ||
161 | + return this.fail({ message: 'Invalid authorization request state.' }, 403); | ||
162 | + } | ||
163 | + } | ||
164 | + | ||
165 | + var params = this.tokenParams(options); | ||
166 | + params.grant_type = 'authorization_code'; | ||
167 | + params.redirect_uri = callbackURL; | ||
168 | + | ||
169 | + this._oauth2.getOAuthAccessToken(code, params, | ||
170 | + function(err, accessToken, refreshToken, params) { | ||
171 | + if (err) { return self.error(self._createOAuthError('Failed to obtain access token', err)); } | ||
172 | + | ||
173 | + self._loadUserProfile(accessToken, function(err, profile) { | ||
174 | + if (err) { return self.error(err); } | ||
175 | + | ||
176 | + function verified(err, user, info) { | ||
177 | + if (err) { return self.error(err); } | ||
178 | + if (!user) { return self.fail(info); } | ||
179 | + self.success(user, info); | ||
180 | + } | ||
181 | + | ||
182 | + try { | ||
183 | + if (self._passReqToCallback) { | ||
184 | + var arity = self._verify.length; | ||
185 | + if (arity == 6) { | ||
186 | + self._verify(req, accessToken, refreshToken, params, profile, verified); | ||
187 | + } else { // arity == 5 | ||
188 | + self._verify(req, accessToken, refreshToken, profile, verified); | ||
189 | + } | ||
190 | + } else { | ||
191 | + var arity = self._verify.length; | ||
192 | + if (arity == 5) { | ||
193 | + self._verify(accessToken, refreshToken, params, profile, verified); | ||
194 | + } else { // arity == 4 | ||
195 | + self._verify(accessToken, refreshToken, profile, verified); | ||
196 | + } | ||
197 | + } | ||
198 | + } catch (ex) { | ||
199 | + return self.error(ex); | ||
200 | + } | ||
201 | + }); | ||
202 | + } | ||
203 | + ); | ||
204 | + } else { | ||
205 | + var params = this.authorizationParams(options); | ||
206 | + params.response_type = 'code'; | ||
207 | + params.redirect_uri = callbackURL; | ||
208 | + var scope = options.scope || this._scope; | ||
209 | + if (scope) { | ||
210 | + if (Array.isArray(scope)) { scope = scope.join(this._scopeSeparator); } | ||
211 | + params.scope = scope; | ||
212 | + } | ||
213 | + var state = options.state; | ||
214 | + if (state) { | ||
215 | + params.state = state; | ||
216 | + } else if (this._state) { | ||
217 | + if (!req.session) { return this.error(new Error('OAuth2Strategy requires session support when using state. Did you forget app.use(express.session(...))?')); } | ||
218 | + | ||
219 | + var key = this._key; | ||
220 | + state = uid(24); | ||
221 | + if (!req.session[key]) { req.session[key] = {}; } | ||
222 | + req.session[key].state = state; | ||
223 | + params.state = state; | ||
224 | + } | ||
225 | + | ||
226 | + var location = this._oauth2.getAuthorizeUrl(params); | ||
227 | + this.redirect(location); | ||
228 | + } | ||
229 | +}; | ||
230 | + | ||
231 | +/** | ||
232 | + * Retrieve user profile from service provider. | ||
233 | + * | ||
234 | + * OAuth 2.0-based authentication strategies can overrride this function in | ||
235 | + * order to load the user's profile from the service provider. This assists | ||
236 | + * applications (and users of those applications) in the initial registration | ||
237 | + * process by automatically submitting required information. | ||
238 | + * | ||
239 | + * @param {String} accessToken | ||
240 | + * @param {Function} done | ||
241 | + * @api protected | ||
242 | + */ | ||
243 | +OAuth2Strategy.prototype.userProfile = function(accessToken, done) { | ||
244 | + return done(null, {}); | ||
245 | +}; | ||
246 | + | ||
247 | +/** | ||
248 | + * Return extra parameters to be included in the authorization request. | ||
249 | + * | ||
250 | + * Some OAuth 2.0 providers allow additional, non-standard parameters to be | ||
251 | + * included when requesting authorization. Since these parameters are not | ||
252 | + * standardized by the OAuth 2.0 specification, OAuth 2.0-based authentication | ||
253 | + * strategies can overrride this function in order to populate these parameters | ||
254 | + * as required by the provider. | ||
255 | + * | ||
256 | + * @param {Object} options | ||
257 | + * @return {Object} | ||
258 | + * @api protected | ||
259 | + */ | ||
260 | +OAuth2Strategy.prototype.authorizationParams = function(options) { | ||
261 | + return {}; | ||
262 | +}; | ||
263 | + | ||
264 | +/** | ||
265 | + * Return extra parameters to be included in the token request. | ||
266 | + * | ||
267 | + * Some OAuth 2.0 providers allow additional, non-standard parameters to be | ||
268 | + * included when requesting an access token. Since these parameters are not | ||
269 | + * standardized by the OAuth 2.0 specification, OAuth 2.0-based authentication | ||
270 | + * strategies can overrride this function in order to populate these parameters | ||
271 | + * as required by the provider. | ||
272 | + * | ||
273 | + * @return {Object} | ||
274 | + * @api protected | ||
275 | + */ | ||
276 | +OAuth2Strategy.prototype.tokenParams = function(options) { | ||
277 | + return {}; | ||
278 | +}; | ||
279 | + | ||
280 | +/** | ||
281 | + * Parse error response from OAuth 2.0 endpoint. | ||
282 | + * | ||
283 | + * OAuth 2.0-based authentication strategies can overrride this function in | ||
284 | + * order to parse error responses received from the token endpoint, allowing the | ||
285 | + * most informative message to be displayed. | ||
286 | + * | ||
287 | + * If this function is not overridden, the body will be parsed in accordance | ||
288 | + * with RFC 6749, section 5.2. | ||
289 | + * | ||
290 | + * @param {String} body | ||
291 | + * @param {Number} status | ||
292 | + * @return {Error} | ||
293 | + * @api protected | ||
294 | + */ | ||
295 | +OAuth2Strategy.prototype.parseErrorResponse = function(body, status) { | ||
296 | + var json = JSON.parse(body); | ||
297 | + if (json.error) { | ||
298 | + return new TokenError(json.error_description, json.error, json.error_uri); | ||
299 | + } | ||
300 | + return null; | ||
301 | +}; | ||
302 | + | ||
303 | +/** | ||
304 | + * Load user profile, contingent upon options. | ||
305 | + * | ||
306 | + * @param {String} accessToken | ||
307 | + * @param {Function} done | ||
308 | + * @api private | ||
309 | + */ | ||
310 | +OAuth2Strategy.prototype._loadUserProfile = function(accessToken, done) { | ||
311 | + var self = this; | ||
312 | + | ||
313 | + function loadIt() { | ||
314 | + return self.userProfile(accessToken, done); | ||
315 | + } | ||
316 | + function skipIt() { | ||
317 | + return done(null); | ||
318 | + } | ||
319 | + | ||
320 | + if (typeof this._skipUserProfile == 'function' && this._skipUserProfile.length > 1) { | ||
321 | + // async | ||
322 | + this._skipUserProfile(accessToken, function(err, skip) { | ||
323 | + if (err) { return done(err); } | ||
324 | + if (!skip) { return loadIt(); } | ||
325 | + return skipIt(); | ||
326 | + }); | ||
327 | + } else { | ||
328 | + var skip = (typeof this._skipUserProfile == 'function') ? this._skipUserProfile() : this._skipUserProfile; | ||
329 | + if (!skip) { return loadIt(); } | ||
330 | + return skipIt(); | ||
331 | + } | ||
332 | +}; | ||
333 | + | ||
334 | +/** | ||
335 | + * Create an OAuth error. | ||
336 | + * | ||
337 | + * @param {String} message | ||
338 | + * @param {Object|Error} err | ||
339 | + * @api private | ||
340 | + */ | ||
341 | +OAuth2Strategy.prototype._createOAuthError = function(message, err) { | ||
342 | + var e; | ||
343 | + if (err.statusCode && err.data) { | ||
344 | + try { | ||
345 | + e = this.parseErrorResponse(err.data, err.statusCode); | ||
346 | + } catch (_) {} | ||
347 | + } | ||
348 | + if (!e) { e = new InternalOAuthError(message, err); } | ||
349 | + return e; | ||
350 | +}; | ||
351 | + | ||
352 | + | ||
353 | +/** | ||
354 | + * Expose `OAuth2Strategy`. | ||
355 | + */ | ||
356 | +module.exports = OAuth2Strategy; |
1 | +/** | ||
2 | + * Reconstructs the original URL of the request. | ||
3 | + * | ||
4 | + * This function builds a URL that corresponds the original URL requested by the | ||
5 | + * client, including the protocol (http or https) and host. | ||
6 | + * | ||
7 | + * If the request passed through any proxies that terminate SSL, the | ||
8 | + * `X-Forwarded-Proto` header is used to detect if the request was encrypted to | ||
9 | + * the proxy, assuming that the proxy has been flagged as trusted. | ||
10 | + * | ||
11 | + * @param {http.IncomingMessage} req | ||
12 | + * @param {Object} [options] | ||
13 | + * @return {String} | ||
14 | + * @api private | ||
15 | + */ | ||
16 | +exports.originalURL = function(req, options) { | ||
17 | + options = options || {}; | ||
18 | + var app = req.app; | ||
19 | + if (app && app.get && app.get('trust proxy')) { | ||
20 | + options.proxy = true; | ||
21 | + } | ||
22 | + var trustProxy = options.proxy; | ||
23 | + | ||
24 | + var proto = (req.headers['x-forwarded-proto'] || '').toLowerCase() | ||
25 | + , tls = req.connection.encrypted || (trustProxy && 'https' == proto.split(/\s*,\s*/)[0]) | ||
26 | + , host = (trustProxy && req.headers['x-forwarded-host']) || req.headers.host | ||
27 | + , protocol = tls ? 'https' : 'http' | ||
28 | + , path = req.url || ''; | ||
29 | + return protocol + '://' + host + path; | ||
30 | +}; |
1 | +{ | ||
2 | + "_from": "passport-oauth2@~1.1.2", | ||
3 | + "_id": "passport-oauth2@1.1.2", | ||
4 | + "_inBundle": false, | ||
5 | + "_integrity": "sha1-vXFjsbYJA3GGjcTvb58uHkzEuUg=", | ||
6 | + "_location": "/passport-kakao/passport-oauth2", | ||
7 | + "_phantomChildren": {}, | ||
8 | + "_requested": { | ||
9 | + "type": "range", | ||
10 | + "registry": true, | ||
11 | + "raw": "passport-oauth2@~1.1.2", | ||
12 | + "name": "passport-oauth2", | ||
13 | + "escapedName": "passport-oauth2", | ||
14 | + "rawSpec": "~1.1.2", | ||
15 | + "saveSpec": null, | ||
16 | + "fetchSpec": "~1.1.2" | ||
17 | + }, | ||
18 | + "_requiredBy": [ | ||
19 | + "/passport-kakao" | ||
20 | + ], | ||
21 | + "_resolved": "https://registry.npmjs.org/passport-oauth2/-/passport-oauth2-1.1.2.tgz", | ||
22 | + "_shasum": "bd7163b1b6090371868dc4ef6f9f2e1e4cc4b948", | ||
23 | + "_spec": "passport-oauth2@~1.1.2", | ||
24 | + "_where": "C:\\Users\\LG\\Desktop\\4-1\\Reminder-Talk\\node_modules\\passport-kakao", | ||
25 | + "author": { | ||
26 | + "name": "Jared Hanson", | ||
27 | + "email": "jaredhanson@gmail.com", | ||
28 | + "url": "http://www.jaredhanson.net/" | ||
29 | + }, | ||
30 | + "bugs": { | ||
31 | + "url": "http://github.com/jaredhanson/passport-oauth2/issues" | ||
32 | + }, | ||
33 | + "bundleDependencies": false, | ||
34 | + "dependencies": { | ||
35 | + "oauth": "0.9.x", | ||
36 | + "passport-strategy": "1.x.x", | ||
37 | + "uid2": "0.0.x" | ||
38 | + }, | ||
39 | + "deprecated": false, | ||
40 | + "description": "OAuth 2.0 authentication strategy for Passport.", | ||
41 | + "devDependencies": { | ||
42 | + "chai": "1.x.x", | ||
43 | + "chai-passport-strategy": "0.2.x", | ||
44 | + "mocha": "1.x.x" | ||
45 | + }, | ||
46 | + "engines": { | ||
47 | + "node": ">= 0.4.0" | ||
48 | + }, | ||
49 | + "homepage": "https://github.com/jaredhanson/passport-oauth2#readme", | ||
50 | + "keywords": [ | ||
51 | + "passport", | ||
52 | + "auth", | ||
53 | + "authn", | ||
54 | + "authentication", | ||
55 | + "authz", | ||
56 | + "authorization", | ||
57 | + "oauth", | ||
58 | + "oauth2" | ||
59 | + ], | ||
60 | + "licenses": [ | ||
61 | + { | ||
62 | + "type": "MIT", | ||
63 | + "url": "http://www.opensource.org/licenses/MIT" | ||
64 | + } | ||
65 | + ], | ||
66 | + "main": "./lib", | ||
67 | + "name": "passport-oauth2", | ||
68 | + "repository": { | ||
69 | + "type": "git", | ||
70 | + "url": "git://github.com/jaredhanson/passport-oauth2.git" | ||
71 | + }, | ||
72 | + "scripts": { | ||
73 | + "test": "mocha --reporter spec --require test/bootstrap/node test/*.test.js test/**/*.test.js" | ||
74 | + }, | ||
75 | + "version": "1.1.2" | ||
76 | +} |
1 | +Copyright (c) 2010 Charlie Robbins. | ||
2 | + | ||
3 | +Permission is hereby granted, free of charge, to any person obtaining a copy | ||
4 | +of this software and associated documentation files (the "Software"), to deal | ||
5 | +in the Software without restriction, including without limitation the rights | ||
6 | +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
7 | +copies of the Software, and to permit persons to whom the Software is | ||
8 | +furnished to do so, subject to the following conditions: | ||
9 | + | ||
10 | +The above copyright notice and this permission notice shall be included in | ||
11 | +all copies or substantial portions of the Software. | ||
12 | + | ||
13 | +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
14 | +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
15 | +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
16 | +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
17 | +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
18 | +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
19 | +THE SOFTWARE. | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
1 | +# node-pkginfo | ||
2 | + | ||
3 | +An easy way to expose properties on a module from a package.json | ||
4 | + | ||
5 | +## Installation | ||
6 | + | ||
7 | +### Installing npm (node package manager) | ||
8 | +``` | ||
9 | + curl http://npmjs.org/install.sh | sh | ||
10 | +``` | ||
11 | + | ||
12 | +### Installing pkginfo | ||
13 | +``` | ||
14 | + [sudo] npm install pkginfo | ||
15 | +``` | ||
16 | + | ||
17 | +## Motivation | ||
18 | +How often when writing node.js modules have you written the following line(s) of code? | ||
19 | + | ||
20 | +* Hard code your version string into your code | ||
21 | + | ||
22 | +``` js | ||
23 | + exports.version = '0.1.0'; | ||
24 | +``` | ||
25 | + | ||
26 | +* Programmatically expose the version from the package.json | ||
27 | + | ||
28 | +``` js | ||
29 | + exports.version = require('/path/to/package.json').version; | ||
30 | +``` | ||
31 | + | ||
32 | +In other words, how often have you wanted to expose basic information from your package.json onto your module programmatically? **WELL NOW YOU CAN!** | ||
33 | + | ||
34 | +## Usage | ||
35 | + | ||
36 | +Using `pkginfo` is idiot-proof, just require and invoke it. | ||
37 | + | ||
38 | +``` js | ||
39 | + var pkginfo = require('pkginfo')(module); | ||
40 | + | ||
41 | + console.dir(module.exports); | ||
42 | +``` | ||
43 | + | ||
44 | +By invoking the `pkginfo` module all of the properties in your `package.json` file will be automatically exposed on the callee module (i.e. the parent module of `pkginfo`). | ||
45 | + | ||
46 | +Here's a sample of the output: | ||
47 | + | ||
48 | +``` | ||
49 | + { name: 'simple-app', | ||
50 | + description: 'A test fixture for pkginfo', | ||
51 | + version: '0.1.0', | ||
52 | + author: 'Charlie Robbins <charlie.robbins@gmail.com>', | ||
53 | + keywords: [ 'test', 'fixture' ], | ||
54 | + main: './index.js', | ||
55 | + scripts: { test: 'vows test/*-test.js --spec' }, | ||
56 | + engines: { node: '>= 0.4.0' } } | ||
57 | +``` | ||
58 | + | ||
59 | +### Expose specific properties | ||
60 | +If you don't want to expose **all** properties on from your `package.json` on your module then simple pass those properties to the `pkginfo` function: | ||
61 | + | ||
62 | +``` js | ||
63 | + var pkginfo = require('pkginfo')(module, 'version', 'author'); | ||
64 | + | ||
65 | + console.dir(module.exports); | ||
66 | +``` | ||
67 | + | ||
68 | +``` | ||
69 | + { version: '0.1.0', | ||
70 | + author: 'Charlie Robbins <charlie.robbins@gmail.com>' } | ||
71 | +``` | ||
72 | + | ||
73 | +If you're looking for further usage see the [examples][0] included in this repository. | ||
74 | + | ||
75 | +## Run Tests | ||
76 | +Tests are written in [vows][1] and give complete coverage of all APIs. | ||
77 | + | ||
78 | +``` | ||
79 | + vows test/*-test.js --spec | ||
80 | +``` | ||
81 | + | ||
82 | +[0]: https://github.com/indexzero/node-pkginfo/tree/master/examples | ||
83 | +[1]: http://vowsjs.org | ||
84 | + | ||
85 | +#### Author: [Charlie Robbins](http://nodejitsu.com) | ||
86 | +#### License: MIT |
1 | +/*--------------------- Layout and Typography ----------------------------*/ | ||
2 | +body { | ||
3 | + font-family: 'Palatino Linotype', 'Book Antiqua', Palatino, FreeSerif, serif; | ||
4 | + font-size: 15px; | ||
5 | + line-height: 22px; | ||
6 | + color: #252519; | ||
7 | + margin: 0; padding: 0; | ||
8 | +} | ||
9 | +a { | ||
10 | + color: #261a3b; | ||
11 | +} | ||
12 | + a:visited { | ||
13 | + color: #261a3b; | ||
14 | + } | ||
15 | +p { | ||
16 | + margin: 0 0 15px 0; | ||
17 | +} | ||
18 | +h4, h5, h6 { | ||
19 | + color: #333; | ||
20 | + margin: 6px 0 6px 0; | ||
21 | + font-size: 13px; | ||
22 | +} | ||
23 | + h2, h3 { | ||
24 | + margin-bottom: 0; | ||
25 | + color: #000; | ||
26 | + } | ||
27 | + h1 { | ||
28 | + margin-top: 40px; | ||
29 | + margin-bottom: 15px; | ||
30 | + color: #000; | ||
31 | + } | ||
32 | +#container { | ||
33 | + position: relative; | ||
34 | +} | ||
35 | +#background { | ||
36 | + position: fixed; | ||
37 | + top: 0; left: 525px; right: 0; bottom: 0; | ||
38 | + background: #f5f5ff; | ||
39 | + border-left: 1px solid #e5e5ee; | ||
40 | + z-index: -1; | ||
41 | +} | ||
42 | +#jump_to, #jump_page { | ||
43 | + background: white; | ||
44 | + -webkit-box-shadow: 0 0 25px #777; -moz-box-shadow: 0 0 25px #777; | ||
45 | + -webkit-border-bottom-left-radius: 5px; -moz-border-radius-bottomleft: 5px; | ||
46 | + font: 10px Arial; | ||
47 | + text-transform: uppercase; | ||
48 | + cursor: pointer; | ||
49 | + text-align: right; | ||
50 | +} | ||
51 | +#jump_to, #jump_wrapper { | ||
52 | + position: fixed; | ||
53 | + right: 0; top: 0; | ||
54 | + padding: 5px 10px; | ||
55 | +} | ||
56 | + #jump_wrapper { | ||
57 | + padding: 0; | ||
58 | + display: none; | ||
59 | + } | ||
60 | + #jump_to:hover #jump_wrapper { | ||
61 | + display: block; | ||
62 | + } | ||
63 | + #jump_page { | ||
64 | + padding: 5px 0 3px; | ||
65 | + margin: 0 0 25px 25px; | ||
66 | + } | ||
67 | + #jump_page .source { | ||
68 | + display: block; | ||
69 | + padding: 5px 10px; | ||
70 | + text-decoration: none; | ||
71 | + border-top: 1px solid #eee; | ||
72 | + } | ||
73 | + #jump_page .source:hover { | ||
74 | + background: #f5f5ff; | ||
75 | + } | ||
76 | + #jump_page .source:first-child { | ||
77 | + } | ||
78 | +table td { | ||
79 | + border: 0; | ||
80 | + outline: 0; | ||
81 | +} | ||
82 | + td.docs, th.docs { | ||
83 | + max-width: 450px; | ||
84 | + min-width: 450px; | ||
85 | + min-height: 5px; | ||
86 | + padding: 10px 25px 1px 50px; | ||
87 | + overflow-x: hidden; | ||
88 | + vertical-align: top; | ||
89 | + text-align: left; | ||
90 | + } | ||
91 | + .docs pre { | ||
92 | + margin: 15px 0 15px; | ||
93 | + padding-left: 15px; | ||
94 | + } | ||
95 | + .docs p tt, .docs p code { | ||
96 | + background: #f8f8ff; | ||
97 | + border: 1px solid #dedede; | ||
98 | + font-size: 12px; | ||
99 | + padding: 0 0.2em; | ||
100 | + } | ||
101 | + .pilwrap { | ||
102 | + position: relative; | ||
103 | + } | ||
104 | + .pilcrow { | ||
105 | + font: 12px Arial; | ||
106 | + text-decoration: none; | ||
107 | + color: #454545; | ||
108 | + position: absolute; | ||
109 | + top: 3px; left: -20px; | ||
110 | + padding: 1px 2px; | ||
111 | + opacity: 0; | ||
112 | + -webkit-transition: opacity 0.2s linear; | ||
113 | + } | ||
114 | + td.docs:hover .pilcrow { | ||
115 | + opacity: 1; | ||
116 | + } | ||
117 | + td.code, th.code { | ||
118 | + padding: 14px 15px 16px 25px; | ||
119 | + width: 100%; | ||
120 | + vertical-align: top; | ||
121 | + background: #f5f5ff; | ||
122 | + border-left: 1px solid #e5e5ee; | ||
123 | + } | ||
124 | + pre, tt, code { | ||
125 | + font-size: 12px; line-height: 18px; | ||
126 | + font-family: Menlo, Monaco, Consolas, "Lucida Console", monospace; | ||
127 | + margin: 0; padding: 0; | ||
128 | + } | ||
129 | + | ||
130 | + | ||
131 | +/*---------------------- Syntax Highlighting -----------------------------*/ | ||
132 | +td.linenos { background-color: #f0f0f0; padding-right: 10px; } | ||
133 | +span.lineno { background-color: #f0f0f0; padding: 0 5px 0 5px; } | ||
134 | +body .hll { background-color: #ffffcc } | ||
135 | +body .c { color: #408080; font-style: italic } /* Comment */ | ||
136 | +body .err { border: 1px solid #FF0000 } /* Error */ | ||
137 | +body .k { color: #954121 } /* Keyword */ | ||
138 | +body .o { color: #666666 } /* Operator */ | ||
139 | +body .cm { color: #408080; font-style: italic } /* Comment.Multiline */ | ||
140 | +body .cp { color: #BC7A00 } /* Comment.Preproc */ | ||
141 | +body .c1 { color: #408080; font-style: italic } /* Comment.Single */ | ||
142 | +body .cs { color: #408080; font-style: italic } /* Comment.Special */ | ||
143 | +body .gd { color: #A00000 } /* Generic.Deleted */ | ||
144 | +body .ge { font-style: italic } /* Generic.Emph */ | ||
145 | +body .gr { color: #FF0000 } /* Generic.Error */ | ||
146 | +body .gh { color: #000080; font-weight: bold } /* Generic.Heading */ | ||
147 | +body .gi { color: #00A000 } /* Generic.Inserted */ | ||
148 | +body .go { color: #808080 } /* Generic.Output */ | ||
149 | +body .gp { color: #000080; font-weight: bold } /* Generic.Prompt */ | ||
150 | +body .gs { font-weight: bold } /* Generic.Strong */ | ||
151 | +body .gu { color: #800080; font-weight: bold } /* Generic.Subheading */ | ||
152 | +body .gt { color: #0040D0 } /* Generic.Traceback */ | ||
153 | +body .kc { color: #954121 } /* Keyword.Constant */ | ||
154 | +body .kd { color: #954121; font-weight: bold } /* Keyword.Declaration */ | ||
155 | +body .kn { color: #954121; font-weight: bold } /* Keyword.Namespace */ | ||
156 | +body .kp { color: #954121 } /* Keyword.Pseudo */ | ||
157 | +body .kr { color: #954121; font-weight: bold } /* Keyword.Reserved */ | ||
158 | +body .kt { color: #B00040 } /* Keyword.Type */ | ||
159 | +body .m { color: #666666 } /* Literal.Number */ | ||
160 | +body .s { color: #219161 } /* Literal.String */ | ||
161 | +body .na { color: #7D9029 } /* Name.Attribute */ | ||
162 | +body .nb { color: #954121 } /* Name.Builtin */ | ||
163 | +body .nc { color: #0000FF; font-weight: bold } /* Name.Class */ | ||
164 | +body .no { color: #880000 } /* Name.Constant */ | ||
165 | +body .nd { color: #AA22FF } /* Name.Decorator */ | ||
166 | +body .ni { color: #999999; font-weight: bold } /* Name.Entity */ | ||
167 | +body .ne { color: #D2413A; font-weight: bold } /* Name.Exception */ | ||
168 | +body .nf { color: #0000FF } /* Name.Function */ | ||
169 | +body .nl { color: #A0A000 } /* Name.Label */ | ||
170 | +body .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */ | ||
171 | +body .nt { color: #954121; font-weight: bold } /* Name.Tag */ | ||
172 | +body .nv { color: #19469D } /* Name.Variable */ | ||
173 | +body .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */ | ||
174 | +body .w { color: #bbbbbb } /* Text.Whitespace */ | ||
175 | +body .mf { color: #666666 } /* Literal.Number.Float */ | ||
176 | +body .mh { color: #666666 } /* Literal.Number.Hex */ | ||
177 | +body .mi { color: #666666 } /* Literal.Number.Integer */ | ||
178 | +body .mo { color: #666666 } /* Literal.Number.Oct */ | ||
179 | +body .sb { color: #219161 } /* Literal.String.Backtick */ | ||
180 | +body .sc { color: #219161 } /* Literal.String.Char */ | ||
181 | +body .sd { color: #219161; font-style: italic } /* Literal.String.Doc */ | ||
182 | +body .s2 { color: #219161 } /* Literal.String.Double */ | ||
183 | +body .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */ | ||
184 | +body .sh { color: #219161 } /* Literal.String.Heredoc */ | ||
185 | +body .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */ | ||
186 | +body .sx { color: #954121 } /* Literal.String.Other */ | ||
187 | +body .sr { color: #BB6688 } /* Literal.String.Regex */ | ||
188 | +body .s1 { color: #219161 } /* Literal.String.Single */ | ||
189 | +body .ss { color: #19469D } /* Literal.String.Symbol */ | ||
190 | +body .bp { color: #954121 } /* Name.Builtin.Pseudo */ | ||
191 | +body .vc { color: #19469D } /* Name.Variable.Class */ | ||
192 | +body .vg { color: #19469D } /* Name.Variable.Global */ | ||
193 | +body .vi { color: #19469D } /* Name.Variable.Instance */ | ||
194 | +body .il { color: #666666 } /* Literal.Number.Integer.Long */ | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
1 | +<!DOCTYPE html> <html> <head> <title>pkginfo.js</title> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <link rel="stylesheet" media="all" href="docco.css" /> </head> <body> <div id="container"> <div id="background"></div> <table cellpadding="0" cellspacing="0"> <thead> <tr> <th class="docs"> <h1> pkginfo.js </h1> </th> <th class="code"> </th> </tr> </thead> <tbody> <tr id="section-1"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-1">¶</a> </div> </td> <td class="code"> <div class="highlight"><pre><span class="cm">/*</span> | ||
2 | +<span class="cm"> * pkginfo.js: Top-level include for the pkginfo module</span> | ||
3 | +<span class="cm"> *</span> | ||
4 | +<span class="cm"> * (C) 2011, Charlie Robbins</span> | ||
5 | +<span class="cm"> *</span> | ||
6 | +<span class="cm"> */</span> | ||
7 | + | ||
8 | +<span class="kd">var</span> <span class="nx">fs</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">'fs'</span><span class="p">),</span> | ||
9 | + <span class="nx">path</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">'path'</span><span class="p">);</span></pre></div> </td> </tr> <tr id="section-2"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-2">¶</a> </div> <h3>function pkginfo ([options, 'property', 'property' ..])</h3> | ||
10 | + | ||
11 | +<h4>@pmodule {Module} Parent module to read from.</h4> | ||
12 | + | ||
13 | +<h4>@options {Object|Array|string} <strong>Optional</strong> Options used when exposing properties.</h4> | ||
14 | + | ||
15 | +<h4>@arguments {string...} <strong>Optional</strong> Specified properties to expose.</h4> | ||
16 | + | ||
17 | +<p>Exposes properties from the package.json file for the parent module on | ||
18 | +it's exports. Valid usage:</p> | ||
19 | + | ||
20 | +<p><code>require('pkginfo')()</code></p> | ||
21 | + | ||
22 | +<p><code>require('pkginfo')('version', 'author');</code></p> | ||
23 | + | ||
24 | +<p><code>require('pkginfo')(['version', 'author']);</code></p> | ||
25 | + | ||
26 | +<p><code>require('pkginfo')({ include: ['version', 'author'] });</code></p> </td> <td class="code"> <div class="highlight"><pre><span class="kd">var</span> <span class="nx">pkginfo</span> <span class="o">=</span> <span class="nx">module</span><span class="p">.</span><span class="nx">exports</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">pmodule</span><span class="p">,</span> <span class="nx">options</span><span class="p">)</span> <span class="p">{</span> | ||
27 | + <span class="kd">var</span> <span class="nx">args</span> <span class="o">=</span> <span class="p">[].</span><span class="nx">slice</span><span class="p">.</span><span class="nx">call</span><span class="p">(</span><span class="nx">arguments</span><span class="p">,</span> <span class="mi">2</span><span class="p">).</span><span class="nx">filter</span><span class="p">(</span><span class="kd">function</span> <span class="p">(</span><span class="nx">arg</span><span class="p">)</span> <span class="p">{</span> | ||
28 | + <span class="k">return</span> <span class="k">typeof</span> <span class="nx">arg</span> <span class="o">===</span> <span class="s1">'string'</span><span class="p">;</span> | ||
29 | + <span class="p">});</span> | ||
30 | + </pre></div> </td> </tr> <tr id="section-3"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-3">¶</a> </div> <p><strong>Parse variable arguments</strong></p> </td> <td class="code"> <div class="highlight"><pre> <span class="k">if</span> <span class="p">(</span><span class="nb">Array</span><span class="p">.</span><span class="nx">isArray</span><span class="p">(</span><span class="nx">options</span><span class="p">))</span> <span class="p">{</span></pre></div> </td> </tr> <tr id="section-4"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-4">¶</a> </div> <p>If the options passed in is an Array assume that | ||
31 | +it is the Array of properties to expose from the | ||
32 | +on the package.json file on the parent module.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">options</span> <span class="o">=</span> <span class="p">{</span> <span class="nx">include</span><span class="o">:</span> <span class="nx">options</span> <span class="p">};</span> | ||
33 | + <span class="p">}</span> | ||
34 | + <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="k">typeof</span> <span class="nx">options</span> <span class="o">===</span> <span class="s1">'string'</span><span class="p">)</span> <span class="p">{</span></pre></div> </td> </tr> <tr id="section-5"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-5">¶</a> </div> <p>Otherwise if the first argument is a string, then | ||
35 | +assume that it is the first property to expose from | ||
36 | +the package.json file on the parent module.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">options</span> <span class="o">=</span> <span class="p">{</span> <span class="nx">include</span><span class="o">:</span> <span class="p">[</span><span class="nx">options</span><span class="p">]</span> <span class="p">};</span> | ||
37 | + <span class="p">}</span> | ||
38 | + </pre></div> </td> </tr> <tr id="section-6"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-6">¶</a> </div> <p><strong>Setup default options</strong></p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">options</span> <span class="o">=</span> <span class="nx">options</span> <span class="o">||</span> <span class="p">{</span> <span class="nx">include</span><span class="o">:</span> <span class="p">[]</span> <span class="p">};</span> | ||
39 | + | ||
40 | + <span class="k">if</span> <span class="p">(</span><span class="nx">args</span><span class="p">.</span><span class="nx">length</span> <span class="o">></span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span></pre></div> </td> </tr> <tr id="section-7"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-7">¶</a> </div> <p>If additional string arguments have been passed in | ||
41 | +then add them to the properties to expose on the | ||
42 | +parent module. </p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">options</span><span class="p">.</span><span class="nx">include</span> <span class="o">=</span> <span class="nx">options</span><span class="p">.</span><span class="nx">include</span><span class="p">.</span><span class="nx">concat</span><span class="p">(</span><span class="nx">args</span><span class="p">);</span> | ||
43 | + <span class="p">}</span> | ||
44 | + | ||
45 | + <span class="kd">var</span> <span class="nx">pkg</span> <span class="o">=</span> <span class="nx">pkginfo</span><span class="p">.</span><span class="nx">read</span><span class="p">(</span><span class="nx">pmodule</span><span class="p">,</span> <span class="nx">options</span><span class="p">.</span><span class="nx">dir</span><span class="p">).</span><span class="kr">package</span><span class="p">;</span> | ||
46 | + <span class="nb">Object</span><span class="p">.</span><span class="nx">keys</span><span class="p">(</span><span class="nx">pkg</span><span class="p">).</span><span class="nx">forEach</span><span class="p">(</span><span class="kd">function</span> <span class="p">(</span><span class="nx">key</span><span class="p">)</span> <span class="p">{</span> | ||
47 | + <span class="k">if</span> <span class="p">(</span><span class="nx">options</span><span class="p">.</span><span class="nx">include</span><span class="p">.</span><span class="nx">length</span> <span class="o">></span> <span class="mi">0</span> <span class="o">&&</span> <span class="o">!~</span><span class="nx">options</span><span class="p">.</span><span class="nx">include</span><span class="p">.</span><span class="nx">indexOf</span><span class="p">(</span><span class="nx">key</span><span class="p">))</span> <span class="p">{</span> | ||
48 | + <span class="k">return</span><span class="p">;</span> | ||
49 | + <span class="p">}</span> | ||
50 | + | ||
51 | + <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">pmodule</span><span class="p">.</span><span class="nx">exports</span><span class="p">[</span><span class="nx">key</span><span class="p">])</span> <span class="p">{</span> | ||
52 | + <span class="nx">pmodule</span><span class="p">.</span><span class="nx">exports</span><span class="p">[</span><span class="nx">key</span><span class="p">]</span> <span class="o">=</span> <span class="nx">pkg</span><span class="p">[</span><span class="nx">key</span><span class="p">];</span> | ||
53 | + <span class="p">}</span> | ||
54 | + <span class="p">});</span> | ||
55 | + | ||
56 | + <span class="k">return</span> <span class="nx">pkginfo</span><span class="p">;</span> | ||
57 | +<span class="p">};</span></pre></div> </td> </tr> <tr id="section-8"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-8">¶</a> </div> <h3>function find (dir)</h3> | ||
58 | + | ||
59 | +<h4>@pmodule {Module} Parent module to read from.</h4> | ||
60 | + | ||
61 | +<h4>@dir {string} <strong>Optional</strong> Directory to start search from.</h4> | ||
62 | + | ||
63 | +<p>Searches up the directory tree from <code>dir</code> until it finds a directory | ||
64 | +which contains a <code>package.json</code> file. </p> </td> <td class="code"> <div class="highlight"><pre><span class="nx">pkginfo</span><span class="p">.</span><span class="nx">find</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">pmodule</span><span class="p">,</span> <span class="nx">dir</span><span class="p">)</span> <span class="p">{</span> | ||
65 | + <span class="nx">dir</span> <span class="o">=</span> <span class="nx">dir</span> <span class="o">||</span> <span class="nx">pmodule</span><span class="p">.</span><span class="nx">filename</span><span class="p">;</span> | ||
66 | + <span class="nx">dir</span> <span class="o">=</span> <span class="nx">path</span><span class="p">.</span><span class="nx">dirname</span><span class="p">(</span><span class="nx">dir</span><span class="p">);</span> | ||
67 | + | ||
68 | + <span class="kd">var</span> <span class="nx">files</span> <span class="o">=</span> <span class="nx">fs</span><span class="p">.</span><span class="nx">readdirSync</span><span class="p">(</span><span class="nx">dir</span><span class="p">);</span> | ||
69 | + | ||
70 | + <span class="k">if</span> <span class="p">(</span><span class="o">~</span><span class="nx">files</span><span class="p">.</span><span class="nx">indexOf</span><span class="p">(</span><span class="s1">'package.json'</span><span class="p">))</span> <span class="p">{</span> | ||
71 | + <span class="k">return</span> <span class="nx">path</span><span class="p">.</span><span class="nx">join</span><span class="p">(</span><span class="nx">dir</span><span class="p">,</span> <span class="s1">'package.json'</span><span class="p">);</span> | ||
72 | + <span class="p">}</span> | ||
73 | + | ||
74 | + <span class="k">if</span> <span class="p">(</span><span class="nx">dir</span> <span class="o">===</span> <span class="s1">'/'</span><span class="p">)</span> <span class="p">{</span> | ||
75 | + <span class="k">throw</span> <span class="k">new</span> <span class="nb">Error</span><span class="p">(</span><span class="s1">'Could not find package.json up from: '</span> <span class="o">+</span> <span class="nx">dir</span><span class="p">);</span> | ||
76 | + <span class="p">}</span> | ||
77 | + | ||
78 | + <span class="k">return</span> <span class="nx">pkginfo</span><span class="p">.</span><span class="nx">find</span><span class="p">(</span><span class="nx">dir</span><span class="p">);</span> | ||
79 | +<span class="p">};</span></pre></div> </td> </tr> <tr id="section-9"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-9">¶</a> </div> <h3>function read (pmodule, dir)</h3> | ||
80 | + | ||
81 | +<h4>@pmodule {Module} Parent module to read from.</h4> | ||
82 | + | ||
83 | +<h4>@dir {string} <strong>Optional</strong> Directory to start search from.</h4> | ||
84 | + | ||
85 | +<p>Searches up the directory tree from <code>dir</code> until it finds a directory | ||
86 | +which contains a <code>package.json</code> file and returns the package information.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nx">pkginfo</span><span class="p">.</span><span class="nx">read</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">pmodule</span><span class="p">,</span> <span class="nx">dir</span><span class="p">)</span> <span class="p">{</span> | ||
87 | + <span class="nx">dir</span> <span class="o">=</span> <span class="nx">pkginfo</span><span class="p">.</span><span class="nx">find</span><span class="p">(</span><span class="nx">pmodule</span><span class="p">,</span> <span class="nx">dir</span><span class="p">);</span> | ||
88 | + | ||
89 | + <span class="kd">var</span> <span class="nx">data</span> <span class="o">=</span> <span class="nx">fs</span><span class="p">.</span><span class="nx">readFileSync</span><span class="p">(</span><span class="nx">dir</span><span class="p">).</span><span class="nx">toString</span><span class="p">();</span> | ||
90 | + | ||
91 | + <span class="k">return</span> <span class="p">{</span> | ||
92 | + <span class="nx">dir</span><span class="o">:</span> <span class="nx">dir</span><span class="p">,</span> | ||
93 | + <span class="kr">package</span><span class="o">:</span> <span class="nx">JSON</span><span class="p">.</span><span class="nx">parse</span><span class="p">(</span><span class="nx">data</span><span class="p">)</span> | ||
94 | + <span class="p">};</span> | ||
95 | +<span class="p">};</span></pre></div> </td> </tr> <tr id="section-10"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-10">¶</a> </div> <p>Call <code>pkginfo</code> on this module and expose version.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nx">pkginfo</span><span class="p">(</span><span class="nx">module</span><span class="p">,</span> <span class="p">{</span> | ||
96 | + <span class="nx">dir</span><span class="o">:</span> <span class="nx">__dirname</span><span class="p">,</span> | ||
97 | + <span class="nx">include</span><span class="o">:</span> <span class="p">[</span><span class="s1">'version'</span><span class="p">],</span> | ||
98 | + <span class="nx">target</span><span class="o">:</span> <span class="nx">pkginfo</span> | ||
99 | +<span class="p">});</span> | ||
100 | + | ||
101 | +</pre></div> </td> </tr> </tbody> </table> </div> </body> </html> | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
1 | +/* | ||
2 | + * all-properties.js: Sample of including all properties from a package.json file | ||
3 | + * | ||
4 | + * (C) 2011, Charlie Robbins | ||
5 | + * | ||
6 | + */ | ||
7 | + | ||
8 | +var util = require('util'), | ||
9 | + pkginfo = require('../lib/pkginfo')(module); | ||
10 | + | ||
11 | +exports.someFunction = function () { | ||
12 | + console.log('some of your custom logic here'); | ||
13 | +}; | ||
14 | + | ||
15 | +console.log('Inspecting module:'); | ||
16 | +console.dir(module.exports); | ||
17 | + | ||
18 | +console.log('\nAll exports exposed:'); | ||
19 | +console.error(Object.keys(module.exports)); | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
1 | +/* | ||
2 | + * array-argument.js: Sample of including specific properties from a package.json file | ||
3 | + * using Array argument syntax. | ||
4 | + * | ||
5 | + * (C) 2011, Charlie Robbins | ||
6 | + * | ||
7 | + */ | ||
8 | + | ||
9 | +var util = require('util'), | ||
10 | + pkginfo = require('../lib/pkginfo')(module, ['version', 'author']); | ||
11 | + | ||
12 | +exports.someFunction = function () { | ||
13 | + console.log('some of your custom logic here'); | ||
14 | +}; | ||
15 | + | ||
16 | +console.log('Inspecting module:'); | ||
17 | +console.dir(module.exports); | ||
18 | + | ||
19 | +console.log('\nAll exports exposed:'); | ||
20 | +console.error(Object.keys(module.exports)); | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
1 | +/* | ||
2 | + * multiple-properties.js: Sample of including multiple properties from a package.json file | ||
3 | + * | ||
4 | + * (C) 2011, Charlie Robbins | ||
5 | + * | ||
6 | + */ | ||
7 | + | ||
8 | +var util = require('util'), | ||
9 | + pkginfo = require('../lib/pkginfo')(module, 'version', 'author'); | ||
10 | + | ||
11 | +exports.someFunction = function () { | ||
12 | + console.log('some of your custom logic here'); | ||
13 | +}; | ||
14 | + | ||
15 | +console.log('Inspecting module:'); | ||
16 | +console.dir(module.exports); | ||
17 | + | ||
18 | +console.log('\nAll exports exposed:'); | ||
19 | +console.error(Object.keys(module.exports)); | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
1 | +/* | ||
2 | + * object-argument.js: Sample of including specific properties from a package.json file | ||
3 | + * using Object argument syntax. | ||
4 | + * | ||
5 | + * (C) 2011, Charlie Robbins | ||
6 | + * | ||
7 | + */ | ||
8 | + | ||
9 | +var util = require('util'), | ||
10 | + pkginfo = require('../lib/pkginfo')(module, { | ||
11 | + include: ['version', 'author'] | ||
12 | + }); | ||
13 | + | ||
14 | +exports.someFunction = function () { | ||
15 | + console.log('some of your custom logic here'); | ||
16 | +}; | ||
17 | + | ||
18 | +console.log('Inspecting module:'); | ||
19 | +console.dir(module.exports); | ||
20 | + | ||
21 | +console.log('\nAll exports exposed:'); | ||
22 | +console.error(Object.keys(module.exports)); | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
1 | +{ | ||
2 | + "name": "simple-app", | ||
3 | + "description": "A test fixture for pkginfo", | ||
4 | + "version": "0.1.0", | ||
5 | + "author": "Charlie Robbins <charlie.robbins@gmail.com>", | ||
6 | + "keywords": ["test", "fixture"], | ||
7 | + "main": "./index.js", | ||
8 | + "scripts": { "test": "vows test/*-test.js --spec" }, | ||
9 | + "engines": { "node": ">= 0.4.0" } | ||
10 | +} |
1 | +/* | ||
2 | + * single-property.js: Sample of including a single specific properties from a package.json file | ||
3 | + * | ||
4 | + * (C) 2011, Charlie Robbins | ||
5 | + * | ||
6 | + */ | ||
7 | + | ||
8 | +var util = require('util'), | ||
9 | + pkginfo = require('../lib/pkginfo')(module, 'version'); | ||
10 | + | ||
11 | +exports.someFunction = function () { | ||
12 | + console.log('some of your custom logic here'); | ||
13 | +}; | ||
14 | + | ||
15 | +console.log('Inspecting module:'); | ||
16 | +console.dir(module.exports); | ||
17 | + | ||
18 | +console.log('\nAll exports exposed:'); | ||
19 | +console.error(Object.keys(module.exports)); | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
1 | +{ | ||
2 | + "name": "simple-app-subdir", | ||
3 | + "description": "A test fixture for pkginfo", | ||
4 | + "version": "0.1.0", | ||
5 | + "author": "Charlie Robbins <charlie.robbins@gmail.com>", | ||
6 | + "keywords": ["test", "fixture"], | ||
7 | + "main": "./index.js", | ||
8 | + "scripts": { "test": "vows test/*-test.js --spec" }, | ||
9 | + "engines": { "node": ">= 0.4.0" }, | ||
10 | + "subdironly": "true" | ||
11 | +} |
1 | +/* | ||
2 | + * multiple-properties.js: Sample of including multiple properties from a package.json file | ||
3 | + * | ||
4 | + * (C) 2011, Charlie Robbins | ||
5 | + * | ||
6 | + */ | ||
7 | + | ||
8 | +var util = require('util'), | ||
9 | + path = require('path'), | ||
10 | + pkginfo = require('../lib/pkginfo')(module, { dir: path.resolve(__dirname, 'subdir' )}); | ||
11 | + | ||
12 | +exports.someFunction = function () { | ||
13 | + console.log('some of your custom logic here'); | ||
14 | +}; | ||
15 | + | ||
16 | +console.log('Inspecting module:'); | ||
17 | +console.dir(module.exports); | ||
18 | + | ||
19 | +console.log('\nAll exports exposed:'); | ||
20 | +console.error(Object.keys(module.exports)); | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
1 | +/* | ||
2 | + * pkginfo.js: Top-level include for the pkginfo module | ||
3 | + * | ||
4 | + * (C) 2011, Charlie Robbins | ||
5 | + * | ||
6 | + */ | ||
7 | + | ||
8 | +var fs = require('fs'), | ||
9 | + path = require('path'); | ||
10 | + | ||
11 | +// | ||
12 | +// ### function pkginfo ([options, 'property', 'property' ..]) | ||
13 | +// #### @pmodule {Module} Parent module to read from. | ||
14 | +// #### @options {Object|Array|string} **Optional** Options used when exposing properties. | ||
15 | +// #### @arguments {string...} **Optional** Specified properties to expose. | ||
16 | +// Exposes properties from the package.json file for the parent module on | ||
17 | +// it's exports. Valid usage: | ||
18 | +// | ||
19 | +// `require('pkginfo')()` | ||
20 | +// | ||
21 | +// `require('pkginfo')('version', 'author');` | ||
22 | +// | ||
23 | +// `require('pkginfo')(['version', 'author']);` | ||
24 | +// | ||
25 | +// `require('pkginfo')({ include: ['version', 'author'] });` | ||
26 | +// | ||
27 | +var pkginfo = module.exports = function (pmodule, options) { | ||
28 | + var args = [].slice.call(arguments, 2).filter(function (arg) { | ||
29 | + return typeof arg === 'string'; | ||
30 | + }); | ||
31 | + | ||
32 | + // | ||
33 | + // **Parse variable arguments** | ||
34 | + // | ||
35 | + if (Array.isArray(options)) { | ||
36 | + // | ||
37 | + // If the options passed in is an Array assume that | ||
38 | + // it is the Array of properties to expose from the | ||
39 | + // on the package.json file on the parent module. | ||
40 | + // | ||
41 | + options = { include: options }; | ||
42 | + } | ||
43 | + else if (typeof options === 'string') { | ||
44 | + // | ||
45 | + // Otherwise if the first argument is a string, then | ||
46 | + // assume that it is the first property to expose from | ||
47 | + // the package.json file on the parent module. | ||
48 | + // | ||
49 | + options = { include: [options] }; | ||
50 | + } | ||
51 | + | ||
52 | + // | ||
53 | + // **Setup default options** | ||
54 | + // | ||
55 | + options = options || {}; | ||
56 | + | ||
57 | + // ensure that includes have been defined | ||
58 | + options.include = options.include || []; | ||
59 | + | ||
60 | + if (args.length > 0) { | ||
61 | + // | ||
62 | + // If additional string arguments have been passed in | ||
63 | + // then add them to the properties to expose on the | ||
64 | + // parent module. | ||
65 | + // | ||
66 | + options.include = options.include.concat(args); | ||
67 | + } | ||
68 | + | ||
69 | + var pkg = pkginfo.read(pmodule, options.dir).package; | ||
70 | + Object.keys(pkg).forEach(function (key) { | ||
71 | + if (options.include.length > 0 && !~options.include.indexOf(key)) { | ||
72 | + return; | ||
73 | + } | ||
74 | + | ||
75 | + if (!pmodule.exports[key]) { | ||
76 | + pmodule.exports[key] = pkg[key]; | ||
77 | + } | ||
78 | + }); | ||
79 | + | ||
80 | + return pkginfo; | ||
81 | +}; | ||
82 | + | ||
83 | +// | ||
84 | +// ### function find (dir) | ||
85 | +// #### @pmodule {Module} Parent module to read from. | ||
86 | +// #### @dir {string} **Optional** Directory to start search from. | ||
87 | +// Searches up the directory tree from `dir` until it finds a directory | ||
88 | +// which contains a `package.json` file. | ||
89 | +// | ||
90 | +pkginfo.find = function (pmodule, dir) { | ||
91 | + if (! dir) { | ||
92 | + dir = path.dirname(pmodule.filename); | ||
93 | + } | ||
94 | + | ||
95 | + var files = fs.readdirSync(dir); | ||
96 | + | ||
97 | + if (~files.indexOf('package.json')) { | ||
98 | + return path.join(dir, 'package.json'); | ||
99 | + } | ||
100 | + | ||
101 | + if (dir === '/') { | ||
102 | + throw new Error('Could not find package.json up from: ' + dir); | ||
103 | + } | ||
104 | + else if (!dir || dir === '.') { | ||
105 | + throw new Error('Cannot find package.json from unspecified directory'); | ||
106 | + } | ||
107 | + | ||
108 | + return pkginfo.find(pmodule, path.dirname(dir)); | ||
109 | +}; | ||
110 | + | ||
111 | +// | ||
112 | +// ### function read (pmodule, dir) | ||
113 | +// #### @pmodule {Module} Parent module to read from. | ||
114 | +// #### @dir {string} **Optional** Directory to start search from. | ||
115 | +// Searches up the directory tree from `dir` until it finds a directory | ||
116 | +// which contains a `package.json` file and returns the package information. | ||
117 | +// | ||
118 | +pkginfo.read = function (pmodule, dir) { | ||
119 | + dir = pkginfo.find(pmodule, dir); | ||
120 | + | ||
121 | + var data = fs.readFileSync(dir).toString(); | ||
122 | + | ||
123 | + return { | ||
124 | + dir: dir, | ||
125 | + package: JSON.parse(data) | ||
126 | + }; | ||
127 | +}; | ||
128 | + | ||
129 | +// | ||
130 | +// Call `pkginfo` on this module and expose version. | ||
131 | +// | ||
132 | +pkginfo(module, { | ||
133 | + dir: __dirname, | ||
134 | + include: ['version'], | ||
135 | + target: pkginfo | ||
136 | +}); | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
1 | +{ | ||
2 | + "_from": "pkginfo@~0.3.0", | ||
3 | + "_id": "pkginfo@0.3.1", | ||
4 | + "_inBundle": false, | ||
5 | + "_integrity": "sha1-Wyn2qB9wcXFC4J52W76rl7T4HiE=", | ||
6 | + "_location": "/passport-kakao/pkginfo", | ||
7 | + "_phantomChildren": {}, | ||
8 | + "_requested": { | ||
9 | + "type": "range", | ||
10 | + "registry": true, | ||
11 | + "raw": "pkginfo@~0.3.0", | ||
12 | + "name": "pkginfo", | ||
13 | + "escapedName": "pkginfo", | ||
14 | + "rawSpec": "~0.3.0", | ||
15 | + "saveSpec": null, | ||
16 | + "fetchSpec": "~0.3.0" | ||
17 | + }, | ||
18 | + "_requiredBy": [ | ||
19 | + "/passport-kakao" | ||
20 | + ], | ||
21 | + "_resolved": "https://registry.npmjs.org/pkginfo/-/pkginfo-0.3.1.tgz", | ||
22 | + "_shasum": "5b29f6a81f70717142e09e765bbeab97b4f81e21", | ||
23 | + "_spec": "pkginfo@~0.3.0", | ||
24 | + "_where": "C:\\Users\\LG\\Desktop\\4-1\\Reminder-Talk\\node_modules\\passport-kakao", | ||
25 | + "author": { | ||
26 | + "name": "Charlie Robbins", | ||
27 | + "email": "charlie.robbins@gmail.com" | ||
28 | + }, | ||
29 | + "bugs": { | ||
30 | + "url": "https://github.com/indexzero/node-pkginfo/issues" | ||
31 | + }, | ||
32 | + "bundleDependencies": false, | ||
33 | + "deprecated": false, | ||
34 | + "description": "An easy way to expose properties on a module from a package.json", | ||
35 | + "devDependencies": { | ||
36 | + "vows": "0.7.x" | ||
37 | + }, | ||
38 | + "engines": { | ||
39 | + "node": ">= 0.4.0" | ||
40 | + }, | ||
41 | + "homepage": "https://github.com/indexzero/node-pkginfo#readme", | ||
42 | + "keywords": [ | ||
43 | + "info", | ||
44 | + "tools", | ||
45 | + "package.json" | ||
46 | + ], | ||
47 | + "license": "MIT", | ||
48 | + "main": "./lib/pkginfo.js", | ||
49 | + "name": "pkginfo", | ||
50 | + "repository": { | ||
51 | + "type": "git", | ||
52 | + "url": "git+ssh://git@github.com/indexzero/node-pkginfo.git" | ||
53 | + }, | ||
54 | + "scripts": { | ||
55 | + "test": "vows test/*-test.js --spec" | ||
56 | + }, | ||
57 | + "version": "0.3.1" | ||
58 | +} |
1 | +/* | ||
2 | + * pkginfo-test.js: Tests for the pkginfo module. | ||
3 | + * | ||
4 | + * (C) 2011, Charlie Robbins | ||
5 | + * | ||
6 | + */ | ||
7 | + | ||
8 | +var assert = require('assert'), | ||
9 | + exec = require('child_process').exec, | ||
10 | + fs = require('fs'), | ||
11 | + path = require('path'), | ||
12 | + vows = require('vows'), | ||
13 | + pkginfo = require('../lib/pkginfo'); | ||
14 | + | ||
15 | +function assertProperties (source, target) { | ||
16 | + assert.lengthOf(source, target.length + 1); | ||
17 | + target.forEach(function (prop) { | ||
18 | + assert.isTrue(!!~source.indexOf(prop)); | ||
19 | + }); | ||
20 | +} | ||
21 | + | ||
22 | +function compareWithExample(targetPath) { | ||
23 | + var examplePaths = ['package.json']; | ||
24 | + | ||
25 | + if (targetPath) { | ||
26 | + examplePaths.unshift(targetPath); | ||
27 | + } | ||
28 | + | ||
29 | + return function(exposed) { | ||
30 | + var pkg = fs.readFileSync(path.join.apply(null, [__dirname, '..', 'examples'].concat(examplePaths))).toString(), | ||
31 | + keys = Object.keys(JSON.parse(pkg)); | ||
32 | + | ||
33 | + assertProperties(exposed, keys); | ||
34 | + }; | ||
35 | +} | ||
36 | + | ||
37 | +function testExposes (options) { | ||
38 | + return { | ||
39 | + topic: function () { | ||
40 | + exec('node ' + path.join(__dirname, '..', 'examples', options.script), this.callback); | ||
41 | + }, | ||
42 | + "should expose that property correctly": function (err, stdout, stderr) { | ||
43 | + assert.isNull(err); | ||
44 | + | ||
45 | + var exposed = stderr.match(/'(\w+)'/ig).map(function (p) { | ||
46 | + return p.substring(1, p.length - 1); | ||
47 | + }); | ||
48 | + | ||
49 | + return !options.assert | ||
50 | + ? assertProperties(exposed, options.properties) | ||
51 | + : options.assert(exposed); | ||
52 | + } | ||
53 | + } | ||
54 | +} | ||
55 | + | ||
56 | +vows.describe('pkginfo').addBatch({ | ||
57 | + "When using the pkginfo module": { | ||
58 | + "and passed a single `string` argument": testExposes({ | ||
59 | + script: 'single-property.js', | ||
60 | + properties: ['version'] | ||
61 | + }), | ||
62 | + "and passed multiple `string` arguments": testExposes({ | ||
63 | + script: 'multiple-properties.js', | ||
64 | + properties: ['version', 'author'] | ||
65 | + }), | ||
66 | + "and passed an `object` argument": testExposes({ | ||
67 | + script: 'object-argument.js', | ||
68 | + properties: ['version', 'author'] | ||
69 | + }), | ||
70 | + "and passed an `array` argument": testExposes({ | ||
71 | + script: 'array-argument.js', | ||
72 | + properties: ['version', 'author'] | ||
73 | + }), | ||
74 | + "and read from a specified directory": testExposes({ | ||
75 | + script: 'target-dir.js', | ||
76 | + assert: compareWithExample('subdir') | ||
77 | + }), | ||
78 | + "and passed no arguments": testExposes({ | ||
79 | + script: 'all-properties.js', | ||
80 | + assert: compareWithExample() | ||
81 | + }) | ||
82 | + } | ||
83 | +}).export(module); |
node_modules/passport-kakao/package.json
0 → 100644
1 | +{ | ||
2 | + "_from": "passport-kakao", | ||
3 | + "_id": "passport-kakao@1.0.0", | ||
4 | + "_inBundle": false, | ||
5 | + "_integrity": "sha512-rOR3+8g1bev/p9ChZLDKQan9oBmSSA2hmb7yQKdBOsjyF1mijx7fgR05pTWPz3g5r0kHZ2Y44sT2Ys6wJQq0xQ==", | ||
6 | + "_location": "/passport-kakao", | ||
7 | + "_phantomChildren": { | ||
8 | + "oauth": "0.9.15", | ||
9 | + "passport-strategy": "1.0.0", | ||
10 | + "uid2": "0.0.3" | ||
11 | + }, | ||
12 | + "_requested": { | ||
13 | + "type": "tag", | ||
14 | + "registry": true, | ||
15 | + "raw": "passport-kakao", | ||
16 | + "name": "passport-kakao", | ||
17 | + "escapedName": "passport-kakao", | ||
18 | + "rawSpec": "", | ||
19 | + "saveSpec": null, | ||
20 | + "fetchSpec": "latest" | ||
21 | + }, | ||
22 | + "_requiredBy": [ | ||
23 | + "#USER", | ||
24 | + "/" | ||
25 | + ], | ||
26 | + "_resolved": "https://registry.npmjs.org/passport-kakao/-/passport-kakao-1.0.0.tgz", | ||
27 | + "_shasum": "11924fb3a5c9f174e3d9a6b8c75d729066ef388d", | ||
28 | + "_spec": "passport-kakao", | ||
29 | + "_where": "C:\\Users\\LG\\Desktop\\4-1\\Reminder-Talk", | ||
30 | + "author": { | ||
31 | + "name": "rotoshine@gmail.com" | ||
32 | + }, | ||
33 | + "bugs": { | ||
34 | + "url": "https://github.com/rotoshine/passport-kakao/issues" | ||
35 | + }, | ||
36 | + "bundleDependencies": false, | ||
37 | + "dependencies": { | ||
38 | + "passport-oauth2": "~1.1.2", | ||
39 | + "pkginfo": "~0.3.0" | ||
40 | + }, | ||
41 | + "deprecated": false, | ||
42 | + "description": "kakao oauth2 login module", | ||
43 | + "devDependencies": { | ||
44 | + "@types/chai": "^4.2.3", | ||
45 | + "@types/mocha": "^5.2.7", | ||
46 | + "@types/node": "^12.7.11", | ||
47 | + "chai": "^4.2.0", | ||
48 | + "mocha": "^6.2.1", | ||
49 | + "ts-node": "^8.4.1", | ||
50 | + "tslint": "^5.20.0", | ||
51 | + "tslint-config-prettier": "^1.18.0", | ||
52 | + "typescript": "^3.6.3" | ||
53 | + }, | ||
54 | + "homepage": "https://github.com/rotoshine/passport-kakao#readme", | ||
55 | + "keywords": [ | ||
56 | + "passport", | ||
57 | + "kakao", | ||
58 | + "kakaotalk", | ||
59 | + "oauth2" | ||
60 | + ], | ||
61 | + "license": "MIT", | ||
62 | + "main": "./dist/passport-kakao", | ||
63 | + "name": "passport-kakao", | ||
64 | + "repository": { | ||
65 | + "type": "git", | ||
66 | + "url": "git://github.com/rotoshine/passport-kakao.git" | ||
67 | + }, | ||
68 | + "scripts": { | ||
69 | + "build": "npx tsc", | ||
70 | + "lint": "tslint --project .", | ||
71 | + "test": "mocha -r node_modules/ts-node/register ./tests/**/*.spec.ts" | ||
72 | + }, | ||
73 | + "version": "1.0.0" | ||
74 | +} |
1 | +{ | ||
2 | + "name": "passport-kakao-sample", | ||
3 | + "requires": true, | ||
4 | + "lockfileVersion": 1, | ||
5 | + "dependencies": { | ||
6 | + "accepts": { | ||
7 | + "version": "1.3.7", | ||
8 | + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", | ||
9 | + "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", | ||
10 | + "requires": { | ||
11 | + "mime-types": "~2.1.24", | ||
12 | + "negotiator": "0.6.2" | ||
13 | + } | ||
14 | + }, | ||
15 | + "array-flatten": { | ||
16 | + "version": "1.1.1", | ||
17 | + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", | ||
18 | + "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" | ||
19 | + }, | ||
20 | + "body-parser": { | ||
21 | + "version": "1.19.0", | ||
22 | + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", | ||
23 | + "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", | ||
24 | + "requires": { | ||
25 | + "bytes": "3.1.0", | ||
26 | + "content-type": "~1.0.4", | ||
27 | + "debug": "2.6.9", | ||
28 | + "depd": "~1.1.2", | ||
29 | + "http-errors": "1.7.2", | ||
30 | + "iconv-lite": "0.4.24", | ||
31 | + "on-finished": "~2.3.0", | ||
32 | + "qs": "6.7.0", | ||
33 | + "raw-body": "2.4.0", | ||
34 | + "type-is": "~1.6.17" | ||
35 | + } | ||
36 | + }, | ||
37 | + "bytes": { | ||
38 | + "version": "3.1.0", | ||
39 | + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", | ||
40 | + "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==" | ||
41 | + }, | ||
42 | + "content-disposition": { | ||
43 | + "version": "0.5.3", | ||
44 | + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", | ||
45 | + "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", | ||
46 | + "requires": { | ||
47 | + "safe-buffer": "5.1.2" | ||
48 | + } | ||
49 | + }, | ||
50 | + "content-type": { | ||
51 | + "version": "1.0.4", | ||
52 | + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", | ||
53 | + "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" | ||
54 | + }, | ||
55 | + "cookie": { | ||
56 | + "version": "0.4.0", | ||
57 | + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", | ||
58 | + "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==" | ||
59 | + }, | ||
60 | + "cookie-signature": { | ||
61 | + "version": "1.0.6", | ||
62 | + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", | ||
63 | + "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" | ||
64 | + }, | ||
65 | + "debug": { | ||
66 | + "version": "2.6.9", | ||
67 | + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", | ||
68 | + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", | ||
69 | + "requires": { | ||
70 | + "ms": "2.0.0" | ||
71 | + } | ||
72 | + }, | ||
73 | + "depd": { | ||
74 | + "version": "1.1.2", | ||
75 | + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", | ||
76 | + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" | ||
77 | + }, | ||
78 | + "destroy": { | ||
79 | + "version": "1.0.4", | ||
80 | + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", | ||
81 | + "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" | ||
82 | + }, | ||
83 | + "ee-first": { | ||
84 | + "version": "1.1.1", | ||
85 | + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", | ||
86 | + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" | ||
87 | + }, | ||
88 | + "encodeurl": { | ||
89 | + "version": "1.0.2", | ||
90 | + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", | ||
91 | + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" | ||
92 | + }, | ||
93 | + "escape-html": { | ||
94 | + "version": "1.0.3", | ||
95 | + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", | ||
96 | + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" | ||
97 | + }, | ||
98 | + "etag": { | ||
99 | + "version": "1.8.1", | ||
100 | + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", | ||
101 | + "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" | ||
102 | + }, | ||
103 | + "express": { | ||
104 | + "version": "4.17.1", | ||
105 | + "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", | ||
106 | + "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", | ||
107 | + "requires": { | ||
108 | + "accepts": "~1.3.7", | ||
109 | + "array-flatten": "1.1.1", | ||
110 | + "body-parser": "1.19.0", | ||
111 | + "content-disposition": "0.5.3", | ||
112 | + "content-type": "~1.0.4", | ||
113 | + "cookie": "0.4.0", | ||
114 | + "cookie-signature": "1.0.6", | ||
115 | + "debug": "2.6.9", | ||
116 | + "depd": "~1.1.2", | ||
117 | + "encodeurl": "~1.0.2", | ||
118 | + "escape-html": "~1.0.3", | ||
119 | + "etag": "~1.8.1", | ||
120 | + "finalhandler": "~1.1.2", | ||
121 | + "fresh": "0.5.2", | ||
122 | + "merge-descriptors": "1.0.1", | ||
123 | + "methods": "~1.1.2", | ||
124 | + "on-finished": "~2.3.0", | ||
125 | + "parseurl": "~1.3.3", | ||
126 | + "path-to-regexp": "0.1.7", | ||
127 | + "proxy-addr": "~2.0.5", | ||
128 | + "qs": "6.7.0", | ||
129 | + "range-parser": "~1.2.1", | ||
130 | + "safe-buffer": "5.1.2", | ||
131 | + "send": "0.17.1", | ||
132 | + "serve-static": "1.14.1", | ||
133 | + "setprototypeof": "1.1.1", | ||
134 | + "statuses": "~1.5.0", | ||
135 | + "type-is": "~1.6.18", | ||
136 | + "utils-merge": "1.0.1", | ||
137 | + "vary": "~1.1.2" | ||
138 | + } | ||
139 | + }, | ||
140 | + "finalhandler": { | ||
141 | + "version": "1.1.2", | ||
142 | + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", | ||
143 | + "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", | ||
144 | + "requires": { | ||
145 | + "debug": "2.6.9", | ||
146 | + "encodeurl": "~1.0.2", | ||
147 | + "escape-html": "~1.0.3", | ||
148 | + "on-finished": "~2.3.0", | ||
149 | + "parseurl": "~1.3.3", | ||
150 | + "statuses": "~1.5.0", | ||
151 | + "unpipe": "~1.0.0" | ||
152 | + } | ||
153 | + }, | ||
154 | + "forwarded": { | ||
155 | + "version": "0.1.2", | ||
156 | + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", | ||
157 | + "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=" | ||
158 | + }, | ||
159 | + "fresh": { | ||
160 | + "version": "0.5.2", | ||
161 | + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", | ||
162 | + "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" | ||
163 | + }, | ||
164 | + "http-errors": { | ||
165 | + "version": "1.7.2", | ||
166 | + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", | ||
167 | + "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", | ||
168 | + "requires": { | ||
169 | + "depd": "~1.1.2", | ||
170 | + "inherits": "2.0.3", | ||
171 | + "setprototypeof": "1.1.1", | ||
172 | + "statuses": ">= 1.5.0 < 2", | ||
173 | + "toidentifier": "1.0.0" | ||
174 | + } | ||
175 | + }, | ||
176 | + "iconv-lite": { | ||
177 | + "version": "0.4.24", | ||
178 | + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", | ||
179 | + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", | ||
180 | + "requires": { | ||
181 | + "safer-buffer": ">= 2.1.2 < 3" | ||
182 | + } | ||
183 | + }, | ||
184 | + "inherits": { | ||
185 | + "version": "2.0.3", | ||
186 | + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", | ||
187 | + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" | ||
188 | + }, | ||
189 | + "ipaddr.js": { | ||
190 | + "version": "1.9.0", | ||
191 | + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.0.tgz", | ||
192 | + "integrity": "sha512-M4Sjn6N/+O6/IXSJseKqHoFc+5FdGJ22sXqnjTpdZweHK64MzEPAyQZyEU3R/KRv2GLoa7nNtg/C2Ev6m7z+eA==" | ||
193 | + }, | ||
194 | + "media-typer": { | ||
195 | + "version": "0.3.0", | ||
196 | + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", | ||
197 | + "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" | ||
198 | + }, | ||
199 | + "merge-descriptors": { | ||
200 | + "version": "1.0.1", | ||
201 | + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", | ||
202 | + "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" | ||
203 | + }, | ||
204 | + "methods": { | ||
205 | + "version": "1.1.2", | ||
206 | + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", | ||
207 | + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" | ||
208 | + }, | ||
209 | + "mime": { | ||
210 | + "version": "1.6.0", | ||
211 | + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", | ||
212 | + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" | ||
213 | + }, | ||
214 | + "mime-db": { | ||
215 | + "version": "1.40.0", | ||
216 | + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.40.0.tgz", | ||
217 | + "integrity": "sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA==" | ||
218 | + }, | ||
219 | + "mime-types": { | ||
220 | + "version": "2.1.24", | ||
221 | + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.24.tgz", | ||
222 | + "integrity": "sha512-WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ==", | ||
223 | + "requires": { | ||
224 | + "mime-db": "1.40.0" | ||
225 | + } | ||
226 | + }, | ||
227 | + "ms": { | ||
228 | + "version": "2.0.0", | ||
229 | + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", | ||
230 | + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" | ||
231 | + }, | ||
232 | + "negotiator": { | ||
233 | + "version": "0.6.2", | ||
234 | + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", | ||
235 | + "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==" | ||
236 | + }, | ||
237 | + "on-finished": { | ||
238 | + "version": "2.3.0", | ||
239 | + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", | ||
240 | + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", | ||
241 | + "requires": { | ||
242 | + "ee-first": "1.1.1" | ||
243 | + } | ||
244 | + }, | ||
245 | + "parseurl": { | ||
246 | + "version": "1.3.3", | ||
247 | + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", | ||
248 | + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" | ||
249 | + }, | ||
250 | + "passport": { | ||
251 | + "version": "0.4.0", | ||
252 | + "resolved": "https://registry.npmjs.org/passport/-/passport-0.4.0.tgz", | ||
253 | + "integrity": "sha1-xQlWkTR71a07XhgCOMORTRbwWBE=", | ||
254 | + "requires": { | ||
255 | + "passport-strategy": "1.x.x", | ||
256 | + "pause": "0.0.1" | ||
257 | + } | ||
258 | + }, | ||
259 | + "passport-strategy": { | ||
260 | + "version": "1.0.0", | ||
261 | + "resolved": "https://registry.npmjs.org/passport-strategy/-/passport-strategy-1.0.0.tgz", | ||
262 | + "integrity": "sha1-tVOaqPwiWj0a0XlHbd8ja0QPUuQ=" | ||
263 | + }, | ||
264 | + "path-to-regexp": { | ||
265 | + "version": "0.1.7", | ||
266 | + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", | ||
267 | + "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" | ||
268 | + }, | ||
269 | + "pause": { | ||
270 | + "version": "0.0.1", | ||
271 | + "resolved": "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz", | ||
272 | + "integrity": "sha1-HUCLP9t2kjuVQ9lvtMnf1TXZy10=" | ||
273 | + }, | ||
274 | + "proxy-addr": { | ||
275 | + "version": "2.0.5", | ||
276 | + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.5.tgz", | ||
277 | + "integrity": "sha512-t/7RxHXPH6cJtP0pRG6smSr9QJidhB+3kXu0KgXnbGYMgzEnUxRQ4/LDdfOwZEMyIh3/xHb8PX3t+lfL9z+YVQ==", | ||
278 | + "requires": { | ||
279 | + "forwarded": "~0.1.2", | ||
280 | + "ipaddr.js": "1.9.0" | ||
281 | + } | ||
282 | + }, | ||
283 | + "qs": { | ||
284 | + "version": "6.7.0", | ||
285 | + "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", | ||
286 | + "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==" | ||
287 | + }, | ||
288 | + "range-parser": { | ||
289 | + "version": "1.2.1", | ||
290 | + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", | ||
291 | + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" | ||
292 | + }, | ||
293 | + "raw-body": { | ||
294 | + "version": "2.4.0", | ||
295 | + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", | ||
296 | + "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", | ||
297 | + "requires": { | ||
298 | + "bytes": "3.1.0", | ||
299 | + "http-errors": "1.7.2", | ||
300 | + "iconv-lite": "0.4.24", | ||
301 | + "unpipe": "1.0.0" | ||
302 | + } | ||
303 | + }, | ||
304 | + "safe-buffer": { | ||
305 | + "version": "5.1.2", | ||
306 | + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", | ||
307 | + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" | ||
308 | + }, | ||
309 | + "safer-buffer": { | ||
310 | + "version": "2.1.2", | ||
311 | + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", | ||
312 | + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" | ||
313 | + }, | ||
314 | + "send": { | ||
315 | + "version": "0.17.1", | ||
316 | + "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", | ||
317 | + "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", | ||
318 | + "requires": { | ||
319 | + "debug": "2.6.9", | ||
320 | + "depd": "~1.1.2", | ||
321 | + "destroy": "~1.0.4", | ||
322 | + "encodeurl": "~1.0.2", | ||
323 | + "escape-html": "~1.0.3", | ||
324 | + "etag": "~1.8.1", | ||
325 | + "fresh": "0.5.2", | ||
326 | + "http-errors": "~1.7.2", | ||
327 | + "mime": "1.6.0", | ||
328 | + "ms": "2.1.1", | ||
329 | + "on-finished": "~2.3.0", | ||
330 | + "range-parser": "~1.2.1", | ||
331 | + "statuses": "~1.5.0" | ||
332 | + }, | ||
333 | + "dependencies": { | ||
334 | + "ms": { | ||
335 | + "version": "2.1.1", | ||
336 | + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", | ||
337 | + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" | ||
338 | + } | ||
339 | + } | ||
340 | + }, | ||
341 | + "serve-static": { | ||
342 | + "version": "1.14.1", | ||
343 | + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", | ||
344 | + "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", | ||
345 | + "requires": { | ||
346 | + "encodeurl": "~1.0.2", | ||
347 | + "escape-html": "~1.0.3", | ||
348 | + "parseurl": "~1.3.3", | ||
349 | + "send": "0.17.1" | ||
350 | + } | ||
351 | + }, | ||
352 | + "setprototypeof": { | ||
353 | + "version": "1.1.1", | ||
354 | + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", | ||
355 | + "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" | ||
356 | + }, | ||
357 | + "statuses": { | ||
358 | + "version": "1.5.0", | ||
359 | + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", | ||
360 | + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" | ||
361 | + }, | ||
362 | + "toidentifier": { | ||
363 | + "version": "1.0.0", | ||
364 | + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", | ||
365 | + "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==" | ||
366 | + }, | ||
367 | + "type-is": { | ||
368 | + "version": "1.6.18", | ||
369 | + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", | ||
370 | + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", | ||
371 | + "requires": { | ||
372 | + "media-typer": "0.3.0", | ||
373 | + "mime-types": "~2.1.24" | ||
374 | + } | ||
375 | + }, | ||
376 | + "unpipe": { | ||
377 | + "version": "1.0.0", | ||
378 | + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", | ||
379 | + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" | ||
380 | + }, | ||
381 | + "utils-merge": { | ||
382 | + "version": "1.0.1", | ||
383 | + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", | ||
384 | + "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" | ||
385 | + }, | ||
386 | + "vary": { | ||
387 | + "version": "1.1.2", | ||
388 | + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", | ||
389 | + "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" | ||
390 | + } | ||
391 | + } | ||
392 | +} |
node_modules/passport-kakao/sample/sample.js
0 → 100644
1 | +const passport = require('passport') | ||
2 | +const express = require('express') | ||
3 | +const KakaoStrategy = require('../dist/passport-kakao.js').Strategy | ||
4 | + | ||
5 | +const appKey = 'YOUR_APP_REST_API_KEY' | ||
6 | +const appSecret = 'YOUR_APP_CLIENT_SECRET_KEY' | ||
7 | + | ||
8 | +// passport 에 Kakao Oauth 추가 | ||
9 | +passport.use( | ||
10 | + new KakaoStrategy( | ||
11 | + { | ||
12 | + clientID: appKey, | ||
13 | + clientSecret: appSecret, | ||
14 | + callbackURL: 'http://localhost:3000/oauth', | ||
15 | + }, | ||
16 | + function(accessToken, refreshToken, params, profile, done) { | ||
17 | + // authorization 에 성공했을때의 액션 | ||
18 | + console.log(`accessToken : ${accessToken}`) | ||
19 | + console.log(`사용자 profile: ${JSON.stringify(profile._json)}`) | ||
20 | + | ||
21 | + save(accessToken, refreshToken, profile) | ||
22 | + return done(null, profile._json) | ||
23 | + } | ||
24 | + ) | ||
25 | +) | ||
26 | +passport.serializeUser(function(user, done) { | ||
27 | + done(null, user) | ||
28 | +}) | ||
29 | +passport.deserializeUser(function(obj, done) { | ||
30 | + done(null, obj) | ||
31 | +}) | ||
32 | + | ||
33 | +// express 앱 설정 | ||
34 | +var app = express() | ||
35 | +app.use(passport.initialize()) | ||
36 | +app.get('/login', passport.authenticate('kakao', { state: 'myStateValue' })) | ||
37 | +app.get('/oauth', passport.authenticate('kakao'), function(req, res) { | ||
38 | + // 로그인 시작시 state 값을 받을 수 있음 | ||
39 | + res.send('state :' + req.query.state) | ||
40 | +}) | ||
41 | +app.listen(3000) | ||
42 | + | ||
43 | +// 사용자 구현 부분 | ||
44 | +function save() { | ||
45 | + //save 로직 구현 | ||
46 | +} |
node_modules/passport-kakao/src/Strategy.ts
0 → 100644
1 | +import { inherits } from 'util' | ||
2 | +import OAuth2Strategy from 'passport-oauth2' | ||
3 | + | ||
4 | +import { StrategyOptions, Profile } from './types/models' | ||
5 | + | ||
6 | +const DEFAULT_CLIENT_SECRET = 'kakao' | ||
7 | +const OAUTH_HOST = 'https://kauth.kakao.com' | ||
8 | +const USER_PROFILE_URL = 'https://kapi.kakao.com/v2/user/me' | ||
9 | + | ||
10 | +export const buildOptions = (options: StrategyOptions) => { | ||
11 | + options.authorizationURL = `${OAUTH_HOST}/oauth/authorize` | ||
12 | + options.tokenURL = `${OAUTH_HOST}/oauth/token` | ||
13 | + | ||
14 | + if (!options.clientSecret) { | ||
15 | + options.clientSecret = DEFAULT_CLIENT_SECRET | ||
16 | + } | ||
17 | + | ||
18 | + options.scopeSeparator = options.scopeSeparator || ',' | ||
19 | + options.customHeaders = options.customHeaders || {} | ||
20 | + | ||
21 | + if (!options.customHeaders['User-Agent']) { | ||
22 | + options.customHeaders['User-Agent'] = options.userAgent || 'passport-kakao' | ||
23 | + } | ||
24 | + | ||
25 | + return options | ||
26 | +} | ||
27 | +/** | ||
28 | + * KaKaoStrategy 생성자 함수.<br/> | ||
29 | + * @param options.clientID 필수. kakao rest app key. | ||
30 | + * @param options.callbackURL 필수. 로그인 처리 후 호출할 URL | ||
31 | + * @param verify | ||
32 | + * @constructor | ||
33 | + */ | ||
34 | +function Strategy(options: StrategyOptions = {}, verify: any) { | ||
35 | + OAuth2Strategy.call(this, buildOptions(options), verify) | ||
36 | + this.name = 'kakao' | ||
37 | + this._userProfileURL = USER_PROFILE_URL | ||
38 | +} | ||
39 | + | ||
40 | +/** | ||
41 | + * `OAuth2Stragegy`를 상속 받는다. | ||
42 | + */ | ||
43 | +inherits(Strategy, OAuth2Strategy) | ||
44 | + | ||
45 | +/** | ||
46 | + * kakao 사용자 정보를 얻는다.<br/> | ||
47 | + * 사용자 정보를 성공적으로 조회하면 아래의 object가 done 콜백함수 호출과 함꼐 넘어간다. | ||
48 | + * | ||
49 | + * - `provider` kakao 고정 | ||
50 | + * - `id` kakao user id number | ||
51 | + * - `username` 사용자의 kakao nickname | ||
52 | + * - `_raw` json string 원문 | ||
53 | + * _ `_json` json 원 데이터 | ||
54 | + * | ||
55 | + * @param {String} accessToken | ||
56 | + * @param {Function} done | ||
57 | + */ | ||
58 | +Strategy.prototype.userProfile = function( | ||
59 | + accessToken: string, | ||
60 | + done: (error: Error, profile?: Profile) => void | ||
61 | +) { | ||
62 | + this._oauth2.get( | ||
63 | + this._userProfileURL, | ||
64 | + accessToken, | ||
65 | + (err: Error, body: string) => { | ||
66 | + if (err) { | ||
67 | + return done(err) | ||
68 | + } | ||
69 | + | ||
70 | + try { | ||
71 | + const json = JSON.parse(body) | ||
72 | + // 카카오톡이나 카카오스토리에 연동한 적이 없는 계정의 경우 | ||
73 | + // properties가 비어있다고 한다. 없을 경우의 처리 | ||
74 | + const properties = json.properties || { | ||
75 | + nickname: '미연동 계정', | ||
76 | + } | ||
77 | + const profile: Profile = { | ||
78 | + provider: 'kakao', | ||
79 | + id: json.id, | ||
80 | + username: properties.nickname, | ||
81 | + displayName: properties.nickname, | ||
82 | + _raw: body, | ||
83 | + _json: json, | ||
84 | + } | ||
85 | + return done(null, profile) | ||
86 | + } catch (e) { | ||
87 | + return done(e) | ||
88 | + } | ||
89 | + } | ||
90 | + ) | ||
91 | +} | ||
92 | + | ||
93 | +export default Strategy |
1 | +export interface StrategyOptions { | ||
2 | + authorizationURL?: string | ||
3 | + tokenURL?: string | ||
4 | + clientSecret?: string | ||
5 | + scopeSeparator?: string | ||
6 | + customHeaders?: { | ||
7 | + 'User-Agent'?: string | ||
8 | + } | ||
9 | + userAgent?: string | ||
10 | +} | ||
11 | + | ||
12 | +export interface Profile { | ||
13 | + provider: 'kakao' | ||
14 | + id?: string | number | ||
15 | + username?: string | ||
16 | + displayName?: string | ||
17 | + _raw: string | ||
18 | + _json: string | ||
19 | +} |
1 | +import { expect } from 'chai' | ||
2 | +import KakaoStrategy, { buildOptions } from '../src/Strategy' | ||
3 | + | ||
4 | +describe('passport-kakao', () => { | ||
5 | + it('passport-kakao 객체가 제대로 생성이 되어 있어야 한다.', () => { | ||
6 | + expect(KakaoStrategy).to.not.equals(null) | ||
7 | + }) | ||
8 | + it('Strategy option의 clientSecret 값이 없을 경우 default 값이 설정되어야 한다.', () => { | ||
9 | + const options = buildOptions({}) | ||
10 | + | ||
11 | + expect(options).to.not.equals(null) | ||
12 | + expect(options.clientSecret).to.be.equals('kakao') | ||
13 | + expect(options.scopeSeparator).to.be.equals(',') | ||
14 | + expect(options.customHeaders['User-Agent']).to.be.equals('passport-kakao') | ||
15 | + }) | ||
16 | + it('Strategy option의 User-Agent값이 있을 경우 customHeaders의 User-Agent가 해당 값으로 설정되어야 한다.', () => { | ||
17 | + const options = buildOptions({ | ||
18 | + customHeaders: { | ||
19 | + 'User-Agent': 'HELLO ROTO', | ||
20 | + }, | ||
21 | + }) | ||
22 | + expect(options.customHeaders['User-Agent']).to.be.equals('HELLO ROTO') | ||
23 | + }) | ||
24 | +}) |
node_modules/passport-kakao/tsconfig.json
0 → 100644
1 | +{ | ||
2 | + "include": ["./src"], | ||
3 | + "compilerOptions": { | ||
4 | + /* Basic Options */ | ||
5 | + // "incremental": true, /* Enable incremental compilation */ | ||
6 | + "target": "es5" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */, | ||
7 | + "module": "commonjs" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */, | ||
8 | + // "lib": [], /* Specify library files to be included in the compilation. */ | ||
9 | + // "allowJs": true, /* Allow javascript files to be compiled. */ | ||
10 | + // "checkJs": true, /* Report errors in .js files. */ | ||
11 | + // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */ | ||
12 | + // "declaration": true, /* Generates corresponding '.d.ts' file. */ | ||
13 | + // "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */ | ||
14 | + // "sourceMap": true, /* Generates corresponding '.map' file. */ | ||
15 | + // "outFile": "./", /* Concatenate and emit output to single file. */ | ||
16 | + "outDir": "./dist" /* Redirect output structure to the directory. */, | ||
17 | + "rootDir": "./src" /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */, | ||
18 | + // "composite": true, /* Enable project compilation */ | ||
19 | + // "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */ | ||
20 | + // "removeComments": true, /* Do not emit comments to output. */ | ||
21 | + // "noEmit": true, /* Do not emit outputs. */ | ||
22 | + // "importHelpers": true, /* Import emit helpers from 'tslib'. */ | ||
23 | + // "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */ | ||
24 | + // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */ | ||
25 | + | ||
26 | + /* Strict Type-Checking Options */ | ||
27 | + "strict": false /* Enable all strict type-checking options. */, | ||
28 | + // "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ | ||
29 | + // "strictNullChecks": true, /* Enable strict null checks. */ | ||
30 | + // "strictFunctionTypes": true, /* Enable strict checking of function types. */ | ||
31 | + // "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */ | ||
32 | + // "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */ | ||
33 | + // "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */ | ||
34 | + // "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */ | ||
35 | + | ||
36 | + /* Additional Checks */ | ||
37 | + // "noUnusedLocals": true, /* Report errors on unused locals. */ | ||
38 | + // "noUnusedParameters": true, /* Report errors on unused parameters. */ | ||
39 | + // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ | ||
40 | + // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ | ||
41 | + | ||
42 | + /* Module Resolution Options */ | ||
43 | + // "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ | ||
44 | + // "baseUrl": "./", /* Base directory to resolve non-absolute module names. */ | ||
45 | + // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ | ||
46 | + // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */ | ||
47 | + // "typeRoots": [], /* List of folders to include type definitions from. */ | ||
48 | + // "types": [], /* Type declaration files to be included in compilation. */ | ||
49 | + // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ | ||
50 | + "esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */ | ||
51 | + // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */ | ||
52 | + // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ | ||
53 | + | ||
54 | + /* Source Map Options */ | ||
55 | + // "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */ | ||
56 | + // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ | ||
57 | + // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */ | ||
58 | + // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */ | ||
59 | + | ||
60 | + /* Experimental Options */ | ||
61 | + // "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */ | ||
62 | + // "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */ | ||
63 | + } | ||
64 | +} |
node_modules/passport-kakao/tslint.json
0 → 100644
1 | +{ | ||
2 | + "defaultSeverity": "error", | ||
3 | + "extends": ["tslint:latest", "tslint-config-prettier"], | ||
4 | + "jsRules": {}, | ||
5 | + "rules": { | ||
6 | + "interface-name": false, | ||
7 | + "semicolon": [true, "never"], | ||
8 | + "member-access": [false], | ||
9 | + "ordered-imports": [false], | ||
10 | + "object-literal-sort-keys": [false], | ||
11 | + "no-console": [false], | ||
12 | + "quotemark": [true, "single", "jsx-double"], | ||
13 | + "jsx-no-lambda": [false], | ||
14 | + "no-submodule-imports": [false], | ||
15 | + "jsx-boolean-value": [false], | ||
16 | + "no-implicit-dependencies": [true, "dev"], | ||
17 | + "no-empty-interface": [false], | ||
18 | + "no-var-requires": [false] | ||
19 | + }, | ||
20 | + "rulesDirectory": [] | ||
21 | +} |
... | @@ -1180,6 +1180,32 @@ | ... | @@ -1180,6 +1180,32 @@ |
1180 | "passport-oauth2": "1.x.x" | 1180 | "passport-oauth2": "1.x.x" |
1181 | } | 1181 | } |
1182 | }, | 1182 | }, |
1183 | + "passport-kakao": { | ||
1184 | + "version": "1.0.0", | ||
1185 | + "resolved": "https://registry.npmjs.org/passport-kakao/-/passport-kakao-1.0.0.tgz", | ||
1186 | + "integrity": "sha512-rOR3+8g1bev/p9ChZLDKQan9oBmSSA2hmb7yQKdBOsjyF1mijx7fgR05pTWPz3g5r0kHZ2Y44sT2Ys6wJQq0xQ==", | ||
1187 | + "requires": { | ||
1188 | + "passport-oauth2": "~1.1.2", | ||
1189 | + "pkginfo": "~0.3.0" | ||
1190 | + }, | ||
1191 | + "dependencies": { | ||
1192 | + "passport-oauth2": { | ||
1193 | + "version": "1.1.2", | ||
1194 | + "resolved": "https://registry.npmjs.org/passport-oauth2/-/passport-oauth2-1.1.2.tgz", | ||
1195 | + "integrity": "sha1-vXFjsbYJA3GGjcTvb58uHkzEuUg=", | ||
1196 | + "requires": { | ||
1197 | + "oauth": "0.9.x", | ||
1198 | + "passport-strategy": "1.x.x", | ||
1199 | + "uid2": "0.0.x" | ||
1200 | + } | ||
1201 | + }, | ||
1202 | + "pkginfo": { | ||
1203 | + "version": "0.3.1", | ||
1204 | + "resolved": "https://registry.npmjs.org/pkginfo/-/pkginfo-0.3.1.tgz", | ||
1205 | + "integrity": "sha1-Wyn2qB9wcXFC4J52W76rl7T4HiE=" | ||
1206 | + } | ||
1207 | + } | ||
1208 | + }, | ||
1183 | "passport-oauth": { | 1209 | "passport-oauth": { |
1184 | "version": "0.1.15", | 1210 | "version": "0.1.15", |
1185 | "resolved": "https://registry.npmjs.org/passport-oauth/-/passport-oauth-0.1.15.tgz", | 1211 | "resolved": "https://registry.npmjs.org/passport-oauth/-/passport-oauth-0.1.15.tgz", | ... | ... |
... | @@ -25,6 +25,7 @@ | ... | @@ -25,6 +25,7 @@ |
25 | "needle": "^2.4.0", | 25 | "needle": "^2.4.0", |
26 | "passport": "^0.4.0", | 26 | "passport": "^0.4.0", |
27 | "passport-google-oauth": "^2.0.0", | 27 | "passport-google-oauth": "^2.0.0", |
28 | - "passport-google-oauth20": "^1.0.0" | 28 | + "passport-google-oauth20": "^1.0.0", |
29 | + "passport-kakao": "^1.0.0" | ||
29 | } | 30 | } |
30 | } | 31 | } | ... | ... |
1 | var express = require('express'); | 1 | var express = require('express'); |
2 | var router = express.Router(); | 2 | var router = express.Router(); |
3 | var gcal = require('google-calendar'); | 3 | var gcal = require('google-calendar'); |
4 | -var accessToken; | ||
5 | 4 | ||
6 | -var id; | ||
7 | var accessToken; | 5 | var accessToken; |
6 | +var id; | ||
7 | + | ||
8 | 8 | ||
9 | router.get('/', function(req, res, next) { | 9 | router.get('/', function(req, res, next) { |
10 | console.log(accessToken); | 10 | console.log(accessToken); |
... | @@ -88,7 +88,6 @@ var timestamp = function (date) { | ... | @@ -88,7 +88,6 @@ var timestamp = function (date) { |
88 | + ":" + pad(Math.abs(offset) % 60, 2); | 88 | + ":" + pad(Math.abs(offset) % 60, 2); |
89 | } | 89 | } |
90 | 90 | ||
91 | - | ||
92 | module.exports = router; | 91 | module.exports = router; |
93 | 92 | ||
94 | //timestamp(new Date(1983, 4, 9, 11, 5, 17)); | 93 | //timestamp(new Date(1983, 4, 9, 11, 5, 17)); |
... | \ No newline at end of file | ... | \ No newline at end of file | ... | ... |
... | @@ -4,14 +4,15 @@ const fs = require('fs'); | ... | @@ -4,14 +4,15 @@ const fs = require('fs'); |
4 | const readline = require('readline'); | 4 | const readline = require('readline'); |
5 | const {google} = require('googleapis'); | 5 | const {google} = require('googleapis'); |
6 | const bodyParser = require('body-parser'); | 6 | const bodyParser = require('body-parser'); |
7 | +const KakaoStrategy = require("passport-kakao").Strategy; | ||
7 | 8 | ||
8 | var passport = require('passport'); | 9 | var passport = require('passport'); |
9 | var GoogleStrategy = require('passport-google-oauth').OAuth2Strategy; | 10 | var GoogleStrategy = require('passport-google-oauth').OAuth2Strategy; |
10 | var gcal = require('google-calendar'); | 11 | var gcal = require('google-calendar'); |
11 | 12 | ||
12 | passport.use(new GoogleStrategy({ | 13 | passport.use(new GoogleStrategy({ |
13 | - clientID:'978869138601-u3euf0c04sbdor68r30m599gilvjn91e.apps.googleusercontent.com', | 14 | + clientID:CLIENTID, |
14 | - clientSecret:'N7Uh_oVQZt-almzA4DkM4bm_', | 15 | + clientSecret:CLIENTSECRET, |
15 | callbackURL:'http://localhost:3000/auth/google/callback', | 16 | callbackURL:'http://localhost:3000/auth/google/callback', |
16 | scope:['openid','email','https://www.googleapis.com/auth/calendar.readonly', | 17 | scope:['openid','email','https://www.googleapis.com/auth/calendar.readonly', |
17 | 'https://www.googleapis.com/auth/calendar', | 18 | 'https://www.googleapis.com/auth/calendar', |
... | @@ -30,6 +31,27 @@ router.get('/auth/google/callback',passport.authenticate('google',{ | ... | @@ -30,6 +31,27 @@ router.get('/auth/google/callback',passport.authenticate('google',{ |
30 | res.redirect('/calendar'); | 31 | res.redirect('/calendar'); |
31 | }); | 32 | }); |
32 | 33 | ||
34 | +const kakaoKey = { | ||
35 | + clientID: KAKAO_API_KEY, | ||
36 | + callbackURL: "/oauth/callback" | ||
37 | +}; | ||
38 | + | ||
39 | +passport.use( | ||
40 | + "kakao-login", | ||
41 | + new KakaoStrategy(kakaoKey, (accessToken, refreshToken, profile, done) => { | ||
42 | + console.log(profile); | ||
43 | + return done(null,profile); | ||
44 | + }) | ||
45 | +); | ||
46 | +router.get("/kakao", passport.authenticate("kakao-login")); | ||
47 | +router.get( | ||
48 | + "/oauth/callback", | ||
49 | + passport.authenticate("kakao-login",{failureRedirect:'/'}),function(req, res) { | ||
50 | + req.session.access_token = req.user.accessToken; | ||
51 | + res.redirect('/'); | ||
52 | + }); | ||
53 | + | ||
54 | + | ||
33 | calList = new Array(); | 55 | calList = new Array(); |
34 | Calendars = new Array(); | 56 | Calendars = new Array(); |
35 | 57 | ... | ... |
routes/login.js
0 → 100644
... | @@ -11,5 +11,7 @@ | ... | @@ -11,5 +11,7 @@ |
11 | <form action='/auth/google' method='GET'> | 11 | <form action='/auth/google' method='GET'> |
12 | <input type="submit" name='submit' value='로그인'/> | 12 | <input type="submit" name='submit' value='로그인'/> |
13 | </form> | 13 | </form> |
14 | + <form action='/kakao' method='GET'> | ||
15 | + <input type="submit" name='submit' value='로그인'/> | ||
14 | </body> | 16 | </body> |
15 | </html> | 17 | </html> |
... | \ No newline at end of file | ... | \ No newline at end of file | ... | ... |
-
Please register or login to post a comment