Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

credentials: Use cross-platform credentials.toml instead of Unix-specific .env files. #2

Merged
merged 22 commits into from
Mar 5, 2023
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,4 @@ vls.log

# Enviroment files
*.env

*.toml
40 changes: 11 additions & 29 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,34 +93,15 @@ klonol -h

## Usage

### Setting the environment variables

For GitHub the following variables need to be set.
### Setting the variables

The following variables need to be set in a file called `credentials.toml`.
| Name | Description | Compulsory |
| ------------------- | ---------------------------------------------------------------------------------------- | ---------- |
| GITHUB_USERNAME | The username whose repositories are to be queried | Yes |
| GITHUB_ACCESS_TOKEN | The personal access token generated previously | Yes |
| GITHUB_BASE_URL | The base domain to be used to test SSH and make API calls from. Defaults to `github.com` | No |

For Gitea the following need to be set:

| Name | Description | Compulsory |
| ------------------ | -------------------------------------------------------------------------------------------- | ---------- |
| GITEA_USERNAME | The username whose repositories are to be queried | Yes |
| GITEA_ACCESS_TOKEN | The personal access token generated previously | Yes |
| GITEA_BASE_URL | The domain where the Gitea instance is hosted. Do not include the protocol (e.g. `https://`) | Yes |
hungrybluedev marked this conversation as resolved.
Show resolved Hide resolved

For Unix-like systems, copy the `.env.sample` file, fill in the appropriate
values, comment out the ones you don't need. Then run the following to add
the required variables to your session:

```bash
source .env
```
| USERNAME | The github or gittea username whose repositories are to be queried | Yes |
| ACCESS_TOKEN | The personal access token generated previously | Yes |
| BASE_URL | The base domain to be used to test SSH and make API calls from. Defaults to `github.com` | No |

For Windows, you need to set the environment variables manually (for now).
If you want to make it analogous to the Unix way, please contribute a solution.

### Running klonol

Expand Down Expand Up @@ -156,11 +137,12 @@ klonol --help


# Options:
# -p, --provider <string> git provider to use
# -a, --action <string> action to perform
# -v, --verbose enable verbose output
# -h, --help display this help and exit
# --version output version information and exit
# -p, --provider <string> git provider to use
# -c, --credentials <string> path to credentials.toml file (default is ./credentials.toml)
# -a, --action <string> action to perform
# -v, --verbose enable verbose output
# -h, --help display this help and exit
# --version output version information and exit

