104 lines
3.9 KiB
Markdown
104 lines
3.9 KiB
Markdown
# UniFi MongoDB Admin Schema (v10.0.162)
|
|
|
|
## Database: `ace`
|
|
|
|
### `admin` Collection — Admin Accounts
|
|
|
|
| Field | Type | Required | Description |
|
|
|---|---|---|---|
|
|
| `_id` | ObjectId | auto | MongoDB ID |
|
|
| `name` | string | yes | Display name |
|
|
| `email` | string | yes | Login email (username) |
|
|
| `x_shadow` | string | yes | SHA-512 crypt password hash (`$6$salt$hash`) |
|
|
| `time_created` | int32 (epoch) | yes | Account creation timestamp |
|
|
| `last_site_name` | string | no | Last site accessed (set on login) |
|
|
| `super_site_permissions` | array | **yes** | Must be `["super"]` for super admin |
|
|
| `super_site_role` | string | **yes** | Must be `"super"` |
|
|
| `is_super` | bool | **yes** | Must be `true` |
|
|
| `last_login_timestamp` | int64 (epoch ms) | auto | Set on login |
|
|
| `last_login_ip` | string | auto | Set on login |
|
|
| `ui_settings` | object | auto | `{"preferredLanguage":"en"}` etc. |
|
|
| `ui_version` | string | auto | UI version string |
|
|
| `email_alert_enabled` | bool | no | Email notifications |
|
|
| `is_owner` | bool | auto | Set to `true` on first admin |
|
|
|
|
**Critical:** Without `super_site_permissions: ["super"]`, `super_site_role: "super"`, and `is_super: true`, the admin will log in but see an empty dashboard even if the database has devices and configs.
|
|
|
|
### `privilege` Collection — Site Access Control
|
|
|
|
| Field | Type | Required | Description |
|
|
|---|---|---|---|
|
|
| `_id` | ObjectId | auto | MongoDB ID |
|
|
| `admin_id` | ObjectId | **yes** | References `admin._id` — MUST be ObjectId, NOT string |
|
|
| `site_id` | ObjectId | **yes** | References `site._id` — MUST be ObjectId, NOT string |
|
|
| `role` | string | **yes** | `"SUPER_ADMIN"` or `"ADMIN"` |
|
|
| `permissions` | array | yes | `["ALL"]` for full access |
|
|
| `is_super` | bool | **yes** | `true` for super admin |
|
|
|
|
**Critical pitfall:** Using `.str` on ObjectIds when inserting privileges (e.g., `admin._id.str` instead of `admin._id`) creates string references that don't match. The admin logs in but sees NO data — exactly the "no content on screen" symptom.
|
|
|
|
### `site` Collection
|
|
|
|
| Field | Type | Description |
|
|
|---|---|---|
|
|
| `_id` | ObjectId | Site ID |
|
|
| `name` | string | `"super"` or `"default"` |
|
|
| `desc` | string | Description |
|
|
| `attr_hidden_id` | string | Internal site key |
|
|
| `attr_hidden` | bool | `true` for "super" site |
|
|
| `attr_no_delete` | bool | `true` for both default sites |
|
|
|
|
A fresh `jacobalberty/unifi` deploy creates two sites automatically: `"super"` (hidden) and `"default"`.
|
|
|
|
### Full Admin Creation Script
|
|
|
|
```javascript
|
|
db = db.getSiblingDB("ace");
|
|
|
|
// 1. Generate hash externally: openssl passwd -6 'password'
|
|
var hash = "$6$salt$hash";
|
|
var now = Math.floor(new Date().getTime() / 1000);
|
|
|
|
// 2. Create admin
|
|
var result = db.admin.insertOne({
|
|
name: "Admin Name",
|
|
email: "admin@example.com",
|
|
x_shadow: hash,
|
|
time_created: now,
|
|
last_site_name: "default",
|
|
super_site_permissions: ["super"],
|
|
super_site_role: "super",
|
|
is_super: true
|
|
});
|
|
|
|
// 3. Create privileges for ALL sites
|
|
var admin = db.admin.findOne({email: "admin@example.com"});
|
|
var sites = db.site.find({}).toArray();
|
|
sites.forEach(function(site) {
|
|
db.privilege.insertOne({
|
|
admin_id: admin._id, // ObjectId, NOT .str
|
|
site_id: site._id, // ObjectId, NOT .str
|
|
role: "SUPER_ADMIN",
|
|
permissions: ["ALL"],
|
|
is_super: true
|
|
});
|
|
});
|
|
|
|
print("Admin created: " + admin._id);
|
|
print("Privileges: " + db.privilege.count());
|
|
```
|
|
|
|
### Verifying Permissions After Login
|
|
|
|
```bash
|
|
# Login
|
|
curl -sk -c /tmp/uf-cookie -X POST https://localhost:8443/api/login \
|
|
-H "Content-Type: application/json" \
|
|
-d '{"username":"admin@example.com","password":"password"}'
|
|
|
|
# Check self — should show is_super:true
|
|
curl -sk -b /tmp/uf-cookie https://localhost:8443/api/self | python3 -m json.tool
|
|
```
|
|
|
|
If `is_super` is `false` or `super_site_permissions` is `[]`, the MongoDB update didn't take — likely the admin document was overwritten by the login process or the update used the wrong query.
|