Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
Y
yii2
Project
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
PSDI Army
yii2
Commits
18c7c63e
Commit
18c7c63e
authored
Mar 05, 2014
by
Qiang Xue
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
rest WIP
parent
3f42d582
Show whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
392 additions
and
90 deletions
+392
-90
rest.md
docs/guide/rest.md
+351
-66
ActiveController.php
framework/rest/ActiveController.php
+0
-17
Controller.php
framework/rest/Controller.php
+17
-0
CreateAction.php
framework/rest/CreateAction.php
+1
-1
DeleteAction.php
framework/rest/DeleteAction.php
+1
-1
IndexAction.php
framework/rest/IndexAction.php
+1
-1
UpdateAction.php
framework/rest/UpdateAction.php
+1
-1
UrlRule.php
framework/rest/UrlRule.php
+19
-2
ViewAction.php
framework/rest/ViewAction.php
+1
-1
No files found.
docs/guide/rest.md
View file @
18c7c63e
...
@@ -147,54 +147,16 @@ While not required, it is recommended that you develop your RESTful APIs as an a
...
@@ -147,54 +147,16 @@ While not required, it is recommended that you develop your RESTful APIs as an a
your Web front end and back end.
your Web front end and back end.
Adding or Removing Endpoint
s
Creating Resource Classe
s
-------------------------
---
-------------------------
As explained above, controllers and actions are used to implement API endpoints.
RESTful APIs are all about accessing and manipulating resources. In Yii, a resource can be an object of any class.
However, if your resource classes extend from
[
[yii\base\Model
]
] or its child classes (e.g.
[
[yii\db\ActiveRecord
]
]),
you may enjoy the following benefits:
To add an API endpoint servicing a new kind of model (resource), create a new controller class by extending
*
Input data validation;
[
[yii\rest\ActiveController
]
] or
[
[yii\rest\Controller
]
]. The difference between these two base controller
*
Query, create, update and delete data, if extending from
[
[yii\db\ActiveRecord
]
];
classes is that the former is a subclass of the latter and implements a commonly needed actions to deal
*
Customizable data formatting (to be explained in the next section).
with ActiveRecord. The controller class should be named after the model class with the
`Controller`
suffix.
For example, for the
`Post`
model, you would create a
`PostController`
class.
If your new controller class extends from
[
[yii\rest\ActiveController
]
], you already have a whole set of
endpoints available out of box, as shown in the quick example. You may want to disable some of the actions
or customize them. This can be easily done by overriding the
`actions()`
method, like the following,
```
php
public
function
actions
()
{
$actions
=
parent
::
actions
();
// disable the "delete" and "create" actions
unset
(
$actions
[
'delete'
],
$actions
[
'create'
]);
// customize the data provider preparation with the "prepareDataProvider()" method
$actions
[
'index'
][
'prepareDataProvider'
]
=
[
$this
,
'prepareDataProvider'
];
return
$actions
;
}
public
function
prepareDataProvider
()
{
// prepare and return a data provider for the "index" action
}
```
You can certainly create new actions like you do with regular controllers. The only difference is that
instead of calling
[
[yii\base\Controller::render()
]
] to render views, you directly return the data
in your action. For example,
```
php
public
function
actionSearch
(
$keyword
)
{
$result
=
SolrService
::
search
(
$keyword
);
return
$result
;
}
```
The data will be automatically formatted and sent to the client, as we will explain in the next section.
Formatting Response Data
Formatting Response Data
...
@@ -203,7 +165,7 @@ Formatting Response Data
...
@@ -203,7 +165,7 @@ Formatting Response Data
By default, Yii supports two response formats for RESTful APIs: JSON and XML. If you want to support
By default, Yii supports two response formats for RESTful APIs: JSON and XML. If you want to support
other formats, you should configure
[
[yii\rest\Controller::supportedFormats
]
] and also
[
[yii\web\Response::formatters
]
].
other formats, you should configure
[
[yii\rest\Controller::supportedFormats
]
] and also
[
[yii\web\Response::formatters
]
].
The data formatting is in general a two-step proces
s:
Formatting response data in general involves two step
s:
1.
The objects (including embedded objects) in the response data are converted into arrays by
[
[yii\rest\Serializer
]
];
1.
The objects (including embedded objects) in the response data are converted into arrays by
[
[yii\rest\Serializer
]
];
2.
The array data are converted into different formats (e.g. JSON, XML) by
[
[yii\web\ResponseFormatterInterface|response formatters
]
].
2.
The array data are converted into different formats (e.g. JSON, XML) by
[
[yii\web\ResponseFormatterInterface|response formatters
]
].
...
@@ -213,32 +175,46 @@ Step 1 involves some major development effort as explained below.
...
@@ -213,32 +175,46 @@ Step 1 involves some major development effort as explained below.
When the
[
[yii\rest\Serializer|serializer
]
] converts an object into an array, it will call the
`toArray()`
method
When the
[
[yii\rest\Serializer|serializer
]
] converts an object into an array, it will call the
`toArray()`
method
of the object if it implements
[
[yii\base\ArrayableInterface
]
]. If an object does not implement this interface,
of the object if it implements
[
[yii\base\ArrayableInterface
]
]. If an object does not implement this interface,
an array consisting of all its public properties will be returne
d.
its public properties will be returned instea
d.
For classes extending from
[
[yii\base\Model
]
] or
[
[yii\db\ActiveRecord
]
], besides directly overriding
`toArray()`
,
For classes extending from
[
[yii\base\Model
]
] or
[
[yii\db\ActiveRecord
]
], besides directly overriding
`toArray()`
,
you may also override the
`fields()`
method and/or the
`extraFields()`
method to customize the data to be returned.
you may also override the
`fields()`
method and/or the
`extraFields()`
method to customize the data being returned.
The method
[
[yii\base\Model::fields()
]
] declares a set of
*fields*
that should be included in the result.
A field is simply a named data item. In a result array, the array keys are the field names, and the array values
are the corresponding field values. The default implementation of
[
[yii\base\Model::fields()
]
] is to return
all attributes of a model as the output fields; for
[
[yii\db\ActiveRecord::fields()
]
], by default it will return
the names of the attributes whose values have been populated into the object.
The method
[
[yii\base\Model::fields()
]
] declares a set of fields of an object that should be included in the result.
You can override the
`fields()`
method to add, remove, rename or redefine fields. For example,
The default implementation returns all attributes of a model as the output fields. You can customize it to add,
remove, rename or reformat the fields. For example,
```
php
```
php
class
User
extends
\yii\db\ActiveRecord
// explicitly list every field, best used when you want to make sure the changes
// in your DB table or model attributes do not cause your field changes (to keep API backward compatibility).
public
function
fields
()
{
return
[
// field name is the same as the attribute name
'id'
,
// field name is "email", the corresponding attribute name is "email_address"
'email'
=>
'email_address'
,
// field name is "name", its value is defined by a PHP callback
'name'
=>
function
()
{
return
$this
->
first_name
.
' '
.
$this
->
last_name
;
},
];
}
// filter out some fields, best used when you want to inherit the parent implementation
// and blacklist some sensitive fields.
public
function
fields
()
{
{
public
function
fields
()
{
$fields
=
parent
::
fields
();
$fields
=
parent
::
fields
();
// remove fields that contain sensitive information
// remove fields that contain sensitive information
unset
(
$fields
[
'auth_key'
],
$fields
[
'password_hash'
],
$fields
[
'password_reset_token'
]);
unset
(
$fields
[
'auth_key'
],
$fields
[
'password_hash'
],
$fields
[
'password_reset_token'
]);
// add a new field "full_name" defined as the concatenation of "first_name" and "last_name"
$fields
[
'full_name'
]
=
function
()
{
return
$this
->
first_name
.
' '
.
$this
->
last_name
;
};
return
$fields
;
return
$fields
;
}
}
}
```
```
...
@@ -274,30 +250,335 @@ For example, `http://localhost/users?fields=id,email&expand=profile` may return
...
@@ -274,30 +250,335 @@ For example, `http://localhost/users?fields=id,email&expand=profile` may return
]
]
```
```
You may wonder who triggers the conversion from objects to arrays when an action returns an object or object collection.
The answer is that this is done by
[
[yii\rest\Controller::serializer
]
] in the
[
[yii\base\Controller::afterAction()|afterAction()
]
]
method. By default,
[
[yii\rest\Serializer
]
] is used as the serializer that can recognize resource objects extending from
[
[yii\base\Model
]
] and collection objects implementing
[
[yii\data\DataProviderInterface
]
]. The serializer
will call the
`toArray()`
method of these objects and pass the
`fields`
and
`expand`
user parameters to the method.
If there are any embedded objects, they will also be converted into arrays recursively.
If all your resource objects are of
[
[yii\base\Model
]
] or its child classes, such as
[
[yii\db\ActiveRecord
]
],
and you only use
[
[yii\data\DataProviderInterface
]
] as resource collections, the default data formatting
implementation should work very well. However, if you want to introduce some new resource classes that do not
extend from
[
[yii\base\Model
]
], or if you want to use some new collection classes, you will need to
customize the serializer class and configure
[
[yii\rest\Controller::serializer
]
] to use it.
You new resource classes may use the trait
[
[yii\base\ArrayableTrait
]
] to support selective field output
as explained above.
### HATEOAS Support
TBD
Creating Controllers and Actions
--------------------------------
So you have the resource data and you have specified how the resource data should be formatted, the next thing
to do is to create controller actions to expose the resource data to end users.
Yii provides two base controller classes to simplify your work of creating RESTful actions:
[
[yii\rest\Controller
]
] and
[
[yii\rest\ActiveController
]
]. The difference between these two controllers
is that the latter provides a default set of actions that are specified designed to deal with
resources represented as ActiveRecord. So if you are using ActiveRecord and you are comfortable with
the provided built-in actions, you may consider creating your controller class by extending from
the latter. Otherwise, extending from
[
[yii\rest\Controller
]
] will allow you to develop actions
from scratch.
Both
[
[yii\rest\Controller
]
] and
[
[yii\rest\ActiveController
]
] provide the following features which will
be described in detail in the next few sections:
*
Response format negotiation;
*
API version negotiation;
*
HTTP method validation;
*
User authentication;
*
Rate limiting.
[
[yii\rest\ActiveController
]
] in addition provides the following features specifically for working
with ActiveRecord:
*
A set of commonly used actions:
`index`
,
`view`
,
`create`
,
`update`
,
`delete`
,
`options`
;
*
User authorization in regard to the requested action and resource.
When creating a new controller class, a convention in naming the controller class is to use
the type name of the resource and use singular form. For example, to serve user information,
the controller may be named as
`UserController`
.
Creating a new action is similar to creating an action for a Web application. The only difference
is that instead of rendering the result using a view by calling the
`render()`
method, for RESTful actions
you directly return the data. The
[
[yii\rest\Controller::serializer|serializer
]
] and the
[
[yii\web\Response|response object
]
] will handle the conversion from the original data to the requested
format. For example,
```
php
public
function
actionSearch
(
$keyword
)
{
$result
=
SolrService
::
search
(
$keyword
);
return
$result
;
}
```
If your controller class extends from
[
[yii\rest\ActiveController
]
], you should set
its
[
[yii\rest\ActiveController::modelClass||modelClass
]
] property to be the name of the resource class
that you plan to serve through this controller. The class must implement
[
[yii\db\ActiveRecordInterface
]
].
With
[
[yii\rest\ActiveController
]
], you may want to disable some of the built-in actions or customize them.
To do so, override the
`actions()`
method like the following:
```
php
public
function
actions
()
{
$actions
=
parent
::
actions
();
// disable the "delete" and "create" actions
unset
(
$actions
[
'delete'
],
$actions
[
'create'
]);
// customize the data provider preparation with the "prepareDataProvider()" method
$actions
[
'index'
][
'prepareDataProvider'
]
=
[
$this
,
'prepareDataProvider'
];
return
$actions
;
}
public
function
prepareDataProvider
()
{
// prepare and return a data provider for the "index" action
}
```
The following list summarizes the built-in actions supported by
[
[yii\rest\ActiveController
]
]:
*
[
[yii\rest\IndexAction|index
]
]: list resources page by page;
*
[
[yii\rest\ViewAction|view
]
]: return the details of a specified resource;
*
[
[yii\rest\CreateAction|create
]
]: create a new resource;
*
[
[yii\rest\UpdateAction|update
]
]: update an existing resource;
*
[
[yii\rest\DeleteAction|delete
]
]: delete the specified resource;
*
[
[yii\rest\OptionsAction|options
]
]: return the supported HTTP methods.
Routing
Routing
-------
-------
With resource and controller classes ready, you can access the resources using the URL like
`http://localhost/index.php?r=user/create`
. As you can see, the format of the URL is the same as that
for Web applications.
In practice, you usually want to enable pretty URLs and take advantage of HTTP verbs.
For example, a request
`POST /users`
would mean accessing the
`user/create`
action.
This can be done easily by configuring the
`urlManager`
application component in the application
configuration like the following:
```
php
'urlManager'
=>
[
'enablePrettyUrl'
=>
true
,
'enableStrictParsing'
=>
true
,
'showScriptName'
=>
false
,
'rules'
=>
[
[
'class'
=>
'yii\rest\UrlRule'
,
'controller'
=>
'user'
],
],
]
```
Compared to the URL management for Web applications, the main new thing above is the use of
[
[yii\rest\UrlRule
]
] for routing RESTful API requests. This special URL rule class will
create a whole set of child URL rules to support routing and URL creation for the specified controller(s).
For example, the above code is roughly equivalent to the following rules:
```
php
[
'PUT,PATCH users/<id>'
=>
'user/update'
,
'DELETE users/<id>'
=>
'user/delete'
,
'GET,HEAD users/<id>'
=>
'user/view'
,
'POST users'
=>
'user/create'
,
'GET,HEAD users'
=>
'user/index'
,
'users/<id>'
=>
'user/options'
,
'users'
=>
'user/options'
,
]
```
And the following API endpoints are supported by this rule:
*
`GET /users`
: list all users page by page;
*
`HEAD /users`
: show the overview information of user listing;
*
`POST /users`
: create a new user;
*
`GET /users/123`
: return the details of the user 123;
*
`HEAD /users/123`
: show the overview information of user 123;
*
`PATCH /users/123`
and
`PUT /users/123`
: update the user 123;
*
`DELETE /users/123`
: delete the user 123;
*
`OPTIONS /users`
: show the supported verbs regarding endpoint
`/users`
;
*
`OPTIONS /users/123`
: show the supported verbs regarding endpoint
`/users/123`
.
You may configure the
`only`
and
`except`
options to explicitly list which actions to support or which
actions should be disabled, respectively. For example,
```
php
[
'class'
=>
'yii\rest\UrlRule'
,
'controller'
=>
'user'
,
'except'
=>
[
'delete'
,
'create'
,
'update'
],
],
```
You may also configure
`patterns`
or
`extra`
to redefine existing patterns or add new patterns supported by this rule.
For example, to support a new action
`search`
by the endpoint
`GET /users/search`
, configure the
`extra`
option as follows,
```
php
[
'class'
=>
'yii\rest\UrlRule'
,
'controller'
=>
'user'
,
'extra'
=>
[
'GET search'
=>
'search'
,
],
```
You may have noticed that the controller ID
`user`
appears in plural form as
`users`
in the endpoints.
This is because
[
[yii\rest\UrlRule
]
] automatically pluralizes controller IDs for them to use in endpoints.
You may disable this behavior by setting
[
[yii\rest\UrlRule::pluralize
]
] to be false, or if you want
to use some special names you may configure the
[
[yii\rest\UrlRule::controller
]
] property.
Authentication
Authentication
--------------
--------------
Unlike Web applications, RESTful APIs should be stateless, which means sessions or cookies should not
be used. Therefore, each request should come with some sort of authentication credentials because
the user authentication status may not be maintained by sessions or cookies. A common practice is
to send a secret access token with each request to authenticate the user. Since an access token
can be used to uniquely identify and authenticate a user,
**
the API requests should always be sent
via HTTPS to prevent from man-in-the-middle (MitM) attacks
**
.
There are different ways to send an access token:
*
[
HTTP Basic Auth
](
http://en.wikipedia.org/wiki/Basic_access_authentication
)
: the access token
is sent as the username. This is should only be used when an access token can be safely stored
on the API consumer side. For example, the API consumer is a program running on a server.
*
Query parameter: the access token is sent as a query parameter in the API URL, e.g.,
`https://example.com/users?access-token=xxxxxxxx`
. Because most Web servers will keep query
parameters in server logs, this approach should be mainly used to serve
`JSONP`
requests which
cannot use HTTP headers to send access tokens.
*
[
OAuth 2
](
http://oauth.net/2/
)
: the access token is obtained by the consumer from an authorization
server and sent to the API server via
[
HTTP Bearer Tokens
](
http://tools.ietf.org/html/rfc6750
)
,
according to the OAuth2 protocol.
Yii supports all of the above authentication methods and can be further extended to support other methods.
To enable authentication for your APIs, do the following two steps:
1.
Configure
[
[yii\rest\Controller::authMethods
]
] with the authentication methods you plan to use.
2.
Implement
[
[yii\web\IdentityInterface::findIdentityByAccessToken()
]
] in your
[
[yii\web\User::identityClass|user identity class
]
].
For example, to enable all three authentication methods explained above, you would configure
`authMethods`
as follows,
```
php
class
UserController
extends
ActiveController
{
public
$authMethods
=
[
'yii\rest\HttpBasicAuth'
,
'yii\rest\QueryParamAuth'
,
'yii\rest\HttpBearerAuth'
,
];
}
```
Each element in
`authMethods`
should be an auth class name or a configuration array. An auth class
must implement
[
[yii\rest\AuthInterface
]
].
Implementation of
`findIdentityByAccessToken()`
is application specific. For example, in simple scenarios
when each user can only have one access token, you may store the access token in an
`access_token`
column
in the user table. The method can then be readily implemented in the
`User`
class as follows,
```
php
use
yii\db\ActiveRecord
;
use
yii\web\IdentityInterface
;
class
User
extends
ActiveRecord
implements
IdentityInterface
{
public
static
function
findIdentityByAccessToken
(
$token
)
{
return
static
::
find
([
'access_token'
=>
$token
]);
}
}
```
After authentication is enabled as described above, for every API request, the requested controller
will try to authenticate the user in its
`beforeAction()`
step.
If authentication succeeds, the controller will perform other checks (such as rate limiting, authorization)
and then run the action. The authenticated user identity information can be retrieved via
`Yii::$app->user->identity`
.
If authentication fails, a response with HTTP status 401 will be sent back together with other appropriate headers
(such as a
`WWW-Authenticate`
header for HTTP Basic Auth).
Authorization
Authorization
-------------
-------------
After a user is authenticated, you probably want to check if he has the permission to perform the requested
action for the requested resource. This process is called
*authorization*
which is covered in detail in
the
[
Authorization chapter
](
authorization.md
)
.
Versioning
You may use the
[
[yii\web\AccessControl
]
] filter and/or the Role-Based Access Control (RBAC) component
----------
to implementation authorization.
To simplify the authorization check, you may also override the
[
[yii\rest\Controller::checkAccess()
]
] method
and then call this method in places where authorization is needed. By default, the built-in actions provided
by
[
[yii\rest\ActiveController
]
] will call this method when they are about to run.
Caching
```
php
-------
/**
* Checks the privilege of the current user.
*
* This method should be overridden to check whether the current user has the privilege
* to run the specified action against the specified data model.
* If the user does not have access, a [[ForbiddenHttpException]] should be thrown.
*
* @param string $action the ID of the action to be executed
* @param \yii\base\Model $model the model to be accessed. If null, it means no specific model is being accessed.
* @param array $params additional parameters
* @throws ForbiddenHttpException if the user does not have access
*/
public
function
checkAccess
(
$action
,
$model
=
null
,
$params
=
[])
{
}
```
Rate Limiting
Rate Limiting
-------------
-------------
To prevent abuse, you should consider adding rate limiting to your APIs. For example, you may limit the API usage
of each user to be at most 100 API calls within a period of 10 minutes. If too many requests are received from a user
within the period of the time, a response with status code 429 (meaning Too Many Requests) should be returned.
To enable rate limiting, the
[
[yii\web\User::identityClass|user identity class
]
] should implement
[
[yii\rest\RateLimitInterface
]
].
This interface requires implementation of the following three methods:
*
`getRateLimit()`
: returns the maximum number of allowed requests and the time period, e.g.,
`[100, 600]`
means
at most 100 API calls within 600 seconds.
*
`loadAllowance()`
: returns the number of remaining requests allowed and the corresponding UNIX timestamp
when the rate limit is checked last time.
*
`saveAllowance()`
: saves the number of remaining requests allowed and the current UNIX timestamp.
You may use two columns in the user table to record the allowance and timestamp information.
And
`loadAllowance()`
and
`saveAllowance()`
can then be implementation by reading and saving the values
of the two columns corresponding to the current authenticated user. To improve performance, you may also
consider storing these information in cache or some NoSQL storage.
Once the identity class implements the required interface, Yii will automatically use the rate limiter
as specified by
[
[yii\rest\Controller::rateLimiter
]
] to perform rate limiting check. The rate limiter
will thrown a
[
[yii\web\TooManyRequestsHttpException
]
] if rate limit is exceeded.
When rate limiting is enabled, every response will be sent with the following HTTP headers containing
the current rate limiting information:
*
`X-Rate-Limit-Limit`
: The maximum number of requests allowed with a time period;
*
`X-Rate-Limit-Remaining`
: The number of remaining requests in the current time period;
*
`X-Rate-Limit-Reset`
: The number of seconds to wait in order to get the maximum number of allowed requests.
Caching
-------
Error Handling
Error Handling
--------------
--------------
...
@@ -309,7 +590,7 @@ Error Handling
...
@@ -309,7 +590,7 @@ Error Handling
*
`304`
: Resource was not modified. You can use the cached version.
*
`304`
: Resource was not modified. You can use the cached version.
*
`400`
: Bad request. This could be caused by various reasons from the user side, such as invalid JSON
*
`400`
: Bad request. This could be caused by various reasons from the user side, such as invalid JSON
data in the request body, invalid action parameters, etc.
data in the request body, invalid action parameters, etc.
*
`401`
:
No valid API access token is provid
ed.
*
`401`
:
Authentication fail
ed.
*
`403`
: The authenticated user is not allowed to access the specified API endpoint.
*
`403`
: The authenticated user is not allowed to access the specified API endpoint.
*
`404`
: The requested resource does not exist.
*
`404`
: The requested resource does not exist.
*
`405`
: Method not allowed. Please check the
`Allow`
header for allowed HTTP methods.
*
`405`
: Method not allowed. Please check the
`Allow`
header for allowed HTTP methods.
...
@@ -319,6 +600,10 @@ Error Handling
...
@@ -319,6 +600,10 @@ Error Handling
*
`500`
: Internal server error. This could be caused by internal program errors.
*
`500`
: Internal server error. This could be caused by internal program errors.
Versioning
----------
Documentation
Documentation
-------------
-------------
...
...
framework/rest/ActiveController.php
View file @
18c7c63e
...
@@ -9,7 +9,6 @@ namespace yii\rest;
...
@@ -9,7 +9,6 @@ namespace yii\rest;
use
yii\base\InvalidConfigException
;
use
yii\base\InvalidConfigException
;
use
yii\base\Model
;
use
yii\base\Model
;
use
yii\web\ForbiddenHttpException
;
/**
/**
* ActiveController implements a common set of actions for supporting RESTful access to ActiveRecord.
* ActiveController implements a common set of actions for supporting RESTful access to ActiveRecord.
...
@@ -124,20 +123,4 @@ class ActiveController extends Controller
...
@@ -124,20 +123,4 @@ class ActiveController extends Controller
'delete'
=>
[
'DELETE'
],
'delete'
=>
[
'DELETE'
],
];
];
}
}
/**
* Checks the privilege of the current user.
*
* This method should be overridden to check whether the current user has the privilege
* to run the specified action against the specified data model.
* If the user does not have access, a [[ForbiddenHttpException]] should be thrown.
*
* @param \yii\base\Action $action the action to be executed
* @param \yii\base\Model $model the model to be accessed. If null, it means no specific model is being accessed.
* @param array $params additional parameters
* @throws ForbiddenHttpException if the user does not have access
*/
public
function
checkAccess
(
$action
,
$model
=
null
,
$params
=
[])
{
}
}
}
framework/rest/Controller.php
View file @
18c7c63e
...
@@ -14,6 +14,7 @@ use yii\web\UnauthorizedHttpException;
...
@@ -14,6 +14,7 @@ use yii\web\UnauthorizedHttpException;
use
yii\web\UnsupportedMediaTypeHttpException
;
use
yii\web\UnsupportedMediaTypeHttpException
;
use
yii\web\TooManyRequestsHttpException
;
use
yii\web\TooManyRequestsHttpException
;
use
yii\web\VerbFilter
;
use
yii\web\VerbFilter
;
use
yii\web\ForbiddenHttpException
;
/**
/**
* Controller is the base class for RESTful API controller classes.
* Controller is the base class for RESTful API controller classes.
...
@@ -227,4 +228,20 @@ class Controller extends \yii\web\Controller
...
@@ -227,4 +228,20 @@ class Controller extends \yii\web\Controller
{
{
return
Yii
::
createObject
(
$this
->
serializer
)
->
serialize
(
$data
);
return
Yii
::
createObject
(
$this
->
serializer
)
->
serialize
(
$data
);
}
}
/**
* Checks the privilege of the current user.
*
* This method should be overridden to check whether the current user has the privilege
* to run the specified action against the specified data model.
* If the user does not have access, a [[ForbiddenHttpException]] should be thrown.
*
* @param string $action the ID of the action to be executed
* @param object $model the model to be accessed. If null, it means no specific model is being accessed.
* @param array $params additional parameters
* @throws ForbiddenHttpException if the user does not have access
*/
public
function
checkAccess
(
$action
,
$model
=
null
,
$params
=
[])
{
}
}
}
framework/rest/CreateAction.php
View file @
18c7c63e
...
@@ -41,7 +41,7 @@ class CreateAction extends Action
...
@@ -41,7 +41,7 @@ class CreateAction extends Action
public
function
run
()
public
function
run
()
{
{
if
(
$this
->
checkAccess
)
{
if
(
$this
->
checkAccess
)
{
call_user_func
(
$this
->
checkAccess
,
$this
);
call_user_func
(
$this
->
checkAccess
,
$this
->
id
);
}
}
/**
/**
...
...
framework/rest/DeleteAction.php
View file @
18c7c63e
...
@@ -32,7 +32,7 @@ class DeleteAction extends Action
...
@@ -32,7 +32,7 @@ class DeleteAction extends Action
$model
=
$this
->
findModel
(
$id
);
$model
=
$this
->
findModel
(
$id
);
if
(
$this
->
checkAccess
)
{
if
(
$this
->
checkAccess
)
{
call_user_func
(
$this
->
checkAccess
,
$this
,
$model
);
call_user_func
(
$this
->
checkAccess
,
$this
->
id
,
$model
);
}
}
if
(
$this
->
transactional
&&
$model
instanceof
ActiveRecord
)
{
if
(
$this
->
transactional
&&
$model
instanceof
ActiveRecord
)
{
...
...
framework/rest/IndexAction.php
View file @
18c7c63e
...
@@ -38,7 +38,7 @@ class IndexAction extends Action
...
@@ -38,7 +38,7 @@ class IndexAction extends Action
public
function
run
()
public
function
run
()
{
{
if
(
$this
->
checkAccess
)
{
if
(
$this
->
checkAccess
)
{
call_user_func
(
$this
->
checkAccess
,
$this
);
call_user_func
(
$this
->
checkAccess
,
$this
->
id
);
}
}
return
$this
->
prepareDataProvider
();
return
$this
->
prepareDataProvider
();
...
...
framework/rest/UpdateAction.php
View file @
18c7c63e
...
@@ -41,7 +41,7 @@ class UpdateAction extends Action
...
@@ -41,7 +41,7 @@ class UpdateAction extends Action
$model
=
$this
->
findModel
(
$id
);
$model
=
$this
->
findModel
(
$id
);
if
(
$this
->
checkAccess
)
{
if
(
$this
->
checkAccess
)
{
call_user_func
(
$this
->
checkAccess
,
$this
,
$model
);
call_user_func
(
$this
->
checkAccess
,
$this
->
id
,
$model
);
}
}
$model
->
scenario
=
$this
->
scenario
;
$model
->
scenario
=
$this
->
scenario
;
...
...
framework/rest/UrlRule.php
View file @
18c7c63e
...
@@ -93,6 +93,12 @@ class UrlRule extends CompositeUrlRule
...
@@ -93,6 +93,12 @@ class UrlRule extends CompositeUrlRule
*/
*/
public
$except
=
[];
public
$except
=
[];
/**
/**
* @var array patterns for supporting extra actions in addition to those listed in [[patterns]].
* The keys are the patterns and the values are the corresponding action IDs.
* These extra patterns will take precedence over [[patterns]].
*/
public
$extra
=
[];
/**
* @var array list of tokens that should be replaced for each pattern. The keys are the token names,
* @var array list of tokens that should be replaced for each pattern. The keys are the token names,
* and the values are the corresponding replacements.
* and the values are the corresponding replacements.
* @see patterns
* @see patterns
...
@@ -117,9 +123,19 @@ class UrlRule extends CompositeUrlRule
...
@@ -117,9 +123,19 @@ class UrlRule extends CompositeUrlRule
'{id}'
=>
'options'
,
'{id}'
=>
'options'
,
''
=>
'options'
,
''
=>
'options'
,
];
];
/**
* @var array the default configuration for creating each URL rule contained by this rule.
*/
public
$ruleConfig
=
[
public
$ruleConfig
=
[
'class'
=>
'yii\web\UrlRule'
,
'class'
=>
'yii\web\UrlRule'
,
];
];
/**
* @var boolean whether to automatically pluralize the URL names for controllers.
* If true, a controller ID will appear in plural form in URLs. For example, `user` controller
* will appear as `users` in URLs.
* @see controllers
*/
public
$pluralize
=
true
;
/**
/**
...
@@ -134,7 +150,7 @@ class UrlRule extends CompositeUrlRule
...
@@ -134,7 +150,7 @@ class UrlRule extends CompositeUrlRule
$controllers
=
[];
$controllers
=
[];
foreach
((
array
)
$this
->
controller
as
$urlName
=>
$controller
)
{
foreach
((
array
)
$this
->
controller
as
$urlName
=>
$controller
)
{
if
(
is_integer
(
$urlName
))
{
if
(
is_integer
(
$urlName
))
{
$urlName
=
Inflector
::
pluralize
(
$controller
)
;
$urlName
=
$this
->
pluralize
?
Inflector
::
pluralize
(
$controller
)
:
$controller
;
}
}
$controllers
[
$urlName
]
=
$controller
;
$controllers
[
$urlName
]
=
$controller
;
}
}
...
@@ -152,10 +168,11 @@ class UrlRule extends CompositeUrlRule
...
@@ -152,10 +168,11 @@ class UrlRule extends CompositeUrlRule
{
{
$only
=
array_flip
(
$this
->
only
);
$only
=
array_flip
(
$this
->
only
);
$except
=
array_flip
(
$this
->
except
);
$except
=
array_flip
(
$this
->
except
);
$patterns
=
array_merge
(
$this
->
patterns
,
$this
->
extra
);
$rules
=
[];
$rules
=
[];
foreach
(
$this
->
controller
as
$urlName
=>
$controller
)
{
foreach
(
$this
->
controller
as
$urlName
=>
$controller
)
{
$prefix
=
trim
(
$this
->
prefix
.
'/'
.
$urlName
,
'/'
);
$prefix
=
trim
(
$this
->
prefix
.
'/'
.
$urlName
,
'/'
);
foreach
(
$
this
->
patterns
as
$pattern
=>
$action
)
{
foreach
(
$patterns
as
$pattern
=>
$action
)
{
if
(
!
isset
(
$except
[
$action
])
&&
(
empty
(
$only
)
||
isset
(
$only
[
$action
])))
{
if
(
!
isset
(
$except
[
$action
])
&&
(
empty
(
$only
)
||
isset
(
$only
[
$action
])))
{
$rules
[
$urlName
][]
=
$this
->
createRule
(
$pattern
,
$prefix
,
$controller
.
'/'
.
$action
);
$rules
[
$urlName
][]
=
$this
->
createRule
(
$pattern
,
$prefix
,
$controller
.
'/'
.
$action
);
}
}
...
...
framework/rest/ViewAction.php
View file @
18c7c63e
...
@@ -26,7 +26,7 @@ class ViewAction extends Action
...
@@ -26,7 +26,7 @@ class ViewAction extends Action
{
{
$model
=
$this
->
findModel
(
$id
);
$model
=
$this
->
findModel
(
$id
);
if
(
$this
->
checkAccess
)
{
if
(
$this
->
checkAccess
)
{
call_user_func
(
$this
->
checkAccess
,
$this
,
$model
);
call_user_func
(
$this
->
checkAccess
,
$this
->
id
,
$model
);
}
}
return
$model
;
return
$model
;
}
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment