Diff -- /var/www/vhosts/3dshawn.com/site1/MODS/Config.pm
Diff
/var/www/vhosts/3dshawn.com/site1/MODS/Config.pm
added on local at 2026-07-10 18:57:30
Added
+110
lines
Removed
-0
lines
Context
0
unchanged
Blobs
from
to 3df94e4ac22a
to 3df94e4ac22a
Unified diff
Naive LCS-based line diff. Additions in emerald, deletions in rose. Both sides decompressed live from BLOB_STORE.| 1 | package MODS::Config; | |
| 2 | #====================================================================== | |
| 3 | # DriftSense -- installation-aware config reader. | |
| 4 | # | |
| 5 | # Reads /etc/drift_sense/drift_sense.conf (or the path in | |
| 6 | # $ENV{DRIFT_SENSE_CONF}) parsed as simple key=value pairs. Values not | |
| 7 | # in the file fall through to a code-default table. | |
| 8 | # | |
| 9 | # Public API: | |
| 10 | # my $cfg = MODS::Config->new; | |
| 11 | # my $v = $cfg->settings('db_host'); # -> string or '' | |
| 12 | # my $all = $cfg->all; # -> hashref of every key | |
| 13 | # | |
| 14 | # Same shape as the portfolio's other MODS::Config modules so callers | |
| 15 | # (DBConnect, Mail, etc.) can use it interchangeably. | |
| 16 | #====================================================================== | |
| 17 | use strict; | |
| 18 | use warnings; | |
| 19 | ||
| 20 | # --- Code defaults (used when the conf file has no matching key) ------ | |
| 21 | my %DEFAULTS = ( | |
| 22 | db_engine => 'mysql', | |
| 23 | db_host => 'localhost', | |
| 24 | db_port => '3306', | |
| 25 | db_name => 'drift_sense', | |
| 26 | db_user => 'drift_sense', | |
| 27 | db_password => '', # never bake a default password | |
| 28 | sqlite_path => '/var/lib/drift_sense/drift_sense.db', | |
| 29 | brand_name => 'DriftSense', | |
| 30 | brand_tagline => 'Silent safety net for code + schema drift', | |
| 31 | public_url => 'http://localhost:8080', | |
| 32 | compression_enabled => '1', | |
| 33 | max_file_size_bytes => '10485760', | |
| 34 | auto_purge_days => '365', | |
| 35 | purge_check_interval_hours => '24', | |
| 36 | agent_ingest_enabled => '0', | |
| 37 | agent_hmac_secret => '', | |
| 38 | agent_max_clock_skew_seconds => '300', | |
| 39 | smtp_host => '', | |
| 40 | smtp_port => '587', | |
| 41 | smtp_user => '', | |
| 42 | smtp_password => '', | |
| 43 | smtp_from => 'drift_sense@localhost', | |
| 44 | docker_awareness_enabled => '0', | |
| 45 | docker_socket_path => '/var/run/docker.sock', | |
| 46 | overlay2_root => '/var/lib/docker/overlay2', | |
| 47 | ||
| 48 | # UI corner-tag (legacy behavior from v1) | |
| 49 | tag_name => 'DriftSense', | |
| 50 | tag_bg_color => '#0f766e', # deep teal | |
| 51 | tag_text_color => '#e5edf5', | |
| 52 | ); | |
| 53 | ||
| 54 | # --- Locate the conf file ------------------------------------------------- | |
| 55 | sub _conf_paths { | |
| 56 | my @paths; | |
| 57 | push @paths, $ENV{DRIFT_SENSE_CONF} if $ENV{DRIFT_SENSE_CONF}; | |
| 58 | push @paths, '/etc/drift_sense/drift_sense.conf'; | |
| 59 | push @paths, '/usr/local/etc/drift_sense/drift_sense.conf'; | |
| 60 | # Dev fallback: next to the CGI (../_config/drift_sense.conf) | |
| 61 | if ($ENV{SCRIPT_FILENAME}) { | |
| 62 | my $sf = $ENV{SCRIPT_FILENAME}; | |
| 63 | $sf =~ s|/[^/]+$||; # strip CGI filename -> docroot | |
| 64 | push @paths, "$sf/_config/drift_sense.conf"; | |
| 65 | } | |
| 66 | return @paths; | |
| 67 | } | |
| 68 | ||
| 69 | my %_CACHE; | |
| 70 | my $_LOADED = 0; | |
| 71 | ||
| 72 | sub _load { | |
| 73 | return if $_LOADED; | |
| 74 | $_LOADED = 1; | |
| 75 | foreach my $p (_conf_paths()) { | |
| 76 | next unless -r $p; | |
| 77 | open(my $fh, '<', $p) or next; | |
| 78 | while (my $line = <$fh>) { | |
| 79 | chomp $line; | |
| 80 | $line =~ s/^\s+|\s+$//g; | |
| 81 | next if $line eq '' || $line =~ /^#/; | |
| 82 | if ($line =~ /^([A-Za-z0-9_]+)\s*=\s*(.*?)\s*$/) { | |
| 83 | my ($k, $v) = ($1, $2); | |
| 84 | $v =~ s/^["']//; $v =~ s/["']$//; # strip optional quotes | |
| 85 | $_CACHE{$k} = $v; | |
| 86 | } | |
| 87 | } | |
| 88 | close $fh; | |
| 89 | last; # first readable conf wins | |
| 90 | } | |
| 91 | } | |
| 92 | ||
| 93 | sub new { return bless({}, shift); } | |
| 94 | ||
| 95 | sub settings { | |
| 96 | my ($self, $key) = @_; | |
| 97 | _load(); | |
| 98 | return $_CACHE{$key} if exists $_CACHE{$key}; | |
| 99 | return $DEFAULTS{$key} if exists $DEFAULTS{$key}; | |
| 100 | return ''; | |
| 101 | } | |
| 102 | ||
| 103 | sub all { | |
| 104 | my $self = shift; | |
| 105 | _load(); | |
| 106 | my %merged = (%DEFAULTS, %_CACHE); | |
| 107 | return \%merged; | |
| 108 | } | |
| 109 | ||
| 110 | 1; |