この記事の対象読者
- 管理画面を作る人
- 権限ごとの表示制御を実装する人
- フロントだけで権限制御してよいか迷う人
本題に入る前に
管理画面で「削除」や「権限変更」ボタンを出すとき、権限がないユーザーには隠すべきでしょうか。
それとも、押せない状態で見せるべきでしょうか。
どちらもありそうで、意外と迷いますよね。CSや管理者から見ると、「ボタンがない」のと「押せない理由が分かる」のでは受け取り方が違います。
この記事では、Reactの画面表示とAPI側の認可を分けて考えます。
フロントの制御はUXのため
まず大事なのは、フロントエンドの表示制御だけで認可を完結させないことです。
画面でボタンを隠すのは、ユーザー体験のためです。
本当に実行してよいかは、API側で必ず確認します。
権限判定を関数にする
たとえば、ユーザー削除の権限を判定します。
type Permission = "user:read" | "user:delete" | "role:update";
type CurrentUser = {
id: string;
permissions: Permission[];
};
function canDeleteUser(currentUser: CurrentUser) {
return currentUser.permissions.includes("user:delete");
}
画面ではこう使います。
function DeleteUserButton({ currentUser }: { currentUser: CurrentUser }) {
if (!canDeleteUser(currentUser)) {
return (
<button type="button" disabled title="削除権限がありません">
削除
</button>
);
}
return <button type="button">削除</button>;
}
隠すのではなくdisabledで見せると、「この操作は存在するが、自分には権限がない」と分かります。
隠すか、押せなくするか
使い分けの目安です。
| 見せ方 | 向いているケース |
|---|---|
| 隠す | その人に関係ない機能 |
| disabledで見せる | 権限があれば使えることを知らせたい機能 |
| 押した後に403 | 権限が変わりやすい、APIで最終確認したい機能 |
削除や権限変更のような重要操作は、画面で制御していてもAPI側で403を返せるようにします。
async function deleteUserHandler(currentUser: CurrentUser, targetUserId: string) {
if (!canDeleteUser(currentUser)) {
return {
status: 403,
body: {
errorCode: "FORBIDDEN",
message: "削除権限がありません",
},
};
}
return {
status: 200,
body: { deletedUserId: targetUserId },
};
}
CS目線では理由があると助かる
問い合わせ対応では、「なぜ操作できないのか」が分かると助かります。
削除ボタンが押せません
だけだと、バグなのか権限なのか分かりません。
削除権限がありません。管理者に権限付与を依頼してください。
と出ていれば、次の案内がしやすくなります。
まとめ
権限がないボタンを隠すか、押せなくするかは、ユーザーに何を伝えたいかで決めます。
ただし、本当の認可はAPI側で必ず見る。フロントはUX、APIは安全性。
この役割分担を意識すると、管理画面の権限制御はかなり整理しやすくなります。