Giter VIP home page Giter VIP logo

cakephp-api's Introduction

API Plugin for CakePHP

Bake Status Downloads Latest Version License Scrutinizer Code Quality Code Coverage

The CakePHP-API Plugin allows to easily expose a versioned API in a few lines of code.

Versions and branches

CakePHP CakeDC Api Plugin Tag Notes
^3.7 master 7.0.0 stable
^3.7 develop - unstable
3.6 master 6.0.1 stable
3.5 5.x 5.0.0 stable
3.4 4.x 4.0.0 stable
3.3 3.x 3.3 stable

Documentation

For documentation, as well as tutorials, see the Docs directory of this repository.

Support

For bugs and feature requests, please use the issues section of this repository.

Commercial support is also available, contact us for more information.

Contributing

This repository follows the CakeDC Plugin Standard. If you'd like to contribute new features, enhancements or bug fixes to the plugin, please read our Contribution Guidelines for detailed instructions.

License

Copyright 2016-2018 Cake Development Corporation (CakeDC). All rights reserved.

Licensed under the MIT License. Redistributions of the source code included in this repository must retain the copyright notice found in each file.

cakephp-api's People

Contributors

ajibarra avatar amandadeegoff avatar andrej-griniuk avatar ddh-ts avatar delamux avatar mamchenkov avatar pmoraes avatar ravage84 avatar rochamarcelo avatar skie avatar splicephp avatar steinkel avatar yeliparra avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

cakephp-api's Issues

Missing \ Wrong documentation on routing

The plugin is great but the documentation really lacks and somewhere refers to older api.
I am trying to build a basic api in a plugin: i have tried to follow the docs but was unable to make it work.
Here there is what I have done so far using cake 4.2.9 :

In my application I have a plugin called GrapeJs : I have created a Service called EditorService under the GrapeJs\Service namespace.

The initialize method maps an action "blocks" for a CustomBlocksAction :

public function initialize(): void
    {
        parent::initialize();
        $this->mapAction('blocks', CustomBlocksAction::class, ['method' => ['GET'], 'mapCors' => true]);
    }

I have created the action under GrapeJs\Api\Service\Action namespace which extends the CakeDC action.
Inside the action there is some entity logic to retrieve some data which is returned like the following :

return [
            'blocks' => $result
        ];

The documentation in the overview section ( and not for example in the service ) says that to define a custom route you must implement a "loadRoutes" like the following in the service ( taken from the doc ) :

public function loadRoutes()
    {
        ApiRouter::scope('/', $this->routerDefaultOptions(), function (RouteBuilder $routes) {
            $routes->extensions($this->_extensions);
            $options = [
                'map' => [
                    'publish' => ['action' => 'publish', 'method' => 'POST', 'path' => ''],
                ]
            ];
            $routes->resources($this->name(), $options);
        });
	}

The first problem encountered is that RouteBuilder no longer have a ->extensions.
"$this->routerDefaultOptions()" is not defined: should I define it somewhere ?
What is the correct way to define this function ?
I would expect then to be able to check the api at /grape_js/api/editor/blocks url isn'it ?

Could you please provide a full detailed example of the full flow from the beginning to the end ?
There is also some doc link broken, like the "routes" one.

Thank you

Rudy

Can't install version >8.0.0 due to dependency on lcobucci/jwt:3.3.x-dev (suggestion: depend on stable version, latest is lcobucci/jwt:4.0.0)

I have version 8.0.0 of CakeDC/cakephp-api plugin installed, but if I try to upgrade to any higher version, composer shows the following error:

Your requirements could not be resolved to an installable set of packages.
Problem 1
- Root composer.json requires cakedc/cakephp-api 8.0.8 -> satisfiable by cakedc/cakephp-api[8.0.8].
- cakedc/cakephp-api 8.0.8 requires lcobucci/jwt 3.3.x-dev -> found lcobucci/jwt[3.3.x-dev] but it does not match your minimum-stability.

Explanation

From CakeDC/cakephp-api:8.0.1 on it depends on lcobucci/jwt:3.3.x-dev, but it seems to be an unstable version and composer won't let it install, so won't install CakeDC/cakephp-api plugin either.

Probably by setting @ dev stability on the dependency line in your composer.json it could work, but lcobucci/jwt already has higher stable versions.

Probably trying to port CakeDC/cakephp-api to lcobucci/jwt:4.0.0 is a better option.

Anyway, we need a solution for this so we are be able to install the newest releases of CakeDC/cakephp-api.

Thanks!

