Showing
48 changed files
with
2718 additions
and
112 deletions
... | @@ -8,6 +8,7 @@ const fileStore = require('session-file-store')(session); | ... | @@ -8,6 +8,7 @@ const fileStore = require('session-file-store')(session); |
8 | const app = express(); | 8 | const app = express(); |
9 | var flash = require('connect-flash'); | 9 | var flash = require('connect-flash'); |
10 | var NaverStrategy = require('passport-naver').Strategy; | 10 | var NaverStrategy = require('passport-naver').Strategy; |
11 | +var KakaoStrategy = require('passport-kakao').Strategy; | ||
11 | 12 | ||
12 | 13 | ||
13 | 14 | ||
... | @@ -51,11 +52,12 @@ app.get('/main',(req,res)=>{ | ... | @@ -51,11 +52,12 @@ app.get('/main',(req,res)=>{ |
51 | }) | 52 | }) |
52 | 53 | ||
53 | 54 | ||
55 | +/*--------------------로그인 처리---------------------- */ | ||
56 | + | ||
54 | //로그인 페이지 | 57 | //로그인 페이지 |
55 | app.get('/login',(req,res)=>{ | 58 | app.get('/login',(req,res)=>{ |
56 | let page = getLoginButton(`<a href="/">뒤로가기</a>`); | 59 | let page = getLoginButton(`<a href="/">뒤로가기</a>`); |
57 | res.send(page); | 60 | res.send(page); |
58 | - | ||
59 | }); | 61 | }); |
60 | 62 | ||
61 | 63 | ||
... | @@ -96,25 +98,65 @@ passport.authenticate('local', { | ... | @@ -96,25 +98,65 @@ passport.authenticate('local', { |
96 | failureFlash: true | 98 | failureFlash: true |
97 | })); | 99 | })); |
98 | 100 | ||
101 | +//로그 아웃 처리 | ||
102 | +app.get('/logout',(req,res)=>{ | ||
103 | + | ||
104 | + //passport 정보 삭제 | ||
105 | + req.logout(); | ||
106 | + //서버측 세션 삭제 | ||
107 | + req.session.destroy(()=>{ | ||
108 | + //클라이언트 측 세션 암호화 쿠키 삭제 | ||
109 | + res.cookie('connect.sid','',{maxAge:0}); | ||
110 | + res.redirect('/'); | ||
111 | + }); | ||
112 | +}); | ||
113 | + | ||
114 | + | ||
115 | +//로그인 로그아웃 여부 | ||
116 | +const authInfo = (req)=>{ | ||
117 | + if(req.user) return `${user.name} | <a href="/logout">로그아웃</a>`; | ||
118 | + return `<a href="/login">로그인</a>`; | ||
119 | +} | ||
120 | + | ||
121 | +// naver 로그인 | ||
122 | +app.get('/naverlogin', passport.authenticate('naver')); | ||
123 | +passport.use('naver',new NaverStrategy({ | ||
124 | + clientID: 'CGVVomc0bhMhzfzbytK2', | ||
125 | + clientSecret: 'XHylcjnZxG', | ||
126 | + callbackURL: "http://localhost:3000/", | ||
127 | + svcType: 0, | ||
128 | + authType: 'reauthenticate' // enable re-authentication | ||
129 | + }, | ||
130 | + | ||
131 | + function(accessToken, refreshToken, profile, done) { | ||
132 | + var _profile = profile._json; | ||
133 | + console.log(_profile.id); | ||
134 | + console.log(_profile.properties.nickname); | ||
135 | + } | ||
136 | + )); | ||
137 | + | ||
138 | + | ||
139 | +// kakao 로그인 | ||
140 | +app.get('/kakaologin', passport.authenticate('kakao-login')); | ||
141 | +passport.use('kakao-login', new KakaoStrategy({ | ||
142 | + clientID: '8a854307a99092b4eeeff5e4a79c0ac0', | ||
143 | + callbackURL: 'http://localhost:3000/' | ||
144 | +}, | ||
145 | +function (accessToken, refreshToken, profile, done) { | ||
146 | + var _profile = profile._json; | ||
147 | + console.log(_profile.id); | ||
148 | + console.log(_profile.properties.nickname); | ||
149 | + | ||
150 | +} | ||
151 | +)); | ||
152 | + | ||
153 | + | ||
154 | +/*--------------------회원가입 처리---------------------- */ | ||
155 | + | ||
99 | 156 | ||
100 | //회원가입 페이지 Get | 157 | //회원가입 페이지 Get |
101 | app.get('/join',(req,res)=>{ | 158 | app.get('/join',(req,res)=>{ |
102 | -<<<<<<< HEAD | 159 | + let page = getPage('회원가입',` |
103 | - let page = getPage('회원가입',` | ||
104 | - <script> function congratulation() | ||
105 | - { | ||
106 | - alert("새로운 회원이 되신걸 축하합니다!:D 레시피 찾을 준비 되셨나요?"); | ||
107 | - } </script> | ||
108 | - <form action="/join" method="post"> | ||
109 | - <input type="email" name="email" placeholder="email"><br> | ||
110 | - <input type="password" name="password" placeholder="****"><br> | ||
111 | - <input type="name" name="name" placeholder="이름"><br> | ||
112 | - <input type="submit" value="회원가입" onClick="javascript:congratulation()"><br> | ||
113 | - </form> | ||
114 | - `,'<a href="/login">뒤로가기</a>'); | ||
115 | - res.send(page); | ||
116 | -======= | ||
117 | - let page = getPage('',` | ||
118 | <html> | 160 | <html> |
119 | <head> | 161 | <head> |
120 | <style> | 162 | <style> |
... | @@ -195,42 +237,14 @@ app.get('/join',(req,res)=>{ | ... | @@ -195,42 +237,14 @@ app.get('/join',(req,res)=>{ |
195 | </html> | 237 | </html> |
196 | `,'<a href="/login">뒤로가기</a>'); | 238 | `,'<a href="/login">뒤로가기</a>'); |
197 | res.send(page); | 239 | res.send(page); |
198 | ->>>>>>> 04a7922847fd162bc1b11e832ee65246c056146d | ||
199 | -}); | ||
200 | - | ||
201 | -//회원가입 처리 Post : 예제를 위해 간단 저장 방식으로 구현 | ||
202 | -var user = {}; | ||
203 | -app.post('/join',(req,res)=>{ | ||
204 | - user.email = req.body.email; | ||
205 | - user.password = req.body.password; | ||
206 | - user.name=req.body.name; | ||
207 | - //로그인 페이지로 이동 | ||
208 | - res.redirect('/login'); | ||
209 | }); | 240 | }); |
210 | 241 | ||
211 | -//로그 아웃 처리 | ||
212 | -app.get('/logout',(req,res)=>{ | ||
213 | - | ||
214 | - //passport 정보 삭제 | ||
215 | - req.logout(); | ||
216 | - //서버측 세션 삭제 | ||
217 | - req.session.destroy(()=>{ | ||
218 | - //클라이언트 측 세션 암호화 쿠키 삭제 | ||
219 | - res.cookie('connect.sid','',{maxAge:0}); | ||
220 | - res.redirect('/'); | ||
221 | - }); | ||
222 | -}); | ||
223 | 242 | ||
224 | 243 | ||
225 | //포트 연결 | 244 | //포트 연결 |
226 | app.listen(3000,()=>console.log(`http://localhost:3000`)); | 245 | app.listen(3000,()=>console.log(`http://localhost:3000`)); |
227 | 246 | ||
228 | 247 | ||
229 | -//로그인 로그아웃 여부 | ||
230 | -const authInfo = (req)=>{ | ||
231 | - if(req.user) return `${user.name} | <a href="/logout">로그아웃</a>`; | ||
232 | - return `<a href="/login">로그인</a>`; | ||
233 | -} | ||
234 | 248 | ||
235 | //페이지 템플릿 | 249 | //페이지 템플릿 |
236 | const getPage = (title, content, auth) =>{ | 250 | const getPage = (title, content, auth) =>{ |
... | @@ -341,22 +355,19 @@ const getLoginButton = (auth) =>{ | ... | @@ -341,22 +355,19 @@ const getLoginButton = (auth) =>{ |
341 | </div> | 355 | </div> |
342 | </div> | 356 | </div> |
343 | </div> | 357 | </div> |
344 | - <!-- 네이버 로그인 버튼 노출 영역 --> | 358 | + |
345 | - <div id="naver_id_login"></div> | 359 | + <div> |
346 | - <!-- //네이버 로그인 버튼 노출 영역 --> | 360 | + <a href="/naverlogin" class="btn btn-block btn-lg btn-success btn_login">Naver</a> |
347 | - <script type="text/javascript"> | 361 | + <a href="/kakaologin" class="btn btn-block btn-lg btn-warning btn_login">KaKao</a> |
348 | - var naver_id_login = new naver_id_login("CGVVomc0bhMhzfzbytK2", "http://localhost:3000/naverlogin"); | 362 | + </div> |
349 | - var state = naver_id_login.getUniqState(); | 363 | + |
350 | - naver_id_login.setButton("white", 2,40); | 364 | + |
351 | - naver_id_login.setState(state); | ||
352 | - naver_id_login.setPopup(); | ||
353 | - naver_id_login.init_naver_id_login(); | ||
354 | - </script> | ||
355 | </body> | 365 | </body> |
356 | </html> | 366 | </html> |
357 | `; | 367 | `; |
358 | } | 368 | } |
359 | 369 | ||
370 | + | ||
360 | //첫 페이지 화면 | 371 | //첫 페이지 화면 |
361 | const getFirstPage =(title, content, auth) =>{ | 372 | const getFirstPage =(title, content, auth) =>{ |
362 | return ` | 373 | return ` |
... | @@ -385,36 +396,3 @@ const getFirstPage =(title, content, auth) =>{ | ... | @@ -385,36 +396,3 @@ const getFirstPage =(title, content, auth) =>{ |
385 | 396 | ||
386 | } | 397 | } |
387 | 398 | ||
388 | - | ||
389 | -var client_id = 'CGVVomc0bhMhzfzbytK2'; | ||
390 | -var client_secret = 'XHylcjnZxG'; | ||
391 | -var state = "RAMDOM_STATE"; | ||
392 | -var redirectURI = encodeURI("http://localhost:3000/"); | ||
393 | -var api_url = ""; | ||
394 | - | ||
395 | - | ||
396 | -app.get('/naverlogin', function (req, res) { | ||
397 | - api_url = 'https://nid.naver.com/oauth2.0/authorize?response_type=code&client_id=' + client_id + '&redirect_uri=' + redirectURI + '&state=' + state; | ||
398 | - res.writeHead(200, {'Content-Type': 'text/html;charset=utf-8'}); | ||
399 | - res.end("<a href='"+ api_url + "'><img height='50' src='http://static.nid.naver.com/oauth/small_g_in.PNG'/></a>"); | ||
400 | - }); | ||
401 | - app.get('/callback', function (req, res) { | ||
402 | - code = req.query.code; | ||
403 | - state = req.query.state; | ||
404 | - api_url = 'https://nid.naver.com/oauth2.0/token?grant_type=authorization_code&client_id=' | ||
405 | - + client_id + '&client_secret=' + client_secret + '&redirect_uri=' + redirectURI + '&code=' + code + '&state=' + state; | ||
406 | - var request = require('request'); | ||
407 | - var options = { | ||
408 | - url: api_url, | ||
409 | - headers: {'X-Naver-Client-Id':client_id, 'X-Naver-Client-Secret': client_secret} | ||
410 | - }; | ||
411 | - request.get(options, function (error, response, body) { | ||
412 | - if (!error && response.statusCode == 200) { | ||
413 | - res.writeHead(200, {'Content-Type': 'text/json;charset=utf-8'}); | ||
414 | - res.end(body); | ||
415 | - } else { | ||
416 | - res.status(response.statusCode).end(); | ||
417 | - console.log('error = ' + response.statusCode); | ||
418 | - } | ||
419 | - }); | ||
420 | - }); | ||
... | \ No newline at end of file | ... | \ No newline at end of file | ... | ... |
naver_login/naverlogin.html
deleted
100644 → 0
1 | -<!doctype html> | ||
2 | -<html lang="ko"> | ||
3 | -<head> | ||
4 | - <meta charset="utf-8"> | ||
5 | - <title>네이버 로그인</title> | ||
6 | - <script type="text/javascript" src="https://static.nid.naver.com/js/naverLogin_implicit-1.0.3.js" charset="utf-8"></script> | ||
7 | - <script type="text/javascript" src="http://code.jquery.com/jquery-1.11.3.min.js"></script> | ||
8 | -</head> | ||
9 | -<body> | ||
10 | - <!-- 네이버 로그인 버튼 노출 영역 --> | ||
11 | - <div id="naver_id_login"></div> | ||
12 | - <!-- //네이버 로그인 버튼 노출 영역 --> | ||
13 | - <script type="text/javascript"> | ||
14 | - var naver_id_login = new naver_id_login("CGVVomc0bhMhzfzbytK2", "http://localhost:3000/"); | ||
15 | - var state = naver_id_login.getUniqState(); | ||
16 | - naver_id_login.setButton("white", 2,40); | ||
17 | - naver_id_login.setDomain("http://localhost:3000/"); | ||
18 | - naver_id_login.setState(state); | ||
19 | - naver_id_login.setPopup(); | ||
20 | - naver_id_login.init_naver_id_login(); | ||
21 | - </script> | ||
22 | -</html> | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
... | @@ -1713,6 +1713,28 @@ | ... | @@ -1713,6 +1713,28 @@ |
1713 | "node": ">= 0.4.0" | 1713 | "node": ">= 0.4.0" |
1714 | } | 1714 | } |
1715 | }, | 1715 | }, |
1716 | + "node_modules/passport-kakao": { | ||
1717 | + "version": "1.0.1", | ||
1718 | + "resolved": "https://registry.npmjs.org/passport-kakao/-/passport-kakao-1.0.1.tgz", | ||
1719 | + "integrity": "sha512-uItaYRVrTHL6iGPMnMZvPa/O1GrAdh/V6EMjOHcFlQcVroZ9wgG7BZ5PonMNJCxfHQ3L2QVNRnzhKWUzSsumbw==", | ||
1720 | + "dependencies": { | ||
1721 | + "passport-oauth2": "~1.1.2", | ||
1722 | + "pkginfo": "~0.3.0" | ||
1723 | + } | ||
1724 | + }, | ||
1725 | + "node_modules/passport-kakao/node_modules/passport-oauth2": { | ||
1726 | + "version": "1.1.2", | ||
1727 | + "resolved": "https://registry.npmjs.org/passport-oauth2/-/passport-oauth2-1.1.2.tgz", | ||
1728 | + "integrity": "sha1-vXFjsbYJA3GGjcTvb58uHkzEuUg=", | ||
1729 | + "dependencies": { | ||
1730 | + "oauth": "0.9.x", | ||
1731 | + "passport-strategy": "1.x.x", | ||
1732 | + "uid2": "0.0.x" | ||
1733 | + }, | ||
1734 | + "engines": { | ||
1735 | + "node": ">= 0.4.0" | ||
1736 | + } | ||
1737 | + }, | ||
1716 | "node_modules/passport-local": { | 1738 | "node_modules/passport-local": { |
1717 | "version": "1.0.0", | 1739 | "version": "1.0.0", |
1718 | "resolved": "https://registry.npmjs.org/passport-local/-/passport-local-1.0.0.tgz", | 1740 | "resolved": "https://registry.npmjs.org/passport-local/-/passport-local-1.0.0.tgz", |
... | @@ -1827,6 +1849,14 @@ | ... | @@ -1827,6 +1849,14 @@ |
1827 | "url": "https://github.com/sponsors/jonschlinkert" | 1849 | "url": "https://github.com/sponsors/jonschlinkert" |
1828 | } | 1850 | } |
1829 | }, | 1851 | }, |
1852 | + "node_modules/pkginfo": { | ||
1853 | + "version": "0.3.1", | ||
1854 | + "resolved": "https://registry.npmjs.org/pkginfo/-/pkginfo-0.3.1.tgz", | ||
1855 | + "integrity": "sha1-Wyn2qB9wcXFC4J52W76rl7T4HiE=", | ||
1856 | + "engines": { | ||
1857 | + "node": ">= 0.4.0" | ||
1858 | + } | ||
1859 | + }, | ||
1830 | "node_modules/prepend-http": { | 1860 | "node_modules/prepend-http": { |
1831 | "version": "2.0.0", | 1861 | "version": "2.0.0", |
1832 | "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", | 1862 | "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", | ... | ... |
node_modules/passport-kakao/.eslintrc.js
0 → 100644
1 | +module.exports = { | ||
2 | + env: { | ||
3 | + es6: true, | ||
4 | + }, | ||
5 | + extends: [ | ||
6 | + 'eslint:recommended', | ||
7 | + 'plugin:@typescript-eslint/eslint-recommended', | ||
8 | + 'plugin:@typescript-eslint/recommended', | ||
9 | + ], | ||
10 | + globals: { | ||
11 | + Atomics: 'readonly', | ||
12 | + SharedArrayBuffer: 'readonly', | ||
13 | + }, | ||
14 | + parser: '@typescript-eslint/parser', | ||
15 | + parserOptions: { | ||
16 | + ecmaFeatures: { | ||
17 | + jsx: true, | ||
18 | + }, | ||
19 | + ecmaVersion: 2018, | ||
20 | + sourceType: 'module', | ||
21 | + }, | ||
22 | + plugins: ['@typescript-eslint'], | ||
23 | + settings: { | ||
24 | + react: { | ||
25 | + version: 'detect', | ||
26 | + }, | ||
27 | + }, | ||
28 | + rules: { | ||
29 | + semi: ['warn', 'never'], | ||
30 | + 'sort-imports': ['off'], | ||
31 | + quotes: ['warn', 'single'], | ||
32 | + 'no-extra-boolean-cast': ['off'], | ||
33 | + '@typescript-eslint/member-delimiter-style': [ | ||
34 | + 'warn', | ||
35 | + { | ||
36 | + multiline: { | ||
37 | + delimiter: 'none', | ||
38 | + requireLast: false, | ||
39 | + }, | ||
40 | + singleline: { | ||
41 | + requireLast: false, | ||
42 | + }, | ||
43 | + }, | ||
44 | + ], | ||
45 | + '@typescript-eslint/no-empty-interface': ['off'], | ||
46 | + '@typescript-eslint/explicit-function-return-type': ['off'], | ||
47 | + '@typescript-eslint/no-explicit-any': ['off'], | ||
48 | + '@typescript-eslint/no-non-null-assertion': ['off'], | ||
49 | + '@typescript-eslint/interface-name-prefix': ['warn'], | ||
50 | + }, | ||
51 | +} |
node_modules/passport-kakao/.prettierrc
0 → 100644
node_modules/passport-kakao/.travis.yml
0 → 100644
node_modules/passport-kakao/README.md
0 → 100644
1 | +# passport-kakao | ||
2 | + | ||
3 | +kakao oauth2 로그인과 passport 모듈 연결체. | ||
4 | + | ||
5 | +## install | ||
6 | + | ||
7 | +```sh | ||
8 | +npm install passport-kakao | ||
9 | +``` | ||
10 | + | ||
11 | +## how to use | ||
12 | + | ||
13 | +- https://developers.kakao.com/ 에서 애플리케이션을 등록한다. | ||
14 | +- 방금 추가한 애플리케이션의 설정 - 사용자 관리에 들어가서 사용을 ON으로 한 뒤 저장한다. | ||
15 | +- 설정 - 일반에서, 플랫폼 추가를 누른 후 웹 플랫폼을 추가한다. | ||
16 | +- 웹 플랫폼 설정의 사이트 도메인에 자신의 사이트 도메인을 추가한다. (ex : http://localhost:3000) | ||
17 | +- 프로그램 상에서는 아래와 같이 사용한다. | ||
18 | + | ||
19 | +> clientSecret을 활성화 한 경우 해당 파라메터를 같이 넘겨줘야한다. | ||
20 | + | ||
21 | +```javascript | ||
22 | +const passport = require('passport') | ||
23 | +const KakaoStrategy = require('passport-kakao').Strategy | ||
24 | + | ||
25 | +passport.use(new KakaoStrategy({ | ||
26 | + clientID : clientID, | ||
27 | + clientSecret: clientSecret, // clientSecret을 사용하지 않는다면 넘기지 말거나 빈 스트링을 넘길 것 | ||
28 | + callbackURL : callbackURL | ||
29 | + }, | ||
30 | + (accessToken, refreshToken, profile, done) => { | ||
31 | + // 사용자의 정보는 profile에 들어있다. | ||
32 | + User.findOrCreate(..., (err, user) => { | ||
33 | + if (err) { return done(err) } | ||
34 | + return done(null, user) | ||
35 | + }) | ||
36 | + } | ||
37 | +)) | ||
38 | +``` | ||
39 | + | ||
40 | +> 기본 callbackPath는 `/oauth` 이고 https://developers.kakao.com 에서 수정할 수 있다. 하지만 callbackURL은 `사이트 도메인/oauth` 로 설정하는 것을 권장함. (ex : http://myhomepage.com:3000/oauth ) | ||
41 | + | ||
42 | +## | ||
43 | + | ||
44 | +## profile property | ||
45 | + | ||
46 | +profile에는 아래의 property들이 설정되어 넘겨진다. | ||
47 | + | ||
48 | +| key | value | 비고 | | ||
49 | +| -------- | ------ | ------------------------------------------ | | ||
50 | +| provider | String | kakao 고정 | | ||
51 | +| id | Number | 사용자의 kakao id | | ||
52 | +| \_raw | String | 사용자 정보 조회로 얻어진 json string | | ||
53 | +| \_json | Object | 사용자 정보 조회로 얻어진 json 원본 데이터 | | ||
54 | + | ||
55 | +## simple sample | ||
56 | + | ||
57 | +### 설치 & 실행 | ||
58 | + | ||
59 | +1. `./sample/sample.js` 의 `appKey` 를 https://developers.kakao.com 에서 발급받은 JS appKey 값으로 셋팅. | ||
60 | +2. command line 에서 아래의 커맨드 실행 | ||
61 | +3. 브라우져를 열고 `127.0.0.1:3000/login` 을 입력 후 이후 과정을 진행한다. | ||
62 | + | ||
63 | +``` | ||
64 | +cd ./sample | ||
65 | +npm install | ||
66 | +node app | ||
67 | +``` | ||
68 | + | ||
69 | +## mean.io 와 쉽게 연동하기 | ||
70 | + | ||
71 | +수정해야하는 파일들은 아래와 같다. | ||
72 | + | ||
73 | +| file path | 설명 | | ||
74 | +| -------------------------------- | ------------------------------ | | ||
75 | +| server/config/env/development.js | 개발환경 설정파일 | | ||
76 | +| server/config/env/production.js | 운영환경 설정파일 | | ||
77 | +| server/config/models/user.js | 사용자 모델 | | ||
78 | +| server/config/passport.js | passport script | | ||
79 | +| server/routes/users.js | 사용자 로그인 관련 routes file | | ||
80 | +| public/auth/views/index.html | 로그인 화면 | | ||
81 | + | ||
82 | +(1) **mean.io app을 생성** 한다. (ex : mean init kakaoTest) | ||
83 | + | ||
84 | +(2) 해당 모듈을 연동할 mean.io app에 설치한다.(npm install passport-kakao --save) | ||
85 | + | ||
86 | +(3) **server/config/env/development.js** 와 **production.js** 에 kakao 관련 설정을 아래와 같이 추가한다. | ||
87 | + | ||
88 | +```javascript | ||
89 | +'use strict' | ||
90 | + | ||
91 | +module.exports = { | ||
92 | + db: 'mongodb', | ||
93 | + app: { | ||
94 | + name: 'passport-kakao', | ||
95 | + }, | ||
96 | + // 그외 설정들...., | ||
97 | + kakao: { | ||
98 | + clientID: 'kakao app rest api key', | ||
99 | + callbackURL: 'http://localhost:3000/oauth', | ||
100 | + }, | ||
101 | +} | ||
102 | +``` | ||
103 | + | ||
104 | +(4) **server/config/models/users.js** 의 사용자 스키마 정의에 **kakao: {}** 를 추가한다. | ||
105 | + | ||
106 | +(5) **server/config/passport.js** 파일에 아래 구문을 추가한다. | ||
107 | + | ||
108 | +```javascript | ||
109 | +// 최상단 require되는 구문에 추가 | ||
110 | +var KakaoStrategy = require('passport-kakao').Strategy | ||
111 | + | ||
112 | +passport.use( | ||
113 | + new KakaoStrategy( | ||
114 | + { | ||
115 | + clientID: config.kakao.clientID, | ||
116 | + callbackURL: config.kakao.callbackURL, | ||
117 | + }, | ||
118 | + function(accessToken, refreshToken, profile, done) { | ||
119 | + User.findOne( | ||
120 | + { | ||
121 | + 'kakao.id': profile.id, | ||
122 | + }, | ||
123 | + function(err, user) { | ||
124 | + if (err) { | ||
125 | + return done(err) | ||
126 | + } | ||
127 | + if (!user) { | ||
128 | + user = new User({ | ||
129 | + name: profile.username, | ||
130 | + username: profile.id, | ||
131 | + roles: ['authenticated'], | ||
132 | + provider: 'kakao', | ||
133 | + kakao: profile._json, | ||
134 | + }) | ||
135 | + | ||
136 | + user.save(function(err) { | ||
137 | + if (err) { | ||
138 | + console.log(err) | ||
139 | + } | ||
140 | + return done(err, user) | ||
141 | + }) | ||
142 | + } else { | ||
143 | + return done(err, user) | ||
144 | + } | ||
145 | + } | ||
146 | + ) | ||
147 | + } | ||
148 | + ) | ||
149 | +) | ||
150 | +``` | ||
151 | + | ||
152 | +(6) **server/routes/users.js** 에 아래와 같은 구문을 추가한다. | ||
153 | + | ||
154 | +```javascript | ||
155 | +app.get( | ||
156 | + '/auth/kakao', | ||
157 | + passport.authenticate('kakao', { | ||
158 | + failureRedirect: '#!/login', | ||
159 | + }), | ||
160 | + users.signin | ||
161 | +) | ||
162 | + | ||
163 | +app.get( | ||
164 | + '/oauth', | ||
165 | + passport.authenticate('kakao', { | ||
166 | + failureRedirect: '#!/login', | ||
167 | + }), | ||
168 | + users.authCallback | ||
169 | +) | ||
170 | +``` | ||
171 | + | ||
172 | +(7) **public/auth/views/index.html** 에 kakao login을 연결한다. | ||
173 | + | ||
174 | +```html | ||
175 | +<!-- 아래는 예시 --> | ||
176 | +<div> | ||
177 | + <div class="row"> | ||
178 | + <div class="col-md-offset-1 col-md-5"> | ||
179 | + <a href="/auth/facebook"> | ||
180 | + <img src="/public/auth/assets/img/icons/facebook.png" /> | ||
181 | + </a> | ||
182 | + <a href="/auth/twitter"> | ||
183 | + <img src="/public/auth/assets/img/icons/twitter.png" /> | ||
184 | + </a> | ||
185 | + | ||
186 | + <!-- kakao login --> | ||
187 | + <a href="/auth/kakao"> | ||
188 | + <img | ||
189 | + src="https://developers.kakao.com/assets/img/about/logos/kakaolink/kakaolink_btn_medium.png" | ||
190 | + /> | ||
191 | + </a> | ||
192 | + </div> | ||
193 | + </div> | ||
194 | + <div class="col-md-6"> | ||
195 | + <div ui-view></div> | ||
196 | + </div> | ||
197 | +</div> | ||
198 | +``` | ||
199 | + | ||
200 | +(8) grunt로 mean.io app 실행 후, 실제 로그인 연동 테스트를 해본다. | ||
201 | + | ||
202 | +## 기타 | ||
203 | + | ||
204 | +passport-oauth 모듈과 passport-facebook 모듈을 참고함. |
node_modules/passport-kakao/dist/Strategy.js
0 → 100644
1 | +"use strict"; | ||
2 | +var __importDefault = (this && this.__importDefault) || function (mod) { | ||
3 | + return (mod && mod.__esModule) ? mod : { "default": mod }; | ||
4 | +}; | ||
5 | +Object.defineProperty(exports, "__esModule", { value: true }); | ||
6 | +var util_1 = require("util"); | ||
7 | +var passport_oauth2_1 = __importDefault(require("passport-oauth2")); | ||
8 | +var DEFAULT_CLIENT_SECRET = 'kakao'; | ||
9 | +var OAUTH_HOST = 'https://kauth.kakao.com'; | ||
10 | +var USER_PROFILE_URL = 'https://kapi.kakao.com/v2/user/me'; | ||
11 | +exports.buildOptions = function (options) { | ||
12 | + options.authorizationURL = OAUTH_HOST + "/oauth/authorize"; | ||
13 | + options.tokenURL = OAUTH_HOST + "/oauth/token"; | ||
14 | + if (!options.clientSecret) { | ||
15 | + options.clientSecret = DEFAULT_CLIENT_SECRET; | ||
16 | + } | ||
17 | + options.scopeSeparator = options.scopeSeparator || ','; | ||
18 | + options.customHeaders = options.customHeaders || {}; | ||
19 | + if (!options.customHeaders['User-Agent']) { | ||
20 | + options.customHeaders['User-Agent'] = options.userAgent || 'passport-kakao'; | ||
21 | + } | ||
22 | + return options; | ||
23 | +}; | ||
24 | +/** | ||
25 | + * KaKaoStrategy 생성자 함수.<br/> | ||
26 | + * @param options.clientID 필수. kakao rest app key. | ||
27 | + * @param options.callbackURL 필수. 로그인 처리 후 호출할 URL | ||
28 | + * @param verify | ||
29 | + * @constructor | ||
30 | + */ | ||
31 | +function Strategy(options, verify) { | ||
32 | + if (options === void 0) { options = {}; } | ||
33 | + passport_oauth2_1.default.call(this, exports.buildOptions(options), verify); | ||
34 | + this.name = 'kakao'; | ||
35 | + this._userProfileURL = USER_PROFILE_URL; | ||
36 | +} | ||
37 | +/** | ||
38 | + * `OAuth2Stragegy`를 상속 받는다. | ||
39 | + */ | ||
40 | +util_1.inherits(Strategy, passport_oauth2_1.default); | ||
41 | +/** | ||
42 | + * kakao 사용자 정보를 얻는다.<br/> | ||
43 | + * 사용자 정보를 성공적으로 조회하면 아래의 object가 done 콜백함수 호출과 함꼐 넘어간다. | ||
44 | + * | ||
45 | + * - `provider` kakao 고정 | ||
46 | + * - `id` kakao user id number | ||
47 | + * - `username` 사용자의 kakao nickname | ||
48 | + * - `_raw` json string 원문 | ||
49 | + * _ `_json` json 원 데이터 | ||
50 | + * | ||
51 | + * @param {String} accessToken | ||
52 | + * @param {Function} done | ||
53 | + */ | ||
54 | +Strategy.prototype.userProfile = function (accessToken, done) { | ||
55 | + this._oauth2.get(this._userProfileURL, accessToken, function (err, body) { | ||
56 | + if (err) { | ||
57 | + return done(err); | ||
58 | + } | ||
59 | + try { | ||
60 | + var json = JSON.parse(body); | ||
61 | + // 카카오톡이나 카카오스토리에 연동한 적이 없는 계정의 경우 | ||
62 | + // properties가 비어있다고 한다. 없을 경우의 처리 | ||
63 | + var properties = json.properties || { | ||
64 | + nickname: '미연동 계정', | ||
65 | + }; | ||
66 | + var profile = { | ||
67 | + provider: 'kakao', | ||
68 | + id: json.id, | ||
69 | + username: properties.nickname, | ||
70 | + displayName: properties.nickname, | ||
71 | + _raw: body, | ||
72 | + _json: json, | ||
73 | + }; | ||
74 | + return done(null, profile); | ||
75 | + } | ||
76 | + catch (e) { | ||
77 | + return done(e); | ||
78 | + } | ||
79 | + }); | ||
80 | +}; | ||
81 | +exports.default = Strategy; |
1 | +"use strict"; | ||
2 | +var __importDefault = (this && this.__importDefault) || function (mod) { | ||
3 | + return (mod && mod.__esModule) ? mod : { "default": mod }; | ||
4 | +}; | ||
5 | +Object.defineProperty(exports, "__esModule", { value: true }); | ||
6 | +var Strategy_1 = __importDefault(require("./Strategy")); | ||
7 | +exports.Strategy = Strategy_1.default; | ||
8 | +exports.default = Strategy_1.default; |
1 | +(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 | +[](https://travis-ci.org/jaredhanson/passport-oauth2) | ||
4 | +[](https://coveralls.io/r/jaredhanson/passport-oauth2) | ||
5 | +[](https://codeclimate.com/github/jaredhanson/passport-oauth2) | ||
6 | +[](https://david-dm.org/jaredhanson/passport-oauth2) | ||
7 | +[](https://www.gittip.com/jaredhanson/) | ||
8 | + | ||
9 | +General-purpose OAuth 2.0 authentication strategy for [Passport](http://passportjs.org/). | ||
10 | + | ||
11 | +This module lets you authenticate using OAuth 2.0 in your Node.js applications. | ||
12 | +By plugging into Passport, OAuth 2.0 authentication can be easily and | ||
13 | +unobtrusively integrated into any application or framework that supports | ||
14 | +[Connect](http://www.senchalabs.org/connect/)-style middleware, including | ||
15 | +[Express](http://expressjs.com/). | ||
16 | + | ||
17 | +Note that this strategy provides generic OAuth 2.0 support. In many cases, a | ||
18 | +provider-specific strategy can be used instead, which cuts down on unnecessary | ||
19 | +configuration, and accommodates any provider-specific quirks. See the | ||
20 | +[list](https://github.com/jaredhanson/passport/wiki/Strategies) for supported | ||
21 | +providers. | ||
22 | + | ||
23 | +Developers who need to implement authentication against an OAuth 2.0 provider | ||
24 | +that is not already supported are encouraged to sub-class this strategy. If you | ||
25 | +choose to open source the new provider-specific strategy, please add it to the | ||
26 | +list so other people can find it. | ||
27 | + | ||
28 | +## Install | ||
29 | + | ||
30 | + $ npm install passport-oauth2 | ||
31 | + | ||
32 | +## Usage | ||
33 | + | ||
34 | +#### Configure Strategy | ||
35 | + | ||
36 | +The OAuth 2.0 authentication strategy authenticates users using a third-party | ||
37 | +account and OAuth 2.0 tokens. The provider's OAuth 2.0 endpoints, as well as | ||
38 | +the client identifer and secret, are specified as options. The strategy | ||
39 | +requires a `verify` callback, which receives an access token and profile, | ||
40 | +and calls `done` providing a user. | ||
41 | + | ||
42 | + passport.use(new OAuth2Strategy({ | ||
43 | + authorizationURL: 'https://www.example.com/oauth2/authorize', | ||
44 | + tokenURL: 'https://www.example.com/oauth2/token', | ||
45 | + clientID: EXAMPLE_CLIENT_ID, | ||
46 | + clientSecret: EXAMPLE_CLIENT_SECRET, | ||
47 | + callbackURL: "http://localhost:3000/auth/example/callback" | ||
48 | + }, | ||
49 | + function(accessToken, refreshToken, profile, done) { | ||
50 | + User.findOrCreate({ exampleId: profile.id }, function (err, user) { | ||
51 | + return done(err, user); | ||
52 | + }); | ||
53 | + } | ||
54 | + )); | ||
55 | + | ||
56 | +#### Authenticate Requests | ||
57 | + | ||
58 | +Use `passport.authenticate()`, specifying the `'oauth2'` strategy, to | ||
59 | +authenticate requests. | ||
60 | + | ||
61 | +For example, as route middleware in an [Express](http://expressjs.com/) | ||
62 | +application: | ||
63 | + | ||
64 | + app.get('/auth/example', | ||
65 | + passport.authenticate('oauth2')); | ||
66 | + | ||
67 | + app.get('/auth/example/callback', | ||
68 | + passport.authenticate('oauth2', { failureRedirect: '/login' }), | ||
69 | + function(req, res) { | ||
70 | + // Successful authentication, redirect home. | ||
71 | + res.redirect('/'); | ||
72 | + }); | ||
73 | + | ||
74 | +## Related Modules | ||
75 | + | ||
76 | +- [passport-oauth1](https://github.com/jaredhanson/passport-oauth1) — OAuth 1.0 authentication strategy | ||
77 | +- [passport-http-bearer](https://github.com/jaredhanson/passport-http-bearer) — Bearer token authentication strategy for APIs | ||
78 | +- [OAuth2orize](https://github.com/jaredhanson/oauth2orize) — OAuth 2.0 authorization server toolkit | ||
79 | + | ||
80 | +## Tests | ||
81 | + | ||
82 | + $ npm install | ||
83 | + $ npm test | ||
84 | + | ||
85 | +## Credits | ||
86 | + | ||
87 | + - [Jared Hanson](http://github.com/jaredhanson) | ||
88 | + | ||
89 | +## License | ||
90 | + | ||
91 | +[The MIT License](http://opensource.org/licenses/MIT) | ||
92 | + | ||
93 | +Copyright (c) 2011-2014 Jared Hanson <[http://jaredhanson.net/](http://jaredhanson.net/)> |
node_modules/passport-kakao/node_modules/passport-oauth2/lib/errors/authorizationerror.js
0 → 100644
1 | +/** | ||
2 | + * `AuthorizationError` error. | ||
3 | + * | ||
4 | + * AuthorizationError represents an error in response to an authorization | ||
5 | + * request. For details, refer to RFC 6749, section 4.1.2.1. | ||
6 | + * | ||
7 | + * References: | ||
8 | + * - [The OAuth 2.0 Authorization Framework](http://tools.ietf.org/html/rfc6749) | ||
9 | + * | ||
10 | + * @constructor | ||
11 | + * @param {String} [message] | ||
12 | + * @param {String} [code] | ||
13 | + * @param {String} [uri] | ||
14 | + * @param {Number} [status] | ||
15 | + * @api public | ||
16 | + */ | ||
17 | +function AuthorizationError(message, code, uri, status) { | ||
18 | + if (!status) { | ||
19 | + switch (code) { | ||
20 | + case 'access_denied': status = 403; break; | ||
21 | + case 'server_error': status = 502; break; | ||
22 | + case 'temporarily_unavailable': status = 503; break; | ||
23 | + } | ||
24 | + } | ||
25 | + | ||
26 | + Error.call(this); | ||
27 | + Error.captureStackTrace(this, arguments.callee); | ||
28 | + this.name = 'AuthorizationError'; | ||
29 | + this.message = message; | ||
30 | + this.code = code || 'server_error'; | ||
31 | + this.uri = uri; | ||
32 | + this.status = status || 500; | ||
33 | +} | ||
34 | + | ||
35 | +/** | ||
36 | + * Inherit from `Error`. | ||
37 | + */ | ||
38 | +AuthorizationError.prototype.__proto__ = Error.prototype; | ||
39 | + | ||
40 | + | ||
41 | +/** | ||
42 | + * Expose `AuthorizationError`. | ||
43 | + */ | ||
44 | +module.exports = AuthorizationError; |
node_modules/passport-kakao/node_modules/passport-oauth2/lib/errors/internaloautherror.js
0 → 100644
1 | +/** | ||
2 | + * `InternalOAuthError` error. | ||
3 | + * | ||
4 | + * InternalOAuthError wraps errors generated by node-oauth. By wrapping these | ||
5 | + * objects, error messages can be formatted in a manner that aids in debugging | ||
6 | + * OAuth issues. | ||
7 | + * | ||
8 | + * @constructor | ||
9 | + * @param {String} [message] | ||
10 | + * @param {Object|Error} [err] | ||
11 | + * @api public | ||
12 | + */ | ||
13 | +function InternalOAuthError(message, err) { | ||
14 | + Error.call(this); | ||
15 | + Error.captureStackTrace(this, arguments.callee); | ||
16 | + this.name = 'InternalOAuthError'; | ||
17 | + this.message = message; | ||
18 | + this.oauthError = err; | ||
19 | +} | ||
20 | + | ||
21 | +/** | ||
22 | + * Inherit from `Error`. | ||
23 | + */ | ||
24 | +InternalOAuthError.prototype.__proto__ = Error.prototype; | ||
25 | + | ||
26 | +/** | ||
27 | + * Returns a string representing the error. | ||
28 | + * | ||
29 | + * @return {String} | ||
30 | + * @api public | ||
31 | + */ | ||
32 | +InternalOAuthError.prototype.toString = function() { | ||
33 | + var m = this.name; | ||
34 | + if (this.message) { m += ': ' + this.message; } | ||
35 | + if (this.oauthError) { | ||
36 | + if (this.oauthError instanceof Error) { | ||
37 | + m = this.oauthError.toString(); | ||
38 | + } else if (this.oauthError.statusCode && this.oauthError.data) { | ||
39 | + m += ' (status: ' + this.oauthError.statusCode + ' data: ' + this.oauthError.data + ')'; | ||
40 | + } | ||
41 | + } | ||
42 | + return m; | ||
43 | +}; | ||
44 | + | ||
45 | + | ||
46 | +/** | ||
47 | + * Expose `InternalOAuthError`. | ||
48 | + */ | ||
49 | +module.exports = InternalOAuthError; |
1 | +/** | ||
2 | + * `TokenError` error. | ||
3 | + * | ||
4 | + * TokenError represents an error received from a token endpoint. For details, | ||
5 | + * refer to RFC 6749, section 5.2. | ||
6 | + * | ||
7 | + * References: | ||
8 | + * - [The OAuth 2.0 Authorization Framework](http://tools.ietf.org/html/rfc6749) | ||
9 | + * | ||
10 | + * @constructor | ||
11 | + * @param {String} [message] | ||
12 | + * @param {String} [code] | ||
13 | + * @param {String} [uri] | ||
14 | + * @param {Number} [status] | ||
15 | + * @api public | ||
16 | + */ | ||
17 | +function TokenError(message, code, uri, status) { | ||
18 | + Error.call(this); | ||
19 | + Error.captureStackTrace(this, arguments.callee); | ||
20 | + this.name = 'TokenError'; | ||
21 | + this.message = message; | ||
22 | + this.code = code || 'invalid_request'; | ||
23 | + this.uri = uri; | ||
24 | + this.status = status || 500; | ||
25 | +} | ||
26 | + | ||
27 | +/** | ||
28 | + * Inherit from `Error`. | ||
29 | + */ | ||
30 | +TokenError.prototype.__proto__ = Error.prototype; | ||
31 | + | ||
32 | + | ||
33 | +/** | ||
34 | + * Expose `TokenError`. | ||
35 | + */ | ||
36 | +module.exports = TokenError; |
1 | +/** | ||
2 | + * Module dependencies. | ||
3 | + */ | ||
4 | +var Strategy = require('./strategy') | ||
5 | + , AuthorizationError = require('./errors/authorizationerror') | ||
6 | + , TokenError = require('./errors/tokenerror') | ||
7 | + , InternalOAuthError = require('./errors/internaloautherror'); | ||
8 | + | ||
9 | + | ||
10 | +/** | ||
11 | + * Expose `Strategy` directly from package. | ||
12 | + */ | ||
13 | +exports = module.exports = Strategy; | ||
14 | + | ||
15 | +/** | ||
16 | + * Export constructors. | ||
17 | + */ | ||
18 | +exports.Strategy = Strategy; | ||
19 | + | ||
20 | +/** | ||
21 | + * Export errors. | ||
22 | + */ | ||
23 | +exports.AuthorizationError = AuthorizationError; | ||
24 | +exports.TokenError = TokenError; | ||
25 | +exports.InternalOAuthError = InternalOAuthError; |
1 | +/** | ||
2 | + * Module dependencies. | ||
3 | + */ | ||
4 | +var passport = require('passport-strategy') | ||
5 | + , url = require('url') | ||
6 | + , uid = require('uid2') | ||
7 | + , util = require('util') | ||
8 | + , utils = require('./utils') | ||
9 | + , OAuth2 = require('oauth').OAuth2 | ||
10 | + , AuthorizationError = require('./errors/authorizationerror') | ||
11 | + , TokenError = require('./errors/tokenerror') | ||
12 | + , InternalOAuthError = require('./errors/internaloautherror'); | ||
13 | + | ||
14 | + | ||
15 | +/** | ||
16 | + * Creates an instance of `OAuth2Strategy`. | ||
17 | + * | ||
18 | + * The OAuth 2.0 authentication strategy authenticates requests using the OAuth | ||
19 | + * 2.0 framework. | ||
20 | + * | ||
21 | + * OAuth 2.0 provides a facility for delegated authentication, whereby users can | ||
22 | + * authenticate using a third-party service such as Facebook. Delegating in | ||
23 | + * this manner involves a sequence of events, including redirecting the user to | ||
24 | + * the third-party service for authorization. Once authorization has been | ||
25 | + * granted, the user is redirected back to the application and an authorization | ||
26 | + * code can be used to obtain credentials. | ||
27 | + * | ||
28 | + * Applications must supply a `verify` callback, for which the function | ||
29 | + * signature is: | ||
30 | + * | ||
31 | + * function(accessToken, refreshToken, profile, done) { ... } | ||
32 | + * | ||
33 | + * The verify callback is responsible for finding or creating the user, and | ||
34 | + * invoking `done` with the following arguments: | ||
35 | + * | ||
36 | + * done(err, user, info); | ||
37 | + * | ||
38 | + * `user` should be set to `false` to indicate an authentication failure. | ||
39 | + * Additional `info` can optionally be passed as a third argument, typically | ||
40 | + * used to display informational messages. If an exception occured, `err` | ||
41 | + * should be set. | ||
42 | + * | ||
43 | + * Options: | ||
44 | + * | ||
45 | + * - `authorizationURL` URL used to obtain an authorization grant | ||
46 | + * - `tokenURL` URL used to obtain an access token | ||
47 | + * - `clientID` identifies client to service provider | ||
48 | + * - `clientSecret` secret used to establish ownership of the client identifer | ||
49 | + * - `callbackURL` URL to which the service provider will redirect the user after obtaining authorization | ||
50 | + * - `passReqToCallback` when `true`, `req` is the first argument to the verify callback (default: `false`) | ||
51 | + * | ||
52 | + * Examples: | ||
53 | + * | ||
54 | + * passport.use(new OAuth2Strategy({ | ||
55 | + * authorizationURL: 'https://www.example.com/oauth2/authorize', | ||
56 | + * tokenURL: 'https://www.example.com/oauth2/token', | ||
57 | + * clientID: '123-456-789', | ||
58 | + * clientSecret: 'shhh-its-a-secret' | ||
59 | + * callbackURL: 'https://www.example.net/auth/example/callback' | ||
60 | + * }, | ||
61 | + * function(accessToken, refreshToken, profile, done) { | ||
62 | + * User.findOrCreate(..., function (err, user) { | ||
63 | + * done(err, user); | ||
64 | + * }); | ||
65 | + * } | ||
66 | + * )); | ||
67 | + * | ||
68 | + * @constructor | ||
69 | + * @param {Object} options | ||
70 | + * @param {Function} verify | ||
71 | + * @api public | ||
72 | + */ | ||
73 | +function OAuth2Strategy(options, verify) { | ||
74 | + if (typeof options == 'function') { | ||
75 | + verify = options; | ||
76 | + options = undefined; | ||
77 | + } | ||
78 | + options = options || {}; | ||
79 | + | ||
80 | + if (!verify) { throw new TypeError('OAuth2Strategy requires a verify callback'); } | ||
81 | + if (!options.authorizationURL) { throw new TypeError('OAuth2Strategy requires a authorizationURL option'); } | ||
82 | + if (!options.tokenURL) { throw new TypeError('OAuth2Strategy requires a tokenURL option'); } | ||
83 | + if (!options.clientID) { throw new TypeError('OAuth2Strategy requires a clientID option'); } | ||
84 | + if (!options.clientSecret) { throw new TypeError('OAuth2Strategy requires a clientSecret option'); } | ||
85 | + | ||
86 | + passport.Strategy.call(this); | ||
87 | + this.name = 'oauth2'; | ||
88 | + this._verify = verify; | ||
89 | + | ||
90 | + // NOTE: The _oauth2 property is considered "protected". Subclasses are | ||
91 | + // allowed to use it when making protected resource requests to retrieve | ||
92 | + // the user profile. | ||
93 | + this._oauth2 = new OAuth2(options.clientID, options.clientSecret, | ||
94 | + '', options.authorizationURL, options.tokenURL, options.customHeaders); | ||
95 | + | ||
96 | + this._callbackURL = options.callbackURL; | ||
97 | + this._scope = options.scope; | ||
98 | + this._scopeSeparator = options.scopeSeparator || ' '; | ||
99 | + this._state = options.state; | ||
100 | + this._key = options.sessionKey || ('oauth2:' + url.parse(options.authorizationURL).hostname); | ||
101 | + this._trustProxy = options.proxy; | ||
102 | + this._passReqToCallback = options.passReqToCallback; | ||
103 | + this._skipUserProfile = (options.skipUserProfile === undefined) ? false : options.skipUserProfile; | ||
104 | +} | ||
105 | + | ||
106 | +/** | ||
107 | + * Inherit from `passport.Strategy`. | ||
108 | + */ | ||
109 | +util.inherits(OAuth2Strategy, passport.Strategy); | ||
110 | + | ||
111 | + | ||
112 | +/** | ||
113 | + * Authenticate request by delegating to a service provider using OAuth 2.0. | ||
114 | + * | ||
115 | + * @param {Object} req | ||
116 | + * @api protected | ||
117 | + */ | ||
118 | +OAuth2Strategy.prototype.authenticate = function(req, options) { | ||
119 | + options = options || {}; | ||
120 | + var self = this; | ||
121 | + | ||
122 | + if (req.query && req.query.error) { | ||
123 | + if (req.query.error == 'access_denied') { | ||
124 | + return this.fail({ message: req.query.error_description }); | ||
125 | + } else { | ||
126 | + return this.error(new AuthorizationError(req.query.error_description, req.query.error, req.query.error_uri)); | ||
127 | + } | ||
128 | + } | ||
129 | + | ||
130 | + var callbackURL = options.callbackURL || this._callbackURL; | ||
131 | + if (callbackURL) { | ||
132 | + var parsed = url.parse(callbackURL); | ||
133 | + if (!parsed.protocol) { | ||
134 | + // The callback URL is relative, resolve a fully qualified URL from the | ||
135 | + // URL of the originating request. | ||
136 | + callbackURL = url.resolve(utils.originalURL(req, { proxy: this._trustProxy }), callbackURL); | ||
137 | + } | ||
138 | + } | ||
139 | + | ||
140 | + if (req.query && req.query.code) { | ||
141 | + var code = req.query.code; | ||
142 | + | ||
143 | + if (this._state) { | ||
144 | + if (!req.session) { return this.error(new Error('OAuth2Strategy requires session support when using state. Did you forget app.use(express.session(...))?')); } | ||
145 | + | ||
146 | + var key = this._key; | ||
147 | + if (!req.session[key]) { | ||
148 | + return this.fail({ message: 'Unable to verify authorization request state.' }, 403); | ||
149 | + } | ||
150 | + var state = req.session[key].state; | ||
151 | + if (!state) { | ||
152 | + return this.fail({ message: 'Unable to verify authorization request state.' }, 403); | ||
153 | + } | ||
154 | + | ||
155 | + delete req.session[key].state; | ||
156 | + if (Object.keys(req.session[key]).length === 0) { | ||
157 | + delete req.session[key]; | ||
158 | + } | ||
159 | + | ||
160 | + if (state !== req.query.state) { | ||
161 | + return this.fail({ message: 'Invalid authorization request state.' }, 403); | ||
162 | + } | ||
163 | + } | ||
164 | + | ||
165 | + var params = this.tokenParams(options); | ||
166 | + params.grant_type = 'authorization_code'; | ||
167 | + params.redirect_uri = callbackURL; | ||
168 | + | ||
169 | + this._oauth2.getOAuthAccessToken(code, params, | ||
170 | + function(err, accessToken, refreshToken, params) { | ||
171 | + if (err) { return self.error(self._createOAuthError('Failed to obtain access token', err)); } | ||
172 | + | ||
173 | + self._loadUserProfile(accessToken, function(err, profile) { | ||
174 | + if (err) { return self.error(err); } | ||
175 | + | ||
176 | + function verified(err, user, info) { | ||
177 | + if (err) { return self.error(err); } | ||
178 | + if (!user) { return self.fail(info); } | ||
179 | + self.success(user, info); | ||
180 | + } | ||
181 | + | ||
182 | + try { | ||
183 | + if (self._passReqToCallback) { | ||
184 | + var arity = self._verify.length; | ||
185 | + if (arity == 6) { | ||
186 | + self._verify(req, accessToken, refreshToken, params, profile, verified); | ||
187 | + } else { // arity == 5 | ||
188 | + self._verify(req, accessToken, refreshToken, profile, verified); | ||
189 | + } | ||
190 | + } else { | ||
191 | + var arity = self._verify.length; | ||
192 | + if (arity == 5) { | ||
193 | + self._verify(accessToken, refreshToken, params, profile, verified); | ||
194 | + } else { // arity == 4 | ||
195 | + self._verify(accessToken, refreshToken, profile, verified); | ||
196 | + } | ||
197 | + } | ||
198 | + } catch (ex) { | ||
199 | + return self.error(ex); | ||
200 | + } | ||
201 | + }); | ||
202 | + } | ||
203 | + ); | ||
204 | + } else { | ||
205 | + var params = this.authorizationParams(options); | ||
206 | + params.response_type = 'code'; | ||
207 | + params.redirect_uri = callbackURL; | ||
208 | + var scope = options.scope || this._scope; | ||
209 | + if (scope) { | ||
210 | + if (Array.isArray(scope)) { scope = scope.join(this._scopeSeparator); } | ||
211 | + params.scope = scope; | ||
212 | + } | ||
213 | + var state = options.state; | ||
214 | + if (state) { | ||
215 | + params.state = state; | ||
216 | + } else if (this._state) { | ||
217 | + if (!req.session) { return this.error(new Error('OAuth2Strategy requires session support when using state. Did you forget app.use(express.session(...))?')); } | ||
218 | + | ||
219 | + var key = this._key; | ||
220 | + state = uid(24); | ||
221 | + if (!req.session[key]) { req.session[key] = {}; } | ||
222 | + req.session[key].state = state; | ||
223 | + params.state = state; | ||
224 | + } | ||
225 | + | ||
226 | + var location = this._oauth2.getAuthorizeUrl(params); | ||
227 | + this.redirect(location); | ||
228 | + } | ||
229 | +}; | ||
230 | + | ||
231 | +/** | ||
232 | + * Retrieve user profile from service provider. | ||
233 | + * | ||
234 | + * OAuth 2.0-based authentication strategies can overrride this function in | ||
235 | + * order to load the user's profile from the service provider. This assists | ||
236 | + * applications (and users of those applications) in the initial registration | ||
237 | + * process by automatically submitting required information. | ||
238 | + * | ||
239 | + * @param {String} accessToken | ||
240 | + * @param {Function} done | ||
241 | + * @api protected | ||
242 | + */ | ||
243 | +OAuth2Strategy.prototype.userProfile = function(accessToken, done) { | ||
244 | + return done(null, {}); | ||
245 | +}; | ||
246 | + | ||
247 | +/** | ||
248 | + * Return extra parameters to be included in the authorization request. | ||
249 | + * | ||
250 | + * Some OAuth 2.0 providers allow additional, non-standard parameters to be | ||
251 | + * included when requesting authorization. Since these parameters are not | ||
252 | + * standardized by the OAuth 2.0 specification, OAuth 2.0-based authentication | ||
253 | + * strategies can overrride this function in order to populate these parameters | ||
254 | + * as required by the provider. | ||
255 | + * | ||
256 | + * @param {Object} options | ||
257 | + * @return {Object} | ||
258 | + * @api protected | ||
259 | + */ | ||
260 | +OAuth2Strategy.prototype.authorizationParams = function(options) { | ||
261 | + return {}; | ||
262 | +}; | ||
263 | + | ||
264 | +/** | ||
265 | + * Return extra parameters to be included in the token request. | ||
266 | + * | ||
267 | + * Some OAuth 2.0 providers allow additional, non-standard parameters to be | ||
268 | + * included when requesting an access token. Since these parameters are not | ||
269 | + * standardized by the OAuth 2.0 specification, OAuth 2.0-based authentication | ||
270 | + * strategies can overrride this function in order to populate these parameters | ||
271 | + * as required by the provider. | ||
272 | + * | ||
273 | + * @return {Object} | ||
274 | + * @api protected | ||
275 | + */ | ||
276 | +OAuth2Strategy.prototype.tokenParams = function(options) { | ||
277 | + return {}; | ||
278 | +}; | ||
279 | + | ||
280 | +/** | ||
281 | + * Parse error response from OAuth 2.0 endpoint. | ||
282 | + * | ||
283 | + * OAuth 2.0-based authentication strategies can overrride this function in | ||
284 | + * order to parse error responses received from the token endpoint, allowing the | ||
285 | + * most informative message to be displayed. | ||
286 | + * | ||
287 | + * If this function is not overridden, the body will be parsed in accordance | ||
288 | + * with RFC 6749, section 5.2. | ||
289 | + * | ||
290 | + * @param {String} body | ||
291 | + * @param {Number} status | ||
292 | + * @return {Error} | ||
293 | + * @api protected | ||
294 | + */ | ||
295 | +OAuth2Strategy.prototype.parseErrorResponse = function(body, status) { | ||
296 | + var json = JSON.parse(body); | ||
297 | + if (json.error) { | ||
298 | + return new TokenError(json.error_description, json.error, json.error_uri); | ||
299 | + } | ||
300 | + return null; | ||
301 | +}; | ||
302 | + | ||
303 | +/** | ||
304 | + * Load user profile, contingent upon options. | ||
305 | + * | ||
306 | + * @param {String} accessToken | ||
307 | + * @param {Function} done | ||
308 | + * @api private | ||
309 | + */ | ||
310 | +OAuth2Strategy.prototype._loadUserProfile = function(accessToken, done) { | ||
311 | + var self = this; | ||
312 | + | ||
313 | + function loadIt() { | ||
314 | + return self.userProfile(accessToken, done); | ||
315 | + } | ||
316 | + function skipIt() { | ||
317 | + return done(null); | ||
318 | + } | ||
319 | + | ||
320 | + if (typeof this._skipUserProfile == 'function' && this._skipUserProfile.length > 1) { | ||
321 | + // async | ||
322 | + this._skipUserProfile(accessToken, function(err, skip) { | ||
323 | + if (err) { return done(err); } | ||
324 | + if (!skip) { return loadIt(); } | ||
325 | + return skipIt(); | ||
326 | + }); | ||
327 | + } else { | ||
328 | + var skip = (typeof this._skipUserProfile == 'function') ? this._skipUserProfile() : this._skipUserProfile; | ||
329 | + if (!skip) { return loadIt(); } | ||
330 | + return skipIt(); | ||
331 | + } | ||
332 | +}; | ||
333 | + | ||
334 | +/** | ||
335 | + * Create an OAuth error. | ||
336 | + * | ||
337 | + * @param {String} message | ||
338 | + * @param {Object|Error} err | ||
339 | + * @api private | ||
340 | + */ | ||
341 | +OAuth2Strategy.prototype._createOAuthError = function(message, err) { | ||
342 | + var e; | ||
343 | + if (err.statusCode && err.data) { | ||
344 | + try { | ||
345 | + e = this.parseErrorResponse(err.data, err.statusCode); | ||
346 | + } catch (_) {} | ||
347 | + } | ||
348 | + if (!e) { e = new InternalOAuthError(message, err); } | ||
349 | + return e; | ||
350 | +}; | ||
351 | + | ||
352 | + | ||
353 | +/** | ||
354 | + * Expose `OAuth2Strategy`. | ||
355 | + */ | ||
356 | +module.exports = OAuth2Strategy; |
1 | +/** | ||
2 | + * Reconstructs the original URL of the request. | ||
3 | + * | ||
4 | + * This function builds a URL that corresponds the original URL requested by the | ||
5 | + * client, including the protocol (http or https) and host. | ||
6 | + * | ||
7 | + * If the request passed through any proxies that terminate SSL, the | ||
8 | + * `X-Forwarded-Proto` header is used to detect if the request was encrypted to | ||
9 | + * the proxy, assuming that the proxy has been flagged as trusted. | ||
10 | + * | ||
11 | + * @param {http.IncomingMessage} req | ||
12 | + * @param {Object} [options] | ||
13 | + * @return {String} | ||
14 | + * @api private | ||
15 | + */ | ||
16 | +exports.originalURL = function(req, options) { | ||
17 | + options = options || {}; | ||
18 | + var app = req.app; | ||
19 | + if (app && app.get && app.get('trust proxy')) { | ||
20 | + options.proxy = true; | ||
21 | + } | ||
22 | + var trustProxy = options.proxy; | ||
23 | + | ||
24 | + var proto = (req.headers['x-forwarded-proto'] || '').toLowerCase() | ||
25 | + , tls = req.connection.encrypted || (trustProxy && 'https' == proto.split(/\s*,\s*/)[0]) | ||
26 | + , host = (trustProxy && req.headers['x-forwarded-host']) || req.headers.host | ||
27 | + , protocol = tls ? 'https' : 'http' | ||
28 | + , path = req.url || ''; | ||
29 | + return protocol + '://' + host + path; | ||
30 | +}; |
1 | +{ | ||
2 | + "name": "passport-oauth2", | ||
3 | + "version": "1.1.2", | ||
4 | + "description": "OAuth 2.0 authentication strategy for Passport.", | ||
5 | + "keywords": [ | ||
6 | + "passport", | ||
7 | + "auth", | ||
8 | + "authn", | ||
9 | + "authentication", | ||
10 | + "authz", | ||
11 | + "authorization", | ||
12 | + "oauth", | ||
13 | + "oauth2" | ||
14 | + ], | ||
15 | + "author": { | ||
16 | + "name": "Jared Hanson", | ||
17 | + "email": "jaredhanson@gmail.com", | ||
18 | + "url": "http://www.jaredhanson.net/" | ||
19 | + }, | ||
20 | + "repository": { | ||
21 | + "type": "git", | ||
22 | + "url": "git://github.com/jaredhanson/passport-oauth2.git" | ||
23 | + }, | ||
24 | + "bugs": { | ||
25 | + "url": "http://github.com/jaredhanson/passport-oauth2/issues" | ||
26 | + }, | ||
27 | + "licenses": [ | ||
28 | + { | ||
29 | + "type": "MIT", | ||
30 | + "url": "http://www.opensource.org/licenses/MIT" | ||
31 | + } | ||
32 | + ], | ||
33 | + "main": "./lib", | ||
34 | + "dependencies": { | ||
35 | + "passport-strategy": "1.x.x", | ||
36 | + "oauth": "0.9.x", | ||
37 | + "uid2": "0.0.x" | ||
38 | + }, | ||
39 | + "devDependencies": { | ||
40 | + "mocha": "1.x.x", | ||
41 | + "chai": "1.x.x", | ||
42 | + "chai-passport-strategy": "0.2.x" | ||
43 | + }, | ||
44 | + "engines": { | ||
45 | + "node": ">= 0.4.0" | ||
46 | + }, | ||
47 | + "scripts": { | ||
48 | + "test": "node_modules/.bin/mocha --reporter spec --require test/bootstrap/node test/*.test.js test/**/*.test.js" | ||
49 | + } | ||
50 | +} |
node_modules/passport-kakao/package.json
0 → 100644
1 | +{ | ||
2 | + "name": "passport-kakao", | ||
3 | + "version": "1.0.1", | ||
4 | + "description": "kakao oauth2 login module", | ||
5 | + "main": "./dist/passport-kakao", | ||
6 | + "keywords": [ | ||
7 | + "passport", | ||
8 | + "kakao", | ||
9 | + "kakaotalk", | ||
10 | + "oauth2" | ||
11 | + ], | ||
12 | + "repository": { | ||
13 | + "type": "git", | ||
14 | + "url": "git://github.com/rotoshine/passport-kakao.git" | ||
15 | + }, | ||
16 | + "author": "rotoshine@gmail.com", | ||
17 | + "license": "MIT", | ||
18 | + "dependencies": { | ||
19 | + "pkginfo": "~0.3.0", | ||
20 | + "passport-oauth2": "~1.1.2" | ||
21 | + }, | ||
22 | + "devDependencies": { | ||
23 | + "@types/chai": "^4.2.3", | ||
24 | + "@types/mocha": "^5.2.7", | ||
25 | + "@types/node": "^12.7.11", | ||
26 | + "@typescript-eslint/eslint-plugin": "^2.30.0", | ||
27 | + "@typescript-eslint/parser": "^2.30.0", | ||
28 | + "chai": "^4.2.0", | ||
29 | + "eslint": "^6.8.0", | ||
30 | + "mocha": "^6.2.1", | ||
31 | + "prettier": "^2.0.5", | ||
32 | + "rimraf": "^3.0.2", | ||
33 | + "ts-node": "^8.4.1", | ||
34 | + "tslint": "^5.20.0", | ||
35 | + "tslint-config-prettier": "^1.18.0", | ||
36 | + "typescript": "^3.6.3" | ||
37 | + }, | ||
38 | + "scripts": { | ||
39 | + "test": "mocha -r node_modules/ts-node/register ./tests/**/*.spec.ts", | ||
40 | + "clean": "rimraf dist/*", | ||
41 | + "build": "npm run clean && npx tsc", | ||
42 | + "lint": "eslint -c .eslintrc.js src/**/*.ts", | ||
43 | + "format": "prettier --write \"src/*.{ts,tsx,json,md}\"" | ||
44 | + } | ||
45 | +} |
node_modules/passport-kakao/sample/README.md
0 → 100644
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 | + "dotenv": { | ||
84 | + "version": "8.2.0", | ||
85 | + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.2.0.tgz", | ||
86 | + "integrity": "sha512-8sJ78ElpbDJBHNeBzUbUVLsqKdccaa/BXF1uPTw3GrvQTBgrQrtObr2mUrE38vzYd8cEv+m/JBfDLioYcfXoaw==" | ||
87 | + }, | ||
88 | + "ee-first": { | ||
89 | + "version": "1.1.1", | ||
90 | + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", | ||
91 | + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" | ||
92 | + }, | ||
93 | + "encodeurl": { | ||
94 | + "version": "1.0.2", | ||
95 | + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", | ||
96 | + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" | ||
97 | + }, | ||
98 | + "escape-html": { | ||
99 | + "version": "1.0.3", | ||
100 | + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", | ||
101 | + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" | ||
102 | + }, | ||
103 | + "etag": { | ||
104 | + "version": "1.8.1", | ||
105 | + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", | ||
106 | + "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" | ||
107 | + }, | ||
108 | + "express": { | ||
109 | + "version": "4.17.1", | ||
110 | + "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", | ||
111 | + "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", | ||
112 | + "requires": { | ||
113 | + "accepts": "~1.3.7", | ||
114 | + "array-flatten": "1.1.1", | ||
115 | + "body-parser": "1.19.0", | ||
116 | + "content-disposition": "0.5.3", | ||
117 | + "content-type": "~1.0.4", | ||
118 | + "cookie": "0.4.0", | ||
119 | + "cookie-signature": "1.0.6", | ||
120 | + "debug": "2.6.9", | ||
121 | + "depd": "~1.1.2", | ||
122 | + "encodeurl": "~1.0.2", | ||
123 | + "escape-html": "~1.0.3", | ||
124 | + "etag": "~1.8.1", | ||
125 | + "finalhandler": "~1.1.2", | ||
126 | + "fresh": "0.5.2", | ||
127 | + "merge-descriptors": "1.0.1", | ||
128 | + "methods": "~1.1.2", | ||
129 | + "on-finished": "~2.3.0", | ||
130 | + "parseurl": "~1.3.3", | ||
131 | + "path-to-regexp": "0.1.7", | ||
132 | + "proxy-addr": "~2.0.5", | ||
133 | + "qs": "6.7.0", | ||
134 | + "range-parser": "~1.2.1", | ||
135 | + "safe-buffer": "5.1.2", | ||
136 | + "send": "0.17.1", | ||
137 | + "serve-static": "1.14.1", | ||
138 | + "setprototypeof": "1.1.1", | ||
139 | + "statuses": "~1.5.0", | ||
140 | + "type-is": "~1.6.18", | ||
141 | + "utils-merge": "1.0.1", | ||
142 | + "vary": "~1.1.2" | ||
143 | + } | ||
144 | + }, | ||
145 | + "finalhandler": { | ||
146 | + "version": "1.1.2", | ||
147 | + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", | ||
148 | + "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", | ||
149 | + "requires": { | ||
150 | + "debug": "2.6.9", | ||
151 | + "encodeurl": "~1.0.2", | ||
152 | + "escape-html": "~1.0.3", | ||
153 | + "on-finished": "~2.3.0", | ||
154 | + "parseurl": "~1.3.3", | ||
155 | + "statuses": "~1.5.0", | ||
156 | + "unpipe": "~1.0.0" | ||
157 | + } | ||
158 | + }, | ||
159 | + "forwarded": { | ||
160 | + "version": "0.1.2", | ||
161 | + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", | ||
162 | + "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=" | ||
163 | + }, | ||
164 | + "fresh": { | ||
165 | + "version": "0.5.2", | ||
166 | + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", | ||
167 | + "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" | ||
168 | + }, | ||
169 | + "http-errors": { | ||
170 | + "version": "1.7.2", | ||
171 | + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", | ||
172 | + "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", | ||
173 | + "requires": { | ||
174 | + "depd": "~1.1.2", | ||
175 | + "inherits": "2.0.3", | ||
176 | + "setprototypeof": "1.1.1", | ||
177 | + "statuses": ">= 1.5.0 < 2", | ||
178 | + "toidentifier": "1.0.0" | ||
179 | + } | ||
180 | + }, | ||
181 | + "iconv-lite": { | ||
182 | + "version": "0.4.24", | ||
183 | + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", | ||
184 | + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", | ||
185 | + "requires": { | ||
186 | + "safer-buffer": ">= 2.1.2 < 3" | ||
187 | + } | ||
188 | + }, | ||
189 | + "inherits": { | ||
190 | + "version": "2.0.3", | ||
191 | + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", | ||
192 | + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" | ||
193 | + }, | ||
194 | + "ipaddr.js": { | ||
195 | + "version": "1.9.0", | ||
196 | + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.0.tgz", | ||
197 | + "integrity": "sha512-M4Sjn6N/+O6/IXSJseKqHoFc+5FdGJ22sXqnjTpdZweHK64MzEPAyQZyEU3R/KRv2GLoa7nNtg/C2Ev6m7z+eA==" | ||
198 | + }, | ||
199 | + "media-typer": { | ||
200 | + "version": "0.3.0", | ||
201 | + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", | ||
202 | + "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" | ||
203 | + }, | ||
204 | + "merge-descriptors": { | ||
205 | + "version": "1.0.1", | ||
206 | + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", | ||
207 | + "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" | ||
208 | + }, | ||
209 | + "methods": { | ||
210 | + "version": "1.1.2", | ||
211 | + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", | ||
212 | + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" | ||
213 | + }, | ||
214 | + "mime": { | ||
215 | + "version": "1.6.0", | ||
216 | + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", | ||
217 | + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" | ||
218 | + }, | ||
219 | + "mime-db": { | ||
220 | + "version": "1.40.0", | ||
221 | + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.40.0.tgz", | ||
222 | + "integrity": "sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA==" | ||
223 | + }, | ||
224 | + "mime-types": { | ||
225 | + "version": "2.1.24", | ||
226 | + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.24.tgz", | ||
227 | + "integrity": "sha512-WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ==", | ||
228 | + "requires": { | ||
229 | + "mime-db": "1.40.0" | ||
230 | + } | ||
231 | + }, | ||
232 | + "ms": { | ||
233 | + "version": "2.0.0", | ||
234 | + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", | ||
235 | + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" | ||
236 | + }, | ||
237 | + "negotiator": { | ||
238 | + "version": "0.6.2", | ||
239 | + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", | ||
240 | + "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==" | ||
241 | + }, | ||
242 | + "on-finished": { | ||
243 | + "version": "2.3.0", | ||
244 | + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", | ||
245 | + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", | ||
246 | + "requires": { | ||
247 | + "ee-first": "1.1.1" | ||
248 | + } | ||
249 | + }, | ||
250 | + "parseurl": { | ||
251 | + "version": "1.3.3", | ||
252 | + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", | ||
253 | + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" | ||
254 | + }, | ||
255 | + "passport": { | ||
256 | + "version": "0.4.0", | ||
257 | + "resolved": "https://registry.npmjs.org/passport/-/passport-0.4.0.tgz", | ||
258 | + "integrity": "sha1-xQlWkTR71a07XhgCOMORTRbwWBE=", | ||
259 | + "requires": { | ||
260 | + "passport-strategy": "1.x.x", | ||
261 | + "pause": "0.0.1" | ||
262 | + } | ||
263 | + }, | ||
264 | + "passport-strategy": { | ||
265 | + "version": "1.0.0", | ||
266 | + "resolved": "https://registry.npmjs.org/passport-strategy/-/passport-strategy-1.0.0.tgz", | ||
267 | + "integrity": "sha1-tVOaqPwiWj0a0XlHbd8ja0QPUuQ=" | ||
268 | + }, | ||
269 | + "path-to-regexp": { | ||
270 | + "version": "0.1.7", | ||
271 | + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", | ||
272 | + "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" | ||
273 | + }, | ||
274 | + "pause": { | ||
275 | + "version": "0.0.1", | ||
276 | + "resolved": "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz", | ||
277 | + "integrity": "sha1-HUCLP9t2kjuVQ9lvtMnf1TXZy10=" | ||
278 | + }, | ||
279 | + "proxy-addr": { | ||
280 | + "version": "2.0.5", | ||
281 | + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.5.tgz", | ||
282 | + "integrity": "sha512-t/7RxHXPH6cJtP0pRG6smSr9QJidhB+3kXu0KgXnbGYMgzEnUxRQ4/LDdfOwZEMyIh3/xHb8PX3t+lfL9z+YVQ==", | ||
283 | + "requires": { | ||
284 | + "forwarded": "~0.1.2", | ||
285 | + "ipaddr.js": "1.9.0" | ||
286 | + } | ||
287 | + }, | ||
288 | + "qs": { | ||
289 | + "version": "6.7.0", | ||
290 | + "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", | ||
291 | + "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==" | ||
292 | + }, | ||
293 | + "range-parser": { | ||
294 | + "version": "1.2.1", | ||
295 | + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", | ||
296 | + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" | ||
297 | + }, | ||
298 | + "raw-body": { | ||
299 | + "version": "2.4.0", | ||
300 | + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", | ||
301 | + "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", | ||
302 | + "requires": { | ||
303 | + "bytes": "3.1.0", | ||
304 | + "http-errors": "1.7.2", | ||
305 | + "iconv-lite": "0.4.24", | ||
306 | + "unpipe": "1.0.0" | ||
307 | + } | ||
308 | + }, | ||
309 | + "safe-buffer": { | ||
310 | + "version": "5.1.2", | ||
311 | + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", | ||
312 | + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" | ||
313 | + }, | ||
314 | + "safer-buffer": { | ||
315 | + "version": "2.1.2", | ||
316 | + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", | ||
317 | + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" | ||
318 | + }, | ||
319 | + "send": { | ||
320 | + "version": "0.17.1", | ||
321 | + "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", | ||
322 | + "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", | ||
323 | + "requires": { | ||
324 | + "debug": "2.6.9", | ||
325 | + "depd": "~1.1.2", | ||
326 | + "destroy": "~1.0.4", | ||
327 | + "encodeurl": "~1.0.2", | ||
328 | + "escape-html": "~1.0.3", | ||
329 | + "etag": "~1.8.1", | ||
330 | + "fresh": "0.5.2", | ||
331 | + "http-errors": "~1.7.2", | ||
332 | + "mime": "1.6.0", | ||
333 | + "ms": "2.1.1", | ||
334 | + "on-finished": "~2.3.0", | ||
335 | + "range-parser": "~1.2.1", | ||
336 | + "statuses": "~1.5.0" | ||
337 | + }, | ||
338 | + "dependencies": { | ||
339 | + "ms": { | ||
340 | + "version": "2.1.1", | ||
341 | + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", | ||
342 | + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" | ||
343 | + } | ||
344 | + } | ||
345 | + }, | ||
346 | + "serve-static": { | ||
347 | + "version": "1.14.1", | ||
348 | + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", | ||
349 | + "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", | ||
350 | + "requires": { | ||
351 | + "encodeurl": "~1.0.2", | ||
352 | + "escape-html": "~1.0.3", | ||
353 | + "parseurl": "~1.3.3", | ||
354 | + "send": "0.17.1" | ||
355 | + } | ||
356 | + }, | ||
357 | + "setprototypeof": { | ||
358 | + "version": "1.1.1", | ||
359 | + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", | ||
360 | + "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" | ||
361 | + }, | ||
362 | + "statuses": { | ||
363 | + "version": "1.5.0", | ||
364 | + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", | ||
365 | + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" | ||
366 | + }, | ||
367 | + "toidentifier": { | ||
368 | + "version": "1.0.0", | ||
369 | + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", | ||
370 | + "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==" | ||
371 | + }, | ||
372 | + "type-is": { | ||
373 | + "version": "1.6.18", | ||
374 | + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", | ||
375 | + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", | ||
376 | + "requires": { | ||
377 | + "media-typer": "0.3.0", | ||
378 | + "mime-types": "~2.1.24" | ||
379 | + } | ||
380 | + }, | ||
381 | + "unpipe": { | ||
382 | + "version": "1.0.0", | ||
383 | + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", | ||
384 | + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" | ||
385 | + }, | ||
386 | + "utils-merge": { | ||
387 | + "version": "1.0.1", | ||
388 | + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", | ||
389 | + "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" | ||
390 | + }, | ||
391 | + "vary": { | ||
392 | + "version": "1.1.2", | ||
393 | + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", | ||
394 | + "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" | ||
395 | + } | ||
396 | + } | ||
397 | +} |
node_modules/passport-kakao/sample/sample.js
0 → 100644
1 | +require('dotenv').config() | ||
2 | + | ||
3 | +const passport = require('passport') | ||
4 | +const express = require('express') | ||
5 | +const KakaoStrategy = require('../dist/passport-kakao.js').Strategy | ||
6 | + | ||
7 | +const appKey = process.env.API_KEY | ||
8 | +const appSecret = process.env.CLIENT_SECRET_KEY | ||
9 | + | ||
10 | +// passport 에 Kakao Oauth 추가 | ||
11 | +passport.use( | ||
12 | + new KakaoStrategy( | ||
13 | + { | ||
14 | + clientID: appKey, | ||
15 | + clientSecret: appSecret, | ||
16 | + callbackURL: 'http://localhost:3000/oauth', | ||
17 | + }, | ||
18 | + function (accessToken, refreshToken, params, profile, done) { | ||
19 | + // authorization 에 성공했을때의 액션 | ||
20 | + console.log(`accessToken : ${accessToken}`) | ||
21 | + console.log(`사용자 profile: ${JSON.stringify(profile._json)}`) | ||
22 | + | ||
23 | + save(accessToken, refreshToken, profile) | ||
24 | + return done(null, profile._json) | ||
25 | + } | ||
26 | + ) | ||
27 | +) | ||
28 | +passport.serializeUser(function (user, done) { | ||
29 | + done(null, user) | ||
30 | +}) | ||
31 | +passport.deserializeUser(function (obj, done) { | ||
32 | + done(null, obj) | ||
33 | +}) | ||
34 | + | ||
35 | +// express 앱 설정 | ||
36 | +var app = express() | ||
37 | +app.use(passport.initialize()) | ||
38 | +app.get('/login', passport.authenticate('kakao', { state: 'myStateValue' })) | ||
39 | +app.get('/oauth', passport.authenticate('kakao'), function (req, res) { | ||
40 | + // 로그인 시작시 state 값을 받을 수 있음 | ||
41 | + res.send('state :' + req.query.state) | ||
42 | +}) | ||
43 | +app.listen(3000) | ||
44 | +console.log('> server start! ') | ||
45 | + | ||
46 | +// 사용자 구현 부분 | ||
47 | +function save() { | ||
48 | + //save 로직 구현 | ||
49 | +} |
node_modules/passport-kakao/src/Strategy.ts
0 → 100644
1 | +import { inherits } from 'util' | ||
2 | +import OAuth2Strategy from 'passport-oauth2' | ||
3 | + | ||
4 | +import { StrategyOptions, Profile } from './types/models' | ||
5 | + | ||
6 | +const DEFAULT_CLIENT_SECRET = 'kakao' | ||
7 | +const OAUTH_HOST = 'https://kauth.kakao.com' | ||
8 | +const USER_PROFILE_URL = 'https://kapi.kakao.com/v2/user/me' | ||
9 | + | ||
10 | +export const buildOptions = (options: StrategyOptions) => { | ||
11 | + options.authorizationURL = `${OAUTH_HOST}/oauth/authorize` | ||
12 | + options.tokenURL = `${OAUTH_HOST}/oauth/token` | ||
13 | + | ||
14 | + if (!options.clientSecret) { | ||
15 | + options.clientSecret = DEFAULT_CLIENT_SECRET | ||
16 | + } | ||
17 | + | ||
18 | + options.scopeSeparator = options.scopeSeparator || ',' | ||
19 | + options.customHeaders = options.customHeaders || {} | ||
20 | + | ||
21 | + if (!options.customHeaders['User-Agent']) { | ||
22 | + options.customHeaders['User-Agent'] = options.userAgent || 'passport-kakao' | ||
23 | + } | ||
24 | + | ||
25 | + return options | ||
26 | +} | ||
27 | +/** | ||
28 | + * KaKaoStrategy 생성자 함수.<br/> | ||
29 | + * @param options.clientID 필수. kakao rest app key. | ||
30 | + * @param options.callbackURL 필수. 로그인 처리 후 호출할 URL | ||
31 | + * @param verify | ||
32 | + * @constructor | ||
33 | + */ | ||
34 | +function Strategy(options: StrategyOptions = {}, verify: any) { | ||
35 | + OAuth2Strategy.call(this, buildOptions(options), verify) | ||
36 | + this.name = 'kakao' | ||
37 | + this._userProfileURL = USER_PROFILE_URL | ||
38 | +} | ||
39 | + | ||
40 | +/** | ||
41 | + * `OAuth2Stragegy`를 상속 받는다. | ||
42 | + */ | ||
43 | +inherits(Strategy, OAuth2Strategy) | ||
44 | + | ||
45 | +/** | ||
46 | + * kakao 사용자 정보를 얻는다.<br/> | ||
47 | + * 사용자 정보를 성공적으로 조회하면 아래의 object가 done 콜백함수 호출과 함꼐 넘어간다. | ||
48 | + * | ||
49 | + * - `provider` kakao 고정 | ||
50 | + * - `id` kakao user id number | ||
51 | + * - `username` 사용자의 kakao nickname | ||
52 | + * - `_raw` json string 원문 | ||
53 | + * _ `_json` json 원 데이터 | ||
54 | + * | ||
55 | + * @param {String} accessToken | ||
56 | + * @param {Function} done | ||
57 | + */ | ||
58 | +Strategy.prototype.userProfile = function ( | ||
59 | + accessToken: string, | ||
60 | + done: (error: Error, profile?: Profile) => void | ||
61 | +) { | ||
62 | + this._oauth2.get( | ||
63 | + this._userProfileURL, | ||
64 | + accessToken, | ||
65 | + (err: Error, body: string) => { | ||
66 | + if (err) { | ||
67 | + return done(err) | ||
68 | + } | ||
69 | + | ||
70 | + try { | ||
71 | + const json = JSON.parse(body) | ||
72 | + // 카카오톡이나 카카오스토리에 연동한 적이 없는 계정의 경우 | ||
73 | + // properties가 비어있다고 한다. 없을 경우의 처리 | ||
74 | + const properties = json.properties || { | ||
75 | + nickname: '미연동 계정', | ||
76 | + } | ||
77 | + const profile: Profile = { | ||
78 | + provider: 'kakao', | ||
79 | + id: json.id, | ||
80 | + username: properties.nickname, | ||
81 | + displayName: properties.nickname, | ||
82 | + _raw: body, | ||
83 | + _json: json, | ||
84 | + } | ||
85 | + return done(null, profile) | ||
86 | + } catch (e) { | ||
87 | + return done(e) | ||
88 | + } | ||
89 | + } | ||
90 | + ) | ||
91 | +} | ||
92 | + | ||
93 | +export default Strategy |
1 | +export interface StrategyOptions { | ||
2 | + authorizationURL?: string | ||
3 | + tokenURL?: string | ||
4 | + clientSecret?: string | ||
5 | + scopeSeparator?: string | ||
6 | + customHeaders?: { | ||
7 | + 'User-Agent'?: string | ||
8 | + } | ||
9 | + userAgent?: string | ||
10 | +} | ||
11 | + | ||
12 | +export interface Profile { | ||
13 | + provider: 'kakao' | ||
14 | + id?: string | number | ||
15 | + username?: string | ||
16 | + displayName?: string | ||
17 | + _raw: string | ||
18 | + _json: string | ||
19 | +} |
1 | +import { expect } from 'chai' | ||
2 | +import KakaoStrategy, { buildOptions } from '../src/Strategy' | ||
3 | + | ||
4 | +describe('passport-kakao', () => { | ||
5 | + it('passport-kakao 객체가 제대로 생성이 되어 있어야 한다.', () => { | ||
6 | + expect(KakaoStrategy).to.not.equals(null) | ||
7 | + }) | ||
8 | + it('Strategy option의 clientSecret 값이 없을 경우 default 값이 설정되어야 한다.', () => { | ||
9 | + const options = buildOptions({}) | ||
10 | + | ||
11 | + expect(options).to.not.equals(null) | ||
12 | + expect(options.clientSecret).to.be.equals('kakao') | ||
13 | + expect(options.scopeSeparator).to.be.equals(',') | ||
14 | + expect(options.customHeaders['User-Agent']).to.be.equals('passport-kakao') | ||
15 | + }) | ||
16 | + it('Strategy option의 User-Agent값이 있을 경우 customHeaders의 User-Agent가 해당 값으로 설정되어야 한다.', () => { | ||
17 | + const options = buildOptions({ | ||
18 | + customHeaders: { | ||
19 | + 'User-Agent': 'HELLO ROTO', | ||
20 | + }, | ||
21 | + }) | ||
22 | + expect(options.customHeaders['User-Agent']).to.be.equals('HELLO ROTO') | ||
23 | + }) | ||
24 | +}) |
node_modules/passport-kakao/tsconfig.json
0 → 100644
1 | +{ | ||
2 | + "include": ["./src"], | ||
3 | + "compilerOptions": { | ||
4 | + /* Basic Options */ | ||
5 | + // "incremental": true, /* Enable incremental compilation */ | ||
6 | + "target": "es5" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */, | ||
7 | + "module": "commonjs" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */, | ||
8 | + // "lib": [], /* Specify library files to be included in the compilation. */ | ||
9 | + // "allowJs": true, /* Allow javascript files to be compiled. */ | ||
10 | + // "checkJs": true, /* Report errors in .js files. */ | ||
11 | + // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */ | ||
12 | + // "declaration": true, /* Generates corresponding '.d.ts' file. */ | ||
13 | + // "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */ | ||
14 | + // "sourceMap": true, /* Generates corresponding '.map' file. */ | ||
15 | + // "outFile": "./", /* Concatenate and emit output to single file. */ | ||
16 | + "outDir": "./dist" /* Redirect output structure to the directory. */, | ||
17 | + "rootDir": "./src" /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */, | ||
18 | + // "composite": true, /* Enable project compilation */ | ||
19 | + // "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */ | ||
20 | + // "removeComments": true, /* Do not emit comments to output. */ | ||
21 | + // "noEmit": true, /* Do not emit outputs. */ | ||
22 | + // "importHelpers": true, /* Import emit helpers from 'tslib'. */ | ||
23 | + // "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */ | ||
24 | + // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */ | ||
25 | + | ||
26 | + /* Strict Type-Checking Options */ | ||
27 | + "strict": false /* Enable all strict type-checking options. */, | ||
28 | + // "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ | ||
29 | + // "strictNullChecks": true, /* Enable strict null checks. */ | ||
30 | + // "strictFunctionTypes": true, /* Enable strict checking of function types. */ | ||
31 | + // "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */ | ||
32 | + // "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */ | ||
33 | + // "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */ | ||
34 | + // "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */ | ||
35 | + | ||
36 | + /* Additional Checks */ | ||
37 | + // "noUnusedLocals": true, /* Report errors on unused locals. */ | ||
38 | + // "noUnusedParameters": true, /* Report errors on unused parameters. */ | ||
39 | + // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ | ||
40 | + // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ | ||
41 | + | ||
42 | + /* Module Resolution Options */ | ||
43 | + // "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ | ||
44 | + // "baseUrl": "./", /* Base directory to resolve non-absolute module names. */ | ||
45 | + // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ | ||
46 | + // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */ | ||
47 | + // "typeRoots": [], /* List of folders to include type definitions from. */ | ||
48 | + // "types": [], /* Type declaration files to be included in compilation. */ | ||
49 | + // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ | ||
50 | + "esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */ | ||
51 | + // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */ | ||
52 | + // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ | ||
53 | + | ||
54 | + /* Source Map Options */ | ||
55 | + // "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */ | ||
56 | + // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ | ||
57 | + // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */ | ||
58 | + // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */ | ||
59 | + | ||
60 | + /* Experimental Options */ | ||
61 | + // "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */ | ||
62 | + // "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */ | ||
63 | + } | ||
64 | +} |
node_modules/pkginfo/.npmignore
0 → 100644
node_modules/pkginfo/LICENSE
0 → 100644
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 |
node_modules/pkginfo/README.md
0 → 100644
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 |
node_modules/pkginfo/docs/docco.css
0 → 100644
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 |
node_modules/pkginfo/docs/pkginfo.html
0 → 100644
1 | +<!DOCTYPE html> <html> <head> <title>pkginfo.js</title> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <link rel="stylesheet" media="all" href="docco.css" /> </head> <body> <div id="container"> <div id="background"></div> <table cellpadding="0" cellspacing="0"> <thead> <tr> <th class="docs"> <h1> pkginfo.js </h1> </th> <th class="code"> </th> </tr> </thead> <tbody> <tr id="section-1"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-1">¶</a> </div> </td> <td class="code"> <div class="highlight"><pre><span class="cm">/*</span> | ||
2 | +<span class="cm"> * pkginfo.js: Top-level include for the pkginfo module</span> | ||
3 | +<span class="cm"> *</span> | ||
4 | +<span class="cm"> * (C) 2011, Charlie Robbins</span> | ||
5 | +<span class="cm"> *</span> | ||
6 | +<span class="cm"> */</span> | ||
7 | + | ||
8 | +<span class="kd">var</span> <span class="nx">fs</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">'fs'</span><span class="p">),</span> | ||
9 | + <span class="nx">path</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">'path'</span><span class="p">);</span></pre></div> </td> </tr> <tr id="section-2"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-2">¶</a> </div> <h3>function pkginfo ([options, 'property', 'property' ..])</h3> | ||
10 | + | ||
11 | +<h4>@pmodule {Module} Parent module to read from.</h4> | ||
12 | + | ||
13 | +<h4>@options {Object|Array|string} <strong>Optional</strong> Options used when exposing properties.</h4> | ||
14 | + | ||
15 | +<h4>@arguments {string...} <strong>Optional</strong> Specified properties to expose.</h4> | ||
16 | + | ||
17 | +<p>Exposes properties from the package.json file for the parent module on | ||
18 | +it's exports. Valid usage:</p> | ||
19 | + | ||
20 | +<p><code>require('pkginfo')()</code></p> | ||
21 | + | ||
22 | +<p><code>require('pkginfo')('version', 'author');</code></p> | ||
23 | + | ||
24 | +<p><code>require('pkginfo')(['version', 'author']);</code></p> | ||
25 | + | ||
26 | +<p><code>require('pkginfo')({ include: ['version', 'author'] });</code></p> </td> <td class="code"> <div class="highlight"><pre><span class="kd">var</span> <span class="nx">pkginfo</span> <span class="o">=</span> <span class="nx">module</span><span class="p">.</span><span class="nx">exports</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">pmodule</span><span class="p">,</span> <span class="nx">options</span><span class="p">)</span> <span class="p">{</span> | ||
27 | + <span class="kd">var</span> <span class="nx">args</span> <span class="o">=</span> <span class="p">[].</span><span class="nx">slice</span><span class="p">.</span><span class="nx">call</span><span class="p">(</span><span class="nx">arguments</span><span class="p">,</span> <span class="mi">2</span><span class="p">).</span><span class="nx">filter</span><span class="p">(</span><span class="kd">function</span> <span class="p">(</span><span class="nx">arg</span><span class="p">)</span> <span class="p">{</span> | ||
28 | + <span class="k">return</span> <span class="k">typeof</span> <span class="nx">arg</span> <span class="o">===</span> <span class="s1">'string'</span><span class="p">;</span> | ||
29 | + <span class="p">});</span> | ||
30 | + </pre></div> </td> </tr> <tr id="section-3"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-3">¶</a> </div> <p><strong>Parse variable arguments</strong></p> </td> <td class="code"> <div class="highlight"><pre> <span class="k">if</span> <span class="p">(</span><span class="nb">Array</span><span class="p">.</span><span class="nx">isArray</span><span class="p">(</span><span class="nx">options</span><span class="p">))</span> <span class="p">{</span></pre></div> </td> </tr> <tr id="section-4"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-4">¶</a> </div> <p>If the options passed in is an Array assume that | ||
31 | +it is the Array of properties to expose from the | ||
32 | +on the package.json file on the parent module.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">options</span> <span class="o">=</span> <span class="p">{</span> <span class="nx">include</span><span class="o">:</span> <span class="nx">options</span> <span class="p">};</span> | ||
33 | + <span class="p">}</span> | ||
34 | + <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="k">typeof</span> <span class="nx">options</span> <span class="o">===</span> <span class="s1">'string'</span><span class="p">)</span> <span class="p">{</span></pre></div> </td> </tr> <tr id="section-5"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-5">¶</a> </div> <p>Otherwise if the first argument is a string, then | ||
35 | +assume that it is the first property to expose from | ||
36 | +the package.json file on the parent module.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">options</span> <span class="o">=</span> <span class="p">{</span> <span class="nx">include</span><span class="o">:</span> <span class="p">[</span><span class="nx">options</span><span class="p">]</span> <span class="p">};</span> | ||
37 | + <span class="p">}</span> | ||
38 | + </pre></div> </td> </tr> <tr id="section-6"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-6">¶</a> </div> <p><strong>Setup default options</strong></p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">options</span> <span class="o">=</span> <span class="nx">options</span> <span class="o">||</span> <span class="p">{</span> <span class="nx">include</span><span class="o">:</span> <span class="p">[]</span> <span class="p">};</span> | ||
39 | + | ||
40 | + <span class="k">if</span> <span class="p">(</span><span class="nx">args</span><span class="p">.</span><span class="nx">length</span> <span class="o">></span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span></pre></div> </td> </tr> <tr id="section-7"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-7">¶</a> </div> <p>If additional string arguments have been passed in | ||
41 | +then add them to the properties to expose on the | ||
42 | +parent module. </p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">options</span><span class="p">.</span><span class="nx">include</span> <span class="o">=</span> <span class="nx">options</span><span class="p">.</span><span class="nx">include</span><span class="p">.</span><span class="nx">concat</span><span class="p">(</span><span class="nx">args</span><span class="p">);</span> | ||
43 | + <span class="p">}</span> | ||
44 | + | ||
45 | + <span class="kd">var</span> <span class="nx">pkg</span> <span class="o">=</span> <span class="nx">pkginfo</span><span class="p">.</span><span class="nx">read</span><span class="p">(</span><span class="nx">pmodule</span><span class="p">,</span> <span class="nx">options</span><span class="p">.</span><span class="nx">dir</span><span class="p">).</span><span class="kr">package</span><span class="p">;</span> | ||
46 | + <span class="nb">Object</span><span class="p">.</span><span class="nx">keys</span><span class="p">(</span><span class="nx">pkg</span><span class="p">).</span><span class="nx">forEach</span><span class="p">(</span><span class="kd">function</span> <span class="p">(</span><span class="nx">key</span><span class="p">)</span> <span class="p">{</span> | ||
47 | + <span class="k">if</span> <span class="p">(</span><span class="nx">options</span><span class="p">.</span><span class="nx">include</span><span class="p">.</span><span class="nx">length</span> <span class="o">></span> <span class="mi">0</span> <span class="o">&&</span> <span class="o">!~</span><span class="nx">options</span><span class="p">.</span><span class="nx">include</span><span class="p">.</span><span class="nx">indexOf</span><span class="p">(</span><span class="nx">key</span><span class="p">))</span> <span class="p">{</span> | ||
48 | + <span class="k">return</span><span class="p">;</span> | ||
49 | + <span class="p">}</span> | ||
50 | + | ||
51 | + <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">pmodule</span><span class="p">.</span><span class="nx">exports</span><span class="p">[</span><span class="nx">key</span><span class="p">])</span> <span class="p">{</span> | ||
52 | + <span class="nx">pmodule</span><span class="p">.</span><span class="nx">exports</span><span class="p">[</span><span class="nx">key</span><span class="p">]</span> <span class="o">=</span> <span class="nx">pkg</span><span class="p">[</span><span class="nx">key</span><span class="p">];</span> | ||
53 | + <span class="p">}</span> | ||
54 | + <span class="p">});</span> | ||
55 | + | ||
56 | + <span class="k">return</span> <span class="nx">pkginfo</span><span class="p">;</span> | ||
57 | +<span class="p">};</span></pre></div> </td> </tr> <tr id="section-8"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-8">¶</a> </div> <h3>function find (dir)</h3> | ||
58 | + | ||
59 | +<h4>@pmodule {Module} Parent module to read from.</h4> | ||
60 | + | ||
61 | +<h4>@dir {string} <strong>Optional</strong> Directory to start search from.</h4> | ||
62 | + | ||
63 | +<p>Searches up the directory tree from <code>dir</code> until it finds a directory | ||
64 | +which contains a <code>package.json</code> file. </p> </td> <td class="code"> <div class="highlight"><pre><span class="nx">pkginfo</span><span class="p">.</span><span class="nx">find</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">pmodule</span><span class="p">,</span> <span class="nx">dir</span><span class="p">)</span> <span class="p">{</span> | ||
65 | + <span class="nx">dir</span> <span class="o">=</span> <span class="nx">dir</span> <span class="o">||</span> <span class="nx">pmodule</span><span class="p">.</span><span class="nx">filename</span><span class="p">;</span> | ||
66 | + <span class="nx">dir</span> <span class="o">=</span> <span class="nx">path</span><span class="p">.</span><span class="nx">dirname</span><span class="p">(</span><span class="nx">dir</span><span class="p">);</span> | ||
67 | + | ||
68 | + <span class="kd">var</span> <span class="nx">files</span> <span class="o">=</span> <span class="nx">fs</span><span class="p">.</span><span class="nx">readdirSync</span><span class="p">(</span><span class="nx">dir</span><span class="p">);</span> | ||
69 | + | ||
70 | + <span class="k">if</span> <span class="p">(</span><span class="o">~</span><span class="nx">files</span><span class="p">.</span><span class="nx">indexOf</span><span class="p">(</span><span class="s1">'package.json'</span><span class="p">))</span> <span class="p">{</span> | ||
71 | + <span class="k">return</span> <span class="nx">path</span><span class="p">.</span><span class="nx">join</span><span class="p">(</span><span class="nx">dir</span><span class="p">,</span> <span class="s1">'package.json'</span><span class="p">);</span> | ||
72 | + <span class="p">}</span> | ||
73 | + | ||
74 | + <span class="k">if</span> <span class="p">(</span><span class="nx">dir</span> <span class="o">===</span> <span class="s1">'/'</span><span class="p">)</span> <span class="p">{</span> | ||
75 | + <span class="k">throw</span> <span class="k">new</span> <span class="nb">Error</span><span class="p">(</span><span class="s1">'Could not find package.json up from: '</span> <span class="o">+</span> <span class="nx">dir</span><span class="p">);</span> | ||
76 | + <span class="p">}</span> | ||
77 | + | ||
78 | + <span class="k">return</span> <span class="nx">pkginfo</span><span class="p">.</span><span class="nx">find</span><span class="p">(</span><span class="nx">dir</span><span class="p">);</span> | ||
79 | +<span class="p">};</span></pre></div> </td> </tr> <tr id="section-9"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-9">¶</a> </div> <h3>function read (pmodule, dir)</h3> | ||
80 | + | ||
81 | +<h4>@pmodule {Module} Parent module to read from.</h4> | ||
82 | + | ||
83 | +<h4>@dir {string} <strong>Optional</strong> Directory to start search from.</h4> | ||
84 | + | ||
85 | +<p>Searches up the directory tree from <code>dir</code> until it finds a directory | ||
86 | +which contains a <code>package.json</code> file and returns the package information.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nx">pkginfo</span><span class="p">.</span><span class="nx">read</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">pmodule</span><span class="p">,</span> <span class="nx">dir</span><span class="p">)</span> <span class="p">{</span> | ||
87 | + <span class="nx">dir</span> <span class="o">=</span> <span class="nx">pkginfo</span><span class="p">.</span><span class="nx">find</span><span class="p">(</span><span class="nx">pmodule</span><span class="p">,</span> <span class="nx">dir</span><span class="p">);</span> | ||
88 | + | ||
89 | + <span class="kd">var</span> <span class="nx">data</span> <span class="o">=</span> <span class="nx">fs</span><span class="p">.</span><span class="nx">readFileSync</span><span class="p">(</span><span class="nx">dir</span><span class="p">).</span><span class="nx">toString</span><span class="p">();</span> | ||
90 | + | ||
91 | + <span class="k">return</span> <span class="p">{</span> | ||
92 | + <span class="nx">dir</span><span class="o">:</span> <span class="nx">dir</span><span class="p">,</span> | ||
93 | + <span class="kr">package</span><span class="o">:</span> <span class="nx">JSON</span><span class="p">.</span><span class="nx">parse</span><span class="p">(</span><span class="nx">data</span><span class="p">)</span> | ||
94 | + <span class="p">};</span> | ||
95 | +<span class="p">};</span></pre></div> </td> </tr> <tr id="section-10"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-10">¶</a> </div> <p>Call <code>pkginfo</code> on this module and expose version.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nx">pkginfo</span><span class="p">(</span><span class="nx">module</span><span class="p">,</span> <span class="p">{</span> | ||
96 | + <span class="nx">dir</span><span class="o">:</span> <span class="nx">__dirname</span><span class="p">,</span> | ||
97 | + <span class="nx">include</span><span class="o">:</span> <span class="p">[</span><span class="s1">'version'</span><span class="p">],</span> | ||
98 | + <span class="nx">target</span><span class="o">:</span> <span class="nx">pkginfo</span> | ||
99 | +<span class="p">});</span> | ||
100 | + | ||
101 | +</pre></div> </td> </tr> </tbody> </table> </div> </body> </html> | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
1 | +/* | ||
2 | + * all-properties.js: Sample of including all properties from a package.json file | ||
3 | + * | ||
4 | + * (C) 2011, Charlie Robbins | ||
5 | + * | ||
6 | + */ | ||
7 | + | ||
8 | +var util = require('util'), | ||
9 | + pkginfo = require('../lib/pkginfo')(module); | ||
10 | + | ||
11 | +exports.someFunction = function () { | ||
12 | + console.log('some of your custom logic here'); | ||
13 | +}; | ||
14 | + | ||
15 | +console.log('Inspecting module:'); | ||
16 | +console.dir(module.exports); | ||
17 | + | ||
18 | +console.log('\nAll exports exposed:'); | ||
19 | +console.error(Object.keys(module.exports)); | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
1 | +/* | ||
2 | + * array-argument.js: Sample of including specific properties from a package.json file | ||
3 | + * using Array argument syntax. | ||
4 | + * | ||
5 | + * (C) 2011, Charlie Robbins | ||
6 | + * | ||
7 | + */ | ||
8 | + | ||
9 | +var util = require('util'), | ||
10 | + pkginfo = require('../lib/pkginfo')(module, ['version', 'author']); | ||
11 | + | ||
12 | +exports.someFunction = function () { | ||
13 | + console.log('some of your custom logic here'); | ||
14 | +}; | ||
15 | + | ||
16 | +console.log('Inspecting module:'); | ||
17 | +console.dir(module.exports); | ||
18 | + | ||
19 | +console.log('\nAll exports exposed:'); | ||
20 | +console.error(Object.keys(module.exports)); | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
1 | +/* | ||
2 | + * multiple-properties.js: Sample of including multiple properties from a package.json file | ||
3 | + * | ||
4 | + * (C) 2011, Charlie Robbins | ||
5 | + * | ||
6 | + */ | ||
7 | + | ||
8 | +var util = require('util'), | ||
9 | + pkginfo = require('../lib/pkginfo')(module, 'version', 'author'); | ||
10 | + | ||
11 | +exports.someFunction = function () { | ||
12 | + console.log('some of your custom logic here'); | ||
13 | +}; | ||
14 | + | ||
15 | +console.log('Inspecting module:'); | ||
16 | +console.dir(module.exports); | ||
17 | + | ||
18 | +console.log('\nAll exports exposed:'); | ||
19 | +console.error(Object.keys(module.exports)); | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
1 | +/* | ||
2 | + * object-argument.js: Sample of including specific properties from a package.json file | ||
3 | + * using Object argument syntax. | ||
4 | + * | ||
5 | + * (C) 2011, Charlie Robbins | ||
6 | + * | ||
7 | + */ | ||
8 | + | ||
9 | +var util = require('util'), | ||
10 | + pkginfo = require('../lib/pkginfo')(module, { | ||
11 | + include: ['version', 'author'] | ||
12 | + }); | ||
13 | + | ||
14 | +exports.someFunction = function () { | ||
15 | + console.log('some of your custom logic here'); | ||
16 | +}; | ||
17 | + | ||
18 | +console.log('Inspecting module:'); | ||
19 | +console.dir(module.exports); | ||
20 | + | ||
21 | +console.log('\nAll exports exposed:'); | ||
22 | +console.error(Object.keys(module.exports)); | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
node_modules/pkginfo/examples/package.json
0 → 100644
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 | +} |
node_modules/pkginfo/examples/target-dir.js
0 → 100644
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 |
node_modules/pkginfo/lib/pkginfo.js
0 → 100644
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 |
node_modules/pkginfo/package.json
0 → 100644
1 | +{ | ||
2 | + "name": "pkginfo", | ||
3 | + "version": "0.3.1", | ||
4 | + "license": "MIT", | ||
5 | + "description": "An easy way to expose properties on a module from a package.json", | ||
6 | + "author": "Charlie Robbins <charlie.robbins@gmail.com>", | ||
7 | + "repository": { | ||
8 | + "type": "git", | ||
9 | + "url": "http://github.com/indexzero/node-pkginfo.git" | ||
10 | + }, | ||
11 | + "bugs": { | ||
12 | + "url": "https://github.com/indexzero/node-pkginfo/issues" | ||
13 | + }, | ||
14 | + "keywords": ["info", "tools", "package.json"], | ||
15 | + "devDependencies": { | ||
16 | + "vows": "0.7.x" | ||
17 | + }, | ||
18 | + "main": "./lib/pkginfo.js", | ||
19 | + "scripts": { "test": "vows test/*-test.js --spec" }, | ||
20 | + "engines": { "node": ">= 0.4.0" } | ||
21 | +} |
node_modules/pkginfo/test/pkginfo-test.js
0 → 100644
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); |
... | @@ -14,6 +14,7 @@ | ... | @@ -14,6 +14,7 @@ |
14 | "express": "^4.17.1", | 14 | "express": "^4.17.1", |
15 | "express-flash": "^0.0.2", | 15 | "express-flash": "^0.0.2", |
16 | "fs": "^0.0.1-security", | 16 | "fs": "^0.0.1-security", |
17 | + "passport-kakao": "^1.0.1", | ||
17 | "passport-naver": "^1.0.6", | 18 | "passport-naver": "^1.0.6", |
18 | "path": "^0.12.7", | 19 | "path": "^0.12.7", |
19 | "request": "^2.88.2", | 20 | "request": "^2.88.2", |
... | @@ -1750,6 +1751,28 @@ | ... | @@ -1750,6 +1751,28 @@ |
1750 | "node": ">= 0.4.0" | 1751 | "node": ">= 0.4.0" |
1751 | } | 1752 | } |
1752 | }, | 1753 | }, |
1754 | + "node_modules/passport-kakao": { | ||
1755 | + "version": "1.0.1", | ||
1756 | + "resolved": "https://registry.npmjs.org/passport-kakao/-/passport-kakao-1.0.1.tgz", | ||
1757 | + "integrity": "sha512-uItaYRVrTHL6iGPMnMZvPa/O1GrAdh/V6EMjOHcFlQcVroZ9wgG7BZ5PonMNJCxfHQ3L2QVNRnzhKWUzSsumbw==", | ||
1758 | + "dependencies": { | ||
1759 | + "passport-oauth2": "~1.1.2", | ||
1760 | + "pkginfo": "~0.3.0" | ||
1761 | + } | ||
1762 | + }, | ||
1763 | + "node_modules/passport-kakao/node_modules/passport-oauth2": { | ||
1764 | + "version": "1.1.2", | ||
1765 | + "resolved": "https://registry.npmjs.org/passport-oauth2/-/passport-oauth2-1.1.2.tgz", | ||
1766 | + "integrity": "sha1-vXFjsbYJA3GGjcTvb58uHkzEuUg=", | ||
1767 | + "dependencies": { | ||
1768 | + "oauth": "0.9.x", | ||
1769 | + "passport-strategy": "1.x.x", | ||
1770 | + "uid2": "0.0.x" | ||
1771 | + }, | ||
1772 | + "engines": { | ||
1773 | + "node": ">= 0.4.0" | ||
1774 | + } | ||
1775 | + }, | ||
1753 | "node_modules/passport-local": { | 1776 | "node_modules/passport-local": { |
1754 | "version": "1.0.0", | 1777 | "version": "1.0.0", |
1755 | "resolved": "https://registry.npmjs.org/passport-local/-/passport-local-1.0.0.tgz", | 1778 | "resolved": "https://registry.npmjs.org/passport-local/-/passport-local-1.0.0.tgz", |
... | @@ -1864,6 +1887,14 @@ | ... | @@ -1864,6 +1887,14 @@ |
1864 | "url": "https://github.com/sponsors/jonschlinkert" | 1887 | "url": "https://github.com/sponsors/jonschlinkert" |
1865 | } | 1888 | } |
1866 | }, | 1889 | }, |
1890 | + "node_modules/pkginfo": { | ||
1891 | + "version": "0.3.1", | ||
1892 | + "resolved": "https://registry.npmjs.org/pkginfo/-/pkginfo-0.3.1.tgz", | ||
1893 | + "integrity": "sha1-Wyn2qB9wcXFC4J52W76rl7T4HiE=", | ||
1894 | + "engines": { | ||
1895 | + "node": ">= 0.4.0" | ||
1896 | + } | ||
1897 | + }, | ||
1867 | "node_modules/prepend-http": { | 1898 | "node_modules/prepend-http": { |
1868 | "version": "2.0.0", | 1899 | "version": "2.0.0", |
1869 | "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", | 1900 | "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", |
... | @@ -4017,6 +4048,27 @@ | ... | @@ -4017,6 +4048,27 @@ |
4017 | "pause": "0.0.1" | 4048 | "pause": "0.0.1" |
4018 | } | 4049 | } |
4019 | }, | 4050 | }, |
4051 | + "passport-kakao": { | ||
4052 | + "version": "1.0.1", | ||
4053 | + "resolved": "https://registry.npmjs.org/passport-kakao/-/passport-kakao-1.0.1.tgz", | ||
4054 | + "integrity": "sha512-uItaYRVrTHL6iGPMnMZvPa/O1GrAdh/V6EMjOHcFlQcVroZ9wgG7BZ5PonMNJCxfHQ3L2QVNRnzhKWUzSsumbw==", | ||
4055 | + "requires": { | ||
4056 | + "passport-oauth2": "~1.1.2", | ||
4057 | + "pkginfo": "~0.3.0" | ||
4058 | + }, | ||
4059 | + "dependencies": { | ||
4060 | + "passport-oauth2": { | ||
4061 | + "version": "1.1.2", | ||
4062 | + "resolved": "https://registry.npmjs.org/passport-oauth2/-/passport-oauth2-1.1.2.tgz", | ||
4063 | + "integrity": "sha1-vXFjsbYJA3GGjcTvb58uHkzEuUg=", | ||
4064 | + "requires": { | ||
4065 | + "oauth": "0.9.x", | ||
4066 | + "passport-strategy": "1.x.x", | ||
4067 | + "uid2": "0.0.x" | ||
4068 | + } | ||
4069 | + } | ||
4070 | + } | ||
4071 | + }, | ||
4020 | "passport-local": { | 4072 | "passport-local": { |
4021 | "version": "1.0.0", | 4073 | "version": "1.0.0", |
4022 | "resolved": "https://registry.npmjs.org/passport-local/-/passport-local-1.0.0.tgz", | 4074 | "resolved": "https://registry.npmjs.org/passport-local/-/passport-local-1.0.0.tgz", |
... | @@ -4102,6 +4154,11 @@ | ... | @@ -4102,6 +4154,11 @@ |
4102 | "integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==", | 4154 | "integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==", |
4103 | "dev": true | 4155 | "dev": true |
4104 | }, | 4156 | }, |
4157 | + "pkginfo": { | ||
4158 | + "version": "0.3.1", | ||
4159 | + "resolved": "https://registry.npmjs.org/pkginfo/-/pkginfo-0.3.1.tgz", | ||
4160 | + "integrity": "sha1-Wyn2qB9wcXFC4J52W76rl7T4HiE=" | ||
4161 | + }, | ||
4105 | "prepend-http": { | 4162 | "prepend-http": { |
4106 | "version": "2.0.0", | 4163 | "version": "2.0.0", |
4107 | "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", | 4164 | "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", | ... | ... |
... | @@ -19,6 +19,7 @@ | ... | @@ -19,6 +19,7 @@ |
19 | "express": "^4.17.1", | 19 | "express": "^4.17.1", |
20 | "express-flash": "^0.0.2", | 20 | "express-flash": "^0.0.2", |
21 | "fs": "^0.0.1-security", | 21 | "fs": "^0.0.1-security", |
22 | + "passport-kakao": "^1.0.1", | ||
22 | "passport-naver": "^1.0.6", | 23 | "passport-naver": "^1.0.6", |
23 | "path": "^0.12.7", | 24 | "path": "^0.12.7", |
24 | "request": "^2.88.2", | 25 | "request": "^2.88.2", | ... | ... |
1 | -{"cookie":{"originalMaxAge":null,"expires":null,"httpOnly":true,"path":"/"},"flash":{"error":["Missing username or password."]},"__lastAccess":1638110555478} | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
1 | +{"cookie":{"originalMaxAge":null,"expires":null,"httpOnly":true,"path":"/"},"flash":{"error":["Missing username or password."]},"__lastAccess":1638446277022} | ||
... | \ No newline at end of file | ... | \ No newline at end of file | ... | ... |
-
Please register or login to post a comment