FluidFrameDev/tutorials/03-server-modules-security.md

87 lines
1.9 KiB
Markdown
Raw Normal View History

**`tutorials/03-server-modules-security.md`**
````markdown
# 03 — Server Modules & Security
## Roles & Helper
```python
import anvil.server
from anvil import users, secrets
ROLES = {"viewer","editor","admin"}
def require_role(*roles):
u = users.get_user()
if not u: raise PermissionError("Login required")
if not set(roles).intersection(set(u.get('roles', []))):
raise PermissionError("Insufficient role")
````
## Validated Callable
```python
@anvil.server.callable
def secure_greet(name):
name = (name or "").strip()
if not (1 <= len(name) <= 64): raise ValueError("Bad name")
return f"Top-secret hello, {name}"
```
## Secrets + Fake External
```python
API_KEY = secrets.get_secret('DEMO_API_KEY') # set in Anvil
```
## Simple Rate Limit (per user)
Use a module-level dict `{user_id: [timestamps...]}`; trim to last 60s, allow ≤5.
## Client UX
* Try/catch PermissionError → Notification("You need editor role").
* Disable button while awaiting server.
````
**`tutorials/04-uplink-file-hash.md`**
```markdown
# 04 — Uplink: Local File Hash
## Uplink Script (local)
```python
import anvil.server, hashlib
@anvil.server.callable("hash_file")
def hash_file(buffer):
h = hashlib.sha256(buffer.get_bytes())
return h.hexdigest()
anvil.server.connect("YOUR-UPLINK-KEY")
anvil.server.wait_forever()
````
## Client
* FileLoader → `file_loader_1_change`: call `hash_file` with the Media object.
* Show result; if timeout/conn error → “Uplink offline”.
````
**`tutorials/05-auth-roles-ui.md`**
```markdown
# 05 — Auth: Users + Roles + UI Gating
## Setup
Enable Users service. Add roles to users (e.g., `editor`, `admin`).
## Server
Use `require_role` from Tutorial 03 to gate `dangerous_action`.
## Client
- Add Login/Logout buttons.
- Show current user + roles.
- Hide/show editor-only actions via `component.visible`.
## Demo Flow
- Viewer logs in → cant see editor actions.
- Editor logs in → sees & runs gated action.
````