Skip to content

Commit 628f83e

Browse files
authored
Merge pull request #109 from delphi-hub/feature/Authorization
WIP: Authorization of Delphi Management at Instance Registry
2 parents 70a0e93 + 2ed6a60 commit 628f83e

File tree

5 files changed

+124
-82
lines changed

5 files changed

+124
-82
lines changed

app/authorization/AuthProvider.scala

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
// Copyright (C) 2018 The Delphi Team.
2+
// See the LICENCE file distributed with this work for additional
3+
// information regarding copyright ownership.
4+
//
5+
// Licensed under the Apache License, Version 2.0 (the "License");
6+
// you may not use this file except in compliance with the License.
7+
// You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing, software
12+
// distributed under the License is distributed on an "AS IS" BASIS,
13+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
// See the License for the specific language governing permissions and
15+
// limitations under the License.
16+
package authorization
17+
18+
19+
import pdi.jwt.{Jwt, JwtAlgorithm, JwtClaim}
20+
import play.api.Configuration
21+
22+
object AuthProvider {
23+
24+
var Token = "" // scalastyle:ignore
25+
26+
/** This method generates JWT token for registering Delphi-Management at the Instance-Registry
27+
*
28+
* @param validFor
29+
* @return
30+
*/
31+
32+
def generateJwt(validFor: Long = 1)(implicit configuration: Configuration): String = {
33+
val jwtSecretKey = configuration.get[String]("play.http.secret.JWTkey")
34+
if (Token == "" || !Jwt.isValid(Token, jwtSecretKey, Seq(JwtAlgorithm.HS256))) {
35+
val claim = JwtClaim()
36+
.issuedNow
37+
.expiresIn(validFor * 300)
38+
.startsNow
39+
. +("user_id", configuration.get[String]("play.http.instance"))
40+
. +("user_type", "Admin")
41+
42+
Token = Jwt.encode(claim, jwtSecretKey, JwtAlgorithm.HS256)
43+
}
44+
Token
45+
}
46+
}

app/controllers/InstanceRegistryController.scala

Lines changed: 51 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,15 @@ import akka.actor.{ActorRef, ActorSystem}
2222
import javax.inject.Inject
2323
import play.api.{Configuration, Logger}
2424
import play.api.libs.concurrent.CustomExecutionContext
25-
import play.api.libs.json._
2625
import play.api.libs.ws.WSClient
2726
import akka.stream.Materializer
2827
import play.api.libs.streams.ActorFlow
2928
import actors.{ClientSocketActor, PublishSocketMessageActor}
3029
import play.api.mvc._
31-
3230
import scala.concurrent.ExecutionContext
31+
import authorization.AuthProvider
32+
import play.api.libs.json.Json
33+
3334

3435

