Merge branch 'main' into akp/CODE-617

This commit is contained in:
Akhilesh Pandey 2023-08-01 17:40:50 +05:30
commit 8f2c1d93ef
193 changed files with 5615 additions and 1786 deletions

View File

@ -10,6 +10,7 @@ import (
"github.com/harness/gitness/cli/provide"
"github.com/harness/gitness/cli/textui"
"github.com/harness/gitness/internal/api/controller/user"
"gopkg.in/alecthomas/kingpin.v2"
)
@ -21,19 +22,25 @@ type loginCommand struct {
func (c *loginCommand) run(*kingpin.ParseContext) error {
ss := provide.NewSession()
username, password := textui.Credentials()
loginIdentifier, password := textui.Credentials()
ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
defer cancel()
ts, err := provide.OpenClient(c.server).Login(ctx, username, password)
in := &user.LoginInput{
LoginIdentifier: loginIdentifier,
Password: password,
}
ts, err := provide.OpenClient(c.server).Login(ctx, in)
if err != nil {
return err
}
return ss.
SetURI(c.server).
SetExpiresAt(ts.Token.ExpiresAt).
// login token always has an expiry date
SetExpiresAt(*ts.Token.ExpiresAt).
SetAccessToken(ts.AccessToken).
Store()
}

View File

@ -11,6 +11,7 @@ import (
"github.com/harness/gitness/cli/provide"
"github.com/harness/gitness/cli/session"
"github.com/harness/gitness/cli/textui"
"github.com/harness/gitness/internal/api/controller/user"
"gopkg.in/alecthomas/kingpin.v2"
)
@ -30,18 +31,26 @@ type registerCommand struct {
func (c *registerCommand) run(*kingpin.ParseContext) error {
ss := provide.NewSession()
username, name, email, password := textui.Registration()
uid, displayName, email, password := textui.Registration()
ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
defer cancel()
ts, err := provide.OpenClient(c.server).Register(ctx, username, name, email, password)
input := &user.RegisterInput{
UID: uid,
Email: email,
DisplayName: displayName,
Password: password,
}
ts, err := provide.OpenClient(c.server).Register(ctx, input)
if err != nil {
return err
}
return ss.
SetURI(c.server).
SetExpiresAt(ts.Token.ExpiresAt).
// register token always has an expiry date
SetExpiresAt(*ts.Token.ExpiresAt).
SetAccessToken(ts.AccessToken).
Store()
}

View File

@ -16,6 +16,7 @@ import (
"github.com/harness/gitness/types/enum"
"github.com/drone/funcmap"
"github.com/gotidy/ptr"
"gopkg.in/alecthomas/kingpin.v2"
)
@ -38,9 +39,14 @@ func (c *createPATCommand) run(*kingpin.ParseContext) error {
ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
defer cancel()
var lifeTime *time.Duration
if c.lifetimeInS > 0 {
lifeTime = ptr.Duration(time.Duration(int64(time.Second) * c.lifetimeInS))
}
in := user.CreateTokenInput{
UID: c.uid,
Lifetime: time.Duration(int64(time.Second) * c.lifetimeInS),
Lifetime: lifeTime,
Grants: enum.AccessGrantAll,
}
@ -71,7 +77,7 @@ func registerCreatePAT(app *kingpin.CmdClause) {
Required().StringVar(&c.uid)
cmd.Arg("lifetime", "the lifetime of the token in seconds").
Required().Int64Var(&c.lifetimeInS)
Int64Var(&c.lifetimeInS)
cmd.Flag("json", "json encode the output").
BoolVar(&c.json)

View File

@ -24,12 +24,6 @@ import (
"gopkg.in/alecthomas/kingpin.v2"
)
const (
// GraceFullShutdownTime defines the max time we wait when shutting down a server.
// 5min should be enough for most git clones to complete.
GraceFullShutdownTime = 300 * time.Second
)
type command struct {
envfile string
enableGitRPC bool
@ -109,7 +103,7 @@ func (c *command) run(*kingpin.ParseContext) error {
log.Info().Msg("shutting down gracefully (press Ctrl+C again to force)")
// shutdown servers gracefully
shutdownCtx, cancel := context.WithTimeout(context.Background(), GraceFullShutdownTime)
shutdownCtx, cancel := context.WithTimeout(context.Background(), config.GracefulShutdownTime)
defer cancel()
if sErr := shutdownHTTP(shutdownCtx); sErr != nil {

View File

@ -14,31 +14,41 @@ import (
"golang.org/x/term"
)
// Registration returns the username, name, email and password from stdin.
// Registration returns the userID, displayName, email and password from stdin.
func Registration() (string, string, string, string) {
return Username(), Name(), Email(), Password()
return UserID(), DisplayName(), Email(), Password()
}
// Credentials returns the username and password from stdin.
// Credentials returns the login identifier and password from stdin.
func Credentials() (string, string) {
return Username(), Password()
return LoginIdentifier(), Password()
}
// Username returns the username from stdin.
func Username() string {
// UserID returns the user ID from stdin.
func UserID() string {
reader := bufio.NewReader(os.Stdin)
fmt.Print("Enter Username: ")
username, _ := reader.ReadString('\n')
fmt.Print("Enter User ID: ")
uid, _ := reader.ReadString('\n')
return strings.TrimSpace(username)
return strings.TrimSpace(uid)
}
// Name returns the name from stdin.
func Name() string {
// LoginIdentifier returns the login identifier from stdin.
func LoginIdentifier() string {
reader := bufio.NewReader(os.Stdin)
fmt.Print("Enter Name: ")
fmt.Print("Enter User ID or Email: ")
id, _ := reader.ReadString('\n')
return strings.TrimSpace(id)
}
// DisplayName returns the display name from stdin.
func DisplayName() string {
reader := bufio.NewReader(os.Stdin)
fmt.Print("Enter Display Name: ")
name, _ := reader.ReadString('\n')
return strings.TrimSpace(name)

View File

@ -59,27 +59,18 @@ func (c *HTTPClient) SetDebug(debug bool) {
}
// Login authenticates the user and returns a JWT token.
func (c *HTTPClient) Login(ctx context.Context, username, password string) (*types.TokenResponse, error) {
form := &url.Values{}
form.Add("username", username)
form.Add("password", password)
func (c *HTTPClient) Login(ctx context.Context, input *user.LoginInput) (*types.TokenResponse, error) {
out := new(types.TokenResponse)
uri := fmt.Sprintf("%s/api/v1/login", c.base)
err := c.post(ctx, uri, true, form, out)
err := c.post(ctx, uri, true, input, out)
return out, err
}
// Register registers a new user and returns a JWT token.
func (c *HTTPClient) Register(ctx context.Context,
username, displayName, email, password string) (*types.TokenResponse, error) {
form := &url.Values{}
form.Add("username", username)
form.Add("displayname", displayName)
form.Add("email", email)
form.Add("password", password)
func (c *HTTPClient) Register(ctx context.Context, input *user.RegisterInput) (*types.TokenResponse, error) {
out := new(types.TokenResponse)
uri := fmt.Sprintf("%s/api/v1/register", c.base)
err := c.post(ctx, uri, true, form, out)
err := c.post(ctx, uri, true, input, out)
return out, err
}
@ -201,12 +192,7 @@ func (c *HTTPClient) stream(ctx context.Context, rawurl, method string, noToken
var buf io.ReadWriter
if in != nil {
buf = &bytes.Buffer{}
// if posting form data, encode the form values.
if form, ok := in.(*url.Values); ok {
if _, err = io.WriteString(buf, form.Encode()); err != nil {
log.Err(err).Msg("in stream method")
}
} else if err = json.NewEncoder(buf).Encode(in); err != nil {
if err = json.NewEncoder(buf).Encode(in); err != nil {
return nil, err
}
}

View File

@ -14,10 +14,10 @@ import (
// Client to access the remote APIs.
type Client interface {
// Login authenticates the user and returns a JWT token.
Login(ctx context.Context, username, password string) (*types.TokenResponse, error)
Login(ctx context.Context, input *user.LoginInput) (*types.TokenResponse, error)
// Register registers a new user and returns a JWT token.
Register(ctx context.Context, username, name, email, password string) (*types.TokenResponse, error)
Register(ctx context.Context, input *user.RegisterInput) (*types.TokenResponse, error)
// Self returns the currently authenticated user.
Self(ctx context.Context) (*types.User, error)

View File

@ -49,16 +49,24 @@ import (
func initSystem(ctx context.Context, config *types.Config) (*server.System, error) {
principalUID := check.ProvidePrincipalUIDCheck()
authorizer := authz.ProvideAuthorizer()
databaseConfig := server.ProvideDatabaseConfig(config)
db, err := database.ProvideDatabase(ctx, databaseConfig)
if err != nil {
return nil, err
}
pathTransformation := store.ProvidePathTransformation()
pathStore := database.ProvidePathStore(db, pathTransformation)
pathCache := cache.ProvidePathCache(pathStore, pathTransformation)
spaceStore := database.ProvideSpaceStore(db, pathCache)
principalInfoView := database.ProvidePrincipalInfoView(db)
principalInfoCache := cache.ProvidePrincipalInfoCache(principalInfoView)
membershipStore := database.ProvideMembershipStore(db, principalInfoCache)
permissionCache := authz.ProvidePermissionCache(spaceStore, membershipStore)
authorizer := authz.ProvideAuthorizer(permissionCache)
principalUIDTransformation := store.ProvidePrincipalUIDTransformation()
principalStore := database.ProvidePrincipalStore(db, principalUIDTransformation)
tokenStore := database.ProvideTokenStore(db)
controller := user.NewController(principalUID, authorizer, principalStore, tokenStore, config)
controller := user.NewController(principalUID, authorizer, principalStore, tokenStore, membershipStore)
serviceController := service.NewController(principalUID, authorizer, principalStore)
bootstrapBootstrap := bootstrap.ProvideBootstrap(config, controller, serviceController)
authenticator := authn.ProvideAuthenticator(principalStore, tokenStore)
@ -67,11 +75,7 @@ func initSystem(ctx context.Context, config *types.Config) (*server.System, erro
return nil, err
}
pathUID := check.ProvidePathUIDCheck()
pathTransformation := store.ProvidePathTransformation()
pathStore := database.ProvidePathStore(db, pathTransformation)
pathCache := cache.ProvidePathCache(pathStore, pathTransformation)
repoStore := database.ProvideRepoStore(db, pathCache)
spaceStore := database.ProvideSpaceStore(db, pathCache)
gitrpcConfig, err := server.ProvideGitRPCClientConfig()
if err != nil {
return nil, err
@ -81,9 +85,7 @@ func initSystem(ctx context.Context, config *types.Config) (*server.System, erro
return nil, err
}
repoController := repo.ProvideController(config, db, provider, pathUID, authorizer, pathStore, repoStore, spaceStore, principalStore, gitrpcInterface)
spaceController := space.ProvideController(db, provider, pathUID, authorizer, pathStore, spaceStore, repoStore, principalStore, repoController)
principalInfoView := database.ProvidePrincipalInfoView(db)
principalInfoCache := cache.ProvidePrincipalInfoCache(principalInfoView)
spaceController := space.ProvideController(db, provider, pathUID, authorizer, pathStore, spaceStore, repoStore, principalStore, repoController, membershipStore)
pullReqStore := database.ProvidePullReqStore(db, principalInfoCache)
pullReqActivityStore := database.ProvidePullReqActivityStore(db, principalInfoCache)
codeCommentView := database.ProvideCodeCommentView(db)
@ -135,7 +137,8 @@ func initSystem(ctx context.Context, config *types.Config) (*server.System, erro
githookController := githook.ProvideController(db, authorizer, principalStore, repoStore, eventsReporter)
serviceaccountController := serviceaccount.NewController(principalUID, authorizer, principalStore, spaceStore, repoStore, tokenStore)
principalController := principal.ProvideController(principalStore)
checkController := check2.ProvideController(db, authorizer, repoStore, gitrpcInterface)
checkStore := database.ProvideCheckStore(db, principalInfoCache)
checkController := check2.ProvideController(db, authorizer, repoStore, checkStore, gitrpcInterface)
systemController := system.NewController(principalStore, config)
apiHandler := router.ProvideAPIHandler(config, authenticator, repoController, spaceController, pullreqController, webhookController, githookController, serviceaccountController, controller, principalController, checkController, systemController)
gitHandler := router.ProvideGitHandler(config, provider, repoStore, authenticator, authorizer, gitrpcInterface)

View File

@ -6,10 +6,12 @@ package gitrpc
import (
"fmt"
"time"
"github.com/harness/gitness/gitrpc/rpc"
"google.golang.org/grpc"
"google.golang.org/grpc/backoff"
"google.golang.org/grpc/credentials/insecure"
)
@ -34,6 +36,7 @@ func New(config Config) (*Client, error) {
// preparate all grpc options
grpcOpts := []grpc.DialOption{
grpc.WithDefaultServiceConfig(fmt.Sprintf(`{"loadBalancingPolicy":"%s"}`, config.LoadBalancingPolicy)),
grpc.WithTransportCredentials(insecure.NewCredentials()),
grpc.WithChainUnaryInterceptor(
logIntc.UnaryClientInterceptor(),
@ -41,6 +44,18 @@ func New(config Config) (*Client, error) {
grpc.WithChainStreamInterceptor(
logIntc.StreamClientInterceptor(),
),
grpc.WithConnectParams(
grpc.ConnectParams{
// This config optimizes for connection recovery instead of load reduction.
// NOTE: we only expect limited number of internal clients, thus low number of connections.
Backoff: backoff.Config{
BaseDelay: 100 * time.Millisecond,
Multiplier: 1.6, // same as default
Jitter: 0.2, // same as default
MaxDelay: time.Second,
},
},
),
}
conn, err := grpc.Dial(config.Addr, grpcOpts...)

View File

@ -10,7 +10,8 @@ import (
// Config represents the config for the gitrpc client.
type Config struct {
Addr string `envconfig:"GITRPC_CLIENT_ADDR" default:"127.0.0.1:3001"`
Addr string `envconfig:"GITRPC_CLIENT_ADDR" default:"127.0.0.1:3001"`
LoadBalancingPolicy string `envconfig:"GITRPC_CLIENT_LOAD_BALANCING_POLICY" default:"pick_first"`
}
func (c *Config) Validate() error {

View File

@ -17,7 +17,7 @@ type Interface interface {
GetSubmodule(ctx context.Context, params *GetSubmoduleParams) (*GetSubmoduleOutput, error)
GetBlob(ctx context.Context, params *GetBlobParams) (*GetBlobOutput, error)
CreateBranch(ctx context.Context, params *CreateBranchParams) (*CreateBranchOutput, error)
CreateTag(ctx context.Context, params *CreateTagParams) (*CreateTagOutput, error)
CreateCommitTag(ctx context.Context, params *CreateCommitTagParams) (*CreateCommitTagOutput, error)
DeleteTag(ctx context.Context, params *DeleteTagParams) error
GetBranch(ctx context.Context, params *GetBranchParams) (*GetBranchOutput, error)
DeleteBranch(ctx context.Context, params *DeleteBranchParams) error

View File

@ -39,16 +39,38 @@ func (g Adapter) GetAnnotatedTags(ctx context.Context, repoPath string, shas []s
return giteaGetAnnotatedTags(ctx, repoPath, shas)
}
func (g Adapter) CreateAnnotatedTag(
// CreateTag creates the tag pointing at the provided SHA (could be any type, e.g. commit, tag, blob, ...)
func (g Adapter) CreateTag(
ctx context.Context,
repoPath string,
request *types.CreateTagRequest,
name string,
targetSHA string,
opts *types.CreateTagOptions,
) error {
cmd := gitea.NewCommand(ctx, "tag", "-a", "-m", request.Message, "--", request.Name, request.TargetSha)
env := []string{
"GIT_COMMITTER_NAME=" + request.TaggerName,
"GIT_COMMITTER_EMAIL=" + request.TaggerEmail,
args := []string{
"tag",
}
env := []string{}
if opts != nil && opts.Message != "" {
args = append(args,
"-m",
opts.Message,
)
env = append(env,
"GIT_COMMITTER_NAME="+opts.Tagger.Identity.Name,
"GIT_COMMITTER_EMAIL="+opts.Tagger.Identity.Email,
"GIT_COMMITTER_DATE="+opts.Tagger.When.Format(time.RFC3339),
)
}
args = append(args,
"--",
name,
targetSHA,
)
cmd := gitea.NewCommand(ctx, args...)
_, _, err := cmd.RunStdString(&gitea.RunOpts{Dir: repoPath, Env: env})
if err != nil {
return processGiteaErrorf(err, "Service failed to create a tag")

View File

@ -62,7 +62,7 @@ func (s ReferenceService) CreateBranch(ctx context.Context,
}
// get target commit (as target could be branch/tag/commit, and tag can't be pushed using source:destination syntax)
targetCommit, err := sharedRepo.GetCommit(strings.TrimSpace(request.GetTarget()))
targetCommit, err := s.adapter.GetCommit(ctx, sharedRepo.tmpPath, strings.TrimSpace(request.GetTarget()))
if git.IsErrNotExist(err) {
return nil, ErrNotFoundf("target '%s' doesn't exist", request.GetTarget())
}
@ -71,7 +71,7 @@ func (s ReferenceService) CreateBranch(ctx context.Context,
}
// push to new branch (all changes should go through push flow for hooks and other safety meassures)
err = sharedRepo.PushCommitToBranch(ctx, base, targetCommit.ID.String(), request.GetBranchName())
err = sharedRepo.PushCommitToBranch(ctx, base, targetCommit.SHA, request.GetBranchName())
if err != nil {
return nil, processGitErrorf(err, "failed to push new branch '%s'", request.GetBranchName())
}

View File

@ -41,7 +41,7 @@ type GitAdapter interface {
GetFullCommitID(ctx context.Context, repoPath, shortID string) (string, error)
GetAnnotatedTag(ctx context.Context, repoPath string, sha string) (*types.Tag, error)
GetAnnotatedTags(ctx context.Context, repoPath string, shas []string) ([]types.Tag, error)
CreateAnnotatedTag(ctx context.Context, repoPath string, request *types.CreateTagRequest) error
CreateTag(ctx context.Context, repoPath string, name string, targetSHA string, opts *types.CreateTagOptions) error
GetBranch(ctx context.Context, repoPath string, branchName string) (*types.Branch, error)
GetCommitDivergences(ctx context.Context, repoPath string,
requests []types.CommitDivergenceRequest, max int32) ([]types.CommitDivergence, error)

View File

@ -156,10 +156,11 @@ func mapRenameDetails(renameDetails []types.PathRenameDetails) []*rpc.RenameDeta
return renameDetailsList
}
func mapCommitTag(tag *types.Tag) *rpc.CommitTag {
func mapAnnotatedTag(tag *types.Tag) *rpc.CommitTag {
return &rpc.CommitTag{
Name: tag.Name,
Sha: tag.Sha,
Title: tag.Title,
Message: tag.Message,
Tagger: mapGitSignature(tag.Tagger),
IsAnnotated: true,

View File

@ -440,7 +440,7 @@ func (s RepositoryService) HashRepository(
res, err := hasher.Hash(source)
if err != nil {
return nil, ErrInternalf("failed to hash repo refs", err)
return nil, processGitErrorf(err, "failed to hash repository")
}
return &rpc.HashRepositoryResponse{

View File

@ -6,7 +6,10 @@ package service
import (
"context"
"errors"
"fmt"
"strings"
"time"
"github.com/harness/gitness/gitrpc/internal/types"
"github.com/harness/gitness/gitrpc/rpc"
@ -46,31 +49,53 @@ func (s ReferenceService) ListCommitTags(request *rpc.ListCommitTagsRequest,
}
}
// populate annotation data for all annotated tags
if len(annotatedTagSHAs) > 0 {
var gitTags []types.Tag
gitTags, err = s.adapter.GetAnnotatedTags(ctx, repoPath, annotatedTagSHAs)
var aTags []types.Tag
aTags, err = s.adapter.GetAnnotatedTags(ctx, repoPath, annotatedTagSHAs)
if err != nil {
return processGitErrorf(err, "failed to get annotated tag")
}
ai := 0 // since only some tags are annotated, we need second index
for i := range tags {
if !tags[i].IsAnnotated {
ai := 0 // index for annotated tags
ri := 0 // read index for all tags
wi := 0 // write index for all tags (as we might remove some non-commit tags)
for ; ri < len(tags); ri++ {
// always copy the current read element to the latest write position (doesn't mean it's kept)
tags[wi] = tags[ri]
commitSHAs[wi] = commitSHAs[ri]
// keep the tag as is if it's not annotated
if !tags[ri].IsAnnotated {
wi++
continue
}
// filter out annotated tags that don't point to commit objects (blobs, trees, nested tags, ...)
// we don't actually wanna write it, so keep write index
// TODO: Support proper pagination: https://harness.atlassian.net/browse/CODE-669
if aTags[ai].TargetType != types.GitObjectTypeCommit {
ai++
continue
}
// correct the commitSHA for the annotated tag (currently it is the tag sha, not the commit sha)
// NOTE: This is required as otherwise gitea will wrongly set the committer to the tagger signature.
commitSHAs[i] = gitTags[ai].TargetSha
commitSHAs[wi] = aTags[ai].TargetSha
// update tag information with annotation details
// NOTE: we keep the name from the reference and ignore the annotated name (similar to github)
tags[i].Message = gitTags[ai].Message
tags[i].Title = gitTags[ai].Title
tags[i].Tagger = mapGitSignature(gitTags[ai].Tagger)
tags[wi].Message = aTags[ai].Message
tags[wi].Title = aTags[ai].Title
tags[wi].Tagger = mapGitSignature(aTags[ai].Tagger)
ai++
wi++
}
// truncate slices based on what was removed
tags = tags[:wi]
commitSHAs = commitSHAs[:wi]
}
// get commits if needed (single call for perf savings: 1s-4s vs 5s-20s)
@ -185,10 +210,10 @@ func listCommitTagsWalkReferencesHandler(tags *[]*rpc.CommitTag) types.WalkRefer
return nil
}
}
func (s ReferenceService) CreateTag(
func (s ReferenceService) CreateCommitTag(
ctx context.Context,
request *rpc.CreateTagRequest,
) (*rpc.CreateTagResponse, error) {
request *rpc.CreateCommitTagRequest,
) (*rpc.CreateCommitTagResponse, error) {
base := request.GetBase()
if base == nil {
return nil, types.ErrBaseCannotBeEmpty
@ -208,35 +233,87 @@ func (s ReferenceService) CreateTag(
defer sharedRepo.Close(ctx)
// clone repo (with HEAD branch - target might be anything)
err = sharedRepo.Clone(ctx, "")
if err != nil {
return nil, processGitErrorf(err, "failed to clone shared repo with branch '%s'", request.GetSha())
return nil, processGitErrorf(err, "failed to clone shared repo")
}
actor := request.GetBase().GetActor()
createTagRequest := types.CreateTagRequest{
Name: request.GetTagName(),
TargetSha: request.GetSha(),
Message: request.GetMessage(),
TaggerEmail: actor.GetEmail(),
TaggerName: actor.GetName(),
}
err = s.adapter.CreateAnnotatedTag(ctx, sharedRepo.tmpPath, &createTagRequest)
// get target commit (as target could be branch/tag/commit, and tag can't be pushed using source:destination syntax)
// NOTE: in case the target is an annotated tag, the targetCommit title and message are that of the tag, not the commit
targetCommit, err := s.adapter.GetCommit(ctx, sharedRepo.tmpPath, strings.TrimSpace(request.GetTarget()))
if git.IsErrNotExist(err) {
return nil, ErrNotFoundf("target '%s' doesn't exist", request.GetTarget())
}
if err != nil {
return nil, processGitErrorf(err, "Failed to create tag %s - %s", request.GetTagName(), err.Error())
return nil, fmt.Errorf("failed to get commit id for target '%s': %w", request.GetTarget(), err)
}
tagger := base.GetActor()
if request.GetTagger() != nil {
tagger = request.GetTagger()
}
taggerDate := time.Now().UTC()
if request.GetTaggerDate() != 0 {
taggerDate = time.Unix(request.GetTaggerDate(), 0)
}
createTagRequest := &types.CreateTagOptions{
Message: request.GetMessage(),
Tagger: types.Signature{
Identity: types.Identity{
Name: tagger.Name,
Email: tagger.Email,
},
When: taggerDate,
},
}
err = s.adapter.CreateTag(
ctx,
sharedRepo.tmpPath,
request.GetTagName(),
targetCommit.SHA,
createTagRequest)
if errors.Is(err, types.ErrAlreadyExists) {
return nil, ErrAlreadyExistsf("tag '%s' already exists", request.GetTagName())
}
if err != nil {
return nil, processGitErrorf(err, "Failed to create tag '%s'", request.GetTagName())
}
if err = sharedRepo.PushTag(ctx, base, request.GetTagName()); err != nil {
return nil, processGitErrorf(err, "Failed to push the tag %s to remote", request.GetTagName())
return nil, processGitErrorf(err, "Failed to push the tag to remote")
}
tag, err := s.adapter.GetAnnotatedTag(ctx, repoPath, request.GetTagName())
var commitTag *rpc.CommitTag
if request.GetMessage() != "" {
tag, err := s.adapter.GetAnnotatedTag(ctx, repoPath, request.GetTagName())
if err != nil {
return nil, fmt.Errorf("failed to read annotated tag after creation: %w", err)
}
commitTag = mapAnnotatedTag(tag)
} else {
commitTag = &rpc.CommitTag{
Name: request.GetTagName(),
IsAnnotated: false,
Sha: targetCommit.SHA,
}
}
// gitea overwrites some commit details in case getCommit(ref) was called with ref being a tag
// To avoid this issue, let's get the commit again using the actual id of the commit
// TODO: can we do this nicer?
rawCommit, err := s.adapter.GetCommit(ctx, repoPath, targetCommit.SHA)
if err != nil {
return nil, err
return nil, fmt.Errorf("failed to get the raw commit '%s' after tag creation: %w", targetCommit.SHA, err)
}
commitTag := mapCommitTag(tag)
return &rpc.CreateTagResponse{Tag: commitTag}, nil
commitTag.Commit, err = mapGitCommit(rawCommit)
if err != nil {
return nil, fmt.Errorf("failed to map target commit after tag creation: %w", err)
}
return &rpc.CreateCommitTagResponse{Tag: commitTag}, nil
}
func (s ReferenceService) DeleteTag(
@ -262,7 +339,8 @@ func (s ReferenceService) DeleteTag(
defer sharedRepo.Close(ctx)
err = sharedRepo.Clone(ctx, request.GetTagName())
// clone repo (with HEAD branch - tag target might be anything)
err = sharedRepo.Clone(ctx, "")
if err != nil {
return nil, processGitErrorf(err, "failed to clone shared repo with tag '%s'", request.GetTagName())
}

View File

@ -150,12 +150,13 @@ type Tag struct {
Tagger Signature
}
type CreateTagRequest struct {
Name string
TargetSha string
Message string
TaggerName string
TaggerEmail string
type CreateTagOptions struct {
// Message is the optional message the tag will be created with - if the message is empty
// the tag will be lightweight, otherwise it'll be annotated.
Message string
// Tagger is the information used in case the tag is annotated (Message is provided).
Tagger Signature
}
// Signature represents the Author or Committer information.

13
gitrpc/kuberesolver.go Normal file
View File

@ -0,0 +1,13 @@
// Copyright 2022 Harness Inc. All rights reserved.
// Use of this source code is governed by the Polyform Free Trial License
// that can be found in the LICENSE.md file for this repository.
package gitrpc
import (
"github.com/sercand/kuberesolver/v5"
)
func init() {
kuberesolver.RegisterInCluster()
}

View File

@ -23,13 +23,17 @@ type MergeParams struct {
Title string
Message string
// Committer overwrites the git committer used for committing the files (optional, default: actor)
// Committer overwrites the git committer used for committing the files
// (optional, default: actor)
Committer *Identity
// CommitterDate overwrites the git committer date used for committing the files (optional, default: current time)
// CommitterDate overwrites the git committer date used for committing the files
// (optional, default: current time on server)
CommitterDate *time.Time
// Author overwrites the git author used for committing the files (optional, default: committer)
// Author overwrites the git author used for committing the files
// (optional, default: committer)
Author *Identity
// AuthorDate overwrites the git author date used for committing the files (optional, default: committer date)
// AuthorDate overwrites the git author date used for committing the files
// (optional, default: committer date)
AuthorDate *time.Time
RefType enum.RefType

View File

@ -45,13 +45,17 @@ type CommitFilesParams struct {
NewBranch string
Actions []CommitFileAction
// Committer overwrites the git committer used for committing the files (optional, default: actor)
// Committer overwrites the git committer used for committing the files
// (optional, default: actor)
Committer *Identity
// CommitterDate overwrites the git committer date used for committing the files (optional, default: current time)
// CommitterDate overwrites the git committer date used for committing the files
// (optional, default: current time on server)
CommitterDate *time.Time
// Author overwrites the git author used for committing the files (optional, default: committer)
// Author overwrites the git author used for committing the files
// (optional, default: committer)
Author *Identity
// AuthorDate overwrites the git author date used for committing the files (optional, default: committer date)
// AuthorDate overwrites the git author date used for committing the files
// (optional, default: committer date)
AuthorDate *time.Time
}

View File

@ -11,21 +11,22 @@ service ReferenceService {
rpc DeleteBranch(DeleteBranchRequest) returns (DeleteBranchResponse);
rpc ListBranches(ListBranchesRequest) returns (stream ListBranchesResponse);
rpc ListCommitTags(ListCommitTagsRequest) returns (stream ListCommitTagsResponse);
rpc CreateTag(CreateTagRequest) returns (CreateTagResponse);
rpc CreateCommitTag(CreateCommitTagRequest) returns (CreateCommitTagResponse);
rpc DeleteTag(DeleteTagRequest) returns (UpdateRefResponse);
rpc GetRef(GetRefRequest) returns (GetRefResponse);
rpc UpdateRef(UpdateRefRequest) returns (UpdateRefResponse);
}
message CreateTagRequest {
message CreateCommitTagRequest {
WriteRequest base = 1;
string sha = 2;
string tag_name = 3;
string tag_name = 2;
string target = 3;
string message = 4;
Identity tagger = 5;
int64 taggerDate = 6;
}
message CreateTagResponse {
message CreateCommitTagResponse {
CommitTag tag = 1;
}

View File

@ -34,13 +34,17 @@ type CreateRepositoryParams struct {
DefaultBranch string
Files []File
// Committer overwrites the git committer used for committing the files (optional, default: actor)
// Committer overwrites the git committer used for committing the files
// (optional, default: actor)
Committer *Identity
// CommitterDate overwrites the git committer date used for committing the files (optional, default: current time)
// CommitterDate overwrites the git committer date used for committing the files
// (optional, default: current time on server)
CommitterDate *time.Time
// Author overwrites the git author used for committing the files (optional, default: committer)
// Author overwrites the git author used for committing the files
// (optional, default: committer)
Author *Identity
// AuthorDate overwrites the git author date used for committing the files (optional, default: committer date)
// AuthorDate overwrites the git author date used for committing the files
// (optional, default: committer date)
AuthorDate *time.Time
}

View File

@ -151,6 +151,7 @@ type ServicePackRequest struct {
// Depending on the service the matching base type has to be passed
//
// Types that are assignable to Base:
//
// *ServicePackRequest_ReadBase
// *ServicePackRequest_WriteBase
Base isServicePackRequest_Base `protobuf_oneof:"base"`

View File

@ -263,6 +263,7 @@ type CommitFilesAction struct {
unknownFields protoimpl.UnknownFields
// Types that are assignable to Payload:
//
// *CommitFilesAction_Header
// *CommitFilesAction_Content
Payload isCommitFilesAction_Payload `protobuf_oneof:"payload"`
@ -346,6 +347,7 @@ type CommitFilesRequest struct {
unknownFields protoimpl.UnknownFields
// Types that are assignable to Payload:
//
// *CommitFilesRequest_Header
// *CommitFilesRequest_Action
Payload isCommitFilesRequest_Payload `protobuf_oneof:"payload"`

View File

@ -118,19 +118,21 @@ func (ListCommitTagsRequest_SortOption) EnumDescriptor() ([]byte, []int) {
return file_ref_proto_rawDescGZIP(), []int{12, 0}
}
type CreateTagRequest struct {
type CreateCommitTagRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Base *WriteRequest `protobuf:"bytes,1,opt,name=base,proto3" json:"base,omitempty"`
Sha string `protobuf:"bytes,2,opt,name=sha,proto3" json:"sha,omitempty"`
TagName string `protobuf:"bytes,3,opt,name=tag_name,json=tagName,proto3" json:"tag_name,omitempty"`
Message string `protobuf:"bytes,4,opt,name=message,proto3" json:"message,omitempty"`
Base *WriteRequest `protobuf:"bytes,1,opt,name=base,proto3" json:"base,omitempty"`
TagName string `protobuf:"bytes,2,opt,name=tag_name,json=tagName,proto3" json:"tag_name,omitempty"`
Target string `protobuf:"bytes,3,opt,name=target,proto3" json:"target,omitempty"`
Message string `protobuf:"bytes,4,opt,name=message,proto3" json:"message,omitempty"`
Tagger *Identity `protobuf:"bytes,5,opt,name=tagger,proto3" json:"tagger,omitempty"`
TaggerDate int64 `protobuf:"varint,6,opt,name=taggerDate,proto3" json:"taggerDate,omitempty"`
}
func (x *CreateTagRequest) Reset() {
*x = CreateTagRequest{}
func (x *CreateCommitTagRequest) Reset() {
*x = CreateCommitTagRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_ref_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
@ -138,13 +140,13 @@ func (x *CreateTagRequest) Reset() {
}
}
func (x *CreateTagRequest) String() string {
func (x *CreateCommitTagRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*CreateTagRequest) ProtoMessage() {}
func (*CreateCommitTagRequest) ProtoMessage() {}
func (x *CreateTagRequest) ProtoReflect() protoreflect.Message {
func (x *CreateCommitTagRequest) ProtoReflect() protoreflect.Message {
mi := &file_ref_proto_msgTypes[0]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
@ -156,40 +158,54 @@ func (x *CreateTagRequest) ProtoReflect() protoreflect.Message {
return mi.MessageOf(x)
}
// Deprecated: Use CreateTagRequest.ProtoReflect.Descriptor instead.
func (*CreateTagRequest) Descriptor() ([]byte, []int) {
// Deprecated: Use CreateCommitTagRequest.ProtoReflect.Descriptor instead.
func (*CreateCommitTagRequest) Descriptor() ([]byte, []int) {
return file_ref_proto_rawDescGZIP(), []int{0}
}
func (x *CreateTagRequest) GetBase() *WriteRequest {
func (x *CreateCommitTagRequest) GetBase() *WriteRequest {
if x != nil {
return x.Base
}
return nil
}
func (x *CreateTagRequest) GetSha() string {
if x != nil {
return x.Sha
}
return ""
}
func (x *CreateTagRequest) GetTagName() string {
func (x *CreateCommitTagRequest) GetTagName() string {
if x != nil {
return x.TagName
}
return ""
}
func (x *CreateTagRequest) GetMessage() string {
func (x *CreateCommitTagRequest) GetTarget() string {
if x != nil {
return x.Target
}
return ""
}
func (x *CreateCommitTagRequest) GetMessage() string {
if x != nil {
return x.Message
}
return ""
}
type CreateTagResponse struct {
func (x *CreateCommitTagRequest) GetTagger() *Identity {
if x != nil {
return x.Tagger
}
return nil
}
func (x *CreateCommitTagRequest) GetTaggerDate() int64 {
if x != nil {
return x.TaggerDate
}
return 0
}
type CreateCommitTagResponse struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
@ -197,8 +213,8 @@ type CreateTagResponse struct {
Tag *CommitTag `protobuf:"bytes,1,opt,name=tag,proto3" json:"tag,omitempty"`
}
func (x *CreateTagResponse) Reset() {
*x = CreateTagResponse{}
func (x *CreateCommitTagResponse) Reset() {
*x = CreateCommitTagResponse{}
if protoimpl.UnsafeEnabled {
mi := &file_ref_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
@ -206,13 +222,13 @@ func (x *CreateTagResponse) Reset() {
}
}
func (x *CreateTagResponse) String() string {
func (x *CreateCommitTagResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*CreateTagResponse) ProtoMessage() {}
func (*CreateCommitTagResponse) ProtoMessage() {}
func (x *CreateTagResponse) ProtoReflect() protoreflect.Message {
func (x *CreateCommitTagResponse) ProtoReflect() protoreflect.Message {
mi := &file_ref_proto_msgTypes[1]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
@ -224,12 +240,12 @@ func (x *CreateTagResponse) ProtoReflect() protoreflect.Message {
return mi.MessageOf(x)
}
// Deprecated: Use CreateTagResponse.ProtoReflect.Descriptor instead.
func (*CreateTagResponse) Descriptor() ([]byte, []int) {
// Deprecated: Use CreateCommitTagResponse.ProtoReflect.Descriptor instead.
func (*CreateCommitTagResponse) Descriptor() ([]byte, []int) {
return file_ref_proto_rawDescGZIP(), []int{1}
}
func (x *CreateTagResponse) GetTag() *CommitTag {
func (x *CreateCommitTagResponse) GetTag() *CommitTag {
if x != nil {
return x.Tag
}
@ -1286,184 +1302,190 @@ var File_ref_proto protoreflect.FileDescriptor
var file_ref_proto_rawDesc = []byte{
0x0a, 0x09, 0x72, 0x65, 0x66, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x03, 0x72, 0x70, 0x63,
0x1a, 0x0c, 0x73, 0x68, 0x61, 0x72, 0x65, 0x64, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x80,
0x01, 0x0a, 0x10, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x54, 0x61, 0x67, 0x52, 0x65, 0x71, 0x75,
0x65, 0x73, 0x74, 0x12, 0x25, 0x0a, 0x04, 0x62, 0x61, 0x73, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28,
0x0b, 0x32, 0x11, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x57, 0x72, 0x69, 0x74, 0x65, 0x52, 0x65, 0x71,
0x75, 0x65, 0x73, 0x74, 0x52, 0x04, 0x62, 0x61, 0x73, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x73, 0x68,
0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x73, 0x68, 0x61, 0x12, 0x19, 0x0a, 0x08,
0x74, 0x61, 0x67, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07,
0x74, 0x61, 0x67, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61,
0x67, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67,
0x65, 0x22, 0x35, 0x0a, 0x11, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x54, 0x61, 0x67, 0x52, 0x65,
0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x20, 0x0a, 0x03, 0x74, 0x61, 0x67, 0x18, 0x01, 0x20,
0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74,
0x54, 0x61, 0x67, 0x52, 0x03, 0x74, 0x61, 0x67, 0x22, 0x54, 0x0a, 0x10, 0x44, 0x65, 0x6c, 0x65,
0x74, 0x65, 0x54, 0x61, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x25, 0x0a, 0x04,
0x62, 0x61, 0x73, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x72, 0x70, 0x63,
0x2e, 0x57, 0x72, 0x69, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x52, 0x04, 0x62,
0x61, 0x73, 0x65, 0x12, 0x19, 0x0a, 0x08, 0x74, 0x61, 0x67, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18,
0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x74, 0x61, 0x67, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0x75,
0x0a, 0x13, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x52, 0x65,
0x1a, 0x0c, 0x73, 0x68, 0x61, 0x72, 0x65, 0x64, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xd3,
0x01, 0x0a, 0x16, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x54,
0x61, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x25, 0x0a, 0x04, 0x62, 0x61, 0x73,
0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x57, 0x72,
0x69, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x52, 0x04, 0x62, 0x61, 0x73, 0x65,
0x12, 0x19, 0x0a, 0x08, 0x74, 0x61, 0x67, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01,
0x28, 0x09, 0x52, 0x07, 0x74, 0x61, 0x67, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x74,
0x61, 0x72, 0x67, 0x65, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x74, 0x61, 0x72,
0x67, 0x65, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x04,
0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x25, 0x0a,
0x06, 0x74, 0x61, 0x67, 0x67, 0x65, 0x72, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e,
0x72, 0x70, 0x63, 0x2e, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, 0x06, 0x74, 0x61,
0x67, 0x67, 0x65, 0x72, 0x12, 0x1e, 0x0a, 0x0a, 0x74, 0x61, 0x67, 0x67, 0x65, 0x72, 0x44, 0x61,
0x74, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x74, 0x61, 0x67, 0x67, 0x65, 0x72,
0x44, 0x61, 0x74, 0x65, 0x22, 0x3b, 0x0a, 0x17, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x43, 0x6f,
0x6d, 0x6d, 0x69, 0x74, 0x54, 0x61, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12,
0x20, 0x0a, 0x03, 0x74, 0x61, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x72,
0x70, 0x63, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x54, 0x61, 0x67, 0x52, 0x03, 0x74, 0x61,
0x67, 0x22, 0x54, 0x0a, 0x10, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x54, 0x61, 0x67, 0x52, 0x65,
0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x25, 0x0a, 0x04, 0x62, 0x61, 0x73, 0x65, 0x18, 0x01, 0x20,
0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x57, 0x72, 0x69, 0x74, 0x65, 0x52,
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x52, 0x04, 0x62, 0x61, 0x73, 0x65, 0x12, 0x1f, 0x0a, 0x0b,
0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28,
0x09, 0x52, 0x0a, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a,
0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x74,
0x61, 0x72, 0x67, 0x65, 0x74, 0x22, 0x3b, 0x0a, 0x14, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x42,
0x72, 0x61, 0x6e, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x23, 0x0a,
0x06, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0b, 0x2e,
0x72, 0x70, 0x63, 0x2e, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x52, 0x06, 0x62, 0x72, 0x61, 0x6e,
0x63, 0x68, 0x22, 0x59, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x52,
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x24, 0x0a, 0x04, 0x62, 0x61, 0x73, 0x65, 0x18, 0x01,
0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x52, 0x65, 0x61, 0x64, 0x52,
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x52, 0x04, 0x62, 0x61, 0x73, 0x65, 0x12, 0x1f, 0x0a, 0x0b,
0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28,
0x09, 0x52, 0x0a, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0x38, 0x0a,
0x11, 0x47, 0x65, 0x74, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
0x73, 0x65, 0x12, 0x23, 0x0a, 0x06, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x18, 0x01, 0x20, 0x01,
0x28, 0x0b, 0x32, 0x0b, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x52,
0x06, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x22, 0x73, 0x0a, 0x13, 0x44, 0x65, 0x6c, 0x65, 0x74,
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x52, 0x04, 0x62, 0x61, 0x73, 0x65, 0x12, 0x19, 0x0a, 0x08,
0x74, 0x61, 0x67, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07,
0x74, 0x61, 0x67, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0x75, 0x0a, 0x13, 0x43, 0x72, 0x65, 0x61, 0x74,
0x65, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x25,
0x0a, 0x04, 0x62, 0x61, 0x73, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x72,
0x70, 0x63, 0x2e, 0x57, 0x72, 0x69, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x52,
0x04, 0x62, 0x61, 0x73, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x5f,
0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x62, 0x72, 0x61, 0x6e,
0x63, 0x68, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x18,
0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x22, 0x28, 0x0a, 0x14,
0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70,
0x6f, 0x6e, 0x73, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x73, 0x68, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28,
0x09, 0x52, 0x03, 0x73, 0x68, 0x61, 0x22, 0xb6, 0x02, 0x0a, 0x13, 0x4c, 0x69, 0x73, 0x74, 0x42,
0x72, 0x61, 0x6e, 0x63, 0x68, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x24,
0x0a, 0x04, 0x62, 0x61, 0x73, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x72,
0x70, 0x63, 0x2e, 0x52, 0x65, 0x61, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x52, 0x04,
0x62, 0x61, 0x73, 0x65, 0x12, 0x25, 0x0a, 0x0e, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x5f,
0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, 0x69, 0x6e,
0x63, 0x6c, 0x75, 0x64, 0x65, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x71,
0x75, 0x65, 0x72, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x71, 0x75, 0x65, 0x72,
0x79, 0x12, 0x37, 0x0a, 0x04, 0x73, 0x6f, 0x72, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32,
0x23, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68,
0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x53, 0x6f, 0x72, 0x74, 0x4f, 0x70,
0x74, 0x69, 0x6f, 0x6e, 0x52, 0x04, 0x73, 0x6f, 0x72, 0x74, 0x12, 0x24, 0x0a, 0x05, 0x6f, 0x72,
0x64, 0x65, 0x72, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x0e, 0x2e, 0x72, 0x70, 0x63, 0x2e,
0x53, 0x6f, 0x72, 0x74, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x52, 0x05, 0x6f, 0x72, 0x64, 0x65, 0x72,
0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x67, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04,
0x70, 0x61, 0x67, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x61, 0x67, 0x65, 0x53, 0x69, 0x7a, 0x65,
0x18, 0x07, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x70, 0x61, 0x67, 0x65, 0x53, 0x69, 0x7a, 0x65,
0x22, 0x2d, 0x0a, 0x0a, 0x53, 0x6f, 0x72, 0x74, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x0b,
0x0a, 0x07, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x10, 0x00, 0x12, 0x08, 0x0a, 0x04, 0x4e,
0x61, 0x6d, 0x65, 0x10, 0x01, 0x12, 0x08, 0x0a, 0x04, 0x44, 0x61, 0x74, 0x65, 0x10, 0x02, 0x22,
0x3b, 0x0a, 0x14, 0x4c, 0x69, 0x73, 0x74, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x65, 0x73, 0x52,
0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x23, 0x0a, 0x06, 0x62, 0x72, 0x61, 0x6e, 0x63,
0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0b, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x42, 0x72,
0x61, 0x6e, 0x63, 0x68, 0x52, 0x06, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x22, 0x53, 0x0a, 0x06,
0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01,
0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x73, 0x68,
0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x73, 0x68, 0x61, 0x12, 0x23, 0x0a, 0x06,
0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0b, 0x2e, 0x72,
0x70, 0x63, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x52, 0x06, 0x63, 0x6f, 0x6d, 0x6d, 0x69,
0x74, 0x22, 0xba, 0x02, 0x0a, 0x15, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74,
0x54, 0x61, 0x67, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x24, 0x0a, 0x04, 0x62,
0x61, 0x73, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x72, 0x70, 0x63, 0x2e,
0x52, 0x65, 0x61, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x52, 0x04, 0x62, 0x61, 0x73,
0x65, 0x12, 0x25, 0x0a, 0x0e, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x5f, 0x63, 0x6f, 0x6d,
0x6d, 0x69, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, 0x69, 0x6e, 0x63, 0x6c, 0x75,
0x64, 0x65, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x71, 0x75, 0x65, 0x72,
0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x71, 0x75, 0x65, 0x72, 0x79, 0x12, 0x39,
0x0a, 0x04, 0x73, 0x6f, 0x72, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x25, 0x2e, 0x72,
0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x54, 0x61, 0x67,
0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x53, 0x6f, 0x72, 0x74, 0x4f, 0x70, 0x74,
0x69, 0x6f, 0x6e, 0x52, 0x04, 0x73, 0x6f, 0x72, 0x74, 0x12, 0x24, 0x0a, 0x05, 0x6f, 0x72, 0x64,
0x65, 0x72, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x0e, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x53,
0x6f, 0x72, 0x74, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x52, 0x05, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x12,
0x12, 0x0a, 0x04, 0x70, 0x61, 0x67, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x70,
0x61, 0x67, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x61, 0x67, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x18,
0x07, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x70, 0x61, 0x67, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x22,
0x2d, 0x0a, 0x0a, 0x53, 0x6f, 0x72, 0x74, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x0b, 0x0a,
0x07, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x10, 0x00, 0x12, 0x08, 0x0a, 0x04, 0x4e, 0x61,
0x6d, 0x65, 0x10, 0x01, 0x12, 0x08, 0x0a, 0x04, 0x44, 0x61, 0x74, 0x65, 0x10, 0x02, 0x22, 0x3a,
0x0a, 0x16, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x54, 0x61, 0x67, 0x73,
0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x20, 0x0a, 0x03, 0x74, 0x61, 0x67, 0x18,
0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x6f, 0x6d, 0x6d,
0x69, 0x74, 0x54, 0x61, 0x67, 0x52, 0x03, 0x74, 0x61, 0x67, 0x22, 0xd1, 0x01, 0x0a, 0x09, 0x43,
0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x54, 0x61, 0x67, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65,
0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x10, 0x0a, 0x03,
0x73, 0x68, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x73, 0x68, 0x61, 0x12, 0x21,
0x0a, 0x0c, 0x69, 0x73, 0x5f, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x65, 0x64, 0x18, 0x03,
0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x69, 0x73, 0x41, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x65,
0x64, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09,
0x52, 0x05, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61,
0x67, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67,
0x65, 0x12, 0x26, 0x0a, 0x06, 0x74, 0x61, 0x67, 0x67, 0x65, 0x72, 0x18, 0x06, 0x20, 0x01, 0x28,
0x0b, 0x32, 0x0e, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72,
0x65, 0x52, 0x06, 0x74, 0x61, 0x67, 0x67, 0x65, 0x72, 0x12, 0x23, 0x0a, 0x06, 0x63, 0x6f, 0x6d,
0x6d, 0x69, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0b, 0x2e, 0x72, 0x70, 0x63, 0x2e,
0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x52, 0x06, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x22, 0x79,
0x0a, 0x0d, 0x47, 0x65, 0x74, 0x52, 0x65, 0x66, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12,
0x63, 0x68, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74,
0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x22, 0x3b,
0x0a, 0x14, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x52, 0x65,
0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x23, 0x0a, 0x06, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68,
0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0b, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x42, 0x72, 0x61,
0x6e, 0x63, 0x68, 0x52, 0x06, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x22, 0x59, 0x0a, 0x10, 0x47,
0x65, 0x74, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12,
0x24, 0x0a, 0x04, 0x62, 0x61, 0x73, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e,
0x72, 0x70, 0x63, 0x2e, 0x52, 0x65, 0x61, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x52,
0x04, 0x62, 0x61, 0x73, 0x65, 0x12, 0x19, 0x0a, 0x08, 0x72, 0x65, 0x66, 0x5f, 0x6e, 0x61, 0x6d,
0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x72, 0x65, 0x66, 0x4e, 0x61, 0x6d, 0x65,
0x12, 0x27, 0x0a, 0x08, 0x72, 0x65, 0x66, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01,
0x28, 0x0e, 0x32, 0x0c, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x52, 0x65, 0x66, 0x54, 0x79, 0x70, 0x65,
0x52, 0x07, 0x72, 0x65, 0x66, 0x54, 0x79, 0x70, 0x65, 0x22, 0x22, 0x0a, 0x0e, 0x47, 0x65, 0x74,
0x52, 0x65, 0x66, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x73,
0x68, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x73, 0x68, 0x61, 0x22, 0xb7, 0x01,
0x0a, 0x10, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x66, 0x52, 0x65, 0x71, 0x75, 0x65,
0x73, 0x74, 0x12, 0x25, 0x0a, 0x04, 0x62, 0x61, 0x73, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b,
0x32, 0x11, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x57, 0x72, 0x69, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75,
0x65, 0x73, 0x74, 0x52, 0x04, 0x62, 0x61, 0x73, 0x65, 0x12, 0x19, 0x0a, 0x08, 0x72, 0x65, 0x66,
0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x72, 0x65, 0x66,
0x4e, 0x61, 0x6d, 0x65, 0x12, 0x27, 0x0a, 0x08, 0x72, 0x65, 0x66, 0x5f, 0x74, 0x79, 0x70, 0x65,
0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x0c, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x52, 0x65, 0x66,
0x54, 0x79, 0x70, 0x65, 0x52, 0x07, 0x72, 0x65, 0x66, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1b, 0x0a,
0x09, 0x6e, 0x65, 0x77, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09,
0x52, 0x08, 0x6e, 0x65, 0x77, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x6f, 0x6c,
0x64, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6f,
0x6c, 0x64, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x13, 0x0a, 0x11, 0x55, 0x70, 0x64, 0x61, 0x74,
0x65, 0x52, 0x65, 0x66, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0xd3, 0x04, 0x0a,
0x10, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63,
0x65, 0x12, 0x43, 0x0a, 0x0c, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x42, 0x72, 0x61, 0x6e, 0x63,
0x68, 0x12, 0x18, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x42, 0x72,
0x61, 0x6e, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x72, 0x70,
0x63, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x52, 0x65,
0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3a, 0x0a, 0x09, 0x47, 0x65, 0x74, 0x42, 0x72, 0x61,
0x6e, 0x63, 0x68, 0x12, 0x15, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x42, 0x72, 0x61,
0x6e, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x72, 0x70, 0x63,
0x2e, 0x47, 0x65, 0x74, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
0x73, 0x65, 0x12, 0x43, 0x0a, 0x0c, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x42, 0x72, 0x61, 0x6e,
0x63, 0x68, 0x12, 0x18, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x42,
0x72, 0x61, 0x6e, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x72,
0x70, 0x63, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x52,
0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x45, 0x0a, 0x0c, 0x4c, 0x69, 0x73, 0x74, 0x42,
0x72, 0x61, 0x6e, 0x63, 0x68, 0x65, 0x73, 0x12, 0x18, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69,
0x73, 0x74, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
0x74, 0x1a, 0x19, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x42, 0x72, 0x61, 0x6e,
0x63, 0x68, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x4b,
0x0a, 0x0e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x54, 0x61, 0x67, 0x73,
0x12, 0x1a, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x69,
0x74, 0x54, 0x61, 0x67, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x72,
0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x54, 0x61, 0x67,
0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x3a, 0x0a, 0x09, 0x43,
0x72, 0x65, 0x61, 0x74, 0x65, 0x54, 0x61, 0x67, 0x12, 0x15, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x43,
0x72, 0x65, 0x61, 0x74, 0x65, 0x54, 0x61, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a,
0x16, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x54, 0x61, 0x67, 0x52,
0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3a, 0x0a, 0x09, 0x44, 0x65, 0x6c, 0x65, 0x74,
0x65, 0x54, 0x61, 0x67, 0x12, 0x15, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74,
0x65, 0x54, 0x61, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x72, 0x70,
0x63, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x66, 0x52, 0x65, 0x73, 0x70, 0x6f,
0x6e, 0x73, 0x65, 0x12, 0x31, 0x0a, 0x06, 0x47, 0x65, 0x74, 0x52, 0x65, 0x66, 0x12, 0x12, 0x2e,
0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x65, 0x66, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
0x74, 0x1a, 0x13, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x65, 0x66, 0x52, 0x65,
0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3a, 0x0a, 0x09, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65,
0x52, 0x65, 0x66, 0x12, 0x15, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65,
0x52, 0x65, 0x66, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x72, 0x70, 0x63,
0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x66, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
0x73, 0x65, 0x42, 0x27, 0x5a, 0x25, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d,
0x2f, 0x68, 0x61, 0x72, 0x6e, 0x65, 0x73, 0x73, 0x2f, 0x67, 0x69, 0x74, 0x6e, 0x65, 0x73, 0x73,
0x2f, 0x67, 0x69, 0x74, 0x72, 0x70, 0x63, 0x2f, 0x72, 0x70, 0x63, 0x62, 0x06, 0x70, 0x72, 0x6f,
0x74, 0x6f, 0x33,
0x04, 0x62, 0x61, 0x73, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x5f,
0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x62, 0x72, 0x61, 0x6e,
0x63, 0x68, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0x38, 0x0a, 0x11, 0x47, 0x65, 0x74, 0x42, 0x72, 0x61,
0x6e, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x23, 0x0a, 0x06, 0x62,
0x72, 0x61, 0x6e, 0x63, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0b, 0x2e, 0x72, 0x70,
0x63, 0x2e, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x52, 0x06, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68,
0x22, 0x73, 0x0a, 0x13, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68,
0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x25, 0x0a, 0x04, 0x62, 0x61, 0x73, 0x65, 0x18,
0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x57, 0x72, 0x69, 0x74,
0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x52, 0x04, 0x62, 0x61, 0x73, 0x65, 0x12, 0x1f,
0x0a, 0x0b, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20,
0x01, 0x28, 0x09, 0x52, 0x0a, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x4e, 0x61, 0x6d, 0x65, 0x12,
0x14, 0x0a, 0x05, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05,
0x66, 0x6f, 0x72, 0x63, 0x65, 0x22, 0x28, 0x0a, 0x14, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x42,
0x72, 0x61, 0x6e, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x10, 0x0a,
0x03, 0x73, 0x68, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x73, 0x68, 0x61, 0x22,
0xb6, 0x02, 0x0a, 0x13, 0x4c, 0x69, 0x73, 0x74, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x65, 0x73,
0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x24, 0x0a, 0x04, 0x62, 0x61, 0x73, 0x65, 0x18,
0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x52, 0x65, 0x61, 0x64,
0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x52, 0x04, 0x62, 0x61, 0x73, 0x65, 0x12, 0x25, 0x0a,
0x0e, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x18,
0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x43, 0x6f,
0x6d, 0x6d, 0x69, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x71, 0x75, 0x65, 0x72, 0x79, 0x18, 0x03, 0x20,
0x01, 0x28, 0x09, 0x52, 0x05, 0x71, 0x75, 0x65, 0x72, 0x79, 0x12, 0x37, 0x0a, 0x04, 0x73, 0x6f,
0x72, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x23, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x4c,
0x69, 0x73, 0x74, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65,
0x73, 0x74, 0x2e, 0x53, 0x6f, 0x72, 0x74, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x04, 0x73,
0x6f, 0x72, 0x74, 0x12, 0x24, 0x0a, 0x05, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x18, 0x05, 0x20, 0x01,
0x28, 0x0e, 0x32, 0x0e, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x6f, 0x72, 0x74, 0x4f, 0x72, 0x64,
0x65, 0x72, 0x52, 0x05, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x67,
0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x70, 0x61, 0x67, 0x65, 0x12, 0x1a, 0x0a,
0x08, 0x70, 0x61, 0x67, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x05, 0x52,
0x08, 0x70, 0x61, 0x67, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x22, 0x2d, 0x0a, 0x0a, 0x53, 0x6f, 0x72,
0x74, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x0b, 0x0a, 0x07, 0x44, 0x65, 0x66, 0x61, 0x75,
0x6c, 0x74, 0x10, 0x00, 0x12, 0x08, 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x10, 0x01, 0x12, 0x08,
0x0a, 0x04, 0x44, 0x61, 0x74, 0x65, 0x10, 0x02, 0x22, 0x3b, 0x0a, 0x14, 0x4c, 0x69, 0x73, 0x74,
0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
0x12, 0x23, 0x0a, 0x06, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b,
0x32, 0x0b, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x52, 0x06, 0x62,
0x72, 0x61, 0x6e, 0x63, 0x68, 0x22, 0x53, 0x0a, 0x06, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x12,
0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e,
0x61, 0x6d, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x73, 0x68, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09,
0x52, 0x03, 0x73, 0x68, 0x61, 0x12, 0x23, 0x0a, 0x06, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x18,
0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0b, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x6f, 0x6d, 0x6d,
0x69, 0x74, 0x52, 0x06, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x22, 0xba, 0x02, 0x0a, 0x15, 0x4c,
0x69, 0x73, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x54, 0x61, 0x67, 0x73, 0x52, 0x65, 0x71,
0x75, 0x65, 0x73, 0x74, 0x12, 0x24, 0x0a, 0x04, 0x62, 0x61, 0x73, 0x65, 0x18, 0x01, 0x20, 0x01,
0x28, 0x0b, 0x32, 0x10, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x52, 0x65, 0x61, 0x64, 0x52, 0x65, 0x71,
0x75, 0x65, 0x73, 0x74, 0x52, 0x04, 0x62, 0x61, 0x73, 0x65, 0x12, 0x25, 0x0a, 0x0e, 0x69, 0x6e,
0x63, 0x6c, 0x75, 0x64, 0x65, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x18, 0x02, 0x20, 0x01,
0x28, 0x08, 0x52, 0x0d, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x43, 0x6f, 0x6d, 0x6d, 0x69,
0x74, 0x12, 0x14, 0x0a, 0x05, 0x71, 0x75, 0x65, 0x72, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09,
0x52, 0x05, 0x71, 0x75, 0x65, 0x72, 0x79, 0x12, 0x39, 0x0a, 0x04, 0x73, 0x6f, 0x72, 0x74, 0x18,
0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x25, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74,
0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x54, 0x61, 0x67, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
0x74, 0x2e, 0x53, 0x6f, 0x72, 0x74, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x04, 0x73, 0x6f,
0x72, 0x74, 0x12, 0x24, 0x0a, 0x05, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x18, 0x05, 0x20, 0x01, 0x28,
0x0e, 0x32, 0x0e, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x6f, 0x72, 0x74, 0x4f, 0x72, 0x64, 0x65,
0x72, 0x52, 0x05, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x67, 0x65,
0x18, 0x06, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x70, 0x61, 0x67, 0x65, 0x12, 0x1a, 0x0a, 0x08,
0x70, 0x61, 0x67, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08,
0x70, 0x61, 0x67, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x22, 0x2d, 0x0a, 0x0a, 0x53, 0x6f, 0x72, 0x74,
0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x0b, 0x0a, 0x07, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c,
0x74, 0x10, 0x00, 0x12, 0x08, 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x10, 0x01, 0x12, 0x08, 0x0a,
0x04, 0x44, 0x61, 0x74, 0x65, 0x10, 0x02, 0x22, 0x3a, 0x0a, 0x16, 0x4c, 0x69, 0x73, 0x74, 0x43,
0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x54, 0x61, 0x67, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
0x65, 0x12, 0x20, 0x0a, 0x03, 0x74, 0x61, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e,
0x2e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x54, 0x61, 0x67, 0x52, 0x03,
0x74, 0x61, 0x67, 0x22, 0xd1, 0x01, 0x0a, 0x09, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x54, 0x61,
0x67, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x73, 0x68, 0x61, 0x18, 0x02, 0x20, 0x01,
0x28, 0x09, 0x52, 0x03, 0x73, 0x68, 0x61, 0x12, 0x21, 0x0a, 0x0c, 0x69, 0x73, 0x5f, 0x61, 0x6e,
0x6e, 0x6f, 0x74, 0x61, 0x74, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x69,
0x73, 0x41, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x65, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x69,
0x74, 0x6c, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x74, 0x69, 0x74, 0x6c, 0x65,
0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28,
0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x26, 0x0a, 0x06, 0x74, 0x61,
0x67, 0x67, 0x65, 0x72, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x72, 0x70, 0x63,
0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x06, 0x74, 0x61, 0x67, 0x67,
0x65, 0x72, 0x12, 0x23, 0x0a, 0x06, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x18, 0x07, 0x20, 0x01,
0x28, 0x0b, 0x32, 0x0b, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x52,
0x06, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x22, 0x79, 0x0a, 0x0d, 0x47, 0x65, 0x74, 0x52, 0x65,
0x66, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x24, 0x0a, 0x04, 0x62, 0x61, 0x73, 0x65,
0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x52, 0x65, 0x61,
0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x52, 0x04, 0x62, 0x61, 0x73, 0x65, 0x12, 0x19,
0x0a, 0x08, 0x72, 0x65, 0x66, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09,
0x52, 0x07, 0x72, 0x65, 0x66, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x27, 0x0a, 0x08, 0x72, 0x65, 0x66,
0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x0c, 0x2e, 0x72, 0x70,
0x63, 0x2e, 0x52, 0x65, 0x66, 0x54, 0x79, 0x70, 0x65, 0x52, 0x07, 0x72, 0x65, 0x66, 0x54, 0x79,
0x70, 0x65, 0x22, 0x22, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x52, 0x65, 0x66, 0x52, 0x65, 0x73, 0x70,
0x6f, 0x6e, 0x73, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x73, 0x68, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28,
0x09, 0x52, 0x03, 0x73, 0x68, 0x61, 0x22, 0xb7, 0x01, 0x0a, 0x10, 0x55, 0x70, 0x64, 0x61, 0x74,
0x65, 0x52, 0x65, 0x66, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x25, 0x0a, 0x04, 0x62,
0x61, 0x73, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x72, 0x70, 0x63, 0x2e,
0x57, 0x72, 0x69, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x52, 0x04, 0x62, 0x61,
0x73, 0x65, 0x12, 0x19, 0x0a, 0x08, 0x72, 0x65, 0x66, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02,
0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x72, 0x65, 0x66, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x27, 0x0a,
0x08, 0x72, 0x65, 0x66, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32,
0x0c, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x52, 0x65, 0x66, 0x54, 0x79, 0x70, 0x65, 0x52, 0x07, 0x72,
0x65, 0x66, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x6e, 0x65, 0x77, 0x5f, 0x76, 0x61,
0x6c, 0x75, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6e, 0x65, 0x77, 0x56, 0x61,
0x6c, 0x75, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x6f, 0x6c, 0x64, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65,
0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6f, 0x6c, 0x64, 0x56, 0x61, 0x6c, 0x75, 0x65,
0x22, 0x13, 0x0a, 0x11, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x66, 0x52, 0x65, 0x73,
0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0xe5, 0x04, 0x0a, 0x10, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65,
0x6e, 0x63, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x43, 0x0a, 0x0c, 0x43, 0x72,
0x65, 0x61, 0x74, 0x65, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x12, 0x18, 0x2e, 0x72, 0x70, 0x63,
0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x52, 0x65, 0x71,
0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74,
0x65, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12,
0x3a, 0x0a, 0x09, 0x47, 0x65, 0x74, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x12, 0x15, 0x2e, 0x72,
0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75,
0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x42, 0x72, 0x61,
0x6e, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x43, 0x0a, 0x0c, 0x44,
0x65, 0x6c, 0x65, 0x74, 0x65, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x12, 0x18, 0x2e, 0x72, 0x70,
0x63, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x52, 0x65,
0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x44, 0x65, 0x6c, 0x65,
0x74, 0x65, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
0x12, 0x45, 0x0a, 0x0c, 0x4c, 0x69, 0x73, 0x74, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x65, 0x73,
0x12, 0x18, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x42, 0x72, 0x61, 0x6e, 0x63,
0x68, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x72, 0x70, 0x63,
0x2e, 0x4c, 0x69, 0x73, 0x74, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x65, 0x73, 0x52, 0x65, 0x73,
0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x4b, 0x0a, 0x0e, 0x4c, 0x69, 0x73, 0x74, 0x43,
0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x54, 0x61, 0x67, 0x73, 0x12, 0x1a, 0x2e, 0x72, 0x70, 0x63, 0x2e,
0x4c, 0x69, 0x73, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x54, 0x61, 0x67, 0x73, 0x52, 0x65,
0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74,
0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x54, 0x61, 0x67, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
0x73, 0x65, 0x30, 0x01, 0x12, 0x4c, 0x0a, 0x0f, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x43, 0x6f,
0x6d, 0x6d, 0x69, 0x74, 0x54, 0x61, 0x67, 0x12, 0x1b, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x72,
0x65, 0x61, 0x74, 0x65, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x54, 0x61, 0x67, 0x52, 0x65, 0x71,
0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74,
0x65, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x54, 0x61, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
0x73, 0x65, 0x12, 0x3a, 0x0a, 0x09, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x54, 0x61, 0x67, 0x12,
0x15, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x54, 0x61, 0x67, 0x52,
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x55, 0x70, 0x64,
0x61, 0x74, 0x65, 0x52, 0x65, 0x66, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x31,
0x0a, 0x06, 0x47, 0x65, 0x74, 0x52, 0x65, 0x66, 0x12, 0x12, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x47,
0x65, 0x74, 0x52, 0x65, 0x66, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x13, 0x2e, 0x72,
0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x65, 0x66, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
0x65, 0x12, 0x3a, 0x0a, 0x09, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x66, 0x12, 0x15,
0x2e, 0x72, 0x70, 0x63, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x66, 0x52, 0x65,
0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x55, 0x70, 0x64, 0x61,
0x74, 0x65, 0x52, 0x65, 0x66, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x27, 0x5a,
0x25, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x72, 0x6e,
0x65, 0x73, 0x73, 0x2f, 0x67, 0x69, 0x74, 0x6e, 0x65, 0x73, 0x73, 0x2f, 0x67, 0x69, 0x74, 0x72,
0x70, 0x63, 0x2f, 0x72, 0x70, 0x63, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
@ -1483,8 +1505,8 @@ var file_ref_proto_msgTypes = make([]protoimpl.MessageInfo, 19)
var file_ref_proto_goTypes = []interface{}{
(ListBranchesRequest_SortOption)(0), // 0: rpc.ListBranchesRequest.SortOption
(ListCommitTagsRequest_SortOption)(0), // 1: rpc.ListCommitTagsRequest.SortOption
(*CreateTagRequest)(nil), // 2: rpc.CreateTagRequest
(*CreateTagResponse)(nil), // 3: rpc.CreateTagResponse
(*CreateCommitTagRequest)(nil), // 2: rpc.CreateCommitTagRequest
(*CreateCommitTagResponse)(nil), // 3: rpc.CreateCommitTagResponse
(*DeleteTagRequest)(nil), // 4: rpc.DeleteTagRequest
(*CreateBranchRequest)(nil), // 5: rpc.CreateBranchRequest
(*CreateBranchResponse)(nil), // 6: rpc.CreateBranchResponse
@ -1503,59 +1525,61 @@ var file_ref_proto_goTypes = []interface{}{
(*UpdateRefRequest)(nil), // 19: rpc.UpdateRefRequest
(*UpdateRefResponse)(nil), // 20: rpc.UpdateRefResponse
(*WriteRequest)(nil), // 21: rpc.WriteRequest
(*ReadRequest)(nil), // 22: rpc.ReadRequest
(SortOrder)(0), // 23: rpc.SortOrder
(*Commit)(nil), // 24: rpc.Commit
(*Signature)(nil), // 25: rpc.Signature
(RefType)(0), // 26: rpc.RefType
(*Identity)(nil), // 22: rpc.Identity
(*ReadRequest)(nil), // 23: rpc.ReadRequest
(SortOrder)(0), // 24: rpc.SortOrder
(*Commit)(nil), // 25: rpc.Commit
(*Signature)(nil), // 26: rpc.Signature
(RefType)(0), // 27: rpc.RefType
}
var file_ref_proto_depIdxs = []int32{
21, // 0: rpc.CreateTagRequest.base:type_name -> rpc.WriteRequest
16, // 1: rpc.CreateTagResponse.tag:type_name -> rpc.CommitTag
21, // 2: rpc.DeleteTagRequest.base:type_name -> rpc.WriteRequest
21, // 3: rpc.CreateBranchRequest.base:type_name -> rpc.WriteRequest
13, // 4: rpc.CreateBranchResponse.branch:type_name -> rpc.Branch
22, // 5: rpc.GetBranchRequest.base:type_name -> rpc.ReadRequest
13, // 6: rpc.GetBranchResponse.branch:type_name -> rpc.Branch
21, // 7: rpc.DeleteBranchRequest.base:type_name -> rpc.WriteRequest
22, // 8: rpc.ListBranchesRequest.base:type_name -> rpc.ReadRequest
0, // 9: rpc.ListBranchesRequest.sort:type_name -> rpc.ListBranchesRequest.SortOption
23, // 10: rpc.ListBranchesRequest.order:type_name -> rpc.SortOrder
13, // 11: rpc.ListBranchesResponse.branch:type_name -> rpc.Branch
24, // 12: rpc.Branch.commit:type_name -> rpc.Commit
22, // 13: rpc.ListCommitTagsRequest.base:type_name -> rpc.ReadRequest
1, // 14: rpc.ListCommitTagsRequest.sort:type_name -> rpc.ListCommitTagsRequest.SortOption
23, // 15: rpc.ListCommitTagsRequest.order:type_name -> rpc.SortOrder
16, // 16: rpc.ListCommitTagsResponse.tag:type_name -> rpc.CommitTag
25, // 17: rpc.CommitTag.tagger:type_name -> rpc.Signature
24, // 18: rpc.CommitTag.commit:type_name -> rpc.Commit
22, // 19: rpc.GetRefRequest.base:type_name -> rpc.ReadRequest
26, // 20: rpc.GetRefRequest.ref_type:type_name -> rpc.RefType
21, // 21: rpc.UpdateRefRequest.base:type_name -> rpc.WriteRequest
26, // 22: rpc.UpdateRefRequest.ref_type:type_name -> rpc.RefType
5, // 23: rpc.ReferenceService.CreateBranch:input_type -> rpc.CreateBranchRequest
7, // 24: rpc.ReferenceService.GetBranch:input_type -> rpc.GetBranchRequest
9, // 25: rpc.ReferenceService.DeleteBranch:input_type -> rpc.DeleteBranchRequest
11, // 26: rpc.ReferenceService.ListBranches:input_type -> rpc.ListBranchesRequest
14, // 27: rpc.ReferenceService.ListCommitTags:input_type -> rpc.ListCommitTagsRequest
2, // 28: rpc.ReferenceService.CreateTag:input_type -> rpc.CreateTagRequest
4, // 29: rpc.ReferenceService.DeleteTag:input_type -> rpc.DeleteTagRequest
17, // 30: rpc.ReferenceService.GetRef:input_type -> rpc.GetRefRequest
19, // 31: rpc.ReferenceService.UpdateRef:input_type -> rpc.UpdateRefRequest
6, // 32: rpc.ReferenceService.CreateBranch:output_type -> rpc.CreateBranchResponse
8, // 33: rpc.ReferenceService.GetBranch:output_type -> rpc.GetBranchResponse
10, // 34: rpc.ReferenceService.DeleteBranch:output_type -> rpc.DeleteBranchResponse
12, // 35: rpc.ReferenceService.ListBranches:output_type -> rpc.ListBranchesResponse
15, // 36: rpc.ReferenceService.ListCommitTags:output_type -> rpc.ListCommitTagsResponse
3, // 37: rpc.ReferenceService.CreateTag:output_type -> rpc.CreateTagResponse
20, // 38: rpc.ReferenceService.DeleteTag:output_type -> rpc.UpdateRefResponse
18, // 39: rpc.ReferenceService.GetRef:output_type -> rpc.GetRefResponse
20, // 40: rpc.ReferenceService.UpdateRef:output_type -> rpc.UpdateRefResponse
32, // [32:41] is the sub-list for method output_type
23, // [23:32] is the sub-list for method input_type
23, // [23:23] is the sub-list for extension type_name
23, // [23:23] is the sub-list for extension extendee
0, // [0:23] is the sub-list for field type_name
21, // 0: rpc.CreateCommitTagRequest.base:type_name -> rpc.WriteRequest
22, // 1: rpc.CreateCommitTagRequest.tagger:type_name -> rpc.Identity
16, // 2: rpc.CreateCommitTagResponse.tag:type_name -> rpc.CommitTag
21, // 3: rpc.DeleteTagRequest.base:type_name -> rpc.WriteRequest
21, // 4: rpc.CreateBranchRequest.base:type_name -> rpc.WriteRequest
13, // 5: rpc.CreateBranchResponse.branch:type_name -> rpc.Branch
23, // 6: rpc.GetBranchRequest.base:type_name -> rpc.ReadRequest
13, // 7: rpc.GetBranchResponse.branch:type_name -> rpc.Branch
21, // 8: rpc.DeleteBranchRequest.base:type_name -> rpc.WriteRequest
23, // 9: rpc.ListBranchesRequest.base:type_name -> rpc.ReadRequest
0, // 10: rpc.ListBranchesRequest.sort:type_name -> rpc.ListBranchesRequest.SortOption
24, // 11: rpc.ListBranchesRequest.order:type_name -> rpc.SortOrder
13, // 12: rpc.ListBranchesResponse.branch:type_name -> rpc.Branch
25, // 13: rpc.Branch.commit:type_name -> rpc.Commit
23, // 14: rpc.ListCommitTagsRequest.base:type_name -> rpc.ReadRequest
1, // 15: rpc.ListCommitTagsRequest.sort:type_name -> rpc.ListCommitTagsRequest.SortOption
24, // 16: rpc.ListCommitTagsRequest.order:type_name -> rpc.SortOrder
16, // 17: rpc.ListCommitTagsResponse.tag:type_name -> rpc.CommitTag
26, // 18: rpc.CommitTag.tagger:type_name -> rpc.Signature
25, // 19: rpc.CommitTag.commit:type_name -> rpc.Commit
23, // 20: rpc.GetRefRequest.base:type_name -> rpc.ReadRequest
27, // 21: rpc.GetRefRequest.ref_type:type_name -> rpc.RefType
21, // 22: rpc.UpdateRefRequest.base:type_name -> rpc.WriteRequest
27, // 23: rpc.UpdateRefRequest.ref_type:type_name -> rpc.RefType
5, // 24: rpc.ReferenceService.CreateBranch:input_type -> rpc.CreateBranchRequest
7, // 25: rpc.ReferenceService.GetBranch:input_type -> rpc.GetBranchRequest
9, // 26: rpc.ReferenceService.DeleteBranch:input_type -> rpc.DeleteBranchRequest
11, // 27: rpc.ReferenceService.ListBranches:input_type -> rpc.ListBranchesRequest
14, // 28: rpc.ReferenceService.ListCommitTags:input_type -> rpc.ListCommitTagsRequest
2, // 29: rpc.ReferenceService.CreateCommitTag:input_type -> rpc.CreateCommitTagRequest
4, // 30: rpc.ReferenceService.DeleteTag:input_type -> rpc.DeleteTagRequest
17, // 31: rpc.ReferenceService.GetRef:input_type -> rpc.GetRefRequest
19, // 32: rpc.ReferenceService.UpdateRef:input_type -> rpc.UpdateRefRequest
6, // 33: rpc.ReferenceService.CreateBranch:output_type -> rpc.CreateBranchResponse
8, // 34: rpc.ReferenceService.GetBranch:output_type -> rpc.GetBranchResponse
10, // 35: rpc.ReferenceService.DeleteBranch:output_type -> rpc.DeleteBranchResponse
12, // 36: rpc.ReferenceService.ListBranches:output_type -> rpc.ListBranchesResponse
15, // 37: rpc.ReferenceService.ListCommitTags:output_type -> rpc.ListCommitTagsResponse
3, // 38: rpc.ReferenceService.CreateCommitTag:output_type -> rpc.CreateCommitTagResponse
20, // 39: rpc.ReferenceService.DeleteTag:output_type -> rpc.UpdateRefResponse
18, // 40: rpc.ReferenceService.GetRef:output_type -> rpc.GetRefResponse
20, // 41: rpc.ReferenceService.UpdateRef:output_type -> rpc.UpdateRefResponse
33, // [33:42] is the sub-list for method output_type
24, // [24:33] is the sub-list for method input_type
24, // [24:24] is the sub-list for extension type_name
24, // [24:24] is the sub-list for extension extendee
0, // [0:24] is the sub-list for field type_name
}
func init() { file_ref_proto_init() }
@ -1566,7 +1590,7 @@ func file_ref_proto_init() {
file_shared_proto_init()
if !protoimpl.UnsafeEnabled {
file_ref_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*CreateTagRequest); i {
switch v := v.(*CreateCommitTagRequest); i {
case 0:
return &v.state
case 1:
@ -1578,7 +1602,7 @@ func file_ref_proto_init() {
}
}
file_ref_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*CreateTagResponse); i {
switch v := v.(*CreateCommitTagResponse); i {
case 0:
return &v.state
case 1:

View File

@ -27,7 +27,7 @@ type ReferenceServiceClient interface {
DeleteBranch(ctx context.Context, in *DeleteBranchRequest, opts ...grpc.CallOption) (*DeleteBranchResponse, error)
ListBranches(ctx context.Context, in *ListBranchesRequest, opts ...grpc.CallOption) (ReferenceService_ListBranchesClient, error)
ListCommitTags(ctx context.Context, in *ListCommitTagsRequest, opts ...grpc.CallOption) (ReferenceService_ListCommitTagsClient, error)
CreateTag(ctx context.Context, in *CreateTagRequest, opts ...grpc.CallOption) (*CreateTagResponse, error)
CreateCommitTag(ctx context.Context, in *CreateCommitTagRequest, opts ...grpc.CallOption) (*CreateCommitTagResponse, error)
DeleteTag(ctx context.Context, in *DeleteTagRequest, opts ...grpc.CallOption) (*UpdateRefResponse, error)
GetRef(ctx context.Context, in *GetRefRequest, opts ...grpc.CallOption) (*GetRefResponse, error)
UpdateRef(ctx context.Context, in *UpdateRefRequest, opts ...grpc.CallOption) (*UpdateRefResponse, error)
@ -132,9 +132,9 @@ func (x *referenceServiceListCommitTagsClient) Recv() (*ListCommitTagsResponse,
return m, nil
}
func (c *referenceServiceClient) CreateTag(ctx context.Context, in *CreateTagRequest, opts ...grpc.CallOption) (*CreateTagResponse, error) {
out := new(CreateTagResponse)
err := c.cc.Invoke(ctx, "/rpc.ReferenceService/CreateTag", in, out, opts...)
func (c *referenceServiceClient) CreateCommitTag(ctx context.Context, in *CreateCommitTagRequest, opts ...grpc.CallOption) (*CreateCommitTagResponse, error) {
out := new(CreateCommitTagResponse)
err := c.cc.Invoke(ctx, "/rpc.ReferenceService/CreateCommitTag", in, out, opts...)
if err != nil {
return nil, err
}
@ -177,7 +177,7 @@ type ReferenceServiceServer interface {
DeleteBranch(context.Context, *DeleteBranchRequest) (*DeleteBranchResponse, error)
ListBranches(*ListBranchesRequest, ReferenceService_ListBranchesServer) error
ListCommitTags(*ListCommitTagsRequest, ReferenceService_ListCommitTagsServer) error
CreateTag(context.Context, *CreateTagRequest) (*CreateTagResponse, error)
CreateCommitTag(context.Context, *CreateCommitTagRequest) (*CreateCommitTagResponse, error)
DeleteTag(context.Context, *DeleteTagRequest) (*UpdateRefResponse, error)
GetRef(context.Context, *GetRefRequest) (*GetRefResponse, error)
UpdateRef(context.Context, *UpdateRefRequest) (*UpdateRefResponse, error)
@ -203,8 +203,8 @@ func (UnimplementedReferenceServiceServer) ListBranches(*ListBranchesRequest, Re
func (UnimplementedReferenceServiceServer) ListCommitTags(*ListCommitTagsRequest, ReferenceService_ListCommitTagsServer) error {
return status.Errorf(codes.Unimplemented, "method ListCommitTags not implemented")
}
func (UnimplementedReferenceServiceServer) CreateTag(context.Context, *CreateTagRequest) (*CreateTagResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method CreateTag not implemented")
func (UnimplementedReferenceServiceServer) CreateCommitTag(context.Context, *CreateCommitTagRequest) (*CreateCommitTagResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method CreateCommitTag not implemented")
}
func (UnimplementedReferenceServiceServer) DeleteTag(context.Context, *DeleteTagRequest) (*UpdateRefResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method DeleteTag not implemented")
@ -324,20 +324,20 @@ func (x *referenceServiceListCommitTagsServer) Send(m *ListCommitTagsResponse) e
return x.ServerStream.SendMsg(m)
}
func _ReferenceService_CreateTag_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(CreateTagRequest)
func _ReferenceService_CreateCommitTag_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(CreateCommitTagRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(ReferenceServiceServer).CreateTag(ctx, in)
return srv.(ReferenceServiceServer).CreateCommitTag(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/rpc.ReferenceService/CreateTag",
FullMethod: "/rpc.ReferenceService/CreateCommitTag",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(ReferenceServiceServer).CreateTag(ctx, req.(*CreateTagRequest))
return srv.(ReferenceServiceServer).CreateCommitTag(ctx, req.(*CreateCommitTagRequest))
}
return interceptor(ctx, in, info, handler)
}
@ -416,8 +416,8 @@ var ReferenceService_ServiceDesc = grpc.ServiceDesc{
Handler: _ReferenceService_DeleteBranch_Handler,
},
{
MethodName: "CreateTag",
Handler: _ReferenceService_CreateTag_Handler,
MethodName: "CreateCommitTag",
Handler: _ReferenceService_CreateCommitTag_Handler,
},
{
MethodName: "DeleteTag",

View File

@ -216,6 +216,7 @@ type CreateRepositoryRequest struct {
unknownFields protoimpl.UnknownFields
// Types that are assignable to Data:
//
// *CreateRepositoryRequest_Header
// *CreateRepositoryRequest_File
Data isCreateRepositoryRequest_Data `protobuf_oneof:"data"`
@ -1162,6 +1163,7 @@ type GetBlobResponse struct {
unknownFields protoimpl.UnknownFields
// Types that are assignable to Data:
//
// *GetBlobResponse_Header
// *GetBlobResponse_Content
Data isGetBlobResponse_Data `protobuf_oneof:"data"`

View File

@ -298,6 +298,7 @@ type FileUpload struct {
unknownFields protoimpl.UnknownFields
// Types that are assignable to Data:
//
// *FileUpload_Header
// *FileUpload_Chunk
Data isFileUpload_Data `protobuf_oneof:"data"`

View File

@ -6,6 +6,7 @@ package server
import (
"errors"
"time"
)
// Config represents the configuration for the gitrpc server.
@ -22,6 +23,8 @@ type Config struct {
HTTP struct {
Bind string `envconfig:"GITRPC_SERVER_HTTP_BIND" default:":4001"`
}
MaxConnAge time.Duration `envconfig:"GITRPC_SERVER_MAX_CONN_AGE" default:"630720000s"`
MaxConnAgeGrace time.Duration `envconfig:"GITRPC_SERVER_MAX_CONN_AGE_GRACE" default:"630720000s"`
}
func (c *Config) Validate() error {
@ -37,6 +40,12 @@ func (c *Config) Validate() error {
if c.GitHookPath == "" {
return errors.New("config.GitHookPath is required")
}
if c.MaxConnAge == 0 {
return errors.New("config.MaxConnAge is required")
}
if c.MaxConnAgeGrace == 0 {
return errors.New("config.MaxConnAgeGrace is required")
}
return nil
}

View File

@ -19,6 +19,7 @@ import (
grpc_middleware "github.com/grpc-ecosystem/go-grpc-middleware"
grpc_recovery "github.com/grpc-ecosystem/go-grpc-middleware/recovery"
"google.golang.org/grpc"
"google.golang.org/grpc/keepalive"
)
const (
@ -58,6 +59,10 @@ func NewServer(config Config, adapter service.GitAdapter) (*GRPCServer, error) {
logIntc.StreamInterceptor(),
errIntc.StreamInterceptor(),
)),
grpc.KeepaliveParams(keepalive.ServerParameters{
MaxConnectionAge: config.MaxConnAge,
MaxConnectionAgeGrace: config.MaxConnAgeGrace,
}),
)
store := storage.NewLocalStore()
// create a temp dir for deleted repositories

View File

@ -9,6 +9,7 @@ import (
"errors"
"fmt"
"io"
"time"
"github.com/harness/gitness/gitrpc/rpc"
@ -47,14 +48,26 @@ type CommitTag struct {
Commit *Commit
}
type CreateTagParams struct {
type CreateCommitTagParams struct {
WriteParams
Name string
SHA string
Name string
// Target is the commit (or points to the commit) the new tag will be pointing to.
Target string
// Message is the optional message the tag will be created with - if the message is empty
// the tag will be lightweight, otherwise it'll be annotated
Message string
// Tagger overwrites the git author used in case the tag is annotated
// (optional, default: actor)
Tagger *Identity
// TaggerDate overwrites the git author date used in case the tag is annotated
// (optional, default: current time on server)
TaggerDate *time.Time
}
func (p *CreateTagParams) Validate() error {
func (p *CreateCommitTagParams) Validate() error {
if p == nil {
return ErrNoParamsProvided
}
@ -62,16 +75,14 @@ func (p *CreateTagParams) Validate() error {
if p.Name == "" {
return errors.New("tag name cannot be empty")
}
if p.SHA == "" {
if p.Target == "" {
return errors.New("target cannot be empty")
}
if p.Message == "" {
return errors.New("message cannot be empty")
}
return nil
}
type CreateTagOutput struct {
type CreateCommitTagOutput struct {
CommitTag
}
@ -139,18 +150,20 @@ func (c *Client) ListCommitTags(ctx context.Context, params *ListCommitTagsParam
return output, nil
}
func (c *Client) CreateTag(ctx context.Context, params *CreateTagParams) (*CreateTagOutput, error) {
func (c *Client) CreateCommitTag(ctx context.Context, params *CreateCommitTagParams) (*CreateCommitTagOutput, error) {
err := params.Validate()
if err != nil {
return nil, err
}
resp, err := c.refService.CreateTag(ctx, &rpc.CreateTagRequest{
Base: mapToRPCWriteRequest(params.WriteParams),
Sha: params.SHA,
TagName: params.Name,
Message: params.Message,
resp, err := c.refService.CreateCommitTag(ctx, &rpc.CreateCommitTagRequest{
Base: mapToRPCWriteRequest(params.WriteParams),
Target: params.Target,
TagName: params.Name,
Message: params.Message,
Tagger: mapToRPCIdentityOptional(params.Tagger),
TaggerDate: mapToRPCTimeOptional(params.TaggerDate),
})
if err != nil {
@ -163,7 +176,7 @@ func (c *Client) CreateTag(ctx context.Context, params *CreateTagParams) (*Creat
return nil, fmt.Errorf("failed to map rpc tag: %w", err)
}
return &CreateTagOutput{
return &CreateCommitTagOutput{
CommitTag: *commitTag,
}, nil
}

44
go.mod
View File

@ -36,6 +36,7 @@ require (
github.com/robfig/cron/v3 v3.0.0
github.com/rs/xid v1.4.0
github.com/rs/zerolog v1.29.0
github.com/sercand/kuberesolver/v5 v5.1.0
github.com/stretchr/testify v1.8.1
github.com/swaggest/openapi-go v0.2.23
github.com/swaggest/swgui v1.4.2
@ -44,23 +45,30 @@ require (
golang.org/x/crypto v0.1.0
golang.org/x/exp v0.0.0-20230108222341-4b8118a2686a
golang.org/x/sync v0.1.0
golang.org/x/term v0.2.0
golang.org/x/text v0.4.0
google.golang.org/grpc v1.50.1
google.golang.org/protobuf v1.28.1
golang.org/x/term v0.6.0
golang.org/x/text v0.8.0
google.golang.org/grpc v1.55.0
google.golang.org/protobuf v1.30.0
gopkg.in/alecthomas/kingpin.v2 v2.2.6
)
require (
cloud.google.com/go v0.105.0 // indirect
cloud.google.com/go/compute v1.12.1 // indirect
cloud.google.com/go/compute/metadata v0.2.1 // indirect
cloud.google.com/go v0.110.0 // indirect
cloud.google.com/go/compute v1.18.0 // indirect
cloud.google.com/go/compute/metadata v0.2.3 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/fsnotify/fsnotify v1.6.0 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/googleapis/enterprise-certificate-proxy v0.2.0 // indirect
github.com/googleapis/enterprise-certificate-proxy v0.2.3 // indirect
github.com/googleapis/gax-go/v2 v2.7.0 // indirect
go.opencensus.io v0.23.0 // indirect
golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783 // indirect
google.golang.org/api v0.102.0 // indirect
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
github.com/prometheus/client_golang v1.15.1 // indirect
github.com/prometheus/client_model v0.3.0 // indirect
github.com/prometheus/common v0.42.0 // indirect
github.com/prometheus/procfs v0.9.0 // indirect
go.opencensus.io v0.24.0 // indirect
golang.org/x/oauth2 v0.6.0 // indirect
google.golang.org/api v0.110.0 // indirect
google.golang.org/appengine v1.6.7 // indirect
)
@ -77,8 +85,8 @@ require (
github.com/ProtonMail/go-crypto v0.0.0-20220407094043-a94812496cf5 // indirect
github.com/acomagu/bufpipe v1.0.3 // indirect
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 // indirect
github.com/alecthomas/units v0.0.0-20210208195552-ff826a37aa15 // indirect
github.com/cespare/xxhash/v2 v2.1.2 // indirect
github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 // indirect
github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
github.com/djherbis/buffer v1.2.0 // indirect
@ -91,7 +99,7 @@ require (
github.com/go-git/go-git/v5 v5.4.3-0.20210630082519-b4368b2a2ca4 // indirect
github.com/gobwas/glob v0.2.3 // indirect
github.com/golang-jwt/jwt/v4 v4.4.1 // indirect
github.com/golang/protobuf v1.5.2 // indirect
github.com/golang/protobuf v1.5.3 // indirect
github.com/google/pprof v0.0.0-20221103000818-d260c55eee4c // indirect
github.com/google/subcommands v1.0.1 // indirect
github.com/hashicorp/errwrap v1.0.0 // indirect
@ -115,11 +123,11 @@ require (
github.com/xanzy/ssh-agent v0.3.1 // indirect
github.com/yuin/goldmark v1.4.13 // indirect
go.uber.org/atomic v1.10.0 // indirect
golang.org/x/mod v0.6.0 // indirect
golang.org/x/net v0.2.0 // indirect
golang.org/x/mod v0.8.0 // indirect
golang.org/x/net v0.8.0 // indirect
golang.org/x/sys v0.6.0 // indirect
golang.org/x/tools v0.2.0 // indirect
google.golang.org/genproto v0.0.0-20221024183307-1bc688fe9f3e // indirect
golang.org/x/tools v0.6.0 // indirect
google.golang.org/genproto v0.0.0-20230306155012-7f2fa6fef1f4 // indirect
gopkg.in/ini.v1 v1.66.4 // indirect
gopkg.in/warnings.v0 v0.1.2 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect

127
go.sum
View File

@ -1,13 +1,16 @@
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.105.0 h1:DNtEKRBAAzeS4KyIory52wWHuClNaXJ5x1F7xa4q+5Y=
cloud.google.com/go v0.105.0/go.mod h1:PrLgOJNe5nfE9UMxKxgXj4mD3voiP+YQ6gdt6KMFOKM=
cloud.google.com/go/compute v1.12.1 h1:gKVJMEyqV5c/UnpzjjQbo3Rjvvqpr9B1DFSbJC4OXr0=
cloud.google.com/go/compute v1.12.1/go.mod h1:e8yNOBcBONZU1vJKCvCoDw/4JQsA0dpM4x/6PIIOocU=
cloud.google.com/go/compute/metadata v0.2.1 h1:efOwf5ymceDhK6PKMnnrTHP4pppY5L22mle96M1yP48=
cloud.google.com/go/compute/metadata v0.2.1/go.mod h1:jgHgmJd2RKBGzXqF5LR2EZMGxBkeanZ9wwa75XHJgOM=
cloud.google.com/go v0.110.0 h1:Zc8gqp3+a9/Eyph2KDmcGaPtbKRIoqq4YTlL4NMD0Ys=
cloud.google.com/go v0.110.0/go.mod h1:SJnCLqQ0FCFGSZMUNUf84MV3Aia54kn7pi8st7tMzaY=
cloud.google.com/go/compute v1.18.0 h1:FEigFqoDbys2cvFkZ9Fjq4gnHBP55anJ0yQyau2f9oY=
cloud.google.com/go/compute v1.18.0/go.mod h1:1X7yHxec2Ga+Ss6jPyjxRxpu2uu7PLgsOVXvgU0yacs=
cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY=
cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA=
cloud.google.com/go/iam v0.12.0 h1:DRtTY29b75ciH6Ov1PHb4/iat2CLCvrOm40Q0a6DFpE=
cloud.google.com/go/longrunning v0.4.1 h1:v+yFJOfKC3yZdY6ZUI933pIYdhyhV8S3NpWrXWmg7jM=
cloud.google.com/go/profiler v0.3.1 h1:b5got9Be9Ia0HVvyt7PavWxXEht15B9lWnigdvHtxOc=
cloud.google.com/go/profiler v0.3.1/go.mod h1:GsG14VnmcMFQ9b+kq71wh3EKMZr3WRMgLzNiFRpW7tE=
cloud.google.com/go/storage v1.28.1 h1:F5QDG5ChchaAVQhINh24U99OWHURqrW8OmQcGKXcbgI=
code.gitea.io/gitea v1.17.2 h1:NRcVr07jF+za4d0NZZlJXeCuQK5FfHMtjPDjq4u3UiY=
code.gitea.io/gitea v1.17.2/go.mod h1:sovminOoSsc8IC2T29rX9+MmaboHTu8QDEvJjaSqIXg=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
@ -20,7 +23,6 @@ github.com/Microsoft/go-winio v0.4.16/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugX
github.com/Microsoft/go-winio v0.5.0/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84=
github.com/Microsoft/go-winio v0.5.2 h1:a9IhgEQBCUEk6QCdml9CiJGhAws+YwffDHEMp1VMrpA=
github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY=
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7/go.mod h1:z4/9nQmJSSwwds7ejkxaJwO37dru3geImFUdJlaLzQo=
github.com/ProtonMail/go-crypto v0.0.0-20220407094043-a94812496cf5 h1:cSHEbLj0GZeHM1mWG84qEnGFojNEQ83W7cwaPRjcwXU=
github.com/ProtonMail/go-crypto v0.0.0-20220407094043-a94812496cf5/go.mod h1:z4/9nQmJSSwwds7ejkxaJwO37dru3geImFUdJlaLzQo=
@ -37,13 +39,12 @@ github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 h1:JYp7IbQjafo
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/alecthomas/units v0.0.0-20210208195552-ff826a37aa15 h1:AUNCr9CiJuwrRYS3XieqF+Z9B9gNxo/eANAJCF2eiN4=
github.com/alecthomas/units v0.0.0-20210208195552-ff826a37aa15/go.mod h1:OMCwj8VM1Kc9e19TLln2VL61YJF0x1XFtfdL4JdbSyE=
github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 h1:s6gZFSlWYmbqAuRjVTiNNhvNRfY2Wxp9nhfyel4rklc=
github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137/go.mod h1:OMCwj8VM1Kc9e19TLln2VL61YJF0x1XFtfdL4JdbSyE=
github.com/andybalholm/brotli v1.0.3/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
github.com/andybalholm/brotli v1.0.4 h1:V7DdXeJtZscaqfNuAdSRuRFzuiKlHSC/Zh3zl9qY3JY=
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c=
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8=
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
@ -57,6 +58,7 @@ github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN
github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
github.com/bool64/dev v0.1.41/go.mod h1:cTHiTDNc8EewrQPy3p1obNilpMpdmlUesDkFTF2zRWU=
@ -66,22 +68,16 @@ github.com/bool64/shared v0.1.5 h1:fp3eUhBsrSjNCQPcSdQqZxxh9bBwrYiZ+zOKFkM0/2E=
github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ=
github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE=
github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI=
github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ=
github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8=
github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI=
@ -124,9 +120,6 @@ github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4s
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ=
github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
@ -134,7 +127,8 @@ github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVB
github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
github.com/fsnotify/fsnotify v1.5.4 h1:jRbGcIw6P2Meqdwuo0H1p6JVLbL5DHKAKlYndzMwVZI=
github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=
github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
github.com/gliderlabs/ssh v0.3.4 h1:+AXBtim7MTKaLVPgvE+3mhewYRawNLTd+jEEz/wExZw=
@ -212,6 +206,7 @@ github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5y
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk=
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
@ -221,8 +216,9 @@ github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QD
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/gomodule/redigo v1.8.2 h1:H5XSIre1MB5NbPYFp+i1NBbb5qN1W8Y8YAQoAYbkm8k=
github.com/gomodule/redigo v1.8.2/go.mod h1:P9dn9mFrCBvWhGE1wpxx6fgq7BAeLBk+UUUzlpkBYO0=
@ -236,14 +232,11 @@ github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg=
github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20220509035851-59ca7ad80af3 h1:vFrXU7L2gqtlP/ZGijSpaDIc16ZQrZI4FAuYtpQTyQc=
github.com/google/pprof v0.0.0-20220509035851-59ca7ad80af3/go.mod h1:Pt31oes+eGImORns3McJn8zHefuQl2rG8l6xQjGYB4U=
github.com/google/pprof v0.0.0-20221103000818-d260c55eee4c h1:lvddKcYTQ545ADhBujtIJmqQrZBDsGo7XIMbAQe/sNY=
github.com/google/pprof v0.0.0-20221103000818-d260c55eee4c/go.mod h1:dDKJzRmX4S37WGHujM7tX//fmj1uioxKzKxz3lo4HJo=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
@ -251,10 +244,11 @@ github.com/google/subcommands v1.0.1 h1:/eqq+otEXm5vhfBrbREPCSVQbvofip6kIz+mX5TU
github.com/google/subcommands v1.0.1/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk=
github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
github.com/google/wire v0.5.0 h1:I7ELFeVBr3yfPIcc8+MWvrjk+3VjbcSzoXm3JVa+jD8=
github.com/google/wire v0.5.0/go.mod h1:ngWDr9Qvq3yZA10YrxfyGELY/AFWGVpy9c1LTRi1EoU=
github.com/googleapis/enterprise-certificate-proxy v0.2.0 h1:y8Yozv7SZtlU//QXbezB6QkpuE6jMD2/gfzk4AftXjs=
github.com/googleapis/enterprise-certificate-proxy v0.2.0/go.mod h1:8C0jb7/mgJe/9KK8Lm7X9ctZC2t60YyIpYEI16jx0Qg=
github.com/googleapis/enterprise-certificate-proxy v0.2.3 h1:yk9/cqRKtT9wXZSsRH9aurXEpJX+U6FLtpYTdC3R06k=
github.com/googleapis/enterprise-certificate-proxy v0.2.3/go.mod h1:AwSRAtLfXpU5Nm3pW+v7rGDHp09LsPtGY9MduiEsR9k=
github.com/googleapis/gax-go/v2 v2.7.0 h1:IcsPKeInNvYi7eqSaDjiZqDDKu5rsmunY0Y1YupQSSQ=
github.com/googleapis/gax-go/v2 v2.7.0/go.mod h1:TEop28CZZQ2y+c0VxMUmu1lV+fQx57QpBWsYpwqHJx8=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
@ -269,7 +263,6 @@ github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 h1:+9834+KizmvFV7pXQGSXQTsaW
github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y=
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
github.com/guregu/null v4.0.0+incompatible h1:4zw0ckM7ECd6FNNddc3Fu4aty9nTlpkkzH7dPn4/4Gw=
github.com/guregu/null v4.0.0+incompatible/go.mod h1:ePGpQaN9cw0tj45IR5E5ehMvsFlLlQZAkkOXZurJ3NM=
github.com/harness/go-rbac v0.0.0-20230409233212-ca97fe90aac8 h1:sQzaA/ithB9mCXTC5VeC4XTWmQ531Tefbgxr1X4y7WU=
@ -397,7 +390,7 @@ github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxv
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
@ -450,6 +443,8 @@ github.com/mattn/go-sqlite3 v1.14.7/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A
github.com/mattn/go-sqlite3 v1.14.12 h1:TJ1bhYJPV44phC+IMu1u2K/i5RriLTPe+yc68XDJ1Z0=
github.com/mattn/go-sqlite3 v1.14.12/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo=
github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
@ -527,23 +522,30 @@ github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXP
github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs=
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og=
github.com/prometheus/client_golang v1.15.1 h1:8tXpTmJbyH5lydzFPoxSIJ0J46jdh3tylbvM1xCv0LI=
github.com/prometheus/client_golang v1.15.1/go.mod h1:e9yaBhRPU2pPNsZwE+JdQl0KEt1N9XgF6zxWmaC0xOk=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.1.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.3.0 h1:UBgGFHqYdG/TPFD1B1ogZywDqEkwp3fBMvqdiQ7Xew4=
github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w=
github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA=
github.com/prometheus/common v0.42.0 h1:EKsfXEYo4JpWMHH5cg+KOUWeuJSov1Id8zGR8eeI1YM=
github.com/prometheus/common v0.42.0/go.mod h1:xBwqVerjNdUDjgODMpudtOMwlOwf2SaTr1yjz4b7Zbc=
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A=
github.com/prometheus/procfs v0.9.0 h1:wzCHvIvM5SxWqYvwgVL7yJY8Lz3PKn49KQtpgMYJfhI=
github.com/prometheus/procfs v0.9.0/go.mod h1:+pB4zwohETzFnmlpe6yd2lSc+0/46IYZRB/chUwxUZY=
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
github.com/robfig/cron/v3 v3.0.0 h1:kQ6Cb7aHOHTSzNVNEhmp8EcWKLb4CbiMW9h9VyIhO4E=
github.com/robfig/cron/v3 v3.0.0/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro=
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/rogpeppe/go-internal v1.8.1 h1:geMPLpDpQOgVyCg5z5GoRwLHepNdb71NXb67XFkP+Eg=
github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ=
@ -558,6 +560,8 @@ github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb
github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E=
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
github.com/sercand/kuberesolver/v5 v5.1.0 h1:YLqreB1vUFbZHSidcqI5ChMp+RIRmop0brQOeUFWiRw=
github.com/sercand/kuberesolver/v5 v5.1.0/go.mod h1:Fs1KbKhVRnB2aDWN12NjKCB+RgYMWZJ294T3BtmVCpQ=
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ=
github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
@ -576,7 +580,6 @@ github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
github.com/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY=
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw=
@ -636,9 +639,8 @@ go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mI
go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.23.0 h1:gqCw0LfLxScz8irSi8exQc7fyQ0fKQU/qnC/X8+V/1M=
go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E=
go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0=
go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo=
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
@ -690,8 +692,8 @@ golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY=
golang.org/x/mod v0.6.0 h1:b9gGHsz9/HhJ3HF5DHQytPpuwocVTChQJK3AvoLRD5I=
golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI=
golang.org/x/mod v0.8.0 h1:LUYupSeNrTNCGzR/hVBk2NHZO4hXcVaW1k4Qx7rjPx8=
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@ -711,7 +713,6 @@ golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLL
golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
@ -723,13 +724,12 @@ golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qx
golang.org/x/net v0.0.0-20211105192438-b53810dc28af/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/net v0.2.0 h1:sZfSu1wtKLGlWI4ZZayP0ck9Y73K1ynO6gqzTdBVdPU=
golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY=
golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ=
golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783 h1:nt+Q6cXKz4MosCSpnbMtqiQ8Oz0pxTef2B4Vca2lvfk=
golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg=
golang.org/x/oauth2 v0.6.0 h1:Lh8GPgSKBfWSwFvtuWOfeI3aAAnbXTSutYxJiOJFgIw=
golang.org/x/oauth2 v0.6.0/go.mod h1:ycmewcwgD4Rpr3eZJLSB4Kyyljb3qDh40vJ8STE5HKw=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@ -789,22 +789,22 @@ golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220422013727-9388b58f7150/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.2.0 h1:z85xZCsEl7bi/KwbNADeBYoOP0++7W1ipu+aGnpwzRM=
golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
golang.org/x/term v0.6.0 h1:clScbb1cHjoCkyRbWwBEUZ5H/tIFu5TAXIqaZD0Gcjw=
golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.4.0 h1:BrVqGRd7+k1DiOgtnFvAkoQEWQvBc25ouMJM6429SFg=
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68=
golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
@ -830,17 +830,18 @@ golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4f
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo=
golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E=
golang.org/x/tools v0.2.0 h1:G6AHpWxTMGY1KyEYoAQ5WTtIekUUvDNjan3ugu60JvE=
golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA=
golang.org/x/tools v0.6.0 h1:BOw41kyTf3PuCW1pVQf8+Cyg8pMlkYB1oo9iJ6D/lKM=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 h1:H2TDz8ibqkAF6YGhCdN3jS9O0/s90v0rJh3X/OLHEUk=
google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk=
google.golang.org/api v0.102.0 h1:JxJl2qQ85fRMPNvlZY/enexbxpCjLwGhZUtgfGeQ51I=
google.golang.org/api v0.102.0/go.mod h1:3VFl6/fzoA+qNuS1N1/VfXY4LjoXN/wzeIp7TweWwGo=
google.golang.org/api v0.110.0 h1:l+rh0KYUooe9JGbGVx71tbFo4SMbMTXK3I3ia2QSEeU=
google.golang.org/api v0.110.0/go.mod h1:7FC4Vvx1Mooxh8C5HWjzZHcavuS2f6pmJpZx60ca7iI=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
@ -852,12 +853,9 @@ google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRn
google.golang.org/genproto v0.0.0-20190530194941-fb225487d101/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s=
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa h1:I0YcKz0I7OAhddo7ya8kMnvprhcWM045PmkBdMO9zN0=
google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
google.golang.org/genproto v0.0.0-20221024183307-1bc688fe9f3e h1:S9GbmC1iCgvbLyAokVCwiO6tVIrU9Y7c5oMx1V/ki/Y=
google.golang.org/genproto v0.0.0-20221024183307-1bc688fe9f3e/go.mod h1:9qHF0xnpdSfF6knlcsnpzUu5y+rpwgbvsyGAZPBMg4s=
google.golang.org/genproto v0.0.0-20230306155012-7f2fa6fef1f4 h1:DdoeryqhaXp1LtT/emMP1BRJPHHKFi5akj/nbx/zNTA=
google.golang.org/genproto v0.0.0-20230306155012-7f2fa6fef1f4/go.mod h1:NWraEVixdDnqcqQ30jipen1STv2r/n24Wb7twVTGR4s=
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM=
@ -870,14 +868,9 @@ google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQ
google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0=
google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
google.golang.org/grpc v1.43.0 h1:Eeu7bZtDZ2DpRCsLhUlcrLnvYaMK1Gz86a+hMVvELmM=
google.golang.org/grpc v1.43.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU=
google.golang.org/grpc v1.50.1 h1:DS/BukOZWp8s6p4Dt/tOaJaTQyPyOoCcrjroHuCeLzY=
google.golang.org/grpc v1.50.1/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI=
google.golang.org/grpc v1.55.0 h1:3Oj82/tFSCeUrRTg/5E/7d/W5A1tj6Ky1ABAuZuv5ag=
google.golang.org/grpc v1.55.0/go.mod h1:iYEXKGkEBhg1PjZQvoYEVPTDkHo1/bjTnfwTeGONTY8=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
@ -889,10 +882,9 @@ google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpAD
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w=
google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng=
google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
gopkg.in/alecthomas/kingpin.v2 v2.2.6 h1:jMFz6MfLP0/4fUyZle81rXUoxOBFi19VUFKVDOQfozc=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
@ -916,7 +908,6 @@ gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRN
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=

View File

@ -25,13 +25,12 @@ var (
ErrParentResourceTypeUnknown = errors.New("Unknown parent resource type")
)
/*
* Check checks if a resource specific permission is granted for the current auth session in the scope.
* Returns nil if the permission is granted, otherwise returns an error.
* NotAuthenticated, NotAuthorized, or any unerlaying error.
*/
// Check checks if a resource specific permission is granted for the current auth session in the scope.
// Returns nil if the permission is granted, otherwise returns an error.
// NotAuthenticated, NotAuthorized, or any underlying error.
func Check(ctx context.Context, authorizer authz.Authorizer, session *auth.Session,
scope *types.Scope, resource *types.Resource, permission enum.Permission) error {
scope *types.Scope, resource *types.Resource, permission enum.Permission,
) error {
if session == nil {
return ErrNotAuthenticated
}
@ -53,12 +52,10 @@ func Check(ctx context.Context, authorizer authz.Authorizer, session *auth.Sessi
return nil
}
/*
* CheckChild checks if a resource specific permission is granted for the current auth session
* in the scope of a parent.
* Returns nil if the permission is granted, otherwise returns an error.
* NotAuthenticated, NotAuthorized, or any unerlaying error.
*/
// CheckChild checks if a resource specific permission is granted for the current auth session
// in the scope of a parent.
// Returns nil if the permission is granted, otherwise returns an error.
// NotAuthenticated, NotAuthorized, or any underlying error.
func CheckChild(ctx context.Context, authorizer authz.Authorizer, session *auth.Session,
spaceStore store.SpaceStore, repoStore store.RepoStore, parentType enum.ParentResourceType, parentID int64,
resourceType enum.ResourceType, resourceName string, permission enum.Permission) error {

View File

@ -16,14 +16,13 @@ import (
"github.com/pkg/errors"
)
/*
* CheckRepo checks if a repo specific permission is granted for the current auth session
* in the scope of its parent.
* Returns nil if the permission is granted, otherwise returns an error.
* NotAuthenticated, NotAuthorized, or any unerlaying error.
*/
// CheckRepo checks if a repo specific permission is granted for the current auth session
// in the scope of its parent.
// Returns nil if the permission is granted, otherwise returns an error.
// NotAuthenticated, NotAuthorized, or any underlying error.
func CheckRepo(ctx context.Context, authorizer authz.Authorizer, session *auth.Session,
repo *types.Repository, permission enum.Permission, orPublic bool) error {
repo *types.Repository, permission enum.Permission, orPublic bool,
) error {
if orPublic && repo.IsPublic {
return nil
}

View File

@ -13,14 +13,13 @@ import (
"github.com/harness/gitness/types/enum"
)
/*
* CheckService checks if a service specific permission is granted for the current auth session.
* Returns nil if the permission is granted, otherwise returns an error.
* NotAuthenticated, NotAuthorized, or any unerlaying error.
*/
// CheckService checks if a service specific permission is granted for the current auth session.
// Returns nil if the permission is granted, otherwise returns an error.
// NotAuthenticated, NotAuthorized, or any underlying error.
func CheckService(ctx context.Context, authorizer authz.Authorizer, session *auth.Session,
svc *types.Service, permission enum.Permission) error {
// a service exists outside of any scope
svc *types.Service, permission enum.Permission,
) error {
// a service exists outside any scope
scope := &types.Scope{}
resource := &types.Resource{
Type: enum.ResourceTypeService,

View File

@ -13,15 +13,15 @@ import (
"github.com/harness/gitness/types/enum"
)
/*
* CheckServiceAccount checks if a service account specific permission is granted for the current auth session
* in the scope of the parent.
* Returns nil if the permission is granted, otherwise returns an error.
* NotAuthenticated, NotAuthorized, or any unerlaying error.
*/
// CheckServiceAccount checks if a service account specific permission is granted for the current auth session
// in the scope of the parent.
// Returns nil if the permission is granted, otherwise returns an error.
// NotAuthenticated, NotAuthorized, or any underlying error.
func CheckServiceAccount(ctx context.Context, authorizer authz.Authorizer, session *auth.Session,
spaceStore store.SpaceStore, repoStore store.RepoStore, parentType enum.ParentResourceType, parentID int64,
saUID string, permission enum.Permission) error {
return CheckChild(ctx, authorizer, session, spaceStore, repoStore, parentType, parentID,
saUID string, permission enum.Permission,
) error {
return CheckChild(ctx, authorizer, session,
spaceStore, repoStore, parentType, parentID,
enum.ResourceTypeServiceAccount, saUID, permission)
}

View File

@ -16,14 +16,13 @@ import (
"github.com/pkg/errors"
)
/*
* CheckSpace checks if a space specific permission is granted for the current auth session
* in the scope of its parent.
* Returns nil if the permission is granted, otherwise returns an error.
* NotAuthenticated, NotAuthorized, or any unerlaying error.
*/
// CheckSpace checks if a space specific permission is granted for the current auth session
// in the scope of its parent.
// Returns nil if the permission is granted, otherwise returns an error.
// NotAuthenticated, NotAuthorized, or any underlying error.
func CheckSpace(ctx context.Context, authorizer authz.Authorizer, session *auth.Session,
space *types.Space, permission enum.Permission, orPublic bool) error {
space *types.Space, permission enum.Permission, orPublic bool,
) error {
if orPublic && space.IsPublic {
return nil
}

View File

@ -13,14 +13,13 @@ import (
"github.com/harness/gitness/types/enum"
)
/*
* CheckUser checks if a user specific permission is granted for the current auth session.
* Returns nil if the permission is granted, otherwise returns an error.
* NotAuthenticated, NotAuthorized, or any unerlaying error.
*/
// CheckUser checks if a user specific permission is granted for the current auth session.
// Returns nil if the permission is granted, otherwise returns an error.
// NotAuthenticated, NotAuthorized, or any underlying error.
func CheckUser(ctx context.Context, authorizer authz.Authorizer, session *auth.Session,
user *types.User, permission enum.Permission) error {
// a user exists outside of any scope
user *types.User, permission enum.Permission,
) error {
// a user exists outside any scope
scope := &types.Scope{}
resource := &types.Resource{
Type: enum.ResourceTypeUser,

View File

@ -23,8 +23,8 @@ import (
type Controller struct {
db *sqlx.DB
authorizer authz.Authorizer
checkStore store.CheckStore
repoStore store.RepoStore
checkStore store.CheckStore
gitRPCClient gitrpc.Interface
}
@ -32,12 +32,14 @@ func NewController(
db *sqlx.DB,
authorizer authz.Authorizer,
repoStore store.RepoStore,
checkStore store.CheckStore,
gitRPCClient gitrpc.Interface,
) *Controller {
return &Controller{
db: db,
authorizer: authorizer,
repoStore: repoStore,
checkStore: checkStore,
gitRPCClient: gitRPCClient,
}
}

View File

@ -18,11 +18,18 @@ var WireSet = wire.NewSet(
ProvideController,
)
func ProvideController(db *sqlx.DB, authorizer authz.Authorizer,
func ProvideController(
db *sqlx.DB,
authorizer authz.Authorizer,
repoStore store.RepoStore,
checkStore store.CheckStore,
rpcClient gitrpc.Interface,
) *Controller {
return NewController(db, authorizer,
return NewController(
db,
authorizer,
repoStore,
rpcClient)
checkStore,
rpcClient,
)
}

View File

@ -83,12 +83,6 @@ func (c *Controller) Merge(
return types.MergeResponse{}, usererror.BadRequest("Pull request must be open")
}
if pr.UnresolvedCount > 0 {
return types.MergeResponse{}, usererror.BadRequest(
"Pull requests with unresolved comments can't be merged. Resolve all the comments first.",
)
}
if pr.IsDraft {
return types.MergeResponse{}, usererror.BadRequest(
"Draft pull requests can't be merged. Clear the draft flag first.",

View File

@ -1,47 +0,0 @@
// Copyright 2022 Harness Inc. All rights reserved.
// Use of this source code is governed by the Polyform Free Trial License
// that can be found in the LICENSE.md file for this repository.
package pullreq
import (
"context"
"fmt"
"io"
"github.com/harness/gitness/gitrpc"
"github.com/harness/gitness/internal/auth"
"github.com/harness/gitness/types/enum"
)
// RawDiff writes raw git diff to writer w.
func (c *Controller) RawDiff(
ctx context.Context,
session *auth.Session,
repoRef string,
pullreqNum int64,
setSHAs func(sourceSHA, mergeBaseSHA string),
w io.Writer,
) error {
repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoView)
if err != nil {
return fmt.Errorf("failed to acquire access to target repo: %w", err)
}
pr, err := c.pullreqStore.FindByNumber(ctx, repo.ID, pullreqNum)
if err != nil {
return fmt.Errorf("failed to get pull request by number: %w", err)
}
headRef := pr.SourceSHA
baseRef := pr.MergeBaseSHA
setSHAs(headRef, baseRef)
return c.gitRPCClient.RawDiff(ctx, &gitrpc.DiffParams{
ReadParams: gitrpc.CreateRPCReadParams(repo),
BaseRef: baseRef,
HeadRef: headRef,
MergeBase: true,
}, w)
}

View File

@ -8,6 +8,7 @@ import (
"bytes"
"context"
"fmt"
"strconv"
"strings"
"time"
@ -34,7 +35,7 @@ var (
)
type CreateInput struct {
ParentID int64 `json:"parent_id"`
ParentRef string `json:"parent_ref"`
UID string `json:"uid"`
DefaultBranch string `json:"default_branch"`
Description string `json:"description"`
@ -47,7 +48,8 @@ type CreateInput struct {
// Create creates a new repository.
func (c *Controller) Create(ctx context.Context, session *auth.Session, in *CreateInput) (*types.Repository, error) {
if err := c.checkAuthRepoCreation(ctx, session, in.ParentID); err != nil {
parentSpace, err := c.getSpaceCheckAuthRepoCreation(ctx, session, in.ParentRef)
if err != nil {
return nil, err
}
@ -64,7 +66,7 @@ func (c *Controller) Create(ctx context.Context, session *auth.Session, in *Crea
err = dbtx.New(c.db).WithTx(ctx, func(ctx context.Context) error {
// lock parent space path to ensure it doesn't get updated while we setup new repo
var spacePath *types.Path
spacePath, err = c.pathStore.FindPrimaryWithLock(ctx, enum.PathTargetTypeSpace, in.ParentID)
spacePath, err = c.pathStore.FindPrimaryWithLock(ctx, enum.PathTargetTypeSpace, parentSpace.ID)
if err != nil {
return usererror.BadRequest("Parent not found'")
}
@ -72,7 +74,7 @@ func (c *Controller) Create(ctx context.Context, session *auth.Session, in *Crea
now := time.Now().UnixMilli()
repo = &types.Repository{
Version: 0,
ParentID: in.ParentID,
ParentID: parentSpace.ID,
UID: in.UID,
GitUID: gitRPCResp.UID,
Path: paths.Concatinate(spacePath.Value, in.UID),
@ -123,10 +125,14 @@ func (c *Controller) Create(ctx context.Context, session *auth.Session, in *Crea
return repo, nil
}
func (c *Controller) checkAuthRepoCreation(ctx context.Context, session *auth.Session, parentID int64) error {
space, err := c.spaceStore.Find(ctx, parentID)
func (c *Controller) getSpaceCheckAuthRepoCreation(
ctx context.Context,
session *auth.Session,
parentRef string,
) (*types.Space, error) {
space, err := c.spaceStore.FindByRef(ctx, parentRef)
if err != nil {
return fmt.Errorf("parent space not found: %w", err)
return nil, fmt.Errorf("parent space not found: %w", err)
}
// create is a special case - check permission without specific resource
@ -138,14 +144,16 @@ func (c *Controller) checkAuthRepoCreation(ctx context.Context, session *auth.Se
err = apiauth.Check(ctx, c.authorizer, session, scope, resource, enum.PermissionRepoEdit)
if err != nil {
return fmt.Errorf("auth check failed: %w", err)
return nil, fmt.Errorf("auth check failed: %w", err)
}
return nil
return space, nil
}
func (c *Controller) sanitizeCreateInput(in *CreateInput) error {
if in.ParentID <= 0 {
parentRefAsID, err := strconv.ParseInt(in.ParentRef, 10, 64)
if (err == nil && parentRefAsID <= 0) || (len(strings.TrimSpace(in.ParentRef)) == 0) {
return errRepositoryRequiresParent
}

View File

@ -22,7 +22,7 @@ type CreateBranchInput struct {
// Target is the commit (or points to the commit) the new branch will be pointing to.
// If no target is provided, the branch points to the same commit as the default branch of the repo.
Target *string `json:"target"`
Target string `json:"target"`
}
// CreateBranch creates a new branch for a repo.
@ -38,8 +38,8 @@ func (c *Controller) CreateBranch(ctx context.Context, session *auth.Session,
}
// set target to default branch in case no target was provided
if in.Target == nil || *in.Target == "" {
in.Target = &repo.DefaultBranch
if in.Target == "" {
in.Target = repo.DefaultBranch
}
err = checkBranchName(in.Name)
@ -55,7 +55,7 @@ func (c *Controller) CreateBranch(ctx context.Context, session *auth.Session,
rpcOut, err := c.gitRPCClient.CreateBranch(ctx, &gitrpc.CreateBranchParams{
WriteParams: writeParams,
BranchName: in.Name,
Target: *in.Target,
Target: in.Target,
})
if err != nil {
return nil, err

View File

@ -7,6 +7,7 @@ package repo
import (
"context"
"fmt"
"time"
"github.com/harness/gitness/gitrpc"
apiauth "github.com/harness/gitness/internal/api/auth"
@ -14,18 +15,21 @@ import (
"github.com/harness/gitness/types/enum"
)
// CreateBranchInput used for branch creation apis.
type CreateTagInput struct {
// CreateCommitTagInput used for tag creation apis.
type CreateCommitTagInput struct {
Name string `json:"name"`
// Target is the commit (or points to the commit) the new branch will be pointing to.
// If no target is provided, the branch points to the same commit as the default branch of the repo.
Target *string `json:"target"`
Message *string `json:"message"`
// Target is the commit (or points to the commit) the new tag will be pointing to.
// If no target is provided, the tag points to the same commit as the default branch of the repo.
Target string `json:"target"`
// Message is the optional message the tag will be created with - if the message is empty
// the tag will be lightweight, otherwise it'll be annotated.
Message string `json:"message"`
}
// CreateTag creates a new tag for a repo.
func (c *Controller) CreateTag(ctx context.Context, session *auth.Session,
repoRef string, in *CreateTagInput) (*CommitTag, error) {
// CreateCommitTag creates a new tag for a repo.
func (c *Controller) CreateCommitTag(ctx context.Context, session *auth.Session,
repoRef string, in *CreateCommitTagInput) (*CommitTag, error) {
repo, err := c.repoStore.FindByRef(ctx, repoRef)
if err != nil {
return nil, err
@ -36,8 +40,8 @@ func (c *Controller) CreateTag(ctx context.Context, session *auth.Session,
}
// set target to default branch in case no branch or commit was provided
if in.Target == nil || *in.Target == "" {
in.Target = &repo.DefaultBranch
if in.Target == "" {
in.Target = repo.DefaultBranch
}
writeParams, err := CreateRPCWriteParams(ctx, c.urlProvider, session, repo)
@ -45,11 +49,14 @@ func (c *Controller) CreateTag(ctx context.Context, session *auth.Session,
return nil, fmt.Errorf("failed to create RPC write params: %w", err)
}
rpcOut, err := c.gitRPCClient.CreateTag(ctx, &gitrpc.CreateTagParams{
now := time.Now()
rpcOut, err := c.gitRPCClient.CreateCommitTag(ctx, &gitrpc.CreateCommitTagParams{
WriteParams: writeParams,
Name: in.Name,
SHA: *in.Target,
Message: *in.Message,
Target: in.Target,
Message: in.Message,
Tagger: rpcIdentityFromPrincipal(session.Principal),
TaggerDate: &now,
})
if err != nil {

View File

@ -7,6 +7,8 @@ package repo
import (
"context"
"fmt"
"strconv"
"strings"
"time"
apiauth "github.com/harness/gitness/internal/api/auth"
@ -20,13 +22,34 @@ import (
// MoveInput is used for moving a repo.
type MoveInput struct {
UID *string `json:"uid"`
ParentID *int64 `json:"parent_id"`
ParentRef *string `json:"parent_ref"`
KeepAsAlias bool `json:"keep_as_alias"`
}
func (i *MoveInput) hasChanges(repo *types.Repository) bool {
return (i.UID != nil && *i.UID != repo.UID) ||
(i.ParentID != nil && *i.ParentID != repo.ParentID)
if i.UID != nil && *i.UID != repo.UID {
return true
}
if i.ParentRef != nil {
parentRefAsID, err := strconv.ParseInt(*i.ParentRef, 10, 64)
// if parsing was successful, user provided actual space id
if err == nil && parentRefAsID != repo.ParentID {
return true
}
// if parsing was unsuccessful, user provided input as path
if err != nil {
// repo is an existing entity, assume that path is not empty and thus no error
repoParentPath, _, _ := paths.DisectLeaf(repo.Path)
parentRefAsPath := *i.ParentRef
if parentRefAsPath != repoParentPath {
return true
}
}
}
return false
}
// Move moves a repository to a new space and/or uid.
@ -40,15 +63,22 @@ func (c *Controller) Move(ctx context.Context, session *auth.Session,
}
permission := enum.PermissionRepoEdit
if in.ParentID != nil && *in.ParentID != repo.ParentID {
var inParentSpaceID *int64
if in.ParentRef != nil {
// ensure user has access to new space (parentId not sanitized!)
if err = c.checkAuthRepoCreation(ctx, session, *in.ParentID); err != nil {
inParentSpace, err := c.getSpaceCheckAuthRepoCreation(ctx, session, *in.ParentRef)
if err != nil {
return nil, fmt.Errorf("failed to verify repo creation permissions on new parent space: %w", err)
}
// TODO: what would be correct permissions on repo? (technically we are deleting it from the old space)
permission = enum.PermissionRepoDelete
inParentSpaceID = &inParentSpace.ID
if inParentSpace.ID != repo.ParentID {
// TODO: what would be correct permissions on repo? (technically we are deleting it from the old space)
permission = enum.PermissionRepoDelete
}
}
if err = apiauth.CheckRepo(ctx, c.authorizer, session, repo, permission, false); err != nil {
return nil, err
}
@ -66,8 +96,8 @@ func (c *Controller) Move(ctx context.Context, session *auth.Session,
if in.UID != nil {
r.UID = *in.UID
}
if in.ParentID != nil {
r.ParentID = *in.ParentID
if inParentSpaceID != nil {
r.ParentID = *inParentSpaceID
}
return nil
})
@ -132,8 +162,9 @@ func (c *Controller) sanitizeMoveInput(in *MoveInput) error {
}
}
if in.ParentID != nil {
if *in.ParentID <= 0 {
if in.ParentRef != nil {
parentRefAsID, err := strconv.ParseInt(*in.ParentRef, 10, 64)
if (err == nil && parentRefAsID <= 0) || (len(strings.TrimSpace(*in.ParentRef)) == 0) {
return errRepositoryRequiresParent
}
}

View File

@ -18,7 +18,7 @@ import (
type CreateTokenInput struct {
UID string `json:"uid"`
Lifetime time.Duration `json:"lifetime"`
Lifetime *time.Duration `json:"lifetime"`
Grants enum.AccessGrant `json:"grants"`
}
@ -33,7 +33,7 @@ func (c *Controller) CreateToken(ctx context.Context, session *auth.Session,
if err = check.UID(in.UID); err != nil {
return nil, err
}
if err = check.TokenLifetime(in.Lifetime); err != nil {
if err = check.TokenLifetime(in.Lifetime, true); err != nil {
return nil, err
}
// TODO: Added to unblock UI - Depending on product decision enforce grants, or remove Grants completely.

View File

@ -15,31 +15,34 @@ import (
)
type Controller struct {
db *sqlx.DB
urlProvider *url.Provider
uidCheck check.PathUID
authorizer authz.Authorizer
pathStore store.PathStore
spaceStore store.SpaceStore
repoStore store.RepoStore
principalStore store.PrincipalStore
repoCtrl *repo.Controller
db *sqlx.DB
urlProvider *url.Provider
uidCheck check.PathUID
authorizer authz.Authorizer
pathStore store.PathStore
spaceStore store.SpaceStore
repoStore store.RepoStore
principalStore store.PrincipalStore
repoCtrl *repo.Controller
membershipStore store.MembershipStore
}
func NewController(db *sqlx.DB, urlProvider *url.Provider,
uidCheck check.PathUID, authorizer authz.Authorizer,
pathStore store.PathStore, spaceStore store.SpaceStore,
repoStore store.RepoStore, principalStore store.PrincipalStore, repoCtrl *repo.Controller,
membershipStore store.MembershipStore,
) *Controller {
return &Controller{
db: db,
urlProvider: urlProvider,
uidCheck: uidCheck,
authorizer: authorizer,
pathStore: pathStore,
spaceStore: spaceStore,
repoStore: repoStore,
principalStore: principalStore,
repoCtrl: repoCtrl,
db: db,
urlProvider: urlProvider,
uidCheck: uidCheck,
authorizer: authorizer,
pathStore: pathStore,
spaceStore: spaceStore,
repoStore: repoStore,
principalStore: principalStore,
repoCtrl: repoCtrl,
membershipStore: membershipStore,
}
}

View File

@ -7,12 +7,14 @@ package space
import (
"context"
"fmt"
"strconv"
"strings"
"time"
apiauth "github.com/harness/gitness/internal/api/auth"
"github.com/harness/gitness/internal/api/usererror"
"github.com/harness/gitness/internal/auth"
"github.com/harness/gitness/internal/bootstrap"
"github.com/harness/gitness/internal/paths"
"github.com/harness/gitness/store/database/dbtx"
"github.com/harness/gitness/types"
@ -26,15 +28,18 @@ var (
)
type CreateInput struct {
ParentID int64 `json:"parent_id"`
ParentRef string `json:"parent_ref"`
UID string `json:"uid"`
Description string `json:"description"`
IsPublic bool `json:"is_public"`
}
// Create creates a new space.
//
//nolint:gocognit // refactor if required
func (c *Controller) Create(ctx context.Context, session *auth.Session, in *CreateInput) (*types.Space, error) {
if err := c.checkAuthSpaceCreation(ctx, session, in.ParentID); err != nil {
parentSpace, err := c.getSpaceCheckAuthSpaceCreation(ctx, session, in.ParentRef)
if err != nil {
return nil, err
}
@ -43,11 +48,13 @@ func (c *Controller) Create(ctx context.Context, session *auth.Session, in *Crea
}
var space *types.Space
err := dbtx.New(c.db).WithTx(ctx, func(ctx context.Context) error {
err = dbtx.New(c.db).WithTx(ctx, func(ctx context.Context) error {
spacePath := in.UID
if in.ParentID > 0 {
parentSpaceID := int64(0)
if parentSpace != nil {
parentSpaceID = parentSpace.ID
// lock parent space path to ensure it doesn't get updated while we setup new space
parentPath, err := c.pathStore.FindPrimaryWithLock(ctx, enum.PathTargetTypeSpace, in.ParentID)
parentPath, err := c.pathStore.FindPrimaryWithLock(ctx, enum.PathTargetTypeSpace, parentSpaceID)
if err != nil {
return usererror.BadRequest("Parent not found")
}
@ -63,7 +70,7 @@ func (c *Controller) Create(ctx context.Context, session *auth.Session, in *Crea
now := time.Now().UnixMilli()
space = &types.Space{
Version: 0,
ParentID: in.ParentID,
ParentID: parentSpaceID,
UID: in.UID,
Path: spacePath,
Description: in.Description,
@ -72,7 +79,7 @@ func (c *Controller) Create(ctx context.Context, session *auth.Session, in *Crea
Created: now,
Updated: now,
}
err := c.spaceStore.Create(ctx, space)
err = c.spaceStore.Create(ctx, space)
if err != nil {
return fmt.Errorf("space creation failed: %w", err)
}
@ -84,14 +91,35 @@ func (c *Controller) Create(ctx context.Context, session *auth.Session, in *Crea
TargetType: enum.PathTargetTypeSpace,
TargetID: space.ID,
CreatedBy: space.CreatedBy,
Created: space.Created,
Updated: space.Updated,
Created: now,
Updated: now,
}
err = c.pathStore.Create(ctx, path)
if err != nil {
return fmt.Errorf("failed to create path: %w", err)
}
// add space membership to top level space only (as the user doesn't have inherited permissions already)
parentRefAsID, err := strconv.ParseInt(in.ParentRef, 10, 64)
if (err == nil && parentRefAsID == 0) || (len(strings.TrimSpace(in.ParentRef)) == 0) {
membership := &types.Membership{
MembershipKey: types.MembershipKey{
SpaceID: space.ID,
PrincipalID: session.Principal.ID,
},
Role: enum.MembershipRoleSpaceOwner,
// membership has been created by the system
CreatedBy: bootstrap.NewSystemServiceSession().Principal.ID,
Created: now,
Updated: now,
}
err = c.membershipStore.Create(ctx, membership)
if err != nil {
return fmt.Errorf("failed to make user owner of the space: %w", err)
}
}
return nil
})
if err != nil {
@ -101,19 +129,25 @@ func (c *Controller) Create(ctx context.Context, session *auth.Session, in *Crea
return space, nil
}
func (c *Controller) checkAuthSpaceCreation(ctx context.Context, session *auth.Session, parentID int64) error {
if parentID <= 0 {
func (c *Controller) getSpaceCheckAuthSpaceCreation(
ctx context.Context,
session *auth.Session,
parentRef string,
) (*types.Space, error) {
parentRefAsID, err := strconv.ParseInt(parentRef, 10, 64)
if (parentRefAsID <= 0 && err == nil) || (len(strings.TrimSpace(parentRef)) == 0) {
// TODO: Restrict top level space creation.
if session == nil {
return usererror.ErrUnauthorized
return nil, usererror.ErrUnauthorized
}
return nil
//nolint:nilnil
return nil, nil
}
parentSpace, err := c.spaceStore.Find(ctx, parentID)
parentSpace, err := c.spaceStore.FindByRef(ctx, parentRef)
if err != nil {
return fmt.Errorf("failed to get parent space: %w", err)
return nil, fmt.Errorf("failed to get parent space: %w", err)
}
// create is a special case - check permission without specific resource
@ -123,18 +157,25 @@ func (c *Controller) checkAuthSpaceCreation(ctx context.Context, session *auth.S
Name: "",
}
if err = apiauth.Check(ctx, c.authorizer, session, scope, resource, enum.PermissionSpaceCreate); err != nil {
return err
return nil, err
}
return nil
return parentSpace, nil
}
func (c *Controller) sanitizeCreateInput(in *CreateInput) error {
if in.ParentID < 0 {
parentRefAsID, err := strconv.ParseInt(in.ParentRef, 10, 64)
if err == nil && parentRefAsID < 0 {
return errParentIDNegative
}
if err := c.uidCheck(in.UID, in.ParentID == 0); err != nil {
isRoot := false
if (err == nil && parentRefAsID == 0) || (len(strings.TrimSpace(in.ParentRef)) == 0) {
isRoot = true
}
if err := c.uidCheck(in.UID, isRoot); err != nil {
return err
}

View File

@ -36,7 +36,7 @@ func (c *Controller) Delete(ctx context.Context, session *auth.Session, spaceRef
func (c *Controller) DeleteNoAuth(ctx context.Context, session *auth.Session, spaceID int64) error {
filter := &types.SpaceFilter{
Page: 1,
Size: int(math.MaxInt),
Size: math.MaxInt,
Query: "",
Order: enum.OrderAsc,
Sort: enum.SpaceAttrNone,

View File

@ -10,13 +10,17 @@ import (
apiauth "github.com/harness/gitness/internal/api/auth"
"github.com/harness/gitness/internal/auth"
"github.com/harness/gitness/store/database/dbtx"
"github.com/harness/gitness/types"
"github.com/harness/gitness/types/enum"
)
// ListSpaces lists the child spaces of a space.
func (c *Controller) ListSpaces(ctx context.Context, session *auth.Session,
spaceRef string, filter *types.SpaceFilter) ([]*types.Space, int64, error) {
func (c *Controller) ListSpaces(ctx context.Context,
session *auth.Session,
spaceRef string,
filter *types.SpaceFilter,
) ([]types.Space, int64, error) {
space, err := c.spaceStore.FindByRef(ctx, spaceRef)
if err != nil {
return nil, 0, err
@ -28,20 +32,30 @@ func (c *Controller) ListSpaces(ctx context.Context, session *auth.Session,
return c.ListSpacesNoAuth(ctx, space.ID, filter)
}
// List spaces WITHOUT checking PermissionSpaceView.
// ListSpacesNoAuth lists spaces WITHOUT checking PermissionSpaceView.
func (c *Controller) ListSpacesNoAuth(
ctx context.Context,
spaceID int64,
filter *types.SpaceFilter,
) ([]*types.Space, int64, error) {
count, err := c.spaceStore.Count(ctx, spaceID, filter)
if err != nil {
return nil, 0, fmt.Errorf("failed to count child spaces: %w", err)
}
) ([]types.Space, int64, error) {
var spaces []types.Space
var count int64
spaces, err := c.spaceStore.List(ctx, spaceID, filter)
err := dbtx.New(c.db).WithTx(ctx, func(ctx context.Context) (err error) {
count, err = c.spaceStore.Count(ctx, spaceID, filter)
if err != nil {
return fmt.Errorf("failed to count child spaces: %w", err)
}
spaces, err = c.spaceStore.List(ctx, spaceID, filter)
if err != nil {
return fmt.Errorf("failed to list child spaces: %w", err)
}
return nil
}, dbtx.TxDefaultReadOnly)
if err != nil {
return nil, 0, fmt.Errorf("failed to list child spaces: %w", err)
return nil, 0, err
}
/*

View File

@ -0,0 +1,100 @@
// Copyright 2022 Harness Inc. All rights reserved.
// Use of this source code is governed by the Polyform Free Trial License
// that can be found in the LICENSE.md file for this repository.
package space
import (
"context"
"fmt"
"time"
apiauth "github.com/harness/gitness/internal/api/auth"
"github.com/harness/gitness/internal/api/usererror"
"github.com/harness/gitness/internal/auth"
"github.com/harness/gitness/store"
"github.com/harness/gitness/types"
"github.com/harness/gitness/types/enum"
"github.com/pkg/errors"
)
type MembershipAddInput struct {
UserUID string `json:"user_uid"`
Role enum.MembershipRole `json:"role"`
}
func (in *MembershipAddInput) Validate() error {
if in.UserUID == "" {
return usererror.BadRequest("UserUID must be provided")
}
if in.Role == "" {
return usererror.BadRequest("Role must be provided")
}
role, ok := in.Role.Sanitize()
if !ok {
msg := fmt.Sprintf("Provided role '%s' is not suppored. Valid values are: %v",
in.Role, enum.MembershipRoles)
return usererror.BadRequest(msg)
}
in.Role = role
return nil
}
// MembershipAdd adds a new membership to a space.
func (c *Controller) MembershipAdd(ctx context.Context,
session *auth.Session,
spaceRef string,
in *MembershipAddInput,
) (*types.MembershipUser, error) {
space, err := c.spaceStore.FindByRef(ctx, spaceRef)
if err != nil {
return nil, err
}
if err = apiauth.CheckSpace(ctx, c.authorizer, session, space, enum.PermissionSpaceEdit, false); err != nil {
return nil, err
}
err = in.Validate()
if err != nil {
return nil, err
}
user, err := c.principalStore.FindUserByUID(ctx, in.UserUID)
if errors.Is(err, store.ErrResourceNotFound) {
return nil, usererror.BadRequestf("User '%s' not found", in.UserUID)
} else if err != nil {
return nil, fmt.Errorf("failed to find the user: %w", err)
}
now := time.Now().UnixMilli()
membership := types.Membership{
MembershipKey: types.MembershipKey{
SpaceID: space.ID,
PrincipalID: user.ID,
},
CreatedBy: session.Principal.ID,
Created: now,
Updated: now,
Role: in.Role,
}
err = c.membershipStore.Create(ctx, &membership)
if err != nil {
return nil, fmt.Errorf("failed to create new membership: %w", err)
}
result := &types.MembershipUser{
Membership: membership,
Principal: *user.ToPrincipalInfo(),
AddedBy: *session.Principal.ToPrincipalInfo(),
}
return result, nil
}

View File

@ -0,0 +1,46 @@
// Copyright 2022 Harness Inc. All rights reserved.
// Use of this source code is governed by the Polyform Free Trial License
// that can be found in the LICENSE.md file for this repository.
package space
import (
"context"
"fmt"
apiauth "github.com/harness/gitness/internal/api/auth"
"github.com/harness/gitness/internal/auth"
"github.com/harness/gitness/types"
"github.com/harness/gitness/types/enum"
)
// MembershipDelete removes an existing membership from a space.
func (c *Controller) MembershipDelete(ctx context.Context,
session *auth.Session,
spaceRef string,
userUID string,
) error {
space, err := c.spaceStore.FindByRef(ctx, spaceRef)
if err != nil {
return err
}
if err = apiauth.CheckSpace(ctx, c.authorizer, session, space, enum.PermissionSpaceEdit, false); err != nil {
return err
}
user, err := c.principalStore.FindUserByUID(ctx, userUID)
if err != nil {
return fmt.Errorf("failed to find user by uid: %w", err)
}
err = c.membershipStore.Delete(ctx, types.MembershipKey{
SpaceID: space.ID,
PrincipalID: user.ID,
})
if err != nil {
return fmt.Errorf("failed to delete user membership: %w", err)
}
return nil
}

View File

@ -0,0 +1,54 @@
// Copyright 2022 Harness Inc. All rights reserved.
// Use of this source code is governed by the Polyform Free Trial License
// that can be found in the LICENSE.md file for this repository.
package space
import (
"context"
"fmt"
apiauth "github.com/harness/gitness/internal/api/auth"
"github.com/harness/gitness/internal/auth"
"github.com/harness/gitness/store/database/dbtx"
"github.com/harness/gitness/types"
"github.com/harness/gitness/types/enum"
)
// MembershipList lists all space memberships.
func (c *Controller) MembershipList(ctx context.Context,
session *auth.Session,
spaceRef string,
opts types.MembershipFilter,
) ([]types.MembershipUser, int64, error) {
space, err := c.spaceStore.FindByRef(ctx, spaceRef)
if err != nil {
return nil, 0, err
}
if err = apiauth.CheckSpace(ctx, c.authorizer, session, space, enum.PermissionSpaceView, false); err != nil {
return nil, 0, err
}
var memberships []types.MembershipUser
var membershipsCount int64
err = dbtx.New(c.db).WithTx(ctx, func(ctx context.Context) error {
memberships, err = c.membershipStore.ListUsers(ctx, space.ID, opts)
if err != nil {
return fmt.Errorf("failed to list memberships for space: %w", err)
}
membershipsCount, err = c.membershipStore.CountUsers(ctx, space.ID, opts)
if err != nil {
return fmt.Errorf("failed to count memberships for space: %w", err)
}
return nil
}, dbtx.TxDefaultReadOnly)
if err != nil {
return nil, 0, err
}
return memberships, membershipsCount, nil
}

View File

@ -0,0 +1,85 @@
// Copyright 2022 Harness Inc. All rights reserved.
// Use of this source code is governed by the Polyform Free Trial License
// that can be found in the LICENSE.md file for this repository.
package space
import (
"context"
"fmt"
apiauth "github.com/harness/gitness/internal/api/auth"
"github.com/harness/gitness/internal/api/usererror"
"github.com/harness/gitness/internal/auth"
"github.com/harness/gitness/types"
"github.com/harness/gitness/types/enum"
)
type MembershipUpdateInput struct {
Role enum.MembershipRole `json:"role"`
}
func (in *MembershipUpdateInput) Validate() error {
if in.Role == "" {
return usererror.BadRequest("Role must be provided")
}
role, ok := in.Role.Sanitize()
if !ok {
msg := fmt.Sprintf("Provided role '%s' is not suppored. Valid values are: %v",
in.Role, enum.MembershipRoles)
return usererror.BadRequest(msg)
}
in.Role = role
return nil
}
// MembershipUpdate changes the role of an existing membership.
func (c *Controller) MembershipUpdate(ctx context.Context,
session *auth.Session,
spaceRef string,
userUID string,
in *MembershipUpdateInput,
) (*types.MembershipUser, error) {
space, err := c.spaceStore.FindByRef(ctx, spaceRef)
if err != nil {
return nil, err
}
if err = apiauth.CheckSpace(ctx, c.authorizer, session, space, enum.PermissionSpaceEdit, false); err != nil {
return nil, err
}
err = in.Validate()
if err != nil {
return nil, err
}
user, err := c.principalStore.FindUserByUID(ctx, userUID)
if err != nil {
return nil, fmt.Errorf("failed to find user by uid: %w", err)
}
membership, err := c.membershipStore.FindUser(ctx, types.MembershipKey{
SpaceID: space.ID,
PrincipalID: user.ID,
})
if err != nil {
return nil, fmt.Errorf("failed to find membership for update: %w", err)
}
if membership.Role == in.Role {
return membership, nil
}
membership.Role = in.Role
err = c.membershipStore.Update(ctx, &membership.Membership)
if err != nil {
return nil, fmt.Errorf("failed to update membership")
}
return membership, nil
}

View File

@ -8,6 +8,7 @@ import (
"context"
"errors"
"fmt"
"strconv"
"strings"
"time"
@ -20,18 +21,41 @@ import (
"github.com/harness/gitness/types"
"github.com/harness/gitness/types/check"
"github.com/harness/gitness/types/enum"
"github.com/gotidy/ptr"
)
// MoveInput is used for moving a space.
type MoveInput struct {
UID *string `json:"uid"`
ParentID *int64 `json:"parent_id"`
ParentRef *string `json:"parent_ref"`
KeepAsAlias bool `json:"keep_as_alias"`
}
func (i *MoveInput) hasChanges(space *types.Space) bool {
return (i.UID != nil && *i.UID != space.UID) ||
(i.ParentID != nil && *i.ParentID != space.ParentID)
if i.UID != nil && *i.UID != space.UID {
return true
}
if i.ParentRef != nil {
parentRefAsID, err := strconv.ParseInt(*i.ParentRef, 10, 64)
// if parsing was successful, user provided actual space id
if err == nil && parentRefAsID != space.ParentID {
return true
}
// if parsing was unsuccessful, user provided input as path
if err != nil {
// space is an existing entity, assume that path is not empty and thus no error
spaceParentPath, _, _ := paths.DisectLeaf(space.Path)
parentRefAsPath := *i.ParentRef
if parentRefAsPath != spaceParentPath {
return true
}
}
}
return false
}
// Move moves a space to a new space and/or name.
@ -44,16 +68,27 @@ func (c *Controller) Move(ctx context.Context, session *auth.Session,
return nil, err
}
var inParentSpaceID *int64
permission := enum.PermissionSpaceEdit
if in.ParentID != nil && *in.ParentID != space.ParentID {
if in.ParentRef != nil {
// ensure user has access to new space (parentId not sanitized!)
if err = c.checkAuthSpaceCreation(ctx, session, *in.ParentID); err != nil {
inParentSpace, err := c.getSpaceCheckAuthSpaceCreation(ctx, session, *in.ParentRef)
if err != nil {
return nil, fmt.Errorf("failed to verify space creation permissions on new parent space: %w", err)
}
// TODO: what would be correct permissions on space? (technically we are deleting it from the old space)
permission = enum.PermissionSpaceDelete
if inParentSpace != nil {
inParentSpaceID = &inParentSpace.ID
} else {
inParentSpaceID = ptr.Int64(0)
}
if *inParentSpaceID != space.ParentID {
// TODO: what would be correct permissions on space? (technically we are deleting it from the old space)
permission = enum.PermissionSpaceDelete
}
}
if err = apiauth.CheckSpace(ctx, c.authorizer, session, space, permission, false); err != nil {
return nil, err
}
@ -71,9 +106,11 @@ func (c *Controller) Move(ctx context.Context, session *auth.Session,
if in.UID != nil {
s.UID = *in.UID
}
if in.ParentID != nil {
s.ParentID = *in.ParentID
if inParentSpaceID != nil {
s.ParentID = *inParentSpaceID
}
return nil
})
if err != nil {
@ -121,11 +158,16 @@ func (c *Controller) Move(ctx context.Context, session *auth.Session,
}
func (c *Controller) sanitizeMoveInput(in *MoveInput, isRoot bool) error {
if in.ParentID != nil {
if *in.ParentID < 0 {
if in.ParentRef != nil {
parentRefAsID, err := strconv.ParseInt(*in.ParentRef, 10, 64)
if err == nil && parentRefAsID < 0 {
return errParentIDNegative
}
isRoot = *in.ParentID == 0
if (err == nil && parentRefAsID == 0) || (len(strings.TrimSpace(*in.ParentRef)) == 0) {
isRoot = true
}
}
if in.UID != nil {

View File

@ -22,6 +22,11 @@ var WireSet = wire.NewSet(
func ProvideController(db *sqlx.DB, urlProvider *url.Provider, uidCheck check.PathUID, authorizer authz.Authorizer,
pathStore store.PathStore, spaceStore store.SpaceStore, repoStore store.RepoStore,
principalStore store.PrincipalStore, repoCtrl *repo.Controller) *Controller {
return NewController(db, urlProvider, uidCheck, authorizer, pathStore, spaceStore, repoStore, principalStore, repoCtrl)
principalStore store.PrincipalStore, repoCtrl *repo.Controller,
membershipStore store.MembershipStore,
) *Controller {
return NewController(db, urlProvider, uidCheck, authorizer,
pathStore, spaceStore, repoStore,
principalStore, repoCtrl,
membershipStore)
}

View File

@ -21,29 +21,36 @@ type Controller struct {
authorizer authz.Authorizer
principalStore store.PrincipalStore
tokenStore store.TokenStore
config *types.Config
membershipStore store.MembershipStore
}
func NewController(principalUIDCheck check.PrincipalUID, authorizer authz.Authorizer,
principalStore store.PrincipalStore, tokenStore store.TokenStore, config *types.Config) *Controller {
func NewController(
principalUIDCheck check.PrincipalUID,
authorizer authz.Authorizer,
principalStore store.PrincipalStore,
tokenStore store.TokenStore,
membershipStore store.MembershipStore,
) *Controller {
return &Controller{
principalUIDCheck: principalUIDCheck,
authorizer: authorizer,
principalStore: principalStore,
tokenStore: tokenStore,
config: config,
membershipStore: membershipStore,
}
}
var hashPassword = bcrypt.GenerateFromPassword
func findUserFromUID(ctx context.Context,
principalStore store.PrincipalStore, userUID string) (*types.User, error) {
principalStore store.PrincipalStore, userUID string,
) (*types.User, error) {
return principalStore.FindUserByUID(ctx, userUID)
}
func findUserFromEmail(ctx context.Context,
principalStore store.PrincipalStore, email string) (*types.User, error) {
principalStore store.PrincipalStore, email string,
) (*types.User, error) {
return principalStore.FindUserByEmail(ctx, email)
}

View File

@ -75,7 +75,7 @@ func (c *Controller) CreateNoAuth(ctx context.Context, in *CreateInput, admin bo
return nil, err
}
uCount, err := c.principalStore.CountUsers(ctx)
uCount, err := c.principalStore.CountUsers(ctx, &types.UserFilter{})
if err != nil {
return nil, err
}

View File

@ -18,7 +18,7 @@ import (
type CreateTokenInput struct {
UID string `json:"uid"`
Lifetime time.Duration `json:"lifetime"`
Lifetime *time.Duration `json:"lifetime"`
Grants enum.AccessGrant `json:"grants"`
}
@ -40,7 +40,7 @@ func (c *Controller) CreateAccessToken(ctx context.Context, session *auth.Sessio
if err = check.UID(in.UID); err != nil {
return nil, err
}
if err = check.TokenLifetime(in.Lifetime); err != nil {
if err = check.TokenLifetime(in.Lifetime, true); err != nil {
return nil, err
}
// TODO: Added to unblock UI - Depending on product decision enforce grants, or remove Grants completely.

View File

@ -9,7 +9,9 @@ import (
"fmt"
apiauth "github.com/harness/gitness/internal/api/auth"
"github.com/harness/gitness/internal/api/usererror"
"github.com/harness/gitness/internal/auth"
"github.com/harness/gitness/types"
"github.com/harness/gitness/types/enum"
)
@ -21,6 +23,18 @@ func (c *Controller) Delete(ctx context.Context, session *auth.Session,
return err
}
// Fail if the user being deleted is the only admin in DB
if user.Admin {
admUsrCount, err := c.principalStore.CountUsers(ctx, &types.UserFilter{Admin: true})
if err != nil {
return fmt.Errorf("failed to check admin user count: %w", err)
}
if admUsrCount == 1 {
return usererror.BadRequest("cannot delete the only admin user")
}
}
// Ensure principal has required permissions on parent
if err = apiauth.CheckUser(ctx, c.authorizer, session, user, enum.PermissionUserDelete); err != nil {
return err

View File

@ -28,7 +28,7 @@ func (c *Controller) List(ctx context.Context, session *auth.Session,
return nil, 0, err
}
count, err := c.principalStore.CountUsers(ctx)
count, err := c.principalStore.CountUsers(ctx, filter)
if err != nil {
return nil, 0, fmt.Errorf("failed to count users: %w", err)
}

View File

@ -0,0 +1,38 @@
// Copyright 2022 Harness Inc. All rights reserved.
// Use of this source code is governed by the Polyform Free Trial License
// that can be found in the LICENSE.md file for this repository.
package user
import (
"context"
"fmt"
apiauth "github.com/harness/gitness/internal/api/auth"
"github.com/harness/gitness/internal/auth"
"github.com/harness/gitness/types"
"github.com/harness/gitness/types/enum"
)
// MembershipSpaces lists all spaces in which the user is a member.
func (c *Controller) MembershipSpaces(ctx context.Context,
session *auth.Session,
userUID string,
) ([]types.MembershipSpace, error) {
user, err := findUserFromUID(ctx, c.principalStore, userUID)
if err != nil {
return nil, fmt.Errorf("failed to find user by UID: %w", err)
}
// Ensure principal has required permissions.
if err = apiauth.CheckUser(ctx, c.authorizer, session, user, enum.PermissionUserView); err != nil {
return nil, err
}
membershipSpaces, err := c.membershipStore.ListSpaces(ctx, user.ID)
if err != nil {
return nil, fmt.Errorf("failed to list membership spaces for user: %w", err)
}
return membershipSpaces, nil
}

View File

@ -7,7 +7,6 @@ package user
import (
"github.com/harness/gitness/internal/auth/authz"
"github.com/harness/gitness/internal/store"
"github.com/harness/gitness/types"
"github.com/harness/gitness/types/check"
"github.com/google/wire"
@ -18,7 +17,17 @@ var WireSet = wire.NewSet(
NewController,
)
func ProvideController(principalUIDCheck check.PrincipalUID, authorizer authz.Authorizer,
principalStore store.PrincipalStore, tokenStore store.TokenStore, config *types.Config) *Controller {
return NewController(principalUIDCheck, authorizer, principalStore, tokenStore, config)
func ProvideController(
principalUIDCheck check.PrincipalUID,
authorizer authz.Authorizer,
principalStore store.PrincipalStore,
tokenStore store.TokenStore,
membershipStore store.MembershipStore,
) *Controller {
return NewController(
principalUIDCheck,
authorizer,
principalStore,
tokenStore,
membershipStore)
}

View File

@ -23,14 +23,14 @@ func HandleCreateCommitTag(repoCtrl *repo.Controller) http.HandlerFunc {
return
}
in := new(repo.CreateTagInput)
in := new(repo.CreateCommitTagInput)
err = json.NewDecoder(r.Body).Decode(in)
if err != nil {
render.BadRequestf(w, "Invalid request body: %s.", err)
return
}
tag, err := repoCtrl.CreateTag(ctx, session, repoRef, in)
tag, err := repoCtrl.CreateCommitTag(ctx, session, repoRef, in)
if err != nil {
render.TranslatedUserError(w, err)
return

View File

@ -7,16 +7,13 @@ package space
import (
"net/http"
"github.com/harness/gitness/internal/api/controller/repo"
"github.com/harness/gitness/internal/api/controller/space"
"github.com/harness/gitness/internal/api/render"
"github.com/harness/gitness/internal/api/request"
)
/*
* Deletes a space.
*/
func HandleDelete(spaceCtrl *space.Controller, repoCtrl *repo.Controller) http.HandlerFunc {
// HandleDelete handles the delete space HTTP API.
func HandleDelete(spaceCtrl *space.Controller) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
session, _ := request.AuthSessionFrom(ctx)

View File

@ -0,0 +1,43 @@
// Copyright 2022 Harness Inc. All rights reserved.
// Use of this source code is governed by the Polyform Free Trial License
// that can be found in the LICENSE.md file for this repository.
package space
import (
"encoding/json"
"net/http"
"github.com/harness/gitness/internal/api/controller/space"
"github.com/harness/gitness/internal/api/render"
"github.com/harness/gitness/internal/api/request"
)
// HandleMembershipAdd handles API that adds a new membership to a space.
func HandleMembershipAdd(spaceCtrl *space.Controller) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
session, _ := request.AuthSessionFrom(ctx)
spaceRef, err := request.GetSpaceRefFromPath(r)
if err != nil {
render.TranslatedUserError(w, err)
return
}
in := new(space.MembershipAddInput)
err = json.NewDecoder(r.Body).Decode(in)
if err != nil {
render.BadRequestf(w, "Invalid Request Body: %s.", err)
return
}
memberInfo, err := spaceCtrl.MembershipAdd(ctx, session, spaceRef, in)
if err != nil {
render.TranslatedUserError(w, err)
return
}
render.JSON(w, http.StatusCreated, memberInfo)
}
}

View File

@ -2,44 +2,40 @@
// Use of this source code is governed by the Polyform Free Trial License
// that can be found in the LICENSE.md file for this repository.
package pullreq
package space
import (
"net/http"
"github.com/harness/gitness/internal/api/controller/pullreq"
"github.com/harness/gitness/internal/api/controller/space"
"github.com/harness/gitness/internal/api/render"
"github.com/harness/gitness/internal/api/request"
)
// HandleRawDiff returns raw git diff for PR.
func HandleRawDiff(pullreqCtrl *pullreq.Controller) http.HandlerFunc {
// HandleMembershipDelete handles API that deletes an existing space membership.
func HandleMembershipDelete(spaceCtrl *space.Controller) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
session, _ := request.AuthSessionFrom(ctx)
repoRef, err := request.GetRepoRefFromPath(r)
spaceRef, err := request.GetSpaceRefFromPath(r)
if err != nil {
render.TranslatedUserError(w, err)
return
}
pullreqNumber, err := request.GetPullReqNumberFromPath(r)
userUID, err := request.GetUserUIDFromPath(r)
if err != nil {
render.TranslatedUserError(w, err)
return
}
setSHAs := func(sourceSHA, mergeBaseSHA string) {
w.Header().Set("X-Source-Sha", sourceSHA)
w.Header().Set("X-Merge-Base-Sha", mergeBaseSHA)
}
if err = pullreqCtrl.RawDiff(ctx, session, repoRef, pullreqNumber, setSHAs, w); err != nil {
err = spaceCtrl.MembershipDelete(ctx, session, spaceRef, userUID)
if err != nil {
render.TranslatedUserError(w, err)
return
}
w.WriteHeader(http.StatusOK)
render.DeleteSuccessful(w)
}
}

View File

@ -0,0 +1,38 @@
// Copyright 2022 Harness Inc. All rights reserved.
// Use of this source code is governed by the Polyform Free Trial License
// that can be found in the LICENSE.md file for this repository.
package space
import (
"net/http"
"github.com/harness/gitness/internal/api/controller/space"
"github.com/harness/gitness/internal/api/render"
"github.com/harness/gitness/internal/api/request"
)
// HandleMembershipList handles API that lists all memberships of a space.
func HandleMembershipList(spaceCtrl *space.Controller) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
session, _ := request.AuthSessionFrom(ctx)
spaceRef, err := request.GetSpaceRefFromPath(r)
if err != nil {
render.TranslatedUserError(w, err)
return
}
filter := request.ParseMembershipFilter(r)
memberships, membershipsCount, err := spaceCtrl.MembershipList(ctx, session, spaceRef, filter)
if err != nil {
render.TranslatedUserError(w, err)
return
}
render.Pagination(r, w, filter.Page, filter.Size, int(membershipsCount))
render.JSON(w, http.StatusOK, memberships)
}
}

View File

@ -0,0 +1,49 @@
// Copyright 2022 Harness Inc. All rights reserved.
// Use of this source code is governed by the Polyform Free Trial License
// that can be found in the LICENSE.md file for this repository.
package space
import (
"encoding/json"
"net/http"
"github.com/harness/gitness/internal/api/controller/space"
"github.com/harness/gitness/internal/api/render"
"github.com/harness/gitness/internal/api/request"
)
// HandleMembershipUpdate handles API that changes the role of an existing space membership.
func HandleMembershipUpdate(spaceCtrl *space.Controller) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
session, _ := request.AuthSessionFrom(ctx)
spaceRef, err := request.GetSpaceRefFromPath(r)
if err != nil {
render.TranslatedUserError(w, err)
return
}
userUID, err := request.GetUserUIDFromPath(r)
if err != nil {
render.TranslatedUserError(w, err)
return
}
in := new(space.MembershipUpdateInput)
err = json.NewDecoder(r.Body).Decode(in)
if err != nil {
render.BadRequestf(w, "Invalid Request Body: %s.", err)
return
}
memberInfo, err := spaceCtrl.MembershipUpdate(ctx, session, spaceRef, userUID, in)
if err != nil {
render.TranslatedUserError(w, err)
return
}
render.JSON(w, http.StatusOK, memberInfo)
}
}

View File

@ -0,0 +1,29 @@
// Copyright 2022 Harness Inc. All rights reserved.
// Use of this source code is governed by the Polyform Free Trial License
// that can be found in the LICENSE.md file for this repository.
package user
import (
"net/http"
"github.com/harness/gitness/internal/api/controller/user"
"github.com/harness/gitness/internal/api/render"
"github.com/harness/gitness/internal/api/request"
)
func HandleMembershipSpaces(userCtrl *user.Controller) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
session, _ := request.AuthSessionFrom(ctx)
userUID := session.Principal.UID
membershipSpaces, err := userCtrl.MembershipSpaces(ctx, session, userUID)
if err != nil {
render.TranslatedUserError(w, err)
return
}
render.JSON(w, http.StatusOK, membershipSpaces)
}
}

View File

@ -459,17 +459,6 @@ func pullReqOperations(reflector *openapi3.Reflector) {
_ = reflector.SetJSONResponse(&opListCommits, new(usererror.Error), http.StatusNotFound)
_ = reflector.Spec.AddOperation(http.MethodGet, "/repos/{repo_ref}/pullreq/{pullreq_number}/commits", opListCommits)
opRawDiff := openapi3.Operation{}
opRawDiff.WithTags("pullreq")
opRawDiff.WithMapOfAnything(map[string]interface{}{"operationId": "rawPullReqDiff"})
_ = reflector.SetRequest(&opRawDiff, new(pullReqRequest), http.MethodGet)
_ = reflector.SetStringResponse(&opRawDiff, http.StatusOK, "text/plain")
_ = reflector.SetJSONResponse(&opRawDiff, new(usererror.Error), http.StatusInternalServerError)
_ = reflector.SetJSONResponse(&opRawDiff, new(usererror.Error), http.StatusUnauthorized)
_ = reflector.SetJSONResponse(&opRawDiff, new(usererror.Error), http.StatusForbidden)
_ = reflector.SetJSONResponse(&opRawDiff, new(usererror.Error), http.StatusNotFound)
_ = reflector.Spec.AddOperation(http.MethodGet, "/repos/{repo_ref}/pullreq/{pullreq_number}/diff", opRawDiff)
opMetaData := openapi3.Operation{}
opMetaData.WithTags("pullreq")
opMetaData.WithMapOfAnything(map[string]interface{}{"operationId": "pullReqMetaData"})

View File

@ -134,7 +134,7 @@ type deleteBranchRequest struct {
type createTagRequest struct {
repoRequest
repo.CreateTagInput
repo.CreateCommitTagInput
}
type listTagsRequest struct {

View File

@ -244,4 +244,60 @@ func spaceOperations(reflector *openapi3.Reflector) {
_ = reflector.SetJSONResponse(&onDeletePath, new(usererror.Error), http.StatusForbidden)
_ = reflector.SetJSONResponse(&onDeletePath, new(usererror.Error), http.StatusNotFound)
_ = reflector.Spec.AddOperation(http.MethodDelete, "/spaces/{space_ref}/paths/{path_id}", onDeletePath)
opMembershipAdd := openapi3.Operation{}
opMembershipAdd.WithTags("space")
opMembershipAdd.WithMapOfAnything(map[string]interface{}{"operationId": "membershipAdd"})
_ = reflector.SetRequest(&opMembershipAdd, struct {
spaceRequest
space.MembershipAddInput
}{}, http.MethodPost)
_ = reflector.SetJSONResponse(&opMembershipAdd, &types.Membership{}, http.StatusCreated)
_ = reflector.SetJSONResponse(&opMembershipAdd, new(usererror.Error), http.StatusInternalServerError)
_ = reflector.SetJSONResponse(&opMembershipAdd, new(usererror.Error), http.StatusUnauthorized)
_ = reflector.SetJSONResponse(&opMembershipAdd, new(usererror.Error), http.StatusForbidden)
_ = reflector.SetJSONResponse(&opMembershipAdd, new(usererror.Error), http.StatusNotFound)
_ = reflector.Spec.AddOperation(http.MethodPost, "/spaces/{space_ref}/members", opMembershipAdd)
opMembershipDelete := openapi3.Operation{}
opMembershipDelete.WithTags("space")
opMembershipDelete.WithMapOfAnything(map[string]interface{}{"operationId": "membershipDelete"})
_ = reflector.SetRequest(&opMembershipDelete, struct {
spaceRequest
UserUID string `path:"user_uid"`
}{}, http.MethodDelete)
_ = reflector.SetJSONResponse(&opMembershipDelete, nil, http.StatusNoContent)
_ = reflector.SetJSONResponse(&opMembershipDelete, new(usererror.Error), http.StatusInternalServerError)
_ = reflector.SetJSONResponse(&opMembershipDelete, new(usererror.Error), http.StatusUnauthorized)
_ = reflector.SetJSONResponse(&opMembershipDelete, new(usererror.Error), http.StatusForbidden)
_ = reflector.SetJSONResponse(&opMembershipDelete, new(usererror.Error), http.StatusNotFound)
_ = reflector.Spec.AddOperation(http.MethodDelete, "/spaces/{space_ref}/members/{user_uid}", opMembershipDelete)
opMembershipUpdate := openapi3.Operation{}
opMembershipUpdate.WithTags("space")
opMembershipUpdate.WithMapOfAnything(map[string]interface{}{"operationId": "membershipUpdate"})
_ = reflector.SetRequest(&opMembershipUpdate, &struct {
spaceRequest
UserUID string `path:"user_uid"`
space.MembershipUpdateInput
}{}, http.MethodPatch)
_ = reflector.SetJSONResponse(&opMembershipUpdate, &types.Membership{}, http.StatusOK)
_ = reflector.SetJSONResponse(&opMembershipUpdate, new(usererror.Error), http.StatusInternalServerError)
_ = reflector.SetJSONResponse(&opMembershipUpdate, new(usererror.Error), http.StatusUnauthorized)
_ = reflector.SetJSONResponse(&opMembershipUpdate, new(usererror.Error), http.StatusForbidden)
_ = reflector.SetJSONResponse(&opMembershipUpdate, new(usererror.Error), http.StatusNotFound)
_ = reflector.Spec.AddOperation(http.MethodPatch, "/spaces/{space_ref}/members/{user_uid}", opMembershipUpdate)
opMembershipList := openapi3.Operation{}
opMembershipList.WithTags("space")
opMembershipList.WithMapOfAnything(map[string]interface{}{"operationId": "membershipList"})
_ = reflector.SetRequest(&opMembershipList, &struct {
spaceRequest
}{}, http.MethodGet)
_ = reflector.SetJSONResponse(&opMembershipList, []types.Membership{}, http.StatusOK)
_ = reflector.SetJSONResponse(&opMembershipList, new(usererror.Error), http.StatusInternalServerError)
_ = reflector.SetJSONResponse(&opMembershipList, new(usererror.Error), http.StatusUnauthorized)
_ = reflector.SetJSONResponse(&opMembershipList, new(usererror.Error), http.StatusForbidden)
_ = reflector.SetJSONResponse(&opMembershipList, new(usererror.Error), http.StatusNotFound)
_ = reflector.Spec.AddOperation(http.MethodGet, "/spaces/{space_ref}/members", opMembershipList)
}

View File

@ -44,4 +44,12 @@ func buildUser(reflector *openapi3.Reflector) {
_ = reflector.SetJSONResponse(&opToken, new(types.TokenResponse), http.StatusCreated)
_ = reflector.SetJSONResponse(&opToken, new(usererror.Error), http.StatusInternalServerError)
_ = reflector.Spec.AddOperation(http.MethodPost, "/user/token", opToken)
opMemberSpaces := openapi3.Operation{}
opMemberSpaces.WithTags("user")
opMemberSpaces.WithMapOfAnything(map[string]interface{}{"operationId": "membershipSpaces"})
_ = reflector.SetRequest(&opMemberSpaces, struct{}{}, http.MethodGet)
_ = reflector.SetJSONResponse(&opMemberSpaces, new([]types.MembershipSpace), http.StatusOK)
_ = reflector.SetJSONResponse(&opMemberSpaces, new(usererror.Error), http.StatusInternalServerError)
_ = reflector.Spec.AddOperation(http.MethodGet, "/user/memberships", opMemberSpaces)
}

View File

@ -0,0 +1,30 @@
// Copyright 2022 Harness Inc. All rights reserved.
// Use of this source code is governed by the Polyform Free Trial License
// that can be found in the LICENSE.md file for this repository.
package request
import (
"net/http"
"github.com/harness/gitness/types"
"github.com/harness/gitness/types/enum"
)
// ParseMembershipSort extracts the membership sort parameter from the url.
func ParseMembershipSort(r *http.Request) enum.MembershipSort {
return enum.ParseMembershipSort(
r.URL.Query().Get(QueryParamSort),
)
}
// ParseMembershipFilter extracts the membership filter from the url.
func ParseMembershipFilter(r *http.Request) types.MembershipFilter {
return types.MembershipFilter{
Page: ParsePage(r),
Size: ParseLimit(r),
Query: ParseQuery(r),
Sort: ParseMembershipSort(r),
Order: ParseOrder(r),
}
}

View File

@ -0,0 +1,99 @@
// Copyright 2022 Harness Inc. All rights reserved.
// Use of this source code is governed by the Polyform Free Trial License
// that can be found in the LICENSE.md file for this repository.
package authz
import (
"context"
"github.com/harness/gitness/internal/auth"
"github.com/harness/gitness/internal/paths"
"github.com/harness/gitness/types"
"github.com/harness/gitness/types/enum"
"github.com/rs/zerolog/log"
)
var _ Authorizer = (*MembershipAuthorizer)(nil)
type MembershipAuthorizer struct {
permissionCache PermissionCache
}
func NewMembershipAuthorizer(
permissionCache PermissionCache,
) *MembershipAuthorizer {
return &MembershipAuthorizer{
permissionCache: permissionCache,
}
}
func (a *MembershipAuthorizer) Check(
ctx context.Context,
session *auth.Session,
scope *types.Scope,
resource *types.Resource,
permission enum.Permission,
) (bool, error) {
log.Ctx(ctx).Debug().Msgf(
"[MembershipAuthorizer] %s with id '%d' requests %s for %s '%s' in scope %#v with metadata %#v",
session.Principal.Type,
session.Principal.ID,
permission,
resource.Type,
resource.Name,
scope,
session.Metadata,
)
if session.Principal.Admin {
return true, nil // system admin can call any API
}
var spaceRef string
switch resource.Type {
case enum.ResourceTypeSpace:
spaceRef = paths.Concatinate(scope.SpacePath, resource.Name)
case enum.ResourceTypeRepo:
spaceRef = scope.SpacePath
case enum.ResourceTypeServiceAccount:
spaceRef = scope.SpacePath
case enum.ResourceTypeUser:
// a user is allowed to view / edit themselves
if resource.Name == session.Principal.UID &&
(permission == enum.PermissionUserView || permission == enum.PermissionUserEdit) {
return true, nil
}
// everything else is reserved for admins only (like operations on users other than yourself, or setting admin)
return false, nil
// Service operations aren't exposed to users
case enum.ResourceTypeService:
return false, nil
default:
return false, nil
}
return a.permissionCache.Get(ctx, PermissionCacheKey{
PrincipalID: session.Principal.ID,
SpaceRef: spaceRef,
Permission: permission,
})
}
func (a *MembershipAuthorizer) CheckAll(ctx context.Context, session *auth.Session,
permissionChecks ...types.PermissionCheck) (bool, error) {
for _, p := range permissionChecks {
if _, err := a.Check(ctx, session, &p.Scope, &p.Resource, p.Permission); err != nil {
return false, err
}
}
return true, nil
}

View File

@ -0,0 +1,91 @@
// Copyright 2022 Harness Inc. All rights reserved.
// Use of this source code is governed by the Polyform Free Trial License
// that can be found in the LICENSE.md file for this repository.
package authz
import (
"context"
"errors"
"fmt"
"time"
"github.com/harness/gitness/cache"
"github.com/harness/gitness/internal/paths"
"github.com/harness/gitness/internal/store"
gitness_store "github.com/harness/gitness/store"
"github.com/harness/gitness/types"
"github.com/harness/gitness/types/enum"
"golang.org/x/exp/slices"
)
type PermissionCacheKey struct {
PrincipalID int64
SpaceRef string
Permission enum.Permission
}
type PermissionCache cache.Cache[PermissionCacheKey, bool]
func NewPermissionCache(
spaceStore store.SpaceStore,
membershipStore store.MembershipStore,
cacheDuration time.Duration,
) PermissionCache {
return cache.New[PermissionCacheKey, bool](permissionCacheGetter{
spaceStore: spaceStore,
membershipStore: membershipStore,
}, cacheDuration)
}
type permissionCacheGetter struct {
spaceStore store.SpaceStore
membershipStore store.MembershipStore
}
func (g permissionCacheGetter) Find(ctx context.Context, key PermissionCacheKey) (bool, error) {
spaceRef := key.SpaceRef
principalID := key.PrincipalID
// Find the starting space.
space, err := g.spaceStore.FindByRef(ctx, spaceRef)
if err != nil {
return false, fmt.Errorf("failed to find space '%s': %w", spaceRef, err)
}
// limit the depth to be safe (e.g. root/space1/space2 => maxDepth of 3)
maxDepth := len(paths.Segments(spaceRef))
for depth := 0; depth < maxDepth; depth++ {
// Find the membership in the current space.
membership, err := g.membershipStore.Find(ctx, types.MembershipKey{
SpaceID: space.ID,
PrincipalID: principalID,
})
if err != nil && !errors.Is(err, gitness_store.ErrResourceNotFound) {
return false, fmt.Errorf("failed to find membership: %w", err)
}
// If the membership is defined in the current space, check if the user has the required permission.
if membership != nil {
_, hasRole := slices.BinarySearch(membership.Role.Permissions(), key.Permission)
if hasRole {
return true, nil
}
}
// If membership with the requested permission has not been found in the current space,
// move to the parent space, if any.
if space.ParentID == 0 {
return false, nil
}
space, err = g.spaceStore.Find(ctx, space.ParentID)
if err != nil {
return false, fmt.Errorf("failed to find parent space with id %d: %w", space.ParentID, err)
}
}
return false, nil
}

View File

@ -5,14 +5,27 @@
package authz
import (
"time"
"github.com/harness/gitness/internal/store"
"github.com/google/wire"
)
// WireSet provides a wire set for this package.
var WireSet = wire.NewSet(
ProvideAuthorizer,
ProvidePermissionCache,
)
func ProvideAuthorizer() Authorizer {
return NewUnsafeAuthorizer()
func ProvideAuthorizer(pCache PermissionCache) Authorizer {
return NewMembershipAuthorizer(pCache)
}
func ProvidePermissionCache(
spaceStore store.SpaceStore,
membershipStore store.MembershipStore,
) PermissionCache {
const permissionCacheTimeout = time.Second * 15
return NewPermissionCache(spaceStore, membershipStore, permissionCacheTimeout)
}

View File

@ -125,7 +125,7 @@ func setupRoutesV1(r chi.Router,
checkCtrl *check.Controller,
sysCtrl *system.Controller,
) {
setupSpaces(r, spaceCtrl, repoCtrl)
setupSpaces(r, spaceCtrl)
setupRepos(r, repoCtrl, pullreqCtrl, webhookCtrl, checkCtrl)
setupUser(r, userCtrl)
setupServiceAccounts(r, saCtrl)
@ -137,7 +137,7 @@ func setupRoutesV1(r chi.Router,
setupResources(r)
}
func setupSpaces(r chi.Router, spaceCtrl *space.Controller, repoCtrl *repo.Controller) {
func setupSpaces(r chi.Router, spaceCtrl *space.Controller) {
r.Route("/spaces", func(r chi.Router) {
// Create takes path and parentId via body, not uri
r.Post("/", handlerspace.HandleCreate(spaceCtrl))
@ -146,7 +146,7 @@ func setupSpaces(r chi.Router, spaceCtrl *space.Controller, repoCtrl *repo.Contr
// space operations
r.Get("/", handlerspace.HandleFind(spaceCtrl))
r.Patch("/", handlerspace.HandleUpdate(spaceCtrl))
r.Delete("/", handlerspace.HandleDelete(spaceCtrl, repoCtrl))
r.Delete("/", handlerspace.HandleDelete(spaceCtrl))
r.Post("/move", handlerspace.HandleMove(spaceCtrl))
r.Get("/spaces", handlerspace.HandleListSpaces(spaceCtrl))
@ -163,6 +163,15 @@ func setupSpaces(r chi.Router, spaceCtrl *space.Controller, repoCtrl *repo.Contr
r.Delete("/", handlerspace.HandleDeletePath(spaceCtrl))
})
})
r.Route("/members", func(r chi.Router) {
r.Get("/", handlerspace.HandleMembershipList(spaceCtrl))
r.Post("/", handlerspace.HandleMembershipAdd(spaceCtrl))
r.Route(fmt.Sprintf("/{%s}", request.PathParamUserUID), func(r chi.Router) {
r.Delete("/", handlerspace.HandleMembershipDelete(spaceCtrl))
r.Patch("/", handlerspace.HandleMembershipUpdate(spaceCtrl))
})
})
})
})
}
@ -304,7 +313,6 @@ func SetupPullReq(r chi.Router, pullreqCtrl *pullreq.Controller) {
r.Post("/", handlerpullreq.HandleReviewSubmit(pullreqCtrl))
})
r.Post("/merge", handlerpullreq.HandleMerge(pullreqCtrl))
r.Get("/diff", handlerpullreq.HandleRawDiff(pullreqCtrl))
r.Get("/commits", handlerpullreq.HandleCommits(pullreqCtrl))
r.Get("/metadata", handlerpullreq.HandleMetadata(pullreqCtrl))
})
@ -348,6 +356,7 @@ func setupUser(r chi.Router, userCtrl *user.Controller) {
r.Use(middlewareprincipal.RestrictTo(enum.PrincipalTypeUser))
r.Get("/", handleruser.HandleFind(userCtrl))
r.Patch("/", handleruser.HandleUpdate(userCtrl))
r.Get("/memberships", handleruser.HandleMembershipSpaces(userCtrl))
// PAT
r.Route("/tokens", func(r chi.Router) {

View File

@ -24,6 +24,21 @@ import (
func (s *Service) triggerPREventOnBranchUpdate(ctx context.Context,
event *events.Event[*gitevents.BranchUpdatedPayload],
) error {
// we should always update PR mergeable status check when target branch is updated.
// - main
// |- develop
// |- feature1
// |- feature2
// when feature2 merge changes into develop branch then feature1 branch is not consistent anymore
// and need to run mergeable check even nothing was changed on feature1, same applies to main if someone
// push new commit to main then develop should merge status should be unchecked.
if branch, err := getBranchFromRef(event.Payload.Ref); err == nil {
err = s.pullreqStore.UpdateMergeCheckStatus(ctx, event.Payload.RepoID, branch, enum.MergeCheckStatusUnchecked)
if err != nil {
return err
}
}
// TODO: This function is currently executed directly on branch update event.
// TODO: But it should be executed after the PR's head ref has been updated.
// TODO: This is to make sure the commit exists on the target repository for forked repositories.
@ -148,17 +163,11 @@ func (s *Service) forEveryOpenPR(ctx context.Context,
repoID int64, ref string,
fn func(pr *types.PullReq) error,
) {
const refPrefix = "refs/heads/"
const largeLimit = 1000000
if !strings.HasPrefix(ref, refPrefix) {
log.Ctx(ctx).Error().Msg("failed to get branch name from branch ref")
return
}
branch := ref[len(refPrefix):]
branch, err := getBranchFromRef(ref)
if len(branch) == 0 {
log.Ctx(ctx).Error().Msg("got an empty branch name from branch ref")
log.Ctx(ctx).Err(err).Send()
return
}
@ -182,3 +191,16 @@ func (s *Service) forEveryOpenPR(ctx context.Context,
}
}
}
func getBranchFromRef(ref string) (string, error) {
const refPrefix = "refs/heads/"
if !strings.HasPrefix(ref, refPrefix) {
return "", fmt.Errorf("failed to get branch name from branch ref %s", ref)
}
branch := ref[len(refPrefix):]
if len(branch) == 0 {
return "", fmt.Errorf("got an empty branch name from branch ref %s", ref)
}
return branch, nil
}

View File

@ -60,8 +60,8 @@ type (
// ListUsers returns a list of users.
ListUsers(ctx context.Context, params *types.UserFilter) ([]*types.User, error)
// CountUsers returns a count of users.
CountUsers(ctx context.Context) (int64, error)
// CountUsers returns a count of users which match the given filter.
CountUsers(ctx context.Context, opts *types.UserFilter) (int64, error)
/*
* SERVICE ACCOUNT RELATED OPERATIONS.
@ -187,7 +187,7 @@ type (
Count(ctx context.Context, id int64, opts *types.SpaceFilter) (int64, error)
// List returns a list of child spaces in a space.
List(ctx context.Context, id int64, opts *types.SpaceFilter) ([]*types.Space, error)
List(ctx context.Context, id int64, opts *types.SpaceFilter) ([]types.Space, error)
}
// RepoStore defines the repository data storage.
@ -223,6 +223,18 @@ type (
Find(ctx context.Context, id int64) (*types.RepositoryGitInfo, error)
}
// MembershipStore defines the membership data storage.
MembershipStore interface {
Find(ctx context.Context, key types.MembershipKey) (*types.Membership, error)
FindUser(ctx context.Context, key types.MembershipKey) (*types.MembershipUser, error)
Create(ctx context.Context, membership *types.Membership) error
Update(ctx context.Context, membership *types.Membership) error
Delete(ctx context.Context, key types.MembershipKey) error
CountUsers(ctx context.Context, spaceID int64, filter types.MembershipFilter) (int64, error)
ListUsers(ctx context.Context, spaceID int64, filter types.MembershipFilter) ([]types.MembershipUser, error)
ListSpaces(ctx context.Context, userID int64) ([]types.MembershipSpace, error)
}
// TokenStore defines the token data storage.
TokenStore interface {
// Find finds the token by id
@ -273,6 +285,9 @@ type (
// It will set new values to the ActivitySeq, Version and Updated fields.
UpdateActivitySeq(ctx context.Context, pr *types.PullReq) (*types.PullReq, error)
// Update all PR where target branch points to new SHA
UpdateMergeCheckStatus(ctx context.Context, targetRepo int64, targetBranch string, status enum.MergeCheckStatus) error
// Delete the pull request.
Delete(ctx context.Context, id int64) error

View File

@ -0,0 +1,409 @@
// Copyright 2022 Harness Inc. All rights reserved.
// Use of this source code is governed by the Polyform Free Trial License
// that can be found in the LICENSE.md file for this repository.
package database
import (
"context"
"fmt"
"strings"
"time"
"github.com/harness/gitness/internal/store"
"github.com/harness/gitness/store/database"
"github.com/harness/gitness/store/database/dbtx"
"github.com/harness/gitness/types"
"github.com/harness/gitness/types/enum"
"github.com/Masterminds/squirrel"
"github.com/jmoiron/sqlx"
)
var _ store.MembershipStore = (*MembershipStore)(nil)
// NewMembershipStore returns a new MembershipStore.
func NewMembershipStore(db *sqlx.DB, pCache store.PrincipalInfoCache) *MembershipStore {
return &MembershipStore{
db: db,
pCache: pCache,
}
}
// MembershipStore implements store.MembershipStore backed by a relational database.
type MembershipStore struct {
db *sqlx.DB
pCache store.PrincipalInfoCache
}
type membership struct {
SpaceID int64 `db:"membership_space_id"`
PrincipalID int64 `db:"membership_principal_id"`
CreatedBy int64 `db:"membership_created_by"`
Created int64 `db:"membership_created"`
Updated int64 `db:"membership_updated"`
Role enum.MembershipRole `db:"membership_role"`
}
type membershipPrincipal struct {
membership
principalInfo
}
type membershipSpace struct {
membership
space
}
const (
membershipColumns = `
membership_space_id
,membership_principal_id
,membership_created_by
,membership_created
,membership_updated
,membership_role`
membershipSelectBase = `
SELECT` + membershipColumns + `
FROM memberships`
)
// Find finds the membership by space id and principal id.
func (s *MembershipStore) Find(ctx context.Context, key types.MembershipKey) (*types.Membership, error) {
const sqlQuery = membershipSelectBase + `
WHERE membership_space_id = $1 AND membership_principal_id = $2`
db := dbtx.GetAccessor(ctx, s.db)
dst := &membership{}
if err := db.GetContext(ctx, dst, sqlQuery, key.SpaceID, key.PrincipalID); err != nil {
return nil, database.ProcessSQLErrorf(err, "Failed to find membership")
}
result := mapToMembership(dst)
return &result, nil
}
func (s *MembershipStore) FindUser(ctx context.Context, key types.MembershipKey) (*types.MembershipUser, error) {
m, err := s.Find(ctx, key)
if err != nil {
return nil, err
}
result, err := s.addPrincipalInfos(ctx, m)
if err != nil {
return nil, err
}
return &result, nil
}
// Create creates a new membership.
func (s *MembershipStore) Create(ctx context.Context, membership *types.Membership) error {
const sqlQuery = `
INSERT INTO memberships (
membership_space_id
,membership_principal_id
,membership_created_by
,membership_created
,membership_updated
,membership_role
) values (
:membership_space_id
,:membership_principal_id
,:membership_created_by
,:membership_created
,:membership_updated
,:membership_role
)`
db := dbtx.GetAccessor(ctx, s.db)
query, arg, err := db.BindNamed(sqlQuery, mapToInternalMembership(membership))
if err != nil {
return database.ProcessSQLErrorf(err, "Failed to bind membership object")
}
if _, err = db.ExecContext(ctx, query, arg...); err != nil {
return database.ProcessSQLErrorf(err, "Failed to insert membership")
}
return nil
}
// Update updates the role of a member of a space.
func (s *MembershipStore) Update(ctx context.Context, membership *types.Membership) error {
const sqlQuery = `
UPDATE memberships
SET
membership_updated = :membership_updated
,membership_role = :membership_role
WHERE membership_space_id = :membership_space_id AND
membership_principal_id = :membership_principal_id`
db := dbtx.GetAccessor(ctx, s.db)
dbMembership := mapToInternalMembership(membership)
dbMembership.Updated = time.Now().UnixMilli()
query, arg, err := db.BindNamed(sqlQuery, dbMembership)
if err != nil {
return database.ProcessSQLErrorf(err, "Failed to bind membership object")
}
_, err = db.ExecContext(ctx, query, arg...)
if err != nil {
return database.ProcessSQLErrorf(err, "Failed to update membership role")
}
membership.Updated = dbMembership.Updated
return nil
}
// Delete deletes the membership.
func (s *MembershipStore) Delete(ctx context.Context, key types.MembershipKey) error {
const sqlQuery = `
DELETE from memberships
WHERE membership_space_id = $1 AND
membership_principal_id = $2`
db := dbtx.GetAccessor(ctx, s.db)
if _, err := db.ExecContext(ctx, sqlQuery, key.SpaceID, key.PrincipalID); err != nil {
return database.ProcessSQLErrorf(err, "delete membership query failed")
}
return nil
}
// CountUsers returns a number of users memberships that matches the provided filter.
func (s *MembershipStore) CountUsers(ctx context.Context,
spaceID int64,
filter types.MembershipFilter,
) (int64, error) {
stmt := database.Builder.
Select("count(*)").
From("memberships").
InnerJoin("principals ON membership_principal_id = principal_id").
Where("membership_space_id = ?", spaceID)
stmt = prepareMembershipListUsersStmt(stmt, filter)
sql, args, err := stmt.ToSql()
if err != nil {
return 0, fmt.Errorf("failed to convert membership count query to sql: %w", err)
}
db := dbtx.GetAccessor(ctx, s.db)
var count int64
err = db.QueryRowContext(ctx, sql, args...).Scan(&count)
if err != nil {
return 0, database.ProcessSQLErrorf(err, "Failed executing membership count query")
}
return count, nil
}
// ListUsers returns a list of memberships for a space or a user.
func (s *MembershipStore) ListUsers(ctx context.Context,
spaceID int64,
filter types.MembershipFilter,
) ([]types.MembershipUser, error) {
const columns = membershipColumns + "," + principalInfoCommonColumns
stmt := database.Builder.
Select(columns).
From("memberships").
InnerJoin("principals ON membership_principal_id = principal_id").
Where("membership_space_id = ?", spaceID)
stmt = prepareMembershipListUsersStmt(stmt, filter)
stmt = stmt.Limit(database.Limit(filter.Size))
stmt = stmt.Offset(database.Offset(filter.Page, filter.Size))
order := filter.Order
if order == enum.OrderDefault {
order = enum.OrderAsc
}
switch filter.Sort {
case enum.MembershipSortName:
stmt = stmt.OrderBy("principal_display_name " + order.String())
case enum.MembershipSortCreated:
stmt = stmt.OrderBy("membership_created " + order.String())
case enum.MembershipSortNone:
}
sql, args, err := stmt.ToSql()
if err != nil {
return nil, fmt.Errorf("failed to convert membership users list query to sql: %w", err)
}
dst := make([]*membershipPrincipal, 0)
db := dbtx.GetAccessor(ctx, s.db)
if err = db.SelectContext(ctx, &dst, sql, args...); err != nil {
return nil, database.ProcessSQLErrorf(err, "Failed executing membership users list query")
}
result, err := s.mapToMembershipUsers(ctx, dst)
if err != nil {
return nil, fmt.Errorf("failed to map memberships users to external type: %w", err)
}
return result, nil
}
func prepareMembershipListUsersStmt(
stmt squirrel.SelectBuilder,
opts types.MembershipFilter,
) squirrel.SelectBuilder {
if opts.Query != "" {
searchTerm := "%%" + strings.ToLower(opts.Query) + "%%"
stmt = stmt.Where("LOWER(principal_display_name) LIKE ?", searchTerm)
}
return stmt
}
// ListSpaces returns a list of spaces in which the provided user is a member.
func (s *MembershipStore) ListSpaces(ctx context.Context,
userID int64,
) ([]types.MembershipSpace, error) {
const columns = membershipColumns + "," + spaceColumnsForJoin
stmt := database.Builder.
Select(columns).
From("memberships").
InnerJoin("spaces ON spaces.space_id = membership_space_id").
InnerJoin(`paths ON spaces.space_id=paths.path_space_id AND paths.path_is_primary=true`).
Where("membership_principal_id = ?", userID).
OrderBy("space_path asc")
sql, args, err := stmt.ToSql()
if err != nil {
return nil, fmt.Errorf("failed to convert membership spaces list query to sql: %w", err)
}
db := dbtx.GetAccessor(ctx, s.db)
dst := make([]*membershipSpace, 0)
if err = db.SelectContext(ctx, &dst, sql, args...); err != nil {
return nil, database.ProcessSQLErrorf(err, "Failed executing custom list query")
}
result, err := s.mapToMembershipSpaces(ctx, dst)
if err != nil {
return nil, fmt.Errorf("failed to map memberships spaces to external type: %w", err)
}
return result, nil
}
func mapToMembership(m *membership) types.Membership {
return types.Membership{
MembershipKey: types.MembershipKey{
SpaceID: m.SpaceID,
PrincipalID: m.PrincipalID,
},
CreatedBy: m.CreatedBy,
Created: m.Created,
Updated: m.Updated,
Role: m.Role,
}
}
func mapToInternalMembership(m *types.Membership) membership {
return membership{
SpaceID: m.SpaceID,
PrincipalID: m.PrincipalID,
CreatedBy: m.CreatedBy,
Created: m.Created,
Updated: m.Updated,
Role: m.Role,
}
}
func (s *MembershipStore) addPrincipalInfos(ctx context.Context, m *types.Membership) (types.MembershipUser, error) {
var result types.MembershipUser
// pull principal infos from cache
infoMap, err := s.pCache.Map(ctx, []int64{m.CreatedBy, m.PrincipalID})
if err != nil {
return result, fmt.Errorf("failed to load membership principal infos: %w", err)
}
if user, ok := infoMap[m.PrincipalID]; ok {
result.Principal = *user
} else {
return result, fmt.Errorf("failed to find membership principal info: %w", err)
}
if addedBy, ok := infoMap[m.CreatedBy]; ok {
result.AddedBy = *addedBy
}
result.Membership = *m
return result, nil
}
func (s *MembershipStore) mapToMembershipUsers(ctx context.Context,
ms []*membershipPrincipal,
) ([]types.MembershipUser, error) {
// collect all principal IDs
ids := make([]int64, 0, len(ms))
for _, m := range ms {
ids = append(ids, m.membership.CreatedBy)
}
// pull principal infos from cache
infoMap, err := s.pCache.Map(ctx, ids)
if err != nil {
return nil, fmt.Errorf("failed to load membership principal infos: %w", err)
}
// attach the principal infos back to the slice items
res := make([]types.MembershipUser, len(ms))
for i, m := range ms {
res[i].Membership = mapToMembership(&m.membership)
res[i].Principal = mapToPrincipalInfo(&m.principalInfo)
if addedBy, ok := infoMap[m.membership.CreatedBy]; ok {
res[i].AddedBy = *addedBy
}
}
return res, nil
}
func (s *MembershipStore) mapToMembershipSpaces(ctx context.Context,
ms []*membershipSpace,
) ([]types.MembershipSpace, error) {
// collect all principal IDs
ids := make([]int64, 0, len(ms))
for _, m := range ms {
ids = append(ids, m.membership.CreatedBy)
}
// pull principal infos from cache
infoMap, err := s.pCache.Map(ctx, ids)
if err != nil {
return nil, fmt.Errorf("failed to load membership principal infos: %w", err)
}
// attach the principal infos back to the slice items
res := make([]types.MembershipSpace, len(ms))
for i, m := range ms {
res[i].Membership = mapToMembership(&m.membership)
res[i].Space = mapToSpace(&m.space)
if addedBy, ok := infoMap[m.membership.CreatedBy]; ok {
res[i].AddedBy = *addedBy
}
}
return res, nil
}

View File

@ -0,0 +1,2 @@
DROP TABLE memberships;

View File

@ -0,0 +1,21 @@
CREATE TABLE memberships (
membership_space_id INTEGER NOT NULL
,membership_principal_id INTEGER NOT NULL
,membership_created_by INTEGER NOT NULL
,membership_created BIGINT NOT NULL
,membership_updated BIGINT NOT NULL
,membership_role TEXT NOT NULL
,CONSTRAINT pk_memberships PRIMARY KEY (membership_space_id, membership_principal_id)
,CONSTRAINT fk_membership_space_id FOREIGN KEY (membership_space_id)
REFERENCES spaces (space_id) MATCH SIMPLE
ON UPDATE NO ACTION
ON DELETE CASCADE
,CONSTRAINT fk_membership_principal_id FOREIGN KEY (membership_principal_id)
REFERENCES principals (principal_id) MATCH SIMPLE
ON UPDATE NO ACTION
ON DELETE CASCADE
,CONSTRAINT fk_membership_created_by FOREIGN KEY (membership_created_by)
REFERENCES principals (principal_id) MATCH SIMPLE
ON UPDATE NO ACTION
ON DELETE NO ACTION
);

View File

@ -0,0 +1,2 @@
DROP TABLE memberships;

View File

@ -0,0 +1,21 @@
CREATE TABLE memberships (
membership_space_id INTEGER NOT NULL
,membership_principal_id INTEGER NOT NULL
,membership_created_by INTEGER NOT NULL
,membership_created BIGINT NOT NULL
,membership_updated BIGINT NOT NULL
,membership_role TEXT NOT NULL
,CONSTRAINT pk_memberships PRIMARY KEY (membership_space_id, membership_principal_id)
,CONSTRAINT fk_membership_space_id FOREIGN KEY (membership_space_id)
REFERENCES spaces (space_id) MATCH SIMPLE
ON UPDATE NO ACTION
ON DELETE CASCADE
,CONSTRAINT fk_membership_principal_id FOREIGN KEY (membership_principal_id)
REFERENCES principals (principal_id) MATCH SIMPLE
ON UPDATE NO ACTION
ON DELETE CASCADE
,CONSTRAINT fk_membership_created_by FOREIGN KEY (membership_created_by)
REFERENCES principals (principal_id) MATCH SIMPLE
ON UPDATE NO ACTION
ON DELETE NO ACTION
);

View File

@ -11,6 +11,7 @@ import (
"github.com/harness/gitness/store/database"
"github.com/harness/gitness/store/database/dbtx"
"github.com/harness/gitness/types"
"github.com/harness/gitness/types/enum"
"github.com/Masterminds/squirrel"
"github.com/jmoiron/sqlx"
@ -32,15 +33,25 @@ type PrincipalInfoView struct {
const (
principalInfoCommonColumns = `
principal_id,
principal_uid,
principal_email,
principal_display_name,
principal_type,
principal_created,
principal_updated`
principal_id
,principal_uid
,principal_email
,principal_display_name
,principal_type
,principal_created
,principal_updated`
)
type principalInfo struct {
ID int64 `db:"principal_id"`
UID string `db:"principal_uid"`
DisplayName string `db:"principal_display_name"`
Email string `db:"principal_email"`
Type enum.PrincipalType `db:"principal_type"`
Created int64 `db:"principal_created"`
Updated int64 `db:"principal_updated"`
}
// Find returns a single principal info object by id from the `principals` database table.
func (s *PrincipalInfoView) Find(ctx context.Context, id int64) (*types.PrincipalInfo, error) {
const sqlQuery = `
@ -107,3 +118,15 @@ func (s *PrincipalInfoView) FindMany(ctx context.Context, ids []int64) ([]*types
return result, nil
}
func mapToPrincipalInfo(p *principalInfo) types.PrincipalInfo {
return types.PrincipalInfo{
ID: p.ID,
UID: p.UID,
DisplayName: p.DisplayName,
Email: p.Email,
Type: p.Type,
Created: p.Created,
Updated: p.Updated,
}
}

View File

@ -104,7 +104,7 @@ func testUserDuplicate(store store.PrincipalStore) func(t *testing.T) {
// and compares to the expected count.
func testUserCount(store store.PrincipalStore) func(t *testing.T) {
return func(t *testing.T) {
got, err := store.CountUsers(context.Background())
got, err := store.CountUsers(context.Background(), &types.UserFilter{})
if err != nil {
t.Error(err)
return

View File

@ -224,17 +224,26 @@ func (s *PrincipalStore) ListUsers(ctx context.Context, opts *types.UserFilter)
return s.mapDBUsers(dst), nil
}
// CountUsers returns a count of users.
func (s *PrincipalStore) CountUsers(ctx context.Context) (int64, error) {
const sqlQuery = `
SELECT count(*)
FROM principals
WHERE principal_type = 'user'`
// CountUsers returns a count of users matching the given filter.
func (s *PrincipalStore) CountUsers(ctx context.Context, opts *types.UserFilter) (int64, error) {
stmt := database.Builder.
Select("count(*)").
From("principals").
Where("principal_type = 'user'")
if opts.Admin {
stmt = stmt.Where("principal_admin = ?", opts.Admin)
}
sql, args, err := stmt.ToSql()
if err != nil {
return 0, errors.Wrap(err, "Failed to convert query to sql")
}
db := dbtx.GetAccessor(ctx, s.db)
var count int64
err := db.QueryRowContext(ctx, sqlQuery).Scan(&count)
err = db.QueryRowContext(ctx, sql, args...).Scan(&count)
if err != nil {
return 0, database.ProcessSQLErrorf(err, "Failed executing count query")
}

View File

@ -335,6 +335,36 @@ func (s *PullReqStore) UpdateActivitySeq(ctx context.Context, pr *types.PullReq)
})
}
// UpdateMergeCheckStatus updates the pull request's mergeability status
// for all pr which target branch points to targetBranch.
func (s *PullReqStore) UpdateMergeCheckStatus(
ctx context.Context,
targetRepo int64,
targetBranch string,
status enum.MergeCheckStatus,
) error {
const query = `
UPDATE pullreqs
SET
pullreq_updated = $1
,pullreq_merge_check_status = $2
WHERE pullreq_target_repo_id = $3 AND
pullreq_target_branch = $4 AND
pullreq_state not in ($5, $6)`
db := dbtx.GetAccessor(ctx, s.db)
updatedAt := time.Now()
_, err := db.ExecContext(ctx, query, updatedAt, status, targetRepo, targetBranch,
enum.PullReqStateClosed, enum.PullReqStateClosed)
if err != nil {
return database.ProcessSQLErrorf(err, "Failed to update mergeable status check %s in pull requests", status)
}
return nil
}
// Delete the pull request.
func (s *PullReqStore) Delete(ctx context.Context, id int64) error {
const pullReqDelete = `DELETE FROM pullreqs WHERE pullreq_id = $1`

View File

@ -86,7 +86,9 @@ func (s *SpaceStore) Find(ctx context.Context, id int64) (*types.Space, error) {
return nil, database.ProcessSQLErrorf(err, "Failed to find space")
}
return mapToSpace(dst), nil
result := mapToSpace(dst)
return &result, nil
}
// FindByRef finds the space using the spaceRef as either the id or the space path.
@ -113,6 +115,10 @@ func (s *SpaceStore) FindByRef(ctx context.Context, spaceRef string) (*types.Spa
// Create a new space.
func (s *SpaceStore) Create(ctx context.Context, space *types.Space) error {
if space == nil {
return errors.New("space is nil")
}
const sqlQuery = `
INSERT INTO spaces (
space_version
@ -134,14 +140,9 @@ func (s *SpaceStore) Create(ctx context.Context, space *types.Space) error {
,:space_updated
) RETURNING space_id`
dbSpace, err := mapToInternalSpace(space)
if err != nil {
return fmt.Errorf("failed to map space: %w", err)
}
db := dbtx.GetAccessor(ctx, s.db)
query, args, err := db.BindNamed(sqlQuery, dbSpace)
query, args, err := db.BindNamed(sqlQuery, mapToInternalSpace(space))
if err != nil {
return database.ProcessSQLErrorf(err, "Failed to bind space object")
}
@ -153,8 +154,12 @@ func (s *SpaceStore) Create(ctx context.Context, space *types.Space) error {
return nil
}
// Updates the space details.
// Update updates the space details.
func (s *SpaceStore) Update(ctx context.Context, space *types.Space) error {
if space == nil {
return errors.New("space is nil")
}
const sqlQuery = `
UPDATE spaces
SET
@ -166,10 +171,7 @@ func (s *SpaceStore) Update(ctx context.Context, space *types.Space) error {
,space_is_public = :space_is_public
WHERE space_id = :space_id AND space_version = :space_version - 1`
dbSpace, err := mapToInternalSpace(space)
if err != nil {
return fmt.Errorf("failed to map space: %w", err)
}
dbSpace := mapToInternalSpace(space)
// update Version (used for optimistic locking) and Updated time
dbSpace.Version++
@ -205,7 +207,8 @@ func (s *SpaceStore) Update(ctx context.Context, space *types.Space) error {
// UpdateOptLock updates the space using the optimistic locking mechanism.
func (s *SpaceStore) UpdateOptLock(ctx context.Context,
space *types.Space,
mutateFn func(space *types.Space) error) (*types.Space, error) {
mutateFn func(space *types.Space) error,
) (*types.Space, error) {
for {
dup := *space
@ -229,7 +232,7 @@ func (s *SpaceStore) UpdateOptLock(ctx context.Context,
}
}
// Deletes the space.
// Delete deletes a space.
func (s *SpaceStore) Delete(ctx context.Context, id int64) error {
const sqlQuery = `
DELETE FROM spaces
@ -271,7 +274,7 @@ func (s *SpaceStore) Count(ctx context.Context, id int64, opts *types.SpaceFilte
}
// List returns a list of spaces under the parent space.
func (s *SpaceStore) List(ctx context.Context, id int64, opts *types.SpaceFilter) ([]*types.Space, error) {
func (s *SpaceStore) List(ctx context.Context, id int64, opts *types.SpaceFilter) ([]types.Space, error) {
stmt := database.Builder.
Select(spaceColumnsForJoin).
From("spaces").
@ -310,7 +313,7 @@ func (s *SpaceStore) List(ctx context.Context, id int64, opts *types.SpaceFilter
db := dbtx.GetAccessor(ctx, s.db)
dst := []*space{}
var dst []*space
if err = db.SelectContext(ctx, &dst, sql, args...); err != nil {
return nil, database.ProcessSQLErrorf(err, "Failed executing custom list query")
}
@ -318,8 +321,8 @@ func (s *SpaceStore) List(ctx context.Context, id int64, opts *types.SpaceFilter
return mapToSpaces(dst), nil
}
func mapToSpace(s *space) *types.Space {
res := &types.Space{
func mapToSpace(s *space) types.Space {
res := types.Space{
ID: s.ID,
Version: s.Version,
UID: s.UID,
@ -339,21 +342,16 @@ func mapToSpace(s *space) *types.Space {
return res
}
func mapToSpaces(spaces []*space) []*types.Space {
res := make([]*types.Space, len(spaces))
func mapToSpaces(spaces []*space) []types.Space {
res := make([]types.Space, len(spaces))
for i := range spaces {
res[i] = mapToSpace(spaces[i])
}
return res
}
func mapToInternalSpace(s *types.Space) (*space, error) {
// space comes from outside.
if s == nil {
return nil, fmt.Errorf("space is nil")
}
res := &space{
func mapToInternalSpace(s *types.Space) space {
res := space{
ID: s.ID,
Version: s.Version,
UID: s.UID,
@ -371,5 +369,5 @@ func mapToInternalSpace(s *types.Space) (*space, error) {
res.ParentID = null.IntFrom(s.ParentID)
}
return res, nil
return res
}

View File

@ -24,6 +24,7 @@ var WireSet = wire.NewSet(
ProvideSpaceStore,
ProvideRepoStore,
ProvideRepoGitInfoView,
ProvideMembershipStore,
ProvideTokenStore,
ProvidePullReqStore,
ProvidePullReqActivityStore,
@ -36,7 +37,7 @@ var WireSet = wire.NewSet(
ProvideReqCheckStore,
)
// helper function to setup the database by performing automated
// migrator is helper function to set up the database by performing automated
// database migration steps.
func migrator(ctx context.Context, db *sqlx.DB) error {
return migrate.Migrate(ctx, db)
@ -82,6 +83,13 @@ func ProvideRepoGitInfoView(db *sqlx.DB) store.RepoGitInfoView {
return NewRepoGitInfoView(db)
}
func ProvideMembershipStore(
db *sqlx.DB,
principalInfoCache store.PrincipalInfoCache,
) store.MembershipStore {
return NewMembershipStore(db, principalInfoCache)
}
// ProvideTokenStore provides a token store.
func ProvideTokenStore(db *sqlx.DB) store.TokenStore {
return NewTokenStore(db)
@ -89,13 +97,15 @@ func ProvideTokenStore(db *sqlx.DB) store.TokenStore {
// ProvidePullReqStore provides a pull request store.
func ProvidePullReqStore(db *sqlx.DB,
principalInfoCache store.PrincipalInfoCache) store.PullReqStore {
principalInfoCache store.PrincipalInfoCache,
) store.PullReqStore {
return NewPullReqStore(db, principalInfoCache)
}
// ProvidePullReqActivityStore provides a pull request activity store.
func ProvidePullReqActivityStore(db *sqlx.DB,
principalInfoCache store.PrincipalInfoCache) store.PullReqActivityStore {
principalInfoCache store.PrincipalInfoCache,
) store.PullReqActivityStore {
return NewPullReqActivityStore(db, principalInfoCache)
}
@ -111,7 +121,8 @@ func ProvidePullReqReviewStore(db *sqlx.DB) store.PullReqReviewStore {
// ProvidePullReqReviewerStore provides a pull request reviewer store.
func ProvidePullReqReviewerStore(db *sqlx.DB,
principalInfoCache store.PrincipalInfoCache) store.PullReqReviewerStore {
principalInfoCache store.PrincipalInfoCache,
) store.PullReqReviewerStore {
return NewPullReqReviewerStore(db, principalInfoCache)
}

View File

@ -27,12 +27,17 @@ type JWTClaims struct {
// GenerateJWTForToken generates a jwt for a given token.
func GenerateJWTForToken(token *types.Token, secret string) (string, error) {
var expiresAt int64
if token.ExpiresAt != nil {
expiresAt = *token.ExpiresAt
}
jwtToken := jwt.NewWithClaims(jwt.SigningMethodHS256, JWTClaims{
jwt.StandardClaims{
Issuer: issuer,
// times required to be in sec not millisec
IssuedAt: token.IssuedAt / 1000,
ExpiresAt: token.ExpiresAt / 1000,
ExpiresAt: expiresAt / 1000,
},
token.Type,
token.ID,

View File

@ -12,6 +12,8 @@ import (
"github.com/harness/gitness/internal/store"
"github.com/harness/gitness/types"
"github.com/harness/gitness/types/enum"
"github.com/gotidy/ptr"
)
const (
@ -28,14 +30,14 @@ func CreateUserSession(ctx context.Context, tokenStore store.TokenStore,
principal,
principal,
uid,
userTokenLifeTime,
ptr.Duration(userTokenLifeTime),
enum.AccessGrantAll,
)
}
func CreatePAT(ctx context.Context, tokenStore store.TokenStore,
createdBy *types.Principal, createdFor *types.User,
uid string, lifetime time.Duration, grants enum.AccessGrant) (*types.Token, string, error) {
uid string, lifetime *time.Duration, grants enum.AccessGrant) (*types.Token, string, error) {
return Create(
ctx,
tokenStore,
@ -50,7 +52,7 @@ func CreatePAT(ctx context.Context, tokenStore store.TokenStore,
func CreateSAT(ctx context.Context, tokenStore store.TokenStore,
createdBy *types.Principal, createdFor *types.ServiceAccount,
uid string, lifetime time.Duration, grants enum.AccessGrant) (*types.Token, string, error) {
uid string, lifetime *time.Duration, grants enum.AccessGrant) (*types.Token, string, error) {
return Create(
ctx,
tokenStore,
@ -65,9 +67,13 @@ func CreateSAT(ctx context.Context, tokenStore store.TokenStore,
func Create(ctx context.Context, tokenStore store.TokenStore,
tokenType enum.TokenType, createdBy *types.Principal, createdFor *types.Principal,
uid string, lifetime time.Duration, grants enum.AccessGrant) (*types.Token, string, error) {
uid string, lifetime *time.Duration, grants enum.AccessGrant) (*types.Token, string, error) {
issuedAt := time.Now()
expiresAt := issuedAt.Add(lifetime)
var expiresAt *int64
if lifetime != nil {
expiresAt = ptr.Int64(issuedAt.Add(*lifetime).UnixMilli())
}
// create db entry first so we get the id.
token := types.Token{
@ -75,7 +81,7 @@ func Create(ctx context.Context, tokenStore store.TokenStore,
UID: uid,
PrincipalID: createdFor.ID,
IssuedAt: issuedAt.UnixMilli(),
ExpiresAt: expiresAt.UnixMilli(),
ExpiresAt: expiresAt,
Grants: grants,
CreatedBy: createdBy.ID,
}

View File

@ -69,7 +69,7 @@ func (m *InMemory) NewMutex(key string, options ...Option) (Mutex, error) {
// https://github.com/go-redsync/redsync/blob/e1e5da6654c81a2069d6a360f1a31c21f05cd22d/mutex.go#LL81C4-L81C100
waitTime := config.Expiry
if config.TimeoutFactor > 0 {
waitTime *= time.Duration(int64(float64(config.Expiry) * config.TimeoutFactor))
waitTime = time.Duration(int64(float64(config.Expiry) * config.TimeoutFactor))
}
lock := inMemMutex{

View File

@ -37,33 +37,33 @@ func (m *MockClient) EXPECT() *MockClientMockRecorder {
}
// Login mocks base method.
func (m *MockClient) Login(arg0 context.Context, arg1, arg2 string) (*types.TokenResponse, error) {
func (m *MockClient) Login(arg0 context.Context, arg1 *user.LoginInput) (*types.TokenResponse, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Login", arg0, arg1, arg2)
ret := m.ctrl.Call(m, "Login", arg0, arg1)
ret0, _ := ret[0].(*types.TokenResponse)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// Login indicates an expected call of Login.
func (mr *MockClientMockRecorder) Login(arg0, arg1, arg2 interface{}) *gomock.Call {
func (mr *MockClientMockRecorder) Login(arg0, arg1 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Login", reflect.TypeOf((*MockClient)(nil).Login), arg0, arg1, arg2)
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Login", reflect.TypeOf((*MockClient)(nil).Login), arg0, arg1)
}
// Register mocks base method.
func (m *MockClient) Register(arg0 context.Context, arg1, arg2, arg3, arg4 string) (*types.TokenResponse, error) {
func (m *MockClient) Register(arg0 context.Context, arg1 *user.RegisterInput) (*types.TokenResponse, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Register", arg0, arg1, arg2, arg3, arg4)
ret := m.ctrl.Call(m, "Register", arg0, arg1)
ret0, _ := ret[0].(*types.TokenResponse)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// Register indicates an expected call of Register.
func (mr *MockClientMockRecorder) Register(arg0, arg1, arg2, arg3, arg4 interface{}) *gomock.Call {
func (mr *MockClientMockRecorder) Register(arg0, arg1 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Register", reflect.TypeOf((*MockClient)(nil).Register), arg0, arg1, arg2, arg3, arg4)
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Register", reflect.TypeOf((*MockClient)(nil).Register), arg0, arg1)
}
// Self mocks base method.

View File

@ -67,18 +67,18 @@ func (mr *MockPrincipalStoreMockRecorder) CountServices(arg0 interface{}) *gomoc
}
// CountUsers mocks base method.
func (m *MockPrincipalStore) CountUsers(arg0 context.Context) (int64, error) {
func (m *MockPrincipalStore) CountUsers(arg0 context.Context, arg1 *types.UserFilter) (int64, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "CountUsers", arg0)
ret := m.ctrl.Call(m, "CountUsers", arg0, arg1)
ret0, _ := ret[0].(int64)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// CountUsers indicates an expected call of CountUsers.
func (mr *MockPrincipalStoreMockRecorder) CountUsers(arg0 interface{}) *gomock.Call {
func (mr *MockPrincipalStoreMockRecorder) CountUsers(arg0, arg1 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CountUsers", reflect.TypeOf((*MockPrincipalStore)(nil).CountUsers), arg0)
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CountUsers", reflect.TypeOf((*MockPrincipalStore)(nil).CountUsers), arg0, arg1)
}
// CreateService mocks base method.
@ -529,10 +529,10 @@ func (mr *MockSpaceStoreMockRecorder) FindByRef(arg0, arg1 interface{}) *gomock.
}
// List mocks base method.
func (m *MockSpaceStore) List(arg0 context.Context, arg1 int64, arg2 *types.SpaceFilter) ([]*types.Space, error) {
func (m *MockSpaceStore) List(arg0 context.Context, arg1 int64, arg2 *types.SpaceFilter) ([]types.Space, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "List", arg0, arg1, arg2)
ret0, _ := ret[0].([]*types.Space)
ret0, _ := ret[0].([]types.Space)
ret1, _ := ret[1].(error)
return ret0, ret1
}

Some files were not shown because too many files have changed in this diff Show More