Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ class DashboardService(
private val visitorRepository: VisitorRepository,
private val visitorStatusRepository: VisitStatusRepository,
private val authorizationService: AuthorizationService,
@Value("\${gatelog.scheduler.overdue-threshold-hours:2}")
@Value($$"${gatelog.scheduler.overdue-threshold-hours:2}")
private val overdueThresholdHours: Long,
) {
@Transactional(readOnly = true)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,6 @@ class ReportService(
writer.println(
csvRow(
v.id.toString(),
v.name,
v.phone,
v.visitorType,
v.purpose,
v.visitStatus.name,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@ package io.github.devcavin.gatelog.backend.sites

import io.github.devcavin.gatelog.backend.sites.dto.SiteRequest
import io.github.devcavin.gatelog.backend.sites.dto.SiteResponse
import io.github.devcavin.gatelog.backend.users.User
import jakarta.validation.Valid
import org.springframework.http.HttpStatus
import org.springframework.http.ResponseEntity
import org.springframework.security.access.prepost.PreAuthorize
import org.springframework.security.core.annotation.AuthenticationPrincipal
import org.springframework.web.bind.annotation.*
import java.util.*

Expand All @@ -30,9 +32,10 @@ class SiteController(
@GetMapping("/{id}")
@PreAuthorize("hasAnyRole('SUPER_ADMIN', 'MANAGER')")
fun getById(
@AuthenticationPrincipal requestedBy: User,
@PathVariable id: UUID
): ResponseEntity<SiteResponse> =
ResponseEntity.ok(siteService.getById(id))
ResponseEntity.ok(siteService.getById(requestedBy, id))

@PutMapping("/{id}")
@PreAuthorize("hasRole('SUPER_ADMIN')")
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,21 @@
package io.github.devcavin.gatelog.backend.sites

import io.github.devcavin.gatelog.backend.auth.AuthorizationService
import io.github.devcavin.gatelog.backend.common.exception.ConflictException
import io.github.devcavin.gatelog.backend.common.exception.ResourceNotFoundException
import io.github.devcavin.gatelog.backend.sites.dto.SiteRequest
import io.github.devcavin.gatelog.backend.sites.dto.SiteResponse
import io.github.devcavin.gatelog.backend.sites.dto.toEntity
import io.github.devcavin.gatelog.backend.sites.dto.toResponse
import io.github.devcavin.gatelog.backend.users.User
import org.springframework.stereotype.Service
import org.springframework.transaction.annotation.Transactional
import java.util.UUID

@Service
class SiteService(
private val siteRepository: SiteRepository
private val siteRepository: SiteRepository,
private val authorizationService: AuthorizationService
) {
@Transactional
fun create(request: SiteRequest): SiteResponse {
Expand All @@ -29,7 +32,11 @@ class SiteService(
fun getAll(): List<SiteResponse> = siteRepository.findAll().map { it.toResponse() }

@Transactional(readOnly = true)
fun getById(id: UUID): SiteResponse {
fun getById(requestBy: User, id: UUID): SiteResponse {

// site access scope check
authorizationService.assertCovers(requestBy, id)

val site = siteRepository.findById(id)
.orElseThrow { ResourceNotFoundException("Site", id) }
return site.toResponse()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ package io.github.devcavin.gatelog.backend.visitors

import io.github.devcavin.gatelog.backend.common.persistence.BaseEntity
import io.github.devcavin.gatelog.backend.sites.Site
import io.github.devcavin.gatelog.backend.zones.Zone
import io.github.devcavin.gatelog.backend.users.User
import io.github.devcavin.gatelog.backend.zones.Zone
import jakarta.persistence.Column
import jakarta.persistence.Entity
import jakarta.persistence.FetchType
Expand All @@ -19,35 +19,28 @@ import java.util.UUID
@Entity
@Table(name = "visitors")
class Visitor(

@Id
@GeneratedValue(strategy = GenerationType.UUID)
@Column(updatable = false, nullable = false)
override var id: UUID? = null,

@Column(nullable = false, length = 100)
var name: String,
@ManyToOne(fetch = FetchType.LAZY, optional = false)
@JoinColumn(name = "visitor_profile_id", nullable = false)
var visitorProfile: VisitorProfile,

@Column(nullable = false, length = 25)
var phone: String,

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "visitor_profile_id")
var visitorProfile: VisitorProfile? = null,

@ManyToOne(fetch = FetchType.LAZY)
@ManyToOne(fetch = FetchType.LAZY, optional = false)
@JoinColumn(name = "site_id", nullable = false)
var site: Site,

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "zone_id")
var zone: Zone? = null,

@ManyToOne(fetch = FetchType.LAZY)
@ManyToOne(fetch = FetchType.LAZY, optional = false)
@JoinColumn(name = "created_by", nullable = false)
var createdBy: User,

@ManyToOne(fetch = FetchType.LAZY)
@ManyToOne(fetch = FetchType.LAZY, optional = false)
@JoinColumn(name = "visit_status_id", nullable = false)
var visitStatus: VisitStatus,

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@ package io.github.devcavin.gatelog.backend.visitors
import io.github.devcavin.gatelog.backend.users.User
import io.github.devcavin.gatelog.backend.visitors.dto.RegisterVisitorRequest
import io.github.devcavin.gatelog.backend.visitors.dto.ReturningVisitorResponse
import io.github.devcavin.gatelog.backend.visitors.dto.UpdateVisitorProfileRequest
import io.github.devcavin.gatelog.backend.visitors.dto.VisitorProfileResponse
import io.github.devcavin.gatelog.backend.visitors.dto.VisitorResponse
import io.github.devcavin.gatelog.backend.visitors.dto.VisitorSearchParams
import jakarta.validation.Valid
Expand All @@ -13,13 +11,11 @@ import org.springframework.data.domain.Pageable
import org.springframework.data.web.PageableDefault
import org.springframework.http.HttpStatus
import org.springframework.http.ResponseEntity
import org.springframework.security.access.prepost.PreAuthorize
import org.springframework.security.core.annotation.AuthenticationPrincipal
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.PatchMapping
import org.springframework.web.bind.annotation.PathVariable
import org.springframework.web.bind.annotation.PostMapping
import org.springframework.web.bind.annotation.PutMapping
import org.springframework.web.bind.annotation.RequestBody
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RequestParam
Expand All @@ -37,26 +33,39 @@ class VisitorController(
fun register(
@AuthenticationPrincipal requestedBy: User,
@Valid @RequestBody request: RegisterVisitorRequest
): ResponseEntity<VisitorResponse> {
val response = visitorService.register(requestedBy, request)
return ResponseEntity.status(HttpStatus.CREATED).body(response)
}
): ResponseEntity<VisitorResponse> =
ResponseEntity
.status(HttpStatus.CREATED)
.body(
visitorService.register(
requestedBy,
request
)
)

@GetMapping("/{id}")
fun getById(
@AuthenticationPrincipal requestedBy: User,
@PathVariable id: UUID
): ResponseEntity<VisitorResponse> {
return ResponseEntity.ok(visitorService.getById(requestedBy, id))
}
): ResponseEntity<VisitorResponse> =
ResponseEntity.ok(
visitorService.getById(
requestedBy,
id
)
)

@PatchMapping("/{id}/checkout")
fun checkOut(
@AuthenticationPrincipal requestedBy: User,
@PathVariable id: UUID
): ResponseEntity<VisitorResponse> {
return ResponseEntity.ok(visitorService.checkOut(requestedBy, id))
}
): ResponseEntity<VisitorResponse> =
ResponseEntity.ok(
visitorService.checkOut(
requestedBy,
id
)
)

@GetMapping
fun search(
Expand All @@ -68,8 +77,13 @@ class VisitorController(
@RequestParam(required = false) status: String?,
@RequestParam(required = false) from: OffsetDateTime?,
@RequestParam(required = false) to: OffsetDateTime?,
@PageableDefault(size = 20, sort = ["checkInTime"]) pageable: Pageable
@PageableDefault(
size = 20,
sort = ["checkInTime"]
)
pageable: Pageable
): ResponseEntity<Page<VisitorResponse>> {

val params = VisitorSearchParams(
name = name,
phone = phone,
Expand All @@ -79,25 +93,32 @@ class VisitorController(
from = from,
to = to
)
return ResponseEntity.ok(visitorService.search(requestedBy, params, pageable))

return ResponseEntity.ok(
visitorService.search(
requestedBy,
params,
pageable
)
)
}

@GetMapping("/returning")
fun findReturning(
@AuthenticationPrincipal requestedBy: User,
@RequestParam phone: String
): ResponseEntity<ReturningVisitorResponse> {
val result = visitorService.findReturningVisitor(requestedBy, phone)
return if (result != null) ResponseEntity.ok(result)
else ResponseEntity.noContent().build()
}

@PutMapping("/profiles/{profileId}")
@PreAuthorize("hasAnyRole('SUPER_ADMIN', 'MANAGER', 'STAFF')")
fun updateProfile(
@AuthenticationPrincipal requestedBy: User,
@PathVariable profileId: UUID,
@Valid @RequestBody request: UpdateVisitorProfileRequest
): ResponseEntity<VisitorProfileResponse> =
ResponseEntity.ok(visitorService.updateProfile(requestedBy, profileId, request))
val result =
visitorService.findReturningVisitor(
requestedBy,
phone
)

return if (result != null) {
ResponseEntity.ok(result)
} else {
ResponseEntity.noContent().build()
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,24 +20,26 @@ import java.util.UUID
@Entity
@Table(
name = "visitor_profiles",
uniqueConstraints = [UniqueConstraint(
name = "uq_visitor_profiles_phone_site",
columnNames = ["phone_number", "site_id"]
)]
uniqueConstraints = [
UniqueConstraint(
name = "uq_visitor_profiles_phone_site",
columnNames = ["phone_number", "site_id"]
)
]
)
class VisitorProfile(
@Id
@GeneratedValue(strategy = GenerationType.UUID)
@Column(updatable = false, nullable = false)
override var id: UUID? = null,

@Column(nullable = false)
@Column(nullable = false, length = 100)
var name: String,

@Column(nullable = false, name = "phone_number", length = 25)
var phoneNumber: String,

@ManyToOne(fetch = FetchType.LAZY)
@ManyToOne(fetch = FetchType.LAZY, optional = false)
@JoinColumn(name = "site_id", nullable = false)
var site: Site,

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package io.github.devcavin.gatelog.backend.visitors

import io.github.devcavin.gatelog.backend.users.User
import io.github.devcavin.gatelog.backend.visitors.dto.UpdateVisitorProfileRequest
import io.github.devcavin.gatelog.backend.visitors.dto.VisitorProfileResponse
import jakarta.validation.Valid
import org.springframework.http.ResponseEntity
import org.springframework.security.access.prepost.PreAuthorize
import org.springframework.security.core.annotation.AuthenticationPrincipal
import org.springframework.web.bind.annotation.PathVariable
import org.springframework.web.bind.annotation.PutMapping
import org.springframework.web.bind.annotation.RequestBody
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RestController
import java.util.UUID

@RestController
@RequestMapping("/api/visitor-profiles")
class VisitorProfileController(
private val visitorProfileService: VisitorProfileService
) {

@PutMapping("/{profileId}")
@PreAuthorize(
"hasAnyRole('SUPER_ADMIN', 'MANAGER', 'STAFF')"
)
fun update(
@AuthenticationPrincipal requestedBy: User,
@PathVariable profileId: UUID,
@Valid @RequestBody request: UpdateVisitorProfileRequest
): ResponseEntity<VisitorProfileResponse> =
ResponseEntity.ok(
visitorProfileService.update(
requestedBy,
profileId,
request
)
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,16 @@ import org.springframework.data.jpa.repository.JpaRepository
import org.springframework.stereotype.Repository
import java.util.UUID

@Repository
interface VisitorProfileRepository : JpaRepository<VisitorProfile, UUID> {
fun findBySiteIdAndPhoneNumber(siteId: UUID, phoneNumber: String): VisitorProfile?
fun existsBySiteIdAndPhoneNumber(siteId: UUID, phoneNumber: String): Boolean
interface VisitorProfileRepository :
JpaRepository<VisitorProfile, UUID> {

fun findBySiteIdAndPhoneNumber(
siteId: UUID,
phoneNumber: String
): VisitorProfile?

fun existsBySiteIdAndPhoneNumber(
siteId: UUID,
phoneNumber: String
): Boolean
}
Loading
Loading