Skip to content

Commit

Permalink
#42 /token/generate now has optional param groups-prefix, e.g.
Browse files Browse the repository at this point in the history
`{{ls_host}}/token/generate?groups-prefix=pam`
  • Loading branch information
dk1844 committed Aug 24, 2023
1 parent 07fd00e commit dd391aa
Show file tree
Hide file tree
Showing 5 changed files with 46 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@ package za.co.absa.loginsvc.rest.controller

import com.fasterxml.jackson.annotation.JsonProperty
import io.swagger.v3.oas.annotations.Operation
import io.swagger.v3.oas.annotations.media.{ArraySchema, Content, ExampleObject, Schema}
import io.swagger.v3.oas.annotations.media.Schema.RequiredMode
import io.swagger.v3.oas.annotations.responses.{ApiResponse, ApiResponses}
import io.swagger.v3.oas.annotations.media.{Content, ExampleObject, Schema}
import io.swagger.v3.oas.annotations.responses.ApiResponse
import io.swagger.v3.oas.annotations.security.SecurityRequirement
import io.swagger.v3.oas.annotations.tags.{Tag, Tags}
import org.springframework.beans.factory.annotation.Autowired
Expand All @@ -29,9 +29,10 @@ import org.springframework.security.core.Authentication
import org.springframework.web.bind.annotation._
import za.co.absa.loginsvc.model.User
import za.co.absa.loginsvc.rest.service.JWTService
import za.co.absa.loginsvc.utils.OptionExt.ImplicitOptionExt

import java.util.Base64
import java.util.concurrent.CompletableFuture
import java.util.{Base64, Optional}
import scala.concurrent.Future


Expand Down Expand Up @@ -76,9 +77,16 @@ class TokenController @Autowired()(jwtService: JWTService) {
)
@ResponseStatus(HttpStatus.OK)
@SecurityRequirement(name = "basicAuth")
def generateToken(authentication: Authentication): CompletableFuture[TokenWrapper] = {
val principal = authentication.getPrincipal.asInstanceOf[User]
val jwt = jwtService.generateToken(principal)
def generateToken(authentication: Authentication, @RequestParam("groups-prefix") optionalGroupsPrefix: Optional[String]): CompletableFuture[TokenWrapper] = {
val user = authentication.getPrincipal.asInstanceOf[User]
val groupsPrefix = optionalGroupsPrefix.toScalaOption

val filteredGroupsUser = groupsPrefix.applyIfDefined(user, { (user: User, prefix) =>
val filteredGroups = user.groups.filter(_.startsWith(prefix))
user.copy(groups = filteredGroups)
})

val jwt = jwtService.generateToken(filteredGroupsUser)
Future.successful(TokenWrapper(jwt))
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,10 @@ object OptionExt {
}
}

implicit class ImplicitOptionExt[OptType](val opt: Option[OptType]) extends AnyVal {
def applyIfDefined[TargetType](target: TargetType, fn: (TargetType, OptType) => TargetType): TargetType = {
OptionExt.applyIfDefined(target, opt, fn)
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import java.util

object FakeAuthentication {

val fakeUser: User = User("fakeUser", Some("[email protected]"), Some("Fake Name"), Seq.empty)
val fakeUser: User = User("fakeUser", Some("[email protected]"), Some("Fake Name"), Seq("fake-group1", "second-fake-group"))

val fakeUserAuthentication: Authentication = new UsernamePasswordAuthenticationToken(
fakeUser, "fakePassword", new util.ArrayList[GrantedAuthority]()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,20 @@ class TokenControllerTest extends AnyFlatSpec with ControllerIntegrationTestBase
)(FakeAuthentication.fakeUserAuthentication)
}

it should "return token generated by mocked JWTService for the authenticated user with groups-prefix" in {
val fakeJWT = "abc.fakeJWTToken.abc"

// `groups-prefix` fill change the groups in user object passed to the jwtService.generateToken
val fakeUserFilteredGroups = FakeAuthentication.fakeUser.copy(groups = Seq("fake-group1"))
when(jwtService.generateToken(fakeUserFilteredGroups)).thenReturn(fakeJWT)

assertOkAndResultBodyJsonEquals(
"/token/generate?groups-prefix=fake",
Post(),
s"""{"token": "$fakeJWT"}"""
)(FakeAuthentication.fakeUserAuthentication)
}

it should "fail for anonymous (not authenticated) user" in {
val fakeJWT = "abc.fakeJWTToken.abc"
when(jwtService.generateToken(any[User]())).thenReturn(fakeJWT)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,18 @@ class OptionExtTest extends AnyFlatSpec with Matchers {
OptionExt.applyIfDefined(1, Some(2), (a:Int, b: Int) => a + b) shouldBe 3
}

"OptionExt.applyIfDefined" should "not apply fn if empty" in {
it should "not apply fn if empty" in {
OptionExt.applyIfDefined(1, None, (a: Int, b: Int) => a + b) shouldBe 1
}

import OptionExt.ImplicitOptionExt

"OptionExt.ImplicitOptionExt" should "apply fn correctly if defined" in {
Some(2).applyIfDefined(1, (a: Int, b: Int) => a + b) shouldBe 3
}

it should "not apply fn if empty" in {
None.applyIfDefined(1, (a: Int, b: Int) => a + b) shouldBe 1
}

}

0 comments on commit dd391aa

Please sign in to comment.