Repository navigation
Releases
Releases · 4spacesdk/CI4RESTExtension
v1.0.23
Fixed bugs
- The API parser's items declare their properties.
ApiItem,EndpointItem,InterfaceItem,
ParameterItem,PropertyItemandApiParseritself set properties they only named in a
@propertyline, and PHP 8.2 and later reports each such property as deprecated each time it
is set. One document of an app with some hundred endpoints was more than sixty thousand of
them, and CodeIgniter logs every one with its stack trace: seconds forgenerateOpenApi()or
an export, more memory than a request or a test has, and logs of a gigabyte a day. Every
property is declared now, with the default it had, so nothing is reported and nothing else
changes - the documents and exports are as they were. A test fails on any deprecation of the
parsers.
Upgrade guide
- Requires OrmExtension v1.1.10, whose model parser declares its properties the same way.
- An app that silenced the parsers' deprecations can stop doing so.
Full Changelog: v1.0.22...v1.0.23
v1.0.22
Enhancements
ApiParser::generateOpenApi()makes a whole, valid OpenAPI 3.0 document.generateSwagger()
gave the paths, and the app put them together with OrmExtension's schemas. Those named a
relation astype: "Workspace"and a nullable astype: "?int", which no OpenAPI reader takes,
and left out a schema only another schema named. The new document has every endpoint, with an
operationId, and the schemas of the models, interfaces and static schemas the endpoints name,
and those they name in turn - a relation and an interface's property as a$ref, a?intas
nullable, anint[]in the query asids=1,2,3, aFileas a field of a multipart body. Every
$refpoints at a schema. It is checked against an OpenAPI reader in the tests.- An endpoint's doc comment is its documentation. The text above the tags is the operation's
summary and description, as PHPDoc has them;@summaryand the new@descriptionsay them over
it. The text after-on a@paramor@parameteris the parameter's description, and the
comment after a@propertythe property's. A resource controller's overriddenget(),post()
and so on keep their text to themselves - it says why they are overridden - and are documented by
@summaryand@descriptiononly.
Fixed bugs
required=falseis not required. It was the string"false", which PHP takes for true, so
generateSwagger()said such a parameter was required. A parameter withoutrequired=is still
required, as it was.
Upgrade guide
- Requires OrmExtension v1.1.9, which has the schemas of the models and the types of OpenAPI.
- Nothing else changes:
generateSwagger(), apart fromrequired=false, and the TypeScript, Vue and
Xamarin exports are as they were. The text of a doc comment is not the summary in Api.ts. - To move to the new document, build it with
generateOpenApi()- see "API Parser" in the README -
where you put togethergenerateSwagger()'s paths andModelParser::generateSwagger()'s schemas.
Give it yourinfo,serversand security schemes;contactbelongs ininfo, and
definitionsis Swagger 2.0, not OpenAPI 3.
Full Changelog: v1.0.21...v1.0.22
v1.0.21
Fixed bugs
- Two relations under the same parent in one request no longer lose all but the last.
include=company.owner_team,company.countryis two includes ofcompany, and with
relationsFollowRuleson each of them fetched the company again and wrote it over the row, so
only the last one was there. Includes that ask nothing else of their parent are now made one
before anything is fetched - one request to the related model instead of two, and nothing to
write over. Without the rules the joins piled up on one query and both already arrived; that is
unchanged. An include with a filter, an ordering or a limit of its own stays as it was: those
belong to that one include, and folding two of them together would change what was asked.
Security
- A sub query followed by more is refused instead of answered wrongly. A comma ends a sub
query, soinclude=a?include=b,cisawithbunder it andcas an include of its own -
not, as it reads,bandcboth undera. Where the model being asked has nocthe
request failed; where it happened to have one, the answer came back withchanging off the
wrong row and nothing to say so. No encoding got round it: the comma is decoded long before the
parser sees it. It is now 422InvalidRequest, naming the dotted form that says either meaning.
Upgrade guide
include=a?include=b,cand anything else that puts a comma after an?include=sub query now
answers 422. Writea.b,a.cfor both undera, or put the plain include first, as
c,a?include=b. A sub query oforderingorfilterfollowed by a comma is untouched.- Nothing else to do. An
includethat was already right returns what it always did.
Full Changelog: v1.0.20...v1.0.21
v1.0.20
Security
-
Writes can follow the rules. With
writesFollowRuleson, a write through the resource
controller goes through the same rules as a read. Off, any caller may read any row: a PATCH
that changes nothing, or a POST with anid, answers with the row that id names without
asking a rule. And a relation given as an object is linked and saved after the rules have been
asked. On:- PATCH, PUT and DELETE of a row
preRestGet()hides is 404, as GET by id is; - a POST ignores an
id, and every write ignores relations given as objects - a relation is
written by its column, which the rules see; - a list of rows is 400
OneResourcePerRequest; - a rule's no is 403
InsufficientAccess, instead of 200 with the unsaved row.
See "Writes and rules" in the README.
- PATCH, PUT and DELETE of a row
-
isRestVisible($id, $queryParser)says whether the caller may read a row, bypreRestGet().
Upgrade guide
- Nothing to do: with
writesFollowRulesoff, nothing changes. - Before turning it on, look for clients that create or change related rows through a relation
given as an object, or post lists of rows: they write each row on its own, through its own
resource, instead.
Full Changelog: v1.0.19...v1.0.20
v1.0.19
Enhancements
- The API export reads more than the app's own controllers and interfaces.
$apiControllerNamespaceand$apiInterfaceNamespacemay be lists, and every namespace in them
is exported - a composer package's along with the app's. Their directories come from
CodeIgniter's autoloader, so subdirectories and packages work asApp\Controllersalways has. A
controller by the same name in two namespaces is the first namespace's. $resourceControllerClasssays which base classes make a controller a resource controller, a
class or a list. It isApp\Core\ResourceControllerunless it says otherwise, as it always was.
Upgrade guide
- Requires CI4OrmExtension 1.1.7.
- Nothing else to do: with one namespace each, the export is the same, byte for byte.
v1.0.18
Include a path through a has-many at every level when relations follo…
v1.0.17
v1.0.16
The TypeScript export can produce a complete Angular client: BaseApi …
v1.0.15
Fixed bugs
- The Vue and TypeScript api clients build when an endpoint has a query parameter named
scope,
summary,topicormethod. The endpoint class has properties with those names, and gave the
parameter a method of the same name, which TypeScript refuses withTS2300: Duplicate identifier.
A query parameter namedscopeorsummarynow takes the place of the property, which BaseApi
never reads. One namedtopicormethodgets the methodtopicParameter()ormethodParameter(),
since BaseApi readsmethodto choose between post, put and patch.
Upgrade guide
- Nothing to do. Every endpoint without such a parameter is generated as before.
Full Changelog: v1.0.14...v1.0.15
v1.0.14
Security
- The access, error and blocked logs no longer store the access token.
user_idandclient_id
still say who called. - The error log writes the value of every header that carries a credential as
[redacted]:
Authorization,Proxy-Authorization,CookieandSet-Cookie, plus any the application names in
$redactedHeaders. It used to store them all as they were, for every request that ended in an
exception, refused ones included. - A filter, a search,
fieldsandorderingmay only name a column of the model's table, or of a
related model's, and never one of the entity'shiddenFields. Filters andfieldsused to reach
the query builder as they were written, so a hidden column such as a password hash could be read a
character at a time. A hidden column is refused with the same words as one that is not there.
Enhancements
RestExtension\Logs::PruneOlderThan($days)removes old rows from the three log tables, in
portions. Nothing removed them before; schedule it from the application.
Fixed bugs
- The hooks and the log cleanup connect to the default database group when
databaseGroupNameis not
set, instead of the group nameddefault. Under test the default is the test database. - Deprecations from PHP 8.2 to 8.5: dynamic properties on
QueryFilter,QueryIncludeandQueryOrder,
implicitly nullable parameters inCore\Model, a(double)cast, and a null message passed to
UnauthorizedException.
Dependencies
codeigniter4/frameworkand4spacesdk/ci4ormextensionare required, as the code has always
needed them. The suggestion of4spacesdk/ci4restextension-zmqis gone.
Upgrade guide
- A filter,
fieldsororderingon a column that is not there, or is hidden, is now an
InvalidRequestException(400) instead of a server error or an answer. - Existing rows keep the tokens and headers they were written with. Clear
access_tokenand redact
api_error_logs.headerswith a migration of your own if they matter.
Full Changelog: v1.0.13...v1.0.14