Skip to content

Commit

Permalink
Merge pull request #231 from RADAR-base/release-4.3.0
Browse files Browse the repository at this point in the history
Release 4.3.0
  • Loading branch information
blootsvoets authored Mar 23, 2023
2 parents ffa1914 + 1cbba97 commit 24d5b46
Show file tree
Hide file tree
Showing 33 changed files with 130 additions and 110 deletions.
5 changes: 1 addition & 4 deletions .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ root = true
# Change these settings to your own preference
indent_style = space
indent_size = 4
continuation_indent_size = 8

# We recommend you to keep these unchanged
end_of_line = lf
Expand All @@ -17,13 +16,11 @@ trim_trailing_whitespace = true
insert_final_newline = true

[*.kt]
continuation_indent_size = 4
disabled_rules=no-wildcard-imports
ktlint_standard_no-wildcard-imports=disabled

[*.md]
trim_trailing_whitespace = false

[*.{json,yaml,yml}]
indent_style = space
indent_size = 2
continuation_indent_size = 4
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,4 @@ local.properties
/.nb-gradle/

/src/main/docker/etc/rest_source_clients_configs.yml
.DS_Store
Original file line number Diff line number Diff line change
Expand Up @@ -67,12 +67,12 @@ data class RegistrationResponse(
)

data class DeregistrationsDTO(
val deregistrations: List<DeregistrationParams>
val deregistrations: List<DeregistrationParams>,
)

data class DeregistrationParams(
val userId: String,
val userAccessToken: String
val userAccessToken: String,
)

