@rpcbase/client 0.148.0 → 0.149.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/auth/SignIn/SignInEmailForm.js +111 -0
- package/auth/SignIn/index.js +24 -118
- package/auth/SignIn/sign-in.scss +0 -14
- package/auth/SignUp/SignUpEmailForm.js +98 -0
- package/auth/SignUp/index.js +28 -84
- package/package.json +1 -1
- package/src/ui/oauth/GitHub.js +26 -0
- package/src/ui/oauth/index.js +10 -0
- package/src/ui/oauth/oauth.scss +16 -0
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/* @flow */
|
|
2
|
+
import assert from "assert"
|
|
3
|
+
import {useState, useEffect} from "react"
|
|
4
|
+
import {useSearchParam} from "react-use"
|
|
5
|
+
import isEmail from "validator/lib/isEmail"
|
|
6
|
+
import page from "page"
|
|
7
|
+
|
|
8
|
+
import post from "../../helpers/post"
|
|
9
|
+
import {reconnect as rts_reconnect} from "../../rts/rts"
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
const SignInEmailForm = ({onSuccess, onSuccessRedirect}) => {
|
|
14
|
+
const redirect = useSearchParam("redirect")
|
|
15
|
+
|
|
16
|
+
const [isLoading, setIsLoading] = useState(false)
|
|
17
|
+
|
|
18
|
+
const [email, setEmail] = useState("")
|
|
19
|
+
const [password, setPassword] = useState("")
|
|
20
|
+
const [forgotUrlParam, setForgotUrlParam] = useState(null)
|
|
21
|
+
|
|
22
|
+
const [errors, setErrors] = useState()
|
|
23
|
+
|
|
24
|
+
useEffect(() => {
|
|
25
|
+
if (isEmail(email)) {
|
|
26
|
+
setForgotUrlParam(btoa(email))
|
|
27
|
+
} else {
|
|
28
|
+
setForgotUrlParam("")
|
|
29
|
+
}
|
|
30
|
+
}, [email])
|
|
31
|
+
|
|
32
|
+
const onSubmit = async(e) => {
|
|
33
|
+
e.preventDefault()
|
|
34
|
+
setIsLoading(true)
|
|
35
|
+
const res = await post("/api/v1/auth/sign_in", {email, password})
|
|
36
|
+
setIsLoading(false)
|
|
37
|
+
|
|
38
|
+
// success
|
|
39
|
+
if (res.status === "ok") {
|
|
40
|
+
log("signed in res: ok", res)
|
|
41
|
+
log("redirect to:", redirect || onSuccessRedirect)
|
|
42
|
+
const {user_id} = res
|
|
43
|
+
assert(res.user_id, "missing user_id")
|
|
44
|
+
|
|
45
|
+
setUid(user_id)
|
|
46
|
+
set_tenant_id(user_id.slice(8, 16))
|
|
47
|
+
set_is_signed_in(true)
|
|
48
|
+
|
|
49
|
+
// we must now reconnect on the websocket as we now have a new cookie
|
|
50
|
+
rts_reconnect()
|
|
51
|
+
onSuccess()
|
|
52
|
+
if (redirect) {
|
|
53
|
+
page(redirect)
|
|
54
|
+
} else {
|
|
55
|
+
page(onSuccessRedirect)
|
|
56
|
+
}
|
|
57
|
+
// errors
|
|
58
|
+
} else {
|
|
59
|
+
log("sign in error", res)
|
|
60
|
+
|
|
61
|
+
setErrors(res.errors)
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const onChangeEmail = (e) => {
|
|
66
|
+
setEmail(e.target.value)
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const onChangePassword = (e) => {
|
|
70
|
+
setPassword(e.target.value)
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
return (
|
|
75
|
+
<form onSubmit={onSubmit}>
|
|
76
|
+
|
|
77
|
+
{errors?.form && (
|
|
78
|
+
<p className="text-danger">{errors.form}</p>
|
|
79
|
+
)}
|
|
80
|
+
|
|
81
|
+
<div className="form-floating text-start">
|
|
82
|
+
<input type="email"
|
|
83
|
+
className="form-control"
|
|
84
|
+
id="input-email"
|
|
85
|
+
placeholder="name@example.com"
|
|
86
|
+
value={email}
|
|
87
|
+
onChange={onChangeEmail} />
|
|
88
|
+
<label htmlFor="input-email">Email Address</label>
|
|
89
|
+
</div>
|
|
90
|
+
|
|
91
|
+
<div className="form-floating text-start">
|
|
92
|
+
<input type="password"
|
|
93
|
+
className="form-control"
|
|
94
|
+
id="input-password"
|
|
95
|
+
placeholder="Password"
|
|
96
|
+
value={password}
|
|
97
|
+
onChange={onChangePassword} />
|
|
98
|
+
<label htmlFor="input-password">Password</label>
|
|
99
|
+
</div>
|
|
100
|
+
|
|
101
|
+
<div className="mt-2 text-start w-100">
|
|
102
|
+
<a href={`/forgot-password${forgotUrlParam && "#" + forgotUrlParam}`}>Forgot your password?</a>
|
|
103
|
+
</div>
|
|
104
|
+
|
|
105
|
+
<button className="mt-4 mb-3 w-100 btn btn-lg btn-primary" type="submit" onClick={onSubmit}>Sign In</button>
|
|
106
|
+
|
|
107
|
+
</form>
|
|
108
|
+
)
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
export default SignInEmailForm
|
package/auth/SignIn/index.js
CHANGED
|
@@ -1,87 +1,31 @@
|
|
|
1
1
|
/* @flow */
|
|
2
2
|
import assert from "assert"
|
|
3
|
-
import {useState, useEffect} from "react"
|
|
4
|
-
import {useSearchParam} from "react-use"
|
|
5
|
-
import isEmail from "validator/lib/isEmail"
|
|
6
3
|
import page from "page"
|
|
7
4
|
import debug from "debug"
|
|
8
5
|
|
|
9
|
-
import
|
|
10
|
-
import {reconnect as rts_reconnect} from "../../rts/rts"
|
|
6
|
+
import authConfig from "@rpcbase/dot-rb/auth"
|
|
11
7
|
|
|
12
8
|
import {set_is_signed_in, setUid, set_tenant_id} from "../index"
|
|
9
|
+
|
|
10
|
+
import {AUTH_BUTTONS} from "../../src/ui/oauth"
|
|
13
11
|
import Footer from "../Footer"
|
|
14
12
|
|
|
13
|
+
import SignInEmailForm from "./SignInEmailForm"
|
|
14
|
+
|
|
15
15
|
import "./sign-in.scss"
|
|
16
16
|
|
|
17
17
|
|
|
18
18
|
const log = debug("rb:auth:signin")
|
|
19
19
|
|
|
20
|
-
const
|
|
20
|
+
const hasOAuth = authConfig.oauth_providers?.length > 0
|
|
21
|
+
const hasEmail = authConfig.has_email_signup
|
|
21
22
|
|
|
22
23
|
const SignIn = ({
|
|
23
24
|
name,
|
|
24
25
|
logo,
|
|
25
|
-
onSuccessRedirect = "/
|
|
26
|
+
onSuccessRedirect = "/",
|
|
26
27
|
onSuccess = () => null
|
|
27
28
|
}) => {
|
|
28
|
-
const [isLoading, setIsLoading] = useState(false)
|
|
29
|
-
const [errors, setErrors] = useState()
|
|
30
|
-
|
|
31
|
-
const [email, setEmail] = useState("")
|
|
32
|
-
const [password, setPassword] = useState("")
|
|
33
|
-
const [forgotUrlParam, setForgotUrlParam] = useState(null)
|
|
34
|
-
|
|
35
|
-
const redirect = useSearchParam("redirect")
|
|
36
|
-
|
|
37
|
-
useEffect(() => {
|
|
38
|
-
if (isEmail(email)) {
|
|
39
|
-
setForgotUrlParam(btoa(email))
|
|
40
|
-
} else {
|
|
41
|
-
setForgotUrlParam("")
|
|
42
|
-
}
|
|
43
|
-
}, [email])
|
|
44
|
-
|
|
45
|
-
const onSubmit = async(e) => {
|
|
46
|
-
e.preventDefault()
|
|
47
|
-
setIsLoading(true)
|
|
48
|
-
const res = await post("/api/v1/auth/sign_in", {email, password})
|
|
49
|
-
setIsLoading(false)
|
|
50
|
-
|
|
51
|
-
// success
|
|
52
|
-
if (res.status === "ok") {
|
|
53
|
-
log("signed in res: ok", res)
|
|
54
|
-
log("redirect to:", redirect || onSuccessRedirect)
|
|
55
|
-
const {user_id} = res
|
|
56
|
-
assert(res.user_id, "missing user_id")
|
|
57
|
-
|
|
58
|
-
setUid(user_id)
|
|
59
|
-
set_tenant_id(user_id.slice(8, 16))
|
|
60
|
-
set_is_signed_in(true)
|
|
61
|
-
|
|
62
|
-
// we must now reconnect on the websocket as we now have a new cookie
|
|
63
|
-
rts_reconnect()
|
|
64
|
-
onSuccess()
|
|
65
|
-
if (redirect) {
|
|
66
|
-
page(redirect)
|
|
67
|
-
} else {
|
|
68
|
-
page(onSuccessRedirect)
|
|
69
|
-
}
|
|
70
|
-
// errors
|
|
71
|
-
} else {
|
|
72
|
-
log("sign in error", res)
|
|
73
|
-
|
|
74
|
-
setErrors(res.errors)
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
const onChangeEmail = (e) => {
|
|
79
|
-
setEmail(e.target.value)
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
const onChangePassword = (e) => {
|
|
83
|
-
setPassword(e.target.value)
|
|
84
|
-
}
|
|
85
29
|
|
|
86
30
|
return (
|
|
87
31
|
<div id="sign-in-wrapper">
|
|
@@ -99,66 +43,28 @@ const SignIn = ({
|
|
|
99
43
|
<a href="/signup" className="ms-1">Sign up here</a>
|
|
100
44
|
</p>
|
|
101
45
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
className="form-control"
|
|
111
|
-
id="input-email"
|
|
112
|
-
placeholder="name@example.com"
|
|
113
|
-
value={email}
|
|
114
|
-
onChange={onChangeEmail} />
|
|
115
|
-
<label htmlFor="input-email">Email Address</label>
|
|
116
|
-
</div>
|
|
117
|
-
|
|
118
|
-
<div className="form-floating text-start">
|
|
119
|
-
<input type="password"
|
|
120
|
-
className="form-control"
|
|
121
|
-
id="input-password"
|
|
122
|
-
placeholder="Password"
|
|
123
|
-
value={password}
|
|
124
|
-
onChange={onChangePassword} />
|
|
125
|
-
<label htmlFor="input-password">Password</label>
|
|
126
|
-
</div>
|
|
127
|
-
|
|
128
|
-
<div className="mt-2 text-start w-100">
|
|
129
|
-
<a href={`/forgot-password${forgotUrlParam && "#" + forgotUrlParam}`}>Forgot your password?</a>
|
|
130
|
-
</div>
|
|
131
|
-
|
|
132
|
-
<button className="mt-4 mb-3 w-100 btn btn-lg btn-primary" type="submit" onClick={onSubmit}>Sign In</button>
|
|
133
|
-
|
|
134
|
-
</form>
|
|
135
|
-
|
|
136
|
-
{SIGNIN_WITH_GITHUB && (
|
|
46
|
+
{hasEmail && (
|
|
47
|
+
<SignInEmailForm
|
|
48
|
+
onSuccess={onSuccess}
|
|
49
|
+
onSuccessRedirect={onSuccessRedirect}
|
|
50
|
+
/>
|
|
51
|
+
)}
|
|
52
|
+
|
|
53
|
+
{hasEmail && hasOAuth && (
|
|
137
54
|
<>
|
|
138
55
|
<hr />
|
|
139
56
|
<p className="text-muted">OR</p>
|
|
140
|
-
|
|
141
|
-
<a href="/signup"
|
|
142
|
-
className="sign-in-github-btn p-2 btn-lg w-100"
|
|
143
|
-
style={{}}>
|
|
144
|
-
<div style={{}} className="me-2">
|
|
145
|
-
<svg height="28px" width="28px" viewBox="0 0 16 16" style={{fill: "currentColor"}}>
|
|
146
|
-
<path fillRule={"evenodd"} d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38
|
|
147
|
-
0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01
|
|
148
|
-
1.08.58 1.23.82.72 1.21 1.87.87
|
|
149
|
-
2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12
|
|
150
|
-
0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08
|
|
151
|
-
2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0
|
|
152
|
-
.21.15.46.55.38A8.013 8.013 0 0016 8c0-4.42-3.58-8-8-8z"/>
|
|
153
|
-
</svg>
|
|
154
|
-
</div>
|
|
155
|
-
<div className="">
|
|
156
|
-
Sign in with GitHub
|
|
157
|
-
</div>
|
|
158
|
-
</a>
|
|
159
57
|
</>
|
|
160
58
|
)}
|
|
161
59
|
|
|
60
|
+
{hasOAuth && authConfig.oauth_providers.map((provider, index) => {
|
|
61
|
+
const Comp = AUTH_BUTTONS[provider.id]
|
|
62
|
+
assert(Comp, `unable to find oauth button for provider: ${JSON.stringify(provider)}`)
|
|
63
|
+
|
|
64
|
+
return <Comp key={`${provider.id}-${index}`} text="Sign in" />
|
|
65
|
+
})}
|
|
66
|
+
|
|
67
|
+
|
|
162
68
|
</div>
|
|
163
69
|
</div>
|
|
164
70
|
|
package/auth/SignIn/sign-in.scss
CHANGED
|
@@ -7,7 +7,6 @@
|
|
|
7
7
|
align-items: center;
|
|
8
8
|
padding-top: 40px;
|
|
9
9
|
padding-bottom: 40px;
|
|
10
|
-
// background-color: var(--bs-secondary);
|
|
11
10
|
background-color: $gray-500;
|
|
12
11
|
|
|
13
12
|
hr {
|
|
@@ -54,17 +53,4 @@
|
|
|
54
53
|
border-top-left-radius: 0;
|
|
55
54
|
border-top-right-radius: 0;
|
|
56
55
|
}
|
|
57
|
-
|
|
58
|
-
.sign-in-github-btn {
|
|
59
|
-
display: inline-flex;
|
|
60
|
-
align-items: center;
|
|
61
|
-
background-color: #24292E;
|
|
62
|
-
font-size: 1.25rem;
|
|
63
|
-
color: $gray-200;
|
|
64
|
-
text-decoration: none;
|
|
65
|
-
|
|
66
|
-
&:hover {
|
|
67
|
-
color: $white;
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
56
|
}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/* @flow */
|
|
2
|
+
import {useState} from "react"
|
|
3
|
+
|
|
4
|
+
import {reconnect as rts_reconnect} from "../../rts/rts"
|
|
5
|
+
|
|
6
|
+
import {set_is_signed_in, setUid, set_tenant_id} from "../index"
|
|
7
|
+
import post from "../../helpers/post"
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
const SignUpEmailForm = ({onSuccessRedirect, onSuccess}) => {
|
|
11
|
+
const [email, setEmail] = useState("")
|
|
12
|
+
const [password, setPassword] = useState("")
|
|
13
|
+
const [passwordConfirm, setPasswordConfirm] = useState("")
|
|
14
|
+
const [error, setError] = useState(null)
|
|
15
|
+
|
|
16
|
+
const onSubmit = async() => {
|
|
17
|
+
setError(null)
|
|
18
|
+
if (!password || password !== passwordConfirm) {
|
|
19
|
+
setError("Passwords do not match")
|
|
20
|
+
return
|
|
21
|
+
}
|
|
22
|
+
const res = await post("/public/v1/auth/sign_up", {email, password})
|
|
23
|
+
|
|
24
|
+
if (res.status === "ok") {
|
|
25
|
+
const {user_id} = res
|
|
26
|
+
setUid(user_id)
|
|
27
|
+
set_tenant_id(user_id.slice(8, 16))
|
|
28
|
+
set_is_signed_in(true)
|
|
29
|
+
|
|
30
|
+
// we must now reconnect on the websocket as we have a new cookie
|
|
31
|
+
rts_reconnect()
|
|
32
|
+
onSuccess()
|
|
33
|
+
page(onSuccessRedirect)
|
|
34
|
+
} else if (res.status === "error") {
|
|
35
|
+
setError(res.message)
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const onChangeEmail = (e) => {
|
|
40
|
+
setEmail(e.target.value)
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const onChangePassword = (e) => {
|
|
44
|
+
setPassword(e.target.value)
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const onChangePasswordConfirm = (e) => {
|
|
48
|
+
setPasswordConfirm(e.target.value)
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
return (
|
|
53
|
+
<>
|
|
54
|
+
{error && (
|
|
55
|
+
<div className="invalid-feedback d-flex text-start">
|
|
56
|
+
{error}
|
|
57
|
+
</div>
|
|
58
|
+
)}
|
|
59
|
+
|
|
60
|
+
<div className="form-floating text-start">
|
|
61
|
+
<input type="email"
|
|
62
|
+
className="form-control"
|
|
63
|
+
id="input-email"
|
|
64
|
+
placeholder="name@example.com"
|
|
65
|
+
value={email}
|
|
66
|
+
onChange={onChangeEmail} />
|
|
67
|
+
<label htmlFor="input-email">Email Address</label>
|
|
68
|
+
</div>
|
|
69
|
+
<div className="form-floating text-start">
|
|
70
|
+
<input type="password"
|
|
71
|
+
className="form-control"
|
|
72
|
+
id="input-password"
|
|
73
|
+
placeholder="Password"
|
|
74
|
+
value={password}
|
|
75
|
+
onChange={onChangePassword} />
|
|
76
|
+
<label htmlFor="input-password">Password</label>
|
|
77
|
+
</div>
|
|
78
|
+
<div className="form-floating text-start">
|
|
79
|
+
<input type="password"
|
|
80
|
+
className="form-control"
|
|
81
|
+
id="input-password-confirm"
|
|
82
|
+
placeholder="Confirm Password"
|
|
83
|
+
value={passwordConfirm}
|
|
84
|
+
onChange={onChangePasswordConfirm} />
|
|
85
|
+
<label htmlFor="input-password-confirm">Confirm Password</label>
|
|
86
|
+
</div>
|
|
87
|
+
|
|
88
|
+
<div className="checkbox mt-3 mb-3 text-start">
|
|
89
|
+
<label style={{cursor: "pointer", userSelect: "none"}}>
|
|
90
|
+
<input type="checkbox" value="terms-accepted" /> I agree to the terms and privacy policy.
|
|
91
|
+
</label>
|
|
92
|
+
</div>
|
|
93
|
+
<button className="w-100 btn btn-lg btn-primary" type="submit" onClick={onSubmit}>Sign Up</button>
|
|
94
|
+
</>
|
|
95
|
+
)
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
export default SignUpEmailForm
|
package/auth/SignUp/index.js
CHANGED
|
@@ -1,61 +1,26 @@
|
|
|
1
1
|
/* @flow */
|
|
2
|
-
import
|
|
3
|
-
import page from "page"
|
|
2
|
+
import assert from "assert"
|
|
4
3
|
|
|
5
|
-
import
|
|
4
|
+
import authConfig from "@rpcbase/dot-rb/auth"
|
|
5
|
+
|
|
6
|
+
import {AUTH_BUTTONS} from "../../src/ui/oauth"
|
|
6
7
|
|
|
7
|
-
import {set_is_signed_in, setUid, set_tenant_id} from "../index"
|
|
8
|
-
import post from "../../helpers/post"
|
|
9
8
|
import Footer from "../Footer"
|
|
10
9
|
|
|
10
|
+
import SignUpEmailForm from "./SignUpEmailForm"
|
|
11
|
+
|
|
11
12
|
import "./sign-up.scss"
|
|
12
13
|
|
|
14
|
+
|
|
15
|
+
const hasOAuth = authConfig.oauth_providers?.length > 0
|
|
16
|
+
const hasEmail = authConfig.has_email_signup
|
|
17
|
+
|
|
13
18
|
const SignUp = ({
|
|
14
19
|
logo,
|
|
15
20
|
name,
|
|
16
|
-
onSuccessRedirect = "/
|
|
21
|
+
onSuccessRedirect = "/",
|
|
17
22
|
onSuccess = () => null,
|
|
18
23
|
}) => {
|
|
19
|
-
const [email, setEmail] = useState("")
|
|
20
|
-
const [password, setPassword] = useState("")
|
|
21
|
-
const [passwordConfirm, setPasswordConfirm] = useState("")
|
|
22
|
-
const [error, setError] = useState(null)
|
|
23
|
-
|
|
24
|
-
const onSubmit = async() => {
|
|
25
|
-
setError(null)
|
|
26
|
-
if (!password || password !== passwordConfirm) {
|
|
27
|
-
setError("Passwords do not match")
|
|
28
|
-
return
|
|
29
|
-
}
|
|
30
|
-
const res = await post("/public/v1/auth/sign_up", {email, password})
|
|
31
|
-
|
|
32
|
-
if (res.status === "ok") {
|
|
33
|
-
const {user_id} = res
|
|
34
|
-
setUid(user_id)
|
|
35
|
-
set_tenant_id(user_id.slice(8, 16))
|
|
36
|
-
set_is_signed_in(true)
|
|
37
|
-
|
|
38
|
-
// we must now reconnect on the websocket as we have a new cookie
|
|
39
|
-
rts_reconnect()
|
|
40
|
-
onSuccess()
|
|
41
|
-
page(onSuccessRedirect)
|
|
42
|
-
} else if (res.status === "error") {
|
|
43
|
-
setError(res.message)
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
const onChangeEmail = (e) => {
|
|
48
|
-
setEmail(e.target.value)
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
const onChangePassword = (e) => {
|
|
52
|
-
setPassword(e.target.value)
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
const onChangePasswordConfirm = (e) => {
|
|
56
|
-
setPasswordConfirm(e.target.value)
|
|
57
|
-
}
|
|
58
|
-
|
|
59
24
|
|
|
60
25
|
return (
|
|
61
26
|
<div id="sign-up-wrapper">
|
|
@@ -68,51 +33,30 @@ const SignUp = ({
|
|
|
68
33
|
<hr />
|
|
69
34
|
|
|
70
35
|
<h1 className="h4 mt-3 mb-3 fw-normal">Sign Up</h1>
|
|
71
|
-
<p className="text-muted">
|
|
36
|
+
<p className="text-start text-muted">
|
|
72
37
|
Already have an account ? <a href="/signin" className="ms-1">Sign in here</a>
|
|
73
38
|
</p>
|
|
74
39
|
|
|
75
|
-
{
|
|
76
|
-
<
|
|
77
|
-
{
|
|
78
|
-
|
|
40
|
+
{hasEmail && (
|
|
41
|
+
<SignUpEmailForm
|
|
42
|
+
onSuccess={onSuccess}
|
|
43
|
+
onSuccessRedirect={onSuccessRedirect}
|
|
44
|
+
/>
|
|
79
45
|
)}
|
|
80
46
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
onChange={onChangeEmail} />
|
|
88
|
-
<label htmlFor="input-email">Email Address</label>
|
|
89
|
-
</div>
|
|
90
|
-
<div className="form-floating text-start">
|
|
91
|
-
<input type="password"
|
|
92
|
-
className="form-control"
|
|
93
|
-
id="input-password"
|
|
94
|
-
placeholder="Password"
|
|
95
|
-
value={password}
|
|
96
|
-
onChange={onChangePassword} />
|
|
97
|
-
<label htmlFor="input-password">Password</label>
|
|
98
|
-
</div>
|
|
99
|
-
<div className="form-floating text-start">
|
|
100
|
-
<input type="password"
|
|
101
|
-
className="form-control"
|
|
102
|
-
id="input-password-confirm"
|
|
103
|
-
placeholder="Confirm Password"
|
|
104
|
-
value={passwordConfirm}
|
|
105
|
-
onChange={onChangePasswordConfirm} />
|
|
106
|
-
<label htmlFor="input-password-confirm">Confirm Password</label>
|
|
107
|
-
</div>
|
|
47
|
+
{hasEmail && hasOAuth && (
|
|
48
|
+
<>
|
|
49
|
+
<hr />
|
|
50
|
+
<p className="text-muted">OR</p>
|
|
51
|
+
</>
|
|
52
|
+
)}
|
|
108
53
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
</label>
|
|
113
|
-
</div>
|
|
114
|
-
<button className="w-100 btn btn-lg btn-primary" type="submit" onClick={onSubmit}>Sign Up</button>
|
|
54
|
+
{hasOAuth && authConfig.oauth_providers.map((provider, index) => {
|
|
55
|
+
const Comp = AUTH_BUTTONS[provider.id]
|
|
56
|
+
assert(Comp, `unable to find oauth button for provider: ${JSON.stringify(provider)}`)
|
|
115
57
|
|
|
58
|
+
return <Comp key={`${provider.id}-${index}`} text="Sign up"/>
|
|
59
|
+
})}
|
|
116
60
|
</div>
|
|
117
61
|
</div>
|
|
118
62
|
|
package/package.json
CHANGED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/* @flow */
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
export const GitHub = ({text}) => {
|
|
5
|
+
|
|
6
|
+
return (
|
|
7
|
+
<a href="/signup"
|
|
8
|
+
className="sign-in-github-btn p-2 btn-lg w-100"
|
|
9
|
+
style={{}}>
|
|
10
|
+
<div style={{}} className="me-2">
|
|
11
|
+
<svg height="28px" width="28px" viewBox="0 0 16 16" style={{fill: "currentColor"}}>
|
|
12
|
+
<path fillRule={"evenodd"} d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38
|
|
13
|
+
0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01
|
|
14
|
+
1.08.58 1.23.82.72 1.21 1.87.87
|
|
15
|
+
2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12
|
|
16
|
+
0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08
|
|
17
|
+
2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0
|
|
18
|
+
.21.15.46.55.38A8.013 8.013 0 0016 8c0-4.42-3.58-8-8-8z"/>
|
|
19
|
+
</svg>
|
|
20
|
+
</div>
|
|
21
|
+
<div className="">
|
|
22
|
+
{text} with GitHub
|
|
23
|
+
</div>
|
|
24
|
+
</a>
|
|
25
|
+
)
|
|
26
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
@import "helpers";
|
|
2
|
+
|
|
3
|
+
.sign-in-github-btn {
|
|
4
|
+
display: inline-flex;
|
|
5
|
+
align-items: center;
|
|
6
|
+
background-color: #24292E;
|
|
7
|
+
font-size: 1.25rem;
|
|
8
|
+
color: $gray-200;
|
|
9
|
+
text-decoration: none;
|
|
10
|
+
|
|
11
|
+
border-radius: $border-radius;
|
|
12
|
+
|
|
13
|
+
&:hover {
|
|
14
|
+
color: $white;
|
|
15
|
+
}
|
|
16
|
+
}
|