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

Oso does not support Kotlin data classes #1655

Open
brizzbuzz opened this issue Dec 15, 2022 · 1 comment
Open

Oso does not support Kotlin data classes #1655

brizzbuzz opened this issue Dec 15, 2022 · 1 comment

Comments

@brizzbuzz
Copy link

Hey 👋 Finally getting around to trialing Oso as an auth solution for a Kotlin application that I'm building.

However, it seems that Oso does not support Kotlin data classes :( Or, as is always possible... I'm just doing something dumb

I am trying to emulate the Java quickstart example, with a User trying to read from a repository.

I have the following models

data class Repo(
  val id: UUID,
  val name: String,
  val isPublic: Boolean
)

data class User (
  val id: UUID,
  val email: String,
  val repoRoles: List<RepoRole>
)

I have set up OSO with the following

private val oso: Oso = Oso()

init {
  // On a tangent... it doesn't seem to even load 
  // unless I explicitly repeat the class name as the second param
  oso.registerClass(Repo::class.java, "Repo")
  oso.registerClass(User::class.java, "User")
  oso.loadStr(
    """
allow(actor, action, resource) if
has_permission(actor, action, resource);

actor User {}

resource Repo {
permissions = ["read", "push", "delete"];
roles = ["contributor", "maintainer", "admin"];

"read" if "contributor";
"push" if "maintainer";
"delete" if "admin";

"maintainer" if "admin";
"contributor" if "maintainer";
}

# This rule tells Oso how to fetch roles for a Repo
has_role(actor: User, role_name: String, Repo: Repo) if
role in actor.repoRoles and
role_name = role.name and
Repo = role.Repo;

has_permission(_actor: User, "read", Repo: Repo) if
Repo.isPublic;

allow(actor, action, resource) if
has_permission(actor, action, resource);
""".trimIndent()
  )
}

Just as a test, I have created a repo with isPublic=true with name test. However, when I run the following

fun readByName(name: String): RepoModels.Response {
    val result = Repo(
      id = UUID.randomUUID(),
      name = name,
      isPublic = true
    )
    val user = User(
      id = UUID.randomUUID(),
      email = "[email protected]",
      repoRoles = listOf(RepoRole(role = "admin", repo = result))
    )
    oso.authorize(user, "read", result)
    return RepoModels.Response.fromRepo(result)
  }

I get an authorization error from oso

com.osohq.oso.Exceptions$NotFoundException: Oso NotFoundException -- The current user does not have permission to read the given resource. You should handle this error by returning a 404 error to the client.
	at com.osohq.oso.Oso.authorize(Oso.java:110)
	at com.osohq.oso.Oso.authorize(Oso.java:118)
	at io.bkbn.sourdough.api.service.RepoService.readByName(RepoService.kt:81)
        // ...

If it helps, I have pushed all of this code to a repo https://github.com/bkbnio/oso-poc Instructions in the README for how to run the app. If you have any issues with getting it set up just let me know :)

You can emulate this error by running GET localhost:8080/repo?name=test

@wcurrie
Copy link

wcurrie commented Jan 14, 2023

Out of curiosity I tried making this work in #1662.

Seems to work with some to the repo

Index: api/src/main/kotlin/io/bkbn/sourdough/api/service/RepoService.kt
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/api/src/main/kotlin/io/bkbn/sourdough/api/service/RepoService.kt b/api/src/main/kotlin/io/bkbn/sourdough/api/service/RepoService.kt
--- a/api/src/main/kotlin/io/bkbn/sourdough/api/service/RepoService.kt	(revision e4e856f304b1c09de9f2cdcdb658dce59deffab5)
+++ b/api/src/main/kotlin/io/bkbn/sourdough/api/service/RepoService.kt	(date 1673734442646)
@@ -35,10 +35,10 @@
 }
 
 # This rule tells Oso how to fetch roles for a Repo
-has_role(actor: User, role_name: String, Repo: Repo) if
+has_role(actor: User, role_name: String, repo: Repo) if
   role in actor.repoRoles and
-  role_name = role.name and
-  Repo = role.Repo;
+  role_name = role.role and
+  repo = role.repo;
 
 has_permission(_actor: User, "read", Repo: Repo) if
   Repo.isPublic;
Index: api/build.gradle.kts
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/api/build.gradle.kts b/api/build.gradle.kts
--- a/api/build.gradle.kts	(revision e4e856f304b1c09de9f2cdcdb658dce59deffab5)
+++ b/api/build.gradle.kts	(date 1673734519566)
@@ -41,7 +41,7 @@
   implementation("org.jetbrains.kotlinx:kotlinx-datetime:0.4.0")
 
   // Auth
-  implementation("com.osohq:oso:0.26.4")
+  implementation("com.osohq:oso:0.26.5-SNAPSHOT")
 }
 
 testing {

image

I used this test for faster feedback:

package io.bkbn.sourdough.api.service

import org.junit.jupiter.api.Assertions.*
import org.junit.jupiter.api.Test

internal class RepoServiceTest {
  @Test
  internal fun `can read by name`() {
    val response = RepoService.readByName("foo")
    assertEquals("foo", response.name)
  }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants