Class: Mysigner::Config
- Inherits:
-
Object
- Object
- Mysigner::Config
- Defined in:
- lib/mysigner/config.rb
Constant Summary collapse
- CONFIG_DIR =
File.('~/.mysigner').freeze
- CONFIG_FILE =
File.join(CONFIG_DIR, 'config.yml').freeze
- KEY_FILE =
File.join(CONFIG_DIR, '.encryption_key').freeze
- KEYCHAIN_SERVICE =
'com.mysigner.cli'- KEYCHAIN_ACCOUNT =
'config_encryption_key'- ENV_API_TOKEN =
Environment variable names for CI/CD support
'MYSIGNER_API_TOKEN'- ENV_API_URL =
'MYSIGNER_API_URL'- ENV_EMAIL =
'MYSIGNER_EMAIL'- ENV_ORG_ID =
'MYSIGNER_ORG_ID'
Instance Attribute Summary collapse
-
#api_url ⇒ Object
Returns the value of attribute api_url.
-
#current_organization_id ⇒ Object
Returns the value of attribute current_organization_id.
-
#encryption_enabled ⇒ Object
Returns the value of attribute encryption_enabled.
-
#organizations ⇒ Object
readonly
Returns the value of attribute organizations.
-
#user_email ⇒ Object
Returns the value of attribute user_email.
Class Method Summary collapse
-
.env_configured? ⇒ Boolean
Check if all required env vars are set for CI/CD mode.
-
.from_env ⇒ Object
Create a Config from environment variables (for CI/CD).
Instance Method Summary collapse
-
#api_token(org_id = nil) ⇒ Object
Get API token for current organization (or specific org).
-
#clear ⇒ Object
Clear all configuration.
-
#disable_encryption! ⇒ Object
Disable encryption and decrypt all tokens.
-
#display ⇒ Object
Display config (with masked tokens).
-
#enable_encryption! ⇒ Object
Enable encryption and re-encrypt all tokens.
-
#encrypted_config? ⇒ Boolean
Check if config uses encryption.
-
#exists? ⇒ Boolean
Check if config file exists.
-
#from_env? ⇒ Boolean
Whether this config was loaded from environment variables.
-
#has_token_for_org?(org_id) ⇒ Boolean
Check if we have a token for a specific organization.
-
#initialize ⇒ Config
constructor
A new instance of Config.
-
#load ⇒ Object
Load configuration from file.
-
#org_name(org_id = nil) ⇒ Object
Get organization name.
- #organization_id ⇒ Object
-
#organization_ids ⇒ Object
Get all organization IDs.
-
#remove_token_for_org(org_id) ⇒ Object
Remove token for specific organization.
-
#save ⇒ Object
Save configuration to file.
-
#save_token_for_org(org_id, org_name, token) ⇒ Object
Save token for a specific organization.
-
#to_h ⇒ Object
Get config as hash.
-
#valid? ⇒ Boolean
Check if configuration is complete (has required fields).
Constructor Details
#initialize ⇒ Config
Returns a new instance of Config.
30 31 32 33 34 35 36 37 38 |
# File 'lib/mysigner/config.rb', line 30 def initialize @api_url = nil @user_email = nil @current_organization_id = nil @organizations = {} @encryption_enabled = true # Enable by default for security @from_env = false load if exists? end |
Instance Attribute Details
#api_url ⇒ Object
Returns the value of attribute api_url.
27 28 29 |
# File 'lib/mysigner/config.rb', line 27 def api_url @api_url end |
#current_organization_id ⇒ Object
Returns the value of attribute current_organization_id.
27 28 29 |
# File 'lib/mysigner/config.rb', line 27 def current_organization_id @current_organization_id end |
#encryption_enabled ⇒ Object
Returns the value of attribute encryption_enabled.
27 28 29 |
# File 'lib/mysigner/config.rb', line 27 def encryption_enabled @encryption_enabled end |
#organizations ⇒ Object (readonly)
Returns the value of attribute organizations.
28 29 30 |
# File 'lib/mysigner/config.rb', line 28 def organizations @organizations end |
#user_email ⇒ Object
Returns the value of attribute user_email.
27 28 29 |
# File 'lib/mysigner/config.rb', line 27 def user_email @user_email end |
Class Method Details
.env_configured? ⇒ Boolean
Check if all required env vars are set for CI/CD mode
41 42 43 44 |
# File 'lib/mysigner/config.rb', line 41 def self.env_configured? ENV.fetch(ENV_API_TOKEN, nil) && !ENV[ENV_API_TOKEN].empty? && ENV.fetch(ENV_ORG_ID, nil) && !ENV[ENV_ORG_ID].empty? end |
.from_env ⇒ Object
Create a Config from environment variables (for CI/CD)
47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 |
# File 'lib/mysigner/config.rb', line 47 def self.from_env config = allocate config.instance_variable_set(:@encryption_enabled, false) config.instance_variable_set(:@from_env, true) org_id = ENV.fetch(ENV_ORG_ID, nil) token = ENV.fetch(ENV_API_TOKEN, nil) config.instance_variable_set(:@api_url, ENV[ENV_API_URL] || 'https://mysigner.dev') config.instance_variable_set(:@user_email, ENV.fetch(ENV_EMAIL, nil)) config.instance_variable_set(:@current_organization_id, org_id.to_i) config.instance_variable_set(:@organizations, { org_id.to_s => { 'name' => 'CI', 'token' => token } }) config end |
Instance Method Details
#api_token(org_id = nil) ⇒ Object
Get API token for current organization (or specific org)
70 71 72 73 74 75 76 77 78 79 80 |
# File 'lib/mysigner/config.rb', line 70 def api_token(org_id = nil) org_id ||= @current_organization_id return nil if org_id.nil? org_data = @organizations[org_id.to_s] token = org_data&.dig('token') return nil if token.nil? # Decrypt if encrypted encrypted?(token) ? decrypt_token(token) : token end |
#clear ⇒ Object
Clear all configuration
158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 |
# File 'lib/mysigner/config.rb', line 158 def clear @api_url = nil @user_email = nil @current_organization_id = nil @organizations = {} File.delete(CONFIG_FILE) if exists? # On non-macOS the encryption key lives in a file fallback. Wipe it on # logout so a fresh login can mint a new key — otherwise the old key # would silently encrypt a new token that nobody else can decrypt. FileUtils.rm_f(KEY_FILE) # Phase 0: logout also purges the keystore cache so a shared machine # doesn't leave prior-user keystore blobs on disk. keystores_dir = File.('~/.mysigner/keystores') FileUtils.rm_rf(keystores_dir) true rescue StandardError => e raise ConfigError, "Failed to clear config: #{e.}" end |
#disable_encryption! ⇒ Object
Disable encryption and decrypt all tokens
244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 |
# File 'lib/mysigner/config.rb', line 244 def disable_encryption! return true unless @encryption_enabled # Decrypt all tokens first @organizations.each_value do |org_data| token = org_data['token'] next if token.nil? || !encrypted?(token) org_data['token'] = decrypt_token(token) end @encryption_enabled = false save true end |
#display ⇒ Object
Display config (with masked tokens)
203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 |
# File 'lib/mysigner/config.rb', line 203 def display current_org_name = org_name(@current_organization_id) || '(not set)' current_token = api_token(@current_organization_id) display_data = { api_url: @api_url || '(not set)', user_email: @user_email || '(not set)', current_organization: "#{current_org_name} (ID: #{@current_organization_id || 'not set'})", current_token: current_token ? mask_token(current_token) : '(not set)' } # Show all organizations if @organizations.any? display_data[:all_organizations] = @organizations.map do |org_id, org_data| token_status = org_data['token'] ? '✓' : '✗' "#{org_data['name']} (ID: #{org_id}) #{token_status}" end.join(', ') end display_data end |
#enable_encryption! ⇒ Object
Enable encryption and re-encrypt all tokens
226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 |
# File 'lib/mysigner/config.rb', line 226 def enable_encryption! return true if @encryption_enabled @encryption_enabled = true # Re-encrypt all existing tokens @organizations.each_value do |org_data| token = org_data['token'] next if token.nil? || encrypted?(token) org_data['token'] = encrypt_token(token) end save true end |
#encrypted_config? ⇒ Boolean
Check if config uses encryption
261 262 263 |
# File 'lib/mysigner/config.rb', line 261 def encrypted_config? @organizations.values.any? { |org_data| encrypted?(org_data['token']) } end |
#exists? ⇒ Boolean
Check if config file exists
182 183 184 |
# File 'lib/mysigner/config.rb', line 182 def exists? File.exist?(CONFIG_FILE) end |
#from_env? ⇒ Boolean
Whether this config was loaded from environment variables
65 66 67 |
# File 'lib/mysigner/config.rb', line 65 def from_env? @from_env end |
#has_token_for_org?(org_id) ⇒ Boolean
Check if we have a token for a specific organization
92 93 94 95 |
# File 'lib/mysigner/config.rb', line 92 def has_token_for_org?(org_id) token = api_token(org_id) !token.nil? && !token.empty? end |
#load ⇒ Object
Load configuration from file
121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 |
# File 'lib/mysigner/config.rb', line 121 def load return false unless exists? data = YAML.load_file(CONFIG_FILE) @api_url = data['api_url'] @user_email = data['user_email'] @current_organization_id = data['current_organization_id'] @organizations = data['organizations'] || {} # Auto-detect encryption from config @encryption_enabled = encrypted_config? true rescue StandardError => e raise ConfigError, "Failed to load config: #{e.}" end |
#org_name(org_id = nil) ⇒ Object
Get organization name
98 99 100 101 102 103 104 |
# File 'lib/mysigner/config.rb', line 98 def org_name(org_id = nil) org_id ||= @current_organization_id return nil if org_id.nil? org_data = @organizations[org_id.to_s] org_data&.dig('name') end |
#organization_id ⇒ Object
111 112 113 |
# File 'lib/mysigner/config.rb', line 111 def organization_id @current_organization_id end |
#organization_ids ⇒ Object
Get all organization IDs
107 108 109 |
# File 'lib/mysigner/config.rb', line 107 def organization_ids @organizations.keys.map(&:to_i) end |
#remove_token_for_org(org_id) ⇒ Object
Remove token for specific organization
116 117 118 |
# File 'lib/mysigner/config.rb', line 116 def remove_token_for_org(org_id) @organizations.delete(org_id.to_s) end |
#save ⇒ Object
Save configuration to file
140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 |
# File 'lib/mysigner/config.rb', line 140 def save ensure_config_dir_exists data = { 'api_url' => @api_url, 'user_email' => @user_email, 'current_organization_id' => @current_organization_id, 'organizations' => @organizations } File.write(CONFIG_FILE, data.to_yaml) File.chmod(0o600, CONFIG_FILE) # Make file readable only by owner true rescue StandardError => e raise ConfigError, "Failed to save config: #{e.}" end |
#save_token_for_org(org_id, org_name, token) ⇒ Object
Save token for a specific organization
83 84 85 86 87 88 89 |
# File 'lib/mysigner/config.rb', line 83 def save_token_for_org(org_id, org_name, token) encrypted_token = @encryption_enabled ? encrypt_token(token) : token @organizations[org_id.to_s] = { 'name' => org_name, 'token' => encrypted_token } end |
#to_h ⇒ Object
Get config as hash
194 195 196 197 198 199 200 |
# File 'lib/mysigner/config.rb', line 194 def to_h { api_url: @api_url, user_email: @user_email, current_organization_id: @current_organization_id } end |
#valid? ⇒ Boolean
Check if configuration is complete (has required fields)
187 188 189 190 191 |
# File 'lib/mysigner/config.rb', line 187 def valid? !@api_url.nil? && !@api_url.empty? && !@current_organization_id.nil? && has_token_for_org?(@current_organization_id) end |