Skip to content

Commit dd586c4

Browse files
authored
Merge pull request #137 from delphi-hub/feature/newUserMgmt
Feature/new user mgmt
2 parents c53e742 + f2e80fa commit dd586c4

29 files changed

+681
-130
lines changed

app/actors/ClientSocketActor.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ class ClientSocketActor(out: ActorRef, publisher: ActorRef) extends Actor with E
2424

2525
override def preStart() {
2626
Logger.debug("pre start called in client" + self)
27-
out ! "successfully registered"
27+
out ! Json.obj("msg" -> "successfully registered").toString()
2828
}
2929

3030
override def postStop() {

app/controllers/ApiRouter.scala

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ class ApiRouter @Inject()(irController: InstanceRegistryController, sysControlle
3737
case GET(p"/instances" ? q"componentType=$componentType") => irController.instances(componentType)
3838
case GET(p"/systemInfo") => sysController.getInfo()
3939
case GET(p"/network") => irController.getNetwork()
40+
case GET(p"/users") => irController.users()
4041
case POST(p"/postInstance" ? q"componentType=$componentType"& q"name=$name") => irController.postInstance(componentType, name)
4142
case POST(p"/startInstance" ? q"instanceID=$instanceID") => irController.handleRequest(action="/start", instanceID)
4243
case POST(p"/stopInstance" ? q"instanceID=$instanceID") => irController.handleRequest(action="/stop", instanceID)
@@ -46,5 +47,7 @@ class ApiRouter @Inject()(irController: InstanceRegistryController, sysControlle
4647
case POST(p"/reconnectInstance" ? q"from=$from"& q"to=$to") => irController.reconnect(from.toInt, to.toInt)
4748
case POST(p"/authenticate") => irController.authentication()
4849
case POST(p"/labelInstance" ? q"instanceID=$instanceID"& q"label=$label") => irController.labelInstance(instanceID, label)
50+
case POST(p"/postUser") => irController.postUser()
51+
case POST(p"/deleteUser" ? q"userID=$userID") => irController.deleteUser(userID)
4952
}
5053
}

app/controllers/InstanceRegistryController.scala

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,22 @@ class InstanceRegistryController @Inject()(implicit system: ActorSystem, mat: Ma
8787
}
8888
}
8989

90+
/** This method lists all Users.
91+
* @return
92+
*/
93+
94+
def users(): Action[AnyContent] = authAction.async{
95+
ws.url(instanceRegistryUri + "/users").withHttpHeaders(("Authorization", s"Bearer ${AuthProvider.generateJwt()}"))
96+
.get().map { response =>
97+
Logger.debug(response.body)
98+
if (response.status == 200) {
99+
Ok(response.body)
100+
} else {
101+
new Status(response.status)
102+
}
103+
}(myExecutionContext)
104+
}
105+
90106
/** Called to fetch network graph of current registry. Contains a list of all instances and all links
91107
* currently registered.
92108
*
@@ -252,4 +268,57 @@ class InstanceRegistryController @Inject()(implicit system: ActorSystem, mat: Ma
252268
}
253269
}(myExecutionContext)
254270
}
271+
272+
/**
273+
* This function is used to add a User.
274+
* Username, Secret and UserType are sent in the body post
275+
* Instance registry returns a valid userID
276+
* @return
277+
*/
278+
279+
def postUser(): Action[AnyContent] = authAction.async {
280+
request =>
281+
val jsonBody: Option[JsValue] = request.body.asJson
282+
jsonBody.map { json =>
283+
val userName = (json \ "userName").as[String]
284+
val secret = (json \ "secret").as[String]
285+
val userType = (json \ "userType").as[String]
286+
ws.url(instanceRegistryUri + "/users" + "/add")
287+
.withHttpHeaders(("Authorization", s"Bearer ${AuthProvider.generateJwt()}"))
288+
.post(json)
289+
.map { response =>
290+
if (response.status == 200) {
291+
Ok(Json.obj("token" -> response.body, "refreshToken" -> ""))
292+
} else {
293+
Logger.info(s"$ws")
294+
Logger.debug(s"$ws")
295+
new Status(response.status)
296+
}
297+
}
298+
}.getOrElse{ Future(BadRequest("Invalid body"))}
299+
}
300+
301+
/**
302+
* This function is used to delete a user.
303+
* @param userID ID of the user that is to be deleted
304+
* @return
305+
*/
306+
def deleteUser( userID: String): Action[AnyContent] = authAction.async {
307+
request =>
308+
ws.url(instanceRegistryUri + "/users/" + userID + "/remove")
309+
.withHttpHeaders(("Authorization", s"Bearer ${AuthProvider.generateJwt()}"))
310+
.post("")
311+
.map { response =>
312+
response.status match {
313+
// scalastyle:off magic.number
314+
case 202 =>
315+
// scalastyle:on magic.number
316+
Ok(Json.obj("msg" -> response.body))
317+
case x: Any =>
318+
new Status(x)
319+
}
320+
}(myExecutionContext)
321+
}
322+
255323
}
324+

