Skip to content

Commit 7138b51

Browse files
authored
fix forgot password (#359)
1 parent fc0be9c commit 7138b51

File tree

7 files changed

+148
-53
lines changed

7 files changed

+148
-53
lines changed

package-lock.json

Lines changed: 25 additions & 25 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/editor/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,8 @@
2727
"@tiptap/core": "^2.0.4",
2828
"@blocknote/core": "^0.9.2",
2929
"@emotion/react": "^11.4.0",
30-
"@supabase/auth-ui-react": "^0.4.2",
31-
"@supabase/auth-ui-shared": "^0.1.6",
30+
"@supabase/auth-ui-react": "^0.4.5",
31+
"@supabase/auth-ui-shared": "^0.1.7",
3232
"@supabase/supabase-js": "^2.26.0",
3333
"@syncedstore/yjs-reactive-bindings": "^0.5.1",
3434
"@typecell-org/util": "^0.0.3",

packages/editor/src/app/App.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,6 @@ export const App = observer(
6565
sessionStore as SupabaseSessionStore,
6666
)}
6767
/>
68-
<Route path="/recover" element={<div>Not implemented yet</div>} />
6968
<Route
7069
path="/login"
7170
element={props.authProvider.routes.login(

packages/editor/src/app/main/components/startscreen/StartScreen.tsx

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -190,8 +190,21 @@ export const StartScreen = observer((props: { sessionStore: SessionStore }) => {
190190
together.
191191
</p>
192192
<p>
193-
Create your own workspace and join the community on Discord to
194-
share your thoughts, or contribute to the project on GitHub.
193+
Create your own workspace and join the community on{" "}
194+
<a
195+
target="_blank"
196+
href="https://discord.gg/TcJ9TRC3SV"
197+
rel="noreferrer">
198+
Discord
199+
</a>{" "}
200+
to share your thoughts, or contribute to the project on{" "}
201+
<a
202+
target="_blank"
203+
href="https://github.com/TypeCellOS/TypeCell"
204+
rel="noreferrer">
205+
GitHub
206+
</a>
207+
.
195208
</p>
196209
<p>
197210
Dive into the sneak-peeks below to check out some features we
@@ -388,7 +401,7 @@ export const StartScreen = observer((props: { sessionStore: SessionStore }) => {
388401
target="_blank"
389402
href="https://discord.gg/TcJ9TRC3SV"
390403
rel="noreferrer">
391-
<span>Chat on discord</span>
404+
<span>Chat on Discord</span>
392405
</a>
393406
</li>
394407
<li>

packages/editor/src/app/supabase-auth/SupabaseSessionStore.ts

Lines changed: 28 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ import ProfileResource from "../../store/ProfileResource";
1616
import { TypeCellRemote } from "../../store/yjs-sync/remote/TypeCellRemote";
1717
import { navigateRef } from "../GlobalNavigateRef";
1818

19-
2019
export type SupabaseClientType = ReturnType<typeof createClient<Database>>;
2120

2221
const colors = [
@@ -98,7 +97,7 @@ export class SupabaseSessionStore extends SessionStore {
9897
scheme: "typecell",
9998
authority: "typecell.org",
10099
path: "/" + uniqueId.generateId("document"),
101-
})
100+
}),
102101
);
103102
}
104103

@@ -110,11 +109,15 @@ export class SupabaseSessionStore extends SessionStore {
110109
isLoggedIn: computed,
111110
isLoaded: computed,
112111
});
113-
this.supabase = createClient<Database>(env.VITE_TYPECELL_SUPABASE_URL, env.VITE_TYPECELL_SUPABASE_ANON_KEY, {
114-
auth: {
115-
persistSession: persist,
112+
this.supabase = createClient<Database>(
113+
env.VITE_TYPECELL_SUPABASE_URL,
114+
env.VITE_TYPECELL_SUPABASE_ANON_KEY,
115+
{
116+
auth: {
117+
persistSession: persist,
118+
},
116119
},
117-
});
120+
);
118121
this.initializeReactions();
119122
}
120123

@@ -125,18 +128,20 @@ export class SupabaseSessionStore extends SessionStore {
125128
this.initialized = true;
126129

127130
try {
128-
const session = (await this.supabase.auth.getSession()).data.session || undefined;
131+
const session =
132+
(await this.supabase.auth.getSession()).data.session || undefined;
129133
let previousSessionId = session?.user.id;
130134
const cbData = this.supabase.auth.onAuthStateChange((event, session) => {
131-
132-
133135
// only trigger if user id changed
134136
if (session?.user.id !== previousSessionId) {
135137
previousSessionId = session?.user.id;
136138
this.updateStateFromAuthStore(session || undefined).catch((e) => {
137139
console.error("error initializing sessionstore", e);
138140
});
139141
}
142+
if (event === "PASSWORD_RECOVERY") {
143+
window.location.href = "/recover";
144+
}
140145
});
141146
this._register({
142147
dispose: cbData.data.subscription.unsubscribe,
@@ -167,7 +172,7 @@ export class SupabaseSessionStore extends SessionStore {
167172
}
168173
const session = (await this.supabase.auth.getSession()).data.session;
169174
if (!session) {
170-
throw new Error("unexpected: no session")
175+
throw new Error("unexpected: no session");
171176
}
172177

173178
// create workspace
@@ -184,7 +189,6 @@ export class SupabaseSessionStore extends SessionStore {
184189
remote.dispose();
185190
}
186191

187-
188192
// create profile
189193
const profileId = this.getIdentifierForNewDocument();
190194
{
@@ -195,7 +199,7 @@ export class SupabaseSessionStore extends SessionStore {
195199
const profile = ret.getSpecificType(ProfileResource);
196200
profile.workspaces.set("public", workspaceId.toString());
197201
profile.username = username;
198-
profile.joinedDate = Date.now()
202+
profile.joinedDate = Date.now();
199203

200204
const avatar = session.user.user_metadata?.avatar_url;
201205

@@ -222,13 +226,15 @@ export class SupabaseSessionStore extends SessionStore {
222226
throw new Error(error.message);
223227
}
224228

225-
226229
await this.updateStateFromAuthStore(session, true);
227230
}
228231
/**
229232
* Updates the state of sessionStore based on the internal matrixAuthStore.loggedIn
230233
*/
231-
private async updateStateFromAuthStore(session: Session | undefined, isSignUp = false) {
234+
private async updateStateFromAuthStore(
235+
session: Session | undefined,
236+
isSignUp = false,
237+
) {
232238
// TODO: make work in offline mode (save username offline)
233239
// TODO: don't trigger on refresh of other browser window
234240

@@ -245,7 +251,7 @@ export class SupabaseSessionStore extends SessionStore {
245251
) {
246252
return;
247253
}
248-
254+
249255
let username = session.user.user_metadata.typecell_username;
250256
let profile_id = session.user.user_metadata.typecell_profile_nano_id;
251257
if (!username || !profile_id) {
@@ -254,16 +260,16 @@ export class SupabaseSessionStore extends SessionStore {
254260
.select()
255261
.eq("owner_user_id", session?.user.id)
256262
.eq("is_username", true);
257-
263+
258264
if (usernameRes.data?.length === 1) {
259265
username = usernameRes.data[0].name;
260266
profile_id = usernameRes.data[0].document_nano_id;
261267
await this.supabase.auth.updateUser({
262268
data: {
263269
typecell_username: username,
264270
typecell_profile_nano_id: profile_id,
265-
}
266-
})
271+
},
272+
});
267273
} else {
268274
if (!navigateRef) {
269275
throw new Error("no global navigateRef");
@@ -272,7 +278,9 @@ export class SupabaseSessionStore extends SessionStore {
272278
this.userId = session.user.id;
273279
});
274280
console.log("redirect");
275-
navigateRef.current?.("/username", { state: window.history?.state?.usr});
281+
navigateRef.current?.("/username", {
282+
state: window.history?.state?.usr,
283+
});
276284
// runInAction(() => {
277285
// this.user = {
278286
// type: "user",
@@ -297,7 +305,7 @@ export class SupabaseSessionStore extends SessionStore {
297305
userId: username,
298306
fullUserId: username,
299307
profileId: profile_id,
300-
isSignUp
308+
isSignUp,
301309
};
302310
});
303311
}
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
import { observer } from "mobx-react-lite";
2+
import { Navigate, useLocation, useNavigate } from "react-router-dom";
3+
4+
import { Auth } from "@supabase/auth-ui-react";
5+
import {
6+
// Import predefined theme
7+
ThemeSupa,
8+
} from "@supabase/auth-ui-shared";
9+
import { SessionStore } from "../../../store/local/SessionStore";
10+
import { Logo } from "../../main/components/Logo";
11+
12+
import { useEffect } from "react";
13+
import { SupabaseSessionStore } from "../SupabaseSessionStore";
14+
import AuthStyles from "./AuthStyles.module.css";
15+
16+
export const Recover = observer((props: { sessionStore: SessionStore }) => {
17+
const { sessionStore } = props;
18+
19+
const location = useLocation();
20+
const navigate = useNavigate();
21+
22+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
23+
const from = (location.state as any)?.from?.pathname || "/";
24+
// let pageAfterLogin = window.location.origin + from;
25+
26+
if (!sessionStore.isLoggedIn) {
27+
return <Navigate to={from} replace={true} />;
28+
}
29+
30+
useEffect(() => {
31+
const { data: authListener } = (
32+
sessionStore as SupabaseSessionStore
33+
).supabase.auth.onAuthStateChange((event) => {
34+
if (event === "USER_UPDATED") {
35+
// bit hacky, but otherwise supabase auth ui just displays a login screen and there's no way to excape.
36+
// navigate to main page instead
37+
navigate(from, { replace: true });
38+
}
39+
});
40+
41+
return () => authListener.subscription.unsubscribe();
42+
}, [from, navigate, sessionStore]);
43+
44+
const redirectTo = from;
45+
46+
return (
47+
<div className={AuthStyles.AuthPage}>
48+
<div className={AuthStyles.AuthHeader}>
49+
<div className={AuthStyles.AuthHeaderLogo}>
50+
<Logo></Logo>
51+
</div>
52+
</div>
53+
<div className={AuthStyles.AuthBody}>
54+
<div className={AuthStyles.AuthForm}>
55+
<Auth
56+
magicLink={true}
57+
supabaseClient={(sessionStore as SupabaseSessionStore).supabase}
58+
view="update_password"
59+
appearance={{ theme: ThemeSupa }}
60+
redirectTo={redirectTo}
61+
providers={["google", "github"]}
62+
/>
63+
{/* <div className={AuthStyles.AuthFormFooter}>sdfsdf</div> */}
64+
</div>
65+
</div>
66+
<div className={AuthStyles.AuthFooter}>
67+
{/* <HelperMessage>Powered by Matrix</HelperMessage> */}
68+
</div>
69+
</div>
70+
);
71+
});

packages/editor/src/app/supabase-auth/supabaseAuthProvider.tsx

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
import { Route } from "react-router-dom";
22

3+
import { SupabaseSessionStore } from "./SupabaseSessionStore";
34
import { Login } from "./routes/Login";
5+
import { Recover } from "./routes/Recover";
46
import { Register } from "./routes/Register";
57
import { Username } from "./routes/Username";
6-
import { SupabaseSessionStore } from "./SupabaseSessionStore";
78

89
export const supabaseAuthProvider = {
910
routes: {
@@ -15,7 +16,10 @@ export const supabaseAuthProvider = {
1516
),
1617
additionalRoutes: (sessionStore: SupabaseSessionStore) => (
1718
<>
18-
<Route path="/recover" element={<div>Not implemented yet</div>} />
19+
<Route
20+
path="/recover"
21+
element={<Recover sessionStore={sessionStore} />}
22+
/>
1923
<Route
2024
path="/username"
2125
element={<Username sessionStore={sessionStore} />}

0 commit comments

Comments
 (0)