func (hooks UserResourceHooks) AllowUpdate(res kit.Resource, obj kit.Model, old kit.Model, user kit.User) bool { if user == nil { return false } if user.HasRole("admin") || user.HasPermission("users.update") { return true } return obj.GetId() == user.GetId() }
func (res *Resource) update(obj kit.Model, user kit.User, partial bool) apperror.Error { if hook, ok := res.hooks.(UpdateHook); ok { return hook.Update(res, obj, user) } oldObj, err := res.FindOne(obj.GetId()) if err != nil { return err } else if oldObj == nil { return apperror.New("not_found") } if allowUpdate, ok := res.hooks.(AllowUpdateHook); ok { if !allowUpdate.AllowUpdate(res, obj, oldObj, user) { return apperror.New("permission_denied") } } if beforeUpdate, ok := res.hooks.(BeforeUpdateHook); ok { if err := beforeUpdate.BeforeUpdate(res, obj, oldObj, user); err != nil { return err } } if partial { rOld := reflector.Reflect(oldObj).MustStruct() rNew := reflector.Reflect(oldObj).MustStruct() for fieldName, _ := range res.modelInfo.Attributes() { val := rNew.Field(fieldName) if !val.IsZero() { rOld.Field(fieldName).Set(val) } } for fieldName, _ := range res.modelInfo.Relations() { val := rNew.Field(fieldName) if !val.IsZero() { rOld.Field(fieldName).Set(val) } } obj = oldObj } if err := res.backend.Update(obj); err != nil { return err } if afterUpdate, ok := res.hooks.(AfterUpdateHook); ok { if err := afterUpdate.AfterUpdate(res, obj, oldObj, user); err != nil { return err } } return nil }
func (s *Service) Create(m kit.Model, user kit.User) apperror.Error { res := s.resources[m.Collection()] if res == nil { return &apperror.Err{ Code: "unknown_resource", Message: fmt.Sprintf("The resource %v was not registered with service", m.Collection()), } } return res.Create(m, user) }
// SerializeModel converts a model into the target format. func (s *Serializer) SerializeModel(model kit.Model) (interface{}, []interface{}, apperror.Error) { // Find backend. backend := s.findBackend(model.Collection()) if backend == nil { return nil, nil, apperror.New("unknown_collection", fmt.Sprintf("Can't serialize model of unknown collection %v", model.Collection())) } // Serialize model. m, extra, err := SerializeModel(backend, model) if err != nil { return nil, nil, err } // Convert extra slice to interface slice. var rawExtra []interface{} for _, item := range extra { rawExtra = append(rawExtra, item) } return m, rawExtra, nil }
func SerializeModel(backend db.Backend, m kit.Model) (*ApiModel, []*ApiModel, apperror.Error) { modelData, err := backend.ModelToMap(m, true, false) if err != nil { return nil, nil, apperror.Wrap(err, "model_convert_error", "") } info := backend.ModelInfo(m.Collection()) data := &ApiModel{ Type: m.Collection(), Id: m.GetStrId(), Attributes: modelData, } // Build relationship data. includedModels := make([]*ApiModel, 0) // Check every model field. r := reflector.R(m).MustStruct() for fieldName, rel := range info.Relations() { // Retrieve the related model. field := r.Field(fieldName) if field != nil { return nil, nil, apperror.Wrap(err, "model_get_field_error") } // If field is zero value, skip. if field.IsZero() { continue } related := make([]kit.Model, 0) if !rel.IsMany() { // Make sure that we have a pointer. if !field.IsPtr() { field = field.Addr() } related = append(related, field.Interface().(kit.Model)) } else { slice := field.MustSlice() for _, item := range slice.Items() { if !item.IsPtr() { item = item.Addr() } related = append(related, item.Interface().(kit.Model)) } } for _, relatedModel := range related { // Convert the related model. relationData, included, err := SerializeModel(backend, relatedModel) if err != nil { return nil, nil, apperror.Wrap(err, "included_model_serialize_error", "") } // Build relation info and set in in relationships map. relation := &ApiModel{ Type: relatedModel.Collection(), Id: relatedModel.GetStrId(), } isSingle := !rel.IsMany() data.AddRelation(rel.MarshalName(), relation, isSingle) // Add related model to included data. includedModels = append(includedModels, relationData) // Add nested included models to included data. includedModels = append(includedModels, included...) } } return data, includedModels, nil }