Skip to content

Commit

Permalink
Added privileges control in UI and user-add (#435)
Browse files Browse the repository at this point in the history
* Internationalization

With this changes the user can input international characters like á, ì and ç.

* Sprint Checklist in correct Order

Correction of the Checklist Order on a Sprint.
Before: 1.1, 1.10, 1.2
Now: 1.1, 1.2, 1.10

* Correction of Codacy Issues

Correction of unused variable and "Redefining built-in 'list'" Codacy issues.

* Order in checklist page

Order requirements in checklist page

* Export failed requirement to Defect Dojo

Now on the Failed requirements page, there is a button to export that requirements to Defect Dojo.

* Buttons hidding acording to status

Buttons hidding or not acordint to checklist status in Project-Summary.

* Fixed Codacy issues of #430

Fixed Codacy issues of #430

* Error fix.

Fix of error introduced by Codacy issue.

* Codacy fix

* Fix of issue #422

Fix of issue in which only admin can create projects and sprints.

* Fix reordening issue 428

Using observable in Angular (thanks RiieCco) with finally making the call for the new list.

* Codacy fixes

* Added privileges control in UI and user-add

Added some controls in the UI according to privileges of the user.
Added select on Create User option.

Fix of issue with privileges.query without privilegeID, that returns every privilege in login action.
  • Loading branch information
martinmarsicano authored and blabla1337 committed Feb 6, 2018
1 parent 895fc61 commit 31d0bd2
Show file tree
Hide file tree
Showing 17 changed files with 113 additions and 20 deletions.
1 change: 1 addition & 0 deletions Angular/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
"@ng-bootstrap/ng-bootstrap": "1.0.0-beta.6",
"angular2-highlight-js": "^5.0.0",
"core-js": "^2.4.1",
"jwt-decode": "^2.2.0",
"rxjs": "^5.1.0",
"typescript": "2.3.4",
"zone.js": "^0.8.4"
Expand Down
4 changes: 2 additions & 2 deletions Angular/src/app/header/header.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -83,11 +83,11 @@
<span id="1">Projects</span>
</a>
<ul *ngIf="projects" class="sub" id="1" style="display:block;">
<li><a routerLink="/project-new" id="1">New Project</a></li>
<li *ngIf="canEdit"><a routerLink="/project-new" id="1">New Project</a></li>
<li><a routerLink="/project-list" id="1">List Projects</a></li>
</ul>
</li>
<li [style.background-color]="getUSerStyle()" class="sub-menu">
<li *ngIf="canManage" [style.background-color]="getUSerStyle()" class="sub-menu">
<a (click)="UsersShow()" id="2" class="primairy" href="javascript:;">
<i class="fa fa-user"></i>
<span id="2">Users</span>
Expand Down
8 changes: 8 additions & 0 deletions Angular/src/app/header/header.component.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router';
import { AppSettings } from '../globals';
import * as JWT from 'jwt-decode';

@Component({
selector: 'app-header',
Expand All @@ -20,10 +21,17 @@ export class HeaderComponent implements OnInit {
public check: boolean;
public color:string = '#515594';
public user: string = AppSettings.USER;
public canManage: boolean;
public canEdit: boolean;
//public canDelete: boolean;
//public canRead: boolean;

ngOnInit() {
if (AppSettings.AUTH_TOKEN) {
this.isLoggedin = true;
let decodedJWT = JWT(AppSettings.AUTH_TOKEN);
this.canManage = decodedJWT.privilege.includes("manage");
this.canEdit = decodedJWT.privilege.includes("edit");
}

this.projects = false;
Expand Down
7 changes: 7 additions & 0 deletions Angular/src/app/models/privilege.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export class Privilege {
constructor(
privilege: string,
privilegeID?: number
){}
}

Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ <h1>Project overview</h1>
<p>An overview of all the current sprints in the project. More information about the security requirements by clicking
on the view button. </p>
</div>
<button style="float:right;" (click)="open(content)" class="btn btn-default"><i class="fa fa-cog" aria-hidden="true"></i> Add new sprint</button>
<button *ngIf="canEdit" style="float:right;" (click)="open(content)" class="btn btn-default"><i class="fa fa-cog" aria-hidden="true"></i> Add new sprint</button>
</div>
</section>
<section class="wrapper" style="margin-top:0px;">
Expand Down Expand Up @@ -90,7 +90,7 @@ <h1>Project overview</h1>
<div class="right">
<a *ngIf="sprint.sprint_sec_fail > 0" class="btn btn-danger btn-xs" href="" [routerLink]="['/project-summary-audit',sprint.sprint_id]"><i class="fa fa-exclamation-triangle" aria-hidden="true"></i> <span *ngIf="sprint.sprint_sec_fail > 0">Failed items!</span></a>
<button [routerLink]="['/project-summary',sprint.sprint_id]" class="btn btn-default btn-xs">View</button>
<button (click)="open(deleteModal)" class="btn btn-danger btn-xs"><i class="fa fa-times"></i> </button>
<button *ngIf="canDelete" (click)="open(deleteModal)" class="btn btn-danger btn-xs"><i class="fa fa-times"></i> </button>

<!-- We have to throw in the model here for the id to delete -->
<ng-template #deleteModal let-c="close" let-d="dismiss">
Expand Down
10 changes: 10 additions & 0 deletions Angular/src/app/project-dashboard/project-dashboard.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import { Sprint } from '../models/sprint'
import { Question_sprint } from '../models/question_sprint'
import { Router, ActivatedRoute, Params } from '@angular/router';
import { NgForm } from '@angular/forms';
import { AppSettings } from '../globals';
import * as JWT from 'jwt-decode';


@Component({
Expand All @@ -31,6 +33,8 @@ export class ProjectDashboardComponent implements OnInit {
public pre_dev_store: Question_pre[] = [];
public delete: string;
public idFromURL: number;
public canDelete: boolean;
public canEdit: boolean;
constructor(
private modalService: NgbModal,
private questionPreService: QuestionPreService,
Expand All @@ -53,6 +57,12 @@ export class ProjectDashboardComponent implements OnInit {
.subscribe(
(projectService) => { this.sprints = projectService },
err => console.log("getting sprint questions failed"));

if (AppSettings.AUTH_TOKEN) {
let decodedJWT = JWT(AppSettings.AUTH_TOKEN);
this.canDelete = decodedJWT.privilege.includes("delete");
this.canEdit = decodedJWT.privilege.includes("edit");
}
}

newSprint() {
Expand Down
4 changes: 2 additions & 2 deletions Angular/src/app/project-list/project-list.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ <h1>All projects</h1>
<th><i class="fa fa-clock-o"></i> Creation date</th>
<th><i class="fa fa-university"></i> Project level</th>
<th><i class="fa fa-bookmark"></i> Project version</th>
<th><i class="fa fa-times"></i> Delete</th>
<th *ngIf="canDelete"><i class="fa fa-times"></i> Delete</th>
</tr>
</thead>
<tbody>
Expand All @@ -60,7 +60,7 @@ <h1>All projects</h1>
<td><span class="label">{{project.timestamp}}</span></td>
<td>{{project.level}}</td>
<td>{{project.projectVersion}}</td>
<td>
<td *ngIf="canDelete">
<button (click)="open(content)" class="btn btn-danger btn-xs">
<i class="fa fa-times "></i>
</button>
Expand Down
7 changes: 7 additions & 0 deletions Angular/src/app/project-list/project-list.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import { ProjectService } from '../services/project.service';
import { Project } from '../models/project';
import { NgbModal, ModalDismissReasons } from '@ng-bootstrap/ng-bootstrap';
import { Observable } from 'rxjs/Rx';
import { AppSettings } from '../globals';
import * as JWT from 'jwt-decode';

@Component({
selector: 'app-project-list',
Expand All @@ -15,11 +17,16 @@ export class ProjectListComponent implements OnInit {
public number: number;
public error: string;
public delete: string;
public canDelete:boolean;

constructor(private _projectService: ProjectService, private modalService: NgbModal) { }

ngOnInit() {
this.projectList();
if (AppSettings.AUTH_TOKEN) {
let decodedJWT = JWT(AppSettings.AUTH_TOKEN);
this.canDelete = decodedJWT.privilege.includes("delete");
}
}

deleter(id: number) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ <h4>{{item.kb_item_title}}</h4>
</p>
</ng-template>
</ngb-tab>
<ngb-tab>
<ngb-tab *ngIf="canEdit">
<ng-template ngbTabTitle><b>Status</b></ng-template>
<ng-template ngbTabContent>
<div class="form-group">
Expand Down
12 changes: 9 additions & 3 deletions Angular/src/app/project-summary/project-summary.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@ import { NgbModal, ModalDismissReasons } from '@ng-bootstrap/ng-bootstrap';
import { Router, ActivatedRoute, Params } from '@angular/router';
import { SprintService } from '../services/sprint.service'
import { CommentService } from '../services/comment.service'

import { Sprint } from '../models/sprint'
import { Comment } from '../models/comment'
import { AppSettings } from '../globals';
import * as JWT from 'jwt-decode';

@Component({
selector: 'app-project-summary',
Expand All @@ -28,15 +29,20 @@ export class ProjectSummaryComponent implements OnInit {
public error: string;
public succes: string;
public selector: string = "Development";
public backID : string;
public showMe : string;
public backID: string;
public showMe: string;
public canEdit: boolean;

ngOnInit() {
this.route.params.subscribe(params => {
this.sprintService.getSprintResults(params['id']).subscribe(
resp => this.sprintResult = resp,
err => console.log("Error getting sprint stats"))
});
if (AppSettings.AUTH_TOKEN) {
let decodedJWT = JWT(AppSettings.AUTH_TOKEN);
this.canEdit = decodedJWT.privilege.includes("edit");
}
}

back() {
Expand Down
5 changes: 5 additions & 0 deletions Angular/src/app/services/user-add.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@ export class UserAddService {
constructor(private http: Http, private router: Router) { }
public headers = new Headers({ 'Content-Type': 'application/json', 'Authorization': AppSettings.AUTH_TOKEN });

getPrivileges() {
return this.http.get(environment.API_ENDPOINT + '/user/list_privileges',
{ headers: this.headers }).map(response => response.json().items)
}

newUser(email: string, privileges: string): Observable<User[]> {

return this.http
Expand Down
8 changes: 3 additions & 5 deletions Angular/src/app/user-add/user-add.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -60,22 +60,20 @@ <h1>Create new user</h1>
</div>
</div>

<!-- All for the next release :-)
<div class="form-group">
<div class="wrap">
<label for="inputmail" class="col-sm-2 control-label">Privileges</label>
<div class="col-sm-10">
<select [(ngModel)]="privileges" name="privileges" class="form-control">
<option value="" selected>-- Please Select --</option>
<option value="2">Observer</option>
<option value="3">Editor</option>
<select [(ngModel)]="privilegeSelected" name="privilegeSelected" class="form-control">
<option *ngFor="let item of privileges;" value="{{item.privilegeID}}">{{item.privilege}}</option>
</select>
<div class="wrap desc alert-info">
<div class="col-sm-10">An <b>observer</b> can only view projects and reports, <b>Editors</b> can add and edit them.</div>
</div>
</div>
</div>
</div>
<!-- All for the next release :-)
<div class="form-group">
<div class="wrap">
<label for="inputmail" class="col-sm-2 control-label">Avatar</label>
Expand Down
17 changes: 13 additions & 4 deletions Angular/src/app/user-add/user-add.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,31 +2,40 @@ import { Component } from '@angular/core';
import { UserAddService } from '../services/user-add.service'
import { User } from '../models/user'
import { Router } from '@angular/router'
import { Privilege } from '../models/privilege'

@Component({
selector: 'app-user-add',
templateUrl: './user-add.component.html',
providers: [UserAddService]
})

export class UserAddComponent{
export class UserAddComponent { //implements OnInit {
public email: string;
public privileges: string;
public privilegeSelected: string;
public return: boolean;
public error: string[] = [];
public data: User[];
public privileges: Privilege[];
constructor(private _userAddService: UserAddService, private _router: Router) { }

ngOnInit() {
this._userAddService.getPrivileges().subscribe(
privileges => this.privileges = privileges,
err => console.log("Getting privileges failed")
)
}

save() {
this.return = true;
this.error = [];
if (!this.email) { this.error.push("No email was provided!"); this.return = false; }
let EMAIL_REGEXP = /^[a-z0-9!#$%&'*+\/=?^_`{|}~.-]+@[a-z0-9]([a-z0-9-]*[a-z0-9])?(\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*$/i;
if(EMAIL_REGEXP.test(this.email) == false) { this.error.push("Email validation failed, provide a valid adress!"); this.return = false}
//if (!this.privileges) { this.error.push("No privilege was provided!"); this.return = false; }
if (!this.privilegeSelected) { this.error.push("No privilege was provided!"); this.return = false; }
if (this.return == false) { return; }

this._userAddService.newUser(this.email, '2')
this._userAddService.newUser(this.email, this.privilegeSelected)
.subscribe(
data => this.data = data,
err => this.error.push("Error whilst adding user, potential duplicate email adres!")
Expand Down
8 changes: 7 additions & 1 deletion skf/api/user/business.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ def login_user(data):
if (user.activated == "True"):
if (user.access == "True"):
if check_password_hash(user.password, data.get('password')):
priv_user = privileges.query.filter(str(user.privilegeID)).first()
priv_user = privileges.query.filter(privileges.privilegeID == str(user.privilegeID)).first()
payload = {
# userid
'UserId': user.userID,
Expand Down Expand Up @@ -78,6 +78,12 @@ def login_user(data):
return {'Authorization token': ''}


def list_privileges():
log("User requested privileges items", "MEDIUM", "PASS")
result = privileges.query.filter(privileges.privilegeID != "1").paginate(1, 500, False)
return result


def create_user(data):
log("A new user created", "MEDIUM", "PASS")
my_secure_rng = secrets.SystemRandom()
Expand Down
26 changes: 26 additions & 0 deletions skf/api/user/endpoints/user_listprivileges.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
from flask import request
from flask_restplus import Resource
from skf.api.security import security_headers, validate_privilege
from skf.api.user.business import list_privileges
from skf.api.user.serializers import privilege_items, message
from skf.api.user.parsers import authorization
from skf.api.restplus import api

ns = api.namespace('user', description='Operations related to users')


@ns.route('/list_privileges')
@api.response(404, 'Validation error', message)
class userListPrivileges(Resource):

@api.expect(authorization)
@api.marshal_with(privilege_items)
@api.response(400, 'No results found', message)
def get(self):
"""
List available users.
* Privileges required: **manage**
"""
validate_privilege(self, 'manage')
result = list_privileges()
return result, 200, security_headers()
9 changes: 9 additions & 0 deletions skf/api/user/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,4 +48,13 @@

user_items = api.inherit('List of user items', {
'items': fields.List(fields.Nested(user_list))
})

privilege_list = api.model('privilege_list', {
'privilege': fields.String(required=True, description='The list of privileges'),
'privilegeID': fields.Integer(required=True, description='The unique identifier of the privilege'),
})

privilege_items = api.inherit('List of privilege items', {
'items': fields.List(fields.Nested(privilege_list))
})
1 change: 1 addition & 0 deletions skf/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
from skf.api.user.endpoints.user_login import ns as users_namespace
from skf.api.user.endpoints.user_list import ns as users_namespace
from skf.api.user.endpoints.user_manage import ns as users_namespace
from skf.api.user.endpoints.user_listprivileges import ns as users_namespace
from skf.api.kb.endpoints.kb_items import ns as kb_namespace
from skf.api.kb.endpoints.kb_item import ns as kb_namespace
from skf.api.kb.endpoints.kb_item_update import ns as kb_namespace
Expand Down

0 comments on commit 31d0bd2

Please sign in to comment.