Skip to content

Commit 369e9d8

Browse files
committed
refactor & add login with google
1 parent 94ad1d2 commit 369e9d8

File tree

10 files changed

+243
-29
lines changed

10 files changed

+243
-29
lines changed

src/chat-api/RawData.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,7 @@ export interface RawUser {
186186

187187
export interface RawUserConnection {
188188
id: string;
189-
provider: "GOOGLE";
189+
provider: "GOOGLE" | "GOOGLE_DRIVE";
190190
connectedAt: number;
191191
}
192192

src/chat-api/services/UserService.ts

Lines changed: 54 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,52 @@ import { Presence } from "../store/useUsers";
1515
import { request } from "./Request";
1616
import ServiceEndpoints from "./ServiceEndpoints";
1717

18-
export async function createGoogleAccountLink(): Promise<string> {
18+
export async function createGoogleDriveAccountLink() {
1919
return request({
20-
url: env.SERVER_URL + "/api/google/create-link",
20+
url: env.SERVER_URL + "/api/connections/google-drive/create-link",
2121
method: "GET",
2222
notJSON: true,
2323
useToken: true
2424
});
2525
}
2626

27+
export async function createGoogleAccountLink(
28+
login?: boolean
29+
): Promise<string> {
30+
return request({
31+
url: env.SERVER_URL + "/api/connections/google/create-link",
32+
params: login ? { login } : undefined,
33+
method: "GET",
34+
notJSON: true,
35+
useToken: true
36+
});
37+
}
38+
39+
export async function unlinkAccountWithGoogle(): Promise<{
40+
status: boolean;
41+
}> {
42+
return request({
43+
url: env.SERVER_URL + "/api/connections/google/unlink-account",
44+
method: "POST",
45+
useToken: true
46+
});
47+
}
48+
49+
export async function linkAccountWithGoogle(
50+
code: string,
51+
nerimityUserToken: string
52+
): Promise<{ connection: RawUserConnection }> {
53+
return request({
54+
url: env.SERVER_URL + "/api/connections/google/link-account",
55+
method: "POST",
56+
body: {
57+
code,
58+
nerimityToken: nerimityUserToken
59+
},
60+
useToken: false
61+
});
62+
}
63+
2764
export async function registerFCM(token: string) {
2865
return request({
2966
url: env.SERVER_URL + "/api" + ServiceEndpoints.user("register-fcm"),
@@ -38,16 +75,16 @@ export async function fetchInventory() {
3875
return request<RawInventoryItem[]>({
3976
url: env.SERVER_URL + "/api" + ServiceEndpoints.user("inventory"),
4077
method: "GET",
41-
useToken: true,
78+
useToken: true
4279
});
4380
}
4481

45-
export async function linkAccountWithGoogle(
82+
export async function linkAccountWithGoogleDrive(
4683
code: string,
4784
nerimityUserToken: string
4885
): Promise<{ connection: RawUserConnection }> {
4986
return request({
50-
url: env.SERVER_URL + "/api/google/link-account",
87+
url: env.SERVER_URL + "/api/connections/google-drive/link-account",
5188
method: "POST",
5289
body: {
5390
code,
@@ -56,17 +93,21 @@ export async function linkAccountWithGoogle(
5693
useToken: false
5794
});
5895
}
59-
export async function unlinkAccountWithGoogle(): Promise<{ status: boolean }> {
96+
export async function unlinkAccountWithGoogleDrive(): Promise<{
97+
status: boolean;
98+
}> {
6099
return request({
61-
url: env.SERVER_URL + "/api/google/unlink-account",
100+
url: env.SERVER_URL + "/api/connections/google-drive/unlink-account",
62101
method: "POST",
63102
useToken: true
64103
});
65104
}
66105

67-
export async function getGoogleAccessToken(): Promise<{ accessToken: string }> {
106+
export async function getGoogleDriveAccessToken(): Promise<{
107+
accessToken: string;
108+
}> {
68109
return request({
69-
url: env.SERVER_URL + "/api/google/access-token",
110+
url: env.SERVER_URL + "/api/connections/google-drive/access-token",
70111
method: "GET",
71112
useToken: true
72113
});
@@ -124,15 +165,17 @@ export async function verifyEmailConfirmCode(
124165
// error returns {path?, message}
125166
export async function loginRequest(
126167
email: string,
127-
password: string
168+
password: string,
169+
googleCode?: string
128170
): Promise<{ token: string }> {
129171
const isUsernameAndTag = email.includes(":");
130172
return request({
131173
url: env.SERVER_URL + "/api" + ServiceEndpoints.login(),
132174
method: "POST",
133175
body: {
134176
...(isUsernameAndTag ? { usernameAndTag: email } : { email }),
135-
password
177+
password,
178+
...(googleCode ? { googleCode } : {})
136179
}
137180
});
138181
}

src/chat-api/store/useMessages.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import socketClient from "../socketClient";
1010
import useAccount from "./useAccount";
1111
import useChannelProperties from "./useChannelProperties";
1212
import useChannels from "./useChannels";
13-
import { getGoogleAccessToken } from "../services/UserService";
13+
import { getGoogleDriveAccessToken } from "../services/UserService";
1414
import { uploadFileGoogleDrive } from "@/common/driveAPI";
1515
import { batch } from "solid-js";
1616
import { uploadAttachment } from "../services/nerimityCDNService";
@@ -243,7 +243,7 @@ const sendAndStoreMessage = async (channelId: string, content?: string) => {
243243
let googleDriveFileId: string | undefined;
244244
if (file && shouldUploadToGoogleDrive) {
245245
try {
246-
const accessToken = await getGoogleAccessToken();
246+
const accessToken = await getGoogleDriveAccessToken();
247247
const res = await uploadFileGoogleDrive(
248248
file,
249249
accessToken.accessToken,

src/components/message-pane/MessagePane.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -403,7 +403,7 @@ function MessageArea(props: {
403403
const shouldUploadToGoogleDrive = attachment.uploadTo === "google_drive";
404404
if (
405405
shouldUploadToGoogleDrive &&
406-
!account.user()?.connections.find((c) => c.provider === "GOOGLE")
406+
!account.user()?.connections.find((c) => c.provider === "GOOGLE_DRIVE")
407407
) {
408408
createPortal((close) => <GoogleDriveLinkModal close={close} />);
409409
return;

src/components/settings/ConnectionsSettings.tsx

Lines changed: 52 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,9 @@ import SettingsBlock, {
1010
import Button from "../ui/Button";
1111
import {
1212
createGoogleAccountLink,
13-
unlinkAccountWithGoogle
13+
createGoogleDriveAccountLink,
14+
unlinkAccountWithGoogle,
15+
unlinkAccountWithGoogleDrive
1416
} from "@/chat-api/services/UserService";
1517
import {
1618
OAuth2AuthorizedApplication,
@@ -54,6 +56,7 @@ export default function ConnectionsSettings() {
5456
function Connections() {
5557
return (
5658
<>
59+
<GoogleDriveLink />
5760
<GoogleLink />
5861
</>
5962
);
@@ -146,9 +149,54 @@ const ThirdPartyConnectionItem = (props: {
146149
);
147150
};
148151

152+
function GoogleDriveLink() {
153+
const { account } = useStore();
154+
const isGoogleDriveConnected = () =>
155+
account.user()?.connections?.find((c) => c.provider === "GOOGLE_DRIVE");
156+
157+
const linkGoogle = () => {
158+
createGoogleDriveAccountLink()
159+
.then((url) => {
160+
window.open(url, "_blank");
161+
})
162+
.catch((err) => {
163+
toast(err.message);
164+
});
165+
};
166+
const unlinkGoogle = async () => {
167+
await unlinkAccountWithGoogleDrive().catch((err) => {
168+
toast(err.message);
169+
});
170+
};
171+
172+
return (
173+
<SettingsBlock
174+
iconSrc="/assets/Google.svg"
175+
label="Google Drive"
176+
description={t("settings.connections.googleDriveDescription")}
177+
>
178+
<Show when={!isGoogleDriveConnected()}>
179+
<Button
180+
label={t("settings.connections.linkButton")}
181+
iconName="link"
182+
onClick={linkGoogle}
183+
/>
184+
</Show>
185+
<Show when={isGoogleDriveConnected()}>
186+
<Button
187+
label={t("settings.connections.unlinkButton")}
188+
color="var(--alert-color)"
189+
iconName="link_off"
190+
onClick={unlinkGoogle}
191+
/>
192+
</Show>
193+
</SettingsBlock>
194+
);
195+
}
196+
149197
function GoogleLink() {
150198
const { account } = useStore();
151-
const isConnected = () =>
199+
const isGoogleConnected = () =>
152200
account.user()?.connections?.find((c) => c.provider === "GOOGLE");
153201

154202
const linkGoogle = () => {
@@ -172,14 +220,14 @@ function GoogleLink() {
172220
label="Google"
173221
description={t("settings.connections.googleDescription")}
174222
>
175-
<Show when={!isConnected()}>
223+
<Show when={!isGoogleConnected()}>
176224
<Button
177225
label={t("settings.connections.linkButton")}
178226
iconName="link"
179227
onClick={linkGoogle}
180228
/>
181229
</Show>
182-
<Show when={isConnected()}>
230+
<Show when={isGoogleConnected()}>
183231
<Button
184232
label={t("settings.connections.unlinkButton")}
185233
color="var(--alert-color)"

src/index.tsx

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -146,9 +146,12 @@ const ResetPasswordPage = lazy(() => import("./pages/ResetPasswordPage"));
146146
const TermsAndConditionsPage = lazy(
147147
() => import("./pages/TermsAndConditionsPage")
148148
);
149-
const GoogleRedirectLinkAccount = lazy(
149+
const GoogleRedirectLinkAccountPage = lazy(
150150
() => import("./pages/GoogleRedirectLinkAccountPage")
151151
);
152+
const GoogleDriveRedirectLinkAccountPage = lazy(
153+
() => import("./pages/GoogleDriveRedirectLinkAccountPage")
154+
);
152155

153156
const TicketsPage = lazy(() => import("./components/tickets/TicketsPage"));
154157

@@ -401,8 +404,12 @@ render(
401404
component={TermsAndConditionsPage}
402405
/>
403406
<Route
404-
path="/google-redirect"
405-
component={GoogleRedirectLinkAccount}
407+
path="/connections/google-drive-redirect"
408+
component={GoogleDriveRedirectLinkAccountPage}
409+
/>
410+
<Route
411+
path="/connections/google-redirect"
412+
component={GoogleRedirectLinkAccountPage}
406413
/>
407414
<Route path="/i/:inviteId" component={InviteRedirect} />
408415
<Route path="/p/:postId" component={PostRedirect} />

src/locales/list/en-gb.json

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -736,7 +736,8 @@
736736
"unauthorizeButton": "Unauthorise",
737737
"unauthorizing": "Un-authorising…"
738738
},
739-
"googleDescription": "Linking your Google account will allow you to upload files in Nerimity. Files will be stored in your Google Drive.",
739+
"googleDriveDescription": "Linking your Google account will allow you to upload files in Nerimity. Files will be stored in your Google Drive.",
740+
"googleDescription": "Linking your Google account will allow you to login using Google quickly and easily.",
740741
"linkButton": "Link",
741742
"unlinkButton": "Unlink"
742743
},
@@ -1167,8 +1168,12 @@
11671168
"addButton": "Add bot",
11681169
"permissions": "Bot Permissions"
11691170
},
1171+
"googleDriveAccountLink": {
1172+
"linking": "Linking your account with Google Drive…",
1173+
"success": "Account linked! You may now close this window."
1174+
},
11701175
"googleAccountLink": {
1171-
"linking": "Linking your account with Google",
1176+
"linking": "Linking your account with Google",
11721177
"success": "Account linked! You may now close this window."
11731178
},
11741179
"invite": {
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
import PageHeader from "../components/PageHeader";
2+
import { styled } from "solid-styled-components";
3+
import { FlexColumn } from "@/components/ui/Flexbox";
4+
import PageFooter from "@/components/PageFooter";
5+
import { useSearchParams } from "solid-navigator";
6+
import { Show, createSignal, onMount } from "solid-js";
7+
import { linkAccountWithGoogleDrive } from "@/chat-api/services/UserService";
8+
import Text from "@/components/ui/Text";
9+
10+
import { useTransContext } from "@nerimity/solid-i18lite";
11+
12+
const PageContainer = styled("div")`
13+
display: flex;
14+
flex-direction: column;
15+
width: 100%;
16+
flex: 1;
17+
`;
18+
19+
const Content = styled("div")`
20+
display: flex;
21+
flex-direction: column;
22+
margin: 8px;
23+
margin-top: 0;
24+
margin-bottom: 0;
25+
border-radius: 8px;
26+
flex: 1;
27+
`;
28+
29+
const CenterContainer = styled(FlexColumn)`
30+
gap: 20px;
31+
margin: 30px;
32+
margin-top: 50px;
33+
max-width: 800px;
34+
align-self: center;
35+
align-items: center;
36+
text-align: center;
37+
`;
38+
39+
export default function GoogleDriveRedirectLinkAccountPage() {
40+
const [t] = useTransContext();
41+
const [searchParams] = useSearchParams<{ state: string; code: string }>();
42+
const [error, setError] = createSignal("");
43+
const [success, setSuccess] = createSignal(false);
44+
45+
onMount(async () => {
46+
const code = searchParams.code;
47+
const userToken = searchParams.state;
48+
49+
const res = await linkAccountWithGoogleDrive(code!, userToken!).catch(
50+
(err) => {
51+
setError(err.message);
52+
}
53+
);
54+
55+
if (!res) return;
56+
if (res.connection) {
57+
setSuccess(true);
58+
}
59+
});
60+
61+
return (
62+
<PageContainer class="page-container">
63+
<PageHeader hideAccountInfo />
64+
<Content class="content">
65+
<CenterContainer>
66+
{t("googleDriveAccountLink.linking")}
67+
<Show when={error()}>
68+
<Text color="var(--alert-color)">{error()}</Text>
69+
</Show>
70+
<Show when={success()}>
71+
<Text color="var(--success-color)">
72+
{t("googleDriveAccountLink.success")}
73+
</Text>
74+
</Show>
75+
</CenterContainer>
76+
</Content>
77+
<PageFooter />
78+
</PageContainer>
79+
);
80+
}

src/pages/GoogleRedirectLinkAccountPage.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ export default function GoogleRedirectLinkAccountPage() {
6767
</Show>
6868
<Show when={success()}>
6969
<Text color="var(--success-color)">
70-
{t("googleAccountLink.success")}
70+
{t("googleDriveAccountLink.success")}
7171
</Text>
7272
</Show>
7373
</CenterContainer>

0 commit comments

Comments
 (0)