diff --git a/api-docs.yml b/api-docs.yml index 1ea8ebe67..cad121625 100644 --- a/api-docs.yml +++ b/api-docs.yml @@ -363,6 +363,8 @@ definitions: user_id: type: integer minimum: 1 + name: + type: string ProjectRequest: type: object @@ -1426,6 +1428,16 @@ paths: - authentication - user summary: Create an API token + parameters: + - name: body + in: body + required: false + schema: + type: object + properties: + name: + type: string + example: "my CI token" responses: 201: description: API Token diff --git a/api/user.go b/api/user.go index 86a9333be..c72363e9f 100644 --- a/api/user.go +++ b/api/user.go @@ -71,6 +71,7 @@ func createAPIToken(w http.ResponseWriter, r *http.Request) { user := helpers.GetFromContext(r, "user").(*db.User) var body struct { + Name string `json:"name"` ExpiresAt *time.Time `json:"expires_at"` } if r.ContentLength > 0 { @@ -94,6 +95,7 @@ func createAPIToken(w http.ResponseWriter, r *http.Request) { UserID: user.ID, Expired: false, ExpiresAt: body.ExpiresAt, + Name: body.Name, }) if err != nil { panic(err) diff --git a/db/APIToken.go b/db/APIToken.go index 4b4150e73..6bb50c254 100644 --- a/db/APIToken.go +++ b/db/APIToken.go @@ -9,6 +9,7 @@ type APIToken struct { Expired bool `db:"expired" json:"expired"` ExpiresAt *time.Time `db:"expires_at" json:"expires_at,omitempty"` UserID int `db:"user_id" json:"user_id"` + Name string `db:"name" json:"name"` } // IsExpiredAt reports whether the token is revoked or past its expiry. diff --git a/db/sql/migrations/v2.18.2.err.sql b/db/sql/migrations/v2.18.2.err.sql index 6a85e025c..ea0ac00c3 100644 --- a/db/sql/migrations/v2.18.2.err.sql +++ b/db/sql/migrations/v2.18.2.err.sql @@ -1 +1,2 @@ alter table `user__token` drop `expires_at`; +alter table `user__token` drop `name`; diff --git a/db/sql/migrations/v2.18.2.sql b/db/sql/migrations/v2.18.2.sql index aaa874273..c3de85fd1 100644 --- a/db/sql/migrations/v2.18.2.sql +++ b/db/sql/migrations/v2.18.2.sql @@ -1 +1,2 @@ alter table `user__token` add `expires_at` datetime null; +alter table `user__token` add `name` varchar(255) not null default ''; \ No newline at end of file diff --git a/web/public/swagger/api-docs.yml b/web/public/swagger/api-docs.yml index 38821a89a..95c86d067 100644 --- a/web/public/swagger/api-docs.yml +++ b/web/public/swagger/api-docs.yml @@ -363,6 +363,8 @@ definitions: user_id: type: integer minimum: 1 + name: + type: string ProjectRequest: type: object @@ -1415,6 +1417,16 @@ paths: - authentication - user summary: Create an API token + parameters: + - name: body + in: body + required: false + schema: + type: object + properties: + name: + type: string + example: "my CI token" responses: 201: description: API Token diff --git a/web/src/lang/en.js b/web/src/lang/en.js index 8e5a68a6f..c8de24d0c 100644 --- a/web/src/lang/en.js +++ b/web/src/lang/en.js @@ -329,6 +329,7 @@ export default { status_stopped: 'Stopped', api_tokens: 'API Tokens', + tokenName: 'Token Name', // Terraform/OpenTofu/Terragrunt auto_approve: 'Auto approve', diff --git a/web/src/views/Tokens.vue b/web/src/views/Tokens.vue index a8c0ce796..260657976 100644 --- a/web/src/views/Tokens.vue +++ b/web/src/views/Tokens.vue @@ -4,6 +4,8 @@ {{ $t('New Token') }} + + + + @@ -137,6 +143,7 @@ export default { data() { return { + newTokenName: '', newTokenDialog: false, creatingToken: false, expiresInDays: 0, @@ -163,6 +170,7 @@ export default { }, newToken() { + this.newTokenName = ''; this.expiresInDays = 0; this.customExpiresAt = null; this.newTokenDialog = true; @@ -188,7 +196,10 @@ export default { method: 'post', url: '/api/user/tokens', responseType: 'json', - data: { expires_at: expiresAt }, + data: { + expires_at: expiresAt, + name: this.newTokenName, + }, }) ).data; await this.loadItems(); @@ -208,6 +219,10 @@ export default { getHeaders() { return [ + { + text: this.$i18n.t('name'), + value: 'name', + }, { text: this.$i18n.t('token'), value: 'id',