Skip to content

Commit c43af82

Browse files
Merge pull request #143 from delphi-hub/release/1.0.0
Release/1.0.0
2 parents 7896c7a + d2e60a6 commit c43af82

File tree

69 files changed

+2151
-1310
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

69 files changed

+2151
-1310
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/authorization/AuthAction.scala

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,15 @@ import play.api.Configuration
2525
import scala.concurrent.{ExecutionContext, Future}
2626
import scala.util.{Failure, Success}
2727

28+
// The following is based on https://auth0.com/blog/build-and-secure-a-scala-play-framework-api/
2829
// A custom request type to hold our JWT claims, we can pass these on to the
2930
// handling action
30-
//case class UserRequest[A](jwt: JwtClaim, token: String, request: Request[A]) extends WrappedRequest[A](request)
31+
32+
case class UserRequest[A](token: String, request: Request[A]) extends WrappedRequest[A](request)
3133

3234
// Our custom action implementation
3335
class AuthAction @Inject()(bodyParser: BodyParsers.Default)(implicit ec: ExecutionContext, config: Configuration)
34-
extends ActionBuilder[Request, AnyContent] {
36+
extends ActionBuilder[UserRequest, AnyContent] {
3537

3638
override def parser: BodyParser[AnyContent] = bodyParser
3739
override protected def executionContext: ExecutionContext = ec
@@ -41,10 +43,10 @@ class AuthAction @Inject()(bodyParser: BodyParsers.Default)(implicit ec: Executi
4143

4244
// Called when a request is invoked. We should validate the bearer token here
4345
// and allow the request to proceed if it is valid.
44-
override def invokeBlock[A](request: Request[A], block: Request[A] => Future[Result]): Future[Result] =
46+
override def invokeBlock[A](request: Request[A], block: UserRequest[A] => Future[Result]): Future[Result] =
4547
extractBearerToken(request) map { token =>
4648
if(AuthProvider.validateJwt(token)) {
47-
block(request) // token was valid - proceed!
49+
block(UserRequest(token,request)) // token was valid - proceed!
4850
} else {
4951
Future.successful(Results.Unauthorized("Invalid")) // token was invalid - return 401
5052
}

app/authorization/AuthProvider.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ import play.api.Configuration
4040
.expiresIn(validFor * 300)
4141
.startsNow
4242
. +("user_id", configuration.get[String]("play.http.instance"))
43-
. +("user_type", "Admin")
43+
. +("user_type", "Component")
4444

4545
Token = Jwt.encode(claim, jwtSecretKey, JwtAlgorithm.HS256)
4646
}

app/controllers/ApiRouter.scala

Lines changed: 4 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,8 @@ 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)
52+
case POST(p"/deleteLabel" ? q"instanceID=$instanceID"& q"label=$label") => irController.deleteLabel(instanceID, label)
4953
}
5054
}

app/controllers/InstanceRegistryController.scala

