Skip to content

Commit

Permalink
feat: admin links
Browse files Browse the repository at this point in the history
  • Loading branch information
nathanfallet committed Apr 11, 2024
1 parent 1cd5b89 commit 80635e5
Show file tree
Hide file tree
Showing 7 changed files with 217 additions and 3 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package me.nathanfallet.groupeminaste.controllers.projects

import io.ktor.server.application.*
import me.nathanfallet.groupeminaste.models.projects.Project
import me.nathanfallet.groupeminaste.models.projects.ProjectLink
import me.nathanfallet.groupeminaste.models.projects.ProjectLinkPayload
import me.nathanfallet.ktorx.controllers.IChildModelController
import me.nathanfallet.ktorx.models.annotations.*

interface IProjectLinksController :
IChildModelController<ProjectLink, String, ProjectLinkPayload, ProjectLinkPayload, Project, String> {

@APIMapping
@AdminTemplateMapping
@ListModelPath
suspend fun list(@ParentModel parent: Project): List<ProjectLink>

@APIMapping
@GetModelPath
@DocumentedError(404, "projects_not_found")
suspend fun get(call: ApplicationCall, @ParentModel parent: Project, @Id id: String): ProjectLink

@APIMapping
@CreateModelPath
@AdminTemplateMapping
@DocumentedError(401, "auth_invalid_credentials")
@DocumentedError(500, "error_internal")
suspend fun create(
call: ApplicationCall,
@ParentModel parent: Project,
@Payload payload: ProjectLinkPayload,
): ProjectLink

@APIMapping
@UpdateModelPath
@AdminTemplateMapping
@DocumentedError(401, "auth_invalid_credentials")
@DocumentedError(404, "projects_not_found")
@DocumentedError(500, "error_internal")
suspend fun update(
call: ApplicationCall,
@ParentModel parent: Project,
@Id id: String,
@Payload payload: ProjectLinkPayload,
): ProjectLink

@APIMapping
@DeleteModelPath
@AdminTemplateMapping
@DocumentedType(ProjectLink::class)
@DocumentedError(401, "auth_invalid_credentials")
@DocumentedError(404, "projects_not_found")
@DocumentedError(500, "error_internal")
suspend fun delete(call: ApplicationCall, @ParentModel parent: Project, @Id id: String)

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package me.nathanfallet.groupeminaste.controllers.projects

import io.ktor.http.*
import io.ktor.server.application.*
import me.nathanfallet.groupeminaste.models.projects.Project
import me.nathanfallet.groupeminaste.models.projects.ProjectLink
import me.nathanfallet.groupeminaste.models.projects.ProjectLinkPayload
import me.nathanfallet.ktorx.models.exceptions.ControllerException
import me.nathanfallet.ktorx.usecases.users.IRequireUserForCallUseCase
import me.nathanfallet.usecases.models.create.ICreateChildModelSuspendUseCase
import me.nathanfallet.usecases.models.delete.IDeleteChildModelSuspendUseCase
import me.nathanfallet.usecases.models.get.IGetChildModelSuspendUseCase
import me.nathanfallet.usecases.models.list.IListChildModelSuspendUseCase
import me.nathanfallet.usecases.models.update.IUpdateChildModelSuspendUseCase

class ProjectLinksController(
private val requireUserForCallUseCase: IRequireUserForCallUseCase,
private val listProjectLinksUseCase: IListChildModelSuspendUseCase<ProjectLink, String>,
private val getProjectLinkUseCase: IGetChildModelSuspendUseCase<ProjectLink, String, String>,
private val createProjectLinkUseCase: ICreateChildModelSuspendUseCase<ProjectLink, ProjectLinkPayload, String>,
private val updateProjectLinkUseCase: IUpdateChildModelSuspendUseCase<ProjectLink, String, ProjectLinkPayload, String>,
private val deleteProjectLinkUseCase: IDeleteChildModelSuspendUseCase<ProjectLink, String, String>,
) : IProjectLinksController {

override suspend fun list(parent: Project): List<ProjectLink> {
return listProjectLinksUseCase(parent.id)
}

override suspend fun get(call: ApplicationCall, parent: Project, id: String): ProjectLink {
return getProjectLinkUseCase(id, parent.id) ?: throw ControllerException(
HttpStatusCode.NotFound, "projects_not_found"
)
}

override suspend fun create(call: ApplicationCall, parent: Project, payload: ProjectLinkPayload): ProjectLink {
requireUserForCallUseCase(call)
return createProjectLinkUseCase(payload, parent.id) ?: throw ControllerException(
HttpStatusCode.InternalServerError, "error_internal"
)
}

override suspend fun update(
call: ApplicationCall,
parent: Project,
id: String,
payload: ProjectLinkPayload,
): ProjectLink {
requireUserForCallUseCase(call)
val link = getProjectLinkUseCase(id, parent.id) ?: throw ControllerException(
HttpStatusCode.NotFound, "projects_not_found"
)
return updateProjectLinkUseCase(link.id, payload, parent.id) ?: throw ControllerException(
HttpStatusCode.InternalServerError, "error_internal"
)
}

override suspend fun delete(call: ApplicationCall, parent: Project, id: String) {
requireUserForCallUseCase(call)
val link = getProjectLinkUseCase(id, parent.id) ?: throw ControllerException(
HttpStatusCode.NotFound, "projects_not_found"
)
if (!deleteProjectLinkUseCase(link.id, parent.id)) throw ControllerException(
HttpStatusCode.InternalServerError, "error_internal"
)
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package me.nathanfallet.groupeminaste.controllers.projects

import io.ktor.util.reflect.*
import me.nathanfallet.groupeminaste.controllers.models.AdminChildModelRouter
import me.nathanfallet.groupeminaste.models.projects.Project
import me.nathanfallet.groupeminaste.models.projects.ProjectLink
import me.nathanfallet.groupeminaste.models.projects.ProjectLinkPayload
import me.nathanfallet.groupeminaste.usecases.web.IGetAdminMenuForCallUseCase
import me.nathanfallet.ktorx.routers.api.APIChildModelRouter
import me.nathanfallet.ktorx.routers.concat.ConcatChildModelRouter
import me.nathanfallet.ktorx.usecases.localization.IGetLocaleForCallUseCase
import me.nathanfallet.usecases.localization.ITranslateUseCase

class ProjectLinksRouter(
controller: IProjectLinksController,
getLocaleForCallUseCase: IGetLocaleForCallUseCase,
translateUseCase: ITranslateUseCase,
getAdminMenuForCallUseCase: IGetAdminMenuForCallUseCase,
projectsRouter: ProjectsRouter,
) : ConcatChildModelRouter<ProjectLink, String, ProjectLinkPayload, ProjectLinkPayload, Project, String>(
APIChildModelRouter(
typeInfo<ProjectLink>(),
typeInfo<ProjectLinkPayload>(),
typeInfo<ProjectLinkPayload>(),
controller,
IProjectLinksController::class,
projectsRouter,
prefix = "/api/v1",
route = "links"
),
AdminChildModelRouter(
typeInfo<ProjectLink>(),
typeInfo<ProjectLinkPayload>(),
typeInfo<ProjectLinkPayload>(),
controller,
IProjectLinksController::class,
projectsRouter,
getLocaleForCallUseCase,
translateUseCase,
getAdminMenuForCallUseCase,
route = "links"
)
)
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,7 @@ import me.nathanfallet.groupeminaste.controllers.auth.IAuthController
import me.nathanfallet.groupeminaste.controllers.dashboard.DashboardController
import me.nathanfallet.groupeminaste.controllers.dashboard.DashboardRouter
import me.nathanfallet.groupeminaste.controllers.dashboard.IDashboardController
import me.nathanfallet.groupeminaste.controllers.projects.IProjectsController
import me.nathanfallet.groupeminaste.controllers.projects.ProjectsController
import me.nathanfallet.groupeminaste.controllers.projects.ProjectsRouter
import me.nathanfallet.groupeminaste.controllers.projects.*
import me.nathanfallet.groupeminaste.controllers.web.IWebController
import me.nathanfallet.groupeminaste.controllers.web.WebController
import me.nathanfallet.groupeminaste.controllers.web.WebRouter
Expand All @@ -19,6 +17,7 @@ import me.nathanfallet.groupeminaste.database.projects.ProjectsDatabaseRepositor
import me.nathanfallet.groupeminaste.database.users.UsersDatabaseRepository
import me.nathanfallet.groupeminaste.models.projects.Project
import me.nathanfallet.groupeminaste.models.projects.ProjectLink
import me.nathanfallet.groupeminaste.models.projects.ProjectLinkPayload
import me.nathanfallet.groupeminaste.models.projects.ProjectPayload
import me.nathanfallet.groupeminaste.models.users.User
import me.nathanfallet.groupeminaste.repositories.projects.IProjectLinksRepository
Expand All @@ -40,17 +39,25 @@ import me.nathanfallet.ktorx.usecases.users.IRequireUserForCallUseCase
import me.nathanfallet.ktorx.usecases.users.RequireUserForCallUseCase
import me.nathanfallet.surexposed.database.IDatabase
import me.nathanfallet.usecases.localization.ITranslateUseCase
import me.nathanfallet.usecases.models.create.CreateChildModelFromRepositorySuspendUseCase
import me.nathanfallet.usecases.models.create.CreateModelFromRepositorySuspendUseCase
import me.nathanfallet.usecases.models.create.ICreateChildModelSuspendUseCase
import me.nathanfallet.usecases.models.create.ICreateModelSuspendUseCase
import me.nathanfallet.usecases.models.delete.DeleteChildModelFromRepositorySuspendUseCase
import me.nathanfallet.usecases.models.delete.DeleteModelFromRepositorySuspendUseCase
import me.nathanfallet.usecases.models.delete.IDeleteChildModelSuspendUseCase
import me.nathanfallet.usecases.models.delete.IDeleteModelSuspendUseCase
import me.nathanfallet.usecases.models.get.GetChildModelFromRepositorySuspendUseCase
import me.nathanfallet.usecases.models.get.GetModelFromRepositorySuspendUseCase
import me.nathanfallet.usecases.models.get.IGetChildModelSuspendUseCase
import me.nathanfallet.usecases.models.get.IGetModelSuspendUseCase
import me.nathanfallet.usecases.models.list.IListChildModelSuspendUseCase
import me.nathanfallet.usecases.models.list.IListModelSuspendUseCase
import me.nathanfallet.usecases.models.list.ListChildModelFromRepositorySuspendUseCase
import me.nathanfallet.usecases.models.list.ListModelFromRepositorySuspendUseCase
import me.nathanfallet.usecases.models.update.IUpdateChildModelSuspendUseCase
import me.nathanfallet.usecases.models.update.IUpdateModelSuspendUseCase
import me.nathanfallet.usecases.models.update.UpdateChildModelFromRepositorySuspendUseCase
import me.nathanfallet.usecases.models.update.UpdateModelFromRepositorySuspendUseCase
import org.koin.core.qualifier.named
import org.koin.dsl.module
Expand Down Expand Up @@ -134,6 +141,18 @@ fun Application.configureKoin() {
single<IListChildModelSuspendUseCase<ProjectLink, String>>(named<ProjectLink>()) {
ListChildModelFromRepositorySuspendUseCase(get<IProjectLinksRepository>())
}
single<IGetChildModelSuspendUseCase<ProjectLink, String, String>>(named<ProjectLink>()) {
GetChildModelFromRepositorySuspendUseCase(get<IProjectLinksRepository>())
}
single<ICreateChildModelSuspendUseCase<ProjectLink, ProjectLinkPayload, String>>(named<ProjectLink>()) {
CreateChildModelFromRepositorySuspendUseCase(get<IProjectLinksRepository>())
}
single<IUpdateChildModelSuspendUseCase<ProjectLink, String, ProjectLinkPayload, String>>(named<ProjectLink>()) {
UpdateChildModelFromRepositorySuspendUseCase(get<IProjectLinksRepository>())
}
single<IDeleteChildModelSuspendUseCase<ProjectLink, String, String>>(named<ProjectLink>()) {
DeleteChildModelFromRepositorySuspendUseCase(get<IProjectLinksRepository>())
}
}
val controllerModule = module {
// Static web pages
Expand All @@ -160,12 +179,23 @@ fun Application.configureKoin() {
get(named<ProjectLink>())
)
}
single<IProjectLinksController> {
ProjectLinksController(
get(),
get(named<ProjectLink>()),
get(named<ProjectLink>()),
get(named<ProjectLink>()),
get(named<ProjectLink>()),
get(named<ProjectLink>())
)
}
}
val routerModule = module {
single { WebRouter(get(), get()) }
single { AuthRouter(get(), get()) }
single { DashboardRouter(get(), get(), get(), get()) }
single { ProjectsRouter(get(), get(), get(), get()) }
single { ProjectLinksRouter(get(), get(), get(), get(), get()) }
}

modules(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import io.swagger.v3.oas.models.OpenAPI
import io.swagger.v3.oas.models.servers.Server
import me.nathanfallet.groupeminaste.controllers.auth.AuthRouter
import me.nathanfallet.groupeminaste.controllers.dashboard.DashboardRouter
import me.nathanfallet.groupeminaste.controllers.projects.ProjectLinksRouter
import me.nathanfallet.groupeminaste.controllers.projects.ProjectsRouter
import me.nathanfallet.groupeminaste.controllers.web.WebRouter
import me.nathanfallet.ktorx.extensions.info
Expand All @@ -34,6 +35,7 @@ fun Application.configureRouting() {
get<AuthRouter>(),
get<DashboardRouter>(),
get<ProjectsRouter>(),
get<ProjectLinksRouter>(),
OpenAPIRouter(), // OpenAPI should be last
).forEach {
it.createRoutes(this, openAPI)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,3 +51,11 @@ projects_info=Project Info
projects_category=Category
projects_updatedAt=Updated at
projects_links=Links
admin_menu_links=Links
admin_links_create=New link
admin_links_update=Update link
admin_links_delete=Are you sure to delete this link?
admin_links_id=Id
admin_links_name=Name
admin_links_url=URL
admin_links_view=View links for this project
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,14 @@
<#macro children name>
<#switch name>
<#case "projects">
<div class="col-md-4">
<div class="card card-body mt-4">
<h6 class="mb-0" id="admin_children"><@t key="admin_menu_links" /></h6>
<a href="links" class="btn bg-gradient-primary m-0 mt-3">
<@t key="admin_links_view" />
</a>
</div>
</div>
<#break>
</#switch>
</#macro>

0 comments on commit 80635e5

Please sign in to comment.