Does not work out of the box with most recent cakedc/users plugin

 └──╼ composer require cakedc/cakephp-api
 Using version ^3.3 for cakedc/cakephp-api
 ./composer.json has been updated
 Loading composer repositories with package information
 Updating dependencies (including require-dev)
 Your requirements could not be resolved to an installable set of packages.

   Problem 1
     - Installation request for cakedc/cakephp-api ^3.3 -> satisfiable by cakedc/cakephp-api[3.3].
     - cakedc/cakephp-api 3.3 requires cakedc/users ^4.0 -> satisfiable by cakedc/users[4.0.0, 4.0.1, 4.1.0, 4.1.1, 4.1.2, 4.1.3, 4.2.0, 4.2.1, 4.x-dev] but these conflict with your requirements or minimum-stability.

 Installation failed, reverting ./composer.json to its original content.

In my composer.json, I have

"cakedc/users": "^5.0",

If you were going to update this api plugin right now, how would you go about doing it.. just type out a bullet list of things you would do and I will attempt to get it done, I just need someone to point me in the right direction

Jwt authentication is not working in 8.0.0

I'm trying to access an endpoint in my API which access is restricted for role=>'retailer'.

The endpoint is: /api/orders

I do NOT want to bypass this endpoint. I want the user to be authenticated as a 'retailer'.

I created this rule in /config/api_permissions.php:

[
    'role' => 'retailer',
    'service' => 'Orders',
    'action' => ['index', 'view'],
    'method' => 'GET'
],

I'm already getting my Jwt Token by logging into the system. Then I send that token in Authorization header like 'Authorization: Bearer ' to access my restricted endpoint at /api/orders.

It fails with the following error:

{
	"status": "error",
	"message": "Forbidden authorization request on line 36 in C:\\xampp-new\\htdocs\\luna\\vendor\\cakedc\\cakephp-api\\src\\Middleware\\UnauthorizedHandler\\ApiExceptionHandler.php",
	"code": 500,
	"data": null,
	"trace": [
		{
			"file": "C:\\xampp-new\\htdocs\\luna\\vendor\\cakephp\\authorization\\src\\Middleware\\AuthorizationMiddleware.php",
			"line": 139,
			"function": "handle",
			"class": "CakeDC\\Api\\Middleware\\UnauthorizedHandler\\ApiExceptionHandler"
		},
		{
			"file": "C:\\xampp-new\\htdocs\\luna\\vendor\\cakephp\\cakephp\\src\\Http\\Runner.php",
			"line": 73,
			"function": "process",
			"class": "Authorization\\Middleware\\AuthorizationMiddleware"
		},
		{
			"file": "C:\\xampp-new\\htdocs\\luna\\src\\Middleware\\LunaParseApiRequestMiddleware.php",
			"line": 88,
			"function": "handle",
			"class": "Cake\\Http\\Runner"
		},
		{
			"file": "C:\\xampp-new\\htdocs\\luna\\vendor\\cakephp\\cakephp\\src\\Http\\Runner.php",
			"line": 73,
			"function": "process",
			"class": "App\\Middleware\\LunaParseApiRequestMiddleware"
		},
		{
			"file": "C:\\xampp-new\\htdocs\\luna\\vendor\\cakephp\\authentication\\src\\Middleware\\AuthenticationMiddleware.php",
			"line": 122,
			"function": "handle",
			"class": "Cake\\Http\\Runner"
		},
		{
			"file": "C:\\xampp-new\\htdocs\\luna\\vendor\\cakephp\\cakephp\\src\\Http\\Runner.php",
			"line": 73,
			"function": "process",
			"class": "Authentication\\Middleware\\AuthenticationMiddleware"
		},
		{
			"file": "C:\\xampp-new\\htdocs\\luna\\vendor\\cakephp\\cakephp\\src\\Http\\Runner.php",
			"line": 58,
			"function": "handle",
			"class": "Cake\\Http\\Runner"
		},
		{
			"file": "C:\\xampp-new\\htdocs\\luna\\vendor\\cakephp\\cakephp\\src\\Routing\\Middleware\\RoutingMiddleware.php",
			"line": 172,
			"function": "run",
			"class": "Cake\\Http\\Runner"
		},
		{
			"file": "C:\\xampp-new\\htdocs\\luna\\vendor\\cakephp\\cakephp\\src\\Http\\Runner.php",
			"line": 73,
			"function": "process",
			"class": "Cake\\Routing\\Middleware\\RoutingMiddleware"
		},
		{
			"file": "C:\\xampp-new\\htdocs\\luna\\vendor\\ozee31\\cakephp-cors\\src\\Routing\\Middleware\\CorsMiddleware.php",
			"line": 19,
			"function": "handle",
			"class": "Cake\\Http\\Runner"
		},
		{
			"file": "C:\\xampp-new\\htdocs\\luna\\vendor\\cakephp\\cakephp\\src\\Http\\Runner.php",
			"line": 73,
			"function": "process",
			"class": "Cors\\Routing\\Middleware\\CorsMiddleware"
		},
		{
			"file": "C:\\xampp-new\\htdocs\\luna\\vendor\\cakephp\\cakephp\\src\\Routing\\Middleware\\AssetMiddleware.php",
			"line": 68,
			"function": "handle",
			"class": "Cake\\Http\\Runner"
		},
		{
			"file": "C:\\xampp-new\\htdocs\\luna\\vendor\\cakephp\\cakephp\\src\\Http\\Runner.php",
			"line": 73,
			"function": "process",
			"class": "Cake\\Routing\\Middleware\\AssetMiddleware"
		},
		{
			"file": "C:\\xampp-new\\htdocs\\luna\\vendor\\cakephp\\cakephp\\src\\Error\\Middleware\\ErrorHandlerMiddleware.php",
			"line": 121,
			"function": "handle",
			"class": "Cake\\Http\\Runner"
		},
		{
			"file": "C:\\xampp-new\\htdocs\\luna\\vendor\\cakephp\\cakephp\\src\\Http\\Runner.php",
			"line": 73,
			"function": "process",
			"class": "Cake\\Error\\Middleware\\ErrorHandlerMiddleware"
		},
		{
			"file": "C:\\xampp-new\\htdocs\\luna\\vendor\\cakephp\\debug_kit\\src\\Middleware\\DebugKitMiddleware.php",
			"line": 60,
			"function": "handle",
			"class": "Cake\\Http\\Runner"
		},
		{
			"file": "C:\\xampp-new\\htdocs\\luna\\vendor\\cakephp\\cakephp\\src\\Http\\Runner.php",
			"line": 73,
			"function": "process",
			"class": "DebugKit\\Middleware\\DebugKitMiddleware"
		},
		{
			"file": "C:\\xampp-new\\htdocs\\luna\\vendor\\cakephp\\cakephp\\src\\Http\\Runner.php",
			"line": 58,
			"function": "handle",
			"class": "Cake\\Http\\Runner"
		},
		{
			"file": "C:\\xampp-new\\htdocs\\luna\\vendor\\cakephp\\cakephp\\src\\Http\\Server.php",
			"line": 90,
			"function": "run",
			"class": "Cake\\Http\\Runner"
		},
		{
			"file": "C:\\xampp-new\\htdocs\\luna\\webroot\\index.php",
			"line": 40,
			"function": "run",
			"class": "Cake\\Http\\Server"
		}
	]
}

When I debug, I see that **it never tries to authenticate the user using any Jwt Authenticator. It fails for SessionAuthenticator and TokenAuthenticator (both from Cakephp/authentication plugin), but it never uses any Jwt Authenticator.

These is my /config/api.php:

return [

	'Api' => [

		'useVersioning' => false,

		'Service' => [
			'default' => [
				'options' => [
					'Extension' => [
						'CakeDC/Api.OptionsHandler'
					],
				],
				'Action' => [
					'default' => [
						'Auth' => [
							'authenticate' => [
								'CakeDC/Api.Jwt'
							],
						],
						'Extension' => [
							'CakeDC/Api.Cors',
						]
					],

					'Index' => [
						'Extension' => [
							'CakeDC/Api.Filter',
							MagicSortExtension::class
						],
					]
				],
			],

			'retailers' => [
				'Action'=>[
					'Login'=>[
						'Auth' => [
							'authenticate' => [
								'CakeDC/Api.Form'
							],
						]
					]
				]
			],
		],

		'Jwt' =>[
			'enabled' => true,
			'userModel'=>'Retailers'
		],
	]
];

And this is my /config/api_permissions.php:

return [
	'CakeDC/Auth.api_permissions' => [
		[
			'role' => '*',
			'service' => '*',
			'action' => '*',
			'method' => 'OPTIONS',
			'bypassAuth' => true,
		],

		[
			'role' => '*',
			'service' => 'Retailers',
			'action' => ['login', 'signup'],
			'method' => 'POST',
			'bypassAuth' => true,
		],

		[
			'role' => 'retailer',
			'service' => 'Orders',
			'action' => ['index', 'view'],
			'method' => 'GET',
		],
	]
];

What seems to be the problem?

What is the correct way to access an endpoint that requires to be authenticated by using a jwt token?

8.0 branch crud not working - Forbidden authorization request

I baked a model called Actors and attempted browsing to it assuming the CRUD functionality works but I get the following error:

Forbidden authorization request on line 36 in /var/www/personal/cakephp-api-demo/vendor/cakedc/cakephp-api/src/Middleware/UnauthorizedHandler/ApiExceptionHandler.php

Auth config:

                        'Auth' => [
                            'allow' => '*', // PUBLIC ACCESS for all API endpoints, remove this line to secure
                            'authorize' => [
                                'CakeDC/Api.Crud' => []
                            ],
                            'authenticate' => [
                                'CakeDC/Api.Token' => [
                                    'require_ssl' => false,
                                ]
                            ],
                        ],

