feat: complete fine-grained RBAC rules across all roles
All checks were successful
Build and Deploy / build-and-push (push) Successful in 1m52s

- Restricted Agent view to own dashboard and hid management tabs.

- Allowed Managers to create teams and members but restricted them from editing roles or emails.

- Allowed Admins to update their own email via profile.

- Protected Admin roles from being modified by anyone other than Super Admins.
This commit is contained in:
Cauê Faleiros
2026-03-06 13:27:43 -03:00
parent 2e766bd197
commit 38eb55793f
6 changed files with 66 additions and 43 deletions

View File

@@ -14,6 +14,7 @@ export const UserProfile: React.FC = () => {
const [name, setName] = useState('');
const [bio, setBio] = useState('');
const [email, setEmail] = useState('');
useEffect(() => {
const fetchUserAndTenant = async () => {
@@ -25,6 +26,7 @@ export const UserProfile: React.FC = () => {
setUser(fetchedUser);
setName(fetchedUser.name);
setBio(fetchedUser.bio || '');
setEmail(fetchedUser.email);
// Fetch tenant info
const tenants = await getTenants();
@@ -85,10 +87,10 @@ export const UserProfile: React.FC = () => {
setIsSuccess(false);
try {
const success = await updateUser(user.id, { name, bio });
const success = await updateUser(user.id, { name, bio, email });
if (success) {
setIsSuccess(true);
setUser({ ...user, name, bio });
setUser({ ...user, name, bio, email });
setTimeout(() => setIsSuccess(false), 3000);
} else {
alert('Erro ao salvar alterações no servidor.');
@@ -107,6 +109,8 @@ export const UserProfile: React.FC = () => {
const displayAvatar = user.avatar_url
? (user.avatar_url.startsWith('http') ? user.avatar_url : `${backendUrl}${user.avatar_url}`)
: `https://ui-avatars.com/api/?name=${encodeURIComponent(user.name)}&background=random`;
const canEditEmail = user.role === 'admin' || user.role === 'super_admin';
return (
<div className="max-w-4xl mx-auto space-y-6 pb-12 transition-colors duration-300">
@@ -213,12 +217,17 @@ export const UserProfile: React.FC = () => {
<input
type="email"
id="email"
value={user.email}
disabled
className="block w-full pl-10 pr-3 py-2 border border-zinc-200 dark:border-zinc-800 rounded-lg bg-zinc-50 dark:bg-zinc-900/50 text-zinc-500 dark:text-zinc-500 cursor-not-allowed sm:text-sm"
value={email}
onChange={(e) => setEmail(e.target.value)}
disabled={!canEditEmail}
className={`block w-full pl-10 pr-3 py-2 border border-zinc-200 dark:border-zinc-800 rounded-lg sm:text-sm transition-all ${
!canEditEmail
? 'bg-zinc-50 dark:bg-zinc-900/50 text-zinc-500 dark:text-zinc-500 cursor-not-allowed'
: 'bg-white dark:bg-zinc-950 text-zinc-900 dark:text-zinc-100 placeholder-zinc-400 dark:placeholder-zinc-600 focus:outline-none focus:ring-2 focus:ring-brand-yellow/20 focus:border-brand-yellow'
}`}
/>
</div>
<p className="text-xs text-zinc-400 dark:text-zinc-500 mt-1">Contate o admin para alterar o e-mail.</p>
{!canEditEmail && <p className="text-xs text-zinc-400 dark:text-zinc-500 mt-1">Contate o admin para alterar o e-mail.</p>}
</div>
</div>