Add_Directory_and_ProfilePicture #9
5 changed files with 61 additions and 95 deletions
|
@ -24,43 +24,39 @@ import (
|
||||||
"github.com/nfnt/resize"
|
"github.com/nfnt/resize"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const PROFILE_PICTURE_FIELD_NAME = "profilePicture"
|
||||||
|
|
||||||
//Upload image through guichet server.
|
//Upload image through guichet server.
|
||||||
func uploadImage(w http.ResponseWriter, r *http.Request, login *LoginStatus) (bool, string, error) {
|
func uploadImage(w http.ResponseWriter, r *http.Request, login *LoginStatus) (string, error) {
|
||||||
file, _, err := r.FormFile("image")
|
file, _, err := r.FormFile("image")
|
||||||
|
|
||||||
if err == http.ErrMissingFile {
|
if err == http.ErrMissingFile {
|
||||||
return false, "", nil
|
return "", nil
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, "", err
|
return "", err
|
||||||
}
|
}
|
||||||
defer file.Close()
|
defer file.Close()
|
||||||
fileType, err := checkImage(file)
|
err = checkImage(file)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, "", err
|
return "", err
|
||||||
}
|
|
||||||
if fileType == "" {
|
|
||||||
return false, "", nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
buff := bytes.NewBuffer([]byte{})
|
buff := bytes.NewBuffer([]byte{})
|
||||||
buff_thumbnail := bytes.NewBuffer([]byte{})
|
buff_thumbnail := bytes.NewBuffer([]byte{})
|
||||||
err = resizeThumb(file, buff, buff_thumbnail)
|
err = resizeThumb(file, buff, buff_thumbnail)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
mc, err := newMimioClient()
|
mc, err := newMinioClient()
|
||||||
if err != nil {
|
if err != nil || mc == nil {
|
||||||
return false, "", err
|
return "", err
|
||||||
}
|
|
||||||
if mc == nil {
|
|
||||||
return false, "", err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var name, nameFull string
|
var name, nameFull string
|
||||||
|
|
||||||
if nameConsul := login.UserEntry.GetAttributeValue("profilImage"); nameConsul != "" {
|
if nameConsul := login.UserEntry.GetAttributeValue(PROFILE_PICTURE_FIELD_NAME); nameConsul != "" {
|
||||||
name = nameConsul
|
name = nameConsul
|
||||||
nameFull = "full_" + name
|
nameFull = "full_" + name
|
||||||
} else {
|
} else {
|
||||||
|
@ -68,34 +64,34 @@ func uploadImage(w http.ResponseWriter, r *http.Request, login *LoginStatus) (bo
|
||||||
nameFull = "full_" + name
|
nameFull = "full_" + name
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = mc.PutObject(context.Background(), "bottin-pictures", name, buff_thumbnail, int64(buff_thumbnail.Len()), minio.PutObjectOptions{
|
_, err = mc.PutObject(context.Background(), config.S3_Bucket, name, buff_thumbnail, int64(buff_thumbnail.Len()), minio.PutObjectOptions{
|
||||||
ContentType: "image/jpeg",
|
ContentType: "image/jpeg",
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = mc.PutObject(context.Background(), "bottin-pictures", nameFull, buff, int64(buff.Len()), minio.PutObjectOptions{
|
_, err = mc.PutObject(context.Background(), config.S3_Bucket, nameFull, buff, int64(buff.Len()), minio.PutObjectOptions{
|
||||||
ContentType: "image/jpeg",
|
ContentType: "image/jpeg",
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
return true, name, nil
|
return name, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func newMimioClient() (*minio.Client, error) {
|
func newMinioClient() (*minio.Client, error) {
|
||||||
endpoint := config.Endpoint
|
endpoint := config.S3_Endpoint
|
||||||
accessKeyID := config.AccesKey
|
accessKeyID := config.S3_AccesKey
|
||||||
secretKeyID := config.SecretKey
|
secretKeyID := config.S3_SecretKey
|
||||||
useSSL := true
|
useSSL := true
|
||||||
|
|
||||||
//Initialize Minio
|
//Initialize Minio
|
||||||
minioCLient, err := minio.New(endpoint, &minio.Options{
|
minioCLient, err := minio.New(endpoint, &minio.Options{
|
||||||
Creds: credentials.NewStaticV4(accessKeyID, secretKeyID, ""),
|
Creds: credentials.NewStaticV4(accessKeyID, secretKeyID, ""),
|
||||||
Secure: useSSL,
|
Secure: useSSL,
|
||||||
Region: "garage",
|
Region: config.S3_Region,
|
||||||
})
|
})
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -106,11 +102,11 @@ func newMimioClient() (*minio.Client, error) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func checkImage(file multipart.File) (string, error) {
|
func checkImage(file multipart.File) error {
|
||||||
buff := make([]byte, 512) //Detect read only the first 512 bytes
|
buff := make([]byte, 512) //Detect read only the first 512 bytes
|
||||||
_, err := file.Read(buff)
|
_, err := file.Read(buff)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return err
|
||||||
}
|
}
|
||||||
file.Seek(0, 0)
|
file.Seek(0, 0)
|
||||||
|
|
||||||
|
@ -118,9 +114,9 @@ func checkImage(file multipart.File) (string, error) {
|
||||||
fileType = strings.Split(fileType, "/")[0]
|
fileType = strings.Split(fileType, "/")[0]
|
||||||
switch fileType {
|
switch fileType {
|
||||||
case "image":
|
case "image":
|
||||||
return fileType, nil
|
return nil
|
||||||
default:
|
default:
|
||||||
return "", errors.New("bad type")
|
return errors.New("bad type")
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -128,17 +124,6 @@ func checkImage(file multipart.File) (string, error) {
|
||||||
func resizeThumb(file multipart.File, buff, buff_thumbnail *bytes.Buffer) error {
|
func resizeThumb(file multipart.File, buff, buff_thumbnail *bytes.Buffer) error {
|
||||||
file.Seek(0, 0)
|
file.Seek(0, 0)
|
||||||
images, _, err := image.Decode(file)
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -164,7 +149,6 @@ func handleDownloadImage(w http.ResponseWriter, r *http.Request) {
|
||||||
//Get input value by user
|
//Get input value by user
|
||||||
dn := mux.Vars(r)["name"]
|
dn := mux.Vars(r)["name"]
|
||||||
size := mux.Vars(r)["size"]
|
size := mux.Vars(r)["size"]
|
||||||
|
|
||||||
//Check login
|
//Check login
|
||||||
login := checkLogin(w, r)
|
login := checkLogin(w, r)
|
||||||
if login == nil {
|
if login == nil {
|
||||||
|
@ -173,11 +157,12 @@ func handleDownloadImage(w http.ResponseWriter, r *http.Request) {
|
||||||
var imageName string
|
var imageName string
|
||||||
if dn != "unknown_profile" {
|
if dn != "unknown_profile" {
|
||||||
//Search values with ldap and filter
|
//Search values with ldap and filter
|
||||||
|
|
||||||
searchRequest := ldap.NewSearchRequest(
|
searchRequest := ldap.NewSearchRequest(
|
||||||
dn,
|
dn,
|
||||||
ldap.ScopeBaseObject, ldap.NeverDerefAliases, 0, 0, false,
|
ldap.ScopeBaseObject, ldap.NeverDerefAliases, 0, 0, false,
|
||||||
"(objectclass=*)",
|
"(objectclass=*)",
|
||||||
[]string{"profilImage"},
|
[]string{PROFILE_PICTURE_FIELD_NAME},
|
||||||
nil)
|
nil)
|
||||||
|
|
||||||
sr, err := login.conn.Search(searchRequest)
|
sr, err := login.conn.Search(searchRequest)
|
||||||
|
@ -189,9 +174,9 @@ func handleDownloadImage(w http.ResponseWriter, r *http.Request) {
|
||||||
http.Error(w, fmt.Sprintf("Not found user: %s cn: %s and numberEntries: %d", dn, strings.Split(dn, ",")[0], len(sr.Entries)), http.StatusInternalServerError)
|
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
|
return
|
||||||
}
|
}
|
||||||
imageName = sr.Entries[0].GetAttributeValue("profilImage")
|
imageName = sr.Entries[0].GetAttributeValue(PROFILE_PICTURE_FIELD_NAME)
|
||||||
if imageName == "" {
|
if imageName == "" {
|
||||||
http.Error(w, "User doesn't have profile image", http.StatusInternalServerError)
|
http.Error(w, "User doesn't have profile image", http.StatusNotFound)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -201,9 +186,8 @@ func handleDownloadImage(w http.ResponseWriter, r *http.Request) {
|
||||||
if size == "full" {
|
if size == "full" {
|
||||||
imageName = "full_" + imageName
|
imageName = "full_" + imageName
|
||||||
}
|
}
|
||||||
|
|
||||||
//Get the object after connect MC
|
//Get the object after connect MC
|
||||||
mc, err := newMimioClient()
|
mc, err := newMinioClient()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(w, "MinioClient: "+err.Error(), http.StatusInternalServerError)
|
http.Error(w, "MinioClient: "+err.Error(), http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
|
@ -216,29 +200,17 @@ func handleDownloadImage(w http.ResponseWriter, r *http.Request) {
|
||||||
defer obj.Close()
|
defer obj.Close()
|
||||||
objStat, err := obj.Stat()
|
objStat, err := obj.Stat()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(w, "MinioObjet: "+err.Error(), http.StatusInternalServerError)
|
http.Error(w, "MiniObjet: "+err.Error(), http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
//Send JSON through xhttp
|
//Send JSON through xhttp
|
||||||
w.Header().Set("Content-Type", objStat.ContentType)
|
w.Header().Set("Content-Type", objStat.ContentType)
|
||||||
w.Header().Set("Content-Length", strconv.Itoa(int(objStat.Size)))
|
w.Header().Set("Content-Length", strconv.Itoa(int(objStat.Size)))
|
||||||
//http.Error(w, fmt.Sprintf("Length buffer: %d", objStat.Size), http.StatusInternalServerError)
|
//Copy obj in w
|
||||||
buff := make([]byte, objStat.Size)
|
writting, err := io.Copy(w, obj)
|
||||||
|
if writting != objStat.Size || err != nil {
|
||||||
obj.Seek(0, 0)
|
http.Error(w, fmt.Sprintf("WriteBody: %s, bytes wrote %d on %d", err.Error(), writting, objStat.Size), http.StatusInternalServerError)
|
||||||
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
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err := w.Write(buff); err != nil {
|
|
||||||
http.Error(w, "WriteBody: "+err.Error(), http.StatusInternalServerError)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
}
|
21
directory.go
21
directory.go
|
@ -22,8 +22,8 @@ func handleDirectory(w http.ResponseWriter, r *http.Request) {
|
||||||
}
|
}
|
||||||
|
|
||||||
type SearchResult struct {
|
type SearchResult struct {
|
||||||
Identifiant string `json:"identifiant"`
|
Id string `json:"id"`
|
||||||
Name string `json:"name"`
|
Displayname string `json:"displayname"`
|
||||||
Email string `json:"email"`
|
Email string `json:"email"`
|
||||||
Description string `json:"description"`
|
Description string `json:"description"`
|
||||||
DN string `json:"dn"`
|
DN string `json:"dn"`
|
||||||
|
@ -61,15 +61,16 @@ func handleSearch(w http.ResponseWriter, r *http.Request) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
//Transform the researh's result in a correct struct to send HSON
|
//Transform the researh's result in a correct struct to send JSON
|
||||||
var result Results
|
var result Results
|
||||||
for _, values := range sr.Entries {
|
for _, values := range sr.Entries {
|
||||||
|
|
||||||
if strings.Contains(values.GetAttributeValue("cn"), input) {
|
if strings.Contains(values.GetAttributeValue(config.UserNameAttr), input) || strings.Contains(values.GetAttributeValue("displayname"), input) ||
|
||||||
|
(values.GetAttributeValue("email") != "" && strings.Contains(values.GetAttributeValue("email"), input)) {
|
||||||
result = Results{
|
result = Results{
|
||||||
Search: append(result.Search, SearchResult{
|
Search: append(result.Search, SearchResult{
|
||||||
Identifiant: values.GetAttributeValue("cn"),
|
Id: values.GetAttributeValue(config.UserNameAttr),
|
||||||
Name: values.GetAttributeValue("displayname"),
|
Displayname: values.GetAttributeValue("displayname"),
|
||||||
Email: values.GetAttributeValue("email"),
|
Email: values.GetAttributeValue("email"),
|
||||||
Description: values.GetAttributeValue("description"),
|
Description: values.GetAttributeValue("description"),
|
||||||
DN: values.DN,
|
DN: values.DN,
|
||||||
|
@ -80,13 +81,7 @@ func handleSearch(w http.ResponseWriter, r *http.Request) {
|
||||||
}
|
}
|
||||||
if result.Search == nil {
|
if result.Search == nil {
|
||||||
result = Results{
|
result = Results{
|
||||||
Search: append(result.Search, SearchResult{
|
Search: append(result.Search, SearchResult{}),
|
||||||
Identifiant: "",
|
|
||||||
Name: "",
|
|
||||||
Email: "",
|
|
||||||
Description: "",
|
|
||||||
DN: "",
|
|
||||||
}),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
13
main.go
13
main.go
|
@ -44,9 +44,11 @@ type ConfigFile struct {
|
||||||
GroupCanInvite string `json:"group_can_invite"`
|
GroupCanInvite string `json:"group_can_invite"`
|
||||||
GroupCanAdmin string `json:"group_can_admin"`
|
GroupCanAdmin string `json:"group_can_admin"`
|
||||||
|
|
||||||
Endpoint string `json:"endpoint"`
|
S3_Endpoint string `json:"s3_endpoint"`
|
||||||
AccesKey string `json:"acces_key"`
|
S3_AccesKey string `json:"s3_acces_key"`
|
||||||
SecretKey string `json:"secret_key"`
|
S3_SecretKey string `json:"s3_secret_key"`
|
||||||
|
S3_Region string `json:"s3_region"`
|
||||||
|
S3_Bucket string `json:"s3_bucket"`
|
||||||
}
|
}
|
||||||
|
|
||||||
var configFlag = flag.String("config", "./config.json", "Configuration file path")
|
var configFlag = flag.String("config", "./config.json", "Configuration file path")
|
||||||
|
@ -250,7 +252,7 @@ func checkLogin(w http.ResponseWriter, r *http.Request) *LoginStatus {
|
||||||
login_info.DN,
|
login_info.DN,
|
||||||
ldap.ScopeBaseObject, ldap.NeverDerefAliases, 0, 0, false,
|
ldap.ScopeBaseObject, ldap.NeverDerefAliases, 0, 0, false,
|
||||||
requestKind,
|
requestKind,
|
||||||
[]string{"dn", "displayname", "givenname", "sn", "mail", "memberof", "visibility", "description", "profilImage"},
|
[]string{"dn", "displayname", "givenname", "sn", "mail", "memberof", "visibility", "description", PROFILE_PICTURE_FIELD_NAME},
|
||||||
nil)
|
nil)
|
||||||
|
|
||||||
sr, err := l.Search(searchRequest)
|
sr, err := l.Search(searchRequest)
|
||||||
|
@ -398,9 +400,6 @@ func handleLogin(w http.ResponseWriter, r *http.Request) *LoginInfo {
|
||||||
session.Values["login_password"] = password
|
session.Values["login_password"] = password
|
||||||
session.Values["login_dn"] = user_dn
|
session.Values["login_dn"] = user_dn
|
||||||
|
|
||||||
//Add Value MessageID
|
|
||||||
session.Values["MessageID"] = uint32(0)
|
|
||||||
|
|
||||||
err = session.Save(r, w)
|
err = session.Save(r, w)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||||
|
|
|
@ -56,12 +56,12 @@ func handleProfile(w http.ResponseWriter, r *http.Request) {
|
||||||
}
|
}
|
||||||
data.Visibility = visible
|
data.Visibility = visible
|
||||||
|
|
||||||
ok, name, err := uploadImage(w, r, login)
|
name, err := uploadImage(w, r, login)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
data.ErrorMessage = err.Error()
|
data.ErrorMessage = err.Error()
|
||||||
}
|
}
|
||||||
|
|
||||||
if ok {
|
if name != "" {
|
||||||
data.NameImage = name
|
data.NameImage = name
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,8 +71,8 @@ func handleProfile(w http.ResponseWriter, r *http.Request) {
|
||||||
modify_request.Replace("sn", []string{data.Surname})
|
modify_request.Replace("sn", []string{data.Surname})
|
||||||
modify_request.Replace("description", []string{data.Description})
|
modify_request.Replace("description", []string{data.Description})
|
||||||
modify_request.Replace("visibility", []string{data.Visibility})
|
modify_request.Replace("visibility", []string{data.Visibility})
|
||||||
if ok {
|
if name != "" {
|
||||||
modify_request.Replace("profilImage", []string{data.NameImage})
|
modify_request.Replace(PROFILE_PICTURE_FIELD_NAME, []string{data.NameImage})
|
||||||
}
|
}
|
||||||
|
|
||||||
err = login.conn.Modify(modify_request)
|
err = login.conn.Modify(modify_request)
|
||||||
|
|
|
@ -23,20 +23,20 @@ function searchDirectory() {
|
||||||
var row = table.insertRow(0);
|
var row = table.insertRow(0);
|
||||||
var urlName = row.insertCell(0);
|
var urlName = row.insertCell(0);
|
||||||
var identifiant = row.insertCell(1);
|
var identifiant = row.insertCell(1);
|
||||||
var name = row.insertCell(2);
|
var displayname = row.insertCell(2);
|
||||||
var email = row.insertCell(3);
|
var email = row.insertCell(3);
|
||||||
var description = row.insertCell(4);
|
var description = row.insertCell(4);
|
||||||
description.setAttribute("style", "word-break: break-all;");
|
description.setAttribute("style", "word-break: break-all;");
|
||||||
|
|
||||||
if (jsonResponse.search[i].dn.localeCompare("")!=0) {
|
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>`
|
urlName.innerText = `<object data="/image/${jsonResponse.search[i].dn}/little" class=".img-thumbnail"><image src="/image/unknown_profile/little" class=".img-thumbnail"></object>`
|
||||||
}else {
|
}else {
|
||||||
urlName.innerHTML=""
|
urlName.innerText=""
|
||||||
}
|
}
|
||||||
identifiant.innerHTML = `<a href="/admin/ldap/${jsonResponse.search[i].dn}">${jsonResponse.search[i].identifiant}</a>`
|
identifiant.innerText = `<a href="/admin/ldap/${jsonResponse.search[i].dn}">${jsonResponse.search[i].id}</a>`
|
||||||
name.innerHTML = jsonResponse.search[i].name
|
displayname.innerText = jsonResponse.search[i].displayname
|
||||||
email.innerHTML = jsonResponse.search[i].email
|
email.innerText = jsonResponse.search[i].email
|
||||||
description.innerHTML = jsonResponse.search[i].description
|
description.innerText = jsonResponse.search[i].description
|
||||||
|
|
||||||
}
|
}
|
||||||
old_table.parentNode.replaceChild(table, old_table)
|
old_table.parentNode.replaceChild(table, old_table)
|
||||||
|
|
Loading…
Reference in a new issue