diff --git a/webapp/sources/rudder/rudder-core/src/main/resources/reportsSchema.sql b/webapp/sources/rudder/rudder-core/src/main/resources/reportsSchema.sql index 33a4b7e5d6..dad9d3af37 100644 --- a/webapp/sources/rudder/rudder-core/src/main/resources/reportsSchema.sql +++ b/webapp/sources/rudder/rudder-core/src/main/resources/reportsSchema.sql @@ -455,18 +455,20 @@ CREATE TABLE NodeFacts ( ); +CREATE TYPE score AS enum ('A', 'B', 'C', 'D', 'E') + Create table GlobalScore ( nodeId text primary key -, score text -, message text -, details jsonb +, score score NOT NULL +, message text NOT NULL +, details jsonb NOT NULL ); Create table scoreDetails ( - nodeId text -, scoreId text -, score text -, message text -, details jsonb + nodeId text NOT NULL +, scoreId text NOT NULL +, score score NOT NULL +, message text NOT NULL +, details jsonb NOT NULL , PRIMARY KEY (nodeId, scoreId) ); \ No newline at end of file diff --git a/webapp/sources/rudder/rudder-core/src/main/scala/com/normation/rudder/score/GlobalScoreRepository.scala b/webapp/sources/rudder/rudder-core/src/main/scala/com/normation/rudder/score/GlobalScoreRepository.scala index 68b7340c80..1f20120020 100644 --- a/webapp/sources/rudder/rudder-core/src/main/scala/com/normation/rudder/score/GlobalScoreRepository.scala +++ b/webapp/sources/rudder/rudder-core/src/main/scala/com/normation/rudder/score/GlobalScoreRepository.scala @@ -42,6 +42,8 @@ import com.normation.inventory.domain.NodeId import com.normation.rudder.db.Doobie import doobie.implicits._ import doobie.implicits.toSqlInterpolator +import doobie.postgres.implicits.pgEnumString +import doobie.util.invariant.InvalidEnum import zio.interop.catz._ trait GlobalScoreRepository { @@ -56,8 +58,17 @@ object GlobalScoreRepositoryImpl { import ScoreSerializer._ import com.normation.rudder.db.json.implicits._ import doobie._ - implicit val getScoreValue: Get[ScoreValue] = Get[String].temap(ScoreValue.fromString) - implicit val putScoreValue: Put[ScoreValue] = Put[String].contramap(_.value) + + implicit val scoreMeta: Meta[ScoreValue] = { + def getValue(value: String) = { + ScoreValue.fromString(value) match { + case Right(s) => s + case Left(err) => throw InvalidEnum[ScoreValue](value) + } + } + + pgEnumString("score", getValue, _.value) + } implicit val stateWrite: Meta[List[NoDetailsScore]] = new Meta(pgDecoderGet, pgEncoderPut) diff --git a/webapp/sources/rudder/rudder-core/src/main/scala/com/normation/rudder/score/ScoreRepository.scala b/webapp/sources/rudder/rudder-core/src/main/scala/com/normation/rudder/score/ScoreRepository.scala index 1e0e07a44c..7a54cd474f 100644 --- a/webapp/sources/rudder/rudder-core/src/main/scala/com/normation/rudder/score/ScoreRepository.scala +++ b/webapp/sources/rudder/rudder-core/src/main/scala/com/normation/rudder/score/ScoreRepository.scala @@ -41,12 +41,13 @@ import com.normation.errors.IOResult import com.normation.inventory.domain.NodeId import com.normation.rudder.db.Doobie import doobie.Fragments -import doobie.Get -import doobie.Put +import doobie.Meta import doobie.Read import doobie.Write import doobie.implicits._ import doobie.implicits.toSqlInterpolator +import doobie.postgres.implicits.pgEnumString +import doobie.util.invariant.InvalidEnum import zio.interop.catz._ import zio.json.ast.Json @@ -63,8 +64,16 @@ trait ScoreRepository { class ScoreRepositoryImpl(doobie: Doobie) extends ScoreRepository { import com.normation.rudder.db.json.implicits._ - implicit val getScoreValue: Get[ScoreValue] = Get[String].temap(ScoreValue.fromString) - implicit val putScoreValue: Put[ScoreValue] = Put[String].contramap(_.value) + + implicit val scoreMeta: Meta[ScoreValue] = { + def getValue(value: String) = { + ScoreValue.fromString(value) match { + case Right(s) => s + case Left(err) => throw InvalidEnum[ScoreValue](value) + } + } + pgEnumString("score", getValue, _.value) + } // implicit val stateWrite: Meta[Score] = new Meta(pgDecoderGet, pgEncoderPut) diff --git a/webapp/sources/rudder/rudder-web/src/main/scala/bootstrap/liftweb/checks/migration/CheckTableScore.scala b/webapp/sources/rudder/rudder-web/src/main/scala/bootstrap/liftweb/checks/migration/CheckTableScore.scala index 7ba86826e0..c2b77b999d 100644 --- a/webapp/sources/rudder/rudder-web/src/main/scala/bootstrap/liftweb/checks/migration/CheckTableScore.scala +++ b/webapp/sources/rudder/rudder-web/src/main/scala/bootstrap/liftweb/checks/migration/CheckTableScore.scala @@ -43,6 +43,7 @@ import com.normation.rudder.db.Doobie import com.normation.zio._ import doobie.implicits._ import zio.interop.catz._ +import zio.syntax.ToZio /* * During 8.1 cycle, we added a score that is applied to every nodes to give a better understanding @@ -53,12 +54,15 @@ class CheckTableScore( import doobie._ - override def description: String = "Check if database tables Users and UserSessions exist" + override def description: String = "Check if score databases exist" def createScoreTables: IOResult[Unit] = { - val sql1 = sql"""CREATE TABLE IF NOT EXISTS GlobalScore ( + + val checkType = sql"SELECT 1 FROM pg_type WHERE typname = 'score'" + val sqlType = sql"""CREATE TYPE score AS enum ('A', 'B', 'C', 'D', 'E')""" + val sql1 = sql"""CREATE TABLE IF NOT EXISTS GlobalScore ( nodeId text primary key - , score text NOT NULL CHECK (score <> '') + , score score NOT NULL CHECK (score <> '') , message text NOT NULL CHECK (message <> '') , details jsonb NOT NULL );""" @@ -66,12 +70,15 @@ class CheckTableScore( val sql2 = sql"""CREATE TABLE IF NOT EXISTS ScoreDetails ( nodeId text , scoreId text - , score text NOT NULL CHECK (score <> '') - , message text NOT NULL CHECK (score <> '') + , score score NOT NULL CHECK (score <> '') + , message text NOT NULL CHECK (message <> '') , details jsonb NOT NULL , PRIMARY KEY (nodeId, scoreId) );""" + transactIOResult(s"Error with 'score' type creation")(xa => + checkType.query[Int].option.transact(xa).flatMap(i => if (i.isDefined) ().succeed else sqlType.update.run.transact(xa)) + ).unit *> transactIOResult(s"Error with 'GlobalScore' table creation")(xa => sql1.update.run.transact(xa)).unit *> transactIOResult(s"Error with 'ScoreDetails' table creation")(xa => sql2.update.run.transact(xa)).unit }