Ajouter responsiveness au header #93
8 changed files with 122 additions and 43 deletions
|
@ -1,4 +1,4 @@
|
||||||
FROM golang:1.20.6 as build
|
FROM golang:1.21.0 as build
|
||||||
|
|
||||||
LABEL author="Victor Lacasse-Beaudoin <vlbeaudoin@agecem.org>"
|
LABEL author="Victor Lacasse-Beaudoin <vlbeaudoin@agecem.org>"
|
||||||
|
|
||||||
|
@ -24,9 +24,7 @@ RUN CGO_ENABLED=0 go build -a -installsuffix cgo -o agecem-org .
|
||||||
|
|
||||||
# Alpine
|
# Alpine
|
||||||
|
|
||||||
FROM alpine:3.17.2
|
FROM alpine:3.18.3
|
||||||
|
|
||||||
RUN apk update && apk upgrade --no-cache
|
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
|
|
104
cmd/server.go
104
cmd/server.go
|
@ -96,7 +96,12 @@ func init() {
|
||||||
viper.BindPFlag("server.documents.use_ssl", serverCmd.Flags().Lookup("server-documents-use-ssl"))
|
viper.BindPFlag("server.documents.use_ssl", serverCmd.Flags().Lookup("server-documents-use-ssl"))
|
||||||
|
|
||||||
// server.documents.buckets - --server-documents-buckets
|
// server.documents.buckets - --server-documents-buckets
|
||||||
serverCmd.Flags().StringSlice("server-documents-buckets", []string{"proces-verbaux", "politiques-et-reglements"}, "Buckets that are allowed to be accessed by the API (config: server.documents.buckets)")
|
serverCmd.Flags().StringToString("server-documents-buckets", map[string]string{
|
||||||
|
"proces-verbaux": "Procès-verbaux",
|
||||||
|
"politiques": "Politiques",
|
||||||
|
"reglements": "Règlements",
|
||||||
|
"formulaires": "Formulaires",
|
||||||
|
}, "Buckets that are allowed to be accessed by the API (config: server.documents.buckets)")
|
||||||
viper.BindPFlag("server.documents.buckets", serverCmd.Flags().Lookup("server-documents-buckets"))
|
viper.BindPFlag("server.documents.buckets", serverCmd.Flags().Lookup("server-documents-buckets"))
|
||||||
|
|
||||||
// server.api.auth - --server-api-auth
|
// server.api.auth - --server-api-auth
|
||||||
|
@ -293,7 +298,7 @@ func handleDocumentation(c echo.Context) error {
|
||||||
return c.Render(http.StatusInternalServerError, "documentation-html", nil)
|
return c.Render(http.StatusInternalServerError, "documentation-html", nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
var buckets []string
|
var buckets map[string]string
|
||||||
|
|
||||||
err = json.Unmarshal(result, &buckets)
|
err = json.Unmarshal(result, &buckets)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -301,13 +306,14 @@ func handleDocumentation(c echo.Context) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
type Bucket struct {
|
type Bucket struct {
|
||||||
Name string
|
Name string
|
||||||
Documents []string
|
DisplayName string
|
||||||
|
Documents []string
|
||||||
}
|
}
|
||||||
|
|
||||||
var data []Bucket
|
var data []Bucket
|
||||||
|
|
||||||
for _, bucket := range buckets {
|
for bucket, displayName := range buckets {
|
||||||
content, err := client.Call(http.MethodGet, fmt.Sprintf("/v1/bucket/%s", bucket))
|
content, err := client.Call(http.MethodGet, fmt.Sprintf("/v1/bucket/%s", bucket))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return c.Render(http.StatusInternalServerError, "documentation-html", nil)
|
return c.Render(http.StatusInternalServerError, "documentation-html", nil)
|
||||||
|
@ -339,8 +345,9 @@ func handleDocumentation(c echo.Context) error {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
data = append(data, Bucket{
|
data = append(data, Bucket{
|
||||||
Name: bucket,
|
Name: bucket,
|
||||||
Documents: documents,
|
DisplayName: displayName,
|
||||||
|
Documents: documents,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -381,10 +388,56 @@ func handleAdmin(c echo.Context) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleAdminDocumentsUpload(c echo.Context) error {
|
func handleAdminDocumentsUpload(c echo.Context) error {
|
||||||
return c.Render(http.StatusOK, "admin-upload-html", nil)
|
client, err := api.NewApiClientFromViper()
|
||||||
|
if err != nil {
|
||||||
|
return c.Render(http.StatusInternalServerError, "documentation-html", nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
result, err := client.Call(http.MethodGet, "/v1/bucket")
|
||||||
|
if err != nil {
|
||||||
|
return c.Render(http.StatusInternalServerError, "documentation-html", nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
var buckets map[string]string
|
||||||
|
|
||||||
|
err = json.Unmarshal(result, &buckets)
|
||||||
|
if err != nil {
|
||||||
|
return c.Render(http.StatusInternalServerError, "documentation-html", nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
type Bucket struct {
|
||||||
|
Name string
|
||||||
|
DisplayName string
|
||||||
|
Documents []string
|
||||||
|
}
|
||||||
|
|
||||||
|
var data struct {
|
||||||
|
Buckets []Bucket
|
||||||
|
Message string
|
||||||
|
}
|
||||||
|
|
||||||
|
for bucketName, displayName := range buckets {
|
||||||
|
data.Buckets = append(data.Buckets, Bucket{
|
||||||
|
Name: bucketName,
|
||||||
|
DisplayName: displayName,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return c.Render(http.StatusOK, "admin-upload-html", data)
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleAdminDocumentsUploadPOST(c echo.Context) error {
|
func handleAdminDocumentsUploadPOST(c echo.Context) error {
|
||||||
|
type Bucket struct {
|
||||||
|
Name string
|
||||||
|
DisplayName string
|
||||||
|
Documents []string
|
||||||
|
}
|
||||||
|
|
||||||
|
var data struct {
|
||||||
|
Buckets []Bucket
|
||||||
|
Message string
|
||||||
|
}
|
||||||
|
|
||||||
client, err := api.New(cfg.Server.Api.Protocol, cfg.Server.Api.Host, cfg.Server.Port, api.APIOptions{
|
client, err := api.New(cfg.Server.Api.Protocol, cfg.Server.Api.Host, cfg.Server.Port, api.APIOptions{
|
||||||
KeyAuth: cfg.Server.Api.Auth,
|
KeyAuth: cfg.Server.Api.Auth,
|
||||||
Key: cfg.Server.Api.Key,
|
Key: cfg.Server.Api.Key,
|
||||||
|
@ -393,29 +446,52 @@ func handleAdminDocumentsUploadPOST(c echo.Context) error {
|
||||||
Password: cfg.Server.Admin.Password,
|
Password: cfg.Server.Admin.Password,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return c.Render(http.StatusInternalServerError, "admin-upload-html", struct{ Message string }{Message: fmt.Sprintf("handleAdminDocumentsUploadPOST#api.New: %s", err)})
|
data.Message = fmt.Sprintf("handleAdminDocumentsUploadPOST#api.New: %s", err)
|
||||||
|
return c.Render(http.StatusInternalServerError, "admin-upload-html", data)
|
||||||
|
}
|
||||||
|
|
||||||
|
result, err := client.Call(http.MethodGet, "/v1/bucket")
|
||||||
|
if err != nil {
|
||||||
|
data.Message = "Error during GET /v1/bucket"
|
||||||
|
return c.Render(http.StatusInternalServerError, "documentation-html", data)
|
||||||
|
}
|
||||||
|
|
||||||
|
var buckets map[string]string
|
||||||
|
|
||||||
|
err = json.Unmarshal(result, &buckets)
|
||||||
|
if err != nil {
|
||||||
|
return c.Render(http.StatusInternalServerError, "documentation-html", nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
for bucketName, displayName := range buckets {
|
||||||
|
data.Buckets = append(data.Buckets, Bucket{
|
||||||
|
Name: bucketName,
|
||||||
|
DisplayName: displayName,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
bucket := c.FormValue("bucket")
|
bucket := c.FormValue("bucket")
|
||||||
|
|
||||||
document, err := c.FormFile("document")
|
document, err := c.FormFile("document")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return c.Render(http.StatusBadRequest, "admin-upload-html", struct{ Message string }{Message: fmt.Sprintf("handleAdminDocumentsUploadPOST#c.FormFile: %s", err)})
|
data.Message = fmt.Sprintf("handleAdminDocumentsUploadPOST#c.FormFile: %s", err)
|
||||||
|
return c.Render(http.StatusBadRequest, "admin-upload-html", data)
|
||||||
}
|
}
|
||||||
|
|
||||||
response, err := client.UploadDocument(bucket, document)
|
response, err := client.UploadDocument(bucket, document)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return c.Render(http.StatusInternalServerError, "admin-upload-html", struct{ Message string }{Message: fmt.Sprintf("handleAdminDocumentsUploadPOST#client.UploadDocument: %s", err)})
|
data.Message = fmt.Sprintf("handleAdminDocumentsUploadPOST#client.UploadDocument: %s", err)
|
||||||
|
return c.Render(http.StatusInternalServerError, "admin-upload-html", data)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Format response
|
// Format response
|
||||||
var message, info, status string
|
var info, status string
|
||||||
|
|
||||||
info = fmt.Sprintf("[%.0f] /public/documentation/%s/%s", response.Info.Size, response.Info.Bucket, response.Info.Object)
|
info = fmt.Sprintf("[%.0f] /public/documentation/%s/%s", response.Info.Size, response.Info.Bucket, response.Info.Object)
|
||||||
|
|
||||||
status = response.Message
|
status = response.Message
|
||||||
|
|
||||||
message = fmt.Sprintf("%s - %s", status, info)
|
data.Message = fmt.Sprintf("%s - %s", status, info)
|
||||||
|
|
||||||
return c.Render(http.StatusOK, "admin-upload-html", struct{ Message string }{Message: message})
|
return c.Render(http.StatusOK, "admin-upload-html", data)
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,13 +28,13 @@ type Config struct {
|
||||||
Protocol string `mapstructure:"protocol"`
|
Protocol string `mapstructure:"protocol"`
|
||||||
} `mapstructure:"api"`
|
} `mapstructure:"api"`
|
||||||
Documents struct {
|
Documents struct {
|
||||||
AccessKeyId string `mapstructure:"access_key_id"`
|
AccessKeyId string `mapstructure:"access_key_id"`
|
||||||
Buckets []string `mapstructure:"buckets"`
|
Buckets map[string]string `mapstructure:"buckets"`
|
||||||
Endpoint string `mapstructure:"endpoint"`
|
Endpoint string `mapstructure:"endpoint"`
|
||||||
SecretAccessKey string `mapstructure:"secret_access_key"`
|
SecretAccessKey string `mapstructure:"secret_access_key"`
|
||||||
UseSSL bool `mapstructure:"use_ssl"`
|
UseSSL bool `mapstructure:"use_ssl"`
|
||||||
KeyId string `mapstructure:"keyid"`
|
KeyId string `mapstructure:"keyid"`
|
||||||
KeyValue string `mapstructure:"keyvalue"`
|
KeyValue string `mapstructure:"keyvalue"`
|
||||||
} `mapstructure:"documents"`
|
} `mapstructure:"documents"`
|
||||||
Port int `mapstructure:"port"`
|
Port int `mapstructure:"port"`
|
||||||
} `mapstructure:"server"`
|
} `mapstructure:"server"`
|
||||||
|
|
|
@ -35,8 +35,10 @@ server:
|
||||||
#
|
#
|
||||||
# Also used to specify which buckets are to be created on receiving a POST request on /v1/seed
|
# Also used to specify which buckets are to be created on receiving a POST request on /v1/seed
|
||||||
buckets:
|
buckets:
|
||||||
- 'proces-verbaux'
|
'proces-verbaux': 'Procès-verbaux'
|
||||||
- 'politiques-et-reglements'
|
'politiques': 'Politiques'
|
||||||
|
'reglements': 'Règlements'
|
||||||
|
'formulaires': 'Formulaires'
|
||||||
|
|
||||||
api:
|
api:
|
||||||
# Enable or disable key auth on /v1 routes
|
# Enable or disable key auth on /v1 routes
|
||||||
|
|
|
@ -58,7 +58,7 @@ func (m *MediaClient) Seed() ([]string, error) {
|
||||||
|
|
||||||
var new_buckets []string
|
var new_buckets []string
|
||||||
|
|
||||||
for _, bucket := range cfg.Server.Documents.Buckets {
|
for bucket := range cfg.Server.Documents.Buckets {
|
||||||
exists, err := m.MinioClient.BucketExists(context.Background(), bucket)
|
exists, err := m.MinioClient.BucketExists(context.Background(), bucket)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return new_buckets, err
|
return new_buckets, err
|
||||||
|
|
|
@ -72,16 +72,16 @@ func HandleV1BucketList(c echo.Context) error {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
var buckets []string
|
var buckets = make(map[string]string)
|
||||||
|
|
||||||
for _, bucket_name := range cfg.Server.Documents.Buckets {
|
for bucket_name, bucket_display_name := range cfg.Server.Documents.Buckets {
|
||||||
exists, err := mediaClient.MinioClient.BucketExists(context.Background(), bucket_name)
|
exists, err := mediaClient.MinioClient.BucketExists(context.Background(), bucket_name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return c.JSON(http.StatusInternalServerError, "Error during minio#BucketExists")
|
return c.JSON(http.StatusInternalServerError, "Error during minio#BucketExists")
|
||||||
}
|
}
|
||||||
|
|
||||||
if exists {
|
if exists {
|
||||||
buckets = append(buckets, bucket_name)
|
buckets[bucket_name] = bucket_display_name
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -99,7 +99,7 @@ func HandleV1BucketRead(c echo.Context) error {
|
||||||
bucket := c.Param("bucket")
|
bucket := c.Param("bucket")
|
||||||
|
|
||||||
allowed := false
|
allowed := false
|
||||||
for _, bucket_allowed := range cfg.Server.Documents.Buckets {
|
for bucket_allowed := range cfg.Server.Documents.Buckets {
|
||||||
if bucket == bucket_allowed {
|
if bucket == bucket_allowed {
|
||||||
allowed = true
|
allowed = true
|
||||||
}
|
}
|
||||||
|
@ -171,7 +171,7 @@ func HandleV1DocumentCreate(c echo.Context) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
allowed := false
|
allowed := false
|
||||||
for _, bucket_allowed := range cfg.Server.Documents.Buckets {
|
for bucket_allowed := range cfg.Server.Documents.Buckets {
|
||||||
if bucket == bucket_allowed {
|
if bucket == bucket_allowed {
|
||||||
allowed = true
|
allowed = true
|
||||||
}
|
}
|
||||||
|
@ -240,7 +240,7 @@ func HandleV1DocumentRead(c echo.Context) error {
|
||||||
document := c.Param("document")
|
document := c.Param("document")
|
||||||
|
|
||||||
allowed := false
|
allowed := false
|
||||||
for _, bucket_allowed := range cfg.Server.Documents.Buckets {
|
for bucket_allowed := range cfg.Server.Documents.Buckets {
|
||||||
if bucket == bucket_allowed {
|
if bucket == bucket_allowed {
|
||||||
allowed = true
|
allowed = true
|
||||||
}
|
}
|
||||||
|
@ -317,7 +317,7 @@ func HandleV1DocumentDelete(c echo.Context) error {
|
||||||
document := c.Param("document")
|
document := c.Param("document")
|
||||||
|
|
||||||
allowed := false
|
allowed := false
|
||||||
for _, bucket_allowed := range cfg.Server.Documents.Buckets {
|
for bucket_allowed := range cfg.Server.Documents.Buckets {
|
||||||
if bucket == bucket_allowed {
|
if bucket == bucket_allowed {
|
||||||
allowed = true
|
allowed = true
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,8 +12,9 @@
|
||||||
<form class="form adminUploadForm" action="/admin/documents/upload" method="post" enctype="multipart/form-data">
|
<form class="form adminUploadForm" action="/admin/documents/upload" method="post" enctype="multipart/form-data">
|
||||||
<label class="formLabel" for="bucket">Type de document:</label>
|
<label class="formLabel" for="bucket">Type de document:</label>
|
||||||
<select class="formSelect" name="bucket" id="bucket">
|
<select class="formSelect" name="bucket" id="bucket">
|
||||||
<option class="formOption" value="proces-verbaux">Procès verbaux</option>
|
{{ range .Buckets }}
|
||||||
<option class="formOption" value="politiques-et-reglements">Politiques et Règlements</option>
|
<option class="formOption" value="{{ .Name }}">{{ .DisplayName }}</option>
|
||||||
|
{{ end }}
|
||||||
</select>
|
</select>
|
||||||
<br>
|
<br>
|
||||||
Document: <input class="formDocUpload" type="file" name="document">
|
Document: <input class="formDocUpload" type="file" name="document">
|
||||||
|
|
|
@ -13,13 +13,15 @@
|
||||||
<p>
|
<p>
|
||||||
{{ range . }}
|
{{ range . }}
|
||||||
{{ $bucket_name := .Name }}
|
{{ $bucket_name := .Name }}
|
||||||
|
{{ $bucket_display_name := .DisplayName }}
|
||||||
<details>
|
<details>
|
||||||
<summary>{{ $bucket_name }}</summary>
|
<summary>{{ $bucket_display_name }}</summary>
|
||||||
<ul>
|
|
||||||
{{ range .Documents }}
|
<ul>
|
||||||
<li> <a href="/public/documentation/{{ $bucket_name }}/{{ . }}">{{ . }}</a></li>
|
{{ range .Documents }}
|
||||||
{{ end}}
|
<li> <a href="/public/documentation/{{ $bucket_name }}/{{ . }}">{{ . }}</a></li>
|
||||||
</ul>
|
{{ end}}
|
||||||
|
</ul>
|
||||||
</details>
|
</details>
|
||||||
{{ end }}
|
{{ end }}
|
||||||
</p>
|
</p>
|
||||||
|
|
Loading…
Reference in a new issue