Compare commits

..

59 commits

Author SHA1 Message Date
8d87105609 WIP
All checks were successful
continuous-integration/drone/push Build is passing
2023-03-03 12:39:39 +01:00
5140eafc51 ui: Also color score on works page
All checks were successful
continuous-integration/drone/push Build is passing
2023-03-03 12:38:13 +01:00
675c462a55 Don't force current promo when loggin via kerberos 2023-03-03 12:35:35 +01:00
f417b6fc57 chore(deps): update module github.com/aws/aws-sdk-go to v1.44.213
All checks were successful
continuous-integration/drone/push Build is passing
2023-03-02 20:07:14 +00:00
4b74ddf109 chore(deps): update module github.com/jcmturner/gokrb5/v8 to v8.4.4
All checks were successful
continuous-integration/drone/push Build is passing
2023-03-02 04:08:48 +00:00
39b20c357d chore(deps): update module github.com/gin-gonic/gin to v1.9.0
All checks were successful
continuous-integration/drone/push Build is passing
2023-03-02 03:08:26 +00:00
04e7dcbb7e chore(deps): update module github.com/aws/aws-sdk-go to v1.44.212
All checks were successful
continuous-integration/drone/push Build is passing
2023-03-01 22:07:06 +00:00
e4ca8d2275 chore(deps): update module github.com/aws/aws-sdk-go to v1.44.211
All checks were successful
continuous-integration/drone/push Build is passing
2023-02-28 22:07:07 +00:00
f2c75b2ce3 chore(deps): update module github.com/aws/aws-sdk-go to v1.44.210
All checks were successful
continuous-integration/drone/push Build is passing
2023-02-27 20:07:08 +00:00
2f18107a05 chore(deps): lock file maintenance
All checks were successful
continuous-integration/drone/push Build is passing
2023-02-27 00:07:21 +00:00
85ffde35f8 chore(deps): update module github.com/aws/aws-sdk-go to v1.44.209
All checks were successful
continuous-integration/drone/push Build is passing
2023-02-24 22:07:20 +00:00
3dbddb629a chore(deps): update module github.com/aws/aws-sdk-go to v1.44.208
All checks were successful
continuous-integration/drone/push Build is passing
2023-02-23 20:07:03 +00:00
7a2e439db5 chore(deps): update module github.com/aws/aws-sdk-go to v1.44.207
All checks were successful
continuous-integration/drone/push Build is passing
2023-02-23 00:07:05 +00:00
7807cc1e9e chore(deps): update module github.com/aws/aws-sdk-go to v1.44.206
All checks were successful
continuous-integration/drone/push Build is passing
2023-02-21 21:07:30 +00:00
7b17c39755 chore(deps): update module github.com/aws/aws-sdk-go to v1.44.205
All checks were successful
continuous-integration/drone/push Build is passing
2023-02-20 20:07:00 +00:00
1237ab55a9 chore(deps): lock file maintenance
All checks were successful
continuous-integration/drone/push Build is passing
2023-02-20 01:07:04 +00:00
1733869884 chore(deps): update github.com/protonmail/go-crypto digest to 7d5c6f0
All checks were successful
continuous-integration/drone/push Build is passing
2023-02-19 11:09:18 +00:00
05f518beb2 chore(deps): update module github.com/aws/aws-sdk-go to v1.44.204
All checks were successful
continuous-integration/drone/push Build is passing
2023-02-17 20:08:00 +00:00
c19b87672a chore(deps): update module github.com/aws/aws-sdk-go to v1.44.201
All checks were successful
continuous-integration/drone/push Build is passing
2023-02-14 21:06:37 +00:00
a4d7092071 chore(deps): update module github.com/aws/aws-sdk-go to v1.44.200
All checks were successful
continuous-integration/drone/push Build is passing
2023-02-13 20:06:27 +00:00
77dd3e97be chore(deps): lock file maintenance
All checks were successful
continuous-integration/drone/push Build is passing
2023-02-13 00:08:21 +00:00
5d7c238ae2 Remove need help menu item
All checks were successful
continuous-integration/drone/push Build is passing
2023-02-13 00:32:57 +01:00
38744c96bc Redirect to the course of the year when promo is different
All checks were successful
continuous-integration/drone/push Build is passing
2023-02-12 21:22:56 +01:00
f86b87bc72 renovate: Enable lock-file maintenance
All checks were successful
continuous-integration/drone/push Build is passing
2023-02-11 21:38:08 +01:00
d7d11f813a chore(deps): update module github.com/aws/aws-sdk-go to v1.44.199
All checks were successful
continuous-integration/drone/push Build is passing
2023-02-10 20:09:02 +00:00
8609e5a3c1 chore(deps): update module github.com/aws/aws-sdk-go to v1.44.198
All checks were successful
continuous-integration/drone/push Build is passing
2023-02-09 20:09:21 +00:00
972a867851 chore(deps): update dependency @sveltejs/adapter-static to v2
All checks were successful
continuous-integration/drone/push Build is passing
2023-02-09 11:02:51 +00:00
da82cfb898 chore(deps): update module golang.org/x/oauth2 to v0.5.0
All checks were successful
continuous-integration/drone/push Build is passing
2023-02-08 23:08:52 +00:00
19f497cc6f chore(deps): update module github.com/aws/aws-sdk-go to v1.44.197
All checks were successful
continuous-integration/drone/push Build is passing
2023-02-08 20:06:32 +00:00
9842889319 chore(deps): update module github.com/aws/aws-sdk-go to v1.44.196
All checks were successful
continuous-integration/drone/push Build is passing
2023-02-07 20:07:44 +00:00
d9202100e7 chore(deps): update module github.com/aws/aws-sdk-go to v1.44.195
All checks were successful
continuous-integration/drone/push Build is passing
2023-02-06 20:06:43 +00:00
710ea782c8 chore(deps): update github.com/protonmail/go-crypto digest to d1d05f4
All checks were successful
continuous-integration/drone/push Build is passing
2023-02-03 21:08:14 +00:00
aa7eab794d chore(deps): update module github.com/aws/aws-sdk-go to v1.44.194
Some checks are pending
continuous-integration/drone/push Build is running
2023-02-03 20:07:35 +00:00
6115ece710 chore(deps): update module github.com/aws/aws-sdk-go to v1.44.193
All checks were successful
continuous-integration/drone/push Build is passing
2023-02-02 21:07:06 +00:00
0177b19794 chore(deps): update module github.com/aws/aws-sdk-go to v1.44.191
All checks were successful
continuous-integration/drone/push Build is passing
2023-01-31 21:07:54 +00:00
5ff1776b93 chore(deps): update module github.com/aws/aws-sdk-go to v1.44.190
All checks were successful
continuous-integration/drone/push Build is passing
2023-01-30 20:08:41 +00:00
b51f73fcd1 chore(deps): update module github.com/aws/aws-sdk-go to v1.44.189
All checks were successful
continuous-integration/drone/push Build is passing
2023-01-27 20:07:22 +00:00
5f2b3419b2 chore(deps): update module github.com/aws/aws-sdk-go to v1.44.188
All checks were successful
continuous-integration/drone/push Build is passing
2023-01-26 20:07:21 +00:00
8fb36edd70 chore(deps): update module github.com/aws/aws-sdk-go to v1.44.187
All checks were successful
continuous-integration/drone/push Build is passing
2023-01-25 20:08:00 +00:00
742693b9e5 chore(deps): update github.com/protonmail/go-crypto digest to 0acdc8a
All checks were successful
continuous-integration/drone/push Build is passing
2023-01-24 21:08:55 +00:00
394af9e07b chore(deps): update module github.com/aws/aws-sdk-go to v1.44.186
All checks were successful
continuous-integration/drone/push Build is passing
2023-01-24 20:07:24 +00:00
f0582fe02e chore(deps): update module github.com/aws/aws-sdk-go to v1.44.185
All checks were successful
continuous-integration/drone/push Build is passing
2023-01-23 20:08:24 +00:00
e991156af5 chore(deps): update module github.com/aws/aws-sdk-go to v1.44.184
All checks were successful
continuous-integration/drone/push Build is passing
2023-01-20 20:07:54 +00:00
a3883aa3ed chore(deps): update module github.com/aws/aws-sdk-go to v1.44.183
All checks were successful
continuous-integration/drone/push Build is passing
2023-01-19 22:06:56 +00:00
4685ba0876 chore(deps): update github.com/protonmail/go-crypto digest to a47887b
All checks were successful
continuous-integration/drone/push Build is passing
2023-01-19 10:06:43 +00:00
76e01298f5 chore(deps): update module github.com/aws/aws-sdk-go to v1.44.182
All checks were successful
continuous-integration/drone/push Build is passing
2023-01-19 09:34:56 +00:00
80a578b6c6 Fix build on arm
Some checks are pending
continuous-integration/drone/push Build is running
2023-01-19 10:33:35 +01:00
81870551b2 chore(deps): update module github.com/aws/aws-sdk-go to v1.44.180
All checks were successful
continuous-integration/drone/push Build is passing
2023-01-13 20:06:21 +00:00
23b7a5a407 chore(deps): update github.com/protonmail/go-crypto digest to 068501e
All checks were successful
continuous-integration/drone/push Build is passing
2023-01-13 19:07:24 +00:00
b233a3e078 chore(deps): update module github.com/aws/aws-sdk-go to v1.44.179
All checks were successful
continuous-integration/drone/push Build is passing
2023-01-12 20:06:13 +00:00
854b70fefa chore(deps): update github.com/protonmail/go-crypto digest to 7efeeb0
All checks were successful
continuous-integration/drone/push Build is passing
2023-01-11 21:08:01 +00:00
f664e66ef5 chore(deps): update module github.com/aws/aws-sdk-go to v1.44.178
All checks were successful
continuous-integration/drone/push Build is passing
2023-01-11 20:06:35 +00:00
c154491bee chore(deps): update module github.com/aws/aws-sdk-go to v1.44.177
All checks were successful
continuous-integration/drone/push Build is passing
2023-01-10 20:08:05 +00:00
a3aa9b6d25 chore(deps): update module github.com/aws/aws-sdk-go to v1.44.176
All checks were successful
continuous-integration/drone/push Build is passing
2023-01-09 20:07:14 +00:00
584b81d6af chore(deps): update github.com/protonmail/go-crypto digest to cdd2c18
All checks were successful
continuous-integration/drone/push Build is passing
2023-01-09 17:56:09 +00:00
ffa51ec796 chore(deps): update module github.com/coreos/go-oidc/v3 to v3.5.0
Some checks are pending
continuous-integration/drone/push Build is running
2023-01-09 17:56:00 +00:00
15a8542af4 chore(deps): update module golang.org/x/oauth2 to v0.4.0
All checks were successful
continuous-integration/drone/push Build is passing
2023-01-08 16:08:28 +00:00
26cc3d67fd chore(deps): update module github.com/aws/aws-sdk-go to v1.44.175
All checks were successful
continuous-integration/drone/push Build is passing
2023-01-08 15:07:25 +00:00
0cc0ae3c7d New route to run gradation tests
All checks were successful
continuous-integration/drone/push Build is passing
2023-01-08 15:05:46 +01:00
46 changed files with 2942 additions and 3665 deletions

View file

@ -1,6 +1,56 @@
---
kind: pipeline
type: docker
name: build-arm
platform:
os: linux
arch: arm
steps:
- name: build front
image: node:19-alpine
commands:
- mkdir deploy
- cd ui
- npm install --network-timeout=100000
- npm run build
- tar chjf ../deploy/static.tar.bz2 build
- name: vet
image: golang:1-alpine
commands:
- apk --no-cache add build-base
- go vet -v -buildvcs=false
- name: backend armv7
image: golang:1-alpine
commands:
- apk --no-cache add build-base
- go get -v
- go build -v -buildvcs=false -ldflags="-s -w"
environment:
GOARM: 7
- name: publish
image: plugins/docker:linux-arm
settings:
repo: nemunaire/atsebay.t
auto_tag: true
auto_tag_suffix: ${DRONE_STAGE_OS}-${DRONE_STAGE_ARCH}
username:
from_secret: docker_username
password:
from_secret: docker_password
trigger:
event:
- cron
- push
- tag
---
kind: pipeline
type: docker
name: build-arm64
platform:
@ -9,7 +59,7 @@ platform:
steps:
- name: build front
image: node:21-alpine
image: node:19-alpine
commands:
- mkdir deploy
- cd ui
@ -69,4 +119,5 @@ trigger:
- tag
depends_on:
- build-arm
- build-arm64

View file

@ -1,4 +1,4 @@
FROM node:21-alpine as nodebuild
FROM node:19-alpine as nodebuild
WORKDIR /ui
@ -22,7 +22,7 @@ RUN go get -d -v && \
go build -v -buildvcs=false -ldflags="-s -w" -o atsebay.t
FROM alpine:3.19
FROM alpine:3.17
EXPOSE 8081

15
auth.go
View file

@ -13,7 +13,6 @@ import (
var LocalAuthFunc = checkAuthKrb5
var allowLocalAuth bool
var localAuthUsers arrayFlags
var mainBanner string
type loginForm struct {
Login string `json:"username"`
@ -48,18 +47,16 @@ func declareAPIAdminAuthRoutes(router *gin.RouterGroup) {
session.Update()
c.JSON(http.StatusOK, authToken{
User: newuser,
CurrentPromo: currentPromo,
MessageBanner: mainBanner,
User: newuser,
CurrentPromo: currentPromo,
})
})
}
type authToken struct {
*User
CurrentPromo uint `json:"current_promo"`
Groups []string `json:"groups"`
MessageBanner string `json:"banner,omitempty"`
CurrentPromo uint `json:"current_promo"`
Groups []string `json:"groups"`
}
func validateAuthToken(c *gin.Context) {
@ -67,7 +64,7 @@ func validateAuthToken(c *gin.Context) {
c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"errmsg": "Not connected"})
return
} else {
t := authToken{User: u.(*User), CurrentPromo: currentPromo, MessageBanner: mainBanner}
t := authToken{User: u.(*User), CurrentPromo: currentPromo}
t.Groups = strings.Split(strings.TrimFunc(t.User.Groups, func(r rune) bool { return !unicode.IsLetter(r) }), ",")
@ -160,6 +157,6 @@ func dummyAuth(c *gin.Context) {
c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"errmsg": err.Error()})
return
} else {
c.JSON(http.StatusOK, authToken{User: usr, CurrentPromo: currentPromo, MessageBanner: mainBanner})
c.JSON(http.StatusOK, authToken{User: usr, CurrentPromo: currentPromo})
}
}

2
db.go
View file

@ -273,7 +273,7 @@ CREATE TABLE IF NOT EXISTS survey_shared(
return err
}
if _, err := db.Exec(`
CREATE VIEW IF NOT EXISTS student_scores AS SELECT "survey" AS kind, T.id_user, T.id_survey AS id, Q.id_question, MAX(R.score) AS score FROM (SELECT DISTINCT R.id_user, S.id_survey FROM survey_responses R INNER JOIN survey_quests Q ON R.id_question = Q.id_question INNER JOIN surveys S ON Q.id_survey = S.id_survey) T LEFT OUTER JOIN survey_quests Q ON T.id_survey = Q.id_survey LEFT OUTER JOIN survey_responses R ON R.id_user = T.id_user AND Q.id_question = R.id_question GROUP BY id_user, kind, id, id_question UNION SELECT "work" AS kind, G.id_user, G.id_work AS id, 0 AS id_question, G.grade AS score FROM works W RIGHT OUTER JOIN user_work_grades G ON G.id_work = W.id_work GROUP BY id_user, kind, id, id_question;
CREATE VIEW IF NOT EXISTS student_scores AS SELECT T.id_user, T.id_survey, Q.id_question, MAX(R.score) AS score FROM (SELECT DISTINCT R.id_user, S.id_survey FROM survey_responses R INNER JOIN survey_quests Q ON R.id_question = Q.id_question INNER JOIN surveys S ON Q.id_survey = S.id_survey) T LEFT OUTER JOIN survey_quests Q ON T.id_survey = Q.id_survey LEFT OUTER JOIN survey_responses R ON R.id_user = T.id_user AND Q.id_question = R.id_question GROUP BY id_user, id_survey, id_question;
`); err != nil {
return err
}

View file

