Skip to content

Commit 38dffd9

Browse files
authored
Add dummy auth model (#171)
closes #156
1 parent 53d9c3d commit 38dffd9

10 files changed

Lines changed: 288 additions & 91 deletions

File tree

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import { useEffect, useState } from "react";
2+
3+
const createDummyUser = () => {
4+
return {
5+
id: 1,
6+
name: "dummy.cat",
7+
image:
8+
"https://user-images.githubusercontent.com/25859075/29918905-88dcc646-8e5c-11e7-81ec-242bc58dce1b.jpg",
9+
email: "dummyuser@rocket.chat",
10+
emailVerified: false,
11+
phoneNumber: null,
12+
displayName: "dummy.cat",
13+
};
14+
};
15+
16+
export const useDummyAuth = () => {
17+
const [user, setUser] = useState({});
18+
19+
useEffect(() => {
20+
const isStoredInSession = JSON.parse(sessionStorage.getItem("dummy_user"));
21+
if (isStoredInSession) {
22+
setUser(isStoredInSession);
23+
}
24+
}, []);
25+
26+
const handleLogin = () => {
27+
const dummy_user = createDummyUser();
28+
setUser(dummy_user);
29+
sessionStorage.setItem("dummy_user", JSON.stringify(dummy_user));
30+
};
31+
32+
const handleLogout = () => {
33+
setUser({});
34+
sessionStorage.removeItem("dummy_user");
35+
};
36+
37+
return {
38+
user,
39+
handleLogin,
40+
handleLogout,
41+
};
42+
};

app/components/auth/dummy/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export { default as DummyLoginButton } from './ui/DummyLoginButton';
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
.authDialogWrapper {
2+
position: relative;
3+
}
4+
.authContainer {
5+
display: block;
6+
position: fixed;
7+
right: 50%;
8+
transform: translate(50%,0);
9+
top: 62px;
10+
width: 350px;
11+
max-height: -webkit-calc(100vh - 62px - 100px);
12+
max-height: calc(100vh - 62px - 100px);
13+
overflow-y: auto;
14+
overflow-x: hidden;
15+
border-radius: 8px;
16+
margin-left: 12px;
17+
z-index: 991;
18+
line-height: normal;
19+
background: #fff;
20+
border: 1px solid #ccc;
21+
border-color: rgba(0,0,0,.2);
22+
color: #000;
23+
-webkit-box-shadow: 0 2px 10px rgb(0 0 0 / 20%);
24+
box-shadow: 0 2px 10px rgb(0 0 0 / 20%);
25+
-webkit-user-select: text;
26+
user-select: text;
27+
}
28+
@media(min-width: 570px) {
29+
.authContainer {
30+
position: absolute;
31+
right: 8px;
32+
top: 62px;
33+
width: 354px;
34+
transform: translateX(0);
35+
}
36+
}
37+
.avatar {
38+
background: var(--bs-gray-300);
39+
border-radius: 50%;
40+
width: 42px;
41+
height: 42px;
42+
display: flex;
43+
justify-content: center;
44+
align-items: center;
45+
}
46+
47+
.avatarButton {
48+
background: none;
49+
border: none;
50+
}
51+
52+
.avatarButton:focus {
53+
outline: none;
54+
}
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
import { useState } from "react";
2+
import { NoUserAvatar } from "../../NoUserAvatar";
3+
import { Button } from "react-bootstrap";
4+
import styles from "../styles/DummyLoginButton.module.css";
5+
import { useDummyAuth } from "../hooks/useDummyAuth";
6+
7+
export default function DummyLoginButton() {
8+
const [isLoginUiOpen, setIsLoginUiOpen] = useState(false);
9+
const { user, handleLogin, handleLogout } = useDummyAuth();
10+
11+
return (
12+
<div className={styles.authDialogWrapper}>
13+
<div className={styles.avatar}>
14+
<button className={styles.avatarButton}>
15+
<span
16+
className="d-flex align-items-center"
17+
onClick={() => setIsLoginUiOpen((prev) => !prev)}
18+
>
19+
{user?.image ? (
20+
<img
21+
src={user.image}
22+
alt={user.name}
23+
className="rounded-circle"
24+
height="42px"
25+
width="42px"
26+
/>
27+
) : (
28+
<NoUserAvatar name={user?.name} size="42" />
29+
)}
30+
</span>
31+
</button>
32+
</div>
33+
{isLoginUiOpen && (
34+
<div className={styles.authContainer}>
35+
{user.id ? (
36+
<>
37+
<div className="d-flex flex-column align-items-center mt-4 mb-3 ml-3 mr-3 border-bottom">
38+
<div className="mb-1">
39+
{user.image ? (
40+
<img
41+
src={user.image}
42+
alt={user.name}
43+
style={{
44+
borderRadius: "50%",
45+
}}
46+
height="64px"
47+
width="64px"
48+
/>
49+
) : (
50+
<NoUserAvatar size="64" name={user.name} />
51+
)}
52+
</div>
53+
<div className="font-weight-bold mb-1">{user.name}</div>
54+
<div className="mb-1" style={{ color: "var(--bs-gray-700)" }}>
55+
{user.email}
56+
</div>
57+
</div>
58+
<div className="d-flex justify-content-center mb-4 mt-3 ml-3 mr-3">
59+
<Button variant="secondary" onClick={handleLogout}>
60+
Sign Out
61+
</Button>
62+
</div>
63+
</>
64+
) : (
65+
<div className="d-flex flex-column align-items-center my-3">
66+
<Button onClick={handleLogin}>Login</Button>
67+
</div>
68+
)}
69+
</div>
70+
)}
71+
</div>
72+
);
73+
}

app/components/footer.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ function Footer() {
44
return (
55
<>
66
<footer>
7-
<a className="d-flex align-item-center justify-content-center text-decoration-none text-black">
7+
<div className="d-flex align-item-center justify-content-center text-decoration-none text-black">
88
<span className="d-flex">Powered by </span>
99
<span className="d-flex ps-2">
1010
<BrandLogo
@@ -18,7 +18,7 @@ function Footer() {
1818
width={98}
1919
/>
2020
</span>
21-
</a>
21+
</div>
2222
</footer>
2323
</>
2424
);

app/components/menubar.js

Lines changed: 63 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,19 @@
1-
import React, {useState } from 'react';
2-
import { Navbar, Nav, NavDropdown, Container, Dropdown } from 'react-bootstrap';
3-
import styles from '../styles/Menubar.module.css';
4-
import {RocketChatAuthMenuButton} from './auth/rocketchat';
1+
import React, { useState } from "react";
2+
import { Navbar, Nav, NavDropdown, Container, Dropdown } from "react-bootstrap";
3+
import styles from "../styles/Menubar.module.css";
4+
import { RocketChatAuthMenuButton } from "./auth/rocketchat";
55
import BrandLogo from "./brandlogo";
6-
import RocketChatLinkButton from './rocketchatlinkbutton';
7-
import Cookies from 'js-cookie';
8-
import Link from 'next/link'
6+
import RocketChatLinkButton from "./rocketchatlinkbutton";
7+
import Cookies from "js-cookie";
8+
import Link from "next/link";
9+
import { DummyLoginButton } from "./auth/dummy";
910

1011
const CustomToggle = React.forwardRef(({ children, onClick }, ref) => (
1112
<a
1213
className={styles.elipses}
1314
href=""
1415
ref={ref}
15-
onClick={e => {
16+
onClick={(e) => {
1617
e.preventDefault();
1718
onClick(e);
1819
}}
@@ -24,28 +25,36 @@ const CustomToggle = React.forwardRef(({ children, onClick }, ref) => (
2425

2526
export default function Menubar(props) {
2627
const [collapsed, setCollapsed] = useState(true);
27-
28+
const userCookie = Cookies.get("user");
29+
const hasAllRequiredCreds =
30+
process.env.NEXTAUTH_URL &&
31+
process.env.ROCKETCHAT_CLIENT_ID &&
32+
process.env.ROCKETCHAT_CLIENT_SECRET &&
33+
process.env.ROCKETCHAT_URL;
34+
if (!hasAllRequiredCreds) console.log("RC4Community is now using a dummy Auth Component! If you wish to use a robust Auth component, provide all the credentials first (https://github.com/RocketChat/RC4Community/tree/master/app/components/auth)")
2835
return (
29-
<Container fluid className='border-bottom '>
30-
<Navbar expand='lg' className=' bg-white mx-4 my-2'>
31-
<BrandLogo
32-
brandLink={'/'}
33-
logoLink={'https://global-uploads.webflow.com/611a19b9853b7414a0f6b3f6/611bbb87319adfd903b90f24_logoRC.svg'}
34-
imageTitle={'Rocket.Chat'}
35-
brandName={'Rocket.Chat Community'}
36+
<Container fluid className="border-bottom ">
37+
<Navbar expand="lg" className=" bg-white mx-4 my-2">
38+
<BrandLogo
39+
brandLink={"/"}
40+
logoLink={
41+
"https://global-uploads.webflow.com/611a19b9853b7414a0f6b3f6/611bbb87319adfd903b90f24_logoRC.svg"
42+
}
43+
imageTitle={"Rocket.Chat"}
44+
brandName={"Rocket.Chat Community"}
3645
height={21}
3746
width={124}
3847
/>
3948
<Navbar.Toggle
40-
aria-controls='basic-navbar-nav'
41-
className={styles.default_toggler+" ms-auto"}
49+
aria-controls="basic-navbar-nav"
50+
className={styles.default_toggler + " ms-auto"}
51+
onClick={() => {
52+
setCollapsed(!collapsed);
53+
}}
4254
>
4355
<button
4456
className={`${styles.navbar_toggler} navbar-toggler collapsed d-flex d-lg-none flex-column justify-content-around bg-white`}
45-
type='button'
46-
onClick={() => {
47-
setCollapsed(!collapsed);
48-
}}
57+
type="button"
4958
>
5059
<span
5160
className={`${styles.toggler_icon} ${
@@ -54,16 +63,16 @@ export default function Menubar(props) {
5463
/>
5564
</button>
5665
</Navbar.Toggle>
57-
<Navbar.Collapse id='basic-navbar-nav'>
58-
<Nav className='mx-auto'>
59-
{props.menu?.data?.attributes?.body?.map((item,index) => {
66+
<Navbar.Collapse id="basic-navbar-nav">
67+
<Nav className="mx-auto">
68+
{props.menu?.data?.attributes?.body?.map((item, index) => {
6069
return item.sub_menus && item?.sub_menus?.data?.length ? (
6170
<NavDropdown
62-
key = {item.id || item._id || `NavDropDown_${index}`}
71+
key={`NavDropDown_${index}`}
6372
title={item.label}
6473
className={`ml-4 fw-normal ${styles.navbarItem}`}
6574
>
66-
{item.sub_menus.data.map((sub,index) => (
75+
{item.sub_menus.data.map((sub, index) => (
6776
<NavDropdown.Item
6877
key={sub.id || sub._id || `NavDropDownItem_${index}`}
6978
href={sub.attributes.url}
@@ -73,33 +82,43 @@ export default function Menubar(props) {
7382
))}
7483
</NavDropdown>
7584
) : (
76-
<Nav.Link href={item.url} className='fw-normal' key={item.id || item._id || `NavLink_${index}`}>
85+
<Nav.Link
86+
href={item.url}
87+
className="fw-normal"
88+
key={item.id || item._id || `NavLink_${index}`}
89+
>
7790
{item.label}
7891
</Nav.Link>
7992
);
8093
})}
8194
</Nav>
82-
<RocketChatLinkButton className={`bg-danger bg-gradient p-2 text-white ${styles.chat}`}>
95+
<RocketChatLinkButton
96+
className={`bg-danger bg-gradient p-2 text-white ${styles.chat}`}
97+
>
8398
Click to Chat
8499
</RocketChatLinkButton>
85100
</Navbar.Collapse>
86101
<div className="mx-3">
87-
{Cookies.get('user') ?
88-
<Dropdown
89-
align="end"
90-
className={styles.dropdown_menu}>
91-
<Dropdown.Toggle as={CustomToggle} />
92-
<Dropdown.Menu size="sm" title="">
93-
<Dropdown.Header>RC4Community Profile</Dropdown.Header>
94-
<Dropdown.Item><Link href={`/profile/${Cookies.get('user')}`}><a className={styles.dropdown_menu_item}>Profile</a></Link></Dropdown.Item>
95-
</Dropdown.Menu>
96-
</Dropdown>
97-
:
98-
""
99-
}
100-
</div>
102+
{userCookie && (
103+
<Dropdown align="end" className={styles.dropdown_menu}>
104+
<Dropdown.Toggle as={CustomToggle} />
105+
<Dropdown.Menu size="sm" title="">
106+
<Dropdown.Header>RC4Community Profile</Dropdown.Header>
107+
<Dropdown.Item>
108+
<Link href={`/profile/${userCookie}`}>
109+
<a className={styles.dropdown_menu_item}>Profile</a>
110+
</Link>
111+
</Dropdown.Item>
112+
</Dropdown.Menu>
113+
</Dropdown>
114+
)}
115+
</div>
101116
<div className="mx-2">
102-
<RocketChatAuthMenuButton/>
117+
{hasAllRequiredCreds ? (
118+
<RocketChatAuthMenuButton />
119+
) : (
120+
<DummyLoginButton />
121+
)}
103122
</div>
104123
</Navbar>
105124
</Container>

0 commit comments

Comments
 (0)