Compare commits
3 Commits
a5105979cc
...
87d60c5fd5
Author | SHA1 | Date | |
---|---|---|---|
87d60c5fd5 | |||
b119fe5da4 | |||
d787d1c350 |
15
surveys.go
15
surveys.go
@ -52,6 +52,7 @@ func declareAPISurveysRoutes(router *gin.RouterGroup) {
|
|||||||
|
|
||||||
surveysRoutes := router.Group("/surveys/:sid")
|
surveysRoutes := router.Group("/surveys/:sid")
|
||||||
surveysRoutes.Use(surveyHandler)
|
surveysRoutes.Use(surveyHandler)
|
||||||
|
surveysRoutes.Use(surveyUserAccessHandler)
|
||||||
|
|
||||||
surveysRoutes.GET("", func(c *gin.Context) {
|
surveysRoutes.GET("", func(c *gin.Context) {
|
||||||
u := c.MustGet("LoggedUser").(*User)
|
u := c.MustGet("LoggedUser").(*User)
|
||||||
@ -198,6 +199,20 @@ func surveyHandler(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func surveyUserAccessHandler(c *gin.Context) {
|
||||||
|
u := c.MustGet("LoggedUser").(*User)
|
||||||
|
w := c.MustGet("survey").(*Survey)
|
||||||
|
|
||||||
|
if u.IsAdmin {
|
||||||
|
c.Next()
|
||||||
|
} else if w.Shown && (w.Group == "" || strings.Contains(u.Groups, ","+w.Group+",")) {
|
||||||
|
c.Next()
|
||||||
|
} else {
|
||||||
|
c.AbortWithStatusJSON(http.StatusNotFound, gin.H{"errmsg": "Survey not found."})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
type Survey struct {
|
type Survey struct {
|
||||||
Id int64 `json:"id"`
|
Id int64 `json:"id"`
|
||||||
Title string `json:"title"`
|
Title string `json:"title"`
|
||||||
|
@ -82,17 +82,20 @@
|
|||||||
{#each repos as repo (repo.id)}
|
{#each repos as repo (repo.id)}
|
||||||
<div class="{className} card">
|
<div class="{className} card">
|
||||||
<div class="card-body d-flex justify-content-between">
|
<div class="card-body d-flex justify-content-between">
|
||||||
<div class="d-flex flex-column justify-content-center">
|
<div class="d-flex flex-column justify-content-center pe-3">
|
||||||
<div>
|
<div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<label for={repo.id + "url"} class="col-sm-6 col-form-label">Dépôt lié :</label>
|
<label for={repo.id + "url"} class="col-sm-4 col-form-label">Dépôt lié :</label>
|
||||||
<div class="col-sm-6">
|
<div class="col-sm-8">
|
||||||
<input type="text" class="form-control form-control-sm" style="font-family: monospace" disabled id={repo.id + "url"} value={repo.uri}>
|
<input type="text" class="form-control form-control-sm" style="font-family: monospace" disabled id={repo.id + "url"} value={repo.uri}>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<p class="mt-2 mb-0 pe-1">
|
||||||
|
Vous pouvez ajouter un <span class="fst-italic">webhook</span> sur les <span class="fst-italic"><strong>Tag push events</strong></span> afin d'automatiser la récupération de votre travail. Dans les paramètres de votre dépôt sur GitLab, faite pointer un webhook sur <code>https://lessons.nemunai.re/api/callbacks/trigger.json</code> avec le secret ci-dessous.
|
||||||
|
</p>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<label for={repo.id + "secret"} class="col-sm-6 col-form-label">Webhook Secret token (à indiquer dans GitLab) :</label>
|
<label for={repo.id + "secret"} class="col-sm-4 col-form-label">Webhook Secret token :</label>
|
||||||
<div class="col-sm-6">
|
<div class="col-sm-8">
|
||||||
<div class="input-group">
|
<div class="input-group">
|
||||||
<input type={repo.show_secret?"text":"password"} class="form-control form-control-sm" disabled id={repo.id + "secret"} value={repo.secret}>
|
<input type={repo.show_secret?"text":"password"} class="form-control form-control-sm" disabled id={repo.id + "secret"} value={repo.secret}>
|
||||||
<button class="btn btn-sm btn-outline-info" on:click={() => { repo.show_secret = !repo.show_secret}}>
|
<button class="btn btn-sm btn-outline-info" on:click={() => { repo.show_secret = !repo.show_secret}}>
|
||||||
@ -175,7 +178,7 @@
|
|||||||
<button
|
<button
|
||||||
type="submit"
|
type="submit"
|
||||||
class="mt-2 btn btn-primary"
|
class="mt-2 btn btn-primary"
|
||||||
disable={submitInProgress || readonly}
|
disable={submitInProgress || readonly || !repo_used || !repo_used.uri}
|
||||||
>
|
>
|
||||||
Utiliser ce dépôt
|
Utiliser ce dépôt
|
||||||
</button>
|
</button>
|
||||||
|
@ -145,8 +145,7 @@
|
|||||||
<ul>
|
<ul>
|
||||||
<li>être dans l'espace de nom de votre utilisateur (à la fin de la liste des <span class="fst-italic">namespaces</span>),</li>
|
<li>être dans l'espace de nom de votre utilisateur (à la fin de la liste des <span class="fst-italic">namespaces</span>),</li>
|
||||||
<li>avoir la visibilité « Privé »,</li>
|
<li>avoir la visibilité « Privé »,</li>
|
||||||
<li>avoir invité <a href="https://gitlab.cri.epita.fr/nemunaire" target="_blank" style="font-family: monospace">nemunaire</a> avec le rôle <span class="fst-italic">Reporter</span> une fois le dépôt créé,</li>
|
<li>avoir invité <a href="https://gitlab.cri.epita.fr/nemunaire" target="_blank" style="font-family: monospace">nemunaire</a> avec le rôle <span class="fst-italic">Reporter</span> une fois le dépôt créé.</li>
|
||||||
<li>avoir configuré un <span class="fst-italic">webhook <strong>Tag push events</strong></span> pointant sur <code>https://lessons.nemunai.re/api/callbacks/trigger.json</code> avec le secret donné.</li>
|
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
{#if w.tag}
|
{#if w.tag}
|
||||||
|
19
works.go
19
works.go
@ -190,6 +190,7 @@ func declareAPIAdminWorksRoutes(router *gin.RouterGroup) {
|
|||||||
func declareAPIAuthWorksRoutes(router *gin.RouterGroup) {
|
func declareAPIAuthWorksRoutes(router *gin.RouterGroup) {
|
||||||
worksRoutes := router.Group("/works/:wid")
|
worksRoutes := router.Group("/works/:wid")
|
||||||
worksRoutes.Use(workHandler)
|
worksRoutes.Use(workHandler)
|
||||||
|
worksRoutes.Use(workUserAccessHandler)
|
||||||
|
|
||||||
worksRoutes.GET("", func(c *gin.Context) {
|
worksRoutes.GET("", func(c *gin.Context) {
|
||||||
u := c.MustGet("LoggedUser").(*User)
|
u := c.MustGet("LoggedUser").(*User)
|
||||||
@ -209,7 +210,9 @@ func declareAPIAuthWorksRoutes(router *gin.RouterGroup) {
|
|||||||
u := c.MustGet("LoggedUser").(*User)
|
u := c.MustGet("LoggedUser").(*User)
|
||||||
w := c.MustGet("work").(*Work)
|
w := c.MustGet("work").(*Work)
|
||||||
|
|
||||||
if g, err := u.GetMyWorkGrade(w); err != nil && errors.Is(err, sql.ErrNoRows) {
|
if !u.IsAdmin && !w.Corrected {
|
||||||
|
c.AbortWithStatusJSON(http.StatusForbidden, gin.H{"errmsg": "Permission denied"})
|
||||||
|
} else if g, err := u.GetMyWorkGrade(w); err != nil && errors.Is(err, sql.ErrNoRows) {
|
||||||
c.AbortWithStatusJSON(http.StatusNotFound, gin.H{"errmsg": "Aucune note n'a été attribuée pour ce travail. Avez-vous rendu ce travail ?"})
|
c.AbortWithStatusJSON(http.StatusNotFound, gin.H{"errmsg": "Aucune note n'a été attribuée pour ce travail. Avez-vous rendu ce travail ?"})
|
||||||
} else if err != nil {
|
} else if err != nil {
|
||||||
log.Printf("Unable to GetMyWorkGrade(uid=%d;wid=%d): %s", u.Id, w.Id, err.Error())
|
log.Printf("Unable to GetMyWorkGrade(uid=%d;wid=%d): %s", u.Id, w.Id, err.Error())
|
||||||
@ -236,6 +239,20 @@ func workHandler(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func workUserAccessHandler(c *gin.Context) {
|
||||||
|
u := c.MustGet("LoggedUser").(*User)
|
||||||
|
w := c.MustGet("work").(*Work)
|
||||||
|
|
||||||
|
if u.IsAdmin {
|
||||||
|
c.Next()
|
||||||
|
} else if w.Shown && (w.Group == "" || strings.Contains(u.Groups, ","+w.Group+",")) {
|
||||||
|
c.Next()
|
||||||
|
} else {
|
||||||
|
c.AbortWithStatusJSON(http.StatusNotFound, gin.H{"errmsg": "Work not found."})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
type OneWork struct {
|
type OneWork struct {
|
||||||
Kind string `json:"kind"`
|
Kind string `json:"kind"`
|
||||||
Id int64 `json:"id"`
|
Id int64 `json:"id"`
|
||||||
|
Reference in New Issue
Block a user