2019-12-08 00:32:00 +05:30
|
|
|
import { getActiveAccount } from 'app/components/accounts/reducer';
|
2016-03-02 02:06:14 +05:30
|
|
|
import AbstractState from './AbstractState';
|
|
|
|
import LoginState from './LoginState';
|
|
|
|
import PermissionsState from './PermissionsState';
|
2016-11-13 20:17:56 +05:30
|
|
|
import ChooseAccountState from './ChooseAccountState';
|
2016-03-02 02:06:14 +05:30
|
|
|
import ActivationState from './ActivationState';
|
2016-08-03 00:29:29 +05:30
|
|
|
import AcceptRulesState from './AcceptRulesState';
|
2016-03-15 12:06:13 +05:30
|
|
|
import FinishState from './FinishState';
|
2019-12-07 16:58:52 +05:30
|
|
|
import { AuthContext } from './AuthFlow';
|
2016-03-02 02:06:14 +05:30
|
|
|
|
2016-11-19 20:11:15 +05:30
|
|
|
const PROMPT_ACCOUNT_CHOOSE = 'select_account';
|
|
|
|
const PROMPT_PERMISSIONS = 'consent';
|
|
|
|
|
2016-03-02 02:06:14 +05:30
|
|
|
export default class CompleteState extends AbstractState {
|
2020-05-24 04:38:24 +05:30
|
|
|
isPermissionsAccepted: boolean | void;
|
2016-11-19 20:11:15 +05:30
|
|
|
|
2020-05-24 04:38:24 +05:30
|
|
|
constructor(
|
|
|
|
options: {
|
|
|
|
accept?: boolean;
|
|
|
|
} = {},
|
|
|
|
) {
|
|
|
|
super();
|
2019-12-07 16:58:52 +05:30
|
|
|
|
2020-05-24 04:38:24 +05:30
|
|
|
this.isPermissionsAccepted = options.accept;
|
2019-12-07 16:58:52 +05:30
|
|
|
}
|
|
|
|
|
2020-05-24 04:38:24 +05:30
|
|
|
enter(context: AuthContext): Promise<void> | void {
|
|
|
|
const {
|
|
|
|
auth: { oauth },
|
|
|
|
user,
|
|
|
|
} = context.getState();
|
|
|
|
|
|
|
|
if (user.isGuest) {
|
|
|
|
context.setState(new LoginState());
|
|
|
|
} else if (!user.isActive) {
|
|
|
|
context.setState(new ActivationState());
|
2020-10-11 22:45:53 +05:30
|
|
|
} else if (user.shouldAcceptRules && !user.isDeleted) {
|
2020-05-24 04:38:24 +05:30
|
|
|
context.setState(new AcceptRulesState());
|
|
|
|
} else if (oauth && oauth.clientId) {
|
|
|
|
return this.processOAuth(context);
|
|
|
|
} else {
|
|
|
|
context.navigate('/');
|
2017-01-29 17:12:51 +05:30
|
|
|
}
|
2019-11-27 14:33:32 +05:30
|
|
|
}
|
2017-01-29 17:12:51 +05:30
|
|
|
|
2020-05-24 04:38:24 +05:30
|
|
|
processOAuth(context: AuthContext): Promise<void> | void {
|
2020-10-11 22:45:53 +05:30
|
|
|
const { auth, accounts, user } = context.getState();
|
2020-05-24 04:38:24 +05:30
|
|
|
|
|
|
|
let { isSwitcherEnabled } = auth;
|
|
|
|
const { oauth } = auth;
|
|
|
|
|
|
|
|
if (!oauth) {
|
|
|
|
throw new Error('Empty oauth state');
|
|
|
|
}
|
|
|
|
|
|
|
|
const { loginHint } = oauth;
|
|
|
|
|
|
|
|
if (loginHint) {
|
|
|
|
const account = accounts.available.find(
|
|
|
|
(item) => item.id === Number(loginHint) || item.email === loginHint || item.username === loginHint,
|
|
|
|
);
|
|
|
|
const activeAccount = getActiveAccount(context.getState());
|
|
|
|
|
|
|
|
if (account) {
|
|
|
|
// disable switching, because we are know the account, user must be authorized with
|
|
|
|
context.run('setAccountSwitcher', false);
|
|
|
|
isSwitcherEnabled = false;
|
|
|
|
|
|
|
|
if (!activeAccount || account.id !== activeAccount.id) {
|
|
|
|
// lets switch user to an account, that is needed for auth
|
|
|
|
return context.run('authenticate', account).then(() => context.setState(new CompleteState()));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-10-11 22:45:53 +05:30
|
|
|
if (
|
|
|
|
isSwitcherEnabled &&
|
|
|
|
(accounts.available.length > 1 ||
|
|
|
|
// we are always showing account switcher for deleted users
|
|
|
|
// so that they can see, that their account was deleted
|
|
|
|
// (this info is displayed on switcher)
|
|
|
|
user.isDeleted ||
|
|
|
|
oauth.prompt.includes(PROMPT_ACCOUNT_CHOOSE))
|
|
|
|
) {
|
2020-05-24 04:38:24 +05:30
|
|
|
context.setState(new ChooseAccountState());
|
2020-10-11 22:45:53 +05:30
|
|
|
} else if (user.isDeleted) {
|
|
|
|
// you shall not pass
|
|
|
|
// if we are here, this means that user have already seen account
|
|
|
|
// switcher and now we should redirect him to his profile,
|
|
|
|
// because oauth is not available for deleted accounts
|
|
|
|
context.navigate('/');
|
2020-05-24 04:38:24 +05:30
|
|
|
} else if (oauth.code) {
|
2019-11-27 14:33:32 +05:30
|
|
|
context.setState(new FinishState());
|
2020-05-24 04:38:24 +05:30
|
|
|
} else {
|
|
|
|
const data: { [key: string]: any } = {};
|
|
|
|
|
|
|
|
if (typeof this.isPermissionsAccepted !== 'undefined') {
|
|
|
|
data.accept = this.isPermissionsAccepted;
|
|
|
|
} else if (oauth.acceptRequired || oauth.prompt.includes(PROMPT_PERMISSIONS)) {
|
|
|
|
context.setState(new PermissionsState());
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO: it seems that oAuthComplete may be a separate state
|
|
|
|
return context.run('oAuthComplete', data).then(
|
|
|
|
(resp: { redirectUri: string }) => {
|
|
|
|
// TODO: пусть в стейт попадает флаг или тип авторизации
|
|
|
|
// вместо волшебства над редирект урлой
|
|
|
|
if (resp.redirectUri.includes('static_page')) {
|
|
|
|
context.setState(new FinishState());
|
|
|
|
} else {
|
|
|
|
return context.run('redirect', resp.redirectUri);
|
|
|
|
}
|
|
|
|
},
|
|
|
|
(resp) => {
|
|
|
|
if (resp.unauthorized) {
|
|
|
|
context.setState(new LoginState());
|
|
|
|
} else if (resp.acceptRequired) {
|
|
|
|
context.setState(new PermissionsState());
|
|
|
|
}
|
|
|
|
},
|
|
|
|
);
|
|
|
|
}
|
2016-03-02 02:06:14 +05:30
|
|
|
}
|
|
|
|
}
|