Ember 数据 Firebase 规则混乱

Ember Data Firebase rules confusion

我正在开始我的第一个 Ember/Firebase 应用程序,但在查找超出 public 数据的文档时遇到了问题。

我的目标是拥有一个应用程序,登录用户可以在其中创建和查看自己的数据。我看到 Firebase 针对这种情况建议了这条规则:

{
  "rules": {
    "users": {
      "$uid": {
        ".read": "$uid === auth.uid",
        ".write": "$uid === auth.uid"
      }
    }
  }
}

但是我找不到任何关于这在 Ember 端如何工作的信息。例如,假设我有一个要保存的 "entry" 模型:

save(model) {
  model.save().then( () => {
    this.transitionToRoute('index');
  }, error => {
    console.error(`error: ${error}`);
  })
},

不确定我是否需要在模型中存储 uid?

然后如果我希望用户获得他们自己的条目列表:

import Ember from 'ember';
export default Ember.Route.extend({
  model() {
    return this.store.findAll('entry');
  }
});

这会产生以下错误:

ember.debug.js:30610 Error while processing route: index permission_denied at /entries: Client doesn't have permission to access the desired data. Error: permission_denied at /entries: Client doesn't have permission to access the desired data.

此时我不确定我应该做什么 –– 我是否需要构建自定义 URL 或在我的 firebase 适配器中添加命名空间以添加 users/xxx 前缀?或者等等?

找不到任何 documentation/tutorials/walkthroughs 涵盖 public read/write 数据以外的任何内容。

我最终完成了这项工作。它基本上归结为在登录后将来自 Firebase auth 的 uid 存储在服务中(我添加 ember-local-storage 以防页面刷新),然后向应用程序适配器添加 pathForType 方法以将所有用户数据嵌套在 users/$ 下{uid},因此在 firebase 中,数据以这种配置结束:users/${uid}/entries/${entry_id}.

application/adapter.js

import FirebaseAdapter from 'emberfire/adapters/firebase';
import Ember from 'ember';
export default FirebaseAdapter.extend({

    /* inject service to access uid */
  journalist: Ember.inject.service('journalist'),

    /* path for type nests /entries under users/${uid} */
    pathForType(type) {
      let uid =  this.get('journalist.uid');
      let path = Ember.String.pluralize(type);
    return  `users/${uid}/${path}`;
   }

});

application/route.js

import Ember from 'ember';

export default Ember.Route.extend({

    /* injecting service to set uid */
  journalist: Ember.inject.service('journalist'),

  beforeModel() {
    return this.get('session').fetch().catch();
  },
  actions: {
    signIn(provider) {
      this.get('session').open('firebase', {provider: provider}).then(data => {

        /* setting uid in service for later retrieval elsewhere */
        this.get('journalist').setUID(data.uid);
        this.transitionTo('entries');
    });
    },
    signOut() {
      this.get('session').close().then(() => this.transitionTo('application'));

    }
  }
});

entries/route.js

import Ember from 'ember';
export default Ember.Route.extend({

    /* nothing special required for ember data save, findAll, etc, adapter takes care of everything */
    model() {
        return this.store.findAll('entry');
    }
});

services/journalist.js:

import Ember from 'ember';
import { storageFor } from 'ember-local-storage';
export default Ember.Service.extend({
    uid: null,
    localStore: storageFor('journalist-session'),
    init() {
        const localStore = this.get('localStore');
    this.set('uid', localStore.get('uid'));
  },
    setUID(id) {
        this.set('uid', id);
        this.set('localStore.uid', id);
    }
});

storages/journalist-session:

import StorageObject from 'ember-local-storage/local/object';
const Storage = StorageObject.extend();
 Storage.reopenClass({
   initialState() {
     return {
       uid: null
     };
   }
 });
export default Storage;

firebase 规则:

{
  "rules": {
    "users": {
      "$uid": {
        ".read": "auth != null && auth.uid == $uid",
        ".write": "auth != null && auth.uid == $uid"
      }
    }
  }
}