3536
trait MyExecutionContext extends ExecutionContext
@@ -63,9 +64,15 @@ class InstanceRegistryController @Inject()(implicit system: ActorSystem, mat: Ma
6364
val instanceRegistryUri = config.get[String]("app.instanceRegistryUri")
6465
val instanceRegistryBasePath = config.get[String]("app.instanceRegistryBasePath")
6566

67+
/**This method maps list of instances with specific componentType.
68+
*
69+
* @param componentType
70+
* @return
71+
*/
6672
def instances(componentType: String): Action[AnyContent] = Action.async {
67-
68-
ws.url(instanceRegistryUri + "/instances").addQueryStringParameters("ComponentType" -> componentType).get().map { response =>
73+
ws.url(instanceRegistryUri).addQueryStringParameters("ComponentType" -> componentType)
74+
.withHttpHeaders(("Authorization", s"Bearer ${AuthProvider.generateJwt()}"))
75+
.get().map { response =>
6976
// TODO: possible handling of parsing the data can be done here
7077

7178
Ok(response.body)
@@ -80,8 +87,15 @@ class InstanceRegistryController @Inject()(implicit system: ActorSystem, mat: Ma
8087
}
8188
}
8289

90+
/**Called to fetch network graph of current registry. Contains a list of all instances and all links
91+
* currently registered.
92+
*
93+
* @return
94+
*/
95+
8396
def getNetwork(): Action[AnyContent] = Action.async {
84-
ws.url(instanceRegistryUri + "/network").get().map { response =>
97+
ws.url(instanceRegistryUri + "/instances/network").withHttpHeaders(("Authorization", s"Bearer ${AuthProvider.generateJwt()}"))
98+
.get().map { response =>
8599
// TODO: possible handling of parsing the data can be done here
86100
Logger.debug(response.body)
87101
if (response.status == 200) {
@@ -92,10 +106,20 @@ class InstanceRegistryController @Inject()(implicit system: ActorSystem, mat: Ma
92106
}(myExecutionContext)
93107
}
94108

95-
def numberOfInstances(componentType: String) : Action[AnyContent] = Action.async {
109+
/**
110+
* Fetches the number of instances for the specified ComponentType. The ComponentType is an optional parameter which is passed as an query
111+
* argument named 'ComponentType'
112+
*
113+
* @param componentType
114+
* @return
115+
*/
116+
117+
def numberOfInstances(componentType: String): Action[AnyContent] = Action.async {
96118
// TODO: handle what should happen if the instance registry is not reachable.
97119
// TODO: create constants for the urls
98-
ws.url(instanceRegistryUri + "/numberOfInstances").addQueryStringParameters("ComponentType" -> componentType).get().map { response =>
120+
ws.url(instanceRegistryUri + "/count").addQueryStringParameters("ComponentType" -> componentType)
121+
.withHttpHeaders(("Authorization", s"Bearer ${AuthProvider.generateJwt()}"))
122+
.get().map { response =>
99123
// TODO: possible handling of parsing the data can be done here
100124
if (response.status == 200) {
101125
Ok(response.body)
@@ -106,31 +130,36 @@ class InstanceRegistryController @Inject()(implicit system: ActorSystem, mat: Ma
106130
}
107131

108132
/**
109-
* This function is for handling all(start, stop, play, pause, resume) POST request.
110-
* To control the instance State
111-
* @param componentId
112-
*/
133+
* This function is for handling all(start, stop, play, pause, resume) POST request.
134+
* To control the instance State (E.g. /instances/42/stop )
135+
*
136+
* @param componentId
137+
*/
113138

114139

115140
def handleRequest(action: String, instanceID: String): Action[AnyContent] = Action.async { request =>
116-
ws.url(instanceRegistryUri + action)
117-
.addQueryStringParameters("Id" -> instanceID)
141+
ws.url(instanceRegistryUri + "/instances/" + instanceID + action)
142+
.withHttpHeaders(("Authorization", s"Bearer ${AuthProvider.generateJwt()}"))
118143
.post("")
119144
.map { response =>
120145
new Status(response.status)
121146
}(myExecutionContext)
122147
}
123148

124149
/**
125-
* This function is for handling an POST request for adding an instance to the Scala web server
126-
*
127-
* @param componentType
128-
* @param name
129-
*/
130-
def postInstance(compType: String, name: String): Action[AnyContent] = Action.async { request =>
131-
ws.url(instanceRegistryUri + "/deploy")
132-
.addQueryStringParameters("ComponentType" -> compType, "InstanceName" -> name)
133-
.post("")
150+
* This function is for handling an POST request for adding an instance to the Scala web server
151+
* (E.g. .../instances/deploy
152+
*
153+
* @param componentType
154+
* @param name
155+
*/
156+
157+
def postInstance(compType: String, name: String): Action[AnyContent] = Action.async
158+
{
159+
request =>
160+
ws.url(instanceRegistryUri + "/instances/deploy")
161+
.withHttpHeaders(("Authorization", s"Bearer ${AuthProvider.generateJwt()}"))
162+
.post(Json.obj("ComponentType" -> compType, "InstanceName" -> name))
134163
.map { response =>
135164
response.status match {
136165
// scalastyle:off magic.number
@@ -142,5 +171,4 @@ class InstanceRegistryController @Inject()(implicit system: ActorSystem, mat: Ma
142171
}
143172
}(myExecutionContext)
144173
}
145-
146174
}

build.sbt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,3 +60,5 @@ libraryDependencies ++= Seq(
6060
"com.google.guava" % "guava" % "25.1-jre",
6161
"org.apache.commons" % "commons-compress" % "1.16"
6262
)
63+
64+
libraryDependencies += "com.pauldijou" %% "jwt-core" % "1.0.0"

0 commit comments

Comments
 (0)