admin: Require to be identitied to change the history

This commit is contained in:
nemunaire 2024-03-17 11:20:38 +01:00
parent 977caccc1f
commit c638789b61
5 changed files with 44 additions and 8 deletions

View File

@ -35,9 +35,12 @@ func declareExercicesRoutes(router *gin.RouterGroup) {
apiExercicesRoutes.GET("/stats.json", getExerciceStats) apiExercicesRoutes.GET("/stats.json", getExerciceStats)
apiExercicesRoutes.GET("/history.json", getExerciceHistory) apiExercicesRoutes.GET("/history.json", getExerciceHistory)
apiExercicesRoutes.PUT("/history.json", appendExerciceHistory)
apiExercicesRoutes.PATCH("/history.json", updateExerciceHistory) apiHistoryRoutes := apiExercicesRoutes.Group("/history.json")
apiExercicesRoutes.DELETE("/history.json", delExerciceHistory) apiHistoryRoutes.Use(AssigneeCookieHandler)
apiHistoryRoutes.PUT("", appendExerciceHistory)
apiHistoryRoutes.PATCH("", updateExerciceHistory)
apiHistoryRoutes.DELETE("", delExerciceHistory)
apiExercicesRoutes.GET("/hints", listExerciceHints) apiExercicesRoutes.GET("/hints", listExerciceHints)
apiExercicesRoutes.POST("/hints", createExerciceHint) apiExercicesRoutes.POST("/hints", createExerciceHint)
@ -469,6 +472,30 @@ func getExercicesStats(c *gin.Context) {
c.JSON(http.StatusOK, ret) c.JSON(http.StatusOK, ret)
} }
func AssigneeCookieHandler(c *gin.Context) {
myassignee, err := c.Cookie("myassignee")
if err != nil {
c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"errmsg": "You must be authenticated to perform this action."})
return
}
aid, err := strconv.ParseInt(myassignee, 10, 32)
if err != nil {
c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"errmsg": "You must be authenticated to perform this action: invalid assignee identifier."})
return
}
assignee, err := fic.GetAssignee(aid)
if err != nil {
c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"errmsg": "You must be authenticated to perform this action: assignee not found."})
return
}
c.Set("assignee", assignee)
c.Next()
}
type uploadedExerciceHistory struct { type uploadedExerciceHistory struct {
IdTeam int64 `json:"team_id"` IdTeam int64 `json:"team_id"`
Kind string Kind string
@ -479,6 +506,7 @@ type uploadedExerciceHistory struct {
func appendExerciceHistory(c *gin.Context) { func appendExerciceHistory(c *gin.Context) {
exercice := c.MustGet("exercice").(*fic.Exercice) exercice := c.MustGet("exercice").(*fic.Exercice)
myassignee := c.MustGet("assignee").(*fic.ClaimAssignee)
var uh uploadedExerciceHistory var uh uploadedExerciceHistory
err := c.ShouldBindJSON(&uh) err := c.ShouldBindJSON(&uh)
@ -493,12 +521,14 @@ func appendExerciceHistory(c *gin.Context) {
c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"errmsg": "An error occurs during history moditication."}) c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"errmsg": "An error occurs during history moditication."})
return return
} }
log.Printf("AUDIT: %s performs an history append: %s for team %d, exercice %d and optional %v", myassignee.Name, uh.Kind, uh.IdTeam, exercice.Id, uh.Secondary)
c.JSON(http.StatusOK, uh) c.JSON(http.StatusOK, uh)
} }
func updateExerciceHistory(c *gin.Context) { func updateExerciceHistory(c *gin.Context) {
exercice := c.MustGet("exercice").(*fic.Exercice) exercice := c.MustGet("exercice").(*fic.Exercice)
myassignee := c.MustGet("assignee").(*fic.ClaimAssignee)
var uh uploadedExerciceHistory var uh uploadedExerciceHistory
err := c.ShouldBindJSON(&uh) err := c.ShouldBindJSON(&uh)
@ -513,12 +543,14 @@ func updateExerciceHistory(c *gin.Context) {
c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"errmsg": "An error occurs during history update."}) c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"errmsg": "An error occurs during history update."})
return return
} }
log.Printf("AUDIT: %s performs an history update: %s for team %d, exercice %d and optional %v, with coeff %f", myassignee.Name, uh.Kind, uh.IdTeam, exercice.Id, uh.Secondary, uh.Coeff)
c.JSON(http.StatusOK, uh) c.JSON(http.StatusOK, uh)
} }
func delExerciceHistory(c *gin.Context) { func delExerciceHistory(c *gin.Context) {
exercice := c.MustGet("exercice").(*fic.Exercice) exercice := c.MustGet("exercice").(*fic.Exercice)
myassignee := c.MustGet("assignee").(*fic.ClaimAssignee)
var uh uploadedExerciceHistory var uh uploadedExerciceHistory
err := c.ShouldBindJSON(&uh) err := c.ShouldBindJSON(&uh)
@ -533,6 +565,7 @@ func delExerciceHistory(c *gin.Context) {
c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"errmsg": "An error occurs during history deletion."}) c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"errmsg": "An error occurs during history deletion."})
return return
} }
log.Printf("AUDIT: %s performs an history deletion: %s for team %d, exercice %d and optional %v", myassignee.Name, uh.Kind, uh.IdTeam, exercice.Id, uh.Secondary)
c.JSON(http.StatusOK, true) c.JSON(http.StatusOK, true)
} }

