87 lines
1.9 KiB
Markdown
87 lines
1.9 KiB
Markdown
|
**`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 → can’t see editor actions.
|
|||
|
- Editor logs in → sees & runs gated action.
|
|||
|
````
|