유희정

kakao login

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) {
......
1 +{
2 + "trailingComma": "es5",
3 + "semi": false,
4 + "singleQuote": true,
5 + "arrowParens": "avoid",
6 + "bracketSpacing": true,
7 + "endOfLine": "auto",
8 + "htmlWhitespaceSensitivity": "css",
9 + "proseWrap": "preserve",
10 + "quoteProps": "as-needed",
11 + "tabWidth": 2
12 +}
1 +language: node_js
2 +node_js:
3 + - '0.10'
4 +before_script:
5 + - npm install -g jasmine-node
6 +
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 모듈을 참고함.
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 +Object.defineProperty(exports, "__esModule", { value: true });
1 +"use strict";
2 +Object.defineProperty(exports, "__esModule", { value: true });
3 +describe('passport-kakao', function () {
4 + it('passport-kakao 객체가 제대로 생성이 되어 있어야 한다.', function () {
5 + var Strategy = require('../lib/passport-kakao');
6 + expect(Strategy).not.toBeNull();
7 + });
8 +});
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 +"use strict";
2 +Object.defineProperty(exports, "__esModule", { value: true });
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/)>
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;
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 +node_modules/
2 +npm-debug.log
...\ No newline at end of file ...\ No newline at end of file
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">&#182;</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">&#39;fs&#39;</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">&#39;path&#39;</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">&#182;</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">&#39;string&#39;</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">&#182;</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">&#182;</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">&#39;string&#39;</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">&#182;</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">&#182;</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">&gt;</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">&#182;</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">&gt;</span> <span class="mi">0</span> <span class="o">&amp;&amp;</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">&#182;</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">&#39;package.json&#39;</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">&#39;package.json&#39;</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">&#39;/&#39;</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">&#39;Could not find package.json up from: &#39;</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">&#182;</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">&#182;</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">&#39;version&#39;</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);
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 +}
1 +{
2 + "name": "passport-kakao-sample",
3 + "repository": {
4 + "type": "git",
5 + "url": "git://github.com/rotoshine/passport-kakao.git"
6 + },
7 + "dependencies": {
8 + "passport": ">= 0.0.0",
9 + "express": ">= 4.4.5"
10 + }
11 +}
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 +}
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 +import Strategy from './Strategy'
2 +
3 +export default Strategy
4 +
5 +export { 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 +})
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 +}
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
......
1 +var express = require('express');
2 +var router = express.Router();
3 +
4 +/* GET users listing. */
5 +router.get('/', function(req, res, next) {
6 + console.log("accepted");
7 +});
8 +
9 +module.exports = router;
...@@ -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
......