Skip to content

Commit

Permalink
Delta-97 > Adjustments needed for login (#10)
Browse files Browse the repository at this point in the history
- Added support for args in $t filter
- Added jwt plugin
- Adjusted google api plugin

Approved by:
- @cedricabuso <[email protected]>
- @wilbertverayin <[email protected]>
  • Loading branch information
Ferriel Melarpis authored Feb 6, 2018
1 parent 95f61de commit 5c54c12
Show file tree
Hide file tree
Showing 14 changed files with 227 additions and 110 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
"i18next": "^10.2.2",
"i18next-browser-languagedetector": "^2.1.0",
"i18next-xhr-backend": "^1.5.1",
"jsonwebtoken": "^8.1.1",
"lodash": "^4.17.4",
"moment": "^2.20.1",
"qs": "^6.5.1",
Expand Down
6 changes: 5 additions & 1 deletion src/config/google-api.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,9 @@ export default {
scope: [
'email',
'profile',
],
].join(' '),
libraries: [
'client',
'auth2'
].join(':'),
};
4 changes: 3 additions & 1 deletion src/config/index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
export default {
server: {
baseURL: '',
}
},

ACCESS_TOKEN_KEY: '',
};
68 changes: 20 additions & 48 deletions src/helpers/google-api-client.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import _ from 'lodash';

