Ensure deploy tokens `expires_at` does not accept invalid dates
What does this MR do and why?
This merge request ensures that deploy tokens expires_at
does not accept invalid inputs (i.e. not in iso8601
format).
This also fixes the bug in which an invalid input would become null
before the token is persisted, resulting in the following exception:
ActiveRecord::NotNullViolation: PG::NotNullViolation: ERROR: null value in column "expires_at" violates not-null constraint
Please note:
- The bug is currently not reproducible via the UI (as the date picker only allows valid dates).
- However, it can still be reproduced when creating deploy tokens via the API.
Resolves #372090.
How to set up and validate locally
- In your local GDK setup, create a project if you don't have one already.
- Make note of the
id
of the new project.
Validate through the API
With invalid input:
- Send a request to create a deploy token:
- Replace
PROJECT_ID
with the id of your project. - Replace
USE_YOUR_OWN_TOKEN_HERE
with your access token.
- Replace
curl -H "PRIVATE-TOKEN: USE_YOUR_OWN_TOKEN_HERE" -X GET "http://gdk.test:3000/api/v4/projects/PROJECT_ID/deploy_tokens" -D '{"expires_at": "text", "name": "New token", "username": "custom-user", "scopes": ["read_repository"]}'
-
Verify the request returns
400 bad request
as status with the following message:expires_at is invalid
. -
Verify that you have not received a
500 internal server error
as status.
With valid input:
- Do the same, replacing
expires_at
with a date in the future (e.g.2023-01-01
).
curl -H "PRIVATE-TOKEN: USE_YOUR_OWN_TOKEN_HERE" -X GET "http://gdk.test:3000/api/v4/projects/PROJECT_ID/deploy_tokens" -D '{"expires_at": "2023-01-01", "name": "new token", "username": "custom user", "scopes": ["read_repository"]}'
-
Verify the request returns
201 created
as status with the body containing the new deploy token data.
rails
console
Validate through You could also verify this in the rails
console. Do not forget to replace PROJECT_ID
with the id of the project you created.
pry(main)> project = Project.find(PROJECT_ID)
pry(main)> deploy_token = project.deploy_tokens.create(name: 'new token', expires_at: 'text', read_repository: true)
pry(main)> deploy_token.errors
pry(main)> => #<ActiveModel::Errors:0x0000000163464330
@base=
#<DeployToken:0x000000016240f9a8
id: nil,
revoked: false,
read_repository: true,
read_registry: false,
expires_at: nil,
created_at: nil,
name: "new",
username: nil,
token_encrypted: nil,
deploy_token_type: "project_type",
write_registry: false,
read_package_registry: false,
write_package_registry: false,
creator_id: nil>,
@errors=[#<ActiveModel::Error attribute=base, type=expires_at must be in ISO 8601 format, options={}>]>
Please note: the two errors returned from the API and the rails
console is different because grape
validates if expires_at
is a datetime
and yields an is invalid
error before we even get to the model validation.
However, trying to create an object of DeployToken
with a datetime
that cannot be parsed as iso8601
(e.g. output of 1.day.from_now
which is a ActiveSupport::TimeWithZone
object) is when the model validation comes in handy!
MR acceptance checklist
This checklist encourages us to confirm any changes have been analyzed to reduce risks in quality, performance, reliability, security, and maintainability.
-
I have evaluated the MR acceptance checklist for this MR.