-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
15 changed files
with
488 additions
and
33 deletions.
There are no files selected for viewing
48 changes: 48 additions & 0 deletions
48
backend/src/main/kotlin/hu/bme/sch/cmsch/component/errorlog/ErrorLogApiController.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
package hu.bme.sch.cmsch.component.errorlog | ||
|
||
import hu.bme.sch.cmsch.model.RoleType | ||
import hu.bme.sch.cmsch.util.getUserOrNull | ||
import org.springframework.http.HttpStatus | ||
import org.springframework.http.ResponseEntity | ||
import org.springframework.security.core.Authentication | ||
import org.springframework.transaction.annotation.Isolation | ||
import org.springframework.transaction.annotation.Transactional | ||
import org.springframework.web.bind.annotation.PostMapping | ||
import org.springframework.web.bind.annotation.RequestBody | ||
import org.springframework.web.bind.annotation.RequestMapping | ||
import org.springframework.web.bind.annotation.RestController | ||
import java.util.Optional | ||
|
||
@RestController() | ||
@RequestMapping("/api") | ||
class ErrorLogApiController( | ||
private val errorLogComponent: Optional<ErrorLogComponent>, | ||
private val errorLogService: Optional<ErrorLogService> | ||
) { | ||
|
||
data class ErrorReportDto(val message: String?, val stack: String?, val userAgent: String?, val href: String?) | ||
|
||
@PostMapping("/error/submit") | ||
@Transactional(isolation = Isolation.SERIALIZABLE) | ||
fun submitError(auth: Authentication?, @RequestBody error: ErrorReportDto): ResponseEntity<Any> { | ||
if (error.message == null && error.stack == null && error.userAgent == null && error.href == null) | ||
return ResponseEntity.badRequest().build() | ||
|
||
val role = auth?.getUserOrNull()?.role ?: RoleType.GUEST | ||
if (!errorLogComponent.map { it.minRole.isAvailableForRole(role) }.orElse(true)) | ||
return ResponseEntity.status(HttpStatus.FORBIDDEN).build() | ||
|
||
errorLogService.ifPresent { | ||
it.submit( | ||
message = error.message ?: "", | ||
stack = error.stack ?: "", | ||
userAgent = error.userAgent ?: "", | ||
href = error.href ?: "", | ||
role = role | ||
) | ||
} | ||
|
||
return ResponseEntity.ok().build() | ||
} | ||
|
||
} |
54 changes: 54 additions & 0 deletions
54
backend/src/main/kotlin/hu/bme/sch/cmsch/component/errorlog/ErrorLogComponent.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
package hu.bme.sch.cmsch.component.errorlog | ||
|
||
import hu.bme.sch.cmsch.component.* | ||
import hu.bme.sch.cmsch.component.app.ComponentSettingService | ||
import hu.bme.sch.cmsch.model.RoleType | ||
import hu.bme.sch.cmsch.service.ControlPermissions | ||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty | ||
import org.springframework.core.env.Environment | ||
import org.springframework.stereotype.Service | ||
|
||
@Service | ||
@ConditionalOnProperty( | ||
prefix = "hu.bme.sch.cmsch.component.load", | ||
name = ["errorlog"], | ||
havingValue = "true", | ||
matchIfMissing = false | ||
) | ||
class ErrorLogComponent( | ||
componentSettingService: ComponentSettingService, | ||
env: Environment | ||
) : ComponentBase( | ||
"errorlog", | ||
"/errorlog", | ||
"Kliens hibaüzenetek", | ||
ControlPermissions.PERMISSION_CONTROL_ERROR_LOG, | ||
listOf(ErrorLogEntity::class), | ||
componentSettingService, env | ||
) { | ||
|
||
final override val allSettings by lazy { | ||
listOf(errorLogGroup, menuDisplayName, minRole, receiveReports) | ||
} | ||
|
||
val errorLogGroup = SettingProxy(componentSettingService, component, | ||
"errorLogGroup", "", type = SettingType.COMPONENT_GROUP, persist = false, | ||
fieldName = "Kliens hibák", | ||
description = "" | ||
) | ||
|
||
final override val menuDisplayName = SettingProxy(componentSettingService, component, | ||
"menuDisplayName", "Kliens hibák", serverSideOnly = true, | ||
fieldName = "Menü neve", description = "Ez lesz a neve a menünek" | ||
) | ||
|
||
final override val minRole = MinRoleSettingProxy(componentSettingService, component, | ||
"minRole", MinRoleSettingProxy.ALL_ROLES, minRoleToEdit = RoleType.SUPERUSER, | ||
fieldName = "Jogosultságok", description = "Melyik roleok küldhetnek hibajelentéseket" | ||
) | ||
|
||
val receiveReports = SettingProxy(componentSettingService, component, "receiveReports", "true", | ||
type = SettingType.BOOLEAN, fieldName = "Kliens hibajelentések fogadása", serverSideOnly = true | ||
) | ||
|
||
} |
29 changes: 29 additions & 0 deletions
29
backend/src/main/kotlin/hu/bme/sch/cmsch/component/errorlog/ErrorLogComponentController.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
package hu.bme.sch.cmsch.component.errorlog | ||
|
||
import hu.bme.sch.cmsch.component.ComponentApiBase | ||
import hu.bme.sch.cmsch.component.app.MenuService | ||
import hu.bme.sch.cmsch.service.AdminMenuService | ||
import hu.bme.sch.cmsch.service.AuditLogService | ||
import hu.bme.sch.cmsch.service.ControlPermissions.PERMISSION_CONTROL_ERROR_LOG | ||
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean | ||
import org.springframework.stereotype.Controller | ||
import org.springframework.web.bind.annotation.RequestMapping | ||
|
||
@Controller | ||
@RequestMapping("/admin/control/component/errorlog") | ||
@ConditionalOnBean(ErrorLogComponent::class) | ||
class ErrorLogComponentController( | ||
adminMenuService: AdminMenuService, | ||
component: ErrorLogComponent, | ||
menuService: MenuService, | ||
auditLogService: AuditLogService | ||
) : ComponentApiBase( | ||
adminMenuService, | ||
ErrorLogComponent::class.java, | ||
component, | ||
PERMISSION_CONTROL_ERROR_LOG, | ||
"Kliens hibaüzenetek", | ||
"Kliens hibaüzenetek testreszabása", | ||
menuService = menuService, | ||
auditLogService = auditLogService | ||
) |
10 changes: 10 additions & 0 deletions
10
...c/main/kotlin/hu/bme/sch/cmsch/component/errorlog/ErrorLogComponentEntityConfiguration.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
package hu.bme.sch.cmsch.component.errorlog | ||
|
||
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean | ||
import org.springframework.boot.autoconfigure.domain.EntityScan | ||
import org.springframework.context.annotation.Configuration | ||
|
||
@Configuration | ||
@ConditionalOnBean(ErrorLogComponent::class) | ||
@EntityScan(basePackageClasses = [ErrorLogComponent::class]) | ||
class ErrorLogComponentEntityConfiguration |
58 changes: 58 additions & 0 deletions
58
backend/src/main/kotlin/hu/bme/sch/cmsch/component/errorlog/ErrorLogController.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
package hu.bme.sch.cmsch.component.errorlog | ||
|
||
import com.fasterxml.jackson.databind.ObjectMapper | ||
import hu.bme.sch.cmsch.controller.admin.OneDeepEntityPage | ||
import hu.bme.sch.cmsch.controller.admin.calculateSearchSettings | ||
import hu.bme.sch.cmsch.service.AdminMenuService | ||
import hu.bme.sch.cmsch.service.AuditLogService | ||
import hu.bme.sch.cmsch.service.ImplicitPermissions | ||
import hu.bme.sch.cmsch.service.ImportService | ||
import hu.bme.sch.cmsch.service.StaffPermissions | ||
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean | ||
import org.springframework.core.env.Environment | ||
import org.springframework.stereotype.Controller | ||
import org.springframework.transaction.PlatformTransactionManager | ||
import org.springframework.web.bind.annotation.RequestMapping | ||
|
||
@Controller | ||
@RequestMapping("/admin/control/errorlog") | ||
@ConditionalOnBean(ErrorLogComponent::class) | ||
class ErrorLogController( | ||
repo: ErrorLogRepository, | ||
importService: ImportService, | ||
adminMenuService: AdminMenuService, | ||
component: ErrorLogComponent, | ||
auditLog: AuditLogService, | ||
objectMapper: ObjectMapper, | ||
transactionManager: PlatformTransactionManager, | ||
env: Environment | ||
) : OneDeepEntityPage<ErrorLogEntity>( | ||
"errorlog", | ||
ErrorLogEntity::class, ::ErrorLogEntity, | ||
"Hibaüzenet", "Hibaüzenetek", | ||
"A jelentett hibaüzenetek megtekintése", | ||
|
||
transactionManager, | ||
repo, | ||
importService, | ||
adminMenuService, | ||
component, | ||
auditLog, | ||
objectMapper, | ||
env, | ||
|
||
showPermission = StaffPermissions.PERMISSION_SHOW_ERROR_LOG, | ||
createPermission = ImplicitPermissions.PERMISSION_NOBODY, | ||
editPermission = ImplicitPermissions.PERMISSION_NOBODY, | ||
deletePermission = StaffPermissions.PERMISSION_DELETE_ERROR_LOG, | ||
|
||
createEnabled = false, | ||
editEnabled = false, | ||
deleteEnabled = true, | ||
importEnabled = false, | ||
exportEnabled = true, | ||
|
||
adminMenuIcon = "error", | ||
adminMenuPriority = 1, | ||
searchSettings = calculateSearchSettings<ErrorLogEntity>(true) | ||
) |
121 changes: 121 additions & 0 deletions
121
backend/src/main/kotlin/hu/bme/sch/cmsch/component/errorlog/ErrorLogEntity.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,121 @@ | ||
package hu.bme.sch.cmsch.component.errorlog | ||
|
||
import com.fasterxml.jackson.annotation.JsonView | ||
import hu.bme.sch.cmsch.admin.* | ||
import hu.bme.sch.cmsch.component.EntityConfig | ||
import hu.bme.sch.cmsch.dto.Edit | ||
import hu.bme.sch.cmsch.dto.FullDetails | ||
import hu.bme.sch.cmsch.dto.Preview | ||
import hu.bme.sch.cmsch.model.ManagedEntity | ||
import hu.bme.sch.cmsch.model.RoleType | ||
import hu.bme.sch.cmsch.service.StaffPermissions | ||
import jakarta.persistence.* | ||
import org.hibernate.Hibernate | ||
import org.hibernate.annotations.JdbcTypeCode | ||
import org.hibernate.type.SqlTypes | ||
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean | ||
import org.springframework.core.env.Environment | ||
|
||
|
||
@Entity | ||
@Table( | ||
name = "errorLog", | ||
uniqueConstraints = [UniqueConstraint(columnNames = ["message", "stack", "userAgent", "href", "role"])] | ||
) | ||
@ConditionalOnBean(ErrorLogComponent::class) | ||
data class ErrorLogEntity( | ||
@Id | ||
@GeneratedValue | ||
@field:JsonView(value = [Edit::class]) | ||
@Column(nullable = false) | ||
@property:GenerateInput(type = INPUT_TYPE_HIDDEN, visible = true, ignore = true) | ||
@property:GenerateOverview(renderer = OVERVIEW_TYPE_ID, columnName = "ID", order = -1) | ||
override var id: Int = 0, | ||
|
||
@field:JsonView(value = [Edit::class, Preview::class, FullDetails::class]) | ||
@Column(nullable = false, length = 2048) | ||
@property:GenerateInput(maxLength = 512, type = INPUT_TYPE_BLOCK_TEXT, order = 1, label = "Hiba") | ||
@property:GenerateOverview(columnName = "Hiba", order = 1, useForSearch = true) | ||
@property:ImportFormat | ||
var message: String = "", | ||
|
||
@field:JsonView(value = [Edit::class, Preview::class, FullDetails::class]) | ||
@Column(nullable = false, length = 25000) | ||
@property:GenerateInput(maxLength = 2048, type = INPUT_TYPE_BLOCK_TEXT, order = 2, label = "Stacktrace") | ||
@property:GenerateOverview(visible = false, columnName = "Stacktrace", order = 2, useForSearch = true) | ||
@property:ImportFormat | ||
var stack: String = "", | ||
|
||
@field:JsonView(value = [Edit::class, Preview::class, FullDetails::class]) | ||
@Column(nullable = false, length = 1024) | ||
@property:GenerateInput(maxLength = 512, type = INPUT_TYPE_BLOCK_TEXT, order = 3, label = "User Agent") | ||
@property:GenerateOverview(visible = false, columnName = "User Agent", order = 3, useForSearch = true) | ||
@property:ImportFormat | ||
var userAgent: String = "", | ||
|
||
@field:JsonView(value = [Edit::class, Preview::class, FullDetails::class]) | ||
@Column(nullable = false, length = 2048) | ||
@property:GenerateInput(maxLength = 512, order = 4, label = "href") | ||
@property:GenerateOverview(columnName = "href", order = 4, useForSearch = true) | ||
@property:ImportFormat | ||
var href: String = "", | ||
|
||
@field:JsonView(value = [Edit::class, FullDetails::class]) | ||
@Enumerated(EnumType.STRING) | ||
@JdbcTypeCode(SqlTypes.VARCHAR) | ||
@property:GenerateInput( | ||
type = INPUT_TYPE_BLOCK_SELECT, order = 5, label = "Jogkör", | ||
source = ["GUEST", "BASIC", "ATTENDEE", "PRIVILEGED", "STAFF", "ADMIN", "SUPERUSER"], | ||
minimumRole = RoleType.ADMIN, note = "BASIC = belépett, STAFF = rendező, ADMIN = minden jog" | ||
) | ||
@property:GenerateOverview(visible = true, columnName = "Jelentő jogköre", order = 5) | ||
@property:ImportFormat | ||
var role: RoleType = RoleType.GUEST, | ||
|
||
@field:JsonView(value = [Edit::class, Preview::class, FullDetails::class]) | ||
@Column(nullable = false) | ||
@property:GenerateInput(type = INPUT_TYPE_NUMBER, order = 6, label = "Ennyiszer jelentve") | ||
@property:GenerateOverview( | ||
visible = true, | ||
columnName = "Ennyiszer jelentve", | ||
order = 6, | ||
renderer = OVERVIEW_TYPE_NUMBER | ||
) | ||
@property:ImportFormat | ||
var count: Long = 1, | ||
|
||
@field:JsonView(value = [Edit::class, Preview::class, FullDetails::class]) | ||
@Column(nullable = false) | ||
@property:GenerateInput(type = INPUT_TYPE_DATE, order = 7, label = "Utoljára jelentve") | ||
@property:GenerateOverview( | ||
visible = true, | ||
columnName = "Utoljára jelentve", | ||
order = 7, | ||
renderer = OVERVIEW_TYPE_DATE | ||
) | ||
@property:ImportFormat | ||
var lastReportedAt: Long = 0, | ||
) : ManagedEntity { | ||
|
||
override fun getEntityConfig(env: Environment) = EntityConfig( | ||
name = "ErrorLogEntity", | ||
view = "control/errorlog", | ||
showPermission = StaffPermissions.PERMISSION_SHOW_ERROR_LOG | ||
) | ||
|
||
override fun equals(other: Any?): Boolean { | ||
if (this === other) return true | ||
if (other == null || Hibernate.getClass(this) != Hibernate.getClass(other)) return false | ||
other as ErrorLogEntity | ||
|
||
return id != 0 && id == other.id | ||
} | ||
|
||
override fun hashCode(): Int = javaClass.hashCode() | ||
|
||
@Override | ||
override fun toString(): String { | ||
return this::class.simpleName + "(id = $id )" | ||
} | ||
|
||
} |
26 changes: 26 additions & 0 deletions
26
backend/src/main/kotlin/hu/bme/sch/cmsch/component/errorlog/ErrorLogRepository.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
package hu.bme.sch.cmsch.component.errorlog | ||
|
||
import hu.bme.sch.cmsch.model.RoleType | ||
import hu.bme.sch.cmsch.repository.EntityPageDataSource | ||
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean | ||
import org.springframework.data.jpa.repository.Query | ||
import org.springframework.data.repository.CrudRepository | ||
import org.springframework.stereotype.Repository | ||
import java.util.Optional | ||
|
||
@Repository | ||
@ConditionalOnBean(ErrorLogComponent::class) | ||
interface ErrorLogRepository : CrudRepository<ErrorLogEntity, Int>, EntityPageDataSource<ErrorLogEntity, Int> { | ||
|
||
@Query("select e from ErrorLogEntity e order by e.lastReportedAt desc") | ||
override fun findAll(): List<ErrorLogEntity> | ||
|
||
fun findByMessageAndStackAndUserAgentAndHrefAndRole( | ||
message: String, | ||
stack: String, | ||
userAgent: String, | ||
href: String, | ||
role: RoleType | ||
): Optional<ErrorLogEntity> | ||
|
||
} |
41 changes: 41 additions & 0 deletions
41
backend/src/main/kotlin/hu/bme/sch/cmsch/component/errorlog/ErrorLogService.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
package hu.bme.sch.cmsch.component.errorlog | ||
|
||
import hu.bme.sch.cmsch.model.RoleType | ||
import hu.bme.sch.cmsch.service.TimeService | ||
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean | ||
import org.springframework.stereotype.Service | ||
import org.springframework.transaction.annotation.Isolation | ||
import org.springframework.transaction.annotation.Transactional | ||
import kotlin.jvm.optionals.getOrNull | ||
|
||
@Service | ||
@ConditionalOnBean(ErrorLogComponent::class) | ||
class ErrorLogService( | ||
private val errorLogComponent: ErrorLogComponent, | ||
private val errorLogRepository: ErrorLogRepository, | ||
private val clock: TimeService | ||
) { | ||
|
||
@Transactional(isolation = Isolation.SERIALIZABLE) | ||
fun submit(message: String, stack: String, userAgent: String, href: String, role: RoleType) { | ||
if (!errorLogComponent.receiveReports.isValueTrue()) return | ||
|
||
val existingLog = errorLogRepository | ||
.findByMessageAndStackAndUserAgentAndHrefAndRole(message, stack, userAgent, href, role).getOrNull() | ||
|
||
val logToSave = existingLog ?: ErrorLogEntity( | ||
message = message, | ||
stack = stack, | ||
userAgent = userAgent, | ||
href = href, | ||
role = role, | ||
) | ||
logToSave.apply { | ||
count = count + 1 | ||
lastReportedAt = clock.getTimeInSeconds() | ||
} | ||
|
||
errorLogRepository.save(logToSave) | ||
} | ||
|
||
} |
Oops, something went wrong.