Skip to content

Commit 4a0834d

Browse files
committed
added auth sub app
1 parent 5a633cf commit 4a0834d

21 files changed

Lines changed: 579 additions & 29 deletions

File tree

.github/workflows/auth.yml

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
name: deploy-auth
2+
3+
on:
4+
push:
5+
branches:
6+
- master
7+
path:
8+
- 'packages/auth/**'
9+
10+
defaults:
11+
run:
12+
working-directory: packages/auth
13+
14+
jobs:
15+
build:
16+
runs-on: ubuntu-latest
17+
18+
steps:
19+
- uses: actions/checkout@v2
20+
- run: npm install
21+
- run: npm run build
22+
23+
- uses: shinyinc/action-aws-cli@v1.2
24+
- run: aws s3 sync dist s3://${{ secrets.AWS_S3_BUCKET_NAME }}/auth/latest
25+
env:
26+
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
27+
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
28+
AWS_DEFAULT_REGION: "ap-southeast-2"
29+
30+
- run: aws cloudfront create-invalidation --distribution-id ${{secrets.AWS_DISTRIBUTION_ID}} --paths "/auth/latest/remoteEntry.js"
31+
env:
32+
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
33+
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
34+
AWS_DEFAULT_REGION: "ap-southeast-2"
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
module.exports = {
2+
module: {
3+
rules: [
4+
{
5+
test: /\.m?js$/,
6+
exclude: /node_modules/,
7+
use: {
8+
loader: 'babel-loader',
9+
options: {
10+
presets: ['@babel/preset-react', '@babel/preset-env'],
11+
plugins: ['@babel/plugin-transform-runtime'],
12+
}
13+
}
14+
}
15+
]
16+
}
17+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
const { merge } = require('webpack-merge')
2+
const HtmlWebpackPlugin = require('html-webpack-plugin')
3+
const ModuleFederationPlugin = require('webpack/lib/container/ModuleFederationPlugin')
4+
const commonConfig = require('./webpack.common')
5+
const packageJson = require('../package.json')
6+
7+
const devConfig = {
8+
mode: 'development',
9+
output:{
10+
publicPath: "http://localhost:8082/"
11+
},
12+
devServer: {
13+
port: 8082,
14+
historyApiFallback: true,
15+
},
16+
plugins: [
17+
new ModuleFederationPlugin({
18+
name: 'auth',
19+
filename: 'remoteEntry.js',
20+
exposes: {
21+
'./AuthApp': './src/bootstrap'
22+
},
23+
shared: packageJson.dependencies,
24+
}),
25+
new HtmlWebpackPlugin({
26+
template: './public/index.html'
27+
})
28+
]
29+
}
30+
31+
module.exports = merge(commonConfig, devConfig)
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
const { merge } = require('webpack-merge')
2+
const ModuleFederationPlugin = require('webpack/lib/container/ModuleFederationPlugin')
3+
const commonConfig = require('./webpack.common')
4+
const packageJson = require('../package.json')
5+
6+
const prodConfig = {
7+
mode: 'production',
8+
output: {
9+
filename: '[name].[contenthash].js',
10+
publicPath: '/auth/latest/'
11+
},
12+
plugins: [
13+
new ModuleFederationPlugin({
14+
name: 'auth',
15+
filename: 'remoteEntry.js',
16+
exposes: {
17+
'./AuthApp': './src/bootstrap'
18+
},
19+
shared: packageJson.dependencies
20+
})
21+
]
22+
}
23+
module.exports = merge(commonConfig, prodConfig)

packages/auth/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22
"name": "auth",
33
"version": "1.0.0",
44
"scripts": {
5-
"test": "echo \"Error: no test specified\" && exit 1"
5+
"start": "webpack serve --config config/webpack.dev.js",
6+
"build": "webpack --config config/webpack.prod.js"
67
},
78
"dependencies": {
89
"@material-ui/core": "^4.11.0",

packages/auth/public/index.html

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8">
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
6+
<title>Auth</title>
7+
</head>
8+
<body>
9+
<!-- assumption,expected to be present only in the auth app and can't be duplicated in the container -->
10+
<div id="_auth-dev-root"></div>
11+
</body>
12+
</html>

packages/auth/src/App.js

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import React from 'react'
2+
import { StylesProvider, createGenerateClassName } from '@material-ui/core/styles'
3+
import { Switch, Route, Router } from 'react-router-dom'
4+
import Signin from './components/Signin'
5+
import Signup from './components/Signup'
6+
7+
const generateClassName = createGenerateClassName({
8+
productionPrefix: "au"
9+
})
10+
11+
const App = ({ history, onSignIn }) => {
12+
return (
13+
<div>
14+
<StylesProvider generateClassName={generateClassName}>
15+
<Router history={history}>
16+
<Switch>
17+
<Route path="/auth/signin" >
18+
<Signin onSignIn={onSignIn} />
19+
</Route>
20+
<Route path="/auth/signup">
21+
<Signup onSignIn={onSignIn} />
22+
</Route>
23+
</Switch>
24+
</Router>
25+
</StylesProvider>
26+
</div>
27+
)
28+
}
29+
30+
export default App

packages/auth/src/bootstrap.js

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import React from "react";
2+
import ReactDOM from "react-dom"
3+
import { createMemoryHistory, createBrowserHistory } from 'history'
4+
import App from "./App";
5+
6+
// Mount function to start up the app
7+
const mount = (el, { onNavigate, onSignIn, defaultHistory, initialPath }) => {
8+
const history = defaultHistory || createMemoryHistory({
9+
initialEntries: [initialPath]
10+
})
11+
if (onNavigate) {
12+
history.listen(onNavigate)
13+
}
14+
ReactDOM.render(
15+
<App onSignIn={onSignIn} history={history} />,
16+
el
17+
)
18+
19+
return {
20+
onParentNavigate({ pathname: nextPathname }) {
21+
const { pathname } = history.location
22+
if (pathname !== nextPathname) {
23+
history.push(nextPathname)
24+
}
25+
}
26+
}
27+
}
28+
29+
// If we are in development and in isolation,
30+
// call mount immediately
31+
if (process.env.NODE_ENV === 'development') {
32+
const devRoot = document.querySelector("#_auth-dev-root")
33+
if (devRoot) {
34+
mount(devRoot, { defaultHistory: createBrowserHistory() })
35+
}
36+
}
37+
38+
// We are running through container
39+
// and we should export the mount function
40+
export { mount }
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
import React from 'react';
2+
import Avatar from '@material-ui/core/Avatar';
3+
import Button from '@material-ui/core/Button';
4+
import TextField from '@material-ui/core/TextField';
5+
import FormControlLabel from '@material-ui/core/FormControlLabel';
6+
import Checkbox from '@material-ui/core/Checkbox';
7+
import Grid from '@material-ui/core/Grid';
8+
import Box from '@material-ui/core/Box';
9+
import LockOutlinedIcon from '@material-ui/icons/LockOutlined';
10+
import Typography from '@material-ui/core/Typography';
11+
import { makeStyles } from '@material-ui/core/styles';
12+
import Container from '@material-ui/core/Container';
13+
import { Link } from 'react-router-dom';
14+
15+
function Copyright() {
16+
return (
17+
<Typography variant="body2" color="textSecondary" align="center">
18+
{'Copyright © '}
19+
<Link color="inherit" to="/">
20+
Your Website
21+
</Link>{' '}
22+
{new Date().getFullYear()}
23+
{'.'}
24+
</Typography>
25+
);
26+
}
27+
28+
const useStyles = makeStyles((theme) => ({
29+
'@global': {
30+
a: {
31+
textDecoration: 'none',
32+
},
33+
},
34+
paper: {
35+
marginTop: theme.spacing(8),
36+
display: 'flex',
37+
flexDirection: 'column',
38+
alignItems: 'center',
39+
},
40+
avatar: {
41+
margin: theme.spacing(1),
42+
backgroundColor: theme.palette.secondary.main,
43+
},
44+
form: {
45+
width: '100%',
46+
marginTop: theme.spacing(1),
47+
},
48+
submit: {
49+
margin: theme.spacing(3, 0, 2),
50+
},
51+
}));
52+
53+
export default function SignIn({ onSignIn }) {
54+
const classes = useStyles();
55+
56+
return (
57+
<Container component="main" maxWidth="xs">
58+
<div className={classes.paper}>
59+
<Avatar className={classes.avatar}>
60+
<LockOutlinedIcon />
61+
</Avatar>
62+
<Typography component="h1" variant="h5">
63+
Sign in
64+
</Typography>
65+
<form
66+
onSubmit={(e) => e.preventDefault()}
67+
className={classes.form}
68+
noValidate
69+
>
70+
<TextField
71+
variant="outlined"
72+
margin="normal"
73+
required
74+
fullWidth
75+
id="email"
76+
label="Email Address"
77+
name="email"
78+
autoComplete="email"
79+
autoFocus
80+
/>
81+
<TextField
82+
variant="outlined"
83+
margin="normal"
84+
required
85+
fullWidth
86+
name="password"
87+
label="Password"
88+
type="password"
89+
id="password"
90+
autoComplete="current-password"
91+
/>
92+
<FormControlLabel
93+
control={<Checkbox value="remember" color="primary" />}
94+
label="Remember me"
95+
/>
96+
<Button
97+
type="submit"
98+
fullWidth
99+
variant="contained"
100+
color="primary"
101+
className={classes.submit}
102+
onClick={onSignIn}
103+
>
104+
Sign In
105+
</Button>
106+
<Grid container>
107+
<Grid item>
108+
<Link to="/auth/signup">{"Don't have an account? Sign Up"}</Link>
109+
</Grid>
110+
</Grid>
111+
</form>
112+
</div>
113+
<Box mt={8}>
114+
<Copyright />
115+
</Box>
116+
</Container>
117+
);
118+
}

0 commit comments

Comments
 (0)