Compare commits

..

5 Commits

Author SHA1 Message Date
af2b7cea6d modifica tipi ID
da integer a long
2025-02-21 17:32:39 +01:00
488cab4ac7 Merge remote-tracking branch 'upstream/dev' into 0002343-endpoint-tessere 2025-02-18 16:07:53 +01:00
8e417f02f2 /tessere
uso del metodo authenticate per la verifica della validità del JWT
2025-02-18 16:02:41 +01:00
728eca6dd6 Merge remote-tracking branch 'upstream/dev' into 0002343-endpoint-tessere 2025-02-18 12:55:00 +01:00
e3fc1f73b7 prima implementazione
mapping e repository
2025-02-18 09:22:59 +01:00
13 changed files with 131 additions and 71 deletions

1
.gitignore vendored
View File

@ -41,4 +41,3 @@ bin/
### Mac OS ###
.DS_Store
.idea/.name
*.log

View File

@ -9,10 +9,6 @@ plugins {
kotlin("plugin.serialization") version "1.9.23" // Aggiungi il plugin di Serialization
}
application {
mainClass.set("eu.maiora.ApplicationKt")
}
group = "org.maiora"
version = "1.0-SNAPSHOT"

View File

@ -1,5 +1,5 @@
plugins {
id("org.gradle.toolchains.foojay-resolver-convention") version "0.5.0"
}
rootProject.name = "Backend_API"
rootProject.name = "Backend_API_DSU"

View File

