Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

[RJA-1469] [feature] - Servers links #796

Merged
merged 2 commits into from

3 participants

@rsvato
Collaborator

No description provided.

@ddurnev ddurnev commented on the diff
...scala/com/griddynamics/genesis/rest/links/Links.scala
@@ -9,10 +9,23 @@ import com.griddynamics.genesis.rest.annotations.LinkTarget
import com.griddynamics.genesis.api.Link
case class WebPath(start: String, elements: List[String] = List()) {
- def / (path: String) = WebPath(start, elements ++ (path :: Nil))
+ def / (p: Any) = {
+ val path: String = p match {
+ case p: String => p
+ case a: Some[_] => String.valueOf(a.get)
@ddurnev
ddurnev added a note

case Some(a) => String.valueOf(a)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@bugzmanov bugzmanov merged commit 9a75c4c into griddynamics:fb-remoting
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
This page is out of date. Refresh to see the latest.
View
5 api/src/main/scala/com/griddynamics/genesis/api/Model.scala
@@ -139,6 +139,9 @@ sealed abstract class ExtendedResult[+S]() extends Product with Serializable {
def get: S
+ final def getOrElse[B >: S](default: => B): B =
+ if (isSuccess) this.get else default
+
def isSuccess: Boolean
}
@@ -329,4 +332,4 @@ case class SystemSettings(links: Array[Link])
case class ApplicationRole(name: String)
-case class ConfigurationAccess(users: Array[User], groups: Array[String])
+case class Access(users: Array[User], groups: Array[String])
View
6 frontend/src/main/java/com/griddynamics/genesis/rest/annotations/LinkTo.java
@@ -12,8 +12,8 @@
public @interface LinkTo {
LinkTarget rel() default LinkTarget.SELF;
RequestMethod[] methods() default {RequestMethod.GET};
- Class<?> controller();
- String controllerMethod() default "";
- Class<?> clazz();
+ Class<?> controller() default Void.class;
+ String path() default "";
+ Class<?> modelClass();
}
View
8 frontend/src/main/scala/com/griddynamics/genesis/rest/ConfigurationController.scala
@@ -80,7 +80,7 @@ class ConfigurationController extends RestApiExceptionsHandler{
def get(@PathVariable("projectId") projectId: Int, @PathVariable("id") id: Int, request: HttpServletRequest): ItemWrapper[Configuration] = {
val item: ItemWrapper[Configuration] =
configRepository.get(projectId, id).getOrElse(throw new ResourceNotFoundException("Can not find environment configuration id = %d".format(id)))
- item.withLinks(LinkBuilder(WebPath(request) / "access", LinkTarget.COLLECTION, classOf[ConfigurationAccess], GET, PUT)).filtered()
+ item.withLinks(LinkBuilder(WebPath(request) / "access", LinkTarget.COLLECTION, classOf[Access], GET, PUT)).filtered()
}
@ResponseBody
@@ -126,12 +126,12 @@ class ConfigurationController extends RestApiExceptionsHandler{
@RequestMapping(value = Array("{configId}/access"), method = Array(RequestMethod.GET))
@ResponseBody
- @AddSelfLinks(methods = Array(GET, PUT), modelClass = classOf[ConfigurationAccess])
+ @AddSelfLinks(methods = Array(GET, PUT), modelClass = classOf[Access])
def getEnvAccess(@PathVariable("projectId") projectId: Int,
@PathVariable("configId") configId: Int,
- request: HttpServletRequest): ItemWrapper[ConfigurationAccess] = {
+ request: HttpServletRequest): ItemWrapper[Access] = {
val (users, groups) = envAuthService.getConfigAccessGrantees(configId)
- ConfigurationAccess(Users.of(userService).forUsernames(users).toArray, groups.toArray)
+ Access(Users.of(userService).forUsernames(users).toArray, groups.toArray)
}
@RequestMapping(value = Array("{configId}/access"), method = Array(RequestMethod.PUT))
View
2  frontend/src/main/scala/com/griddynamics/genesis/rest/CredentialsController.scala
@@ -79,7 +79,7 @@ class CredentialsController extends RestApiExceptionsHandler {
@RequestMapping(value = Array("{id}"), method = Array(RequestMethod.GET))
@ResponseBody
- @AddSelfLinks(methods = Array(GET, PUT), modelClass = classOf[Credentials])
+ @AddSelfLinks(methods = Array(GET, PUT, DELETE), modelClass = classOf[Credentials])
def getCredentials(@PathVariable("projectId") projectId: Int, @PathVariable("id") credId: Int, request: HttpServletRequest): ItemWrapper[Credentials] = {
val cred = service.get(projectId, credId).getOrElse(
throw new ResourceNotFoundException("Credential [id = %d] was not found in Project [id = %d]".format(credId, projectId))
View
2  frontend/src/main/scala/com/griddynamics/genesis/rest/EnvironmentsController.scala
@@ -214,7 +214,7 @@ class EnvironmentsController extends RestApiExceptionsHandler {
implicit val req: HttpServletRequest = request
val wrapped = environments.map(environment =>
wrap(environment).withLinks(LinkBuilder(HrefBuilder.withPathParam(request, environment.id),
- SELF, classOf[Environment], GET))
+ SELF, classOf[Environment], GET)).filtered()
)
wrapCollection(wrapped).withLinks(LinkBuilder(request,
View
16 frontend/src/main/scala/com/griddynamics/genesis/rest/ProjectsController.scala
@@ -1,6 +1,6 @@
package com.griddynamics.genesis.rest
-import annotations.{LinkTarget, LinkTo, LinksTo}
+import annotations.{AddSelfLinks, LinkTarget}
import LinkTarget._
import javax.servlet.http.{HttpServletResponse, HttpServletRequest}
import com.griddynamics.genesis.rest.GenesisRestController._
@@ -67,7 +67,7 @@ class ProjectsController extends RestApiExceptionsHandler {
@RequestMapping(method = Array(RequestMethod.GET))
@ResponseBody
- @LinksTo(value = Array(new LinkTo(methods = Array(RequestMethod.POST), clazz = classOf[Project], controller = classOf[ProjectsController])))
+ @AddSelfLinks(methods = Array(GET, POST), modelClass = classOf[Project])
def listProjects(@RequestParam(value = "sorting", required = false, defaultValue = "name") sorting: Ordering,
request: HttpServletRequest): CollectionWrapper[ItemWrapper[_]] = {
val projects = if (request.isUserInRole(GenesisRole.SystemAdmin.toString) || request.isUserInRole(GenesisRole.ReadonlySystemAdmin.toString)) {
@@ -205,16 +205,16 @@ class ProjectsController extends RestApiExceptionsHandler {
@RequestMapping(value = Array("{projectId}/roles/{roleName}"), method = Array(RequestMethod.GET))
@ResponseBody
+ @AddSelfLinks(methods = Array(GET, PUT), modelClass = classOf[Access])
def loadProjectAuths(@PathVariable("projectId") projectId: Int,
@PathVariable("roleName") roleName: String,
request: HttpServletRequest,
- response: HttpServletResponse): ExtendedResult[Map[String, Any]] = {
- authorityService.getProjectAuthority(projectId, GenesisRole.withName(roleName)).map{ case (users, groups) =>
- Map(
- "users" -> Users.of(userService).forUsernames(users),
- "groups" -> groups
- )
+ response: HttpServletResponse): ItemWrapper[Access] = {
+ val result: ExtendedResult[Access] = authorityService.getProjectAuthority(projectId, GenesisRole.withName(roleName)).map {
+ case (users, groups) =>
+ Access(Users.of(userService).forUsernames(users).toArray, groups.toArray)
}
+ result.getOrElse(throw new ResourceNotFoundException(s"Cannot find access map for role ${roleName}"))
}
@RequestMapping(value = Array("{projectId}/permissions"), method = Array(RequestMethod.GET))
View
22 frontend/src/main/scala/com/griddynamics/genesis/rest/ServersController.scala
@@ -22,7 +22,7 @@
*/
package com.griddynamics.genesis.rest
-import annotations.{AddSelfLinks, LinkTarget}
+import annotations.{LinkTo, LinksTo, AddSelfLinks, LinkTarget}
import links.CollectionWrapper._
import links.{CollectionWrapper, ItemWrapper, WebPath, LinkBuilder}
import links.HrefBuilder._
@@ -33,7 +33,7 @@ import javax.servlet.http.HttpServletRequest
import com.griddynamics.genesis.service.{CredentialsStoreService, ServersLoanService, ServersService}
import com.griddynamics.genesis.rest.GenesisRestController._
import com.griddynamics.genesis.api
-import api.{ServerArray, ServerDescription, ExtendedResult}
+import api.{Server, ServerArray, ServerDescription, ExtendedResult}
import org.springframework.beans.factory.annotation.Autowired
import javax.validation.Valid
import com.griddynamics.genesis.spring.security.LinkSecurityBean
@@ -58,16 +58,15 @@ class ServersController extends RestApiExceptionsHandler {
@AddSelfLinks(methods = Array(GET, POST), modelClass = classOf[ServerArray])
def list(@PathVariable("projectId") projectId: Int, request: HttpServletRequest) : CollectionWrapper[ItemWrapper[ServerArray]] = {
implicit val req = request
- def wrapServer(server: ServerArray) = {
- val top = WebPath(request)
- wrap(server).withLinks(LinkBuilder(top / server.id.get.toString, LinkTarget.SELF, server.getClass, PUT, DELETE, GET)).filtered()
+ wrap(service.list(projectId)) { serverArray =>
+ wrap(serverArray).withLinksToSelf(WebPath(request) / serverArray.id, PUT, DELETE, GET)
}
- wrapCollection(service.list(projectId).map(wrapServer(_)))
}
@RequestMapping(value = Array("{id}"), method = Array(RequestMethod.GET))
@ResponseBody
@AddSelfLinks(methods = Array(GET, PUT, DELETE), modelClass = classOf[ServerArray])
+ @LinksTo(value = Array(new LinkTo(path = "servers", methods = Array(GET, POST), modelClass = classOf[Server])))
def get(@PathVariable("projectId") projectId: Int, @PathVariable("id") id: Int, request: HttpServletRequest) : ItemWrapper[ServerArray] = {
find(projectId, id)
}
@@ -102,10 +101,12 @@ class ServersController extends RestApiExceptionsHandler {
@RequestMapping(value = Array("{arrayId}/servers"), method = Array(RequestMethod.GET))
@ResponseBody
- def getServersInArray(@PathVariable("projectId") projectId: Int, @PathVariable("arrayId") arrayId: Int): Seq[api.Server] = {
+ @AddSelfLinks(methods = Array(GET, POST), modelClass = classOf[Server])
+ def getServersInArray(@PathVariable("projectId") projectId: Int, @PathVariable("arrayId") arrayId: Int, request: HttpServletRequest): CollectionWrapper[ItemWrapper[Server]] = {
assertArrayBelongsToProject(projectId, arrayId)
-
- service.getServers(arrayId)
+ wrap(service.getServers(arrayId)) { server => {
+ server.withLinksToSelf(WebPath(request) / server.id, GET, PUT, DELETE)
+ }}
}
@RequestMapping(value = Array("{arrayId}/servers/{serverId}"), method = Array(RequestMethod.DELETE))
@@ -119,10 +120,11 @@ class ServersController extends RestApiExceptionsHandler {
@RequestMapping(value = Array("{arrayId}/servers/{serverId}"), method = Array(RequestMethod.GET))
@ResponseBody
+ @AddSelfLinks(methods = Array(GET, PUT, DELETE), modelClass = classOf[ServerDescription])
def getServerDescription(@PathVariable("projectId") projectId: Int,
@PathVariable("arrayId") arrayId: Int,
@PathVariable("serverId") serverId: Int,
- request: HttpServletRequest): ServerDescription = {
+ request: HttpServletRequest): ItemWrapper[ServerDescription] = {
assertArrayBelongsToProject(projectId, arrayId)
val server = service.getServer(arrayId, serverId).getOrElse(throw new ResourceNotFoundException("Couldn't find server in the array"))
val envs = loanService.debtorEnvironments(server)
View
4 frontend/src/main/scala/com/griddynamics/genesis/rest/links/CollectionWrapper.scala
@@ -26,6 +26,7 @@ case class CollectionWrapper[T](items: Iterable[T], links: Iterable[Link]) exten
case class ItemWrapper[T](item: T, links: Iterable[Link]) extends WithLinks {
override def add(coll: Iterable[Link]) = copy(item = item, links = links ++ coll)
implicit def withLinks(link: Link, rest: Link*) = copy(item = item, links = links ++ (link :: rest.toList))
+ def withLinksToSelf(path: String, methods: RequestMethod*) = withLinks(LinkBuilder(path, LinkTarget.SELF, item.getClass, methods : _*))
override def filtered()(implicit security: LinkSecurityBean) = copy(item = item, links = security.filter(links.toArray))
def withLinksToSelf(method: RequestMethod, methods: RequestMethod*)(implicit request: HttpServletRequest) =
copy(item = item, links = LinkBuilder(request, LinkTarget.SELF, item.getClass, (method :: methods.toList).toArray : _*) :: Nil)
@@ -35,5 +36,8 @@ case class ItemWrapper[T](item: T, links: Iterable[Link]) extends WithLinks {
object CollectionWrapper {
implicit def wrapCollection[T](coll: Iterable[T]) = new CollectionWrapper[T](coll, List())
implicit def wrap[T](item: T) = ItemWrapper[T](item, List())
+ implicit def wrap[T](coll: Iterable[T])(block: (T) => ItemWrapper[T])(implicit security: LinkSecurityBean) : CollectionWrapper[ItemWrapper[T]] = {
+ coll.map(block(_).filtered())
+ }
}
View
17 frontend/src/main/scala/com/griddynamics/genesis/rest/links/Links.scala
@@ -9,10 +9,23 @@ import com.griddynamics.genesis.rest.annotations.LinkTarget
import com.griddynamics.genesis.api.Link
case class WebPath(start: String, elements: List[String] = List()) {
- def / (path: String) = WebPath(start, elements ++ (path :: Nil))
+ def / (p: Any) = {
+ val path: String = p match {
+ case p: String => p
+ case a: Some[_] => String.valueOf(a.get)
@ddurnev
ddurnev added a note

case Some(a) => String.valueOf(a)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
+ case None => ""
+ case x => String.valueOf(x)
+ }
+ WebPath(start, elements ++ (path :: Nil))
+ }
override def toString = (start :: elements).mkString("/")
}
+object WebPath {
+ implicit def webPathToString(path: WebPath) = path.toString
+ implicit def fromRequest(request: HttpServletRequest) = WebPath(request.getServletPath)
+}
+
object LinkBuilder {
def apply(href: String, rel: LinkTarget, methods: RequestMethod*) =
Link(href, rel.toRel, None, (methods.toList).map(_.toString.toLowerCase).toArray)
@@ -35,8 +48,6 @@ object HrefBuilder {
absolutePath(request.getServletPath.stripSuffix("/") + "/" + pathParam.toString)
}
- implicit def webPathToString(path: WebPath) = path.toString
-
private[links] def uriBuilder(implicit request: HttpServletRequest): UriComponentsBuilder = {
request.getHeader(TunnelFilter.FORWARDED_HEADER) match {
View
10 frontend/src/main/scala/com/griddynamics/genesis/spring/aop/LinksToAspect.scala
@@ -3,7 +3,7 @@ package com.griddynamics.genesis.spring.aop
import org.aspectj.lang.annotation._
import org.aspectj.lang.ProceedingJoinPoint
import com.griddynamics.genesis.rest.annotations.{LinkTarget, AddSelfLinks, LinksTo}
-import com.griddynamics.genesis.rest.links.{LinkBuilder, WebPath, ControllerClassAggregator, WithLinks}
+import com.griddynamics.genesis.rest.links._
import com.griddynamics.genesis.rest.links.HrefBuilder._
import javax.servlet.http.HttpServletRequest
import com.griddynamics.genesis.util.Logging
@@ -41,7 +41,13 @@ class LinksToAspect extends Logging {
}
private def processAnnotation(ann: LinksTo)(implicit request: HttpServletRequest): Array[Link] = {
- ann.value().map(a => ControllerClassAggregator(a.controller, a.clazz(), a.rel(), a.methods())).flatten
+ ann.value().map(a => {
+ val links: Array[Link] = a.path() match {
+ case "" => ControllerClassAggregator(a.controller, a.modelClass(), a.rel(), a.methods())
+ case x => Array(LinkBuilder(WebPath(request) / x, a.rel(), a.modelClass(), a.methods(): _*))
+ }
+ links
+ }).flatten
}
private def processAnnotation(ann: AddSelfLinks)(implicit request: HttpServletRequest): Array[Link] = {
View
18 ui/src/main/resources/genesis/app/modules/project_properties/servers.js
@@ -57,7 +57,14 @@ function(genesis, status, validation, Backbone, $) {
this.serverArrayId = options.serverArrayId;
},
- url: function() { return "rest/projects/" + this.projectId + "/server-arrays/" + this.serverArrayId + "/servers"; }
+ url: function() { return "rest/projects/" + this.projectId + "/server-arrays/" + this.serverArrayId + "/servers"; },
+ parse: function(json) {
+ if (json.items) {
+ return json.items;
+ } else {
+ return json;
+ }
+ }
});
var CredentialsRef = Backbone.Collection.extend({
@@ -65,7 +72,14 @@ function(genesis, status, validation, Backbone, $) {
this.projectId = options.projectId;
},
- url: function() { return "rest/projects/" + this.projectId + "/credentials/?type=static" }
+ url: function() { return "rest/projects/" + this.projectId + "/credentials/?type=static" },
+ parse: function(json) {
+ if (json.items) {
+ return json.items;
+ } else {
+ return json;
+ }
+ }
});
Servers.Views.Main = Backbone.View.extend({
Something went wrong with that request. Please try again.