Skip to content

Commit

Permalink
add preparation for row permission insert
Browse files Browse the repository at this point in the history
on create row
  • Loading branch information
zingmane committed Oct 11, 2023
1 parent 42f494c commit 1894ebc
Show file tree
Hide file tree
Showing 8 changed files with 137 additions and 28 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,8 @@ class SystemController(
columnIds = columns.map(_.id)
rowsWithColumnIdAndValue = rows.map(columnIds.zip(_))

_ <- tableauxModel.createRows(table, rowsWithColumnIdAndValue)
// don't pass row permissions here, because method is only used for demo data
_ <- tableauxModel.createRows(table, rowsWithColumnIdAndValue, None)
} yield table
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,11 @@ class TableauxController(
}
}

def createRow(tableId: TableId, values: Option[Seq[Seq[(ColumnId, _)]]])(
def createRow(
tableId: TableId,
values: Option[Seq[Seq[(ColumnId, _)]]],
rowPermissionsOpt: Option[Seq[String]] = None
)(
implicit user: TableauxUser
): Future[DomainObject] = {
checkArguments(greaterZero(tableId))
Expand All @@ -254,10 +258,10 @@ class TableauxController(
case Some(seq) =>
checkArguments(nonEmpty(seq, "rows"))
logger.info(s"createRows ${table.id} $values")
repository.createRows(table, seq)
repository.createRows(table, seq, rowPermissionsOpt)
case None =>
logger.info(s"createRow ${table.id}")
repository.createRow(table)
repository.createRow(table, rowPermissionsOpt)
}
} yield row
}
Expand Down Expand Up @@ -529,7 +533,8 @@ class TableauxController(
}
table <- repository.createTable(tableName, hidden = false)
columnIds <- repository.createColumns(table, columns).map(_.map(_.id))
_ <- repository.createRows(table, rows.map(columnIds.zip(_)))
// TODO: pass row permissions to createRows
_ <- repository.createRows(table, rows.map(columnIds.zip(_)), None)
completeTable <- retrieveCompleteTable(table.id)
} yield completeTable
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -900,8 +900,10 @@ case class CreateHistoryModel(tableauxModel: TableauxModel, connection: Database
}
}

