pgchief 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +24 -1
- data/README.md +8 -2
- data/lib/pgchief/command/database_create.rb +1 -0
- data/lib/pgchief/command/database_privileges_grant.rb +23 -0
- data/lib/pgchief/command/user_drop.rb +27 -1
- data/lib/pgchief/prompt/base.rb +32 -3
- data/lib/pgchief/prompt/create_database.rb +1 -2
- data/lib/pgchief/prompt/create_user.rb +6 -2
- data/lib/pgchief/prompt/database_management.rb +1 -1
- data/lib/pgchief/prompt/drop_database.rb +1 -2
- data/lib/pgchief/prompt/drop_user.rb +1 -2
- data/lib/pgchief/prompt/grant_database_privileges.rb +20 -0
- data/lib/pgchief/prompt/start.rb +1 -2
- data/lib/pgchief/prompt/user_management.rb +7 -3
- data/lib/pgchief/version.rb +1 -1
- data/lib/pgchief.rb +2 -0
- metadata +4 -3
- data/lib/pgchief/prompt/grant_database_priveleges.rb +0 -15
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: dac74bd646caf6b54ac884174ea91654af3733a4a638b45cf7e690c501c0534a
|
4
|
+
data.tar.gz: b0be173c4090cda9a176f25434318f805f6892324e8b7a148db6ee93a09e24c5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 57135dde1c56aee8a082a36f03b440470a74549bd21ae970167ca5e4c02da91ed254ecf2a670818a712cdd6ad615372cd9a75229ff3f20c61f8ade718f0bf0a0
|
7
|
+
data.tar.gz: 2a70cc3718d84daba51d552c5d7a3ae144567bdb660db57fc4f890ff13ff3b154996f0ae5cae15212e3a433d01e8f2188cb1e62064cd364c51e7c9c0705d4671
|
data/CHANGELOG.md
CHANGED
@@ -1,6 +1,26 @@
|
|
1
|
+
# Changelog
|
2
|
+
|
3
|
+
All notable changes to this project will be documented in this file.
|
4
|
+
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
6
|
+
and this project will try its best to adhere to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
7
|
+
|
1
8
|
## [Unreleased]
|
2
9
|
|
3
|
-
|
10
|
+
### Additions
|
11
|
+
|
12
|
+
- Add `j` and `k` keys as substitutes for `↑` and `↓`.
|
13
|
+
- Allow exiting the program with the `esc` key.
|
14
|
+
- Add ability to grant access privileges for newly created users.
|
15
|
+
- Or grant privileges for existing users to database(s).
|
16
|
+
|
17
|
+
### Fixes
|
18
|
+
|
19
|
+
- GitHub now running CI successfully.
|
20
|
+
- Newly created databases are no longer open for connection by default. `CONNECT` is revoked by default for them.
|
21
|
+
- When dropping users, loop through all the databases they have access to and revoke access before dropping them.
|
22
|
+
|
23
|
+
## [0.1.0] - 2024-08-30
|
4
24
|
|
5
25
|
- Initial release
|
6
26
|
- Create database ✅
|
@@ -8,3 +28,6 @@
|
|
8
28
|
- Drop database ✅
|
9
29
|
- Drop user ✅
|
10
30
|
- List databases ✅
|
31
|
+
|
32
|
+
[Unreleased]: https://github.com/jayroh/pgchief/compare/v0.1.0...HEAD
|
33
|
+
[0.1.0]: https://github.com/jayroh/pgchief/releases/tag/v0.1.0
|
data/README.md
CHANGED
@@ -32,6 +32,11 @@ export DATABASE_URL=postgresql://postgres:password@postgres.local:5432
|
|
32
32
|
pgchief
|
33
33
|
```
|
34
34
|
|
35
|
+
Note:
|
36
|
+
|
37
|
+
1. Prompts accept both `↑` and `↓` arrows, as well as `j` and `k`.
|
38
|
+
2. Pressing the `esc` key at any point amidst a prompt will exit out of the program.
|
39
|
+
|
35
40
|
## Development of the gem
|
36
41
|
|
37
42
|
1. Clone this repo.
|
@@ -106,7 +111,8 @@ backup_dir = "~/.pg_backups"
|
|
106
111
|
- [x] Drop database
|
107
112
|
- [x] Drop user
|
108
113
|
- [x] List databases
|
109
|
-
- [
|
114
|
+
- [x] Give user permissions to use database
|
115
|
+
- [ ] Initialize toml file
|
110
116
|
- [ ] Back up database
|
111
117
|
- [ ] Restore database
|
112
|
-
- [ ]
|
118
|
+
- [ ] Display connection information
|
@@ -11,6 +11,7 @@ module Pgchief
|
|
11
11
|
raise Pgchief::Errors::DatabaseExistsError if db_exists?
|
12
12
|
|
13
13
|
conn.exec("CREATE DATABASE #{database}")
|
14
|
+
conn.exec("REVOKE CONNECT ON DATABASE #{database} FROM PUBLIC")
|
14
15
|
|
15
16
|
"Database '#{database}' created successfully!"
|
16
17
|
rescue PG::Error => e
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Pgchief
|
4
|
+
module Command
|
5
|
+
# Class to grant database privileges
|
6
|
+
class DatabasePrivilegesGrant < Base
|
7
|
+
def call
|
8
|
+
username = params.first
|
9
|
+
databases = params.last
|
10
|
+
|
11
|
+
databases.each do |database|
|
12
|
+
conn.exec("GRANT CONNECT ON DATABASE #{database} TO #{username};")
|
13
|
+
end
|
14
|
+
|
15
|
+
"Privileges granted to #{username} on #{databases.join(", ")}"
|
16
|
+
rescue PG::Error => e
|
17
|
+
"Error: #{e.message}"
|
18
|
+
ensure
|
19
|
+
conn.close
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -10,7 +10,8 @@ module Pgchief
|
|
10
10
|
@username = params.first
|
11
11
|
raise Pgchief::Errors::UserExistsError unless user_exists?
|
12
12
|
|
13
|
-
|
13
|
+
revoke_all_privileges
|
14
|
+
drop_user
|
14
15
|
|
15
16
|
"User '#{username}' dropped successfully!"
|
16
17
|
rescue PG::Error => e
|
@@ -19,10 +20,35 @@ module Pgchief
|
|
19
20
|
conn.close
|
20
21
|
end
|
21
22
|
|
23
|
+
private
|
24
|
+
|
22
25
|
def user_exists?
|
23
26
|
query = "SELECT 1 FROM pg_user WHERE usename = '#{username}'"
|
24
27
|
conn.exec(query).any?
|
25
28
|
end
|
29
|
+
|
30
|
+
def revoke_all_privileges
|
31
|
+
databases_with_access.each do |database|
|
32
|
+
conn.exec("REVOKE ALL PRIVILEGES ON DATABASE #{database} FROM #{username};")
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def drop_user
|
37
|
+
conn.exec("DROP USER #{username}")
|
38
|
+
end
|
39
|
+
|
40
|
+
def databases_with_access
|
41
|
+
@databases_with_access ||= begin
|
42
|
+
results = conn.exec <<~SQL
|
43
|
+
SELECT datname
|
44
|
+
FROM pg_database
|
45
|
+
WHERE has_database_privilege('#{username}', datname, 'CONNECT')
|
46
|
+
AND datname NOT IN ('postgres', 'template1', 'template0')
|
47
|
+
SQL
|
48
|
+
|
49
|
+
results.map { |row| row["datname"] }
|
50
|
+
end
|
51
|
+
end
|
26
52
|
end
|
27
53
|
end
|
28
54
|
end
|
data/lib/pgchief/prompt/base.rb
CHANGED
@@ -4,16 +4,45 @@ module Pgchief
|
|
4
4
|
module Prompt
|
5
5
|
# Base class for prompt classes
|
6
6
|
class Base
|
7
|
-
def self.
|
8
|
-
|
7
|
+
def self.call(*params)
|
8
|
+
new(*params).call
|
9
9
|
end
|
10
10
|
|
11
|
-
|
11
|
+
attr_reader :params
|
12
|
+
|
13
|
+
def initialize(*params)
|
14
|
+
@params = params
|
15
|
+
end
|
16
|
+
|
17
|
+
def call
|
18
|
+
raise NotImplementedError
|
19
|
+
end
|
20
|
+
|
21
|
+
def klassify(scope, words)
|
12
22
|
Object.const_get([
|
13
23
|
"Pgchief", "::", scope.capitalize, "::",
|
14
24
|
words.split.map(&:capitalize)
|
15
25
|
].flatten.join)
|
16
26
|
end
|
27
|
+
|
28
|
+
def yes_or_no(question, yes: nil, no: nil) # rubocop:disable Naming/MethodParameterName
|
29
|
+
response = prompt.yes?(question)
|
30
|
+
response ? yes&.call : no&.call
|
31
|
+
end
|
32
|
+
|
33
|
+
def prompt
|
34
|
+
@prompt ||= TTY::Prompt.new.tap do |p|
|
35
|
+
p.on(:keypress) do |event|
|
36
|
+
p.trigger(:keydown) if event.value == "j"
|
37
|
+
p.trigger(:keyup) if event.value == "k"
|
38
|
+
end
|
39
|
+
|
40
|
+
p.on(:keyescape) do
|
41
|
+
p.say "\n\nExiting...bye-bye 👋\n\n"
|
42
|
+
exit
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
17
46
|
end
|
18
47
|
end
|
19
48
|
end
|
@@ -4,8 +4,7 @@ module Pgchief
|
|
4
4
|
module Prompt
|
5
5
|
# Class to ask for database name, in order to create it
|
6
6
|
class CreateDatabase < Base
|
7
|
-
def
|
8
|
-
prompt = TTY::Prompt.new
|
7
|
+
def call
|
9
8
|
database = prompt.ask("Database name:")
|
10
9
|
result = Pgchief::Command::DatabaseCreate.call(database)
|
11
10
|
|
@@ -4,13 +4,17 @@ module Pgchief
|
|
4
4
|
module Prompt
|
5
5
|
# Class to prompt for user creation details
|
6
6
|
class CreateUser < Base
|
7
|
-
def
|
8
|
-
prompt = TTY::Prompt.new
|
7
|
+
def call
|
9
8
|
username = prompt.ask("Username:")
|
10
9
|
password = prompt.mask("Password:")
|
11
10
|
result = Pgchief::Command::UserCreate.call(username, password)
|
12
11
|
|
13
12
|
prompt.say result
|
13
|
+
|
14
|
+
yes_or_no(
|
15
|
+
"Give \"#{username}\" access to database(s)?",
|
16
|
+
yes: -> { Pgchief::Prompt::GrantDatabasePrivileges.call(username) }
|
17
|
+
)
|
14
18
|
end
|
15
19
|
end
|
16
20
|
end
|
@@ -4,7 +4,7 @@ module Pgchief
|
|
4
4
|
module Prompt
|
5
5
|
# Class to manage database operations
|
6
6
|
class DatabaseManagement < Base
|
7
|
-
def
|
7
|
+
def call
|
8
8
|
prompt = TTY::Prompt.new
|
9
9
|
result = prompt.select("Database management", ["Create database", "Drop database", "Database List"])
|
10
10
|
scope = result == "Database List" ? "command" : "prompt"
|
@@ -4,8 +4,7 @@ module Pgchief
|
|
4
4
|
module Prompt
|
5
5
|
# Class to prompt for which database to drop
|
6
6
|
class DropDatabase < Base
|
7
|
-
def
|
8
|
-
prompt = TTY::Prompt.new
|
7
|
+
def call
|
9
8
|
database = prompt.select("Which database needs to be dropped?", Pgchief::Database.all)
|
10
9
|
result = Pgchief::Command::DatabaseDrop.call(database)
|
11
10
|
|
@@ -4,8 +4,7 @@ module Pgchief
|
|
4
4
|
module Prompt
|
5
5
|
# Class to prompt for which user to drop
|
6
6
|
class DropUser < Base
|
7
|
-
def
|
8
|
-
prompt = TTY::Prompt.new
|
7
|
+
def call
|
9
8
|
user = prompt.select("Which user needs to be deleted?", Pgchief::User.all)
|
10
9
|
result = Pgchief::Command::UserDrop.call(user)
|
11
10
|
|
@@ -0,0 +1,20 @@
|
|
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 GrantDatabasePrivileges < Base
|
7
|
+
def call
|
8
|
+
username = params.first || select_user
|
9
|
+
databases = prompt.multi_select("Give \"#{username}\" access to database(s):", Pgchief::Database.all)
|
10
|
+
result = Pgchief::Command::DatabasePrivilegesGrant.call(username, databases)
|
11
|
+
|
12
|
+
prompt.say result
|
13
|
+
end
|
14
|
+
|
15
|
+
def select_user
|
16
|
+
prompt.select("Select user to update:", Pgchief::User.all)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
data/lib/pgchief/prompt/start.rb
CHANGED
@@ -4,9 +4,13 @@ module Pgchief
|
|
4
4
|
module Prompt
|
5
5
|
# Class to manage users
|
6
6
|
class UserManagement < Base
|
7
|
-
def
|
8
|
-
|
9
|
-
|
7
|
+
def call
|
8
|
+
result = prompt.select("User management", [
|
9
|
+
"Create user",
|
10
|
+
"Drop user",
|
11
|
+
"User list",
|
12
|
+
"Grant database privileges"
|
13
|
+
])
|
10
14
|
|
11
15
|
scope = result == "User list" ? "command" : "prompt"
|
12
16
|
klassify(scope, result).call
|
data/lib/pgchief/version.rb
CHANGED
data/lib/pgchief.rb
CHANGED
@@ -14,11 +14,13 @@ require "pgchief/prompt/database_management"
|
|
14
14
|
require "pgchief/prompt/drop_database"
|
15
15
|
require "pgchief/prompt/drop_user"
|
16
16
|
require "pgchief/prompt/user_management"
|
17
|
+
require "pgchief/prompt/grant_database_privileges"
|
17
18
|
|
18
19
|
require "pgchief/command/base"
|
19
20
|
require "pgchief/command/database_create"
|
20
21
|
require "pgchief/command/database_drop"
|
21
22
|
require "pgchief/command/database_list"
|
23
|
+
require "pgchief/command/database_privileges_grant"
|
22
24
|
require "pgchief/command/user_create"
|
23
25
|
require "pgchief/command/user_drop"
|
24
26
|
require "pgchief/command/user_list"
|
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.2.0
|
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-08-
|
11
|
+
date: 2024-08-31 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: pg
|
@@ -90,6 +90,7 @@ files:
|
|
90
90
|
- lib/pgchief/command/database_create.rb
|
91
91
|
- lib/pgchief/command/database_drop.rb
|
92
92
|
- lib/pgchief/command/database_list.rb
|
93
|
+
- lib/pgchief/command/database_privileges_grant.rb
|
93
94
|
- lib/pgchief/command/user_create.rb
|
94
95
|
- lib/pgchief/command/user_drop.rb
|
95
96
|
- lib/pgchief/command/user_list.rb
|
@@ -101,7 +102,7 @@ files:
|
|
101
102
|
- lib/pgchief/prompt/database_management.rb
|
102
103
|
- lib/pgchief/prompt/drop_database.rb
|
103
104
|
- lib/pgchief/prompt/drop_user.rb
|
104
|
-
- lib/pgchief/prompt/
|
105
|
+
- lib/pgchief/prompt/grant_database_privileges.rb
|
105
106
|
- lib/pgchief/prompt/start.rb
|
106
107
|
- lib/pgchief/prompt/user_management.rb
|
107
108
|
- lib/pgchief/user.rb
|
@@ -1,15 +0,0 @@
|
|
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 GrantDatabasePrivileges
|
7
|
-
def self.call(username)
|
8
|
-
databases = Pgchief::Database.all
|
9
|
-
prompt = TTY::Prompt.new
|
10
|
-
databases = prompt.select("Select database:", databases, multiselect: true)
|
11
|
-
Pgchief::Command::GrantDatabasePrivileges.call(username, databases)
|
12
|
-
end
|
13
|
-
end
|
14
|
-
end
|
15
|
-
end
|