```

Expand Down
8 changes: 6 additions & 2 deletions common/types.v
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,12 @@ import x.json2
pub struct Credentials {
pub:
base_url string = 'github.com'
username string
access_token string = 'unset value'
username string = 'unset_value'
access_token string = 'unset_value'
}

pub fn (c Credentials) to_toml() string {
return 'ACCESS_TOKEN="${c.access_token}"\nBASE_URL="${c.base_url}"\nUSERNAME="${c.username}"'
}

pub struct Repository {
Expand Down
102 changes: 45 additions & 57 deletions credentials.v
Original file line number Diff line number Diff line change
@@ -1,94 +1,82 @@
module main

import common
import toml
import os

fn display_unprotected_access_token_warning() {
println('\nIMPORTANT: Make sure to clear your terminal history to avoid leaking this
access token. Otherwise, regenerate this token as soon as possible. Also,
consider storing the credentials in a .env file instead. Refer to the
README.md for more instructions.\n')
}

fn get_credentials_for(provider Provider) !common.Credentials {
return match provider {
.gitea {
get_gitea_credentials()!
}
.github {
get_github_credentials()!
}
fn create_default_config(path string) ?common.Credentials {
if os.exists(path) && os.file_size(path) != 0 {
return none
}
}

fn get_github_credentials() !common.Credentials {
base_url := os.getenv_opt('GITHUB_BASE_URL') or { 'github.com' }

if base_url.contains('http') {
return error('Do not include the protocol in the GITHUB_BASE_URL environment variable. Valid example: "git.example.com".')
}

username := os.getenv_opt('GITHUB_USERNAME') or {
eprintln('GITHUB_USERNAME environment variable is not set.')
username := os.input_opt('Please enter username: ') or {
return error('Please enter your username.')
}
username
creds := common.Credentials{}
os.write_file(path, toml.encode(creds)) or {
return error('Cannot write default config to "${path}"')
}
return creds
}

access_token := os.getenv_opt('GITHUB_ACCESS_TOKEN') or {
eprintln('GITHUB_ACCESS_TOKEN environment variable is not set.')
display_unprotected_access_token_warning()
access_token := os.input_opt('Please enter access token: ') or {
return error('Please enter your access token.')
fn load_config(path string) ?common.Credentials {
if !os.exists(path) {
return create_default_config(path) or {
eprintln(err)
exit(1)
}
access_token
}

token_is_valid := common.is_access_token_valid(access_token, 'https://api.github.com/user/issues')

if !token_is_valid {
return error('The access token is invalid.')
creds := toml.parse_file(path) or {
eprintln('Error parsing config at "${path}". Using default config"')
exit(1)
}

return common.Credentials{
A1ex-N marked this conversation as resolved.
Show resolved Hide resolved
base_url: base_url
username: username
access_token: access_token
base_url: creds.value('BASE_URL').string()
username: creds.value('USERNAME').string()
access_token: creds.value('ACCESS_TOKEN').string()
}
}

fn get_gitea_credentials() !common.Credentials {
base_url := os.getenv_opt('GITEA_BASE_URL') or {
eprintln('GITEA_BASE_URL environment variable is not set.')
base_url := os.input_opt('Please the base URL (without protocol): ') or {
return error('Please enter your base URL.')
}
base_url
fn display_unprotected_access_token_warning() {
println('\nIMPORTANT: Make sure to clear your terminal history to avoid leaking this
access token. Otherwise, regenerate this token as soon as possible. Also,
consider storing the credentials in a .env file instead. Refer to the
A1ex-N marked this conversation as resolved.
Show resolved Hide resolved
README.md for more instructions.\n')
}

fn get_credentials_for(provider Provider, path string) !common.Credentials {
credentials := load_config(path) or {
eprintln(err)
exit(1)
}
base_url := credentials.base_url

if base_url.contains('http') {
return error('Do not include the protocol in the GITEA_BASE_URL environment variable. Valid example: "git.example.com".')
return error('Do not include the protocol in the BASE_URL environment variable. Valid example: "git.example.com".')
}

username := os.getenv_opt('GITEA_USERNAME') or {
eprintln('GITEA_USERNAME environment variable is not set.')
username := os.input_opt('Please enter username: ') or {
mut username := credentials.username
if username == 'unset_value' {
eprintln('USERNAME variable is not set in ${path}.')
username = os.input_opt('Please enter username: ') or {
return error('Please enter your username.')
}
username
}

access_token := os.getenv_opt('GITEA_ACCESS_TOKEN') or {
eprintln('GITEA_ACCESS_TOKEN environment variable is not set.')
mut access_token := credentials.access_token
if access_token == 'unset_value' {
eprintln('ACCESS_TOKEN variable is not set ${path}.')
display_unprotected_access_token_warning()
access_token := os.input_opt('Please enter access token: ') or {
access_token = os.input_opt('Please enter access token: ') or {
return error('Please enter your access token.')
}
access_token
}

token_is_valid := common.is_access_token_valid('unset_value', 'https://${base_url}/api/v1/user?access_token=${access_token}')
token_is_valid := match provider {
.github { common.is_access_token_valid(access_token, 'https://api.github.com/user/issues') }
.gitea { common.is_access_token_valid(access_token, 'https://${base_url}/api/v1/user?access_token=${access_token}') }
}

if !token_is_valid {
return error('The access token is invalid.')
Expand Down
7 changes: 4 additions & 3 deletions klonol.v
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,9 @@ fn main() {
fp.description('${description}\n${instructions}')
fp.skip_executable()

provider_str := fp.string('provider', `p`, 'github', 'git provider to use').to_lower()
action_str := fp.string('action', `a`, 'list', 'action to perform').to_lower()
provider_str := fp.string('provider', `p`, 'github', 'git provider to use (default is github)').to_lower()
credentials_path := fp.string('credentials', `c`, 'credentials.toml', 'path to credentials.toml file (default is ./credentials.toml)').to_lower()
action_str := fp.string('action', `a`, 'list', 'action to perform [list, clone, pull] ').to_lower()
verbose := fp.bool('verbose', `v`, false, 'enable verbose output')

additional_args := fp.finalize() or {
Expand Down Expand Up @@ -64,7 +65,7 @@ fn main() {
exit(1)
}

credentials := get_credentials_for(provider)!
credentials := get_credentials_for(provider, credentials_path)!

if !git.can_use_ssh(credentials.base_url) {
eprintln('Please setup an SSH Key pair and add the public key to your remote Git server.')
Expand Down