Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat/#740 #752

Merged
merged 8 commits into from
Sep 12, 2024
10 changes: 9 additions & 1 deletion daikoku/app/controllers/ApiController.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3394,13 +3394,21 @@ class ApiController(
if (ctx.user.isDaikokuAdmin) Json.obj()
else Json.obj("users.userId" -> ctx.user.id.value)

val typeFilter = if (ctx.tenant.subscriptionSecurity.isDefined
&& ctx.tenant.subscriptionSecurity.exists(identity)) {
Json.obj(
"type" -> Json.obj("$ne" -> TeamType.Personal.name)
)
} else {
Json.obj()
}
for {
myTeams <- env.dataStore.teamRepo.myTeams(ctx.tenant, ctx.user)
teams <-
env.dataStore.teamRepo
.forTenant(ctx.tenant.id)
.findNotDeleted(
Json.obj("name" -> searchAsRegex) ++ teamUsersFilter,
Json.obj("name" -> searchAsRegex) ++ teamUsersFilter ++ typeFilter,
5,
Json.obj("name" -> 1).some
)
Expand Down
26 changes: 22 additions & 4 deletions daikoku/app/domain/CommonServices.scala
Original file line number Diff line number Diff line change
Expand Up @@ -648,19 +648,29 @@ object CommonServices {
env: Env,
ec: ExecutionContext
) = {

val typeFilter = if (ctx.tenant.subscriptionSecurity.isDefined
&& ctx.tenant.subscriptionSecurity.exists(identity)) {
Json.obj(
"type" -> Json.obj("$ne" ->TeamType.Personal.name)
)
} else {
Json.obj()
}
_UberPublicUserAccess(
AuditTrailEvent("@{user.name} has accessed his team list")
)(ctx) {
(if (ctx.user.isDaikokuAdmin)
env.dataStore.teamRepo
.forTenant(ctx.tenant)
.findAllNotDeleted()
.findNotDeleted(typeFilter)
else
env.dataStore.teamRepo
.forTenant(ctx.tenant)
.findNotDeleted(Json.obj("users.userId" -> ctx.user.id.value)))
.findNotDeleted(Json.obj("users.userId" -> ctx.user.id.value) ++ typeFilter))
.map(teams =>
teams.sortWith((a, b) => a.name.compareToIgnoreCase(b.name) < 0)
teams
.sortWith((a, b) => a.name.compareToIgnoreCase(b.name) < 0)
)
}
}
Expand All @@ -673,6 +683,14 @@ object CommonServices {
_TenantAdminAccessTenant(
AuditTrailEvent("@{user.name} has accessed to all teams list")
)(ctx) {
val typeFilter = if (ctx.tenant.subscriptionSecurity.isDefined
&& ctx.tenant.subscriptionSecurity.exists(identity)) {
Json.obj(
"type" -> TeamType.Organization.name
)
} else {
Json.obj()
}
for {
teams <-
env.dataStore.teamRepo
Expand All @@ -681,7 +699,7 @@ object CommonServices {
Json.obj(
"_deleted" -> false,
"name" -> Json.obj("$regex" -> research)
),
) ++ typeFilter,
offset,
limit,
Some(Json.obj("_humanReadableId" -> 1))
Expand Down
16 changes: 14 additions & 2 deletions daikoku/app/storage/api.scala
Original file line number Diff line number Diff line change
Expand Up @@ -402,15 +402,27 @@ trait TeamRepo extends TenantCapableRepo[Team, TeamId] {
env: Env,
ec: ExecutionContext
): Future[Seq[Team]] = {
val typeFilter = if (tenant.subscriptionSecurity.isDefined
&& tenant.subscriptionSecurity.exists(identity)) {
Json.obj(
"type" -> Json.obj("$ne" -> TeamType.Personal.name)
)
} else {
Json.obj()
}
if (user.isDaikokuAdmin) {
env.dataStore.teamRepo
.forTenant(tenant.id)
.findAllNotDeleted()
.findNotDeleted(
typeFilter
)


} else {
env.dataStore.teamRepo
.forTenant(tenant.id)
.findNotDeleted(
Json.obj("users.userId" -> user.id.value)
Json.obj("users.userId" -> user.id.value) ++ typeFilter
)
}
}
Expand Down
2 changes: 1 addition & 1 deletion daikoku/javascript/tests/completeJourney.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ test('test a complete user journey', async ({ page }) => {
//create a new API
await page.locator('div:nth-child(4) > .notification-link').first().click();
await page.locator('span').filter({ hasText: 'API' }).first().click();
await page.locator('div').filter({ hasText: /^The A team$/ }).click();
await page.locator('div').filter({ hasText: /^The A team$/ }).nth(1).click();

await page.getByRole('button', { name: 'Published' }).click();
await page.getByPlaceholder('New Api').fill('Test API');
Expand Down
138 changes: 133 additions & 5 deletions daikoku/test/daikoku/ApiControllerSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -545,9 +545,9 @@ class ApiControllerSpec()
resp.status mustBe 403
}

"see his teams" in {
"see his teams (graphQl)" in {
setupEnvBlocking(
tenants = Seq(tenant),
tenants = Seq(tenant.copy(subscriptionSecurity = Some(true))),
users = Seq(userAdmin),
teams = Seq(teamOwner, teamConsumer)
)
Expand Down Expand Up @@ -580,7 +580,135 @@ class ApiControllerSpec()
resp.status mustBe 200

val result = (resp.json \ "data" \ "myTeams").as[JsArray]
result.value.length mustBe 3
result.value.length mustBe 2

setupEnvBlocking(
tenants = Seq(tenant.copy(subscriptionSecurity = Some(false))),
users = Seq(userAdmin),
teams = Seq(teamOwner, teamConsumer)
)
val session2 = loginWithBlocking(userAdmin, tenant)
val resp2 = httpJsonCallBlocking(
"/api/search",
"POST",
body = Some(
Json.obj(
"query" ->
"""
|query MyTeams {
| myTeams {
| name
| _humanReadableId
| _id
| type
| users {
| user {
| userId: id
| }
| teamPermission
| }
| }
| }
|""".stripMargin
)
)
)(tenant, session2)
resp2.status mustBe 200

val result2 = (resp2.json \ "data" \ "myTeams").as[JsArray]
result2.value.length mustBe 3
}
"see his teams" in {
setupEnvBlocking(
tenants = Seq(tenant.copy(subscriptionSecurity = Some(true))),
users = Seq(userAdmin),
teams = Seq(teamOwner, teamConsumer)
)
val session = loginWithBlocking(userAdmin, tenant)
val resp = httpJsonCallBlocking("/api/me/teams")(tenant, session)
resp.status mustBe 200

val result = resp.json.as[JsArray]
result.value.length mustBe 2

setupEnvBlocking(
tenants = Seq(tenant.copy(subscriptionSecurity = Some(false))),
users = Seq(userAdmin),
teams = Seq(teamOwner, teamConsumer)
)
val session2 = loginWithBlocking(userAdmin, tenant)
val resp2 = httpJsonCallBlocking("/api/me/teams")(tenant, session2)
resp2.status mustBe 200

val result2 = resp2.json.as[JsArray]
result2.value.length mustBe 3
}

"search a team" in {
setupEnvBlocking(
tenants = Seq(tenant.copy(subscriptionSecurity = Some(true))),
users = Seq(userAdmin),
teams = Seq(teamOwner, teamConsumer)
)
val session = loginWithBlocking(userAdmin, tenant)

val resp =
httpJsonCallBlocking(
path = s"/api/_search",
method = "POST",
body = Some(Json.obj("search" -> ""))
)(tenant, session)

resp.status mustBe 200
val maybeValue = resp.json.as[JsArray].value.find(entry => (entry \ "label").as[String] == "Teams")
maybeValue.isDefined mustBe true
(maybeValue.get \ "options").as[JsArray].value.length mustBe 2

val resp2 =
httpJsonCallBlocking(
path = s"/api/_search",
method = "POST",
body = Some(Json.obj("search" -> "Admin"))
)(tenant, session)

resp2.status mustBe 200
val maybeValue2 = resp2.json.as[JsArray].value.find(entry => (entry \ "label").as[String] == "Teams")
maybeValue2.isDefined mustBe true
(maybeValue2.get \ "options").as[JsArray].value.length mustBe 0

//disable subscription security

setupEnvBlocking(
tenants = Seq(tenant.copy(subscriptionSecurity = Some(false))),
users = Seq(userAdmin, userApiEditor),
teams = Seq(teamOwner, teamConsumer)
)
val session2 = loginWithBlocking(userAdmin, tenant)

val resp3 =
httpJsonCallBlocking(
path = s"/api/_search",
method = "POST",
body = Some(Json.obj("search" -> ""))
)(tenant, session2)

resp3.status mustBe 200
val maybeValue3 = resp3.json.as[JsArray].value.find(entry => (entry \ "label").as[String] == "Teams")
maybeValue3.isDefined mustBe true
(maybeValue3.get \ "options").as[JsArray].value.length mustBe 3

val resp4 =
httpJsonCallBlocking(
path = s"/api/_search",
method = "POST",
body = Some(Json.obj("search" -> "Admin"))
)(tenant, session2)

resp4.status mustBe 200
val maybeValue4 = resp4.json.as[JsArray].value.find(entry => (entry \ "label").as[String] == "Teams")
maybeValue4.isDefined mustBe true
(maybeValue4.get \ "options").as[JsArray].value.length mustBe 1

}

"see one of his teams" in {
Expand Down Expand Up @@ -3262,7 +3390,7 @@ class ApiControllerSpec()
resp.status mustBe 200

val result = (resp.json \ "data" \ "myTeams").as[JsArray]
result.value.length mustBe 2
result.value.length mustBe 1
}

"see one of his teams" in {
Expand Down Expand Up @@ -3879,7 +4007,7 @@ class ApiControllerSpec()
resp.status mustBe 200

val result = (resp.json \ "data" \ "myTeams").as[JsArray]
result.value.length mustBe 3
result.value.length mustBe 2
}

"see one of his teams" in {
Expand Down
75 changes: 75 additions & 0 deletions daikoku/test/daikoku/TeamControllerSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,81 @@ class TeamControllerSpec()
)(tenant, session)
respDelete.status mustBe 403
}

"list all teams" in {
setupEnvBlocking(
tenants = Seq(tenant.copy(subscriptionSecurity = Some(true))),
users = Seq(userAdmin, tenantAdmin),
teams = Seq(teamOwner, teamConsumer, defaultAdminTeam)
)
val session = loginWithBlocking(tenantAdmin, tenant)
val resp = httpJsonCallBlocking(
"/api/search",
"POST",
body = Some(
Json.obj(
"query" ->
"""
|query getAllteams($research: String, $limit: Int, $offset: Int) {
| teamsPagination(research: $research, limit: $limit, offset: $offset) {
| teams {
| _id
| _humanReadableId
| name
| avatar
| type
| }
| total
| }
| }
|""".stripMargin,
"variables" -> Json.obj(
"research" -> "",
"limit" -> 10,
"offset" -> 0
)
)
)
)(tenant, session)

resp.status mustBe 200
val result = (resp.json \ "data" \ "teamsPagination" \ "total").as[Int]
result mustBe 2

setupEnvBlocking(
tenants = Seq(tenant.copy(subscriptionSecurity = Some(false))),
users = Seq(userAdmin, tenantAdmin),
teams = Seq(teamOwner, teamConsumer, defaultAdminTeam)
)
val session2 = loginWithBlocking(tenantAdmin, tenant)
val resp2 = httpJsonCallBlocking(
"/api/search",
"POST",
body = Some(
Json.obj(
"query" ->
"""
|query getAllteams {
| teamsPagination {
| teams {
| _id
| _humanReadableId
| name
| avatar
| type
| }
| total
| }
| }
|""".stripMargin
)
)
)(tenant, session2)
resp2.status mustBe 200

val result2 = (resp2.json \ "data" \ "teamsPagination" \ "total").as[Int]
result2 mustBe 4
}
}

"a team administrator" can {
Expand Down
Loading