diff --git a/packages/app/src/components/Root/Root.tsx b/packages/app/src/components/Root/Root.tsx index af7759d86f..8795b50e1d 100644 --- a/packages/app/src/components/Root/Root.tsx +++ b/packages/app/src/components/Root/Root.tsx @@ -18,6 +18,7 @@ import React, { FC, useContext } from 'react'; import PropTypes from 'prop-types'; import { Link, makeStyles, Typography } from '@material-ui/core'; import HomeIcon from '@material-ui/icons/Home'; +import AccountCircle from '@material-ui/icons/AccountCircle'; import { Sidebar, SidebarPage, @@ -77,6 +78,7 @@ const Root: FC<{}> = ({ children }) => ( + diff --git a/packages/core/src/api/app/AppBuilder.tsx b/packages/core/src/api/app/AppBuilder.tsx index e2f56c4cdb..393388cc38 100644 --- a/packages/core/src/api/app/AppBuilder.tsx +++ b/packages/core/src/api/app/AppBuilder.tsx @@ -25,6 +25,7 @@ import { SystemIconKey, defaultSystemIcons, } from '../../icons'; +import LoginPage from './LoginPage'; class AppImpl implements App { constructor(private readonly systemIcons: SystemIcons) {} @@ -86,6 +87,10 @@ export default class AppBuilder { } } + routes.push( + , + ); + return () => ( diff --git a/packages/core/src/api/app/LoginPage/LoginPage.tsx b/packages/core/src/api/app/LoginPage/LoginPage.tsx new file mode 100644 index 0000000000..4f8214b35c --- /dev/null +++ b/packages/core/src/api/app/LoginPage/LoginPage.tsx @@ -0,0 +1,177 @@ +/* + * Copyright 2020 Spotify AB + * + * 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, { FC, useState } from 'react'; +import { GitHub as GitHubIcon } from '@material-ui/icons'; +import Page from '../../../layout/Page'; +import Header from '../../../layout/Header'; +import Content from '../../../layout/Content/Content'; +import ContentHeader from '../../../layout/ContentHeader/ContentHeader'; +import { + Grid, + Typography, + Button, + TextField, + List, + ListItem, + Link +} from '@material-ui/core'; +import InfoCard from '../../../layout/InfoCard/InfoCard'; + +enum AuthType { + GitHub, +} + +const LoginPage: FC<{}> = () => { + const [githubUsername, setGithubUsername] = useState(String); + const [githubPersonalAuthToken, setGithubPersonalAuthToken] = useState(String); + const [loginDetails, setLoginDetails] = useState(Object); + + const saveGithubInfo = (info: {}) => { + localStorage.setItem('githubLoginDetails', JSON.stringify(info)); + setLoginDetails(info); + }; + + const deleteGithubInfo = () => { + localStorage.removeItem('githubLoginDetails'); + setLoginDetails(undefined); + }; + + const handleTokenRegistration = (event: any) => { + switch (event.target.name) { + case 'github-username-tf': + setGithubUsername(event.target.value); + break; + case 'github-auth-tf': + setGithubPersonalAuthToken(event.target.value); + break; + default: + break; + } + }; + + const fetchGitHubToken = (username: String, token: String) => { + fetch('https://api.github.com/user', { + headers: new Headers({ + Authorization: `Basic ${btoa(`${username}:${token}`)}`, + 'Content-Type': 'application/x-www-form-urlencoded', + }), + }) + .then((response) => { + if (response.status === 200) return response.json(); + throw Error(`${response.status} ${response.statusText}`); + }) + .then((data) => { + const info = { + username: username, + token: token, + name: data.name || data.login, + }; + saveGithubInfo(info); + }) + .catch(() => {}); + }; + + const validateUsernameAndToken = (username: String, token: String) => { + if (username === undefined || username === null || username === '') + return false; + + if (token === undefined || token === null || token === '') return false; + + return true; + }; + + const authenticate = (type: AuthType) => { + switch (type) { + case AuthType.GitHub: + { + const username = githubUsername; + const token = githubPersonalAuthToken; + if (validateUsernameAndToken(username, token)) + fetchGitHubToken(username, token); + } + break; + default: + break; + } + }; + + const LoginIndicator = () => { + const ls = localStorage.getItem('githubLoginDetails'); + if (ls !== null) { + const obj = ls || loginDetails ? JSON.parse(ls) : loginDetails; + return ( + + {`Welcome, ${obj.name}!`} +
+ Logout +
+ ); + } + return ( + + Welcome, guest! + + ); + }; + + return ( + +
+ +
+ + + + + + + GitHub + + + + + + + + + + + + + + + + +
+ ); +}; + +export default LoginPage; \ No newline at end of file diff --git a/packages/core/src/api/app/LoginPage/index.ts b/packages/core/src/api/app/LoginPage/index.ts new file mode 100644 index 0000000000..094029448c --- /dev/null +++ b/packages/core/src/api/app/LoginPage/index.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2020 Spotify AB + * + * 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. + */ + +export { default } from './LoginPage';