Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/api v2 auth #141

Closed
wants to merge 62 commits into from
Closed
Changes from 1 commit
Commits
Show all changes
62 commits
Select commit Hold shift + click to select a range
2688257
login and set user_id from cookie
trickpattyFH20 Jun 6, 2018
f09b82c
store cookie and user login info
trickpattyFH20 Jun 7, 2018
60bbcb2
send login data to view
trickpattyFH20 Jun 7, 2018
ae132f3
- add CSRF cookie
trickpattyFH20 Jun 8, 2018
2d9edc3
csrf token fix cookie name
trickpattyFH20 Jun 8, 2018
22336d0
fix return fetch
trickpattyFH20 Jun 8, 2018
aa708e6
err handle for missing cookie
trickpattyFH20 Jun 8, 2018
392d9ee
lint
trickpattyFH20 Jun 8, 2018
53f8b4f
pull settings
trickpattyFH20 Jun 12, 2018
5942c8d
v2 loggout
trickpattyFH20 Jul 6, 2018
74ab458
settings conf and fix hanging promise
trickpattyFH20 Jul 10, 2018
258c2bf
pull user settings
trickpattyFH20 Jul 10, 2018
6583b4c
move api js from panel to background
trickpattyFH20 Jul 11, 2018
810c7d8
lint
trickpattyFH20 Jul 11, 2018
1d3423b
Enable log in init from the website.
jsignanini Jul 12, 2018
ee54389
Move auth/account domains to globals.
jsignanini Jul 12, 2018
885abf9
pull user settings on login and init
trickpattyFH20 Jul 12, 2018
545c6b5
lint
trickpattyFH20 Jul 12, 2018
dbb9941
Implement logout.
jsignanini Jul 12, 2018
f88d3a2
Implement send verify email.
jsignanini Jul 12, 2018
31df7c8
login data success missing
trickpattyFH20 Jul 12, 2018
e6d964c
Merge branch 'feature/api-v2-auth' of github.com:ghostery/ghostery-ex…
trickpattyFH20 Jul 12, 2018
260d988
pushUserSettings and remove unused
trickpattyFH20 Jul 12, 2018
d00a1eb
Implement create account v2.
jsignanini Jul 12, 2018
99da32f
Fix logout from platform pages not sending message to background.
jsignanini Jul 12, 2018
ac0213d
remove api from panel
trickpattyFH20 Jul 12, 2018
8fb4e18
Merge branch 'feature/api-v2-auth' of github.com:ghostery/ghostery-ex…
trickpattyFH20 Jul 12, 2018
b1f78fa
Fix missing function.
jsignanini Jul 12, 2018
cd56624
Merge branch 'feature/api-v2-auth' of github.com:ghostery/ghostery-ex…
jsignanini Jul 12, 2018
a695d77
Add error handling for v2 login.
jsignanini Jul 12, 2018
a584db6
move userLogin fetch to background
trickpattyFH20 Jul 12, 2018
70f62ff
forgot password email
trickpattyFH20 Jul 13, 2018
1a43e2f
fix lgmogout
trickpattyFH20 Jul 13, 2018
b988746
fix legacy settings conf
trickpattyFH20 Jul 13, 2018
8135136
setup login
trickpattyFH20 Jul 13, 2018
4172242
setup createAccount
trickpattyFH20 Jul 13, 2018
beb276d
move createAccount fetch
trickpattyFH20 Jul 13, 2018
1572834
Several refactors and fixes.
jsignanini Jul 13, 2018
49bf9b1
Remove catch from logout.
jsignanini Jul 16, 2018
02981a8
account actions unit tests
trickpattyFH20 Jul 16, 2018
dc44e85
Merge branch 'feature/api-v2-auth' of github.com:ghostery/ghostery-ex…
trickpattyFH20 Jul 16, 2018
c6f2f16
lint
trickpattyFH20 Jul 16, 2018
1348cb7
Further refactor.
jsignanini Jul 16, 2018
d18d847
Refactor account.register.
jsignanini Jul 16, 2018
5e547e2
Refactor send validate account email.
jsignanini Jul 16, 2018
5418b62
Refactor reset password.
jsignanini Jul 17, 2018
a525f8d
More refactoring.
jsignanini Jul 17, 2018
0c7e1d8
fix unit test
trickpattyFH20 Jul 17, 2018
7027d39
Merge branch 'feature/api-v2-auth' of github.com:ghostery/ghostery-ex…
trickpattyFH20 Jul 17, 2018
8032ca3
Linter fix.
jsignanini Jul 17, 2018
ac8eee0
fix login_info unit tests
trickpattyFH20 Jul 17, 2018
8b455a1
Add specific babel-loader for background source files.
jsignanini Jul 18, 2018
9fb0e71
refresh token logout handler - api as class
trickpattyFH20 Jul 18, 2018
82f499e
export _getJSONAPIErrorsObject - move getCsrfCookie to api
trickpattyFH20 Jul 18, 2018
c6836b9
lint
trickpattyFH20 Jul 18, 2018
ce0b31f
Refactor account into own component.
jsignanini Jul 18, 2018
f17f476
Move logged in check into Account class. Cleanup.
jsignanini Jul 18, 2018
beef14e
Refactor account in setup page.
jsignanini Jul 19, 2018
b570527
Refactor setup page header log in.
jsignanini Jul 19, 2018
07ab815
Merge branch 'develop' into feature/api-v2-auth
jsignanini Jul 19, 2018
220cec8
lint - use logger in ExtMessenger
trickpattyFH20 Jul 19, 2018
b550262
update tests
trickpattyFH20 Jul 19, 2018
File filter
Filter file types
Jump to
Jump to file
Failed to load files.

