diff --git a/entry_token.go b/entry_token.go deleted file mode 100644 index 9779177..0000000 --- a/entry_token.go +++ /dev/null @@ -1,50 +0,0 @@ -package gitlab - -import ( - "strconv" - "time" -) - -type EntryToken struct { - TokenID int `json:"token_id"` - UserID int `json:"user_id"` - ParentID string `json:"parent_id"` - Path string `json:"path"` - Name string `json:"name"` - Token string `json:"token"` - TokenType TokenType `json:"token_type"` - CreatedAt *time.Time `json:"created_at"` - ExpiresAt *time.Time `json:"expires_at"` - Scopes []string `json:"scopes"` - AccessLevel AccessLevel `json:"access_level"` // not used for personal access tokens - RoleName string `json:"role_name"` - ConfigName string `json:"config_name"` - GitlabRevokesToken bool `json:"gitlab_revokes_token"` -} - -func (e EntryToken) SecretResponse() (map[string]any, map[string]any) { - return map[string]any{ - "name": e.Name, - "token": e.Token, - "path": e.Path, - "scopes": e.Scopes, - "role_name": e.RoleName, - "access_level": e.AccessLevel.String(), - "created_at": e.CreatedAt, - "expires_at": e.ExpiresAt, - }, - map[string]any{ - "path": e.Path, - "name": e.Name, - "token": e.Token, - "user_id": e.UserID, - "parent_id": e.ParentID, - "token_id": e.TokenID, - "token_type": e.TokenType.String(), - "scopes": e.Scopes, - "access_level": e.AccessLevel.String(), - "role_name": e.RoleName, - "config_name": e.ConfigName, - "gitlab_revokes_token": strconv.FormatBool(e.GitlabRevokesToken), - } -} diff --git a/gitlab_client.go b/gitlab_client.go index a87a5e1..7857b70 100644 --- a/gitlab_client.go +++ b/gitlab_client.go @@ -25,26 +25,26 @@ type Client interface { GitlabClient(ctx context.Context) *g.Client Valid(ctx context.Context) bool Metadata(ctx context.Context) (*g.Metadata, error) - CurrentTokenInfo(ctx context.Context) (*EntryToken, error) - RotateCurrentToken(ctx context.Context) (newToken *EntryToken, oldToken *EntryToken, err error) - CreatePersonalAccessToken(ctx context.Context, username string, userId int, name string, expiresAt time.Time, scopes []string) (*EntryToken, error) - CreateGroupAccessToken(ctx context.Context, groupId string, name string, expiresAt time.Time, scopes []string, accessLevel AccessLevel) (*EntryToken, error) - CreateProjectAccessToken(ctx context.Context, projectId string, name string, expiresAt time.Time, scopes []string, accessLevel AccessLevel) (*EntryToken, error) + CurrentTokenInfo(ctx context.Context) (*TokenConfig, error) + RotateCurrentToken(ctx context.Context) (newToken *TokenConfig, oldToken *TokenConfig, err error) + CreatePersonalAccessToken(ctx context.Context, username string, userId int, name string, expiresAt time.Time, scopes []string) (*TokenPersonal, error) + CreateGroupAccessToken(ctx context.Context, groupId string, name string, expiresAt time.Time, scopes []string, accessLevel AccessLevel) (*TokenGroup, error) + CreateProjectAccessToken(ctx context.Context, projectId string, name string, expiresAt time.Time, scopes []string, accessLevel AccessLevel) (*TokenProject, error) RevokePersonalAccessToken(ctx context.Context, tokenId int) error RevokeProjectAccessToken(ctx context.Context, tokenId int, projectId string) error RevokeGroupAccessToken(ctx context.Context, tokenId int, groupId string) error GetUserIdByUsername(ctx context.Context, username string) (int, error) GetGroupIdByPath(ctx context.Context, path string) (int, error) GetProjectIdByPath(ctx context.Context, path string) (int, error) - CreateGroupServiceAccountAccessToken(ctx context.Context, group string, groupId string, userId int, name string, expiresAt time.Time, scopes []string) (*EntryToken, error) - CreateUserServiceAccountAccessToken(ctx context.Context, username string, userId int, name string, expiresAt time.Time, scopes []string) (*EntryToken, error) + CreateGroupServiceAccountAccessToken(ctx context.Context, group string, groupId string, userId int, name string, expiresAt time.Time, scopes []string) (*TokenGroupServiceAccount, error) + CreateUserServiceAccountAccessToken(ctx context.Context, username string, userId int, name string, expiresAt time.Time, scopes []string) (*TokenUserServiceAccount, error) RevokeUserServiceAccountAccessToken(ctx context.Context, token string) error RevokeGroupServiceAccountAccessToken(ctx context.Context, token string) error - CreatePipelineProjectTriggerAccessToken(ctx context.Context, path, name string, projectId int, description string, expiresAt *time.Time) (*EntryToken, error) + CreatePipelineProjectTriggerAccessToken(ctx context.Context, path, name string, projectId int, description string, expiresAt *time.Time) (*TokenPipelineProjectTrigger, error) RevokePipelineProjectTriggerAccessToken(ctx context.Context, projectId int, tokenId int) error - CreateProjectDeployToken(ctx context.Context, path string, projectId int, name string, expiresAt *time.Time, scopes []string) (et *EntryToken, err error) + CreateProjectDeployToken(ctx context.Context, path string, projectId int, name string, expiresAt *time.Time, scopes []string) (et *TokenProjectDeploy, err error) RevokeProjectDeployToken(ctx context.Context, projectId, deployTokenId int) (err error) - CreateGroupDeployToken(ctx context.Context, path string, groupId int, name string, expiresAt *time.Time, scopes []string) (et *EntryToken, err error) + CreateGroupDeployToken(ctx context.Context, path string, groupId int, name string, expiresAt *time.Time, scopes []string) (et *TokenGroupDeploy, err error) RevokeGroupDeployToken(ctx context.Context, groupId, deployTokenId int) (err error) } @@ -69,7 +69,7 @@ func (gc *gitlabClient) GetProjectIdByPath(ctx context.Context, path string) (pr return projectId, err } -func (gc *gitlabClient) CreateGroupDeployToken(ctx context.Context, path string, groupId int, name string, expiresAt *time.Time, scopes []string) (et *EntryToken, err error) { +func (gc *gitlabClient) CreateGroupDeployToken(ctx context.Context, path string, groupId int, name string, expiresAt *time.Time, scopes []string) (et *TokenGroupDeploy, err error) { var dt *g.DeployToken defer func() { gc.logger.Debug("Create group deploy token", "groupId", groupId, "name", name, "path", path, "expiresAt", expiresAt, "scopes", scopes, "error", err) @@ -84,22 +84,26 @@ func (gc *gitlabClient) CreateGroupDeployToken(ctx context.Context, path string, }, g.WithContext(ctx), ); err == nil { - et = &EntryToken{ - TokenID: dt.ID, - ParentID: strconv.Itoa(groupId), - Path: path, - Name: name, - Token: dt.Token, - TokenType: TokenTypeGroupDeploy, - Scopes: scopes, - AccessLevel: AccessLevelUnknown, - CreatedAt: g.Ptr(time.Now()), + et = &TokenGroupDeploy{ + TokenWithScopes: TokenWithScopes{ + Token: Token{ + TokenID: dt.ID, + ParentID: strconv.Itoa(groupId), + Path: path, + Name: name, + Token: dt.Token, + TokenType: TokenTypeGroupDeploy, + CreatedAt: g.Ptr(time.Now()), + }, + Scopes: scopes, + }, + Username: dt.Username, } } return et, err } -func (gc *gitlabClient) CreateProjectDeployToken(ctx context.Context, path string, projectId int, name string, expiresAt *time.Time, scopes []string) (et *EntryToken, err error) { +func (gc *gitlabClient) CreateProjectDeployToken(ctx context.Context, path string, projectId int, name string, expiresAt *time.Time, scopes []string) (et *TokenProjectDeploy, err error) { var dt *g.DeployToken defer func() { gc.logger.Debug("Create project deploy token", "projectId", projectId, "name", name, "path", path, "expiresAt", expiresAt, "scopes", scopes, "error", err) @@ -113,16 +117,20 @@ func (gc *gitlabClient) CreateProjectDeployToken(ctx context.Context, path strin }, g.WithContext(ctx), ); err == nil { - et = &EntryToken{ - TokenID: dt.ID, - ParentID: strconv.Itoa(projectId), - Path: path, - Name: name, - Token: dt.Token, - TokenType: TokenTypeProjectDeploy, - Scopes: scopes, - AccessLevel: AccessLevelUnknown, - CreatedAt: g.Ptr(time.Now()), + et = &TokenProjectDeploy{ + TokenWithScopes: TokenWithScopes{ + Token: Token{ + TokenID: dt.ID, + ParentID: strconv.Itoa(projectId), + Path: path, + Name: name, + Token: dt.Token, + TokenType: TokenTypeProjectDeploy, + CreatedAt: g.Ptr(time.Now()), + }, + Scopes: scopes, + }, + Username: dt.Username, } } return et, err @@ -155,7 +163,7 @@ func (gc *gitlabClient) Metadata(ctx context.Context) (metadata *g.Metadata, err return metadata, err } -func (gc *gitlabClient) CreatePipelineProjectTriggerAccessToken(ctx context.Context, path, name string, projectId int, description string, expiresAt *time.Time) (et *EntryToken, err error) { +func (gc *gitlabClient) CreatePipelineProjectTriggerAccessToken(ctx context.Context, path, name string, projectId int, description string, expiresAt *time.Time) (et *TokenPipelineProjectTrigger, err error) { var pt *g.PipelineTrigger defer func() { gc.logger.Debug("Create a pipeline project trigger access token", "path", path, "name", name, "projectId", description, "description", "error", err) @@ -166,16 +174,17 @@ func (gc *gitlabClient) CreatePipelineProjectTriggerAccessToken(ctx context.Cont &g.AddPipelineTriggerOptions{Description: &description}, g.WithContext(ctx), ); err == nil { - et = &EntryToken{ - TokenID: pt.ID, - ParentID: strconv.Itoa(projectId), - Path: path, - Name: name, - Token: pt.Token, - TokenType: TokenTypePipelineProjectTrigger, - Scopes: []string{}, - AccessLevel: AccessLevelUnknown, - ExpiresAt: expiresAt, + et = &TokenPipelineProjectTrigger{ + Token: Token{ + TokenID: pt.ID, + ParentID: strconv.Itoa(projectId), + Path: path, + Name: name, + Token: pt.Token, + TokenType: TokenTypePipelineProjectTrigger, + CreatedAt: g.Ptr(time.Now()), + ExpiresAt: expiresAt, + }, } } @@ -216,7 +225,7 @@ func (gc *gitlabClient) GitlabClient(ctx context.Context) *g.Client { return gc.client } -func (gc *gitlabClient) CreateGroupServiceAccountAccessToken(ctx context.Context, path string, groupId string, userId int, name string, expiresAt time.Time, scopes []string) (et *EntryToken, err error) { +func (gc *gitlabClient) CreateGroupServiceAccountAccessToken(ctx context.Context, path string, groupId string, userId int, name string, expiresAt time.Time, scopes []string) (et *TokenGroupServiceAccount, err error) { var at *g.PersonalAccessToken defer func() { gc.logger.Debug("Create group service access token", "pat", at, "et", et, "path", path, "groupId", groupId, "userId", userId, "name", name, "expiresAt", expiresAt, "scopes", scopes, "error", err) @@ -227,30 +236,48 @@ func (gc *gitlabClient) CreateGroupServiceAccountAccessToken(ctx context.Context Scopes: &scopes, }, g.WithContext(ctx)) if err == nil { - et = &EntryToken{ - TokenID: at.ID, - UserID: userId, - ParentID: groupId, - Path: path, - Name: name, - Token: at.Token, - TokenType: TokenTypeGroupServiceAccount, - CreatedAt: at.CreatedAt, - ExpiresAt: (*time.Time)(at.ExpiresAt), - Scopes: scopes, - AccessLevel: AccessLevelUnknown, + et = &TokenGroupServiceAccount{ + TokenWithScopes: TokenWithScopes{ + Token: Token{ + TokenID: at.ID, + ParentID: groupId, + Path: path, + Name: name, + Token: at.Token, + TokenType: TokenTypeGroupServiceAccount, + CreatedAt: at.CreatedAt, + ExpiresAt: (*time.Time)(at.ExpiresAt), + }, + Scopes: scopes, + }, + UserID: userId, } } return et, err } -func (gc *gitlabClient) CreateUserServiceAccountAccessToken(ctx context.Context, username string, userId int, name string, expiresAt time.Time, scopes []string) (et *EntryToken, err error) { +func (gc *gitlabClient) CreateUserServiceAccountAccessToken(ctx context.Context, username string, userId int, name string, expiresAt time.Time, scopes []string) (et *TokenUserServiceAccount, err error) { defer func() { gc.logger.Debug("Create user service access token", "et", et, "username", username, "userId", userId, "name", name, "expiresAt", expiresAt, "scopes", scopes, "error", err) }() - et, err = gc.CreatePersonalAccessToken(ctx, username, userId, name, expiresAt, scopes) - if err == nil && et != nil { - et.TokenType = TokenTypeUserServiceAccount + var etp *TokenPersonal + etp, err = gc.CreatePersonalAccessToken(ctx, username, userId, name, expiresAt, scopes) + if err == nil && etp != nil { + et = &TokenUserServiceAccount{ + TokenWithScopes: TokenWithScopes{ + Token: Token{ + TokenID: etp.TokenID, + ParentID: etp.ParentID, + Path: etp.Path, + Name: etp.Name, + Token: etp.Token.Token, + TokenType: TokenTypeUserServiceAccount, + CreatedAt: etp.CreatedAt, + ExpiresAt: etp.ExpiresAt, + }, + Scopes: etp.Scopes, + }, + } } return et, err } @@ -291,28 +318,29 @@ func (gc *gitlabClient) RevokeGroupServiceAccountAccessToken(ctx context.Context return err } -func (gc *gitlabClient) CurrentTokenInfo(ctx context.Context) (et *EntryToken, err error) { +func (gc *gitlabClient) CurrentTokenInfo(ctx context.Context) (et *TokenConfig, err error) { var pat *g.PersonalAccessToken defer func() { gc.logger.Debug("Current token info", "token", et, "error", err) }() if pat, _, err = gc.client.PersonalAccessTokens.GetSinglePersonalAccessToken(g.WithContext(ctx)); err == nil { - et = &EntryToken{ - TokenID: pat.ID, - UserID: pat.UserID, - ParentID: "", - Path: "", - Name: pat.Name, - Token: pat.Token, - TokenType: TokenTypePersonal, - CreatedAt: pat.CreatedAt, - ExpiresAt: (*time.Time)(pat.ExpiresAt), - Scopes: pat.Scopes, - AccessLevel: "", + et = &TokenConfig{ + TokenWithScopes: TokenWithScopes{ + Token: Token{ + TokenID: pat.ID, + Name: pat.Name, + Token: pat.Token, + TokenType: TokenTypePersonal, + CreatedAt: pat.CreatedAt, + ExpiresAt: (*time.Time)(pat.ExpiresAt), + }, + Scopes: pat.Scopes, + }, + UserID: pat.UserID, } } return et, err } -func (gc *gitlabClient) RotateCurrentToken(ctx context.Context) (token *EntryToken, currentEntryToken *EntryToken, err error) { +func (gc *gitlabClient) RotateCurrentToken(ctx context.Context) (token *TokenConfig, currentEntryToken *TokenConfig, err error) { var expiresAt time.Time defer func() { gc.logger.Debug("Rotate current token", "token", token, "currentEntryToken", currentEntryToken, "expiresAt", expiresAt, "error", err) @@ -341,21 +369,24 @@ func (gc *gitlabClient) RotateCurrentToken(ctx context.Context) (token *EntryTok return nil, nil, err } - token = &EntryToken{ - TokenID: pat.ID, - UserID: pat.UserID, - ParentID: "", - Path: usr.Username, - Name: pat.Name, - Token: pat.Token, - TokenType: TokenTypePersonal, - CreatedAt: pat.CreatedAt, - ExpiresAt: (*time.Time)(pat.ExpiresAt), - Scopes: pat.Scopes, - AccessLevel: AccessLevelUnknown, + token = &TokenConfig{ + TokenWithScopes: TokenWithScopes{ + Token: Token{ + TokenID: pat.ID, + ParentID: "", + Path: usr.Username, + Name: pat.Name, + Token: pat.Token, + TokenType: TokenTypePersonal, + CreatedAt: pat.CreatedAt, + ExpiresAt: (*time.Time)(pat.ExpiresAt), + }, + Scopes: pat.Scopes, + }, + UserID: pat.UserID, } - gc.config.Token = token.Token + gc.config.Token = token.Token.Token gc.config.TokenId = token.TokenID gc.config.Scopes = token.Scopes if token.CreatedAt != nil { @@ -389,7 +420,7 @@ func (gc *gitlabClient) GetUserIdByUsername(ctx context.Context, username string return userId, nil } -func (gc *gitlabClient) CreatePersonalAccessToken(ctx context.Context, username string, userId int, name string, expiresAt time.Time, scopes []string) (et *EntryToken, err error) { +func (gc *gitlabClient) CreatePersonalAccessToken(ctx context.Context, username string, userId int, name string, expiresAt time.Time, scopes []string) (et *TokenPersonal, err error) { var at *g.PersonalAccessToken defer func() { gc.logger.Debug("Create personal access token", "pat", at, "et", et, "username", username, "userId", userId, "name", name, "expiresAt", expiresAt, "scopes", scopes, "error", err) @@ -399,24 +430,26 @@ func (gc *gitlabClient) CreatePersonalAccessToken(ctx context.Context, username ExpiresAt: (*g.ISOTime)(&expiresAt), Scopes: &scopes, }, g.WithContext(ctx)); err == nil { - et = &EntryToken{ - TokenID: at.ID, - UserID: userId, - ParentID: "", - Path: username, - Name: name, - Token: at.Token, - TokenType: TokenTypePersonal, - CreatedAt: at.CreatedAt, - ExpiresAt: (*time.Time)(at.ExpiresAt), - Scopes: scopes, - AccessLevel: AccessLevelUnknown, + et = &TokenPersonal{ + TokenWithScopes: TokenWithScopes{ + Token: Token{ + TokenID: at.ID, + Path: username, + Name: name, + Token: at.Token, + TokenType: TokenTypePersonal, + CreatedAt: at.CreatedAt, + ExpiresAt: (*time.Time)(at.ExpiresAt), + }, + Scopes: scopes, + }, + UserID: userId, } } return et, err } -func (gc *gitlabClient) CreateGroupAccessToken(ctx context.Context, groupId string, name string, expiresAt time.Time, scopes []string, accessLevel AccessLevel) (et *EntryToken, err error) { +func (gc *gitlabClient) CreateGroupAccessToken(ctx context.Context, groupId string, name string, expiresAt time.Time, scopes []string, accessLevel AccessLevel) (et *TokenGroup, err error) { var at *g.GroupAccessToken defer func() { gc.logger.Debug("Create group access token", "gat", at, "et", et, "groupId", groupId, "name", name, "expiresAt", expiresAt, "scopes", scopes, "accessLevel", accessLevel, "error", err) @@ -429,24 +462,27 @@ func (gc *gitlabClient) CreateGroupAccessToken(ctx context.Context, groupId stri ExpiresAt: (*g.ISOTime)(&expiresAt), AccessLevel: al, }, g.WithContext(ctx)); err == nil { - et = &EntryToken{ - TokenID: at.ID, - UserID: 0, - ParentID: groupId, - Path: groupId, - Name: name, - Token: at.Token, - TokenType: TokenTypeGroup, - CreatedAt: at.CreatedAt, - ExpiresAt: (*time.Time)(at.ExpiresAt), - Scopes: scopes, - AccessLevel: accessLevel, + et = &TokenGroup{ + TokenWithScopesAndAccessLevel: TokenWithScopesAndAccessLevel{ + Token: Token{ + TokenID: at.ID, + ParentID: groupId, + Path: groupId, + Name: name, + Token: at.Token, + TokenType: TokenTypeGroup, + CreatedAt: at.CreatedAt, + ExpiresAt: (*time.Time)(at.ExpiresAt), + }, + Scopes: scopes, + AccessLevel: accessLevel, + }, } } return et, err } -func (gc *gitlabClient) CreateProjectAccessToken(ctx context.Context, projectId string, name string, expiresAt time.Time, scopes []string, accessLevel AccessLevel) (et *EntryToken, err error) { +func (gc *gitlabClient) CreateProjectAccessToken(ctx context.Context, projectId string, name string, expiresAt time.Time, scopes []string, accessLevel AccessLevel) (et *TokenProject, err error) { var at *g.ProjectAccessToken defer func() { gc.logger.Debug("Create project access token", "gat", at, "et", et, "projectId", projectId, "name", name, "expiresAt", expiresAt, "scopes", scopes, "accessLevel", accessLevel, "error", err) @@ -459,18 +495,21 @@ func (gc *gitlabClient) CreateProjectAccessToken(ctx context.Context, projectId ExpiresAt: (*g.ISOTime)(&expiresAt), AccessLevel: al, }, g.WithContext(ctx)); err == nil { - et = &EntryToken{ - TokenID: at.ID, - UserID: 0, - ParentID: projectId, - Path: projectId, - Name: name, - Token: at.Token, - TokenType: TokenTypeProject, - CreatedAt: at.CreatedAt, - ExpiresAt: (*time.Time)(at.ExpiresAt), - Scopes: scopes, - AccessLevel: accessLevel, + et = &TokenProject{ + TokenWithScopesAndAccessLevel: TokenWithScopesAndAccessLevel{ + Token: Token{ + TokenID: at.ID, + ParentID: projectId, + Path: projectId, + Name: name, + Token: at.Token, + TokenType: TokenTypeProject, + CreatedAt: at.CreatedAt, + ExpiresAt: (*time.Time)(at.ExpiresAt), + }, + Scopes: scopes, + AccessLevel: accessLevel, + }, } } return et, err diff --git a/gitlab_client_test.go b/gitlab_client_test.go index 77d7c39..28fd459 100644 --- a/gitlab_client_test.go +++ b/gitlab_client_test.go @@ -87,17 +87,17 @@ func TestGitlabClient_InvalidToken(t *testing.T) { _, err = client.GetUserIdByUsername(ctx, "username") require.Error(t, err) - entryToken, err := client.CreateGroupAccessToken(ctx, "groupId", "name", timeExpiresAt, []string{"scope"}, gitlab.AccessLevelUnknown) + gatToken, err := client.CreateGroupAccessToken(ctx, "groupId", "name", timeExpiresAt, []string{"scope"}, gitlab.AccessLevelUnknown) require.Error(t, err) - require.Nil(t, entryToken) + require.Nil(t, gatToken) - entryToken, err = client.CreateProjectAccessToken(ctx, "projectId", "name", timeExpiresAt, []string{"scope"}, gitlab.AccessLevelUnknown) + prjAtToken, err := client.CreateProjectAccessToken(ctx, "projectId", "name", timeExpiresAt, []string{"scope"}, gitlab.AccessLevelUnknown) require.Error(t, err) - require.Nil(t, entryToken) + require.Nil(t, prjAtToken) - entryToken, err = client.CreatePersonalAccessToken(ctx, "username", 0, "name", timeExpiresAt, []string{"scope"}) + patToken, err := client.CreatePersonalAccessToken(ctx, "username", 0, "name", timeExpiresAt, []string{"scope"}) require.Error(t, err) - require.Nil(t, entryToken) + require.Nil(t, patToken) } func TestGitlabClient_RevokeToken_NotFound(t *testing.T) { @@ -248,7 +248,7 @@ func TestGitlabClient_CreateAccessToken_And_Revoke(t *testing.T) { require.NotNil(t, client) require.True(t, client.Valid(ctx)) - entryToken, err := client.CreateGroupAccessToken( + gatToken, err := client.CreateGroupAccessToken( ctx, "example", "name", @@ -257,12 +257,12 @@ func TestGitlabClient_CreateAccessToken_And_Revoke(t *testing.T) { gitlab.AccessLevelGuestPermissions, ) require.NoError(t, err) - require.NotNil(t, entryToken) - require.EqualValues(t, gitlab.TokenTypeGroup, entryToken.TokenType) - require.NotEmpty(t, entryToken.Token) - require.NoError(t, client.RevokeGroupAccessToken(ctx, entryToken.TokenID, "example")) + require.NotNil(t, gatToken) + require.EqualValues(t, gitlab.TokenTypeGroup, gatToken.TokenType) + require.NotEmpty(t, gatToken.Token) + require.NoError(t, client.RevokeGroupAccessToken(ctx, gatToken.TokenID, "example")) - entryToken, err = client.CreateProjectAccessToken( + prjatToken, err := client.CreateProjectAccessToken( ctx, "example/example", "name", @@ -271,12 +271,12 @@ func TestGitlabClient_CreateAccessToken_And_Revoke(t *testing.T) { gitlab.AccessLevelDeveloperPermissions, ) require.NoError(t, err) - require.NotNil(t, entryToken) - require.EqualValues(t, gitlab.TokenTypeProject, entryToken.TokenType) - require.NotEmpty(t, entryToken.Token) - require.NoError(t, client.RevokeProjectAccessToken(ctx, entryToken.TokenID, "example/example")) + require.NotNil(t, prjatToken) + require.EqualValues(t, gitlab.TokenTypeProject, prjatToken.TokenType) + require.NotEmpty(t, prjatToken.Token) + require.NoError(t, client.RevokeProjectAccessToken(ctx, prjatToken.TokenID, "example/example")) - entryToken, err = client.CreatePersonalAccessToken( + patToken, err := client.CreatePersonalAccessToken( ctx, "normal-user", 1, @@ -285,10 +285,10 @@ func TestGitlabClient_CreateAccessToken_And_Revoke(t *testing.T) { []string{gitlab.TokenScopeReadApi.String()}, ) require.NoError(t, err) - require.NotNil(t, entryToken) - require.EqualValues(t, gitlab.TokenTypePersonal, entryToken.TokenType) - require.NotEmpty(t, entryToken.Token) - require.NoError(t, client.RevokePersonalAccessToken(ctx, entryToken.TokenID)) + require.NotNil(t, patToken) + require.EqualValues(t, gitlab.TokenTypePersonal, patToken.TokenType) + require.NotEmpty(t, patToken.Token) + require.NoError(t, client.RevokePersonalAccessToken(ctx, patToken.TokenID)) } func TestGitlabClient_RotateCurrentToken(t *testing.T) { diff --git a/go.mod b/go.mod index cdfdf98..619a743 100644 --- a/go.mod +++ b/go.mod @@ -8,6 +8,7 @@ require ( github.com/hashicorp/go-multierror v1.1.1 github.com/hashicorp/vault/api v1.16.0 github.com/hashicorp/vault/sdk v0.15.2 + github.com/mitchellh/mapstructure v1.5.0 github.com/stretchr/testify v1.10.0 gitlab.com/gitlab-org/api/client-go v0.123.0 golang.org/x/time v0.11.0 @@ -64,7 +65,6 @@ require ( github.com/mitchellh/copystructure v1.2.0 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/mitchellh/go-testing-interface v1.14.1 // indirect - github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/mitchellh/reflectwalk v1.0.2 // indirect github.com/moby/docker-image-spec v1.3.1 // indirect github.com/oklog/run v1.1.0 // indirect diff --git a/helpers_test.go b/helpers_test.go index 144164e..b92727d 100644 --- a/helpers_test.go +++ b/helpers_test.go @@ -150,10 +150,24 @@ func newInMemoryClient(valid bool) *inMemoryClient { return &inMemoryClient{ users: make([]string, 0), valid: valid, - accessTokens: make(map[string]gitlab.EntryToken), - - mainTokenInfo: gitlab.EntryToken{CreatedAt: g.Ptr(time.Now()), ExpiresAt: g.Ptr(time.Now())}, - rotateMainToken: gitlab.EntryToken{CreatedAt: g.Ptr(time.Now()), ExpiresAt: g.Ptr(time.Now())}, + accessTokens: make(map[string]gitlab.IToken), + + mainTokenInfo: gitlab.TokenConfig{ + TokenWithScopes: gitlab.TokenWithScopes{ + Token: gitlab.Token{ + CreatedAt: g.Ptr(time.Now()), + ExpiresAt: g.Ptr(time.Now()), + }, + }, + }, + rotateMainToken: gitlab.TokenConfig{ + TokenWithScopes: gitlab.TokenWithScopes{ + Token: gitlab.Token{ + CreatedAt: g.Ptr(time.Now()), + ExpiresAt: g.Ptr(time.Now()), + }, + }, + }, } } @@ -187,10 +201,10 @@ type inMemoryClient struct { calledRotateMainToken int calledValid int - mainTokenInfo gitlab.EntryToken - rotateMainToken gitlab.EntryToken + mainTokenInfo gitlab.TokenConfig + rotateMainToken gitlab.TokenConfig - accessTokens map[string]gitlab.EntryToken + accessTokens map[string]gitlab.IToken valueGetProjectIdByPath int } @@ -202,7 +216,7 @@ func (i *inMemoryClient) GetProjectIdByPath(ctx context.Context, path string) (i return i.valueGetProjectIdByPath, nil } -func (i *inMemoryClient) CreateProjectDeployToken(ctx context.Context, path string, projectId int, name string, expiresAt *time.Time, scopes []string) (et *gitlab.EntryToken, err error) { +func (i *inMemoryClient) CreateProjectDeployToken(ctx context.Context, path string, projectId int, name string, expiresAt *time.Time, scopes []string) (et *gitlab.TokenProjectDeploy, err error) { i.muLock.Lock() defer i.muLock.Unlock() if i.createProjectDeployTokenError { @@ -211,21 +225,26 @@ func (i *inMemoryClient) CreateProjectDeployToken(ctx context.Context, path stri i.internalCounter++ var tokenId = i.internalCounter key := fmt.Sprintf("%s_%v_%v", gitlab.TokenTypeProjectDeploy.String(), projectId, tokenId) - var entryToken = gitlab.EntryToken{ - TokenID: tokenId, - ParentID: strconv.Itoa(projectId), - Path: path, - Name: name, - Token: fmt.Sprintf("glpat-%s", uuid.New().String()), - TokenType: gitlab.TokenTypeProjectDeploy, - ExpiresAt: expiresAt, - CreatedAt: g.Ptr(time.Now()), + var entryToken = &gitlab.TokenProjectDeploy{ + TokenWithScopes: gitlab.TokenWithScopes{ + Token: gitlab.Token{ + TokenID: tokenId, + ParentID: strconv.Itoa(projectId), + Path: path, + Name: name, + Token: fmt.Sprintf("glpat-%s", uuid.New().String()), + TokenType: gitlab.TokenTypeProjectDeploy, + ExpiresAt: expiresAt, + CreatedAt: g.Ptr(time.Now())}, + Scopes: scopes, + }, + Username: uuid.New().String(), } i.accessTokens[key] = entryToken - return &entryToken, nil + return entryToken, nil } -func (i *inMemoryClient) CreateGroupDeployToken(ctx context.Context, path string, groupId int, name string, expiresAt *time.Time, scopes []string) (et *gitlab.EntryToken, err error) { +func (i *inMemoryClient) CreateGroupDeployToken(ctx context.Context, path string, groupId int, name string, expiresAt *time.Time, scopes []string) (et *gitlab.TokenGroupDeploy, err error) { i.muLock.Lock() defer i.muLock.Unlock() if i.createGroupDeployTokenError { @@ -234,18 +253,24 @@ func (i *inMemoryClient) CreateGroupDeployToken(ctx context.Context, path string i.internalCounter++ var tokenId = i.internalCounter key := fmt.Sprintf("%s_%v_%v", gitlab.TokenTypeGroupDeploy.String(), groupId, tokenId) - var entryToken = gitlab.EntryToken{ - TokenID: tokenId, - ParentID: strconv.Itoa(groupId), - Path: path, - Name: name, - Token: fmt.Sprintf("glpat-%s", uuid.New().String()), - TokenType: gitlab.TokenTypeGroupDeploy, - ExpiresAt: expiresAt, - CreatedAt: g.Ptr(time.Now()), + var entryToken = &gitlab.TokenGroupDeploy{ + TokenWithScopes: gitlab.TokenWithScopes{ + Token: gitlab.Token{ + TokenID: tokenId, + ParentID: strconv.Itoa(groupId), + Path: path, + Name: name, + Token: fmt.Sprintf("glpat-%s", uuid.New().String()), + TokenType: gitlab.TokenTypeGroupDeploy, + ExpiresAt: expiresAt, + CreatedAt: g.Ptr(time.Now()), + }, + Scopes: scopes, + }, + Username: uuid.New().String(), } i.accessTokens[key] = entryToken - return &entryToken, nil + return entryToken, nil } func (i *inMemoryClient) RevokeProjectDeployToken(ctx context.Context, projectId, deployTokenId int) (err error) { @@ -281,7 +306,7 @@ func (i *inMemoryClient) Metadata(ctx context.Context) (*g.Metadata, error) { }, nil } -func (i *inMemoryClient) CreatePipelineProjectTriggerAccessToken(ctx context.Context, path, name string, projectId int, description string, expiresAt *time.Time) (et *gitlab.EntryToken, err error) { +func (i *inMemoryClient) CreatePipelineProjectTriggerAccessToken(ctx context.Context, path, name string, projectId int, description string, expiresAt *time.Time) (et *gitlab.TokenPipelineProjectTrigger, err error) { i.muLock.Lock() defer i.muLock.Unlock() if i.createPipelineProjectTriggerAccessTokenError { @@ -290,18 +315,20 @@ func (i *inMemoryClient) CreatePipelineProjectTriggerAccessToken(ctx context.Con i.internalCounter++ var tokenId = i.internalCounter key := fmt.Sprintf("%s_%v_%v", gitlab.TokenTypePipelineProjectTrigger.String(), projectId, tokenId) - var entryToken = gitlab.EntryToken{ - TokenID: tokenId, - ParentID: strconv.Itoa(projectId), - Path: strconv.Itoa(projectId), - Name: name, - Token: fmt.Sprintf("glptt-%s", uuid.New().String()), - TokenType: gitlab.TokenTypePipelineProjectTrigger, - ExpiresAt: expiresAt, - CreatedAt: g.Ptr(time.Now()), + var entryToken = &gitlab.TokenPipelineProjectTrigger{ + Token: gitlab.Token{ + TokenID: tokenId, + ParentID: strconv.Itoa(projectId), + Path: strconv.Itoa(projectId), + Name: name, + Token: fmt.Sprintf("glptt-%s", uuid.New().String()), + TokenType: gitlab.TokenTypePipelineProjectTrigger, + ExpiresAt: expiresAt, + CreatedAt: g.Ptr(time.Now()), + }, } i.accessTokens[key] = entryToken - return &entryToken, nil + return entryToken, nil } func (i *inMemoryClient) RevokePipelineProjectTriggerAccessToken(ctx context.Context, projectId int, tokenId int) error { @@ -328,7 +355,7 @@ func (i *inMemoryClient) GitlabClient(ctx context.Context) *g.Client { return nil } -func (i *inMemoryClient) CreateGroupServiceAccountAccessToken(ctx context.Context, path string, groupId string, userId int, name string, expiresAt time.Time, scopes []string) (*gitlab.EntryToken, error) { +func (i *inMemoryClient) CreateGroupServiceAccountAccessToken(ctx context.Context, path string, groupId string, userId int, name string, expiresAt time.Time, scopes []string) (*gitlab.TokenGroupServiceAccount, error) { i.muLock.Lock() defer i.muLock.Unlock() if i.createGroupServiceAccountAccessTokenError { @@ -337,14 +364,35 @@ func (i *inMemoryClient) CreateGroupServiceAccountAccessToken(ctx context.Contex return nil, nil } -func (i *inMemoryClient) CreateUserServiceAccountAccessToken(ctx context.Context, username string, userId int, name string, expiresAt time.Time, scopes []string) (*gitlab.EntryToken, error) { +func (i *inMemoryClient) CreateUserServiceAccountAccessToken(ctx context.Context, username string, userId int, name string, expiresAt time.Time, scopes []string) (*gitlab.TokenUserServiceAccount, error) { i.muLock.Lock() if i.createUserServiceAccountAccessTokenError { i.muLock.Unlock() return nil, fmt.Errorf("CreateUserServiceAccountAccessToken") } i.muLock.Unlock() - return i.CreatePersonalAccessToken(ctx, username, userId, name, expiresAt, scopes) + var t *gitlab.TokenUserServiceAccount + var err error + var cpat *gitlab.TokenPersonal + if cpat, err = i.CreatePersonalAccessToken(ctx, username, userId, name, expiresAt, scopes); err != nil && cpat != nil { + t = &gitlab.TokenUserServiceAccount{ + TokenWithScopes: gitlab.TokenWithScopes{ + Token: gitlab.Token{ + CreatedAt: cpat.CreatedAt, + ExpiresAt: cpat.ExpiresAt, + TokenType: gitlab.TokenTypeUserServiceAccount, + Token: cpat.Token.Token, + TokenID: cpat.TokenID, + ParentID: cpat.ParentID, + Name: cpat.Name, + Path: cpat.Path, + }, + Scopes: cpat.Scopes, + }, + } + + } + return t, err } func (i *inMemoryClient) RevokeUserServiceAccountAccessToken(ctx context.Context, token string) error { @@ -367,14 +415,14 @@ func (i *inMemoryClient) RevokeGroupServiceAccountAccessToken(ctx context.Contex return nil } -func (i *inMemoryClient) CurrentTokenInfo(ctx context.Context) (*gitlab.EntryToken, error) { +func (i *inMemoryClient) CurrentTokenInfo(ctx context.Context) (*gitlab.TokenConfig, error) { i.muLock.Lock() defer i.muLock.Unlock() i.calledMainToken++ return &i.mainTokenInfo, nil } -func (i *inMemoryClient) RotateCurrentToken(ctx context.Context) (*gitlab.EntryToken, *gitlab.EntryToken, error) { +func (i *inMemoryClient) RotateCurrentToken(ctx context.Context) (*gitlab.TokenConfig, *gitlab.TokenConfig, error) { i.muLock.Lock() defer i.muLock.Unlock() i.calledRotateMainToken++ @@ -388,7 +436,7 @@ func (i *inMemoryClient) Valid(ctx context.Context) bool { return i.valid } -func (i *inMemoryClient) CreatePersonalAccessToken(ctx context.Context, username string, userId int, name string, expiresAt time.Time, scopes []string) (*gitlab.EntryToken, error) { +func (i *inMemoryClient) CreatePersonalAccessToken(ctx context.Context, username string, userId int, name string, expiresAt time.Time, scopes []string) (*gitlab.TokenPersonal, error) { i.muLock.Lock() defer i.muLock.Unlock() if i.personalAccessTokenCreateError { @@ -396,23 +444,27 @@ func (i *inMemoryClient) CreatePersonalAccessToken(ctx context.Context, username } i.internalCounter++ var tokenId = i.internalCounter - var entryToken = gitlab.EntryToken{ - TokenID: tokenId, - UserID: userId, - ParentID: "", - Path: username, - Name: name, - Token: "", - TokenType: gitlab.TokenTypePersonal, - CreatedAt: g.Ptr(time.Now()), - ExpiresAt: &expiresAt, - Scopes: scopes, + var entryToken = &gitlab.TokenPersonal{ + TokenWithScopes: gitlab.TokenWithScopes{ + Token: gitlab.Token{ + TokenID: tokenId, + ParentID: "", + Path: username, + Name: name, + Token: fmt.Sprintf("glpat-%s", uuid.New().String()), + TokenType: gitlab.TokenTypePersonal, + CreatedAt: g.Ptr(time.Now()), + ExpiresAt: &expiresAt, + }, + Scopes: scopes, + }, + UserID: userId, } i.accessTokens[fmt.Sprintf("%s_%v", gitlab.TokenTypePersonal.String(), tokenId)] = entryToken - return &entryToken, nil + return entryToken, nil } -func (i *inMemoryClient) CreateGroupAccessToken(ctx context.Context, groupId string, name string, expiresAt time.Time, scopes []string, accessLevel gitlab.AccessLevel) (*gitlab.EntryToken, error) { +func (i *inMemoryClient) CreateGroupAccessToken(ctx context.Context, groupId string, name string, expiresAt time.Time, scopes []string, accessLevel gitlab.AccessLevel) (*gitlab.TokenGroup, error) { i.muLock.Lock() defer i.muLock.Unlock() if i.groupAccessTokenCreateError { @@ -420,24 +472,27 @@ func (i *inMemoryClient) CreateGroupAccessToken(ctx context.Context, groupId str } i.internalCounter++ var tokenId = i.internalCounter - var entryToken = gitlab.EntryToken{ - TokenID: tokenId, - UserID: 0, - ParentID: groupId, - Path: groupId, - Name: name, - Token: "", - TokenType: gitlab.TokenTypeGroup, - CreatedAt: g.Ptr(time.Now()), - ExpiresAt: &expiresAt, - Scopes: scopes, - AccessLevel: accessLevel, + var entryToken = &gitlab.TokenGroup{ + TokenWithScopesAndAccessLevel: gitlab.TokenWithScopesAndAccessLevel{ + Token: gitlab.Token{ + TokenID: tokenId, + ParentID: groupId, + Path: groupId, + Name: name, + Token: fmt.Sprintf("glgat-%s", uuid.New().String()), + TokenType: gitlab.TokenTypeGroup, + CreatedAt: g.Ptr(time.Now()), + ExpiresAt: &expiresAt, + }, + Scopes: scopes, + AccessLevel: accessLevel, + }, } i.accessTokens[fmt.Sprintf("%s_%v", gitlab.TokenTypeGroup.String(), tokenId)] = entryToken - return &entryToken, nil + return entryToken, nil } -func (i *inMemoryClient) CreateProjectAccessToken(ctx context.Context, projectId string, name string, expiresAt time.Time, scopes []string, accessLevel gitlab.AccessLevel) (*gitlab.EntryToken, error) { +func (i *inMemoryClient) CreateProjectAccessToken(ctx context.Context, projectId string, name string, expiresAt time.Time, scopes []string, accessLevel gitlab.AccessLevel) (*gitlab.TokenProject, error) { i.muLock.Lock() defer i.muLock.Unlock() if i.projectAccessTokenCreateError { @@ -445,21 +500,24 @@ func (i *inMemoryClient) CreateProjectAccessToken(ctx context.Context, projectId } i.internalCounter++ var tokenId = i.internalCounter - var entryToken = gitlab.EntryToken{ - TokenID: tokenId, - UserID: 0, - ParentID: projectId, - Path: projectId, - Name: name, - Token: "", - TokenType: gitlab.TokenTypeProject, - CreatedAt: g.Ptr(time.Now()), - ExpiresAt: &expiresAt, - Scopes: scopes, - AccessLevel: accessLevel, + var entryToken = &gitlab.TokenProject{ + TokenWithScopesAndAccessLevel: gitlab.TokenWithScopesAndAccessLevel{ + Token: gitlab.Token{ + Token: fmt.Sprintf("glpat-%s", uuid.New().String()), + TokenType: gitlab.TokenTypeProject, + CreatedAt: g.Ptr(time.Now()), + ExpiresAt: &expiresAt, + TokenID: tokenId, + ParentID: projectId, + Name: name, + Path: projectId, + }, + Scopes: scopes, + AccessLevel: accessLevel, + }, } i.accessTokens[fmt.Sprintf("%s_%v", gitlab.TokenTypeProject.String(), tokenId)] = entryToken - return &entryToken, nil + return entryToken, nil } func (i *inMemoryClient) RevokePersonalAccessToken(ctx context.Context, tokenId int) error { diff --git a/path_config.go b/path_config.go index 83b65e2..9ada889 100644 --- a/path_config.go +++ b/path_config.go @@ -152,13 +152,15 @@ func (b *Backend) pathConfigPatch(ctx context.Context, req *logical.Request, dat return lResp, err } -func (b *Backend) updateConfigClientInfo(ctx context.Context, config *EntryConfig) (et *EntryToken, err error) { +func (b *Backend) updateConfigClientInfo(ctx context.Context, config *EntryConfig) (et *TokenConfig, err error) { var httpClient *http.Client var client Client httpClient, _ = HttpClientFromContext(ctx) if client, _ = GitlabClientFromContext(ctx); client == nil { if client, err = NewGitlabClient(config, httpClient, b.Logger()); err == nil { b.SetClient(client, config.Name) + } else { + return nil, err } } diff --git a/path_config_rotate.go b/path_config_rotate.go index c39a735..a8fc213 100644 --- a/path_config_rotate.go +++ b/path_config_rotate.go @@ -81,14 +81,14 @@ func (b *Backend) pathConfigTokenRotate(ctx context.Context, request *logical.Re return nil, err } - var entryToken *EntryToken + var entryToken *TokenConfig entryToken, _, err = client.RotateCurrentToken(ctx) if err != nil { b.Logger().Error("Failed to rotate main token", "err", err) return nil, err } - config.Token = entryToken.Token + config.Token = entryToken.Token.Token config.TokenId = entryToken.TokenID config.Scopes = entryToken.Scopes if entryToken.CreatedAt != nil { diff --git a/path_config_token_autorotate_test.go b/path_config_token_autorotate_test.go index 290f5a7..033c44f 100644 --- a/path_config_token_autorotate_test.go +++ b/path_config_token_autorotate_test.go @@ -183,7 +183,7 @@ func TestPathConfig_AutoRotateToken(t *testing.T) { }) require.NoError(t, err) - client.rotateMainToken.Token = "new token" + client.rotateMainToken.Token.Token = "new token" b.SetClient(client, gitlab.DefaultConfigName) resp, err := b.HandleRequest(ctx, &logical.Request{ diff --git a/path_token_role.go b/path_token_role.go index 60560ca..68b4384 100644 --- a/path_token_role.go +++ b/path_token_role.go @@ -5,7 +5,6 @@ import ( "context" "fmt" "net/http" - "strconv" "strings" "time" @@ -57,7 +56,7 @@ func (b *Backend) pathTokenRoleCreate(ctx context.Context, req *logical.Request, defer b.Logger().Debug("Created token for role", "role_name", roleName, "token_type", role.TokenType.String()) var name string - var token *EntryToken + var token IToken var expiresAt time.Time var startTime = TimeFromContext(ctx).UTC() @@ -132,39 +131,30 @@ func (b *Backend) pathTokenRoleCreate(ctx context.Context, req *logical.Request, return nil, cmp.Or(err, fmt.Errorf("%w: token is nil", ErrNilValue)) } - token.ConfigName = cmp.Or(role.ConfigName, DefaultConfigName) - token.RoleName = role.RoleName - token.GitlabRevokesToken = role.GitlabRevokesTokens + token.SetConfigName(cmp.Or(role.ConfigName, DefaultConfigName)) + token.SetRoleName(role.RoleName) + token.SetGitlabRevokesToken(role.GitlabRevokesTokens) if vaultRevokesTokens { // since vault is controlling the expiry we need to override here // and make the expiry time accurate expiresAt = startTime.Add(role.TTL) - token.ExpiresAt = &expiresAt + token.SetExpiresAt(&expiresAt) } - var secretData, secretInternal = token.SecretResponse() - resp = b.Secret(SecretAccessTokenType).Response(secretData, secretInternal) + resp = b.Secret(SecretAccessTokenType).Response(token.Data(), token.Internal()) resp.Secret.MaxTTL = role.TTL resp.Secret.TTL = role.TTL resp.Secret.IssueTime = startTime if gitlabRevokesTokens { - resp.Secret.TTL = token.ExpiresAt.Sub(*token.CreatedAt) + resp.Secret.TTL = token.TTL() } - event(ctx, b.Backend, "token-write", map[string]string{ - "path": fmt.Sprintf("%s/%s", PathRoleStorage, roleName), - "name": name, - "parent_id": role.Path, - "ttl": resp.Secret.TTL.String(), - "role_name": roleName, - "token_id": strconv.Itoa(token.TokenID), - "token_type": role.TokenType.String(), - "scopes": strings.Join(role.Scopes, ","), - "access_level": role.AccessLevel.String(), - "config_name": token.ConfigName, - }) + event( + ctx, b.Backend, "token-write", + token.Event(map[string]string{"path": fmt.Sprintf("%s/%s", PathRoleStorage, roleName)}), + ) return resp, nil } diff --git a/secret_access_tokens.go b/secret_access_tokens.go index 0824493..2b50a94 100644 --- a/secret_access_tokens.go +++ b/secret_access_tokens.go @@ -74,7 +74,7 @@ func (b *Backend) secretAccessTokenRevoke(ctx context.Context, req *logical.Requ return nil, fmt.Errorf("token_id: %w", err) } - var gitlabRevokesToken, _ = strconv.ParseBool(req.Secret.InternalData["gitlab_revokes_token"].(string)) + var gitlabRevokesToken = req.Secret.InternalData["gitlab_revokes_token"].(bool) var vaultRevokesToken = !gitlabRevokesToken var parentId = req.Secret.InternalData["parent_id"].(string) var tokenType TokenType diff --git a/token.go b/token.go new file mode 100644 index 0000000..4752b08 --- /dev/null +++ b/token.go @@ -0,0 +1,107 @@ +package gitlab + +import ( + "crypto/sha1" + "fmt" + "maps" + "strconv" + "time" +) + +type IToken interface { + Internal() map[string]any + Data() map[string]any + Event(map[string]string) map[string]string + Type() TokenType + SetConfigName(string) + SetRoleName(string) + SetGitlabRevokesToken(bool) + SetExpiresAt(*time.Time) + GetExpiresAt() time.Time + GetCreatedAt() time.Time + TTL() time.Duration +} + +type Token struct { + RoleName string `json:"role_name"` + ConfigName string `json:"config_name"` + GitlabRevokesToken bool `json:"gitlab_revokes_token"` + CreatedAt *time.Time `json:"created_at"` + ExpiresAt *time.Time `json:"expires_at"` + TokenType TokenType `json:"type"` + Token string `json:"token"` + TokenID int `json:"token_id"` + ParentID string `json:"parent_id"` + Name string `json:"name"` + Path string `json:"path"` +} + +func (t *Token) TTL() time.Duration { + return t.GetExpiresAt().Sub(t.GetCreatedAt()) +} + +func (t *Token) GetExpiresAt() (tm time.Time) { + if t.ExpiresAt != nil { + tm = *t.ExpiresAt + } + return tm +} +func (t *Token) GetCreatedAt() (tm time.Time) { + if t.CreatedAt != nil { + tm = *t.CreatedAt + } + return tm +} +func (t *Token) SetExpiresAt(expiresAt *time.Time) { t.ExpiresAt = expiresAt } +func (t *Token) SetConfigName(name string) { t.ConfigName = name } +func (t *Token) SetRoleName(name string) { t.RoleName = name } +func (t *Token) SetGitlabRevokesToken(b bool) { t.GitlabRevokesToken = b } +func (t *Token) Type() TokenType { return t.TokenType } + +func (t *Token) Internal() map[string]any { + return map[string]any{ + "name": t.Name, + "path": t.Path, + "token": t.Token, + "token_id": t.TokenID, + "parent_id": t.ParentID, + "role_name": t.RoleName, + "config_name": t.ConfigName, + "gitlab_revokes_token": t.GitlabRevokesToken, + "created_at": t.CreatedAt, + "expires_at": t.ExpiresAt, + "token_type": t.Type().String(), + } +} + +func (t *Token) Data() map[string]any { + return map[string]any{ + "path": t.Path, + "name": t.Name, + "token": t.Token, + "token_sha1_hash": fmt.Sprintf("%x", sha1.Sum([]byte(t.Token))), + "token_id": t.TokenID, + "token_type": t.Type().String(), + "parent_id": t.ParentID, + "role_name": t.RoleName, + "config_name": t.ConfigName, + "created_at": t.CreatedAt, + "expires_at": t.ExpiresAt, + } +} + +func (t *Token) Event(m map[string]string) (d map[string]string) { + d = map[string]string{ + "config_name": t.ConfigName, + "role_name": t.RoleName, + "token_id": strconv.Itoa(t.TokenID), + "parent_id": t.ParentID, + "token_type": t.Type().String(), + "ttl": t.TTL().String(), + "name": t.Name, + } + maps.Copy(d, m) + return d +} + +var _ IToken = (*Token)(nil) diff --git a/token_config.go b/token_config.go new file mode 100644 index 0000000..16f791a --- /dev/null +++ b/token_config.go @@ -0,0 +1,7 @@ +package gitlab + +type TokenConfig struct { + TokenWithScopes `json:",inline"` + + UserID int `json:"user_id"` +} diff --git a/token_group.go b/token_group.go new file mode 100644 index 0000000..86c10af --- /dev/null +++ b/token_group.go @@ -0,0 +1,5 @@ +package gitlab + +type TokenGroup struct { + TokenWithScopesAndAccessLevel `json:",inline"` +} diff --git a/token_group_deploy.go b/token_group_deploy.go new file mode 100644 index 0000000..efcd629 --- /dev/null +++ b/token_group_deploy.go @@ -0,0 +1,29 @@ +package gitlab + +import ( + "maps" +) + +type TokenGroupDeploy struct { + TokenWithScopes `json:",inline"` + + Username string `json:"username"` +} + +func (t *TokenGroupDeploy) Internal() (d map[string]any) { + d = map[string]any{"username": t.Username} + maps.Copy(d, t.TokenWithScopes.Internal()) + return d +} + +func (t *TokenGroupDeploy) Data() (d map[string]any) { + d = map[string]any{"username": t.Username} + maps.Copy(d, t.TokenWithScopes.Internal()) + return d +} + +func (t *TokenGroupDeploy) Event(m map[string]string) (d map[string]string) { + d = map[string]string{"username": t.Username} + maps.Copy(d, t.Token.Event(m)) + return d +} diff --git a/token_group_service_account.go b/token_group_service_account.go new file mode 100644 index 0000000..020fee0 --- /dev/null +++ b/token_group_service_account.go @@ -0,0 +1,30 @@ +package gitlab + +import ( + "maps" + "strconv" +) + +type TokenGroupServiceAccount struct { + TokenWithScopes `json:",inline"` + + UserID int `json:"user_id"` +} + +func (t *TokenGroupServiceAccount) Internal() (d map[string]any) { + d = map[string]any{"user_id": t.UserID} + maps.Copy(d, t.TokenWithScopes.Internal()) + return d +} + +func (t *TokenGroupServiceAccount) Data() (d map[string]any) { + d = map[string]any{"user_id": t.UserID} + maps.Copy(d, t.TokenWithScopes.Internal()) + return d +} + +func (t *TokenGroupServiceAccount) Event(m map[string]string) (d map[string]string) { + d = map[string]string{"user_id": strconv.Itoa(t.UserID)} + maps.Copy(d, t.Token.Event(m)) + return d +} diff --git a/token_personal.go b/token_personal.go new file mode 100644 index 0000000..e8f854a --- /dev/null +++ b/token_personal.go @@ -0,0 +1,30 @@ +package gitlab + +import ( + "maps" + "strconv" +) + +type TokenPersonal struct { + TokenWithScopes `json:",inline"` + + UserID int `json:"user_id"` +} + +func (t *TokenPersonal) Internal() (d map[string]any) { + d = map[string]any{"user_id": t.UserID} + maps.Copy(d, t.TokenWithScopes.Internal()) + return d +} + +func (t *TokenPersonal) Data() (d map[string]any) { + d = map[string]any{"user_id": t.UserID} + maps.Copy(d, t.TokenWithScopes.Internal()) + return d +} + +func (t *TokenPersonal) Event(m map[string]string) (d map[string]string) { + d = map[string]string{"user_id": strconv.Itoa(t.UserID)} + maps.Copy(d, t.Token.Event(m)) + return d +} diff --git a/token_pipeline_project_trigger.go b/token_pipeline_project_trigger.go new file mode 100644 index 0000000..81131c8 --- /dev/null +++ b/token_pipeline_project_trigger.go @@ -0,0 +1,5 @@ +package gitlab + +type TokenPipelineProjectTrigger struct { + Token `json:",inline"` +} diff --git a/token_project.go b/token_project.go new file mode 100644 index 0000000..99e28a4 --- /dev/null +++ b/token_project.go @@ -0,0 +1,5 @@ +package gitlab + +type TokenProject struct { + TokenWithScopesAndAccessLevel `json:",inline"` +} diff --git a/token_project_deploy.go b/token_project_deploy.go new file mode 100644 index 0000000..dec53c3 --- /dev/null +++ b/token_project_deploy.go @@ -0,0 +1,27 @@ +package gitlab + +import "maps" + +type TokenProjectDeploy struct { + TokenWithScopes `json:",inline"` + + Username string `json:"username"` +} + +func (t *TokenProjectDeploy) Internal() (d map[string]any) { + d = map[string]any{"username": t.Username} + maps.Copy(d, t.TokenWithScopes.Internal()) + return d +} + +func (t *TokenProjectDeploy) Data() (d map[string]any) { + d = map[string]any{"username": t.Username} + maps.Copy(d, t.TokenWithScopes.Internal()) + return d +} + +func (t *TokenProjectDeploy) Event(m map[string]string) (d map[string]string) { + d = map[string]string{"username": t.Username} + maps.Copy(d, t.Token.Event(m)) + return d +} diff --git a/token_user_service_account.go b/token_user_service_account.go new file mode 100644 index 0000000..f3db5f0 --- /dev/null +++ b/token_user_service_account.go @@ -0,0 +1,5 @@ +package gitlab + +type TokenUserServiceAccount struct { + TokenWithScopes `json:",inline"` +} diff --git a/token_with_scopes.go b/token_with_scopes.go new file mode 100644 index 0000000..d3a7ced --- /dev/null +++ b/token_with_scopes.go @@ -0,0 +1,32 @@ +package gitlab + +import ( + "maps" + "strings" +) + +type TokenWithScopes struct { + Token `json:",inline"` + + Scopes []string `json:"scopes"` +} + +func (t *TokenWithScopes) Internal() (d map[string]any) { + d = map[string]any{"scopes": t.Scopes} + maps.Copy(d, t.Token.Internal()) + return d +} + +func (t *TokenWithScopes) Data() (d map[string]any) { + d = map[string]any{"scopes": t.Scopes} + maps.Copy(d, t.Token.Data()) + return d +} + +func (t *TokenWithScopes) Event(m map[string]string) (d map[string]string) { + d = map[string]string{"scopes": strings.Join(t.Scopes, ",")} + maps.Copy(d, t.Token.Event(m)) + return d +} + +var _ IToken = (*TokenWithScopes)(nil) diff --git a/token_with_scopes_and_access_level.go b/token_with_scopes_and_access_level.go new file mode 100644 index 0000000..6aacc72 --- /dev/null +++ b/token_with_scopes_and_access_level.go @@ -0,0 +1,42 @@ +package gitlab + +import ( + "maps" + "strings" +) + +type TokenWithScopesAndAccessLevel struct { + Token `json:",inline"` + + Scopes []string `json:"scopes"` + AccessLevel AccessLevel `json:"access_level"` +} + +func (t *TokenWithScopesAndAccessLevel) Internal() (d map[string]any) { + d = map[string]any{ + "scopes": t.Scopes, + "access_level": t.AccessLevel.String(), + } + maps.Copy(d, t.Token.Internal()) + return d +} + +func (t *TokenWithScopesAndAccessLevel) Data() (d map[string]any) { + d = map[string]any{ + "scopes": t.Scopes, + "access_level": t.AccessLevel.String(), + } + maps.Copy(d, t.Token.Data()) + return d +} + +func (t *TokenWithScopesAndAccessLevel) Event(m map[string]string) (d map[string]string) { + d = map[string]string{ + "scopes": strings.Join(t.Scopes, ","), + "access_level": t.AccessLevel.String(), + } + maps.Copy(d, t.Token.Event(m)) + return d +} + +var _ IToken = (*TokenWithScopesAndAccessLevel)(nil)