2017-03-02 32 views
7

ReactとRedux(Node.jsバックエンドを使用)で1ページのアプリケーションを作成しています。ユーザーの役割に応じてReactコンポーネントの子を非表示にする

ロールベースのアクセス制御を実装したいと思います。アプリケーションの特定の部分(またはサブ部分)の表示を制御したいと考えています。私はこのような構造を持つだけのオブジェクトであるのNode.js、より権限のリストを取得するつもりです

{ 
    users: 'read', 
    models: 'write', 
    ... 
    dictionaries: 'none', 
} 

キー保護されたリソースを、

は、ユーザー権限でありますこのリソース(none,read,writeのいずれか)。

私はそれを還元状態に保管しています。十分に簡単だと思われる。

nonereact-routerルートonEnter/onChangeフックまたはredux-auth-wrapperによって許可が確認されます。それも簡単だね。

read/writeのアクセス許可をどのコンポーネントビューにも適用するにはどのような方法が良いですか(たとえば、ユーザーが{ models: 'read' }権限を持っている場合は、モデルコンポーネントの編集ボタンを非表示にします)。

私はthis solutionを見つけたし、私の仕事のためにそれを少し変更します。

class Check extends React.Component { 
    static propTypes = { 
    resource: React.PropTypes.string.isRequired, 
    permission: React.PropTypes.oneOf(['read', 'write']), 
    userPermissions: React.PropTypes.object, 
    }; 

    // Checks that user permission for resource is the same or greater than required 
    allowed() { 
    const permissions = ['read', 'write']; 
    const { permission, userPermissions } = this.props; 
    const userPermission = userPermissions[resource] || 'none'; 

    return permissions.indexOf(userPermission) >= permissions.indexOf(permission) 
    } 

    render() { 
    if (this.allowed()) return { this.props.children }; 
    } 
} 

export default connect(userPermissionsSelector)(Check) 

userPermissionsSelectorはこのようなものになるだろう。ここで(store) => store.userPermisisonsとユーザー権限オブジェクトを返します。その後

Checkで保護された要素ラップ:ユーザーがmodelsボタンのwrite許可は表示されませんがない場合はそう

<Check resource="models" permission="write"> 
    <Button>Edit model</Button> 
</Check> 

を。

誰もこのようなことをしましたか?これ以上の "エレガントな"ソリューションはありますか?

ありがとうございました!

P.S.もちろん、サーバー側でもユーザー権限がチェックされます。

+0

が:)してください。私はユーザーに基づいて制限された管理ページを持っていました。あなたがやっていることは基本的に私がやったことです。私はバックエンドとしてPHPを使用し、PHPセッションをチェックすることでそれを検証しました(ベストではなく、私が知っていた/うまく機能していました)。そしてそれはうまくページを隠しました。あなたのソリューションがうまくいけば、私はあまり気にしませんが、レンダリングで 'else'ステートメントを'あなたはこのページへのアクセス権がありません。ページが壊れていると思っているのではなく、何かを見ることができます。 –

+0

ありがとうございますが、すでに開いているページの 'edit'や 'delete'ボタンのようなアクションコントロールを非表示にしたいので、 'else'ステートメントは不要です。 –

+0

あなたが '{exists &&

some stuff
}'のような行為をして存在していれば、divは存在しないでしょう( 'display:none'だけではありません) –

答えて

2

私はあなたが望むものを理解していると思います。私は私のために働く何かをして、私はそれを持っている方法が好きですが、他の実行可能な解決策がそこにあることを理解します。

私が書いたのは、HOC反応ルータスタイルでした。

基本的には私が許可を持っています私はユーザーのアクセス許可を初期化します。私は別のものを持っていますwithPermissions私は以前私のコンポーネントに提供した権限を注入するHOCです。

その特定のコンポーネントでアクセス許可をチェックする必要がある場合は、簡単にアクセスできます。

// PermissionsProvider.js 
import React, { Component } from "react"; 
import PropTypes from "prop-types"; 
import hoistStatics from "hoist-non-react-statics"; 

class PermissionsProvider extends React.Component { 
    static propTypes = { 
    permissions: PropTypes.array.isRequired, 
    }; 

    static contextTypes = { 
    permissions: PropTypes.array, 
    }; 

    static childContextTypes = { 
    permissions: PropTypes.array.isRequired, 
    }; 

    getChildContext() { 
    // maybe you want to transform the permissions somehow 
    // maybe run them through some helpers. situational stuff 
    // otherwise just return the object with the props.permissions 
    // const permissions = doSomething(this.props.permissions); 
    // maybe add some validation methods 
    return { permissions: this.props.permissions }; 
    } 

    render() { 
    return React.Children.only(this.props.children); 
    } 
} 

const withPermissions = Component => { 
    const C = (props, context) => { 
    const { wrappedComponentRef, ...remainingProps } = props; 

    return (
     <Component permissions={context.permissions} {...remainingProps} ref={wrappedComponentRef} /> 
    ); 
    }; 

    C.displayName = `withPermissions(${Component.displayName || Component.name})`; 
    C.WrappedComponent = Component; 
    C.propTypes = { 
    wrappedComponentRef: PropTypes.func 
    }; 

    C.contextTypes = { 
    permissions: PropTypes.array.isRequired 
    }; 

    return hoistStatics(C, Component); 
}; 

export { PermissionsProvider as default, withPermissions }; 

いいえこれは多くのコードです。しかし、これらはHOCです(詳細はhereをご覧ください)。

上位コンポーネント(HOC)は、コンポーネントロジックを再利用するためのReactの高度な技術です。 HOCはそれ自体React APIの一部ではありません。 これらはReactの構成上の性質から現れるパターンです。 具体的には、上位コンポーネントは、 コンポーネントを受け取り、新しいコンポーネントを返す関数です。

基本的に私は反応ルータが何をしたかに触発されたので、これを行いました。 あなたはちょうどデコレータ@withRouterを追加することができますし、彼らはあなたのコンポーネントに小道具を注入し、いくつかのルーティングのものを知りたい時はいつでも。 なぜ同じことをしないのですか?

  1. セットアッププロバイダ
  2. と権限が次にあなたが権限どこかSomeStuff内部

//App render 
return (
    <PermissionsProvider permissions={permissions}> 
     <SomeStuff /> 
    </PermissionsProvider> 
); 

をチェックコンポーネントのwithPermissionsデコレータを使用する必要があります。まず、権限をチェックする広く普及しているツールバーがありますか?

@withPermissions 
export default class Toolbar extends React.Component { 
    render() { 
    const { permissions } = this.props; 

    return permissions.canDoStuff ? <RenderStuff /> : <HeCantDoStuff />; 
    } 
} 

あなたはデコレータを使用できない場合は、ここでは、この

export default withPermissions(Toolbar); 

のようなツールバーをエクスポートするには、私が実際にそれを示したcodesandboxです:

https://codesandbox.io/s/lxor8v3pkz

注:

  • 私は実際にはパーミッションを単純化しました。なぜならそのロジックはあなたの目的であり、デモのために単純化したからです。
  • 私はHOCのPropTypes.arrayをチェックする理由で、アクセス権が配列であると仮定しました
  • これは本当に長く複雑な答えです。私は最高の能力で明確にしようとしました。私はここにいくつかのミスをグリルないと私は前にこのような何かをやった
+0

@AntonNovikあなたの状況はどうですか? – Lokuzt

関連する問題