Skip to content

Commit b9e0b12

Browse files
authored
Fix 'managers' functionalities (#614)
* fix bad logic * allow admins to add/remove managers * fix manager add/remove success message * fix worse logic * changelog
1 parent e5c6033 commit b9e0b12

6 files changed

Lines changed: 81 additions & 10 deletions

File tree

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
* Fix database creation validation confirmation email
1010
* Fix database creation request email title
1111
* Remove DB 'size' attribute
12+
* Allow admins to add/remove project managers
13+
* Fix add/remove manager http returns
1214

1315
## 1.4.32 (2025-04-22)
1416

manager2/src/app/admin/project/project.component.html

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,28 @@ <h4>
9494
<div class="card-header">User management</div>
9595
<div class="card-body">
9696
<form role="form" class="user-form form-horizontal form-register">
97+
<div class="form-group row">
98+
<div class="col-sm-3">
99+
<label for="new_manager">New project manager</label>
100+
<select id="add_manager" [ngModelOptions]="{standalone: true}" [(ngModel)]="new_manager" class="form-control">
101+
<option *ngFor="let user of users" [value]="user.uid">{{user.uid}}</option>
102+
</select>
103+
</div>
104+
<div class="col-sm-3">
105+
<label style="opacity: 0;">Add new manager</label>
106+
<button type="button" class="p-button p-button-sm p-button-success" (click)="add_manager(new_manager)">Promote to Manager</button>
107+
</div>
108+
<div class="col-sm-3">
109+
<label for="rm_manager">Remove project manager</label>
110+
<select id="rm_manager" [ngModelOptions]="{standalone: true}" [(ngModel)]="rm_manager" class="form-control">
111+
<option *ngFor="let manager of this.project.managers" [value]="manager">{{manager}}</option>
112+
</select>
113+
</div>
114+
<div class="col-sm-3">
115+
<label style="opacity: 0;">Remove manager</label>
116+
<button type="button" class="p-button p-button-sm p-button-warning"(click)="remove_manager(rm_manager)">Demote to Member</button>
117+
</div>
118+
</div>
97119
<div *ngIf="admin_user_msg" class="alert alert-success">{{ admin_user_msg }}</div>
98120
<div *ngIf="admin_user_err_msg" class="alert alert-danger">{{ admin_user_err_msg }}</div>
99121
<div class="form-group row">
@@ -116,7 +138,7 @@ <h4>
116138
</div>
117139
<div class="col-sm-3">
118140
<label style="opacity: 0">Remove member</label>
119-
<button type="button" class="p-button p-button-sm p-button-danger" (click)="remove_user()">Remove member</button>
141+
<button type="button" class="p-button p-button-sm p-button-warning" (click)="remove_user()">Remove member</button>
120142
</div>
121143
</div>
122144
</form>

manager2/src/app/admin/project/project.component.ts

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ export class ProjectComponent implements OnInit {
2626

2727
new_user_admin: string = '';
2828
remove_user_admin: string = '';
29+
new_manager: string = '';
30+
rm_manager: string = '';
2931

3032
admin_user_err_msg: string;
3133
admin_user_msg: string;
@@ -97,6 +99,48 @@ export class ProjectComponent implements OnInit {
9799
);
98100
}
99101

102+
add_manager(new_manager: string) {
103+
this.admin_user_msg = '';
104+
this.admin_user_err_msg = '';
105+
if (!new_manager) {
106+
this.admin_user_err_msg = 'User id is required';
107+
return;
108+
}
109+
for (var i = 0; i < this.project.managers.length; i++) {
110+
if (this.project.managers[i] === new_manager) {
111+
this.admin_user_err_msg = 'User is already a manager';
112+
return;
113+
}
114+
}
115+
this.projectsService.add_manager(this.project.id, new_manager).subscribe(
116+
resp => {
117+
this.admin_user_msg = resp['message']
118+
this.show_project_users(this.project.id)
119+
},
120+
err => this.admin_user_err_msg = err.error.message
121+
);
122+
}
123+
124+
remove_manager(rm_manager: string) {
125+
this.admin_user_msg = '';
126+
this.admin_user_err_msg = '';
127+
if (!rm_manager) {
128+
this.admin_user_err_msg = 'User id is required';
129+
return;
130+
}
131+
if (this.project.owner === rm_manager) {
132+
this.admin_user_err_msg = 'The project owner is always a manager';
133+
return;
134+
}
135+
this.projectsService.remove_manager(this.project.id, rm_manager).subscribe(
136+
resp => {
137+
this.admin_user_msg = resp['message']
138+
this.show_project_users(this.project.id);
139+
},
140+
err => this.admin_user_err_msg = err.error.message
141+
);
142+
}
143+
100144
add_user() {
101145
this.admin_user_msg = '';
102146
this.admin_user_err_msg = '';

manager2/src/app/project/project.component.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -227,7 +227,7 @@ export class ProjectComponent implements OnInit {
227227
);
228228
return;
229229
}
230-
// Owner request
230+
// Owner or Manager request
231231
this.projectsService.request_user(project.id, { request: request_type, user: user_id }).subscribe(
232232
(resp) => {
233233
this.manager_request_msg = resp['message'];

routes/projects.js

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -333,9 +333,12 @@ router.post('/project/:id/request/user', async function (req, res) {
333333
if (!project) {
334334
return res.status(404).send({ message: 'Project ' + req.params.id + ' not found' });
335335
}
336-
if ((!project.managers || !project.managers.includes(user.uid)) && user.uid != project.owner) {
336+
if ((!project.managers || !project.managers.includes(user.uid)) && user.uid !== project.owner && !user.is_admin) {
337337
return res.status(401).send({ message: 'User ' + user.uid + ' is not project manager for project ' + project.id });
338338
}
339+
if (req.body.user == project.owner) {
340+
return res.status(403).send({ message: 'User ' + req.body.user + ' is the owner of project ' + project.id });
341+
}
339342
let newuser = await dbsrv.mongo_users().findOne({ uid: req.body.user });
340343
if (!newuser) {
341344
return res.status(404).send({ message: 'User ' + req.body.user + ' not found' });
@@ -377,8 +380,8 @@ router.post('/project/:id/add/manager/:uid', async function(req, res) {
377380
if (!project) {
378381
return res.status(404).send({ message: 'Project ' + req.params.id + ' not found' });
379382
}
380-
if (user.uid != project.owner) {
381-
return res.status(401).send({ message: 'User ' + user.uid + ' is not the owner of project ' + project.id });
383+
if (user.uid != project.owner && !user.is_admin) {
384+
return res.status(401).send({ message: 'Non-admin user ' + user.uid + ' is not the owner of project ' + project.id });
382385
}
383386
const new_manager = await dbsrv.mongo_users().findOne({ 'uid': req.params.uid });
384387
if (!new_manager) {
@@ -405,7 +408,7 @@ router.post('/project/:id/add/manager/:uid', async function(req, res) {
405408
return res.status(500).send({ message: 'Server Error, contact admin' });
406409
}
407410
}
408-
return res.send({ message: req.body.request + ' ' + req.body.user + ' done' });
411+
return res.send({ message: 'Add manager ' + new_manager.uid + ' done' });
409412
});
410413

411414

@@ -424,8 +427,8 @@ router.post('/project/:id/remove/manager/:uid', async function(req, res) {
424427
if (!project) {
425428
return res.status(404).send({ message: 'Project ' + req.params.id + ' not found' });
426429
}
427-
if (user.uid != project.owner) {
428-
return res.status(401).send({ message: 'User ' + user.uid + ' is not the owner of project ' + project.id });
430+
if (user.uid != project.owner && !user.is_admin) {
431+
return res.status(401).send({ message: 'Non-admin user ' + user.uid + ' is not the owner of project ' + project.id });
429432
}
430433
const ex_manager = await dbsrv.mongo_users().findOne({ 'uid': req.params.uid });
431434
if (!ex_manager) {
@@ -449,7 +452,7 @@ router.post('/project/:id/remove/manager/:uid', async function(req, res) {
449452
return res.status(500).send({ message: 'Server Error, contact admin' });
450453
}
451454
}
452-
return res.send({ message: req.body.request + ' ' + req.body.user + ' done' });
455+
return res.send({ message: 'Remove manager ' + ex_manager.uid + ' done' });
453456
});
454457

455458

routes/users.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1655,7 +1655,7 @@ router.delete('/user/:id/project/:project', async function (req, res) {
16551655
return res.status(404).send({ message: 'Project not found' });
16561656
}
16571657

1658-
if (!isadmin && session_user.uid != project.owner && session_user.uid != uid) {
1658+
if (!isadmin && session_user.uid !== project.owner && (!project.managers || !project.managers.includes(session_user.uid)) && session_user.uid != uid) {
16591659
return res.status(401).send({ message: 'Not authorized' });
16601660
}
16611661

0 commit comments

Comments
 (0)