Skip to content

Commit a6f0acf

Browse files
committed
feat: API-Endpunkte für Dateiverwaltung und Doku ergänzen
1 parent 2ba44fd commit a6f0acf

File tree

13 files changed

+923
-14
lines changed

13 files changed

+923
-14
lines changed

CHANGELOG.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,27 @@
11
# Changelog
22

3+
## [1.5.0] - 2026-03-03
4+
### Added
5+
- API-Integration für das `api` AddOn über RoutePackages (`code` und `backend/code`).
6+
- Neue Endpunkte für Dateiverwaltung:
7+
- `GET /api/code/files` (`code/files/list`)
8+
- `POST /api/code/files` (`code/files/create`)
9+
- `GET /api/code/file` (`code/file/read`)
10+
- `PUT/PATCH /api/code/file` (`code/file/update`)
11+
- `DELETE /api/code/file` (`code/file/delete`)
12+
- Backend-Mirror-Routen für Session-Auth über `/api/backend/code/*`.
13+
- Neuer `CodeFileService` mit zentraler Logik für Browse/Create/Read/Update/Delete.
14+
- Erweiterte erlaubte Textformate (u.a. `csv`, `tsv`, `log`, `rst`, `toml`, `cfg`, `properties`).
15+
16+
### Changed
17+
- API-Routen werden nur registriert, wenn das `api` AddOn verfügbar ist.
18+
- API-Dateioperationen respektieren den Schalter `enable_file_browser` und liefern bei Deaktivierung `403`.
19+
- README erweitert um Scope-Liste, Curl-Beispiele und Copilot-Instructions-Beispiel.
20+
21+
### Security
22+
- Pfadzugriffe bleiben auf den REDAXO-Basispfad beschränkt (Traversal-Schutz via `realpath`).
23+
- Löschen geschützter Dateien bleibt blockiert (z.B. `.htaccess`, `index.php`, `composer.json`, `boot.php`, `install.php`).
24+
325
## [1.2.1] - 2026-01-28
426
### Fixed
527
- Fatal Error: `CodeApi::__construct()` neu deklariert (doppelter Konstruktor entfernt).

README.md

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,146 @@ The Monaco Editor automatically replaces `.rex-code` textareas in:
177177
3. Results show filename, line number, context
178178
4. Click result to open file at specific line
179179