Always

Just for now

move api js from panel to background
  • Loading branch information
trickpattyFH20 committed Jul 11, 2018
commit 6583b4c3b9a287e7b5fdae6112121f18361e597e
@@ -210,8 +210,9 @@ export function userLogin(email, password) {
});
});
}
return sendMessageInPromise('getLoginCookie')
.then((user_id) => {
return sendMessageInPromise('fetchUser')
.then((user) => {
console.log('fetchUser', user);
dispatch({
type: LOGIN_SUCCESS
});
@@ -222,7 +223,7 @@ export function userLogin(email, password) {
classes: 'success',
},
});
return user_id;
return user;
})
.catch((error) => {
// server error
@@ -248,58 +249,6 @@ export function userLogin(email, password) {
},
});
});
// return doXHR('POST', `${API_ROOT_URL}/api/v2/login`, JSON.stringify(query)).then((response) => {
// if (response) {
// sendMessageInPromise('setLoginInfo', {
// user_token: response.Token,
// decoded_user_token: decodedToken.payload,
// }).then((data) => {
// dispatch({
// type: LOGIN_SUCCESS,
// data: decodedToken.payload,
// });
// dispatch({
// type: SHOW_NOTIFICATION,
// data: {
// text: `${t('panel_signin_success')} ${query.EmailAddress}`,
// classes: 'success',
// },
// });
// }).catch((err) => {
// log('PanelActions userLogin returned with an error', err);
// dispatch({ type: LOGIN_FAILED });
// dispatch({
// type: SHOW_NOTIFICATION,
// data: {
// text: `${t('panel_signin_success')} ${query.EmailAddress}`,
// classes: 'alert',
// },
// });
// });
// } else {
// // XHR was successful but we did not get a token back
// log('PanelActions userLogin callback error', response);
// dispatch({ type: LOGIN_FAILED });
// dispatch({
// type: SHOW_NOTIFICATION,
// data: {
// text: t('banner_no_such_account_message'),
// classes: 'alert',
// },
// });
// }
// }).catch((error) => {
// // server error
// log('PanelActions userLogin server error', error);
// dispatch({ type: LOGIN_FAILED });
// dispatch({
// type: SHOW_NOTIFICATION,
// data: {
// text: t('server_error_message'),
// classes: 'alert',
// },
// });
// });
};
}

@@ -89,11 +89,7 @@ class Login extends React.Component {
}

