watchguardian 0.1.0__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.
Files changed (66) hide show
  1. watchguardian-0.1.0/PKG-INFO +19 -0
  2. watchguardian-0.1.0/README.md +0 -0
  3. watchguardian-0.1.0/WatchGuardian/__init__.py +1 -0
  4. watchguardian-0.1.0/WatchGuardian/database.py +1 -0
  5. watchguardian-0.1.0/WatchGuardian/server.py +1 -0
  6. watchguardian-0.1.0/pyproject.toml +36 -0
  7. watchguardian-0.1.0/setup.cfg +4 -0
  8. watchguardian-0.1.0/src/auth/token.py +62 -0
  9. watchguardian-0.1.0/src/cache/connect.py +72 -0
  10. watchguardian-0.1.0/src/cache/control.py +175 -0
  11. watchguardian-0.1.0/src/cache/manage.py +11 -0
  12. watchguardian-0.1.0/src/cli/auth.py +88 -0
  13. watchguardian-0.1.0/src/cli/main.py +48 -0
  14. watchguardian-0.1.0/src/cli/migrate.py +49 -0
  15. watchguardian-0.1.0/src/cli/server.py +138 -0
  16. watchguardian-0.1.0/src/client/auth.py +43 -0
  17. watchguardian-0.1.0/src/client/logs.py +148 -0
  18. watchguardian-0.1.0/src/client/manage.py +30 -0
  19. watchguardian-0.1.0/src/client/obs.py +140 -0
  20. watchguardian-0.1.0/src/core/module.py +2 -0
  21. watchguardian-0.1.0/src/core/settings.py +106 -0
  22. watchguardian-0.1.0/src/core/url.py +25 -0
  23. watchguardian-0.1.0/src/database/base.py +8 -0
  24. watchguardian-0.1.0/src/database/connection/engine.py +66 -0
  25. watchguardian-0.1.0/src/database/connection/manage.py +18 -0
  26. watchguardian-0.1.0/src/database/connection/session.py +25 -0
  27. watchguardian-0.1.0/src/database/control/logs.py +261 -0
  28. watchguardian-0.1.0/src/database/control/observability.py +250 -0
  29. watchguardian-0.1.0/src/database/manage.py +30 -0
  30. watchguardian-0.1.0/src/database/migrate.py +80 -0
  31. watchguardian-0.1.0/src/database/models/logs.py +21 -0
  32. watchguardian-0.1.0/src/database/models/observability.py +20 -0
  33. watchguardian-0.1.0/src/logs/colors.py +54 -0
  34. watchguardian-0.1.0/src/logs/loggin.py +14 -0
  35. watchguardian-0.1.0/src/logs/logs.py +184 -0
  36. watchguardian-0.1.0/src/logs/module.py +2 -0
  37. watchguardian-0.1.0/src/server/depends.py +56 -0
  38. watchguardian-0.1.0/src/server/handles/auth.py +74 -0
  39. watchguardian-0.1.0/src/server/handles/logs.py +76 -0
  40. watchguardian-0.1.0/src/server/handles/obs.py +106 -0
  41. watchguardian-0.1.0/src/server/manage.py +82 -0
  42. watchguardian-0.1.0/src/server/midlleware.py +41 -0
  43. watchguardian-0.1.0/src/server/schema/logs.py +16 -0
  44. watchguardian-0.1.0/src/server/schema/obs.py +20 -0
  45. watchguardian-0.1.0/src/service/cache.py +15 -0
  46. watchguardian-0.1.0/src/service/client.py +18 -0
  47. watchguardian-0.1.0/src/service/db/__init__.py +11 -0
  48. watchguardian-0.1.0/src/service/db/db.py +29 -0
  49. watchguardian-0.1.0/src/service/db/logs.py +154 -0
  50. watchguardian-0.1.0/src/service/db/manage.py +74 -0
  51. watchguardian-0.1.0/src/service/db/merge.py +31 -0
  52. watchguardian-0.1.0/src/service/db/obs.py +178 -0
  53. watchguardian-0.1.0/src/service/logs.py +104 -0
  54. watchguardian-0.1.0/src/service/module.py +28 -0
  55. watchguardian-0.1.0/src/service/obs/context.py +53 -0
  56. watchguardian-0.1.0/src/service/obs/manage.py +22 -0
  57. watchguardian-0.1.0/src/service/obs/watch.py +88 -0
  58. watchguardian-0.1.0/src/service/server.py +10 -0
  59. watchguardian-0.1.0/src/service/token.py +48 -0
  60. watchguardian-0.1.0/src/util/cmd.py +43 -0
  61. watchguardian-0.1.0/watchguardian.egg-info/PKG-INFO +19 -0
  62. watchguardian-0.1.0/watchguardian.egg-info/SOURCES.txt +64 -0
  63. watchguardian-0.1.0/watchguardian.egg-info/dependency_links.txt +1 -0
  64. watchguardian-0.1.0/watchguardian.egg-info/entry_points.txt +2 -0
  65. watchguardian-0.1.0/watchguardian.egg-info/requires.txt +11 -0
  66. watchguardian-0.1.0/watchguardian.egg-info/top_level.txt +2 -0