Reproduction Steps

  1. Install 8.0 from composer require
  2. Copied over api.php into config/api.php
  3. Baked the model below
  4. curl -i http://localhost:8765/api/actors

Model schema from a migration snapshot:

        $this->table('actors')
            ->addColumn('id', 'integer', [
                'autoIncrement' => true,
                'default' => null,
                'limit' => 5,
                'null' => false,
                'signed' => false,
            ])
            ->addPrimaryKey(['id'])
            ->addColumn('first_name', 'string', [
                'default' => null,
                'limit' => 45,
                'null' => false,
            ])
            ->addColumn('last_name', 'string', [
                'default' => null,
                'limit' => 45,
                'null' => false,
            ])
            ->addColumn('modified', 'datetime', [
                'default' => null,
                'limit' => null,
                'null' => false,
            ])
            ->addIndex(
                [
                    'last_name',
                ]
            )
            ->create();

Full stack trace:

curl -i http://localhost:8765/api/actors
HTTP/1.1 200 OK
Host: localhost:8765
Date: Wed, 20 May 2020 02:41:39 GMT
Connection: close
X-Powered-By: PHP/7.2.30-1+ubuntu18.04.1+deb.sury.org+1
Content-Type: application/json
X-DEBUGKIT-ID: 7e8ec295-df44-4b35-b178-3b714725611c

{
    "status": "error",
    "message": "Forbidden authorization request on line 36 in \/var\/www\/personal\/cakephp-api-demo\/vendor\/cakedc\/cakephp-api\/src\/Middleware\/UnauthorizedHandler\/ApiExceptionHandler.php",
    "code": 500,
    "data": null,
    "trace": [
        {
            "file": "\/var\/www\/personal\/cakephp-api-demo\/vendor\/cakephp\/authorization\/src\/Middleware\/AuthorizationMiddleware.php",
            "line": 139,
            "function": "handle",
            "class": "CakeDC\\Api\\Middleware\\UnauthorizedHandler\\ApiExceptionHandler"
        },
        {
            "file": "\/var\/www\/personal\/cakephp-api-demo\/vendor\/cakephp\/cakephp\/src\/Http\/Runner.php",
            "line": 73,
            "function": "process",
            "class": "Authorization\\Middleware\\AuthorizationMiddleware"
        },
        {
            "file": "\/var\/www\/personal\/cakephp-api-demo\/vendor\/cakedc\/cakephp-api\/src\/Middleware\/ParseApiRequestMiddleware.php",
            "line": 87,
            "function": "handle",
            "class": "Cake\\Http\\Runner"
        },
        {
            "file": "\/var\/www\/personal\/cakephp-api-demo\/vendor\/cakephp\/cakephp\/src\/Http\/Runner.php",
            "line": 73,
            "function": "process",
            "class": "CakeDC\\Api\\Middleware\\ParseApiRequestMiddleware"
        },
        {
            "file": "\/var\/www\/personal\/cakephp-api-demo\/vendor\/cakephp\/authentication\/src\/Middleware\/AuthenticationMiddleware.php",
            "line": 124,
            "function": "handle",
            "class": "Cake\\Http\\Runner"
        },
        {
            "file": "\/var\/www\/personal\/cakephp-api-demo\/vendor\/cakephp\/cakephp\/src\/Http\/Runner.php",
            "line": 73,
            "function": "process",
            "class": "Authentication\\Middleware\\AuthenticationMiddleware"
        },
        {
            "file": "\/var\/www\/personal\/cakephp-api-demo\/vendor\/cakephp\/cakephp\/src\/Http\/Runner.php",
            "line": 58,
            "function": "handle",
            "class": "Cake\\Http\\Runner"
        },
        {
            "file": "\/var\/www\/personal\/cakephp-api-demo\/vendor\/cakephp\/cakephp\/src\/Routing\/Middleware\/RoutingMiddleware.php",
            "line": 162,
            "function": "run",
            "class": "Cake\\Http\\Runner"
        },
        {
            "file": "\/var\/www\/personal\/cakephp-api-demo\/vendor\/cakephp\/cakephp\/src\/Http\/Runner.php",
            "line": 73,
            "function": "process",
            "class": "Cake\\Routing\\Middleware\\RoutingMiddleware"
        },
        {
            "file": "\/var\/www\/personal\/cakephp-api-demo\/vendor\/cakephp\/cakephp\/src\/Routing\/Middleware\/AssetMiddleware.php",
            "line": 68,
            "function": "handle",
            "class": "Cake\\Http\\Runner"
        },
        {
            "file": "\/var\/www\/personal\/cakephp-api-demo\/vendor\/cakephp\/cakephp\/src\/Http\/Runner.php",
            "line": 73,
            "function": "process",
            "class": "Cake\\Routing\\Middleware\\AssetMiddleware"
        },
        {
            "file": "\/var\/www\/personal\/cakephp-api-demo\/vendor\/cakephp\/cakephp\/src\/Error\/Middleware\/ErrorHandlerMiddleware.php",
            "line": 119,
            "function": "handle",
            "class": "Cake\\Http\\Runner"
        },
        {
            "file": "\/var\/www\/personal\/cakephp-api-demo\/vendor\/cakephp\/cakephp\/src\/Http\/Runner.php",
            "line": 73,
            "function": "process",
            "class": "Cake\\Error\\Middleware\\ErrorHandlerMiddleware"
        },
        {
            "file": "\/var\/www\/personal\/cakephp-api-demo\/vendor\/cakephp\/debug_kit\/src\/Middleware\/DebugKitMiddleware.php",
            "line": 60,
            "function": "handle",
            "class": "Cake\\Http\\Runner"
        },
        {
            "file": "\/var\/www\/personal\/cakephp-api-demo\/vendor\/cakephp\/cakephp\/src\/Http\/Runner.php",
            "line": 73,
            "function": "process",
            "class": "DebugKit\\Middleware\\DebugKitMiddleware"
        },
        {
            "file": "\/var\/www\/personal\/cakephp-api-demo\/vendor\/cakephp\/cakephp\/src\/Http\/Runner.php",
            "line": 58,
            "function": "handle",
            "class": "Cake\\Http\\Runner"
        },
        {
            "file": "\/var\/www\/personal\/cakephp-api-demo\/vendor\/cakephp\/cakephp\/src\/Http\/Server.php",
            "line": 90,
            "function": "run",
            "class": "Cake\\Http\\Runner"
        },
        {
            "file": "\/var\/www\/personal\/cakephp-api-demo\/webroot\/index.php",
            "line": 40,
            "function": "run",
            "class": "Cake\\Http\\Server"
        }
    ]
}