@ -9,26 +9,21 @@ import io.ktor.server.engine.*
import io.ktor.server.netty.*
import io.ktor.server.plugins.callloging.*
import io.ktor.server.plugins.cors.routing.*
import java.io.FileInputStream
import java.util.*
fun main() {
val properties = loadConfig()
val port = properties.getProperty("server.port").toInt()
embeddedServer(Netty, port = port, host = "0.0.0.0") {
module(properties)
}.start(wait = true)
embeddedServer(Netty, port = 8098, host = "0.0.0.0", module = Application::module)
.start(wait = true)
}
fun Application.module(configFile: Properties) {
fun Application.module() {
val config = ApplicationConfig("application.conf")
val dbUrl = configFile.getProperty("ktor.database.url")
val username = configFile.getProperty("ktor.database.username")
val password = configFile.getProperty("ktor.database.password")
val dbUrl = config.property("ktor.database.url").getString()
val username = config.property("ktor.database.username").getString()
val password = config.property("ktor.database.password").getString()
val secret = config.property("ktor.jwt.secret").getString()
configureDatabases(dbUrl, username, password)
configureSecurity(secret)
configureRouting()
configureRouting(dbUrl, username, password)
configureSerialization()
install(CallLogging)
@ -44,10 +39,3 @@ fun Application.module(configFile: Properties) {
allowMethod(HttpMethod.Delete)
}
}
fun loadConfig(): Properties {
val properties = Properties()
val inputStream = FileInputStream("/home/backend_api/config.properties")
properties.load(inputStream)
return properties
}

View File

@ -3,6 +3,7 @@ package eu.maiora.db
import com.fasterxml.jackson.databind.deser.impl.CreatorCandidate.Param
import eu.maiora.model.Accounts
import eu.maiora.model.Parametri
import eu.maiora.model.Tessere
import kotlinx.coroutines.Dispatchers
import org.jetbrains.exposed.dao.IntEntity
import org.jetbrains.exposed.dao.IntEntityClass
@ -27,6 +28,17 @@ object ParametriTable : IdTable<Int>("parametri"){
override val primaryKey = PrimaryKey(id)
}
object TessereTable : IdTable<Long>("view_tessere_api"){
override val id = long("id").entityId()
val idUtente = long("id_utente")
val codiceFiscale = varchar("codice_fiscale", 255)
val numero = varchar("numero", 255)
val saldo = double("saldo")
val punti = integer("punti")
override val primaryKey = PrimaryKey(id)
}
class AccountsDAO(id: EntityID<Int>) :IntEntity(id) {
companion object : IntEntityClass<AccountsDAO>(AccountsTable)
@ -41,6 +53,16 @@ class ParametriDAO(id: EntityID<Int>) :IntEntity(id) {
var valore by ParametriTable.valore
}
class TessereDao(id: EntityID<Long>) :LongEntity(id) {
companion object : LongEntityClass<TessereDao>(TessereTable)
var idUtente by TessereTable.idUtente
var codiceFiscale by TessereTable.codiceFiscale
var numero by TessereTable.numero
var saldo by TessereTable.saldo
var punti by TessereTable.punti
}
fun accountsDaoToModel(dao: AccountsDAO) = Accounts(
dao.id.value,
@ -54,6 +76,15 @@ fun parametriDaoToModel(dao: ParametriDAO) = Parametri(
dao.valore
)
fun tessereDaoToModel(dao: TessereDao) = Tessere(
dao.id.value,
dao.idUtente,
dao.codiceFiscale,
dao.numero,
dao.saldo,
dao.punti
)
suspend fun <T> suspendTransaction(block: Transaction.() -> T): T =
newSuspendedTransaction(Dispatchers.IO, statement = block)

View File

@ -0,0 +1,13 @@
package eu.maiora.model
import kotlinx.serialization.Serializable
@Serializable
data class Tessere(
val id: Long,
val idUtente : Long,
val codiceFiscale : String,
val numero : String,
val saldo : Double,
val punti : Int
)

View File

@ -0,0 +1,5 @@
package eu.maiora.model
interface TessereRepository {
suspend fun tesseraByCodiceFiscale(cf : String): Tessere?
}

View File

@ -0,0 +1,13 @@
package eu.maiora.model
import eu.maiora.db.*
class TessereRepositoryImpl : TessereRepository {
override suspend fun tesseraByCodiceFiscale(cf: String): Tessere? = suspendTransaction {
// Cerca tessere in base al codice fiscale
TessereDao.find { TessereTable.codiceFiscale eq cf }
.singleOrNull() // Restituisce un singolo risultato o null se non trovato
?.let { tessereDaoToModel(it) } // Converte il DAO in un oggetto Tessere
}
}

View File

@ -1,17 +1,26 @@
package eu.maiora.plugins
//import eu.maiora.model.LogScriptRepositoryImpl
//import eu.maiora.routes.analizzaURLRoute
//import eu.maiora.routes.eseguiScriptSQLRoute
//import eu.maiora.routes.logScriptRouting
import eu.maiora.model.AccountsRepositoryImpl
import eu.maiora.model.ParametriRepositoryImpl
import eu.maiora.model.TessereRepositoryImpl
import eu.maiora.routes.auth
import eu.maiora.routes.tessere
import io.ktor.server.application.*
import io.ktor.server.response.*
import io.ktor.server.routing.*
fun Application.configureRouting() {
//fun Application.configureRouting(dbUrl : String, username : String, password : String, repository : LogScriptRepositoryImpl ) {
fun Application.configureRouting(dbUrl : String, username : String, password : String) {
routing {
get("/") {
call.respondText("Hello World!")
}
auth(AccountsRepositoryImpl())
tessere(TessereRepositoryImpl())
}
}

View File

@ -16,7 +16,7 @@ import java.util.*
fun Route.auth(accountsRepository: AccountsRepositoryImpl) {
route("/api/auth") {
route("/auth") {
post() {
// Riceve il body della richiesta e lo deserializza in ReceivedResponse
val receivedResponse = try {
@ -31,7 +31,7 @@ fun Route.auth(accountsRepository: AccountsRepositoryImpl) {
logger.info(
"param: " +
receivedResponse.param
)
);
// Decodifica la stringa da Base64 a oggetto Credentials
val decodedBytes = Base64.getDecoder().decode(receivedResponse.param)

View File

@ -0,0 +1,35 @@
package eu.maiora.routes
import eu.maiora.model.TessereRepositoryImpl
import io.ktor.http.*
import io.ktor.server.application.*
import io.ktor.server.auth.*
import io.ktor.server.response.*
import io.ktor.server.routing.*
fun Route.tessere(tessereRepository: TessereRepositoryImpl){
route("/api/tessere"){
authenticate("auth-jwt") {
get("{cf}"){
// Ottieni il codice fiscale dal percorso
val cf = call.parameters["cf"]
if (cf == null) {
call.respondText("Codice fiscale non valido", status = HttpStatusCode.BadRequest)
return@get
}
// Cerca la tessera per codice fiscale
val tessera = tessereRepository.tesseraByCodiceFiscale(cf)
if (tessera != null) {
call.respond(tessera)
} else {
call.respondText("Tessera non trovata", status = HttpStatusCode.NotFound)
}
}
}
}
}

View File

@ -1,4 +1,18 @@
ktor {
database {
; url = "jdbc:postgresql://192.168.20.49:5432/caritas"
; username = "caritas"
; password = "caritas"
; driver = "org.postgresql.Driver"
driver = "com.microsoft.sqlserver.jdbc.SQLServerDriver"
url = "jdbc:sqlserver://192.168.20.45;databaseName=EP_FAER;integratedSecurity=false;encrypt=true;trustServerCertificate=true;"
username = "SA"
password = "I5fz9l1a"
;driver = "oracle.jdbc.OracleDriver"
;url = "jdbc:oracle:thin:@//192.168.20.101:1521/SIR"
;username = "EP_DONORIONE"
;password = "ep_donorione"
}
jwt {
# secret per JWT generato partendo dalla stringa '?Backend_API*06022025!' codificato in Base64
secret = "P0JhY2tlbmRfQVBJKjA2MDIyMDI1IQ=="

View File

@ -1,43 +0,0 @@
<configuration>
<!-- Appender per la console -->
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{YYYY-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<!-- Appender per il file di log con rotazione basata su tempo e dimensione -->
<appender name="ROLLING_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>./log/logFile.log</file> <!-- File di log principale -->
<append>true</append>
<!-- RollingPolicy per dimensione e tempo -->
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<!-- Pattern per il nome dei file ruotati: include la data -->
<FileNamePattern>./log/logFile.%d{yyyy-MM-dd}.%i.log</FileNamePattern> <!-- %i è il numero di file generato -->
<!-- Limita la dimensione del file a 100MB -->
<maxFileSize>100MB</maxFileSize> <!-- Ruota il file quando raggiunge 100MB -->
<!-- Conserva i log per due settimane -->
<maxHistory>15</maxHistory> <!-- Limita a 15 giorni i log archiviati -->
<!-- Limita la dimensione totale dei file di log a 5GB -->
<totalSizeCap>5GB</totalSizeCap>
</rollingPolicy>
<encoder>
<pattern>%d{YYYY-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<!-- Configurazione del livello di log -->
<root level="DEBUG">
<appender-ref ref="ROLLING_FILE"/>
<appender-ref ref="STDOUT"/>
</root>
<logger name="io.netty" level="INFO"/>
</configuration>