data class RequestTokenPayload(
Expand Down Expand Up @@ -118,7 +118,7 @@ data class RestSourceUserDTO(

data class RestSourceUsers(
val users: List<RestSourceUserDTO>,
val metadata: Page?
val metadata: Page?,
)

data class TokenDTO(
Expand All @@ -129,7 +129,7 @@ data class TokenDTO(
data class Page(
val pageNumber: Int = 1,
val pageSize: Int = Integer.MAX_VALUE,
val totalElements: Long? = null
val totalElements: Long? = null,
) {
val offset: Int
get() = (this.pageNumber - 1) * this.pageSize
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ fun MPProject.toProject() = Project(
id = id,
name = name,
location = location,
organization = organization,
organization = organization?.id,
description = description,
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,6 @@ class RestSourceClientMapper {
}

fun fromSourceClientConfigs(clientConfigs: List<RestSourceClient>) = ShareableClientDetails(
sourceClients = clientConfigs.map { toSourceClientConfig(it) }
sourceClients = clientConfigs.map { toSourceClientConfig(it) },
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ class RestSourceUserMapper(
) {
fun fromEntity(user: RestSourceUser): RestSourceUserDTO {
val mpUser = user.projectId?.let { p ->
user.userId?.let { u -> projectService.getUser(p, u) }
user.userId?.let { u -> projectService.subject(p, u) }
}
return RestSourceUserDTO(
id = user.id.toString(),
Expand All @@ -44,12 +44,12 @@ class RestSourceUserMapper(
startDate = user.startDate,
serviceUserId = user.externalUserId,
version = user.version,
timesReset = user.timesReset
timesReset = user.timesReset,
)
}

fun fromRestSourceUsers(records: List<RestSourceUser>, page: Page?) = RestSourceUsers(
users = records.map(::fromEntity),
metadata = page
metadata = page,
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
import org.radarbase.authorizer.enhancer.ManagementPortalEnhancerFactory
import org.radarbase.jersey.enhancer.EnhancerFactory
import java.net.URI
import java.time.Duration
import kotlin.time.Duration.Companion.days

data class AuthorizerServiceConfig(
val baseUri: URI = URI.create("http://0.0.0.0:8080/rest-sources/backend/"),
Expand All @@ -16,7 +16,7 @@ data class AuthorizerServiceConfig(
val syncProjectsIntervalMin: Long = 30,
val syncParticipantsIntervalMin: Long = 30,
val tokenExpiryTimeInMinutes: Long = 15,
val persistentTokenExpiryInMin: Long = Duration.ofDays(3).toMinutes(),
val persistentTokenExpiryInMin: Long = 3.days.inWholeMinutes,
) {
val callbackUrl: HttpUrl by lazy {
val frontendBaseUrlBuilder = when {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,24 +11,25 @@ import org.radarbase.authorizer.util.Hmac256Secret
import org.radarbase.authorizer.util.Hmac256Secret.Companion.encodeToBase64
import org.radarbase.authorizer.util.Hmac256Secret.Companion.randomize
import org.radarbase.jersey.hibernate.HibernateRepository
import java.time.Duration
import java.time.Instant
import kotlin.time.Duration.Companion.minutes

class RegistrationRepository(
@Context private val config: AuthorizerConfig,
@Context em: Provider<EntityManager>,
) : HibernateRepository(em) {

private val tokenExpiryTime = Duration.ofMinutes(config.service.tokenExpiryTimeInMinutes)
private val persistentTokenExpiryTime = Duration.ofMinutes(config.service.persistentTokenExpiryInMin)
private val tokenExpiryTime = config.service.tokenExpiryTimeInMinutes.minutes
private val persistentTokenExpiryTime = config.service.persistentTokenExpiryInMin.minutes

fun generate(
user: RestSourceUser,
secret: Hmac256Secret?,
persistent: Boolean,
): RegistrationState? {
val createdAt = Instant.now()
val expiresAt = createdAt + if (persistent) persistentTokenExpiryTime else tokenExpiryTime
val expiryTime = if (persistent) persistentTokenExpiryTime else tokenExpiryTime
val expiresAt = createdAt.plusMillis(expiryTime.inWholeMilliseconds)
val numberOfBytes = if (persistent) 18 else 9
return randomStrings(numberOfBytes)
.take(10)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ class RestSourceUserRepositoryImpl(
WHERE u.sourceType = :sourceType
AND u.userId = :userId
""".trimIndent(),
RestSourceUser::class.java
RestSourceUser::class.java,
)
.setParameter("sourceType", user.sourceType)
.setParameter("userId", user.userId)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ class RestSourceUser(
fetch = FetchType.EAGER,
targetEntity = RegistrationState::class,
cascade = [CascadeType.REMOVE],
mappedBy = "user"
mappedBy = "user",
)
@Fetch(FetchMode.SELECT)
@BatchSize(size = 2)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ class AuthorizerResourceEnhancer(
.onEach {
requireNotNull(it.clientId) { "Client ID of ${it.sourceType} is missing" }
requireNotNull(it.clientSecret) { "Client secret of ${it.sourceType} is missing" }
}
},
)

override val classes: Array<Class<*>>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@ import java.util.concurrent.TimeUnit
@Provider
@Singleton
class RegistrationLifecycleManager(
@BackgroundScheduler @Context private val executor: ScheduledExecutorService,
@BackgroundScheduler
@Context
private val executor: ScheduledExecutorService,
@Context private val entityManagerFactory: EntityManagerFactory,
@Context private val config: AuthorizerConfig,
) : ApplicationEventListener {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import jakarta.annotation.Resource
import jakarta.inject.Singleton
import jakarta.ws.rs.*
import jakarta.ws.rs.core.Context
import jakarta.ws.rs.core.HttpHeaders.AUTHORIZATION
import jakarta.ws.rs.core.MediaType
import org.radarbase.auth.authorization.Permission
import org.radarbase.authorizer.api.*
Expand All @@ -41,28 +42,28 @@ class ProjectResource(
) {

@GET
@NeedsPermission(Permission.Entity.PROJECT, Permission.Operation.READ)
@Cache(maxAge = 300, isPrivate = true)
@NeedsPermission(Permission.PROJECT_READ)
@Cache(maxAge = 300, isPrivate = true, vary = [AUTHORIZATION])
fun projects() = ProjectList(
projectService.userProjects(auth)
.map { it.toProject() }
.map { it.toProject() },
)

@GET
@Path("{projectId}/users")
@NeedsPermission(Permission.Entity.SUBJECT, Permission.Operation.READ, "projectId")
@Cache(maxAge = 60, isPrivate = true)
@NeedsPermission(Permission.SUBJECT_READ, "projectId")
@Cache(maxAge = 60, isPrivate = true, vary = [AUTHORIZATION])
fun users(
@PathParam("projectId") projectId: String,
) = UserList(
projectService.projectUsers(projectId)
.map { it.toUser() }
projectService.projectSubjects(projectId)
.map { it.toUser() },
)

@GET
@Path("{projectId}")
@NeedsPermission(Permission.Entity.PROJECT, Permission.Operation.READ, "projectId")
@Cache(maxAge = 300, isPrivate = true)
@NeedsPermission(Permission.PROJECT_READ, "projectId")
@Cache(maxAge = 300, isPrivate = true, vary = [AUTHORIZATION])
fun project(@PathParam("projectId") projectId: String): Project {
return projectService.project(projectId).toProject()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ class RegistrationResource(
) {
@POST
@Authenticated
@NeedsPermission(entity = Permission.Entity.SUBJECT, operation = Permission.Operation.UPDATE)
@NeedsPermission(Permission.SUBJECT_UPDATE)
fun createState(
@Context auth: Auth,
createState: StateCreateDTO,
Expand Down Expand Up @@ -77,7 +77,7 @@ class RegistrationResource(

@DELETE
@Authenticated
@NeedsPermission(entity = Permission.Entity.SUBJECT, operation = Permission.Operation.UPDATE)
@NeedsPermission(Permission.SUBJECT_UPDATE)
@Path("{token}")
fun deleteState(
@PathParam("token") token: String,
Expand Down Expand Up @@ -108,7 +108,7 @@ class RegistrationResource(
authEndpointUrl = authorizationService.getAuthorizationEndpointWithParams(
sourceType = registration.user.sourceType,
userId = registration.user.id!!,
state = registration.token
state = registration.token,
),
userId = registration.user.id!!.toString(),
project = project,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import jakarta.annotation.Resource
import jakarta.inject.Singleton
import jakarta.ws.rs.*
import jakarta.ws.rs.core.Context
import jakarta.ws.rs.core.HttpHeaders
import jakarta.ws.rs.core.MediaType
import jakarta.ws.rs.core.Response
import org.radarbase.auth.authorization.Permission
Expand Down Expand Up @@ -52,14 +53,20 @@ class RestSourceUserResource(
@Context private val userService: RestSourceUserService,
) {
@GET
@NeedsPermission(Permission.Entity.SUBJECT, Permission.Operation.READ)
@NeedsPermission(Permission.SUBJECT_READ)
fun query(
@QueryParam("project-id") projectId: String?,
@QueryParam("source-type") sourceType: String?,
@QueryParam("search") search: String?,
@DefaultValue("true") @QueryParam("authorized") isAuthorized: String,
@DefaultValue(Integer.MAX_VALUE.toString()) @QueryParam("size") pageSize: Int,
@DefaultValue("1") @QueryParam("page") pageNumber: Int,
@DefaultValue("true")
@QueryParam("authorized")
isAuthorized: String,
@DefaultValue(Integer.MAX_VALUE.toString())
@QueryParam("size")
pageSize: Int,
@DefaultValue("1")
@QueryParam("page")
pageNumber: Int,
): RestSourceUsers {
val projectIds = if (projectId == null) {
projectService.userProjects(auth, Permission.SUBJECT_READ)
Expand All @@ -81,18 +88,18 @@ class RestSourceUserResource(
val sanitizedSearch = search?.takeIf { it.length >= 2 }

val userIds = if (sanitizedSearch != null) {
if (projectId == null) {
throw HttpBadRequestException(
"missing_project_id",
"Cannot search without a fixed project ID.",
)
}
projectService.projectUsers(projectId)
projectId ?: throw HttpBadRequestException(
"missing_project_id",
"Cannot search without a fixed project ID.",
)
projectService.projectSubjects(projectId)
.mapNotNull { sub ->
val externalId = sub.externalId ?: return@mapNotNull null
sub.id.takeIf { sanitizedSearch in externalId }
}
} else emptyList()
} else {
emptyList()
}

val authorizedBoolean = when (isAuthorized) {
"true", "yes" -> true
Expand All @@ -114,7 +121,7 @@ class RestSourceUserResource(
}

@POST
@NeedsPermission(Permission.Entity.SUBJECT, Permission.Operation.CREATE)
@NeedsPermission(Permission.SUBJECT_CREATE)
fun create(
userDto: RestSourceUserDTO,
): Response {
Expand All @@ -127,47 +134,47 @@ class RestSourceUserResource(

@POST
@Path("{id}")
@NeedsPermission(Permission.Entity.SUBJECT, Permission.Operation.UPDATE)
@NeedsPermission(Permission.SUBJECT_UPDATE)
fun update(
@PathParam("id") userId: Long,
user: RestSourceUserDTO,
): RestSourceUserDTO = userService.update(userId, user)

@GET
@Path("{id}")
@NeedsPermission(Permission.Entity.SUBJECT, Permission.Operation.READ)
@Cache(maxAge = 300, isPrivate = true)
@NeedsPermission(Permission.SUBJECT_READ)
@Cache(maxAge = 300, isPrivate = true, vary = [HttpHeaders.AUTHORIZATION])
fun readUser(@PathParam("id") userId: Long): RestSourceUserDTO = userService.get(userId)

@DELETE
@Path("{id}")
@NeedsPermission(Permission.Entity.SUBJECT, Permission.Operation.UPDATE)
@NeedsPermission(Permission.SUBJECT_UPDATE)
fun deleteUser(@PathParam("id") userId: Long): Response {
userService.delete(userId)
return Response.noContent().header("user-removed", userId).build()
}

@POST
@Path("{id}/reset")
@NeedsPermission(Permission.Entity.SUBJECT, Permission.Operation.UPDATE)
@NeedsPermission(Permission.SUBJECT_UPDATE)
fun reset(
@PathParam("id") userId: Long,
user: RestSourceUserDTO,
): RestSourceUserDTO = userService.reset(userId, user)

@GET
@Path("{id}/token")
@NeedsPermission(Permission.Entity.MEASUREMENT, Permission.Operation.CREATE)
@NeedsPermission(Permission.MEASUREMENT_CREATE)
fun requestToken(@PathParam("id") userId: Long): TokenDTO = userService.ensureToken(userId)

@POST
@Path("{id}/token")
@NeedsPermission(Permission.Entity.MEASUREMENT, Permission.Operation.CREATE)
@NeedsPermission(Permission.MEASUREMENT_CREATE)
fun refreshToken(@PathParam("id") userId: Long): TokenDTO = userService.refreshToken(userId)

@POST
@Path("{id}/token/sign")
@NeedsPermission(Permission.Entity.MEASUREMENT, Permission.Operation.READ)
@NeedsPermission(Permission.MEASUREMENT_READ)
fun signRequest(
@PathParam("id") userId: Long,
payload: SignRequestParams,
Expand Down
Loading

0 comments on commit 24d5b46

Please sign in to comment.