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

marscoin / martianrepublic / 29796968107

21 Jul 2026 02:52AM UTC coverage: 10.965% (-0.03%) from 10.997%
29796968107

push

github

Martian Congress
fix: Drop dynamic DateInterval->w in time_elapsed_string

PHPStan (bumped to larastan 3.10 in the Laravel 12 upgrade) flagged the
$diff->w dynamic property on DateInterval, and its new error-message
format no longer matched the phpstan-baseline entry, failing the Test
Coverage job on both counts. Derive weeks from days in local vars
instead (also removes a PHP 8.2 dynamic-property deprecation) and drop
the now-stale baseline entry. Output unchanged; phpstan clean.

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

0 of 15 new or added lines in 1 file covered. (0.0%)

238 existing lines in 4 files now uncovered.

665 of 6065 relevant lines covered (10.96%)

1.55 hits per line

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

0.0
/app/Http/Controllers/AuthApiController.php
1
<?php
2

3
namespace App\Http\Controllers;
4

5
use App\Includes\MarscoinECDSA;
6
use App\Models\Citizen;
7
use App\Models\CivicWallet;
8
use App\Models\MSession;
9
use App\Models\Profile;
10
use App\Models\User;
11
use BitcoinPHP\BitcoinECDSA\BitcoinECDSA;
12
use Carbon\Carbon;
13
use Illuminate\Http\Request;
14
use Illuminate\Support\Facades\Auth;
15
use Illuminate\Support\Facades\Hash;
16
use Illuminate\Support\Facades\Log;
17
use Illuminate\Support\Str;
18

