Skip to content

Commit

Permalink
feat: support for Project Authorization events (#54)
Browse files Browse the repository at this point in the history
  • Loading branch information
jachro authored Mar 12, 2024
1 parent 133c5c0 commit 70044f9
Show file tree
Hide file tree
Showing 24 changed files with 796 additions and 60 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -88,3 +88,13 @@ object projects:

def unsafeFromString(v: String): Visibility =
valueOf(v.toLowerCase.capitalize)

enum MemberRole derives Codec:
lazy val name: String = productPrefix.toLowerCase
case Owner, Member

object MemberRole:
given Order[MemberRole] = Order.by(_.ordinal)

def unsafeFromString(v: String): MemberRole =
valueOf(v.toLowerCase.capitalize)
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,23 @@ import java.time.temporal.ChronoUnit

object ModelGenerators:

val projectNameGen: Gen[projects.Name] =
alphaStringGen(max = 10).map(projects.Name.apply)
val projectDescGen: Gen[projects.Description] =
alphaStringGen(max = 30).map(projects.Description.apply)

val projectVisibilityGen: Gen[projects.Visibility] =
Gen.oneOf(projects.Visibility.values.toList)
val projectMemberRoleGen: Gen[projects.MemberRole] =
Gen.oneOf(projects.MemberRole.values.toList)
val projectCreationDateGen: Gen[projects.CreationDate] =
instantGen().map(projects.CreationDate.apply)

private def alphaStringGen(max: Int): Gen[String] =
Gen
.chooseNum(3, max)
.flatMap(Gen.stringOfN(_, Gen.alphaChar))

private def instantGen(
min: Instant = Instant.EPOCH,
max: Instant = Instant.now()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@

package io.renku.events

import io.renku.events.v1.{ProjectCreated, UserAdded, Visibility}
import io.renku.events.v1.*
import org.scalacheck.Gen
import org.scalacheck.Gen.{alphaChar, alphaNumChar}

Expand All @@ -27,7 +27,10 @@ import java.time.temporal.ChronoUnit

object EventsGenerators:

val projectVisibilityGen: Gen[Visibility] = Gen.oneOf(Visibility.values().toList)
val projectVisibilityGen: Gen[Visibility] =
Gen.oneOf(Visibility.values().toList)
val projectMemberRoleGen: Gen[ProjectMemberRole] =
Gen.oneOf(ProjectMemberRole.values().toList)

def projectCreatedGen(prefix: String): Gen[ProjectCreated] =
for
Expand All @@ -49,6 +52,26 @@ object EventsGenerators:
Instant.now().truncatedTo(ChronoUnit.MILLIS)
)

def projectAuthorizationAddedGen(
projectIdGen: Gen[String] = Gen.uuid.map(_.toString),
roleGen: Gen[ProjectMemberRole] = projectMemberRoleGen
): Gen[ProjectAuthorizationAdded] =
for
projectId <- projectIdGen
userId <- Gen.uuid.map(_.toString)
role <- roleGen
yield ProjectAuthorizationAdded(projectId, userId, role)

def projectAuthorizationUpdatedGen(
projectIdGen: Gen[String] = Gen.uuid.map(_.toString),
roleGen: Gen[ProjectMemberRole] = projectMemberRoleGen
): Gen[ProjectAuthorizationUpdated] =
for
projectId <- projectIdGen
userId <- Gen.uuid.map(_.toString)
role <- roleGen
yield ProjectAuthorizationUpdated(projectId, userId, role)

def userAddedGen(prefix: String): Gen[UserAdded] =
for
id <- Gen.uuid.map(_.toString)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ import io.renku.search.GeneratorSyntax.*
import io.renku.search.api.data.*
import io.renku.search.model.users
import io.renku.search.query.Query
import io.renku.search.solr.client.SearchSolrClientGenerators.*
import io.renku.search.solr.client.SearchSolrSpec
import io.renku.search.solr.client.SolrDocumentGenerators.*
import io.renku.search.solr.documents.{Entity as SolrEntity, User as SolrUser}
import munit.CatsEffectSuite
import scribe.Scribe
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,39 @@ object Microservice extends IOApp:
.make[IO](cfg.queuesConfig.projectRemoved, cfg.redisConfig, cfg.solrConfig)
.map(_.removalProcess.start)
),
(
"ProjectAuthorizationAdded",
cfg.queuesConfig.projectAuthorizationAdded,
AuthorizationAddedProvisioning
.make[IO](
cfg.queuesConfig.projectAuthorizationAdded,
cfg.redisConfig,
cfg.solrConfig
)
.map(_.provisioningProcess.start)
),
(
"ProjectAuthorizationUpdated",
cfg.queuesConfig.projectAuthorizationUpdated,
AuthorizationUpdatedProvisioning
.make[IO](
cfg.queuesConfig.projectAuthorizationUpdated,
cfg.redisConfig,
cfg.solrConfig
)
.map(_.provisioningProcess.start)
),
(
"ProjectAuthorizationRemoved",
cfg.queuesConfig.projectAuthorizationRemoved,
AuthorizationRemovedProvisioning
.make[IO](
cfg.queuesConfig.projectAuthorizationRemoved,
cfg.redisConfig,
cfg.solrConfig
)
.map(_.provisioningProcess.start)
),
(
"UserAdded",
cfg.queuesConfig.userAdded,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ final case class QueuesConfig(
projectCreated: QueueName,
projectUpdated: QueueName,
projectRemoved: QueueName,
projectAuthorizationAdded: QueueName,
projectAuthorizationUpdated: QueueName,
projectAuthorizationRemoved: QueueName,
userAdded: QueueName,
userUpdated: QueueName
)
Expand All @@ -37,6 +40,9 @@ object QueuesConfig:
ConfigValues.eventQueue("projectCreated"),
ConfigValues.eventQueue("projectUpdated"),
ConfigValues.eventQueue("projectRemoved"),
ConfigValues.eventQueue("projectAuthorizationAdded"),
ConfigValues.eventQueue("projectAuthorizationUpdated"),
ConfigValues.eventQueue("projectAuthorizationRemoved"),
ConfigValues.eventQueue("userAdded"),
ConfigValues.eventQueue("userUpdated")
).mapN(QueuesConfig.apply)
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,6 @@ trait TypeTransformers:

