added path security, documented api endpoints
This commit is contained in:
parent
54df891e94
commit
8d78c278ee
|
|
@ -783,7 +783,8 @@ async def get_notes_by_tag_endpoint(tag_name: str):
|
|||
# --- Template Endpoints ---
|
||||
|
||||
@api_router.get("/templates")
|
||||
async def list_templates():
|
||||
@limiter.limit("120/minute")
|
||||
async def list_templates(request: Request):
|
||||
"""
|
||||
List all available templates from _templates folder.
|
||||
|
||||
|
|
@ -798,7 +799,8 @@ async def list_templates():
|
|||
|
||||
|
||||
@api_router.get("/templates/{template_name}")
|
||||
async def get_template(template_name: str):
|
||||
@limiter.limit("120/minute")
|
||||
async def get_template(request: Request, template_name: str):
|
||||
"""
|
||||
Get content of a specific template.
|
||||
|
||||
|
|
|
|||
|
|
@ -668,9 +668,19 @@ def get_templates(notes_dir: str) -> List[Dict]:
|
|||
if not templates_path.exists():
|
||||
return templates
|
||||
|
||||
# Security check: ensure _templates folder is within notes directory
|
||||
if not validate_path_security(notes_dir, templates_path):
|
||||
print(f"Security: Templates directory is outside notes directory: {templates_path}")
|
||||
return templates
|
||||
|
||||
try:
|
||||
for template_file in templates_path.glob("*.md"):
|
||||
try:
|
||||
# Security check: ensure each template is within notes directory
|
||||
if not validate_path_security(notes_dir, template_file):
|
||||
print(f"Security: Skipping template outside notes directory: {template_file}")
|
||||
continue
|
||||
|
||||
stat = template_file.stat()
|
||||
templates.append({
|
||||
"name": template_file.stem,
|
||||
|
|
|
|||
|
|
@ -295,6 +295,120 @@ Self-documenting endpoint listing all available API routes.
|
|||
|
||||
---
|
||||
|
||||
## 🏷️ Tags
|
||||
|
||||
### List All Tags
|
||||
`GET /api/tags`
|
||||
|
||||
Returns all tags found in notes with their usage counts.
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"tags": {
|
||||
"python": 5,
|
||||
"tutorial": 3,
|
||||
"backend": 2
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Get Notes by Tag
|
||||
`GET /api/tags/{tag_name}`
|
||||
|
||||
Returns all notes that have a specific tag.
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"tag": "python",
|
||||
"notes": [
|
||||
{
|
||||
"path": "tutorials/python-basics.md",
|
||||
"name": "python-basics",
|
||||
"folder": "tutorials",
|
||||
"tags": ["python", "tutorial"]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📄 Templates
|
||||
|
||||
### List Templates
|
||||
`GET /api/templates`
|
||||
|
||||
Returns all available note templates from the `_templates` folder.
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"templates": [
|
||||
{
|
||||
"name": "meeting-notes",
|
||||
"path": "_templates/meeting-notes.md",
|
||||
"modified": "2025-11-26T10:30:00"
|
||||
},
|
||||
{
|
||||
"name": "daily-journal",
|
||||
"path": "_templates/daily-journal.md",
|
||||
"modified": "2025-11-26T10:25:00"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### Get Template Content
|
||||
`GET /api/templates/{template_name}`
|
||||
|
||||
Returns the content of a specific template.
|
||||
|
||||
**Parameters:**
|
||||
- `template_name` - Template name (without .md extension)
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"name": "meeting-notes",
|
||||
"content": "# Meeting Notes\n\nDate: {{date}}\n..."
|
||||
}
|
||||
```
|
||||
|
||||
### Create Note from Template
|
||||
`POST /api/templates/create-note`
|
||||
|
||||
Creates a new note from a template with placeholder replacement.
|
||||
|
||||
**Request Body:**
|
||||
```json
|
||||
{
|
||||
"templateName": "meeting-notes",
|
||||
"notePath": "meetings/weekly-sync.md"
|
||||
}
|
||||
```
|
||||
|
||||
**Placeholders:**
|
||||
- `{{date}}` - Current date (YYYY-MM-DD)
|
||||
- `{{time}}` - Current time (HH:MM:SS)
|
||||
- `{{datetime}}` - Current datetime
|
||||
- `{{timestamp}}` - Unix timestamp
|
||||
- `{{title}}` - Note name without extension
|
||||
- `{{folder}}` - Parent folder name
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"path": "meetings/weekly-sync.md",
|
||||
"message": "Note created from template successfully",
|
||||
"content": "# Meeting Notes\n\nDate: 2025-11-26\n..."
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📝 Response Format
|
||||
|
||||
All endpoints return JSON responses:
|
||||
|
|
@ -315,5 +429,41 @@ All endpoints return JSON responses:
|
|||
```
|
||||
---
|
||||
|
||||
---
|
||||
|
||||
## 🔒 Security & Rate Limiting
|
||||
|
||||
### Authentication
|
||||
When authentication is enabled (via `AUTHENTICATION_ENABLED` environment variable or `config.yaml`), all API endpoints require a valid session cookie obtained through the `/login` endpoint.
|
||||
|
||||
### Rate Limiting
|
||||
When `DEMO_MODE` is enabled, the following rate limits are enforced:
|
||||
|
||||
**Read Operations:**
|
||||
- `GET /api/notes` - 120/minute
|
||||
- `GET /api/templates` - 120/minute
|
||||
- `GET /api/templates/{template_name}` - 120/minute
|
||||
- `GET /api/tags` - 120/minute
|
||||
- `GET /api/tags/{tag}` - 120/minute
|
||||
|
||||
**Write Operations:**
|
||||
- `POST /api/notes` - 60/minute
|
||||
- `DELETE /api/notes/*` - 60/minute
|
||||
- `POST /api/folders` - 60/minute
|
||||
- `DELETE /api/folders/*` - 60/minute
|
||||
- `POST /api/images/upload` - 30/minute
|
||||
- `DELETE /api/images/*` - 60/minute
|
||||
- `POST /api/templates/create-note` - 60/minute
|
||||
- `POST /api/plugins/*/toggle` - 60/minute
|
||||
|
||||
### Path Security
|
||||
All file operations validate that paths are within the configured `notes_dir` to prevent directory traversal attacks. This includes:
|
||||
- Note operations
|
||||
- Folder operations
|
||||
- Image operations
|
||||
- Template operations
|
||||
|
||||
---
|
||||
|
||||
💡 **Tip:** Use the `/api` endpoint to get a live, self-documented list of all available endpoints!
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue