@rpcbase/client 0.12.0 → 0.13.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.
@@ -0,0 +1,37 @@
1
+ @import "helpers";
2
+
3
+ #forgot-password-wrapper {
4
+ height: 100%;
5
+ display: flex;
6
+ flex-direction: column;
7
+ align-items: center;
8
+ padding-top: 40px;
9
+ padding-bottom: 40px;
10
+ // background-color: var(--bs-secondary);
11
+ background-color: $gray-500;
12
+
13
+ hr {
14
+ background-color: $gray-500;
15
+ }
16
+
17
+ footer {
18
+ color: $light !important;
19
+ border-top: none !important;
20
+ padding-top: 0 !important;
21
+ margin-bottom: 0 !important;
22
+ }
23
+
24
+
25
+ .form-forgot {
26
+ width: 100%;
27
+ max-width: 380px;
28
+ margin: auto;
29
+ background-color: $light;
30
+ border-radius: 22px;
31
+ border: 1px solid $gray-600;
32
+ }
33
+
34
+ .form-forgot .form-floating:focus-within {
35
+ z-index: 2;
36
+ }
37
+ }
@@ -0,0 +1,117 @@
1
+ /* @flow */
2
+ import {useState, useEffect} from "react"
3
+ import {useHash} from "react-use"
4
+ import {ActivityIndicator} from "react-native"
5
+ import isEmail from "validator/lib/isEmail"
6
+
7
+ import post from "../../helpers/post"
8
+
9
+ import {set_is_signed_in} from "../index"
10
+ import Footer from "../Footer"
11
+
12
+ import "./forgot-password.scss"
13
+
14
+ const ForgotPassword = ({name, logo}) => {
15
+ const [hash, setHash] = useHash()
16
+
17
+ const [isLoading, setIsLoading] = useState(false)
18
+ const [isSuccess, setIsSuccess] = useState(false)
19
+ const [errors, setErrors] = useState()
20
+
21
+ const [email, setEmail] = useState("")
22
+
23
+ useEffect(() => {
24
+ if (hash?.length > 1) {
25
+ const val = hash.slice(1)
26
+
27
+ const decoded = atob(val)
28
+ if (isEmail(decoded)) {
29
+ setEmail(decoded)
30
+ // remove the hash
31
+ // isn't there a better way
32
+ history.pushState(
33
+ "",
34
+ document.title,
35
+ window.location.pathname + window.location.search
36
+ )
37
+ }
38
+ }
39
+ }, [hash])
40
+
41
+ const onSubmit = async(e) => {
42
+ e.preventDefault()
43
+ setIsLoading(true)
44
+ const res = await post("/api/v1/auth/reset_password", {email})
45
+ setIsLoading(false)
46
+
47
+ if (res.status === "ok") {
48
+ setErrors(null)
49
+ setIsSuccess(true)
50
+ } else {
51
+ setErrors(res.errors)
52
+ }
53
+ }
54
+
55
+ const onChangeEmail = (e) => setEmail(e.target.value)
56
+
57
+ return (
58
+ <div id="forgot-password-wrapper">
59
+ <div className="form-forgot text-center px-4 py-4 shadow-lg">
60
+ <div>
61
+ <div className="d-flex align-items-center justify-content-center">
62
+ {logo}
63
+ <span className="ms-1 fs-4">{name}</span>
64
+ </div>
65
+
66
+ <hr />
67
+
68
+ <h1 className="h4 mt-3 mb-3 fw-normal">Reset your password</h1>
69
+
70
+ {isSuccess && (
71
+ <p className="text-success">
72
+ Success. If there is an account associated with this email, you will receive a password reset link in your inbox.
73
+ </p>
74
+ )}
75
+
76
+ <form onSubmit={onSubmit}>
77
+
78
+ {errors?.form && (
79
+ <p className="text-danger">{errors.form}</p>
80
+ )}
81
+
82
+ <div className="form-floating mb-4">
83
+ <input type="email"
84
+ disabled={isSuccess}
85
+ className="form-control"
86
+ id="input-email"
87
+ placeholder="name@example.com"
88
+ value={email}
89
+ onChange={onChangeEmail} />
90
+ <label htmlFor="input-email">Email Address</label>
91
+ </div>
92
+
93
+
94
+ <button id={"btn-submit"}
95
+ type="submit"
96
+ disabled={isLoading || isSuccess}
97
+ className="w-100 btn btn-lg btn-primary"
98
+ onClick={onSubmit}>
99
+ <div className="d-flex flex-row align-items-center justify-content-center">
100
+ {isLoading && (
101
+ <div className="me-2"><ActivityIndicator color="#FFFFFF" /></div>
102
+ )}
103
+ Reset my Password
104
+ </div>
105
+ </button>
106
+
107
+ </form>
108
+
109
+ </div>
110
+ </div>
111
+
112
+ <Footer name={name} />
113
+ </div>
114
+ )
115
+ }
116
+
117
+ export default ForgotPassword
@@ -0,0 +1,138 @@
1
+ /* @flow */
2
+ import {useState, useEffect} from "react"
3
+ import {useSearchParam} from "react-use"
4
+ import {ActivityIndicator} from "react-native"
5
+ import isEmail from "validator/lib/isEmail"
6
+
7
+ import post from "../../helpers/post"
8
+
9
+ import {set_is_signed_in} from "../index"
10
+ import Footer from "../Footer"
11
+
12
+ import "./set-new-password.scss"
13
+
14
+ const SetNewPassword = ({name, logo}) => {
15
+ const [isLoading, setIsLoading] = useState(false)
16
+ const [error, setError] = useState()
17
+ const [isSuccess, setIsSuccess] = useState(false)
18
+
19
+ const [password1, setPassword1] = useState("")
20
+ const [password2, setPassword2] = useState("")
21
+
22
+ const user_id = useSearchParam("id")
23
+ const token = useSearchParam("token")
24
+
25
+ useEffect(() => {
26
+ console.log("TOKEN", user_id, token)
27
+ }, [user_id, token])
28
+
29
+ const onSubmit = async(e) => {
30
+ e.preventDefault()
31
+
32
+ if (password1.length < 12) {
33
+ setError("Your password is too short")
34
+ return
35
+ }
36
+
37
+ if (password1 !== password2) {
38
+ setError("Passwords do not match")
39
+ return
40
+ }
41
+
42
+ setIsLoading(true)
43
+ setError(null)
44
+
45
+ const password = password1
46
+ const res = await post("/api/v1/auth/set_new_password", {
47
+ user_id,
48
+ token,
49
+ password,
50
+ })
51
+ console.log("GOT RESSSS", res)
52
+ setIsLoading(false)
53
+
54
+ if (res.status === "ok") {
55
+ setIsSuccess(true)
56
+ } else {
57
+ setError(res.message)
58
+ }
59
+ }
60
+
61
+ const onChangePassword1 = (e) => setPassword1(e.target.value)
62
+ const onChangePassword2 = (e) => setPassword2(e.target.value)
63
+
64
+ return (
65
+ <div id="set-new-password-wrapper">
66
+ <div className="form-set-new-password text-center px-4 py-4 shadow-lg">
67
+ <div>
68
+ <div className="d-flex align-items-center justify-content-center">
69
+ {logo}
70
+ <span className="ms-1 fs-4">{name}</span>
71
+ </div>
72
+
73
+ <hr />
74
+
75
+ <h1 className="h4 mt-3 mb-3 fw-normal">New Password</h1>
76
+ <p className="text-start text-muted">
77
+ Passwords must use at least 12 characters.
78
+ </p>
79
+
80
+ {error && (
81
+ <p className="text-start text-danger">{error}</p>
82
+ )}
83
+
84
+ {isSuccess && (
85
+ <p className="text-start text-success">
86
+ Your new password has successfully been set, you may now <a href="/signin">sign in</a> to your account
87
+ </p>
88
+ )}
89
+
90
+
91
+ <form onSubmit={onSubmit}>
92
+
93
+ <div className="form-floating">
94
+ <input type="password"
95
+ className="form-control"
96
+ id="input-password1"
97
+ placeholder="Password"
98
+ disabled={isLoading || isSuccess}
99
+ value={password1}
100
+ onChange={onChangePassword1} />
101
+ <label htmlFor="input-password1">Password</label>
102
+ </div>
103
+
104
+ <div className="form-floating">
105
+ <input type="password"
106
+ className="form-control"
107
+ id="input-password2"
108
+ placeholder="Confirm Password"
109
+ disabled={isLoading || isSuccess}
110
+ value={password2}
111
+ onChange={onChangePassword2} />
112
+ <label htmlFor="input-password2">Confirm Password</label>
113
+ </div>
114
+
115
+ <button id={"btn-submit"}
116
+ type="submit"
117
+ disabled={isLoading || isSuccess}
118
+ className="w-100 btn btn-lg btn-primary mt-4"
119
+ onClick={onSubmit}>
120
+ <div className="d-flex flex-row align-items-center justify-content-center">
121
+ {isLoading && (
122
+ <div className="me-2"><ActivityIndicator color="#FFFFFF" /></div>
123
+ )}
124
+ Set new Password
125
+ </div>
126
+ </button>
127
+
128
+ </form>
129
+
130
+ </div>
131
+ </div>
132
+
133
+ <Footer name={name} />
134
+ </div>
135
+ )
136
+ }
137
+
138
+ export default SetNewPassword
@@ -0,0 +1,47 @@
1
+ @import "helpers";
2
+
3
+ #set-new-password-wrapper {
4
+ height: 100%;
5
+ display: flex;
6
+ flex-direction: column;
7
+ align-items: center;
8
+ padding-top: 40px;
9
+ padding-bottom: 40px;
10
+ // background-color: var(--bs-secondary);
11
+ background-color: $gray-500;
12
+
13
+ hr {
14
+ background-color: $gray-500;
15
+ }
16
+
17
+ footer {
18
+ color: $light !important;
19
+ border-top: none !important;
20
+ padding-top: 0 !important;
21
+ margin-bottom: 0 !important;
22
+ }
23
+
24
+ .form-set-new-password {
25
+ width: 100%;
26
+ max-width: 380px;
27
+ margin: auto;
28
+ background-color: $light;
29
+ border-radius: 22px;
30
+ border: 1px solid $gray-600;
31
+ }
32
+
33
+ .form-set-new-password .form-floating:focus-within {
34
+ z-index: 2;
35
+ }
36
+
37
+ .form-set-new-password #input-password1 {
38
+ margin-bottom: -1px;
39
+ border-bottom-right-radius: 0;
40
+ border-bottom-left-radius: 0;
41
+ }
42
+
43
+ .form-set-new-password #input-password2 {
44
+ border-top-left-radius: 0;
45
+ border-top-right-radius: 0;
46
+ }
47
+ }
@@ -1,24 +1,34 @@
1
1
  /* @flow */