No way to disable SortExtension to prevent it of executing on some requests

I'm using CakeDC/cakephp-api version 8.0.10

Hi there!

I created my own Extension to be able to sort my API results via a request query param, like:

/endpoint?sort=-created,+price

The cakephp-api plugin comes with a SortExtension that works with certain structure, but I prefer my own structure, and I also want to support sorting with relations' fields (probably will open a new feature request later), like:

/endpoint?sort=-Orders.created

So, I want to use my own Extension to sort results, instead of the default one, and I want it in my Index endpoints.

I already configured the plugin for that in my /config/api.php and it is executing my OwnSortExtension like expected.

What is the problem I'm having?

When I send a request to my endpoint, it always executes the SortExtension that comes by default within the plugin, besides my OwnSortExtension. In the end, both extensions are executed.

Executing both extensions creates problems for me because it creates duplicate ORDER BY clauses in the sql query and I'm getting errors. Also, the structure I defined for my query params to sort the results is not very compatible with how the default SortExtension operates, so it creates problems for me.

What could be the problem in the plugin?

  1. The SortExtension is being activated for all API requests in the plugin's /config/api.php config file.
  2. Even if I override the configuration entries, the plugin seems to merge the configurations (my own and the plugin's), so there is no way to desactivate the plugin' SortExtension to prevent its execution.

Possible ways to tackle this:

  1. Allow full override of plugin's configurations, instead of merging.
  2. Remove SortExtension from the "global" extensions in the plugin's configuration and activate it only for Index by default (I don't see the need to activate it for any other REST endpoint). This will need full override too.
  3. Do not activate SortExtension for ANY endpoint by default, and let the users of the plugin decide whether to use it or not (again, I would use it only for Index)

In conclusion, we should have some way to desactivate the default SortExtension so we can use our own or not use it at all.

Thanks a lot in advance!

Fix log extension.

It always is logging into the error.log file.

By default LogTrait log there.

JWT tokens not authorizing until a minute after refresh

Hi, I don't know if anyone else is having this issue.
After a response from the refresh token I get forbidden access until about a second after the token was refreshed.
In CakeDC\Api\Service\Action\Auth\JwtTokenTrait around line 40 inside the generateTokenResponse method the line reads:
$timestamp = new DateTimeImmutable();
setting it to:
$timestamp = new DateTimeImmutable('-1 second');
fixes the issue.

CrudAction::_getEntities() should return a ResultSetInterface instead of a ResultSet - errors might happen if not.

CakeDC/Api version: 8.0.8

Hi there!

I'm getting an error from my endpoint when I try to retrieve results from it. This is the error:

Return value of CakeDC\\Api\\Service\\Action\\CrudAction::_getEntities() must be an instance of Cake\\ORM\\ResultSet, instance of Cake\\Datasource\\ResultSetDecorator returned

What provokes this error?

I want to pre-process my entities in an "afterFind" operation, so I added a beforeFind() hook, like this:

public function beforeFind(EventInterface $event, Query $query, ArrayObject $options, $primary) {
    $query->formatResults(function (CollectionInterface $results) {
        return $results->map(function ($row) {
           
            // Process entities

            return $row;
        });
    });
}