19
class AuthApiController extends Controller
20
{
21
    public function marsAuth(Request $request)
×
22
    {
23
        $this->setCorsHeaders();
×
24

25
        if (! $request->isMethod('post')) {
×
26
            return $this->fastcode(400, 'bad request');
×
27
        }
28

29
        $challenge = $request->query('c');
×
30
        $session_string = $request->query('sid');
×
31
        $timestamp = hexdec($request->query('t'));
×
32
        $pubk = $request->input('pubk');
×
33
        $msg = $request->input('msg');
×
34
        $sig = $request->input('sig');
×
35
        $address = $request->input('addr');
×
36

37
        if ($timestamp < (time() - 600)) {
×
38
            return $this->fastcode(408, 'request timed out');
×
39
        }
40

41
        $session = MSession::where('sid', $session_string)->first();
×
42

43
        if ($session && in_array($challenge, explode(',', $session->v))) {
×
44
            $marscoinECDSA = new MarscoinECDSA;
×
45
            if ($marscoinECDSA->checkSignatureForMessage($address, $sig, $msg)) {
×
46
                $session->s = $address;
×
47
                $session->save();
×
48

49
                return $this->fastcode(200, 'successfully authenticated');
×
50
            } else {
51
                return $this->fastcode(406, "couldn't verify message");
×
52
            }
53
        } else {
54
            return $this->fastcode(404, 'no challenge found');
×
55
        }
56
    }
57

58
    public function checkAuth(Request $request)
×
59
    {
60
        $session_string = (string) $request->query('sid');
×
61
        $session = MSession::where('sid', $session_string)->first();
×
62

63
        $authenticated = (! is_null($session) && ! empty($session->s)) ? true : false;
×
64

65
        // Attack probes send invalid UTF-8 in ?sid= (e.g. %EF%BF%BD injection
66
        // payloads). Reflecting that back through json_encode throws
67
        // InvalidArgumentException (500). Such a sid never matches a session
68
        // anyway, so blank it rather than echo malformed bytes.
UNCOV
69
        if (! mb_check_encoding($session_string, 'UTF-8')) {
×
70
            $session_string = '';
×
71
        }
72

UNCOV
73
        return response()->json(['sid' => $session_string, 'authenticated' => $authenticated]);
×
74
    }
75

UNCOV
76
    public function wauth(Request $request)
×
77
    {
UNCOV
78
        Log::debug('MarsAuth');
×
79
        $sid = $request->query('sid');
×
UNCOV
80
        Log::debug('MarsAuth');
×
81

UNCOV
82
        if (! empty($sid)) {
×
83
            $mars_session = MSession::where('sid', $sid)->first(); // Retrieve the session using Eloquent
×
84

UNCOV
85
            if ($mars_session && ! is_null($mars_session->s) && ! empty($mars_session->s)) {
×
86
                // Attempt to retrieve a user via the public address
87
                $citizen = Citizen::where('public_address', $mars_session->s)->first();
×
88

89
                if ($citizen) {
×
90
                    // If a citizen record exists, retrieve the associated user
91
                    $user = User::find($citizen->userid);
×
92
                } else {
93
                    // Create a new user and citizen if no citizen record exists
94
                    $user = User::create([
×
95
                        'email' => $mars_session->s.'@martianrepublic.org',
×
96
                        'password' => Hash::make(Str::random(16)), // Generate a random password
×
UNCOV
97
                    ]);
×
98

UNCOV
99
                    $citizen = new Citizen([
×
UNCOV
100
                        'userid' => $user->id,
×
101
                        'firstname' => 'Unknown', // Set default or use input
×
102
                        'lastname' => 'Uknown',
×
UNCOV
103
                        'public_address' => $mars_session->s,
×
104
                    ]);
×
105

106
                    $citizen->save();
×
107
                }
108

109
                Auth::login($user); // Authenticate the user
×
UNCOV
110
                session()->save(); // Ensure the session is saved immediately
×
111

112
                Log::debug('User authenticated immediately after login: '.(Auth::check() ? 'true' : 'false'));
×
113

UNCOV
114
                return redirect('/wallet/dashboard');
×
115
            }
116

UNCOV
117
            return redirect('/login')->withErrors('Could not find User.');
×
118
        } else {
119
            // Handle invalid or expired SID
120
            return redirect('/login')->withErrors('Your session has expired or is invalid.');
×
121
        }
122
    }
123

124
    public function token(Request $request)
×
125
    {
126
        $publicAddress = $request->input('a');
×
UNCOV
127
        $msg = $request->input('m');
×
128
        $sig = $request->input('s');
×
129
        $timestamp = $request->input('t');
×
130

131
        Log::debug('Address: '.$publicAddress);
×
132
        Log::debug('msg: '.$msg);
×
133
        Log::debug('sig: '.$sig);
×
134
        Log::debug('timestamp: '.$timestamp);
×
135

UNCOV
136
        if (empty($msg)) {
×
UNCOV
137
            $data = $request->json()->all();
×
138

139
            if (isset($data['data'])) {
×
140
                $msg = $data['data']['m'] ?? null;
×
UNCOV
141
                $sig = $data['data']['s'] ?? null;
×
UNCOV
142
                $publicAddress = $data['data']['a'] ?? null;
×
143
                $timestamp = $data['data']['t'] ?? '0';
×
144
            }
145
        }
146
        // Validate timestamp
UNCOV
147
        if (Carbon::now()->diffInSeconds(Carbon::createFromTimestamp($timestamp)) > 600) { // 5 minutes tolerance
×
148
            return response()->json(['error' => 'Request timestamp is too old.'], 401);
×
149
        }
150

UNCOV
151
        $bitcoinECDSA = new BitcoinECDSA;
×
UNCOV
152
        $marscoinECDSA = new MarscoinECDSA;
×
153
        if ($marscoinECDSA->checkSignatureForMessage($publicAddress, $sig, $msg)) {
×
154
            $wallet = CivicWallet::where('public_addr', $publicAddress)->first();
×
155

156
            if ($wallet) {
×
157
                // Wallet found, get the associated user
158
                $user = $wallet->user;
×
159
            } else {
160
                // Wallet not found, create a new user without a wallet
UNCOV
161
                $user = User::where('email', $publicAddress.'@martianrepublic.org')->first();
×
162
                if (! $user) {
×
163
                    $user = User::create([
×
164
                        'fullname' => 'UserWithoutWallet', // Or any other default or generated name
×
165
                        'email' => $publicAddress.'@martianrepublic.org',
×
166
                        'password' => Hash::make(Str::random(10)), // Random password
×
167
                    ]);
×
168
                    Log::debug('..created user');
×
169
                }
170
                $profile = Profile::where('userid', $user->id)->first();
×
UNCOV
171
                if (! $profile) {
×
UNCOV
172
                    $profile = Profile::create([
×
173
                        'userid' => $user->id,
×
174
                        'wallet_open' => 0,
×
175
                        'civic_wallet_open' => 0,
×
176
                        'has_application' => 0,
×
177
                    ]);
×
178
                    Log::debug('..created profile');
×
179
                }
180
                // create a citcache entry
181
                $citcache = Citizen::where('userid', $user->id)->first();
×
UNCOV
182
                if (! $citcache) {
×
UNCOV
183
                    $citizen = Citizen::create([
×
184
                        'userid' => $user->id,
×
185
                        'public_address' => $publicAddress,
×
186
                        'created_at' => now(),
×
187
                        'updated_at' => now(),
×
188
                    ]);
×
189
                    Log::debug('..created citizen cache');
×
190
                }
191
                // register civic wallet for the new user
192
                $wallet = CivicWallet::create([
×
193
                    'user_id' => $user->id,
×
UNCOV
194
                    'wallet_type' => 'MARS',
×
195
                    'backup' => 0,
×
196
                    'encrypted_seed' => '',
×
UNCOV
197
                    'public_addr' => $publicAddress,
×
UNCOV
198
                    'created_at' => now(),
×
199
                    'opened_at' => now(),
×
UNCOV
200
                ]);
×
201
                Log::debug('..created civic wallet');
×
202
            }
203
            if ($user->status == 'inactive') {
×
UNCOV
204
                return response()->json(['token' => 'inactive']);
×
205
            }
206

207
            $token = $user->createToken('authToken')->plainTextToken;
×
208

UNCOV
209
            return response()->json(['token' => $token]);
×
210
        } else {
211
            return response()->json(['message' => 'couldnt verify message'], 406);
×
212
        }
213
    }
214

215
    public function test()
×
216
    {
217

218
        $messageM = 'https://martianrepublic.org/api/token?a=MCHe2XTUEegyqsYc5ePe2dQiPtixLfhppR&t=1715354045';
×
219
        $addressM = 'MCHe2XTUEegyqsYc5ePe2dQiPtixLfhppR';
×
220
        $signatureM = 'H+Qrav6eWNrB0P5DiRaGRRR/RVtD8qd5dKlWA3FOfeiFc4h04769HtfMbsmxrrNPk0MeTJmwPCR9xg67f1NatOA=';
×
221

222
        $bitcoinECDSA = new BitcoinECDSA;
×
UNCOV
223
        $bitcoinECDSA->generateRandomPrivateKey(); // generate new random private key
×
UNCOV
224
        $address = $bitcoinECDSA->getAddress();
×
UNCOV
225
        $message = 'Test message';
×
226
        $signedMessage = $bitcoinECDSA->signMessage($message, true);
×
227
        echo 'message: '.PHP_EOL.'<br>';
×
228
        echo $message.PHP_EOL.'<br>';
×
UNCOV
229
        echo 'signed message: '.PHP_EOL.'<br>';
×
230
        echo $signedMessage.PHP_EOL.'<br>';
×
231
        // $signedMessage = "random";
232

233
        // loading Bitcoin crypto library
234
        if ($bitcoinECDSA->checkSignatureForMessage($address, $signedMessage, $message)) {       // verifying signature
×
235
            Log::debug('True');
×
236
            echo 'True<br>';
×
237
        } else {
238
            Log::debug('False');
×
UNCOV
239
            echo 'False<br>';
×
240
        }
241

242
        echo 'mars test';
×
UNCOV
243
        $marscoinECDSA = new MarscoinECDSA;
×
244
        echo 'Address; '.$addressM;
×
245
        echo 'Message:'.$messageM;
×
UNCOV
246
        echo 'sig:'.$signatureM;
×
247
        // loading Bitcoin crypto library
UNCOV
248
        if ($marscoinECDSA->checkSignatureForMessage($addressM, $signatureM, $messageM)) {       // verifying signature
×
249
            Log::debug('True');
×
UNCOV
250
            echo 'True<br>';
×
251
        } else {
UNCOV
252
            Log::debug('False');
×
UNCOV
253
            echo 'False<br>';
×
254
        }
255
    }
256

257
    private function fastcode($status, $message)
×
258
    {
UNCOV
259
        return response()->json(['status' => $status, 'message' => $message], $status);
×
260
    }
261

UNCOV
262
    private function setCorsHeaders()
×
263
    {
UNCOV
264
        header('Access-Control-Allow-Origin: *');
×
UNCOV
265
        header('Access-Control-Allow-Methods: GET, POST');
×
UNCOV
266
        header('Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept, Authorization');
×
267
    }
268
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc