diff --git a/code/client/config.ts b/code/client/config.ts
index 676c4c15..fb438260 100644
--- a/code/client/config.ts
+++ b/code/client/config.ts
@@ -11,6 +11,7 @@ const firebaseConfig = {
};
const app = initializeApp(firebaseConfig);
+
const auth = getAuth(app);
const googleAuthProvider = new GoogleAuthProvider();
const githubAuthProvider = new GithubAuthProvider();
diff --git a/code/client/src/App.tsx b/code/client/src/App.tsx
index d786e65e..2c02f6a9 100644
--- a/code/client/src/App.tsx
+++ b/code/client/src/App.tsx
@@ -4,13 +4,13 @@ import Header from '@ui/components/header/Header';
import Workspace from '@ui/pages/workspace/Workspace';
import NotFound from '@ui/pages/notfound/NotFound';
import './App.scss';
-import { ErrorProvider } from '@ui/contexts/error/ErrorContext';
+import { ErrorProvider } from '@/contexts/error/ErrorContext';
import Sidebar from '@ui/components/sidebar/Sidebar';
-import { WorkspaceProvider } from '@ui/contexts/workspace/WorkspaceContext';
+import { WorkspaceProvider } from '@/contexts/workspace/WorkspaceContext';
import Workspaces from '@ui/pages/workspaces/Workspaces';
-import { CommunicationProvider } from '@ui/contexts/communication/CommunicationContext';
+import { CommunicationProvider } from '@/contexts/communication/CommunicationContext';
import Home from '@ui/pages/home/Home';
-import AuthProvider from '@ui/contexts/auth/AuthContext';
+import AuthProvider from '@/contexts/auth/AuthContext';
import Profile from '@ui/pages/profile/Profile';
import Landing from '@ui/pages/landing/Landing';
@@ -18,9 +18,9 @@ function App() {
return (
-
-
-
+
+
+
@@ -66,9 +66,9 @@ function App() {
} />
-
-
-
+
+
+
);
diff --git a/code/client/src/ui/contexts/auth/AuthContext.tsx b/code/client/src/contexts/auth/AuthContext.tsx
similarity index 72%
rename from code/client/src/ui/contexts/auth/AuthContext.tsx
rename to code/client/src/contexts/auth/AuthContext.tsx
index 025546e5..fb411afc 100644
--- a/code/client/src/ui/contexts/auth/AuthContext.tsx
+++ b/code/client/src/contexts/auth/AuthContext.tsx
@@ -1,9 +1,10 @@
import Cookies from 'js-cookie';
import { auth, githubAuthProvider, googleAuthProvider } from '@config';
import { createContext, ReactNode, useEffect, useState } from 'react';
-import { signInWithPopup, signOut, User, type AuthProvider as Provider } from 'firebase/auth';
-import useError from '@ui/contexts/error/useError';
+import { signInWithPopup, signOut, User, type AuthProvider as Provider, inMemoryPersistence } from 'firebase/auth';
+import useError from '@/contexts/error/useError';
import useAuthService from '@services/auth/useAuthService';
+import { useNavigate } from 'react-router-dom';
export type AuthContextType = {
currentUser: User | null;
@@ -29,14 +30,17 @@ export function AuthProvider({ children }: AuthProviderProps) {
const [currentUser, setCurrentUser] = useState(null);
const [loading, setLoading] = useState(true);
const { publishError } = useError();
- const { registerUser } = useAuthService();
+ const { sessionLogin, sessionLogout } = useAuthService();
+ const navigate = useNavigate();
const loginWithProvider = async (provider: Provider) => {
try {
+ auth.setPersistence(inMemoryPersistence); // for httpOnly cookies, do not persist any state client side
const { user } = await signInWithPopup(auth, provider);
- await registerUser(user.uid, { name: user.displayName!, email: user.email! });
- const token = await user.getIdToken(true);
- Cookies.set('token', token, { expires: 1, secure: true, sameSite: 'Strict' });
+ const userInfo = { name: user.displayName!, email: user.email! };
+ const idToken = await user.getIdToken();
+ const csrfToken = Cookies.get('csrfToken')!;
+ await sessionLogin(idToken, csrfToken, user.uid, userInfo);
} catch (e) {
publishError(e as Error);
}
@@ -47,15 +51,16 @@ export function AuthProvider({ children }: AuthProviderProps) {
const loginWithGithub = () => loginWithProvider(githubAuthProvider);
const logout = async () => {
+ console.log('logging out');
+ await sessionLogout();
await signOut(auth);
- Cookies.remove('token');
- window.location.href = '/';
+ navigate('/');
};
const deleteAccount = async () => {
+ await sessionLogout();
await currentUser?.delete();
- Cookies.remove('token');
- window.location.href = '/';
+ navigate('/');
};
useEffect(() => {
diff --git a/code/client/src/ui/contexts/auth/useAuth.ts b/code/client/src/contexts/auth/useAuth.ts
similarity index 60%
rename from code/client/src/ui/contexts/auth/useAuth.ts
rename to code/client/src/contexts/auth/useAuth.ts
index e165f62a..9909a756 100644
--- a/code/client/src/ui/contexts/auth/useAuth.ts
+++ b/code/client/src/contexts/auth/useAuth.ts
@@ -1,5 +1,5 @@
import { useContext } from 'react';
-import { AuthContext, AuthContextType } from '@ui/contexts/auth/AuthContext';
+import { AuthContext, AuthContextType } from '@/contexts/auth/AuthContext';
export function useAuth(): AuthContextType {
return useContext(AuthContext);
diff --git a/code/client/src/ui/contexts/communication/CommunicationContext.tsx b/code/client/src/contexts/communication/CommunicationContext.tsx
similarity index 100%
rename from code/client/src/ui/contexts/communication/CommunicationContext.tsx
rename to code/client/src/contexts/communication/CommunicationContext.tsx
diff --git a/code/client/src/ui/contexts/communication/useCommunication.ts b/code/client/src/contexts/communication/useCommunication.ts
similarity index 69%
rename from code/client/src/ui/contexts/communication/useCommunication.ts
rename to code/client/src/contexts/communication/useCommunication.ts
index 6b5facaf..262be5c2 100644
--- a/code/client/src/ui/contexts/communication/useCommunication.ts
+++ b/code/client/src/contexts/communication/useCommunication.ts
@@ -1,6 +1,6 @@
import { Communication } from '@services/communication/communication';
import { useContext } from 'react';
-import { CommunicationContext } from '@ui/contexts/communication/CommunicationContext';
+import { CommunicationContext } from '@/contexts/communication/CommunicationContext';
export function useCommunication(): Communication {
return useContext(CommunicationContext);
diff --git a/code/client/src/ui/contexts/error/ErrorContext.tsx b/code/client/src/contexts/error/ErrorContext.tsx
similarity index 100%
rename from code/client/src/ui/contexts/error/ErrorContext.tsx
rename to code/client/src/contexts/error/ErrorContext.tsx
diff --git a/code/client/src/ui/contexts/error/useError.ts b/code/client/src/contexts/error/useError.ts
similarity index 63%
rename from code/client/src/ui/contexts/error/useError.ts
rename to code/client/src/contexts/error/useError.ts
index 9c960014..24509056 100644
--- a/code/client/src/ui/contexts/error/useError.ts
+++ b/code/client/src/contexts/error/useError.ts
@@ -1,5 +1,5 @@
import { useContext } from 'react';
-import { ErrorContext } from '@ui/contexts/error/ErrorContext';
+import { ErrorContext } from '@/contexts/error/ErrorContext';
const useError = () => useContext(ErrorContext);
diff --git a/code/client/src/ui/contexts/workspace/WorkspaceContext.tsx b/code/client/src/contexts/workspace/WorkspaceContext.tsx
similarity index 94%
rename from code/client/src/ui/contexts/workspace/WorkspaceContext.tsx
rename to code/client/src/contexts/workspace/WorkspaceContext.tsx
index d616b556..0ed013bc 100644
--- a/code/client/src/ui/contexts/workspace/WorkspaceContext.tsx
+++ b/code/client/src/contexts/workspace/WorkspaceContext.tsx
@@ -1,8 +1,8 @@
import * as React from 'react';
import { useState, createContext, useEffect } from 'react';
import { WorkspaceMeta } from '@notespace/shared/src/workspace/types/workspace';
-import { useCommunication } from '@ui/contexts/communication/useCommunication';
-import useError from '@ui/contexts/error/useError';
+import { useCommunication } from '@/contexts/communication/useCommunication';
+import useError from '@/contexts/error/useError';
import { useParams } from 'react-router-dom';
import useWorkspaceService from '@services/workspace/useWorkspaceService';
import useResources from '@domain/workspaces/useResources';
diff --git a/code/client/src/ui/contexts/workspace/useWorkspace.ts b/code/client/src/contexts/workspace/useWorkspace.ts
similarity index 62%
rename from code/client/src/ui/contexts/workspace/useWorkspace.ts
rename to code/client/src/contexts/workspace/useWorkspace.ts
index 5be486a4..3279011d 100644
--- a/code/client/src/ui/contexts/workspace/useWorkspace.ts
+++ b/code/client/src/contexts/workspace/useWorkspace.ts
@@ -1,5 +1,5 @@
import { useContext } from 'react';
-import { WorkspaceContext } from '@ui/contexts/workspace/WorkspaceContext';
+import { WorkspaceContext } from '@/contexts/workspace/WorkspaceContext';
const useWorkspace = () => useContext(WorkspaceContext);
diff --git a/code/client/src/domain/workspaces/tree/useWorkspaceTree.ts b/code/client/src/domain/workspaces/tree/useWorkspaceTree.ts
index 15efb9e0..0f11da62 100644
--- a/code/client/src/domain/workspaces/tree/useWorkspaceTree.ts
+++ b/code/client/src/domain/workspaces/tree/useWorkspaceTree.ts
@@ -1,6 +1,6 @@
import { useState } from 'react';
import { Resource } from '@notespace/shared/src/workspace/types/resource';
-import { Resources } from '@ui/contexts/workspace/WorkspaceContext';
+import { Resources } from '@/contexts/workspace/WorkspaceContext';
function useWorkspaceTree() {
const [nodes, setNodes] = useState({});
diff --git a/code/client/src/domain/workspaces/tree/utils.ts b/code/client/src/domain/workspaces/tree/utils.ts
index cfa4361e..ae82812a 100644
--- a/code/client/src/domain/workspaces/tree/utils.ts
+++ b/code/client/src/domain/workspaces/tree/utils.ts
@@ -1,5 +1,5 @@
import { TreeNode } from '@domain/workspaces/tree/types';
-import { Resources } from '@ui/contexts/workspace/WorkspaceContext';
+import { Resources } from '@/contexts/workspace/WorkspaceContext';
export function getTree(id: string, nodes: Resources): TreeNode {
const node = nodes[id];
diff --git a/code/client/src/domain/workspaces/useResources.ts b/code/client/src/domain/workspaces/useResources.ts
index c3323b28..46eb0ff8 100644
--- a/code/client/src/domain/workspaces/useResources.ts
+++ b/code/client/src/domain/workspaces/useResources.ts
@@ -1,7 +1,7 @@
import { ResourceType, Resource } from '@notespace/shared/src/workspace/types/resource';
import useResourceService from '@services/resource/useResourceService';
import useSocketListeners from '@services/communication/socket/useSocketListeners';
-import { useCommunication } from '@ui/contexts/communication/useCommunication';
+import { useCommunication } from '@/contexts/communication/useCommunication';
import useWorkspaceTree from '@domain/workspaces/tree/useWorkspaceTree';
function useResources() {
diff --git a/code/client/src/domain/workspaces/useWorkspaces.ts b/code/client/src/domain/workspaces/useWorkspaces.ts
index a01c988b..9d619a14 100644
--- a/code/client/src/domain/workspaces/useWorkspaces.ts
+++ b/code/client/src/domain/workspaces/useWorkspaces.ts
@@ -1,9 +1,9 @@
import { useEffect, useState } from 'react';
import { WorkspaceInputModel, WorkspaceMeta } from '@notespace/shared/src/workspace/types/workspace';
import useSocketListeners from '@services/communication/socket/useSocketListeners';
-import { useCommunication } from '@ui/contexts/communication/useCommunication';
+import { useCommunication } from '@/contexts/communication/useCommunication';
import useWorkspaceService from '@services/workspace/useWorkspaceService';
-import useError from '@ui/contexts/error/useError';
+import useError from '@/contexts/error/useError';
function useWorkspaces() {
const { socket } = useCommunication();
diff --git a/code/client/src/domain/workspaces/utils.ts b/code/client/src/domain/workspaces/utils.ts
index 6a87a10f..c71b9798 100644
--- a/code/client/src/domain/workspaces/utils.ts
+++ b/code/client/src/domain/workspaces/utils.ts
@@ -1,6 +1,6 @@
import { WorkspaceMeta } from '@notespace/shared/src/workspace/types/workspace';
import { DocumentResource, ResourceType } from '@notespace/shared/src/workspace/types/resource';
-import { Resources } from '@ui/contexts/workspace/WorkspaceContext';
+import { Resources } from '@/contexts/workspace/WorkspaceContext';
export function sortWorkspaces(workspaces: WorkspaceMeta[], column: string, ascending: boolean): WorkspaceMeta[] {
return workspaces.sort((a, b) => {
diff --git a/code/client/src/services/auth/authService.ts b/code/client/src/services/auth/authService.ts
index b3800e64..fe5c513e 100644
--- a/code/client/src/services/auth/authService.ts
+++ b/code/client/src/services/auth/authService.ts
@@ -1,10 +1,13 @@
import { User, UserData } from '@notespace/shared/src/users/types';
import { HttpCommunication } from '@services/communication/http/httpCommunication';
-import Cookies from 'js-cookie';
function authService(http: HttpCommunication) {
- async function registerUser(id: string, data: UserData) {
- await http.post('/users', { id, ...data });
+ async function sessionLogin(idToken: string, csrfToken: string, id: string, data: UserData) {
+ await http.post('/users/login', { idToken, csrfToken, id, ...data });
+ }
+
+ async function sessionLogout() {
+ await http.post('/users/logout');
}
async function getUser(id: string): Promise {
@@ -17,11 +20,11 @@ function authService(http: HttpCommunication) {
async function deleteUser(id: string) {
await http.delete(`/users/${id}`);
- Cookies.remove('token');
}
return {
- registerUser,
+ sessionLogin,
+ sessionLogout,
getUser,
updateUser,
deleteUser,
diff --git a/code/client/src/services/auth/useAuthService.ts b/code/client/src/services/auth/useAuthService.ts
index e4eb000f..96f4d235 100644
--- a/code/client/src/services/auth/useAuthService.ts
+++ b/code/client/src/services/auth/useAuthService.ts
@@ -1,5 +1,5 @@
import { useMemo } from 'react';
-import { useCommunication } from '@ui/contexts/communication/useCommunication';
+import { useCommunication } from '@/contexts/communication/useCommunication';
import authService from '@services/auth/authService';
function useAuthService() {
diff --git a/code/client/src/services/resource/useResourceService.ts b/code/client/src/services/resource/useResourceService.ts
index cf613c21..735c17f4 100644
--- a/code/client/src/services/resource/useResourceService.ts
+++ b/code/client/src/services/resource/useResourceService.ts
@@ -1,5 +1,5 @@
import { useMemo } from 'react';
-import { useCommunication } from '@ui/contexts/communication/useCommunication';
+import { useCommunication } from '@/contexts/communication/useCommunication';
import { useParams } from 'react-router-dom';
import resourceService from '@services/resource/resourceService';
diff --git a/code/client/src/services/workspace/useWorkspaceService.ts b/code/client/src/services/workspace/useWorkspaceService.ts
index 01cad51a..3faf8cde 100644
--- a/code/client/src/services/workspace/useWorkspaceService.ts
+++ b/code/client/src/services/workspace/useWorkspaceService.ts
@@ -1,5 +1,5 @@
import { useMemo } from 'react';
-import { useCommunication } from '@ui/contexts/communication/useCommunication';
+import { useCommunication } from '@/contexts/communication/useCommunication';
import workspaceService from '@services/workspace/workspaceService';
function useWorkspaceService() {
diff --git a/code/client/src/ui/components/header/Header.tsx b/code/client/src/ui/components/header/Header.tsx
index 8bac00ee..5f4522d3 100644
--- a/code/client/src/ui/components/header/Header.tsx
+++ b/code/client/src/ui/components/header/Header.tsx
@@ -1,5 +1,5 @@
import './Header.scss';
-import { useAuth } from '@ui/contexts/auth/useAuth';
+import { useAuth } from '@/contexts/auth/useAuth';
import { Link } from 'react-router-dom';
function Header() {
diff --git a/code/client/src/ui/components/sidebar/Sidebar.tsx b/code/client/src/ui/components/sidebar/Sidebar.tsx
index 15d089ce..20491d45 100644
--- a/code/client/src/ui/components/sidebar/Sidebar.tsx
+++ b/code/client/src/ui/components/sidebar/Sidebar.tsx
@@ -1,7 +1,7 @@
import { IoMenu, IoTime } from 'react-icons/io5';
import { Link } from 'react-router-dom';
import { RiMenuFold2Line, RiMenuFoldLine, RiTeamFill } from 'react-icons/ri';
-import useWorkspace from '@ui/contexts/workspace/useWorkspace';
+import useWorkspace from '@/contexts/workspace/useWorkspace';
import useSidebarState from '@ui/components/sidebar/hooks/useSidebarState';
import WorkspaceTree from '@ui/components/sidebar/components/workspace-tree/WorkspaceTree';
import { IoMdSettings } from 'react-icons/io';
diff --git a/code/client/src/ui/components/sidebar/components/workspace-tree/WorkspaceTree.tsx b/code/client/src/ui/components/sidebar/components/workspace-tree/WorkspaceTree.tsx
index 26a8ed80..5482f04a 100644
--- a/code/client/src/ui/components/sidebar/components/workspace-tree/WorkspaceTree.tsx
+++ b/code/client/src/ui/components/sidebar/components/workspace-tree/WorkspaceTree.tsx
@@ -3,7 +3,7 @@ import { WorkspaceMeta } from '@notespace/shared/src/workspace/types/workspace';
import { getTree } from '@domain/workspaces/tree/utils';
import { ResourceType } from '@notespace/shared/src/workspace/types/resource';
import { DragEvent, useState } from 'react';
-import { Resources, WorkspaceOperations } from '@ui/contexts/workspace/WorkspaceContext';
+import { Resources, WorkspaceOperations } from '@/contexts/workspace/WorkspaceContext';
import './WorkspaceTree.scss';
type WorkspaceTreeProps = {
diff --git a/code/client/src/ui/pages/document/Document.tsx b/code/client/src/ui/pages/document/Document.tsx
index bb71e3f5..2ec8c428 100644
--- a/code/client/src/ui/pages/document/Document.tsx
+++ b/code/client/src/ui/pages/document/Document.tsx
@@ -2,8 +2,8 @@ import Editor from '@ui/pages/document/components/editor/Editor';
import useFugue from '@domain/editor/fugue/useFugue';
import { useEffect, useState } from 'react';
import { useParams, useNavigate } from 'react-router-dom';
-import { useCommunication } from '@ui/contexts/communication/useCommunication';
-import useError from '@ui/contexts/error/useError';
+import { useCommunication } from '@/contexts/communication/useCommunication';
+import useError from '@/contexts/error/useError';
import useDocumentService from '@services/resource/useResourceService';
import useConnectors from '@domain/editor/connectors/useConnectors';
import { DocumentResource } from '@notespace/shared/src/workspace/types/resource';
diff --git a/code/client/src/ui/pages/landing/Landing.tsx b/code/client/src/ui/pages/landing/Landing.tsx
index a3ba4268..f0bd21ca 100644
--- a/code/client/src/ui/pages/landing/Landing.tsx
+++ b/code/client/src/ui/pages/landing/Landing.tsx
@@ -1,4 +1,4 @@
-import { useAuth } from '@ui/contexts/auth/useAuth';
+import { useAuth } from '@/contexts/auth/useAuth';
import { useNavigate } from 'react-router-dom';
import { useEffect } from 'react';
import googleIcon from '@assets/images/google-icon.png';
diff --git a/code/client/src/ui/pages/profile/Profile.tsx b/code/client/src/ui/pages/profile/Profile.tsx
index 88a2124f..500a75ef 100644
--- a/code/client/src/ui/pages/profile/Profile.tsx
+++ b/code/client/src/ui/pages/profile/Profile.tsx
@@ -3,7 +3,7 @@ import { useNavigate, useParams } from 'react-router-dom';
import useAuthService from '@services/auth/useAuthService';
import { User } from '@notespace/shared/src/users/types';
import { formatDate } from '@/utils/utils';
-import { useAuth } from '@ui/contexts/auth/useAuth';
+import { useAuth } from '@/contexts/auth/useAuth';
import './Profile.scss';
function Profile() {
diff --git a/code/client/src/ui/pages/workspace/Workspace.tsx b/code/client/src/ui/pages/workspace/Workspace.tsx
index f3308410..d56b57c4 100644
--- a/code/client/src/ui/pages/workspace/Workspace.tsx
+++ b/code/client/src/ui/pages/workspace/Workspace.tsx
@@ -1,7 +1,7 @@
import { ResourceType } from '@notespace/shared/src/workspace/types/resource';
import DocumentView from '@ui/pages/workspace/components/DocumentView';
-import useError from '@ui/contexts/error/useError';
-import useWorkspace from '@ui/contexts/workspace/useWorkspace';
+import useError from '@/contexts/error/useError';
+import useWorkspace from '@/contexts/workspace/useWorkspace';
import { useEffect, useState } from 'react';
import DataTable from '@ui/components/table/DataTable';
import { FaPlus } from 'react-icons/fa';
diff --git a/code/client/src/ui/pages/workspaces/Workspaces.tsx b/code/client/src/ui/pages/workspaces/Workspaces.tsx
index 7124ae89..c9fc0332 100644
--- a/code/client/src/ui/pages/workspaces/Workspaces.tsx
+++ b/code/client/src/ui/pages/workspaces/Workspaces.tsx
@@ -1,12 +1,12 @@
import useWorkspaces from '@domain/workspaces/useWorkspaces';
import WorkspaceView from '@ui/pages/workspaces/components/WorkspaceView';
import CreateWorkspaceDialog from '@ui/pages/workspaces/components/CreateWorkspaceDialog';
-import useError from '@ui/contexts/error/useError';
+import useError from '@/contexts/error/useError';
import DataTable from '@ui/components/table/DataTable';
import { MdDelete } from 'react-icons/md';
import { useEffect, useState } from 'react';
import { sortWorkspaces } from '@domain/workspaces/utils';
-import { useCommunication } from '@ui/contexts/communication/useCommunication';
+import { useCommunication } from '@/contexts/communication/useCommunication';
import './Workspaces.scss';
function Workspaces() {
diff --git a/code/server/src/controllers/http/handlers/usersHandlers.ts b/code/server/src/controllers/http/handlers/usersHandlers.ts
index c1524bad..233078c3 100644
--- a/code/server/src/controllers/http/handlers/usersHandlers.ts
+++ b/code/server/src/controllers/http/handlers/usersHandlers.ts
@@ -4,10 +4,28 @@ import { UsersService } from '@services/UsersService';
import { httpResponse } from '@controllers/http/utils/httpResponse';
import { UserData } from '@notespace/shared/src/users/types';
import { enforceAuth } from '@controllers/http/middlewares/authMiddleware';
+import admin from 'firebase-admin';
function usersHandlers(service: UsersService) {
- const registerUser = async (req: Request, res: Response) => {
- const { id, ...data } = req.body;
+ const sessionLogin = async (req: Request, res: Response) => {
+ const { id, idToken, csrfToken, ...data } = req.body;
+ // guard against CSRF attacks
+ if (csrfToken !== req.cookies.csrfToken) {
+ httpResponse.unauthorized(res).send();
+ return;
+ }
+ // session login - create session cookie, verifying ID token in the process
+ try {
+ const expiresIn = 60 * 60 * 24 * 5 * 1000; // 5 days
+ const sessionCookie = await admin.auth().createSessionCookie(idToken, { expiresIn });
+ const options = { maxAge: expiresIn, httpOnly: true, secure: true };
+ res.cookie('session', sessionCookie, options);
+ } catch (e) {
+ httpResponse.unauthorized(res).send();
+ return;
+ }
+
+ // register user in database if not already registered
try {
const user = await service.getUser(id);
if (user) {
@@ -22,6 +40,11 @@ function usersHandlers(service: UsersService) {
}
};
+ const sessionLogout = async (req: Request, res: Response) => {
+ res.clearCookie('session');
+ httpResponse.noContent(res).send();
+ };
+
const getUser = async (req: Request, res: Response) => {
const { id } = req.params;
const user = await service.getUser(id);
@@ -47,7 +70,8 @@ function usersHandlers(service: UsersService) {
};
const router = PromiseRouter({ mergeParams: true });
- router.post('/', registerUser);
+ router.post('/login', sessionLogin);
+ router.post('/logout', sessionLogout);
router.get('/:id', getUser);
router.get('/', getUsers);
router.put('/:id', enforceAuth, updateUser);
diff --git a/code/server/src/controllers/http/middlewares/errorMiddleware.ts b/code/server/src/controllers/http/middlewares/errorMiddleware.ts
index eea9dd6d..e3a921de 100644
--- a/code/server/src/controllers/http/middlewares/errorMiddleware.ts
+++ b/code/server/src/controllers/http/middlewares/errorMiddleware.ts
@@ -28,5 +28,4 @@ export default function errorMiddleware(error: Error, req: Request, res: Respons
const message = response.statusCode === 500 ? 'Internal server error' : error.message;
response.send({ error: message });
ErrorLogger.logError(error.message);
- console.error(error.stack);
}
diff --git a/code/server/src/controllers/http/middlewares/loggingMiddleware.ts b/code/server/src/controllers/http/middlewares/loggingMiddleware.ts
new file mode 100644
index 00000000..91464565
--- /dev/null
+++ b/code/server/src/controllers/http/middlewares/loggingMiddleware.ts
@@ -0,0 +1,9 @@
+import { NextFunction, Request, Response } from 'express';
+import { ControllersLogger } from '@src/utils/logging';
+
+const logger = ControllersLogger('ws');
+
+export default async function loggingMiddleware(req: Request, res: Response, next: NextFunction) {
+ logger.logInfo(`Request: ${req.method} ${req.url}`);
+ next();
+}
diff --git a/code/server/src/controllers/http/router.ts b/code/server/src/controllers/http/router.ts
index c07aeef1..e644d181 100644
--- a/code/server/src/controllers/http/router.ts
+++ b/code/server/src/controllers/http/router.ts
@@ -6,6 +6,7 @@ import errorMiddleware from '@controllers/http/middlewares/errorMiddleware';
import usersHandlers from '@controllers/http/handlers/usersHandlers';
import { Server } from 'socket.io';
import { authMiddleware } from '@controllers/http/middlewares/authMiddleware';
+import loggingMiddleware from '@controllers/http/middlewares/loggingMiddleware';
export default function (services: Services, io: Server) {
if (!services) throw new Error('Services parameter is required');
@@ -13,6 +14,7 @@ export default function (services: Services, io: Server) {
// automatically routes unhandled errors to error handling middleware
const router = PromiseRouter();
router.use(express.urlencoded({ extended: true }));
+ router.use(loggingMiddleware);
router.use(authMiddleware);
router.use('/users', usersHandlers(services.users));
diff --git a/code/server/src/controllers/ws/initSocketEvents.ts b/code/server/src/controllers/ws/initSocketEvents.ts
index ec681100..2e3f6feb 100644
--- a/code/server/src/controllers/ws/initSocketEvents.ts
+++ b/code/server/src/controllers/ws/initSocketEvents.ts
@@ -13,7 +13,7 @@ export default function initSocketEvents(events: Record)
Object.entries(events).forEach(([event, handler]) => {
socket.on(event, async data => {
try {
- logger.logInfo('Event: ' + event + ': ' + JSON.stringify(data));
+ logger.logInfo('Event: ' + event);
await handler(socket, data);
} catch (e: any) {
logger.logError(e);
diff --git a/code/server/src/firebaseConfig.ts b/code/server/src/firebaseConfig.ts
index 3fbade44..b425fd10 100644
--- a/code/server/src/firebaseConfig.ts
+++ b/code/server/src/firebaseConfig.ts
@@ -1,11 +1,20 @@
-import { cert, initializeApp, ServiceAccount } from 'firebase-admin/app';
-import serviceAccount from '@/firestore-key-5cddf-472039f8dbb6.json';
+import { config } from 'dotenv';
+import admin from 'firebase-admin';
import { getFirestore } from 'firebase-admin/firestore';
-initializeApp({
- credential: cert(serviceAccount as ServiceAccount),
+config();
+
+// decode the base64 encoded service account json
+const serviceAccountBase64 = process.env.FIREBASE_SERVICE_ACCOUNT;
+const serviceAccountBuffer = Buffer.from(serviceAccountBase64!, 'base64');
+const serviceAccount = JSON.parse(serviceAccountBuffer.toString('utf8'));
+
+// initialize firebase admin sdk
+admin.initializeApp({
+ credential: admin.credential.cert(serviceAccount),
});
+// initialize firestore
const db = getFirestore();
export default db;
diff --git a/code/shared/src/workspace/types/workspace.ts b/code/shared/src/workspace/types/workspace.ts
index a4c58349..aa4295c5 100644
--- a/code/shared/src/workspace/types/workspace.ts
+++ b/code/shared/src/workspace/types/workspace.ts
@@ -4,7 +4,7 @@ export type WorkspaceMeta = {
name: string;
id: string;
createdAt: string;
- members: number;
+ members: number | string[];
isPrivate: boolean;
};