2020-11-23 20:10:15 +03:00
|
|
|
/*
|
|
|
|
Copyright 2020 The Matrix.org Foundation C.I.C.
|
|
|
|
|
|
|
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
you may not use this file except in compliance with the License.
|
|
|
|
You may obtain a copy of the License at
|
|
|
|
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
See the License for the specific language governing permissions and
|
|
|
|
limitations under the License.
|
|
|
|
*/
|
|
|
|
|
|
|
|
import React from "react";
|
2021-01-21 16:33:25 +03:00
|
|
|
import { chunk } from "lodash";
|
|
|
|
import classNames from "classnames";
|
2020-11-23 20:10:15 +03:00
|
|
|
import {MatrixClient} from "matrix-js-sdk/src/client";
|
|
|
|
|
|
|
|
import PlatformPeg from "../../../PlatformPeg";
|
|
|
|
import AccessibleButton from "./AccessibleButton";
|
|
|
|
import {_t} from "../../../languageHandler";
|
2021-01-27 17:27:41 +03:00
|
|
|
import {IdentityProviderBrand, IIdentityProvider, ISSOFlow} from "../../../Login";
|
2021-01-29 15:05:15 +03:00
|
|
|
import AccessibleTooltipButton from "./AccessibleTooltipButton";
|
2020-11-23 20:10:15 +03:00
|
|
|
|
|
|
|
interface ISSOButtonProps extends Omit<IProps, "flow"> {
|
|
|
|
idp: IIdentityProvider;
|
|
|
|
mini?: boolean;
|
|
|
|
}
|
|
|
|
|
2021-01-27 17:27:41 +03:00
|
|
|
const getIcon = (brand: IdentityProviderBrand | string) => {
|
|
|
|
switch (brand) {
|
|
|
|
case IdentityProviderBrand.Apple:
|
|
|
|
return require(`../../../../res/img/element-icons/brands/apple.svg`);
|
|
|
|
case IdentityProviderBrand.Facebook:
|
|
|
|
return require(`../../../../res/img/element-icons/brands/facebook.svg`);
|
|
|
|
case IdentityProviderBrand.Github:
|
|
|
|
return require(`../../../../res/img/element-icons/brands/github.svg`);
|
|
|
|
case IdentityProviderBrand.Gitlab:
|
|
|
|
return require(`../../../../res/img/element-icons/brands/gitlab.svg`);
|
|
|
|
case IdentityProviderBrand.Google:
|
|
|
|
return require(`../../../../res/img/element-icons/brands/google.svg`);
|
|
|
|
case IdentityProviderBrand.Twitter:
|
|
|
|
return require(`../../../../res/img/element-icons/brands/twitter.svg`);
|
|
|
|
default:
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-11-23 20:10:15 +03:00
|
|
|
const SSOButton: React.FC<ISSOButtonProps> = ({
|
|
|
|
matrixClient,
|
|
|
|
loginType,
|
|
|
|
fragmentAfterLogin,
|
|
|
|
idp,
|
|
|
|
primary,
|
|
|
|
mini,
|
|
|
|
...props
|
|
|
|
}) => {
|
|
|
|
const kind = primary ? "primary" : "primary_outline";
|
|
|
|
const label = idp ? _t("Continue with %(provider)s", { provider: idp.name }) : _t("Sign in with single sign-on");
|
|
|
|
|
|
|
|
const onClick = () => {
|
2020-12-03 14:08:16 +03:00
|
|
|
PlatformPeg.get().startSingleSignOn(matrixClient, loginType, fragmentAfterLogin, idp?.id);
|
2020-11-23 20:10:15 +03:00
|
|
|
};
|
|
|
|
|
|
|
|
let icon;
|
2021-01-27 17:27:41 +03:00
|
|
|
let brandClass;
|
|
|
|
const brandIcon = idp ? getIcon(idp.brand) : null;
|
|
|
|
if (brandIcon) {
|
|
|
|
const brandName = idp.brand.split(".").pop();
|
|
|
|
brandClass = `mx_SSOButton_brand_${brandName}`;
|
|
|
|
icon = <img src={brandIcon} height="24" width="24" alt={brandName} />;
|
|
|
|
} else if (typeof idp?.icon === "string" && idp.icon.startsWith("mxc://")) {
|
|
|
|
const src = matrixClient.mxcUrlToHttp(idp.icon, 24, 24, "crop", true);
|
|
|
|
icon = <img src={src} height="24" width="24" alt={idp.name} />;
|
2020-11-23 20:10:15 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
const classes = classNames("mx_SSOButton", {
|
2021-01-27 17:27:41 +03:00
|
|
|
[brandClass]: brandClass,
|
2020-11-23 20:10:15 +03:00
|
|
|
mx_SSOButton_mini: mini,
|
|
|
|
});
|
|
|
|
|
|
|
|
if (mini) {
|
|
|
|
// TODO fallback icon
|
|
|
|
return (
|
2021-01-29 15:05:15 +03:00
|
|
|
<AccessibleTooltipButton {...props} title={label} className={classes} kind={kind} onClick={onClick}>
|
2020-11-23 20:10:15 +03:00
|
|
|
{ icon }
|
2021-01-29 15:05:15 +03:00
|
|
|
</AccessibleTooltipButton>
|
2020-11-23 20:10:15 +03:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
return (
|
|
|
|
<AccessibleButton {...props} className={classes} kind={kind} onClick={onClick}>
|
|
|
|
{ icon }
|
|
|
|
{ label }
|
|
|
|
</AccessibleButton>
|
|
|
|
);
|
|
|
|
};
|
|
|
|
|
|
|
|
interface IProps {
|
|
|
|
matrixClient: MatrixClient;
|
|
|
|
flow: ISSOFlow;
|
|
|
|
loginType?: "sso" | "cas";
|
|
|
|
fragmentAfterLogin?: string;
|
|
|
|
primary?: boolean;
|
|
|
|
}
|
|
|
|
|
2021-01-21 16:33:25 +03:00
|
|
|
const MAX_PER_ROW = 6;
|
|
|
|
|
2020-11-23 20:10:15 +03:00
|
|
|
const SSOButtons: React.FC<IProps> = ({matrixClient, flow, loginType, fragmentAfterLogin, primary}) => {
|
2020-12-16 13:07:07 +03:00
|
|
|
const providers = flow["org.matrix.msc2858.identity_providers"] || [];
|
2020-11-23 20:10:15 +03:00
|
|
|
if (providers.length < 2) {
|
|
|
|
return <div className="mx_SSOButtons">
|
|
|
|
<SSOButton
|
|
|
|
matrixClient={matrixClient}
|
|
|
|
loginType={loginType}
|
|
|
|
fragmentAfterLogin={fragmentAfterLogin}
|
|
|
|
idp={providers[0]}
|
|
|
|
primary={primary}
|
|
|
|
/>
|
|
|
|
</div>;
|
|
|
|
}
|
|
|
|
|
2021-01-21 16:33:25 +03:00
|
|
|
const rows = Math.ceil(providers.length / MAX_PER_ROW);
|
|
|
|
const size = Math.ceil(providers.length / rows);
|
|
|
|
|
2020-11-23 20:10:15 +03:00
|
|
|
return <div className="mx_SSOButtons">
|
2021-01-21 16:33:25 +03:00
|
|
|
{ chunk(providers, size).map(chunk => (
|
|
|
|
<div key={chunk[0].id} className="mx_SSOButtons_row">
|
|
|
|
{ chunk.map(idp => (
|
|
|
|
<SSOButton
|
|
|
|
key={idp.id}
|
|
|
|
matrixClient={matrixClient}
|
|
|
|
loginType={loginType}
|
|
|
|
fragmentAfterLogin={fragmentAfterLogin}
|
|
|
|
idp={idp}
|
|
|
|
mini={true}
|
|
|
|
primary={primary}
|
|
|
|
/>
|
|
|
|
)) }
|
|
|
|
</div>
|
2020-11-23 20:10:15 +03:00
|
|
|
)) }
|
|
|
|
</div>;
|
|
|
|
};
|
|
|
|
|
|
|
|
export default SSOButtons;
|