summaryrefslogtreecommitdiff
path: root/opendc-web/opendc-web-server/src/main/kotlin
diff options
context:
space:
mode:
authorFabian Mastenbroek <mail.fabianm@gmail.com>2022-10-06 23:05:27 +0200
committerFabian Mastenbroek <mail.fabianm@gmail.com>2022-10-10 12:14:50 +0200
commit2c739c4fdb5aab1d1d4480d4e233a1174bc85494 (patch)
treea0f2bab88d23277cebf54240b1cb18f8c34b0934 /opendc-web/opendc-web-server/src/main/kotlin
parent5b8dfc78496452bd23fab59e3ead84a8941da779 (diff)
feat(web/server): Add API for querying user accounting data
This change updates the Quarkus-based web server with a new endpoint for querying data about the active user including accounting data.
Diffstat (limited to 'opendc-web/opendc-web-server/src/main/kotlin')
-rw-r--r--opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/rest/user/UserResource.kt45
-rw-r--r--opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/service/UserAccountingService.kt23
-rw-r--r--opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/service/UserService.kt44
3 files changed, 111 insertions, 1 deletions
diff --git a/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/rest/user/UserResource.kt b/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/rest/user/UserResource.kt
new file mode 100644
index 00000000..d640cc08
--- /dev/null
+++ b/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/rest/user/UserResource.kt
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2022 AtLarge Research
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package org.opendc.web.server.rest.user
+
+import io.quarkus.security.identity.SecurityIdentity
+import org.opendc.web.proto.user.User
+import org.opendc.web.server.service.UserService
+import javax.annotation.security.RolesAllowed
+import javax.inject.Inject
+import javax.ws.rs.GET
+import javax.ws.rs.Path
+
+/**
+ * A resource representing the active user.
+ */
+@Path("/users")
+@RolesAllowed("openid")
+class UserResource @Inject constructor(private val userService: UserService, private val identity: SecurityIdentity) {
+ /**
+ * Get the current active user data.
+ */
+ @GET
+ @Path("me")
+ fun get(): User = userService.getUser(identity)
+}
diff --git a/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/service/UserAccountingService.kt b/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/service/UserAccountingService.kt
index 13440a81..11066bfb 100644
--- a/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/service/UserAccountingService.kt
+++ b/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/service/UserAccountingService.kt
@@ -31,6 +31,7 @@ import java.time.temporal.TemporalAdjusters
import javax.enterprise.context.ApplicationScoped
import javax.inject.Inject
import javax.persistence.EntityExistsException
+import org.opendc.web.proto.user.UserAccounting as UserAccountingDto
/**
* Service for tracking the simulation budget of users.
@@ -45,6 +46,19 @@ class UserAccountingService @Inject constructor(
private val simulationBudget: Duration
) {
/**
+ * Return the [UserAccountingDto] object for the user with the specified [userId]. If the object does not exist in the
+ * database, a default value is constructed.
+ */
+ fun getAccounting(userId: String): UserAccountingDto {
+ val accounting = repository.findForUser(userId)
+ return if (accounting != null) {
+ UserAccountingDto(accounting.periodEnd, accounting.simulationTime, accounting.simulationTimeBudget)
+ } else {
+ UserAccountingDto(getNextAccountingPeriod(), 0, simulationBudget.toSeconds().toInt())
+ }
+ }
+
+ /**
* Determine whether the user with [userId] has any remaining simulation budget.
*
* @param userId The unique identifier of the user.
@@ -67,7 +81,7 @@ class UserAccountingService @Inject constructor(
*/
fun consumeSimulationBudget(userId: String, seconds: Int): Boolean {
val today = LocalDate.now()
- val nextAccountingPeriod = today.with(TemporalAdjusters.firstDayOfNextMonth())
+ val nextAccountingPeriod = getNextAccountingPeriod(today)
val repository = repository
// We need to be careful to prevent conflicts in case of concurrency
@@ -104,4 +118,11 @@ class UserAccountingService @Inject constructor(
throw IllegalStateException("Failed to allocate consume budget due to conflict")
}
+
+ /**
+ * Helper method to find next accounting period.
+ */
+ private fun getNextAccountingPeriod(today: LocalDate = LocalDate.now()): LocalDate {
+ return today.with(TemporalAdjusters.firstDayOfNextMonth())
+ }
}
diff --git a/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/service/UserService.kt b/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/service/UserService.kt
new file mode 100644
index 00000000..39352267
--- /dev/null
+++ b/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/service/UserService.kt
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2021 AtLarge Research
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package org.opendc.web.server.service
+
+import io.quarkus.security.identity.SecurityIdentity
+import org.opendc.web.proto.user.User
+import javax.enterprise.context.ApplicationScoped
+import javax.inject.Inject
+
+/**
+ * Service for managing [User]s.
+ */
+@ApplicationScoped
+class UserService @Inject constructor(private val accounting: UserAccountingService) {
+ /**
+ * Obtain the [User] object for the specified [identity].
+ */
+ fun getUser(identity: SecurityIdentity): User {
+ val userId = identity.principal.name
+ val accounting = accounting.getAccounting(userId)
+
+ return User(userId, accounting)
+ }
+}