|  | @@ -9,18 +9,16 @@ import (
 | 
	
		
			
				|  |  |  )
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  var (
 | 
	
		
			
				|  |  | -	ErrItemNotfound  = errors.New("svc: item not found")
 | 
	
		
			
				|  |  | -	ErrInternalError = errors.New("svc: internal error") // ErrInternalError 上游函数错误时返回
 | 
	
		
			
				|  |  | -	ErrDataError     = errors.New("svc: data error")     // ErrDataError 数据校验失败
 | 
	
		
			
				|  |  | +	ErrItemNotfound     = errors.New("svc: item not found")
 | 
	
		
			
				|  |  | +	ErrInternalError    = errors.New("svc: internal error") // ErrInternalError 上游函数错误时返回
 | 
	
		
			
				|  |  | +	ErrDataError        = errors.New("svc: data error")     // ErrDataError 数据校验失败
 | 
	
		
			
				|  |  | +	ErrPermissionDenied = errors.New("svc: permission denied")
 | 
	
		
			
				|  |  |  )
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -type Permission interface {
 | 
	
		
			
				|  |  | -	Have() bool
 | 
	
		
			
				|  |  | -	User() ii.User
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |  type Service struct {
 | 
	
		
			
				|  |  |  	Items  ii.Items
 | 
	
		
			
				|  |  | +	Perms  ii.Permission
 | 
	
		
			
				|  |  | +	User   ii.User
 | 
	
		
			
				|  |  |  	Client *mo.Client
 | 
	
		
			
				|  |  |  	Logs   *logs.Logs
 | 
	
		
			
				|  |  |  }
 | 
	
	
		
			
				|  | @@ -47,6 +45,11 @@ func (s *Service) Find(name string, filter mo.D) ([]mo.M, error) {
 | 
	
		
			
				|  |  |  		return nil, ErrInternalError
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +	if err = s.AC(itemInfo.Name, &filter); err != nil {
 | 
	
		
			
				|  |  | +		s.Logs.Println("svc.Find: AC: %s", err)
 | 
	
		
			
				|  |  | +		return nil, ErrPermissionDenied
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  	if len(lookField) == 0 {
 | 
	
		
			
				|  |  |  		cursor, err = itemInfo.Open(s.Client).Find(filter)
 | 
	
		
			
				|  |  |  	} else {
 | 
	
	
		
			
				|  | @@ -93,6 +96,11 @@ func (s *Service) FindOne(name string, filter mo.D) (mo.M, error) {
 | 
	
		
			
				|  |  |  		return nil, ErrInternalError
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +	if err = s.AC(itemInfo.Name, &filter); err != nil {
 | 
	
		
			
				|  |  | +		s.Logs.Println("svc.FindOne: AC: %s", err)
 | 
	
		
			
				|  |  | +		return nil, ErrPermissionDenied
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  	if len(lookField) == 0 {
 | 
	
		
			
				|  |  |  		// MongoDB 内的 FindOne 也是由 Find 实现, 只需在 FindOptions 内设置 Limit 为负数即可, 详情参见 MongoDB FindOne 函数
 | 
	
		
			
				|  |  |  		opt := mo.Options.Find().SetLimit(-1)
 | 
	
	
		
			
				|  | @@ -129,6 +137,12 @@ func (s *Service) DeleteOne(name string, filter mo.D) error {
 | 
	
		
			
				|  |  |  		s.Logs.Println("svc.DeleteOne: item not found: %s", name)
 | 
	
		
			
				|  |  |  		return ErrItemNotfound
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	if err := s.AC(itemInfo.Name, &filter); err != nil {
 | 
	
		
			
				|  |  | +		s.Logs.Println("svc.DeleteOne: AC: %s", err)
 | 
	
		
			
				|  |  | +		return ErrPermissionDenied
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  	result, err := itemInfo.Open(s.Client).DeleteOne(filter)
 | 
	
		
			
				|  |  |  	if err != nil {
 | 
	
		
			
				|  |  |  		s.Logs.Println("svc.DeleteOne: %s internal error: %s", name, err)
 | 
	
	
		
			
				|  | @@ -144,6 +158,12 @@ func (s *Service) DeleteMany(name string, filter mo.D) error {
 | 
	
		
			
				|  |  |  		s.Logs.Println("svc.DeleteMany: item not found: %s", name)
 | 
	
		
			
				|  |  |  		return ErrItemNotfound
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	if err := s.AC(itemInfo.Name, &filter); err != nil {
 | 
	
		
			
				|  |  | +		s.Logs.Println("svc.DeleteMany: AC: %s", err)
 | 
	
		
			
				|  |  | +		return ErrPermissionDenied
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  	result, err := itemInfo.Open(s.Client).DeleteMany(filter)
 | 
	
		
			
				|  |  |  	if err != nil {
 | 
	
		
			
				|  |  |  		s.Logs.Println("svc.DeleteMany: %s internal error: %s", name, err)
 | 
	
	
		
			
				|  | @@ -165,11 +185,16 @@ func (s *Service) FindOneAndUpdate(name string, filter mo.D, update mo.M) error
 | 
	
		
			
				|  |  |  		return ErrDataError
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -	if err := itemInfo.PrepareUpdate(update); err != nil {
 | 
	
		
			
				|  |  | +	if err := itemInfo.PrepareUpdate(update, s.User); err != nil {
 | 
	
		
			
				|  |  |  		s.Logs.Println("svc.FindOneAndUpdate: PrepareUpdate: %s data error: %s", name, err)
 | 
	
		
			
				|  |  |  		return ErrDataError
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +	if err := s.AC(itemInfo.Name, &filter); err != nil {
 | 
	
		
			
				|  |  | +		s.Logs.Println("svc.FindOneAndUpdate: AC: %s", err)
 | 
	
		
			
				|  |  | +		return ErrPermissionDenied
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  	ou := OptionUpdate{}
 | 
	
		
			
				|  |  |  	ou.SetSet(update)
 | 
	
		
			
				|  |  |  	ou.SetCurrentDate()
 | 
	
	
		
			
				|  | @@ -211,6 +236,10 @@ func (s *Service) CountDocuments(name string, filter mo.D) (int64, error) {
 | 
	
		
			
				|  |  |  		s.Logs.Println("svc.CountDocuments: PrepareFilter: %s data error: %s", name, err)
 | 
	
		
			
				|  |  |  		return 0, ErrDataError
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  | +	if err := s.AC(itemInfo.Name, &filter); err != nil {
 | 
	
		
			
				|  |  | +		s.Logs.Println("svc.CountDocuments: AC: %s", err)
 | 
	
		
			
				|  |  | +		return 0, ErrPermissionDenied
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  |  	length, err := itemInfo.Open(s.Client).CountDocuments(filter)
 | 
	
		
			
				|  |  |  	if err != nil {
 | 
	
		
			
				|  |  |  		s.Logs.Println("svc.CountDocuments: %s internal error: %s", name, err)
 | 
	
	
		
			
				|  | @@ -229,7 +258,7 @@ func (s *Service) InsertOne(name string, doc mo.M) (mo.ObjectID, error) {
 | 
	
		
			
				|  |  |  		return mo.NilObjectID, ErrItemNotfound
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -	if err := itemInfo.PrepareInsert(doc); err != nil {
 | 
	
		
			
				|  |  | +	if err := itemInfo.PrepareInsert(doc, s.User); err != nil {
 | 
	
		
			
				|  |  |  		s.Logs.Println("svc.InsertOne: %s data error: %s", name, err)
 | 
	
		
			
				|  |  |  		return mo.NilObjectID, ErrDataError
 | 
	
		
			
				|  |  |  	}
 | 
	
	
		
			
				|  | @@ -254,7 +283,7 @@ func (s *Service) InsertMany(name string, docs mo.A) ([]mo.ObjectID, error) {
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	err := s.toMaps(docs, func(row mo.M) error {
 | 
	
		
			
				|  |  | -		if err := itemInfo.PrepareInsert(row); err != nil {
 | 
	
		
			
				|  |  | +		if err := itemInfo.PrepareInsert(row, s.User); err != nil {
 | 
	
		
			
				|  |  |  			s.Logs.Println("svc.InsertMany: %s data error: %s", name, err)
 | 
	
		
			
				|  |  |  			return ErrDataError
 | 
	
		
			
				|  |  |  		}
 | 
	
	
		
			
				|  | @@ -290,7 +319,11 @@ func (s *Service) UpdateOne(name string, filter mo.D, update mo.M) error {
 | 
	
		
			
				|  |  |  		s.Logs.Println("svc.UpdateOne: PrepareFilter: %s data error: %s", name, err)
 | 
	
		
			
				|  |  |  		return ErrDataError
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  | -	if err := itemInfo.PrepareUpdate(update); err != nil {
 | 
	
		
			
				|  |  | +	if err := s.AC(itemInfo.Name, &filter); err != nil {
 | 
	
		
			
				|  |  | +		s.Logs.Println("svc.UpdateOne: AC: %s", err)
 | 
	
		
			
				|  |  | +		return ErrPermissionDenied
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +	if err := itemInfo.PrepareUpdate(update, s.User); err != nil {
 | 
	
		
			
				|  |  |  		s.Logs.Println("svc.UpdateOne: PrepareUpdate: %s data error: %s", name, err)
 | 
	
		
			
				|  |  |  		return ErrDataError
 | 
	
		
			
				|  |  |  	}
 | 
	
	
		
			
				|  | @@ -317,7 +350,7 @@ func (s *Service) UpdateByID(name string, id mo.ObjectID, update mo.M) error {
 | 
	
		
			
				|  |  |  		s.Logs.Println("svc.UpdateByID: id are zero: %s", name)
 | 
	
		
			
				|  |  |  		return ErrDataError
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  | -	if err := itemInfo.PrepareUpdate(update); err != nil {
 | 
	
		
			
				|  |  | +	if err := itemInfo.PrepareUpdate(update, s.User); err != nil {
 | 
	
		
			
				|  |  |  		s.Logs.Println("svc.UpdateByID: %s data error: %s", name, err)
 | 
	
		
			
				|  |  |  		return ErrDataError
 | 
	
		
			
				|  |  |  	}
 | 
	
	
		
			
				|  | @@ -341,10 +374,14 @@ func (s *Service) UpdateMany(name string, filter mo.D, update mo.M) error {
 | 
	
		
			
				|  |  |  		return ErrItemNotfound
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  	if err := itemInfo.PrepareFilter(filter); err != nil {
 | 
	
		
			
				|  |  | -		s.Logs.Println("svc.UpdateOne: PrepareFilter: %s data error: %s", name, err)
 | 
	
		
			
				|  |  | +		s.Logs.Println("svc.UpdateMany: PrepareFilter: %s data error: %s", name, err)
 | 
	
		
			
				|  |  |  		return ErrDataError
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  | -	if err := itemInfo.PrepareUpdate(update); err != nil {
 | 
	
		
			
				|  |  | +	if err := s.AC(itemInfo.Name, &filter); err != nil {
 | 
	
		
			
				|  |  | +		s.Logs.Println("svc.UpdateMany: AC: %s", err)
 | 
	
		
			
				|  |  | +		return ErrPermissionDenied
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +	if err := itemInfo.PrepareUpdate(update, s.User); err != nil {
 | 
	
		
			
				|  |  |  		s.Logs.Println("svc.UpdateMany: PrepareUpdate: %s data error: %s", name, err)
 | 
	
		
			
				|  |  |  		return ErrDataError
 | 
	
		
			
				|  |  |  	}
 | 
	
	
		
			
				|  | @@ -370,8 +407,20 @@ func (s *Service) Aggregate(name string, pipe mo.Pipeline, v interface{}) error
 | 
	
		
			
				|  |  |  		return ErrItemNotfound
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +	if i, d, o := mo.HasOperator(pipe, "$match"); o {
 | 
	
		
			
				|  |  | +		filter, ok := d.(mo.D)
 | 
	
		
			
				|  |  | +		if !ok {
 | 
	
		
			
				|  |  | +			return ErrDataError
 | 
	
		
			
				|  |  | +		}
 | 
	
		
			
				|  |  | +		if err := s.AC(itemInfo.Name, &filter); err != nil {
 | 
	
		
			
				|  |  | +			s.Logs.Println("svc.Aggregate: AC: %s", err)
 | 
	
		
			
				|  |  | +			return ErrPermissionDenied
 | 
	
		
			
				|  |  | +		}
 | 
	
		
			
				|  |  | +		pipe[i] = mo.D{{Key: "$match", Value: filter}}
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  	// 如果 pipe 中已包含 $lookup 命令, 则此处不再补充 itemInfo 中所附带的 Lookup, 否则会冲突导致命令失效
 | 
	
		
			
				|  |  | -	if _, o := mo.HasOperator(pipe, "$lookup"); !o {
 | 
	
		
			
				|  |  | +	if _, _, o := mo.HasOperator(pipe, "$lookup"); !o {
 | 
	
		
			
				|  |  |  		lookField, err := itemInfo.Lookup(s.Items)
 | 
	
		
			
				|  |  |  		if err != nil {
 | 
	
		
			
				|  |  |  			s.Logs.Println("svc.Aggregate: Lookup: %s", err)
 | 
	
	
		
			
				|  | @@ -394,3 +443,14 @@ func (s *Service) Aggregate(name string, pipe mo.Pipeline, v interface{}) error
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  	return nil
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +func (s *Service) AC(name ii.Name, filter *mo.D) error {
 | 
	
		
			
				|  |  | +	perms, ok := s.Perms.Get(name, s.User)
 | 
	
		
			
				|  |  | +	if !ok {
 | 
	
		
			
				|  |  | +		return ErrPermissionDenied
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +	// perms 应当在 filter 后面, 假设 filter 与 perms 同时存在 name=1 的条件, 按照权限限制应当以 perms 为准
 | 
	
		
			
				|  |  | +	// MongoDB 对于同一个字段出现多次时, 以最后出现的字段生效
 | 
	
		
			
				|  |  | +	*filter = append(*filter, perms...)
 | 
	
		
			
				|  |  | +	return nil
 | 
	
		
			
				|  |  | +}
 |