Http Server / Client communication #7
13 changed files with 301 additions and 213 deletions
|
@ -1,7 +1,9 @@
|
||||||
package com.faraphel.tasks_valider.connectivity.task
|
package com.faraphel.tasks_valider.connectivity.task
|
||||||
|
|
||||||
|
import com.faraphel.tasks_valider.connectivity.task.api.TaskSessionManagerApi
|
||||||
import com.faraphel.tasks_valider.connectivity.task.session.TaskSessionManager
|
import com.faraphel.tasks_valider.connectivity.task.session.TaskSessionManager
|
||||||
import com.faraphel.tasks_valider.database.TaskDatabase
|
import com.faraphel.tasks_valider.database.TaskDatabase
|
||||||
|
import com.faraphel.tasks_valider.database.api.TaskDatabaseApi
|
||||||
import fi.iki.elonen.NanoHTTPD
|
import fi.iki.elonen.NanoHTTPD
|
||||||
|
|
||||||
|
|
||||||
|
@ -16,50 +18,41 @@ class TaskServer(
|
||||||
) : NanoHTTPD(port) {
|
) : NanoHTTPD(port) {
|
||||||
private val sessionManager = TaskSessionManager() ///< the session manager
|
private val sessionManager = TaskSessionManager() ///< the session manager
|
||||||
|
|
||||||
|
private val sessionManagerApi = TaskSessionManagerApi(this.sessionManager) ///< the api of the session manager
|
||||||
|
private val databaseApi = TaskDatabaseApi(this.database) ///< the api of the database
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle an API request
|
||||||
|
* @param httpSession the http session
|
||||||
|
*/
|
||||||
override fun serve(httpSession: IHTTPSession): Response {
|
override fun serve(httpSession: IHTTPSession): Response {
|
||||||
// get the session data of the client
|
// get the session data of the client
|
||||||
val taskSession = this.sessionManager.getOrCreateSessionData(httpSession)
|
val taskSession = this.sessionManager.getOrCreateSessionData(httpSession)
|
||||||
|
|
||||||
// get the method used
|
|
||||||
val method: Method = httpSession.method
|
|
||||||
|
|
||||||
// parse the url
|
// parse the url
|
||||||
val uri: String = httpSession.uri.substring(1) // remove the first slash
|
val uri: String = httpSession.uri.substring(1) // remove the first slash
|
||||||
val uriComponents = uri.split("/")
|
val path = uri.split("/").toMutableList()
|
||||||
|
|
||||||
// get the type of the request from the uri
|
// get the type of the request from the uri
|
||||||
val requestType = uriComponents.getOrNull(0)
|
val requestType = path.removeFirstOrNull()
|
||||||
?: return newFixedLengthResponse(
|
?: return newFixedLengthResponse(
|
||||||
NanoHTTPD.Response.Status.BAD_REQUEST,
|
NanoHTTPD.Response.Status.BAD_REQUEST,
|
||||||
"text/plain",
|
"text/plain",
|
||||||
"Invalid request type"
|
"Missing request type"
|
||||||
)
|
)
|
||||||
|
|
||||||
// get the response from the correct part of the application
|
// get the response from the correct part of the application
|
||||||
val response = when (requestType) {
|
val response = when (requestType) {
|
||||||
// session requests
|
// session requests
|
||||||
"sessions" ->
|
"sessions" -> this.sessionManagerApi.handleRequest(taskSession, httpSession, path)
|
||||||
this.sessionManager.handleApiRequest(taskSession, httpSession, method)
|
|
||||||
|
|
||||||
// entities requests
|
// entities requests
|
||||||
"entities" -> {
|
"entities" -> return this.databaseApi.handleRequest(taskSession, httpSession, path)
|
||||||
val entityName = uriComponents.getOrNull(1)
|
|
||||||
?: return newFixedLengthResponse(
|
|
||||||
NanoHTTPD.Response.Status.BAD_REQUEST,
|
|
||||||
"text/plain",
|
|
||||||
"Invalid entity name"
|
|
||||||
)
|
|
||||||
|
|
||||||
// TODO(Faraphel): the uri arguments should be handled in the handleApiRequest
|
|
||||||
return this.database.handleApiRequest(taskSession, httpSession, method, entityName)
|
|
||||||
}
|
|
||||||
|
|
||||||
// invalid requests
|
// invalid requests
|
||||||
else ->
|
else ->
|
||||||
newFixedLengthResponse(
|
newFixedLengthResponse(
|
||||||
NanoHTTPD.Response.Status.BAD_REQUEST,
|
NanoHTTPD.Response.Status.BAD_REQUEST,
|
||||||
"text/plain",
|
"text/plain",
|
||||||
"Invalid request type"
|
"Unknown request type"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,139 @@
|
||||||
|
package com.faraphel.tasks_valider.connectivity.task.api
|
||||||
|
|
||||||
|
import com.faraphel.tasks_valider.connectivity.task.session.TaskPermission
|
||||||
|
import com.faraphel.tasks_valider.connectivity.task.session.TaskRole
|
||||||
|
import com.faraphel.tasks_valider.connectivity.task.session.TaskSession
|
||||||
|
import com.faraphel.tasks_valider.connectivity.task.session.TaskSessionManager
|
||||||
|
import com.google.gson.Gson
|
||||||
|
import com.google.gson.reflect.TypeToken
|
||||||
|
import fi.iki.elonen.NanoHTTPD
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* the HTTP API for the session manager
|
||||||
|
*/
|
||||||
|
class TaskSessionManagerApi(private val sessionManager: TaskSessionManager) {
|
||||||
|
private val jsonParser = Gson() ///< the json parser
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle a HTTP Api request
|
||||||
|
* @param taskSession the data of the client session
|
||||||
|
* @param httpSession the data of the http session
|
||||||
|
* @param path the path of the request
|
||||||
|
*/
|
||||||
|
fun handleRequest(
|
||||||
|
taskSession: TaskSession,
|
||||||
|
httpSession: NanoHTTPD.IHTTPSession,
|
||||||
|
path: MutableList<String>,
|
||||||
|
): NanoHTTPD.Response {
|
||||||
|
// get the target session id
|
||||||
|
val targetSessionId = path.removeFirstOrNull()
|
||||||
|
|
||||||
|
return if (targetSessionId == null) {
|
||||||
|
// no specific session targeted
|
||||||
|
this.handleRequestGeneric(taskSession, httpSession)
|
||||||
|
} else {
|
||||||
|
// a specific session is targeted
|
||||||
|
this.handleRequestSpecific(taskSession, httpSession, targetSessionId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle a request with no specific session targeted
|
||||||
|
*/
|
||||||
|
private fun handleRequestGeneric(
|
||||||
|
taskSession: TaskSession,
|
||||||
|
httpSession: NanoHTTPD.IHTTPSession,
|
||||||
|
): NanoHTTPD.Response {
|
||||||
|
when (httpSession.method) {
|
||||||
|
// get all the session data
|
||||||
|
NanoHTTPD.Method.GET -> {
|
||||||
|
// check the permission of the session
|
||||||
|
if (taskSession.role.permissions.contains(TaskPermission.READ))
|
||||||
|
return NanoHTTPD.newFixedLengthResponse(
|
||||||
|
NanoHTTPD.Response.Status.FORBIDDEN,
|
||||||
|
"text/plain",
|
||||||
|
"Forbidden"
|
||||||
|
)
|
||||||
|
|
||||||
|
// return the session data
|
||||||
|
return NanoHTTPD.newFixedLengthResponse(
|
||||||
|
NanoHTTPD.Response.Status.OK,
|
||||||
|
"application/json",
|
||||||
|
jsonParser.toJson(taskSession)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
// other action are limited
|
||||||
|
else -> {
|
||||||
|
return NanoHTTPD.newFixedLengthResponse(
|
||||||
|
NanoHTTPD.Response.Status.METHOD_NOT_ALLOWED,
|
||||||
|
"text/plain",
|
||||||
|
"Unknown method"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun handleRequestSpecific(
|
||||||
|
taskSession: TaskSession,
|
||||||
|
httpSession: NanoHTTPD.IHTTPSession,
|
||||||
|
targetSessionId: String,
|
||||||
|
): NanoHTTPD.Response {
|
||||||
|
when (httpSession.method) {
|
||||||
|
// change a specific client session data
|
||||||
|
NanoHTTPD.Method.POST -> {
|
||||||
|
// check the permission of the session
|
||||||
|
if (taskSession.role.permissions.contains(TaskPermission.ADMIN))
|
||||||
|
return NanoHTTPD.newFixedLengthResponse(
|
||||||
|
NanoHTTPD.Response.Status.FORBIDDEN,
|
||||||
|
"text/plain",
|
||||||
|
"You are not allowed to update a session"
|
||||||
|
)
|
||||||
|
|
||||||
|
// parse the content of the request
|
||||||
|
val targetSession = jsonParser.fromJson(
|
||||||
|
httpSession.inputStream.bufferedReader().readText(),
|
||||||
|
TaskSession::class.java
|
||||||
|
)
|
||||||
|
|
||||||
|
// update the session
|
||||||
|
this.sessionManager.setSessionData(targetSessionId, targetSession)
|
||||||
|
|
||||||
|
// success message
|
||||||
|
return NanoHTTPD.newFixedLengthResponse(
|
||||||
|
NanoHTTPD.Response.Status.OK,
|
||||||
|
"text/plain",
|
||||||
|
"Session updated"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
// delete the session
|
||||||
|
NanoHTTPD.Method.DELETE -> {
|
||||||
|
// check the permission of the session
|
||||||
|
if (taskSession.role.permissions.contains(TaskPermission.ADMIN))
|
||||||
|
return NanoHTTPD.newFixedLengthResponse(
|
||||||
|
NanoHTTPD.Response.Status.FORBIDDEN,
|
||||||
|
"text/plain",
|
||||||
|
"You are not allowed to delete a session"
|
||||||
|
)
|
||||||
|
|
||||||
|
// delete the target session
|
||||||
|
this.sessionManager.deleteSessionData(targetSessionId)
|
||||||
|
|
||||||
|
// success message
|
||||||
|
return NanoHTTPD.newFixedLengthResponse(
|
||||||
|
NanoHTTPD.Response.Status.OK,
|
||||||
|
"text/plain",
|
||||||
|
"Session deleted"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
// ignore other methods
|
||||||
|
else -> {
|
||||||
|
return NanoHTTPD.newFixedLengthResponse(
|
||||||
|
NanoHTTPD.Response.Status.METHOD_NOT_ALLOWED,
|
||||||
|
"text/plain",
|
||||||
|
"Invalid method"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -10,15 +10,13 @@ import java.util.*
|
||||||
* The manager for the session system
|
* The manager for the session system
|
||||||
*/
|
*/
|
||||||
class TaskSessionManager {
|
class TaskSessionManager {
|
||||||
private val jsonParser = Gson() ///< the json parser
|
|
||||||
private val jsonTypeToken = object : TypeToken<Map<String, String>>(){} ///< the json type
|
|
||||||
private val sessions = mutableMapOf<String, TaskSession>() ///< sessions specific data
|
private val sessions = mutableMapOf<String, TaskSession>() ///< sessions specific data
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new session
|
* Create a new session
|
||||||
* @param session the data for the session (optional)
|
* @param session the data for the session (optional)
|
||||||
* @param sessionId the session id to use (optional)
|
* @param sessionId the session id to use (optional)
|
||||||
* @return a new session identifiant
|
* @return a new session identifier
|
||||||
*/
|
*/
|
||||||
fun newSessionData(
|
fun newSessionData(
|
||||||
session: TaskSession = TaskSession(),
|
session: TaskSession = TaskSession(),
|
||||||
|
@ -40,14 +38,31 @@ class TaskSessionManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get data from a session identifiant
|
* Get data from a session identifier
|
||||||
* @param sessionId the identifiant of the session
|
* @param sessionId the identifier of the session
|
||||||
* @return the session data
|
* @return the session data
|
||||||
*/
|
*/
|
||||||
fun getSessionData(sessionId: String): TaskSession? {
|
fun getSessionData(sessionId: String): TaskSession? {
|
||||||
return this.sessions[sessionId]
|
return this.sessions[sessionId]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the data of a session
|
||||||
|
* @param sessionId the identifier of the session
|
||||||
|
* @param session the session data
|
||||||
|
*/
|
||||||
|
fun setSessionData(sessionId: String, session: TaskSession) {
|
||||||
|
this.sessions[sessionId] = session
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete a session
|
||||||
|
* @param sessionId the identifier of the session
|
||||||
|
*/
|
||||||
|
fun deleteSessionData(sessionId: String): TaskSession? {
|
||||||
|
return this.sessions.remove(sessionId)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get data from a http session. If it does not exist, create it.
|
* Get data from a http session. If it does not exist, create it.
|
||||||
* @param httpSession the HTTP session
|
* @param httpSession the HTTP session
|
||||||
|
@ -75,86 +90,11 @@ class TaskSessionManager {
|
||||||
response: NanoHTTPD.Response,
|
response: NanoHTTPD.Response,
|
||||||
cookies: NanoHTTPD.CookieHandler
|
cookies: NanoHTTPD.CookieHandler
|
||||||
): NanoHTTPD.Response {
|
): NanoHTTPD.Response {
|
||||||
|
// update the cookie of the user
|
||||||
cookies.set(NanoHTTPD.Cookie("sessionId", this.newSessionData()))
|
cookies.set(NanoHTTPD.Cookie("sessionId", this.newSessionData()))
|
||||||
|
// load them in the response
|
||||||
cookies.unloadQueue(response)
|
cookies.unloadQueue(response)
|
||||||
|
|
||||||
return response
|
return response
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Handle a HTTP Api request
|
|
||||||
* @param taskSession the data of the client session
|
|
||||||
* @param httpSession the data of the http session
|
|
||||||
* @param method the method used
|
|
||||||
*/
|
|
||||||
fun handleApiRequest(
|
|
||||||
taskSession: TaskSession,
|
|
||||||
httpSession: NanoHTTPD.IHTTPSession,
|
|
||||||
method: NanoHTTPD.Method
|
|
||||||
): NanoHTTPD.Response {
|
|
||||||
when (method) {
|
|
||||||
// get a client session data
|
|
||||||
NanoHTTPD.Method.GET -> {
|
|
||||||
// check the permission of the session
|
|
||||||
if (taskSession.role.permissions.contains(TaskPermission.READ))
|
|
||||||
return NanoHTTPD.newFixedLengthResponse(
|
|
||||||
NanoHTTPD.Response.Status.FORBIDDEN,
|
|
||||||
"text/plain",
|
|
||||||
"Forbidden"
|
|
||||||
)
|
|
||||||
|
|
||||||
// return the session data
|
|
||||||
return NanoHTTPD.newFixedLengthResponse(
|
|
||||||
NanoHTTPD.Response.Status.OK,
|
|
||||||
"application/json",
|
|
||||||
jsonParser.toJson(taskSession)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
// change a client session data
|
|
||||||
NanoHTTPD.Method.POST -> {
|
|
||||||
// check the permission of the session
|
|
||||||
if (taskSession.role.permissions.contains(TaskPermission.ADMIN))
|
|
||||||
return NanoHTTPD.newFixedLengthResponse(
|
|
||||||
NanoHTTPD.Response.Status.FORBIDDEN,
|
|
||||||
"text/plain",
|
|
||||||
"Forbidden"
|
|
||||||
)
|
|
||||||
|
|
||||||
// parse the content of the request
|
|
||||||
val data: Map<String, String> = jsonParser.fromJson(
|
|
||||||
httpSession.inputStream.bufferedReader().readText(),
|
|
||||||
jsonTypeToken.type
|
|
||||||
)
|
|
||||||
|
|
||||||
// update the role
|
|
||||||
data["role"]?.let { role ->
|
|
||||||
try {
|
|
||||||
taskSession.role = TaskRole.valueOf(role)
|
|
||||||
} catch (exception: IllegalArgumentException) {
|
|
||||||
return NanoHTTPD.newFixedLengthResponse(
|
|
||||||
NanoHTTPD.Response.Status.BAD_REQUEST,
|
|
||||||
"text/plain",
|
|
||||||
"Invalid role"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
// NOTE(Faraphel): does a modification on the object require updating the array ?
|
|
||||||
}
|
|
||||||
|
|
||||||
// success message
|
|
||||||
return NanoHTTPD.newFixedLengthResponse(
|
|
||||||
NanoHTTPD.Response.Status.OK,
|
|
||||||
"text/plain",
|
|
||||||
"Session updated"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// other action are limited
|
|
||||||
else -> {
|
|
||||||
return NanoHTTPD.newFixedLengthResponse(
|
|
||||||
NanoHTTPD.Response.Status.METHOD_NOT_ALLOWED,
|
|
||||||
"text/plain",
|
|
||||||
"Method not allowed"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -4,10 +4,9 @@ import androidx.room.Database
|
||||||
import androidx.room.RoomDatabase
|
import androidx.room.RoomDatabase
|
||||||
import androidx.room.TypeConverters
|
import androidx.room.TypeConverters
|
||||||
import com.faraphel.tasks_valider.connectivity.task.session.TaskPermission
|
import com.faraphel.tasks_valider.connectivity.task.session.TaskPermission
|
||||||
import com.faraphel.tasks_valider.connectivity.task.session.TaskRole
|
|
||||||
import com.faraphel.tasks_valider.connectivity.task.session.TaskSession
|
import com.faraphel.tasks_valider.connectivity.task.session.TaskSession
|
||||||
import com.faraphel.tasks_valider.database.api.*
|
import com.faraphel.tasks_valider.database.api.entities.base.BaseApi
|
||||||
import com.faraphel.tasks_valider.database.api.base.BaseApi
|
import com.faraphel.tasks_valider.database.api.entities.*
|
||||||
import com.faraphel.tasks_valider.database.converters.InstantConverter
|
import com.faraphel.tasks_valider.database.converters.InstantConverter
|
||||||
import com.faraphel.tasks_valider.database.dao.GroupDao
|
import com.faraphel.tasks_valider.database.dao.GroupDao
|
||||||
import com.faraphel.tasks_valider.database.dao.GroupStudentDao
|
import com.faraphel.tasks_valider.database.dao.GroupStudentDao
|
||||||
|
@ -44,8 +43,6 @@ import fi.iki.elonen.NanoHTTPD
|
||||||
InstantConverter::class
|
InstantConverter::class
|
||||||
)
|
)
|
||||||
abstract class TaskDatabase : RoomDatabase() {
|
abstract class TaskDatabase : RoomDatabase() {
|
||||||
// entities
|
|
||||||
|
|
||||||
abstract fun groupDao(): GroupDao
|
abstract fun groupDao(): GroupDao
|
||||||
abstract fun studentDao(): StudentDao
|
abstract fun studentDao(): StudentDao
|
||||||
abstract fun teacherDao(): TeacherDao
|
abstract fun teacherDao(): TeacherDao
|
||||||
|
@ -53,93 +50,4 @@ abstract class TaskDatabase : RoomDatabase() {
|
||||||
|
|
||||||
abstract fun groupStudentDao(): GroupStudentDao
|
abstract fun groupStudentDao(): GroupStudentDao
|
||||||
abstract fun taskGroupDao(): TaskGroupDao
|
abstract fun taskGroupDao(): TaskGroupDao
|
||||||
|
|
||||||
// api
|
|
||||||
|
|
||||||
private val api: Map<String, BaseApi> = mapOf(
|
|
||||||
"group" to GroupApi(this.groupDao()),
|
|
||||||
"student" to StudentApi(this.studentDao()),
|
|
||||||
"teacher" to TeacherApi(this.teacherDao()),
|
|
||||||
"task" to TaskApi(this.taskDao()),
|
|
||||||
|
|
||||||
"group_student" to GroupStudentApi(this.groupStudentDao()),
|
|
||||||
"task_group" to TaskGroupApi(this.taskGroupDao()),
|
|
||||||
)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* dispatch an API request
|
|
||||||
*/
|
|
||||||
fun handleApiRequest(
|
|
||||||
taskSession: TaskSession,
|
|
||||||
httpSession: NanoHTTPD.IHTTPSession,
|
|
||||||
method: NanoHTTPD.Method,
|
|
||||||
entityName: String
|
|
||||||
): NanoHTTPD.Response {
|
|
||||||
// get the correspond Api object for this entity
|
|
||||||
val entityApi = this.api[entityName]
|
|
||||||
?: return NanoHTTPD.newFixedLengthResponse(
|
|
||||||
NanoHTTPD.Response.Status.NOT_FOUND,
|
|
||||||
"text/plain",
|
|
||||||
"Invalid entity name"
|
|
||||||
)
|
|
||||||
|
|
||||||
// dispatch the request to the correct entity API
|
|
||||||
when (method) {
|
|
||||||
// check if the data is in the database
|
|
||||||
NanoHTTPD.Method.HEAD -> {
|
|
||||||
// check the permission of the session
|
|
||||||
if (taskSession.role.permissions.contains(TaskPermission.READ))
|
|
||||||
return NanoHTTPD.newFixedLengthResponse(
|
|
||||||
NanoHTTPD.Response.Status.FORBIDDEN,
|
|
||||||
"text/plain",
|
|
||||||
"Forbidden"
|
|
||||||
)
|
|
||||||
|
|
||||||
return entityApi.head(httpSession)
|
|
||||||
}
|
|
||||||
// get the data from the database
|
|
||||||
NanoHTTPD.Method.GET -> {
|
|
||||||
// check the permission of the session
|
|
||||||
if (taskSession.role.permissions.contains(TaskPermission.READ))
|
|
||||||
return NanoHTTPD.newFixedLengthResponse(
|
|
||||||
NanoHTTPD.Response.Status.FORBIDDEN,
|
|
||||||
"text/plain",
|
|
||||||
"Forbidden"
|
|
||||||
)
|
|
||||||
|
|
||||||
return entityApi.get(httpSession)
|
|
||||||
}
|
|
||||||
// insert the data into the database
|
|
||||||
NanoHTTPD.Method.POST -> {
|
|
||||||
// check the permission of the session
|
|
||||||
if (taskSession.role.permissions.contains(TaskPermission.WRITE))
|
|
||||||
return NanoHTTPD.newFixedLengthResponse(
|
|
||||||
NanoHTTPD.Response.Status.FORBIDDEN,
|
|
||||||
"text/plain",
|
|
||||||
"Forbidden"
|
|
||||||
)
|
|
||||||
|
|
||||||
return entityApi.post(httpSession)
|
|
||||||
}
|
|
||||||
// delete the data from the database
|
|
||||||
NanoHTTPD.Method.DELETE -> {
|
|
||||||
// check the permission of the session
|
|
||||||
if (taskSession.role.permissions.contains(TaskPermission.WRITE))
|
|
||||||
return NanoHTTPD.newFixedLengthResponse(
|
|
||||||
NanoHTTPD.Response.Status.FORBIDDEN,
|
|
||||||
"text/plain",
|
|
||||||
"Forbidden"
|
|
||||||
)
|
|
||||||
|
|
||||||
return entityApi.delete(httpSession)
|
|
||||||
}
|
|
||||||
// other methods are not allowed
|
|
||||||
else ->
|
|
||||||
return NanoHTTPD.newFixedLengthResponse(
|
|
||||||
NanoHTTPD.Response.Status.METHOD_NOT_ALLOWED,
|
|
||||||
"text/plain",
|
|
||||||
"Method not allowed"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,108 @@
|
||||||
|
package com.faraphel.tasks_valider.database.api
|
||||||
|
|
||||||
|
import com.faraphel.tasks_valider.connectivity.task.session.TaskPermission
|
||||||
|
import com.faraphel.tasks_valider.connectivity.task.session.TaskSession
|
||||||
|
import com.faraphel.tasks_valider.database.TaskDatabase
|
||||||
|
import com.faraphel.tasks_valider.database.api.entities.*
|
||||||
|
import com.faraphel.tasks_valider.database.api.entities.base.BaseApi
|
||||||
|
import fi.iki.elonen.NanoHTTPD
|
||||||
|
|
||||||
|
class TaskDatabaseApi(private val database: TaskDatabase) {
|
||||||
|
private val api: Map<String, BaseApi> = mapOf(
|
||||||
|
"group" to GroupApi(this.database.groupDao()),
|
||||||
|
"student" to StudentApi(this.database.studentDao()),
|
||||||
|
"teacher" to TeacherApi(this.database.teacherDao()),
|
||||||
|
"task" to TaskApi(this.database.taskDao()),
|
||||||
|
|
||||||
|
"group_student" to GroupStudentApi(this.database.groupStudentDao()),
|
||||||
|
"task_group" to TaskGroupApi(this.database.taskGroupDao()),
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* handle an API request
|
||||||
|
* @param taskSession the current user session
|
||||||
|
* @param httpSession the http session
|
||||||
|
* @param path the path of the request
|
||||||
|
*/
|
||||||
|
fun handleRequest(
|
||||||
|
taskSession: TaskSession,
|
||||||
|
httpSession: NanoHTTPD.IHTTPSession,
|
||||||
|
path: MutableList<String>
|
||||||
|
): NanoHTTPD.Response {
|
||||||
|
// get the entity name
|
||||||
|
val entityName = path.removeFirstOrNull()
|
||||||
|
?: return NanoHTTPD.newFixedLengthResponse(
|
||||||
|
NanoHTTPD.Response.Status.BAD_REQUEST,
|
||||||
|
"text/plain",
|
||||||
|
"Missing entity name"
|
||||||
|
)
|
||||||
|
|
||||||
|
// get the correspond Api object for this entity
|
||||||
|
val entityApi = this.api[entityName]
|
||||||
|
?: return NanoHTTPD.newFixedLengthResponse(
|
||||||
|
NanoHTTPD.Response.Status.NOT_FOUND,
|
||||||
|
"text/plain",
|
||||||
|
"Unknown entity name"
|
||||||
|
)
|
||||||
|
|
||||||
|
// dispatch the request to the correct entity API
|
||||||
|
when (httpSession.method) {
|
||||||
|
// check if the data is in the database
|
||||||
|
// TODO(Faraphel): should only be allowed to read data concerning the current class session
|
||||||
|
NanoHTTPD.Method.HEAD -> {
|
||||||
|
// check the permission of the session
|
||||||
|
if (taskSession.role.permissions.contains(TaskPermission.READ))
|
||||||
|
return NanoHTTPD.newFixedLengthResponse(
|
||||||
|
NanoHTTPD.Response.Status.FORBIDDEN,
|
||||||
|
"text/plain",
|
||||||
|
"Forbidden"
|
||||||
|
)
|
||||||
|
|
||||||
|
return entityApi.head(httpSession)
|
||||||
|
}
|
||||||
|
// get the data from the database
|
||||||
|
NanoHTTPD.Method.GET -> {
|
||||||
|
// check the permission of the session
|
||||||
|
if (taskSession.role.permissions.contains(TaskPermission.READ))
|
||||||
|
return NanoHTTPD.newFixedLengthResponse(
|
||||||
|
NanoHTTPD.Response.Status.FORBIDDEN,
|
||||||
|
"text/plain",
|
||||||
|
"Forbidden"
|
||||||
|
)
|
||||||
|
|
||||||
|
return entityApi.get(httpSession)
|
||||||
|
}
|
||||||
|
// insert the data into the database
|
||||||
|
NanoHTTPD.Method.POST -> {
|
||||||
|
// check the permission of the session
|
||||||
|
if (taskSession.role.permissions.contains(TaskPermission.WRITE))
|
||||||
|
return NanoHTTPD.newFixedLengthResponse(
|
||||||
|
NanoHTTPD.Response.Status.FORBIDDEN,
|
||||||
|
"text/plain",
|
||||||
|
"Forbidden"
|
||||||
|
)
|
||||||
|
|
||||||
|
return entityApi.post(httpSession)
|
||||||
|
}
|
||||||
|
// delete the data from the database
|
||||||
|
NanoHTTPD.Method.DELETE -> {
|
||||||
|
// check the permission of the session
|
||||||
|
if (taskSession.role.permissions.contains(TaskPermission.WRITE))
|
||||||
|
return NanoHTTPD.newFixedLengthResponse(
|
||||||
|
NanoHTTPD.Response.Status.FORBIDDEN,
|
||||||
|
"text/plain",
|
||||||
|
"Forbidden"
|
||||||
|
)
|
||||||
|
|
||||||
|
return entityApi.delete(httpSession)
|
||||||
|
}
|
||||||
|
// other methods are not allowed
|
||||||
|
else ->
|
||||||
|
return NanoHTTPD.newFixedLengthResponse(
|
||||||
|
NanoHTTPD.Response.Status.METHOD_NOT_ALLOWED,
|
||||||
|
"text/plain",
|
||||||
|
"Method not allowed"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
package com.faraphel.tasks_valider.database.api
|
package com.faraphel.tasks_valider.database.api.entities
|
||||||
|
|
||||||
import com.faraphel.tasks_valider.database.api.base.BaseJsonApi
|
import com.faraphel.tasks_valider.database.api.entities.base.BaseJsonApi
|
||||||
import com.faraphel.tasks_valider.database.dao.base.BaseDao
|
import com.faraphel.tasks_valider.database.dao.base.BaseDao
|
||||||
import com.faraphel.tasks_valider.database.entities.GroupEntity
|
import com.faraphel.tasks_valider.database.entities.GroupEntity
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
package com.faraphel.tasks_valider.database.api
|
package com.faraphel.tasks_valider.database.api.entities
|
||||||
|
|
||||||
import com.faraphel.tasks_valider.database.api.base.BaseJsonApi
|
import com.faraphel.tasks_valider.database.api.entities.base.BaseJsonApi
|
||||||
import com.faraphel.tasks_valider.database.dao.base.BaseDao
|
import com.faraphel.tasks_valider.database.dao.base.BaseDao
|
||||||
import com.faraphel.tasks_valider.database.entities.GroupStudentEntity
|
import com.faraphel.tasks_valider.database.entities.GroupStudentEntity
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
package com.faraphel.tasks_valider.database.api
|
package com.faraphel.tasks_valider.database.api.entities
|
||||||
|
|
||||||
import com.faraphel.tasks_valider.database.api.base.BaseJsonApi
|
import com.faraphel.tasks_valider.database.api.entities.base.BaseJsonApi
|
||||||
import com.faraphel.tasks_valider.database.dao.base.BaseDao
|
import com.faraphel.tasks_valider.database.dao.base.BaseDao
|
||||||
import com.faraphel.tasks_valider.database.entities.StudentEntity
|
import com.faraphel.tasks_valider.database.entities.StudentEntity
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
package com.faraphel.tasks_valider.database.api
|
package com.faraphel.tasks_valider.database.api.entities
|
||||||
|
|
||||||
import com.faraphel.tasks_valider.database.api.base.BaseJsonApi
|
import com.faraphel.tasks_valider.database.api.entities.base.BaseJsonApi
|
||||||
import com.faraphel.tasks_valider.database.dao.base.BaseDao
|
import com.faraphel.tasks_valider.database.dao.base.BaseDao
|
||||||
import com.faraphel.tasks_valider.database.entities.TaskEntity
|
import com.faraphel.tasks_valider.database.entities.TaskEntity
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
package com.faraphel.tasks_valider.database.api
|
package com.faraphel.tasks_valider.database.api.entities
|
||||||
|
|
||||||
import com.faraphel.tasks_valider.database.api.base.BaseJsonApi
|
import com.faraphel.tasks_valider.database.api.entities.base.BaseJsonApi
|
||||||
import com.faraphel.tasks_valider.database.dao.base.BaseDao
|
import com.faraphel.tasks_valider.database.dao.base.BaseDao
|
||||||
import com.faraphel.tasks_valider.database.entities.TaskGroupEntity
|
import com.faraphel.tasks_valider.database.entities.TaskGroupEntity
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
package com.faraphel.tasks_valider.database.api
|
package com.faraphel.tasks_valider.database.api.entities
|
||||||
|
|
||||||
import com.faraphel.tasks_valider.database.api.base.BaseJsonApi
|
import com.faraphel.tasks_valider.database.api.entities.base.BaseJsonApi
|
||||||
import com.faraphel.tasks_valider.database.dao.base.BaseDao
|
import com.faraphel.tasks_valider.database.dao.base.BaseDao
|
||||||
import com.faraphel.tasks_valider.database.entities.TeacherEntity
|
import com.faraphel.tasks_valider.database.entities.TeacherEntity
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package com.faraphel.tasks_valider.database.api.base
|
package com.faraphel.tasks_valider.database.api.entities.base
|
||||||
|
|
||||||
import fi.iki.elonen.NanoHTTPD
|
import fi.iki.elonen.NanoHTTPD
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package com.faraphel.tasks_valider.database.api.base
|
package com.faraphel.tasks_valider.database.api.entities.base
|
||||||
|
|
||||||
import com.faraphel.tasks_valider.database.dao.base.BaseDao
|
import com.faraphel.tasks_valider.database.dao.base.BaseDao
|
||||||
import com.faraphel.tasks_valider.database.entities.base.BaseEntity
|
import com.faraphel.tasks_valider.database.entities.base.BaseEntity
|
Loading…
Reference in a new issue