@@ -41,6 +41,7 @@ def __call__(self,
41
41
raise argparse .ArgumentError (self , f'invalid filter argument "{ value } ", expected "key=value"' )
42
42
setattr (namespace , self .dest , {key : val })
43
43
44
+
44
45
@dataclass
45
46
class Filters :
46
47
"""Dataclass representing a set of filters."""
@@ -68,10 +69,13 @@ class Command(BaseCommand):
68
69
parser = get_custom_argparse_formatter (prog = 'audit' , description = 'Google Workspace Audit' )
69
70
parser .add_argument ('application' , help = 'Application name' )
70
71
parser .add_argument ('duration' , help = 'Duration in format Xs, Xm, Xh or Xd.' )
71
- parser .add_argument ('--columns' , nargs = '+' , help = 'Columns to keep in the output. If not set, will take columns from config.' )
72
+ parser .add_argument ('--columns' , nargs = '+' ,
73
+ help = 'Columns to keep in the output. If not set, will take columns from config.' )
72
74
parser .add_argument ('--export' , action = 'store_true' , default = False , help = 'Path to export the data' )
73
- parser .add_argument ('--export-format' , choices = ['csv' , 'ndjson' ], default = 'csv' , help = 'Export format. Default is csv.' )
74
- parser .add_argument ('--filters' , nargs = '*' , action = KeyValueAction , dest = 'filters' , default = {}, help = 'Filters to apply on the data' )
75
+ parser .add_argument ('--export-format' , choices = ['csv' , 'ndjson' ], default = 'csv' ,
76
+ help = 'Export format. Default is csv.' )
77
+ parser .add_argument ('--filters' , nargs = '*' , action = KeyValueAction , dest = 'filters' , default = {},
78
+ help = 'Filters to apply on the data' )
75
79
parser .add_argument ('--interactive' , action = 'store_true' , help = 'Interactive mode' )
76
80
77
81
def __init__ (self , ** kwargs ) -> None :
@@ -89,7 +93,7 @@ def __init__(self, **kwargs) -> None:
89
93
90
94
# Check if the session exists in the credential store
91
95
if self .obj .cred_store .store .get ('default' ) is None :
92
- self .logger .error (f'Please authenticate with "auth session -- default --creds " before running this command.' )
96
+ self .logger .error (f'Please add "default" creds with "creds add default ... " before running this command.' )
93
97
return
94
98
95
99
try :
@@ -99,7 +103,8 @@ def __init__(self, **kwargs) -> None:
99
103
return
100
104
101
105
try :
102
- self .service = build ('admin' , 'reports_v1' , credentials = self .obj .cred_store .store ['default' ].session )
106
+ creds = self .obj .cred_store .get ('default' , validate_type = 'oauth' )
107
+ self .service = build ('admin' , 'reports_v1' , credentials = creds .session ())
103
108
except HttpError as err :
104
109
self .logger .error (f'An error occurred: { err } ' )
105
110
return
@@ -114,7 +119,6 @@ def __init__(self, **kwargs) -> None:
114
119
self .args .filters = [f .strip ('\' "' ) for f in self .args .filters ]
115
120
self .filters = Filters (self .args .filters )
116
121
117
-
118
122
def export_data (self , df : pd .DataFrame ) -> None :
119
123
"""
120
124
Exports the dataframe to a specified format.
@@ -135,7 +139,6 @@ def export_data(self, df: pd.DataFrame) -> None:
135
139
else :
136
140
self .logger .warning (f'Unsupported export format: { self .args .export_format } . No data was exported.' )
137
141
138
-
139
142
def flatten_json (self , y : dict ) -> dict :
140
143
"""
141
144
Flattens a nested dictionary and returns a new dictionary with
@@ -187,7 +190,6 @@ def flatten_activities(self, activities: list) -> pd.DataFrame:
187
190
flattened_data .append (merged_data )
188
191
return pd .DataFrame (flattened_data )
189
192
190
-
191
193
def fetch_data (self ) -> pd .DataFrame :
192
194
"""
193
195
Fetches the activity data from the Google Workspace Audit service, using the provided start time,
@@ -227,9 +229,14 @@ def filter_columns(self, df: pd.DataFrame) -> pd.DataFrame:
227
229
Returns:
228
230
pd.DataFrame: The filtered dataframe.
229
231
"""
230
- columns = self .args .columns or self .obj .config ['google' ]['audit' ]['columns' ]
232
+ columns = self .args .columns or self .obj .config . merged ['google' ]['audit' ]['columns' ]
231
233
modified_columns = ['.*' + column + '.*' for column in columns ]
232
- df = df [[column for column in df .columns for pattern in modified_columns if re .search (pattern , column , re .IGNORECASE )]]
234
+ df = df [
235
+ [
236
+ column for column in df .columns for pattern in modified_columns
237
+ if re .search (pattern , column , re .IGNORECASE )
238
+ ]
239
+ ]
233
240
return df
234
241
235
242
def interactive_session (self , df : pd .DataFrame , df_unfiltered : pd .DataFrame ) -> None :
@@ -244,7 +251,8 @@ def interactive_session(self, df: pd.DataFrame, df_unfiltered: pd.DataFrame) ->
244
251
None
245
252
"""
246
253
# Ask the user which columns to display
247
- selected_columns_input = input ('Enter the columns to display, separated by commas (see logged available columns): ' )
254
+ selected_columns_input = input ('Enter the columns to display, separated by commas '
255
+ '(see logged available columns): ' )
248
256
selected_columns = [column .strip () for column in selected_columns_input .split (',' )]
249
257
250
258
# Keep only the selected columns
@@ -267,7 +275,8 @@ def interactive_session(self, df: pd.DataFrame, df_unfiltered: pd.DataFrame) ->
267
275
except ValueError :
268
276
self .logger .warning (f'Invalid row number: { row_number } ' )
269
277
270
- def show_results (self , df : pd .DataFrame ) -> None :
278
+ @staticmethod
279
+ def show_results (df : pd .DataFrame ) -> None :
271
280
"""
272
281
Prints the DataFrame to the console in a markdown table format.
273
282
@@ -279,7 +288,6 @@ def show_results(self, df: pd.DataFrame) -> None:
279
288
"""
280
289
print (Fore .GREEN + df .to_markdown (headers = 'keys' , tablefmt = 'fancy_grid' ) + Fore .RESET )
281
290
282
-
283
291
def execute (self ) -> None :
284
292
"""
285
293
Main execution method of the Command class.
0 commit comments