aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMrArmonius <mrarmonius@gmail.com>2021-07-30 00:04:17 +0200
committerAlex Auvolat <alex@adnab.me>2021-08-16 12:54:08 +0200
commita2a484daba1ef42d82f596a989caf203ee9a370f (patch)
treea3ec45738fa59448dd99d6dd5e69172f18043e90
parent0ca6a159b215967a6d13b9bad5c008983e032c3f (diff)
downloadguichet-a2a484daba1ef42d82f596a989caf203ee9a370f.tar.gz
guichet-a2a484daba1ef42d82f596a989caf203ee9a370f.zip
Add profile image front-end and back-end
Correct when empty result The image showed when the result was empty. Now if the `dn == ""` then we write in the column image just `""`
-rw-r--r--directory.go5
-rw-r--r--go.mod6
-rw-r--r--go.sum43
-rw-r--r--main.go8
-rw-r--r--mimioClient.go244
-rw-r--r--profile.go25
-rw-r--r--static/image/34431.pngbin0 -> 782061 bytes
-rw-r--r--static/javascript/minio.js5
-rw-r--r--static/javascript/search.js14
-rw-r--r--templates/directory.html1
-rw-r--r--templates/profile.html16
11 files changed, 350 insertions, 17 deletions
diff --git a/directory.go b/directory.go
index fd9a085..a66ef28 100644
--- a/directory.go
+++ b/directory.go
@@ -47,11 +47,6 @@ func handleSearch(w http.ResponseWriter, r *http.Request) {
return
}
- /**session, err := store.Get(r, SESSION_NAME)
- if err != nil {
- return
- }**/
-
//Search values with ldap and filter
searchRequest := ldap.NewSearchRequest(
config.UserBaseDN,
diff --git a/go.mod b/go.mod
index 4930fb2..781b3ce 100644
--- a/go.mod
+++ b/go.mod
@@ -7,8 +7,12 @@ require (
github.com/emersion/go-smtp v0.12.1
github.com/go-ldap/ldap v3.0.3+incompatible
github.com/go-ldap/ldap/v3 v3.1.6
+ github.com/google/uuid v1.1.1
github.com/gorilla/mux v1.7.3
github.com/gorilla/sessions v1.2.0
- github.com/sirupsen/logrus v1.4.2
+ github.com/minio/minio-go/v7 v7.0.0
+ github.com/sirupsen/logrus v1.6.0
+ github.com/stretchr/objx v0.1.1 // indirect
golang.org/x/crypto v0.0.0-20200214034016-1d94cc7ab1c6
+ github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646
)
diff --git a/go.sum b/go.sum
index 49da79d..9594bab 100644
--- a/go.sum
+++ b/go.sum
@@ -1,4 +1,6 @@
+github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
github.com/emersion/go-sasl v0.0.0-20190817083125-240c8404624e/go.mod h1:G/dpzLu16WtQpBfQ/z3LYiYJn3ZhKSGWn83fyoyQe/k=
github.com/emersion/go-sasl v0.0.0-20191210011802-430746ea8b9b h1:uhWtEWBHgop1rqEk2klKaxPAkVDCXexai6hSuRQ7Nvs=
github.com/emersion/go-sasl v0.0.0-20191210011802-430746ea8b9b/go.mod h1:G/dpzLu16WtQpBfQ/z3LYiYJn3ZhKSGWn83fyoyQe/k=
@@ -10,25 +12,66 @@ github.com/go-ldap/ldap v3.0.3+incompatible h1:HTeSZO8hWMS1Rgb2Ziku6b8a7qRIZZMHj
github.com/go-ldap/ldap v3.0.3+incompatible/go.mod h1:qfd9rJvER9Q0/D/Sqn1DfHRoBp40uXYvFoEVrNEPqRc=
github.com/go-ldap/ldap/v3 v3.1.6 h1:VTihvB7egSAvU6KOagaiA/EvgJMR2jsjRAVIho2ydBo=
github.com/go-ldap/ldap/v3 v3.1.6/go.mod h1:5Zun81jBTabRaI8lzN7E1JjyEl1g6zI6u9pd8luAK4Q=
+github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
+github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY=
+github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/gorilla/mux v1.7.3 h1:gnP5JzjVOuiZD07fKKToCAOjS0yOpj/qPETTXCCS6hw=
github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
github.com/gorilla/securecookie v1.1.1 h1:miw7JPhV+b/lAHSXz4qd/nN9jRiAFV5FwjeKyCS8BvQ=
github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4=
github.com/gorilla/sessions v1.2.0 h1:S7P+1Hm5V/AT9cjEcUD5uDaQSX0OE577aCXgoaKpYbQ=
github.com/gorilla/sessions v1.2.0/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM=
+github.com/json-iterator/go v1.1.10 h1:Kz6Cvnvv2wGdaG/V8yMvfkmNiXq9Ya2KUv4rouJJr68=
+github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
+github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
+github.com/klauspost/cpuid v1.2.3 h1:CCtW0xUnWGVINKvE/WWOYKdsPV6mawAtvQuSl8guwQs=
+github.com/klauspost/cpuid v1.2.3/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
+github.com/konsorten/go-windows-terminal-sequences v1.0.3 h1:CE8S1cTafDpPvMhIxNJKvHsGVBgn1xWYf1NbHQhywc8=
+github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
+github.com/minio/md5-simd v1.1.0 h1:QPfiOqlZH+Cj9teu0t9b1nTBfPbyTl16Of5MeuShdK4=
+github.com/minio/md5-simd v1.1.0/go.mod h1:XpBqgZULrMYD3R+M28PcmP0CkI7PEMzB3U77ZrKZ0Gw=
+github.com/minio/minio-go/v7 v7.0.0 h1:99hRCmsmMi+hKK93C26iPnRQebTsdK8GEx8Xb4XLr7I=
+github.com/minio/minio-go/v7 v7.0.0/go.mod h1:dJ80Mv2HeGkYLH1sqS/ksz07ON6csH3S6JUMSQ2zAns=
+github.com/minio/sha256-simd v0.1.1 h1:5QHSlgo3nt5yKOJrC7W8w7X+NFl8cMPZm96iu8kKUJU=
+github.com/minio/sha256-simd v0.1.1/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM=
+github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
+github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
+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/reflect2 v0.0.0-20180701023420-4b7aa43c6742 h1:Esafd1046DLDQ0W1YjYsBW+p8U2u7vzgW2SQVmlNazg=
+github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
+github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6Oo2LfFZAehjjQMERAvZLEDnQ=
+github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
+github.com/sirupsen/logrus v1.6.0 h1:UBcNElsrwanuuMsnGSlYmtmgbb23qDR5dG+6X6Oo89I=
+github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
+github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
+github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
+github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
+github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
+golang.org/x/crypto v0.0.0-20190513172903-22d7a77e9e5f/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200214034016-1d94cc7ab1c6 h1:Sy5bstxEqwwbYs6n0/pBuxKENqOeZUgD45Gp3Q3pqLg=
golang.org/x/crypto v0.0.0-20200214034016-1d94cc7ab1c6/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190522155817-f3200d17e092 h1:4QSRKanuywn15aTZvI/mIDEgPQpswuFndXpOj3rKEco=
+golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190422165155-953cdadca894 h1:Cz4ceDQGXuKRnVBDTS23GTn/pU5OE2C0WrNTOYK1Uuc=
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae h1:/WDfKMnPU+m5M4xB+6x4kaepxRw6jWvR5iDRdvjHgy8=
+golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
+gopkg.in/ini.v1 v1.57.0 h1:9unxIsFcTt4I55uWluz+UmL95q4kdJ0buvQ1ZIqVQww=
+gopkg.in/ini.v1 v1.57.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
diff --git a/main.go b/main.go
index 98a9cdd..7dc51df 100644
--- a/main.go
+++ b/main.go
@@ -43,6 +43,10 @@ type ConfigFile struct {
AdminAccount string `json:"admin_account"`
GroupCanInvite string `json:"group_can_invite"`
GroupCanAdmin string `json:"group_can_admin"`
+
+ Endpoint string `json:"endpoint"`
+ AccesKey string `json:"acces_key"`
+ SecretKey string `json:"secret_key"`
}
var configFlag = flag.String("config", "./config.json", "Configuration file path")
@@ -133,6 +137,8 @@ func main() {
r.HandleFunc("/profile", handleProfile)
r.HandleFunc("/passwd", handlePasswd)
+ r.HandleFunc("/image/{name}/{size}", handleDownloadImage)
+
r.HandleFunc("/directory", handleDirectory)
r.HandleFunc("/search/{input}", handleSearch)
@@ -244,7 +250,7 @@ func checkLogin(w http.ResponseWriter, r *http.Request) *LoginStatus {
login_info.DN,
ldap.ScopeBaseObject, ldap.NeverDerefAliases, 0, 0, false,
requestKind,
- []string{"dn", "displayname", "givenname", "sn", "mail", "memberof", "visibility", "description"},
+ []string{"dn", "displayname", "givenname", "sn", "mail", "memberof", "visibility", "description", "profilImage"},
nil)
sr, err := l.Search(searchRequest)
diff --git a/mimioClient.go b/mimioClient.go
new file mode 100644
index 0000000..a3cfdfc
--- /dev/null
+++ b/mimioClient.go
@@ -0,0 +1,244 @@
+package main
+
+import (
+ "bytes"
+ "context"
+ "errors"
+ "fmt"
+ "io"
+ "strconv"
+
+ "image"
+ "image/jpeg"
+ _ "image/png"
+
+ "mime/multipart"
+ "net/http"
+ "strings"
+
+ "github.com/go-ldap/ldap/v3"
+ "github.com/google/uuid"
+ "github.com/gorilla/mux"
+ "github.com/minio/minio-go/v7"
+ "github.com/minio/minio-go/v7/pkg/credentials"
+ "github.com/nfnt/resize"
+)
+
+//Upload image through guichet server.
+func uploadImage(w http.ResponseWriter, r *http.Request, login *LoginStatus) (bool, string, error) {
+ file, _, err := r.FormFile("image")
+
+ if err == http.ErrMissingFile {
+ return false, "", nil
+ }
+ if err != nil {
+ return false, "", err
+ }
+ defer file.Close()
+ fileType, err := checkImage(file)
+ if err != nil {
+ return false, "", err
+ }
+ if fileType == "" {
+ return false, "", nil
+ }
+
+ buff := bytes.NewBuffer([]byte{})
+ buff_thumbnail := bytes.NewBuffer([]byte{})
+ err = resizeThumb(file, buff, buff_thumbnail)
+ if err != nil {
+ return false, "", err
+ }
+
+ mc, err := newMimioClient()
+ if err != nil {
+ return false, "", err
+ }
+ if mc == nil {
+ return false, "", err
+ }
+
+ var name, nameFull string
+
+ if nameConsul := login.UserEntry.GetAttributeValue("profilImage"); nameConsul != "" {
+ name = nameConsul
+ nameFull = "full_" + name
+ } else {
+ name = uuid.New().String() + ".jpeg"
+ nameFull = "full_" + name
+ }
+
+ _, err = mc.PutObject(context.Background(), "bottin-pictures", name, buff_thumbnail, int64(buff_thumbnail.Len()), minio.PutObjectOptions{
+ ContentType: "image/jpeg",
+ })
+ if err != nil {
+ return false, "", err
+ }
+
+ _, err = mc.PutObject(context.Background(), "bottin-pictures", nameFull, buff, int64(buff.Len()), minio.PutObjectOptions{
+ ContentType: "image/jpeg",
+ })
+ if err != nil {
+ return false, "", err
+ }
+
+ return true, name, nil
+}
+
+func newMimioClient() (*minio.Client, error) {
+ endpoint := config.Endpoint
+ accessKeyID := config.AccesKey
+ secretKeyID := config.SecretKey
+ useSSL := true
+
+ //Initialize Minio
+ minioCLient, err := minio.New(endpoint, &minio.Options{
+ Creds: credentials.NewStaticV4(accessKeyID, secretKeyID, ""),
+ Secure: useSSL,
+ Region: "garage",
+ })
+
+ if err != nil {
+ return nil, err
+ }
+
+ return minioCLient, nil
+
+}
+
+func checkImage(file multipart.File) (string, error) {
+ buff := make([]byte, 512) //Detect read only the first 512 bytes
+ _, err := file.Read(buff)
+ if err != nil {
+ return "", err
+ }
+ file.Seek(0, 0)
+
+ fileType := http.DetectContentType(buff)
+ fileType = strings.Split(fileType, "/")[0]
+ switch fileType {
+ case "image":
+ return fileType, nil
+ default:
+ return "", errors.New("bad type")
+ }
+
+}
+
+func resizeThumb(file multipart.File, buff, buff_thumbnail *bytes.Buffer) error {
+ file.Seek(0, 0)
+ images, _, err := image.Decode(file)
+ if err != nil {
+ return errors.New("Decode: " + err.Error())
+ }
+ //Encode image to jpeg a first time to eliminate all problems
+ err = jpeg.Encode(buff, images, &jpeg.Options{
+ Quality: 100, //Between 1 to 100, higher is better
+ })
+ if err != nil {
+ return err
+ }
+ images, _, err = image.Decode(buff)
+ if err != nil {
+ return err
+ }
+ buff.Reset()
+ images = resize.Thumbnail(200, 200, images, resize.Lanczos3)
+ images_thumbnail := resize.Thumbnail(80, 80, images, resize.Lanczos3)
+
+ err = jpeg.Encode(buff, images, &jpeg.Options{
+ Quality: 95,
+ })
+ if err != nil {
+ return err
+ }
+
+ err = jpeg.Encode(buff_thumbnail, images_thumbnail, &jpeg.Options{
+ Quality: 95,
+ })
+
+ return err
+}
+
+func handleDownloadImage(w http.ResponseWriter, r *http.Request) {
+ //Get input value by user
+ dn := mux.Vars(r)["name"]
+ size := mux.Vars(r)["size"]
+
+ //Check login
+ login := checkLogin(w, r)
+ if login == nil {
+ return
+ }
+ var imageName string
+ if dn != "unknown_profile" {
+ //Search values with ldap and filter
+ searchRequest := ldap.NewSearchRequest(
+ dn,
+ ldap.ScopeBaseObject, ldap.NeverDerefAliases, 0, 0, false,
+ "(objectclass=*)",
+ []string{"profilImage"},
+ nil)
+
+ sr, err := login.conn.Search(searchRequest)
+ if err != nil {
+ http.Error(w, "Search: "+err.Error(), http.StatusInternalServerError)
+ return
+ }
+ if len(sr.Entries) != 1 {
+ http.Error(w, fmt.Sprintf("Not found user: %s cn: %s and numberEntries: %d", dn, strings.Split(dn, ",")[0], len(sr.Entries)), http.StatusInternalServerError)
+ return
+ }
+ imageName = sr.Entries[0].GetAttributeValue("profilImage")
+ if imageName == "" {
+ http.Error(w, "User doesn't have profile image", http.StatusInternalServerError)
+ return
+ }
+ } else {
+ imageName = "unknown_profile.jpg"
+ }
+
+ if size == "full" {
+ imageName = "full_" + imageName
+ }
+
+ //Get the object after connect MC
+ mc, err := newMimioClient()
+ if err != nil {
+ http.Error(w, "MinioClient: "+err.Error(), http.StatusInternalServerError)
+ return
+ }
+ obj, err := mc.GetObject(context.Background(), "bottin-pictures", imageName, minio.GetObjectOptions{})
+ if err != nil {
+ http.Error(w, "MinioClient: GetObject: "+err.Error(), http.StatusInternalServerError)
+ return
+ }
+ defer obj.Close()
+ objStat, err := obj.Stat()
+ if err != nil {
+ http.Error(w, "MinioObjet: "+err.Error(), http.StatusInternalServerError)
+ return
+ }
+
+ //Send JSON through xhttp
+ w.Header().Set("Content-Type", objStat.ContentType)
+ w.Header().Set("Content-Length", strconv.Itoa(int(objStat.Size)))
+ //http.Error(w, fmt.Sprintf("Length buffer: %d", objStat.Size), http.StatusInternalServerError)
+ buff := make([]byte, objStat.Size)
+
+ obj.Seek(0, 0)
+ n, err := obj.Read(buff)
+ if err != nil && err != io.EOF {
+ http.Error(w, fmt.Sprintf("Read Error: %s, bytes Read: %d, bytes in file: %d", err.Error(), n, objStat.Size), http.StatusInternalServerError)
+ return
+ }
+ if int64(n) != objStat.Size {
+ http.Error(w, fmt.Sprintf("Read %d bytes on %d bytes", n, objStat.Size), http.StatusInternalServerError)
+ return
+ }
+
+ if _, err := w.Write(buff); err != nil {
+ http.Error(w, "WriteBody: "+err.Error(), http.StatusInternalServerError)
+ return
+ }
+}
diff --git a/profile.go b/profile.go
index ba317fe..ab43922 100644
--- a/profile.go
+++ b/profile.go
@@ -18,6 +18,7 @@ type ProfileTplData struct {
Surname string
Visibility string
Description string
+ NameImage string
}
func handleProfile(w http.ResponseWriter, r *http.Request) {
@@ -42,13 +43,27 @@ func handleProfile(w http.ResponseWriter, r *http.Request) {
data.Description = login.UserEntry.GetAttributeValue("description")
if r.Method == "POST" {
- r.ParseForm()
+ //5MB maximum size files
+ r.ParseMultipartForm(5 << 20)
data.DisplayName = strings.TrimSpace(strings.Join(r.Form["display_name"], ""))
data.GivenName = strings.TrimSpace(strings.Join(r.Form["given_name"], ""))
data.Surname = strings.TrimSpace(strings.Join(r.Form["surname"], ""))
data.Description = strings.Trim(strings.Join(r.Form["description"], ""), "")
- data.Visibility = strings.TrimSpace(strings.Join(r.Form["visibility"], ""))
+ visible := strings.TrimSpace(strings.Join(r.Form["visibility"], ""))
+ if visible != "" {
+ visible = "on"
+ }
+ data.Visibility = visible
+
+ ok, name, err := uploadImage(w, r, login)
+ if err != nil {
+ data.ErrorMessage = err.Error()
+ }
+
+ if ok {
+ data.NameImage = name
+ }
modify_request := ldap.NewModifyRequest(login.Info.DN, nil)
modify_request.Replace("displayname", []string{data.DisplayName})
@@ -56,13 +71,17 @@ func handleProfile(w http.ResponseWriter, r *http.Request) {
modify_request.Replace("sn", []string{data.Surname})
modify_request.Replace("description", []string{data.Description})
modify_request.Replace("visibility", []string{data.Visibility})
+ if ok {
+ modify_request.Replace("profilImage", []string{data.NameImage})
+ }
- err := login.conn.Modify(modify_request)
+ err = login.conn.Modify(modify_request)
if err != nil {
data.ErrorMessage = err.Error()
} else {
data.Success = true
}
+
}
templateProfile.Execute(w, data)
diff --git a/static/image/34431.png b/static/image/34431.png
new file mode 100644
index 0000000..2aba26b
--- /dev/null
+++ b/static/image/34431.png
Binary files differ
diff --git a/static/javascript/minio.js b/static/javascript/minio.js
new file mode 100644
index 0000000..cea2a18
--- /dev/null
+++ b/static/javascript/minio.js
@@ -0,0 +1,5 @@
+document.querySelector('.custom-file-input').addEventListener('change',function(e){
+ var fileName = document.getElementById("image").files[0].name;
+ var nextSibling = e.target.nextElementSibling
+ nextSibling.innerText = fileName
+ })
diff --git a/static/javascript/search.js b/static/javascript/search.js
index 6d33fe6..212ed15 100644
--- a/static/javascript/search.js
+++ b/static/javascript/search.js
@@ -21,12 +21,18 @@ function searchDirectory() {
for (let i =0; i < Object.keys(jsonResponse.search).length; i++) {
var row = table.insertRow(0);
- var identifiant = row.insertCell(0);
- var name = row.insertCell(1);
- var email = row.insertCell(2);
- var description = row.insertCell(3);
+ var urlName = row.insertCell(0);
+ var identifiant = row.insertCell(1);
+ var name = row.insertCell(2);
+ var email = row.insertCell(3);
+ var description = row.insertCell(4);
description.setAttribute("style", "word-break: break-all;");
+ if (jsonResponse.search[i].dn.localeCompare("")!=0) {
+ urlName.innerHTML = `<object data="/image/${jsonResponse.search[i].dn}/little" class=".img-thumbnail"><image src="/image/unknown_profile/little" class=".img-thumbnail"></object>`
+ }else {
+ urlName.innerHTML=""
+ }
identifiant.innerHTML = `<a href="/admin/ldap/${jsonResponse.search[i].dn}">${jsonResponse.search[i].identifiant}</a>`
name.innerHTML = jsonResponse.search[i].name
email.innerHTML = jsonResponse.search[i].email
diff --git a/templates/directory.html b/templates/directory.html
index e91354d..f9bad61 100644
--- a/templates/directory.html
+++ b/templates/directory.html
@@ -19,6 +19,7 @@
<table class="table mt-4">
<thead>
+ <th scope="col">Profil image</th>
<th scope="col">Identifiant</th>
<th scope="col">Nom complet</th>
<th scope="col">Email</th>
diff --git a/templates/profile.html b/templates/profile.html
index 5445d6d..92e229a 100644
--- a/templates/profile.html
+++ b/templates/profile.html
@@ -5,7 +5,10 @@
<h4>Modifier mon profil</h4>
<a class="ml-auto btn btn-info" href="/">Retour</a>
</div>
-
+<h5>Photo de profil</h5>
+<object data="/image/{{ .Status.Info.DN}}/full" class=".img-thumbnail">
+ <img src="/image/unknown_profile/full" alt="Stack Overflow logo and icons and such">
+</object>
{{if .ErrorMessage}}
<div class="alert alert-danger mt-4">Impossible d'effectuer la modification.
<div style="font-size: 0.8em">{{ .ErrorMessage }}</div>
@@ -16,7 +19,7 @@
Profil enregistré.
</div>
{{end}}
- <form method="POST" class="mt-4">
+ <form method="POST" class="mt-4" enctype="multipart/form-data">
<div class="form-group">
<label>Nom d'utilisateur:</label>
<input type="text" disabled="true" class="form-control" value="{{ .Status.Info.Username }}" />
@@ -43,12 +46,19 @@
</div>
<div class="form-group form-check">
{{if .Visibility}}
- <input class="form-check-input" name="visibility" type="checkbox" id="visibility" checked>
+ <input class="form-check-input" name="visibility" type="checkbox" id="visibility" value="on" checked>
{{else}}
<input class="form-check-input" name="visibility" type="checkbox" id="visibility">
{{end}}
<label class="form-check-label" for="visibility">Apparaît sur l'annuaire</label>
</div>
+ <div class="form-group input-group mb-3">
+ <div class="form-group custom-file">
+ <input type="file" name="image" class="custom-file-input" id="image">
+ <label class="custom-file-label" for="image">Choose picture (jpeg, jpg or png)</label>
+ </div>
+ </div>
<button type="submit" class="btn btn-primary">Enregistrer les modifications</button>
</form>
+ <script src="/static/javascript/minio.js"></script>
{{end}}