@ -2,10 +2,8 @@ package main
import (
"context"
"fmt"
"log"
"net/http"
"strings"
"sync"
"time"
@ -282,62 +280,6 @@ func getCorrectionString(qid int64) (ret map[string]int) {
return
}
func getResponsesStats(qid int64) map[string]interface{} {
q, err := getQuestion(int(qid))
if err != nil {
return nil
}
responses, err := q.GetResponses()
if err != nil {
log.Println("Unable to retrieve responses:", err)
return nil
}
labels := []string{}
values := []uint{}
if q.Kind == "mcq" || q.Kind == "ucq" {
proposals, err := q.GetProposals()
if err != nil {
return nil
}
proposal_idx := map[string]int{}
for _, p := range proposals {
proposal_idx[fmt.Sprintf("%d", p.Id)] = len(labels)
labels = append(labels, p.Label)
values = append(values, 0)
}
for _, r := range responses {
for _, v := range strings.Split(r.Answer, ",") {
values[proposal_idx[v]]++
}
}
} else {
stats := map[string]uint{}
for _, r := range responses {
stats[r.Answer]++
}
for k, v := range stats {
labels = append(labels, k)
values = append(values, v)
}
}
return map[string]interface{}{
"labels": labels,
"datasets": []map[string][]uint{
map[string][]uint{
"values": values,
},
},
}
}
func SurveyWSAdmin(c *gin.Context) {
u := c.MustGet("LoggedUser").(*User)
survey := c.MustGet("survey").(*Survey)
@ -367,7 +309,6 @@ func SurveyWSAdmin(c *gin.Context) {
go func(c chan WSMessage, sid int) {
var v WSMessage
var err error
var surveyTimer *time.Timer
for {
// Reset variable state
v.Corrected = false
@ -385,35 +326,19 @@ func SurveyWSAdmin(c *gin.Context) {
if survey, err := getSurvey(sid); err != nil {
log.Println("Unable to retrieve survey:", err)
} else {
// Skip any existing scheduled timer
if surveyTimer != nil {
if !surveyTimer.Stop() {
<-surveyTimer.C
}
surveyTimer = nil
}
survey.Direct = v.QuestionId
if v.Timer > 0 {
survey.Corrected = false
survey.Update()
// Save corrected state for the callback
corrected := v.Corrected
with_stats := v.Stats != nil
go func(corrected bool) {
time.Sleep(time.Duration(OffsetQuestionTimer+v.Timer) * time.Millisecond)
surveyTimer = time.AfterFunc(time.Duration(OffsetQuestionTimer+v.Timer)*time.Millisecond, func() {
surveyTimer = nil
if corrected {
survey.Corrected = v.Corrected
survey.Update()
var stats map[string]interface{}
if with_stats {
stats = getResponsesStats(*v.QuestionId)
}
survey.WSWriteAll(WSMessage{Action: "new_question", QuestionId: v.QuestionId, Corrected: true, Stats: stats, Corrections: getCorrectionString(*v.QuestionId)})
survey.WSWriteAll(WSMessage{Action: "new_question", QuestionId: v.QuestionId, Corrected: true, Corrections: getCorrectionString(*v.QuestionId)})
} else {
var z int64 = 0
survey.Direct = &z
@ -422,20 +347,12 @@ func SurveyWSAdmin(c *gin.Context) {
survey.WSWriteAll(WSMessage{Action: "pause"})
WSAdminWriteAll(WSMessage{Action: "pause", SurveyId: &survey.Id})
}
})
}(v.Corrected)
v.Corrected = false
v.Stats = nil
} else {
survey.Corrected = v.Corrected
if v.Corrected {
v.Corrections = getCorrectionString(*v.QuestionId)
if v.Stats != nil {
v.Stats = getResponsesStats(*v.QuestionId)
} else {
v.Stats = nil
}
} else {
v.Stats = nil
}
}
_, err = survey.Update()

View file

@ -170,13 +170,11 @@ type GitLabUser struct {
Username string
Name string
State string
Email string
}
type GitLabUserKey struct {
ID int
Key string
UsageType string `json:"usage_type"`
ID int
Key string
}
type GitLabRepository struct {
@ -271,7 +269,7 @@ func GitLab_getUsersRepositories(c context.Context, u *User) ([]*GitLabRepositor
return repositories, err
}
func GitLab_getUser(c context.Context, u *User) (*GitLabUser, error) {
func GitLab_getUserId(c context.Context, u *User) (int, error) {
client := gitlaboauth2Config.Client(c, gitlabToken())
val := url.Values{}
@ -279,35 +277,26 @@ func GitLab_getUser(c context.Context, u *User) (*GitLabUser, error) {
req, err := http.NewRequest("GET", gitlabBaseURL+fmt.Sprintf("/api/v4/users?%s", val.Encode()), nil)
if err != nil {
return nil, err
return 0, err
}
resp, err := client.Do(req)
if err != nil {
return nil, err
return 0, err
}
if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("Bad status code from the API")
return 0, fmt.Errorf("Bad status code from the API")
}
var users []*GitLabUser
err = json.NewDecoder(resp.Body).Decode(&users)
if len(users) == 0 {
return nil, fmt.Errorf("Login not found in GitLab")
return 0, fmt.Errorf("Login not found in GitLab")
}
return users[0], nil
}
func GitLab_getUserId(c context.Context, u *User) (int, error) {
user, err := GitLab_getUser(c, u)
if err != nil {
return 0, err
}
return user.ID, nil
return users[0].ID, nil
}
func GitLab_getUserPGPKeys(c context.Context, u *User) ([]byte, error) {
@ -345,33 +334,3 @@ func GitLab_getUserPGPKeys(c context.Context, u *User) ([]byte, error) {
return b.Bytes(), nil
}
func GitLab_getUserSSHKeys(c context.Context, u *User) ([]*GitLabUserKey, error) {
userid, err := GitLab_getUserId(c, u)
if err != nil {
return nil, err
}
client := gitlaboauth2Config.Client(c, gitlabToken())
req, err := http.NewRequest("GET", gitlabBaseURL+fmt.Sprintf("/api/v4/users/%d/keys", userid), nil)
if err != nil {
return nil, err
}
resp, err := client.Do(req)
if err != nil {
return nil, err
}
if resp.StatusCode != http.StatusOK {
rep, _ := ioutil.ReadAll(resp.Body)
log.Printf("%d %s", resp.StatusCode, rep)
return nil, fmt.Errorf("Bad status code from the API")
}
var keys []*GitLabUserKey
err = json.NewDecoder(resp.Body).Decode(&keys)
return keys, err
}

59
go.mod
View file

@ -1,36 +1,31 @@
module git.nemunai.re/atsebay.t
go 1.21
toolchain go1.22.1
go 1.18
require (
github.com/ProtonMail/go-crypto v1.0.0
github.com/aws/aws-sdk-go v1.51.9
github.com/coreos/go-oidc/v3 v3.10.0
github.com/ProtonMail/go-crypto v0.0.0-20230217124315-7d5c6f04bbb8
github.com/aws/aws-sdk-go v1.44.213
github.com/coreos/go-oidc/v3 v3.5.0
github.com/drone/drone-go v1.7.1
github.com/gin-gonic/gin v1.9.1
github.com/go-sql-driver/mysql v1.8.1
github.com/gin-gonic/gin v1.9.0
github.com/go-sql-driver/mysql v1.7.0
github.com/jcmturner/gokrb5/v8 v8.4.4
github.com/russross/blackfriday/v2 v2.1.0
golang.org/x/oauth2 v0.18.0
nhooyr.io/websocket v1.8.10
golang.org/x/oauth2 v0.5.0
nhooyr.io/websocket v1.8.7
)
require (
filippo.io/edwards25519 v1.1.0 // indirect
github.com/bytedance/sonic v1.9.1 // indirect
github.com/bytedance/sonic v1.8.0 // indirect
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect
github.com/cloudflare/circl v1.3.3 // indirect
github.com/gabriel-vasile/mimetype v1.4.2 // indirect
github.com/cloudflare/circl v1.1.0 // indirect
github.com/gin-contrib/sse v0.1.0 // indirect
github.com/go-jose/go-jose/v3 v3.0.1 // indirect
github.com/go-jose/go-jose/v4 v4.0.1 // indirect
github.com/go-jose/go-jose/v3 v3.0.0 // indirect
github.com/go-playground/locales v0.14.1 // indirect
github.com/go-playground/universal-translator v0.18.1 // indirect
github.com/go-playground/validator/v10 v10.14.0 // indirect
github.com/goccy/go-json v0.10.2 // indirect
github.com/golang/protobuf v1.5.3 // indirect
github.com/go-playground/validator/v10 v10.11.2 // indirect
github.com/goccy/go-json v0.10.0 // indirect
github.com/golang/protobuf v1.5.2 // indirect
github.com/hashicorp/go-uuid v1.0.3 // indirect
github.com/jcmturner/aescts/v2 v2.0.0 // indirect
github.com/jcmturner/dnsutils/v2 v2.0.0 // indirect
@ -39,21 +34,21 @@ require (
github.com/jmespath/go-jmespath v0.4.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/klauspost/compress v1.10.3 // indirect
github.com/klauspost/cpuid/v2 v2.2.4 // indirect
github.com/leodido/go-urn v1.2.4 // indirect
github.com/mattn/go-isatty v0.0.19 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/klauspost/cpuid/v2 v2.0.9 // indirect
github.com/leodido/go-urn v1.2.1 // indirect
github.com/mattn/go-isatty v0.0.17 // indirect
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/pelletier/go-toml/v2 v2.0.8 // indirect
github.com/pelletier/go-toml/v2 v2.0.6 // indirect
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
github.com/ugorji/go/codec v1.2.11 // indirect
golang.org/x/arch v0.3.0 // indirect
golang.org/x/crypto v0.21.0 // indirect
golang.org/x/net v0.22.0 // indirect
golang.org/x/sys v0.18.0 // indirect
golang.org/x/text v0.14.0 // indirect
google.golang.org/appengine v1.6.8 // indirect
google.golang.org/protobuf v1.31.0 // indirect
github.com/ugorji/go/codec v1.2.9 // indirect
golang.org/x/arch v0.0.0-20210923205945-b76863e36670 // indirect
golang.org/x/crypto v0.6.0 // indirect
golang.org/x/net v0.7.0 // indirect
golang.org/x/sys v0.5.0 // indirect
golang.org/x/text v0.7.0 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/protobuf v1.28.1 // indirect
gopkg.in/square/go-jose.v2 v2.6.0 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect

639
go.sum
View file

@ -55,8 +55,6 @@ cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RX
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
cloud.google.com/go/storage v1.22.1/go.mod h1:S8N1cAStu7BOeFfE8KAQzmyyLkK8p/vmRq6kuBTW58Y=
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
github.com/99designs/httpsignatures-go v0.0.0-20170731043157-88528bf4ca7e/go.mod h1:Xa6lInWHNQnuWoF0YPSsx+INFA9qk7/7pTjwb3PInkY=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
@ -81,34 +79,6 @@ github.com/ProtonMail/go-crypto v0.0.0-20230201104953-d1d05f4e2bfb h1:Vx1Bw/nGUL
github.com/ProtonMail/go-crypto v0.0.0-20230201104953-d1d05f4e2bfb/go.mod h1:I0gYDMZ6Z5GRU7l58bNFSkPTFN6Yl12dsUlAZ8xy98g=
github.com/ProtonMail/go-crypto v0.0.0-20230217124315-7d5c6f04bbb8 h1:wPbRQzjjwFc0ih8puEVAOFGELsn1zoIIYdxvML7mDxA=
github.com/ProtonMail/go-crypto v0.0.0-20230217124315-7d5c6f04bbb8/go.mod h1:I0gYDMZ6Z5GRU7l58bNFSkPTFN6Yl12dsUlAZ8xy98g=
github.com/ProtonMail/go-crypto v0.0.0-20230316153859-cb82d937a5d9 h1:rndY7RCFW5vUcdVvhfIRsQhYm1MdvwI+dTFbyrWiGHY=
github.com/ProtonMail/go-crypto v0.0.0-20230316153859-cb82d937a5d9/go.mod h1:I0gYDMZ6Z5GRU7l58bNFSkPTFN6Yl12dsUlAZ8xy98g=
github.com/ProtonMail/go-crypto v0.0.0-20230320150741-8451524ecd7e h1:zEBUcFZPNx8/ZOg8VFISN2ty4YyLSiVBnzG9Edqh9Z4=
github.com/ProtonMail/go-crypto v0.0.0-20230320150741-8451524ecd7e/go.mod h1:I0gYDMZ6Z5GRU7l58bNFSkPTFN6Yl12dsUlAZ8xy98g=
github.com/ProtonMail/go-crypto v0.0.0-20230331115716-d34776aa93ec h1:eQusauqzE1cAFR5hGnwkuSmFxKoy3+j9/cVaDeYfjjs=
github.com/ProtonMail/go-crypto v0.0.0-20230331115716-d34776aa93ec/go.mod h1:8TI4H3IbrackdNgv+92dI+rhpCaLqM0IfpgCgenFvRE=
github.com/ProtonMail/go-crypto v0.0.0-20230411080316-8b3893ee7fca h1:3N4LNZ++dKh8SXcBRsT6P6mxhDm5swmkgmahlIS9yb0=
github.com/ProtonMail/go-crypto v0.0.0-20230411080316-8b3893ee7fca/go.mod h1:8TI4H3IbrackdNgv+92dI+rhpCaLqM0IfpgCgenFvRE=
github.com/ProtonMail/go-crypto v0.0.0-20230417170513-8ee5748c52b5 h1:QXMwHM/lB4ZQhdEF7JUTNgYOJR/gWoFbgQ/2Aj1h3Dk=
github.com/ProtonMail/go-crypto v0.0.0-20230417170513-8ee5748c52b5/go.mod h1:8TI4H3IbrackdNgv+92dI+rhpCaLqM0IfpgCgenFvRE=
github.com/ProtonMail/go-crypto v0.0.0-20230426101702-58e86b294756 h1:L6S7kR7SlhQKplIBpkra3s6yhcZV51lhRnXmYc4HohI=
github.com/ProtonMail/go-crypto v0.0.0-20230426101702-58e86b294756/go.mod h1:8TI4H3IbrackdNgv+92dI+rhpCaLqM0IfpgCgenFvRE=
github.com/ProtonMail/go-crypto v0.0.0-20230518184743-7afd39499903 h1:ZK3C5DtzV2nVAQTx5S5jQvMeDqWtD1By5mOoyY/xJek=
github.com/ProtonMail/go-crypto v0.0.0-20230518184743-7afd39499903/go.mod h1:8TI4H3IbrackdNgv+92dI+rhpCaLqM0IfpgCgenFvRE=
github.com/ProtonMail/go-crypto v0.0.0-20230528122434-6f98819771a1 h1:JMDGhoQvXNTqH6Y3MC0IUw6tcZvaUdujNqzK2HYWZc8=
github.com/ProtonMail/go-crypto v0.0.0-20230528122434-6f98819771a1/go.mod h1:EjAoLdwvbIOoOQr3ihjnSoLZRtE8azugULFRteWMNc0=
github.com/ProtonMail/go-crypto v0.0.0-20230626094100-7e9e0395ebec h1:vV3RryLxt42+ZIVOFbYJCH1jsZNTNmj2NYru5zfx+4E=
github.com/ProtonMail/go-crypto v0.0.0-20230626094100-7e9e0395ebec/go.mod h1:EjAoLdwvbIOoOQr3ihjnSoLZRtE8azugULFRteWMNc0=
github.com/ProtonMail/go-crypto v0.0.0-20230710112148-e01326fd72eb h1:RU+Ff2vE68zFQSoBqlb/LChFztEWWJ9EZ8LU4gA3ubU=
github.com/ProtonMail/go-crypto v0.0.0-20230710112148-e01326fd72eb/go.mod h1:EjAoLdwvbIOoOQr3ihjnSoLZRtE8azugULFRteWMNc0=
github.com/ProtonMail/go-crypto v0.0.0-20230717121422-5aa5874ade95 h1:KLq8BE0KwCL+mmXnjLWEAOYO+2l2AE4YMmqG1ZpZHBs=
github.com/ProtonMail/go-crypto v0.0.0-20230717121422-5aa5874ade95/go.mod h1:EjAoLdwvbIOoOQr3ihjnSoLZRtE8azugULFRteWMNc0=
github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371 h1:kkhsdkhsCvIsutKu5zLMgWtgh9YxGCNAw8Ad8hjwfYg=
github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371/go.mod h1:EjAoLdwvbIOoOQr3ihjnSoLZRtE8azugULFRteWMNc0=
github.com/ProtonMail/go-crypto v0.0.0-20230923063757-afb1ddc0824c h1:kMFnB0vCcX7IL/m9Y5LO+KQYv+t1CQOiFe6+SV2J7bE=
github.com/ProtonMail/go-crypto v0.0.0-20230923063757-afb1ddc0824c/go.mod h1:EjAoLdwvbIOoOQr3ihjnSoLZRtE8azugULFRteWMNc0=
github.com/ProtonMail/go-crypto v1.0.0 h1:LRuvITjQWX+WIfr930YHG2HNfjR1uOfyf5vE0kC2U78=
github.com/ProtonMail/go-crypto v1.0.0/go.mod h1:EjAoLdwvbIOoOQr3ihjnSoLZRtE8azugULFRteWMNc0=
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
github.com/aws/aws-sdk-go v1.44.96 h1:S9paaqnJ0AJ95t5AB+iK8RM6YNZN0W0Lek1gOVJsEr8=
github.com/aws/aws-sdk-go v1.44.96/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo=
@ -310,435 +280,10 @@ github.com/aws/aws-sdk-go v1.44.212 h1:IRstlErdeKeQ8qBsCwWt4MG2RihUOcUJVqYwbvqpE
github.com/aws/aws-sdk-go v1.44.212/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/aws/aws-sdk-go v1.44.213 h1:WahquyWs7cQdz0vpDVWyWETEemgSoORx0PbWL9oz2WA=
github.com/aws/aws-sdk-go v1.44.213/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/aws/aws-sdk-go v1.44.214 h1:YzDuC+9UtrAOUkItlK7l3BvKI9o6qAog9X8i289HORc=
github.com/aws/aws-sdk-go v1.44.214/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/aws/aws-sdk-go v1.44.215 h1:K3KERfO6MaV349idub2w1u1H0R0KSkED0LshPnaAn3Q=
github.com/aws/aws-sdk-go v1.44.215/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/aws/aws-sdk-go v1.44.216 h1:nDL5hEGBlUNHXMWbpP4dIyP8IB5tvRgksWE7biVu8JY=
github.com/aws/aws-sdk-go v1.44.216/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/aws/aws-sdk-go v1.44.218 h1:p707+xOCazWhkSpZOeyhtTcg7Z+asxxvueGgYPSitn4=
github.com/aws/aws-sdk-go v1.44.218/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/aws/aws-sdk-go v1.44.219 h1:YOFxTUQZvdRzgwb6XqLFRwNHxoUdKBuunITC7IFhvbc=
github.com/aws/aws-sdk-go v1.44.219/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/aws/aws-sdk-go v1.44.220 h1:yAj99qAt0Htjle9Up3DglgHfOP77lmFPrElA4jKnrBo=
github.com/aws/aws-sdk-go v1.44.220/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/aws/aws-sdk-go v1.44.221 h1:yndn4uvLolKXPoXIwKHhO5XtwlTnJfXLBKXs84C5+hQ=
github.com/aws/aws-sdk-go v1.44.221/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/aws/aws-sdk-go v1.44.222 h1:hagcC+MrGo60DKEbX0g6/ge4pIj7vBbsIb+vrhA/54I=
github.com/aws/aws-sdk-go v1.44.222/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/aws/aws-sdk-go v1.44.223 h1:8FiGnB6W3WO5R0iCGuW2E0pgdunN37jtNcoHJ7tSa98=
github.com/aws/aws-sdk-go v1.44.223/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/aws/aws-sdk-go v1.44.224 h1:09CiaaF35nRmxrzWZ2uRq5v6Ghg/d2RiPjZnSgtt+RQ=
github.com/aws/aws-sdk-go v1.44.224/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/aws/aws-sdk-go v1.44.225 h1:JNJpUg+M1cm4jtKnyex//Mw1Rv8QN/kWT3dtr+oLdW4=
github.com/aws/aws-sdk-go v1.44.225/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/aws/aws-sdk-go v1.44.226 h1:lqTNeHJUq0U6dpMGJc9ZcmfTUkuAjklcwewj96RhMlc=
github.com/aws/aws-sdk-go v1.44.226/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/aws/aws-sdk-go v1.44.227 h1:HWNpINBu20yyfEXGHHSIsB955KUjWmZJETqnLIXizN4=
github.com/aws/aws-sdk-go v1.44.227/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/aws/aws-sdk-go v1.44.228 h1:CkkAlgNFf7qPZy/bAssF6lafR/ThMiiwKQEHVfPJixc=
github.com/aws/aws-sdk-go v1.44.228/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/aws/aws-sdk-go v1.44.234 h1:8YbQ5AhpgV/cC7jYX8qS34Am/vcn2ZoIFJ1qIgwOL+0=
github.com/aws/aws-sdk-go v1.44.234/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/aws/aws-sdk-go v1.44.235 h1:5MS1ZW1Pr27mmHFqqjuXYwGMlNTW/g6DqU5ekamPMeU=
github.com/aws/aws-sdk-go v1.44.235/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/aws/aws-sdk-go v1.44.236 h1:Ilbq/9B617BNjviTPjZrSbMxUkCb/1M7DqHO6sXOJTc=
github.com/aws/aws-sdk-go v1.44.236/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/aws/aws-sdk-go v1.44.237 h1:gsmVP8eTB6id4tmEsBPcjLlYi1sXtKA047bSn7kJZAI=
github.com/aws/aws-sdk-go v1.44.237/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/aws/aws-sdk-go v1.44.238 h1:qSWVXr/y/SsYyuvwVHYQpzcMKa2UzOjKgqPp7BTGfbo=
github.com/aws/aws-sdk-go v1.44.238/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/aws/aws-sdk-go v1.44.239 h1:AenB6byCYGSBb30q99CGYqFbqpLpWrTidzm7MzxtuPo=
github.com/aws/aws-sdk-go v1.44.239/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/aws/aws-sdk-go v1.44.244 h1:QzBWLD5HjZHdRZyTMTOWtD9Pobzf1n8/CeTJB4giXi0=
github.com/aws/aws-sdk-go v1.44.244/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/aws/aws-sdk-go v1.44.245 h1:KtY2s4q31/kn33AdV63R5t77mdxsI7rq3YT7Mgo805M=
github.com/aws/aws-sdk-go v1.44.245/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/aws/aws-sdk-go v1.44.246 h1:iLxPX6JU0bxAci9R6/bp8rX0kL871ByCTx0MZlQWv1U=
github.com/aws/aws-sdk-go v1.44.246/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/aws/aws-sdk-go v1.44.247 h1:oUJZr62HT8RIo9nRCwam8iXzXnSIwwndSVGH0/gym+E=
github.com/aws/aws-sdk-go v1.44.247/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/aws/aws-sdk-go v1.44.248 h1:GvkxpgsxqNc03LmhXiaxKpzbyxndnex7V+OThLx4g5M=
github.com/aws/aws-sdk-go v1.44.248/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/aws/aws-sdk-go v1.44.249 h1:UbUvh/oYHdAD3vZjNi316M0NIupJsrqAcJckVuhaCB8=
github.com/aws/aws-sdk-go v1.44.249/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/aws/aws-sdk-go v1.44.251 h1:unCIT7a/BkYvJ/43D0Ts/0aRbWDMQM0SUzBtdsKPwCg=
github.com/aws/aws-sdk-go v1.44.251/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/aws/aws-sdk-go v1.44.252 h1:a8PaCCQsxkeqCkcn7YN/O6C73gS/MOLuBDPjAsb/mv0=
github.com/aws/aws-sdk-go v1.44.252/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/aws/aws-sdk-go v1.44.253 h1:iqDd0okcH4ShfFexz2zzf4VmeDFf6NOMm07pHnEb8iY=
github.com/aws/aws-sdk-go v1.44.253/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/aws/aws-sdk-go v1.44.254 h1:8baW4yal2xGiM/Wm5/ZU10drS8sd+BVjMjPFjJx2ooc=
github.com/aws/aws-sdk-go v1.44.254/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/aws/aws-sdk-go v1.44.256 h1:O8VH+bJqgLDguqkH/xQBFz5o/YheeZqgcOYIgsTVWY4=
github.com/aws/aws-sdk-go v1.44.256/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/aws/aws-sdk-go v1.44.257 h1:HwelXYZZ8c34uFFhgVw3ybu2gB5fkk8KLj2idTvzZb8=
github.com/aws/aws-sdk-go v1.44.257/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/aws/aws-sdk-go v1.44.258 h1:JVk1lgpsTnb1kvUw3eGhPLcTpEBp6HeSf1fxcYDs2Ho=
github.com/aws/aws-sdk-go v1.44.258/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/aws/aws-sdk-go v1.44.259 h1:7yDn1dcv4DZFMKpu+2exIH5O6ipNj9qXrKfdMUaIJwY=
github.com/aws/aws-sdk-go v1.44.259/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/aws/aws-sdk-go v1.44.260 h1:78IJkDpDPXvLXvIkNAKDP/i3z8Vj+3sTAtQYw/v/2o8=
github.com/aws/aws-sdk-go v1.44.260/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/aws/aws-sdk-go v1.44.261 h1:PcTMX/QVk+P3yh2n34UzuXDF5FS2z5Lse2bt+r3IpU4=
github.com/aws/aws-sdk-go v1.44.261/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/aws/aws-sdk-go v1.44.262 h1:gyXpcJptWoNkK+DiAiaBltlreoWKQXjAIh6FRh60F+I=
github.com/aws/aws-sdk-go v1.44.262/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/aws/aws-sdk-go v1.44.263 h1:Dkt5fcdtL8QtK3cz0bOTQ84m9dGx+YDeTsDl+wY2yW4=
github.com/aws/aws-sdk-go v1.44.263/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/aws/aws-sdk-go v1.44.266 h1:MWd775dcYf7NrwgcHLtlsIbWoWkX8p4vomfNHr88zH0=
github.com/aws/aws-sdk-go v1.44.266/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/aws/aws-sdk-go v1.44.267 h1:Asrp6EMqqRxZvjK0NjzkWcrOk15RnWtupuUrUuZMabk=
github.com/aws/aws-sdk-go v1.44.267/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/aws/aws-sdk-go v1.44.268 h1:WoK20tlAvsvQzTcE6TajoprbXmTbcud6MjhErL4P/38=
github.com/aws/aws-sdk-go v1.44.268/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/aws/aws-sdk-go v1.44.269 h1:NUNq++KMjhWUVVUIx7HYLgBpX16bWfTY1EdQRraLALo=
github.com/aws/aws-sdk-go v1.44.269/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/aws/aws-sdk-go v1.44.271 h1:aa+Nu2JcnFmW1TLIz/67SS7KPq1I1Adl4RmExSMjGVo=
github.com/aws/aws-sdk-go v1.44.271/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/aws/aws-sdk-go v1.44.272 h1:cP7BaZCz1a4P80vOxi8OVma8ZcxZNDYyuyU5/bojU+Y=
github.com/aws/aws-sdk-go v1.44.272/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/aws/aws-sdk-go v1.44.273 h1:CX8O0gK+cGrgUyv7bgJ6QQP9mQg7u5mweHdNzULH47c=
github.com/aws/aws-sdk-go v1.44.273/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/aws/aws-sdk-go v1.44.274 h1:vfreSv19e/9Ka9YytOzgzJasrRZfX7dnttLlbh8NKeA=
github.com/aws/aws-sdk-go v1.44.274/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/aws/aws-sdk-go v1.44.275 h1:VqRULgqrigvQLll4e4hXuc568EQAtZQ6jmBzLlQHzSI=
github.com/aws/aws-sdk-go v1.44.275/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/aws/aws-sdk-go v1.44.276 h1:ywPlx9C5Yc482dUgAZ9bHpQ6onVvJvYE9FJWsNDCEy0=
github.com/aws/aws-sdk-go v1.44.276/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/aws/aws-sdk-go v1.44.277 h1:YHmyzBPARTJ7LLYV1fxbfEbQOaUh3kh52hb7nBvX3BQ=
github.com/aws/aws-sdk-go v1.44.277/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/aws/aws-sdk-go v1.44.278 h1:jJFDO/unYFI48WQk7UGSyO3rBA/gnmRpNYNuAw/fPgE=
github.com/aws/aws-sdk-go v1.44.278/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/aws/aws-sdk-go v1.44.279 h1:g23dxnYjIiPlQo0gIKNR0zVPsSvo1bj5frWln+5sfhk=
github.com/aws/aws-sdk-go v1.44.279/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/aws/aws-sdk-go v1.44.280 h1:UYl/yxhDxP8naok6ftWyQ9/9ZzNwjC9dvEs/j8BkGhw=
github.com/aws/aws-sdk-go v1.44.280/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/aws/aws-sdk-go v1.44.281 h1:z/ptheJvINaIAsKXthxONM+toTKw2pxyk700Hfm6yUw=
github.com/aws/aws-sdk-go v1.44.281/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/aws/aws-sdk-go v1.44.284 h1:Oc5Kubi43/VCkerlt3ZU3KpBju6BpNkoG3s7E8vj/O8=
github.com/aws/aws-sdk-go v1.44.284/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/aws/aws-sdk-go v1.44.289 h1:5CVEjiHFvdiVlKPBzv0rjG4zH/21W/onT18R5AH/qx0=
github.com/aws/aws-sdk-go v1.44.289/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/aws/aws-sdk-go v1.44.295 h1:SGjU1+MqttXfRiWHD6WU0DRhaanJgAFY+xIhEaugV8Y=
github.com/aws/aws-sdk-go v1.44.295/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/aws/aws-sdk-go v1.44.296 h1:ALRZIIKI+6EBWDiWP4RHWmOtHZ7dywRzenL4NWgNI2A=
github.com/aws/aws-sdk-go v1.44.296/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/aws/aws-sdk-go v1.44.298 h1:5qTxdubgV7PptZJmp/2qDwD2JL187ePL7VOxsSh1i3g=
github.com/aws/aws-sdk-go v1.44.298/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/aws/aws-sdk-go v1.44.299 h1:HVD9lU4CAFHGxleMJp95FV/sRhtg7P4miHD1v88JAQk=
github.com/aws/aws-sdk-go v1.44.299/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/aws/aws-sdk-go v1.44.302 h1:ST3ko6GrJKn3Xi+nAvxjG3uk/V1pW8KC52WLeIxqqNk=
github.com/aws/aws-sdk-go v1.44.302/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/aws/aws-sdk-go v1.44.303 h1:GybJmj22u3KVMghsqYZoicS3NpiWiNaPE1+5bhvkxIs=
github.com/aws/aws-sdk-go v1.44.303/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/aws/aws-sdk-go v1.44.304 h1:crcJBVeewWcVAXDQChzJWZYGFq9i1TYLycAtQ6Xpi4c=
github.com/aws/aws-sdk-go v1.44.304/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/aws/aws-sdk-go v1.44.305 h1:fU/5lY3WyBjGU9fkmQYd8o4fZu+2RaOv/i+sPaJVvFg=
github.com/aws/aws-sdk-go v1.44.305/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/aws/aws-sdk-go v1.44.306 h1:H487V/1N09BDxeGR7oR+LloC2uUpmf4atmqJaBgQOIs=
github.com/aws/aws-sdk-go v1.44.306/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/aws/aws-sdk-go v1.44.307 h1:2R0/EPgpZcFSUwZhYImq/srjaOrOfLv5MNRzrFyAM38=
github.com/aws/aws-sdk-go v1.44.307/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/aws/aws-sdk-go v1.44.308 h1:XKu+76UHsD5LaiU2Zb1q42uWakw80Az7x39jJXXahos=
github.com/aws/aws-sdk-go v1.44.308/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/aws/aws-sdk-go v1.44.309 h1:IPJOFBzXekakxmEpDwd4RTKmmBR6LIAiXgNsM51bWbU=
github.com/aws/aws-sdk-go v1.44.309/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/aws/aws-sdk-go v1.44.312 h1:llrElfzeqG/YOLFFKjg1xNpZCFJ2xraIi3PqSuP+95k=
github.com/aws/aws-sdk-go v1.44.312/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/aws/aws-sdk-go v1.44.313 h1:u6EuNQqgAmi09GEZ5g/XGHLF0XV31WcdU5rnHyIBHBc=
github.com/aws/aws-sdk-go v1.44.313/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/aws/aws-sdk-go v1.44.314 h1:d/5Jyk/Fb+PBd/4nzQg0JuC2W4A0knrDIzBgK/ggAow=
github.com/aws/aws-sdk-go v1.44.314/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/aws/aws-sdk-go v1.44.315 h1:kYTC+Y/bJ9M7QQRvkI/LN5OWvhkIOL/YuFFRhS5QAOo=
github.com/aws/aws-sdk-go v1.44.315/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/aws/aws-sdk-go v1.44.316 h1:UC3alCEyzj2XU13ZFGIOHW3yjCNLGTIGVauyetl9fwE=
github.com/aws/aws-sdk-go v1.44.316/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/aws/aws-sdk-go v1.44.317 h1:+8XWrLmGMwPPXSRSLPzhgcGnzJ2mYkgkrcB9C/GnSOU=
github.com/aws/aws-sdk-go v1.44.317/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/aws/aws-sdk-go v1.44.318 h1:Yl66rpbQHFUbxe9JBKLcvOvRivhVgP6+zH0b9KzARX8=
github.com/aws/aws-sdk-go v1.44.318/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/aws/aws-sdk-go v1.44.322 h1:7JfwifGRGQMHd99PvfXqxBaZsjuRaOF6e3X9zRx2uYo=
github.com/aws/aws-sdk-go v1.44.322/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/aws/aws-sdk-go v1.44.323 h1:97/dn93DWrN1VfhAWQ2tV+xuE6oO/LO9rSsEsuC4PLU=
github.com/aws/aws-sdk-go v1.44.323/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/aws/aws-sdk-go v1.44.324 h1:/uja9PtgeeqrZCPOJTenjMLNpciIMuzaRKooq+erG4A=
github.com/aws/aws-sdk-go v1.44.324/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/aws/aws-sdk-go v1.44.325 h1:jF/L99fJSq/BfiLmUOflO/aM+LwcqBm0Fe/qTK5xxuI=
github.com/aws/aws-sdk-go v1.44.325/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/aws/aws-sdk-go v1.44.326 h1:/6xD/9mKZ2RMTDfbhh9qCxw+CaTbJRvfHJ/NHPFbI38=
github.com/aws/aws-sdk-go v1.44.326/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/aws/aws-sdk-go v1.44.327 h1:ZS8oO4+7MOBLhkdwIhgtVeDzCeWOlTfKJS7EgggbIEY=
github.com/aws/aws-sdk-go v1.44.327/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/aws/aws-sdk-go v1.44.328 h1:WBwlf8ym9SDQ/GTIBO9eXyvwappKJyOetWJKl4mT7ZU=
github.com/aws/aws-sdk-go v1.44.328/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/aws/aws-sdk-go v1.44.329 h1:Rqy+wYI8h+iq+FphR59KKTsHR1Lz7YiwRqFzWa7xoYU=
github.com/aws/aws-sdk-go v1.44.329/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/aws/aws-sdk-go v1.44.330 h1:kO41s8I4hRYtWSIuMc/O053wmEGfMTT8D4KtPSojUkA=
github.com/aws/aws-sdk-go v1.44.330/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/aws/aws-sdk-go v1.44.331 h1:hEwdOTv6973uegCUY2EY8jyyq0OUg9INc0HOzcu2bjw=
github.com/aws/aws-sdk-go v1.44.331/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/aws/aws-sdk-go v1.44.332 h1:Ze+98F41+LxoJUdsisAFThV+0yYYLYw17/Vt0++nFYM=
github.com/aws/aws-sdk-go v1.44.332/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/aws/aws-sdk-go v1.44.333 h1:X0j5TGXtHLZzDB/uRcGKLG77ERFtxYQtXefs+Apf2PU=
github.com/aws/aws-sdk-go v1.44.333/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/aws/aws-sdk-go v1.44.334 h1:h2bdbGb//fez6Sv6PaYv868s9liDeoYM6hYsAqTB4MU=
github.com/aws/aws-sdk-go v1.44.334/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/aws/aws-sdk-go v1.45.0 h1:qoVOQHuLacxJMO71T49KeE70zm+Tk3vtrl7XO4VUPZc=
github.com/aws/aws-sdk-go v1.45.0/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/aws/aws-sdk-go v1.45.1 h1:PXuxDZIo/Y9Bvtg2t055+dY4hRwNAEcq6bUMv9fXcjk=
github.com/aws/aws-sdk-go v1.45.1/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/aws/aws-sdk-go v1.45.2 h1:hTong9YUklQKqzrGk3WnKABReb5R8GjbG4Y6dEQfjnk=
github.com/aws/aws-sdk-go v1.45.2/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/aws/aws-sdk-go v1.45.3 h1:Q8BksXg2ZUu2dCbA62+UCEtfvqsW8EO4tzt2IVeYAws=
github.com/aws/aws-sdk-go v1.45.3/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/aws/aws-sdk-go v1.45.4 h1:6B8oTYNEncxga8EV1C6Q4iJNnpDIqLEigy0v0oh2qYw=
github.com/aws/aws-sdk-go v1.45.4/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/aws/aws-sdk-go v1.45.5 h1:bxilnhv9FngUgdPNJmOIv2bk+2sP0dpqX3e4olhWcGM=
github.com/aws/aws-sdk-go v1.45.5/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/aws/aws-sdk-go v1.45.6 h1:Y2isQQBZsnO15dzUQo9YQRThtHgrV200XCH05BRHVJI=
github.com/aws/aws-sdk-go v1.45.6/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/aws/aws-sdk-go v1.45.11 h1:8qiSrA12+NRr+2MVpMApi3JxtiFFjDVU1NeWe+80bYg=
github.com/aws/aws-sdk-go v1.45.11/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/aws/aws-sdk-go v1.45.12 h1:+bKbbesGNPp+TeGrcqfrWuZoqcIEhjwKyBMHQPp80Jo=
github.com/aws/aws-sdk-go v1.45.12/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/aws/aws-sdk-go v1.45.13 h1:LwD/G+PX7FQnbU8wXekx12e90i1GuKJQC2+pl4IlPAs=
github.com/aws/aws-sdk-go v1.45.13/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/aws/aws-sdk-go v1.45.14 h1:/IPMEh9oelbK7506fdMHkbV9mq4a6f5aeiy9OT0PRKw=
github.com/aws/aws-sdk-go v1.45.14/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/aws/aws-sdk-go v1.45.15 h1:gYBTVSYuhXdatrLbsPaRgVcc637zzdgThWmsDRwXLOo=
github.com/aws/aws-sdk-go v1.45.15/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/aws/aws-sdk-go v1.45.16 h1:spca2z7UJgoQ5V2fX6XiHDCj2E65kOJAfbUPozSkE24=
github.com/aws/aws-sdk-go v1.45.16/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/aws/aws-sdk-go v1.45.17 h1:EclP31IdsIVaHNgIlUtvFIDuyFUtTCa9oYthZmGlZ1U=
github.com/aws/aws-sdk-go v1.45.17/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/aws/aws-sdk-go v1.45.18 h1:uSOGg4LFtpQH/bq9FsumMKfZHNl7BdH7WURHOqKXHNU=
github.com/aws/aws-sdk-go v1.45.18/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/aws/aws-sdk-go v1.45.19 h1:+4yXWhldhCVXWFOQRF99ZTJ92t4DtoHROZIbN7Ujk/U=
github.com/aws/aws-sdk-go v1.45.19/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/aws/aws-sdk-go v1.45.20 h1:U/wLZEwqVB6o2XlcJ7um8kczx+A1X2MgO2y4wdKDQTs=
github.com/aws/aws-sdk-go v1.45.20/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/aws/aws-sdk-go v1.45.21 h1:9LN2/pMQY2qwGJgSMzv0xNGnstFHCgpSfenvsurX2nk=
github.com/aws/aws-sdk-go v1.45.21/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/aws/aws-sdk-go v1.45.22 h1:yq86HCbyWIn2A6Ayoa61WCf7jkMmsESXUB9+QrbxK50=
github.com/aws/aws-sdk-go v1.45.22/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/aws/aws-sdk-go v1.45.23 h1:0xRQw5fsFMpisaliDZ8iUZtw9w+3YjY9/UwUGRbB/i4=
github.com/aws/aws-sdk-go v1.45.23/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/aws/aws-sdk-go v1.45.24 h1:TZx/CizkmCQn8Rtsb11iLYutEQVGK5PK9wAhwouELBo=
github.com/aws/aws-sdk-go v1.45.24/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/aws/aws-sdk-go v1.45.27 h1:b+zOTPkAG4i2RvqPdHxkJZafmhhVaVHBp4r41Tu4I6U=
github.com/aws/aws-sdk-go v1.45.27/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/aws/aws-sdk-go v1.45.28 h1:p2ATcaK6ffSw4yZ2UAGzgRyRXwKyOJY6ZCiKqj5miJE=
github.com/aws/aws-sdk-go v1.45.28/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/aws/aws-sdk-go v1.46.0 h1:Igh7W8P+sA6mXJ9yhreOSweefLapcqekhxQlY1llxcM=
github.com/aws/aws-sdk-go v1.46.0/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/aws/aws-sdk-go v1.46.1 h1:U26quvBWFZMQuultLw5tloW4GnmWaChEwMZNq8uYatw=
github.com/aws/aws-sdk-go v1.46.1/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/aws/aws-sdk-go v1.46.2 h1:XZbOmjtN1VCfEtQq7QNFsbxIqO+bB+bRhiOBjp6AzWc=
github.com/aws/aws-sdk-go v1.46.2/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/aws/aws-sdk-go v1.46.3 h1:zcrCu14ANOji6m38bUTxYdPqne4EXIvJQ2KXZ5oi9k0=
github.com/aws/aws-sdk-go v1.46.3/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/aws/aws-sdk-go v1.46.5 h1:NYYUrhOftwiXPkqZwEpB3043bMukegJAt15ozrqJbEY=
github.com/aws/aws-sdk-go v1.46.5/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/aws/aws-sdk-go v1.46.6 h1:6wFnNC9hETIZLMf6SOTN7IcclrOGwp/n9SLp8Pjt6E8=
github.com/aws/aws-sdk-go v1.46.6/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/aws/aws-sdk-go v1.46.7 h1:IjvAWeiJZlbETOemOwvheN5L17CvKvKW0T1xOC6d3Sc=
github.com/aws/aws-sdk-go v1.46.7/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/aws/aws-sdk-go v1.47.0 h1:/JUg9V1+xh+qBn8A6ec/l15ETPaMaBqxkjz+gg63dNk=
github.com/aws/aws-sdk-go v1.47.0/go.mod h1:DlEaEbWKZmsITVbqlSVvekPARM1HzeV9PMYg15ymSDA=
github.com/aws/aws-sdk-go v1.47.1 h1:j9ih0Ashcw8tQcnfqNimBM8ARQ/CMpoBwjKue1D6Fuk=
github.com/aws/aws-sdk-go v1.47.1/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=
github.com/aws/aws-sdk-go v1.47.2 h1:KEdO2PbjfEBmHvnEwbYEpr65ZIkmwK5aB85Gj19ASuA=
github.com/aws/aws-sdk-go v1.47.2/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=
github.com/aws/aws-sdk-go v1.47.3 h1:e0H6NFXiniCpR8Lu3lTphVdRaeRCDLAeRyTHd1tJSd8=
github.com/aws/aws-sdk-go v1.47.3/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=
github.com/aws/aws-sdk-go v1.47.4 h1:IyhNbmPt+5ldi5HNzv7ZnXiqSglDMaJiZlzj4Yq3qnk=
github.com/aws/aws-sdk-go v1.47.4/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=
github.com/aws/aws-sdk-go v1.47.5 h1:U2JlfPmrUoz5p+2X/XwKxmaJFo2oV+LbJqx8jyEvyAY=
github.com/aws/aws-sdk-go v1.47.5/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=
github.com/aws/aws-sdk-go v1.47.6 h1:WMnLApoJAKC+KBt8f53QccGBZghLRoVfAcOo52jUtY0=
github.com/aws/aws-sdk-go v1.47.6/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=
github.com/aws/aws-sdk-go v1.47.7 h1:Y1J7g48WAzO4dYGQELbWJ57rASV8G7rd4u9hDB+AevU=
github.com/aws/aws-sdk-go v1.47.7/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=
github.com/aws/aws-sdk-go v1.47.8 h1:VCFyO5UTREnhR0HRf9roqFfJeeRVin58zUy+pBMhwjY=
github.com/aws/aws-sdk-go v1.47.8/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=
github.com/aws/aws-sdk-go v1.47.9 h1:rarTsos0mA16q+huicGx0e560aYRtOucV5z2Mw23JRY=
github.com/aws/aws-sdk-go v1.47.9/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=
github.com/aws/aws-sdk-go v1.47.10 h1:cvufN7WkD1nlOgpRopsmxKQlFp5X1MfyAw4r7BBORQc=
github.com/aws/aws-sdk-go v1.47.10/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=
github.com/aws/aws-sdk-go v1.47.11 h1:Dol+MA+hQblbnXUI3Vk9qvoekU6O1uDEuAItezjiWNQ=
github.com/aws/aws-sdk-go v1.47.11/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=
github.com/aws/aws-sdk-go v1.47.12 h1:1daICVijigVEXCzhg27A5d7hbkR4wODPGn9GHyBclKM=
github.com/aws/aws-sdk-go v1.47.12/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=
github.com/aws/aws-sdk-go v1.47.13 h1:pJgCtldg5azDAFoEcE0fz6n+FnCc1/FY4krtUa5uvZQ=
github.com/aws/aws-sdk-go v1.47.13/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=
github.com/aws/aws-sdk-go v1.48.0 h1:1SeJ8agckRDQvnSCt1dGZYAwUaoD2Ixj6IaXB4LCv8Q=
github.com/aws/aws-sdk-go v1.48.0/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=
github.com/aws/aws-sdk-go v1.48.1 h1:OXPUVL4cLdsDsqkVIuhwY+D389tjI7e1xu0lsDYyeMk=
github.com/aws/aws-sdk-go v1.48.1/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=
github.com/aws/aws-sdk-go v1.48.2 h1:Lf7+Y4WmHB0AQLRQZA46diSwDa+LWbwY6IGaYoCVtTc=
github.com/aws/aws-sdk-go v1.48.2/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=
github.com/aws/aws-sdk-go v1.48.3 h1:btYjT+opVFxUbRz+qSCjJe07cdX82BHmMX/FXYmoL7g=
github.com/aws/aws-sdk-go v1.48.3/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=
github.com/aws/aws-sdk-go v1.48.4 h1:HS2L7ynVhkcRrQRro9CLJZ/xLRb4UOzDEfPzgevZwXM=
github.com/aws/aws-sdk-go v1.48.4/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=
github.com/aws/aws-sdk-go v1.48.5 h1:cp3inTx9trQNCNZV/Id5S5egpilBXKdF32uKtb1LszI=
github.com/aws/aws-sdk-go v1.48.5/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=
github.com/aws/aws-sdk-go v1.48.6 h1:hnL/TE3eRigirDLrdRE9AWE1ALZSVLAsC4wK8TGsMqk=
github.com/aws/aws-sdk-go v1.48.6/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=
github.com/aws/aws-sdk-go v1.48.7 h1:gDcOhmkohlNk20j0uWpko5cLBbwSkB+xpkshQO45F7Y=
github.com/aws/aws-sdk-go v1.48.7/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=
github.com/aws/aws-sdk-go v1.48.8 h1:KE7PPWWbvU/qvuSCASrKalblCZGsYaiU5JVw6vsGAWI=
github.com/aws/aws-sdk-go v1.48.8/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=
github.com/aws/aws-sdk-go v1.48.9 h1:vqzjg5FCi/QDWTEenBs65gu57GJdvkqZ0+5steFb44g=
github.com/aws/aws-sdk-go v1.48.9/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=
github.com/aws/aws-sdk-go v1.48.10 h1:0LIFG3wp2Dt6PsxKWCg1Y1xRrn2vZnW5/gWdgaBalKg=
github.com/aws/aws-sdk-go v1.48.10/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=
github.com/aws/aws-sdk-go v1.48.11 h1:9YbiSbaF/jWi+qLRl+J5dEhr2mcbDYHmKg2V7RBcD5M=
github.com/aws/aws-sdk-go v1.48.11/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=
github.com/aws/aws-sdk-go v1.48.12 h1:n+eGzflzzvYubu2cOjqpVll7lF+Ci0ThyCpg5kzfzbo=
github.com/aws/aws-sdk-go v1.48.12/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=
github.com/aws/aws-sdk-go v1.48.13 h1:6N4GTme6MpxfCisWf5pql8k3TBORiKTmbeutZCDXlG8=
github.com/aws/aws-sdk-go v1.48.13/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=
github.com/aws/aws-sdk-go v1.48.14 h1:nVLrp+F84SG+xGiFMfe1TE6ZV6smF+42tuuNgYGV30s=
github.com/aws/aws-sdk-go v1.48.14/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=
github.com/aws/aws-sdk-go v1.48.16 h1:mcj2/9J/MJ55Dov+ocMevhR8Jv6jW/fAxbrn4a1JFc8=
github.com/aws/aws-sdk-go v1.48.16/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=
github.com/aws/aws-sdk-go v1.49.0 h1:g9BkW1fo9GqKfwg2+zCD+TW/D36Ux+vtfJ8guF4AYmY=
github.com/aws/aws-sdk-go v1.49.0/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=
github.com/aws/aws-sdk-go v1.49.1 h1:Dsamcd8d/nNb3A+bZ0ucfGl0vGZsW5wlRW0vhoYGoeQ=
github.com/aws/aws-sdk-go v1.49.1/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=
github.com/aws/aws-sdk-go v1.49.2 h1:+4BEcm1nPCoDbVd+gg8cdxpa1qJfrvnddy12vpEVWjw=
github.com/aws/aws-sdk-go v1.49.2/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=
github.com/aws/aws-sdk-go v1.49.3 h1:+UGwhC3kChk0pRCxSsbaQSNIc8MfFURQL44Ig6RRR3I=
github.com/aws/aws-sdk-go v1.49.3/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=
github.com/aws/aws-sdk-go v1.49.4 h1:qiXsqEeLLhdLgUIyfr5ot+N/dGPWALmtM1SetRmbUlY=
github.com/aws/aws-sdk-go v1.49.4/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=
github.com/aws/aws-sdk-go v1.49.5 h1:y2yfBlwjPDi3/sBVKeznYEdDy6wIhjA2L5NCBMLUIYA=
github.com/aws/aws-sdk-go v1.49.5/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=
github.com/aws/aws-sdk-go v1.49.8 h1:gKgEiyJ8CPnr4r6pS06WfNXvp6z34JER1pBIwuocvVA=
github.com/aws/aws-sdk-go v1.49.8/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=
github.com/aws/aws-sdk-go v1.49.9 h1:4xoyi707rsifB1yMsd5vGbAH21aBzwpL3gNRMSmjIyc=
github.com/aws/aws-sdk-go v1.49.9/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=
github.com/aws/aws-sdk-go v1.49.10 h1:xcTIazQPKoQWmegkQu5C7oPDgXwGaN7/E9y6TGmxNUE=
github.com/aws/aws-sdk-go v1.49.10/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=
github.com/aws/aws-sdk-go v1.49.11 h1:hRFpovmI+0K4kuJ8AGAblS/tU4oAoVOmCdNty8urB+M=
github.com/aws/aws-sdk-go v1.49.11/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=
github.com/aws/aws-sdk-go v1.49.13 h1:f4mGztsgnx2dR9r8FQYa9YW/RsKb+N7bgef4UGrOW1Y=
github.com/aws/aws-sdk-go v1.49.13/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=
github.com/aws/aws-sdk-go v1.49.14 h1:AZ7wfESxXuqQElXRnDCaohJSUSaf2s7c2uPB7g5js/w=
github.com/aws/aws-sdk-go v1.49.14/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=
github.com/aws/aws-sdk-go v1.49.15 h1:aH9bSV4kL4ziH0AMtuYbukGIVebXddXBL0cKZ1zj15k=
github.com/aws/aws-sdk-go v1.49.15/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=
github.com/aws/aws-sdk-go v1.49.16 h1:KAQwhLg296hfffRdh+itA9p7Nx/3cXS/qOa3uF9ssig=
github.com/aws/aws-sdk-go v1.49.16/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=
github.com/aws/aws-sdk-go v1.49.17 h1:Cc+7LgPjKeJkF2SdNo1IkpQ5Dfl9HCZEVw9OP3CPuEI=
github.com/aws/aws-sdk-go v1.49.17/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=
github.com/aws/aws-sdk-go v1.49.18 h1:g/iMXkfXeJQ7MvnLwroxWsTTNkHtdVJGxIgrAIEG62M=
github.com/aws/aws-sdk-go v1.49.18/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=
github.com/aws/aws-sdk-go v1.49.19 h1:oZryiqeQpeJsIcAmZlp86duMu/s/DJ43qyfwa51qmLg=
github.com/aws/aws-sdk-go v1.49.19/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=
github.com/aws/aws-sdk-go v1.49.20 h1:VgEUq2/ZbUkLbqPyDcxrirfXB+PgiZUUF5XbsgWe2S0=
github.com/aws/aws-sdk-go v1.49.20/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=
github.com/aws/aws-sdk-go v1.49.21 h1:Rl8KW6HqkwzhATwvXhyr7vD4JFUMi7oXGAw9SrxxIFY=
github.com/aws/aws-sdk-go v1.49.21/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=
github.com/aws/aws-sdk-go v1.49.22 h1:r01+cQJ3cORQI1PJxG8af0jzrZpUOL9L+/3kU2x1geU=
github.com/aws/aws-sdk-go v1.49.22/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=
github.com/aws/aws-sdk-go v1.49.23 h1:Wu3bVzvSiu2xEUlnG28454I7Dt3kVnrz4/ccJXKV56E=
github.com/aws/aws-sdk-go v1.49.23/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=
github.com/aws/aws-sdk-go v1.49.24 h1:2ekq9ZvaoB2aRbTDfARzgVGUBB9N8XD2QYhFmTBlp+c=
github.com/aws/aws-sdk-go v1.49.24/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=
github.com/aws/aws-sdk-go v1.50.0 h1:HBtrLeO+QyDKnc3t1+5DR1RxodOHCGr8ZcrHudpv7jI=
github.com/aws/aws-sdk-go v1.50.0/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=
github.com/aws/aws-sdk-go v1.50.1 h1:AwnLUM7TcH9vMZqA4TcDKmGfLmDW5VXwT5tPH6kXylo=
github.com/aws/aws-sdk-go v1.50.1/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=
github.com/aws/aws-sdk-go v1.50.2 h1:/vS+Uhv2FPcqcTxBmgT3tvvN5q6pMAKu6QXltgXlGgo=
github.com/aws/aws-sdk-go v1.50.2/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=
github.com/aws/aws-sdk-go v1.50.3 h1:NnXC/ukOakZbBwQcwAzkAXYEB4SbWboP9TFx9vvhIrE=
github.com/aws/aws-sdk-go v1.50.3/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=
github.com/aws/aws-sdk-go v1.50.4 h1:jJNhxunBgfjmCSjMZ3INwQ19ZN3RoGEZfgSCUYF/NZw=
github.com/aws/aws-sdk-go v1.50.4/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=
github.com/aws/aws-sdk-go v1.50.5 h1:H2Aadcgwr7a2aqS6ZwcE+l1mA6ZrTseYCvjw2QLmxIA=
github.com/aws/aws-sdk-go v1.50.5/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=
github.com/aws/aws-sdk-go v1.50.6 h1:FaXvNwHG3Ri1paUEW16Ahk9zLVqSAdqa1M3phjZR35Q=
github.com/aws/aws-sdk-go v1.50.6/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=
github.com/aws/aws-sdk-go v1.50.7 h1:odKb+uneeGgF2jgAerKjFzpljiyZxleV4SHB7oBK+YA=
github.com/aws/aws-sdk-go v1.50.7/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=
github.com/aws/aws-sdk-go v1.50.9 h1:yX66aKnEtRc/uNV/1EH8CudRT5aLwVwcSwTBphuVPt8=
github.com/aws/aws-sdk-go v1.50.9/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=
github.com/aws/aws-sdk-go v1.50.10 h1:H3NQvqRUKG+9oysCKTIyylpkqfPA7MiBtzTnu/cIGqE=
github.com/aws/aws-sdk-go v1.50.10/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=
github.com/aws/aws-sdk-go v1.50.11 h1:BxUqMbkzKzzQ6FXLlZFNFkFjHnv6utbc4PItVs5SvaE=
github.com/aws/aws-sdk-go v1.50.11/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=
github.com/aws/aws-sdk-go v1.50.12 h1:Gc6QS4Ys++cWSl63U+HyPbKeLVcoOvi6veayhcipPac=
github.com/aws/aws-sdk-go v1.50.12/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=
github.com/aws/aws-sdk-go v1.50.13 h1:yeXram2g7q8uKkQkAEeZyk9FmPzxI4UpGwAZGZtEGmM=
github.com/aws/aws-sdk-go v1.50.13/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=
github.com/aws/aws-sdk-go v1.50.14 h1:m1bxKtd1lJpNnl+Owah0+UPRuS9f3GFvxBPgc8RiodE=
github.com/aws/aws-sdk-go v1.50.14/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=
github.com/aws/aws-sdk-go v1.50.15 h1:wEMnPfEQQFaoIJwuO18zq/vtG4Ft7NxQ3r9xlEi/8zg=
github.com/aws/aws-sdk-go v1.50.15/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=
github.com/aws/aws-sdk-go v1.50.16 h1:/KuHK+Sadp9BKXWWtMhPtBdj+PLIFCnQZxQnsuLhxKc=
github.com/aws/aws-sdk-go v1.50.16/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=
github.com/aws/aws-sdk-go v1.50.17 h1:KsbzUKDgGNlkDHGvoQDhiJ63a9jtZd+O+/s3pTOr/ns=
github.com/aws/aws-sdk-go v1.50.17/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=
github.com/aws/aws-sdk-go v1.50.18 h1:h+FQjxp5sSDqFKScTUXHVahBlqduKtiR0qM18evcvag=
github.com/aws/aws-sdk-go v1.50.18/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=
github.com/aws/aws-sdk-go v1.50.19 h1:YSIDKRSkh/TW0RPWoocdLqtC/T5W6IGBVhFs6P7Qcac=
github.com/aws/aws-sdk-go v1.50.19/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=
github.com/aws/aws-sdk-go v1.50.20 h1:xfAnSDVf/azIWTVQXQODp89bubvCS85r70O3nuQ4dnE=
github.com/aws/aws-sdk-go v1.50.20/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=
github.com/aws/aws-sdk-go v1.50.21 h1:W8awpwiInOt4qHQE6JghRYQJhHcf/cDJS3mlZYqioSQ=
github.com/aws/aws-sdk-go v1.50.21/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=
github.com/aws/aws-sdk-go v1.50.22 h1:BUhSaO2qLk2jkcyLebcvDmbdOunVe/Wq8RsCyI8szL0=
github.com/aws/aws-sdk-go v1.50.22/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=
github.com/aws/aws-sdk-go v1.50.23 h1:BB99ohyCmq6O7m5RvjN2yqTt57snL8OhDvfxEvM6ihs=
github.com/aws/aws-sdk-go v1.50.23/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=
github.com/aws/aws-sdk-go v1.50.24 h1:3o2Pg7mOoVL0jv54vWtuafoZqAeEXLhm1tltWA2GcEw=
github.com/aws/aws-sdk-go v1.50.24/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=
github.com/aws/aws-sdk-go v1.50.25 h1:vhiHtLYybv1Nhx3Kv18BBC6L0aPJHaG9aeEsr92W99c=
github.com/aws/aws-sdk-go v1.50.25/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=
github.com/aws/aws-sdk-go v1.50.30 h1:2OelKH1eayeaH7OuL1Y9Ombfw4HK+/k0fEnJNWjyLts=
github.com/aws/aws-sdk-go v1.50.30/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=
github.com/aws/aws-sdk-go v1.50.31 h1:gx2NRLLEDUmQFC4YUsfMUKkGCwpXVO8ijUecq/nOQGA=
github.com/aws/aws-sdk-go v1.50.31/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=
github.com/aws/aws-sdk-go v1.50.32 h1:POt81DvegnpQKM4DMDLlHz1CO6OBnEoQ1gRhYFd7QRY=
github.com/aws/aws-sdk-go v1.50.32/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=
github.com/aws/aws-sdk-go v1.50.33 h1:/SKPJ7ZVPCFOYZyTKo5YdjeUEeOn2J2M0qfDTXWAoEU=
github.com/aws/aws-sdk-go v1.50.33/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=
github.com/aws/aws-sdk-go v1.50.34 h1:J1LjHzWNN/yVxQDTr0NIlI5vz9xRPvWiNCjQ4+5wh58=
github.com/aws/aws-sdk-go v1.50.34/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=
github.com/aws/aws-sdk-go v1.50.35 h1:llQnNddBI/64pK7pwUFBoWYmg8+XGQUCs214eMbSDZc=
github.com/aws/aws-sdk-go v1.50.35/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=
github.com/aws/aws-sdk-go v1.50.36 h1:PjWXHwZPuTLMR1NIb8nEjLucZBMzmf84TLoLbD8BZqk=
github.com/aws/aws-sdk-go v1.50.36/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=
github.com/aws/aws-sdk-go v1.50.37 h1:gnAf6eYPSTb4QpVwugtWFqD07QXOoX7LewRrtLUx3lI=
github.com/aws/aws-sdk-go v1.50.37/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=
github.com/aws/aws-sdk-go v1.50.38 h1:h8wxaLin7sFGK4sKassc1VpNcDbgAAEQJ5PHjqLAvXQ=
github.com/aws/aws-sdk-go v1.50.38/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=
github.com/aws/aws-sdk-go v1.51.0 h1:EA6GlEYMT3ouCO+v+oTWzKB/vcoHD2T9H9qulRx3lPg=
github.com/aws/aws-sdk-go v1.51.0/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=
github.com/aws/aws-sdk-go v1.51.1 h1:AFvTihcDPanvptoKS09a4yYmNtPm3+pXlk6uYHmZiFk=
github.com/aws/aws-sdk-go v1.51.1/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=
github.com/aws/aws-sdk-go v1.51.2 h1:Ruwgz5aqIXin5Yfcgc+PCzoqW5tEGb9aDL/JWDsre7k=
github.com/aws/aws-sdk-go v1.51.2/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=
github.com/aws/aws-sdk-go v1.51.3 h1:OqSyEXcJwf/XhZNVpMRgKlLA9nmbo5X8dwbll4RWxq8=
github.com/aws/aws-sdk-go v1.51.3/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=
github.com/aws/aws-sdk-go v1.51.4 h1:yOVfGhRJyReBrACK0alLosJl8iXhWkNY1vrePYmhHdw=
github.com/aws/aws-sdk-go v1.51.4/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=
github.com/aws/aws-sdk-go v1.51.5 h1:tUHg/ZJgS2Hog4Wl4xpbBqCrmFg6AYv7gPVaCs4v0+s=
github.com/aws/aws-sdk-go v1.51.5/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=
github.com/aws/aws-sdk-go v1.51.7 h1:RRjxHhx9RCjw5AhgpmmShq3F4JDlleSkyhYMQ2xUAe8=
github.com/aws/aws-sdk-go v1.51.7/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=
github.com/aws/aws-sdk-go v1.51.9 h1:w6ZlyFX7l4+ZNVPmWw7LwOHSaBDDQuP22l1gh7OYu7w=
github.com/aws/aws-sdk-go v1.51.9/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=
github.com/bwesterb/go-ristretto v1.2.0/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0=
github.com/bwesterb/go-ristretto v1.2.3/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0=
github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM=
github.com/bytedance/sonic v1.8.0 h1:ea0Xadu+sHlu7x5O3gKhRpQ1IKiMrSiHttPF0ybECuA=
github.com/bytedance/sonic v1.8.0/go.mod h1:i736AoUSYt75HyZLoJW9ERYxcy6eaN6h4BZXU064P/U=
github.com/bytedance/sonic v1.9.1 h1:6iJ6NqdoxCDr6mbY8h18oSO+cShGSMRGCEo7F2h0x8s=
github.com/bytedance/sonic v1.9.1/go.mod h1:i736AoUSYt75HyZLoJW9ERYxcy6eaN6h4BZXU064P/U=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
@ -751,8 +296,6 @@ github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMn
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cloudflare/circl v1.1.0 h1:bZgT/A+cikZnKIwn7xL2OBj012Bmvho/o6RpRvv3GKY=
github.com/cloudflare/circl v1.1.0/go.mod h1:prBCrKB9DV4poKZY1l9zBXg2QJY7mvgRvtMxxK7fi4I=
github.com/cloudflare/circl v1.3.3 h1:fE/Qz0QdIGqeWfnwq0RE0R7MI51s0M2E4Ga9kq5AEMs=
github.com/cloudflare/circl v1.3.3/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUKZrLbUZFA=
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
@ -766,16 +309,6 @@ github.com/coreos/go-oidc/v3 v3.4.0 h1:xz7elHb/LDwm/ERpwHd+5nb7wFHL32rsr6bBOgaeu
github.com/coreos/go-oidc/v3 v3.4.0/go.mod h1:eHUXhZtXPQLgEaDrOVTgwbgmz1xGOkJNye6h3zkD2Pw=
github.com/coreos/go-oidc/v3 v3.5.0 h1:VxKtbccHZxs8juq7RdJntSqtXFtde9YpNpGn0yqgEHw=
github.com/coreos/go-oidc/v3 v3.5.0/go.mod h1:ecXRtV4romGPeO6ieExAsUK9cb/3fp9hXNz1tlv8PIM=
github.com/coreos/go-oidc/v3 v3.6.0 h1:AKVxfYw1Gmkn/w96z0DbT/B/xFnzTd3MkZvWLjF4n/o=
github.com/coreos/go-oidc/v3 v3.6.0/go.mod h1:ZpHUsHBucTUj6WOkrP4E20UPynbLZzhTQ1XKCXkxyPc=
github.com/coreos/go-oidc/v3 v3.7.0 h1:FTdj0uexT4diYIPlF4yoFVI5MRO1r5+SEcIpEw9vC0o=
github.com/coreos/go-oidc/v3 v3.7.0/go.mod h1:yQzSCqBnK3e6Fs5l+f5i0F8Kwf0zpH9bPEsbY00KanM=
github.com/coreos/go-oidc/v3 v3.8.0 h1:s3e30r6VEl3/M7DTSCEuImmrfu1/1WBgA0cXkdzkrAY=
github.com/coreos/go-oidc/v3 v3.8.0/go.mod h1:yQzSCqBnK3e6Fs5l+f5i0F8Kwf0zpH9bPEsbY00KanM=
github.com/coreos/go-oidc/v3 v3.9.0 h1:0J/ogVOd4y8P0f0xUh8l9t07xRP/d8tccvjHl2dcsSo=
github.com/coreos/go-oidc/v3 v3.9.0/go.mod h1:rTKz2PYwftcrtoCzV5g5kvfJoWcm0Mk8AF8y1iAQro4=
github.com/coreos/go-oidc/v3 v3.10.0 h1:tDnXHnLyiTVyT/2zLDGj09pFPkhND8Gl8lnTRhoEaJU=
github.com/coreos/go-oidc/v3 v3.10.0/go.mod h1:5j11xcw0D3+SGxn6Z/WFADsgcWVMyNAlSQupk0KK3ac=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
@ -792,8 +325,6 @@ github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.m
github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0=
github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/gabriel-vasile/mimetype v1.4.2 h1:w5qFW6JKBz9Y393Y4q372O9A7cUSequkh1Q7OhCmWKU=
github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9BFQgN3qGY5GnNgA=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
@ -804,17 +335,11 @@ github.com/gin-gonic/gin v1.8.2 h1:UzKToD9/PoFj/V4rvlKqTRKnQYyz8Sc1MJlv4JHPtvY=
github.com/gin-gonic/gin v1.8.2/go.mod h1:qw5AYuDrzRTnhvusDsrov+fDIxp9Dleuu12h8nfB398=
github.com/gin-gonic/gin v1.9.0 h1:OjyFBKICoexlu99ctXNR2gg+c5pKrKMuyjgARg9qeY8=
github.com/gin-gonic/gin v1.9.0/go.mod h1:W1Me9+hsUSyj3CePGrd1/QrKJMSJ1Tu/0hFEH89961k=
github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg=
github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SUcPTeU=
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-jose/go-jose/v3 v3.0.0 h1:s6rrhirfEP/CGIoc6p+PZAeogN2SxKav6Wp7+dyMWVo=
github.com/go-jose/go-jose/v3 v3.0.0/go.mod h1:RNkWWRld676jZEYoV3+XK8L2ZnNSvIsxFMht0mSX+u8=
github.com/go-jose/go-jose/v3 v3.0.1 h1:pWmKFVtt+Jl0vBZTIpz/eAKwsm6LkIxDVVbFHKkchhA=
github.com/go-jose/go-jose/v3 v3.0.1/go.mod h1:RNkWWRld676jZEYoV3+XK8L2ZnNSvIsxFMht0mSX+u8=
github.com/go-jose/go-jose/v4 v4.0.1 h1:QVEPDE3OluqXBQZDcnNvQrInro2h0e4eqNbnZSWqS6U=
github.com/go-jose/go-jose/v4 v4.0.1/go.mod h1:WVf9LFMHh/QVrmqrOfqun0C45tMe3RoiKJMPvgWwLfY=
github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A=
github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8=
@ -834,18 +359,10 @@ github.com/go-playground/validator/v10 v10.11.1 h1:prmOlTVv+YjZjmRmNSF3VmspqJIxJ
github.com/go-playground/validator/v10 v10.11.1/go.mod h1:i+3WkQ1FvaUjjxh1kSvIA4dMGDBiPU55YFDl0WbKdWU=
github.com/go-playground/validator/v10 v10.11.2 h1:q3SHpufmypg+erIExEKUmsgmhDTyhcJ38oeKGACXohU=
github.com/go-playground/validator/v10 v10.11.2/go.mod h1:NieE624vt4SCTJtD87arVLvdmjPAeV8BQlHtMnw9D7s=
github.com/go-playground/validator/v10 v10.14.0 h1:vgvQWe3XCz3gIeFDm/HnTIbj6UGmg/+t63MyGU2n5js=
github.com/go-playground/validator/v10 v10.14.0/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU=
github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE=
github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
github.com/go-sql-driver/mysql v1.7.0 h1:ueSltNNllEqE3qcWBTD0iQd3IpL/6U+mJxLkazJ7YPc=
github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
github.com/go-sql-driver/mysql v1.7.1 h1:lUIinVbN1DY0xBg0eMOzmmtGoHwWBbvnWubQUrtU8EI=
github.com/go-sql-driver/mysql v1.7.1/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
github.com/go-sql-driver/mysql v1.8.0 h1:UtktXaU2Nb64z/pLiGIxY4431SJ4/dR5cjMmlVHgnT4=
github.com/go-sql-driver/mysql v1.8.0/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg=
github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y=
github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg=
github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee h1:s+21KNqlpePfkah2I+gwHF8xmJWRjooY+5248k6m4A0=
github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo=
github.com/gobwas/pool v0.2.0 h1:QEmUOlnSjWtnpRGHF3SauEiOsy82Cup83Vf2LcMlnc8=
@ -858,8 +375,6 @@ github.com/goccy/go-json v0.9.11 h1:/pAaQDLHEoCq/5FFmSKBswWmK6H0e8g4159Kc/X/nqk=
github.com/goccy/go-json v0.9.11/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
github.com/goccy/go-json v0.10.0 h1:mXKd9Qw4NuzShiRlOXKews24ufknHO7gx30lsDyokKA=
github.com/goccy/go-json v0.10.0/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
@ -891,8 +406,6 @@ github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaS
github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM=
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
@ -981,8 +494,6 @@ github.com/klauspost/compress v1.10.3 h1:OP96hzwJVBIHYU52pVTI6CczrxPvrGfgqF9N5eT
github.com/klauspost/compress v1.10.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
github.com/klauspost/cpuid/v2 v2.0.9 h1:lgaqFMSdTdQYdZ04uHyN2d/eKdOMyi2YLSvlQIBFYa4=
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
github.com/klauspost/cpuid/v2 v2.2.4 h1:acbojRNwl3o09bUq+yDCtZFc1aiwaAAxtcn8YkZXnvk=
github.com/klauspost/cpuid/v2 v2.2.4/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
@ -994,8 +505,6 @@ github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w=
github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY=
github.com/leodido/go-urn v1.2.4 h1:XlAE/cm/ms7TE/VMVoduSpNBoyc2dOxHs5MZSwAN63Q=
github.com/leodido/go-urn v1.2.4/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
@ -1003,12 +512,8 @@ github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peK
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng=
github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA=
github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
@ -1016,8 +521,6 @@ github.com/pelletier/go-toml/v2 v2.0.1 h1:8e3L2cCQzLFi2CR4g7vGFuFxX7Jl1kKX8gW+iV
github.com/pelletier/go-toml/v2 v2.0.1/go.mod h1:r9LEWfGN8R5k0VXJ+0BkIe7MYkRdwZOjgMj2KwnJFUo=
github.com/pelletier/go-toml/v2 v2.0.6 h1:nrzqCb7j9cDFj2coyLNLaZuJTLjWjlaz6nvTvIwycIU=
github.com/pelletier/go-toml/v2 v2.0.6/go.mod h1:eumQOmlWiOPt5WriQQqoM5y18pDHwha2N+QD+EUNTek=
github.com/pelletier/go-toml/v2 v2.0.8 h1:0ctb6s9mE31h0/lhu+J6OPmVeDxJn+kYnJc2jZR9tGQ=
github.com/pelletier/go-toml/v2 v2.0.8/go.mod h1:vuYfssBdrU2XDZ9bYydBu6t+6a6PYNcZljzZR9VXg+4=
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
@ -1043,8 +546,6 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
@ -1054,8 +555,6 @@ github.com/ugorji/go/codec v1.2.7 h1:YPXUKf7fYbp/y8xloBqZOw2qaVggbfwMlI8WM3wZUJ0
github.com/ugorji/go/codec v1.2.7/go.mod h1:WGN1fab3R1fzQlVQTkfxVtIBhWDRqOviHU95kRgeqEY=
github.com/ugorji/go/codec v1.2.9 h1:rmenucSohSTiyL09Y+l2OCk+FrMxGMzho2+tjr5ticU=
github.com/ugorji/go/codec v1.2.9/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU=
github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
@ -1072,8 +571,6 @@ go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E=
go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
golang.org/x/arch v0.0.0-20210923205945-b76863e36670 h1:18EFjUmQOcUvxNYSkA6jO9VAiXCnxFY6NyDX0bHDmkU=
golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
golang.org/x/arch v0.3.0 h1:02VY4/ZcO/gBOH6PUaoiptASxtXU10jazRCP865E97k=
golang.org/x/arch v0.3.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
@ -1085,35 +582,10 @@ golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5y
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa h1:zuSxTR4o9y82ebqCUJYNGJbGPo6sKVl54f/TVDObg1c=
golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4=
golang.org/x/crypto v0.5.0 h1:U/0M97KRkSFvyD/3FSmdP5W5swImpNgle/EHFhOsQPE=
golang.org/x/crypto v0.5.0/go.mod h1:NK/OQwhpMQP3MwtdjgLlYHnH9ebylxKWv3e0fK+mkQU=
golang.org/x/crypto v0.6.0 h1:qfktjS5LUO+fFKeJXZ+ikTRijMmljikvG68fpMMruSc=
golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58=
golang.org/x/crypto v0.7.0 h1:AvwMYaRytfdeVt3u6mLaxYtErKYjxA2OXjJ1HHq6t3A=
golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU=
golang.org/x/crypto v0.9.0 h1:LF6fAI+IutBocDJ2OT0Q1g8plpYljMZ4+lty+dsqw3g=
golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0=
golang.org/x/crypto v0.10.0 h1:LKqV2xt9+kDzSTfOhx4FrkEBcMrAgHSYgzywV9zcGmM=
golang.org/x/crypto v0.10.0/go.mod h1:o4eNf7Ede1fv+hwOwZsTHl9EsPFO6q6ZvYR8vYfY45I=
golang.org/x/crypto v0.11.0 h1:6Ewdq3tDic1mg5xRO4milcWCfMVQhI4NkqWWvqejpuA=
golang.org/x/crypto v0.11.0/go.mod h1:xgJhtzW8F9jGdVFWZESrid1U1bjeNy4zgy5cRr/CIio=
golang.org/x/crypto v0.12.0 h1:tFM/ta59kqch6LlvYnPa0yx5a83cL2nHflFhYKvv9Yk=
golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw=
golang.org/x/crypto v0.13.0 h1:mvySKfSWJ+UKUii46M40LOvyWfN0s2U+46/jDd0e6Ck=
golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc=
golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
golang.org/x/crypto v0.15.0 h1:frVn1TEaCEaZcn3Tmd7Y2b5KKPaZ+I32Q2OA3kYp5TA=
golang.org/x/crypto v0.15.0/go.mod h1:4ChreQoLWfG3xLDer1WdlH5NdlQ3+mwnQq1YTKY+72g=
golang.org/x/crypto v0.16.0 h1:mMMrFzRSCF0GvB7Ne27XVtVAaXLrPmgPC7/v0tkwHaY=
golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc=
golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg=
golang.org/x/crypto v0.19.0 h1:ENy+Az/9Y1vSrlrvBSyna3PITt4tiZLf7sgCjZBX7Wo=
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA=
golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
@ -1150,7 +622,6 @@ golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@ -1212,34 +683,6 @@ golang.org/x/net v0.6.0 h1:L4ZwwTvKW9gr0ZMS1yrHD9GZhIuVjOBBnaKH+SPQK0Q=
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g=
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ=
golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
golang.org/x/net v0.9.0 h1:aWJ/m6xSmxWBx+V0XRHTlrYrPG56jKsLdTFmsSsCzOM=
golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M=
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
golang.org/x/net v0.11.0 h1:Gi2tvZIJyBtO9SDr1q9h5hEQCp/4L2RQ+ar0qjx2oNU=
golang.org/x/net v0.11.0/go.mod h1:2L/ixqYpgIVXmeoSA/4Lu7BzTG4KIyPIryS4IsOd1oQ=
golang.org/x/net v0.12.0 h1:cfawfvKITfUsFCeJIHJrbSxpeu/E81khclypR0GVT50=
golang.org/x/net v0.12.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA=
golang.org/x/net v0.14.0 h1:BONx9s002vGdD9umnlX1Po8vOZmrgH34qlHcD1MfK14=
golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI=
golang.org/x/net v0.15.0 h1:ugBLEUaxABaB5AJqW9enI0ACdci2RUd4eP51NTBvuJ8=
golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
golang.org/x/net v0.16.0 h1:7eBu7KsSvFDtSXUIDbh3aqlK4DPsZ1rByC8PFfBThos=
golang.org/x/net v0.16.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM=
golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
golang.org/x/net v0.18.0 h1:mIYleuAkSbHh0tCv7RvjL3F6ZVbLjq4+R7zbOn3Kokg=
golang.org/x/net v0.18.0/go.mod h1:/czyP5RqHAH4odGYxBJ1qz0+CE5WZ+2j1YgoEo8F2jQ=
golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c=
golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U=
golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo=
golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY=
golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4=
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
golang.org/x/net v0.22.0 h1:9sGLhx7iRIHEiX0oAJ3MRZMUCElJgy7Br1nO+AMN3Tc=
golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@ -1277,32 +720,6 @@ golang.org/x/oauth2 v0.4.0 h1:NF0gk8LVPg1Ml7SSbGyySuoxdsXitj7TvgvuRxIMc/M=
golang.org/x/oauth2 v0.4.0/go.mod h1:RznEsdpjGAINPTOF0UH/t+xJ75L18YO3Ho6Pyn+uRec=
golang.org/x/oauth2 v0.5.0 h1:HuArIo48skDwlrvM3sEdHXElYslAMsf3KwRkkW4MC4s=
golang.org/x/oauth2 v0.5.0/go.mod h1:9/XBHVqLaWO3/BRHs5jbpYCnOZVjj5V0ndyaAM7KB4I=
golang.org/x/oauth2 v0.6.0 h1:Lh8GPgSKBfWSwFvtuWOfeI3aAAnbXTSutYxJiOJFgIw=
golang.org/x/oauth2 v0.6.0/go.mod h1:ycmewcwgD4Rpr3eZJLSB4Kyyljb3qDh40vJ8STE5HKw=
golang.org/x/oauth2 v0.7.0 h1:qe6s0zUXlPX80/dITx3440hWZ7GwMwgDDyrSGTPJG/g=
golang.org/x/oauth2 v0.7.0/go.mod h1:hPLQkd9LyjfXTiRohC/41GhcFqxisoUQ99sCUOHO9x4=
golang.org/x/oauth2 v0.8.0 h1:6dkIjl3j3LtZ/O3sTgZTMsLKSftL/B8Zgq4huOIIUu8=
golang.org/x/oauth2 v0.8.0/go.mod h1:yr7u4HXZRm1R1kBWqr/xKNqewf0plRYoB7sla+BCIXE=
golang.org/x/oauth2 v0.9.0 h1:BPpt2kU7oMRq3kCHAA1tbSEshXRw1LpG2ztgDwrzuAs=
golang.org/x/oauth2 v0.9.0/go.mod h1:qYgFZaFiu6Wg24azG8bdV52QJXJGbZzIIsRCdVKzbLw=
golang.org/x/oauth2 v0.10.0 h1:zHCpF2Khkwy4mMB4bv0U37YtJdTGW8jI0glAApi0Kh8=
golang.org/x/oauth2 v0.10.0/go.mod h1:kTpgurOux7LqtuxjuyZa4Gj2gdezIt/jQtGnNFfypQI=
golang.org/x/oauth2 v0.11.0 h1:vPL4xzxBM4niKCW6g9whtaWVXTJf1U5e4aZxxFx/gbU=
golang.org/x/oauth2 v0.11.0/go.mod h1:LdF7O/8bLR/qWK9DrpXmbHLTouvRHK0SgJl0GmDBchk=
golang.org/x/oauth2 v0.12.0 h1:smVPGxink+n1ZI5pkQa8y6fZT0RW0MgCO5bFpepy4B4=
golang.org/x/oauth2 v0.12.0/go.mod h1:A74bZ3aGXgCY0qaIC9Ahg6Lglin4AMAco8cIv9baba4=
golang.org/x/oauth2 v0.13.0 h1:jDDenyj+WgFtmV3zYVoi8aE2BwtXFLWOA67ZfNWftiY=
golang.org/x/oauth2 v0.13.0/go.mod h1:/JMhi4ZRXAf4HG9LiNmxvk+45+96RUlVThiH8FzNBn0=
golang.org/x/oauth2 v0.14.0 h1:P0Vrf/2538nmC0H+pEQ3MNFRRnVR7RlqyVw+bvm26z0=
golang.org/x/oauth2 v0.14.0/go.mod h1:lAtNWgaWfL4cm7j2OV8TxGi9Qb7ECORx8DktCY74OwM=
golang.org/x/oauth2 v0.15.0 h1:s8pnnxNVzjWyrvYdFUQq5llS1PX2zhPXmccZv99h7uQ=
golang.org/x/oauth2 v0.15.0/go.mod h1:q48ptWNTY5XWf+JNten23lcvHpLJ0ZSxF5ttTHKVCAM=
golang.org/x/oauth2 v0.16.0 h1:aDkGMBSYxElaoP81NpoUoz2oo2R2wHdZpGToUxfyQrQ=
golang.org/x/oauth2 v0.16.0/go.mod h1:hqZ+0LWXsiVoZpeld6jVt06P3adbS2Uu911W1SsJv2o=
golang.org/x/oauth2 v0.17.0 h1:6m3ZPmLEFdVxKKWnKq4VqZ60gutO35zm+zrAHVmHyDQ=
golang.org/x/oauth2 v0.17.0/go.mod h1:OzPDGQiuQMguemayvdylqddI7qcD9lnSDb+1FiwQ5HA=
golang.org/x/oauth2 v0.18.0 h1:09qnuIAgzdx1XplqJvW6CQqMCtGZykZWcXzPMPUusvI=
golang.org/x/oauth2 v0.18.0/go.mod h1:Wf7knwG0MPoWIMMBgFlEaSUDaKskp0dCfrlJRJXbBi8=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@ -1316,7 +733,6 @@ golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@ -1377,7 +793,6 @@ golang.org/x/sys v0.0.0-20220502124256-b6088ccd6cba/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220610221304-9f5ed59c137d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10 h1:WIoqL4EROvwiPdUtaip4VcDdpZ4kha7wBWZrbVKCIZg=
golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
@ -1392,39 +807,11 @@ golang.org/x/sys v0.4.0 h1:Zr2JFtRQNX3BCZ8YtxRE9hNJYC8J6I1MVbMg6owUp18=
golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU=
golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.9.0 h1:KS/R3tvhPqvJvwcKfnBHJwwthS11LRhmM5D59eEXa0s=
golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.10.0 h1:SqMFp9UcQJZa+pmYuAKjd9xq1f0j5rLcDIk0mj4qAsA=
golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.11.0 h1:eG7RXZHdqOJ1i+0lgLgCpSXAp6M3LYlAo6osgSi0xOM=
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o=
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE=
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q=
golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU=
golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y=
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4=
golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@ -1435,7 +822,6 @@ golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
golang.org/x/text v0.4.0 h1:BrVqGRd7+k1DiOgtnFvAkoQEWQvBc25ouMJM6429SFg=
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.5.0 h1:OLmvp0KP+FVG99Ct/qFiL/Fhk4zp4QQnZ7b2U+5piUM=
@ -1444,20 +830,6 @@ golang.org/x/text v0.6.0 h1:3XmdazWV+ubf7QgHSTWeykHOci5oeekaGJBLkrkaw4k=
golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68=
golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE=
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.10.0 h1:UpjohKhiEgNc0CSauXmwYftY1+LlaC75SJwh0SgCX58=
golang.org/x/text v0.10.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/text v0.11.0 h1:LAntKIrcmeSKERyiOh0XMV39LXS8IE9UL2yP7+f5ij4=
golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/text v0.12.0 h1:k+n5B8goJNdU7hSvEtMUz3d1Q6D/XW4COJSJR6fN0mc=
golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k=
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
@ -1513,7 +885,6 @@ golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
@ -1568,8 +939,6 @@ google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCID
google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c=
google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM=
google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
@ -1697,10 +1066,6 @@ google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscL
google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w=
google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng=
google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8=
google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
@ -1726,10 +1091,6 @@ honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
nhooyr.io/websocket v1.8.7 h1:usjR2uOr/zjjkVMy0lW+PPohFok7PCow5sDjLgX4P4g=
nhooyr.io/websocket v1.8.7/go.mod h1:B70DZP8IakI65RVQ51MsWP/8jndNma26DVA/nFSCgW0=
nhooyr.io/websocket v1.8.9 h1:+U/9DCNIH1XnzrWKs7yZp4jO0e/m6mUEh2kRPKRQYeg=
nhooyr.io/websocket v1.8.9/go.mod h1:rN9OFWIUwuxg4fR5tELlYC04bXYowCP9GX47ivo2l+c=
nhooyr.io/websocket v1.8.10 h1:mv4p+MnGrLDcPlBoWsvPP7XCzTYMXP9F9eIGoKbgx7Q=
nhooyr.io/websocket v1.8.10/go.mod h1:rN9OFWIUwuxg4fR5tELlYC04bXYowCP9GX47ivo2l+c=
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=

View file

@ -1,12 +1,8 @@
package main
import (
"fmt"
"log"
"math"
"net/http"
"strconv"
"strings"
"github.com/drone/drone-go/drone"
"github.com/gin-gonic/gin"
@ -34,88 +30,3 @@ func declareAPIAdminGradationRoutes(router *gin.RouterGroup) {
c.JSON(http.StatusOK, result)
})
}
type TestsWebhook struct {
Login string `json:"login"`
RepositoryId int `json:"repository_id"`
BuildNumber int `json:"build_number"`
UpTo float64 `json:"upto"`
Steps map[string]float64 `json:"steps,omitempty"`
}
func (tw *TestsWebhook) fetchRepoTests(r *Repository) error {
tmp := strings.Split(r.TestsRef, "/")
if len(tmp) < 3 {
return fmt.Errorf("This repository tests reference is not filled properly.")
}
work, err := getWork(r.IdWork)
if err != nil {
return fmt.Errorf("Unable to retrieve the related work: %w", err)
}
client := drone.NewClient(droneEndpoint, droneConfig)
result, err := client.Build(tmp[0], tmp[1], tw.BuildNumber)
if err != nil {
return fmt.Errorf("Unable to find the referenced build (%d): %w", tw.BuildNumber, err)
}
if result.Finished > 0 {
return fmt.Errorf("The test phase is not finished")
}
var grade float64
for _, stage := range result.Stages {
for _, step := range stage.Steps {
if g, ok := tw.Steps[fmt.Sprintf("%d", step.Number)]; ok {
log.Printf("Step %q (%d) in status %q", step.Name, step.Number, step.Status)
// Give the point if it succeed
if step.Status == "success" {
grade += g
}
continue
}
if g, ok := tw.Steps[step.Name]; ok {
log.Printf("Step %q (%d) in status %q", step.Name, step.Number, step.Status)
// Give the point if it succeed
if step.Status == "success" {
grade += g
}
continue
}
logs, err := client.Logs(tmp[0], tmp[1], tw.BuildNumber, stage.Number, step.Number)
if err != nil {
log.Printf("Unable to retrieve build logs %s/%s/%d/%d/%d: %s", tmp[0], tmp[1], tw.BuildNumber, stage.Number, step.Number, err.Error())
continue
}
if len(logs) < 2 {
continue
}
line := logs[len(logs)-1]
if strings.HasPrefix(logs[len(logs)-2].Message, "+ echo grade:") && strings.HasPrefix(line.Message, "grade:") {
g, err := strconv.ParseFloat(strings.TrimSpace(strings.TrimPrefix(line.Message, "grade:")), 64)
if err == nil {
grade += g
} else {
log.Println("Unable to parse grade:", err.Error())
}
}
}
}
if tw.UpTo != 0 {
grade = math.Trunc(grade*2000/tw.UpTo) / 100
}
work.AddGrade(WorkGrade{
IdUser: r.IdUser,
IdWork: work.Id,
Grade: grade,
})
return nil
}

View file

@ -1,10 +1,8 @@
package main
import (
"fmt"
"log"
"net/http"
"strconv"
"github.com/gin-gonic/gin"
)
@ -67,44 +65,28 @@ func declareAPIAuthGradesRoutes(router *gin.RouterGroup) {
})
}
func gradeHandler(c *gin.Context) {
work := c.MustGet("work").(*Work)
if gid, err := strconv.Atoi(string(c.Param("gid"))); err != nil {
c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"errmsg": "Bad grade identifier."})
return
} else if grade, err := work.GetGrade(int64(gid)); err != nil {
c.AbortWithStatusJSON(http.StatusNotFound, gin.H{"errmsg": "Grade not found."})
return
} else {
c.Set("grade", grade)
c.Next()
}
}
func GetAllGrades() (scores map[int64]map[string]*float64, err error) {
if rows, errr := DBQuery("SELECT id_user, kind, id, SUM(score)/COUNT(*) FROM student_scores GROUP BY id_user, kind, id"); errr != nil {
func GetAllGrades() (scores map[int64]map[int64]*float64, err error) {
if rows, errr := DBQuery("SELECT id_user, id_survey, SUM(score)/COUNT(*) FROM student_scores GROUP BY id_user, id_survey"); errr != nil {
return nil, errr
} else {
defer rows.Close()
scores = map[int64]map[string]*float64{}
scores = map[int64]map[int64]*float64{}
for rows.Next() {
var id_user int64
var kind string
var id int64
var id_survey int64
var score *float64
if err = rows.Scan(&id_user, &kind, &id, &score); err != nil {
if err = rows.Scan(&id_user, &id_survey, &score); err != nil {
return
}
if scores[id_user] == nil {
scores[id_user] = map[string]*float64{}
scores[id_user] = map[int64]*float64{}
}
scores[id_user][fmt.Sprintf("%c.%d", kind[0], id)] = score
scores[id_user][id_survey] = score
}
if err = rows.Err(); err != nil {
return
@ -115,7 +97,7 @@ func GetAllGrades() (scores map[int64]map[string]*float64, err error) {
}
func (s Survey) GetGrades() (scores map[int64]*float64, err error) {
if rows, errr := DBQuery("SELECT id_question, SUM(score)/COUNT(*) FROM student_scores WHERE kind = 'survey' AND id=? GROUP BY id_question", s.Id); errr != nil {
if rows, errr := DBQuery("SELECT id_question, SUM(score)/COUNT(*) FROM student_scores WHERE id_survey=? GROUP BY id_question", s.Id); errr != nil {
return nil, errr
} else {
defer rows.Close()
@ -140,7 +122,7 @@ func (s Survey) GetGrades() (scores map[int64]*float64, err error) {
}
func (s Survey) GetUserGrades(u *User) (scores map[int64]*float64, err error) {
if rows, errr := DBQuery("SELECT id_question, MAX(score) FROM student_scores WHERE kind = 'survey' AND id=? AND id_user = ? GROUP BY id_question", s.Id, u.Id); errr != nil {
if rows, errr := DBQuery("SELECT id_question, MAX(score) FROM student_scores WHERE id_survey=? AND id_user = ? GROUP BY id_question", s.Id, u.Id); errr != nil {
return nil, errr
} else {
defer rows.Close()

38
keys.go
View file

@ -50,44 +50,6 @@ func declareAPIKeysRoutes(router *gin.RouterGroup) {
c.Data(http.StatusOK, "application/pgp-keys", ret)
})
usersRoutes.GET("/allowed_signers", func(c *gin.Context) {
var u *User
if user, ok := c.Get("user"); ok {
u = user.(*User)
} else {
u = c.MustGet("LoggedUser").(*User)
}
user, err := GitLab_getUser(c.Request.Context(), u)
if err != nil {
log.Println("Unable to GitLab_getUser:", err)
c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"errmsg": "Unable to retrieve your GitLab user. Please try again in a few moment."})
return
}
keys, err := GitLab_getUserSSHKeys(c.Request.Context(), u)
if err != nil {
log.Println("Unable to GitLab_getUserSSHKeys:", err)
c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"errmsg": "Unable to retrieve your keys from GitLab. Please try again in a few moment."})
return
}
var ret string
for _, k := range keys {
if k.UsageType != "auth_and_signing" && k.UsageType != "signing" {
continue
}
if len(user.Email) > 0 {
ret += fmt.Sprintf("%s %s\n", user.Email, k.Key)
} else {
ret += fmt.Sprintf("*@epita.fr %s\n", k.Key)
}
}
c.Data(http.StatusOK, "text/plain", []byte(ret))
})
}
func declareAPIAuthKeysRoutes(router *gin.RouterGroup) {

View file

@ -58,7 +58,6 @@ func main() {
var bind = flag.String("bind", ":8081", "Bind port/socket")
var dsn = flag.String("dsn", DSNGenerator(), "DSN to connect to the MySQL server")
var dummyauth = flag.Bool("dummy-auth", false, "If set, allow any authentication credentials")
flag.StringVar(&mainBanner, "banner-message", mainBanner, "Display a message to connected user, at the top of the screen")
flag.StringVar(&DevProxy, "dev", DevProxy, "Proxify traffic to this host for static assets")
flag.StringVar(&baseURL, "baseurl", baseURL, "URL prepended to each URL")
flag.UintVar(&currentPromo, "current-promo", currentPromo, "Year of the current promotion")

View file

@ -1,7 +1,14 @@
{
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": [
"local>iac/renovate-config",
"local>iac/renovate-config//automerge-common"
"lockFileMaintenance": {
"enabled": true,
"automerge": true
},
"packageRules": [
{
"matchPackageNames": ["alpine", "golang.org/x/oauth2", "github.com/aws/aws-sdk-go"],
"automerge": true,
"automergeType": "branch"
}
]
}

View file

@ -21,16 +21,14 @@ import (
)
var (
droneToken = ""
droneConfig *http.Client
droneEndpoint string
testsCallbackToken string
droneToken = ""
droneConfig *http.Client
droneEndpoint string
)
func init() {
flag.StringVar(&droneToken, "drone-token", droneToken, "Token for Drone Oauth")
flag.StringVar(&droneEndpoint, "drone-endpoint", droneEndpoint, "Drone Endpoint")
flag.StringVar(&testsCallbackToken, "tests-callback-token", testsCallbackToken, "Token of the callback token")
}
func initializeDroneOauth() {
@ -115,11 +113,6 @@ func declareAPIAuthRepositoriesRoutes(router *gin.RouterGroup) {
}
}
if uri.Scheme != "ssh" && uri.Scheme != "git+ssh" {
c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"errmsg": "Unrecognized URL scheme. You need to provide a SSH repository URL."})
return
}
if strings.Contains(uri.Host, "epita.fr") {
if !strings.HasPrefix(uri.Path, fmt.Sprintf("/%s/", u.Login)) {
c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"errmsg": "repository URL forbidden"})
@ -132,7 +125,7 @@ func declareAPIAuthRepositoriesRoutes(router *gin.RouterGroup) {
w = work.(*Work)
} else if repository.IdWork > 0 {
var err error
w, err = getWork(repository.IdWork)
w, err = getWork(int(repository.IdWork))
if err != nil {
c.AbortWithStatusJSON(http.StatusNotFound, gin.H{"errmsg": "Unable to find the given work identifier."})
return
@ -194,7 +187,7 @@ func declareAPIAuthRepositoriesRoutes(router *gin.RouterGroup) {
repositoriesRoutes.DELETE("", func(c *gin.Context) {
loggeduser := c.MustGet("LoggedUser").(*User)
repository := c.MustGet("repository").(*Repository)
work, err := getWork(repository.IdWork)
work, err := getWork(int(repository.IdWork))
if err != nil {
c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"errmsg": "Unable to find related work."})
return
@ -226,7 +219,7 @@ func declareAPIAuthRepositoriesRoutes(router *gin.RouterGroup) {
u = loggeduser
}
repo := c.MustGet("repository").(*Repository)
work, err := getWork(repo.IdWork)
work, err := getWork(int(repo.IdWork))
if err != nil {
c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"errmsg": "Unable to find related work."})
return
@ -316,7 +309,7 @@ func declareAPIAuthRepositoriesRoutes(router *gin.RouterGroup) {
u = loggeduser
}
repo := c.MustGet("repository").(*Repository)
work, err := getWork(repo.IdWork)
work, err := getWork(int(repo.IdWork))
if err != nil {
c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"errmsg": "Unable to find related work."})
return
@ -324,42 +317,6 @@ func declareAPIAuthRepositoriesRoutes(router *gin.RouterGroup) {
TriggerTests(c, work, repo, u)
})
repositoriesRoutes.GET("/gradation_status", func(c *gin.Context) {
loggeduser := c.MustGet("LoggedUser").(*User)
if !loggeduser.IsAdmin {
c.AbortWithStatusJSON(http.StatusForbidden, gin.H{"errmsg": "Permission denied."})
return
}
repo := c.MustGet("repository").(*Repository)
slug := strings.Split(repo.TestsRef, "/")
if len(slug) < 3 {
return
}
buildn, err := strconv.ParseInt(slug[2], 10, 32)
if err != nil {
return
}
client := drone.NewClient(droneEndpoint, droneConfig)
build, err := client.Build(slug[0], slug[1], int(buildn))
if err != nil {
log.Println("Unable to communicate with Drone:", err.Error())
c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"errmsg": "Unable to communicate with Drone"})
return
}
c.JSON(http.StatusOK, build)
})
repositoriesRoutes.GET("/traces", func(c *gin.Context) {
repo := c.MustGet("repository").(*Repository)
c.Redirect(http.StatusFound, fmt.Sprintf("%s/%s", droneEndpoint, repo.TestsRef))
})
}
type GitLabWebhook struct {
@ -404,7 +361,7 @@ func declareCallbacksRoutes(router *gin.RouterGroup) {
return
}
work, err := getWork(repo.IdWork)
work, err := getWork(int(repo.IdWork))
if err != nil {
log.Println("Unable to getWork:", err.Error())
c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"errmsg": "Unable to find related work."})
@ -430,7 +387,7 @@ func declareCallbacksRoutes(router *gin.RouterGroup) {
// Allow to use a secret for another tag
if len(repos) > 1 {
for _, r := range repos {
w, err := getWork(r.IdWork)
w, err := getWork(int(r.IdWork))
if err != nil {
log.Println("Unable to getWork:", err.Error())
continue
@ -452,36 +409,6 @@ func declareCallbacksRoutes(router *gin.RouterGroup) {
TriggerTagUpdate(c, work, repo, user, &tmp[2], false)
})
router.POST("/callbacks/tests.json", func(c *gin.Context) {
// Check auth token
if c.GetHeader("X-Authorization") != testsCallbackToken {
c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"errmsg": "Authorization token is invalid"})
return
}
// Get form data
hook := TestsWebhook{}
if err := c.ShouldBindJSON(&hook); err != nil {
c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"errmsg": err.Error()})
return
}
// Retrieve corresponding repository
repo, err := getRepository(hook.RepositoryId)
if err != nil {
log.Printf("Unable to getRepository(%d): %s", hook.RepositoryId, err.Error())
c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"errmsg": "Unable to retrieve repository."})
return
}
err = hook.fetchRepoTests(repo)
if err != nil {
log.Printf("Unable to fetchRepoTests(%d): %s", hook.RepositoryId, err.Error())
c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"errmsg": "Unable to fetch tests results."})
return
}
})
}
func repositoryHandler(c *gin.Context) {
@ -516,7 +443,7 @@ func TriggerTagUpdate(c *gin.Context, work *Work, repo *Repository, u *User, tag
loggeduser := c.MustGet("LoggedUser").(*User)
now := time.Now()
if (loggeduser == nil || !loggeduser.IsAdmin) && (!work.Shown || work.Corrected || work.StartAvailability.After(now) || work.EndAvailability.Add(time.Hour).Before(now)) {
if !loggeduser.IsAdmin && (!work.Shown || work.Corrected || work.StartAvailability.After(now) || work.EndAvailability.Add(time.Hour).Before(now)) {
c.AbortWithStatusJSON(http.StatusForbidden, gin.H{"errmsg": "The submission is closed."})
return
}
@ -602,10 +529,10 @@ func TriggerTests(c *gin.Context, work *Work, repo *Repository, u *User) {
req, _ := s3.New(s).GetObjectRequest(&s3.GetObjectInput{
Bucket: aws.String(s3_bucket),
Key: aws.String(filepath.Join(fmt.Sprintf("%d", work.Id), fmt.Sprintf("rendu-%s.tar.xz", login))),
Key: aws.String(filepath.Join(fmt.Sprintf("%d", work.Id), fmt.Sprintf("rendu-%s.tar.xz", u.Login))),
})
url, err := req.Presign(SharingTime * 20)
url, err := req.Presign(SharingTime)
if err != nil {
log.Println("Unable to create presign URL:", err)
c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"errmsg": "Something goes wrong when creating the presigned URL."})
@ -614,7 +541,6 @@ func TriggerTests(c *gin.Context, work *Work, repo *Repository, u *User) {
env := map[string]string{
"SUBMISSION_URL": repo.URI,
"REPO_ID": fmt.Sprintf("%d", repo.Id),
"META_URL": url,
"LOGIN": login,
"GROUPS": groups,
@ -625,7 +551,7 @@ func TriggerTests(c *gin.Context, work *Work, repo *Repository, u *User) {
result, err := client.BuildCreate(slug[0], slug[1], "", branch, env)
if err != nil {
log.Println("Unable to communicate with Drone:", err.Error())
c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"errmsg": "Unable to communication with the gradation service."})
c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"errmsg": "Unable to communication with the extraction service."})
return
}
@ -638,42 +564,6 @@ func TriggerTests(c *gin.Context, work *Work, repo *Repository, u *User) {
c.JSON(http.StatusOK, repo)
}
func (w *Work) stopTests() error {
repos, err := w.GetRepositories()
if err != nil {
return err
}
client := drone.NewClient(droneEndpoint, droneConfig)
for _, repo := range repos {
slug := strings.Split(repo.TestsRef, "/")
if len(slug) < 3 {
continue
}
buildn, err := strconv.ParseInt(slug[2], 10, 32)
if err != nil {
continue
}
build, err := client.Build(slug[0], slug[1], int(buildn))
if err != nil {
log.Println("Unable to communicate with Drone:", err.Error())
continue
}
if build.Status == "pending" {
err := client.BuildCancel(slug[0], slug[1], int(buildn))
if err != nil {
log.Println("Unable to cancel the build:", err.Error())
continue
}
}
}
return nil
}
type Repository struct {
Id int64 `json:"id"`
IdUser int64 `json:"id_user"`
@ -708,27 +598,6 @@ func (u *User) GetRepositories() (repositories []*Repository, err error) {
}
}
func (w *Work) GetRepositories() (repositories []*Repository, err error) {
if rows, errr := DBQuery("SELECT id_repository, id_user, id_work, uri, secret, last_check, droneref, last_tests, testsref FROM user_work_repositories WHERE id_work=?", w.Id); errr != nil {
return nil, errr
} else {
defer rows.Close()
for rows.Next() {
var repo Repository
if err = rows.Scan(&repo.Id, &repo.IdUser, &repo.IdWork, &repo.URI, &repo.Secret, &repo.LastCheck, &repo.DroneRef, &repo.LastTests, &repo.TestsRef); err != nil {
return
}
repositories = append(repositories, &repo)
}
if err = rows.Err(); err != nil {
return
}
return
}
}
func getRepositoriesByURI(uri string) (repositories []*Repository, err error) {
if rows, errr := DBQuery("SELECT id_repository, id_user, id_work, uri, secret, last_check, droneref, last_tests, testsref FROM user_work_repositories WHERE uri=?", uri); errr != nil {
return nil, errr
@ -762,12 +631,6 @@ func (u *User) getRepository(id int) (r *Repository, err error) {
return
}
func (u *User) getRepositoryByWork(id int64) (r *Repository, err error) {
r = new(Repository)
err = DBQueryRow("SELECT id_repository, id_user, id_work, uri, secret, last_check, droneref, last_tests, testsref FROM user_work_repositories WHERE id_work=? AND id_user=? ORDER BY last_tests DESC LIMIT 1", id, u.Id).Scan(&r.Id, &r.IdUser, &r.IdWork, &r.URI, &r.Secret, &r.LastCheck, &r.DroneRef, &r.LastTests, &r.TestsRef)
return
}
func (u *User) NewRepository(w *Work, uri string) (*Repository, error) {
secret := make([]byte, 24)
_, err := rand.Read(secret)
@ -775,7 +638,7 @@ func (u *User) NewRepository(w *Work, uri string) (*Repository, error) {
return nil, err
}
if res, err := DBExec("INSERT INTO user_work_repositories (id_user, id_work, uri, secret, droneref, testsref) VALUES (?, ?, ?, ?, ?, '')", u.Id, w.Id, uri, secret, ""); err != nil {
if res, err := DBExec("INSERT INTO user_work_repositories (id_user, id_work, uri, secret, droneref) VALUES (?, ?, ?, ?, ?)", u.Id, w.Id, uri, secret, ""); err != nil {
return nil, err
} else if rid, err := res.LastInsertId(); err != nil {
return nil, err

View file

@ -56,7 +56,6 @@ func declareStaticRoutes(router *gin.Engine) {
router.GET("/categories/*_", serveOrReverse("/"))
router.GET("/donnees-personnelles", serveOrReverse("/"))
router.GET("/grades", serveOrReverse("/"))
router.GET("/grades/*_", serveOrReverse("/"))
router.GET("/help", serveOrReverse("/"))
router.GET("/keys", serveOrReverse("/"))
router.GET("/results", serveOrReverse("/"))

View file

@ -17,7 +17,7 @@ import (
"github.com/gin-gonic/gin"
)
const SharingTime = 10 * time.Minute
const SharingTime = 15 * time.Minute
var (
s3_endpoint string

View file

@ -342,7 +342,7 @@ func (s Survey) GetScore(u *User) (score *float64, err error) {
if ok {
score = v
} else {
err = DBQueryRow("SELECT SUM(score)/COUNT(*) FROM student_scores WHERE kind = 'survey' AND id=? AND id_user=?", s.Id, u.Id).Scan(&score)
err = DBQueryRow("SELECT SUM(score)/COUNT(*) FROM student_scores WHERE id_survey=? AND id_user=?", s.Id, u.Id).Scan(&score)
if score != nil {
*score = *score / 5.0
}
@ -355,7 +355,7 @@ func (s Survey) GetScore(u *User) (score *float64, err error) {
}
func (s Survey) GetScores() (scores map[int64]*float64, err error) {
if rows, errr := DBQuery("SELECT id_user, SUM(score)/COUNT(*) FROM student_scores WHERE kind = 'survey' AND id_survey=? GROUP BY id_user", s.Id); errr != nil {
if rows, errr := DBQuery("SELECT id_user, SUM(score)/COUNT(*) FROM student_scores WHERE id_survey=? GROUP BY id_user", s.Id); errr != nil {
return nil, errr
} else {
defer rows.Close()

3831
ui/package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -11,22 +11,21 @@
"format": "prettier --ignore-path .gitignore --write --plugin-search-dir=. ."
},
"devDependencies": {
"@sveltejs/adapter-static": "^3.0.0",
"@sveltejs/kit": "^2.0.0",
"@sveltejs/vite-plugin-svelte": "^3.0.0",
"@typescript-eslint/eslint-plugin": "^7.0.0",
"@typescript-eslint/parser": "^7.0.0",
"@sveltejs/adapter-static": "^2.0.0",
"@sveltejs/kit": "^1.0.0",
"@typescript-eslint/eslint-plugin": "^5.21.0",
"@typescript-eslint/parser": "^5.0.0",
"eslint": "^8.14.0",
"eslint-config-prettier": "^9.0.0",
"eslint-plugin-svelte": "^2.35.0",
"prettier": "^3.0.0",
"prettier-plugin-svelte": "^3.1.2",
"svelte": "^4.0.0",
"svelte-check": "^3.4.3",
"svelte-preprocess": "^5.0.3",
"eslint-config-prettier": "^8.5.0",
"eslint-plugin-svelte3": "^4.0.0",
"prettier": "^2.6.2",
"prettier-plugin-svelte": "^2.7.0",
"svelte": "^3.48.0",
"svelte-check": "^3.0.0",
"svelte-preprocess": "^5.0.0",
"tslib": "^2.4.0",
"typescript": "^5.0.0",
"vite": "^5.0.0"
"typescript": "^4.6.4",
"vite": "^4.0.0"
},
"type": "module",
"dependencies": {

View file

@ -1,14 +0,0 @@
<script>
export let score = 0;
</script>
<span
class="badge"
class:bg-success={score >= 18}
class:bg-info={score < 18 && score >= 15}
class:bg-warning={score < 15 && score >= 9}
class:bg-danger={score < 9}
class:bg-dark={score == "N/A"}
>
{score}
</span>

View file

@ -1,10 +1,8 @@
<script>
import { getCategories } from '$lib/categories';
import { getSurveys } from '$lib/surveys';
import { getUsers, getGrades, getPromos } from '$lib/users';
export let promo = null;
export let category = null;
</script>
{#await getPromos() then promos}
@ -17,24 +15,12 @@
</select>
</div>
{/await}
{#await getCategories() then categories}
<div class="float-end me-2">
<select class="form-select" bind:value={category}>
<option value={null}>toutes</option>
{#each categories as categ (categ.id)}
{#if !promo || categ.promo == promo}
<option value={categ.id}>{categ.label}</option>
{/if}
{/each}
</select>
</div>
{/await}
<h2>
Étudiants {#if promo !== null}{promo}{/if}
<small class="text-muted">Notes</small>
</h2>
{#await getSurveys(true)}
{#await getSurveys()}
<div class="d-flex justify-content-center">
<div class="spinner-border me-2" role="status"></div>
Chargement des questionnaires corrigés&hellip;
@ -52,15 +38,9 @@
<tr>
<th>ID</th>
<th>Login</th>
{#each surveys as survey}
{#if survey.corrected && (!promo || survey.promo == promo) && (!category || survey.id_category == category)}
<th>
{#if survey.kind == "survey"}
<a href="surveys/{survey.id}" style="text-decoration: none">{survey.title}</a>
{:else}
<a href="works/{survey.id}" style="text-decoration: none">{survey.title}</a>
{/if}
</th>
{#each surveys as survey (survey.id)}
{#if survey.corrected && (promo === null || survey.promo == promo)}
<th><a href="surveys/{survey.id}" style="text-decoration: none">{survey.title}</a></th>
{/if}
{/each}
</tr>
@ -77,15 +57,13 @@
</tr>
{:then users}
{#each users as user (user.id)}
{#if !promo || user.promo == promo}
{#if promo === null || user.promo === promo}
<tr>
<td><a href="users/{user.id}" style="text-decoration: none">{user.id}</a></td>
<td><a href="users/{user.login}" style="text-decoration: none">{user.login}</a></td>
{#each surveys as survey}
{#if survey.corrected && (!promo || survey.promo == promo) && (!category || survey.id_category == category)}
<td>
{grades[user.id] && grades[user.id][survey.kind + "." + survey.id]?grades[user.id][survey.kind + "." + survey.id]:""}
</td>
{#each surveys as survey (survey.id)}
{#if survey.corrected && (promo === null || survey.promo == promo)}
<td>{grades[user.id] && grades[user.id][survey.id]?grades[user.id][survey.id]:""}</td>
{/if}
{/each}
</tr>

View file

@ -4,7 +4,6 @@
import { user } from '$lib/stores/user';
import DateFormat from '$lib/components/DateFormat.svelte';
import SurveyBadge from '$lib/components/SurveyBadge.svelte';
import ScoreBadge from '$lib/components/ScoreBadge.svelte';
import SubmissionStatus from '$lib/components/SubmissionStatus.svelte';
import { getCategories } from '$lib/categories';
import { getSurveys } from '$lib/surveys';
@ -145,7 +144,16 @@
{/if}
</span>
{:else}
<ScoreBadge score={score.score} />
<span
class="badge"
class:bg-success={score.score >= 18}
class:bg-info={score.score < 18 && score.score >= 15}
class:bg-warning={score.score < 15 && score.score >= 9}
class:bg-danger={score.score < 9}
class:bg-dark={score.score == "N/A"}
>
{score.score}
</span>
{/if}
{:catch error}
<i class="bi text-warning bi-exclamation-triangle-fill" title={error}></i>

View file

@ -1,15 +0,0 @@
<script>
export let status = null;
</script>
{#if status}
<span
class="badge"
class:bg-success={status == "success"}
class:bg-danger={status == "failure" || status == "killed"}
class:bg-warning={status == "pending" || status == "running"}
class:bg-dark={status != "success" && status != "failure" && status != "killed" && status != "pending" && status != "running"}
>
{status}
</span>
{/if}

View file

@ -1,192 +0,0 @@
<script>
import { createEventDispatcher } from 'svelte';
import ScoreBadge from '$lib/components/ScoreBadge.svelte';
import { ToastsStore } from '$lib/stores/toasts';
const dispatch = createEventDispatcher();
export let work;
let gradesP = null;
let gradationStatus = {};
let stats = {"mean": 0, "min": 999, "max": 0};
let chgrade = {grade: null, modal: null};
$: refresh_grades(work);
function refresh_grades(w) {
gradesP = w.getGrades();
gradesP.then((grades) => {
if (grades.length <= 0) return;
let sum = 0;
for (const grade of grades) {
if (!gradationStatus[grade.id])
gradationStatus[grade.id] = grade.gradationStatus();
sum += grade.score;
if (stats.min > grade.score && grade.comment != "- Non rendu -") stats.min = grade.score;
if (stats.max < grade.score) stats.max = grade.score;
}
stats.mean = sum / grades.length;
});
}
async function addMissingStudents(w) {
await w.addMissingGrades();
refresh_grades(w);
}
</script>
<div class="d-flex justify-content-between align-items-center">
<h3 class="mt-3">
Notes
<small class="text-muted">
{#if stats.mean > 0}(moyenne&nbsp;: {Math.round(stats.mean*100)/100}, min&nbsp;: {stats.min}, max&nbsp;: {stats.max}){/if}
</small>
</h3>
<div>
<button
class="btn btn-outline-primary"
title="Afficher le résumé par étapes"
on:click={() => dispatch("switch_steps")}
>
<i class="bi bi-bar-chart-steps"></i>
</button>
<button
class="btn btn-outline-info"
title="Ajouter les étudiants manquant"
on:click={() => addMissingStudents(work)}
>
<i class="bi bi-people"></i>
</button>
<button
class="btn btn-light"
title="Rafraîchir l'affichage des notes"
on:click={() => refresh_grades(work)}
>
<i class="bi bi-arrow-clockwise"></i>
</button>
</div>
</div>
<div class="card mt-3 mb-5">
{#await gradesP}
<div class="text-center my-5">
<div class="spinner-border text-primary mx-3" role="status"></div>
<span>Chargement des notes &hellip;</span>
</div>
{:then grades}
<table class="table table-hover table-striped table-sm mb-0">
<thead>
<tr>
<th>Login</th>
<th>Note</th>
<th>Commentaire</th>
<th>Date de la note</th>
</tr>
</thead>
<tbody>
{#if !grades}
<div class="text-center">
Aucune note n'a encore été envoyée pour ce travail.
</div>
{:else}
{#each grades as grade, gid (grade.id)}
<tr>
<td>
<a href="users/{grade.id_user}">{grade.login}</a>
</td>
<td><ScoreBadge score={grade.score} /></td>
<td>{#if grade.comment}{grade.comment}{:else}-{/if}</td>
<td>{grade.date}</td>
<td>
<a
href="/api/users/{grade.id_user}/works/{work.id}/grades/{grade.id}/traces"
target="_blank"
class="btn btn-sm btn-outline-info mr-1"
title="Voir le détail de la notation"
>
<i class="bi bi-list-check"></i>
</a>
<a
href="/api/users/{grade.id_user}/works/{work.id}/grades/{grade.id}/forge"
target="_blank"
class="btn btn-sm btn-outline-primary mr-1"
title="Voir le contenu du dépôt lié"
>
<i class="bi bi-git"></i>
</a>
{#if gradationStatus[grade.id]}
{#await gradationStatus[grade.id]}
<button
class="btn btn-sm btn-outline-success mr-1"
title="Relancer la notation"
on:click={() => { grade.redoGradation().then(() => gradationStatus[grade.id] = grade.gradationStatus()); }}
>
<div class="spinner-border spinner-border-sm" role="status"></div>
</button>
{:then status}
<button
class="btn btn-sm mr-1"
class:btn-success={status.status == "success"}
class:btn-danger={status.status == "failure"}
class:btn-outline-danger={status.status == "killed"}
class:btn-outline-warning={status.status == "pending" || status.status == "running"}
title="Relancer la notation"
on:click={() => { grade.redoGradation(); gradationStatus[grade.id] = null; }}
>
<i class="bi bi-arrow-clockwise"></i>
</button>
{/await}
{/if}
<button
class="btn btn-sm btn-primary mr-1"
title="Changer la note"
on:click={() => { chgrade = { grade, modal: new bootstrap.Modal(document.getElementById('chgradeModal'))}; chgrade.modal.show(); }}
>
<i class="bi bi-pencil"></i>
</button>
<button
class="btn btn-sm btn-danger mr-1"
title="Supprimer la note"
on:click={() => { grade.delete().then(() => refresh_grades(work)); }}
>
<i class="bi bi-trash"></i>
</button>
</td>
</tr>
{/each}
{/if}
</tbody>
</table>
{/await}
</div>
<div class="modal fade" tabindex="-1" id="chgradeModal">
<div class="modal-dialog">
<form class="modal-content" on:submit|preventDefault={() => {chgrade.modal.hide(); try { chgrade.grade.save().then(() => refresh_grades(work)); } catch(err) { ToastsStore.addToast({color: "danger", title: "Impossible de changer la note", msg: err}) };}}>
<div class="modal-header">
<h5 class="modal-title">Changer la note {#if chgrade.grade}de {chgrade.grade.login}{/if}</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
{#if chgrade.grade}
<div class="form-group row mb-2">
<label class="col-2 col-form-label" for="new-grade">Note</label>
<!-- svelte-ignore a11y-autofocus -->
<input type="number" class="form-control col" id="new-grade" autofocus placeholder="15" bind:value={chgrade.grade.score}>
</div>
<div class="form-group row mb-2">
<label class="col-2 col-form-label" for="new-comment">Commentaire</label>
<input class="form-control col" id="new-comment" bind:value={chgrade.grade.comment}>
</div>
{/if}
</div>
<div class="modal-footer">
<button type="submit" class="btn btn-primary">
Changer la note
</button>
</div>
</form>
</div>
</div>

View file

@ -1,214 +0,0 @@
<script>
import { createEventDispatcher } from 'svelte';
import ScoreBadge from '$lib/components/ScoreBadge.svelte';
const dispatch = createEventDispatcher();
export let work;
let gradesP = null;
let grade_idx = {};
let gradationStatus = {};
let stats = [];
$: refresh_grades(work);
function refresh_grades(w) {
gradesP = w.getGrades();
gradesP.then((grades) => {
if (grades.length <= 0) return;
for (const grade of grades) {
grade_idx[grade.id] = grade;
if (!gradationStatus[grade.id]) {
gradationStatus[grade.id] = grade.gradationStatus();
gradationStatus[grade.id].then((status) => {
for (const istage in status.stages) {
const stage = status.stages[istage];
if (stats.length <= istage) {
stats.push({
arch: stage.arch,
name: stage.name,
number: stage.number,
status: [],
steps: [],
});
}
stats[istage].status.push(stage.status);
for (const istep in stage.steps) {
const step = stage.steps[istep];
if (stats[istage].steps.length <= istep) {
stats[istage].steps.push({
name: step.name,
number: step.number,
status: [],
});
}
stats[istage].steps[istep].status.push(step.status);
}
}
stats = stats;
});
}
}
});
}
let view_step = null;
</script>
<div class="d-flex justify-content-between align-items-center">
<h3 class="mt-3">
Réussite des étapes
</h3>
<div>
<button
class="btn btn-primary"
title="Afficher le résumé par étapes"
on:click={() => dispatch("switch_steps")}
>
<i class="bi bi-bar-chart-steps"></i>
</button>
<button
class="btn btn-light"
title="Rafraîchir l'affichage des notes"
on:click={() => refresh_grades(work)}
>
<i class="bi bi-arrow-clockwise"></i>
</button>
</div>
</div>
{#each stats as stage, istage}
<h5>
{stage.name}
<small>{stage.arch}</small>
</h5>
<div class="row row-cols-5">
{#each stage.steps as step, istep}
<div class="col">
<div class="card mb-3">
<div class="card-body fw-bolder text-truncate" title={step.name}>
{step.number}. {step.name}
</div>
<div
class="card-footer text-center"
class:bg-success={step.status.filter((e) => e == "success").length/step.status.length > 0.5}
on:click={() => view_step = {istage, istep, status: "success"}}
>
<i class="bi bi-check me-2 fw-bolder"></i>
{step.status.filter((e) => e == "success").length}
({Math.trunc(step.status.filter((e) => e == "success").length*100/step.status.length)}&nbsp;%)
</div>
<div
class="card-footer text-center"
class:bg-danger={step.status.filter((e) => e == "failure").length/step.status.length >= 0.5}
on:click={() => view_step = {istage, istep, status: "failure"}}
>
<i class="bi bi-x me-2 fw-bolder"></i>
{step.status.filter((e) => e == "failure").length}
({Math.trunc(step.status.filter((e) => e == "failure").length*100/step.status.length)}&nbsp;%)
</div>
{#if step.status.filter((e) => e == "skipped").length > 0}
<div
class="card-footer text-center"
class:fw-bold={step.status.filter((e) => e == "skipped").length/step.status.length >= 0.5}
on:click={() => view_step = {istage, istep, status: "skipped"}}
>
<i class="bi bi-skip-end me-2 fw-bolder"></i>
{step.status.filter((e) => e == "skipped").length}
({Math.trunc(step.status.filter((e) => e == "skipped").length*100/step.status.length)}&nbsp;%)
</div>
{/if}
</div>
</div>
{/each}
</div>
{/each}
{#if view_step}
<h3>
Étudiants correspondant
<small class="text-muted">
{"{"}
{stats[view_step.istage].name}
<i class="bi bi-arrow-right"></i>
<em>{stats[view_step.istage].steps[view_step.istep].name}</em>
"{view_step.status}"
{"}"}
</small>
</h3>
<div class="row row-cols-6">
{#each Object.keys(gradationStatus) as gsi}
{#await gradationStatus[gsi] then gs}
{#if gs.stages[view_step.istage] && gs.stages[view_step.istage].steps[view_step.istep] && gs.stages[view_step.istage].steps[view_step.istep].status == view_step.status}
<div class="col">
<div class="card mb-3">
<div
class="card-header text-monospace text-truncate"
title={grade_idx[gsi].login}
>
<a href="/users/{grade_idx[gsi].id_user}">
{grade_idx[gsi].login}
</a>
</div>
<ul class="list-group list-group-flush">
{#each gs.stages[view_step.istage].steps as step}
<li
class="list-group-item text-truncate p-2"
class:bg-success={step.status == "success"}
class:bg-light={step.status == "skipped"}
class:bg-danger={step.status == "failure"}
class:bg-warning={step.status == "pending" || step.status == "running"}
class:bg-info={step.status == "killed"}
>
<a
href="/api/users/{grade_idx[gsi].id_user}/works/{work.id}/grades/{grade_idx[gsi].id}/traces/{gs.stages[view_step.istage].number}/{step.number}"
target="_blank"
title="Voir le détail de cette étape"
>
{step.number}.
</a>
{step.name}
</li>
{/each}
</ul>
<div
class="card-footer d-flex justify-content-around align-items-center px-0"
>
<ScoreBadge score={grade_idx[gsi].score} />
<a
href="/api/users/{grade_idx[gsi].id_user}/works/{work.id}/grades/{grade_idx[gsi].id}/traces"
target="_blank"
class="btn btn-sm btn-outline-info"
title="Voir le détail de la notation"
>
<i class="bi bi-list-check"></i>
</a>
<a
href="/api/users/{grade_idx[gsi].id_user}/works/{work.id}/grades/{grade_idx[gsi].id}/forge"
target="_blank"
class="btn btn-sm btn-outline-primary"
title="Voir le contenu du dépôt lié"
>
<i class="bi bi-git"></i>
</a>
<button
class="btn btn-sm btn-outline-success"
title="Relancer la notation"
on:click={() => { grade_idx[gsi].redoGradation(); gradationStatus[gsi] = null; }}
>
<i class="bi bi-arrow-clockwise"></i>
</button>
</div>
</div>
</div>
{/if}
{/await}
{/each}
</div>
{/if}

View file

@ -1,39 +0,0 @@
<script>
import { user } from '$lib/stores/user';
import DateFormat from '$lib/components/DateFormat.svelte';
import SubmissionStatus from '$lib/components/SubmissionStatus.svelte';
export let work;
export let my_submission;
</script>
<dl style="columns: 3">
<dt>Date de début</dt>
<dd><DateFormat date={new Date(work.start_availability)} dateStyle="medium" timeStyle="medium" /></dd>
<dt>Date de fin</dt>
<dd><DateFormat date={new Date(work.end_availability)} dateStyle="medium" timeStyle="medium" /></dd>
{#if work.submission_url != "-"}
<dt>Rendu&nbsp;?</dt>
<dd>
{#if work.submission_url}
<SubmissionStatus work={w} user={$user} />
{:else}
{#await my_submission}
<div class="spinner-grow spinner-grow-sm mx-1" role="status"></div>
{:then submission}
<i
class="bi bi-check-circle text-success"
title="Oui !"
></i>
<DateFormat date={new Date(submission.date)} dateStyle="medium" timeStyle="medium" />
{:catch}
<i
class="bi bi-x-circle text-danger"
title="Pas de rendu trouvé"
></i>
Non
{/await}
{/if}
</dd>
{/if}
</dl>

View file

@ -160,7 +160,7 @@
</div>
{:then rrepos}
<select id="repolist" class="form-select col" disabled={readonly} bind:value={repo_used.uri}>
{#each rrepos as r (r.ssh_url_to_repo)}
{#each rrepos as r (r.Id)}
<option value={r.ssh_url_to_repo}>{r.path_with_namespace}</option>
{/each}
</select>

View file

@ -1,70 +0,0 @@
export class Grade {
constructor(res) {
if (res) {
this.update(res);
}
}
update({ id, login, id_user, id_work, date, score, comment }) {
this.id = id;
this.login = login;
this.id_user = id_user;
this.id_work = id_work;
this.date = date;
this.score = score;
this.comment = comment;
}
async save() {
const res = await fetch(`api/works/${this.id_work}/grades/${this.id}`, {
method: 'PUT',
headers: {'Accept': 'application/json'},
body: JSON.stringify(this),
});
if (res.status == 200) {
const data = await res.json()
this.update(data);
return data;
} else {
throw new Error((await res.json()).errmsg);
}
}
async delete() {
if (this.id) {
const res = await fetch(`api/works/${this.id_work}/grades/${this.id}`, {
method: 'DELETE',
headers: {'Accept': 'application/json'},
});
if (res.status == 200) {
return true;
} else {
throw new Error((await res.json()).errmsg);
}
}
}
async redoGradation() {
const res = await fetch(this.id_user?`api/users/${this.id_user}/works/${this.id_work}/grades/${this.id}/traces`:`api/works/${this.id_work}/grades/${this.id}/traces`, {
method: 'POST',
headers: {'Accept': 'application/json'},
});
if (res.status == 200) {
return await res.json();
} else {
throw new Error((await res.json()).errmsg);
}
}
async gradationStatus() {
const res = await fetch(this.id_user?`api/users/${this.id_user}/works/${this.id_work}/grades/${this.id}/status`:`api/works/${this.id_work}/grades/${this.id}/status`, {
method: 'GET',
headers: {'Accept': 'application/json'},
});
if (res.status == 200) {
return await res.json();
} else {
throw new Error((await res.json()).errmsg);
}
}
}

View file

@ -76,30 +76,6 @@ export class WorkRepository {
}
}
async runGradation() {
const res = await fetch(this.id_work?`api/works/${this.id_work}/repositories/${this.id}/gradation`:`api/repositories/${this.id}/gradation`, {
method: 'POST',
headers: {'Accept': 'application/json'},
});
if (res.status == 200) {
return await res.json();
} else {
throw new Error((await res.json()).errmsg);
}
}
async gradationStatus() {
const res = await fetch(this.id_work?`api/works/${this.id_work}/repositories/${this.id}/gradation_status`:`api/repositories/${this.id}/gradation_status`, {
method: 'GET',
headers: {'Accept': 'application/json'},
});
if (res.status == 200) {
return await res.json();
} else {
throw new Error((await res.json()).errmsg);
}
}
async save(user) {
let url = this.id?`repositories/${this.id}`:'repositories';

View file

@ -19,18 +19,6 @@ export async function getUsers(promo, group) {
}
}
export async function anonOldAccounts() {
const res = await fetch('api/users', {
method: 'PATCH',
headers: {'Accept': 'application/json'},
});
if (res.status == 200) {
return await res.json()
} else {
throw new Error((await res.json()).errmsg);
}
}
export class User {
constructor(res) {
if (res) {

View file

@ -1,5 +1,3 @@
import { Grade } from '$lib/grades';
export class Work {
constructor(res) {
this.kind = "w";
@ -95,32 +93,6 @@ export class Work {
}
}
async stopTests() {
if (this.id) {
const res = await fetch(`api/works/${this.id}/tests`, {
method: 'DELETE',
headers: {'Accept': 'application/json'},
});
if (res.status == 200) {
return true;
} else {
throw new Error((await res.json()).errmsg);
}
}
}
async addMissingGrades() {
const res = await fetch(`api/works/${this.id}/grades`, {
method: 'PATCH',
headers: {'Accept': 'application/json'},
});
if (res.status == 200) {
return (await res.json()).map((g) => new Grade(g));
} else {
throw new Error((await res.json()).errmsg);
}
}
async getSubmission(uid) {
const res = await fetch(uid?`api/users/${uid}/works/${this.id}/submission`:`api/works/${this.id}/submission`, {
headers: {'Accept': 'application/json'}
@ -132,25 +104,25 @@ export class Work {
}
}
async getMyTraces() {
const res = await fetch(`api/works/${this.id}/traces`, {
method: 'GET',
headers: {'Accept': 'application/json'},
});
if (res.status == 200) {
return await res.json();
} else {
throw new Error((await res.json()).errmsg);
}
}
async getGrades() {
const res = await fetch(`api/works/${this.id}/grades`, {
method: 'GET',
headers: {'Accept': 'application/json'},
});
if (res.status == 200) {
return (await res.json()).map((g) => new Grade(g));
return await res.json();
} else {
throw new Error((await res.json()).errmsg);
}
}
async runGradation(uid) {
const res = await fetch(uid?`api/users/${uid}/works/${this.id}/gradation`:`api/works/${this.id}/gradation`, {
method: 'POST',
headers: {'Accept': 'application/json'},
});
if (res.status == 200) {
return await res.json();
} else {
throw new Error((await res.json()).errmsg);
}

View file

@ -29,11 +29,6 @@
<title>ЕРІТА: MCQ and others courses related stuff</title>
</svelte:head>
{#if $user && $user.banner}
<div class="bg-danger text-white text-center py-1 fw-bolder">
{$user.banner}
</div>
{/if}
{#if isSRS}
<div style="position: fixed; bottom: 20px; right: 20px; z-index: -1; background-image: url('img/srstamps.png'); background-size: cover; width: 125px; height: 125px;"></div>
{/if}

View file

@ -1,5 +1,5 @@
export async function load({ params }) {
return {
promo: parseInt(params.promo),
promo: params.promo,
};
}

View file

@ -1,6 +0,0 @@
export async function load({ params }) {
return {
promo: parseInt(params.promo),
cid: parseInt(params.cid),
};
}

View file

@ -1,7 +0,0 @@
<script>
import StudentGrades from '$lib/components/StudentGrades.svelte';
export let data;
</script>
<StudentGrades promo={data.promo} category={data.cid} />

View file

@ -44,7 +44,7 @@
<p>
Si tu souhaites me parler d'une situation qui t'a troublé&middot;e, d'un problème que tu rencontres ou me faire une remarque,
n'hésite pas à venir me voir lors d'un cours, par exemple à la pause ou à la fin{#if $user}&nbsp;;
je suis aussi joignable <a href="mailto:nemunaire@nemunai.re" data-umami-event="need-help-mail">par e-mail</a> ou bien <a href="https://matrix.to/#/@nemunaire:nemunai.re" data-umami-event="need-help-matrix">sur Matrix</a> ou Teams{/if}.
je suis aussi joignable <a href="mailto:nemunaire@nemunai.re" class="umami--click--need-help-mail">par e-mail</a> ou bien <a href="https://matrix.to/#/@nemunaire:nemunai.re" class="umami--click--need-help-matrix">sur Matrix</a> ou Teams{/if}.
</p>
{#if $user}
@ -52,8 +52,7 @@
Si tu souhaites juste avoir un peu plus d'attention, soit parce que tu te sens à l'écart, en difficulté ou autre&nbsp;:
<button
type="button"
class="btn btn-sm btn-primary"
data-umami-event="need-help"
class="btn btn-sm btn-primary umami--click--need-help"
on:click={needhelp}
>
Clique ce bouton

View file

@ -8,13 +8,29 @@
let surveyP = null;
$: surveyP = getSharedSurvey(data.idsurvey, data.secret);
let max_responses = 0;
function calc_responses(responses) {
const len = responses.length;
if (max_responses < len) {
max_responses = len;
}
return len;
}
</script>
{#await surveyP then survey}
<div class="d-flex align-items-center">
<h2>
{survey.title}
<small class="text-muted">Réponses</small>
<small class="text-muted">
Réponses
{#if max_responses > 0}
({max_responses})
{/if}
</small>
</h2>
<SurveyBadge class="ms-2" {survey} />
</div>
@ -26,10 +42,17 @@
</div>
{:then questions}
{#each questions as question (question.id)}
<h3>{question.title}</h3>
{#if question.kind == "text" || (data.exportview_list && question.kind.indexOf("list") == 0)}
{#await question.getResponses(data.secret) then responses}
{#each responses as response (response.id)}
{#await question.getResponses(data.secret)}
<h3>{question.title}</h3>
{:then responses}
<h3>
{question.title}
<small class="text-muted float-end">
{calc_responses(responses)} réponses
</small>
</h3>
{#each calc_responses(responses) as response (response.id)}
<div class="card mb-2">
<div class="card-body">
<p class="card-text" style:white-space="pre-line">

View file

@ -47,7 +47,6 @@
let responses = {};
let corrected = false;
let next_corrected = false;
let with_stats = false;
let timer = 20;
let timer_end = null;
let timer_remain = 0;
@ -309,6 +308,7 @@
Réponses
</th>
<th>
Actions
<button
type="button"
class="btn btn-sm btn-primary"
@ -330,13 +330,11 @@
</button>
<button
type="button"
class="btn btn-sm"
class:btn-outline-success={!with_stats}
class:btn-success={with_stats}
on:click={() => { with_stats = !with_stats } }
title="La prochaine correction sera affichée avec les statistiques"
class="btn btn-sm btn-info"
on:click={() => { edit_question = new Question({ id_survey: survey.id }) } }
title="Ajouter une question"
>
<i class="bi bi-bar-chart-fill"></i>
<i class="bi bi-plus"></i>
</button>
<button
type="button"
@ -346,14 +344,6 @@
>
<i class="bi bi-bandaid-fill"></i>
</button>
<button
type="button"
class="btn btn-sm btn-info mt-1"
on:click={() => { edit_question = new Question({ id_survey: survey.id }) } }
title="Ajouter une question"
>
<i class="bi bi-plus"></i>
</button>
</th>
</tr>
</thead>
@ -384,7 +374,7 @@
class:btn-primary={!next_corrected}
class:btn-success={next_corrected}
disabled={(question.id === current_question && next_corrected == corrected) || !ws_up}
on:click={() => { ws.send('{"action":"new_question", "corrected": ' + next_corrected + (with_stats?', "stats": {}':'') + ', "timer": 0, "question":' + question.id + '}')} }
on:click={() => { ws.send('{"action":"new_question", "corrected": ' + next_corrected + ', "timer": 0, "question":' + question.id + '}')} }
>
<i class="bi bi-play-fill"></i>
</button>
@ -392,7 +382,7 @@
type="button"
class="btn btn-sm btn-danger"
disabled={question.id === current_question || !ws_up}
on:click={() => { ws.send('{"action":"new_question", "corrected": ' + next_corrected + (with_stats?', "stats": {}':'') + ', "timer": ' + timer * 1000 + ',"question":' + question.id + '}')} }
on:click={() => { ws.send('{"action":"new_question", "corrected": ' + next_corrected + ', "timer": ' + timer * 1000 + ',"question":' + question.id + '}')} }
>
<i class="bi bi-stopwatch-fill"></i>
</button>

View file

@ -3,9 +3,8 @@
import { user } from '$lib/stores/user';
import { ToastsStore } from '$lib/stores/toasts';
import CorrectionPieChart from '$lib/components/CorrectionPieChart.svelte';
import QuestionForm from '$lib/components/QuestionForm.svelte';
import SurveyBadge from '$lib/components/SurveyBadge.svelte';
import QuestionForm from '$lib/components/QuestionForm.svelte';
import { getQuestion } from '$lib/questions';
export let data;
@ -89,12 +88,7 @@
if (data.action && data.action == "new_question") {
show_question = data.question;
survey.corrected = data.corrected;
if (data.stats) {
stats = data.stats;
} else {
stats = null;
}
if(data.corrected) {
if (data.corrected) {
corrections = data.corrections;
} else {
corrections = null;
@ -174,7 +168,6 @@
}
let corrections = null;
let stats = null;
</script>
<div
@ -214,13 +207,6 @@
<span>Chargement d'une nouvelle question &hellip;</span>
</div>
{:then question}
{#if stats != null}
<CorrectionPieChart
{question}
proposals={true}
data={stats}
/>
{/if}
<QuestionForm
{survey}
{question}
@ -235,7 +221,7 @@
</div>
{/if}
</QuestionForm>
{#if !survey.corrected && question.kind != 'mcq' && question.kind != 'ucq' && question.kind != 'none'}
{#if question.kind != 'mcq' && question.kind != 'ucq' && question.kind != 'none'}
<button
class="btn btn-primary"
>

View file

@ -3,45 +3,28 @@
import { user } from '$lib/stores/user';
import DateFormat from '$lib/components/DateFormat.svelte';
import { anonOldAccounts, getUsers, getPromos } from '$lib/users';
import { getUsers, getPromos } from '$lib/users';
function showUser(user) {
goto(`users/${user.id}`)
}
let usersP = getUsers();
function refreshUsers() {
usersP = getUsers();
}
function askAnon() {
if (confirm("Ceci va anonymiser tous les comptes des étudiants avant " + ($user.current_promo - 1) + ". Voulez-vous continuer ?"))
anonOldAccounts().then(refreshUsers);
}
let filterPromo = "";
</script>
{#if $user && $user.is_admin}
<button
class="btn btn-danger ms-2 float-end"
on:click={askAnon}
>
<i class="bi bi-back"></i>
Anonymiser vieux comptes
</button>
<a
href="auth/gitlabcri?next={window.location.pathname}"
class="btn btn-primary float-end ms-2"
class="btn btn-primary float-end"
>
<i class="bi bi-link-45deg"></i>
OAuth GitLab
</a>
<a href="grades/{filterPromo}" class="btn btn-success ms-2 float-end" title="Notes">
<a href="grades" class="btn btn-success me-1 float-end" title="Notes">
<i class="bi bi-files"></i>
</a>
{#await getPromos() then promos}
<div class="float-end ms-2">
<div class="float-end me-2">
<select class="form-select" bind:value={filterPromo}>
<option value="">-</option>
{#each promos as promo, pid (pid)}
@ -55,7 +38,7 @@
Étudiants
</h2>
{#await usersP}
{#await getUsers()}
<div class="text-center">
<div class="spinner-border text-danger mx-3" role="status"></div>
<span>Chargement des &eacute;tudiants &hellip;</span>

View file

@ -3,7 +3,6 @@
import { user } from '$lib/stores/user';
import DateFormat from '$lib/components/DateFormat.svelte';
import ScoreBadge from '$lib/components/ScoreBadge.svelte';
import SurveyBadge from '$lib/components/SurveyBadge.svelte';
import SubmissionStatus from '$lib/components/SubmissionStatus.svelte';
import { getCategories } from '$lib/categories';
@ -121,7 +120,16 @@
{#await getScore(work)}
<div class="spinner-border spinner-border-sm" role="status"></div>
{:then score}
<ScoreBadge score={score.score} />
<span
class="badge"
class:bg-success={score.score >= 18}
class:bg-info={score.score < 18 && score.score >= 15}
class:bg-warning={score.score < 15 && score.score >= 9}
class:bg-danger={score.score < 9}
class:bg-dark={score.score == "N/A"}
>
{score.score}
</span>
{:catch error}
<i class="bi text-warning bi-exclamation-triangle-fill" title={error}></i>
{/await}

View file

@ -5,11 +5,7 @@
import DateFormat from '$lib/components/DateFormat.svelte';
import SubmissionStatus from '$lib/components/SubmissionStatus.svelte';
import SurveyBadge from '$lib/components/SurveyBadge.svelte';
import TraceStatus from '$lib/components/TraceStatus.svelte';
import WorkAdmin from '$lib/components/WorkAdmin.svelte';
import WorkGrades from '$lib/components/WorkGrades.svelte';
import WorkGradesSteps from '$lib/components/WorkGradesSteps.svelte';
import WorkHeader from '$lib/components/WorkHeader.svelte';
import WorkRepository from '$lib/components/WorkRepository.svelte';
import { getScore } from '$lib/users';
@ -17,7 +13,6 @@
let edit = false;
let my_submission = null;
let warn_already_used = false;
let showSteps = false;
let w = null;
$: w = data.work;
@ -40,10 +35,8 @@
<SurveyBadge class="ms-2" survey={w} />
</div>
{#if $user && $user.is_admin && (edit || w.endAvailability() < Date.now())}
{#if edit}
<WorkAdmin work={w} on:saved={() => edit = false} />
{/if}
{#if $user && $user.is_admin && edit}
<WorkAdmin work={w} on:saved={() => edit = false} />
{#if w.description}
<hr>
@ -51,24 +44,80 @@
{/if}
<hr>
{#if showSteps}
<WorkGradesSteps
work={w}
on:switch_steps={() => showSteps = false}
/>
{:else}
<WorkGrades
work={w}
on:switch_steps={() => showSteps = true}
/>
{/if}
<h3 class="mt-3">Notes</h3>
<div class="card mt-3 mb-5">
{#await w.getGrades()}
<div class="text-center">
<div class="spinner-border text-primary mx-3" role="status"></div>
<span>Chargement des notes &hellip;</span>
</div>
{:then grades}
<table class="table table-hover table-striped mb-0">
<thead>
<tr>
<th>Login</th>
<th>Note</th>
<th>Commentaire</th>
<th>Date de la note</th>
</tr>
</thead>
<tbody>
{#if !grades}
<div class="text-center">
Aucune note n'a encore été envoyée pour ce travail.
</div>
{:else}
{#each grades as grade, gid (grade.id)}
<tr>
<td>
<a href="users/{grade.id_user}">{grade.login}</a>
</td>
<td>{grade.score}</td>
<td>{#if grade.comment}{grade.comment}{:else}-{/if}</td>
<td>{grade.date}</td>
</tr>
{/each}
{/if}
</tbody>
</table>
{/await}
</div>
{:else if (!$user || !$user.is_admin) && new Date(w.start_availability) > new Date()}
<div class="alert alert-warning">
<i class="bi bi-stopwatch-fill"></i>
<strong>Ce travail n'est pas encore ouvert.</strong> Revenez plus tard&nbsp;!
</div>
{:else}
<WorkHeader work={w} {my_submission} />
<dl style="columns: 3">
<dt>Date de début</dt>
<dd><DateFormat date={new Date(w.start_availability)} dateStyle="medium" timeStyle="medium" /></dd>
<dt>Date de fin</dt>
<dd><DateFormat date={new Date(w.end_availability)} dateStyle="medium" timeStyle="medium" /></dd>
{#if w.submission_url != "-"}
<dt>Rendu&nbsp;?</dt>
<dd>
{#if w.submission_url}
<SubmissionStatus work={w} user={$user} />
{:else}
{#await my_submission}
<div class="spinner-grow spinner-grow-sm mx-1" role="status"></div>
{:then submission}
<i
class="bi bi-check-circle text-success"
title="Oui !"
></i>
<DateFormat date={new Date(submission.date)} dateStyle="medium" timeStyle="medium" />
{:catch}
<i
class="bi bi-x-circle text-danger"
title="Pas de rendu trouvé"
></i>
Non
{/await}
{/if}
</dd>
{/if}
</dl>
{#if w.description}
<hr>
{@html w.description}
@ -98,9 +147,7 @@
{/if}
{#if w.submission_url != "-"}
{#if !w.corrected}
<WorkRepository class="mb-3" readonly={w.corrected || new Date(w.end_availability) <= new Date()} work={w} on:update_submission={() => refresh_submission(w)} bind:already_used={warn_already_used} />
{/if}
<WorkRepository class="mb-3" readonly={w.corrected || new Date(w.end_availability) <= new Date()} work={w} on:update_submission={() => refresh_submission(w)} bind:already_used={warn_already_used} />
<div class="card mb-3">
<div class="card-body d-flex justify-content-between">
<div>
@ -111,7 +158,7 @@
{#await my_submission}
<div class="spinner-grow spinner-grow-sm mx-1" role="status"></div>
{:then submission}
<strong><a href="/api/works/{w.id}/forge/-/tree/{submission.commit}" target="_blank">{submission.commit}</a> (<a href="/api/works/{w.id}/forge/-/tree/{submission.tag}" target="_blank">{submission.tag}</a>)</strong> (taille&nbsp;: {submission.size}&nbsp;o, date&nbsp;: <DateFormat date={new Date(submission.date)} dateStyle="medium" timeStyle="medium" />)
<strong>{submission.commit} ({submission.tag})</strong> (taille&nbsp;: {submission.size}&nbsp;o, date&nbsp;: <DateFormat date={new Date(submission.date)} dateStyle="medium" timeStyle="medium" />)
{:catch}
<strong>-</strong>
{/await}
@ -145,53 +192,7 @@
<i class="bi bi-clipboard2-check-fill text-info me-1"></i>
<strong>Note finale&nbsp;:</strong> <span title="Établie le {grade.date}">{grade.score}</span> {#if grade.comment}&ndash; {grade.comment}{/if}
</div>
{#await w.getMyTraces()}
<div class="spinner-border spinner-border-sm" role="status"></div>
{:then traces}
{#each traces as trace}
<div class="d-flex align-items-center gap-2">
<h4>{trace.title}</h4>
<TraceStatus status={trace.status} />
</div>
{#if trace.items}
<ul class="list-group mb-3">
{#each trace.items as item}
<li class="list-group-item">
<i
class="me-1 bi"
class:bi-check-lg={item.status == "success"}
class:bi-x-lg={item.status == "failure"}
class:bi-exclamation-lg={item.status == "warning"}
class:bi-question-lg={item.status != "success" && item.status != "failure" && item.status != "warning"}
></i>
<strong
class:text-success={item.status == "success"}
class:text-danger={item.status == "failure"}
class:text-warning={item.status == "warning"}
class:text-info={item.status != "success" && item.status != "failure" && item.status != "warning"}
>
{item.title}
</strong>
{#if item.msg}
{item.msg}
{/if}
</li>
{/each}
</ul>
{/if}
{#if trace.logs}
<div class="bg-dark text-light px-2 pt-2">
<pre class="pb-2">{#each trace.logs as l (l.pos)}{l.out}{/each}</pre>
</div>
{/if}
{/each}
{:catch error}
<div class="alert alert-danger">
<i class="bi text-warning bi-exclamation-triangle-fill" title={error}></i>
<strong>{error.message}</strong>
</div>
{/await}
{:catch error}
{:catch error}
<div class="alert alert-danger">
<i class="bi text-warning bi-exclamation-triangle-fill" title={error}></i>
<strong>{error.message}</strong>

View file

@ -32,23 +32,6 @@
repositoriesP[userid] = getRepositories(wid, userid);
}
let gradation_preflight = false;
async function runGradations() {
gradation_preflight = true;
for (const user of await usersP) {
if (repositoriesP[user.id] && show_dl_btn[user.id]) {
try {
for (const repo of await repositoriesP[user.id]) {
repo.runGradation();
}
} catch (err) {
ToastsStore.addToast({color: "danger", title: "Impossible de lancer la notation de " + user.login, msg: err})
}
}
}
gradation_preflight = false;
}
let nb_rendus = 0;
let nb_users = 0;
@ -57,36 +40,13 @@
let search_repo_for = {repo: null, user: null};
</script>
<div class="d-flex justify-content-between">
<div class="d-flex align-items-center">
<h2>
<a href="works/{w.id}" class="text-muted" style="text-decoration: none">&lt;</a>
{w.title}
<small class="text-muted">Rendus {Math.trunc(nb_rendus/nb_users*100)}&nbsp;% ({nb_rendus}/{nb_users})</small>
</h2>
<SurveyBadge class="ms-2" survey={w} />
</div>
<div>
<button
class="btn btn-sm btn-success mr-1"
title="Relancer les tests"
on:click={runGradations}
disabled={gradation_preflight}
>
{#if gradation_preflight}
<div class="spinner-border spinner-border-sm" role="status"></div>
{:else}
<i class="bi bi-play"></i>
{/if}
</button>
<button
class="btn btn-sm btn-danger mr-1"
title="Arrêter tous les tests en cours"
on:click={() => w.stopTests()}
>
<i class="bi bi-stop"></i>
</button>
</div>
<div class="d-flex align-items-center">
<h2>
<a href="works/{w.id}" class="text-muted" style="text-decoration: none">&lt;</a>
{w.title}
<small class="text-muted">Rendus {Math.trunc(nb_rendus/nb_users*100)}&nbsp;% ({nb_rendus}/{nb_users})</small>
</h2>
<SurveyBadge class="ms-2" survey={w} />
</div>
{#await usersP then users}
@ -140,46 +100,6 @@
>
<i class="bi bi-trash"></i>
</button>
{#await repo.gradationStatus()}
<button
class="btn btn-sm btn-outline-success mr-1"
class:disabled={!show_dl_btn[user.id]}
title="Relancer les tests"
on:click={() => { repo.runGradation(); }}
>
<div class="spinner-border spinner-border-sm" role="status"></div>
</button>
{:then status}
<button
class="btn btn-sm mr-1"
class:btn-success={status.status == "success"}
class:btn-danger={status.status == "failure"}
class:btn-outline-danger={status.status == "killed"}
class:btn-outline-warning={status.status == "pending" || status.status == "running"}
class:disabled={!show_dl_btn[user.id]}
title="Relancer les tests"
on:click={() => { repo.runGradation(); }}
>
<i class="bi bi-play"></i>
</button>
{:catch err}
<button
class="btn btn-sm mr-1 btn-outline-dark"
class:disabled={!show_dl_btn[user.id]}
title={JSON.stringify(err)}
on:click={() => { repo.runGradation(); }}
>
<i class="bi bi-play"></i>
</button>
{/await}
<a
href="/api/users/{user.id}/works/{w.id}/repositories/{repo.id}/traces"
target="_blank"
class="btn btn-sm btn-outline-info mr-1"
title="Voir le détail de la notation"
>
<i class="bi bi-list-check"></i>
</a>
</div>
</div>
{/each}
@ -207,6 +127,14 @@
>
<i class="bi bi-download"></i>
</a>
<button
class="btn btn-sm btn-success mr-1"
class:disabled={!show_dl_btn[user.id]}
title="Relancer les tests"
on:click={() => { w.runGradation(user.id); }}
>
<i class="bi bi-play"></i>
</button>
</td>
</tr>
{/each}

View file

@ -1,7 +1,7 @@
{
"extends": "./.svelte-kit/tsconfig.json",
"compilerOptions": {
"moduleResolution": "bundler",
"moduleResolution": "node",
"module": "es2020",
"lib": ["es2020", "DOM"],
"target": "es2019",
@ -9,6 +9,7 @@
svelte-preprocess cannot figure out whether you have a value or a type, so tell TypeScript
to enforce using \`import type\` instead of \`import\` for Types.
*/
"importsNotUsedAsValues": "error",
"isolatedModules": true,
"resolveJsonModule": true,
/**

View file

@ -4,7 +4,6 @@ import (
"fmt"
"log"
"net/http"
"regexp"
"strconv"
"strings"
"time"
@ -81,38 +80,6 @@ func declareAPIAdminUsersRoutes(router *gin.RouterGroup) {
c.JSON(http.StatusOK, ret)
})
// Anonymize old accounts
router.PATCH("/users", func(c *gin.Context) {
users, err := getUsers()
if err != nil {
log.Println("Unable to getUsers:", err)
c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"errmsg": "Unable to retrieve users. Please try again later."})
return
}
var filterPromo *uint64
if c.Query("promo") != "" {
fPromo, err := strconv.ParseUint(c.Query("promo"), 10, 64)
if err != nil {
c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"errmsg": fmt.Sprintf("Unable to parse promo: %s", err.Error())})
return
}
filterPromo = &fPromo
}
for _, u := range users {
if (filterPromo == nil && u.Promo < currentPromo-1) || (filterPromo != nil && uint(*filterPromo) == u.Promo) {
u.Anonymize()
_, err = u.Update()
if err != nil {
log.Printf("Unable to anonymize %s: %s", u.Login, err.Error())
}
}
}
c.JSON(http.StatusOK, true)
})
usersRoutes := router.Group("/users/:uid")
usersRoutes.Use(userHandler)
@ -131,7 +98,6 @@ func declareAPIAdminUsersRoutes(router *gin.RouterGroup) {
declareAPIAdminUserCorrectionsRoutes(usersRoutes)
declareAPIAdminUserQuestionsRoutes(usersRoutes)
declareAPIAdminWorksRoutes(usersRoutes)
}
func userHandler(c *gin.Context) {
@ -202,33 +168,6 @@ func getUsers() (users []User, err error) {
}
}
func getFilteredUsers(promo uint, group string) (users []User, err error) {
// Avoid SQL injection: check group name doesn't contains harmful content
var validGroup = regexp.MustCompile(`^[a-z0-9-]*$`)
if !validGroup.MatchString(group) {
return nil, fmt.Errorf("%q is not a valid group name", group)
}
if rows, errr := DBQuery("SELECT id_user, login, email, firstname, lastname, time, promo, groups, is_admin FROM users WHERE promo = ? AND groups LIKE '%,"+group+",%' ORDER BY promo DESC, id_user DESC", promo); errr != nil {
return nil, errr
} else {
defer rows.Close()
for rows.Next() {
var u User
if err = rows.Scan(&u.Id, &u.Login, &u.Email, &u.Firstname, &u.Lastname, &u.Time, &u.Promo, &u.Groups, &u.IsAdmin); err != nil {
return
}
users = append(users, u)
}
if err = rows.Err(); err != nil {
return
}
return
}
}
func getPromos() (promos []uint, err error) {
if rows, errr := DBQuery("SELECT DISTINCT promo FROM users ORDER BY promo DESC"); errr != nil {
return nil, errr
@ -279,13 +218,6 @@ func NewUser(login string, email string, firstname string, lastname string, prom
}
}
func (u *User) Anonymize() {
u.Login = fmt.Sprintf("Anonyme #%d", u.Id)
u.Email = fmt.Sprintf("anonyme-%d@non-existant.email", u.Id)
u.Firstname = "Arnaud"
u.Lastname = "Nimes"
}
func (u User) Update() (int64, error) {
if res, err := DBExec("UPDATE users SET login = ?, email = ?, firstname = ?, lastname = ?, time = ?, promo = ?, groups = ? WHERE id_user = ?", u.Login, u.Email, u.Firstname, u.Lastname, u.Time, u.Promo, u.Groups, u.Id); err != nil {
return 0, err

375
works.go
View file

@ -10,7 +10,6 @@ import (
"strings"
"time"
"github.com/drone/drone-go/drone"
"github.com/gin-gonic/gin"
"github.com/russross/blackfriday/v2"
)
@ -154,18 +153,6 @@ func declareAPIAdminWorksRoutes(router *gin.RouterGroup) {
c.JSON(http.StatusOK, nil)
})
worksRoutes.DELETE("/tests", func(c *gin.Context) {
w := c.MustGet("work").(*Work)
err := w.stopTests()
if err != nil {
log.Println("Unable to stop tests:", err)
c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"errmsg": "An error occurs during test stop."})
return
}
c.JSON(http.StatusOK, true)
})
// Grades related to works
worksRoutes.GET("/grades", func(c *gin.Context) {
@ -180,49 +167,6 @@ func declareAPIAdminWorksRoutes(router *gin.RouterGroup) {
c.JSON(http.StatusOK, grades)
})
worksRoutes.PATCH("/grades", func(c *gin.Context) {
w := c.MustGet("work").(*Work)
// Fetch existing grades
grades, err := w.GetGrades("")
if err != nil {
log.Printf("Unable to GetGrades(wid=%d): %s", w.Id, err.Error())
c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"errmsg": "An error occurs during grades retrieval."})
return
}
// Create an index
known_users := map[int64]bool{}
for _, g := range grades {
known_users[g.IdUser] = true
}
// Fetch students list registered for this course
users, err := getFilteredUsers(w.Promo, w.Group)
if err != nil {
log.Printf("Unable to getFilteredUsers(%d, %s): %s", w.Promo, w.Group, err.Error())
c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"errmsg": "An error occurs during users retrieval."})
return
}
var toAdd []WorkGrade
for _, user := range users {
if _, ok := known_users[user.Id]; !ok {
toAdd = append(toAdd, WorkGrade{
IdUser: user.Id,
Login: user.Login,
Grade: 0,
Comment: "- Non rendu -",
})
}
}
if len(toAdd) > 0 {
w.AddGrades(toAdd)
}
c.JSON(http.StatusOK, toAdd)
})
worksRoutes.PUT("/grades", func(c *gin.Context) {
w := c.MustGet("work").(*Work)
@ -248,143 +192,6 @@ func declareAPIAdminWorksRoutes(router *gin.RouterGroup) {
c.JSON(http.StatusOK, true)
})
gradesRoutes := worksRoutes.Group("/grades/:gid")
gradesRoutes.Use(gradeHandler)
gradesRoutes.PUT("", func(c *gin.Context) {
current := c.MustGet("grade").(*WorkGrade)
var new WorkGrade
if err := c.ShouldBindJSON(&new); err != nil {
c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"errmsg": err.Error()})
return
}
new.Id = current.Id
grade, err := new.Update()
if err != nil {
log.Println("Unable to Update grade:", err)
c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"errmsg": "An error occurs during grade update."})
return
}
c.JSON(http.StatusOK, grade)
})
gradesRoutes.DELETE("", func(c *gin.Context) {
g := c.MustGet("grade").(*WorkGrade)
g.Delete()
c.JSON(http.StatusOK, true)
})
gradesRoutes.GET("/status", func(c *gin.Context) {
g := c.MustGet("grade").(*WorkGrade)
var u *User
if user, ok := c.Get("user"); ok {
u = user.(*User)
} else {
u = c.MustGet("LoggedUser").(*User)
}
repo, err := u.getRepositoryByWork(g.IdWork)
if err != nil {
log.Printf("Unable to getRepositoryByWork(uid=%d, wid=%d): %s", u.Id, g.IdWork, err.Error())
c.AbortWithStatusJSON(http.StatusNotFound, gin.H{"errmsg": "Unable to find a corresponding repository."})
return
}
slug := strings.Split(repo.TestsRef, "/")
if len(slug) < 3 {
return
}
buildn, err := strconv.ParseInt(slug[2], 10, 32)
if err != nil {
return
}
client := drone.NewClient(droneEndpoint, droneConfig)
build, err := client.Build(slug[0], slug[1], int(buildn))
if err != nil {
log.Println("Unable to communicate with Drone:", err.Error())
c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"errmsg": "Unable to communicate with Drone"})
return
}
c.JSON(http.StatusOK, build)
})
gradesRoutes.GET("/traces/*path", func(c *gin.Context) {
g := c.MustGet("grade").(*WorkGrade)
var u *User
if user, ok := c.Get("user"); ok {
u = user.(*User)
} else {
u = c.MustGet("LoggedUser").(*User)
}
repo, err := u.getRepositoryByWork(g.IdWork)
if err != nil {
log.Printf("Unable to getRepositoryByWork(uid=%d, wid=%d): %s", u.Id, g.IdWork, err.Error())
c.AbortWithStatusJSON(http.StatusNotFound, gin.H{"errmsg": "Unable to find a corresponding repository."})
return
}
c.Redirect(http.StatusFound, fmt.Sprintf("%s/%s", droneEndpoint, repo.TestsRef)+c.Param("path"))
})
gradesRoutes.POST("/traces", func(c *gin.Context) {
w := c.MustGet("work").(*Work)
g := c.MustGet("grade").(*WorkGrade)
var u *User
if user, ok := c.Get("user"); ok {
u = user.(*User)
} else {
u = c.MustGet("LoggedUser").(*User)
}
repo, err := u.getRepositoryByWork(g.IdWork)
if err != nil {
log.Printf("Unable to getRepositoryByWork(uid=%d, wid=%d): %s", u.Id, g.IdWork, err.Error())
c.AbortWithStatusJSON(http.StatusNotFound, gin.H{"errmsg": "Unable to find a corresponding repository."})
return
}
TriggerTests(c, w, repo, u)
})
gradesRoutes.GET("/forge/*path", func(c *gin.Context) {
g := c.MustGet("grade").(*WorkGrade)
var u *User
if user, ok := c.Get("user"); ok {
u = user.(*User)
} else {
u = c.MustGet("LoggedUser").(*User)
}
repo, err := u.getRepositoryByWork(g.IdWork)
if err != nil {
log.Printf("Unable to getRepositoryByWork(uid=%d, wid=%d): %s", u.Id, g.IdWork, err.Error())
c.AbortWithStatusJSON(http.StatusNotFound, gin.H{"errmsg": "Unable to find a corresponding repository."})
return
}
c.Redirect(http.StatusFound, strings.Replace(strings.Replace(repo.URI, ":", "/", 1), "git@", "https://", 1)+c.Param("path"))
})
}
type UserTraceItem struct {
Title string `json:"title"`
Status string `json:"status"`
Message string `json:"msg,omitempty"`
}
type UserTrace struct {
Title string `json:"title"`
Status string `json:"status"`
Logs []*drone.Line `json:"logs,omitempty"`
Items []UserTraceItem `json:"items,omitempty"`
}
func declareAPIAuthWorksRoutes(router *gin.RouterGroup) {
@ -397,26 +204,6 @@ func declareAPIAuthWorksRoutes(router *gin.RouterGroup) {
})
// Grades related to works
worksRoutes.GET("/forge/*path", func(c *gin.Context) {
w := c.MustGet("work").(*Work)
var u *User
if user, ok := c.Get("user"); ok {
u = user.(*User)
} else {
u = c.MustGet("LoggedUser").(*User)
}
repo, err := u.getRepositoryByWork(w.Id)
if err != nil {
log.Printf("Unable to getRepositoryByWork(uid=%d, wid=%d): %s", u.Id, w.Id, err.Error())
c.AbortWithStatusJSON(http.StatusNotFound, gin.H{"errmsg": "Unable to find a corresponding repository."})
return
}
c.Redirect(http.StatusFound, strings.TrimSuffix(strings.Replace(strings.Replace(repo.URI, ":", "/", 1), "git@", "https://", 1), ".git")+c.Param("path"))
})
worksRoutes.GET("/score", func(c *gin.Context) {
u := c.MustGet("LoggedUser").(*User)
w := c.MustGet("work").(*Work)
@ -433,123 +220,6 @@ func declareAPIAuthWorksRoutes(router *gin.RouterGroup) {
}
})
worksRoutes.GET("/traces", func(c *gin.Context) {
u := c.MustGet("LoggedUser").(*User)
w := c.MustGet("work").(*Work)
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 ?"})
} else if err != nil {
log.Printf("Unable to GetMyWorkGrade(uid=%d;wid=%d): %s", u.Id, w.Id, err.Error())
c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"errmsg": "An error occurs during gradation."})
} else {
repo, err := u.getRepositoryByWork(g.IdWork)
if err != nil {
log.Printf("Unable to getRepositoryByWork(uid=%d, wid=%d): %s", u.Id, g.IdWork, err.Error())
c.AbortWithStatusJSON(http.StatusNotFound, gin.H{"errmsg": "Unable to find a corresponding repository."})
return
}
slug := strings.Split(repo.TestsRef, "/")
if len(slug) < 3 {
return
}
buildn, err := strconv.ParseInt(slug[2], 10, 32)
if err != nil {
return
}
client := drone.NewClient(droneEndpoint, droneConfig)
build, err := client.Build(slug[0], slug[1], int(buildn))
if err != nil {
log.Println("Unable to communicate with Drone:", err.Error())
c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"errmsg": "Unable to communicate with the gradation service"})
return
}
var traces []UserTrace
for _, stage := range build.Stages {
for _, step := range stage.Steps {
if step.Name == "TP checks" || step.Name == "Clean archive" || strings.HasPrefix(step.Name, "Test ") || strings.HasPrefix(step.Name, "Has ") || strings.HasPrefix(step.Name, "Build ") {
result, err := client.Logs(slug[0], slug[1], int(buildn), stage.Number, step.Number)
if err != nil {
log.Printf("An error occurs when retrieving logs from Drone (%s/%s/%d/%d/%d): %s", slug[0], slug[1], buildn, stage.Number, step.Number, err.Error())
continue
}
keeptLogs := []*drone.Line{}
firstCmdShown := false
for _, line := range result {
// Infos about image, skip
if !firstCmdShown {
if strings.HasPrefix(line.Message, "+ ") {
firstCmdShown = true
} else {
continue
}
}
if strings.HasPrefix(line.Message, "+ export GRADE") {
continue
}
if strings.HasPrefix(line.Message, "+ echo grade:") {
line.Message = "+ Your grade for this step is:\r\n"
}
keeptLogs = append(keeptLogs, line)
}
traces = append(traces, UserTrace{
Title: step.Name,
Status: step.Status,
Logs: keeptLogs,
})
} else if strings.HasPrefix(step.Name, "Check") {
result, err := client.Logs(slug[0], slug[1], int(buildn), stage.Number, step.Number)
if err != nil {
log.Printf("An error occurs when retrieving logs from Drone (%s/%s/%d/%d/%d): %s", slug[0], slug[1], buildn, stage.Number, step.Number, err.Error())
continue
}
items := []UserTraceItem{}
for _, line := range result {
if strings.HasPrefix(line.Message, "report:") {
tmp := strings.SplitN(strings.TrimSpace(line.Message), ":", 4)
if len(tmp) < 3 {
continue
}
uti := UserTraceItem{
Title: tmp[1],
Status: tmp[2],
}
if len(tmp) >= 4 {
uti.Message = tmp[3]
}
items = append(items, uti)
}
}
traces = append(traces, UserTrace{
Title: step.Name,
Status: step.Status,
Items: items,
})
}
}
}
if traces == nil {
c.JSON(http.StatusOK, []interface{}{})
} else {
c.JSON(http.StatusOK, traces)
}
}
})
declareAPIAuthRepositoriesRoutes(worksRoutes)
declareAPIWorkSubmissionsRoutes(worksRoutes)
}
@ -558,7 +228,7 @@ func workHandler(c *gin.Context) {
if wid, err := strconv.Atoi(string(c.Param("wid"))); err != nil {
c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"errmsg": "Bad work identifier."})
return
} else if work, err := getWork(int64(wid)); err != nil {
} else if work, err := getWork(wid); err != nil {
c.AbortWithStatusJSON(http.StatusNotFound, gin.H{"errmsg": "Work not found."})
return
} else {
@ -661,7 +331,7 @@ func getWorks(cnd string, param ...interface{}) (items []*Work, err error) {
}
}
func getWork(id int64) (w *Work, err error) {
func getWork(id int) (w *Work, err error) {
w = new(Work)
err = DBQueryRow("SELECT id_work, id_category, title, promo, grp, shown, description, tag, submission_url, gradation_repo, corrected, start_availability, end_availability FROM works WHERE id_work=?", id).Scan(&w.Id, &w.IdCategory, &w.Title, &w.Promo, &w.Group, &w.Shown, &w.DescriptionRaw, &w.Tag, &w.SubmissionURL, &w.GradationRepo, &w.Corrected, &w.StartAvailability, &w.EndAvailability)
w.Description = string(blackfriday.Run([]byte(w.DescriptionRaw)))
@ -717,24 +387,6 @@ type WorkGrade struct {
Comment string `json:"comment,omitempty"`
}
func (g *WorkGrade) Update() (*WorkGrade, error) {
if _, err := DBExec("UPDATE user_work_grades SET id_user = ?, id_work = ?, date = ?, grade = ?, comment = ? WHERE id_gradation = ?", g.IdUser, g.IdWork, g.Date, g.Grade, g.Comment, g.Id); err != nil {
return nil, err
} else {
return g, err
}
}
func (g WorkGrade) Delete() (int64, error) {
if res, err := DBExec("DELETE FROM user_work_grades WHERE id_gradation = ?", g.Id); err != nil {
return 0, err
} else if nb, err := res.RowsAffected(); err != nil {
return 0, err
} else {
return nb, err
}
}
func (w *Work) GetGrades(cnd string, param ...interface{}) (grades []WorkGrade, err error) {
param = append([]interface{}{w.Id}, param...)
@ -758,34 +410,11 @@ func (w *Work) GetGrades(cnd string, param ...interface{}) (grades []WorkGrade,
}
}
func (w *Work) GetGrade(id int64) (g *WorkGrade, err error) {
g = new(WorkGrade)
err = DBQueryRow("SELECT G.id_gradation, G.id_user, U.login, G.id_work, G.date, G.grade, G.comment FROM user_work_grades G INNER JOIN users U ON U.id_user = G.id_user WHERE id_work = ? AND id_gradation = ?", w.Id, id).Scan(&g.Id, &g.IdUser, &g.Login, &g.IdWork, &g.Date, &g.Grade, &g.Comment)
return
}
func (u *User) GetMyWorkGrade(w *Work) (g WorkGrade, err error) {
err = DBQueryRow("SELECT id_gradation, id_user, id_work, date, grade, comment FROM user_work_grades WHERE id_work = ? AND id_user = ? ORDER BY date DESC LIMIT 1", w.Id, u.Id).Scan(&g.Id, &g.IdUser, &g.IdWork, &g.Date, &g.Grade, &g.Comment)
return
}
func (w *Work) AddGrade(grade WorkGrade) error {
u := User{Id: grade.IdUser}
// Search a previous record
g, err := u.GetMyWorkGrade(w)
if err != nil && err != sql.ErrNoRows {
return err
} else if err == nil {
_, err = g.Delete()
if err != nil {
return err
}
}
return w.AddGrades([]WorkGrade{grade})
}
func (w *Work) AddGrades(grades []WorkGrade) error {
var zerotime time.Time
for i, g := range grades {