feat: add GPS tracking with Traccar integration

- Add GPS module with Traccar client service for device management
- Add driver enrollment flow with QR code generation
- Add real-time location tracking on driver profiles
- Add GPS settings configuration in admin tools
- Add Auth0 OpenID Connect setup script for Traccar
- Add deployment configs for production server
- Update nginx configs for SSL on GPS port 5055
- Add timezone setting support
- Various UI improvements and bug fixes

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-02-03 18:13:17 +01:00
parent 3814d175ff
commit 5ded039793
91 changed files with 4403 additions and 68 deletions

View File

@@ -106,7 +106,12 @@ export class SignalService {
/**
* Register a new phone number (requires verification)
*/
async registerNumber(phoneNumber: string, captcha?: string): Promise<{ success: boolean; message: string }> {
async registerNumber(phoneNumber: string, captcha?: string): Promise<{
success: boolean;
message: string;
captchaRequired?: boolean;
captchaUrl?: string;
}> {
try {
const response = await this.client.post(`/v1/register/${phoneNumber}`, {
captcha,
@@ -118,10 +123,27 @@ export class SignalService {
message: 'Verification code sent. Check your phone.',
};
} catch (error: any) {
this.logger.error('Failed to register number:', error.message);
const errorMessage = error.response?.data?.error || error.message;
this.logger.error('Failed to register number:', errorMessage);
// Check if CAPTCHA is required
const isCaptchaRequired =
errorMessage.toLowerCase().includes('captcha') ||
error.response?.status === 402; // Signal uses 402 for captcha requirement
if (isCaptchaRequired) {
return {
success: false,
captchaRequired: true,
captchaUrl: 'https://signalcaptchas.org/registration/generate.html',
message:
'CAPTCHA verification required. Please solve the CAPTCHA and submit the token.',
};
}
return {
success: false,
message: error.response?.data?.error || error.message,
message: errorMessage,
};
}
}
@@ -151,7 +173,8 @@ export class SignalService {
*/
async unlinkAccount(phoneNumber: string): Promise<{ success: boolean; message: string }> {
try {
await this.client.delete(`/v1/accounts/${phoneNumber}`);
// Use POST /v1/unregister/{number} - the correct Signal API endpoint
await this.client.post(`/v1/unregister/${phoneNumber}`);
return {
success: true,