As soon as I do this and I try to access the endpoint, I get this error:

Return value of CakeDC\\Api\\Service\\Action\\CrudAction::_getEntities() must be an instance of Cake\\ORM\\ResultSet, instance of Cake\\Datasource\\ResultSetDecorator returned

What code fails inside CakeDC/Api plugin?

The CrudAction::_getEntities() function has a return type of ResultSet, and under normal conditions it works well... until you use the $query->formatResults() function in your Model::beforeFind() hook.

When you do this, line 244 of CrudAction (in the _getEntities() function) doesn't return what is expected.

It returns a ResultSetDecorator instance!

And it's okay, because after all, Query::all() function returns a ResultSetInterface.

So, when _getEntities() function wants to return, it fails with an unrecoverable error.

(...)

I think CrudAction::_getEntities() should have its return type as ResultSetInterface (an interface), not ResultSet (a subtype).

Thanks for your help!

Restrict API endpoints

How can I restrict endpoints to selected models only?
Changing Api.ServiceFallback to '\\CakeDC\\Api\\Service\\FallbackService' doesn't work.

exisiting v1 api no longer works

We have an api/v1 prefix which we used for our 1st api version.

We have since used this plugin and created a v2. The calls to v2 work fine, but all calls to our v1 (exisitng) api now result in a class not found. We have placed the ApiMiddleware at the end of the middleware queue.

Without changing the version prefix, is there a solution to this?

Thanks

DashedRoute routing?

I can't figure out how to get the default API routing to use dashedRoute.

For example, using the cakephp-api-example repo, if my "posts" table were "blog_posts" (and the table & entity classes were appropriately renamed BlogPostsTable / BlogPost, etc.), I would wish to access the api via host/api/blog-posts instead of host/api/blog_posts. If I bake controller & templates for BlogPosts, it lights up as expected under host/blog-posts.

Perhaps this would be explained under Routing in docs, but this returns 404 ... ?

How can I read a custom action?

I created a test action in ArticlesController.

How can I acces from the Api? Because so far i can only access the CRUD actions.

All errors are returned with [status code 200 OK] in the response header. It should return the real status code of the exception.

When an exception occurs during an API call, the Status response header always returns with 200 OK, which is not appropriate for exception handling on the client code.

NOTICE: I tested this only with JSendRenderer.

The json response DOES contain an entry with the status code, like:

{
    "status": "error",
    "message": "Forbidden authorization request",
    "code": 403
}

But the status header should also contain the real status for convenience in the client code.

What's wrong in the CakeDC/Api code?

On line 115 in JSendRenderer, inside the error() function, the line goes like:

->withStatus((int)$this->errorCode)

The problem is that $this->errorCode is NEVER updated with the actual exception code (and never updated at all inside JSendRenderer), so it always equals 200.

I think the line should be:

->withStatus((int) $exception->getCode())

Or otherwise add $this->errorCode = $exception->getCode(); before building the response.

That way the status header would return with the real status code.

Unable to call method validateUnique in table provider for field username

I'm using v9.1.0 migrating from v7.x without much problems :-), but in that case the cake bake command for the UsersTable generated a validator and a Rule layers for unique field username. Both can't stay together in my code because fails as you can see below in new user entity (auth/register action). This just happens when i config in CakeDC/Users plugin my own table extending the plugin model table.

class UsersTable extends PluginUsersTable

$validator
    ->scalar('username')
    ->maxLength('username', 255)
    ->requirePresence('username', 'create')
    ->notEmptyString('username');
    // ->add('username', 'unique', ['rule' => 'validateUnique', 'provider' => 'table']);
    // para que no se repita el username no utilizar un validador, sino una regla (abajo) - DA PROBLEMAS AL REGISTRAR USUARIO   
public function buildRules(RulesChecker $rules): RulesChecker
{
    $rules->add($rules->isUnique(['username']), ['errorField' => 'username']);

[I attached the debug code]
error_provider_isUnique_cakephp_api.txt

Current composer install 3.6 / 5.0 incompatibilities

A current install of CakePHP (3.6.1) followed with

composer require cakedc/cakephp-api

pulls in 5.0.0 with at least one major incompatibility (cors extension) that I encountered.

I needed dev-master to get the thing to work.

JSONApi output format

This question is like #11 but for JSONApi formatting:

{
  "data": {
    "id": "1", // Item id
    "type": "authors", // Model name
    "attributes": { // Other attributes
      "name": "J. R. R. Tolkien",
      "date_of_birth": "1892-01-03",
      "date_of_death": "1973-09-02",
      "created_at": "2016-12-31 03:52:33",
      "updated_at": "2016-12-31 03:52:33"
    },
    "relationships": { // Interesting section
      "books": {
        "links": {
          "self": "/v1/authors/1/relationships/books",
          "related": "/v1/authors/1/books"
        }
      },
      "photos": {
        "links": {
          "self": "/v1/authors/1/relationships/photos",
          "related": "/v1/authors/1/photos"
        }
      }
    },
    "links": { // Links
      "self": "/v1/authors/1"
    }
  }
}

As this format seems much more complex to reproduce, the documentation should really state what does what in the plugin, and how we can extend it.
I'd be happy to help in any way, but I first need to understand how the plugin can be extended.

$this->getData() is always empty

On latest version of cakeapi

When we inspect $this->getData(), it is always an empty array (for POST, PUT)

We have to use this to retrieve the request payload:

$data = $this->getService()->getRequest()->input('json_decode', true);

request url /myapp/api/v1/example

headers:
'Content-Type': 'application/json',
'Accept': 'application/json'

Dependency Injection inside service actions

Is there same way to inject DI inside API Service actions ?
Actually the constructor allows only to parent $config.
It would be nice to have the possibility of getting the $container in some way to be able to inject services declared in service providers, or by autowire, since it is now available in cake.

Espose api for plugins

I am trying to use the Api plugin for my application. My application highly relies on plugins, all located inside plugin folder of the application.
I try to explain my scenario.
I have a plugin calle Acme. I have created a PostsService which extends Api Service.
In my plugin I have a folder Api -> Service -> Action -> PostsAction

namespace Acme\Api\Service\Action;

class PostsAction extends Action
{

    use LocatorAwareTrait;

    /**
     * @return bool
     */
    public function validates(): bool
    {
        return true;
    }

    /**
     * @return array
     */
    public function execute(): array
    {
        $params = Hash::get($this->getRoute(), '?');

        /** @var PostsTable $tablePosts */
        $tablePosts = $this->fetchTable('Posts');
        $query = $tablPosts->find();

        if (!empty($params['id'])) {
            $result = $query->where(['id' => $params['id']])->first();
        } else {
            $result = $query->toArray();
        }

        return [
            'posts' => $result
        ];
    }
}

Then i created a service under the namescape Acme/Service

namespace Acme\Service;

class PostsService extends ApiService {
    /**
     * @throws ReflectionException
     */
    public function initialize(): void
    {
        parent::initialize();

       $this->mapAction('list', PostsAction::class, ['method' => ['GET'], 'mapCors' => true]);

     }
}

Now I would like to test it 

`... /api/acme/posts/list`

What is the correct way to test it ? I have only route not found errors !

The documentation Routing is broken since years!!! please fix it or remove form the legend!!!

Thank you for any clarification.

Rudy

Versioning docs missing / broken link

The versioning documentation seems to be missing or the link pointing to it is wrong. The link can be found on /docs/home.md (last item from the list), but the versioning.md is not on the Documentations folder.

problems with api

I try to use this plugin but it is giving me some problerm:

I have

Service/v1/ArticleService.php

'\CakeDC\Api\Service\Action\CrudDescribeAction', 'index' => '\App\Service\v1\Action\Articles\IndexAction', 'view' => '\App\Service\v1\Action\Articles\ViewAction', 'add' => '\App\Service\v1\Action\Articles\AddAction', 'edit' => '\App\Service\v1\Action\Articles\EditAction', 'delete' => '\App\Service\v1\Action\Articles\DeleteAction', ]; } Then in the files Service\v1\Action\Articles\IndexAction _getEntities(); return $results; } } Then everything I try to visit everywhere it says a route matching articles can not be found

Cannot set response status code

I have tried setting the response code to something other than a 200.

What I tried:

In an Action

$response = $this->getService()->getResponse();
$this->getService()->setResponse($response->withStatus(404));

The response is still always a 200

API Route on my own service dosn't work

I try this form our documentation (service.md)

use App\\Posts\\FlagAction;

    public function initialize()
    {
        parent::initialize(); 
        $this->mapAction('flag', FlagAction::class, [
            'method' => ['POST'],
            'mapCors' => true,
            'path' => ':id/:flag'
        ]); 
    }

message: A route matching "/flag/1/myflag" could not be found. on line 199 in .../vendor/cakephp/cakephp/src/Routing/RouteCollection.php

I take a look into method "mapAction" if $route['path'] is set then the actionName will be missing.

Here my work arround:

use App\\Posts\\FlagAction;

    public function initialize()
    {
        parent::initialize(); 
        $this->mapAction('flag', FlagAction::class, [
            'method' => ['POST'],
            'mapCors' => true,
            'path' => 'flag/:id/:flag'
        ]); 
    }

Is it wanted like that?

I could really use an example project

I could really use a simple example project, maybe one that showcases each feature? I am glad to help, I will even get it started under my own repo's if you want, just thought I would see if you would prefer to have the example repo under CakeDC as more people will find it there...

8.0 versioning does not work

Hi,
when you try to use the versioning on the 8.0 branch you get an error.

Argument 2 passed to CakeDC\Api\Service\ConfigReader::serviceOptions() must be of the type int or null, string given, called in \vendor\cakedc\cakephp-api\src\Middleware\ParseApiRequestMiddleware.php on line 80.

This seams to be a problem with the regex in ParseApiRequestMiddleware.

If you change this part, so the error does not get thrown anymore, you remove the prefix from the capture group, but then only the fallback service will be used. It seems that in the _getClassName Method of ServiceLocator there is then missing the Prefix and cant find the Class that should be used, because the Prefix is missing from the search in the ServiceLocator.

Kind Regards

versioning config

'useVersioning' => true,
'versionPrefix' => 'v',

'Service' => [
'default' => [ ...........
'vv1' => [

Access the api at website.com/api/v1/articles

I need to declare the version as "vv1" otherwise the version configuration not loaded correctly...

Disabling public access

I have followed doc to completely disable public access of crud api:

  • loaded plugin in Application.php
  • loaded api.php configuration file
  • removed the following line from api.php configuration file:

'allow' => '*', // PUBLIC ACCESS for all API endpoints, remove this line to secure

but this is not working because my api are stille visible and open without any authentication

I would need to secure my api using url token and/or JWT

Do you have a walkthough for setup all needed part ?

Thank you

Rudy

Extension CorsExtension could not be found...

"status": "error",
"message": "Extension class CorsExtension could not be found. on line 73 in \/Users\/jlroberts\/Projects\/JeffreyLRobertsCom\/CakePHPKitchen\/AdminLTE\/vendor\/cakedc\/cakephp-api\/src\/Service\/ExtensionRegistry.php",
"code": 500,
"data": null,
"trace": [
    {
        "file": "\/Users\/jlroberts\/Projects\/JeffreyLRobertsCom\/CakePHPKitchen\/AdminLTE\/vendor\/cakephp\/cakephp\/src\/Core\/ObjectRegistry.php",
        "line": 91,
        "function": "_throwMissingClassError",
        "class": "CakeDC\\Api\\Service\\ExtensionRegistry"
    },
    {
        "file": "\/Users\/jlroberts\/Projects\/JeffreyLRobertsCom\/CakePHPKitchen\/AdminLTE\/vendor\/cakedc\/cakephp-api\/src\/Service\/Service.php",
        "line": 729,
        "function": "load",
        "class": "Cake\\Core\\ObjectRegistry"
    },

Social Login

I am trying to implement social login with FB. We are using a frontend lib to perform the FB authentication. I am then lost as to what we do next.

  • The user is asked to login with FB

  • The FB window opens asking if the suer wants to connect

  • The user clicks connect

...

  • FB calls back to our redirectUri

We are not sure what to do next... Is there any documentation on this, or perhaps a working example?

v1 version route issue

{"status":"error","message":"A route matching "/v1/articles" could not be found.","code":404,"data":null}

JSend output don't look like JSend

As per this example, the model for each dataset is sent in the response:

{
    status : "success",
    data : {
        "post" : { 
            "id" : 1, "title" : "A blog post", "body" : "Some useful content"
        }
     }
}

For now the JSend renderer outputs:

{
    status : "success",
    data : {
        "id" : 1, "title" : "A blog post", "body" : "Some useful content"
     }
}

I managed to loop through the dataset in the JsendRenderer, but I don't think that's where the code belongs to.
Where is the best place to change the output formatting when it needs data from the Table classes ?

JSendRenderer _error() function won't accept string as error code

The JSendRenderer::_error() function takes the error code as the second parameter, but it takes it as an integer param, strictly.

In my case, I got a database error with code="23000" (notice the error code is a string).

This is the error: "SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'user_id' cannot be null on line 39 in C:\xampp-new\htdocs\luna\vendor\cakephp\cakephp\src\Database\Statement\MysqlStatement.php"

Then, when JSendRenderer tries to respond, it calls $this->_error() on line 114. It quickly rises a new exception due to it trying to pass a string as error code in _error() function, which it finally sends as response:

{
"message": "Argument 2 passed to CakeDC\Api\Service\Renderer\JSendRenderer::_error() must be of the type int, string given, called in C:\xampp-new\htdocs\luna\vendor\cakedc\cakephp-api\src\Service\Renderer\JSendRenderer.php on line 114",
"url": "/api/orders",
"code": 500,
"file": "C:\xampp-new\htdocs\luna\vendor\cakedc\cakephp-api\src\Service\Renderer\JSendRenderer.php",
"line": 171
}

The strict check seems to be the problem. Hope my comment helps solving it :)

loading a component inside action

Hi,

is it possible to load a component inside an action and how to do that?

I have made a component that sanitize the data, so I can reuse it.

How to load that into the action?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.