180+
### API (api AddOn)
181+
When the **api** addon is installed and active, the code addon registers these endpoints automatically:
182+
183+
**Important prerequisite:** File operations (`/api/code/files` and `/api/code/file`) only work when **Code → Settings → File-Browser aktivieren** is enabled. If disabled, the API returns `403`.
184+
185+
- `GET /api/code/capabilities` (Bearer token scope: `code/capabilities`)
186+
- `GET /api/code/files` (Bearer token scope: `code/files/list`, query: `path`)
187+
- `POST /api/code/files` (Bearer token scope: `code/files/create`, JSON body: `path`, `name`, `type=file|folder`)
188+
- `GET /api/code/file` (Bearer token scope: `code/file/read`, query: `path`)
189+
- `PUT/PATCH /api/code/file` (Bearer token scope: `code/file/update`, JSON body: `path`, `content`)
190+
- `DELETE /api/code/file` (Bearer token scope: `code/file/delete`, query: `path`)
191+
- `GET /api/backend/code/capabilities` (Backend session/cookie auth)
192+
- `GET /api/backend/code/files` (Backend session/cookie auth)
193+
- `POST /api/backend/code/files` (Backend session/cookie auth)
194+
- `GET/PUT/PATCH/DELETE /api/backend/code/file` (Backend session/cookie auth)
195+
196+
Response includes:
197+
- addon metadata (`addon`, `version`)
198+
- file browser status (`file_browser_enabled`)
199+
- editable file formats (`allowed_extensions`)
200+
- excluded directories (`excluded_directories`)
201+
202+
`GET /api/code/files` returns the current directory entries (folders + allowed file types).
203+
204+
`POST /api/code/files` creates a new file or folder. Example body:
205+
206+
```json
207+
{
208+
"path": "redaxo/src/addons/code",
209+
"name": "example.csv",
210+
"type": "file"
211+
}
212+
```
213+
214+
`GET /api/code/file` returns file metadata and `content` for an allowed file.
215+
216+
`PUT /api/code/file` updates file content. Example body:
217+
218+
```json
219+
{
220+
"path": "redaxo/src/addons/code/example.csv",
221+
"content": "id;name\n1;Demo\n"
222+
}
223+
```
224+
225+
`DELETE /api/code/file` deletes an allowed non-protected file.
226+
227+
#### Curl examples (copy & paste)
228+
229+
Note: These examples require that the file browser is enabled in the code addon settings.
230+
231+
```bash
232+
BASE='https://localhost:8443'
233+
TOKEN='YOUR_TOKEN'
234+
```
235+
236+
List directory entries:
237+
238+
```bash
239+
curl -k -sS -G \
240+
-H "Authorization: Bearer $TOKEN" \
241+
--data-urlencode "path=redaxo/src/addons/code" \
242+
"$BASE/api/code/files"
243+
```
244+
245+
Create a new CSV file:
246+
247+
```bash
248+
curl -k -sS -X POST \
249+
-H "Authorization: Bearer $TOKEN" \
250+
-H "Content-Type: application/json" \
251+
--data '{"path":"redaxo/src/addons/code","name":"api_demo.csv","type":"file"}' \
252+
"$BASE/api/code/files"
253+
```
254+
255+
Read file content:
256+
257+
```bash
258+
curl -k -sS -G \
259+
-H "Authorization: Bearer $TOKEN" \
260+
--data-urlencode "path=redaxo/src/addons/code/api_demo.csv" \
261+
"$BASE/api/code/file"
262+
```
263+
264+
Update file content:
265+
266+
```bash
267+
curl -k -sS -X PUT \
268+
-H "Authorization: Bearer $TOKEN" \
269+
-H "Content-Type: application/json" \
270+
--data '{"path":"redaxo/src/addons/code/api_demo.csv","content":"id;name\n1;Demo\n"}' \
271+
"$BASE/api/code/file"
272+
```
273+
274+
Delete file:
275+
276+
```bash
277+
curl -k -sS -X DELETE -G \
278+
-H "Authorization: Bearer $TOKEN" \
279+
--data-urlencode "path=redaxo/src/addons/code/api_demo.csv" \
280+
"$BASE/api/code/file"
281+
```
282+
283+
Required token scopes:
284+
285+
- `code/capabilities`
286+
- `code/files/list`
287+
- `code/files/create`
288+
- `code/file/read`
289+
- `code/file/update`
290+
- `code/file/delete`
291+
292+
#### Copilot instructions example
293+
294+
Copy this block into your project-level `.github/copilot-instructions.md` if you want consistent implementation rules for this addon API:
295+
296+
```md
297+
## Code AddOn API Conventions
298+
299+
For `redaxo/src/addons/code` API routes registered into the `api` addon:
300+
301+
- Register route packages only when the `api` addon is available:
302+
- `rex_addon::get('api')->isAvailable()`
303+
- `class_exists(\FriendsOfRedaxo\Api\RouteCollection::class)`
304+
- Keep implementation in `lib/Api/RoutePackage/Code.php` and `lib/Api/CodeFileService.php`.
305+
- Use `FriendsOfRedaxo\Api\RouteCollection::registerRoute(...)` with `BearerAuth` and tag `code`.
306+
- Provide backend mirror routes via `lib/Api/RoutePackage/Backend/Code.php`.
307+
- Respect code addon config flag `enable_file_browser` and return `403` if disabled.
308+
- Accept only file types from `FriendsOfRedaxo\Code\EditorConfig::getAllowedExtensions()`.
309+
- Keep directory/path restrictions inside REDAXO base path and block traversal via realpath checks.
310+
- Do not allow deletion of protected files (e.g. `.htaccess`, `index.php`, `composer.json`, `boot.php`, `install.php`).
311+
- Keep route scopes stable for token management:
312+
- `code/capabilities`
313+
- `code/files/list`
314+
- `code/files/create`
315+
- `code/file/read`
316+
- `code/file/update`
317+
- `code/file/delete`
318+
```
319+
180320
### Backup & Trash
181321
1. Navigate to **Code → Backup & Trash**
182322
2. **Backups tab** - restore previous file versions

