Skip to content

Commit

Permalink
reserve usage of apiPassword to admins (!! requires new esup-otp-api !!)
Browse files Browse the repository at this point in the history
Only managers/admin can use api_password.
Users without privileges will now use the hash.
  • Loading branch information
floriannari committed Jan 15, 2024
1 parent f846bb8 commit d17bd63
Show file tree
Hide file tree
Showing 3 changed files with 112 additions and 86 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "esup-otp-manager",
"version": "0.9.0",
"version": "1.1.5",
"private": true,
"repository": {
"type": "git",
Expand Down
146 changes: 77 additions & 69 deletions public/javascripts/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -99,84 +99,92 @@ var TotpMethod = Vue.extend({
template: '#totp-method'
});

var RandomCodeMethod = Vue.extend({
props: {
'user': Object,
'messages': Object,
'activate': Function,
'deactivate': Function,
},
methods: {
saveTransport: function(transport) {
var new_transport = document.getElementById(transport + '-input').value;
var reg;
if (transport == 'sms') reg = new RegExp("^0[6-7]([-. ]?[0-9]{2}){4}$");
else reg = new RegExp(/^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/);
if (reg.test(new_transport)) {
function randomCodeMethod(isManagerDashboard) {
const urlPrefix = '/api/' + (isManagerDashboard ? 'admin/' : '');
function urlSufix(context) {
return isManagerDashboard ? '/' + context.user.uid : '';
}
return Vue.extend({
props: {
'user': Object,
'messages': Object,
'activate': Function,
'deactivate': Function,
},
methods: {
saveTransport: function(transport) {
var new_transport = document.getElementById(transport + '-input').value;
var reg;
if (transport == 'sms') reg = new RegExp("^0[6-7]([-. ]?[0-9]{2}){4}$");
else reg = new RegExp(/^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/);
if (reg.test(new_transport)) {
var oldTransport = this.user.transports[transport];
this.user.transports[transport]= new_transport;
document.getElementById(transport + '-input').value = '';
$.ajax({
method: 'PUT',
url: urlPrefix + 'transport/' + transport + '/' + new_transport + urlSufix(this),
dataType: 'json',
cache: false,
success: function(data) {
if (data.code != "Ok") {
this.user.transports[transport]= oldTransport;
document.getElementById(transport + '-input').value = oldTransport;
Materialize.toast('Erreur interne, veuillez réessayer plus tard.', 3000, 'red darken-1');
}else Materialize.toast('Transport vérifié', 3000, 'green darken-1');
}.bind(this),
error: function(xhr, status, err) {
this.user.transports[transport]= oldTransport;
document.getElementById(transport + '-input').value = oldTransport;
Materialize.toast(err, 3000, 'red darken-1');
console.error('/api/transport/' + transport + '/' + new_transport, status, err.toString());
}.bind(this)
});
}else Materialize.toast('Format invalide.', 3000, 'red darken-1');
},
deleteTransport: function(transport) {
var oldTransport = this.user.transports[transport];
this.user.transports[transport]= new_transport;
document.getElementById(transport + '-input').value = '';
this.user.transports[transport]= null;
$.ajax({
method: 'PUT',
url: '/api/transport/' + transport + '/' + new_transport + '/' + this.user.uid,
method: 'DELETE',
url: urlPrefix + 'transport/' + transport + urlSufix(this),
dataType: 'json',
cache: false,
success: function(data) {
if (data.code != "Ok") {
this.user.transports[transport]= oldTransport;
document.getElementById(transport + '-input').value = oldTransport;
Materialize.toast('Erreur interne, veuillez réessayer plus tard.', 3000, 'red darken-1');
}else Materialize.toast('Transport vérifié', 3000, 'green darken-1');
if (data.code != "Ok") this.user.transports[transport]= oldTransport;
}.bind(this),
error: function(xhr, status, err) {
this.user.transports[transport]= oldTransport;
document.getElementById(transport + '-input').value = oldTransport;
Materialize.toast(err, 3000, 'red darken-1');
console.error('/api/transport/' + transport + '/' + new_transport, status, err.toString());
console.error("/data/deactivate.json", status, err.toString());
}.bind(this)
});
}else Materialize.toast('Format invalide.', 3000, 'red darken-1');
},
deleteTransport: function(transport) {
var oldTransport = this.user.transports[transport];
this.user.transports[transport]= null;
$.ajax({
method: 'DELETE',
url: '/api/transport/' + transport + '/' + this.user.uid,
dataType: 'json',
cache: false,
success: function(data) {
if (data.code != "Ok") this.user.transports[transport]= oldTransport;
}.bind(this),
error: function(xhr, status, err) {
this.user.transports[transport]= oldTransport;
Materialize.toast(err, 3000, 'red darken-1');
console.error("/data/deactivate.json", status, err.toString());
}.bind(this)
});
},
testTransport: function(transport) {
$.ajax({
url: '/api/transport/' + transport + '/test/' + this.user.uid,
dataType: 'json',
cache: false,
success: function(data) {
if (data.code != "Ok") Materialize.toast(data.message, 3000, 'red darken-1');
else Materialize.toast('Transport vérifié', 3000, 'green darken-1');
}.bind(this),
error: function(xhr, status, err) {
Materialize.toast(err, 3000, 'red darken-1');
console.error('/api/transport/' + transport + '/test', status, err.toString());
}.bind(this)
});
},
testTransport: function(transport) {
$.ajax({
url: urlPrefix + 'transport/' + transport + '/test' + urlSufix(this),
dataType: 'json',
cache: false,
success: function(data) {
if (data.code != "Ok") Materialize.toast(data.message, 3000, 'red darken-1');
else Materialize.toast('Transport vérifié', 3000, 'green darken-1');
}.bind(this),
error: function(xhr, status, err) {
Materialize.toast(err, 3000, 'red darken-1');
console.error('/api/transport/' + transport + '/test', status, err.toString());
}.bind(this)
});
},
},
},
template: '#random_code-method'
});
template: '#random_code-method'
});
}

var RandomCodeMailMethod = RandomCodeMethod.extend({
template:'#random_code_mail-method'
});
function randomCodeMailMethod(isManagerDashboard) {
randomCodeMethod(isManagerDashboard).extend({
template: '#random_code_mail-method'
});
}

var Esupnfc = Vue.extend({
template:'#esupnfc-method'
Expand All @@ -194,8 +202,8 @@ var UserDashboard = Vue.extend({
"push": PushMethod,
"totp": TotpMethod,
"bypass": BypassMethod,
"random_code": RandomCodeMethod,
"random_code_mail":RandomCodeMailMethod,
"random_code": randomCodeMethod(false),
"random_code_mail": randomCodeMailMethod(false),
"esupnfc":Esupnfc
},
template: "#user-dashboard",
Expand Down Expand Up @@ -351,8 +359,8 @@ var UserView = Vue.extend({
"push": PushMethod,
"totp": TotpMethod,
"bypass": BypassMethod,
"random_code": RandomCodeMethod,
"random_code_mail":RandomCodeMailMethod,
"random_code": randomCodeMethod(true),
"random_code_mail": randomCodeMailMethod(true),
"esupnfc":Esupnfc
},
data: function () {
Expand Down
50 changes: 34 additions & 16 deletions server/routes.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,15 +52,6 @@ function isUser(req, res, next) {
res.redirect('/login');
}

function currentUserCanUpdateUidParam(req, res, next) {
const paramUid = req.params.uid;
if (paramUid && paramUid != req.session.passport.user.uid) {
return isManager(req, res, next);
} else {
return next();
}
}

function isManager(req, res, next) {
if (isAuthenticated(req, res)) {
if (utils.is_manager(req.session.passport.user) || utils.is_admin(req.session.passport.user))return next();
Expand All @@ -77,6 +68,13 @@ function isAdmin(req, res, next) {
res.redirect('/login');
}

/**
* @returns hash for current user
*/
function getHash(req) {
return utils.get_hash(req.session.passport.user.uid);
}

function routing() {
router.get('/', function(req, res) {
res.render('index', {
Expand Down Expand Up @@ -126,7 +124,7 @@ function routing() {
})(req, res, next);
});

router.get('/logout', function(req, res) {
router.get('/logout', function(req, res, next) {
req.logout(function(err) {
if (err) { return next(err); }
res.redirect(properties.esup.CAS.casBaseURL+'/logout');
Expand All @@ -136,7 +134,7 @@ function routing() {
//API
router.get('/api/user', isUser, function(req, res) {
request_otp_api(req, res, {
relUrl: 'users/' + req.session.passport.user.uid + '/' + utils.get_hash(req.session.passport.user.uid),
relUrl: 'users/' + req.session.passport.user.uid + '/' + getHash(req),
});
});

Expand Down Expand Up @@ -164,7 +162,13 @@ function routing() {
res.send(data);
});

router.get('/api/transport/:transport/test/:uid', isUser, currentUserCanUpdateUidParam, function(req, res) {
router.get('/api/transport/:transport/test', isUser, function(req, res) {
request_otp_api(req, res, {
relUrl: 'users/' + req.session.passport.user.uid + '/transports/'+ req.params.transport+'/test/' + getHash(req),
});
});

router.get('/api/admin/transport/:transport/test/:uid', isManager, function(req, res) {
request_otp_api(req, res, {
relUrl: 'protected/users/' + req.params.uid + '/transports/'+ req.params.transport+'/test/', bearerAuth: true,
});
Expand Down Expand Up @@ -196,14 +200,28 @@ function routing() {
});
});

router.put('/api/transport/:transport/:new_transport/:uid', isUser, currentUserCanUpdateUidParam, function(req, res) {
router.put('/api/transport/:transport/:new_transport', isUser, function(req, res) {
request_otp_api(req, res, {
method: 'PUT',
relUrl: 'users/'+ req.session.passport.user.uid +'/transports/'+req.params.transport+'/'+req.params.new_transport+'/' + getHash(req), bearerAuth: true,
});
});

router.put('/api/admin/transport/:transport/:new_transport/:uid', isManager, function(req, res) {
request_otp_api(req, res, {
method: 'PUT',
relUrl: 'protected/users/'+ req.params.uid +'/transports/'+req.params.transport+'/'+req.params.new_transport+'/', bearerAuth: true,
});
});

router.delete('/api/transport/:transport/:uid', isUser, currentUserCanUpdateUidParam, function(req, res) {
router.delete('/api/transport/:transport/', isUser, function(req, res) {
request_otp_api(req, res, {
method: 'DELETE',
relUrl: 'users/'+ req.session.passport.user.uid +'/transports/'+req.params.transport+'/' + getHash(req),
});
});

router.delete('/api/admin/transport/:transport/:uid', isManager, function(req, res) {
request_otp_api(req, res, {
method: 'DELETE',
relUrl: 'protected/users/'+ req.params.uid +'/transports/'+req.params.transport+'/', bearerAuth: true,
Expand All @@ -213,7 +231,7 @@ function routing() {
router.post('/api/generate/:method', isUser, function(req, res) {
request_otp_api(req, res, {
method: 'POST',
relUrl: 'protected/users/'+ req.session.passport.user.uid + '/methods/' + req.params.method + '/secret/', bearerAuth: true,
relUrl: 'users/'+ req.session.passport.user.uid + '/methods/' + req.params.method + '/secret/' + getHash(req),
});
});

Expand All @@ -225,7 +243,7 @@ function routing() {

router.get('/api/admin/user/:uid', isManager, function(req, res) {
request_otp_api(req, res, {
relUrl: 'users/' + req.params.uid + '/' + utils.get_hash(req.params.uid),
relUrl: 'protected/users/' + req.params.uid, bearerAuth: true,
});
});

Expand Down

0 comments on commit d17bd63

Please sign in to comment.