Move files
Move Application and configurations file to the application package Move JWT files to the auth.jwt package Move ApplicationContext to auth package an rename to CitizenContext
This commit is contained in:
264
src/main/kotlin/application/Application.kt
Normal file
264
src/main/kotlin/application/Application.kt
Normal file
@@ -0,0 +1,264 @@
|
||||
package fr.dcproject.application
|
||||
|
||||
import com.fasterxml.jackson.core.util.DefaultIndenter
|
||||
import com.fasterxml.jackson.core.util.DefaultPrettyPrinter
|
||||
import com.fasterxml.jackson.databind.DeserializationFeature
|
||||
import com.fasterxml.jackson.databind.PropertyNamingStrategy
|
||||
import com.fasterxml.jackson.databind.SerializationFeature
|
||||
import com.fasterxml.jackson.datatype.joda.JodaModule
|
||||
import com.github.jasync.sql.db.postgresql.exceptions.GenericDatabaseException
|
||||
import fr.dcproject.application.Env.PROD
|
||||
import fr.dcproject.component.article.routes.findArticleVersions
|
||||
import fr.dcproject.component.article.routes.findArticles
|
||||
import fr.dcproject.component.article.routes.getOneArticle
|
||||
import fr.dcproject.component.article.routes.upsertArticle
|
||||
import fr.dcproject.component.auth.ForbiddenException
|
||||
import fr.dcproject.component.auth.User
|
||||
import fr.dcproject.component.auth.UserRepository
|
||||
import fr.dcproject.component.auth.jwt.JwtConfig
|
||||
import fr.dcproject.component.auth.routes.authLogin
|
||||
import fr.dcproject.component.auth.routes.authRegister
|
||||
import fr.dcproject.component.auth.routes.authSso
|
||||
import fr.dcproject.component.auth.user
|
||||
import fr.dcproject.component.citizen.routes.changeMyPassword
|
||||
import fr.dcproject.component.citizen.routes.findCitizen
|
||||
import fr.dcproject.component.citizen.routes.getCurrentCitizen
|
||||
import fr.dcproject.component.citizen.routes.getOneCitizen
|
||||
import fr.dcproject.component.comment.article.routes.createCommentArticle
|
||||
import fr.dcproject.component.comment.article.routes.getArticleComments
|
||||
import fr.dcproject.component.comment.article.routes.getCitizenArticleComments
|
||||
import fr.dcproject.component.comment.generic.routes.createCommentChildren
|
||||
import fr.dcproject.component.comment.generic.routes.editComment
|
||||
import fr.dcproject.component.comment.generic.routes.getChildrenComments
|
||||
import fr.dcproject.component.comment.generic.routes.getOneComment
|
||||
import fr.dcproject.component.workgroup.routes.CreateWorkgroup.createWorkgroup
|
||||
import fr.dcproject.component.workgroup.routes.DeleteWorkgroup.deleteWorkgroup
|
||||
import fr.dcproject.component.workgroup.routes.EditWorkgroup.editWorkgroup
|
||||
import fr.dcproject.component.workgroup.routes.GetWorkgroup.getWorkgroup
|
||||
import fr.dcproject.component.workgroup.routes.GetWorkgroups.getWorkgroups
|
||||
import fr.dcproject.component.workgroup.routes.members.AddMemberToWorkgroup.addMemberToWorkgroup
|
||||
import fr.dcproject.component.workgroup.routes.members.DeleteMembersOfWorkgroup.deleteMemberOfWorkgroup
|
||||
import fr.dcproject.component.workgroup.routes.members.UpdateMemberOfWorkgroup.updateMemberOfWorkgroup
|
||||
import fr.dcproject.elasticsearch.configElasticIndexes
|
||||
import fr.dcproject.event.EventNotification
|
||||
import fr.dcproject.event.EventSubscriber
|
||||
import fr.dcproject.routes.*
|
||||
import fr.dcproject.security.voter.*
|
||||
import fr.ktorVoter.AuthorizationVoter
|
||||
import fr.ktorVoter.VoterException
|
||||
import fr.postgresjson.migration.Migrations
|
||||
import io.ktor.application.*
|
||||
import io.ktor.auth.*
|
||||
import io.ktor.auth.jwt.*
|
||||
import io.ktor.client.*
|
||||
import io.ktor.client.engine.jetty.Jetty
|
||||
import io.ktor.features.*
|
||||
import io.ktor.http.*
|
||||
import io.ktor.http.auth.*
|
||||
import io.ktor.jackson.*
|
||||
import io.ktor.locations.*
|
||||
import io.ktor.response.*
|
||||
import io.ktor.routing.*
|
||||
import io.ktor.server.jetty.*
|
||||
import io.ktor.util.*
|
||||
import io.ktor.websocket.*
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import org.eclipse.jetty.util.log.Slf4jLog
|
||||
import org.koin.core.qualifier.named
|
||||
import org.koin.ktor.ext.Koin
|
||||
import org.koin.ktor.ext.get
|
||||
import org.slf4j.event.Level
|
||||
import java.time.Duration
|
||||
import java.util.*
|
||||
import java.util.concurrent.CompletionException
|
||||
|
||||
fun main(args: Array<String>): Unit = EngineMain.main(args)
|
||||
|
||||
enum class Env { PROD, TEST, CUCUMBER }
|
||||
|
||||
@ExperimentalCoroutinesApi
|
||||
@KtorExperimentalAPI
|
||||
@KtorExperimentalLocationsAPI
|
||||
@Suppress("unused") // Referenced in application.conf
|
||||
fun Application.module(env: Env = PROD) {
|
||||
install(Koin) {
|
||||
Slf4jLog()
|
||||
modules(KoinModule)
|
||||
}
|
||||
|
||||
install(CallLogging) {
|
||||
level = Level.INFO
|
||||
}
|
||||
|
||||
install(DataConversion, converters)
|
||||
|
||||
install(Locations)
|
||||
|
||||
install(AuthorizationVoter) {
|
||||
voters = listOf(
|
||||
ConstitutionVoter(),
|
||||
VoteVoter(),
|
||||
FollowVoter(),
|
||||
OpinionVoter(),
|
||||
OpinionChoiceVoter()
|
||||
)
|
||||
}
|
||||
|
||||
HttpClient(Jetty) {
|
||||
engine {
|
||||
}
|
||||
}
|
||||
|
||||
configElasticIndexes(get())
|
||||
|
||||
install(WebSockets) {
|
||||
pingPeriod = Duration.ofSeconds(60) // Disabled (null) by default
|
||||
timeout = Duration.ofSeconds(15)
|
||||
maxFrameSize = Long.MAX_VALUE // Disabled (max value). The connection will be closed if surpassed this length.
|
||||
masking = false
|
||||
}
|
||||
|
||||
install(EventSubscriber) {
|
||||
EventNotification(this, get(), get(), get(), get(), get()).config()
|
||||
}
|
||||
|
||||
install(Authentication) {
|
||||
/**
|
||||
* Setup the JWT authentication to be used in [Routing].
|
||||
* If the token is valid, the corresponding [User] is fetched from the database.
|
||||
* The [User] can then be accessed in each [ApplicationCall].
|
||||
*/
|
||||
jwt {
|
||||
verifier(JwtConfig.verifier)
|
||||
realm = "dc-project.fr"
|
||||
validate {
|
||||
it.payload.getClaim("id").asString()?.let { id ->
|
||||
get<UserRepository>().findById(UUID.fromString(id))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
jwt("url") {
|
||||
verifier(JwtConfig.verifier)
|
||||
realm = "dc-project.fr"
|
||||
authHeader { call ->
|
||||
call.request.queryParameters["token"]?.let {
|
||||
HttpAuthHeader.Single("Bearer", it)
|
||||
}
|
||||
}
|
||||
validate {
|
||||
it.payload.getClaim("id").asString()?.let { id ->
|
||||
get<UserRepository>().findById(UUID.fromString(id))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
install(AutoHeadResponse)
|
||||
|
||||
install(ContentNegotiation) {
|
||||
jackson {
|
||||
propertyNamingStrategy = PropertyNamingStrategy.SNAKE_CASE
|
||||
|
||||
registerModule(JodaModule())
|
||||
disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
|
||||
configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
|
||||
configure(SerializationFeature.INDENT_OUTPUT, true)
|
||||
setDefaultPrettyPrinter(DefaultPrettyPrinter().apply {
|
||||
indentArraysWith(DefaultPrettyPrinter.FixedSpaceIndenter.instance)
|
||||
indentObjectsWith(DefaultIndenter(" ", "\n"))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
install(Routing.Feature) {
|
||||
// trace { application.log.trace(it.buildText()) }
|
||||
authenticate(optional = true) {
|
||||
/* Article */
|
||||
findArticles(get(), get())
|
||||
getOneArticle(get(), get())
|
||||
upsertArticle(get(), get(), get())
|
||||
findArticleVersions(get(), get())
|
||||
/* Citizen */
|
||||
findCitizen(get(), get())
|
||||
getOneCitizen(get())
|
||||
getCurrentCitizen(get())
|
||||
changeMyPassword(get(), get())
|
||||
/* Comment */
|
||||
editComment(get(), get())
|
||||
getOneComment(get(), get())
|
||||
createCommentChildren(get(), get())
|
||||
getChildrenComments(get(), get())
|
||||
/* Comment Article */
|
||||
getArticleComments(get(), get())
|
||||
createCommentArticle(get(), get())
|
||||
getCitizenArticleComments(get(), get())
|
||||
/* Auth */
|
||||
authLogin(get())
|
||||
authRegister(get())
|
||||
authSso(get())
|
||||
/* Workgroup */
|
||||
getWorkgroups(get(), get())
|
||||
getWorkgroup(get(), get())
|
||||
createWorkgroup(get(), get())
|
||||
editWorkgroup(get(), get())
|
||||
deleteWorkgroup(get(), get())
|
||||
/* Workgroup members */
|
||||
addMemberToWorkgroup(get(), get())
|
||||
deleteMemberOfWorkgroup(get(), get())
|
||||
updateMemberOfWorkgroup(get(), get())
|
||||
/* TODO */
|
||||
constitution(get())
|
||||
followArticle(get())
|
||||
followConstitution(get())
|
||||
commentConstitution(get(), get())
|
||||
voteArticle(get(), get(), get())
|
||||
voteConstitution(get())
|
||||
opinionArticle(get())
|
||||
opinionChoice(get())
|
||||
definition()
|
||||
}
|
||||
|
||||
authenticate("url") {
|
||||
notificationArticle(get(), get(named("ws")))
|
||||
}
|
||||
}
|
||||
|
||||
install(StatusPages) {
|
||||
// TODO move to postgresJson lib
|
||||
exception<CompletionException> { e ->
|
||||
val parent = e.cause?.cause
|
||||
if (parent is GenericDatabaseException) {
|
||||
call.respond(HttpStatusCode.BadRequest, parent.errorMessage.message!!)
|
||||
} else {
|
||||
throw e
|
||||
}
|
||||
}
|
||||
exception<NotFoundException> { e ->
|
||||
call.respond(HttpStatusCode.NotFound, e.message!!)
|
||||
}
|
||||
exception<VoterException> {
|
||||
if (call.user == null) call.respond(HttpStatusCode.Unauthorized)
|
||||
else call.respond(HttpStatusCode.Forbidden)
|
||||
}
|
||||
exception<ForbiddenException> {
|
||||
call.respond(HttpStatusCode.Forbidden)
|
||||
}
|
||||
}
|
||||
|
||||
install(CORS) {
|
||||
method(HttpMethod.Options)
|
||||
method(HttpMethod.Put)
|
||||
method(HttpMethod.Delete)
|
||||
header(HttpHeaders.Authorization)
|
||||
anyHost()
|
||||
// host("localhost:4200", schemes = listOf("http", "https"))
|
||||
allowCredentials = true
|
||||
allowSameOrigin = true
|
||||
maxAge = Duration.ofDays(1)
|
||||
}
|
||||
|
||||
if (env == PROD) {
|
||||
get<Migrations>().run()
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user