Skip to content

Commit

Permalink
Started Implementing Authorization
Browse files Browse the repository at this point in the history
sign up, login, logout, login with google and login with github
  • Loading branch information
R1c4rdCo5t4 committed Jun 11, 2024
1 parent 49995af commit 2c3a598
Show file tree
Hide file tree
Showing 19 changed files with 513 additions and 64 deletions.
19 changes: 19 additions & 0 deletions code/client/config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { initializeApp } from 'firebase/app';
import { getAuth, GoogleAuthProvider, GithubAuthProvider } from 'firebase/auth';

const firebaseConfig = {
apiKey: import.meta.env.VITE_FIREBASE_API_KEY,
authDomain: import.meta.env.VITE_FIREBASE_AUTH_DOMAIN,
projectId: import.meta.env.VITE_FIREBASE_PROJECT_ID,
storageBucket: import.meta.env.VITE_FIREBASE_STORAGE_BUCKET,
messagingSenderId: import.meta.env.VITE_FIREBASE_MESSAGING_SENDER_ID,
appId: import.meta.env.VITE_FIREBASE_APP_ID,
};

const app = initializeApp(firebaseConfig);
const auth = getAuth(app);
const googleAuthProvider = new GoogleAuthProvider();
const githubAuthProvider = new GithubAuthProvider();
const SERVER_URL = import.meta.env.VITE_SERVER_URL || 'http://localhost:8080';

export { SERVER_URL, auth, googleAuthProvider, githubAuthProvider };
2 changes: 2 additions & 0 deletions code/client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
"@testing-library/jest-dom": "^6.4.5",
"dotenv": "^16.4.5",
"eslint-plugin-playwright": "^1.6.0",
"firebase": "^10.12.2",
"lodash": "^4.17.21",
"msw": "^2.2.14",
"react": "^18.3.1",
Expand All @@ -41,6 +42,7 @@
"@testing-library/dom": "^10.1.0",
"@testing-library/react": "^15.0.7",
"@testing-library/user-event": "^14.5.2",
"@types/firebase": "^3.2.1",
"@types/jest": "^29.5.12",
"@types/lodash": "^4.17.1",
"@types/node": "^20.12.10",
Expand Down
101 changes: 54 additions & 47 deletions code/client/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,58 +10,65 @@ import { WorkspaceProvider } from '@ui/contexts/workspace/WorkspaceContext';
import Workspaces from '@ui/pages/workspaces/Workspaces';
import { CommunicationProvider } from '@ui/contexts/communication/CommunicationContext';
import Home from '@ui/pages/home/Home';
import Login from '@ui/pages/auth/login/Login';
import Signup from '@ui/pages/auth/signup/Signup';
import AuthProvider from '@ui/contexts/auth/AuthContext';

