Skip to content

Commit

Permalink
feat: Add Storage (#8)
Browse files Browse the repository at this point in the history
Added Mongo db driver
Added ReactiveMongo Zlayer
Added  Mongo repo and collection update and query
Updated the docker-compose to create the collection and indexes required.

Co-authored-by: Shailesh Patil <shailesh.patil@iohk.io>
Signed-off-by: Fabio <Pinheiro>
  • Loading branch information
2 people authored and Fabio committed Apr 30, 2024
1 parent 420310e commit 2c198ab
Show file tree
Hide file tree
Showing 20 changed files with 932 additions and 271 deletions.
49 changes: 13 additions & 36 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -25,21 +25,8 @@ lazy val V = new {
// val zioMunitTest = "0.1.1"
val zioHttp = "0.0.5"
val zioConfig = "4.0.0-RC16"
// val zioPrelude = "1.0.0-RC19"

// // https://mvnrepository.com/artifact/io.github.cquiroz/scala-java-time
// val scalaJavaTime = "2.3.0"

// val logbackClassic = "1.2.10"
// val scalaLogging = "3.9.4"

// val laika = "0.19.1"

// val laminar = "15.0.1"
// val waypoint = "6.0.0"
// val upickle = "3.1.0"
// // https://www.npmjs.com/package/material-components-web
// val materialComponents = "12.0.0"
val zioSl4j = "2.1.13"
val mongo = "1.1.0-RC10"
}

/** Dependencies */
Expand All @@ -66,28 +53,10 @@ lazy val D = new {
val zioConfig = Def.setting("dev.zio" %% "zio-config" % V.zioConfig)
val zioConfigMagnolia = Def.setting("dev.zio" %% "zio-config-magnolia" % V.zioConfig) // For deriveConfig
val zioConfigTypesafe = Def.setting("dev.zio" %% "zio-config-typesafe" % V.zioConfig) // For HOCON
// val zioPrelude = Def.setting("dev.zio" %%% "zio-prelude" % V.zioPrelude)
// // val zioTest = Def.setting("dev.zio" %%% "zio-test" % V.zio % Test)
// // val zioTestSBT = Def.setting("dev.zio" %%% "zio-test-sbt" % V.zio % Test)
// // val zioTestMagnolia = Def.setting("dev.zio" %%% "zio-test-magnolia" % V.zio % Test)
// val zioMunitTest = Def.setting("com.github.poslegm" %%% "munit-zio" % V.zioMunitTest % Test)

// // Needed for ZIO
// val scalaJavaT = Def.setting("io.github.cquiroz" %%% "scala-java-time" % V.scalaJavaTime)
// val scalaJavaTZ = Def.setting("io.github.cquiroz" %%% "scala-java-time-tzdb" % V.scalaJavaTime)

// // Test DID comm
// // val didcomm = Def.setting("org.didcommx" % "didcomm" % "0.3.1")

val zioLoggingSl4j = Def.setting("dev.zio" %% "zio-logging-slf4j" % V.zioSl4j)
val mongo = Def.setting("org.reactivemongo" %% "reactivemongo" % V.mongo)
// // For munit https://scalameta.org/munit/docs/getting-started.html#scalajs-setup
val munit = Def.setting("org.scalameta" %%% "munit" % V.munit % Test)

// val laika = Def.setting("org.planet42" %%% "laika-core" % V.laika) // JVM & JS

// // For WEBAPP
// val laminar = Def.setting("com.raquo" %%% "laminar" % V.laminar)
// val waypoint = Def.setting("com.raquo" %%% "waypoint" % V.waypoint)
// val upickle = Def.setting("com.lihaoyi" %%% "upickle" % V.upickle)
}

inThisBuild(
Expand Down Expand Up @@ -171,6 +140,7 @@ lazy val buildInfoConfigure: Project => Project = _.enablePlugins(BuildInfoPlugi
lazy val httpUtils = crossProject(JSPlatform, JVMPlatform) // project
.in(file("http-utils"))
.settings(publish / skip := true)
.settings((setupTestConfig): _*)
.settings(
libraryDependencies += D.scalaDID.value,
)
Expand All @@ -181,11 +151,18 @@ lazy val httpUtils = crossProject(JSPlatform, JVMPlatform) // project
lazy val mediator = project
.in(file("did-mediator"))
.settings(publish / skip := true)
.settings((setupTestConfig): _*)
.settings(
libraryDependencies += D.scalaDID_imp.value,
libraryDependencies += D.scalaDID_peer.value,
libraryDependencies += D.zioHttp.value,
libraryDependencies ++= Seq(D.zioConfig.value, D.zioConfigMagnolia.value, D.zioConfigTypesafe.value),
libraryDependencies ++= Seq(
D.zioConfig.value,
D.zioConfigMagnolia.value,
D.zioConfigTypesafe.value,
D.zioLoggingSl4j.value
),
libraryDependencies += D.mongo.value,
)
.settings(
Compile / mainClass := Some("fmgp.did.demo.MediatorStandalone"),
Expand Down
14 changes: 14 additions & 0 deletions did-mediator/src/main/resources/application.conf
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,18 @@ mediator = {
}
server.http.port = 8080
# server.http.port = ${?PORT}
database = {
protocol = mongodb
protocol = ${?MONGODB_PROTOCOL}
port = 27017
port = ${?MONGODB_PORT}
host = "localhost"
host = ${?MONGODB_HOST}
userName = "admin"
userName = ${?MONGODB_USER}
password = "admin"
password = ${?MONGODB_PASSWORD}
dbName = "mediator"
dbName = ${?MONGODB_DB_NAME}
}
}
50 changes: 50 additions & 0 deletions did-mediator/src/main/scala/fmgp/did/Error.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package fmgp.did

import fmgp.crypto.error._
import fmgp.did._
import fmgp.did.comm._
import zio.json._

trait MediatorError

case class MediatorException(fail: MediatorError) extends Exception(fail.toString())

final case class MediatorDidError(val error: DidFail) extends MediatorError
object MediatorDidError {
def apply(error: DidFail) = new MediatorDidError(error)
}

final case class MediatorThrowable(val error: String) extends StorageError
object MediatorThrowable {
def apply(throwable: Throwable) = new MediatorThrowable(throwable.getClass.getName() + ":" + throwable.getMessage)
}

// Storage

trait StorageError extends MediatorError {
def error: String
}

final case class StorageCollection(val error: String) extends StorageError
object StorageCollection {
def apply(throwable: Throwable) = new StorageCollection(throwable.getClass.getName() + ":" + throwable.getMessage)
}

final case class StorageThrowable(val error: String) extends StorageError
object StorageThrowable {
def apply(throwable: Throwable) = new StorageThrowable(throwable.getClass.getName() + ":" + throwable.getMessage)
}

sealed trait ProtocolError extends MediatorError {
def piuri: PIURI
}

// Protocol

object ProtocolError {
given decoder: JsonDecoder[ProtocolError] = DeriveJsonDecoder.gen[ProtocolError]
given encoder: JsonEncoder[ProtocolError] = DeriveJsonEncoder.gen[ProtocolError]
}

case class MissingProtocolError(piuri: PIURI) extends ProtocolError
case class FailToEncodeMessage(piuri: PIURI, error: String) extends ProtocolError
23 changes: 0 additions & 23 deletions did-mediator/src/main/scala/fmgp/did/MessageDB.scala

This file was deleted.

59 changes: 59 additions & 0 deletions did-mediator/src/main/scala/fmgp/did/MongoDriver.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package fmgp.did

import scala.concurrent.{ExecutionContext, Future}

import reactivemongo.api.{Cursor, DB, MongoConnection, AsyncDriver}
import reactivemongo.api.bson.{BSONDocumentWriter, BSONDocumentReader, Macros, document}

object MongoDriver {
// My settings (see available connection options)
// val connectionString = "mongodb://localhost:27017/mydb?authMode=scram-sha1"
val connectionString =
// "mongodb+srv://mediator:@fmgp-db.orfjsdi.mongodb.net/?retryWrites=true&w=majority"
"mongodb+srv://mediator:w419cDYIQ2lxpDKT@mediatordb.sa0rfqg.mongodb.net"

import ExecutionContext.Implicits.global // use any appropriate context

// Connect to the database: Must be done only once per application
val driver = AsyncDriver()
val parsedUri = MongoConnection.fromString(connectionString)

// Database and collections: Get references
val futureConnection = parsedUri.flatMap(driver.connect(_))
def db1: Future[DB] = futureConnection.flatMap(_.database("firstdb"))
def db2: Future[DB] = futureConnection.flatMap(_.database("anotherdb"))
def personCollection = db1.map(_.collection("person"))

// Write Documents: insert or update

implicit def personWriter: BSONDocumentWriter[Person] = Macros.writer[Person]
// or provide a custom one

// use personWriter
def createPerson(person: Person): Future[Unit] =
personCollection.flatMap(_.insert.one(person).map(_ => {}))

def updatePerson(person: Person): Future[Int] = {
val selector = document(
"firstName" -> person.firstName,
"lastName" -> person.lastName
)

// Update the matching person
personCollection.flatMap(_.update.one(selector, person).map(_.n))
}

implicit def personReader: BSONDocumentReader[Person] = Macros.reader[Person]
// or provide a custom one

def findPersonByAge(age: Int): Future[List[Person]] =
personCollection.flatMap(
_.find(document("age" -> age))
.cursor[Person]()
.collect[List](-1, Cursor.FailOnError[List[Person]]())
)
// ... deserializes the document using personReader

// Custom persistent types
case class Person(firstName: String, lastName: String, age: Int)
}
15 changes: 0 additions & 15 deletions did-mediator/src/main/scala/fmgp/did/MsgContex.scala

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,18 @@ import fmgp.did._
import fmgp.did.comm._
import fmgp.did.comm.protocol._
import fmgp.did.comm.protocol.routing2._
import fmgp.did.db._

object ForwardMessageExecuter extends ProtocolExecuterWithServices[ProtocolExecuter.Services & Ref[MediatorDB]] {
object ForwardMessageExecuter
extends ProtocolExecuterWithServices[
ProtocolExecuter.Services & DidAccountRepo & MessageItemRepo
] {

override def suportedPIURI: Seq[PIURI] = Seq(ForwardMessage.piuri)

override def program[R1 <: Ref[MediatorDB]](
override def program[R1 <: DidAccountRepo & MessageItemRepo](
plaintextMessage: PlaintextMessage
): ZIO[R1, DidFail, Action] = {
): ZIO[R1, MediatorError, Action] = {
// the val is from the match to be definitely stable
val piuriForwardMessage = ForwardMessage.piuri

Expand All @@ -23,8 +27,16 @@ object ForwardMessageExecuter extends ProtocolExecuterWithServices[ProtocolExecu
}).map { case m: ForwardMessage =>
for {
_ <- ZIO.logInfo("ForwardMessage")
db <- ZIO.service[Ref[MediatorDB]]
_ <- db.update(_.store(m.next, m.msg))
repoMessageItem <- ZIO.service[MessageItemRepo]
repoDidAccount <- ZIO.service[DidAccountRepo]
recipientsSubject = Set(m.next) // m.msg.recipientsSubject
numbreOfUpdated <- repoDidAccount.addToInboxes(recipientsSubject, m.msg)
msg <-
if (numbreOfUpdated > 0) { // Or maybe we can add all the time
repoMessageItem.insert(MessageItem(m.msg)) *>
ZIO.logInfo("Add next msg (of the ForwardMessage) to the Message Repo") // TODO change to debug level
} else
ZIO.logWarning("Note: No update on the DidAccount of the recipients")
} yield None
} match
case Left(error) => ZIO.logError(error) *> ZIO.succeed(NoReply)
Expand Down
Loading

0 comments on commit 2c198ab

Please sign in to comment.