新增角色

1-新增角色包( https://github.com/alanning/meteor-roles)

meteor add alanning:roles

2-建立一些角色常量。在檔案 imports / api / accounts / roles.js 中

const ROLES = {
  ROLE1: 'ROLE1',
  ROLE2: 'ROLE2',
  ADMIN: 'ADMIN'
};

export default ROLES;

3-我不會展示如何在使用者上新增/更新角色,只需提及在伺服器端,你可以通過 Roles.setUserRoles(user.id, roles); 設定使用者角色在 https://github.com/alanning/meteor-roles 中檢視更多資訊和 http://alanning.github.io/meteor-roles/classes/Roles.html

4-假設你已經設定了所有帳戶和角色檔案(請參閱 https://github.com/rafa-lft/Meteor_React_Base 中的完整示例。查詢標籤 Step4_roles )我們現在可以建立一個負責允許的方法(或不)訪問不同的路線。在 imports / startup / client / Routes.jsx 中

class Routes extends Component {
  constructor(props) {
    super(props);
  }

  authenticate(roles, nextState, replace) {
    if (!Meteor.loggingIn() && !Meteor.userId()) {
      replace({
        pathname: '/login',
        state: {nextPathname: nextState.location.pathname}
      });
      return;
    }
    if ('*' === roles) { // allow any logged user
      return;
    }
    let rolesArr = roles;
    if (!_.isArray(roles)) {
      rolesArr = [roles];
    }
    // rolesArr = _.union(rolesArr, [ROLES.ADMIN]);// so ADMIN has access to everything
    if (!Roles.userIsInRole(Meteor.userId(), rolesArr)) {
      replace({
        pathname: '/forbidden',
        state: {nextPathname: nextState.location.pathname}
      });
    }
  }

  render() {
    return (
      <Router history={ browserHistory }>
        <Route path="/" component={ App }>
          <IndexRoute name="index" component={ Index }/>
          <Route name="login" path="/login" component={ Login }/>
          <Route name="signup" path="/signup" component={ Signup }/>

          <Route name="users" path="/users" component={ Users }/>

          <Route name="editUser" path="/users/:userId" component={ EditUser }
                 onEnter={_.partial(this.authenticate, ROLES.ADMIN)} />

          {/* ********************
           Below links are there to show Roles authentication usage.
           Note that you can NOT hide them by
           { Meteor.user() && Roles.userIsInRole(Meteor.user(), ROLES.ROLE1) &&
           <Route name=.....
           }
           as doing so will change the Router component on render(), and ReactRouter will complain with:
           Warning: [react-router] You cannot change <Router routes>; it will be ignored

           Instead, you can/should hide them on the NavBar.jsx component... don't worry: if someone tries to access
           them, they will receive the Forbidden.jsx component
           *************/ }
          <Route name="forAnyOne" path="/for_any_one" component={ ForAnyone }/>

          <Route name="forLoggedOnes" path="/for_logged_ones" component={ ForLoggedOnes }
                 onEnter={_.partial(this.authenticate, '*')} />

          <Route name="forAnyRole" path="/for_any_role" component={ ForAnyRole }
                 onEnter={_.partial(this.authenticate, _.keys(ROLES))}/>

          <Route name="forRole1or2" path="/for_role_1_or_2" component={ ForRole1or2 }
                 onEnter={_.partial(this.authenticate, [ROLES.ROLE1, ROLES.ROLE2])} />

          <Route name="forRole1" path="/for_role1" component={ ForRole1 }
                 onEnter={_.partial(this.authenticate, ROLES.ROLE1)}/>

          <Route name="forRole2" path="/for_role2" component={ ForRole2 }
                 onEnter={_.partial(this.authenticate, ROLES.ROLE2)} />

          <Route name="forbidden" path="/forbidden" component={ Forbidden }/>

          <Route path="*" component={ NotFound }/>
        </Route>
      </Router>
    );
  }
}

我們在某些路線上新增了一個 onEnter 觸發器。對於那些路線,我們也通過允許哪些角色進入。請注意,onEnter 回撥最初接收 2 個引數。我們使用下劃線的部分( http://underscorejs.org/#partial) ,新增另一個(角色) authenticate 方法(由 onEnter 呼叫)接收角色,並且:

  • 檢查使用者是否完全登入。如果沒有,請重定向到’/ login’。
  • 如果 role ===’*‘我們假設任何登入使用者都可以輸入,所以我們允許它
  • 否則,我們驗證是否允許使用者(Roles.userIsInRole),如果不允許,我們重定向到禁止。
  • (可選)你可以取消註釋一行,以便 ADMIN 可以訪問所有內容。

該程式碼包含幾個允許任何人(不允許 onEnter 回撥),任何已記錄使用者,任何具有至少 1 個角色的已記錄使用者以及特定角色的路徑的示例。

另請注意,ReactRouter(至少在版本 3 上)不允許在 Render 上修改路由。因此,你無法隱藏 Routes.jsx 中的路由。因此,我們在 authenticate 方法中重定向到/禁止。

5- ReactRouter 和 Meteor 的常見錯誤,與未顯示的使用者狀態更新有關。例如,使用者已登出,但我們仍在導航欄上顯示他/她的名字。這是因為 Meteor.user() 發生了變化,但我們沒有重新渲染。

可以通過在 createContainer 中呼叫 Meteor.user() 來解決該錯誤。以下是 import / ui / layouts / NavBar.jsx 中使用的示例:

export default createContainer((/* {params}*/) =>{
  Meteor.user(); // so we render again in logout or if any change on our User (ie: new roles)
  const loading = !subscription.ready();
  return {subscriptions: [subscription], loading};
}, NavBar);

注意:

  • 我正在跳過你需要的其他檔案,以縮短時間。具體來說,檢查 imports / startup / server / index.js imports / ui / layouts / {App,NavBar} .jsx 和 import / ui / pages / {Login,Signup,Users,EditUser} .jsx

  • 你可以在 https://github.com/rafa-lft/Meteor_React_Base 中檢視完整示例。尋找標籤 Step4_roles