function App() {
return (
<div className="app">
<ErrorProvider>
<CommunicationProvider>
<Router>
<Header />
<div className="content">
<Routes>
<Route
path="/"
element={
<>
<Sidebar />
<Home />
</>
}
/>
<Route
path="/workspaces/*"
element={
<Routes>
<Route
path="/"
element={
<>
<Sidebar />
<Workspaces />
</>
}
/>
<Route
path="/:wid/*"
element={
<WorkspaceProvider>
<Sidebar />
<Routes>
<Route path="/" element={<Workspace />} />
<Route path="/:id" element={<Document />} />
</Routes>
</WorkspaceProvider>
}
/>
</Routes>
}
/>
<Route path="*" element={<NotFound />} />
</Routes>
</div>
</Router>
</CommunicationProvider>
<AuthProvider>
<CommunicationProvider>
<Router>
<Header />
<div className="content">
<Routes>
<Route
path="/"
element={
<>
<Sidebar />
<Home />
</>
}
/>
<Route path="/login" element={<Login />} />
<Route path="/signup" element={<Signup />} />
<Route
path="/workspaces/*"
element={
<Routes>
<Route
path="/"
element={
<>
<Sidebar />
<Workspaces />
</>
}
/>
<Route
path="/:wid/*"
element={
<WorkspaceProvider>
<Sidebar />
<Routes>
<Route path="/" element={<Workspace />} />
<Route path="/:id" element={<Document />} />
</Routes>
</WorkspaceProvider>
}
/>
</Routes>
}
/>
<Route path="*" element={<NotFound />} />
</Routes>
</div>
</Router>
</CommunicationProvider>
</AuthProvider>
</ErrorProvider>
</div>
);
Expand Down
File renamed without changes
Binary file added code/client/src/assets/images/google-icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 0 additions & 5 deletions code/client/src/config.ts

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
import config from '@/config';

export const BASE_URL = config.SERVER_URL;
import { SERVER_URL } from '@config';

export interface HttpCommunication {
post: (url: string, data?: any) => Promise<any>;
Expand Down Expand Up @@ -32,7 +30,7 @@ const request = async (url: string, method: string, body?: any) => {
};
if (body) requestInit.body = JSON.stringify(body);

const response = await fetch(BASE_URL + url, requestInit);
const response = await fetch(SERVER_URL + url, requestInit);
const noBody = response.status === 204 || response.headers.get('content-length') === '0';
if (noBody) return;
const result = await response.json();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { io } from 'socket.io-client';
import config from '@/config';
import { SERVER_URL } from '@config';
import { OperationEmitter } from '@services/communication/socket/operationEmitter';

type EmitType = (event: string, data?: any) => void;
Expand All @@ -15,7 +15,7 @@ export interface SocketCommunication {
disconnect: ConnectionType;
}

const socket = io(config.SERVER_URL);
const socket = io(SERVER_URL);
const OPERATION_DELAY = 100;
const operationEmitter = new OperationEmitter(socket, OPERATION_DELAY);

Expand Down
11 changes: 8 additions & 3 deletions code/client/src/ui/components/header/Header.scss
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
header {
.header {
position: sticky;
width: 100%;
height: 6vh;
height: 8vh;
top: 0;
left: 0;
color: black;
background: white;
padding: 1vh 0 1vh 15vh;
box-shadow: black 0 0 1px;
display: flex;
justify-content: space-between;
align-items: center;

div {
display: flex;
align-items: center;
}
}
12 changes: 11 additions & 1 deletion code/client/src/ui/components/header/Header.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,17 @@
import './Header.scss';
import { useAuth } from '@ui/contexts/auth/useAuth';

function Header() {
return <header></header>;
const { currentUser, logout } = useAuth();
return (
<header className="header">
<p></p>
<div>
<p>{currentUser?.email}</p>
<button onClick={logout}>Logout</button>
</div>
</header>
);
}

export default Header;
94 changes: 94 additions & 0 deletions code/client/src/ui/contexts/auth/AuthContext.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
import { auth, googleAuthProvider, githubAuthProvider } from '@config';
import { createContext, ReactNode, useEffect, useState } from 'react';
import {
signInWithPopup,
createUserWithEmailAndPassword,
signInWithEmailAndPassword,
signOut,
updateProfile,
User,
UserCredential,
} from 'firebase/auth';

export type AuthContextType = {
currentUser: User | null;
login: (email: string, password: string) => Promise<UserCredential>;
loginWithGoogle: () => Promise<UserCredential>;
loginWithGithub: () => Promise<UserCredential>;
signup: (email: string, password: string) => Promise<UserCredential>;
logout: () => Promise<void>;
updateUserProfile: (user: User, profile: UserProfile) => Promise<void>;
};

export const AuthContext = createContext<AuthContextType>({
currentUser: null,
login: async () => ({}) as UserCredential,
loginWithGoogle: async () => ({}) as UserCredential,
loginWithGithub: async () => ({}) as UserCredential,
signup: async () => ({}) as UserCredential,
logout: async () => {},
updateUserProfile: async () => {},
});

type AuthProviderProps = {
children: ReactNode;
};

type UserProfile = {
displayName?: string;
photoURL?: string;
};

export function AuthProvider({ children }: AuthProviderProps) {
const [currentUser, setCurrentUser] = useState<User | null>(null);
const [loading, setLoading] = useState(true);

function signup(email: string, password: string) {
return createUserWithEmailAndPassword(auth, email, password);
}

function login(email: string, password: string) {
return signInWithEmailAndPassword(auth, email, password);
}

function logout() {
return signOut(auth);
}

function updateUserProfile(user: User, profile: UserProfile) {
return updateProfile(user, profile);
}

function loginWithGoogle() {
return signInWithPopup(auth, googleAuthProvider);
}

function loginWithGithub() {
return signInWithPopup(auth, githubAuthProvider);
}

useEffect(() => {
return auth.onAuthStateChanged(user => {
setCurrentUser(user);
setLoading(false);
});
}, []);

return (
<AuthContext.Provider
value={{
currentUser,
login,
loginWithGoogle,
loginWithGithub,
signup,
logout,
updateUserProfile,
}}
>
{!loading && children}
</AuthContext.Provider>
);
}

export default AuthProvider;
6 changes: 6 additions & 0 deletions code/client/src/ui/contexts/auth/useAuth.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { useContext } from 'react';
import { AuthContext, AuthContextType } from '@ui/contexts/auth/AuthContext';

export function useAuth(): AuthContextType {
return useContext(AuthContext);
}
38 changes: 38 additions & 0 deletions code/client/src/ui/pages/auth/Auth.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
.auth {
.auth-box {
margin-top: 8vh;
display: flex;
flex-direction: column;
align-items: center;
}

.auth-form {
margin-top: 1vh;
}

.auth-submit-btn {
margin-top: 3vh;
margin-bottom: 2vh;
text-transform: capitalize;
}

.auth-links-container {
display: flex;
gap: 1vh;
}

.remember-me * {
user-select: none;
}

a {
color: #1976d2;
text-decoration: underline;
font-size: smaller;
font-weight: 500;
}

a:hover {
color: #1976d2;
}
}
Loading

0 comments on commit 2c3a598

Please sign in to comment.