this.props.actions.userLogin(email, password)
.then((user_id) => {
if (user_id) {
this.props.actions.fetchUser(user_id);
}
});
.catch(e => log(e));
}
/**
* Intercept Return key and call showSigninResult.
@@ -703,41 +703,34 @@ function onMessageHandler(request, sender, callback) {
}
});
return true;
} else if (name === 'setConfUserSettings') {
accounts.setConfUserSettings(message.settingsJson);
} else if (name === 'pullUserSettings') {
console.log('background pullUserSettings: ', message);
accounts.pullUserSettings(message);
return true;
} else if (name === 'getTrackerDescription') {
utils.getJson(message.url).then((result) => {
const description = (result) ? ((result.company_in_their_own_words) ? result.company_in_their_own_words : ((result.company_description) ? result.company_description : '')) : '';
callback(description);
});
return true;
} else if (name === 'getLoginInfo') {
accounts.getLoginInfo().then((result) => {
// this sends the loginInfo directly to panelView. TODO: use model change event instead
utils.sendMessageToPanel('onLoginInfoUpdated', result);
// this sends the loginInfo back to the collection
callback(result);
}).catch((err) => {
callback();
log('GET LOGIN INFO ERROR:', err);
});
return true;
} else if (name === 'getLoginCookie') {
// Note: if you want to trigger a logout, send message as empty {}
accounts.getLoginCookie().then((result) => {
callback(result);
}).catch((err) => {
callback();
log('GET LOGIN COOKIE ERROR');
} else if (name === 'userLogin') {
accounts.userLogin(message)
.then((response) => {
callback(response);
})
.catch((err) => {
callback(err);
log('LOGIN ERROR');
});
return true;
} else if (name === 'setLoginInfo') {
accounts.setLoginInfo(message).then((result) => {
callback(result);
}).catch((err) => {
callback();
log('SET LOGIN INFO ERROR');
} else if (name === 'fetchUser') {
accounts.fetchUser(message)
.then((user) => {
callback(user);
})
.catch((err) => {
callback(err);
log('FETCH USER ERROR');
});
return true;
} else if (name === 'update_database') {
@@ -23,9 +23,12 @@
/* eslint no-param-reassign: 0 */

import _ from 'underscore';
import normalize from 'json-api-normalizer';
import build from 'redux-object';
import globals from '../classes/Globals';
import conf from '../classes/Conf';
import { log, decodeJwt } from './common';
import { Config, get, save } from './api';
import { getJson, postJson, sendMessageToPanel } from './utils';

const IS_EDGE = (globals.BROWSER_INFO.name === 'edge');
@@ -38,11 +41,6 @@ const API_ROOT_URL = 'https://localhost:8080';
const VERIFICATION_URL = `https://signon.${GHOSTERY_DOMAIN}.com/register/verify/`; // can't set culture because site needs to append guid
const REDIRECT_URL = `https://account.${GHOSTERY_DOMAIN}.com/`;
const SIGNON_URL = `https://signon.${GHOSTERY_DOMAIN}.com/`; // culture query param not needed, only for cookie
const AUTH_COOKIE = 'AUTH';
// milliseconds. Refresh call will be made REFRESH_OFFSET seconds in advance of Account expiration.
const REFRESH_OFFSET = 60000;
const LOGOUT_TIMEOUT = 604800000; // one week in millisec
const GROUND_ZERO_TIME = (new Date(0)).getTime();
const SYNC_SET = new Set(globals.SYNC_ARRAY);