/**
* Helper class for using google api from CDN
*/
Expand All @@ -12,19 +14,17 @@ export default class GoogleAPIClient {
* @param {string[]} options.scope - The scopes to request.
*/
constructor(options) {
this._apiKey = options.apiKey;
this._clientId = options.clientId;
this._discoveryDocs = options.discoveryDocs;
this._scope = options.scope.join(' ');
this._libraries = ['client', 'auth2'];
this._options = options;
}

/**
* Injects google api script from cdn
* @param {string} clientURL - The CDN for the google api client to be used.
* @param {Object} param
* @param {string} param.clientURL - The CDN for the google api client to be used.
* @param {string} param.libraries - Google API client libraries to be loaded.
* @return {Promise<any>}
*/
static load(clientURL = 'https://apis.google.com/js/api.js') {
static load({ clientURL = '', libraries = '' }) {

if (window.gapi) {
return Promise.resolve(); // already injected
Expand All @@ -35,7 +35,7 @@ export default class GoogleAPIClient {
// need to wrap to a native promise object since google has its own goog.Thenable
return new Promise(resolve => {

window[callback] = () => resolve();
window[callback] = () => window.gapi.load(libraries, resolve);

const script = document.createElement('script');

Expand All @@ -55,23 +55,16 @@ export default class GoogleAPIClient {

/**
* Initializes the client to be used with the specified libraries.
* @param {string[]} libraries - Google libraries
* @return {Promise<any>}
*/
init(libraries = []) {
return GoogleAPIClient.load().then(() => {
return new Promise(resolve => {
window.gapi.load(this._libraries.concat(libraries).join(':'), resolve);
}).then(() => {
return new Promise(resolve => {
window.gapi.client.init({
apiKey: this._apiKey,
client_id: this._clientId,
discoveryDocs: this._discoveryDocs,
scope: this._scope
}).then(resolve);
});
});
init() {
return new Promise(resolve => {
window.gapi.client.init(_.pick(this._options, [
'apiKey',
'clientId',
'discoveryDocs',
'scope',
])).then(resolve);
});
}

Expand All @@ -88,19 +81,15 @@ export default class GoogleAPIClient {
* @return {Promise<Object, Error>}
*/
signIn() {
return new Promise((resolve, reject) => {

GoogleAPIClient.__assertAuth2ClientExists();

if (this._offlineAccess) {
return new Promise((resolve, reject) => {
if (this._offlineAccess) {
return window.gapi.auth2
.getAuthInstance()
.grantOfflineAccess({ prompt: 'select_account' })
.grantOfflineAccess()
.then(resolve, reject);
});
}
}

return new Promise((resolve, reject) => {
return window.gapi.auth2
.getAuthInstance()
.signIn()
Expand All @@ -113,9 +102,6 @@ export default class GoogleAPIClient {
* @return {Promise<Object, Error>}
*/
signOut() {

GoogleAPIClient.__assertAuth2ClientExists();

return new Promise((resolve, reject) => {
return window.gapi.auth2
.getAuthInstance()
Expand All @@ -129,20 +115,6 @@ export default class GoogleAPIClient {
* @return {Promise<Object, Error>}
*/
attachClickHandler() {

GoogleAPIClient.__assertAuth2ClientExists();

window.gapi.auth2.getAuthInstance().attachClickHandler(...arguments);
}

// private properties __
/**
* Check if google api script has been loaded and client has been initialized.
* @throws Error
*/
static __assertAuth2ClientExists() {
if (!(window.gapi && window.gapi.auth2)) {
throw new Error('Auth2 client is not initialized. Perhaps you forgot to call init().');
}
}
}
35 changes: 35 additions & 0 deletions src/helpers/jwt.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import jwt from 'jsonwebtoken';
import { LocalStorage } from 'quasar';


export default class JWT {

constructor(key) {
this.key = key;
}

hasToken() {
return LocalStorage.has(this.key);
}

getToken() {
return LocalStorage.get.item(this.key);
}

setToken(token) {
LocalStorage.set(this.key, token);
return this;
}

removeToken() {
LocalStorage.remove(this.key);
return this;
}

decode() {
return jwt.decode(this.getToken(), {
complete: true,
force: true
});
}
}
13 changes: 10 additions & 3 deletions src/plugins/google-api.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,19 @@ import GoogleAPIClient from 'helpers/google-api-client';
* import GoogleAPIPlugin from 'src/plugins/google-api-plugin';
* ...
* Vue.use(GoogleAPIPlugin);
* ...
* const googleClient = await this.$googleAPI
*/
const GoogleAPIPlugin = {
install(Vue, options) {
Vue.googleAPI = GoogleAPIClient;
async install(Vue, options) {

const config = _.defaults(options, googleAPIConfig);

await GoogleAPIClient.load(config);

const instance = new GoogleAPIClient(config);

const instance = new GoogleAPIClient(_.merge(googleAPIConfig, options));
Vue.googleAPI = instance;

Object.defineProperties(Vue.prototype, {
$googleAPI: {
Expand Down
2 changes: 1 addition & 1 deletion src/plugins/i18n.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ const i18nPlugin = {
inserted: translateInnerHTML,
componentUpdated: translateInnerHTML
});
Vue.filter('$t', key => i18n.i18next.t(key));
Vue.filter('$t', (key, data) => i18n.i18next.t(key, data));
Vue.mixin({
methods: {
$trans(obj, props, trim = false) {
Expand Down
2 changes: 2 additions & 0 deletions src/plugins/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import AxiosPlugin from './axios';
import ToastPlugin from './toast';
import i18nPlugin from './i18n';
import GoogleAPIPlugin from './google-api';
import JWTPlugin from './jwt';

export default [
Quasar,
Expand All @@ -12,4 +13,5 @@ export default [
ToastPlugin,
i18nPlugin,
GoogleAPIPlugin,
JWTPlugin,
];
37 changes: 37 additions & 0 deletions src/plugins/jwt.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import JWT from 'src/helpers/jwt';

import config from 'config';

/**
* Plugin for injecting axios globally as default $http resource
* @example
* import JWTPlugin from 'src/plugins/jwt';
* ...
* Vue.use(JWTPlugin);
* @example
* // In a component you can use it like:
* this.$jwt.decode(...);
* Vue.jwt.decode(...);
*/
const JWTPlugin = {
install(Vue) {

const jwt = new JWT(config.ACCESS_TOKEN_KEY);

Vue.jwt = jwt;

Object.defineProperties(Vue.prototype, {
$jwt: {
get() {
return jwt;
}
}
});
}
};

if (typeof window !== 'undefined' && window.Vue) {
window.Vue.use(JWTPlugin);
}

export default JWTPlugin;
55 changes: 5 additions & 50 deletions test/unit/specs/helpers/google-api-client.spec.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import _ from 'lodash';
import sinon from 'sinon';

import googleConfig from 'src/config/google-api';
import GoogleAPIClient from 'src/helpers/google-api-client';


Expand Down Expand Up @@ -33,7 +35,7 @@ describe('GoogleAPIClient', function () {
* @test {GoogleAPIClient#load}
*/
it('GoogleAPIClient#load should return a promise', function () {
GoogleAPIClient.load().should.be.an.instanceof(Promise);
GoogleAPIClient.load(_.pick(googleConfig, ['clientURL', 'libraries'])).should.be.an.instanceof(Promise);
});

/**
Expand All @@ -42,9 +44,8 @@ describe('GoogleAPIClient', function () {
it('GoogleAPIClient#load should request for google api script', function () {

sandbox.useFakeServer();
const clientURL = 'https://apis.google.com/js/api.js';
const content = '(function(){})()';
sandbox.server.respondWith('GET', 'https://apis.google.com/js/api.js', [
sandbox.server.respondWith('GET', googleConfig.clientURL, [
200,
{ 'Content-Type': 'application/javascript' },
content
Expand All @@ -54,7 +55,7 @@ describe('GoogleAPIClient', function () {

delete window.gapi;

GoogleAPIClient.load(clientURL)
GoogleAPIClient.load(_.pick(googleConfig, ['clientURL', 'libraries']))
.then(callback);

sandbox.server.respond();
Expand Down Expand Up @@ -101,50 +102,4 @@ describe('GoogleAPIClient', function () {
client.grantOfflineAccess(true);
spy.thisValues[0]._offlineAccess.should.be.equals(true);
});

/**
* @test {GoogleAPIClient#signIn}
*/
it('GoogleAPIClient#signIn should throw error when init is not called first', function () {

const client = new GoogleAPIClient({
apiKey: '',
clientId: '',
discoveryDocs: [],
scope: []
});
delete window.gapi;

client.signIn.should.throw();
});

/**
* @test {GoogleAPIClient#signOut}
*/
it('GoogleAPIClient#signOut should throw error when init is not called first', function () {

const client = new GoogleAPIClient({
apiKey: '',
clientId: '',
discoveryDocs: [],
scope: []
});

client.signOut.should.throw();
});

/**
* @test {GoogleAPIClient#attachClickHandler}
*/
it('GoogleAPIClient#attachClickHandler should throw error when init is not called first', function () {

const client = new GoogleAPIClient({
apiKey: '',
clientId: '',
discoveryDocs: [],
scope: []
});

client.attachClickHandler.should.throw();
});
});
Loading

0 comments on commit 5c54c12

Please sign in to comment.