196 lines
7.6 KiB
JavaScript
196 lines
7.6 KiB
JavaScript
import assert from "assert";
|
||
/**
|
||
* OAuth 授权页面组件
|
||
*/
|
||
export default OakComponent({
|
||
// Virtual Component
|
||
isList: false,
|
||
filters: [],
|
||
properties: {
|
||
onUnLogin: null,
|
||
},
|
||
data: {
|
||
clientInfo: null,
|
||
loading: true,
|
||
userInfo: null,
|
||
hasError: false,
|
||
errorMsg: '',
|
||
name: '',
|
||
nickname: '',
|
||
mobile: '',
|
||
avatarUrl: '',
|
||
response_type: '',
|
||
client_id: '',
|
||
redirect_uri: '',
|
||
scope: '',
|
||
state: '',
|
||
},
|
||
lifetimes: {
|
||
async ready() {
|
||
const searchParams = new URLSearchParams(window.location.search);
|
||
const clientId = searchParams.get('client_id') || '';
|
||
const responseType = searchParams.get('response_type') || '';
|
||
const redirectUri = searchParams.get('redirect_uri') || '';
|
||
const scope = searchParams.get('scope') || '';
|
||
const state = searchParams.get('state') || '';
|
||
//判断是否允许oauth登录
|
||
const application = this.features.application.getApplication();
|
||
const { result: applicationPassports } = await this.features.cache.exec('getApplicationPassports', { applicationId: application.id });
|
||
const oauthPassport = applicationPassports?.find((ele) => ele.passport?.type === 'oauth');
|
||
const oauthIds = oauthPassport?.config?.oauthIds;
|
||
let allowOauth = false;
|
||
if (clientId) {
|
||
const { data: [oauthProvider] } = await this.features.cache.refresh('oauthProvider', {
|
||
data: {
|
||
id: 1,
|
||
clientId: 1,
|
||
systemId: 1,
|
||
},
|
||
filter: {
|
||
clientId,
|
||
systemId: application.systemId,
|
||
}
|
||
});
|
||
if (oauthProvider?.id && oauthIds?.length > 0 && oauthIds.includes(oauthProvider?.id)) {
|
||
allowOauth = true;
|
||
}
|
||
}
|
||
if (!allowOauth) {
|
||
this.setState({
|
||
hasError: true,
|
||
errorMsg: 'oauth.login',
|
||
});
|
||
this.setState({ loading: false });
|
||
return;
|
||
}
|
||
this.setState({
|
||
client_id: clientId,
|
||
response_type: responseType,
|
||
redirect_uri: redirectUri,
|
||
scope: scope,
|
||
state: state,
|
||
});
|
||
// load userinfo
|
||
const userId = this.features.token.getUserId(true);
|
||
if (!userId) {
|
||
// const params = new URLSearchParams();
|
||
// params.set('response_type', responseType || "");
|
||
// params.set('client_id', clientId || "");
|
||
// params.set('redirect_uri', redirectUri || "");
|
||
// params.set('scope', scope || "");
|
||
// params.set('state', state || "");
|
||
// const redirectUrl = `/login/oauth/authorize?${params.toString()}`;
|
||
// console.log('Not logged in, redirecting to login page:', redirectUrl);
|
||
// const encoded = btoa(encodeURIComponent(redirectUrl));
|
||
// this.features.navigator.navigateTo({
|
||
// url: `/login?redirect=${encoded}`,
|
||
// }, undefined, true);
|
||
if (!this.props.onUnLogin) {
|
||
console.error('用户未登录,请在使用Oauth授权组件时配置onUnLogin回调函数');
|
||
return;
|
||
}
|
||
this.props.onUnLogin({
|
||
response_type: responseType,
|
||
client_id: clientId,
|
||
redirect_uri: redirectUri,
|
||
scope: scope,
|
||
state: state,
|
||
});
|
||
return;
|
||
}
|
||
const userInfo = this.features.token.getUserInfo();
|
||
const { mobile } = (userInfo?.mobile$user && userInfo?.mobile$user[0]) ||
|
||
(userInfo?.user$ref &&
|
||
userInfo?.user$ref[0] &&
|
||
userInfo?.user$ref[0].mobile$user &&
|
||
userInfo?.user$ref[0].mobile$user[0]) ||
|
||
{};
|
||
const extraFile = userInfo?.extraFile$entity?.find((ele) => ele.tag1 === 'avatar');
|
||
const avatarUrl = this.features.extraFile.getUrl(extraFile);
|
||
this.setState({
|
||
userInfo: userId ? this.features.token.getUserInfo() : null,
|
||
name: userInfo?.name || '',
|
||
nickname: userInfo?.nickname || '',
|
||
mobile: mobile || '',
|
||
avatarUrl,
|
||
});
|
||
// end load userinfo
|
||
if (!clientId) {
|
||
this.setState({
|
||
hasError: true,
|
||
errorMsg: 'oauth.authorize.error.missing_client_id',
|
||
});
|
||
this.setState({ loading: false });
|
||
return;
|
||
}
|
||
if (!responseType) {
|
||
this.setState({
|
||
hasError: true,
|
||
errorMsg: 'oauth.authorize.error.missing_response_type',
|
||
});
|
||
this.setState({ loading: false });
|
||
return;
|
||
}
|
||
this.features.cache.exec("getOAuthClientInfo", {
|
||
client_id: clientId,
|
||
currentUserId: userId,
|
||
}).then((clientInfo) => {
|
||
if (!clientInfo.result) {
|
||
this.setState({ loading: false });
|
||
this.setState({
|
||
hasError: true,
|
||
errorMsg: 'oauth.authorize.error.invalid_client_id',
|
||
});
|
||
}
|
||
else {
|
||
this.setState({
|
||
clientInfo: clientInfo.result.data,
|
||
});
|
||
if (clientInfo.result.alreadyAuth) {
|
||
// 已经授权过,直接跳转
|
||
this.handleGrant();
|
||
}
|
||
else {
|
||
this.setState({ loading: false });
|
||
}
|
||
}
|
||
}).catch((err) => {
|
||
this.setState({ loading: false });
|
||
console.error('Error loading OAuth client info:', err);
|
||
this.setState({
|
||
hasError: true,
|
||
errorMsg: err.message || 'oauth.authorize.error.unknown',
|
||
});
|
||
});
|
||
},
|
||
},
|
||
methods: {
|
||
handleGrant() {
|
||
this.callAspectAuthorize("grant");
|
||
},
|
||
handleDeny() {
|
||
this.callAspectAuthorize("deny");
|
||
},
|
||
callAspectAuthorize(action) {
|
||
this.features.cache.exec("authorize", {
|
||
response_type: this.state.response_type || "",
|
||
client_id: this.state.client_id || "",
|
||
redirect_uri: this.state.redirect_uri || "",
|
||
scope: this.state.scope || "",
|
||
state: this.state.state || "",
|
||
action: action,
|
||
}).then((result) => {
|
||
const { redirectUri } = result.result;
|
||
assert(redirectUri, 'redirectUri should be present in authorize result');
|
||
window.location.replace(redirectUri);
|
||
}).catch((err) => {
|
||
console.error('Error during OAuth authorization:', err);
|
||
this.setState({
|
||
hasError: true,
|
||
errorMsg: err.message || 'oauth.authorize.error.unknown',
|
||
});
|
||
});
|
||
}
|
||
},
|
||
});
|