client/src/app/api/api/api.service.ts

Lines changed: 96 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,10 @@
1717
*/
1818

1919

20-
import {CustomHttpUrlEncodingCodec} from '../encoder';
21-
import {Instance} from '../../model/models/instance';
22-
import {SysInfo} from '../../model/models/sysInfo';
20+
import { CustomHttpUrlEncodingCodec } from '../encoder';
21+
import { Instance } from '../../model/models/instance';
22+
import { SysInfo } from '../../model/models/sysInfo';
23+
import { User } from '../../model/models/user';
2324
import { Inject, Injectable, Optional } from '@angular/core';
2425
import { HttpClient, HttpHeaders, HttpParams } from '@angular/common/http';
2526
import { Observable } from 'rxjs';
@@ -28,6 +29,8 @@ import {
2829
BASE_PATH,
2930
INSTANCES,
3031
NUMBER_OF_INSTANCES,
32+
USERS,
33+
NEW_USER,
3134
SYS_INFO,
3235
NEW_INSTANCE,
3336
START_INSTANCE,
@@ -37,6 +40,7 @@ import {
3740
DELETE_INSTANCE,
3841
NEW_LABEL_INSTANCE,
3942
INSTANCE_NETWORK,
43+
DELETE_USER,
4044
RECONNECT,
4145
AUTH
4246
} from '../variables';
@@ -92,7 +96,7 @@ export class ApiService {
9296
* @param observe set whether or not to return the data Observable as the body, response or events. defaults to returning the body.
9397
* @param reportProgress flag to report request and response progress.
9498
*/
95-
public getNumberOfInstances(componentType: string, observe: any = 'body', reportProgress: boolean = false ): Observable<number> {
99+
public getNumberOfInstances(componentType: string, observe: any = 'body', reportProgress: boolean = false): Observable<number> {
96100
return this.get(NUMBER_OF_INSTANCES, componentType);
97101
}
98102

@@ -169,7 +173,7 @@ export class ApiService {
169173
* @param observe set whether or not to return the data Observable as the body, response or events. defaults to returning the body.
170174
* @param reportProgress flag to report request and response progress.
171175
*/
172-
public pauseInstance(instanceId: string, observe: any = 'body', reportProgress: boolean = false) {
176+
public pauseInstance(instanceId: string, observe: any = 'body', reportProgress: boolean = false) {
173177
return this.postAction(PAUSE_INSTANCE, instanceId);
174178
}
175179

@@ -200,10 +204,71 @@ export class ApiService {
200204
* @param observe set whether or not to return the data Observable as the body, response or events. defaults to returning the body.
201205
* @param reportProgress flag to report request and response progress.
202206
*/
203-
public labelInstance( instanceId: string, labelName: string, observe: any = 'body', reportProgress: boolean = false) {
207+
public labelInstance(instanceId: string, labelName: string, observe: any = 'body', reportProgress: boolean = false) {
204208
return this.postLabel(NEW_LABEL_INSTANCE, instanceId, labelName);
205209
}
206210

211+
/**
212+
* Create a User
213+
* @param userName
214+
* @param secret
215+
* @param userType
216+
* @param observe set whether or not to return the data Observable as the body, response or events. defaults to returning the body.
217+
* @param reportProgress flag to report request and response progress.
218+
*/
219+
220+
public postUser(userName: string, secret: string, userType: string, observe: any = 'body', reportProgress: boolean = false)
221+
: Observable<User> {
222+
return this.userAdd(userName, secret, userType);
223+
}
224+
225+
private userAdd(username: string, secret: string, userType: string): Observable<User> {
226+
let headers = this.defaultHeaders;
227+
// to determine the Accept header
228+
const httpHeaderAccepts: string[] = [
229+
'application/json'
230+
];
231+
const httpHeaderAcceptSelected: string | undefined = this.configuration.selectHeaderAccept(httpHeaderAccepts);
232+
if (httpHeaderAcceptSelected !== undefined) {
233+
headers = headers.set('Accept', httpHeaderAcceptSelected);
234+
}
235+
236+
return this.httpClient.post<User>(`${this.basePath}${NEW_USER}`, {
237+
userName: username,
238+
secret: secret,
239+
userType: userType
240+
},
241+
{
242+
withCredentials: this.configuration.withCredentials,
243+
headers: headers
244+
}
245+
);
246+
}
247+
248+
public deleteUser(userId: string) {
249+
return this.deleteAction(DELETE_USER, userId);
250+
}
251+
252+
/**
253+
* Delete a User
254+
* @param idUser
255+
* @param observe set whether or not to return the data Observable as the body, response or events. defaults to returning the body.
256+
* @param reportProgress flag to report request and response progress.
257+
*/
258+
259+
private deleteAction(endpoint: string, idUser: string, observe: any = 'body', reportProgress: boolean = false) {
260+
let queryParam = new HttpParams({ encoder: new CustomHttpUrlEncodingCodec() });
261+
262+
if (idUser === null || idUser === undefined) {
263+
throw new Error('Required ID User parameter');
264+
} else {
265+
queryParam = queryParam.set('userID', <any>idUser);
266+
}
267+
268+
return this.commonConf(endpoint, queryParam, observe, reportProgress);
269+
}
270+
271+
207272
private get<T>(endpoint: string, componentType?: string) {
208273

209274
let queryParameters = new HttpParams({ encoder: new CustomHttpUrlEncodingCodec() });
@@ -301,6 +366,31 @@ export class ApiService {
301366
return this.commonConf(endpoint, queryParam, observe, reportProgress);
302367
}
303368

369+
public getUsers(observe: any = 'body', reportProgress: boolean = false): Observable<Array<User>> {
370+
return this.getList(USERS);
371+
}
372+
373+
private getList<T>(endpoint: string) {
374+
375+
let headers = this.defaultHeaders;
376+
377+
// to determine the Accept header
378+
const httpHeaderAccepts: string[] = [
379+
'application/json'
380+
];
381+
const httpHeaderAcceptSelected: string | undefined = this.configuration.selectHeaderAccept(httpHeaderAccepts);
382+
if (httpHeaderAcceptSelected !== undefined) {
383+
headers = headers.set('Accept', httpHeaderAcceptSelected);
384+
}
385+
386+
return this.httpClient.get<T>(`${this.basePath}${endpoint}`,
387+
{
388+
withCredentials: this.configuration.withCredentials,
389+
headers: headers
390+
}
391+
);
392+
}
393+
304394

305395
private commonConf(endpoint: string, queryParameters: HttpParams, observe: any = 'body', reportProgress: boolean = false) {
306396
let headers = this.defaultHeaders;

client/src/app/api/variables.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,17 @@ export const STOP_INSTANCE = 'api/stopInstance';
2929
export const PAUSE_INSTANCE = 'api/pauseInstance';
3030
export const RESUME_INSTANCE = 'api/resumeInstance';
3131
export const DELETE_INSTANCE = 'api/deleteInstance';
32+
export const USERS = '/api/users';
33+
export const NEW_USER = '/api/postUser';
3234
export const RECONNECT = 'api/reconnectInstance';
3335
export const AUTH = 'api/authenticate';
3436
export const NEW_LABEL_INSTANCE = 'api/labelInstance';
37+
export const DELETE_USER = 'api/deleteUser';
3538
export const COLLECTION_FORMATS = {
3639
'csv': ',',
3740
'tsv': ' ',
3841
'ssv': ' ',
3942
'pipes': '|'
4043
};
44+
45+

client/src/app/dashboard/dashboard-overview/dashboard-overview.component.spec.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import { RouterModule } from '@angular/router';
2525
import { MaterialModule } from '../../material-module/material.module';
2626
import { InfoCenterComponent} from '../info-center/info-center.component';
2727
import { GraphViewModule} from '../graph-view/graph-view.module';
28+
import { MatSortModule } from '@angular/material';
2829
import { DashboardOverviewComponent } from './dashboard-overview.component';
2930
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
3031

@@ -36,7 +37,7 @@ describe('DashboardOverviewComponent', () => {
3637
beforeEach(async(() => {
3738
TestBed.configureTestingModule({
3839
declarations: [ DashboardOverviewComponent, DashboardCardComponent, StatusCardComponent, InfoCenterComponent],
39-
imports: [RouterModule, HttpClientModule, RouterTestingModule, MaterialModule, GraphViewModule, NoopAnimationsModule]
40+
imports: [RouterModule, HttpClientModule, RouterTestingModule, MaterialModule, GraphViewModule, MatSortModule, NoopAnimationsModule]
4041
})
4142
.compileComponents();
4243
}));

client/src/app/dashboard/dashboard.component.spec.ts

Lines changed: 0 additions & 55 deletions
This file was deleted.

client/src/app/dashboard/dashboard.module.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ import { TableOverviewComponent } from './table-overview/table-overview.componen
4444
import { InfoCenterComponent } from './info-center/info-center.component';
4545
import {MatTableModule, MatPaginatorModule, MatSortModule, MatIconModule} from '@angular/material';
4646
import { LabelDialogComponent } from './label-dialog/label-dialog.component';
47+
import { UserAddComponent } from './user-add/user-add.component';
48+
import { DeleteUserComponent } from './delete-user/delete-user.component';
4749

4850
@NgModule({
4951
imports: [
@@ -80,10 +82,12 @@ import { LabelDialogComponent } from './label-dialog/label-dialog.component';
8082
InstanceDetailsComponent,
8183
InfoCenterComponent,
8284
TableOverviewComponent,
83-
LabelDialogComponent
85+
LabelDialogComponent,
86+
UserAddComponent,
87+
DeleteUserComponent
8488
],
8589
entryComponents: [
86-
DeleteDialogComponent, AddDialogComponent, LabelDialogComponent
90+
DeleteDialogComponent, AddDialogComponent, LabelDialogComponent, UserAddComponent, DeleteUserComponent
8791
],
8892
providers: [],
8993
})

client/src/app/dashboard/delete-dialog/delete-dialog.component.spec.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ import { MatIconModule } from '@angular/material/icon';
99
import { MatFormFieldModule } from '@angular/material/form-field';
1010
import { MatDialogModule } from '@angular/material/dialog';
1111
import { ApiService } from '../../api/api/api.service';
12-
1312
import { DeleteDialogComponent } from './delete-dialog.component';
1413

1514
describe('DeleteDialogComponent', () => {

client/src/app/dashboard/delete-user/delete-user.component.css

Whitespace-only changes.

0 commit comments

Comments
 (0)