Commit 5af11df5 authored by Mathieu's avatar Mathieu
Browse files

Create separate admin js file and panel. Test admin role on connection

parent 2abd0747
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0">
<!--
This listener loads a class in the default package called ScalatraBootstrap.
That class should implement org.scalatra.LifeCycle. Your app can be
configured in Scala code there.
-->
<listener>
<listener-class>org.scalatra.servlet.ScalatraListener</listener-class>
</listener>
</web-app>
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
<svg xmlns="http://www.w3.org/2000/svg">
<metadata>Generated by IcoMoon</metadata>
<defs>
<font id="icomoon" horiz-adv-x="1024">
<font-face units-per-em="1024" ascent="960" descent="-64" />
<missing-glyph horiz-adv-x="1024" />
<glyph unicode="&#x20;" horiz-adv-x="512" d="" />
<glyph unicode="&#xe600;" glyph-name="book" d="M896 832v-832h-672c-53.026 0-96 42.98-96 96s42.974 96 96 96h608v768h-640c-70.398 0-128-57.6-128-128v-768c0-70.4 57.602-128 128-128h768v896h-64zM224.056 128v0c-0.018-0.002-0.038 0-0.056 0-17.672 0-32-14.326-32-32s14.328-32 32-32c0.018 0 0.038 0.002 0.056 0.002v-0.002h607.89v64h-607.89z" />
<glyph unicode="&#xe601;" glyph-name="power-cord" d="M1024 677.5l-90.506 90.5-178.746-178.752-101.5 101.502 178.75 178.75-90.5 90.5-178.75-178.75-114.748 114.75-86.626-86.624 512.002-512 86.624 86.622-114.752 114.752 178.752 178.75zM794.040 286.21l-443.824 443.824c-95.818-114.904-204.52-292.454-129.396-445.216l-132.248-132.248c-31.112-31.114-31.112-82.024 0-113.136l14.858-14.858c31.114-31.114 82.026-31.114 113.138 0l132.246 132.244c152.764-75.132 330.318 33.566 445.226 129.39z" />
<glyph unicode="&#xe900;" glyph-name="database" d="M512 960c-282.77 0-512-71.634-512-160v-128c0-88.366 229.23-160 512-160s512 71.634 512 160v128c0 88.366-229.23 160-512 160zM512 416c-282.77 0-512 71.634-512 160v-192c0-88.366 229.23-160 512-160s512 71.634 512 160v192c0-88.366-229.23-160-512-160zM512 128c-282.77 0-512 71.634-512 160v-192c0-88.366 229.23-160 512-160s512 71.634 512 160v192c0-88.366-229.23-160-512-160z" />
</font></defs></svg>
\ No newline at end of file
<svg xmlns="http://www.w3.org/2000/svg" width="505" height="142.6" viewBox="0 0 505 142.6">
<g fill="#403D56">
<path d="M100 92.6c-13.2 0-24.5-11.3-24.5-24.5S86.8 43.6 100 43.6s24.5 11.3 24.5 24.5c0 13.1-11.4 24.5-24.5 24.5zm0-38.6c-7.4 0-14 6.7-14 14 0 7.4 6.7 14.1 14 14.1 7.4 0 14-6.7 14-14.1 0-7.3-6.7-14-14-14zM130.6 109.4V61h10.5v3.8c2.7-3.4 6.6-4.5 10.6-4.5 8.8 0 15.3 7.6 15.3 16.2s-6.6 16.1-15.3 16.1c-4 0-8.5-1.3-10.6-4.4v21.2h-10.5zm17.9-25.2c4.2 0 7.4-3.6 7.4-7.7s-3.2-7.7-7.4-7.7-7.4 3.6-7.4 7.7 3.2 7.7 7.4 7.7zM206 77.7h-23.9c0 3.6 2.5 7.4 6.7 7.4 3.7 0 6-2.5 6.1-4.7h10.7c-1.8 8.1-8.4 12.2-16.6 12.2-10.6 0-18-6.3-18-16.1 0-9.7 7.6-16.2 18-16.2 9.4 0 17.2 5.6 17.2 15.5-.1.6-.2 1.3-.2 1.9zm-10-4.9s-.5-5.7-6.9-5.7c-6.6 0-6.9 5.7-6.9 5.7H196zM243.3 91.9h-10.5V74.4c0-3.6-1.4-5.6-4.7-5.6s-5.9 3.5-5.9 7.7v15.4h-10.5V61h10.5v3.8c2.1-2.7 5.4-4.5 9.5-4.5 8.3 0 11.6 5.7 11.6 14.1v17.5z"/>
</g>
<g fill="#A6BF25">
<path d="M299.3 91.9l-5.6-32.8-9.3 32.8h-10.3l-9.3-32.8-5.6 32.8h-11.6l9.2-47.6h12.5l9.9 33.4 9.9-33.4h12.5l9.2 47.6h-11.5zM337.3 92.6c-13.2 0-24.5-11.3-24.5-24.5s11.3-24.5 24.5-24.5 24.5 11.3 24.5 24.5c0 13.1-11.3 24.5-24.5 24.5zm0-38.6c-7.4 0-14 6.7-14 14 0 7.4 6.7 14.1 14 14.1 7.4 0 14-6.7 14-14.1 0-7.3-6.6-14-14-14zM368.2 44.3h10.5v38.1h17.1v9.5h-27.6V44.3zM427.9 91.9h-27.6V44.3h27.6v9.5h-17.1v9.5h16.4v9.5h-16.4v9.6h17.1v9.5z"/>
</g>
</svg>
package org.openmoleconnect.adminclient
import org.scalajs.dom
import scaladget.bootstrapnative.bsn._
import org.scalajs.dom.raw.{Event, HTMLFormElement}
import scalatags.JsDom.all._
import scalatags.JsDom.tags
import scala.concurrent.Future
import scala.scalajs.js.annotation.JSExportTopLevel
object AdminPanel {
@JSExportTopLevel("admin")
def admin() = {
dom.document.body.appendChild(div("Admin").render)
}
}
......@@ -15,7 +15,7 @@ val rosHttpVersion = "2.2.4"
val skuberVersion = "2.2.0"
val httpComponentsVersion = "4.5.9"
val slickVersion = "3.3.1"
val h2Version ="1.4.200"
val h2Version = "1.4.200"
val Resolvers = Seq(Resolver.sonatypeRepo("snapshots"),
"Typesafe repository" at "http://repo.typesafe.com/typesafe/releases/",
......@@ -43,6 +43,16 @@ lazy val client = project.in(file("client")) enablePlugins (ExecNpmPlugin) setti
)
) dependsOn (shared)
lazy val adminclient = project.in(file("adminclient")) enablePlugins (ExecNpmPlugin) settings (defaultSettings) settings(
skip in packageJSDependencies := false,
libraryDependencies ++= Seq(
"com.lihaoyi" %%% "scalatags" % scalatagsVersion,
"fr.iscpif.scaladget" %%% "tools" % scaladgetVersion,
"fr.iscpif.scaladget" %%% "bootstrapnative" % scaladgetVersion,
"org.scala-js" %%% "scalajs-dom" % scalajsDomVersion
)
) dependsOn (shared)
lazy val server = project.in(file("server")) settings (defaultSettings) settings (
libraryDependencies ++= Seq(
"com.lihaoyi" %% "scalatags" % scalatagsVersion,
......@@ -76,19 +86,37 @@ lazy val application = project.in(file("application")) settings (defaultSettings
packageName in Docker := "openmole-connect"
)
lazy val bootstrap = project.in(file("target/bootstrap")) settings (defaultSettings) settings (
go := {
val jsBuild = (fullOptJS in client in Compile).value.data
val appTarget = (target in application in Compile).value
def copyToTarget(jsBuild: sbt.File,
appTarget: sbt.File,
clientResources: sbt.File,
dependencyJS: sbt.File,
depsCSS: sbt.File,
targetName: String) = {
IO.copyFile(jsBuild, appTarget / s"webapp/js/${targetName}.js")
IO.copyFile(dependencyJS, appTarget / "webapp/js/${targetName}-deps.js")
IO.copyDirectory(depsCSS, appTarget / "webapp/css")
IO.copyDirectory(clientResources, appTarget)
}
val appTarget = (target in application in Compile).value
val jsBuild = (fullOptJS in client in Compile).value.data
val clientResources = (resourceDirectory in client in Compile).value
val dependencyJS = (dependencyFile in client in Compile).value
val depsCSS = (cssFile in client in Compile).value
copyToTarget(jsBuild, appTarget, clientResources, dependencyJS, depsCSS, "connect")
val jsBuildAdmin = (fullOptJS in adminclient in Compile).value.data
val clientResourcesAdmin = (resourceDirectory in adminclient in Compile).value
val dependencyJSAdmin = (dependencyFile in adminclient in Compile).value
val depsCSSAdmin = (cssFile in adminclient in Compile).value
copyToTarget(jsBuildAdmin, appTarget, clientResourcesAdmin, dependencyJSAdmin, depsCSSAdmin, "admin")
IO.copyFile(jsBuild, appTarget / "webapp/js/connect.js")
IO.copyFile(dependencyJS, appTarget / "webapp/js/connect-deps.js")
IO.copyDirectory(depsCSS, appTarget / "webapp/css")
IO.copyDirectory(clientResources, appTarget)
}) dependsOn(client, server)
package org.openmoleconnect.client
object AdminPanel {
}
package org.openmoleconnect.client
//import java.nio.ByteBuffer
//import boopickle.Default.{Pickle, Pickler, Unpickle}
//import fr.hmil.roshttp.body.URLEncodedBody
//import fr.hmil.roshttp.util.HeaderMap
import org.scalajs.dom
import scaladget.bootstrapnative.bsn._
import org.scalajs.dom.raw.{Event, HTMLFormElement}
import org.scalajs.dom.raw._
import scalatags.JsDom.all._
import scalatags.JsDom.tags
import scala.concurrent.Future
import scala.scalajs.js.annotation.JSExportTopLevel
//import scala.concurrent.ExecutionContext.Implicits.global
//import scala.scalajs.js.typedarray.{ArrayBuffer, TypedArrayBuffer}
//import boopickle.Default._
//import fr.hmil.roshttp.HttpRequest
//import monix.execution.Scheduler.Implicits.global
//import scala.util.{Failure, Success}
//import fr.hmil.roshttp.response.SimpleHttpResponse
import scala.collection.mutable
import shared.Data._
......
......@@ -46,7 +46,7 @@ class ConnectServlet(arguments: ConnectServer.ServletArguments) extends Scalatra
buildAndAddCookieToHeader(tokenData)
action(tokenData)
}
case false => connectionHtml
case false => Ok(connectionHtml)
}
}
}
......@@ -54,16 +54,21 @@ class ConnectServlet(arguments: ConnectServer.ServletArguments) extends Scalatra
def withRefreshToken(action: TokenData => ActionResult): Serializable = {
Authentication.tokenData(request, TokenType.refreshToken) match {
case Some(tokenData: TokenData) => action(tokenData)
case None => connectionHtml
case None => Ok(connectionHtml)
}
}
def connectionAppRedirection = {
withAccesToken { tokenData =>
tokenData.host.hostIP.map { hip =>
getFromHip(hip)
Ok()
}.getOrElse(NotFound())
if (DBQueries.isAdmin(tokenData.email)) {
Ok(adminHtml)
}
else {
tokenData.host.hostIP.map { hip =>
getFromHip(hip)
Ok()
}.getOrElse(NotFound())
}
}
}
......@@ -123,7 +128,7 @@ class ConnectServlet(arguments: ConnectServer.ServletArguments) extends Scalatra
// Get login and password from the post request parameters
val password = params.getOrElse("password", "")
if (email.isEmpty || password.isEmpty) connectionHtml
if (email.isEmpty || password.isEmpty) Ok(connectionHtml)
//Build cookie with JWT token if login/password are valid and redirect to the openmole manager url
else {
......@@ -133,7 +138,7 @@ class ConnectServlet(arguments: ConnectServer.ServletArguments) extends Scalatra
buildAndAddCookieToHeader(TokenData.accessToken(host, DB.Email(email)))
buildAndAddCookieToHeader(TokenData.refreshToken(host, DB.Email(email)))
redirect("/")
case _ => connectionHtml
case _ => Ok(connectionHtml)
}
}
case true =>
......@@ -153,7 +158,7 @@ class ConnectServlet(arguments: ConnectServer.ServletArguments) extends Scalatra
}
private def deleteCookie(tokenData: TokenData) = {
response.addHeader("Set-Cookie", s"${tokenData.tokenType.cookieKey}=;Expires=${dateFormat.format(0L)}")
response.addHeader("Set-Cookie", s"${tokenData.tokenType.cookieKey}=;Expires=${dateFormat.format(0L)}")
}
private def getResource(path: String, requestContentType: String) = {
......@@ -206,7 +211,7 @@ class ConnectServlet(arguments: ConnectServer.ServletArguments) extends Scalatra
get("/logout") {
withAccesToken { accessTokenData =>
withRefreshToken {refreshTokenData =>
withRefreshToken { refreshTokenData =>
deleteCookie(refreshTokenData)
deleteCookie(accessTokenData)
redirect("/")
......@@ -215,17 +220,21 @@ class ConnectServlet(arguments: ConnectServer.ServletArguments) extends Scalatra
}
}
def connectionHtml = {
def connectionHtml = someHtml("connect", "connection();")
def adminHtml = someHtml("admin", "admin();")
def someHtml(jsFileName: String, jsCall: String) = {
contentType = "text/html"
tags.html(
tags.head(
tags.meta(tags.httpEquiv := "Content-Type", tags.content := "text/html; charset=UTF-8"),
tags.link(tags.rel := "stylesheet", tags.`type` := "text/css", href := "css/deps.css"),
Seq("connect-deps.js", "connect.js").map {
Seq(s"${jsFileName}-deps.js", s"${jsFileName}.js").map {
jf => tags.script(tags.`type` := "text/javascript", tags.src := s"js/$jf ")
}
),
tags.body(tags.onload := "connection();")
tags.body(tags.onload := jsCall)
)
}
......
......@@ -77,26 +77,8 @@ object DB {
}
}
type UserQuery = Query[Users, (UUID, Email, Password, Role), Seq]
def runQuery(query: UserQuery) =
Await.result(
db.run(
query.result
), Duration.Inf
).map { case (u, e, p, r) => User(e, p, r, u) }
def exists(email: Email) = {
runQuery(
for {
u <- userTable if (u.email === email)
} yield (u)
).length != 0
}
def addUser(email: Email, password: Password, role: Role = simpleUser) = {
if (!exists(email)) {
if (!DBQueries.exists(email)) {
runTransaction(
userTable += (UUID(util.UUID.randomUUID().toString), email, password, role)
)
......
package org.openmoleconnect.server
import org.openmoleconnect.server.DB._
import slick.lifted.Query
import slick.jdbc.H2Profile.api._
import scala.concurrent.Await
import scala.concurrent.duration.Duration
import scala.concurrent.ExecutionContext.Implicits.global
object DBQueries {
type UserQuery = Query[Users, (UUID, Email, Password, Role), Seq]
def runQuery(query: UserQuery) =
Await.result(
db.run(
query.result
), Duration.Inf
).map { case (u, e, p, r) => User(e, p, r, u) }
def exists(email: Email) = get(email).isDefined
def isAdmin(email: Email) = get(email).map{_.role} == Some(DB.admin)
def get(email: Email) = {
runQuery(
for {
u <- userTable if (u.email === email)
} yield (u)
).headOption
}
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment