diff options
author | Quentin <quentin@deuxfleurs.fr> | 2021-08-19 22:14:53 +0200 |
---|---|---|
committer | Quentin <quentin@deuxfleurs.fr> | 2021-08-19 22:14:53 +0200 |
commit | 8f7e8d2c73ff1a9de7d49ee212efa5a27b5461bc (patch) | |
tree | b73a88acc8bc45b333a5dd6702613ac5e73f1a84 /main.go | |
parent | d69640894d3f8259c7c6f843ecc8c963aa91ff97 (diff) | |
download | bagage-8f7e8d2c73ff1a9de7d49ee212efa5a27b5461bc.tar.gz bagage-8f7e8d2c73ff1a9de7d49ee212efa5a27b5461bc.zip |
Format the source file
Diffstat (limited to 'main.go')
-rw-r--r-- | main.go | 439 |
1 files changed, 220 insertions, 219 deletions
@@ -1,42 +1,43 @@ package main import ( - "context" + "context" + "errors" + "fmt" + "io/fs" "log" - "fmt" - "os" - "io/fs" - "time" - "errors" "net/http" - "strings" - "path" + "os" + "path" + "strings" + "time" "golang.org/x/net/webdav" - "github.com/go-ldap/ldap/v3" + "github.com/go-ldap/ldap/v3" "github.com/minio/minio-go/v7" "github.com/minio/minio-go/v7/pkg/credentials" ) type bagageCtxKey string + const garageEntry = bagageCtxKey("garage") type garageCtx struct { - MC *minio.Client - StatCache map[string]*GarageStat + MC *minio.Client + StatCache map[string]*GarageStat } func main() { - pathPrefix := "/webdav" - UserBaseDN := "ou=users,dc=deuxfleurs,dc=fr" - UserNameAttr := "cn" - Endpoint := "garage.deuxfleurs.fr" - UseSSL := true + pathPrefix := "/webdav" + UserBaseDN := "ou=users,dc=deuxfleurs,dc=fr" + UserNameAttr := "cn" + Endpoint := "garage.deuxfleurs.fr" + UseSSL := true srv := &webdav.Handler{ - Prefix: pathPrefix, + Prefix: pathPrefix, FileSystem: NewGarageFS(), LockSystem: webdav.NewMemLS(), Logger: func(r *http.Request, err error) { @@ -45,79 +46,79 @@ func main() { } //http.Handle("/", srv) - http.HandleFunc(pathPrefix + "/", func(w http.ResponseWriter, r *http.Request) { - username, password, ok := r.BasicAuth() - - if !ok { - NotAuthorized(w,r) - return - } - - ldapSock, err := ldap.Dial("tcp", "127.0.0.1:1389") - if err != nil { - log.Println(err) - InternalError(w,r) - return - } - defer ldapSock.Close() - - // Check credential - userDn := fmt.Sprintf("%s=%s,%s", UserNameAttr, username, UserBaseDN) - err = ldapSock.Bind(userDn, password) - if err != nil { - log.Println(err) - NotAuthorized(w,r) - return - } - - // Get S3 creds garage_s3_access_key garage_s3_secret_key - searchRequest := ldap.NewSearchRequest( - userDn, - ldap.ScopeBaseObject, - ldap.NeverDerefAliases, - 0, - 0, - false, - "(objectClass=*)", - []string{"garage_s3_access_key", "garage_s3_secret_key"}, - nil) - - sr, err := ldapSock.Search(searchRequest) - if err != nil { - log.Println(err) - InternalError(w,r) - return - } - - if len(sr.Entries) != 1 { - log.Println("Wrong number of LDAP entries, expected 1, got", len(sr.Entries)) - InternalError(w,r) - return - } - - access_key := sr.Entries[0].GetAttributeValue("garage_s3_access_key") - secret_key := sr.Entries[0].GetAttributeValue("garage_s3_secret_key") - - if access_key == "" || secret_key == "" { - log.Println("Either access key or secret key is missing in LDAP for ", userDn) - InternalError(w,r) - return - } - - mc, err := minio.New(Endpoint, &minio.Options{ - Creds: credentials.NewStaticV4(access_key, secret_key, ""), - Secure: UseSSL, - }) - if err != nil { - log.Println(err) - InternalError(w,r) - return - } - - nctx := context.WithValue(r.Context(), garageEntry, garageCtx{MC: mc, StatCache: make(map[string]*GarageStat)}) - srv.ServeHTTP(w, r.WithContext(nctx)) - return - }) + http.HandleFunc(pathPrefix+"/", func(w http.ResponseWriter, r *http.Request) { + username, password, ok := r.BasicAuth() + + if !ok { + NotAuthorized(w, r) + return + } + + ldapSock, err := ldap.Dial("tcp", "127.0.0.1:1389") + if err != nil { + log.Println(err) + InternalError(w, r) + return + } + defer ldapSock.Close() + + // Check credential + userDn := fmt.Sprintf("%s=%s,%s", UserNameAttr, username, UserBaseDN) + err = ldapSock.Bind(userDn, password) + if err != nil { + log.Println(err) + NotAuthorized(w, r) + return + } + + // Get S3 creds garage_s3_access_key garage_s3_secret_key + searchRequest := ldap.NewSearchRequest( + userDn, + ldap.ScopeBaseObject, + ldap.NeverDerefAliases, + 0, + 0, + false, + "(objectClass=*)", + []string{"garage_s3_access_key", "garage_s3_secret_key"}, + nil) + + sr, err := ldapSock.Search(searchRequest) + if err != nil { + log.Println(err) + InternalError(w, r) + return + } + + if len(sr.Entries) != 1 { + log.Println("Wrong number of LDAP entries, expected 1, got", len(sr.Entries)) + InternalError(w, r) + return + } + + access_key := sr.Entries[0].GetAttributeValue("garage_s3_access_key") + secret_key := sr.Entries[0].GetAttributeValue("garage_s3_secret_key") + + if access_key == "" || secret_key == "" { + log.Println("Either access key or secret key is missing in LDAP for ", userDn) + InternalError(w, r) + return + } + + mc, err := minio.New(Endpoint, &minio.Options{ + Creds: credentials.NewStaticV4(access_key, secret_key, ""), + Secure: UseSSL, + }) + if err != nil { + log.Println(err) + InternalError(w, r) + return + } + + nctx := context.WithValue(r.Context(), garageEntry, garageCtx{MC: mc, StatCache: make(map[string]*GarageStat)}) + srv.ServeHTTP(w, r.WithContext(nctx)) + return + }) if err := http.ListenAndServe(":8080", nil); err != nil { log.Fatalf("Error with WebDAV server: %v", err) @@ -132,7 +133,7 @@ func NotAuthorized(w http.ResponseWriter, r *http.Request) { func InternalError(w http.ResponseWriter, r *http.Request) { w.WriteHeader(500) - w.Write([]byte("500 Internal Server Error\n")) + w.Write([]byte("500 Internal Server Error\n")) } /* @@ -146,7 +147,7 @@ func InternalError(w http.ResponseWriter, r *http.Request) { Else return obj */ -type GarageFS struct {} +type GarageFS struct{} func NewGarageFS() *GarageFS { grg := new(GarageFS) @@ -154,53 +155,53 @@ func NewGarageFS() *GarageFS { } func (s *GarageFS) Mkdir(ctx context.Context, name string, perm os.FileMode) error { - return errors.New("Not implemented Mkdir") + return errors.New("Not implemented Mkdir") } func (s *GarageFS) OpenFile(ctx context.Context, name string, flag int, perm os.FileMode) (webdav.File, error) { - return NewGarageFile(ctx, name) + return NewGarageFile(ctx, name) } func (s *GarageFS) RemoveAll(ctx context.Context, name string) error { - return errors.New("Not implemented RemoveAll") + return errors.New("Not implemented RemoveAll") } func (s *GarageFS) Rename(ctx context.Context, oldName, newName string) error { - return errors.New("Not implemented Rename") + return errors.New("Not implemented Rename") } func (s *GarageFS) Stat(ctx context.Context, name string) (os.FileInfo, error) { - return NewGarageStat(ctx, name) + return NewGarageStat(ctx, name) } type GarageFile struct { - ctx context.Context - mc *minio.Client - path string + ctx context.Context + mc *minio.Client + path string } func NewGarageFile(ctx context.Context, path string) (webdav.File, error) { - gf := new(GarageFile) - gf.ctx = ctx - gf.mc = ctx.Value(garageEntry).(garageCtx).MC - gf.path = path - return gf, nil + gf := new(GarageFile) + gf.ctx = ctx + gf.mc = ctx.Value(garageEntry).(garageCtx).MC + gf.path = path + return gf, nil } func (gf *GarageFile) Close() error { - return errors.New("not implemented Close") + return errors.New("not implemented Close") } func (gf *GarageFile) Read(p []byte) (n int, err error) { - return 0, errors.New("not implemented Read") + return 0, errors.New("not implemented Read") } -func (gf *GarageFile) Write(p []byte) (n int, err error) { - return 0, errors.New("not implemented Write") +func (gf *GarageFile) Write(p []byte) (n int, err error) { + return 0, errors.New("not implemented Write") } func (gf *GarageFile) Seek(offset int64, whence int) (int64, error) { - return 0, errors.New("not implemented Seek") + return 0, errors.New("not implemented Seek") } /* @@ -211,155 +212,155 @@ If n > 0, ReadDir returns at most n DirEntry records. In this case, if ReadDir r If n <= 0, ReadDir returns all the DirEntry records remaining in the directory. When it succeeds, it returns a nil error (not io.EOF). */ func (gf *GarageFile) Readdir(count int) ([]fs.FileInfo, error) { - log.Println("Call Readdir with count", count) - - if gf.path == "/" { - return gf.readDirRoot(count) - } else { - exploded_path := strings.SplitN(gf.path, "/", 3) - return gf.readDirChild(count, exploded_path[1], exploded_path[2]) - } + log.Println("Call Readdir with count", count) + + if gf.path == "/" { + return gf.readDirRoot(count) + } else { + exploded_path := strings.SplitN(gf.path, "/", 3) + return gf.readDirChild(count, exploded_path[1], exploded_path[2]) + } } func (gf *GarageFile) readDirRoot(count int) ([]fs.FileInfo, error) { - buckets, err := gf.mc.ListBuckets(gf.ctx) - if err != nil { - return nil, err - } - - entries := make([]fs.FileInfo, 0, len(buckets)) - for _, bucket := range buckets { - ngf, err := NewGarageStat(gf.ctx, "/"+bucket.Name) - if err != nil { - return nil, err - } - entries = append(entries, ngf) - } - - return entries, nil + buckets, err := gf.mc.ListBuckets(gf.ctx) + if err != nil { + return nil, err + } + + entries := make([]fs.FileInfo, 0, len(buckets)) + for _, bucket := range buckets { + ngf, err := NewGarageStat(gf.ctx, "/"+bucket.Name) + if err != nil { + return nil, err + } + entries = append(entries, ngf) + } + + return entries, nil } func (gf *GarageFile) readDirChild(count int, bucket, prefix string) ([]fs.FileInfo, error) { - log.Println("call ListObjects with", bucket, prefix) - objs_info := gf.mc.ListObjects(gf.ctx, bucket, minio.ListObjectsOptions{ - Prefix: prefix, - Recursive: false, - }) - - entries := make([]fs.FileInfo,0) - for object := range objs_info { - if object.Err != nil { - return nil, object.Err - } - ngf, err := NewGarageStatFromObjectInfo(gf.ctx, bucket, object) - if err != nil { - return nil, err - } - entries = append(entries, ngf) - } - - return entries, nil + log.Println("call ListObjects with", bucket, prefix) + objs_info := gf.mc.ListObjects(gf.ctx, bucket, minio.ListObjectsOptions{ + Prefix: prefix, + Recursive: false, + }) + + entries := make([]fs.FileInfo, 0) + for object := range objs_info { + if object.Err != nil { + return nil, object.Err + } + ngf, err := NewGarageStatFromObjectInfo(gf.ctx, bucket, object) + if err != nil { + return nil, err + } + entries = append(entries, ngf) + } + + return entries, nil } func (gf *GarageFile) Stat() (fs.FileInfo, error) { - return NewGarageStat(gf.ctx, gf.path) + return NewGarageStat(gf.ctx, gf.path) } /* Implements */ // StatObject??? type GarageStat struct { - obj minio.ObjectInfo - bucket string + obj minio.ObjectInfo + bucket string } func NewGarageStat(ctx context.Context, path string) (*GarageStat, error) { - cache := ctx.Value(garageEntry).(garageCtx).StatCache - if entry, ok := cache[path]; ok { - return entry, nil - } - - gs, err := newGarageStatFresh(ctx, path) - if err != nil { - return nil, err - } - - cache[path] = gs - return gs, nil + cache := ctx.Value(garageEntry).(garageCtx).StatCache + if entry, ok := cache[path]; ok { + return entry, nil + } + + gs, err := newGarageStatFresh(ctx, path) + if err != nil { + return nil, err + } + + cache[path] = gs + return gs, nil } func newGarageStatFresh(ctx context.Context, path string) (*GarageStat, error) { - mc := ctx.Value(garageEntry).(garageCtx).MC - gs := new(GarageStat) - gs.bucket = "/" - gs.obj = minio.ObjectInfo{} - - exploded_path := strings.SplitN(path, "/", 3) - - // Check if we can extract the bucket name - if len(exploded_path) < 2 { - return gs, nil - } - gs.bucket = exploded_path[1] - - // Check if we can extract the prefix - if len(exploded_path) < 3 || exploded_path[2] == "" { - return gs, nil - } - gs.obj.Key = exploded_path[2] - - // Check if this is a file or a folder - log.Println("call StatObject with", gs.bucket, gs.obj.Key) - obj, err := mc.StatObject(ctx, gs.bucket, gs.obj.Key, minio.StatObjectOptions{}) - if e, ok := err.(minio.ErrorResponse); ok && e.Code == "NoSuchKey" { - return gs, nil - } - if err != nil { - return nil, err - } - - // If it is a file, assign its data - gs.obj = obj - return gs, nil + mc := ctx.Value(garageEntry).(garageCtx).MC + gs := new(GarageStat) + gs.bucket = "/" + gs.obj = minio.ObjectInfo{} + + exploded_path := strings.SplitN(path, "/", 3) + + // Check if we can extract the bucket name + if len(exploded_path) < 2 { + return gs, nil + } + gs.bucket = exploded_path[1] + + // Check if we can extract the prefix + if len(exploded_path) < 3 || exploded_path[2] == "" { + return gs, nil + } + gs.obj.Key = exploded_path[2] + + // Check if this is a file or a folder + log.Println("call StatObject with", gs.bucket, gs.obj.Key) + obj, err := mc.StatObject(ctx, gs.bucket, gs.obj.Key, minio.StatObjectOptions{}) + if e, ok := err.(minio.ErrorResponse); ok && e.Code == "NoSuchKey" { + return gs, nil + } + if err != nil { + return nil, err + } + + // If it is a file, assign its data + gs.obj = obj + return gs, nil } func NewGarageStatFromObjectInfo(ctx context.Context, bucket string, obj minio.ObjectInfo) (*GarageStat, error) { - gs := new(GarageStat) - gs.bucket = bucket - gs.obj = obj + gs := new(GarageStat) + gs.bucket = bucket + gs.obj = obj - cache := ctx.Value(garageEntry).(garageCtx).StatCache - cache[path.Join("/", bucket, obj.Key)] = gs - return gs, nil + cache := ctx.Value(garageEntry).(garageCtx).StatCache + cache[path.Join("/", bucket, obj.Key)] = gs + return gs, nil } func (gs *GarageStat) Name() string { - if gs.obj.Key != "" { - return path.Base(gs.obj.Key) - } else { - return gs.bucket - } + if gs.obj.Key != "" { + return path.Base(gs.obj.Key) + } else { + return gs.bucket + } } func (gs *GarageStat) Size() int64 { - return gs.obj.Size + return gs.obj.Size } func (gs *GarageStat) Mode() fs.FileMode { - if gs.obj.ETag == "" { - return fs.ModeDir | fs.ModePerm - } else { - return fs.ModePerm - } + if gs.obj.ETag == "" { + return fs.ModeDir | fs.ModePerm + } else { + return fs.ModePerm + } } func (gs *GarageStat) ModTime() time.Time { - return gs.obj.LastModified + return gs.obj.LastModified } func (gs *GarageStat) IsDir() bool { - return gs.Mode().IsDir() + return gs.Mode().IsDir() } func (gs *GarageStat) Sys() interface{} { - return nil + return nil } |