19
19
Any charm using this library should import the `psycopg2` or `psycopg2-binary` dependency.
20
20
"""
21
21
import logging
22
- from typing import Set
22
+ from typing import List , Set
23
23
24
24
import psycopg2
25
25
from psycopg2 import sql
32
32
33
33
# Increment this PATCH version before using `charmcraft publish-lib` or reset
34
34
# to 0 if you are raising the major API version
35
- LIBPATCH = 9
35
+ LIBPATCH = 10
36
36
37
37
38
38
logger = logging .getLogger (__name__ )
@@ -46,6 +46,10 @@ class PostgreSQLCreateUserError(Exception):
46
46
"""Exception raised when creating a user fails."""
47
47
48
48
49
+ class PostgreSQLDatabasesSetupError (Exception ):
50
+ """Exception raised when the databases setup fails."""
51
+
52
+
49
53
class PostgreSQLDeleteUserError (Exception ):
50
54
"""Exception raised when deleting a user fails."""
51
55
@@ -76,12 +80,14 @@ def __init__(
76
80
user : str ,
77
81
password : str ,
78
82
database : str ,
83
+ system_users : List [str ] = [],
79
84
):
80
85
self .primary_host = primary_host
81
86
self .current_host = current_host
82
87
self .user = user
83
88
self .password = password
84
89
self .database = database
90
+ self .system_users = system_users
85
91
86
92
def _connect_to_database (
87
93
self , database : str = None , connect_to_current_host : bool = False
@@ -119,10 +125,16 @@ def create_database(self, database: str, user: str) -> None:
119
125
if cursor .fetchone () is None :
120
126
cursor .execute (sql .SQL ("CREATE DATABASE {};" ).format (sql .Identifier (database )))
121
127
cursor .execute (
122
- sql .SQL ("GRANT ALL PRIVILEGES ON DATABASE {} TO {} ;" ).format (
123
- sql .Identifier (database ), sql . Identifier ( user )
128
+ sql .SQL ("REVOKE ALL PRIVILEGES ON DATABASE {} FROM PUBLIC ;" ).format (
129
+ sql .Identifier (database )
124
130
)
125
131
)
132
+ for user_to_grant_access in [user ] + self .system_users :
133
+ cursor .execute (
134
+ sql .SQL ("GRANT ALL PRIVILEGES ON DATABASE {} TO {};" ).format (
135
+ sql .Identifier (database ), sql .Identifier (user_to_grant_access )
136
+ )
137
+ )
126
138
with self ._connect_to_database (database = database ) as conn :
127
139
with conn .cursor () as curs :
128
140
statements = []
@@ -331,6 +343,26 @@ def list_users(self) -> Set[str]:
331
343
logger .error (f"Failed to list PostgreSQL database users: { e } " )
332
344
raise PostgreSQLListUsersError ()
333
345
346
+ def set_up_database (self ) -> None :
347
+ """Set up postgres database with the right permissions."""
348
+ connection = None
349
+ try :
350
+ with self ._connect_to_database () as connection , connection .cursor () as cursor :
351
+ # Allow access to the postgres database only to the system users.
352
+ cursor .execute ("REVOKE ALL PRIVILEGES ON DATABASE postgres FROM PUBLIC;" )
353
+ for user in self .system_users :
354
+ cursor .execute (
355
+ sql .SQL ("GRANT ALL PRIVILEGES ON DATABASE postgres TO {};" ).format (
356
+ sql .Identifier (user )
357
+ )
358
+ )
359
+ except psycopg2 .Error as e :
360
+ logger .error (f"Failed to set up databases: { e } " )
361
+ raise PostgreSQLDatabasesSetupError ()
362
+ finally :
363
+ if connection is not None :
364
+ connection .close ()
365
+
334
366
def update_user_password (self , username : str , password : str ) -> None :
335
367
"""Update a user password.
336
368
0 commit comments