/**
@@ -75,6 +73,49 @@ export function setLoginInfo(user) {
return Promise.resolve(conf.login_info);
}

export function userLogin(credentials) {
return fetch(`${Config.auth_server.host}/api/v2/login`, {
method: 'POST',
body: credentials,
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Content-Length': Buffer.byteLength(credentials),
},
credentials: 'include',
})
.then((response) => {
console.log('fetch response', response);
return Promise.resolve(response);
})
.catch(e => Promise.reject(e));
}

export function fetchUser() {
let userId;
return getLoginCookie()
.then(cookie => {
userId = cookie;
console.log('fetchUser userId', userId);
return get('users', userId);
})
.then(response => {
const user = build(normalize(response), 'users', userId);
user.loggedIn = true;
return setLoginInfo(user)
})
.then(loginInfo => {
console.log('fetchUser loginInfo', loginInfo);
return Promise.resolve(loginInfo);
})
.catch(err => {
return Promise.reject(err);
});
}

export function pullUserSettings() {

}

export function getLoginCookie() {
return new Promise((resolve, reject) => {
chrome.cookies.get({
@@ -155,13 +196,6 @@ function _logOut() {
* @return {Promise} user settings json or error
*/
export function setConfUserSettings(settings) {
// TODO settings are in settings.settingsJson
// need to set those to `settings`
try {
settings = settings ? JSON.parse(settings) : {};
} catch (e) {
return Promise.reject('Corrupted settings');
}
log('SET USER SETTINGS', settings);
if (IS_EDGE) {
settings.enable_human_web = false;
@@ -0,0 +1,156 @@
import globals from '../classes/Globals';

// TODO make this not global vars
let isRefreshing = false;
const tokenRefreshedEventType = 'tokenRefreshed';

const _getJSONAPIErrorsObject = e => ([{ title: 'Something went wrong.', detail: e.toString() }]);

const _refreshToken = function () {
if (isRefreshing) {
let bindedResolve;
const _processRefreshTokenEvent = (resolve, e) => {
window.removeEventListener(tokenRefreshedEventType, bindedResolve, false);
resolve(e.detail);
};
return new Promise((resolve, reject) => {
bindedResolve = _processRefreshTokenEvent.bind(null, resolve);
window.addEventListener(tokenRefreshedEventType, bindedResolve, false);
});
}

isRefreshing = true;
return fetch(`${Config.auth_server.host}/api/v2/refresh_token`, { // eslint-disable-line no-undef
method: 'POST',
credentials: 'include',
});
};

const getCsrfCookie = () => new Promise((resolve, reject) => {
chrome.cookies.get({
url: `https://${globals.GHOSTERY_DOMAIN}.com`, // ghostery.com || ghosterystage.com
name: 'csrf_token',
}, (cookie) => {
if (cookie) {
resolve(cookie);
return;
}
reject();
});
});

const _sendReq = (method, path, body) => getCsrfCookie()
.then(cookie => fetch(`${Config.account_server.host}${path}`, { // eslint-disable-line no-undef
method,
headers: {
'Content-Type': 'application/vnd.api+json',
'Content-Length': Buffer.byteLength(JSON.stringify(body)),
'X-CSRF-Token': cookie.value,
},
body: JSON.stringify(body),
credentials: 'include',
}));

const _processResponse = res => (
new Promise((resolve, reject) => {
const { status } = res;
if (status === 204) {
resolve();
return;
}
res.json().then((data) => {
if (status >= 400) {
reject(data);
} else {
resolve(data);
}
});
})
);

const _sendAuthenticatedRequest = (method, path, body) => (
new Promise((resolve, reject) => {
_sendReq(method, path, body)
.then(_processResponse)
.then((data) => {
resolve(data);
})
.catch((data) => {
let shouldRefresh = false;
if (data && data.errors) {
data.errors.forEach((e) => {
if (e.code === '10021' || e.code === '10022') { // token is expired or missing
shouldRefresh = true;
}
});
}
if (shouldRefresh) {
_refreshToken()
.then((res) => {
isRefreshing = false;
window.dispatchEvent(new CustomEvent(tokenRefreshedEventType, {
detail: res,
}));
const { status } = res;
if (status >= 400) {
res.json().then((data2) => {
reject(data2.errors);
}).catch((err) => {
reject(_getJSONAPIErrorsObject(err));
});
return;
}
_sendReq(method, path, body)
.then(_processResponse)
.then((data3) => {
resolve(data3);
})
.catch((err) => {
reject(_getJSONAPIErrorsObject(err));
});
});
} else {
reject(_getJSONAPIErrorsObject(data));
}
});
})
);

export const get = function (type, id, include = '') {
if (!id) { return Promise.reject(new Error('id is missing')); }
return _sendAuthenticatedRequest('GET', `/api/v2/${type}/${id}?include=${include}`);
};

export const save = function (type, data) {
return _sendAuthenticatedRequest('POST', `/api/v2/${type}/`, data);
};

export const update = function (type, data) {
// TODO check for data.id and fail
return _sendAuthenticatedRequest('PATCH', `/api/v2/${type}/${data.id}`, { data });
};

export const remove = function (type, id) {
return _sendAuthenticatedRequest('DELETE', `/api/v2/${type}/${id}`);
};

export const Config = {
auth_server: {
host: `https://consumerapi.${globals.GHOSTERY_DOMAIN}.com`
},
account_server: {
host: `https://accountapi.${globals.GHOSTERY_DOMAIN}.com`
},
};

// @TODO move to accounts.js
// export const logout = function () {
// return getCsrfCookie()
// .then(cookie => fetch(`${Config.auth_server.host}/api/v2/logout`, { // eslint-disable-line no-undef
// method: 'POST',
// credentials: 'include',
// headers: {
// 'X-CSRF-Token': cookie.value,
// },
// }));
// };
ProTip! Use n and p to navigate between commits in a pull request.