Lines changed: 117 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -70,12 +70,13 @@ class InstanceRegistryController @Inject()(implicit system: ActorSystem, mat: Ma
7070
* @return
7171
*/
7272
def instances(componentType: String): Action[AnyContent] = authAction.async {
73-
ws.url(instanceRegistryUri).addQueryStringParameters("ComponentType" -> componentType)
74-
.withHttpHeaders(("Authorization", s"Bearer ${AuthProvider.generateJwt()}"))
75-
.get().map { response =>
76-
// TODO: possible handling of parsing the data can be done here
73+
request =>
74+
ws.url(instanceRegistryUri).addQueryStringParameters("ComponentType" -> componentType)
75+
.withHttpHeaders(("Authorization", s"Bearer ${request.token}"))
76+
.get().map { response =>
77+
// TODO: possible handling of parsing the data can be done here
7778

78-
Ok(response.body)
79+
Ok(response.body)
7980
}(myExecutionContext)
8081
}
8182

@@ -87,22 +88,39 @@ class InstanceRegistryController @Inject()(implicit system: ActorSystem, mat: Ma
8788
}
8889
}
8990

91+
/** This method lists all Users.
92+
* @return
93+
*/
94+
95+
def users(): Action[AnyContent] = authAction.async{
96+
request =>
97+
ws.url(instanceRegistryUri + "/users").withHttpHeaders(("Authorization", s"Bearer ${request.token}"))
98+
.get().map { response =>
99+
if (response.status == 200) {
100+
Ok(response.body)
101+
} else {
102+
new Status(response.status)
103+
}
104+
}(myExecutionContext)
105+
}
106+
90107
/** Called to fetch network graph of current registry. Contains a list of all instances and all links
91108
* currently registered.
92109
*
93110
* @return
94111
*/
95112

96113
def getNetwork(): Action[AnyContent] = authAction.async {
97-
ws.url(instanceRegistryUri + "/instances/network").withHttpHeaders(("Authorization", s"Bearer ${AuthProvider.generateJwt()}"))
98-
.get().map { response =>
99-
// TODO: possible handling of parsing the data can be done here
100-
Logger.debug(response.body)
101-
if (response.status == 200) {
102-
Ok(response.body)
103-
} else {
104-
new Status(response.status)
105-
}
114+
request =>
115+
ws.url(instanceRegistryUri + "/instances/network").withHttpHeaders(("Authorization", s"Bearer ${request.token}"))
116+
.get().map { response =>
117+
// TODO: possible handling of parsing the data can be done here
118+
Logger.debug(response.body)
119+
if (response.status == 200) {
120+
Ok(response.body)
121+
} else {
122+
new Status(response.status)
123+
}
106124
}(myExecutionContext)
107125
}
108126

@@ -117,15 +135,16 @@ class InstanceRegistryController @Inject()(implicit system: ActorSystem, mat: Ma
117135
def numberOfInstances(componentType: String): Action[AnyContent] = authAction.async {
118136
// TODO: handle what should happen if the instance registry is not reachable.
119137
// TODO: create constants for the urls
120-
ws.url(instanceRegistryUri + "/count").addQueryStringParameters("ComponentType" -> componentType)
121-
.withHttpHeaders(("Authorization", s"Bearer ${AuthProvider.generateJwt()}"))
122-
.get().map { response =>
123-
// TODO: possible handling of parsing the data can be done here
124-
if (response.status == 200) {
125-
Ok(response.body)
126-
} else {
127-
new Status(response.status)
128-
}
138+
request =>
139+
ws.url(instanceRegistryUri + "/count").addQueryStringParameters("ComponentType" -> componentType)
140+
.withHttpHeaders(("Authorization", s"Bearer ${request.token}"))
141+
.get().map { response =>
142+
// TODO: possible handling of parsing the data can be done here
143+
if (response.status == 200) {
144+
Ok(response.body)
145+
} else {
146+
new Status(response.status)
147+
}
129148
}(myExecutionContext)
130149
}
131150

@@ -139,7 +158,7 @@ class InstanceRegistryController @Inject()(implicit system: ActorSystem, mat: Ma
139158

140159
def handleRequest(action: String, instanceID: String): Action[AnyContent] = authAction.async { request =>
141160
ws.url(instanceRegistryUri + "/instances/" + instanceID + action)
142-
.withHttpHeaders(("Authorization", s"Bearer ${AuthProvider.generateJwt()}"))
161+
.withHttpHeaders(("Authorization", s"Bearer ${request.token}"))
143162
.post("")
144163
.map { response =>
145164
new Status(response.status)
@@ -157,7 +176,7 @@ class InstanceRegistryController @Inject()(implicit system: ActorSystem, mat: Ma
157176

158177
ws.url(instanceRegistryUri + "/instances/" + from + "/assignInstance"
159178
)
160-
.withHttpHeaders(("Authorization", s"Bearer ${AuthProvider.generateJwt()}"))
179+
.withHttpHeaders(("Authorization", s"Bearer ${request.token}"))
161180
.post(Json.obj("AssignedInstanceId" -> to))
162181
.map { response =>
163182
response.status match {
@@ -180,7 +199,7 @@ class InstanceRegistryController @Inject()(implicit system: ActorSystem, mat: Ma
180199
def postInstance(compType: String, name: String): Action[AnyContent] = authAction.async {
181200
request =>
182201
ws.url(instanceRegistryUri + "/instances/deploy")
183-
.withHttpHeaders(("Authorization", s"Bearer ${AuthProvider.generateJwt()}"))
202+
.withHttpHeaders(("Authorization", s"Bearer ${request.token}"))
184203
.post(Json.obj("ComponentType" -> compType, "InstanceName" -> name))
185204
.map { response =>
186205
response.status match {
@@ -203,8 +222,6 @@ class InstanceRegistryController @Inject()(implicit system: ActorSystem, mat: Ma
203222

204223
def authentication(): Action[AnyContent] = Action.async {
205224
request =>
206-
//val json = request.body.asJson.get
207-
208225

209226
val jsonBody: Option[JsValue] = request.body.asJson
210227

@@ -219,7 +236,7 @@ class InstanceRegistryController @Inject()(implicit system: ActorSystem, mat: Ma
219236
.post("")
220237
.map { response =>
221238
if (response.status == 200) {
222-
Ok(Json.obj("token" -> response.body, "refreshToken" -> ""))
239+
Ok(response.body)
223240
} else {
224241
new Status(response.status)
225242
}
@@ -239,7 +256,7 @@ class InstanceRegistryController @Inject()(implicit system: ActorSystem, mat: Ma
239256
{
240257
request =>
241258
ws.url(instanceRegistryUri + "/instances/" + instanceID + "/label")
242-
.withHttpHeaders(("Authorization", s"Bearer ${AuthProvider.generateJwt()}"))
259+
.withHttpHeaders(("Authorization", s"Bearer ${request.token}"))
243260
.post(Json.obj("Label" -> label))
244261
.map { response =>
245262
response.status match {
@@ -252,4 +269,74 @@ class InstanceRegistryController @Inject()(implicit system: ActorSystem, mat: Ma
252269
}
253270
}(myExecutionContext)
254271
}
272+
273+
/**
274+
* This function is used to add a User.
275+
* Username, Secret and UserType are sent in the body post
276+
* Instance registry returns a valid userID
277+
* @return
278+
*/
279+
280+
def postUser(): Action[AnyContent] = authAction.async {
281+
request =>
282+
val jsonBody: Option[JsValue] = request.body.asJson
283+
jsonBody.map { json =>
284+
val userName = (json \ "userName").as[String]
285+
val secret = (json \ "secret").as[String]
286+
val userType = (json \ "userType").as[String]
287+
ws.url(instanceRegistryUri + "/users" + "/add")
288+
.withHttpHeaders(("Authorization", s"Bearer ${request.token}"))
289+
.post(json)
290+
.map { response =>
291+
if (response.status == 200) {
292+
Ok(response.body)
293+
} else {
294+
Logger.info(s"$ws")
295+
Logger.debug(s"$ws")
296+
new Status(response.status)
297+
}
298+
}
299+
}.getOrElse{ Future(BadRequest("Invalid body"))}
300+
}
301+
302+
/**
303+
* This function is used to delete a user.
304+
* @param userID ID of the user that is to be deleted
305+
* @return
306+
*/
307+
def deleteUser( userID: String): Action[AnyContent] = authAction.async {
308+
request =>
309+
ws.url(instanceRegistryUri + "/users/" + userID + "/remove")
310+
.withHttpHeaders(("Authorization", s"Bearer ${request.token}"))
311+
.post("")
312+
.map { response =>
313+
response.status match {
314+
// scalastyle:off magic.number
315+
case 202 =>
316+
// scalastyle:on magic.number
317+
Ok(Json.obj("msg" -> response.body))
318+
case x: Any =>
319+
new Status(x)
320+
}
321+
}(myExecutionContext)
322+
}
323+
324+
def deleteLabel(instanceID: String, label: String): Action[AnyContent] = authAction.async
325+
{
326+
request =>
327+
ws.url(instanceRegistryUri + "/instances/" + instanceID + "/label/" + label + "/delete")
328+
.withHttpHeaders(("Authorization", s"Bearer ${request.token}"))
329+
.post("")
330+
.map { response =>
331+
response.status match {
332+
// scalastyle:off magic.number
333+
case 202 =>
334+
// scalastyle:on magic.number
335+
Ok(response.body)
336+
case x: Any =>
337+
new Status(x)
338+
}
339+
}(myExecutionContext)
340+
}
255341
}
342+

build.sbt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ name := "delphi-management"
55
organization := "de.upb"
66

77

8-
version := "0.9.5"
8+
version := "1.0.0"
99

1010

1111
scalaVersion := "2.12.4"
@@ -42,7 +42,7 @@ libraryDependencies += "org.scalatestplus.play" %% "scalatestplus-play" % "3.1.2
4242
libraryDependencies += "net.codingwell" %% "scala-guice" % "4.1.1"
4343
libraryDependencies += "com.iheart" %% "ficus" % "1.4.3"
4444
libraryDependencies += "org.webjars" % "bootstrap" % "4.1.0"
45-
libraryDependencies += "org.webjars" %% "webjars-play" % "2.6.3"
45+
libraryDependencies += "org.webjars" %% "webjars-play" % "2.7.0"
4646
libraryDependencies += "com.adrianhurt" %% "play-bootstrap" % "1.4-P26-B4-SNAPSHOT"
4747
libraryDependencies += "eu.bitwalker" % "UserAgentUtils" % "1.20"
4848
libraryDependencies += "com.typesafe.akka" %% "akka-http" % "10.1.5"
@@ -58,7 +58,7 @@ libraryDependencies ++= Seq(
5858
"com.nimbusds" % "nimbus-jose-jwt" % "5.14",
5959
"org.bouncycastle" % "bcprov-jdk15on" % "1.60",
6060
"com.google.guava" % "guava" % "25.1-jre",
61-
"org.apache.commons" % "commons-compress" % "1.16"
61+
"org.apache.commons" % "commons-compress" % "1.18"
6262
)
6363

6464
libraryDependencies += "com.pauldijou" %% "jwt-core" % "1.0.0"

0 commit comments

Comments
 (0)