View File

@ -516,6 +516,8 @@ angular.module("FICApp")
}, 750); }, 750);
} }
}); });
$rootScope.logged = parseInt(getCookie("myassignee")) > 0;
}) })
.controller("VersionController", function($scope, Version) { .controller("VersionController", function($scope, Version) {

View File

@ -85,7 +85,7 @@
<div class="btn-group mx-2" role="group"> <div class="btn-group mx-2" role="group">
<button type="button" ng-click="addChoice()" class="btn btn-sm btn-primary"><span class="glyphicon glyphicon-plus" aria-hidden="true"></span> Ajouter choix</button> <button type="button" ng-click="addChoice()" class="btn btn-sm btn-primary"><span class="glyphicon glyphicon-plus" aria-hidden="true"></span> Ajouter choix</button>
</div> </div>
<div class="btn-group" role="group"> <div class="btn-group" role="group" ng-show="logged">
<button type="button" class="btn btn-sm btn-dark" data-toggle="modal" data-target="#validationModal" data-flag="{{ flag.label }}" data-flagid="{{ flag.id }}" data-kind="flag_found"><span class="glyphicon glyphicon-check" aria-hidden="true"></span> Valider pour &nbsp;</button> <button type="button" class="btn btn-sm btn-dark" data-toggle="modal" data-target="#validationModal" data-flag="{{ flag.label }}" data-flagid="{{ flag.id }}" data-kind="flag_found"><span class="glyphicon glyphicon-check" aria-hidden="true"></span> Valider pour &nbsp;</button>
</div> </div>
</div> </div>

View File

@ -306,11 +306,12 @@
</div> </div>
</div> </div>
<div class="mt-2" style="overflow-y: scroll; height: 450px" ng-controller="ExerciceHistoryController"> <div class="mt-2" style="overflow-y: scroll; height: 450px" id="exercicehistory" ng-controller="ExerciceHistoryController">
<div class="d-flex justify-content-between align-items-start"> <div class="d-flex justify-content-between align-items-start">
<h3>Historique</h3> <h3>Historique</h3>
<div class="btn-group" role="group"> <div class="btn-group" role="group">
<button type="button" class="btn btn-sm btn-dark" data-toggle="modal" data-target="#appendHistoryModal"><span class="glyphicon glyphicon-plus" aria-hidden="true"></span></button> <button type="button" class="btn btn-sm btn-dark" data-toggle="modal" data-target="#appendHistoryModal" ng-show="logged"><span class="glyphicon glyphicon-plus" aria-hidden="true"></span></button>
<button type="button" class="btn btn-sm btn-primary" ng-click="refreshHistory()"><span class="glyphicon glyphicon-refresh" aria-hidden="true"></span></button>
</div> </div>
</div> </div>
<table class="table table-hover table-striped table-bordered bg-primary text-light"> <table class="table table-hover table-striped table-bordered bg-primary text-light">
@ -331,7 +332,7 @@
</span> </span>
<span ng-if="!row.secondary_title && row.secondary && row.kind != 'solved'">: {{ row.secondary }}</span> <span ng-if="!row.secondary_title && row.secondary && row.kind != 'solved'">: {{ row.secondary }}</span>
</td> </td>
<td style="vertical-align: middle; padding: 0; background-color: {{ row.team_color }}"> <td style="vertical-align: middle; padding: 0; background-color: {{ row.team_color }}" ng-show="logged">
<button type="button" data-toggle="modal" data-target="#updHistory" ng-if="row.kind != 'flag_found' && row.kind != 'tries' && row.kind != 'mcq_found'" data-idteam="{{ row.team_id }}" data-kind="{{ row.kind }}" data-time="{{ row.time }}" data-secondary="{{ row.secondary }}" data-coeff="{{ row.coefficient }}" class="float-right btn btn-sm btn-info"><span class="glyphicon glyphicon-edit" aria-hidden="true"></span></button> <button type="button" data-toggle="modal" data-target="#updHistory" ng-if="row.kind != 'flag_found' && row.kind != 'tries' && row.kind != 'mcq_found'" data-idteam="{{ row.team_id }}" data-kind="{{ row.kind }}" data-time="{{ row.time }}" data-secondary="{{ row.secondary }}" data-coeff="{{ row.coefficient }}" class="float-right btn btn-sm btn-info"><span class="glyphicon glyphicon-edit" aria-hidden="true"></span></button>
<button type="button" ng-click="delHistory(row)" class="float-right btn btn-sm btn-danger"><span class="glyphicon glyphicon-remove" aria-hidden="true"></span></button> <button type="button" ng-click="delHistory(row)" class="float-right btn btn-sm btn-danger"><span class="glyphicon glyphicon-remove" aria-hidden="true"></span></button>
</td> </td>

View File

@ -168,7 +168,7 @@
<span ng-if="!row.secondary_title && row.secondary && row.kind == 'solved'">(coeff x{{ row.secondary }})</span> <span ng-if="!row.secondary_title && row.secondary && row.kind == 'solved'">(coeff x{{ row.secondary }})</span>
<span ng-if="!row.secondary_title && row.secondary && row.kind != 'solved'">: {{ row.secondary }}</span> <span ng-if="!row.secondary_title && row.secondary && row.kind != 'solved'">: {{ row.secondary }}</span>
</td> </td>
<td style="vertical-align: middle; padding: 0"> <td style="vertical-align: middle; padding: 0" ng-show="logged">
<button type="button" data-toggle="modal" data-target="#updHistory" ng-if="row.kind != 'flag_found' && row.kind != 'tries' && row.kind != 'mcq_found'" data-kind="{{ row.kind }}" data-time="{{ row.time }}" data-primary="{{ row.primary }}" data-secondary="{{ row.secondary }}" data-coeff="{{ row.coefficient }}" class="float-right btn btn-sm btn-info"><span class="glyphicon glyphicon-edit" aria-hidden="true"></span></button> <button type="button" data-toggle="modal" data-target="#updHistory" ng-if="row.kind != 'flag_found' && row.kind != 'tries' && row.kind != 'mcq_found'" data-kind="{{ row.kind }}" data-time="{{ row.time }}" data-primary="{{ row.primary }}" data-secondary="{{ row.secondary }}" data-coeff="{{ row.coefficient }}" class="float-right btn btn-sm btn-info"><span class="glyphicon glyphicon-edit" aria-hidden="true"></span></button>
<button type="button" ng-click="delHistory(row)" class="float-right btn btn-sm btn-danger"><span class="glyphicon glyphicon-remove" aria-hidden="true"></span></button> <button type="button" ng-click="delHistory(row)" class="float-right btn btn-sm btn-danger"><span class="glyphicon glyphicon-remove" aria-hidden="true"></span></button>
</td> </td>