• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

daycry / jwt / 25548624368

08 May 2026 09:39AM UTC coverage: 90.154% (+11.8%) from 78.328%
25548624368

push

github

daycry
docs: re-tag the upcoming release as v3.0 (v2.0.1 already on Packagist)

The 2.x line is already published on Packagist (latest tag v2.0.1,
2026-03-03) running on lcobucci/jwt ^4 with the legacy mutable API.
What this branch redesigns is therefore the v3 cycle, not v2 — fix
the version labels everywhere so consumers reading the changelog,
the migration guide and the README are not pointed at the wrong
diff.

* Rename docs/migration-v1-to-v2.md → docs/migration-v2-to-v3.md and
  rewrite the prose (heading, "before" snippets, breaking-changes
  table, upgrade checklist).
* CHANGELOG.md: replace the [2.0.0] entry with [3.0.0]; record
  [2.0.1] (2026-03-03) and [2.0.0] as the prior 2.x line; update the
  Unreleased compare URL and the release link list.
* README.md, docs/index.md: point the upgrade hint and the docs
  table at migration-v2-to-v3.md.
* docs/advanced.md, docs/configuration.md, docs/usage.md: change
  references that called the cached-clock bug "v1.x" — it shipped
  with v2.x — and the legacy ValidAt alias likewise.

No source / test changes.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

293 of 325 relevant lines covered (90.15%)

9.72 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

84.78
/src/Commands/JWTGenerateKey.php
1
<?php
2

3
namespace Daycry\JWT\Commands;
4

5
use CodeIgniter\CLI\BaseCommand;
6
use CodeIgniter\CLI\CLI;
7
use Exception;
8

9
class JWTGenerateKey extends BaseCommand
10
{
11
    protected $group       = 'JWT';
12
    protected $name        = 'jwt:key';
13
    protected $description = 'Generate a secure JWT signing key';
14
    protected $usage       = 'jwt:key [length]';
15
    protected $arguments   = [
16
        'length' => 'Key length in bytes (default: 32)',
17
    ];
18
    protected $options = [
19
        '--show'  => 'Display the key instead of updating .env file',
20
        '--force' => 'Force overwrite existing key in .env',
21
    ];
22

23
    public function run(array $params)
24
    {
25
        $length = (int) ($params[0] ?? 32);
10✔
26

27
        // Validate length
28
        if ($length < 16) {
10✔
29
            CLI::error('Key length must be at least 16 bytes for security');
1✔
30

31
            return;
1✔
32
        }
33

34
        if ($length > 128) {
9✔
35
            CLI::error('Key length cannot exceed 128 bytes');
1✔
36

37
            return;
1✔
38
        }
39

40
        try {
41
            // Generate secure random key
42
            $key = base64_encode(random_bytes($length));
8✔
43

44
            if (CLI::getOption('show')) {
8✔
45
                $this->displayKey($key, $length);
3✔
46

47
                return;
3✔
48
            }
49

50
            $this->updateEnvFile($key);
5✔
51
        } catch (Exception $e) {
×
52
            CLI::error('Failed to generate key: ' . $e->getMessage());
×
53
        }
54
    }
55

56
    private function displayKey(string $key, int $length): void
57
    {
58
        CLI::write('Generated JWT Key (' . $length . ' bytes):', 'yellow');
3✔
59
        CLI::write($key, 'green');
3✔
60
        CLI::newLine();
3✔
61
        CLI::write('Add this to your .env file:', 'yellow');
3✔
62
        CLI::write("jwt.signer={$key}", 'cyan');
3✔
63
        CLI::newLine();
3✔
64
        CLI::write('⚠️  Keep this key secure and never commit it to version control!', 'red');
3✔
65
    }
66

67
    /**
68
     * Resolve the .env file path. Override in tests to redirect to a sandbox.
69
     */
70
    protected function envPath(): string
71
    {
72
        return ROOTPATH . '.env';
×
73
    }
74

75
    /**
76
     * Resolve the .env.example file path. Override in tests.
77
     */
78
    protected function envExamplePath(): string
79
    {
80
        return ROOTPATH . '.env.example';
×
81
    }
82

83
    private function updateEnvFile(string $key): void
84
    {
85
        $envPath        = $this->envPath();
5✔
86
        $envExamplePath = $this->envExamplePath();
5✔
87

88
        // Check if .env exists
89
        if (! file_exists($envPath)) {
5✔
90
            CLI::error('.env file not found. Please create one first.');
2✔
91
            CLI::write('You can copy from .env.example if it exists:', 'yellow');
2✔
92
            if (file_exists($envExamplePath)) {
2✔
93
                CLI::write("cp {$envExamplePath} {$envPath}", 'cyan');
1✔
94
            }
95

96
            return;
2✔
97
        }
98

99
        $envContent = file_get_contents($envPath);
3✔
100

101
        // Check if jwt.signer already exists
102
        if (preg_match('/^jwt\.signer\s*=.*$/m', $envContent)) {
3✔
103
            // In testing environment or with --force flag, skip prompt
104
            $isTestingEnv   = (getenv('CI_ENVIRONMENT') === 'testing' || getenv('APP_ENV') === 'testing');
2✔
105
            $forceOverwrite = CLI::getOption('force') || $isTestingEnv;
2✔
106

107
            if (! $forceOverwrite && CLI::prompt('JWT key already exists in .env. Overwrite?', ['y', 'n']) === 'n') {
2✔
108
                CLI::write('Operation cancelled.', 'yellow');
×
109

110
                return;
×
111
            }
112

113
            // Update existing key
114
            $envContent = preg_replace('/^jwt\.signer\s*=.*$/m', "jwt.signer={$key}", $envContent);
2✔
115
        } else {
116
            // Add new key
117
            $envContent .= "\n# JWT Configuration\njwt.signer={$key}\n";
1✔
118
        }
119

120
        if (file_put_contents($envPath, $envContent)) {
3✔
121
            CLI::write('✅ JWT key successfully added to .env file', 'green');
3✔
122
            CLI::write('Generated key: ' . $key, 'cyan');
3✔
123
            CLI::newLine();
3✔
124
            CLI::write('⚠️  Keep your .env file secure and never commit it to version control!', 'red');
3✔
125
        } else {
126
            CLI::error('Failed to write to .env file. Check permissions.');
×
127
        }
128
    }
129
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc