コード例 #1
0
func (s *server) Rm(ctx context.Context, req *pb.RmReq) (*pb.Void, error) {

	traceID, err := getTraceID(ctx)
	if err != nil {
		rus.Error(err)
		return &pb.Void{}, err
	}
	log := rus.WithField("trace", traceID).WithField("svc", serviceID)
	ctx = newTraceContext(ctx, traceID)

	log.Info("request started")

	// Time request
	reqStart := time.Now()

	defer func() {
		// Compute request duration
		reqDur := time.Since(reqStart)

		// Log access info
		log.WithFields(rus.Fields{
			"method":   "rm",
			"type":     "grpcaccess",
			"duration": reqDur.Seconds(),
		}).Info("request finished")

	}()

	idt, err := authlib.ParseToken(req.AccessToken, s.p.sharedSecret)
	if err != nil {
		log.Error(err)
		return &pb.Void{}, unauthenticatedError
	}

	log.Infof("%s", idt)

	p := path.Clean(req.Path)

	log.Infof("path is %s", p)

	if !isUnderHome(p, idt) {
		log.Error(permissionDenied)
		return &pb.Void{}, permissionDenied
	}

	if p == getHome(idt) {
		return &pb.Void{}, grpc.Errorf(codes.PermissionDenied, "cannot remove home directory")
	}

	pp := s.getPhysicalPath(p)

	log.Infof("physical path is %s", pp)

	err = os.RemoveAll(pp)
	if err != nil {
		log.Error(err)
		return &pb.Void{}, err
	}

	log.Infof("removed %s", pp)

	resource, err := s.grpcPool.Get("")
	if err != nil {
		log.Error(err)
		return &pb.Void{}, err
	}

	defer resource.Release()

	handle, err := resource.Handle()
	if err != nil {
		log.Error(err)
		return &pb.Void{}, err
	}
	con := handle.(*grpc.ClientConn)
	log.Infof("created connection to %s", s.p.prop)

	client := proppb.NewPropClient(con)

	in := &proppb.RmReq{}
	in.Path = p
	in.AccessToken = req.AccessToken

	_, err = client.Rm(ctx, in)
	if err != nil {
		log.Error(err)
		return &pb.Void{}, err
	}

	log.Infof("paths with prefix %s removed from prop", p)

	return &pb.Void{}, nil
}
コード例 #2
0
func (s *server) Home(ctx context.Context, req *pb.HomeReq) (*pb.Void, error) {

	traceID, err := getTraceID(ctx)
	if err != nil {
		rus.Error(err)
		return &pb.Void{}, err
	}
	log := rus.WithField("trace", traceID).WithField("svc", serviceID)
	ctx = newTraceContext(ctx, traceID)

	log.Info("request started")

	// Time request
	reqStart := time.Now()

	defer func() {
		// Compute request duration
		reqDur := time.Since(reqStart)

		// Log access info
		log.WithFields(rus.Fields{
			"method":   "home",
			"type":     "grpcaccess",
			"duration": reqDur.Seconds(),
		}).Info("request finished")

	}()

	idt, err := authlib.ParseToken(req.AccessToken, s.p.sharedSecret)
	if err != nil {
		log.Error(err)
		return &pb.Void{}, unauthenticatedError
	}

	log.Infof("%s", idt)

	home := getHome(idt)

	log.Infof("user home is %s", home)

	pp := s.getPhysicalPath(home)

	log.Infof("user physical home is %s", pp)

	resource, err := s.grpcPool.Get("")
	if err != nil {
		log.Error(err)
		return &pb.Void{}, err
	}

	defer resource.Release()

	handle, err := resource.Handle()
	if err != nil {
		log.Error(err)
		return &pb.Void{}, err
	}
	con := handle.(*grpc.ClientConn)
	log.Infof("created connection to %s", s.p.prop)

	client := proppb.NewPropClient(con)

	_, err = os.Stat(pp)

	// Create home dir if not exists
	if os.IsNotExist(err) {

		log.Infof("user physical home %s does not exist", pp)

		err = os.MkdirAll(pp, dirPerm)
		if err != nil {
			log.Error(err)
			return &pb.Void{}, err
		}

		log.Infof("user physical home created at %s", pp)

		// trigger file id creation on xattr
		// if it is not set
		_, err = s.getMeta(pp)
		if err != nil {
			return &pb.Void{}, err
		}

		in := &proppb.GetReq{}
		in.Path = home
		in.AccessToken = req.AccessToken
		in.ForceCreation = true

		_, err = client.Get(ctx, in)
		if err != nil {
			return &pb.Void{}, nil
		}

		log.Info("home saved to %s", s.p.prop)

		return &pb.Void{}, nil
	}

	if err != nil {
		log.Error(err)
		return &pb.Void{}, err
	}

	log.Infof("user physical home at %s already created")

	// trigger file id creation on xattr
	// if it is not set
	_, err = s.getMeta(pp)
	if err != nil {
		return &pb.Void{}, err
	}

	in := &proppb.GetReq{}
	in.Path = home
	in.AccessToken = req.AccessToken
	in.ForceCreation = true

	_, err = client.Get(ctx, in)
	if err != nil {
		return &pb.Void{}, nil
	}

	return &pb.Void{}, nil
}
コード例 #3
0
func (s *server) Stat(ctx context.Context, req *pb.StatReq) (*pb.Metadata, error) {

	traceID, err := getTraceID(ctx)
	if err != nil {
		rus.Error(err)
		return &pb.Metadata{}, err
	}
	log := rus.WithField("trace", traceID).WithField("svc", serviceID)
	ctx = newTraceContext(ctx, traceID)

	log.Info("request started")

	// Time request
	reqStart := time.Now()

	defer func() {
		// Compute request duration
		reqDur := time.Since(reqStart)

		// Log access info
		log.WithFields(rus.Fields{
			"method":   "stat",
			"type":     "grpcaccess",
			"duration": reqDur.Seconds(),
		}).Info("request finished")

	}()

	idt, err := authlib.ParseToken(req.AccessToken, s.p.sharedSecret)
	if err != nil {
		log.Error(err)
		return &pb.Metadata{}, unauthenticatedError
	}

	log.Infof("%s", idt)

	p := path.Clean(req.Path)

	log.Infof("path is %s", p)

	// The hierarchy is /local/users/d/demo
	// All paths in the hierarchy above the user home directory must be
	// accessible for all logged in users
	if isCommonDomain(p) {

	} else { // it must be under /local/users/{letter}
		if isUnderOtherHome(p, idt) {
			if req.Children == true {
				// TODO(labkode) Sharing
				return &pb.Metadata{}, permissionDenied
			}
		} else {
			// asset is under logged in user home directory
			if !isUnderHome(p, idt) {
				log.WithField("criticial", "").Errorf("path %s has not been handled correclty or fake path", p)
				return &pb.Metadata{}, permissionDenied
			}
		}
	}

	/*
		if !isUnderHome(p, idt) { // constrained to /local/users/d/demo/...
			log.Error(permissionDenied)
			return &pb.Metadata{}, permissionDenied
		}
	*/

	pp := s.getPhysicalPath(p)

	log.Infof("physical path is %s", pp)

	parentMeta, err := s.getMeta(pp)
	if err != nil {
		log.Error(err)
		return &pb.Metadata{}, err
	}

	log.Infof("stated parent %s", pp)

	resource, err := s.grpcPool.Get("")
	if err != nil {
		log.Error(err)
		return &pb.Metadata{}, err
	}

	defer resource.Release()

	handle, err := resource.Handle()
	if err != nil {
		log.Error(err)
		return &pb.Metadata{}, err
	}
	con := handle.(*grpc.ClientConn)
	log.Infof("created connection to %s", s.p.prop)

	client := proppb.NewPropClient(con)

	in := &proppb.GetReq{}
	in.Path = p
	in.AccessToken = req.AccessToken
	in.ForceCreation = true

	rec, err := client.Get(ctx, in)
	if err != nil {
		log.Error(err)
		return &pb.Metadata{}, err
	}

	parentMeta.Etag = rec.Etag
	parentMeta.Modified = rec.Modified

	if !parentMeta.IsContainer || req.Children == false {
		return parentMeta, nil
	}

	dir, err := os.Open(pp)
	if err != nil {
		log.Error(err)
		return &pb.Metadata{}, err
	}

	log.Infof("opened dir %s", pp)

	defer dir.Close()

	names, err := dir.Readdirnames(0)
	if err != nil {
		log.Error(err)
		return &pb.Metadata{}, err
	}

	log.Infof("dir %s has %d entries", pp, len(names))

	for _, n := range names {
		cp := path.Join(parentMeta.Path, path.Clean(n))
		cpp := s.getPhysicalPath(cp)
		m, err := s.getMeta(cpp)
		if err != nil {
			log.Error(err)
		} else {
			in := &proppb.GetReq{}
			in.Path = cp
			in.AccessToken = req.AccessToken
			in.ForceCreation = true

			rec, err := client.Get(ctx, in)
			if err != nil {
				log.Errorf("path %s has not been added because %s", p, err.Error())
			} else {
				m.Etag = rec.Etag
				m.Modified = rec.Modified
				parentMeta.Children = append(parentMeta.Children, m)

				log.Infof("added %s to parent", m.Path)
			}
		}
	}

	log.Infof("added %d entries to parent", len(parentMeta.Children))

	return parentMeta, nil
}
コード例 #4
0
func (s *server) Mv(ctx context.Context, req *pb.MvReq) (*pb.Void, error) {

	traceID, err := getTraceID(ctx)
	if err != nil {
		rus.Error(err)
		return &pb.Void{}, err
	}
	log := rus.WithField("trace", traceID).WithField("svc", serviceID)
	ctx = newTraceContext(ctx, traceID)

	log.Info("request started")

	// Time request
	reqStart := time.Now()

	defer func() {
		// Compute request duration
		reqDur := time.Since(reqStart)

		// Log access info
		log.WithFields(rus.Fields{
			"method":   "mv",
			"type":     "grpcaccess",
			"duration": reqDur.Seconds(),
		}).Info("request finished")

	}()

	idt, err := authlib.ParseToken(req.AccessToken, s.p.sharedSecret)
	if err != nil {
		log.Error(err)
		return &pb.Void{}, unauthenticatedError
	}

	log.Infof("%s", idt)

	src := path.Clean(req.Src)
	dst := path.Clean(req.Dst)

	log.Infof("src is %s", src)
	log.Info("dst is %s", dst)

	if !isUnderHome(src, idt) {
		log.Error(permissionDenied)
		return &pb.Void{}, permissionDenied
	}

	if !isUnderHome(dst, idt) {
		log.Error(permissionDenied)
		return &pb.Void{}, permissionDenied
	}

	if src == getHome(idt) || dst == getHome(idt) {
		return &pb.Void{}, grpc.Errorf(codes.PermissionDenied, "cannot rename from/to home directory")
	}

	psrc := s.getPhysicalPath(src)
	pdst := s.getPhysicalPath(dst)

	log.Infof("physical src is %s", psrc)
	log.Infof("physical dst is %s", pdst)

	err = os.Rename(psrc, pdst)
	if err != nil {
		log.Error(err)
		return &pb.Void{}, err
	}

	log.Infof("renamed from %s to %s", psrc, pdst)

	resource, err := s.grpcPool.Get("")
	if err != nil {
		log.Error(err)
		return &pb.Void{}, err
	}

	defer resource.Release()

	handle, err := resource.Handle()
	if err != nil {
		log.Error(err)
		return &pb.Void{}, err
	}
	con := handle.(*grpc.ClientConn)
	log.Infof("created connection to %s", s.p.prop)

	client := proppb.NewPropClient(con)

	in := &proppb.MvReq{}
	in.Src = src
	in.Dst = dst
	in.AccessToken = req.AccessToken

	_, err = client.Mv(ctx, in)
	if err != nil {
		log.Error(err)
		return &pb.Void{}, err
	}

	log.Infof("renamed %s to %s in prop", src, dst)

	return &pb.Void{}, nil
}
コード例 #5
0
ファイル: server.go プロジェクト: clawio/service-localfs-prop
func (s *server) Get(ctx context.Context, req *pb.GetReq) (*pb.Record, error) {

	traceID, err := getGRPCTraceID(ctx)
	if err != nil {
		rus.Error(err)
		return &pb.Record{}, err
	}
	log := rus.WithField("trace", traceID).WithField("svc", serviceID)
	ctx = newGRPCTraceContext(ctx, traceID)

	log.Info("request started")

	// Time request
	reqStart := time.Now()

	defer func() {
		// Compute request duration
		reqDur := time.Since(reqStart)

		// Log access info
		log.WithFields(rus.Fields{
			"method":   "get",
			"type":     "grpcaccess",
			"duration": reqDur.Seconds(),
		}).Info("request finished")

	}()

	idt, err := lib.ParseToken(req.AccessToken, s.p.sharedSecret)
	if err != nil {
		log.Error(err)
		return &pb.Record{}, unauthenticatedError
	}

	log.Infof("%s", idt)

	p := path.Clean(req.Path)

	log.Infof("path is %s", p)

	var rec *record

	rec, err = s.getByPath(p)
	if err != nil {
		log.Error(err)
		if err != gorm.RecordNotFound {
			return &pb.Record{}, err
		}

		if !req.ForceCreation {
			return &pb.Record{}, err
		}

		if req.ForceCreation {
			in := &pb.PutReq{}
			in.AccessToken = req.AccessToken
			in.Path = req.Path
			_, e := s.Put(ctx, in)
			if e != nil {
				return &pb.Record{}, err
			}

			rec, err = s.getByPath(p)
			if err != nil {
				return &pb.Record{}, nil
			}
		}
	}

	r := &pb.Record{}
	r.Id = rec.ID
	r.Path = rec.Path
	r.Etag = rec.ETag
	r.Modified = rec.MTime
	r.Checksum = rec.Checksum
	return r, nil
}
コード例 #6
0
ファイル: server.go プロジェクト: clawio/service-localfs-data
func (s *server) getIdentityFromReq(r *http.Request) (*authlib.Identity, error) {
	return authlib.ParseToken(s.getTokenFromReq(r), s.p.sharedSecret)
}
コード例 #7
0
ファイル: server.go プロジェクト: clawio/service-localfs-prop
func (s *server) Put(ctx context.Context, req *pb.PutReq) (*pb.Void, error) {

	traceID, err := getGRPCTraceID(ctx)
	if err != nil {
		rus.Error(err)
		return &pb.Void{}, err
	}
	log := rus.WithField("trace", traceID).WithField("svc", serviceID)
	ctx = newGRPCTraceContext(ctx, traceID)

	log.Info("request started")

	// Time request
	reqStart := time.Now()

	defer func() {
		// Compute request duration
		reqDur := time.Since(reqStart)

		// Log access info
		log.WithFields(rus.Fields{
			"method":   "put",
			"type":     "grpcaccess",
			"duration": reqDur.Seconds(),
		}).Info("request finished")

	}()

	idt, err := lib.ParseToken(req.AccessToken, s.p.sharedSecret)
	if err != nil {
		log.Error(err)
		return &pb.Void{}, unauthenticatedError
	}

	log.Infof("%s", idt)

	p := path.Clean(req.Path)

	log.Infof("path is %s", p)

	var id string
	rawEtag, err := uuid.NewV4()
	if err != nil {
		log.Error(err)
		return &pb.Void{}, err
	}
	etag := rawEtag.String()

	var mtime = uint32(time.Now().Unix())

	r, err := s.getByPath(p)
	if err != nil {
		log.Error(err)
		if err == gorm.RecordNotFound {
			rawEtag, err := uuid.NewV4()
			if err != nil {
				log.Error(err)
				return &pb.Void{}, err
			}

			id = rawEtag.String()
		} else {
			return &pb.Void{}, err
		}
	} else {
		id = r.ID
	}

	log.Infof("new record will have id=%s path=%s checksum=%s etag=%s mtime=%d", id, p, req.Checksum, etag, mtime)

	err = s.insert(id, p, req.Checksum, etag, mtime)
	if err != nil {
		log.Error(err)
		return &pb.Void{}, err
	}

	log.Infof("new record saved to db")

	err = s.propagateChanges(ctx, p, etag, mtime, "")
	if err != nil {
		log.Error(err)
	}

	log.Infof("propagated changes till ancestor %s", "")

	return &pb.Void{}, nil
}
コード例 #8
0
ファイル: server.go プロジェクト: clawio/service-localfs-prop
func (s *server) Rm(ctx context.Context, req *pb.RmReq) (*pb.Void, error) {

	traceID, err := getGRPCTraceID(ctx)
	if err != nil {
		rus.Error(err)
		return &pb.Void{}, err
	}
	log := rus.WithField("trace", traceID).WithField("svc", serviceID)
	ctx = newGRPCTraceContext(ctx, traceID)

	log.Info("request started")

	// Time request
	reqStart := time.Now()

	defer func() {
		// Compute request duration
		reqDur := time.Since(reqStart)

		// Log access info
		log.WithFields(rus.Fields{
			"method":   "rm",
			"type":     "grpcaccess",
			"duration": reqDur.Seconds(),
		}).Info("request finished")

	}()

	idt, err := lib.ParseToken(req.AccessToken, s.p.sharedSecret)
	if err != nil {
		log.Error(err)
		return &pb.Void{}, unauthenticatedError
	}

	log.Infof("%s", idt)

	p := path.Clean(req.Path)

	log.Infof("path is %s", p)

	ts := time.Now().Unix()
	err = s.db.Where("(path LIKE ? OR path=? ) AND m_time < ?", p+"/%", p, ts).Delete(record{}).Error
	if err != nil {
		log.Error(err)
		return &pb.Void{}, err
	}

	etag, err := uuid.NewV4()
	if err != nil {
		return &pb.Void{}, err
	}

	err = s.propagateChanges(ctx, p, etag.String(), uint32(ts), "")
	if err != nil {
		log.Error(err)
	}

	log.Infof("propagated changes till %s", "")

	return &pb.Void{}, nil
}
コード例 #9
0
ファイル: server.go プロジェクト: clawio/service-localfs-prop
func (s *server) Mv(ctx context.Context, req *pb.MvReq) (*pb.Void, error) {

	traceID, err := getGRPCTraceID(ctx)
	if err != nil {
		rus.Error(err)
		return &pb.Void{}, err
	}
	if err != nil {
		rus.Error(err)
		return &pb.Void{}, err
	}
	log := rus.WithField("trace", traceID).WithField("svc", serviceID)
	ctx = newGRPCTraceContext(ctx, traceID)

	log.Info("request started")

	// Time request
	reqStart := time.Now()

	defer func() {
		// Compute request duration
		reqDur := time.Since(reqStart)

		// Log access info
		log.WithFields(rus.Fields{
			"method":   "mv",
			"type":     "grpcaccess",
			"duration": reqDur.Seconds(),
		}).Info("request finished")

	}()

	idt, err := lib.ParseToken(req.AccessToken, s.p.sharedSecret)
	if err != nil {
		log.Error(err)
		return &pb.Void{}, unauthenticatedError
	}

	log.Infof("%s", idt)

	src := path.Clean(req.Src)
	dst := path.Clean(req.Dst)

	log.Infof("src path is %s", src)
	log.Infof("dst path is %s", dst)

	recs, err := s.getRecordsWithPathPrefix(src)
	if err != nil {
		log.Error(err)
		return &pb.Void{}, nil
	}

	tx := s.db.Begin()
	for _, rec := range recs {
		newPath := path.Join(dst, path.Clean(strings.TrimPrefix(rec.Path, src)))
		log.Infof("src path %s will be renamed to %s", rec.Path, newPath)

		err = s.db.Model(record{}).Where("id=?", rec.ID).Updates(record{Path: newPath}).Error
		if err != nil {
			log.Error(err)
			tx.Rollback()
			return &pb.Void{}, err
		}
	}
	tx.Commit()

	log.Infof("renamed %d entries", len(recs))

	etag, err := uuid.NewV4()
	if err != nil {
		log.Error(err)
		return &pb.Void{}, err
	}
	mtime := uint32(time.Now().Unix())
	err = s.propagateChanges(ctx, dst, etag.String(), mtime, "")
	if err != nil {
		log.Error(err)
	}

	log.Infof("propagated changes till %s", "")

	return &pb.Void{}, nil
}
コード例 #10
0
ファイル: server.go プロジェクト: clawio/service-ocwebdav
// authHandler validates the access token sent in the Cookie or if not present sends
// a the Basic Auth params to the auth service to authenticate the request.
func (s *server) authHandler(ctx context.Context, w http.ResponseWriter, r *http.Request,
	next func(ctx context.Context, w http.ResponseWriter, r *http.Request)) {

	logger := MustFromLogContext(ctx)

	idt, err := getIdentityFromReq(r, s.p.sharedSecret)
	if err == nil {

		logger.Info(idt)

		ctx = authlib.NewContext(ctx, idt)
		ctx = authlib.NewTokenContext(ctx, getTokenFromReq(r))
		next(ctx, w, r)
	} else {
		// Authenticate against auth service
		// if basic credentials are found
		user, pass, ok := r.BasicAuth()
		if !ok {
			logger.Error("no credentials found in request")
			w.Header().Set("WWW-Authenticate", "Basic Realm='ClawIO credentials'")
			http.Error(w, "", http.StatusUnauthorized)
			return
		}

		con, err := getConnection(s.p.authServer)
		if err != nil {
			logger.Error(err)
			http.Error(w, "", http.StatusInternalServerError)
			return
		}

		defer con.Close()

		logger.Infof("connected to %s", s.p.authServer)

		client := authpb.NewAuthClient(con)

		in := &authpb.AuthRequest{}
		in.Username = user
		in.Password = pass

		res, err := client.Authenticate(ctx, in)
		if err != nil {
			logger.Error(err)

			if grpc.Code(err) == codes.Unauthenticated {
				w.Header().Set("WWW-Authenticate", "Basic Realm='ClawIO credentials'")
				http.Error(w, "", http.StatusUnauthorized)
				return
			}

			http.Error(w, "", http.StatusInternalServerError)
			return
		}

		logger.Infof("basic auth successful for username %s", user)

		idt, err := authlib.ParseToken(res.Token, s.p.sharedSecret)
		if err != nil {
			logger.Error(err)
			http.Error(w, "", http.StatusInternalServerError)
			return
		}

		logger.Info(idt)

		cookie := &http.Cookie{}
		cookie.Name = "OC_SessionPassphrase"
		cookie.Value = res.Token

		http.SetCookie(w, cookie)

		// token added to the request because when proxied
		// no all servers will handle basic auth, but all will handle
		// the access token
		r.Header.Set("Authorization", "Bearer "+res.Token)

		ctx = authlib.NewContext(ctx, idt)
		ctx = authlib.NewTokenContext(ctx, res.Token)
		next(ctx, w, r)
	}
}
コード例 #11
0
ファイル: utils.go プロジェクト: clawio/service-ocwebdav
func getIdentityFromReq(r *http.Request, secret string) (*authlib.Identity, error) {
	return authlib.ParseToken(getTokenFromReq(r), secret)
}