diff --git a/README.md b/README.md index c4e4447c5..bee18eb0f 100644 --- a/README.md +++ b/README.md @@ -23,8 +23,8 @@ $ popd Build the server and command line tools: ```bash -$ go generate ./... -$ go build -o release/gitness +# STANDALONE +$ make build ``` # Test @@ -42,7 +42,8 @@ This project supports all operating systems and architectures supported by Go. Start the server at `localhost:3000` ```bash -$ release/gitness server +# STANDALONE +./gitness server .local.env ``` # User Interface @@ -53,60 +54,70 @@ This project includes a simple user interface for interacting with the system. W This project includes a swagger specification. When you run the application, you can access the swagger specification by navigating to `http://localhost:3000/swagger` in your browser. -# Command Line - +# CLI This project includes simple command line tools for interacting with the system. Please remember that you must start the server before you can execute commands. Register a new user: ```bash -$ release/gitness register +$ ./gitness register ``` +> NOTE: A user `admin` (pw: `changeit`) gets created by default. + + Login to the application: ```bash -$ release/gitness login +$ ./gitness login ``` Logout from the application: ```bash -$ release/gitness logout +$ ./gitness logout ``` View your account details: ```bash -$ release/gitness account +$ ./gitness user self ``` Generate a personal access token: ```bash -$ release/gitness token -``` - -Create a pipeline: - -```bash -$ release/gitness pipeline create -``` - -List pipelines: - -```bash -$ release/gitness pipeline ls +$ ./gitness user pat $NAME $LIFETIME_IN_S ``` Debug and output http responses from the server: ```bash -$ DEBUG=true release/gitness pipeline ls +$ DEBUG=true ./gitness user self ``` View all commands: ```bash -$ release/gitness --help +$ ./gitness --help ``` + +# REST API +Please refer to the swagger for the specification of our rest API. + +For testing, it's simplest to execute operations as the default user `admin` using a PAT: +```bash +# LOGIN (user: admin, pw: changeit) +$ ./gitness login + +# GENERATE PAT (1 YEAR VALIDITY) +$ ./gitness user pat mypat 2592000 +``` + +The command outputs a valid PAT that has been granted full access as the user. +The token can then be send as part of the `Authorization` header with Postman or curl: + +```bash +$ curl http://localhost:3000/api/v1/user \ +-H "Authorization: Bearer $TOKEN" +``` \ No newline at end of file diff --git a/cli/operations/user/create_pat.go b/cli/operations/user/create_pat.go new file mode 100644 index 000000000..65dc0af1c --- /dev/null +++ b/cli/operations/user/create_pat.go @@ -0,0 +1,86 @@ +// 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" + "encoding/json" + "os" + "text/template" + "time" + + "github.com/harness/gitness/cli/util" + "github.com/harness/gitness/internal/api/controller/user" + "github.com/harness/gitness/types/enum" + + "github.com/drone/funcmap" + "gopkg.in/alecthomas/kingpin.v2" +) + +const tokenTmpl = ` +name: {{ .Token.Name }} +expiresAt: {{ .Token.ExpiresAt }} +token: {{ .AccessToken }} +` //#nosec G101 + +type createPATCommand struct { + name string + lifetimeInS int64 + + json bool + tmpl string +} + +func (c *createPATCommand) run(*kingpin.ParseContext) error { + client, err := util.Client() + if err != nil { + return err + } + ctx, cancel := context.WithTimeout(context.Background(), time.Minute) + defer cancel() + + in := user.CreateTokenInput{ + Name: c.name, + Lifetime: time.Duration(int64(time.Second) * c.lifetimeInS), + Grants: enum.AccessGrantAll, + } + + tokenResp, err := client.UserCreatePAT(ctx, in) + if err != nil { + return err + } + if c.json { + enc := json.NewEncoder(os.Stdout) + enc.SetIndent("", " ") + return enc.Encode(tokenResp) + } + tmpl, err := template.New("_").Funcs(funcmap.Funcs).Parse(c.tmpl) + if err != nil { + return err + } + return tmpl.Execute(os.Stdout, tokenResp) +} + +// Register the command. +func registerCreatePAT(app *kingpin.CmdClause) { + c := new(createPATCommand) + + cmd := app.Command("pat", "create personal access token"). + Action(c.run) + + cmd.Arg("name", "the name of the token"). + Required().StringVar(&c.name) + + cmd.Arg("lifetime", "the lifetime of the token in seconds"). + Required().Int64Var(&c.lifetimeInS) + + cmd.Flag("json", "json encode the output"). + BoolVar(&c.json) + + cmd.Flag("format", "format the output using a Go template"). + Default(tokenTmpl). + Hidden(). + StringVar(&c.tmpl) +} diff --git a/cli/operations/user/user.go b/cli/operations/user/self.go similarity index 92% rename from cli/operations/user/user.go rename to cli/operations/user/self.go index 2aa2206de..274c84700 100644 --- a/cli/operations/user/user.go +++ b/cli/operations/user/self.go @@ -53,10 +53,10 @@ func (c *command) run(*kingpin.ParseContext) error { } // Register the command. -func Register(app *kingpin.Application) { +func registerSelf(app *kingpin.CmdClause) { c := new(command) - cmd := app.Command("account", "display authenticated user"). + cmd := app.Command("self", "display authenticated user"). Action(c.run) cmd.Flag("json", "json encode the output"). diff --git a/cli/operations/user/users.go b/cli/operations/user/users.go new file mode 100644 index 000000000..e39e78287 --- /dev/null +++ b/cli/operations/user/users.go @@ -0,0 +1,14 @@ +// 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 "gopkg.in/alecthomas/kingpin.v2" + +// Register the command. +func Register(app *kingpin.Application) { + cmd := app.Command("user", "manage currently logged-in user") + registerSelf(cmd) + registerCreatePAT(cmd) +} diff --git a/cli/operations/users/users.go b/cli/operations/users/users.go index 2323f8fa9..dbe51f11e 100644 --- a/cli/operations/users/users.go +++ b/cli/operations/users/users.go @@ -8,7 +8,7 @@ import "gopkg.in/alecthomas/kingpin.v2" // Register the command. func Register(app *kingpin.Application) { - cmd := app.Command("user", "manage users") + cmd := app.Command("users", "manage users") registerFind(cmd) registerList(cmd) registerCreate(cmd) diff --git a/client/client.go b/client/client.go index 2c2f61027..a16b0cba0 100644 --- a/client/client.go +++ b/client/client.go @@ -16,6 +16,7 @@ import ( "github.com/rs/zerolog/log" + "github.com/harness/gitness/internal/api/controller/user" "github.com/harness/gitness/types" "github.com/harness/gitness/version" ) @@ -94,6 +95,14 @@ func (c *HTTPClient) Self(ctx context.Context) (*types.User, error) { return out, err } +// UserCreatePAT creates a new PAT for the user. +func (c *HTTPClient) UserCreatePAT(ctx context.Context, in user.CreateTokenInput) (*types.TokenResponse, error) { + out := new(types.TokenResponse) + uri := fmt.Sprintf("%s/api/v1/user/tokens", c.base) + err := c.post(ctx, uri, in, out) + return out, err +} + // User returns a user by ID or email. func (c *HTTPClient) User(ctx context.Context, key string) (*types.User, error) { out := new(types.User) diff --git a/types/check/token.go b/types/check/token.go index decc47d8a..6621e4a97 100644 --- a/types/check/token.go +++ b/types/check/token.go @@ -15,7 +15,7 @@ const ( var ( ErrTokenLifeTimeOutOfBounds = &ValidationError{ - "The life time of a token has to be between 1 second and 365 days.", + "The life time of a token has to be between 1 day and 365 days.", } )