pgchief 0.2.0 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.rubocop.yml +12 -0
- data/CHANGELOG.md +51 -3
- data/README.md +44 -28
- data/config/pgchief.toml +10 -0
- data/exe/pgchief +3 -1
- data/lib/pgchief/cli.rb +22 -0
- data/lib/pgchief/command/base.rb +1 -1
- data/lib/pgchief/command/config_create.rb +20 -0
- data/lib/pgchief/command/database_privileges_grant.rb +45 -7
- data/lib/pgchief/command/retrieve_connection_string.rb +34 -0
- data/lib/pgchief/command/store_connection_string.rb +24 -0
- data/lib/pgchief/command/user_create.rb +18 -1
- data/lib/pgchief/command/user_drop.rb +2 -0
- data/lib/pgchief/config.rb +36 -0
- data/lib/pgchief/connection_string.rb +63 -0
- data/lib/pgchief/database.rb +1 -1
- data/lib/pgchief/prompt/create_user.rb +1 -1
- data/lib/pgchief/prompt/grant_database_privileges.rb +9 -3
- data/lib/pgchief/prompt/start.rb +9 -0
- data/lib/pgchief/prompt/user_management.rb +2 -1
- data/lib/pgchief/prompt/view_database_connection_string.rb +21 -0
- data/lib/pgchief/user.rb +1 -1
- data/lib/pgchief/version.rb +1 -1
- data/lib/pgchief.rb +11 -1
- data/tmp/.gitkeep +0 -0
- metadata +12 -4
- data/LICENSE +0 -21
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 627e9af2dc140bd7210c9f4e999f5be13ba0bf514e6397619d42bef8a6d8b838
|
|
4
|
+
data.tar.gz: 78a5456432854cebd9b6d6fb68f9f02256a9a37c626ac0d78ef35b3bf79f4f21
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 26a19391751adbd9846cd70532becfa91c4f2e6a704405764c207e817f388b5ad900a5993eb2e20b574e09e78a089658b9f1f14591e9ea5f0349476fa7b49c13
|
|
7
|
+
data.tar.gz: e96db718dd3e594b4f612d47b2d63bfe0792e94b4ba622d9093db6b2d8138c02cf8dc45885557a8048f767d280f597103a410468914496dd937e25b759eb2c18
|
data/.rubocop.yml
CHANGED
|
@@ -18,5 +18,17 @@ Metrics/BlockLength:
|
|
|
18
18
|
- 'spec/**/*'
|
|
19
19
|
- '*.gemspec'
|
|
20
20
|
|
|
21
|
+
Lint/MixedRegexpCaptureTypes:
|
|
22
|
+
Enabled: false
|
|
23
|
+
|
|
21
24
|
RSpec/MultipleExpectations:
|
|
22
25
|
Max: 5
|
|
26
|
+
|
|
27
|
+
RSpec/ExampleLength:
|
|
28
|
+
Max: 20
|
|
29
|
+
|
|
30
|
+
Lint/MissingSuper:
|
|
31
|
+
Enabled: false
|
|
32
|
+
|
|
33
|
+
Metrics/ParameterLists:
|
|
34
|
+
Enabled: false
|
data/CHANGELOG.md
CHANGED
|
@@ -9,6 +9,50 @@ and this project will try its best to adhere to [Semantic Versioning](https://se
|
|
|
9
9
|
|
|
10
10
|
### Additions
|
|
11
11
|
|
|
12
|
+
### Changes
|
|
13
|
+
|
|
14
|
+
### Fixes
|
|
15
|
+
|
|
16
|
+
## [0.3.1]
|
|
17
|
+
|
|
18
|
+
### Changes
|
|
19
|
+
|
|
20
|
+
- The main database url will be accessed via the config class and will prioritize
|
|
21
|
+
the ENV over the config file, if it is set.
|
|
22
|
+
|
|
23
|
+
### Fixes
|
|
24
|
+
|
|
25
|
+
- Do not use the ENV only. Until now that was the only method and it was ignoring
|
|
26
|
+
what was set in the config file. This fixes the issue where nothing will work
|
|
27
|
+
if `ENV["DATABASE_URL"]` is not set.
|
|
28
|
+
|
|
29
|
+
## [0.3.0]
|
|
30
|
+
|
|
31
|
+
### Additions
|
|
32
|
+
|
|
33
|
+
- Refactor `exe/pgchief` to utilize `TTY::Option` for kicking off config initialization
|
|
34
|
+
- `pgchief --init` now creates a toml config file in your `$HOME`
|
|
35
|
+
- Added ability to store credentials if your config sets `credentials_file`
|
|
36
|
+
when db's and users are created
|
|
37
|
+
- Added `ConnectionString` class that abstracts the base db connection,
|
|
38
|
+
allowing for additions of users and db's
|
|
39
|
+
- Load everything in the config file to the Config attributes
|
|
40
|
+
|
|
41
|
+
### Changes
|
|
42
|
+
|
|
43
|
+
- Default location of config changed from `~/.pgchief.toml` to `~/.config/pgchief/config.toml`
|
|
44
|
+
- Automatically require 'pry' in the test suite
|
|
45
|
+
|
|
46
|
+
### Fixes
|
|
47
|
+
|
|
48
|
+
- When dropping user, ignore whenever a database has no privileges for the
|
|
49
|
+
selected user
|
|
50
|
+
- Retroactive addition of tests to cover any regressions
|
|
51
|
+
|
|
52
|
+
## [0.2.0] - 2024-08-30
|
|
53
|
+
|
|
54
|
+
### Additions
|
|
55
|
+
|
|
12
56
|
- Add `j` and `k` keys as substitutes for `↑` and `↓`.
|
|
13
57
|
- Allow exiting the program with the `esc` key.
|
|
14
58
|
- Add ability to grant access privileges for newly created users.
|
|
@@ -17,8 +61,10 @@ and this project will try its best to adhere to [Semantic Versioning](https://se
|
|
|
17
61
|
### Fixes
|
|
18
62
|
|
|
19
63
|
- GitHub now running CI successfully.
|
|
20
|
-
- Newly created databases are no longer open for connection by default.
|
|
21
|
-
|
|
64
|
+
- Newly created databases are no longer open for connection by default.
|
|
65
|
+
`CONNECT` is revoked by default for them.
|
|
66
|
+
- When dropping users, loop through all the databases they have access to and
|
|
67
|
+
revoke access before dropping them.
|
|
22
68
|
|
|
23
69
|
## [0.1.0] - 2024-08-30
|
|
24
70
|
|
|
@@ -29,5 +75,7 @@ and this project will try its best to adhere to [Semantic Versioning](https://se
|
|
|
29
75
|
- Drop user ✅
|
|
30
76
|
- List databases ✅
|
|
31
77
|
|
|
32
|
-
[Unreleased]: https://github.com/jayroh/pgchief/compare/v0.
|
|
78
|
+
[Unreleased]: https://github.com/jayroh/pgchief/compare/v0.3.0...HEAD
|
|
79
|
+
[0.3.0]: https://github.com/jayroh/pgchief/releases/tag/v0.3.0
|
|
80
|
+
[0.2.0]: https://github.com/jayroh/pgchief/releases/tag/v0.2.0
|
|
33
81
|
[0.1.0]: https://github.com/jayroh/pgchief/releases/tag/v0.1.0
|
data/README.md
CHANGED
|
@@ -21,17 +21,41 @@ below for the feature check-list and current progress.
|
|
|
21
21
|
|
|
22
22
|
***
|
|
23
23
|
|
|
24
|
-
## Usage
|
|
24
|
+
## Usage
|
|
25
25
|
|
|
26
|
-
```
|
|
26
|
+
```sh
|
|
27
27
|
gem install pgchief
|
|
28
28
|
|
|
29
|
-
#
|
|
30
|
-
|
|
29
|
+
# To initialize the config file at `~/.config/pgchief/config.toml`:
|
|
30
|
+
|
|
31
|
+
pgchief --init
|
|
32
|
+
|
|
33
|
+
# edit the config file and set your main administrative connection string
|
|
34
|
+
# (vim|nano|pico|ed) ~/.config/pgchief/config.toml
|
|
35
|
+
|
|
36
|
+
# OR ... make sure the DATABASE_URL env is set to the connection string
|
|
37
|
+
# export DATABASE_URL=postgresql://postgres:password@postgres.local:5432
|
|
31
38
|
|
|
32
39
|
pgchief
|
|
33
40
|
```
|
|
34
41
|
|
|
42
|
+
## Config
|
|
43
|
+
|
|
44
|
+
Format of `~/.pgchief.toml`
|
|
45
|
+
|
|
46
|
+
```toml
|
|
47
|
+
# Connection string to superuser account at your PG instance
|
|
48
|
+
pgurl = "postgresql://username:password@host:5432"
|
|
49
|
+
|
|
50
|
+
# Directory where db backups will be placed
|
|
51
|
+
backup_dir = "~/.pgchief/backups"
|
|
52
|
+
|
|
53
|
+
# ** OPTIONAL **
|
|
54
|
+
|
|
55
|
+
# Location of encrypted database connection strings
|
|
56
|
+
# credentials_file = "~/.pgchief/credentials"
|
|
57
|
+
```
|
|
58
|
+
|
|
35
59
|
Note:
|
|
36
60
|
|
|
37
61
|
1. Prompts accept both `↑` and `↓` arrows, as well as `j` and `k`.
|
|
@@ -43,13 +67,15 @@ Note:
|
|
|
43
67
|
2. `bundle install`
|
|
44
68
|
3. `cp .env.sample .env`
|
|
45
69
|
4. Edit `.env` and change:
|
|
46
|
-
|
|
47
|
-
|
|
70
|
+
* `DATABASE_URL` to point to your main pg instance's superuser account with a
|
|
71
|
+
connection string.
|
|
72
|
+
* `TEST_DATABASE_URL` to point to your local pg instance where tests can be
|
|
73
|
+
run against.
|
|
48
74
|
5. `bundle exec rake` to run test suite & rubocop.
|
|
49
75
|
|
|
50
|
-
## The ideal, aspirational, DX
|
|
76
|
+
## The ideal, aspirational, DX
|
|
51
77
|
|
|
52
|
-
```
|
|
78
|
+
```sh
|
|
53
79
|
$ pgchief --init # create the TOML file in your home dir (w/600 permissions)
|
|
54
80
|
$ pgchief
|
|
55
81
|
|
|
@@ -92,27 +118,17 @@ Give "rando-username" access to database(s):
|
|
|
92
118
|
# ... etc.
|
|
93
119
|
```
|
|
94
120
|
|
|
95
|
-
Format of `~/.pgchief.toml`
|
|
96
|
-
|
|
97
|
-
```toml
|
|
98
|
-
pgurl = "postgres://username:password@host:5432"
|
|
99
|
-
backup_dir = "~/.pg_backups"
|
|
100
|
-
|
|
101
|
-
# [optional] encryption key (to display hashed passwords)
|
|
102
|
-
# encryption_key = "my-password"
|
|
103
|
-
```
|
|
104
|
-
|
|
105
121
|
***
|
|
106
122
|
|
|
107
123
|
## Feature Roadmap
|
|
108
124
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
125
|
+
* [x] Create database
|
|
126
|
+
* [x] Create user
|
|
127
|
+
* [x] Drop database
|
|
128
|
+
* [x] Drop user
|
|
129
|
+
* [x] List databases
|
|
130
|
+
* [x] Give user permissions to use database
|
|
131
|
+
* [x] Initialize toml file
|
|
132
|
+
* [x] Display connection information
|
|
133
|
+
* [ ] Back up database
|
|
134
|
+
* [ ] Restore database
|
data/config/pgchief.toml
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# Connection string to superuser account at your PG instance
|
|
2
|
+
pgurl = "postgresql://localhost:5432"
|
|
3
|
+
|
|
4
|
+
# Directory where db backups will be placed
|
|
5
|
+
backup_dir = "~/.config/pgchief/backups"
|
|
6
|
+
|
|
7
|
+
# ** OPTIONAL **
|
|
8
|
+
|
|
9
|
+
# Location of saved database connection strings
|
|
10
|
+
# credentials_file = "~/.config/pgchief/credentials"
|
data/exe/pgchief
CHANGED
data/lib/pgchief/cli.rb
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Pgchief
|
|
4
|
+
# Command line interface and option parsing
|
|
5
|
+
class Cli
|
|
6
|
+
include TTY::Option
|
|
7
|
+
|
|
8
|
+
option :init do
|
|
9
|
+
short "-i"
|
|
10
|
+
long "--init"
|
|
11
|
+
desc "Initialize the TOML configuration file"
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def run
|
|
15
|
+
if params[:init]
|
|
16
|
+
Pgchief::Command::ConfigCreate.call
|
|
17
|
+
else
|
|
18
|
+
Pgchief::Prompt::Start.call
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
data/lib/pgchief/command/base.rb
CHANGED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "fileutils"
|
|
4
|
+
|
|
5
|
+
module Pgchief
|
|
6
|
+
module Command
|
|
7
|
+
# Create a configuration file at $HOME
|
|
8
|
+
class ConfigCreate < Base
|
|
9
|
+
def call(dir: "#{Dir.home}/.config/pgchief")
|
|
10
|
+
return if File.exist?("#{dir}/config.toml")
|
|
11
|
+
|
|
12
|
+
template = File.join(__dir__, "..", "..", "..", "config", "pgchief.toml")
|
|
13
|
+
FileUtils.mkdir_p(dir)
|
|
14
|
+
FileUtils.cp(template, "#{dir}/config.toml")
|
|
15
|
+
|
|
16
|
+
puts "Configuration file created at #{dir}/config.toml"
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -4,19 +4,57 @@ module Pgchief
|
|
|
4
4
|
module Command
|
|
5
5
|
# Class to grant database privileges
|
|
6
6
|
class DatabasePrivilegesGrant < Base
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
attr_reader :username, :password, :database
|
|
8
|
+
|
|
9
|
+
def initialize(*params)
|
|
10
|
+
@username = params[0]
|
|
11
|
+
@password = params[1]
|
|
12
|
+
@databases = params[2]
|
|
13
|
+
end
|
|
10
14
|
|
|
11
|
-
|
|
12
|
-
|
|
15
|
+
def call
|
|
16
|
+
@databases.each do |database|
|
|
17
|
+
@database = database
|
|
18
|
+
grant_privs!
|
|
19
|
+
store_credentials!
|
|
13
20
|
end
|
|
14
21
|
|
|
15
|
-
"Privileges granted to #{username} on #{databases.join(", ")}"
|
|
22
|
+
"Privileges granted to #{username} on #{@databases.join(", ")}"
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
private
|
|
26
|
+
|
|
27
|
+
def grant_privs! # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
|
|
28
|
+
conn = PG.connect("#{Pgchief::Config.pgurl}/#{database}")
|
|
29
|
+
conn.exec("GRANT CONNECT ON DATABASE #{database} TO #{username};")
|
|
30
|
+
conn.exec("GRANT CREATE ON SCHEMA public TO #{username};")
|
|
31
|
+
conn.exec("GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO #{username};")
|
|
32
|
+
conn.exec("GRANT USAGE ON SCHEMA public TO #{username};")
|
|
33
|
+
conn.exec(
|
|
34
|
+
<<~SQL
|
|
35
|
+
ALTER DEFAULT PRIVILEGES IN SCHEMA public
|
|
36
|
+
GRANT SELECT, INSERT, UPDATE, DELETE ON TABLES
|
|
37
|
+
TO #{username};
|
|
38
|
+
SQL
|
|
39
|
+
)
|
|
40
|
+
conn.close
|
|
16
41
|
rescue PG::Error => e
|
|
17
42
|
"Error: #{e.message}"
|
|
18
43
|
ensure
|
|
19
|
-
conn.close
|
|
44
|
+
conn.finished? || conn.close
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def store_credentials!
|
|
48
|
+
Pgchief::Command::StoreConnectionString.call(connection_string)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def connection_string
|
|
52
|
+
ConnectionString.new(
|
|
53
|
+
Pgchief::Config.pgurl,
|
|
54
|
+
username: username,
|
|
55
|
+
password: password,
|
|
56
|
+
database: database
|
|
57
|
+
).to_s
|
|
20
58
|
end
|
|
21
59
|
end
|
|
22
60
|
end
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Pgchief
|
|
4
|
+
module Command
|
|
5
|
+
# Class to view database connection string
|
|
6
|
+
class RetrieveConnectionString < Base
|
|
7
|
+
attr_reader :username, :database
|
|
8
|
+
|
|
9
|
+
def initialize(username, database = nil)
|
|
10
|
+
@username = username
|
|
11
|
+
@database = database
|
|
12
|
+
@connection_string = nil
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def call
|
|
16
|
+
File.foreach(Config.credentials_file) do |line|
|
|
17
|
+
@connection_string = line if regex.match?(line)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
@connection_string.nil? ? "No connection string found" : @connection_string
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
private
|
|
24
|
+
|
|
25
|
+
def regex
|
|
26
|
+
if database
|
|
27
|
+
/#{username}.*#{database}$/
|
|
28
|
+
else
|
|
29
|
+
/#{username}.*\d$/
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Pgchief
|
|
4
|
+
module Command
|
|
5
|
+
# Class to store connection string
|
|
6
|
+
class StoreConnectionString
|
|
7
|
+
def self.call(connection_string)
|
|
8
|
+
new(connection_string).call
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
attr_reader :connection_string
|
|
12
|
+
|
|
13
|
+
def initialize(connection_string)
|
|
14
|
+
@connection_string = connection_string
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def call
|
|
18
|
+
File.open(Config.credentials_file, "a") do |file|
|
|
19
|
+
file.puts @connection_string
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -18,7 +18,8 @@ module Pgchief
|
|
|
18
18
|
@username, @password = params
|
|
19
19
|
raise Pgchief::Errors::UserExistsError if user_exists?
|
|
20
20
|
|
|
21
|
-
|
|
21
|
+
create_user!
|
|
22
|
+
save_credentials!
|
|
22
23
|
|
|
23
24
|
"User '#{username}' created successfully!"
|
|
24
25
|
rescue PG::Error => e
|
|
@@ -34,9 +35,25 @@ module Pgchief
|
|
|
34
35
|
conn.exec(query).any?
|
|
35
36
|
end
|
|
36
37
|
|
|
38
|
+
def create_user!
|
|
39
|
+
conn.exec("CREATE USER #{username} WITH #{user_options} PASSWORD '#{password}'")
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def save_credentials!
|
|
43
|
+
Pgchief::Command::StoreConnectionString.call(connection_string)
|
|
44
|
+
end
|
|
45
|
+
|
|
37
46
|
def user_options
|
|
38
47
|
USER_OPTIONS.join(" ")
|
|
39
48
|
end
|
|
49
|
+
|
|
50
|
+
def connection_string
|
|
51
|
+
ConnectionString.new(
|
|
52
|
+
Pgchief::Config.pgurl,
|
|
53
|
+
username: username,
|
|
54
|
+
password: password
|
|
55
|
+
).to_s
|
|
56
|
+
end
|
|
40
57
|
end
|
|
41
58
|
end
|
|
42
59
|
end
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "toml-rb"
|
|
4
|
+
|
|
5
|
+
module Pgchief
|
|
6
|
+
# Class to store configuration settings
|
|
7
|
+
class Config
|
|
8
|
+
class << self
|
|
9
|
+
attr_accessor \
|
|
10
|
+
:backup_dir,
|
|
11
|
+
:credentials_file
|
|
12
|
+
|
|
13
|
+
attr_writer :pgurl
|
|
14
|
+
|
|
15
|
+
def load_config!(toml_file = "#{Dir.home}/.config/pgchief/config.toml")
|
|
16
|
+
config = TomlRB.load_file(toml_file, symbolize_keys: true)
|
|
17
|
+
|
|
18
|
+
@backup_dir = config[:backup_dir].gsub("~", Dir.home)
|
|
19
|
+
@credentials_file = config[:credentials_file]&.gsub("~", Dir.home)
|
|
20
|
+
@pgurl = config[:pgurl]
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def pgurl
|
|
24
|
+
ENV.fetch("DATABASE_URL", @pgurl)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def set_up_file_structure!
|
|
28
|
+
FileUtils.mkdir_p(backup_dir)
|
|
29
|
+
|
|
30
|
+
return unless credentials_file && !File.exist?(credentials_file)
|
|
31
|
+
|
|
32
|
+
FileUtils.touch(credentials_file)
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Pgchief
|
|
4
|
+
# Class to parse and manipulate connection strings
|
|
5
|
+
class ConnectionString
|
|
6
|
+
URL_REGEX = %r{(?x)\A
|
|
7
|
+
postgres(ql)?://
|
|
8
|
+
(?<username>[^:@]*)?
|
|
9
|
+
:?(?<password>[^@]*)?
|
|
10
|
+
@?(?<host>[^:]*)?
|
|
11
|
+
:?(?<port>\d+)?
|
|
12
|
+
/?(?<database>[^\?]*)?
|
|
13
|
+
\z}
|
|
14
|
+
|
|
15
|
+
attr_reader :database_url
|
|
16
|
+
|
|
17
|
+
def initialize(
|
|
18
|
+
database_url,
|
|
19
|
+
username: nil,
|
|
20
|
+
password: nil,
|
|
21
|
+
host: nil,
|
|
22
|
+
port: nil,
|
|
23
|
+
database: nil
|
|
24
|
+
)
|
|
25
|
+
@database_url = database_url
|
|
26
|
+
@host = host
|
|
27
|
+
@username = username
|
|
28
|
+
@password = password
|
|
29
|
+
@port = port
|
|
30
|
+
@database = database
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def to_s
|
|
34
|
+
"postgresql://#{username}:#{password}@#{host}:#{port}/#{database}"
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def host
|
|
38
|
+
@host || (matched[:username] if matched[:host].empty?) || matched[:host]
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def username
|
|
42
|
+
@username || ("" if matched[:host].empty? && !matched[:username].empty?) || matched[:username] || ""
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def password
|
|
46
|
+
@password || matched[:password] || ""
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def port
|
|
50
|
+
@port || matched[:port] || "5432"
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def database
|
|
54
|
+
@database || matched[:database] || ""
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
private
|
|
58
|
+
|
|
59
|
+
def matched
|
|
60
|
+
@matched ||= database_url.match(URL_REGEX) || {}
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
data/lib/pgchief/database.rb
CHANGED
|
@@ -6,7 +6,7 @@ module Pgchief
|
|
|
6
6
|
# Database information and operations
|
|
7
7
|
class Database
|
|
8
8
|
def self.all
|
|
9
|
-
conn = PG.connect(
|
|
9
|
+
conn = PG.connect(Pgchief::Config.pgurl)
|
|
10
10
|
result = conn.exec("SELECT datname FROM pg_database WHERE datistemplate = false")
|
|
11
11
|
result
|
|
12
12
|
.map { |row| row["datname"] }
|
|
@@ -5,16 +5,22 @@ module Pgchief
|
|
|
5
5
|
# Class to ask for database names, in order to create it
|
|
6
6
|
class GrantDatabasePrivileges < Base
|
|
7
7
|
def call
|
|
8
|
-
username = params
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
username = params[0] || select_user
|
|
9
|
+
password = params[1] || ask_for_password
|
|
10
|
+
databases = params[2] || prompt.multi_select("Give \"#{username}\" access to database(s):",
|
|
11
|
+
Pgchief::Database.all)
|
|
11
12
|
|
|
13
|
+
result = Pgchief::Command::DatabasePrivilegesGrant.call(username, password, databases)
|
|
12
14
|
prompt.say result
|
|
13
15
|
end
|
|
14
16
|
|
|
15
17
|
def select_user
|
|
16
18
|
prompt.select("Select user to update:", Pgchief::User.all)
|
|
17
19
|
end
|
|
20
|
+
|
|
21
|
+
def ask_for_password
|
|
22
|
+
prompt.mask("Password:")
|
|
23
|
+
end
|
|
18
24
|
end
|
|
19
25
|
end
|
|
20
26
|
end
|
data/lib/pgchief/prompt/start.rb
CHANGED
|
@@ -5,6 +5,8 @@ module Pgchief
|
|
|
5
5
|
# Kicks off the CLI with an initial prompt
|
|
6
6
|
class Start < Base
|
|
7
7
|
def call
|
|
8
|
+
manage_config!
|
|
9
|
+
|
|
8
10
|
result = prompt.select(
|
|
9
11
|
"Welcome! How can I help?",
|
|
10
12
|
[
|
|
@@ -15,6 +17,13 @@ module Pgchief
|
|
|
15
17
|
|
|
16
18
|
klassify("prompt", result).call
|
|
17
19
|
end
|
|
20
|
+
|
|
21
|
+
private
|
|
22
|
+
|
|
23
|
+
def manage_config!
|
|
24
|
+
Pgchief::Config.load_config!
|
|
25
|
+
Pgchief::Config.set_up_file_structure!
|
|
26
|
+
end
|
|
18
27
|
end
|
|
19
28
|
end
|
|
20
29
|
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Pgchief
|
|
4
|
+
module Prompt
|
|
5
|
+
# Class to ask for database names, in order to create it
|
|
6
|
+
class ViewDatabaseConnectionString < Base
|
|
7
|
+
def call
|
|
8
|
+
username = params.first || select_user
|
|
9
|
+
database = prompt.select("Database you're connecting to:", Pgchief::Database.all + ["None"])
|
|
10
|
+
database = nil if database == "None"
|
|
11
|
+
result = Pgchief::Command::RetrieveConnectionString.call(username, database)
|
|
12
|
+
|
|
13
|
+
prompt.say result
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def select_user
|
|
17
|
+
prompt.select("Select user to update:", Pgchief::User.all)
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
data/lib/pgchief/user.rb
CHANGED
|
@@ -6,7 +6,7 @@ module Pgchief
|
|
|
6
6
|
# Database information and operations
|
|
7
7
|
class User
|
|
8
8
|
def self.all
|
|
9
|
-
conn = PG.connect(
|
|
9
|
+
conn = PG.connect(Pgchief::Config.pgurl)
|
|
10
10
|
result = conn.exec("SELECT usename FROM pg_user")
|
|
11
11
|
|
|
12
12
|
result.map { |row| row["usename"] }.reject { |name| name == "postgres" }
|
data/lib/pgchief/version.rb
CHANGED
data/lib/pgchief.rb
CHANGED
|
@@ -2,10 +2,15 @@
|
|
|
2
2
|
|
|
3
3
|
require "pg"
|
|
4
4
|
require "tty-prompt"
|
|
5
|
-
require "
|
|
5
|
+
require "tty-option"
|
|
6
6
|
|
|
7
|
+
require "pgchief/cli"
|
|
8
|
+
require "pgchief/config"
|
|
9
|
+
require "pgchief/connection_string"
|
|
10
|
+
require "pgchief/version"
|
|
7
11
|
require "pgchief/database"
|
|
8
12
|
require "pgchief/user"
|
|
13
|
+
|
|
9
14
|
require "pgchief/prompt/base"
|
|
10
15
|
require "pgchief/prompt/start"
|
|
11
16
|
require "pgchief/prompt/create_database"
|
|
@@ -15,12 +20,17 @@ require "pgchief/prompt/drop_database"
|
|
|
15
20
|
require "pgchief/prompt/drop_user"
|
|
16
21
|
require "pgchief/prompt/user_management"
|
|
17
22
|
require "pgchief/prompt/grant_database_privileges"
|
|
23
|
+
require "pgchief/prompt/view_database_connection_string"
|
|
18
24
|
|
|
25
|
+
require "pgchief/command"
|
|
19
26
|
require "pgchief/command/base"
|
|
27
|
+
require "pgchief/command/config_create"
|
|
20
28
|
require "pgchief/command/database_create"
|
|
21
29
|
require "pgchief/command/database_drop"
|
|
22
30
|
require "pgchief/command/database_list"
|
|
23
31
|
require "pgchief/command/database_privileges_grant"
|
|
32
|
+
require "pgchief/command/retrieve_connection_string"
|
|
33
|
+
require "pgchief/command/store_connection_string"
|
|
24
34
|
require "pgchief/command/user_create"
|
|
25
35
|
require "pgchief/command/user_drop"
|
|
26
36
|
require "pgchief/command/user_list"
|
data/tmp/.gitkeep
ADDED
|
File without changes
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: pgchief
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.3.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Joel Oliveira
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2024-
|
|
11
|
+
date: 2024-11-12 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: pg
|
|
@@ -79,21 +79,27 @@ files:
|
|
|
79
79
|
- ".rubocop.yml"
|
|
80
80
|
- CHANGELOG.md
|
|
81
81
|
- CODE_OF_CONDUCT.md
|
|
82
|
-
- LICENSE
|
|
83
82
|
- LICENSE.txt
|
|
84
83
|
- README.md
|
|
85
84
|
- Rakefile
|
|
85
|
+
- config/pgchief.toml
|
|
86
86
|
- exe/pgchief
|
|
87
87
|
- lib/pgchief.rb
|
|
88
|
+
- lib/pgchief/cli.rb
|
|
88
89
|
- lib/pgchief/command.rb
|
|
89
90
|
- lib/pgchief/command/base.rb
|
|
91
|
+
- lib/pgchief/command/config_create.rb
|
|
90
92
|
- lib/pgchief/command/database_create.rb
|
|
91
93
|
- lib/pgchief/command/database_drop.rb
|
|
92
94
|
- lib/pgchief/command/database_list.rb
|
|
93
95
|
- lib/pgchief/command/database_privileges_grant.rb
|
|
96
|
+
- lib/pgchief/command/retrieve_connection_string.rb
|
|
97
|
+
- lib/pgchief/command/store_connection_string.rb
|
|
94
98
|
- lib/pgchief/command/user_create.rb
|
|
95
99
|
- lib/pgchief/command/user_drop.rb
|
|
96
100
|
- lib/pgchief/command/user_list.rb
|
|
101
|
+
- lib/pgchief/config.rb
|
|
102
|
+
- lib/pgchief/connection_string.rb
|
|
97
103
|
- lib/pgchief/database.rb
|
|
98
104
|
- lib/pgchief/prompt.rb
|
|
99
105
|
- lib/pgchief/prompt/base.rb
|
|
@@ -105,9 +111,11 @@ files:
|
|
|
105
111
|
- lib/pgchief/prompt/grant_database_privileges.rb
|
|
106
112
|
- lib/pgchief/prompt/start.rb
|
|
107
113
|
- lib/pgchief/prompt/user_management.rb
|
|
114
|
+
- lib/pgchief/prompt/view_database_connection_string.rb
|
|
108
115
|
- lib/pgchief/user.rb
|
|
109
116
|
- lib/pgchief/version.rb
|
|
110
117
|
- sig/pgchief.rbs
|
|
118
|
+
- tmp/.gitkeep
|
|
111
119
|
homepage: https://github.com/jayroh/pgchief
|
|
112
120
|
licenses:
|
|
113
121
|
- MIT
|
|
@@ -131,7 +139,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
131
139
|
- !ruby/object:Gem::Version
|
|
132
140
|
version: '0'
|
|
133
141
|
requirements: []
|
|
134
|
-
rubygems_version: 3.
|
|
142
|
+
rubygems_version: 3.2.33
|
|
135
143
|
signing_key:
|
|
136
144
|
specification_version: 4
|
|
137
145
|
summary: A simple ruby script to manage postgresql databases and users
|
data/LICENSE
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2024 Joel Oliveira
|
|
4
|
-
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
-
in the Software without restriction, including without limitation the rights
|
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
furnished to do so, subject to the following conditions:
|
|
11
|
-
|
|
12
|
-
The above copyright notice and this permission notice shall be included in all
|
|
13
|
-
copies or substantial portions of the Software.
|
|
14
|
-
|
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|