@@ -0,0 +1,19 @@
1
+ Metadata-Version: 2.4
2
+ Name: watchguardian
3
+ Version: 0.1.0
4
+ Summary: Observability, logging, database, authentication and server utilities for Python applications.
5
+ Author: Brayan de Souza Dias Vaz
6
+ Project-URL: Repository, https://github.com/BrayanDevZN/WatchGuardian
7
+ Requires-Python: >=3.12
8
+ Description-Content-Type: text/markdown
9
+ Requires-Dist: aiosqlite==0.22.1
10
+ Requires-Dist: asyncpg==0.32.0
11
+ Requires-Dist: fastapi==0.143.0
12
+ Requires-Dist: opentelemetry-api==1.45.1
13
+ Requires-Dist: pydantic==2.14.0
14
+ Requires-Dist: PyJWT==2.15.1
15
+ Requires-Dist: python-dotenv==1.2.4
16
+ Requires-Dist: redis==8.1.0
17
+ Requires-Dist: requests==2.34.2
18
+ Requires-Dist: SQLAlchemy==2.1.4
19
+ Requires-Dist: uvicorn==0.54.0
File without changes
@@ -0,0 +1 @@
1
+ from src.service.module import Settings, WatchLogs, WatchObs, WatchAuth
@@ -0,0 +1 @@
1
+ from src.service.module import WatchDb, CacheManage
@@ -0,0 +1 @@
1
+ from src.service.module import ClientHttp, WatchServer
@@ -0,0 +1,36 @@
1
+ [build-system]
2
+ requires = ["setuptools>=68", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "watchguardian"
7
+ version = "0.1.0"
8
+ description = "Observability, logging, database, authentication and server utilities for Python applications."
9
+ readme = "README.md"
10
+ requires-python = ">=3.12"
11
+ authors = [
12
+ { name = "Brayan de Souza Dias Vaz" }
13
+ ]
14
+ dependencies = [
15
+ "aiosqlite==0.22.1",
16
+ "asyncpg==0.32.0",
17
+ "fastapi==0.143.0",
18
+ "opentelemetry-api==1.45.1",
19
+ "pydantic==2.14.0",
20
+ "PyJWT==2.15.1",
21
+ "python-dotenv==1.2.4",
22
+ "redis==8.1.0",
23
+ "requests==2.34.2",
24
+ "SQLAlchemy==2.1.4",
25
+ "uvicorn==0.54.0",
26
+ ]
27
+
28
+ [project.urls]
29
+ Repository = "https://github.com/BrayanDevZN/WatchGuardian"
30
+
31
+ [project.scripts]
32
+ watchguardian = "src.cli.main:main"
33
+
34
+ [tool.setuptools.packages.find]
35
+ where = ["."]
36
+ include = ["WatchGuardian*", "src*"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,62 @@
1
+ "gera o token jwt"
2
+
3
+ from src.logs.module import Logs
4
+ logger = Logs(loglevel="SUCCESS")
5
+
6
+
7
+ import jwt
8
+ from jwt.exceptions import InvalidSignatureError
9
+
10
+ class JWT:
11
+
12
+ def __init__(self, secret:str) -> None:
13
+
14
+ self.secret = secret
15
+ self.alg = "HS256"
16
+
17
+ #Gera o token
18
+ async def encode(self, payload:dict) -> str:
19
+
20
+ try:
21
+
22
+ logger.info("Criando token...")
23
+
24
+ token= jwt.encode(
25
+ key=self.secret,
26
+ algorithm=self.alg,
27
+ payload=payload
28
+ )
29
+
30
+ logger.success("Token criado com sucesso!!")
31
+
32
+ return token
33
+
34
+ except Exception as error:
35
+
36
+ logger.error(f"Erro ao gerar token: {error}")
37
+ raise
38
+
39
+ async def decode(self, token:str) -> dict:
40
+
41
+ try:
42
+
43
+ logger.info("Decodificando token...")
44
+
45
+ payload = jwt.decode(
46
+ key=self.secret,
47
+ algorithms=self.alg,
48
+ jwt=token
49
+ )
50
+
51
+ logger.success("Toekn decodificado com sucesso!!")
52
+
53
+ return payload
54
+
55
+ except InvalidSignatureError as error:
56
+
57
+ logger.error(f"Erro ao decodificar token: {error}")
58
+ raise
59
+
60
+
61
+
62
+
@@ -0,0 +1,72 @@
1
+ from src.logs.module import Logs
2
+ logger = Logs(loglevel="SUCCESS")
3
+ import time
4
+ "Cria conexão com redis"
5
+
6
+ from redis import Redis
7
+
8
+ class RedisConnect:
9
+
10
+ def __init__(self, host:str, port:str|int, password:str|None = None)-> None:
11
+
12
+ self.host = host
13
+ self.port = port
14
+ self.password = password
15
+
16
+ #Cria conexão
17
+ def _conn(self) -> None:
18
+
19
+ try:
20
+
21
+ logger.info("Criando conexão com redis...")
22
+
23
+ self.client = (Redis(host=self.host, port=self.port, password=self.password, decode_responses=True)
24
+ if self.password is not None else
25
+ Redis(host=self.host, port=self.port, decode_responses=True))
26
+
27
+ logger.success("Conexão criada!!")
28
+
29
+ except Exception as error:
30
+
31
+ logger.error(f"Houve um erro ao criar conexão: {error}")
32
+ raise
33
+
34
+ #testa a conexão
35
+ def _test(self) -> None:
36
+
37
+ countdown = 0
38
+
39
+ while True:
40
+
41
+ try:
42
+
43
+ logger.info("Testando conexão com redis...")
44
+
45
+ self.client.ping()
46
+
47
+ logger.success("Conexão ok!!")
48
+
49
+ break
50
+
51
+ except Exception as error:
52
+
53
+ if countdown !=3:
54
+
55
+ logger.warning("Houve um erro na conexão, executando um novo teste em 5 segundos...")
56
+ countdown+=1
57
+ time.sleep(5)
58
+ continue
59
+
60
+ logger.error(f"Houve um erro ao se conectar: {error}")
61
+ raise
62
+
63
+ #Executa os metodos e retorna conexão
64
+ def get_client(self) ->Redis:
65
+
66
+ self._conn()
67
+ self._test()
68
+ return self.client
69
+
70
+
71
+
72
+
@@ -0,0 +1,175 @@
1
+ """
2
+ Cria as operações do Redis
3
+ """
4
+
5
+ import asyncio
6
+
7
+ from typing import Any, AsyncIterator
8
+
9
+ from redis import Redis
10
+ from redis.exceptions import WatchError
11
+
12
+ from src.logs.module import Logs
13
+
14
+
15
+ logger = Logs(loglevel="SUCCESS")
16
+
17
+
18
+ class RedisControl:
19
+
20
+ def __init__(self, client: Redis) -> None:
21
+ self.client = client
22
+
23
+ async def incr(self, key: str, time: int | None = None) -> int:
24
+ logger.info(f"Incrementando chave '{key}'...")
25
+
26
+ expire = time if time is not None else 60
27
+
28
+ while True:
29
+ try:
30
+ with self.client.pipeline(transaction=True) as session:
31
+ session.watch(key)
32
+
33
+ session.multi()
34
+ session.incr(key)
35
+ session.expire(key, expire)
36
+
37
+ result = session.execute()
38
+ value = result[0]
39
+
40
+ logger.success(f"Chave '{key}' incrementada com sucesso!")
41
+ return value
42
+
43
+ except WatchError:
44
+ logger.warning(f"A chave '{key}' foi alterada por outra operação. Tentando novamente...")
45
+
46
+ except Exception as error:
47
+ logger.error(f"Erro ao incrementar chave '{key}': {error}")
48
+ raise
49
+
50
+ async def hash(self, key: str, data: dict, time: int | None = None) -> None:
51
+ logger.info(f"Salvando hash '{key}'...")
52
+
53
+ expire = time if time is not None else 60
54
+
55
+ while True:
56
+ try:
57
+ with self.client.pipeline(transaction=True) as session:
58
+ session.watch(key)
59
+
60
+ session.multi()
61
+ session.hset(key, mapping=data)
62
+ session.expire(key, expire)
63
+
64
+ session.execute()
65
+
66
+ logger.success(f"Hash '{key}' salvo com sucesso!")
67
+ return
68
+
69
+ except WatchError:
70
+ logger.warning(f"O hash '{key}' foi alterado por outra operação. Tentando novamente...")
71
+
72
+ except Exception as error:
73
+ logger.error(f"Erro ao salvar hash '{key}': {error}")
74
+ raise
75
+
76
+ async def read(self, key: str, hash: bool = False) -> Any:
77
+ logger.info(f"Lendo chave '{key}'...")
78
+
79
+ try:
80
+ with self.client.pipeline(transaction=True) as session:
81
+ session.multi()
82
+
83
+ if hash:
84
+ session.hgetall(key)
85
+ else:
86
+ session.get(key)
87
+
88
+ result = session.execute()
89
+ value = result[0]
90
+
91
+ logger.success(f"Chave '{key}' lida com sucesso!")
92
+ return value
93
+
94
+ except Exception as error:
95
+ logger.error(f"Erro ao ler chave '{key}': {error}")
96
+ raise
97
+
98
+ async def delete(self, key: str) -> bool:
99
+ logger.info(f"Apagando cache '{key}'...")
100
+
101
+ while True:
102
+ try:
103
+ with self.client.pipeline(transaction=True) as session:
104
+ session.watch(key)
105
+
106
+ session.multi()
107
+ session.delete(key)
108
+
109
+ result = session.execute()
110
+ deleted = bool(result[0])
111
+
112
+ logger.success(f"Cache '{key}' apagado com sucesso!")
113
+ return deleted
114
+
115
+ except WatchError:
116
+ logger.warning(f"A chave '{key}' foi alterada antes de ser apagada. Tentando novamente...")
117
+
118
+ except Exception as error:
119
+ logger.error(f"Erro ao apagar cache '{key}': {error}")
120
+ raise
121
+
122
+ async def publish(self, channel: str, event: str) -> int:
123
+ logger.info(f"Publicando evento no canal '{channel}'...")
124
+
125
+ try:
126
+ with self.client.pipeline(transaction=True) as session:
127
+ session.multi()
128
+ session.publish(channel, event)
129
+
130
+ result = session.execute()
131
+ listeners = result[0]
132
+
133
+ logger.success(f"Evento publicado no canal '{channel}' com sucesso!")
134
+ return listeners
135
+
136
+ except Exception as error:
137
+ logger.error(f"Erro ao publicar evento no canal '{channel}': {error}")
138
+ raise
139
+
140
+ async def listen(self, channel: str) -> AsyncIterator[Any]:
141
+ logger.info(f"Iniciando escuta do canal '{channel}'...")
142
+
143
+ pubsub = self.client.pubsub()
144
+
145
+ try:
146
+ pubsub.subscribe(channel)
147
+
148
+ logger.success(f"Escutando canal '{channel}'!")
149
+
150
+ while True:
151
+ message = await asyncio.to_thread(
152
+ pubsub.get_message,
153
+ ignore_subscribe_messages=True,
154
+ timeout=1
155
+ )
156
+
157
+ if message is None:
158
+ continue
159
+
160
+ logger.info(f"Evento recebido no canal '{channel}'")
161
+ yield message["data"]
162
+
163
+ except Exception as error:
164
+ logger.error(f"Erro ao escutar canal '{channel}': {error}")
165
+ raise
166
+
167
+ finally:
168
+ try:
169
+ pubsub.unsubscribe(channel)
170
+ pubsub.close()
171
+
172
+ logger.info(f"Escuta do canal '{channel}' encerrada")
173
+
174
+ except Exception as error:
175
+ logger.error(f"Erro ao encerrar Pub/Sub '{channel}': {error}")
@@ -0,0 +1,11 @@
1
+ "junta os modulos de redis"
2
+
3
+
4
+ from .connect import RedisConnect
5
+ from .control import RedisControl
6
+
7
+ class RedisManage(RedisControl):
8
+ def __init__(self, host:str, port:int|str, password = None):
9
+ client = RedisConnect(host=host, port=port, password=password).get_client()
10
+
11
+ super().__init__(client=client)
@@ -0,0 +1,88 @@
1
+ """
2
+ Comandos CLI de autenticação.
3
+ """
4
+
5
+ import argparse
6
+ import json
7
+
8
+ from src.logs.module import Logs
9
+ from src.service.module import Settings, WatchAuth
10
+
11
+
12
+ logger = Logs(loglevel="SUCCESS")
13
+
14
+
15
+ def auth(subparser) -> None:
16
+
17
+ auth_parser = subparser.add_parser("auth")
18
+
19
+ auth_parser.add_argument("--env-file")
20
+
21
+ auth_cmd = auth_parser.add_subparsers(
22
+ dest="command",
23
+ required=True
24
+ )
25
+
26
+ auth_cmd.add_parser("secret")
27
+
28
+ token_parser = auth_cmd.add_parser("token")
29
+ token_parser.add_argument(
30
+ "--type",
31
+ dest="token_type",
32
+ choices=[
33
+ "user_token",
34
+ "refresh_token"
35
+ ],
36
+ required=True
37
+ )
38
+ token_parser.add_argument(
39
+ "--payload",
40
+ default=None
41
+ )
42
+
43
+
44
+ async def run_auth(args) -> None:
45
+
46
+ if args.command == "secret":
47
+ watch_auth = WatchAuth()
48
+ secret = watch_auth.secret()
49
+
50
+ logger.success(
51
+ f"Secret: {logger.highlighted_white(secret)}"
52
+ )
53
+
54
+ elif args.command == "token":
55
+ env = args.env_file
56
+
57
+ settings = (
58
+ Settings(env_file=env)
59
+ if env is not None
60
+ else Settings()
61
+ )
62
+
63
+ settings.add_secret("secret")
64
+ settings.required_secrets("secret")
65
+
66
+ watch_auth = WatchAuth(
67
+ settings=settings
68
+ )
69
+
70
+ payload = (
71
+ json.loads(args.payload)
72
+ if args.payload is not None
73
+ else None
74
+ )
75
+
76
+ if args.token_type == "user_token":
77
+ token = await watch_auth.user_token(
78
+ payload=payload
79
+ )
80
+
81
+ elif args.token_type == "refresh_token":
82
+ token = await watch_auth.refresh_token(
83
+ payload=payload
84
+ )
85
+
86
+ logger.success(
87
+ f"Token: {logger.highlighted_white(token)}"
88
+ )
@@ -0,0 +1,48 @@
1
+ """
2
+ Junta todos os comandos CLI
3
+ """
4
+
5
+ from .migrate import migrate, run_migrate
6
+ from .auth import auth, run_auth
7
+ from .server import server, run_server
8
+
9
+ import argparse
10
+ import asyncio
11
+
12
+
13
+ async def run() -> None:
14
+
15
+ parser = argparse.ArgumentParser()
16
+
17
+ modules = parser.add_subparsers(
18
+ dest="module",
19
+ required=True
20
+ )
21
+
22
+ commands = [
23
+ migrate,
24
+ auth,
25
+ server,
26
+ ]
27
+
28
+ for command in commands:
29
+ command(modules)
30
+
31
+ args = parser.parse_args()
32
+
33
+ if args.module == "migrate":
34
+ await run_migrate(args)
35
+
36
+ elif args.module == "auth":
37
+ await run_auth(args)
38
+
39
+ elif args.module == "server":
40
+ await run_server(args)
41
+
42
+
43
+ def main() -> None:
44
+ asyncio.run(run())
45
+
46
+
47
+ if __name__ == "__main__":
48
+ main()
@@ -0,0 +1,49 @@
1
+ from src.service.module import Settings, WatchDb
2
+ import argparse
3
+
4
+
5
+ def migrate(subparser) -> None:
6
+
7
+ migrate_parser = subparser.add_parser("migrate")
8
+
9
+ migrate_parser.add_argument("--env-file")
10
+
11
+ migrate_cmd = migrate_parser.add_subparsers(
12
+ dest="command",
13
+ required=True
14
+ )
15
+
16
+ migrate_cmd.add_parser("make_tables")
17
+ migrate_cmd.add_parser("reset")
18
+ migrate_cmd.add_parser("drop")
19
+
20
+
21
+ async def run_migrate(args) -> None:
22
+
23
+ env = args.env_file
24
+
25
+ settings = (
26
+ Settings(env_file=env)
27
+ if env is not None
28
+ else Settings()
29
+ )
30
+
31
+ control_db = await WatchDb(
32
+ settings=settings
33
+ )
34
+
35
+ if args.command == "make_tables":
36
+ await control_db.create_tables()
37
+
38
+ elif args.command == "reset":
39
+ await control_db.reset_tables()
40
+
41
+ elif args.command == "drop":
42
+ await control_db.drop_tables()
43
+
44
+
45
+
46
+
47
+
48
+
49
+