clickhouse-users-cli 0.1.3__tar.gz → 0.1.5__tar.gz
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.
- clickhouse_users_cli-0.1.5/PKG-INFO +205 -0
- clickhouse_users_cli-0.1.5/README.md +181 -0
- {clickhouse_users_cli-0.1.3 → clickhouse_users_cli-0.1.5}/clickhouse_users_cli/__init__.py +1 -1
- {clickhouse_users_cli-0.1.3 → clickhouse_users_cli-0.1.5}/clickhouse_users_cli/app.py +28 -14
- clickhouse_users_cli-0.1.5/clickhouse_users_cli.egg-info/PKG-INFO +205 -0
- clickhouse_users_cli-0.1.3/PKG-INFO +0 -126
- clickhouse_users_cli-0.1.3/README.md +0 -102
- clickhouse_users_cli-0.1.3/clickhouse_users_cli.egg-info/PKG-INFO +0 -126
- {clickhouse_users_cli-0.1.3 → clickhouse_users_cli-0.1.5}/LICENSE +0 -0
- {clickhouse_users_cli-0.1.3 → clickhouse_users_cli-0.1.5}/clickhouse_users_cli/db.py +0 -0
- {clickhouse_users_cli-0.1.3 → clickhouse_users_cli-0.1.5}/clickhouse_users_cli/session.py +0 -0
- {clickhouse_users_cli-0.1.3 → clickhouse_users_cli-0.1.5}/clickhouse_users_cli/sql_builder.py +0 -0
- {clickhouse_users_cli-0.1.3 → clickhouse_users_cli-0.1.5}/clickhouse_users_cli/style.py +0 -0
- {clickhouse_users_cli-0.1.3 → clickhouse_users_cli-0.1.5}/clickhouse_users_cli/validators.py +0 -0
- {clickhouse_users_cli-0.1.3 → clickhouse_users_cli-0.1.5}/clickhouse_users_cli.egg-info/SOURCES.txt +0 -0
- {clickhouse_users_cli-0.1.3 → clickhouse_users_cli-0.1.5}/clickhouse_users_cli.egg-info/dependency_links.txt +0 -0
- {clickhouse_users_cli-0.1.3 → clickhouse_users_cli-0.1.5}/clickhouse_users_cli.egg-info/entry_points.txt +0 -0
- {clickhouse_users_cli-0.1.3 → clickhouse_users_cli-0.1.5}/clickhouse_users_cli.egg-info/requires.txt +0 -0
- {clickhouse_users_cli-0.1.3 → clickhouse_users_cli-0.1.5}/clickhouse_users_cli.egg-info/top_level.txt +0 -0
- {clickhouse_users_cli-0.1.3 → clickhouse_users_cli-0.1.5}/pyproject.toml +0 -0
- {clickhouse_users_cli-0.1.3 → clickhouse_users_cli-0.1.5}/setup.cfg +0 -0
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: clickhouse-users-cli
|
|
3
|
+
Version: 0.1.5
|
|
4
|
+
Summary: CLI interativa para criar usuarios ClickHouse com privilegio minimo (least privilege)
|
|
5
|
+
License-Expression: MIT
|
|
6
|
+
Keywords: clickhouse,cli,users,access-control,least-privilege
|
|
7
|
+
Classifier: Programming Language :: Python :: 3
|
|
8
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
9
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
10
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
11
|
+
Classifier: Environment :: Console
|
|
12
|
+
Classifier: Intended Audience :: System Administrators
|
|
13
|
+
Classifier: Operating System :: OS Independent
|
|
14
|
+
Classifier: Topic :: Database
|
|
15
|
+
Classifier: Topic :: System :: Systems Administration
|
|
16
|
+
Requires-Python: >=3.10
|
|
17
|
+
Description-Content-Type: text/markdown
|
|
18
|
+
License-File: LICENSE
|
|
19
|
+
Requires-Dist: questionary>=2.0.0
|
|
20
|
+
Requires-Dist: clickhouse-connect>=0.8.0
|
|
21
|
+
Requires-Dist: rich>=13.0.0
|
|
22
|
+
Requires-Dist: pyyaml>=6.0
|
|
23
|
+
Dynamic: license-file
|
|
24
|
+
|
|
25
|
+
# ⬢ ClickHouse Users CLI
|
|
26
|
+
|
|
27
|
+
[](https://pypi.org/project/clickhouse-users-cli/)
|
|
28
|
+
[](https://pypi.org/project/clickhouse-users-cli/)
|
|
29
|
+
[](https://opensource.org/licenses/MIT)
|
|
30
|
+
|
|
31
|
+
> Crie e gerencie usuários no ClickHouse com **privilégio mínimo** (*least privilege*) — sem decorar sintaxe de `GRANT`, sem acesso amplo por acidente.
|
|
32
|
+
|
|
33
|
+
CLI interativa em Python ([`questionary`](https://questionary.readthedocs.io/) + [`rich`](https://github.com/Textualize/rich)): ela pergunta, você marca com `espaço`, confere o **SQL exato com preview** e só então executa. Nada roda sem confirmação.
|
|
34
|
+
|
|
35
|
+
```
|
|
36
|
+
╔══════════════════════════════════════════════════════════════════════════════╗
|
|
37
|
+
║ ║
|
|
38
|
+
║ ╭──────────╮ ║
|
|
39
|
+
║ │ ▓▓▓▓▓▓▓▓ │ ║
|
|
40
|
+
║ │ │ ║
|
|
41
|
+
║ ╰──────────╯ ║
|
|
42
|
+
║ ⬢ ClickHouse Users CLI ║
|
|
43
|
+
║ Crie usuários com escopo mínimo necessário ║
|
|
44
|
+
║ criar ◆ listar ◆ desativar ◆ auditar ║
|
|
45
|
+
║ ║
|
|
46
|
+
╚═════════════════════════ least privilege por padrão ═════════════════════════╝
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
---
|
|
50
|
+
|
|
51
|
+
## 🚀 Instalação
|
|
52
|
+
|
|
53
|
+
```powershell
|
|
54
|
+
pip install clickhouse-users-cli
|
|
55
|
+
ch-users
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
| Cenário | Comando |
|
|
59
|
+
|---|---|
|
|
60
|
+
| Instalar / atualizar | `pip install -U clickhouse-users-cli` |
|
|
61
|
+
| Rodar | `ch-users` |
|
|
62
|
+
| Do código-fonte | `pip install -r requirements.txt` + `python main.py` |
|
|
63
|
+
| Requisitos | Python `>= 3.10` + conta admin no ClickHouse (ex.: `default`) |
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
## ⚡ Comece em 60 segundos
|
|
68
|
+
|
|
69
|
+
1. Rode `ch-users` e conecte com sua conta admin (host, protocolo, porta, usuário/senha — testado com `SELECT 1`).
|
|
70
|
+
2. Escolha **Criar usuário** → perfil `readonly` → nome + senha → marque os bancos/tabelas → confira o preview.
|
|
71
|
+
3. Confirme. Pronto — o SQL abaixo foi executado:
|
|
72
|
+
|
|
73
|
+
```sql
|
|
74
|
+
CREATE USER IF NOT EXISTS `analyst_julho` IDENTIFIED WITH plaintext_password BY '***' HOST ANY;
|
|
75
|
+
GRANT SHOW, SELECT ON `vendas`.`pedidos` TO `analyst_julho`;
|
|
76
|
+
GRANT SHOW, SELECT ON `vendas`.`clientes` TO `analyst_julho`;
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
---
|
|
80
|
+
|
|
81
|
+
## 🧭 Menu principal
|
|
82
|
+
|
|
83
|
+
Após conectar, o menu fica em loop — dá para fazer várias operações sem reconectar:
|
|
84
|
+
|
|
85
|
+
| Opção | O que faz |
|
|
86
|
+
|---|---|
|
|
87
|
+
| 🌱 **Criar usuário** | Fluxo guiado em 6 etapas (perfil → credenciais → escopo → hosts → revisão) |
|
|
88
|
+
| 📋 **Listar usuários** | Tabela via `SHOW USERS` + detalhe opcional (`SHOW CREATE USER` e `SHOW GRANTS FOR`) |
|
|
89
|
+
| 🛠️ **Gerenciar usuário** | Editar permissões · desativar · reativar · excluir |
|
|
90
|
+
| 🧹 **Esquecer sessão** | Apaga o YAML de conexão salva *(aparece só se existir)* |
|
|
91
|
+
| 👋 **Sair** | Encerra (Ctrl+C também sai limpo, sem executar nada) |
|
|
92
|
+
|
|
93
|
+
### Criar — as 6 etapas
|
|
94
|
+
|
|
95
|
+
1. 🔌 **Conexão** — host, protocolo (`http:8123` / `https:8443`), porta, usuário/senha admin. Falhou? Tentar de novo / editar / sair.
|
|
96
|
+
2. 🎭 **Tipo de usuário** — perfil com descrição (`readonly`, `readwrite`, `admin`, `custom`).
|
|
97
|
+
3. 🪪 **Novo usuário** — nome validado (letras, números, `_`; bloqueia `default`, `root`…) + senha com confirmação.
|
|
98
|
+
4. 🗂️ **Escopo** — `SHOW DATABASES` → marque bancos (nada vem marcado; há a opção `✓ Todos os bancos`) → por banco, marque tabelas ou `banco.*` (vale para tabelas futuras).
|
|
99
|
+
5. 🔑 **Privilégios + origem** — no `custom`, marque só o necessário (`DROP`/`TRUNCATE` pedem confirmação extra); depois `HOST ANY | LOCALHOST | IPs`.
|
|
100
|
+
6. 👀 **Revisão** — tabela-resumo + SQL com syntax highlight + confirmação final.
|
|
101
|
+
|
|
102
|
+
### Gerenciar — os 4 poderes
|
|
103
|
+
|
|
104
|
+
Escolhe 1 usuário, vê status (`HOST NONE` = inativo) + grants atuais, depois:
|
|
105
|
+
|
|
106
|
+
| Ação | SQL executado | Reversível? |
|
|
107
|
+
|---|---|---|
|
|
108
|
+
| ✏️ **Editar permissões** | `REVOKE ALL ON *.*` + novos `GRANTs` (perfil + escopo perguntados de novo, com frases próprias de edição) | ✅ ( reaplicando) |
|
|
109
|
+
| 🚫 **Desativar** | `ALTER USER \`nome\` HOST NONE` (bloqueia login, mantém grants) | ✅ via Reativar |
|
|
110
|
+
| ✅ **Reativar** | `ALTER USER \`nome\` HOST ANY` | — |
|
|
111
|
+
| 🗑️ **Excluir** | `DROP USER IF EXISTS \`nome\`` | ❌ definitivo |
|
|
112
|
+
|
|
113
|
+
> Todo DDL tem preview + confirmação com default **não**. Mexer no próprio usuário logado gera alerta extra. 👻
|
|
114
|
+
|
|
115
|
+
### 💾 Sessão salva (manter conectado)
|
|
116
|
+
|
|
117
|
+
- Após conectar, o CLI pergunta se quer **manter conectado**: salva `~/.ch-users/connection.yaml` (host, porta, protocolo, usuário, senha).
|
|
118
|
+
- Na próxima execução: **usar a salva · nova conexão · apagar a salva** (a senha nunca é exibida).
|
|
119
|
+
- ⚠️ A senha fica em **texto puro** no arquivo (`0600` no Linux/mac; no Windows vale o aviso em tela). Use só em máquina confiável — nunca compartilhe o arquivo.
|
|
120
|
+
|
|
121
|
+
---
|
|
122
|
+
|
|
123
|
+
## 🔐 Permissões que sua conta admin precisa
|
|
124
|
+
|
|
125
|
+
| Para… | Privilégio ClickHouse |
|
|
126
|
+
|---|---|
|
|
127
|
+
| Criar + conceder | `CREATE USER` + `GRANT` (nos escopos) |
|
|
128
|
+
| Listar / auditar | `SHOW USERS` (+ acesso aos grants) |
|
|
129
|
+
| Desativar / reativar / editar acessos | `ALTER USER` + `GRANT`/`REVOKE` nos escopos |
|
|
130
|
+
| Excluir | `DROP USER` |
|
|
131
|
+
|
|
132
|
+
Sem a permissão, o comando falha com mensagem amigável + dica — nada quebra pela metade sem aviso (na edição, se o `GRANT` falhar após o `REVOKE`, o CLI avisa para conferir em **Listar**).
|
|
133
|
+
|
|
134
|
+
---
|
|
135
|
+
|
|
136
|
+
## 🎭 Perfis (tipo de acesso)
|
|
137
|
+
|
|
138
|
+
| Perfil | Privilégios | Feito para |
|
|
139
|
+
|---|---|---|
|
|
140
|
+
| `readonly` | `SHOW, SELECT` | BI, analistas |
|
|
141
|
+
| `readwrite` | `SHOW, SELECT, INSERT` | Engenheiros, ingestão |
|
|
142
|
+
| `admin` | `ALL ... WITH GRANT OPTION` | ⚠️ Acesso total — cuidado! |
|
|
143
|
+
| `custom` | Você marca: `SELECT/SHOW/INSERT/CREATE/ALTER/DROP/TRUNCATE/OPTIMIZE/KILL QUERY` | Casos especiais |
|
|
144
|
+
|
|
145
|
+
---
|
|
146
|
+
|
|
147
|
+
## 🧠 Por que cada tela é do jeito que é
|
|
148
|
+
|
|
149
|
+
| Dado | Widget | Motivo |
|
|
150
|
+
|---|---|---|
|
|
151
|
+
| Host, porta, nomes, IPs | `text` + validação + `default` | Entrada livre com exemplo; `default` acelera localhost:8123 |
|
|
152
|
+
| Senhas | `password` mascarado | Não ecoa segredo; novo usuário pede confirmação |
|
|
153
|
+
| Protocolo / perfil / ação | `select` com descrição | Escolha única; descrição explica o impacto |
|
|
154
|
+
| Bancos, tabelas, privilégios | `checkbox` (espaço marca) | Multi-seleção; `banco.*` evita marcar 100 tabelas |
|
|
155
|
+
| Confirmações destrutivas | `confirm` com default seguro | O "não" é sempre o padrão |
|
|
156
|
+
| Progresso | spinner + cabeçalho de etapa | Você sempre sabe "onde estou" e o que está carregando |
|
|
157
|
+
| Revisão | tabela + SQL destacado | Sem caixa-preta: o SQL exato antes de executar |
|
|
158
|
+
|
|
159
|
+
Princípios: **opt-in explícito** (nada pré-marcado), **escape correto** (backticks em identificadores, aspas simples em strings), **SQL separado da UI** (`sql_builder.py` é puro e testável sem banco).
|
|
160
|
+
|
|
161
|
+
---
|
|
162
|
+
|
|
163
|
+
## 🧑💻 Desenvolvimento
|
|
164
|
+
|
|
165
|
+
```powershell
|
|
166
|
+
pip install -r requirements.txt
|
|
167
|
+
python main.py # roda do fonte
|
|
168
|
+
python -m build # gera sdist + wheel em dist/
|
|
169
|
+
python -m twine check dist/* # valida (inclusive este README)
|
|
170
|
+
python -m twine upload dist/* # publica (precisa de token PyPI)
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
Versão em fonte única: `clickhouse_users_cli/__init__.py` (`__version__`).
|
|
174
|
+
|
|
175
|
+
```
|
|
176
|
+
main.py # entrypoint (dev local)
|
|
177
|
+
requirements.txt
|
|
178
|
+
pyproject.toml # build + metadados PyPI (comando: ch-users)
|
|
179
|
+
clickhouse_users_cli/
|
|
180
|
+
__init__.py # __version__
|
|
181
|
+
app.py # fluxos interativos (criar, listar, gerenciar, sessão)
|
|
182
|
+
db.py # clickhouse-connect: connect, SHOWs, DDL
|
|
183
|
+
session.py # sessão YAML local (salvar/carregar/apagar)
|
|
184
|
+
sql_builder.py # CREATE/ALTER/DROP/GRANT/REVOKE puros (testável)
|
|
185
|
+
validators.py # validações por tipo de input
|
|
186
|
+
style.py # banner, etapas, tabelas e mensagens (Rich)
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
---
|
|
190
|
+
|
|
191
|
+
## 📝 Changelog
|
|
192
|
+
|
|
193
|
+
| Versão | Novidade |
|
|
194
|
+
|---|---|
|
|
195
|
+
| `0.1.4` | Frases próprias no modo edição (sem `2/6`, `4/6` da criação) |
|
|
196
|
+
| `0.1.3` | Editar permissões (`REVOKE ALL` + novos `GRANTs`) |
|
|
197
|
+
| `0.1.2` | Sessão salva em YAML + visual profissional (banner, badges, tabelas) |
|
|
198
|
+
| `0.1.1` | Lista sem pré-seleção + opção `✓ Todos os bancos` |
|
|
199
|
+
| `0.1.0` | Criar, listar e gerenciar (desativar/reativar/excluir) |
|
|
200
|
+
|
|
201
|
+
---
|
|
202
|
+
|
|
203
|
+
## 📄 Licença
|
|
204
|
+
|
|
205
|
+
MIT — veja [LICENSE](LICENSE).
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
# ⬢ ClickHouse Users CLI
|
|
2
|
+
|
|
3
|
+
[](https://pypi.org/project/clickhouse-users-cli/)
|
|
4
|
+
[](https://pypi.org/project/clickhouse-users-cli/)
|
|
5
|
+
[](https://opensource.org/licenses/MIT)
|
|
6
|
+
|
|
7
|
+
> Crie e gerencie usuários no ClickHouse com **privilégio mínimo** (*least privilege*) — sem decorar sintaxe de `GRANT`, sem acesso amplo por acidente.
|
|
8
|
+
|
|
9
|
+
CLI interativa em Python ([`questionary`](https://questionary.readthedocs.io/) + [`rich`](https://github.com/Textualize/rich)): ela pergunta, você marca com `espaço`, confere o **SQL exato com preview** e só então executa. Nada roda sem confirmação.
|
|
10
|
+
|
|
11
|
+
```
|
|
12
|
+
╔══════════════════════════════════════════════════════════════════════════════╗
|
|
13
|
+
║ ║
|
|
14
|
+
║ ╭──────────╮ ║
|
|
15
|
+
║ │ ▓▓▓▓▓▓▓▓ │ ║
|
|
16
|
+
║ │ │ ║
|
|
17
|
+
║ ╰──────────╯ ║
|
|
18
|
+
║ ⬢ ClickHouse Users CLI ║
|
|
19
|
+
║ Crie usuários com escopo mínimo necessário ║
|
|
20
|
+
║ criar ◆ listar ◆ desativar ◆ auditar ║
|
|
21
|
+
║ ║
|
|
22
|
+
╚═════════════════════════ least privilege por padrão ═════════════════════════╝
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## 🚀 Instalação
|
|
28
|
+
|
|
29
|
+
```powershell
|
|
30
|
+
pip install clickhouse-users-cli
|
|
31
|
+
ch-users
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
| Cenário | Comando |
|
|
35
|
+
|---|---|
|
|
36
|
+
| Instalar / atualizar | `pip install -U clickhouse-users-cli` |
|
|
37
|
+
| Rodar | `ch-users` |
|
|
38
|
+
| Do código-fonte | `pip install -r requirements.txt` + `python main.py` |
|
|
39
|
+
| Requisitos | Python `>= 3.10` + conta admin no ClickHouse (ex.: `default`) |
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
## ⚡ Comece em 60 segundos
|
|
44
|
+
|
|
45
|
+
1. Rode `ch-users` e conecte com sua conta admin (host, protocolo, porta, usuário/senha — testado com `SELECT 1`).
|
|
46
|
+
2. Escolha **Criar usuário** → perfil `readonly` → nome + senha → marque os bancos/tabelas → confira o preview.
|
|
47
|
+
3. Confirme. Pronto — o SQL abaixo foi executado:
|
|
48
|
+
|
|
49
|
+
```sql
|
|
50
|
+
CREATE USER IF NOT EXISTS `analyst_julho` IDENTIFIED WITH plaintext_password BY '***' HOST ANY;
|
|
51
|
+
GRANT SHOW, SELECT ON `vendas`.`pedidos` TO `analyst_julho`;
|
|
52
|
+
GRANT SHOW, SELECT ON `vendas`.`clientes` TO `analyst_julho`;
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
---
|
|
56
|
+
|
|
57
|
+
## 🧭 Menu principal
|
|
58
|
+
|
|
59
|
+
Após conectar, o menu fica em loop — dá para fazer várias operações sem reconectar:
|
|
60
|
+
|
|
61
|
+
| Opção | O que faz |
|
|
62
|
+
|---|---|
|
|
63
|
+
| 🌱 **Criar usuário** | Fluxo guiado em 6 etapas (perfil → credenciais → escopo → hosts → revisão) |
|
|
64
|
+
| 📋 **Listar usuários** | Tabela via `SHOW USERS` + detalhe opcional (`SHOW CREATE USER` e `SHOW GRANTS FOR`) |
|
|
65
|
+
| 🛠️ **Gerenciar usuário** | Editar permissões · desativar · reativar · excluir |
|
|
66
|
+
| 🧹 **Esquecer sessão** | Apaga o YAML de conexão salva *(aparece só se existir)* |
|
|
67
|
+
| 👋 **Sair** | Encerra (Ctrl+C também sai limpo, sem executar nada) |
|
|
68
|
+
|
|
69
|
+
### Criar — as 6 etapas
|
|
70
|
+
|
|
71
|
+
1. 🔌 **Conexão** — host, protocolo (`http:8123` / `https:8443`), porta, usuário/senha admin. Falhou? Tentar de novo / editar / sair.
|
|
72
|
+
2. 🎭 **Tipo de usuário** — perfil com descrição (`readonly`, `readwrite`, `admin`, `custom`).
|
|
73
|
+
3. 🪪 **Novo usuário** — nome validado (letras, números, `_`; bloqueia `default`, `root`…) + senha com confirmação.
|
|
74
|
+
4. 🗂️ **Escopo** — `SHOW DATABASES` → marque bancos (nada vem marcado; há a opção `✓ Todos os bancos`) → por banco, marque tabelas ou `banco.*` (vale para tabelas futuras).
|
|
75
|
+
5. 🔑 **Privilégios + origem** — no `custom`, marque só o necessário (`DROP`/`TRUNCATE` pedem confirmação extra); depois `HOST ANY | LOCALHOST | IPs`.
|
|
76
|
+
6. 👀 **Revisão** — tabela-resumo + SQL com syntax highlight + confirmação final.
|
|
77
|
+
|
|
78
|
+
### Gerenciar — os 4 poderes
|
|
79
|
+
|
|
80
|
+
Escolhe 1 usuário, vê status (`HOST NONE` = inativo) + grants atuais, depois:
|
|
81
|
+
|
|
82
|
+
| Ação | SQL executado | Reversível? |
|
|
83
|
+
|---|---|---|
|
|
84
|
+
| ✏️ **Editar permissões** | `REVOKE ALL ON *.*` + novos `GRANTs` (perfil + escopo perguntados de novo, com frases próprias de edição) | ✅ ( reaplicando) |
|
|
85
|
+
| 🚫 **Desativar** | `ALTER USER \`nome\` HOST NONE` (bloqueia login, mantém grants) | ✅ via Reativar |
|
|
86
|
+
| ✅ **Reativar** | `ALTER USER \`nome\` HOST ANY` | — |
|
|
87
|
+
| 🗑️ **Excluir** | `DROP USER IF EXISTS \`nome\`` | ❌ definitivo |
|
|
88
|
+
|
|
89
|
+
> Todo DDL tem preview + confirmação com default **não**. Mexer no próprio usuário logado gera alerta extra. 👻
|
|
90
|
+
|
|
91
|
+
### 💾 Sessão salva (manter conectado)
|
|
92
|
+
|
|
93
|
+
- Após conectar, o CLI pergunta se quer **manter conectado**: salva `~/.ch-users/connection.yaml` (host, porta, protocolo, usuário, senha).
|
|
94
|
+
- Na próxima execução: **usar a salva · nova conexão · apagar a salva** (a senha nunca é exibida).
|
|
95
|
+
- ⚠️ A senha fica em **texto puro** no arquivo (`0600` no Linux/mac; no Windows vale o aviso em tela). Use só em máquina confiável — nunca compartilhe o arquivo.
|
|
96
|
+
|
|
97
|
+
---
|
|
98
|
+
|
|
99
|
+
## 🔐 Permissões que sua conta admin precisa
|
|
100
|
+
|
|
101
|
+
| Para… | Privilégio ClickHouse |
|
|
102
|
+
|---|---|
|
|
103
|
+
| Criar + conceder | `CREATE USER` + `GRANT` (nos escopos) |
|
|
104
|
+
| Listar / auditar | `SHOW USERS` (+ acesso aos grants) |
|
|
105
|
+
| Desativar / reativar / editar acessos | `ALTER USER` + `GRANT`/`REVOKE` nos escopos |
|
|
106
|
+
| Excluir | `DROP USER` |
|
|
107
|
+
|
|
108
|
+
Sem a permissão, o comando falha com mensagem amigável + dica — nada quebra pela metade sem aviso (na edição, se o `GRANT` falhar após o `REVOKE`, o CLI avisa para conferir em **Listar**).
|
|
109
|
+
|
|
110
|
+
---
|
|
111
|
+
|
|
112
|
+
## 🎭 Perfis (tipo de acesso)
|
|
113
|
+
|
|
114
|
+
| Perfil | Privilégios | Feito para |
|
|
115
|
+
|---|---|---|
|
|
116
|
+
| `readonly` | `SHOW, SELECT` | BI, analistas |
|
|
117
|
+
| `readwrite` | `SHOW, SELECT, INSERT` | Engenheiros, ingestão |
|
|
118
|
+
| `admin` | `ALL ... WITH GRANT OPTION` | ⚠️ Acesso total — cuidado! |
|
|
119
|
+
| `custom` | Você marca: `SELECT/SHOW/INSERT/CREATE/ALTER/DROP/TRUNCATE/OPTIMIZE/KILL QUERY` | Casos especiais |
|
|
120
|
+
|
|
121
|
+
---
|
|
122
|
+
|
|
123
|
+
## 🧠 Por que cada tela é do jeito que é
|
|
124
|
+
|
|
125
|
+
| Dado | Widget | Motivo |
|
|
126
|
+
|---|---|---|
|
|
127
|
+
| Host, porta, nomes, IPs | `text` + validação + `default` | Entrada livre com exemplo; `default` acelera localhost:8123 |
|
|
128
|
+
| Senhas | `password` mascarado | Não ecoa segredo; novo usuário pede confirmação |
|
|
129
|
+
| Protocolo / perfil / ação | `select` com descrição | Escolha única; descrição explica o impacto |
|
|
130
|
+
| Bancos, tabelas, privilégios | `checkbox` (espaço marca) | Multi-seleção; `banco.*` evita marcar 100 tabelas |
|
|
131
|
+
| Confirmações destrutivas | `confirm` com default seguro | O "não" é sempre o padrão |
|
|
132
|
+
| Progresso | spinner + cabeçalho de etapa | Você sempre sabe "onde estou" e o que está carregando |
|
|
133
|
+
| Revisão | tabela + SQL destacado | Sem caixa-preta: o SQL exato antes de executar |
|
|
134
|
+
|
|
135
|
+
Princípios: **opt-in explícito** (nada pré-marcado), **escape correto** (backticks em identificadores, aspas simples em strings), **SQL separado da UI** (`sql_builder.py` é puro e testável sem banco).
|
|
136
|
+
|
|
137
|
+
---
|
|
138
|
+
|
|
139
|
+
## 🧑💻 Desenvolvimento
|
|
140
|
+
|
|
141
|
+
```powershell
|
|
142
|
+
pip install -r requirements.txt
|
|
143
|
+
python main.py # roda do fonte
|
|
144
|
+
python -m build # gera sdist + wheel em dist/
|
|
145
|
+
python -m twine check dist/* # valida (inclusive este README)
|
|
146
|
+
python -m twine upload dist/* # publica (precisa de token PyPI)
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
Versão em fonte única: `clickhouse_users_cli/__init__.py` (`__version__`).
|
|
150
|
+
|
|
151
|
+
```
|
|
152
|
+
main.py # entrypoint (dev local)
|
|
153
|
+
requirements.txt
|
|
154
|
+
pyproject.toml # build + metadados PyPI (comando: ch-users)
|
|
155
|
+
clickhouse_users_cli/
|
|
156
|
+
__init__.py # __version__
|
|
157
|
+
app.py # fluxos interativos (criar, listar, gerenciar, sessão)
|
|
158
|
+
db.py # clickhouse-connect: connect, SHOWs, DDL
|
|
159
|
+
session.py # sessão YAML local (salvar/carregar/apagar)
|
|
160
|
+
sql_builder.py # CREATE/ALTER/DROP/GRANT/REVOKE puros (testável)
|
|
161
|
+
validators.py # validações por tipo de input
|
|
162
|
+
style.py # banner, etapas, tabelas e mensagens (Rich)
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
---
|
|
166
|
+
|
|
167
|
+
## 📝 Changelog
|
|
168
|
+
|
|
169
|
+
| Versão | Novidade |
|
|
170
|
+
|---|---|
|
|
171
|
+
| `0.1.4` | Frases próprias no modo edição (sem `2/6`, `4/6` da criação) |
|
|
172
|
+
| `0.1.3` | Editar permissões (`REVOKE ALL` + novos `GRANTs`) |
|
|
173
|
+
| `0.1.2` | Sessão salva em YAML + visual profissional (banner, badges, tabelas) |
|
|
174
|
+
| `0.1.1` | Lista sem pré-seleção + opção `✓ Todos os bancos` |
|
|
175
|
+
| `0.1.0` | Criar, listar e gerenciar (desativar/reativar/excluir) |
|
|
176
|
+
|
|
177
|
+
---
|
|
178
|
+
|
|
179
|
+
## 📄 Licença
|
|
180
|
+
|
|
181
|
+
MIT — veja [LICENSE](LICENSE).
|
|
@@ -106,11 +106,16 @@ def connect_with_retry(conn: ConnectionInfo) -> ClickHouseAdmin:
|
|
|
106
106
|
|
|
107
107
|
# ── Etapa 2: perfil do novo usuário ───────────────────────────────────────────
|
|
108
108
|
|
|
109
|
-
def ask_profile() -> str:
|
|
110
|
-
|
|
109
|
+
def ask_profile(mode: str = "create") -> str:
|
|
110
|
+
if mode == "edit":
|
|
111
|
+
step("Editar · Tipo de acesso", "O perfil redefine os privilégios (os atuais serão zerados).")
|
|
112
|
+
question = "Qual o novo tipo de acesso?"
|
|
113
|
+
else:
|
|
114
|
+
step("2/6 · Tipo de usuário", "O perfil define os privilégios padrão (least privilege primeiro).")
|
|
115
|
+
question = "Que tipo de usuário criar?"
|
|
111
116
|
return _ask_or_abort(
|
|
112
117
|
Q.select(
|
|
113
|
-
|
|
118
|
+
question,
|
|
114
119
|
choices=[Q.Choice(PROFILE_LABELS[k], value=k) for k in ("readonly", "readwrite", "admin", "custom")],
|
|
115
120
|
default="readonly",
|
|
116
121
|
style=APP_STYLE, qmark="›",
|
|
@@ -140,8 +145,11 @@ def ask_new_credentials() -> tuple[str, str]:
|
|
|
140
145
|
|
|
141
146
|
# ── Etapa 4: escopo (bancos → tabelas) ────────────────────────────────────────
|
|
142
147
|
|
|
143
|
-
def ask_databases(admin: ClickHouseAdmin) -> list[str]:
|
|
144
|
-
|
|
148
|
+
def ask_databases(admin: ClickHouseAdmin, mode: str = "create") -> list[str]:
|
|
149
|
+
if mode == "edit":
|
|
150
|
+
step("Editar · Escopo — bancos", "Espaço marca · A confirma · Ctrl+A inverte a seleção.")
|
|
151
|
+
else:
|
|
152
|
+
step("4/6 · Escopo — bancos", "Espaço marca · A confirma · Ctrl+A inverte a seleção.")
|
|
145
153
|
with console.status("[cyan]Listando bancos…[/]", spinner="dots"):
|
|
146
154
|
try:
|
|
147
155
|
databases = admin.list_databases()
|
|
@@ -176,8 +184,11 @@ def ask_databases(admin: ClickHouseAdmin) -> list[str]:
|
|
|
176
184
|
return selected
|
|
177
185
|
|
|
178
186
|
|
|
179
|
-
def ask_tables(admin: ClickHouseAdmin, databases: list[str]) -> list[GrantScope]:
|
|
180
|
-
|
|
187
|
+
def ask_tables(admin: ClickHouseAdmin, databases: list[str], mode: str = "create") -> list[GrantScope]:
|
|
188
|
+
if mode == "edit":
|
|
189
|
+
step("Editar · Escopo — tabelas", "Escolha '*' para o banco inteiro ou marque tabelas específicas.")
|
|
190
|
+
else:
|
|
191
|
+
step("4/6 · Escopo — tabelas", "Escolha '*' para o banco inteiro ou marque tabelas específicas.")
|
|
181
192
|
scopes: list[GrantScope] = []
|
|
182
193
|
for db in databases:
|
|
183
194
|
try:
|
|
@@ -226,13 +237,16 @@ PRIVILEGE_CHOICES = [
|
|
|
226
237
|
]
|
|
227
238
|
|
|
228
239
|
|
|
229
|
-
def ask_privileges(profile: str) -> tuple[list[str], bool]:
|
|
240
|
+
def ask_privileges(profile: str, mode: str = "create") -> tuple[list[str], bool]:
|
|
230
241
|
"""Retorna (privilégios, grant_option)."""
|
|
231
242
|
if profile != "custom":
|
|
232
243
|
grant_option = profile == "admin"
|
|
233
244
|
return list(PROFILE_PRIVILEGES[profile]), grant_option
|
|
234
245
|
|
|
235
|
-
|
|
246
|
+
if mode == "edit":
|
|
247
|
+
step("Editar · Privilégios personalizados", "Marque só o necessário — DROP/TRUNCATE exigem confirmação extra.")
|
|
248
|
+
else:
|
|
249
|
+
step("5/6 · Privilégios personalizados", "Marque só o necessário — DROP/TRUNCATE exigem confirmação extra.")
|
|
236
250
|
privs: list[str] = _ask_or_abort(
|
|
237
251
|
Q.checkbox(
|
|
238
252
|
"Quais privilégios conceder?",
|
|
@@ -247,7 +261,7 @@ def ask_privileges(profile: str) -> tuple[list[str], bool]:
|
|
|
247
261
|
Q.confirm("Você marcou privilégio destrutivo. Tem certeza?", default=False, style=APP_STYLE, qmark="›")
|
|
248
262
|
)
|
|
249
263
|
if not grant_option_confirm:
|
|
250
|
-
return ask_privileges("custom")
|
|
264
|
+
return ask_privileges("custom", mode=mode)
|
|
251
265
|
else:
|
|
252
266
|
grant_option = _ask_or_abort(
|
|
253
267
|
Q.confirm("Permitir repassar acessos (WITH GRANT OPTION)?", default=False, style=APP_STYLE, qmark="›")
|
|
@@ -511,12 +525,12 @@ def flow_edit_grants(admin: ClickHouseAdmin, username: str) -> None:
|
|
|
511
525
|
if username == admin.conn.username:
|
|
512
526
|
warn(f"'{username}' é o usuário conectado agora. Zerar os próprios acessos pode te derrubar.")
|
|
513
527
|
|
|
514
|
-
profile = ask_profile()
|
|
515
|
-
privileges, grant_option = ask_privileges(profile)
|
|
528
|
+
profile = ask_profile(mode="edit")
|
|
529
|
+
privileges, grant_option = ask_privileges(profile, mode="edit")
|
|
516
530
|
if profile == "admin":
|
|
517
531
|
grant_option = True
|
|
518
|
-
databases = ask_databases(admin)
|
|
519
|
-
scopes = ask_tables(admin, databases)
|
|
532
|
+
databases = ask_databases(admin, mode="edit")
|
|
533
|
+
scopes = ask_tables(admin, databases, mode="edit")
|
|
520
534
|
|
|
521
535
|
statements = build_edit_grants_statements(username, privileges, scopes, grant_option)
|
|
522
536
|
table = make_table(f"Novos acessos de '{username}'")
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: clickhouse-users-cli
|
|
3
|
+
Version: 0.1.5
|
|
4
|
+
Summary: CLI interativa para criar usuarios ClickHouse com privilegio minimo (least privilege)
|
|
5
|
+
License-Expression: MIT
|
|
6
|
+
Keywords: clickhouse,cli,users,access-control,least-privilege
|
|
7
|
+
Classifier: Programming Language :: Python :: 3
|
|
8
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
9
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
10
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
11
|
+
Classifier: Environment :: Console
|
|
12
|
+
Classifier: Intended Audience :: System Administrators
|
|
13
|
+
Classifier: Operating System :: OS Independent
|
|
14
|
+
Classifier: Topic :: Database
|
|
15
|
+
Classifier: Topic :: System :: Systems Administration
|
|
16
|
+
Requires-Python: >=3.10
|
|
17
|
+
Description-Content-Type: text/markdown
|
|
18
|
+
License-File: LICENSE
|
|
19
|
+
Requires-Dist: questionary>=2.0.0
|
|
20
|
+
Requires-Dist: clickhouse-connect>=0.8.0
|
|
21
|
+
Requires-Dist: rich>=13.0.0
|
|
22
|
+
Requires-Dist: pyyaml>=6.0
|
|
23
|
+
Dynamic: license-file
|
|
24
|
+
|
|
25
|
+
# ⬢ ClickHouse Users CLI
|
|
26
|
+
|
|
27
|
+
[](https://pypi.org/project/clickhouse-users-cli/)
|
|
28
|
+
[](https://pypi.org/project/clickhouse-users-cli/)
|
|
29
|
+
[](https://opensource.org/licenses/MIT)
|
|
30
|
+
|
|
31
|
+
> Crie e gerencie usuários no ClickHouse com **privilégio mínimo** (*least privilege*) — sem decorar sintaxe de `GRANT`, sem acesso amplo por acidente.
|
|
32
|
+
|
|
33
|
+
CLI interativa em Python ([`questionary`](https://questionary.readthedocs.io/) + [`rich`](https://github.com/Textualize/rich)): ela pergunta, você marca com `espaço`, confere o **SQL exato com preview** e só então executa. Nada roda sem confirmação.
|
|
34
|
+
|
|
35
|
+
```
|
|
36
|
+
╔══════════════════════════════════════════════════════════════════════════════╗
|
|
37
|
+
║ ║
|
|
38
|
+
║ ╭──────────╮ ║
|
|
39
|
+
║ │ ▓▓▓▓▓▓▓▓ │ ║
|
|
40
|
+
║ │ │ ║
|
|
41
|
+
║ ╰──────────╯ ║
|
|
42
|
+
║ ⬢ ClickHouse Users CLI ║
|
|
43
|
+
║ Crie usuários com escopo mínimo necessário ║
|
|
44
|
+
║ criar ◆ listar ◆ desativar ◆ auditar ║
|
|
45
|
+
║ ║
|
|
46
|
+
╚═════════════════════════ least privilege por padrão ═════════════════════════╝
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
---
|
|
50
|
+
|
|
51
|
+
## 🚀 Instalação
|
|
52
|
+
|
|
53
|
+
```powershell
|
|
54
|
+
pip install clickhouse-users-cli
|
|
55
|
+
ch-users
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
| Cenário | Comando |
|
|
59
|
+
|---|---|
|
|
60
|
+
| Instalar / atualizar | `pip install -U clickhouse-users-cli` |
|
|
61
|
+
| Rodar | `ch-users` |
|
|
62
|
+
| Do código-fonte | `pip install -r requirements.txt` + `python main.py` |
|
|
63
|
+
| Requisitos | Python `>= 3.10` + conta admin no ClickHouse (ex.: `default`) |
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
## ⚡ Comece em 60 segundos
|
|
68
|
+
|
|
69
|
+
1. Rode `ch-users` e conecte com sua conta admin (host, protocolo, porta, usuário/senha — testado com `SELECT 1`).
|
|
70
|
+
2. Escolha **Criar usuário** → perfil `readonly` → nome + senha → marque os bancos/tabelas → confira o preview.
|
|
71
|
+
3. Confirme. Pronto — o SQL abaixo foi executado:
|
|
72
|
+
|
|
73
|
+
```sql
|
|
74
|
+
CREATE USER IF NOT EXISTS `analyst_julho` IDENTIFIED WITH plaintext_password BY '***' HOST ANY;
|
|
75
|
+
GRANT SHOW, SELECT ON `vendas`.`pedidos` TO `analyst_julho`;
|
|
76
|
+
GRANT SHOW, SELECT ON `vendas`.`clientes` TO `analyst_julho`;
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
---
|
|
80
|
+
|
|
81
|
+
## 🧭 Menu principal
|
|
82
|
+
|
|
83
|
+
Após conectar, o menu fica em loop — dá para fazer várias operações sem reconectar:
|
|
84
|
+
|
|
85
|
+
| Opção | O que faz |
|
|
86
|
+
|---|---|
|
|
87
|
+
| 🌱 **Criar usuário** | Fluxo guiado em 6 etapas (perfil → credenciais → escopo → hosts → revisão) |
|
|
88
|
+
| 📋 **Listar usuários** | Tabela via `SHOW USERS` + detalhe opcional (`SHOW CREATE USER` e `SHOW GRANTS FOR`) |
|
|
89
|
+
| 🛠️ **Gerenciar usuário** | Editar permissões · desativar · reativar · excluir |
|
|
90
|
+
| 🧹 **Esquecer sessão** | Apaga o YAML de conexão salva *(aparece só se existir)* |
|
|
91
|
+
| 👋 **Sair** | Encerra (Ctrl+C também sai limpo, sem executar nada) |
|
|
92
|
+
|
|
93
|
+
### Criar — as 6 etapas
|
|
94
|
+
|
|
95
|
+
1. 🔌 **Conexão** — host, protocolo (`http:8123` / `https:8443`), porta, usuário/senha admin. Falhou? Tentar de novo / editar / sair.
|
|
96
|
+
2. 🎭 **Tipo de usuário** — perfil com descrição (`readonly`, `readwrite`, `admin`, `custom`).
|
|
97
|
+
3. 🪪 **Novo usuário** — nome validado (letras, números, `_`; bloqueia `default`, `root`…) + senha com confirmação.
|
|
98
|
+
4. 🗂️ **Escopo** — `SHOW DATABASES` → marque bancos (nada vem marcado; há a opção `✓ Todos os bancos`) → por banco, marque tabelas ou `banco.*` (vale para tabelas futuras).
|
|
99
|
+
5. 🔑 **Privilégios + origem** — no `custom`, marque só o necessário (`DROP`/`TRUNCATE` pedem confirmação extra); depois `HOST ANY | LOCALHOST | IPs`.
|
|
100
|
+
6. 👀 **Revisão** — tabela-resumo + SQL com syntax highlight + confirmação final.
|
|
101
|
+
|
|
102
|
+
### Gerenciar — os 4 poderes
|
|
103
|
+
|
|
104
|
+
Escolhe 1 usuário, vê status (`HOST NONE` = inativo) + grants atuais, depois:
|
|
105
|
+
|
|
106
|
+
| Ação | SQL executado | Reversível? |
|
|
107
|
+
|---|---|---|
|
|
108
|
+
| ✏️ **Editar permissões** | `REVOKE ALL ON *.*` + novos `GRANTs` (perfil + escopo perguntados de novo, com frases próprias de edição) | ✅ ( reaplicando) |
|
|
109
|
+
| 🚫 **Desativar** | `ALTER USER \`nome\` HOST NONE` (bloqueia login, mantém grants) | ✅ via Reativar |
|
|
110
|
+
| ✅ **Reativar** | `ALTER USER \`nome\` HOST ANY` | — |
|
|
111
|
+
| 🗑️ **Excluir** | `DROP USER IF EXISTS \`nome\`` | ❌ definitivo |
|
|
112
|
+
|
|
113
|
+
> Todo DDL tem preview + confirmação com default **não**. Mexer no próprio usuário logado gera alerta extra. 👻
|
|
114
|
+
|
|
115
|
+
### 💾 Sessão salva (manter conectado)
|
|
116
|
+
|
|
117
|
+
- Após conectar, o CLI pergunta se quer **manter conectado**: salva `~/.ch-users/connection.yaml` (host, porta, protocolo, usuário, senha).
|
|
118
|
+
- Na próxima execução: **usar a salva · nova conexão · apagar a salva** (a senha nunca é exibida).
|
|
119
|
+
- ⚠️ A senha fica em **texto puro** no arquivo (`0600` no Linux/mac; no Windows vale o aviso em tela). Use só em máquina confiável — nunca compartilhe o arquivo.
|
|
120
|
+
|
|
121
|
+
---
|
|
122
|
+
|
|
123
|
+
## 🔐 Permissões que sua conta admin precisa
|
|
124
|
+
|
|
125
|
+
| Para… | Privilégio ClickHouse |
|
|
126
|
+
|---|---|
|
|
127
|
+
| Criar + conceder | `CREATE USER` + `GRANT` (nos escopos) |
|
|
128
|
+
| Listar / auditar | `SHOW USERS` (+ acesso aos grants) |
|
|
129
|
+
| Desativar / reativar / editar acessos | `ALTER USER` + `GRANT`/`REVOKE` nos escopos |
|
|
130
|
+
| Excluir | `DROP USER` |
|
|
131
|
+
|
|
132
|
+
Sem a permissão, o comando falha com mensagem amigável + dica — nada quebra pela metade sem aviso (na edição, se o `GRANT` falhar após o `REVOKE`, o CLI avisa para conferir em **Listar**).
|
|
133
|
+
|
|
134
|
+
---
|
|
135
|
+
|
|
136
|
+
## 🎭 Perfis (tipo de acesso)
|
|
137
|
+
|
|
138
|
+
| Perfil | Privilégios | Feito para |
|
|
139
|
+
|---|---|---|
|
|
140
|
+
| `readonly` | `SHOW, SELECT` | BI, analistas |
|
|
141
|
+
| `readwrite` | `SHOW, SELECT, INSERT` | Engenheiros, ingestão |
|
|
142
|
+
| `admin` | `ALL ... WITH GRANT OPTION` | ⚠️ Acesso total — cuidado! |
|
|
143
|
+
| `custom` | Você marca: `SELECT/SHOW/INSERT/CREATE/ALTER/DROP/TRUNCATE/OPTIMIZE/KILL QUERY` | Casos especiais |
|
|
144
|
+
|
|
145
|
+
---
|
|
146
|
+
|
|
147
|
+
## 🧠 Por que cada tela é do jeito que é
|
|
148
|
+
|
|
149
|
+
| Dado | Widget | Motivo |
|
|
150
|
+
|---|---|---|
|
|
151
|
+
| Host, porta, nomes, IPs | `text` + validação + `default` | Entrada livre com exemplo; `default` acelera localhost:8123 |
|
|
152
|
+
| Senhas | `password` mascarado | Não ecoa segredo; novo usuário pede confirmação |
|
|
153
|
+
| Protocolo / perfil / ação | `select` com descrição | Escolha única; descrição explica o impacto |
|
|
154
|
+
| Bancos, tabelas, privilégios | `checkbox` (espaço marca) | Multi-seleção; `banco.*` evita marcar 100 tabelas |
|
|
155
|
+
| Confirmações destrutivas | `confirm` com default seguro | O "não" é sempre o padrão |
|
|
156
|
+
| Progresso | spinner + cabeçalho de etapa | Você sempre sabe "onde estou" e o que está carregando |
|
|
157
|
+
| Revisão | tabela + SQL destacado | Sem caixa-preta: o SQL exato antes de executar |
|
|
158
|
+
|
|
159
|
+
Princípios: **opt-in explícito** (nada pré-marcado), **escape correto** (backticks em identificadores, aspas simples em strings), **SQL separado da UI** (`sql_builder.py` é puro e testável sem banco).
|
|
160
|
+
|
|
161
|
+
---
|
|
162
|
+
|
|
163
|
+
## 🧑💻 Desenvolvimento
|
|
164
|
+
|
|
165
|
+
```powershell
|
|
166
|
+
pip install -r requirements.txt
|
|
167
|
+
python main.py # roda do fonte
|
|
168
|
+
python -m build # gera sdist + wheel em dist/
|
|
169
|
+
python -m twine check dist/* # valida (inclusive este README)
|
|
170
|
+
python -m twine upload dist/* # publica (precisa de token PyPI)
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
Versão em fonte única: `clickhouse_users_cli/__init__.py` (`__version__`).
|
|
174
|
+
|
|
175
|
+
```
|
|
176
|
+
main.py # entrypoint (dev local)
|
|
177
|
+
requirements.txt
|
|
178
|
+
pyproject.toml # build + metadados PyPI (comando: ch-users)
|
|
179
|
+
clickhouse_users_cli/
|
|
180
|
+
__init__.py # __version__
|
|
181
|
+
app.py # fluxos interativos (criar, listar, gerenciar, sessão)
|
|
182
|
+
db.py # clickhouse-connect: connect, SHOWs, DDL
|
|
183
|
+
session.py # sessão YAML local (salvar/carregar/apagar)
|
|
184
|
+
sql_builder.py # CREATE/ALTER/DROP/GRANT/REVOKE puros (testável)
|
|
185
|
+
validators.py # validações por tipo de input
|
|
186
|
+
style.py # banner, etapas, tabelas e mensagens (Rich)
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
---
|
|
190
|
+
|
|
191
|
+
## 📝 Changelog
|
|
192
|
+
|
|
193
|
+
| Versão | Novidade |
|
|
194
|
+
|---|---|
|
|
195
|
+
| `0.1.4` | Frases próprias no modo edição (sem `2/6`, `4/6` da criação) |
|
|
196
|
+
| `0.1.3` | Editar permissões (`REVOKE ALL` + novos `GRANTs`) |
|
|
197
|
+
| `0.1.2` | Sessão salva em YAML + visual profissional (banner, badges, tabelas) |
|
|
198
|
+
| `0.1.1` | Lista sem pré-seleção + opção `✓ Todos os bancos` |
|
|
199
|
+
| `0.1.0` | Criar, listar e gerenciar (desativar/reativar/excluir) |
|
|
200
|
+
|
|
201
|
+
---
|
|
202
|
+
|
|
203
|
+
## 📄 Licença
|
|
204
|
+
|
|
205
|
+
MIT — veja [LICENSE](LICENSE).
|
|
@@ -1,126 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.4
|
|
2
|
-
Name: clickhouse-users-cli
|
|
3
|
-
Version: 0.1.3
|
|
4
|
-
Summary: CLI interativa para criar usuarios ClickHouse com privilegio minimo (least privilege)
|
|
5
|
-
License-Expression: MIT
|
|
6
|
-
Keywords: clickhouse,cli,users,access-control,least-privilege
|
|
7
|
-
Classifier: Programming Language :: Python :: 3
|
|
8
|
-
Classifier: Programming Language :: Python :: 3.10
|
|
9
|
-
Classifier: Programming Language :: Python :: 3.11
|
|
10
|
-
Classifier: Programming Language :: Python :: 3.12
|
|
11
|
-
Classifier: Environment :: Console
|
|
12
|
-
Classifier: Intended Audience :: System Administrators
|
|
13
|
-
Classifier: Operating System :: OS Independent
|
|
14
|
-
Classifier: Topic :: Database
|
|
15
|
-
Classifier: Topic :: System :: Systems Administration
|
|
16
|
-
Requires-Python: >=3.10
|
|
17
|
-
Description-Content-Type: text/markdown
|
|
18
|
-
License-File: LICENSE
|
|
19
|
-
Requires-Dist: questionary>=2.0.0
|
|
20
|
-
Requires-Dist: clickhouse-connect>=0.8.0
|
|
21
|
-
Requires-Dist: rich>=13.0.0
|
|
22
|
-
Requires-Dist: pyyaml>=6.0
|
|
23
|
-
Dynamic: license-file
|
|
24
|
-
|
|
25
|
-
# ClickHouse Users CLI
|
|
26
|
-
|
|
27
|
-
CLI interativa em Python com [`questionary`](https://questionary.readthedocs.io/) para criar usuários no ClickHouse com **privilégio mínimo** (least privilege): pergunta credenciais, lista bancos, lista tabelas, define perfil e gera `CREATE USER` + `GRANT`s com preview antes de executar.
|
|
28
|
-
|
|
29
|
-
## Instalar
|
|
30
|
-
|
|
31
|
-
```powershell
|
|
32
|
-
pip install clickhouse-users-cli
|
|
33
|
-
ch-users
|
|
34
|
-
```
|
|
35
|
-
|
|
36
|
-
## Rodar do código-fonte
|
|
37
|
-
|
|
38
|
-
```powershell
|
|
39
|
-
pip install -r requirements.txt
|
|
40
|
-
python main.py
|
|
41
|
-
```
|
|
42
|
-
|
|
43
|
-
Requer uma conta admin (ex.: `default`) com permissão `CREATE USER` + `GRANT`.
|
|
44
|
-
Para listar/gerenciar também precisa de `SHOW USERS` + `ALTER USER` / `DROP USER`.
|
|
45
|
-
|
|
46
|
-
## Menu
|
|
47
|
-
|
|
48
|
-
Após conectar, escolha: **Criar usuário** · **Listar usuários** · **Gerenciar usuário** · **Sair**.
|
|
49
|
-
O menu fica em loop — dá para criar, auditar e desativar vários sem reconectar.
|
|
50
|
-
|
|
51
|
-
## Sessão salva (manter conectado)
|
|
52
|
-
|
|
53
|
-
- Na primeira conexão o CLI pergunta se quer **manter conectado**: salva `~/.ch-users/connection.yaml` com host, porta, protocolo, usuário e senha.
|
|
54
|
-
- Na próxima execução, oferece **usar a salva / nova conexão / apagar a salva**.
|
|
55
|
-
- No menu há **Esquecer sessão** (apaga o YAML, com confirmação).
|
|
56
|
-
- Segurança: a senha fica em **texto puro** no arquivo (permissão `0600` no Linux/mac; no Windows vale o aviso em tela). Só use em máquina confiável — nunca compartilhe o arquivo.
|
|
57
|
-
|
|
58
|
-
## Fluxo — criar (6 etapas)
|
|
59
|
-
|
|
60
|
-
1. **Conexão** — host, protocolo, porta, usuário/senha admin. Testa com `SELECT 1` e permite tentar de novo / editar / sair.
|
|
61
|
-
2. **Tipo de usuário** — perfil (`readonly`, `readwrite`, `admin`, `custom`).
|
|
62
|
-
3. **Novo usuário** — nome validado + senha com confirmação.
|
|
63
|
-
4. **Escopo** — `SHOW DATABASES` → checkbox de bancos → `SHOW TABLES FROM` por banco → checkbox de tabelas (com opção `banco.*`).
|
|
64
|
-
5. **Privilégios + origem** — se `custom`, checkbox de privilégios; depois `HOST ANY | LOCALHOST | IPs`.
|
|
65
|
-
6. **Revisão** — tabela resumo (Rich) + SQL com syntax highlight + confirmação final.
|
|
66
|
-
|
|
67
|
-
Exemplo do SQL gerado:
|
|
68
|
-
|
|
69
|
-
```sql
|
|
70
|
-
CREATE USER IF NOT EXISTS `analyst_julho` IDENTIFIED WITH plaintext_password BY '***' HOST ANY;
|
|
71
|
-
GRANT SHOW, SELECT ON `vendas`.`pedidos` TO `analyst_julho`;
|
|
72
|
-
GRANT SHOW, SELECT ON `vendas`.`clientes` TO `analyst_julho`;
|
|
73
|
-
```
|
|
74
|
-
|
|
75
|
-
## Fluxo — listar / gerenciar
|
|
76
|
-
|
|
77
|
-
- **Listar** — `SHOW USERS` em tabela + opção de ver `SHOW CREATE USER` e `SHOW GRANTS FOR` de um usuário.
|
|
78
|
-
- **Gerenciar** — escolhe 1 usuário, vê status (`HOST NONE` = inativo) + grants, depois:
|
|
79
|
-
- **Editar permissões** → pergunta perfil (tipo de acesso) + bancos/tabelas e aplica `REVOKE ALL ON *.*` + novos `GRANTs` (com preview e confirmação);
|
|
80
|
-
- **Desativar** → `ALTER USER \`nome\` HOST NONE` (reversível, bloqueia login);
|
|
81
|
-
- **Reativar** → `ALTER USER \`nome\` HOST ANY`;
|
|
82
|
-
- **Excluir** → `DROP USER IF EXISTS \`nome\`` (definitivo).
|
|
83
|
-
- Todo DDL mostra preview + confirmação com default `não`. Mexer no próprio usuário logado gera alerta extra.
|
|
84
|
-
|
|
85
|
-
## Por que cada widget?
|
|
86
|
-
|
|
87
|
-
| Dado | Widget | Motivo semântico / UX |
|
|
88
|
-
|---|---|---|
|
|
89
|
-
| Host, porta, nomes, IPs | `text` + `validate` + `default` | Entrada livre com validação imediata e exemplo; `default` acelera o caminho feliz (localhost:8123) |
|
|
90
|
-
| Senhas (admin e nova) | `password` (mascarado) | Não ecoa segredo; com validação de tamanho e dupla confirmação no novo usuário |
|
|
91
|
-
| Protocolo (http/https) | `select` | Escolha única em lista pequena; descrição já indica a porta padrão |
|
|
92
|
-
| Perfil | `select` com descrição | 4 opções mutuamente exclusivas; descrição diz o privilégio e o público (analista, engenheiro…) |
|
|
93
|
-
| Bancos, tabelas, privilégios custom | `checkbox` + validação mín. 1 | Multi-seleção com `espaço`; instrução de teclado visível; `banco.*` evita marcar 100 tabelas |
|
|
94
|
-
| Confirmações (IF NOT EXISTS, GRANT OPTION, DROP, executar) | `confirm` com default seguro | Yes/No explícito; default é sempre a opção menos destrutiva |
|
|
95
|
-
| Progresso e erros | `rich.status` (spinner) + `Rule` por etapa | Feedback durante `SHOW DATABASES` / DDL; cabeçalho `1/6…6/6` orienta "onde estou" |
|
|
96
|
-
| Revisão | `rich.table` + `rich.syntax` | Resumo legível + SQL exato que será executado — sem "caixa-preta" |
|
|
97
|
-
|
|
98
|
-
Decisões de UX:
|
|
99
|
-
|
|
100
|
-
- **Nada pré-marcado + opção `✓ Todos os bancos`** (least privilege: acesso só via opt-in explícito; sistemas vão por último com tag `(sistema)`).
|
|
101
|
-
- **Ctrl+C = saída limpa**, nada executa sem confirmação final.
|
|
102
|
-
- **SQL separado da UI** (`clickhouse_users_cli/sql_builder.py`) — dá para testar sem banco.
|
|
103
|
-
- **Escape correto** de identificadores (backticks) e strings (aspas simples).
|
|
104
|
-
- **Perfis com defaults seguros**: `readonly → SHOW+SELECT`, `readwrite → +INSERT`, `admin → ALL + GRANT OPTION`, `custom → você escolhe` (com confirmação extra para `DROP`/`TRUNCATE`).
|
|
105
|
-
|
|
106
|
-
## Estrutura
|
|
107
|
-
|
|
108
|
-
```
|
|
109
|
-
main.py # entrypoint (dev local)
|
|
110
|
-
requirements.txt
|
|
111
|
-
pyproject.toml # build + metadados PyPI (comando: ch-users)
|
|
112
|
-
clickhouse_users_cli/
|
|
113
|
-
__init__.py # __version__ (fonte única da versão)
|
|
114
|
-
app.py # fluxo questionary (6 etapas)
|
|
115
|
-
db.py # clickhouse-connect: connect, list_databases/tables, execute
|
|
116
|
-
sql_builder.py # CREATE USER / GRANT puros (testável)
|
|
117
|
-
validators.py # validações por tipo de input
|
|
118
|
-
style.py # Style questionary + banner/tabela Rich
|
|
119
|
-
```
|
|
120
|
-
|
|
121
|
-
## Perfis
|
|
122
|
-
|
|
123
|
-
- `readonly`: `SHOW, SELECT` — BI, analistas.
|
|
124
|
-
- `readwrite`: `SHOW, SELECT, INSERT` — engenheiros, ingestão.
|
|
125
|
-
- `admin`: `ALL ... WITH GRANT OPTION` em `*.*` — cuidado!
|
|
126
|
-
- `custom`: `SELECT/SHOW/INSERT/CREATE/ALTER/DROP/TRUNCATE/OPTIMIZE/KILL QUERY` à escolha.
|
|
@@ -1,102 +0,0 @@
|
|
|
1
|
-
# ClickHouse Users CLI
|
|
2
|
-
|
|
3
|
-
CLI interativa em Python com [`questionary`](https://questionary.readthedocs.io/) para criar usuários no ClickHouse com **privilégio mínimo** (least privilege): pergunta credenciais, lista bancos, lista tabelas, define perfil e gera `CREATE USER` + `GRANT`s com preview antes de executar.
|
|
4
|
-
|
|
5
|
-
## Instalar
|
|
6
|
-
|
|
7
|
-
```powershell
|
|
8
|
-
pip install clickhouse-users-cli
|
|
9
|
-
ch-users
|
|
10
|
-
```
|
|
11
|
-
|
|
12
|
-
## Rodar do código-fonte
|
|
13
|
-
|
|
14
|
-
```powershell
|
|
15
|
-
pip install -r requirements.txt
|
|
16
|
-
python main.py
|
|
17
|
-
```
|
|
18
|
-
|
|
19
|
-
Requer uma conta admin (ex.: `default`) com permissão `CREATE USER` + `GRANT`.
|
|
20
|
-
Para listar/gerenciar também precisa de `SHOW USERS` + `ALTER USER` / `DROP USER`.
|
|
21
|
-
|
|
22
|
-
## Menu
|
|
23
|
-
|
|
24
|
-
Após conectar, escolha: **Criar usuário** · **Listar usuários** · **Gerenciar usuário** · **Sair**.
|
|
25
|
-
O menu fica em loop — dá para criar, auditar e desativar vários sem reconectar.
|
|
26
|
-
|
|
27
|
-
## Sessão salva (manter conectado)
|
|
28
|
-
|
|
29
|
-
- Na primeira conexão o CLI pergunta se quer **manter conectado**: salva `~/.ch-users/connection.yaml` com host, porta, protocolo, usuário e senha.
|
|
30
|
-
- Na próxima execução, oferece **usar a salva / nova conexão / apagar a salva**.
|
|
31
|
-
- No menu há **Esquecer sessão** (apaga o YAML, com confirmação).
|
|
32
|
-
- Segurança: a senha fica em **texto puro** no arquivo (permissão `0600` no Linux/mac; no Windows vale o aviso em tela). Só use em máquina confiável — nunca compartilhe o arquivo.
|
|
33
|
-
|
|
34
|
-
## Fluxo — criar (6 etapas)
|
|
35
|
-
|
|
36
|
-
1. **Conexão** — host, protocolo, porta, usuário/senha admin. Testa com `SELECT 1` e permite tentar de novo / editar / sair.
|
|
37
|
-
2. **Tipo de usuário** — perfil (`readonly`, `readwrite`, `admin`, `custom`).
|
|
38
|
-
3. **Novo usuário** — nome validado + senha com confirmação.
|
|
39
|
-
4. **Escopo** — `SHOW DATABASES` → checkbox de bancos → `SHOW TABLES FROM` por banco → checkbox de tabelas (com opção `banco.*`).
|
|
40
|
-
5. **Privilégios + origem** — se `custom`, checkbox de privilégios; depois `HOST ANY | LOCALHOST | IPs`.
|
|
41
|
-
6. **Revisão** — tabela resumo (Rich) + SQL com syntax highlight + confirmação final.
|
|
42
|
-
|
|
43
|
-
Exemplo do SQL gerado:
|
|
44
|
-
|
|
45
|
-
```sql
|
|
46
|
-
CREATE USER IF NOT EXISTS `analyst_julho` IDENTIFIED WITH plaintext_password BY '***' HOST ANY;
|
|
47
|
-
GRANT SHOW, SELECT ON `vendas`.`pedidos` TO `analyst_julho`;
|
|
48
|
-
GRANT SHOW, SELECT ON `vendas`.`clientes` TO `analyst_julho`;
|
|
49
|
-
```
|
|
50
|
-
|
|
51
|
-
## Fluxo — listar / gerenciar
|
|
52
|
-
|
|
53
|
-
- **Listar** — `SHOW USERS` em tabela + opção de ver `SHOW CREATE USER` e `SHOW GRANTS FOR` de um usuário.
|
|
54
|
-
- **Gerenciar** — escolhe 1 usuário, vê status (`HOST NONE` = inativo) + grants, depois:
|
|
55
|
-
- **Editar permissões** → pergunta perfil (tipo de acesso) + bancos/tabelas e aplica `REVOKE ALL ON *.*` + novos `GRANTs` (com preview e confirmação);
|
|
56
|
-
- **Desativar** → `ALTER USER \`nome\` HOST NONE` (reversível, bloqueia login);
|
|
57
|
-
- **Reativar** → `ALTER USER \`nome\` HOST ANY`;
|
|
58
|
-
- **Excluir** → `DROP USER IF EXISTS \`nome\`` (definitivo).
|
|
59
|
-
- Todo DDL mostra preview + confirmação com default `não`. Mexer no próprio usuário logado gera alerta extra.
|
|
60
|
-
|
|
61
|
-
## Por que cada widget?
|
|
62
|
-
|
|
63
|
-
| Dado | Widget | Motivo semântico / UX |
|
|
64
|
-
|---|---|---|
|
|
65
|
-
| Host, porta, nomes, IPs | `text` + `validate` + `default` | Entrada livre com validação imediata e exemplo; `default` acelera o caminho feliz (localhost:8123) |
|
|
66
|
-
| Senhas (admin e nova) | `password` (mascarado) | Não ecoa segredo; com validação de tamanho e dupla confirmação no novo usuário |
|
|
67
|
-
| Protocolo (http/https) | `select` | Escolha única em lista pequena; descrição já indica a porta padrão |
|
|
68
|
-
| Perfil | `select` com descrição | 4 opções mutuamente exclusivas; descrição diz o privilégio e o público (analista, engenheiro…) |
|
|
69
|
-
| Bancos, tabelas, privilégios custom | `checkbox` + validação mín. 1 | Multi-seleção com `espaço`; instrução de teclado visível; `banco.*` evita marcar 100 tabelas |
|
|
70
|
-
| Confirmações (IF NOT EXISTS, GRANT OPTION, DROP, executar) | `confirm` com default seguro | Yes/No explícito; default é sempre a opção menos destrutiva |
|
|
71
|
-
| Progresso e erros | `rich.status` (spinner) + `Rule` por etapa | Feedback durante `SHOW DATABASES` / DDL; cabeçalho `1/6…6/6` orienta "onde estou" |
|
|
72
|
-
| Revisão | `rich.table` + `rich.syntax` | Resumo legível + SQL exato que será executado — sem "caixa-preta" |
|
|
73
|
-
|
|
74
|
-
Decisões de UX:
|
|
75
|
-
|
|
76
|
-
- **Nada pré-marcado + opção `✓ Todos os bancos`** (least privilege: acesso só via opt-in explícito; sistemas vão por último com tag `(sistema)`).
|
|
77
|
-
- **Ctrl+C = saída limpa**, nada executa sem confirmação final.
|
|
78
|
-
- **SQL separado da UI** (`clickhouse_users_cli/sql_builder.py`) — dá para testar sem banco.
|
|
79
|
-
- **Escape correto** de identificadores (backticks) e strings (aspas simples).
|
|
80
|
-
- **Perfis com defaults seguros**: `readonly → SHOW+SELECT`, `readwrite → +INSERT`, `admin → ALL + GRANT OPTION`, `custom → você escolhe` (com confirmação extra para `DROP`/`TRUNCATE`).
|
|
81
|
-
|
|
82
|
-
## Estrutura
|
|
83
|
-
|
|
84
|
-
```
|
|
85
|
-
main.py # entrypoint (dev local)
|
|
86
|
-
requirements.txt
|
|
87
|
-
pyproject.toml # build + metadados PyPI (comando: ch-users)
|
|
88
|
-
clickhouse_users_cli/
|
|
89
|
-
__init__.py # __version__ (fonte única da versão)
|
|
90
|
-
app.py # fluxo questionary (6 etapas)
|
|
91
|
-
db.py # clickhouse-connect: connect, list_databases/tables, execute
|
|
92
|
-
sql_builder.py # CREATE USER / GRANT puros (testável)
|
|
93
|
-
validators.py # validações por tipo de input
|
|
94
|
-
style.py # Style questionary + banner/tabela Rich
|
|
95
|
-
```
|
|
96
|
-
|
|
97
|
-
## Perfis
|
|
98
|
-
|
|
99
|
-
- `readonly`: `SHOW, SELECT` — BI, analistas.
|
|
100
|
-
- `readwrite`: `SHOW, SELECT, INSERT` — engenheiros, ingestão.
|
|
101
|
-
- `admin`: `ALL ... WITH GRANT OPTION` em `*.*` — cuidado!
|
|
102
|
-
- `custom`: `SELECT/SHOW/INSERT/CREATE/ALTER/DROP/TRUNCATE/OPTIMIZE/KILL QUERY` à escolha.
|
|
@@ -1,126 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.4
|
|
2
|
-
Name: clickhouse-users-cli
|
|
3
|
-
Version: 0.1.3
|
|
4
|
-
Summary: CLI interativa para criar usuarios ClickHouse com privilegio minimo (least privilege)
|
|
5
|
-
License-Expression: MIT
|
|
6
|
-
Keywords: clickhouse,cli,users,access-control,least-privilege
|
|
7
|
-
Classifier: Programming Language :: Python :: 3
|
|
8
|
-
Classifier: Programming Language :: Python :: 3.10
|
|
9
|
-
Classifier: Programming Language :: Python :: 3.11
|
|
10
|
-
Classifier: Programming Language :: Python :: 3.12
|
|
11
|
-
Classifier: Environment :: Console
|
|
12
|
-
Classifier: Intended Audience :: System Administrators
|
|
13
|
-
Classifier: Operating System :: OS Independent
|
|
14
|
-
Classifier: Topic :: Database
|
|
15
|
-
Classifier: Topic :: System :: Systems Administration
|
|
16
|
-
Requires-Python: >=3.10
|
|
17
|
-
Description-Content-Type: text/markdown
|
|
18
|
-
License-File: LICENSE
|
|
19
|
-
Requires-Dist: questionary>=2.0.0
|
|
20
|
-
Requires-Dist: clickhouse-connect>=0.8.0
|
|
21
|
-
Requires-Dist: rich>=13.0.0
|
|
22
|
-
Requires-Dist: pyyaml>=6.0
|
|
23
|
-
Dynamic: license-file
|
|
24
|
-
|
|
25
|
-
# ClickHouse Users CLI
|
|
26
|
-
|
|
27
|
-
CLI interativa em Python com [`questionary`](https://questionary.readthedocs.io/) para criar usuários no ClickHouse com **privilégio mínimo** (least privilege): pergunta credenciais, lista bancos, lista tabelas, define perfil e gera `CREATE USER` + `GRANT`s com preview antes de executar.
|
|
28
|
-
|
|
29
|
-
## Instalar
|
|
30
|
-
|
|
31
|
-
```powershell
|
|
32
|
-
pip install clickhouse-users-cli
|
|
33
|
-
ch-users
|
|
34
|
-
```
|
|
35
|
-
|
|
36
|
-
## Rodar do código-fonte
|
|
37
|
-
|
|
38
|
-
```powershell
|
|
39
|
-
pip install -r requirements.txt
|
|
40
|
-
python main.py
|
|
41
|
-
```
|
|
42
|
-
|
|
43
|
-
Requer uma conta admin (ex.: `default`) com permissão `CREATE USER` + `GRANT`.
|
|
44
|
-
Para listar/gerenciar também precisa de `SHOW USERS` + `ALTER USER` / `DROP USER`.
|
|
45
|
-
|
|
46
|
-
## Menu
|
|
47
|
-
|
|
48
|
-
Após conectar, escolha: **Criar usuário** · **Listar usuários** · **Gerenciar usuário** · **Sair**.
|
|
49
|
-
O menu fica em loop — dá para criar, auditar e desativar vários sem reconectar.
|
|
50
|
-
|
|
51
|
-
## Sessão salva (manter conectado)
|
|
52
|
-
|
|
53
|
-
- Na primeira conexão o CLI pergunta se quer **manter conectado**: salva `~/.ch-users/connection.yaml` com host, porta, protocolo, usuário e senha.
|
|
54
|
-
- Na próxima execução, oferece **usar a salva / nova conexão / apagar a salva**.
|
|
55
|
-
- No menu há **Esquecer sessão** (apaga o YAML, com confirmação).
|
|
56
|
-
- Segurança: a senha fica em **texto puro** no arquivo (permissão `0600` no Linux/mac; no Windows vale o aviso em tela). Só use em máquina confiável — nunca compartilhe o arquivo.
|
|
57
|
-
|
|
58
|
-
## Fluxo — criar (6 etapas)
|
|
59
|
-
|
|
60
|
-
1. **Conexão** — host, protocolo, porta, usuário/senha admin. Testa com `SELECT 1` e permite tentar de novo / editar / sair.
|
|
61
|
-
2. **Tipo de usuário** — perfil (`readonly`, `readwrite`, `admin`, `custom`).
|
|
62
|
-
3. **Novo usuário** — nome validado + senha com confirmação.
|
|
63
|
-
4. **Escopo** — `SHOW DATABASES` → checkbox de bancos → `SHOW TABLES FROM` por banco → checkbox de tabelas (com opção `banco.*`).
|
|
64
|
-
5. **Privilégios + origem** — se `custom`, checkbox de privilégios; depois `HOST ANY | LOCALHOST | IPs`.
|
|
65
|
-
6. **Revisão** — tabela resumo (Rich) + SQL com syntax highlight + confirmação final.
|
|
66
|
-
|
|
67
|
-
Exemplo do SQL gerado:
|
|
68
|
-
|
|
69
|
-
```sql
|
|
70
|
-
CREATE USER IF NOT EXISTS `analyst_julho` IDENTIFIED WITH plaintext_password BY '***' HOST ANY;
|
|
71
|
-
GRANT SHOW, SELECT ON `vendas`.`pedidos` TO `analyst_julho`;
|
|
72
|
-
GRANT SHOW, SELECT ON `vendas`.`clientes` TO `analyst_julho`;
|
|
73
|
-
```
|
|
74
|
-
|
|
75
|
-
## Fluxo — listar / gerenciar
|
|
76
|
-
|
|
77
|
-
- **Listar** — `SHOW USERS` em tabela + opção de ver `SHOW CREATE USER` e `SHOW GRANTS FOR` de um usuário.
|
|
78
|
-
- **Gerenciar** — escolhe 1 usuário, vê status (`HOST NONE` = inativo) + grants, depois:
|
|
79
|
-
- **Editar permissões** → pergunta perfil (tipo de acesso) + bancos/tabelas e aplica `REVOKE ALL ON *.*` + novos `GRANTs` (com preview e confirmação);
|
|
80
|
-
- **Desativar** → `ALTER USER \`nome\` HOST NONE` (reversível, bloqueia login);
|
|
81
|
-
- **Reativar** → `ALTER USER \`nome\` HOST ANY`;
|
|
82
|
-
- **Excluir** → `DROP USER IF EXISTS \`nome\`` (definitivo).
|
|
83
|
-
- Todo DDL mostra preview + confirmação com default `não`. Mexer no próprio usuário logado gera alerta extra.
|
|
84
|
-
|
|
85
|
-
## Por que cada widget?
|
|
86
|
-
|
|
87
|
-
| Dado | Widget | Motivo semântico / UX |
|
|
88
|
-
|---|---|---|
|
|
89
|
-
| Host, porta, nomes, IPs | `text` + `validate` + `default` | Entrada livre com validação imediata e exemplo; `default` acelera o caminho feliz (localhost:8123) |
|
|
90
|
-
| Senhas (admin e nova) | `password` (mascarado) | Não ecoa segredo; com validação de tamanho e dupla confirmação no novo usuário |
|
|
91
|
-
| Protocolo (http/https) | `select` | Escolha única em lista pequena; descrição já indica a porta padrão |
|
|
92
|
-
| Perfil | `select` com descrição | 4 opções mutuamente exclusivas; descrição diz o privilégio e o público (analista, engenheiro…) |
|
|
93
|
-
| Bancos, tabelas, privilégios custom | `checkbox` + validação mín. 1 | Multi-seleção com `espaço`; instrução de teclado visível; `banco.*` evita marcar 100 tabelas |
|
|
94
|
-
| Confirmações (IF NOT EXISTS, GRANT OPTION, DROP, executar) | `confirm` com default seguro | Yes/No explícito; default é sempre a opção menos destrutiva |
|
|
95
|
-
| Progresso e erros | `rich.status` (spinner) + `Rule` por etapa | Feedback durante `SHOW DATABASES` / DDL; cabeçalho `1/6…6/6` orienta "onde estou" |
|
|
96
|
-
| Revisão | `rich.table` + `rich.syntax` | Resumo legível + SQL exato que será executado — sem "caixa-preta" |
|
|
97
|
-
|
|
98
|
-
Decisões de UX:
|
|
99
|
-
|
|
100
|
-
- **Nada pré-marcado + opção `✓ Todos os bancos`** (least privilege: acesso só via opt-in explícito; sistemas vão por último com tag `(sistema)`).
|
|
101
|
-
- **Ctrl+C = saída limpa**, nada executa sem confirmação final.
|
|
102
|
-
- **SQL separado da UI** (`clickhouse_users_cli/sql_builder.py`) — dá para testar sem banco.
|
|
103
|
-
- **Escape correto** de identificadores (backticks) e strings (aspas simples).
|
|
104
|
-
- **Perfis com defaults seguros**: `readonly → SHOW+SELECT`, `readwrite → +INSERT`, `admin → ALL + GRANT OPTION`, `custom → você escolhe` (com confirmação extra para `DROP`/`TRUNCATE`).
|
|
105
|
-
|
|
106
|
-
## Estrutura
|
|
107
|
-
|
|
108
|
-
```
|
|
109
|
-
main.py # entrypoint (dev local)
|
|
110
|
-
requirements.txt
|
|
111
|
-
pyproject.toml # build + metadados PyPI (comando: ch-users)
|
|
112
|
-
clickhouse_users_cli/
|
|
113
|
-
__init__.py # __version__ (fonte única da versão)
|
|
114
|
-
app.py # fluxo questionary (6 etapas)
|
|
115
|
-
db.py # clickhouse-connect: connect, list_databases/tables, execute
|
|
116
|
-
sql_builder.py # CREATE USER / GRANT puros (testável)
|
|
117
|
-
validators.py # validações por tipo de input
|
|
118
|
-
style.py # Style questionary + banner/tabela Rich
|
|
119
|
-
```
|
|
120
|
-
|
|
121
|
-
## Perfis
|
|
122
|
-
|
|
123
|
-
- `readonly`: `SHOW, SELECT` — BI, analistas.
|
|
124
|
-
- `readwrite`: `SHOW, SELECT, INSERT` — engenheiros, ingestão.
|
|
125
|
-
- `admin`: `ALL ... WITH GRANT OPTION` em `*.*` — cuidado!
|
|
126
|
-
- `custom`: `SELECT/SHOW/INSERT/CREATE/ALTER/DROP/TRUNCATE/OPTIMIZE/KILL QUERY` à escolha.
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{clickhouse_users_cli-0.1.3 → clickhouse_users_cli-0.1.5}/clickhouse_users_cli/sql_builder.py
RENAMED
|
File without changes
|
|
File without changes
|
{clickhouse_users_cli-0.1.3 → clickhouse_users_cli-0.1.5}/clickhouse_users_cli/validators.py
RENAMED
|
File without changes
|
{clickhouse_users_cli-0.1.3 → clickhouse_users_cli-0.1.5}/clickhouse_users_cli.egg-info/SOURCES.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{clickhouse_users_cli-0.1.3 → clickhouse_users_cli-0.1.5}/clickhouse_users_cli.egg-info/requires.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|