mirror of
https://github.com/ets-cfuhrman-pfe/EvalueTonSavoir.git
synced 2025-08-11 21:23:54 -04:00
Merge pull request #152 from ets-cfuhrman-pfe/feat-auth-only-student
Adds (no) authentication requirement to join a room
This commit is contained in:
commit
ba77b73899
11 changed files with 113 additions and 3 deletions
|
|
@ -28,6 +28,7 @@ import OAuthCallback from './pages/AuthManager/callback/AuthCallback';
|
||||||
const App: React.FC = () => {
|
const App: React.FC = () => {
|
||||||
const [isAuthenticated, setIsAuthenticated] = useState(ApiService.isLoggedIn());
|
const [isAuthenticated, setIsAuthenticated] = useState(ApiService.isLoggedIn());
|
||||||
const [isTeacherAuthenticated, setIsTeacherAuthenticated] = useState(ApiService.isLoggedInTeacher());
|
const [isTeacherAuthenticated, setIsTeacherAuthenticated] = useState(ApiService.isLoggedInTeacher());
|
||||||
|
const [isRoomRequireAuthentication, setRoomsRequireAuth] = useState(null);
|
||||||
const location = useLocation();
|
const location = useLocation();
|
||||||
|
|
||||||
// Check login status every time the route changes
|
// Check login status every time the route changes
|
||||||
|
|
@ -37,7 +38,13 @@ const App: React.FC = () => {
|
||||||
setIsTeacherAuthenticated(ApiService.isLoggedInTeacher());
|
setIsTeacherAuthenticated(ApiService.isLoggedInTeacher());
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const fetchAuthenticatedRooms = async () => {
|
||||||
|
const data = await ApiService.getRoomsRequireAuth();
|
||||||
|
setRoomsRequireAuth(data);
|
||||||
|
};
|
||||||
|
|
||||||
checkLoginStatus();
|
checkLoginStatus();
|
||||||
|
fetchAuthenticatedRooms();
|
||||||
}, [location]);
|
}, [location]);
|
||||||
|
|
||||||
const handleLogout = () => {
|
const handleLogout = () => {
|
||||||
|
|
@ -76,7 +83,7 @@ const App: React.FC = () => {
|
||||||
{/* Pages espace étudiant */}
|
{/* Pages espace étudiant */}
|
||||||
<Route
|
<Route
|
||||||
path="/student/join-room"
|
path="/student/join-room"
|
||||||
element={isAuthenticated ? <JoinRoom /> : <Navigate to="/login" />}
|
element={( !isRoomRequireAuthentication || isAuthenticated ) ? <JoinRoom /> : <Navigate to="/login" />}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{/* Pages authentification */}
|
{/* Pages authentification */}
|
||||||
|
|
|
||||||
|
|
@ -9,9 +9,11 @@ const OAuthCallback: React.FC = () => {
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const searchParams = new URLSearchParams(location.search);
|
const searchParams = new URLSearchParams(location.search);
|
||||||
const user = searchParams.get('user');
|
const user = searchParams.get('user');
|
||||||
|
const username = searchParams.get('username');
|
||||||
|
|
||||||
if (user) {
|
if (user) {
|
||||||
apiService.saveToken(user);
|
apiService.saveToken(user);
|
||||||
|
apiService.saveUsername(username || "");
|
||||||
navigate('/');
|
navigate('/');
|
||||||
} else {
|
} else {
|
||||||
navigate('/login');
|
navigate('/login');
|
||||||
|
|
|
||||||
|
|
@ -15,9 +15,11 @@ import LoadingButton from '@mui/lab/LoadingButton';
|
||||||
|
|
||||||
import LoginContainer from '../../../components/LoginContainer/LoginContainer'
|
import LoginContainer from '../../../components/LoginContainer/LoginContainer'
|
||||||
|
|
||||||
|
import ApiService from '../../../services/ApiService'
|
||||||
|
|
||||||
const JoinRoom: React.FC = () => {
|
const JoinRoom: React.FC = () => {
|
||||||
const [roomName, setRoomName] = useState('');
|
const [roomName, setRoomName] = useState('');
|
||||||
const [username, setUsername] = useState('');
|
const [username, setUsername] = useState(ApiService.getUsername());
|
||||||
const [socket, setSocket] = useState<Socket | null>(null);
|
const [socket, setSocket] = useState<Socket | null>(null);
|
||||||
const [isWaitingForTeacher, setIsWaitingForTeacher] = useState(false);
|
const [isWaitingForTeacher, setIsWaitingForTeacher] = useState(false);
|
||||||
const [question, setQuestion] = useState<QuestionType>();
|
const [question, setQuestion] = useState<QuestionType>();
|
||||||
|
|
|
||||||
|
|
@ -105,7 +105,43 @@ class ApiService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public saveUsername(username: string): void {
|
||||||
|
if (!username || username.length === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const object = {
|
||||||
|
username: username
|
||||||
|
}
|
||||||
|
|
||||||
|
localStorage.setItem("username", JSON.stringify(object));
|
||||||
|
}
|
||||||
|
|
||||||
|
public getUsername(): string {
|
||||||
|
const objectStr = localStorage.getItem("username");
|
||||||
|
|
||||||
|
if (!objectStr) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
const object = JSON.parse(objectStr)
|
||||||
|
|
||||||
|
return object.username;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Route to know if rooms need authentication to join
|
||||||
|
public async getRoomsRequireAuth(): Promise<any> {
|
||||||
|
const url: string = this.constructRequestUrl(`/auth/getRoomsRequireAuth`);
|
||||||
|
const result: AxiosResponse = await axios.get(url);
|
||||||
|
|
||||||
|
if (result.status == 200) {
|
||||||
|
return result.data.roomsRequireAuth;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
public logout(): void {
|
public logout(): void {
|
||||||
|
localStorage.removeItem("username");
|
||||||
return localStorage.removeItem("jwt");
|
return localStorage.removeItem("jwt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,7 @@ services:
|
||||||
SITE_URL: http://localhost
|
SITE_URL: http://localhost
|
||||||
FRONTEND_PORT: 5173
|
FRONTEND_PORT: 5173
|
||||||
USE_PORTS: false
|
USE_PORTS: false
|
||||||
|
AUTHENTICATED_ROOMS: false
|
||||||
volumes:
|
volumes:
|
||||||
- ./server/auth_config.json:/usr/src/app/serveur/config/auth_config.json
|
- ./server/auth_config.json:/usr/src/app/serveur/config/auth_config.json
|
||||||
depends_on:
|
depends_on:
|
||||||
|
|
|
||||||
|
|
@ -19,3 +19,5 @@ SESSION_Secret='session_secret'
|
||||||
SITE_URL=http://localhost
|
SITE_URL=http://localhost
|
||||||
FRONTEND_PORT=5173
|
FRONTEND_PORT=5173
|
||||||
USE_PORTS=false
|
USE_PORTS=false
|
||||||
|
|
||||||
|
AUTHENTICATED_ROOMS=false
|
||||||
|
|
|
||||||
|
|
@ -205,3 +205,40 @@ describe(
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
|
describe(
|
||||||
|
"Rooms requiring authentication", () => {
|
||||||
|
// Making a copy of env variables to restore them later
|
||||||
|
const OLD_ENV_VARIABLES = process.env;
|
||||||
|
|
||||||
|
let authConfigInstance;
|
||||||
|
|
||||||
|
beforeAll(() => {
|
||||||
|
authConfigInstance = new AuthConfig();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Clearing cache just in case
|
||||||
|
beforeEach(() => {
|
||||||
|
jest.resetModules();
|
||||||
|
process.env = { ...OLD_ENV_VARIABLES };
|
||||||
|
});
|
||||||
|
|
||||||
|
// Resetting the old values
|
||||||
|
afterAll(() => {
|
||||||
|
process.env = OLD_ENV_VARIABLES;
|
||||||
|
});
|
||||||
|
|
||||||
|
// tests cases as [environment variable value, expected value]
|
||||||
|
const cases = [["true", true], ["false", false], ["", false], ["other_than_true_false", false]];
|
||||||
|
test.each(cases)(
|
||||||
|
"Given %p as AUTHENTICATED_ROOMS environment variable value, returns %p",
|
||||||
|
(envVarArg, expectedResult) => {
|
||||||
|
process.env.AUTHENTICATED_ROOMS = envVarArg;
|
||||||
|
const isAuthRequired = authConfigInstance.getRoomsRequireAuth();
|
||||||
|
|
||||||
|
expect(isAuthRequired).toEqual(expectedResult);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
|
||||||
|
|
@ -44,7 +44,7 @@ class AuthManager{
|
||||||
|
|
||||||
async login(userInfo,req,res,next){
|
async login(userInfo,req,res,next){
|
||||||
const tokenToSave = jwt.create(userInfo.email, userInfo._id,userInfo.roles);
|
const tokenToSave = jwt.create(userInfo.email, userInfo._id,userInfo.roles);
|
||||||
res.redirect(`/auth/callback?user=${tokenToSave}`);
|
res.redirect(`/auth/callback?user=${tokenToSave}&username=${userInfo.name}`);
|
||||||
console.info(`L'utilisateur '${userInfo.name}' vient de se connecter`)
|
console.info(`L'utilisateur '${userInfo.name}' vient de se connecter`)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -175,6 +175,17 @@ class AuthConfig {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check if students must be authenticated to join a room
|
||||||
|
getRoomsRequireAuth() {
|
||||||
|
const roomRequireAuth = process.env.AUTHENTICATED_ROOMS;
|
||||||
|
|
||||||
|
if (!roomRequireAuth || roomRequireAuth !== "true") {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,17 @@ class authController {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async getRoomsRequireAuth(req, res, next) {
|
||||||
|
const authC = new AuthConfig();
|
||||||
|
const roomsRequireAuth = authC.getRoomsRequireAuth();
|
||||||
|
|
||||||
|
const response = {
|
||||||
|
roomsRequireAuth
|
||||||
|
}
|
||||||
|
|
||||||
|
return res.json(response);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = new authController;
|
module.exports = new authController;
|
||||||
|
|
@ -5,5 +5,6 @@ const jwt = require('../middleware/jwtToken.js');
|
||||||
const authController = require('../controllers/auth.js')
|
const authController = require('../controllers/auth.js')
|
||||||
|
|
||||||
router.get("/getActiveAuth",authController.getActive);
|
router.get("/getActiveAuth",authController.getActive);
|
||||||
|
router.get("/getRoomsRequireAuth", authController.getRoomsRequireAuth);
|
||||||
|
|
||||||
module.exports = router;
|
module.exports = router;
|
||||||
Loading…
Reference in a new issue