assets/code-editor.js

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -991,8 +991,15 @@ class CodeFileBrowser {
991991
'sql': 'fa-database',
992992
'md': 'fa-file-text-o',
993993
'txt': 'fa-file-text-o',
994+
'csv': 'fa-file-text-o',
995+
'tsv': 'fa-file-text-o',
996+
'log': 'fa-file-text-o',
997+
'rst': 'fa-file-text-o',
994998
'yml': 'fa-file-code-o',
995-
'yaml': 'fa-file-code-o'
999+
'yaml': 'fa-file-code-o',
1000+
'toml': 'fa-file-code-o',
1001+
'cfg': 'fa-file-code-o',
1002+
'properties': 'fa-file-code-o'
9961003
};
9971004

9981005
return iconMap[item.extension] || 'fa-file-o';
@@ -1011,8 +1018,15 @@ class CodeFileBrowser {
10111018
'sql': 'sql',
10121019
'md': 'markdown',
10131020
'txt': 'plaintext',
1021+
'csv': 'plaintext',
1022+
'tsv': 'plaintext',
1023+
'log': 'plaintext',
1024+
'rst': 'plaintext',
10141025
'yml': 'yaml',
1015-
'yaml': 'yaml'
1026+
'yaml': 'yaml',
1027+
'toml': 'plaintext',
1028+
'cfg': 'plaintext',
1029+
'properties': 'plaintext'
10161030
};
10171031

10181032
return languageMap[extension] || 'plaintext';
@@ -1021,7 +1035,8 @@ class CodeFileBrowser {
10211035
isEditableFile(extension) {
10221036
const editableExtensions = [
10231037
'php', 'html', 'htm', 'css', 'scss', 'less', 'js', 'json', 'xml', 'sql',
1024-
'md', 'txt', 'yml', 'yaml', 'ini', 'conf', 'htaccess', 'gitignore', 'env'
1038+
'md', 'txt', 'csv', 'tsv', 'log', 'rst', 'toml', 'cfg', 'properties',
1039+
'yml', 'yaml', 'ini', 'conf', 'htaccess', 'gitignore', 'env'
10251040
];
10261041

10271042
return editableExtensions.includes(extension);

boot.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@
99
require_once __DIR__ . '/lib/code_api.php';
1010

1111
use FriendsOfRedaxo\Code\CodeApi;
12+
use FriendsOfRedaxo\Code\Api\RoutePackage\Backend\Code as ApiBackendCodeRoutePackage;
13+
use FriendsOfRedaxo\Code\Api\RoutePackage\Code as ApiCodeRoutePackage;
14+
use FriendsOfRedaxo\Api\RouteCollection;
1215

1316
if (rex::isBackend()) {
1417
$addon = rex_addon::get('code');
@@ -28,6 +31,11 @@
2831
rex_view::addJsFile($this->getAssetsUrl('code-editor.js') . '?t=' . (time() + 1));
2932
}
3033

34+
if (rex_addon::get('api')->isAvailable() && class_exists(RouteCollection::class)) {
35+
RouteCollection::registerRoutePackage(new ApiCodeRoutePackage());
36+
RouteCollection::registerRoutePackage(new ApiBackendCodeRoutePackage());
37+
}
38+
3139
// API Endpoints registrieren
3240
if (rex_get('code_api', 'bool')) {
3341
$action = rex_get('action', 'string');

composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
"extra": {
2121
"redaxo": {
2222
"name": "code",
23-
"version": "1.0.0"
23+
"version": "1.5.0"
2424
}
2525
},
2626
"replace": {

lang/de_de.lang

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,3 +90,5 @@ file_browser_security_point_4 = Nicht für Produktivsysteme empfohlen
9090
file_browser_security_point_5 = Deaktiviert sich automatisch nach 2 Tagen ohne Nutzung
9191
file_browser_activate_button = File-Browser aktivieren (2 Tage)
9292
file_browser_activate_help = Nach Aktivierung kann der File-Browser in den <a href="index.php?page=code/settings">Einstellungen</a> konfiguriert werden.
93+
94+
api_openapi_tag_code_description = Endpunkte des Code-AddOns

lang/en_gb.lang

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ code_file_restored = File restored
3030
code_trash_emptied = Trash emptied
3131
code_confirm_delete = Really delete?
3232
code_confirm_empty_trash = Really empty trash?
33+
34+
api_openapi_tag_code_description = Endpoints of the code addon
3335
code_unsaved_changes = There are unsaved changes. Continue anyway?
3436
code_create_file = Create new file
3537
code_create_folder = Create new folder

0 commit comments

Comments
 (0)