| name | obsidian-enterprise-rbac |
| description | Implement team vault access patterns and role-based controls.
Use when managing shared vaults, implementing access controls,
or building team collaboration features for Obsidian.
Trigger with phrases like "obsidian team", "obsidian access control",
"obsidian enterprise", "shared vault permissions".
|
| allowed-tools | Read, Write, Edit |
| version | 1.0.0 |
| license | MIT |
| author | Jeremy Longshore <jeremy@intentsolutions.io> |
Obsidian Enterprise RBAC
Overview
Implement role-based access control patterns for team vaults and shared Obsidian environments.
Prerequisites
- Understanding of RBAC concepts
- Multi-user vault setup
- Backend service for authentication (optional)
Access Control Concepts
Role Hierarchy
| Role | Read | Write | Delete | Admin | Settings |
|---|
| Viewer | Yes | No | No | No | No |
| Editor | Yes | Yes | No | No | No |
| Contributor | Yes | Yes | Own | No | No |
| Manager | Yes | Yes | Yes | No | View |
| Admin | Yes | Yes | Yes | Yes | Full |
Folder-Based Permissions
vault/
├── public/ # All roles can read
├── team/ # Editors+ can read/write
├── projects/
│ ├── project-a/ # Project members only
│ └── project-b/ # Project members only
├── management/ # Managers+ only
└── admin/ # Admins only
Instructions
Step 1: Permission System
export type Role = 'viewer' | 'editor' | 'contributor' | 'manager' | 'admin';
export type Permission = 'read' | 'write' | 'delete' | 'admin' | 'settings';
export interface User {
id: string;
name: string;
email: string;
role: Role;
teamIds: string[];
projectIds: string[];
}
export interface FolderPermission {
path: string;
allowedRoles: Role[];
allowedTeams?: string[];
allowedUsers?: string[];
}
const rolePermissions: Record<Role, Permission[]> = {
viewer: ['read'],
editor: ['read', 'write'],
contributor: [, , ],
: [, , , ],
: [, , , , ],
};
{
: | = ;
: [] = [];
(: ): {
. = user;
}
(: []): {
. = permissions;
}
(: ): {
(!.) ;
rolePermissions[..].(permission);
}
(: ): {
(!.) ;
(.. === ) ;
folderPerm = .(path);
(!folderPerm) ;
(folderPerm..(..)) {
;
}
(folderPerm.) {
hasTeam = folderPerm..(
.!..(teamId)
);
(hasTeam) ;
}
(folderPerm.) {
(folderPerm..(..)) {
;
}
}
;
}
(: ): {
.() && .(path);
}
(: ): {
.() && .(path);
}
(: , ?: ): {
(!.) ;
(.. === ) {
ownerId === .. && .(path);
}
.() && .(path);
}
(: ): | {
: | = ;
matchLength = ;
( perm .) {
(path.(perm.) && perm.. > matchLength) {
match = perm;
matchLength = perm..;
}
}
match;
}
}
Step 2: Protected Operations Wrapper
import { App, TFile, Notice } from 'obsidian';
import { PermissionService } from './permissions';
export class ProtectedVault {
constructor(
private app: App,
private permissions: PermissionService
) {}
async readFile(file: TFile): Promise<string | null> {
if (!this.permissions.canReadFile(file.path)) {
new Notice('Permission denied: Cannot read this file');
return null;
}
return this.app.vault.read(file);
}
async writeFile(file: TFile, content: string): Promise<boolean> {
(!..(file.)) {
();
;
}
...(file, content);
;
}
(: , : ): < | > {
(!..(path)) {
();
;
}
...(path, content);
}
(: , ?: ): <> {
(!..(file., ownerId)) {
();
;
}
...(file);
;
}
(): [] {
...().(
..(file.)
);
}
}
Step 3: User Management
import { Plugin } from 'obsidian';
export interface TeamConfig {
id: string;
name: string;
members: string[];
folders: string[];
}
export interface RBACConfig {
enabled: boolean;
users: Record<string, {
role: Role;
teams: string[];
}>;
teams: TeamConfig[];
folderPermissions: FolderPermission[];
}
export class UserManager {
private config: RBACConfig;
private plugin: Plugin;
constructor(plugin: Plugin) {
this.plugin = plugin;
this.config = this.loadConfig();
}
private loadConfig(): {
{
: ,
: {},
: [],
: [],
};
}
(): | {
userId = .();
(!userId) ;
userConfig = ..[userId];
(!userConfig) ;
{
: userId,
: .(userId),
: .(userId),
: userConfig.,
: userConfig.,
: .(userId),
};
}
(): | {
.();
}
(: ): {
userId;
}
(: ): {
;
}
(: ): [] {
[];
}
(): [] {
..;
}
(): [] {
..;
}
(: , : , : []): <> {
..[userId] = { role, teams };
.();
}
(: , : ): <> {
(..[userId]) {
..[userId]. = role;
.();
}
}
(: ): <> {
...(permission);
.();
}
(): <> {
}
}
Step 4: Audit Logging
export interface AuditEntry {
timestamp: string;
userId: string;
action: 'read' | 'write' | 'delete' | 'permission_denied' | 'login' | 'logout';
resource: string;
details?: Record<string, any>;
success: boolean;
}
export class AuditLogger {
private entries: AuditEntry[] = [];
private maxEntries = 1000;
log(entry: Omit<AuditEntry, 'timestamp'>): void {
const fullEntry: AuditEntry = {
...entry,
timestamp: new Date().toISOString(),
};
this.entries.push(fullEntry);
if (this.entries.length > .) {
. = ..(-.);
}
.(, {
: fullEntry.,
: fullEntry.,
});
}
(: , : , : | | , : ): {
.({
userId,
action,
: path,
success,
});
}
(: , : , : ): {
.({
userId,
: ,
: path,
: { requestedAction },
: ,
});
}
(?: {
?: ;
?: [];
?: ;
}): [] {
results = [....];
(filter?.) {
results = results.( e. === filter.);
}
(filter?.) {
results = results.( e. === filter.);
}
(filter?.) {
results = results.(
(e.) >= filter.!
);
}
results;
}
(): [] {
..( e. === );
}
(): {
.(., , );
}
}
Step 5: UI Integration
import { App, Modal, Setting } from 'obsidian';
import { Role, User, PermissionService } from './permissions';
export class UserRoleModal extends Modal {
private user: User;
private onSave: (role: Role) => void;
constructor(app: App, user: User, onSave: (role: Role) => void) {
super(app);
this.user = user;
this.onSave = onSave;
}
onOpen() {
const { contentEl } = this;
contentEl.empty();
contentEl.createEl('h2', { text: `Edit User: ${this.user.name}` });
new (contentEl)
.()
.()
.( {
dropdown
.(, )
.(, )
.(, )
.(, )
.(, )
.(..)
.( {
.. = value ;
});
});
(contentEl)
.( btn
.()
.()
.( {
.(..);
.();
}))
.( btn
.()
.( .()));
}
}
(): {
user = permissions.();
(!user) ;
statusBar = plugin.();
statusBar.();
statusBar.();
}
Output
- Role-based permission system
- Folder-level access control
- Protected vault operations
- Audit logging
- User management UI
Error Handling
| Issue | Cause | Solution |
|---|
| Permission denied | Insufficient role | Check role assignment |
| User not found | Auth not configured | Set up user management |
| Folder access blocked | Team not assigned | Add user to team |
| Audit log full | No rotation | Implement log rotation |
Examples
Configuration File
enabled: true
users:
alice:
role: admin
teams: [management, engineering]
bob:
role: editor
teams: [engineering]
charlie:
role: viewer
teams: [support]
teams:
- id: management
name: Management
folders: [management/, projects/]
- id: engineering
name: Engineering
folders: [engineering/, projects/]
- id: support
name: Support
folders: [support/, public/]
folderPermissions:
- path: public/
allowedRoles: [viewer, editor, contributor, manager, admin]
-
[, ]
[]
[]
Resources
Next Steps
For major migrations, see obsidian-migration-deep-dive.