Skip to content

Commit

Permalink
Merge branch 'release/1.10'
Browse files Browse the repository at this point in the history
  • Loading branch information
To-om committed Mar 18, 2019
2 parents d834de8 + 8afba30 commit aeb5aec
Show file tree
Hide file tree
Showing 7 changed files with 96 additions and 63 deletions.
13 changes: 12 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,18 @@
# Change Log

## [1.9.0](https://github.com/TheHive-Project/elastic4play/tree/1.9.0) (2019-03-07)
## [1.10.0](https://github.com/TheHive-Project/elastic4play/tree/1.10.0)

[Full Changelog](https://github.com/TheHive-Project/elastic4play/compare/1.9.0...1.10.0)

**Implemented enhancements:**

- Add attribute format for large raw data [\#80](https://github.com/TheHive-Project/elastic4play/issues/80)

**Fixed bugs:**

- Numeric field can't be searched with wildcard operator [\#81](https://github.com/TheHive-Project/elastic4play/issues/81)

## [1.9.0](https://github.com/TheHive-Project/elastic4play/tree/1.9.0) (2019-03-07)
[Full Changelog](https://github.com/TheHive-Project/elastic4play/compare/1.8.0...1.9.0)

**Implemented enhancements:**
Expand Down
5 changes: 3 additions & 2 deletions app/org/elastic4play/models/Attributes.scala
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ object AttributeFormat {
val uuidFmt = UUIDAttributeFormat
val hashFmt = HashAttributeFormat
val binaryFmt = BinaryAttributeFormat
val rawFmt = RawAttributeFormat

def enumFmt[T <: Enumeration](e: T)(implicit format: Format[T#Value]): EnumerationAttributeFormat[T] = EnumerationAttributeFormat[T](e)

Expand Down Expand Up @@ -95,8 +96,8 @@ case class Attribute[T](
}

def elasticMapping: FieldDefinition = format.elasticType(attributeName) match {
case a: BasicFieldDefinition if isSensitive a.index("no")
case a a
case a: BasicFieldDefinition if isSensitive && a.`type` == "String" a.index("no")
case a a
}

def elasticTemplate(attributePath: Seq[String] = Nil): Seq[DynamicTemplateDefinition] =
Expand Down
25 changes: 25 additions & 0 deletions app/org/elastic4play/models/RawAttributeFormat.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package org.elastic4play.models

import play.api.libs.json.{ JsString, JsValue }

import com.sksamuel.elastic4s.ElasticDsl.binaryField
import com.sksamuel.elastic4s.mappings.BasicFieldDefinition
import org.scalactic._

import org.elastic4play.controllers.{ InputValue, JsonInputValue }
import org.elastic4play.{ AttributeError, InvalidFormatAttributeError }

class RawAttributeFormat extends AttributeFormat[String]("raw") {
override def checkJson(subNames: Seq[String], value: JsValue): Or[JsValue, One[InvalidFormatAttributeError]] = value match {
case _: JsString if subNames.isEmpty Good(value)
case _ formatError(JsonInputValue(value))
}
override def fromInputValue(subNames: Seq[String], value: InputValue): String Or Every[AttributeError] = TextAttributeFormat.fromInputValue(subNames, value) match {
case Bad(One(ifae: InvalidFormatAttributeError)) Bad(One(ifae.copy(format = name)))
case other other
}

override def elasticType(attributeName: String): BasicFieldDefinition = binaryField(attributeName)
}

object RawAttributeFormat extends RawAttributeFormat
106 changes: 51 additions & 55 deletions app/org/elastic4play/services/JsonFormat.scala
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ object JsonFormat {

implicit val roleWrites: Writes[Role] = Writes[Role](role JsString(role.name))

implicit def configWrites: OWrites[Configuration] = OWrites { (cfg: Configuration)
implicit def configWrites: OWrites[Configuration] = OWrites[Configuration] { cfg
JsObject(cfg.subKeys.map(key key configValueWrites.writes(cfg.underlying.getValue(key))).toSeq)
}

Expand Down Expand Up @@ -139,63 +139,59 @@ object JsonFormat {
}

implicit val queryReads: Reads[QueryDef] = {
Reads { (json: JsValue)
json match {
case JsObjOne(("_and", JsArray(v))) JsSuccess(and(v.map(_.as[QueryDef]): _*))
case JsObjOne(("_or", JsArray(v))) JsSuccess(or(v.map(_.as[QueryDef]): _*))
case JsObjOne(("_contains", JsString(v))) JsSuccess(contains(v))
case JsObjOne(("_not", v: JsObject)) JsSuccess(not(v.as[QueryDef]))
case JsObjOne(("_any", _)) JsSuccess(any)
case j: JsObject if j.fields.isEmpty JsSuccess(any)
case JsObjOne(("_gt", JsObjOne(n, JsVal(v)))) JsSuccess(n ~> v)
case JsObjOne(("_gte", JsObjOne(n, JsVal(v)))) JsSuccess(n ~>= v)
case JsObjOne(("_lt", JsObjOne(n, JsVal(v)))) JsSuccess(n ~< v)
case JsObjOne(("_lte", JsObjOne(n, JsVal(v)))) JsSuccess(n ~<= v)
case JsObjOne(("_between", JsRange(n, f, t))) JsSuccess(n ~<> (f t))
case JsObjOne(("_parent", JsParent(p, q))) JsSuccess(parent(p, q))
case JsObjOne(("_parent", JsParentId(p, i))) JsSuccess(withParent(p, i))
case JsObjOne(("_id", JsString(id))) JsSuccess(withId(id))
case JsField(field, value) JsSuccess(field ~= value)
case JsObjOne(("_child", JsParent(p, q))) JsSuccess(child(p, q))
case JsObjOne(("_string", JsString(s))) JsSuccess(string(s))
case JsObjOne(("_in", JsFieldIn(f, v))) JsSuccess(f in (v: _*))
case JsObjOne(("_type", JsString(v))) JsSuccess(ofType(v))
case JsObjOne(("_like", JsField(field, value))) JsSuccess(field like value)
case JsObjOne(("_strict", JsField(field, value))) JsSuccess(field ~== value)
case JsObjOne((n, JsVal(v)))
if (n.startsWith("_")) logger.warn(s"""Potentially invalid search query : {"$n": "$v"}"""); JsSuccess(n ~= v)
case other JsError(s"Invalid query: unexpected $other")
}
Reads {
case JsObjOne(("_and", JsArray(v))) JsSuccess(and(v.map(_.as[QueryDef]): _*))
case JsObjOne(("_or", JsArray(v))) JsSuccess(or(v.map(_.as[QueryDef]): _*))
case JsObjOne(("_contains", JsString(v))) JsSuccess(contains(v))
case JsObjOne(("_not", v: JsObject)) JsSuccess(not(v.as[QueryDef]))
case JsObjOne(("_any", _)) JsSuccess(any)
case j: JsObject if j.fields.isEmpty JsSuccess(any)
case JsObjOne(("_gt", JsObjOne(n, JsVal(v)))) JsSuccess(n ~> v)
case JsObjOne(("_gte", JsObjOne(n, JsVal(v)))) JsSuccess(n ~>= v)
case JsObjOne(("_lt", JsObjOne(n, JsVal(v)))) JsSuccess(n ~< v)
case JsObjOne(("_lte", JsObjOne(n, JsVal(v)))) JsSuccess(n ~<= v)
case JsObjOne(("_between", JsRange(n, f, t))) JsSuccess(n ~<> (f t))
case JsObjOne(("_parent", JsParent(p, q))) JsSuccess(parent(p, q))
case JsObjOne(("_parent", JsParentId(p, i))) JsSuccess(withParent(p, i))
case JsObjOne(("_id", JsString(id))) JsSuccess(withId(id))
case JsField(field, value) JsSuccess(field ~= value)
case JsObjOne(("_child", JsParent(p, q))) JsSuccess(child(p, q))
case JsObjOne(("_string", JsString(s))) JsSuccess(string(s))
case JsObjOne(("_in", JsFieldIn(f, v))) JsSuccess(f in (v: _*))
case JsObjOne(("_type", JsString(v))) JsSuccess(ofType(v))
case JsObjOne(("_like", JsField(field, value))) JsSuccess(field like value)
case JsObjOne(("_wildcard", JsField(field, value))) JsSuccess(field ~=~ value)
case JsObjOne((n, JsVal(v)))
if (n.startsWith("_")) logger.warn(s"""Potentially invalid search query : {"$n": "$v"}"""); JsSuccess(n ~= v)
case other JsError(s"Invalid query: unexpected $other")
}
}

implicit val aggReads: Reads[Agg] = Reads { (json: JsValue)
json match {
case JsAgg("avg", aggregationName, JsAggFieldQuery(field, query)) JsSuccess(selectAvg(aggregationName, field, query))
case JsAgg("min", aggregationName, JsAggFieldQuery(field, query)) JsSuccess(selectMin(aggregationName, field, query))
case JsAgg("max", aggregationName, JsAggFieldQuery(field, query)) JsSuccess(selectMax(aggregationName, field, query))
case JsAgg("sum", aggregationName, JsAggFieldQuery(field, query)) JsSuccess(selectSum(aggregationName, field, query))
case JsAgg("count", aggregationName, _) JsSuccess(selectCount(aggregationName, (json \ "_query").asOpt[QueryDef]))
case JsAgg("top", aggregationName, _)
val size = (json \ "_size").asOpt[Int].getOrElse(10)
val order = (json \ "_order").asOpt[Seq[String]].getOrElse(Nil)
JsSuccess(selectTop(aggregationName, size, order))
case JsAgg("time", aggregationName, _)
val fields = (json \ "_fields").as[Seq[String]]
val interval = (json \ "_interval").as[String]
val selectables = (json \ "_select").as[Seq[Agg]]
JsSuccess(groupByTime(aggregationName, fields, interval, selectables: _*))
case JsAgg("field", aggregationName, _)
val field = (json \ "_field").as[String]
val size = (json \ "_size").asOpt[Int].getOrElse(10)
val order = (json \ "_order").asOpt[Seq[String]].getOrElse(Nil)
val selectables = (json \ "_select").as[Seq[Agg]]
JsSuccess(groupByField(aggregationName, field, size, order, selectables: _*))
case JsAgg("category", aggregationName, _)
val categories = (json \ "_categories").as[Map[String, QueryDef]]
val selectables = (json \ "_select").as[Seq[Agg]]
JsSuccess(groupByCaterogy(aggregationName, categories, selectables: _*))
}
implicit val aggReads: Reads[Agg] = Reads {
case JsAgg("avg", aggregationName, JsAggFieldQuery(field, query)) JsSuccess(selectAvg(aggregationName, field, query))
case JsAgg("min", aggregationName, JsAggFieldQuery(field, query)) JsSuccess(selectMin(aggregationName, field, query))
case JsAgg("max", aggregationName, JsAggFieldQuery(field, query)) JsSuccess(selectMax(aggregationName, field, query))
case JsAgg("sum", aggregationName, JsAggFieldQuery(field, query)) JsSuccess(selectSum(aggregationName, field, query))
case json @ JsAgg("count", aggregationName, _) JsSuccess(selectCount(aggregationName, (json \ "_query").asOpt[QueryDef]))
case json @ JsAgg("top", aggregationName, _)
val size = (json \ "_size").asOpt[Int].getOrElse(10)
val order = (json \ "_order").asOpt[Seq[String]].getOrElse(Nil)
JsSuccess(selectTop(aggregationName, size, order))
case json @ JsAgg("time", aggregationName, _)
val fields = (json \ "_fields").as[Seq[String]]
val interval = (json \ "_interval").as[String]
val selectables = (json \ "_select").as[Seq[Agg]]
JsSuccess(groupByTime(aggregationName, fields, interval, selectables: _*))
case json @ JsAgg("field", aggregationName, _)
val field = (json \ "_field").as[String]
val size = (json \ "_size").asOpt[Int].getOrElse(10)
val order = (json \ "_order").asOpt[Seq[String]].getOrElse(Nil)
val selectables = (json \ "_select").as[Seq[Agg]]
JsSuccess(groupByField(aggregationName, field, size, order, selectables: _*))
case json @ JsAgg("category", aggregationName, _)
val categories = (json \ "_categories").as[Map[String, QueryDef]]
val selectables = (json \ "_select").as[Seq[Agg]]
JsSuccess(groupByCaterogy(aggregationName, categories, selectables: _*))
}

implicit val authContextWrites: OWrites[AuthContext] = OWrites[AuthContext] { authContext
Expand Down
4 changes: 2 additions & 2 deletions app/org/elastic4play/services/QueryDSL.scala
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,8 @@ object QueryDSL {
case bd: BigDecimal bd.toDouble
case _ value
}
def ~=(value: Any) = QueryDef(nestedField(field, wildcardQuery(_, convertValue(value))))
def ~==(value: Any) = QueryDef(nestedField(field, termQuery(_, convertValue(value))))
def ~=(value: Any) = QueryDef(nestedField(field, termQuery(_, convertValue(value))))
def ~=~(value: Any) = QueryDef(nestedField(field, wildcardQuery(_, convertValue(value))))
def like(value: Any) = QueryDef(nestedField(field, matchQuery(_, convertValue(value))))
def ~!=(value: Any): QueryDef = not(QueryDef(nestedField(field, termQuery(_, convertValue(value)))))
def ~<(value: Any) = QueryDef(nestedField(field, rangeQuery(_).lt(value.toString)))
Expand Down
4 changes: 2 additions & 2 deletions app/org/elastic4play/utils/package.scala
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import org.scalactic.{ Bad, Good, Or }

package object utils {
implicit class RichFuture[T](future: Future[T]) {
def withTimeout(after: FiniteDuration, default: T)(implicit system: ActorSystem, ec: ExecutionContext): Future[T] = {
def withTimeout(after: FiniteDuration, default: T)(implicit system: ActorSystem, ec: ExecutionContext): Future[T] = {
val prom = Promise[T]()
val timeout = system.scheduler.scheduleOnce(after) { prom.success(default); () }
future onComplete { _ timeout.cancel() }
Expand Down Expand Up @@ -41,7 +41,7 @@ package object utils {
obj + (name writes.writes(value))
}

def mapValues(f: (JsValue) JsValue) = JsObject(obj.fields.map {
def mapValues(f: JsValue JsValue) = JsObject(obj.fields.map {
case (key, value) key f(value)
})

Expand Down
2 changes: 1 addition & 1 deletion version.sbt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
version := "1.9.0"
version := "1.10.0"

0 comments on commit aeb5aec

Please sign in to comment.