def createRow(table: Table, rowId: RowId)(implicit user: TableauxUser): Future[RowId] = {
def createRow(table: Table, rowId: RowId, rowPermissionsOpt: Option[Seq[String]])(implicit
user: TableauxUser): Future[RowId] = {
insertCreateRowHistory(table, rowId)
// TODO create history row with row permissions
}

def deleteRow(table: Table, rowId: RowId, replacingRowIdOpt: Option[Int])(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -357,15 +357,15 @@ class TableauxModel(

}

def createRow(table: Table)(implicit user: TableauxUser): Future[Row] = {
def createRow(table: Table, rowPermissionsOpt: Option[Seq[String]])(implicit user: TableauxUser): Future[Row] = {
for {
rowId <- createRowModel.createRow(table, Seq.empty)
_ <- createHistoryModel.createRow(table, rowId)
rowId <- createRowModel.createRow(table, Seq.empty, rowPermissionsOpt)
_ <- createHistoryModel.createRow(table, rowId, rowPermissionsOpt)
row <- retrieveRow(table, rowId)
} yield row
}

def createRows(table: Table, rows: Seq[Seq[(ColumnId, Any)]])(
def createRows(table: Table, rows: Seq[Seq[(ColumnId, Any)]], rowPermissionsOpt: Option[Seq[String]])(
implicit user: TableauxUser
): Future[RowSeq] = {
for {
Expand Down Expand Up @@ -396,8 +396,8 @@ class TableauxModel(
case _ => Future.successful(())
}

rowId <- createRowModel.createRow(table, columnValuePairs)
_ <- createHistoryModel.createRow(table, rowId)
rowId <- createRowModel.createRow(table, columnValuePairs, rowPermissionsOpt)
_ <- createHistoryModel.createRow(table, rowId, rowPermissionsOpt)
_ <- createHistoryModel.createCells(table, rowId, columnValuePairs)

newRow <- retrieveRow(table, columns, rowId)
Expand Down Expand Up @@ -1175,7 +1175,7 @@ class TableauxModel(
rowValues = row.values

// First create a empty row
duplicatedRowId <- createRowModel.createRow(table, Seq.empty)
duplicatedRowId <- createRowModel.createRow(table, Seq.empty, Option(row.rowPermissions.value))

// Fill the row with life
_ <- updateRowModel
Expand All @@ -1187,7 +1187,7 @@ class TableauxModel(
.flatMap(_ => Future.failed(ex))
})

_ <- createHistoryModel.createRow(table, duplicatedRowId)
_ <- createHistoryModel.createRow(table, duplicatedRowId, Option(row.rowPermissions.value))
_ <- createHistoryModel.createCells(table, rowId, columns.zip(rowValues))

// Retrieve duplicated row with all columns
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ sealed trait UpdateCreateRowModelHelper extends LazyLogging {
table: Table,
rowId: RowId,
values: Seq[(LinkColumn, Seq[RowId])],
rowPermissionsOpt: Option[Seq[String]],
maybeTransaction: Option[DbTransaction] = None
)(implicit ec: ExecutionContext): Future[Unit] = {
val func = (value: (LinkColumn, Seq[RowId])) => {
Expand Down Expand Up @@ -498,7 +499,7 @@ class UpdateRowModel(val connection: DatabaseConnection) extends DatabaseQuery w
for {
_ <- if (simple.isEmpty) Future.successful(()) else updateSimple(table, rowId, simple)
_ <- if (multis.isEmpty) Future.successful(()) else updateTranslations(table, rowId, multis)
_ <- if (links.isEmpty) Future.successful(()) else updateLinks(table, rowId, links, maybeTransaction)
_ <- if (links.isEmpty) Future.successful(()) else updateLinks(table, rowId, links, None, maybeTransaction)
_ <- if (attachments.isEmpty) Future.successful(()) else updateAttachments(table, rowId, attachments)
} yield ()
}
Expand Down Expand Up @@ -755,18 +756,25 @@ class UpdateRowModel(val connection: DatabaseConnection) extends DatabaseQuery w
class CreateRowModel(val connection: DatabaseConnection) extends DatabaseQuery with UpdateCreateRowModelHelper {
val attachmentModel = AttachmentModel(connection)

def createRow(table: Table, values: Seq[(ColumnType[_], _)]): Future[RowId] = {
def createRow(
table: Table,
values: Seq[(ColumnType[_], _)],
rowPermissionsOpt: Option[Seq[String]]
): Future[RowId] = {
val tableId = table.id
ColumnType.splitIntoTypesWithValues(values) match {
case Failure(ex) =>
Future.failed(ex)

case Success((simple, multis, links, attachments)) =>
for {
rowId <- if (simple.isEmpty) createEmpty(tableId) else createSimple(tableId, simple)
_ <- if (multis.isEmpty) Future.successful(()) else createTranslations(tableId, rowId, multis)
_ <- if (links.isEmpty) Future.successful(()) else updateLinks(table, rowId, links)
_ <- if (attachments.isEmpty) Future.successful(()) else createAttachments(tableId, rowId, attachments)
rowId <- if (simple.isEmpty) createEmpty(tableId) else createSimple(tableId, simple, rowPermissionsOpt)
_ <-
if (multis.isEmpty) Future.successful(()) else createTranslations(tableId, rowId, multis, rowPermissionsOpt)
_ <- if (links.isEmpty) Future.successful(()) else updateLinks(table, rowId, links, rowPermissionsOpt)
_ <-
if (attachments.isEmpty) Future.successful(())
else createAttachments(tableId, rowId, attachments, rowPermissionsOpt)
} yield rowId
}
}
Expand All @@ -779,7 +787,11 @@ class CreateRowModel(val connection: DatabaseConnection) extends DatabaseQuery w
}
}

private def createSimple(tableId: TableId, values: Seq[(SimpleValueColumn[_], Option[Any])]): Future[RowId] = {
private def createSimple(
tableId: TableId,
values: Seq[(SimpleValueColumn[_], Option[Any])],
rowPermissionsOpt: Option[Seq[String]]
): Future[RowId] = {
val placeholder = values.map(_ => "?").mkString(", ")
val columns = values.map({ case (column: ColumnType[_], _) => s"column_${column.id}" }).mkString(", ")
val binds = values.map({ case (_, value) => value.orNull })
Expand All @@ -795,7 +807,8 @@ class CreateRowModel(val connection: DatabaseConnection) extends DatabaseQuery w
private def createTranslations(
tableId: TableId,
rowId: RowId,
values: Seq[(SimpleValueColumn[_], Map[String, Option[_]])]
values: Seq[(SimpleValueColumn[_], Map[String, Option[_]])],
rowPermissionsOpt: Option[Seq[String]]
): Future[_] = {
val entries = for {
(column, langtagValueOptMap) <- values
Expand Down Expand Up @@ -826,7 +839,8 @@ class CreateRowModel(val connection: DatabaseConnection) extends DatabaseQuery w
private def createAttachments(
tableId: TableId,
rowId: RowId,
values: Seq[(AttachmentColumn, Seq[(UUID, Option[Ordering])])]
values: Seq[(AttachmentColumn, Seq[(UUID, Option[Ordering])])],
rowPermissionsOpt: Option[Seq[String]]
): Future[_] = {
val futureSequence = for {
(column: AttachmentColumn, attachmentValue) <- values
Expand Down
16 changes: 15 additions & 1 deletion src/main/scala/com/campudus/tableaux/helper/JsonUtils.scala
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,20 @@ object JsonUtils extends LazyLogging {
}
}

def getRowPermissionsOpt(json: JsonObject): Option[Seq[String]] = {
val rowPermissionsOpt = booleanToValueOption(
json.containsKey("rowPermissions"), {
checkAllValuesOfArray[String](
json.getJsonArray("rowPermissions"),
d => d.isInstanceOf[String],
"rowPermissions"
).get
}
).map(_.asScala.toSeq.map({ case perm: String => perm }))

rowPermissionsOpt
}

def toLocationType(json: JsonObject): LocationType = {
(for {
location <- notNull(json.getString("location"), "location")
Expand Down Expand Up @@ -403,7 +417,7 @@ object JsonUtils extends LazyLogging {
* Helper to cast a Json Array to a scala Seq of class A
*
* @param jsonArray
* @tparam A
* @param A
* @return
* Seq[A]
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -522,9 +522,9 @@ class TableauxRouter(override val config: TableauxConfig, val controller: Tablea
*/
private def createRow(context: RoutingContext): Unit = {
implicit val user = TableauxUser(context)
val json = getJson(context)

def getOptionalValues = {
val json = getJson(context)
if (json.containsKey("columns") && json.containsKey("rows")) {
Some(toColumnValueSeq(json))
} else {
Expand All @@ -543,9 +543,8 @@ class TableauxRouter(override val config: TableauxConfig, val controller: Tablea
case _: NoJsonFoundException => None
})
.get

controller
.createRow(tableId, optionalValues)
val rowPermissionsOpt = getRowPermissionsOpt(json)
controller.createRow(tableId, optionalValues, rowPermissionsOpt)
}
)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
package com.campudus.tableaux.api.permission

import com.campudus.tableaux.database.DatabaseConnection
import com.campudus.tableaux.database.model.SystemModel
import com.campudus.tableaux.testtools.{RequestCreation, TableauxTestBase}
import com.campudus.tableaux.testtools.RequestCreation.{Identifier, TextCol}

import io.vertx.ext.unit.TestContext
import io.vertx.ext.unit.junit.VertxUnitRunner
import io.vertx.scala.SQLConnection
import org.vertx.scala.core.json.Json

import scala.concurrent.Future

import org.junit.Assert._
import org.junit.Test
import org.junit.runner.RunWith

@RunWith(classOf[VertxUnitRunner])
class CreateRowWithRowPermissionsTest extends TableauxTestBase {

val createTableJson = Json.obj("name" -> "Test Nr. 1")

def createTextColumnJson(name: String) = RequestCreation.Columns().add(RequestCreation.TextCol(name)).getJson

def createNumberColumnJson(name: String) = RequestCreation.Columns().add(RequestCreation.NumericCol(name)).getJson

@Test
def createMultipleFullRowsWithRowPermissions(implicit c: TestContext): Unit = {
okTest {
val sqlConnection = SQLConnection(this.vertxAccess(), databaseConfig)
val dbConnection = DatabaseConnection(this.vertxAccess(), sqlConnection)

val valuesRow = Json.obj(
"columns" -> Json.arr(Json.obj("id" -> 1), Json.obj("id" -> 2)),
"rows" -> Json.arr(
Json.obj("values" -> Json.arr("Test Field 1", 2)),
Json.obj("values" -> Json.arr("Test Field 2", 5))
),
"rowPermissions" -> Json.arr(
"perm_group_1",
"perm_group_2"
)
)
val expectedJson = Json.obj(
"status" -> "ok",
"rows" -> Json.arr(
Json.obj("id" -> 1, "values" -> Json.arr("Test Field 1", 2)),
Json.obj("id" -> 2, "values" -> Json.arr("Test Field 2", 5))
)
)

for {
_ <- sendRequest("POST", "/tables", createTableJson)
_ <- sendRequest("POST", "/tables/1/columns", createTextColumnJson("Test Column 1"))
_ <- sendRequest("POST", "/tables/1/columns", createNumberColumnJson("Test Column 2"))
test <- sendRequest("POST", "/tables/1/rows", valuesRow)

rowPermissions <-
dbConnection.query("SELECT row_permissions FROM user_table_1")
.map(_.getJsonArray("results").getJsonArray(0))

// rowPermissionsHistory <-
// dbConnection.query(
// "SELECT value FROM user_table_history_1 WHERE event = 'row_permission_changed' AND history_type = 'permission'"
// )
// .map(_.getJsonArray("results").getJsonArray(0))
} yield {
assertJSONEquals(expectedJson, test)
println(s"rowPermissions: $rowPermissions")
}
}
}
}

0 comments on commit 1894ebc

Please sign in to comment.