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

1.9 KiB
Raw Blame History

tutorials/03-server-modules-security.md

# 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

@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

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.