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

marscoin / martianrepublic / 23823524774

31 Mar 2026 11:03PM UTC coverage: 10.419%. Remained the same
23823524774

push

github

Martian Congress
refactor: A1 — split ApiController (1,147 lines) into 5 controllers

The god controller is dead. Long live focused controllers:

- FeedApiController (287 lines) — allPublic, allCitizen, allApplicants,
  allFeed, showCitizen, scitizen
- AuthApiController (260 lines) — marsAuth, checkAuth, wauth, token
- ForumApiController (205 lines) — threads, comments, categories
- ContentApiController (230 lines) — pinpic, pinvideo, pinjson (IPFS)
- UserManagementController (95 lines) — blockUser, deleteUser, eula

ApiController.php is now 18 lines (empty shell with migration notes).
All routes updated to array notation pointing to new controllers.
Zero method logic changed — pure structural refactor.

127 tests, 0 PHPStan errors, API endpoints verified.

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

31 of 637 new or added lines in 5 files covered. (4.87%)

599 of 5749 relevant lines covered (10.42%)

1.47 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
{
NEW
21
    public function marsAuth(Request $request)
×
22
    {
NEW
23
        $this->setCorsHeaders();
×
24

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

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

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

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

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

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

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

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

NEW
65
        return response()->json(['sid' => $session_string, 'authenticated' => $authenticated]);
×
66
    }
67

NEW
68
    public function wauth(Request $request)
×
69
    {
NEW
70
        Log::debug('MarsAuth');
×
NEW
71
        $sid = $request->query('sid');
×
NEW
72
        Log::debug('MarsAuth');
×
73

NEW
74
        if (! empty($sid)) {
×
NEW
75
            $mars_session = MSession::where('sid', $sid)->first(); // Retrieve the session using Eloquent
×
76

NEW
77
            if ($mars_session && ! is_null($mars_session->s) && ! empty($mars_session->s)) {
×
78
                // Attempt to retrieve a user via the public address
NEW
79
                $citizen = Citizen::where('public_address', $mars_session->s)->first();
×
80

NEW
81
                if ($citizen) {
×
82
                    // If a citizen record exists, retrieve the associated user
NEW
83
                    $user = User::find($citizen->userid);
×
84
                } else {
85
                    // Create a new user and citizen if no citizen record exists
NEW
86
                    $user = User::create([
×
NEW
87
                        'email' => $mars_session->s.'@martianrepublic.org',
×
NEW
88
                        'password' => Hash::make(Str::random(16)), // Generate a random password
×
NEW
89
                    ]);
×
90

NEW
91
                    $citizen = new Citizen([
×
NEW
92
                        'userid' => $user->id,
×
NEW
93
                        'firstname' => 'Unknown', // Set default or use input
×
NEW
94
                        'lastname' => 'Uknown',
×
NEW
95
                        'public_address' => $mars_session->s,
×
NEW
96
                    ]);
×
97

NEW
98
                    $citizen->save();
×
99
                }
100

NEW
101
                Auth::login($user); // Authenticate the user
×
NEW
102
                session()->save(); // Ensure the session is saved immediately
×
103

NEW
104
                Log::debug('User authenticated immediately after login: '.(Auth::check() ? 'true' : 'false'));
×
105

NEW
106
                return redirect('/wallet/dashboard');
×
107
            }
108

NEW
109
            return redirect('/login')->withErrors('Could not find User.');
×
110
        } else {
111
            // Handle invalid or expired SID
NEW
112
            return redirect('/login')->withErrors('Your session has expired or is invalid.');
×
113
        }
114
    }
115

NEW
116
    public function token(Request $request)
×
117
    {
NEW
118
        $publicAddress = $request->input('a');
×
NEW
119
        $msg = $request->input('m');
×
NEW
120
        $sig = $request->input('s');
×
NEW
121
        $timestamp = $request->input('t');
×
122

NEW
123
        Log::debug('Address: '.$publicAddress);
×
NEW
124
        Log::debug('msg: '.$msg);
×
NEW
125
        Log::debug('sig: '.$sig);
×
NEW
126
        Log::debug('timestamp: '.$timestamp);
×
127

NEW
128
        if (empty($msg)) {
×
NEW
129
            $data = $request->json()->all();
×
130

NEW
131
            if (isset($data['data'])) {
×
NEW
132
                $msg = $data['data']['m'] ?? null;
×
NEW
133
                $sig = $data['data']['s'] ?? null;
×
NEW
134
                $publicAddress = $data['data']['a'] ?? null;
×
NEW
135
                $timestamp = $data['data']['t'] ?? '0';
×
136
            }
137
        }
138
        // Validate timestamp
NEW
139
        if (Carbon::now()->diffInSeconds(Carbon::createFromTimestamp($timestamp)) > 600) { // 5 minutes tolerance
×
NEW
140
            return response()->json(['error' => 'Request timestamp is too old.'], 401);
×
141
        }
142

NEW
143
        $bitcoinECDSA = new BitcoinECDSA;
×
NEW
144
        $marscoinECDSA = new MarscoinECDSA;
×
NEW
145
        if ($marscoinECDSA->checkSignatureForMessage($publicAddress, $sig, $msg)) {
×
NEW
146
            $wallet = CivicWallet::where('public_addr', $publicAddress)->first();
×
147

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

NEW
199
            $token = $user->createToken('authToken')->plainTextToken;
×
200

NEW
201
            return response()->json(['token' => $token]);
×
202
        } else {
NEW
203
            return response()->json(['message' => 'couldnt verify message'], 406);
×
204
        }
205
    }
206

NEW
207
    public function test()
×
208
    {
209

NEW
210
        $messageM = 'https://martianrepublic.org/api/token?a=MCHe2XTUEegyqsYc5ePe2dQiPtixLfhppR&t=1715354045';
×
NEW
211
        $addressM = 'MCHe2XTUEegyqsYc5ePe2dQiPtixLfhppR';
×
NEW
212
        $signatureM = 'H+Qrav6eWNrB0P5DiRaGRRR/RVtD8qd5dKlWA3FOfeiFc4h04769HtfMbsmxrrNPk0MeTJmwPCR9xg67f1NatOA=';
×
213

NEW
214
        $bitcoinECDSA = new BitcoinECDSA;
×
NEW
215
        $bitcoinECDSA->generateRandomPrivateKey(); // generate new random private key
×
NEW
216
        $address = $bitcoinECDSA->getAddress();
×
NEW
217
        $message = 'Test message';
×
NEW
218
        $signedMessage = $bitcoinECDSA->signMessage($message, true);
×
NEW
219
        echo 'message: '.PHP_EOL.'<br>';
×
NEW
220
        echo $message.PHP_EOL.'<br>';
×
NEW
221
        echo 'signed message: '.PHP_EOL.'<br>';
×
NEW
222
        echo $signedMessage.PHP_EOL.'<br>';
×
223
        // $signedMessage = "random";
224

225
        // loading Bitcoin crypto library
NEW
226
        if ($bitcoinECDSA->checkSignatureForMessage($address, $signedMessage, $message)) {       // verifying signature
×
NEW
227
            Log::debug('True');
×
NEW
228
            echo 'True<br>';
×
229
        } else {
NEW
230
            Log::debug('False');
×
NEW
231
            echo 'False<br>';
×
232
        }
233

NEW
234
        echo 'mars test';
×
NEW
235
        $marscoinECDSA = new MarscoinECDSA;
×
NEW
236
        echo 'Address; '.$addressM;
×
NEW
237
        echo 'Message:'.$messageM;
×
NEW
238
        echo 'sig:'.$signatureM;
×
239
        // loading Bitcoin crypto library
NEW
240
        if ($marscoinECDSA->checkSignatureForMessage($addressM, $signatureM, $messageM)) {       // verifying signature
×
NEW
241
            Log::debug('True');
×
NEW
242
            echo 'True<br>';
×
243
        } else {
NEW
244
            Log::debug('False');
×
NEW
245
            echo 'False<br>';
×
246
        }
247
    }
248

NEW
249
    private function fastcode($status, $message)
×
250
    {
NEW
251
        return response()->json(['status' => $status, 'message' => $message], $status);
×
252
    }
253

NEW
254
    private function setCorsHeaders()
×
255
    {
NEW
256
        header('Access-Control-Allow-Origin: *');
×
NEW
257
        header('Access-Control-Allow-Methods: GET, POST');
×
NEW
258
        header('Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept, Authorization');
×
259
    }
260
}
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