feat: expose access token creation date in API responses (#12620)

## Checklist

Following the previous contribution that added admin-level management of user access tokens (particularly useful for bot/service accounts), this change exposes the created_at field in the API response when listing or retrieving access tokens.

This information is needed to implement token rotation policies for these users — knowing when a token was created allows administrators to identify and revoke stale tokens.

### Tests for Go changes

- I added test coverage for Go changes...
  - [X] in their respective `*_test.go` for unit tests.
  - [X] `make pr-go` before pushing

### Documentation

- [X] I did not document these changes and I do not expect someone else to do it.

### Release notes

- [X] This change will be noticed by a Forgejo user or admin (feature, bug fix, performance, etc.). I suggest to include a release note for this change.

<!--start release-notes-assistant-->

## Release notes
<!--URL:https://codeberg.org/forgejo/forgejo-->
- Features
  - [PR](https://codeberg.org/forgejo/forgejo/pulls/12620): <!--number 12620 --><!--line 0 --><!--description ZXhwb3NlIGFjY2VzcyB0b2tlbiBjcmVhdGlvbiBkYXRlIGluIEFQSSByZXNwb25zZXM=-->expose access token creation date in API responses<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/12620
Reviewed-by: Andreas Ahlenstorf <aahlenst@noreply.codeberg.org>
This commit is contained in:
steven.guiheux
2026-05-20 18:45:38 +02:00
committed by Mathieu Fenniak
parent aec047c7b5
commit 0ef80f6b0f
5 changed files with 17 additions and 5 deletions
@@ -43,6 +43,7 @@ func TestAPIAdminCreateUserAccessToken(t *testing.T) {
assert.NotEmpty(t, newToken.Token)
assert.NotEmpty(t, newToken.TokenLastEight)
assert.Contains(t, newToken.Scopes, "all")
assert.NotZero(t, newToken.Created)
// Verify the token exists in DB
unittest.AssertExistsAndLoadBean(t, &auth_model.AccessToken{
@@ -143,6 +144,7 @@ func TestAPIAdminListUserAccessTokens(t *testing.T) {
if tk.Name == "list-test-token" {
found = true
assert.NotEmpty(t, tk.TokenLastEight)
assert.NotZero(t, tk.Created)
break
}
}
+2
View File
@@ -57,6 +57,7 @@ func TestAPIGetTokens(t *testing.T) {
assert.Equal(t, []string{""}, at.Scopes)
assert.Empty(t, at.Token)
assert.Equal(t, "69d28c91", at.TokenLastEight)
assert.NotZero(t, at.Created)
assert.Nil(t, at.Repositories) // not repo-specific access token - nil expected, not an empty array
})
@@ -753,6 +754,7 @@ func TestAPITokenCreation(t *testing.T) {
resp := MakeRequest(t, req, http.StatusCreated)
var token api.AccessToken
DecodeJSON(t, resp, &token)
assert.NotZero(t, token.Created)
})
t.Run("repo-specific", func(t *testing.T) {