diff --git a/client/src/pages/Teacher/Dashboard/Dashboard.tsx b/client/src/pages/Teacher/Dashboard/Dashboard.tsx
index 7c0bff5..2faacbe 100644
--- a/client/src/pages/Teacher/Dashboard/Dashboard.tsx
+++ b/client/src/pages/Teacher/Dashboard/Dashboard.tsx
@@ -357,8 +357,9 @@ const Dashboard: React.FC = () => {
}
}
-
-
+ if (!ApiService.isTeacher()) {
+ return (
);
+ }
return (
diff --git a/client/src/pages/Teacher/EditorQuiz/EditorQuiz.tsx b/client/src/pages/Teacher/EditorQuiz/EditorQuiz.tsx
index 15ceeb2..8313280 100644
--- a/client/src/pages/Teacher/EditorQuiz/EditorQuiz.tsx
+++ b/client/src/pages/Teacher/EditorQuiz/EditorQuiz.tsx
@@ -171,6 +171,10 @@ const QuizForm: React.FC = () => {
navigator.clipboard.writeText(link);
}
+ if (!ApiService.isTeacher()) {
+ return ();
+ }
+
return (
diff --git a/client/src/services/ApiService.tsx b/client/src/services/ApiService.tsx
index 55dccb7..90d8d20 100644
--- a/client/src/services/ApiService.tsx
+++ b/client/src/services/ApiService.tsx
@@ -76,6 +76,22 @@ class ApiService {
return true;
}
+ public isTeacher(): boolean {
+ const token = this.getToken()
+
+ if (token == null) {
+ return false;
+ }
+
+ let user = JSON.parse(atob(token.split('.')[1]))
+
+ if (user.role == "teacher") {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
public logout(): void {
return localStorage.removeItem("jwt");
}
diff --git a/server/auth/modules/passport-providers/oauth.js b/server/auth/modules/passport-providers/oauth.js
index a38dc44..5ca2f39 100644
--- a/server/auth/modules/passport-providers/oauth.js
+++ b/server/auth/modules/passport-providers/oauth.js
@@ -1,4 +1,5 @@
var OAuth2Strategy = require('passport-oauth2')
+const model = require("../../../models/users");
class PassportOAuth {
register(app, passport,endpoint, name, provider) {
@@ -17,6 +18,15 @@ class PassportOAuth {
headers: { 'Authorization': `Bearer ${accessToken}` }
});
const userInfo = await userInfoResponse.json();
+ let role;
+
+ if (userInfo.groups.includes(provider.OAUTH_ROLE_TEACHER_VALUE)) {
+ role = "teacher";
+ } else if (userInfo.groups.includes(provider.OAUTH_ROLE_STUDENT_VALUE)) {
+ role = "student";
+ } else {
+ role = "anonymous";
+ }
const user = {
id: userInfo.sub,
@@ -25,7 +35,8 @@ class PassportOAuth {
groups: userInfo.groups ?? [],
accessToken: accessToken,
refreshToken: refreshToken,
- expiresIn: params.expires_in
+ expiresIn: params.expires_in,
+ role: role
};
// Store the tokens in the session
diff --git a/server/auth/modules/passport-providers/oidc.js b/server/auth/modules/passport-providers/oidc.js
index 7f7ffa2..7f2fa4e 100644
--- a/server/auth/modules/passport-providers/oidc.js
+++ b/server/auth/modules/passport-providers/oidc.js
@@ -1,4 +1,5 @@
var OpenIDConnectStrategy = require('passport-openidconnect')
+const model = require("../../../models/users");
class PassportOpenIDConnect {
@@ -54,6 +55,13 @@ class PassportOpenIDConnect {
},
(req, res) => {
if (req.user) {
+ if (req.user.groups.includes(provider.OAUTH_ROLE_TEACHER_VALUE)) {
+ model.register(req.user.email, "teacher");
+ } else if (req.user.groups.includes(provider.OAUTH_ROLE_STUDENT_VALUE)) {
+ model.register(req.user.email, "student");
+ } else {
+ model.register(req.user.email, "anonymous");
+ }
res.json(req.user)
console.info(`L'utilisateur '${req.user.name}' vient de se connecter`)
} else {
diff --git a/server/config/auth.js b/server/config/auth.js
index 6d2b425..ffb5927 100644
--- a/server/config/auth.js
+++ b/server/config/auth.js
@@ -151,15 +151,11 @@ class AuthConfig {
if (providerConfig.type === 'oauth') {
passportConfig[providerName] = {
- type: providerConfig.type,
- authorizationUrl: providerConfig.OAUTH_AUTHORIZATION_URL,
- callbackUrl: providerConfig.OAUTH_CALLBACK_URL,
+ type: providerConfig.type
};
} else if (providerConfig.type === 'oidc') {
passportConfig[providerName] = {
- type: providerConfig.type,
- issuerUrl: providerConfig.OIDC_ISSUER_URL,
- callbackUrl: providerConfig.OIDC_CALLBACK_URL
+ type: providerConfig.type
};
}
});
diff --git a/server/config/roles.json b/server/config/roles.json
index 3195e49..8d0880e 100644
--- a/server/config/roles.json
+++ b/server/config/roles.json
@@ -14,7 +14,8 @@
"permissions": [
"crud_quiz",
"crud_folders",
- "crud_images"
+ "crud_images",
+ "participate_quiz"
]
},
{
diff --git a/server/middleware/rbac.js b/server/middleware/rbac.js
index 2a32d86..f1628e7 100644
--- a/server/middleware/rbac.js
+++ b/server/middleware/rbac.js
@@ -1,12 +1,18 @@
const Permissions = require('../models/permissions');
const AppError = require("./AppError");
const { UNAUTHORIZED_PERMISSION_MISSING} = require("../constants/errorCodes");
-const jwt = require("jsonwebtoken");
class Rbac {
checkPermission = (...permissions) => {
return (req, res, next) => {
- const userRole = req.user ? req.user.role : 'anonymous';
+ let userRole;
+ if (req.user) {
+ userRole = req.user.role;
+ } else if (req.session.passport.user) {
+ userRole = req.session.passport.user.role;
+ } else {
+ userRole = 'anonymous';
+ }
const userPermissions = Permissions.getPermissionsByRoleName(userRole);
for (let permission of permissions) {
diff --git a/server/models/users.js b/server/models/users.js
index 829ac64..b3606a8 100644
--- a/server/models/users.js
+++ b/server/models/users.js
@@ -47,6 +47,37 @@ class Users {
// TODO: verif if inserted properly...
}
+ async register(email, role) {
+ await db.connect();
+ const conn = db.getConnection();
+
+ const userCollection = conn.collection('users');
+
+ const existingUser = await userCollection.findOne({ email: email });
+
+ if (existingUser) {
+ await userCollection.updateOne(
+ { email: existingUser.email },
+ {
+ $set: { 'role': role },
+ $currentDate: { lastModified: true }
+ }
+ );
+ } else {
+ const newUser = {
+ email: email,
+ role: role,
+ created_at: new Date()
+ };
+
+ await userCollection.insertOne(newUser);
+
+ const folderTitle = 'Dossier par Défaut';
+ const userId = newUser._id.toString();
+ await Folders.create(folderTitle, userId);
+ }
+ }
+
async login(email, password) {
await db.connect()
const conn = db.getConnection();
diff --git a/server/socket/socket.js b/server/socket/socket.js
index 90bb7fb..8d95720 100644
--- a/server/socket/socket.js
+++ b/server/socket/socket.js
@@ -1,11 +1,38 @@
const MAX_USERS_PER_ROOM = 60;
const MAX_TOTAL_CONNECTIONS = 2000;
+var passport = require('passport')
+const Permissions = require("../models/permissions");
+const AppError = require("../middleware/AppError");
+const {UNAUTHORIZED_PERMISSION_MISSING} = require("../constants/errorCodes");
const setupWebsocket = (io) => {
let totalConnections = 0;
+ function onlyForHandshake(middleware) {
+ return (req, res, next) => {
+ const isHandshake = req._query.sid === undefined;
+ if (isHandshake) {
+ middleware(req, res, next);
+ } else {
+ next();
+ }
+ };
+ }
+
+ io.engine.use(onlyForHandshake(passport.session()));
+ io.engine.use(
+ onlyForHandshake((req, res, next) => {
+ if (req.user) {
+ next();
+ } else {
+ res.writeHead(401);
+ res.end();
+ }
+ }),
+ );
+
io.on("connection", (socket) => {
- // Get jwt and roles
+ const userRole = socket.request.user.role;
if (totalConnections >= MAX_TOTAL_CONNECTIONS) {
console.log("Connection limit reached. Disconnecting client.");
socket.emit(
@@ -25,10 +52,10 @@ const setupWebsocket = (io) => {
);
socket.on("create-room", (sentRoomName) => {
- // If roles authorize else send error message
- // else {
- // socket.emit('access_denied', 'You do not have permission to perform this action');
- // }
+ const userPermissions = Permissions.getPermissionsByRoleName(userRole);
+ if (!userPermissions.includes("create_quiz")) {
+ socket.emit(UNAUTHORIZED_PERMISSION_MISSING.code, UNAUTHORIZED_PERMISSION_MISSING.message);
+ }
if (sentRoomName) {
const roomName = sentRoomName.toUpperCase();
if (!io.sockets.adapter.rooms.get(roomName)) {
@@ -49,6 +76,10 @@ const setupWebsocket = (io) => {
});
socket.on("join-room", ({ enteredRoomName, username }) => {
+ const userPermissions = Permissions.getPermissionsByRoleName(userRole);
+ if (!userPermissions.includes("participate_quiz")) {
+ socket.emit(UNAUTHORIZED_PERMISSION_MISSING.code, UNAUTHORIZED_PERMISSION_MISSING.message);
+ }
if (io.sockets.adapter.rooms.has(enteredRoomName)) {
const clientsInRoom =
io.sockets.adapter.rooms.get(enteredRoomName).size;