From 805e79983c6bc3e549c3268a727ebf56dfa530f8 Mon Sep 17 00:00:00 2001 From: Ilya Mikhailov Date: Wed, 21 Jan 2015 11:20:43 +0400 Subject: [PATCH 1/9] auth basics are implemented --- app.js | 15 ++++++++ assets/i/github-loagind.gif | Bin 0 -> 98455 bytes assets/js/modules/auth.js | 43 +++++++++++++++++++++ assets/templates/auth-done.ejs | 15 ++++++++ assets/templates/header.inc.html | 20 +++++++++- core/auth.js | 64 +++++++++++++++++++++++++++++++ 6 files changed, 156 insertions(+), 1 deletion(-) create mode 100644 assets/i/github-loagind.gif create mode 100644 assets/js/modules/auth.js create mode 100644 assets/templates/auth-done.ejs create mode 100644 core/auth.js diff --git a/app.js b/app.js index ca16383..7fd6179 100644 --- a/app.js +++ b/app.js @@ -50,6 +50,21 @@ global.app.use(require('compression')()); // Cookies global.app.use(require('cookie-parser')()); +global.app.use(require('express-session')({ + secret: (function() { + var d = new Date().getTime(); + return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) { + var r = (d + Math.random() * 16) % 16 | 0; + d = Math.floor(d / 16); + return (c === 'x' ? r : (r & 0x3 | 0x8)).toString(16); + }); + })(), + resave: false, + saveUninitialized: true +})); + +require('./core/auth')(app); + app.use(function (req, res, next) { res.cookie('source-mode', global.MODE, { maxAge: 3600000, httpOnly: false }); diff --git a/assets/i/github-loagind.gif b/assets/i/github-loagind.gif new file mode 100644 index 0000000000000000000000000000000000000000..f08ac50e14262768ece4c4d56e461dd8a7fec41e GIT binary patch literal 98455 zcmaI6cT`i+w=SB51VRteK_pb^gdVD)cL>sZ=)L!9=p8~)K|tvpL_jGbhTajSHwEcU zQHr1-&)<3XocsQ`_wBLA*lW!_=QrnE``dGkvDQ-8R6|PJVF|DVzit69-ZviaBMod`h`|5>fUVu5^EmF- z;f|MYKejca78e#CqS50Y*Vymfi^#0?@{n%p9=`*Fbq~x)Ng*?83k)n=%pCkfLqa6A zM2i}S^n;a^R5aM(@YyK^Z&kjEw(; zkdRwDIrlZyNHDj!p|-BpzCcHqjX9^XclXC=Mp;ixT48zP``z!IPjXRqZovV`A)X3;XX&Ea6&DHPg&LC}e zLG}_Gp}eSIgqS2P6Rm57-us?FOOIIUJ5&j6aqHX1v03Fd))I+9-Wi$Mhh-^TyaJs= z3mjbB3Z}@Dru^Js?}Gwgd+!(q28NdA=9Nu+ePe5UMll%)G36bq5^OLzC55G#X+Ryu z*3Ito=CP@T-6MA=Zf-UMD?>L=m+YLUWfir#&U(!E?uDnm$nGqQOw6UGrHMAxHZ?W3 zvT<73I3^||t$l?b(UC!+6l~N`FJ2Cpz8Ynqql4eOmz7_`bD!r$bw^FdRAuAal`lI8 zVWINIw=fFwU%xJUM;DqqhS$G*VPU@eY3?%t82qe$Fut(!_V$+TmQ+vG$WU1kttu*n zAo#~^z(0|hE*h?47ijnIDfb}M*UrJiDG+Y&^+qddE*gf2qYSJ}zc zO(Wdj$uL~c$RXUrLE4f1fdX7ER3_BR*UKr;4j$^|=^Y>wD$j1`=wt6B^RN9Mu`oOQ zzf=M}~aN+W+$PuP4v$8W`v+BP<*e5+W2LCgkJqA}k^;E&U%1QBlEv z8iD~~-hp20qMf}@P@p{fzexYz6uf-@2i7}4=)ckt za`5pI4z=?Y77;@HC#C;Z)Ybj}SM~DxAMJp^hfe=H-v1+TfKiyQlkh{Q0G}X#2d97P z9RG3UE2Hf1WEbe;Z{*|S`QM|6cJ&GL32^oCg)19M!g+M<9NfJBBjEin3te3qP49p} zJ8uUkO%-|ee;7h;ZjLf)(o!O7(qa{oX(e$bRSD#O+p73D z1bI1m2mZIMIjZ^lc)|ZGX&JZwLo8AvN}`Ggk^ej1 z|FU)bzsDl}e~m@>UogV|`LzF^PyOGbfBgAR^M8o@uk%0Dck=$ncmIFH2HyU?x&HI} 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%0AxpXM;ns z$M>?5iqHHRF)~@IHt;Utz012{YuSd^=Y8=ffm`pJ-%ADzmk)gv39TLc@diDR@1rA< zFuLrR401WLp_%hX$szsqCbynH-H*7DLCKtCc-Wi}G~C^+emd{8O^VgQ(U&zx;|^I~`%?3tql^WMRI#b{XI|*M4|9j*Aol zBO`!`4ANFK*75Zlx{5G1QL;I7DC7pmvL5VIPw+w370^!qJd#8EwUpq#^;k-9%$!=V zqXBt3Rvj8qSC2`pghhXYAU^>O7(SG?hjta3aUMX@uPrB9$$b69@QMP=7VWGIxF0v@ z(&8bB(aKZk2$>rYZzkFFCQ#`B_yKIG(oTzlBg8YY485@Rtb;2kPzI%b8l$8#O_**s zAn_CP>dgq*8xa1frnq*LyAvKI2W8<5VT%!t$~_w8l!PT)5he`tYK0Me!{w)Skj@$< z&B%;Wx&o!#yb<4gSt5o(T#qU5Pc^q_Xb*^XY``qPdBZyjcwP}kEQ=M=9^+^&bhIBK z+zWVnMMB6QOTMW_dL1iV7&|2r=Sr@89!WO0Y3$99J68z)BdXw`XIbx0+3FuNY8+R7 z0C?m?)+#Fx$ByA`M%B%{nZQGBI^w}^5ZY|9B{Xr2VJ<(e5#lq^Pm)01+Q@4o6PyMD z(iS|>VtiMW%TZfghcOUcigDf^MqH>vgNHozv*zYc`neAP-jF;LDBIYByARNlcp4V0 zG3CYyOtXZT0ikK7=&>zAZjV@*1Az6t6PW=lF5H-7_y9mT3LvKq?Gz(@vB@)W0C=B? zwb)F^B#u$GME3L>&<~Qb)}TMt4=4l2GchG>W-2C&MH8d3)|&%OqN5(qVsUY%M>i8b zQ%Mp>WAY0ST54x_^Al1>pbVpFF6%LWRHRO}!*#9k>Htx;w06HXc>}IH_ zU`dLZN}r_aM1#u;Gp7s??4Aty?=vz;(``882%z!{16k})GwH$v|4flgKW(OfEK
  • ?lI&`M5`AS?3Dle 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%0Am=0uhS!Lsy18KiWFo; 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 ByUhRq literal 0 HcmV?d00001 diff --git a/assets/js/modules/auth.js b/assets/js/modules/auth.js new file mode 100644 index 0000000..672a69f --- /dev/null +++ b/assets/js/modules/auth.js @@ -0,0 +1,43 @@ +define(['jquery'], function($) { + "use strict"; + + var _userStorageKey = 'sourcejsUser'; + + var auth = function() { + open('/auth/stub', 'popup', 'width=1015,height=500'); + }; + + var drawLoginControl = function() { + if (isLoginned()) { + console.log('drawLogined', getUser()); + } else { + console.log('drawUnlogined', getUser()); + } + }; + + var authCallback = function(user) { + localStorage.setItem(_userStorageKey, user); + drawLoginControl(); + }; + + var unAuth = function() { + localStorage.removeItem(_userStorageKey); + drawLoginControl(); + }; + + var isLoginned = function() { + return !!localStorage['user']; + }; + + var getUser = function() { + return JSON.parse(localStorage.getItem(_userStorageKey) || ""); + }; + + return { + "login": auth, + "logout": unAuth, + "isLoginned": isLoginned, + "getUser": getUser, + "done": authCallback + }; +}); \ No newline at end of file diff --git a/assets/templates/auth-done.ejs b/assets/templates/auth-done.ejs new file mode 100644 index 0000000..6f6a53f --- /dev/null +++ b/assets/templates/auth-done.ejs @@ -0,0 +1,15 @@ + + + Github OAuth + + + + Loading + + diff --git a/assets/templates/header.inc.html b/assets/templates/header.inc.html index bb5a402..87fede1 100644 --- a/assets/templates/header.inc.html +++ b/assets/templates/header.inc.html @@ -17,7 +17,25 @@
  • Link
  • + - + \ No newline at end of file diff --git a/core/auth.js b/core/auth.js new file mode 100644 index 0000000..8981ead --- /dev/null +++ b/core/auth.js @@ -0,0 +1,64 @@ +module.exports = function(app) { + "use strict"; + + var everyauth = require('everyauth'); + var fs = require('fs'); + var path = require('path'); + + app.states = app.states || {}; + app.states.users = app.states.users || {}; + + var currentUserId = ""; + + // users data processing + var getUser = function(id) { + id = id; + return app.states.users[id]; + }; + + var setUser = function(user) { + app.states.users[user.id] = user; + return user; + }; + + // TODO: remove debug mode or change it according to current environment + everyauth.debug = true; + + everyauth.everymodule.findUserById(function(id, callback) { + console.log('findUserById', id); + console.log(callback); + callback(null, getUser(id)); + }); + + // TODO: separated id & secret for dev mode + everyauth.github + .appId(global.opts.github.appId) + .appSecret(global.opts.github.appSecret) + .findOrCreateUser(function(sess, accessToken, accessTokenExtra, ghUser) { + setUser(ghUser); + currentUserId = ghUser.id; + return ghUser;//getUser(ghUser.id) || setUser(ghUser); + }) + .redirectPath('/auth/done'); + + + everyauth.everymodule.handleLogout( function (req, res) { + delete req.session.authCache; + req.logout(); + this.redirect(res, this.logoutRedirectPath()); + }); + + // application routes + var authTemplate = fs.readFileSync(path.join(global.pathToApp, '/assets/templates/auth-done.ejs'), "utf8"); + app.get('/auth/stub', function (req, res) { + res.send(require('ejs').render(authTemplate, {'user': "{}"})); + }); + + app.get('/auth/done', function (req, res) { + req.session.authCache = req.session.auth; + res.send(require('ejs').render(authTemplate, {'user': JSON.stringify(getUser(currentUserId))})); + }); + + app.use(everyauth.middleware()); + +}; \ No newline at end of file From bfd244c28fe04decd103f9df8d27c084bc79f8a5 Mon Sep 17 00:00:00 2001 From: Ilya Mikhailov Date: Wed, 21 Jan 2015 15:45:58 +0400 Subject: [PATCH 2/9] auth draft is ready --- assets/css/defaults.less | 1 + assets/css/project/auth.less | 31 +++++++++++++++++++++++++ assets/i/unknown.gif | Bin 0 -> 1062 bytes assets/js/modules/auth.js | 38 +++++++++++++++++++------------ assets/templates/auth-done.ejs | 10 +++++++- assets/templates/header.inc.html | 21 ++++++++--------- core/auth.js | 14 ++++++------ options.js | 4 ++++ 8 files changed, 86 insertions(+), 33 deletions(-) create mode 100644 assets/css/project/auth.less create mode 100644 assets/i/unknown.gif diff --git a/assets/css/defaults.less b/assets/css/defaults.less index 1f45268..440459d 100644 --- a/assets/css/defaults.less +++ b/assets/css/defaults.less @@ -31,6 +31,7 @@ @import url('project/modal.less'); @import url('project/autocomplete.less'); @import url('project/clarify-in-spec.less'); +@import url('project/auth.less'); //Cosmetic @import url('cosmetic/highlights.less'); diff --git a/assets/css/project/auth.less b/assets/css/project/auth.less new file mode 100644 index 0000000..3ffeece --- /dev/null +++ b/assets/css/project/auth.less @@ -0,0 +1,31 @@ +.sjs-login { + display: inline-block; + height: 40px; + float: right; + + margin-top: 2px; + vertical-align: top; + } + + .sjs-login-avatar { + width: 25px; + height: 25px; + + border-radius: 50%; + border: 1px solid #FFF; + cursor: pointer; + } + + .sjs-login-button { + display: inline-block; + + color: #999; + text-decoration: none; + line-height: 1; + cursor: pointer; + vertical-align: top; + margin: 5px 0px 0px 10px; + } + .sjs-login-button:hover { + color: #FFF + } \ No newline at end of file diff --git a/assets/i/unknown.gif b/assets/i/unknown.gif new file mode 100644 index 0000000000000000000000000000000000000000..9cc7478da240356d0ea5295b2c504b63dbde3018 GIT binary patch literal 1062 zcmV+>1ljvXNk%w1VSoUD0M!5h?d|Q=)z#kK-sR=x`1ttS+uQH&@BIAy_4W1c?(X~h z`{(E9+1c6C)6>Vt$IZ>n*x1gwv++S=06()#-P^78WN=;-0$;q2_}_xJbYU3i*VpUo>+taK|NsBR#l-*s000000000000000000000000000000 z00000A^8LV00000EC2ui0Du61000L6z?yJKEE41ejE#Un4-~rn0*J6>u03-J^yS%K>;4AY;ILivW70H;|EoQX|_{0JW$= z%6$zO33y3Q0HXyo+bv*ZAZI!M1B@p4BsYPPf}z|LFp7Y5TZE-er#)SCG-@)Xi-cN5 zR&-I%t-pXS!U@*b&P6lJ*0R}BZLOG#PP$FCvXRKSrb;sEh}RUzMHtm?l-SpzBZhM! zx+RbIqf4Joy}B6*9t2nbKmx@j8kta#0AN9Y z2MN}RNMJA^1MF!BG7MmVUV4WRAJ`ov@F7Hp+#+aD+DHg!Ai`(?lrREPBa~p=BMp@B z9#RLC0M{cAXrLch1ZXh-+ae)k&=(CEgs{j37GN-r?-Aeq!?-S+D?yObU=cz^pN1_7r`Q14zXNpAfmJFWbkVjEl|5p3txz-Z8C## z;la22c+dq|(LESW{K?{WjJ6=f| g@HAps!NI=^Z-c>?RnQx;H1|d!!^PytutX35JLFLWNdN!< literal 0 HcmV?d00001 diff --git a/assets/js/modules/auth.js b/assets/js/modules/auth.js index 672a69f..a757aea 100644 --- a/assets/js/modules/auth.js +++ b/assets/js/modules/auth.js @@ -2,42 +2,52 @@ define(['jquery'], function($) { "use strict"; var _userStorageKey = 'sourcejsUser'; + var loginWrapperSelector = '.sjs-login'; + var defaultAvatarURL = '/source/assets/i/unknown.gif'; + var labels = { + login: "Login", + logout: "Logout" + }; + var popup; - var auth = function() { - open('/auth/stub', 'popup', 'width=1015,height=500'); + var login = function() { + popup = open('/auth/stub', 'popup', 'width=1015,height=500'); }; var drawLoginControl = function() { - if (isLoginned()) { - console.log('drawLogined', getUser()); - } else { - console.log('drawUnlogined', getUser()); - } + var $wrapper = $(loginWrapperSelector); + var user = getUser(); + $wrapper + .html('') + .append($('')) + .append($('')); }; var authCallback = function(user) { - localStorage.setItem(_userStorageKey, user); + popup.close(); + localStorage.setItem(_userStorageKey, JSON.stringify(user)); drawLoginControl(); }; - var unAuth = function() { + var logout = function() { localStorage.removeItem(_userStorageKey); drawLoginControl(); }; var isLoginned = function() { - return !!localStorage['user']; + return !!localStorage[_userStorageKey]; }; var getUser = function() { - return JSON.parse(localStorage.getItem(_userStorageKey) || ""); + return JSON.parse(localStorage.getItem(_userStorageKey) || "{}"); }; return { - "login": auth, - "logout": unAuth, + "login": login, + "logout": logout, "isLoginned": isLoginned, "getUser": getUser, - "done": authCallback + "done": authCallback, + "drawControls": drawLoginControl }; }); \ No newline at end of file diff --git a/assets/templates/auth-done.ejs b/assets/templates/auth-done.ejs index 6f6a53f..4848a2f 100644 --- a/assets/templates/auth-done.ejs +++ b/assets/templates/auth-done.ejs @@ -9,7 +9,15 @@ Loading diff --git a/assets/templates/header.inc.html b/assets/templates/header.inc.html index 87fede1..46bed5d 100644 --- a/assets/templates/header.inc.html +++ b/assets/templates/header.inc.html @@ -17,25 +17,24 @@
  • Link
  • - + \ No newline at end of file diff --git a/core/auth.js b/core/auth.js index 8981ead..5f4dd7d 100644 --- a/core/auth.js +++ b/core/auth.js @@ -21,12 +21,7 @@ module.exports = function(app) { return user; }; - // TODO: remove debug mode or change it according to current environment - everyauth.debug = true; - everyauth.everymodule.findUserById(function(id, callback) { - console.log('findUserById', id); - console.log(callback); callback(null, getUser(id)); }); @@ -51,12 +46,17 @@ module.exports = function(app) { // application routes var authTemplate = fs.readFileSync(path.join(global.pathToApp, '/assets/templates/auth-done.ejs'), "utf8"); app.get('/auth/stub', function (req, res) { - res.send(require('ejs').render(authTemplate, {'user': "{}"})); + res.send(require('ejs').render(authTemplate, { + 'user': JSON.stringify({}) + })); }); app.get('/auth/done', function (req, res) { req.session.authCache = req.session.auth; - res.send(require('ejs').render(authTemplate, {'user': JSON.stringify(getUser(currentUserId))})); + + res.send(require('ejs').render(authTemplate, { + 'user': JSON.stringify(getUser(currentUserId)) + })); }); app.use(everyauth.middleware()); diff --git a/options.js b/options.js index d80ff24..de43405 100644 --- a/options.js +++ b/options.js @@ -84,5 +84,9 @@ module.exports = { pluginsEnabled: {}, npmPluginsEnabled: {} } + }, + github: { + appId: "1a203d58ae8cc1e0366f", + appSecret: "572aeb73c2602d1778ca308c0f42ae81d7c54b08" } }; \ No newline at end of file From a9556e5dea83768ab89fc447439a81402f42e7d2 Mon Sep 17 00:00:00 2001 From: Ilya Mikhailov Date: Wed, 21 Jan 2015 18:18:53 +0400 Subject: [PATCH 3/9] auth module structure is improved a bit --- assets/js/modules/auth.js | 140 +++++++++++++++++++++---------- assets/templates/auth-done.ejs | 6 +- assets/templates/header.inc.html | 18 +--- core/auth.js | 3 +- 4 files changed, 107 insertions(+), 60 deletions(-) diff --git a/assets/js/modules/auth.js b/assets/js/modules/auth.js index a757aea..61b9c5f 100644 --- a/assets/js/modules/auth.js +++ b/assets/js/modules/auth.js @@ -1,53 +1,107 @@ -define(['jquery'], function($) { - "use strict"; - - var _userStorageKey = 'sourcejsUser'; - var loginWrapperSelector = '.sjs-login'; - var defaultAvatarURL = '/source/assets/i/unknown.gif'; - var labels = { - login: "Login", - logout: "Logout" - }; - var popup; +define([ + 'jquery', + 'sourceModules/module' +], function($, module) { + + 'use strict'; - var login = function() { - popup = open('/auth/stub', 'popup', 'width=1015,height=500'); + /** + * @Object default module option values + */ + var defaults = { + 'storageKey': 'sourcejsUser', + 'defaultAvatarURL': '/source/assets/i/unknown.gif', + 'classes': { + 'controlsWrapper': 'sjs-login', + 'loginButton': 'sjs-login-button', + 'avatar': 'sjs-login-avatar' + }, + 'labels': { + 'login': 'Login', + 'logout': 'Logout' + } }; - var drawLoginControl = function() { - var $wrapper = $(loginWrapperSelector); - var user = getUser(); - $wrapper - .html('') - .append($('')) - .append($('')); - }; + /** + * @constructor Auth + * @param [Object] config - auth inline configuration set of options + * @param [Object] config.target - jquery domElement which goes to be auth controlls container + * @param [Object] config.options - options set + */ - var authCallback = function(user) { - popup.close(); - localStorage.setItem(_userStorageKey, JSON.stringify(user)); - drawLoginControl(); - }; + function Auth(config) { + var _this = this; - var logout = function() { - localStorage.removeItem(_userStorageKey); - drawLoginControl(); - }; + this.conf = $.extend(true, {}, + defaults, + config.options + ); - var isLoginned = function() { - return !!localStorage[_userStorageKey]; - }; + this.target = config.target || $(this.conf.classes.controlsWrapper); + this.popup; - var getUser = function() { - return JSON.parse(localStorage.getItem(_userStorageKey) || "{}"); - }; + $(function() { + _this.init(); + }); + } + + + Auth.prototype = module.createInstance(); + Auth.prototype.constructor = Auth; + + Auth.renderers = {}; - return { - "login": login, - "logout": logout, - "isLoginned": isLoginned, - "getUser": getUser, - "done": authCallback, - "drawControls": drawLoginControl + Auth.prototype = { + login: function() { + this.popup = open('/auth/stub', 'popup', 'width=1015,height=500'); + }, + + init: function() { + var self = window.__auth = this; + this.render(); + + $('body').on('click', '.' + this.conf.classes.loginButton, function(e) { + e.preventDefault(); + if (self.isLoginned()) { + self.logout(); + } else { + self.login(); + } + }); + }, + + render: function() { + var user = this.getUser(); + this.target.html('') + .append($('' + )) + .append($('
    ' + + (!!user.id ? this.conf.labels.logout : this.conf.labels.login) + + '
    ' + )); + }, + + logout: function() { + localStorage.removeItem(this.conf.storageKey); + this.render(); + }, + + isLoginned: function() { + return !!localStorage[this.conf.storageKey]; + }, + + getUser: function() { + return JSON.parse(localStorage.getItem(this.conf.storageKey) || "{}"); + }, + + done: function(user) { + this.popup.close(); + localStorage.setItem(this.conf.storageKey, JSON.stringify(user)); + this.render(); + } }; + + return Auth; }); \ No newline at end of file diff --git a/assets/templates/auth-done.ejs b/assets/templates/auth-done.ejs index 4848a2f..dd2e4f7 100644 --- a/assets/templates/auth-done.ejs +++ b/assets/templates/auth-done.ejs @@ -12,11 +12,13 @@ var data; try { data = JSON.parse("<%= user %>".split(""").join('"')); - } catch(e) {} + } catch(e) { + console.log('incorrect user data', e); + } if (!data instanceof Object || !data.id) { window.location = "/auth/github"; } else { - opener.__auth.done(data) + opener.__auth.done(data); } }); diff --git a/assets/templates/header.inc.html b/assets/templates/header.inc.html index 46bed5d..68c70dc 100644 --- a/assets/templates/header.inc.html +++ b/assets/templates/header.inc.html @@ -21,20 +21,10 @@ \ No newline at end of file diff --git a/core/auth.js b/core/auth.js index 5f4dd7d..13c35e7 100644 --- a/core/auth.js +++ b/core/auth.js @@ -8,6 +8,7 @@ module.exports = function(app) { app.states = app.states || {}; app.states.users = app.states.users || {}; + //TODO: wrong! var currentUserId = ""; // users data processing @@ -32,7 +33,7 @@ module.exports = function(app) { .findOrCreateUser(function(sess, accessToken, accessTokenExtra, ghUser) { setUser(ghUser); currentUserId = ghUser.id; - return ghUser;//getUser(ghUser.id) || setUser(ghUser); + return ghUser; }) .redirectPath('/auth/done'); From d37bbb8d07cdec64c093af3c796f017bfca33b38 Mon Sep 17 00:00:00 2001 From: Ilya Mikhailov Date: Wed, 21 Jan 2015 18:47:49 +0400 Subject: [PATCH 4/9] missed renderers are added --- assets/js/modules/auth.js | 34 +++++++++++++++++++++++----------- 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/assets/js/modules/auth.js b/assets/js/modules/auth.js index 61b9c5f..9a3bf08 100644 --- a/assets/js/modules/auth.js +++ b/assets/js/modules/auth.js @@ -49,7 +49,20 @@ define([ Auth.prototype = module.createInstance(); Auth.prototype.constructor = Auth; - Auth.renderers = {}; + Auth.renderers = { + 'avatar': function() { + this.target.append($('' + )); + }, + 'loginButton': function() { + this.target.append($('
    ' + + (!!this.user.id ? this.conf.labels.logout : this.conf.labels.login) + + '
    ' + )); + } + }; Auth.prototype = { login: function() { @@ -59,7 +72,6 @@ define([ init: function() { var self = window.__auth = this; this.render(); - $('body').on('click', '.' + this.conf.classes.loginButton, function(e) { e.preventDefault(); if (self.isLoginned()) { @@ -72,15 +84,15 @@ define([ render: function() { var user = this.getUser(); - this.target.html('') - .append($('' - )) - .append($('
    ' - + (!!user.id ? this.conf.labels.logout : this.conf.labels.login) - + '
    ' - )); + var _this = this; + this.target.html(''); + Object.keys(Auth.renderers).forEach(function(name) { + Auth.renderers[name].call({ + 'target': _this.target, + 'user': user, + 'conf': _this.conf + }); + }); }, logout: function() { From 1b51534c2c67fd63a2dc0f89e7389645457b8b5c Mon Sep 17 00:00:00 2001 From: Ilya Mikhailov Date: Thu, 5 Feb 2015 11:20:18 +0400 Subject: [PATCH 5/9] comments are added; demo key is added --- assets/js/modules/auth.js | 37 ++++++++++++++++++++++++++++++++----- options.js | 8 +++++++- 2 files changed, 39 insertions(+), 6 deletions(-) diff --git a/assets/js/modules/auth.js b/assets/js/modules/auth.js index 9a3bf08..4df15e8 100644 --- a/assets/js/modules/auth.js +++ b/assets/js/modules/auth.js @@ -23,10 +23,15 @@ define([ }; /** - * @constructor Auth + * @module Auth - basic GitHub authorization module. + * + * @constructor + * * @param [Object] config - auth inline configuration set of options + * * @param [Object] config.target - jquery domElement which goes to be auth controlls container - * @param [Object] config.options - options set + * + * @param [Object] config.options - options set, which allows to define component configuration. */ function Auth(config) { @@ -52,19 +57,24 @@ define([ Auth.renderers = { 'avatar': function() { this.target.append($('' )); }, 'loginButton': function() { this.target.append($('
    ' - + (!!this.user.id ? this.conf.labels.logout : this.conf.labels.login) + + (this.user && this.user.id ? this.conf.labels.logout : this.conf.labels.login) + '
    ' )); } }; Auth.prototype = { + + /** + * @method Auth.login. + * This function initiates logging in process and creates github login popup. + */ login: function() { this.popup = open('/auth/stub', 'popup', 'width=1015,height=500'); }, @@ -95,17 +105,34 @@ define([ }); }, + /** + * @method Auth.logout. + * This method removes existed user entity and refreshes control. + */ logout: function() { localStorage.removeItem(this.conf.storageKey); this.render(); }, + /** + * @method Auth.isLoginned User state getter. + * + * @returns {Boolean} isLoginned. It returns true if user is loginned. + */ isLoginned: function() { return !!localStorage[this.conf.storageKey]; }, + /** + * @method Auth.getUser GitHub user entity getter. + * + * @returns {Object} user || null. + * If user is loginned it returns user object and null in other case. + */ getUser: function() { - return JSON.parse(localStorage.getItem(this.conf.storageKey) || "{}"); + return this.isLoginned() + ? JSON.parse(localStorage.getItem(this.conf.storageKey)) + : null; }, done: function(user) { diff --git a/options.js b/options.js index de43405..4fffc8f 100644 --- a/options.js +++ b/options.js @@ -85,8 +85,14 @@ module.exports = { npmPluginsEnabled: {} } }, + /* + * Please pay your attention. This is demo github applicatio key. + * To get your own one please use github applications service. + * Please visit this link to get more information: + * https://developer.github.com/guides/basics-of-authentication/#registering-your-app + */ github: { - appId: "1a203d58ae8cc1e0366f", + appId: "a05d80a72d360fba596f", appSecret: "572aeb73c2602d1778ca308c0f42ae81d7c54b08" } }; \ No newline at end of file From fd8cb758ceb5fa76be1e28583cefaaf798eb7ee0 Mon Sep 17 00:00:00 2001 From: Robert Haritonov Date: Thu, 5 Feb 2015 22:18:37 +0100 Subject: [PATCH 6/9] missed deps --- package.json | 2 ++ 1 file changed, 2 insertions(+) diff --git a/package.json b/package.json index 1c96ded..942ed45 100755 --- a/package.json +++ b/package.json @@ -16,7 +16,9 @@ "cookie-parser": "~1.3.2", "deep-extend": "~0.2.11", "ejs": "~0.8.4", + "everyauth": "^0.4.9", "express": "~4.8.3", + "express-session": "^1.10.2", "extend": "~1.2.1", "flat": "^1.2.1", "fs-extra": "~0.11.1", From a25ceda7880ff8fe06fdb2e7a2fbfa5082559301 Mon Sep 17 00:00:00 2001 From: Ilya Mikhailov Date: Mon, 9 Feb 2015 13:02:32 +0400 Subject: [PATCH 7/9] CR fixes --- app.js | 5 +- assets/css/project/auth.less | 44 ++--- assets/js/enter-the-source.js | 11 +- assets/js/modules/auth.js | 153 +++++++++--------- assets/templates/header.inc.html | 9 +- core/auth.js | 32 +++- .../templates => core/views}/auth-done.ejs | 2 +- options.js | 3 +- 8 files changed, 143 insertions(+), 116 deletions(-) rename {assets/templates => core/views}/auth-done.ejs (93%) diff --git a/app.js b/app.js index 98dbdc8..e6ad2a6 100644 --- a/app.js +++ b/app.js @@ -64,7 +64,7 @@ global.app.use(require('express-session')({ saveUninitialized: true })); -require('./core/auth')(app); +var auth = require('./core/auth')(app); app.use(function (req, res, next) { res.cookie('source-mode', global.MODE, { maxAge: 3600000, httpOnly: false }); @@ -86,6 +86,9 @@ app.use(bodyParser.json()); /* Middlewares */ +// Auth initializing +app.use(auth.everyauth.middleware()); + // LESS processing if (global.MODE === 'development') { var less = require('less-middleware'); diff --git a/assets/css/project/auth.less b/assets/css/project/auth.less index 3ffeece..cf78d3f 100644 --- a/assets/css/project/auth.less +++ b/assets/css/project/auth.less @@ -2,30 +2,34 @@ display: inline-block; height: 40px; float: right; - + margin-top: 2px; vertical-align: top; } - .sjs-login-avatar { - width: 25px; - height: 25px; +.sjs-login-avatar { + width: 25px; + height: 25px; - border-radius: 50%; - border: 1px solid #FFF; - cursor: pointer; - } + border-radius: 50%; + border: 1px solid #FFF; + cursor: pointer; + } - .sjs-login-button { - display: inline-block; - - color: #999; - text-decoration: none; - line-height: 1; - cursor: pointer; - vertical-align: top; - margin: 5px 0px 0px 10px; + .sjs-login-avatar.anonymous { + border: 1px solid #333; } - .sjs-login-button:hover { - color: #FFF - } \ No newline at end of file + +.sjs-login-button { + display: inline-block; + + color: #999; + text-decoration: none; + line-height: 1; + cursor: pointer; + vertical-align: top; + margin: 5px 0px 0px 10px; + } + .sjs-login-button:hover { + color: #FFF + } \ No newline at end of file diff --git a/assets/js/enter-the-source.js b/assets/js/enter-the-source.js index 601db6b..b09ebab 100644 --- a/assets/js/enter-the-source.js +++ b/assets/js/enter-the-source.js @@ -8,7 +8,12 @@ require([ "jquery", "source/load-options", // TODO: remove when all modules inherit Module() "sourceModules/browser", - "sourceModules/moduleLoader" - ], function ($, options) { - + "sourceModules/moduleLoader", + 'sourceModules/auth', + ], function ($, options, browser, Loader, Auth) { + if (options && options.modulesEnabled && options.modulesEnabled.auth === true) { + new Auth({ + target: $('.sjs-login') + }); + } }); diff --git a/assets/js/modules/auth.js b/assets/js/modules/auth.js index 4df15e8..72990d8 100644 --- a/assets/js/modules/auth.js +++ b/assets/js/modules/auth.js @@ -1,7 +1,7 @@ define([ 'jquery', 'sourceModules/module' -], function($, module) { +], function($, Module) { 'use strict'; @@ -14,7 +14,8 @@ define([ 'classes': { 'controlsWrapper': 'sjs-login', 'loginButton': 'sjs-login-button', - 'avatar': 'sjs-login-avatar' + 'avatar': 'sjs-login-avatar', + 'anonymous': 'anonymous' }, 'labels': { 'login': 'Login', @@ -39,7 +40,8 @@ define([ this.conf = $.extend(true, {}, defaults, - config.options + config.options, + this.options.modulesOptions.auth ); this.target = config.target || $(this.conf.classes.controlsWrapper); @@ -50,96 +52,95 @@ define([ }); } - - Auth.prototype = module.createInstance(); + Auth.prototype = Module.createInstance(); Auth.prototype.constructor = Auth; Auth.renderers = { 'avatar': function() { - this.target.append($('' + var hasAvatar = this.user && this.user.avatar_url; + this.target.append($([''].join('') )); }, 'loginButton': function() { - this.target.append($('
    ' - + (this.user && this.user.id ? this.conf.labels.logout : this.conf.labels.login) - + '
    ' + this.target.append($(['
    ', + (this.user && this.user.id ? this.conf.labels.logout : this.conf.labels.login), + '
    '].join('') )); } }; - Auth.prototype = { - - /** - * @method Auth.login. - * This function initiates logging in process and creates github login popup. - */ - login: function() { - this.popup = open('/auth/stub', 'popup', 'width=1015,height=500'); - }, + /** + * @method Auth.login. + * This function initiates logging in process and creates github login popup. + */ + Auth.prototype.login = function() { + this.popup = open('/auth/stub', 'popup', 'width=1015,height=500'); + }; - init: function() { - var self = window.__auth = this; - this.render(); - $('body').on('click', '.' + this.conf.classes.loginButton, function(e) { - e.preventDefault(); - if (self.isLoginned()) { - self.logout(); - } else { - self.login(); - } - }); - }, + /** + * @method Auth.logout. + * This method removes existed user entity and refreshes control. + */ + Auth.prototype.logout = function() { + localStorage.removeItem(this.conf.storageKey); + this.render(); + }; - render: function() { - var user = this.getUser(); - var _this = this; - this.target.html(''); - Object.keys(Auth.renderers).forEach(function(name) { - Auth.renderers[name].call({ - 'target': _this.target, - 'user': user, - 'conf': _this.conf - }); - }); - }, + /** + * @method Auth.isLoginned User state getter. + * + * @returns {Boolean} isLoginned. It returns true if user is loginned. + */ + Auth.prototype.isLoginned = function() { + return !!localStorage[this.conf.storageKey]; + }; - /** - * @method Auth.logout. - * This method removes existed user entity and refreshes control. - */ - logout: function() { - localStorage.removeItem(this.conf.storageKey); - this.render(); - }, + /** + * @method Auth.getUser GitHub user entity getter. + * + * @returns {Object} user || null. + * If user is loginned it returns user object and null in other case. + */ + Auth.prototype.getUser = function() { + return this.isLoginned() + ? JSON.parse(localStorage.getItem(this.conf.storageKey)) + : null; + }; - /** - * @method Auth.isLoginned User state getter. - * - * @returns {Boolean} isLoginned. It returns true if user is loginned. - */ - isLoginned: function() { - return !!localStorage[this.conf.storageKey]; - }, + Auth.prototype.init = function() { + window.sourcejs = window.sourcejs || {}; + var self = window.sourcejs.__auth = this; + this.render(); + $('body').on('click', '.' + this.conf.classes.loginButton, function(e) { + e.preventDefault(); + if (self.isLoginned()) { + self.logout(); + } else { + self.login(); + } + }); + }; - /** - * @method Auth.getUser GitHub user entity getter. - * - * @returns {Object} user || null. - * If user is loginned it returns user object and null in other case. - */ - getUser: function() { - return this.isLoginned() - ? JSON.parse(localStorage.getItem(this.conf.storageKey)) - : null; - }, + Auth.prototype.render = function() { + var user = this.getUser(); + var self = this; + this.target.html(''); + Object.keys(Auth.renderers).forEach(function(name) { + Auth.renderers[name].call({ + 'target': self.target, + 'user': user, + 'conf': self.conf + }); + }); + }; - done: function(user) { - this.popup.close(); - localStorage.setItem(this.conf.storageKey, JSON.stringify(user)); - this.render(); - } + Auth.prototype.done = function(user) { + this.popup.close(); + localStorage.setItem(this.conf.storageKey, JSON.stringify(user)); + this.render(); }; return Auth; diff --git a/assets/templates/header.inc.html b/assets/templates/header.inc.html index 68c70dc..66a1589 100644 --- a/assets/templates/header.inc.html +++ b/assets/templates/header.inc.html @@ -17,14 +17,7 @@
  • Link
  • - + - \ No newline at end of file diff --git a/core/auth.js b/core/auth.js index 13c35e7..9605559 100644 --- a/core/auth.js +++ b/core/auth.js @@ -3,21 +3,37 @@ module.exports = function(app) { var everyauth = require('everyauth'); var fs = require('fs'); + var ejs = require('ejs'); var path = require('path'); app.states = app.states || {}; app.states.users = app.states.users || {}; - //TODO: wrong! var currentUserId = ""; // users data processing + /** + * @method getUser - user getter + * + * @param {String} id - github user id + * + * @returns {Object} - user - github user entity or empty object, if user is undefined + */ var getUser = function(id) { - id = id; - return app.states.users[id]; + return app.states.users[id] || {}; }; + /** + * @method setUser - user setter + * + * @param {Object} user - github user entity + * + * @param {String} user.id - required user field, which is used as user templral storage key. + * + * @returns {Object} user - returns user parameter + */ var setUser = function(user) { + if (typeof user !== "object" || !user.id) return; app.states.users[user.id] = user; return user; }; @@ -45,7 +61,7 @@ module.exports = function(app) { }); // application routes - var authTemplate = fs.readFileSync(path.join(global.pathToApp, '/assets/templates/auth-done.ejs'), "utf8"); + var authTemplate = fs.readFileSync(path.join(global.pathToApp, '/core/views/auth-done.ejs'), "utf8"); app.get('/auth/stub', function (req, res) { res.send(require('ejs').render(authTemplate, { 'user': JSON.stringify({}) @@ -55,11 +71,15 @@ module.exports = function(app) { app.get('/auth/done', function (req, res) { req.session.authCache = req.session.auth; - res.send(require('ejs').render(authTemplate, { + res.send(ejs.render(authTemplate, { 'user': JSON.stringify(getUser(currentUserId)) })); }); - app.use(everyauth.middleware()); + return { + 'getUser': getUser, + 'setUser': setUser, + 'everyauth': everyauth + }; }; \ No newline at end of file diff --git a/assets/templates/auth-done.ejs b/core/views/auth-done.ejs similarity index 93% rename from assets/templates/auth-done.ejs rename to core/views/auth-done.ejs index dd2e4f7..677887f 100644 --- a/assets/templates/auth-done.ejs +++ b/core/views/auth-done.ejs @@ -18,7 +18,7 @@ if (!data instanceof Object || !data.id) { window.location = "/auth/github"; } else { - opener.__auth.done(data); + opener.sourcejs.__auth.done(data); } }); diff --git a/options.js b/options.js index 4fffc8f..54ceecb 100644 --- a/options.js +++ b/options.js @@ -44,7 +44,8 @@ module.exports = { globalNav: true, search: true, loadEvents: true, - navHighlight: true + navHighlight: true, + auth: false }, modulesOptions : { From 03847ad95b1f43d81eee122e9f4ccaed09200b24 Mon Sep 17 00:00:00 2001 From: Ilya Mikhailov Date: Mon, 16 Feb 2015 13:40:13 +0300 Subject: [PATCH 8/9] auth polishing --- app.js | 3 +-- assets/css/project/auth.less | 10 +++++----- assets/js/enter-the-source.js | 2 +- assets/js/modules/auth.js | 32 ++++++++++++++++++++------------ assets/templates/header.inc.html | 2 +- core/auth.js | 10 +++++----- options.js | 5 +++-- 7 files changed, 36 insertions(+), 28 deletions(-) diff --git a/app.js b/app.js index e6ad2a6..07e1170 100644 --- a/app.js +++ b/app.js @@ -64,8 +64,6 @@ global.app.use(require('express-session')({ saveUninitialized: true })); -var auth = require('./core/auth')(app); - app.use(function (req, res, next) { res.cookie('source-mode', global.MODE, { maxAge: 3600000, httpOnly: false }); @@ -87,6 +85,7 @@ app.use(bodyParser.json()); /* Middlewares */ // Auth initializing +var auth = require('./core/auth')(app); app.use(auth.everyauth.middleware()); // LESS processing diff --git a/assets/css/project/auth.less b/assets/css/project/auth.less index cf78d3f..994cafc 100644 --- a/assets/css/project/auth.less +++ b/assets/css/project/auth.less @@ -1,4 +1,4 @@ -.sjs-login { +.source_login { display: inline-block; height: 40px; float: right; @@ -7,7 +7,7 @@ vertical-align: top; } -.sjs-login-avatar { +.source_login-avatar { width: 25px; height: 25px; @@ -16,11 +16,11 @@ cursor: pointer; } - .sjs-login-avatar.anonymous { + .source_login-avatar.anonymous { border: 1px solid #333; } -.sjs-login-button { +.source_login-button { display: inline-block; color: #999; @@ -30,6 +30,6 @@ vertical-align: top; margin: 5px 0px 0px 10px; } - .sjs-login-button:hover { + .source_login-button:hover { color: #FFF } \ No newline at end of file diff --git a/assets/js/enter-the-source.js b/assets/js/enter-the-source.js index b09ebab..92cc5b7 100644 --- a/assets/js/enter-the-source.js +++ b/assets/js/enter-the-source.js @@ -13,7 +13,7 @@ require([ ], function ($, options, browser, Loader, Auth) { if (options && options.modulesEnabled && options.modulesEnabled.auth === true) { new Auth({ - target: $('.sjs-login') + target: $('.js-hook') }); } }); diff --git a/assets/js/modules/auth.js b/assets/js/modules/auth.js index 72990d8..dd5a117 100644 --- a/assets/js/modules/auth.js +++ b/assets/js/modules/auth.js @@ -12,10 +12,11 @@ define([ 'storageKey': 'sourcejsUser', 'defaultAvatarURL': '/source/assets/i/unknown.gif', 'classes': { - 'controlsWrapper': 'sjs-login', - 'loginButton': 'sjs-login-button', - 'avatar': 'sjs-login-avatar', - 'anonymous': 'anonymous' + 'controlsWrapper': 'source_login', + 'loginButton': 'source_login-button', + 'avatar': 'source_login-avatar', + 'anonymous': 'anonymous', + 'hook': 'js-hook' }, 'labels': { 'login': 'Login', @@ -44,7 +45,10 @@ define([ this.options.modulesOptions.auth ); - this.target = config.target || $(this.conf.classes.controlsWrapper); + this.target = config.target || $(this.conf.classes.hook); + if(!$(this.target).hasClass(this.conf.classes.controlsWrapper)) { + $(this.target).addClass(this.conf.classes.controlsWrapper); + } this.popup; $(function() { @@ -58,16 +62,20 @@ define([ Auth.renderers = { 'avatar': function() { var hasAvatar = this.user && this.user.avatar_url; - this.target.append($([''].join('') + this.target.append($([ + '' + ].join('') )); }, 'loginButton': function() { - this.target.append($(['
    ', - (this.user && this.user.id ? this.conf.labels.logout : this.conf.labels.login), - '
    '].join('') + this.target.append($([ + '
    ', + (this.user && this.user.id ? this.conf.labels.logout : this.conf.labels.login), + '
    ' + ].join('') )); } }; diff --git a/assets/templates/header.inc.html b/assets/templates/header.inc.html index 66a1589..455e794 100644 --- a/assets/templates/header.inc.html +++ b/assets/templates/header.inc.html @@ -17,7 +17,7 @@
  • Link
  • - + \ No newline at end of file diff --git a/core/auth.js b/core/auth.js index 9605559..07cbbc9 100644 --- a/core/auth.js +++ b/core/auth.js @@ -1,11 +1,11 @@ +var everyauth = require('everyauth'); +var fs = require('fs'); +var ejs = require('ejs'); +var path = require('path'); + module.exports = function(app) { "use strict"; - var everyauth = require('everyauth'); - var fs = require('fs'); - var ejs = require('ejs'); - var path = require('path'); - app.states = app.states || {}; app.states.users = app.states.users || {}; diff --git a/options.js b/options.js index 54ceecb..5e013c8 100644 --- a/options.js +++ b/options.js @@ -91,9 +91,10 @@ module.exports = { * To get your own one please use github applications service. * Please visit this link to get more information: * https://developer.github.com/guides/basics-of-authentication/#registering-your-app + * Current demo key is used in test mode for http://127.0.0.1:8080 */ github: { - appId: "a05d80a72d360fba596f", - appSecret: "572aeb73c2602d1778ca308c0f42ae81d7c54b08" + appId: "cf00a9e7ee5d9d6af36f", + appSecret: "aebe08e0aa66f6911e4f54df81ce64c9d6e0003b" } }; \ No newline at end of file From f3a4a80fc09be345402cab4deb3ba98ceb3aa27c Mon Sep 17 00:00:00 2001 From: Ilya Mikhailov Date: Mon, 16 Feb 2015 16:25:30 +0300 Subject: [PATCH 9/9] some polishing, auth description draft is added --- assets/js/enter-the-source.js | 2 +- assets/templates/header.inc.html | 2 +- docs/auth/index.src | 65 ++++++++++++++++++++++++++++++++ docs/auth/info.json | 4 ++ 4 files changed, 71 insertions(+), 2 deletions(-) create mode 100644 docs/auth/index.src create mode 100644 docs/auth/info.json diff --git a/assets/js/enter-the-source.js b/assets/js/enter-the-source.js index 92cc5b7..bc56341 100644 --- a/assets/js/enter-the-source.js +++ b/assets/js/enter-the-source.js @@ -13,7 +13,7 @@ require([ ], function ($, options, browser, Loader, Auth) { if (options && options.modulesEnabled && options.modulesEnabled.auth === true) { new Auth({ - target: $('.js-hook') + target: $('.js-hook.source_login') }); } }); diff --git a/assets/templates/header.inc.html b/assets/templates/header.inc.html index 455e794..7ff7e9f 100644 --- a/assets/templates/header.inc.html +++ b/assets/templates/header.inc.html @@ -17,7 +17,7 @@
  • Link
  • - + \ No newline at end of file diff --git a/docs/auth/index.src b/docs/auth/index.src new file mode 100644 index 0000000..d57a9ba --- /dev/null +++ b/docs/auth/index.src @@ -0,0 +1,65 @@ +

    Using Github Auth

    + +
    +

    Quick Start

    + +

    Before you start, please make sure that you have referenced GitHub App registered. Please visit this link to get more information.

    + +

    If you allready have registered app replace existed github api key and secret into your local options file, as mentioned here.

    + +

    Values, given below, are cretated as a demo. They are useble for local instance at 127.0.0.1:8080

    + + + github: { + appId: "cf00a9e7ee5d9d6af36f", + appSecret: "aebe08e0aa66f6911e4f54df81ce64c9d6e0003b" + } + + +

    Please take into account, that auth feature is turned off by default and you have to set related option: options.modulesEnabled.auth to true in your config.

    + +

    After that, auth feature is able to use.

    + + +

    Client-side auth controll.

    + +

    Github auth module includes client-side controll. It should be included into your header.inc.html (if you have the overriden one). Here is the example:

    + + + + + + +

    Auth uses js-hook and source_login classes for targeting. This hook is defined into /assets/js/enter-the-source.js file.

    +
    + +
    +

    Auth configuration

    +

    Auth configuration is availible from your instance options, as it was mentioned above. Here is the full options list:

    + +// localStorage key for client-side user object +'storageKey': 'sourcejsUser', +// avatar stub URL +'defaultAvatarURL': '/source/assets/i/unknown.gif', +// set of client-side control classes +'classes': { + 'controlsWrapper': 'source_login', + 'loginButton': 'source_login-button', + 'avatar': 'source_login-avatar', + 'anonymous': 'anonymous', + 'hook': 'js-hook' +}, +// login/logout button labels +'labels': { + 'login': 'Login', + 'logout': 'Logout' +} + +
    + +
    +

    Auth modules usage

    +

    Both server-side and client-side auth parts are able to use from other modules.

    +

    Server-side part provides The everyauth API whitch it is based on. Also there are methods either to get or to set GitHub user into temporary users storage.

    +

    Client-side part allows to login/logout using github, to check if user is logined and to get user data.

    +
    \ No newline at end of file diff --git a/docs/auth/info.json b/docs/auth/info.json new file mode 100644 index 0000000..f04fb2d --- /dev/null +++ b/docs/auth/info.json @@ -0,0 +1,4 @@ +{ + "keywords": "auth, github", + "title": "Github Auth" +}