AgentStack
Browse Sign in
Browse Why AgentStack Sell Docs
Sign in
SKILL verified MIT Self-run

Nextcloud Syntax Controllers

skill-impertio-studio-nextcloud-claude-skill-package-nextcloud-syntax-controllers · by Impertio-Studio

>

No reviews yet
0 installs
9 views
0.0% view→install

Install

$ agentstack add skill-impertio-studio-nextcloud-claude-skill-package-nextcloud-syntax-controllers

✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures

What it can access

  • Network access No
  • Filesystem access No
  • Shell / process execution No
  • Environment & secrets No
  • Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

View the full security report →

Verified badge

Passed review? Show it. Paste this badge into your README, it links to the public security report.

AgentStack Verified badge Links to your public security report.
[![AgentStack Verified](https://agentstack.voostack.com/badges/verified.svg)](https://agentstack.voostack.com/security/report/skill-impertio-studio-nextcloud-claude-skill-package-nextcloud-syntax-controllers)

Reliability & compatibility

Security review passed
0 installs to date
no reviews yet
1mo ago

Declared compatibility

Claude CodeClaude Desktop

Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.

Preview Execution monitoring

We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.

How agent discovery & health will work →
Are you the author of Nextcloud Syntax Controllers? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

nextcloud-syntax-controllers

Quick Reference

Controller Types

| Class | Base Path | Use Case | |-------|-----------|----------| | OCP\AppFramework\Controller | /index.php/apps/{appid}/ | Page rendering, internal endpoints | | OCP\AppFramework\OCSController | /ocs/v2.php/apps/{appid}/ | OCS API with JSON/XML envelope | | OCP\AppFramework\ApiController | /index.php/apps/{appid}/ | REST API (extends Controller, adds CORS) |

Route Definition Arrays (appinfo/routes.php)

| Array | URL Prefix | Controller Base | |-------|-----------|-----------------| | routes | /index.php/apps/{appid}/ | Controller or ApiController | | ocs | /ocs/v2.php/apps/{appid}/ | OCSController | | resources | /index.php/apps/{appid}/ | Auto-generates 5 CRUD routes |

Route Name Resolution

| Route Name | Controller Class | Method | |------------|-----------------|--------| | page#index | PageController | index() | | author_api#some_method | AuthorApiController | someMethod() | | api#getData | ApiController | getData() |

Parameter Extraction

| Source | Example | Extraction | |--------|---------|------------| | URL path | /authors/{id} | $id parameter | | Query string | ?name=john | $name parameter | | JSON body | {"title": "Test"} | $title parameter | | Form data | name=john | $name parameter | | Default value | $page = 1 | Falls back if not in request |

Type Casting (via type hints or @param)

| Type | PHP Hint | Notes | |------|----------|-------| | int / integer | int $id | Numeric string to int | | float | float $value | Numeric string to float | | bool / boolean | bool $flag | "true"/"1" to true | | string | string $name | Default, no conversion | | array | array $items | From JSON body |

Security Attributes (NC 27+)

| Attribute | Effect | |-----------|--------| | #[NoAdminRequired] | Allow non-admin authenticated users | | #[PublicPage] | No login required | | #[NoCSRFRequired] | Skip CSRF token validation | | #[NoTwoFactorRequired] | Bypass 2FA requirement | | #[UserRateLimit(limit: 5, period: 100)] | Rate limit for logged-in users | | #[AnonRateLimit(limit: 1, period: 100)] | Rate limit for anonymous users | | #[BruteForceProtection(action: 'login')] | Enable brute force throttling |

Default security posture (no attributes): admin-only, authenticated, 2FA required, CSRF validated.

Response Types

| Class | Use Case | |-------|----------| | TemplateResponse | Render server-side PHP template | | PublicTemplateResponse | Public page with header actions | | JSONResponse | JSON data with HTTP status | | DataResponse | Generic data (format via responder) | | RedirectResponse | HTTP redirect | | DownloadResponse | File download | | StreamResponse | Stream file contents |

Critical Warnings

NEVER create controller methods without security attributes and assume they are public -- the default is admin-only. Explicitly add #[NoAdminRequired] for regular user access or #[PublicPage] for anonymous access.

NEVER use #[NoCSRFRequired] on state-changing endpoints without alternative protection -- either require the OCS-APIRequest: true header or use token-based authentication.

NEVER use #[PublicPage] + #[NoCSRFRequired] on state-changing endpoints without additional authentication -- this leaves the endpoint completely unprotected.

NEVER return a response without the correct HTTP status code -- use the Http::STATUS_* constants for clarity.

ALWAYS extend OCSController for OCS API endpoints -- using Controller with OCS routes will break the response envelope.

ALWAYS define routes in appinfo/routes.php -- controllers without routes are unreachable.

ALWAYS use constructor injection for dependencies -- Nextcloud auto-wires by type hint.

ALWAYS call $response->throttle() only on failure conditions when using #[BruteForceProtection] -- never on success.


Essential Patterns

Pattern 1: Page Controller with Template

namespace OCA\MyApp\Controller;

use OCP\AppFramework\Controller;
use OCP\AppFramework\Http\TemplateResponse;
use OCP\IRequest;

class PageController extends Controller {
    public function __construct(
        string $appName,
        IRequest $request,
        private MyService $service,
    ) {
        parent::__construct($appName, $request);
    }

    #[NoAdminRequired]
    #[NoCSRFRequired]
    public function index(): TemplateResponse {
        return new TemplateResponse($this->appName, 'main');
    }
}
// appinfo/routes.php
return [
    'routes' => [
        ['name' => 'page#index', 'url' => '/', 'verb' => 'GET'],
    ],
];

Pattern 2: OCS API Controller

namespace OCA\MyApp\Controller;

use OCP\AppFramework\Http\DataResponse;
use OCP\AppFramework\OCSController;
use OCP\IRequest;

class ItemApiController extends OCSController {
    public function __construct(
        string $appName,
        IRequest $request,
        private ItemService $service,
        private ?string $userId,
    ) {
        parent::__construct($appName, $request);
    }

    #[NoAdminRequired]
    public function index(): DataResponse {
        return new DataResponse($this->service->findAll($this->userId));
    }

    #[NoAdminRequired]
    public function show(int $id): DataResponse {
        return new DataResponse($this->service->find($id, $this->userId));
    }

    #[NoAdminRequired]
    public function create(string $title, string $content = ''): DataResponse {
        return new DataResponse(
            $this->service->create($title, $content, $this->userId)
        );
    }
}
// appinfo/routes.php
return [
    'ocs' => [
        ['name' => 'item_api#index', 'url' => '/api/v1/items', 'verb' => 'GET'],
        ['name' => 'item_api#show', 'url' => '/api/v1/items/{id}', 'verb' => 'GET'],
        ['name' => 'item_api#create', 'url' => '/api/v1/items', 'verb' => 'POST'],
    ],
];

Pattern 3: Resource Routes (Auto-CRUD)

// appinfo/routes.php
return [
    'resources' => [
        'author' => ['url' => '/authors'],
    ],
];

This auto-generates five routes mapping to AuthorController:

| Verb | URL | Method | |------|-----|--------| | GET | /authors | index() | | GET | /authors/{id} | show(int $id) | | POST | /authors | create() | | PUT | /authors/{id} | update(int $id) | | DELETE | /authors/{id} | destroy(int $id) |

Pattern 4: Attribute-Based Routing (NC 29+)

use OCP\AppFramework\Http\Attribute\FrontpageRoute;
use OCP\AppFramework\Http\Attribute\ApiRoute;

class PageController extends Controller {

    #[NoAdminRequired]
    #[FrontpageRoute(verb: 'GET', url: '/')]
    public function index(): TemplateResponse {
        return new TemplateResponse($this->appName, 'main');
    }
}

class ItemApiController extends OCSController {

    #[NoAdminRequired]
    #[ApiRoute(verb: 'GET', url: '/api/v1/items')]
    public function index(): DataResponse {
        return new DataResponse($this->service->findAll());
    }
}

Pattern 5: Error Handling with Status Codes

use OCP\AppFramework\Http;
use OCP\AppFramework\Http\JSONResponse;

#[NoAdminRequired]
public function show(int $id): JSONResponse {
    try {
        return new JSONResponse($this->service->find($id, $this->userId));
    } catch (NotFoundException $e) {
        return new JSONResponse([], Http::STATUS_NOT_FOUND);
    } catch (ForbiddenException $e) {
        return new JSONResponse(['message' => $e->getMessage()], Http::STATUS_FORBIDDEN);
    }
}

Pattern 6: Complete routes.php with All Three Arrays

 [
        ['name' => 'page#index', 'url' => '/', 'verb' => 'GET'],
        ['name' => 'page#settings', 'url' => '/settings', 'verb' => 'GET'],
        [
            'name' => 'file#download',
            'url' => '/files/{path}',
            'verb' => 'GET',
            'requirements' => ['path' => '.+'],  // match slashes in path
        ],
        [
            'name' => 'page#list',
            'url' => '/list',
            'verb' => 'GET',
            'defaults' => ['page' => 1, 'limit' => 20],
        ],
    ],
    'ocs' => [
        ['name' => 'api#getData', 'url' => '/api/v1/data', 'verb' => 'GET'],
        ['name' => 'api#updateData', 'url' => '/api/v1/data/{id}', 'verb' => 'PUT'],
    ],
    'resources' => [
        'author' => ['url' => '/authors'],
    ],
];

Responder System (Format Negotiation)

Priority order for response format:

  1. ?format=xml or ?format=json query parameter (highest)
  2. Accept HTTP header
  3. Default: json

OCSController handles this automatically -- DataResponse is rendered as JSON or XML based on negotiation.

For custom formats, register a responder:

class MyController extends Controller {
    public function __construct(string $appName, IRequest $request) {
        parent::__construct($appName, $request);
        $this->registerResponder('xml', function ($data) {
            return new XMLResponse($data);
        });
    }
}

URL Generation

use OCP\IURLGenerator;

// Route URL: /index.php/apps/myapp/authors/3
$url = $urlGenerator->linkToRoute('myapp.author.show', ['id' => 3]);

// OCS route URL: /ocs/v2.php/apps/myapp/api/v1/data
$url = $urlGenerator->linkToOCSRoute('myapp.api.getData');

Route name format: {appid}.{controller}.{method} where hashes become dots and underscores are preserved.


Reference Links

  • [references/methods.md](references/methods.md) -- Controller types, route syntax, response types, parameter extraction
  • [references/examples.md](references/examples.md) -- Controller patterns, routing patterns
  • [references/anti-patterns.md](references/anti-patterns.md) -- Controller mistakes

Official Sources

  • https://docs.nextcloud.com/server/latest/developermanual/diggingdeeper/controllers.html
  • https://docs.nextcloud.com/server/latest/developer_manual/basics/routing.html
  • https://docs.nextcloud.com/server/latest/developermanual/diggingdeeper/middleware.html

Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet, be the first.

Versions

  • v0.1.0 Imported from the upstream source.