Skip to content

Commit

Permalink
Avoid same user in multi devices (#47)
Browse files Browse the repository at this point in the history
  • Loading branch information
rcmuniz1994 authored Oct 29, 2023
1 parent d351113 commit 265e14c
Show file tree
Hide file tree
Showing 13 changed files with 379 additions and 34 deletions.
4 changes: 4 additions & 0 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,11 @@ import P2PCallMain from "./features/p2p-call/P2PCallMain";
import CallCreationMain from "./features/call-selection/CallCreationMain";
import CallJoinMain from "./features/call-selection/CallJoinMain";
import PendingUserMain from "./features/call-selection/PendingUserMain";
import useValidateSession from "./hooks/useValidateSession";
import BlockedSession from "./features/auth/BlockedSession";

export default function App() {
useValidateSession();
const dispatch = useAppDispatch();

useEffect(() => {
Expand All @@ -29,6 +32,7 @@ export default function App() {
<Route path="/join" component={CallJoinMain} />
<Route path="/left" component={() => <p>Left.</p>} />
<Route path="/p2p-call/:callUid" component={P2PCallMain} />
<Route path="/blocked-session" component={BlockedSession} />
<Route>
<Redirect to="/" />
</Route>
Expand Down
21 changes: 21 additions & 0 deletions src/components/templates/HomeTemplate.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -161,4 +161,25 @@ describe("HomeTemplate", () => {
)
).toBe(null);
});

it("does not show logout and settings buttons when user session is blocked", () => {
fullRender(
<HomeTemplate>
<p>Hello World!</p>
</HomeTemplate>,
{
preloadedState: {
user: {
...userInitialState,
uid: "123",
status: "authenticated",
isSessionBlocked: true,
},
},
}
);

expect(screen.queryByLabelText("Logout")).toBe(null);
expect(screen.queryByLabelText("Settings")).toBe(null);
});
});
25 changes: 16 additions & 9 deletions src/components/templates/HomeTemplate.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,11 @@ import mainCharWhiteOutlineImg from "../../assets/main-char-white-outline.png";
import mainCharPinkOutlineImg from "../../assets/main-char-pink-outline.png";
import { useAppDispatch, useAppSelector } from "../../state";
import useAgentHelper from "../../hooks/useAgentHelper";
import { logout, selectIsUserAuthenticated } from "../../state/user";
import {
logout,
selectIsSessionBlocked,
selectIsUserAuthenticated,
} from "../../state/user";
import SettingsModal from "../settings/SettingsModal";
import ErrorAlert from "../basic/ErrorAlert";
import WarningAlert from "../basic/WarningAlert";
Expand All @@ -32,6 +36,7 @@ export default function HomeTemplate({
const handleLogoutClick = () => dispatch(logout());

const isAuthenticated = useAppSelector(selectIsUserAuthenticated);
const isSessionBlocked = useAppSelector(selectIsSessionBlocked);

const { canRunWebRTC, isChromeBased, isFirefoxBased } = useAgentHelper();

Expand Down Expand Up @@ -92,7 +97,7 @@ export default function HomeTemplate({
pb: 1,
}}
>
{isAuthenticated && (
{isAuthenticated && !isSessionBlocked && (
<IconButton
aria-label="Logout"
title="Logout"
Expand All @@ -103,13 +108,15 @@ export default function HomeTemplate({
<LogoutIcon />
</IconButton>
)}
<IconButton
aria-label="Settings"
title="Settings"
onClick={openSettings}
>
<SettingsIcon />
</IconButton>
{!isSessionBlocked && (
<IconButton
aria-label="Settings"
title="Settings"
onClick={openSettings}
>
<SettingsIcon />
</IconButton>
)}
</Box>
</Box>
{!canRunWebRTC() && (
Expand Down
10 changes: 10 additions & 0 deletions src/features/auth/BlockedSession.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import "../../testing-helpers/mock-firestore-auth";
import { act } from "react-dom/test-utils";
import fullRender from "../../testing-helpers/fullRender";
import BlockedSession from "./BlockedSession";

describe("BlockedSession", () => {
it("renders", async () => {
await act(() => fullRender(<BlockedSession />));
});
});
21 changes: 21 additions & 0 deletions src/features/auth/BlockedSession.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import Box from "@mui/material/Box";
import HomeTemplate from "../../components/templates/HomeTemplate";
import useRedirectionRule from "../../hooks/useRedirectionRule";
import { Redirect } from "wouter";
import ErrorAlert from "../../components/basic/ErrorAlert";

export default function BlockedSession() {
const goTo = useRedirectionRule();

if (goTo) {
return <Redirect to={goTo} />;
}

return (
<HomeTemplate>
<Box component="span" pr={1}>
<ErrorAlert message="Account in use in another device. Reload to restore this session." />
</Box>
</HomeTemplate>
);
}
129 changes: 110 additions & 19 deletions src/hooks/useRedirectionRule.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,32 @@ import { getRedirectionRule } from "./useRedirectionRule";

describe("getRedirectionRule: / (auth)", () => {
it("when authenticated, go to creation", () => {
const result = getRedirectionRule({ path: "/", hasAuth: true }, {});
const result = getRedirectionRule(
{ path: "/", hasAuth: true, isSessionBlocked: false },
{}
);
expect(result).toBe("/create");
});

it("when not authenticated, stay here for auth", () => {
const result = getRedirectionRule({ path: "/", hasAuth: false }, {});
const result = getRedirectionRule(
{ path: "/", hasAuth: false, isSessionBlocked: false },
{}
);
expect(result).toBe("");
});

it("when autenticated and provided joining uid, then go to join page proceed to device testing", () => {
const result = getRedirectionRule(
{ path: "/", hasAuth: true },
{ path: "/", hasAuth: true, isSessionBlocked: false },
{ joining: "123-321" }
);
expect(result).toBe("/join?callUid=123-321");
});

it("when autenticated and provided creating display name, then go to create page proceed to device testing", () => {
const result = getRedirectionRule(
{ path: "/", hasAuth: true },
{ path: "/", hasAuth: true, isSessionBlocked: false },
{ creating: "Daily" }
);
expect(result).toBe("/create?callDisplayName=Daily"); // TODO: names with special characters?
Expand All @@ -30,100 +36,177 @@ describe("getRedirectionRule: / (auth)", () => {

describe("getRedirectionRule: /create", () => {
it("when not authenticated, then go back to root for login", () => {
const result = getRedirectionRule({ path: "/create", hasAuth: false }, {});
const result = getRedirectionRule(
{ path: "/create", hasAuth: false, isSessionBlocked: false },
{}
);
expect(result).toBe("/");
});

it("when authenticated, stay here for device testing and call creation", () => {
const result = getRedirectionRule({ path: "/create", hasAuth: true }, {});
const result = getRedirectionRule(
{ path: "/create", hasAuth: true, isSessionBlocked: false },
{}
);
expect(result).toBe("");
});

it("when authenticated and has ongoing call, go to its page", () => {
const result = getRedirectionRule(
{ path: "/create", hasAuth: true, ongoingCall: "123-321" },
{
path: "/create",
hasAuth: true,
ongoingCall: "123-321",
isSessionBlocked: false,
},
{}
);
expect(result).toBe("/p2p-call/123-321");
});

it("when session is blocked, got to blocked session page", () => {
const result = getRedirectionRule(
{
path: "/create",
hasAuth: true,
ongoingCall: "123-321",
isSessionBlocked: true,
},
{}
);
expect(result).toBe("/blocked-session");
});
});

describe("getRedirectionRule: /join", () => {
it("when authenticated and provided call uid, then stay here for device testing", () => {
const result = getRedirectionRule(
{ path: "/join", hasAuth: true },
{ path: "/join", hasAuth: true, isSessionBlocked: false },
{ callUid: "123-321" }
);
expect(result).toBe("");
});

it("when not authenticated but provided call uid, then go authenticate", () => {
const result = getRedirectionRule(
{ path: "/join", hasAuth: false },
{ path: "/join", hasAuth: false, isSessionBlocked: false },
{ callUid: "123-321" }
);
expect(result).toBe("/?joining=123-321");
});

it("when not authenticated nor provided call uid, then start reset entire flow (came here by mistake?)", () => {
const result = getRedirectionRule({ path: "/join", hasAuth: false }, {});
const result = getRedirectionRule(
{ path: "/join", hasAuth: false, isSessionBlocked: false },
{}
);
expect(result).toBe("/");
});

it("when authenticated and didnt provide call uid, then stay to manually type it", () => {
const result = getRedirectionRule({ path: "/join", hasAuth: true }, {});
const result = getRedirectionRule(
{ path: "/join", hasAuth: true, isSessionBlocked: false },
{}
);
expect(result).toBe("");
});

it("when authenticated and has pending call, go to pending user page", () => {
const result = getRedirectionRule(
{ path: "/join", hasAuth: true, pendingCall: "123-call-321" },
{
path: "/join",
hasAuth: true,
pendingCall: "123-call-321",
isSessionBlocked: false,
},
{}
);
expect(result).toBe("/pending");
});

it("when session is blocked, got to blocked session page", () => {
const result = getRedirectionRule(
{
path: "/join",
hasAuth: true,
pendingCall: "123-call-321",
isSessionBlocked: true,
},
{}
);
expect(result).toBe("/blocked-session");
});
});

describe("getRedirectionRule: /join", () => {
it("if has pending call, stay waiting", () => {
const result = getRedirectionRule(
{ path: "/pending", hasAuth: true, pendingCall: "123-call-321" },
{
path: "/pending",
hasAuth: true,
pendingCall: "123-call-321",
isSessionBlocked: false,
},
{}
);
expect(result).toBe("");
});

it("if has ongoing call, go for it", () => {
const result = getRedirectionRule(
{ path: "/pending", hasAuth: true, ongoingCall: "123-call-321" },
{
path: "/pending",
hasAuth: true,
ongoingCall: "123-call-321",
isSessionBlocked: false,
},
{}
);
expect(result).toBe("/p2p-call/123-call-321");
});

it("if has none, reset navigation flow", () => {
const result = getRedirectionRule({ path: "/pending", hasAuth: true }, {});
const result = getRedirectionRule(
{ path: "/pending", hasAuth: true, isSessionBlocked: false },
{}
);
expect(result).toBe("/");
});

it("when not authenticated, reset navigation flow", () => {
const result = getRedirectionRule({ path: "/pending", hasAuth: false }, {});
const result = getRedirectionRule(
{ path: "/pending", hasAuth: false, isSessionBlocked: false },
{}
);
expect(result).toBe("/");
});

it("when session is blocked, got to blocked session page", () => {
const result = getRedirectionRule(
{ path: "/pending", hasAuth: true, isSessionBlocked: true },
{}
);
expect(result).toBe("/blocked-session");
});
});

describe("getRedirectionRule: /p2p-call", () => {
it("when authenticated with ongoing call, then stay here", () => {
const result = getRedirectionRule(
{ path: "/p2p-call/123-321", hasAuth: true, ongoingCall: "123-321" },
{
path: "/p2p-call/123-321",
hasAuth: true,
ongoingCall: "123-321",
isSessionBlocked: false,
},
{}
);
expect(result).toBe("");
});

it("when authenticated without ongoing call, go to a page saying good bye", () => {
const result = getRedirectionRule(
{ path: "/p2p-call/123-321", hasAuth: true },
{ path: "/p2p-call/123-321", hasAuth: true, isSessionBlocked: false },
{}
);
// expect(result).toBe("/left");
Expand All @@ -133,9 +216,17 @@ describe("getRedirectionRule: /p2p-call", () => {
it("when not authenticated, be forced to reset flow", () => {
// TODO: retrieve attempt call uid and convert into "/?joining=" flow
const result = getRedirectionRule(
{ path: "/p2p-call/123-321", hasAuth: false },
{ path: "/p2p-call/123-321", hasAuth: false, isSessionBlocked: false },
{}
);
expect(result).toBe("/");
});

it("when session is blocked, got to blocked session page", () => {
const result = getRedirectionRule(
{ path: "/p2p-call/123-321", hasAuth: false, isSessionBlocked: true },
{}
);
expect(result).toBe("/blocked-session");
});
});
Loading

0 comments on commit 265e14c

Please sign in to comment.