2
2
  import {useState, useEffect} from "react"
3
3
  import {useSearchParam} from "react-use"
4
+ import isEmail from "validator/lib/isEmail"
4
5
 
5
6
  import post from "../../helpers/post"
6
7
 
7
8
  import {set_is_signed_in} from "../index"
8
9
  import Footer from "../Footer"
9
- // import sign_in from "rpc!server/auth/sign_in"
10
10
 
11
11
  import "./sign-in.scss"
12
12
 
13
13
  const SignIn = ({name, logo}) => {
14
- const [email, setEmail] = useState("")
15
- const [password, setPassword] = useState("")
16
-
17
14
  const [isLoading, setIsLoading] = useState(false)
18
15
  const [errors, setErrors] = useState()
19
16
 
17
+ const [email, setEmail] = useState("")
18
+ const [password, setPassword] = useState("")
19
+ const [forgotUrlParam, setForgotUrlParam] = useState(null)
20
+
20
21
  const redirect = useSearchParam("redirect")
21
22
 
23
+ useEffect(() => {
24
+ console.log("email changed", email)
25
+ if (isEmail(email)) {
26
+ setForgotUrlParam(btoa(email))
27
+ } else {
28
+ setForgotUrlParam("")
29
+ }
30
+ }, [email])
31
+
22
32
  const onSubmit = async(e) => {
23
33
  e.preventDefault()
24
34
  setIsLoading(true)
@@ -99,6 +109,10 @@ const SignIn = ({name, logo}) => {
99
109
  </div>
100
110
 
101
111
  <button className="w-100 btn btn-lg btn-primary" type="submit" onClick={onSubmit}>Sign In</button>
112
+
113
+ <div className="mt-3 text-start w-100">
114
+ <a href={`/forgot-password${forgotUrlParam && "#" + forgotUrlParam}`}>Forgot your password?</a>
115
+ </div>
102
116
  </form>
103
117
 
104
118
  <hr />
package/auth/index.js CHANGED
@@ -4,10 +4,18 @@ import page from "page"
4
4
  import SignIn from "./SignIn"
5
5
  import SignUp from "./SignUp"
6
6
  import SignOut from "./SignOut"
7
+ import ForgotPassword from "./ForgotPassword"
8
+ import SetNewPassword from "./SetNewPassword"
7
9
 
8
10
  import post from "../helpers/post"
9
11
 
10
- export {SignIn, SignUp, SignOut}
12
+ export {
13
+ SignIn,
14
+ SignUp,
15
+ SignOut,
16
+ ForgotPassword,
17
+ SetNewPassword,
18
+ }
11
19
 
12
20
  const UID_STORAGE_KEY = "rb::session-user_id"
13
21
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rpcbase/client",
3
- "version": "0.12.0",
3
+ "version": "0.13.0",
4
4
  "scripts": {
5
5
  "test": "echo \"Error: no test specified\" && exit 0"
6
6
  },