given Transformer[v1.Visibility, projects.Visibility] =
(from: v1.Visibility) => projects.Visibility.unsafeFromString(from.name())

given memberRoleTransformer: Transformer[v1.ProjectMemberRole, projects.MemberRole] =
(from: v1.ProjectMemberRole) => projects.MemberRole.unsafeFromString(from.name())
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
/*
* Copyright 2024 Swiss Data Science Center (SDSC)
* A partnership between École Polytechnique Fédérale de Lausanne (EPFL) and
* Eidgenössische Technische Hochschule Zürich (ETHZ).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package io.renku.search.provision
package project

import cats.Show
import cats.effect.{Async, Resource}
import fs2.io.net.Network
import io.renku.avro.codec.decoders.all.given
import io.renku.events.v1.ProjectAuthorizationAdded
import io.renku.redis.client.{QueueName, RedisConfig}
import io.renku.search.model.users
import io.renku.search.provision.TypeTransformers.given
import io.renku.search.solr.documents
import io.renku.solr.client.SolrConfig
import scribe.Scribe

object AuthorizationAddedProvisioning:

def make[F[_]: Async: Network](
queueName: QueueName,
redisConfig: RedisConfig,
solrConfig: SolrConfig
): Resource[F, UpdateProvisioningProcess[F]] =
given Scribe[F] = scribe.cats[F]

UpdateProvisioningProcess.make[F, ProjectAuthorizationAdded, documents.Project](
queueName,
ProjectAuthorizationAdded.SCHEMA$,
idExtractor,
docUpdate,
redisConfig,
solrConfig
)

private given Show[ProjectAuthorizationAdded] =
Show.show[ProjectAuthorizationAdded](v =>
s"projectId '${v.projectId}', userId '${v.userId}', role '${v.role}'"
)

private lazy val idExtractor: ProjectAuthorizationAdded => String = _.projectId

private lazy val docUpdate
: ((ProjectAuthorizationAdded, documents.Project)) => documents.Project = {
case (update, orig) =>
orig.addMember(
users.Id(update.userId),
memberRoleTransformer.transform(update.role)
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/*
* Copyright 2024 Swiss Data Science Center (SDSC)
* A partnership between École Polytechnique Fédérale de Lausanne (EPFL) and
* Eidgenössische Technische Hochschule Zürich (ETHZ).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package io.renku.search.provision
package project

import cats.Show
import cats.effect.{Async, Resource}
import fs2.io.net.Network
import io.renku.avro.codec.decoders.all.given
import io.renku.events.v1.ProjectAuthorizationRemoved
import io.renku.redis.client.{QueueName, RedisConfig}
import io.renku.search.model.users
import io.renku.search.solr.documents
import io.renku.solr.client.SolrConfig
import scribe.Scribe

object AuthorizationRemovedProvisioning:

def make[F[_]: Async: Network](
queueName: QueueName,
redisConfig: RedisConfig,
solrConfig: SolrConfig
): Resource[F, UpdateProvisioningProcess[F]] =
given Scribe[F] = scribe.cats[F]

UpdateProvisioningProcess.make[F, ProjectAuthorizationRemoved, documents.Project](
queueName,
ProjectAuthorizationRemoved.SCHEMA$,
idExtractor,
docUpdate,
redisConfig,
solrConfig
)

private given Show[ProjectAuthorizationRemoved] =
Show.show[ProjectAuthorizationRemoved](v =>
s"projectId '${v.projectId}', userId '${v.userId}'"
)

private lazy val idExtractor: ProjectAuthorizationRemoved => String = _.projectId

private lazy val docUpdate
: ((ProjectAuthorizationRemoved, documents.Project)) => documents.Project = {
case (update, orig) =>
orig.removeMember(users.Id(update.userId))
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
/*
* Copyright 2024 Swiss Data Science Center (SDSC)
* A partnership between École Polytechnique Fédérale de Lausanne (EPFL) and
* Eidgenössische Technische Hochschule Zürich (ETHZ).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package io.renku.search.provision
package project

import cats.Show
import cats.effect.{Async, Resource}
import fs2.io.net.Network
import io.renku.avro.codec.decoders.all.given
import io.renku.events.v1.ProjectAuthorizationUpdated
import io.renku.redis.client.{QueueName, RedisConfig}
import io.renku.search.model.users
import io.renku.search.provision.TypeTransformers.given
import io.renku.search.solr.documents
import io.renku.solr.client.SolrConfig
import scribe.Scribe

object AuthorizationUpdatedProvisioning:

def make[F[_]: Async: Network](
queueName: QueueName,
redisConfig: RedisConfig,
solrConfig: SolrConfig
): Resource[F, UpdateProvisioningProcess[F]] =
given Scribe[F] = scribe.cats[F]

UpdateProvisioningProcess.make[F, ProjectAuthorizationUpdated, documents.Project](
queueName,
ProjectAuthorizationUpdated.SCHEMA$,
idExtractor,
docUpdate,
redisConfig,
solrConfig
)

private given Show[ProjectAuthorizationUpdated] =
Show.show[ProjectAuthorizationUpdated](v =>
s"projectId '${v.projectId}', userId '${v.userId}', role '${v.role}'"
)

private lazy val idExtractor: ProjectAuthorizationUpdated => String = _.projectId

private lazy val docUpdate
: ((ProjectAuthorizationUpdated, documents.Project)) => documents.Project = {
case (update, orig) =>
orig.addMember(
users.Id(update.userId),
memberRoleTransformer.transform(update.role)
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ import io.renku.events.v1
import io.renku.events.v1.{ProjectCreated, Visibility}
import io.renku.redis.client.{QueueName, RedisConfig}
import io.renku.search.model.*
import io.renku.search.provision.UpsertProvisioningProcess
import io.renku.search.provision.TypeTransformers.given
import io.renku.search.provision.UpsertProvisioningProcess
import io.renku.search.solr.documents
import io.renku.solr.client.SolrConfig
import scribe.Scribe
Expand All @@ -53,4 +53,8 @@ object ProjectCreatedProvisioning:
Show.show[ProjectCreated](pc => show"slug '${pc.slug}'")

private given Transformer[ProjectCreated, documents.Project] =
_.into[documents.Project].transform(Field.default(_.score))
_.into[documents.Project].transform(
Field.computed(_.owners, pc => List(users.Id(pc.createdBy))),
Field.default(_.members),
Field.default(_.score)
)
Loading

0 comments on commit 70044f9

Please sign in to comment.