Skip to content

Commit

Permalink
Added Permission check to the Endpoints and moved token check to Auth…
Browse files Browse the repository at this point in the history
…Util.kt
  • Loading branch information
TheCGuyGitHub committed Jul 7, 2024
1 parent 48fa1ab commit c1f5686
Show file tree
Hide file tree
Showing 6 changed files with 98 additions and 24 deletions.
13 changes: 13 additions & 0 deletions readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<div align="center">

![GitHub Actions Workflow Status](https://img.shields.io/github/actions/workflow/status/TheCGuyGitHub/CloudNet-Rest-Module/gradle.yml)

</div>
<br clear="both">
<h1 align="center">CloudNet-Rest-Module</h2>
<h2 align="center">This is a Rest-API Module for CloudNet</h2>
<br clear="both">



Note: This is my first time using the CloudNet API and Kotlin!
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,15 @@ import eu.cloudnetservice.node.ShutdownHandler
import eu.cloudnetservice.node.command.CommandProvider
import eu.cloudnetservice.node.service.CloudServiceManager
import eu.cloudnetservice.driver.provider.ServiceTaskProvider


import io.github.thecguy.cloudnet_rest_module.commands.rest
import io.github.thecguy.cloudnet_rest_module.config.Configuration
import io.github.thecguy.cloudnet_rest_module.coroutines.AuthChecker
import io.github.thecguy.cloudnet_rest_module.utli.AuthUtil
import io.github.thecguy.cloudnet_rest_module.utli.DBManager
import io.github.thecguy.cloudnet_rest_module.utli.JsonUtils

import io.ktor.http.*
import io.ktor.server.application.*
import io.ktor.server.auth.*
Expand All @@ -29,6 +33,7 @@ import io.ktor.server.response.*
import io.ktor.server.routing.*
import jakarta.inject.Named
import jakarta.inject.Singleton
import kong.unirest.core.json.JSONObject
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import org.jetbrains.annotations.NotNull
Expand All @@ -37,11 +42,12 @@ import java.util.*

@Singleton
class CloudNet_Rest_Module : DriverModule() {
private val dbm = DBManager()
private val jsonUtils = JsonUtils()
private val dbm = DBManager()
private val jsonUtils = JsonUtils()
private val authChecker = AuthChecker()
private val authUtil = AuthUtil()
@Volatile
private var configuration: Configuration? = null
private var configuration: Configuration? = null


@ModuleTask(order = 127, lifecycle = ModuleLifeCycle.LOADED)
Expand Down Expand Up @@ -79,7 +85,7 @@ class CloudNet_Rest_Module : DriverModule() {
)
dbm.dbexecute("CREATE TABLE IF NOT EXISTS cloudnet_rest_users (id SERIAL PRIMARY KEY, user TEXT, password TEXT)")
dbm.dbexecute("CREATE TABLE IF NOT EXISTS cloudnet_rest_permission (id SERIAL PRIMARY KEY, user TEXT, permission TEXT)")
dbm.dbexecute("CREATE TABLE IF NOT EXISTS cloudnet_rest_auths (id SERIAL PRIMARY KEY, type TEXT, value TEXT, timestamp TEXT)")
dbm.dbexecute("CREATE TABLE IF NOT EXISTS cloudnet_rest_auths (id SERIAL PRIMARY KEY, type TEXT, value TEXT, timestamp TEXT, user TEXT)")
dbm.dbexecute("DELETE FROM cloudnet_rest_auths")
authChecker.schedule()
}
Expand All @@ -96,7 +102,7 @@ class CloudNet_Rest_Module : DriverModule() {
GlobalScope.launch {
main(cloudServiceManager, shutdownHandler, serviceTaskProvider)
}
println("Rest API listening on port {configuration!!.restapi_port}!")
println("Rest API listening on port ${configuration!!.restapi_port}!")
}
@ModuleTask(lifecycle = ModuleLifeCycle.STARTED)
fun start(commandProvider: CommandProvider) {
Expand Down Expand Up @@ -146,20 +152,23 @@ class CloudNet_Rest_Module : DriverModule() {
}

routing {

swaggerUI(path = "swagger", swaggerFile = "openapi/swagger.yaml")
authenticate("auth-basic") {
get("/auth") {
call.respond(jsonUtils.token().toString(4))
call.respond(jsonUtils.token(call.principal<UserIdPrincipal>()?.name.toString()).toString(4))
}
}
//val token = call.request.headers["Authorization"]
//if (authUtil.authToken(token.toString(), "cloudnet.rest.services")) {
//} else {
// call.response.status(HttpStatusCode.Unauthorized)
//}

//services
get("/services") {
val services = jsonUtils.services(cloudServiceManager)
val tokens = dbm.tokens()
val rToken = call.request.headers["Authorization"]
if (tokens.contains(rToken)) {
val token = call.request.headers["Authorization"]
if (authUtil.authToken(token.toString(), "cloudnet.rest.services")) {
call.respondText(
services.toString(4)
.replace("[", "")
Expand All @@ -168,16 +177,17 @@ class CloudNet_Rest_Module : DriverModule() {
} else {
call.response.status(HttpStatusCode.Unauthorized)
}

}

get("/services/{service}") {
val services = cloudServiceManager.services().map { it.name() }.toList()
val serv = services.contains(call.parameters["service"])
val tokens = dbm.tokens()
val rToken = call.request.headers["Authorization"]
if (tokens.contains(rToken)) {

val token = call.request.headers["Authorization"]
if (authUtil.authToken(token.toString(), "cloudnet.rest.service")) {
if (serv) {
call.respond(jsonUtils.service(cloudServiceManager, call.parameters["service"].toString()).toString(4))
call.respond(jsonUtils.service(cloudServiceManager, call.parameters["service"].toString()).toString(4))
} else {
call.response.status(HttpStatusCode.NotFound)
}
Expand All @@ -188,9 +198,8 @@ class CloudNet_Rest_Module : DriverModule() {

//tasks
get("/tasks") {
val tokens = dbm.tokens()
val rToken = call.request.headers["Authorization"]
if (tokens.contains(rToken)) {
val token = call.request.headers["Authorization"]
if (authUtil.authToken(token.toString(), "cloudnet.rest.tasks")) {
call.respond(jsonUtils.tasks(serviceTaskProvider).toString(4))
} else {
call.response.status(HttpStatusCode.Unauthorized)
Expand All @@ -200,9 +209,9 @@ class CloudNet_Rest_Module : DriverModule() {
get("/tasks/{task}") {
val tasks = serviceTaskProvider.serviceTasks().map { it.name() }.toList()
val tas = tasks.contains(call.parameters["task"])
val tokens = dbm.tokens()
val rToken = call.request.headers["Authorization"]
if (tokens.contains(rToken)) {

val token = call.request.headers["Authorization"]
if (authUtil.authToken(token.toString(), "cloudnet.rest.task")) {
if (tas) {
call.respond(jsonUtils.task(serviceTaskProvider, call.parameters["task"].toString()))
} else {
Expand All @@ -212,8 +221,22 @@ class CloudNet_Rest_Module : DriverModule() {
call.response.status(HttpStatusCode.Unauthorized)
}
}
delete("/tasks/{task}") {
val tasks = serviceTaskProvider.serviceTasks().map { it.name() }.toList()
val tas = tasks.contains(call.parameters["task"])


val token = call.request.headers["Authorization"]
if (authUtil.authToken(token.toString(), "cloudnet.rest.task.delete")) {
if (tas) {
serviceTaskProvider.removeServiceTask(serviceTaskProvider.serviceTask(call.parameters["task"].toString())!!)
call.response.status(HttpStatusCode.OK)
} else {
call.response.status(HttpStatusCode.NotFound)
}
} else {
call.response.status(HttpStatusCode.Unauthorized)
}
}



Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import java.security.SecureRandom


class AuthUtil internal constructor() {

val dbManager = DBManager()

init {

Expand All @@ -24,6 +24,29 @@ class AuthUtil internal constructor() {
return token.toString()
}

fun authUser(user: String, permission: String) {

}

fun authToken(token: String, permission: String): Boolean {
return if (validToken(token)) {
val user = dbManager.tokenToUser(token)
val perms = dbManager.cmd_rest_perms(user)
if (perms.contains(permission) || perms.contains("*")) {
true
} else {
false
}
} else {
false
}
}

private fun validToken(token: String): Boolean {
val tokens = dbManager.tokens()
return tokens.contains(token)
}

companion object {
private var instance: AuthUtil? = null
fun getInstance(): AuthUtil {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,20 @@ class DBManager internal constructor() {
return exprList
}

fun tokenToUser(token: String): String {
var user = ""
ds.connection.use { connection ->
connection.prepareStatement("SELECT user FROM cloudnet_rest_auths WHERE value = '$token'").use { statement ->
statement.executeQuery().use { resultSet ->
if (resultSet.next()) {
user = resultSet.getString("user").toString()
}
}
}
}
return user
}



fun cmd_rest_users(): List<String> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package io.github.thecguy.cloudnet_rest_module.utli

import eu.cloudnetservice.driver.provider.ServiceTaskProvider
import eu.cloudnetservice.node.service.CloudServiceManager
import io.github.thecguy.cloudnet_rest_module.config.Configuration
import kong.unirest.core.json.JSONArray
import kong.unirest.core.json.JSONObject
import org.jetbrains.annotations.NotNull
Expand Down Expand Up @@ -153,7 +154,7 @@ class JsonUtils internal constructor() {



fun token():JSONObject {
fun token(user: String):JSONObject {
val token = JSONObject()
val ttoken = authUtil.generateToken(256)
val date = Date(System.currentTimeMillis() + 600000)
Expand All @@ -163,7 +164,7 @@ class JsonUtils internal constructor() {
} else {
token.put("token", ttoken)
token.put("expire_date", date)
dbManager.dbexecute("INSERT INTO cloudnet_rest_auths (type, value, timestamp) VALUES ('QUERY', '$ttoken', '$date')")
dbManager.dbexecute("INSERT INTO cloudnet_rest_auths (type, value, timestamp, user) VALUES ('QUERY', '$ttoken', '$date', '$user')")
}
println(dbManager.tokensDate())
return token
Expand Down
Empty file.

0 comments on commit c1f5686

Please sign in to comment.