2017-05-30 02:08:03 +00:00
|
|
|
// @flow
|
2017-11-27 06:26:02 +00:00
|
|
|
import { observable, action, computed, autorun, runInAction } from 'mobx';
|
2017-05-30 02:08:03 +00:00
|
|
|
import invariant from 'invariant';
|
2019-03-02 22:58:56 +00:00
|
|
|
import { getCookie, setCookie, removeCookie } from 'tiny-cookie';
|
2017-05-30 02:08:03 +00:00
|
|
|
import { client } from 'utils/ApiClient';
|
2018-11-10 07:40:33 +00:00
|
|
|
import { stripSubdomain } from 'shared/utils/domains';
|
2018-12-05 06:24:30 +00:00
|
|
|
import RootStore from 'stores/RootStore';
|
|
|
|
import User from 'models/User';
|
|
|
|
import Team from 'models/Team';
|
2017-05-30 02:08:03 +00:00
|
|
|
|
|
|
|
const AUTH_STORE = 'AUTH_STORE';
|
|
|
|
|
2018-12-05 06:24:30 +00:00
|
|
|
export default class AuthStore {
|
2017-05-30 02:08:03 +00:00
|
|
|
@observable user: ?User;
|
|
|
|
@observable team: ?Team;
|
|
|
|
@observable token: ?string;
|
2018-05-31 19:07:49 +00:00
|
|
|
@observable isSaving: boolean = false;
|
2018-03-05 06:18:23 +00:00
|
|
|
@observable isSuspended: boolean = false;
|
2018-03-07 07:38:52 +00:00
|
|
|
@observable suspendedContactEmail: ?string;
|
2018-12-05 06:24:30 +00:00
|
|
|
rootStore: RootStore;
|
2017-05-30 02:08:03 +00:00
|
|
|
|
2018-12-05 06:24:30 +00:00
|
|
|
constructor(rootStore: RootStore) {
|
|
|
|
// Rehydrate
|
|
|
|
let data = {};
|
|
|
|
try {
|
|
|
|
data = JSON.parse(localStorage.getItem(AUTH_STORE) || '{}');
|
|
|
|
} catch (_) {
|
|
|
|
// no-op Safari private mode
|
|
|
|
}
|
|
|
|
|
|
|
|
this.rootStore = rootStore;
|
|
|
|
this.user = data.user;
|
|
|
|
this.team = data.team;
|
2019-03-02 22:58:56 +00:00
|
|
|
this.token = getCookie('accessToken');
|
2018-12-05 06:24:30 +00:00
|
|
|
|
|
|
|
if (this.token) setImmediate(() => this.fetch());
|
|
|
|
|
|
|
|
autorun(() => {
|
|
|
|
try {
|
|
|
|
localStorage.setItem(AUTH_STORE, this.asJson);
|
|
|
|
} catch (_) {
|
|
|
|
// no-op Safari private mode
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
2017-05-30 02:08:03 +00:00
|
|
|
|
2017-11-10 22:14:30 +00:00
|
|
|
@computed
|
|
|
|
get authenticated(): boolean {
|
2017-05-30 02:08:03 +00:00
|
|
|
return !!this.token;
|
|
|
|
}
|
|
|
|
|
2017-11-10 22:14:30 +00:00
|
|
|
@computed
|
|
|
|
get asJson(): string {
|
2017-05-30 02:08:03 +00:00
|
|
|
return JSON.stringify({
|
|
|
|
user: this.user,
|
|
|
|
team: this.team,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2017-11-27 06:26:02 +00:00
|
|
|
@action
|
|
|
|
fetch = async () => {
|
|
|
|
try {
|
|
|
|
const res = await client.post('/auth.info');
|
|
|
|
invariant(res && res.data, 'Auth not available');
|
|
|
|
|
|
|
|
runInAction('AuthStore#fetch', () => {
|
2018-12-05 06:24:30 +00:00
|
|
|
const { user, team } = res.data;
|
|
|
|
this.user = user;
|
|
|
|
this.team = team;
|
|
|
|
|
|
|
|
if (window.Bugsnag) {
|
|
|
|
Bugsnag.user = {
|
|
|
|
id: user.id,
|
|
|
|
name: user.name,
|
|
|
|
teamId: team.id,
|
|
|
|
team: team.name,
|
|
|
|
};
|
|
|
|
}
|
2017-11-27 06:26:02 +00:00
|
|
|
});
|
2018-02-13 06:44:43 +00:00
|
|
|
} catch (err) {
|
2019-02-16 05:49:48 +00:00
|
|
|
if (err.error === 'user_suspended') {
|
2018-03-05 06:18:23 +00:00
|
|
|
this.isSuspended = true;
|
2019-02-16 05:49:48 +00:00
|
|
|
this.suspendedContactEmail = err.data.adminEmail;
|
2018-03-05 06:18:23 +00:00
|
|
|
}
|
2017-11-27 06:26:02 +00:00
|
|
|
}
|
|
|
|
};
|
2017-05-30 02:08:03 +00:00
|
|
|
|
2018-07-07 23:09:39 +00:00
|
|
|
@action
|
|
|
|
deleteUser = async () => {
|
2018-12-05 06:24:30 +00:00
|
|
|
await client.post(`/users.delete`, { confirmation: true });
|
2018-07-07 23:09:39 +00:00
|
|
|
|
|
|
|
runInAction('AuthStore#updateUser', () => {
|
|
|
|
this.user = null;
|
|
|
|
this.team = null;
|
|
|
|
this.token = null;
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
2018-05-31 18:42:39 +00:00
|
|
|
@action
|
2018-11-18 02:25:10 +00:00
|
|
|
updateUser = async (params: { name?: string, avatarUrl: ?string }) => {
|
2018-05-31 19:07:49 +00:00
|
|
|
this.isSaving = true;
|
2018-05-31 18:42:39 +00:00
|
|
|
|
2018-05-31 19:07:49 +00:00
|
|
|
try {
|
2018-12-05 06:24:30 +00:00
|
|
|
const res = await client.post(`/users.update`, params);
|
2018-05-31 19:07:49 +00:00
|
|
|
invariant(res && res.data, 'User response not available');
|
|
|
|
|
|
|
|
runInAction('AuthStore#updateUser', () => {
|
|
|
|
this.user = res.data;
|
2018-05-31 19:44:32 +00:00
|
|
|
});
|
|
|
|
} finally {
|
|
|
|
this.isSaving = false;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
@action
|
2018-08-19 23:06:39 +00:00
|
|
|
updateTeam = async (params: {
|
|
|
|
name?: string,
|
|
|
|
avatarUrl?: ?string,
|
|
|
|
sharing?: boolean,
|
|
|
|
}) => {
|
2018-05-31 19:44:32 +00:00
|
|
|
this.isSaving = true;
|
|
|
|
|
|
|
|
try {
|
|
|
|
const res = await client.post(`/team.update`, params);
|
|
|
|
invariant(res && res.data, 'Team response not available');
|
|
|
|
|
|
|
|
runInAction('AuthStore#updateTeam', () => {
|
|
|
|
this.team = res.data;
|
2018-05-31 19:07:49 +00:00
|
|
|
});
|
|
|
|
} finally {
|
|
|
|
this.isSaving = false;
|
|
|
|
}
|
2018-05-31 18:42:39 +00:00
|
|
|
};
|
|
|
|
|
2017-11-10 22:14:30 +00:00
|
|
|
@action
|
2018-02-13 06:44:43 +00:00
|
|
|
logout = async () => {
|
2017-05-30 02:08:03 +00:00
|
|
|
this.user = null;
|
|
|
|
this.token = null;
|
2018-02-13 06:44:43 +00:00
|
|
|
|
2018-11-11 22:23:31 +00:00
|
|
|
// remove authentication token itself
|
2019-03-02 22:58:56 +00:00
|
|
|
removeCookie('accessToken', { path: '/' });
|
2018-11-10 07:40:33 +00:00
|
|
|
|
2018-11-11 22:23:31 +00:00
|
|
|
// remove session record on apex cookie
|
|
|
|
const team = this.team;
|
|
|
|
if (team) {
|
2019-03-02 22:58:56 +00:00
|
|
|
const sessions = JSON.parse(getCookie('sessions') || '{}');
|
2018-11-14 07:08:27 +00:00
|
|
|
delete sessions[team.id];
|
2018-11-10 07:40:33 +00:00
|
|
|
|
2019-03-02 22:58:56 +00:00
|
|
|
setCookie('sessions', JSON.stringify(sessions), {
|
2018-11-10 07:40:33 +00:00
|
|
|
domain: stripSubdomain(window.location.hostname),
|
|
|
|
});
|
|
|
|
this.team = null;
|
|
|
|
}
|
2018-05-30 05:18:11 +00:00
|
|
|
|
|
|
|
// add a timestamp to force reload from server
|
|
|
|
window.location.href = `${BASE_URL}?done=${new Date().getTime()}`;
|
2017-05-30 02:08:03 +00:00
|
|
|
};
|
|
|
|
}
|