-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feature: added recaptcha to integrate with new service, and keys to use
- Loading branch information
1 parent
0fa8ce7
commit a90d2f8
Showing
15 changed files
with
591 additions
and
33 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
# You can get these keys from https://www.google.com/recaptcha/admin | ||
RECAPTCHA_PUBLIC_KEY=your_public_key | ||
RECAPTCHA_SECRET_KEY=your_secret_key | ||
|
||
# Create your api key from AWS SES / API Gateway: | ||
# - https://aws.amazon.com/ses/; | ||
# - https://aws.amazon.com/api-gateway/ | ||
API_SEND_MAIL=your_api_send_mail |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
{ | ||
// Use IntelliSense to learn about possible attributes. | ||
// Hover to view descriptions of existing attributes. | ||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 | ||
"version": "0.2.0", | ||
"configurations": [ | ||
{ | ||
"name": "site", | ||
"request": "launch", | ||
"type": "dart", | ||
"flutterMode": "debug" | ||
}, | ||
{ | ||
"name": "site (profile mode)", | ||
"request": "launch", | ||
"type": "dart", | ||
"flutterMode": "profile" | ||
}, | ||
{ | ||
"name": "site (release mode)", | ||
"request": "launch", | ||
"type": "dart", | ||
"flutterMode": "release" | ||
} | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,15 @@ | ||
import 'package:site/infra/env/env.dart'; | ||
|
||
class ConstantsAPI { | ||
static const baseUrl = 'https://api.emailjs.com/api/v1.0/email/send'; | ||
static const headers = { | ||
'origin': 'http://localhost', | ||
'Content-Type': 'application/json', | ||
}; | ||
|
||
/// Recaptcha information. | ||
static final recaptchaPublicKey = Env.recaptchaPublicKey; | ||
static final recaptchaSecretKey = Env.recaptchaSecretKey; | ||
static final recaptchaUrl = | ||
Uri.parse('https://www.google.com/recaptcha/api/siteverify'); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
export 'recaptcha_model.dart'; | ||
export 'recaptcha_service.dart'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
import 'dart:convert'; | ||
|
||
import 'package:flutter/foundation.dart'; | ||
|
||
class RecaptchaResponse { | ||
RecaptchaResponse({ | ||
required this.success, | ||
required this.challengeTimeStamp, | ||
required this.hostName, | ||
required this.score, | ||
required this.action, | ||
this.errorCodes = const [], | ||
}); | ||
|
||
factory RecaptchaResponse.fromMap(Map<String, dynamic> json) { | ||
return RecaptchaResponse( | ||
success: json['success'] ?? false, | ||
challengeTimeStamp: DateTime.parse(json['challenge_ts']), | ||
hostName: json['hostname'] ?? '', | ||
score: double.tryParse('${json['score']}') ?? 0.0, | ||
action: json['action'] ?? '', | ||
errorCodes: json['error-codes'] ?? [], | ||
); | ||
} | ||
|
||
factory RecaptchaResponse.fromJson(String source) => | ||
RecaptchaResponse.fromMap(json.decode(source)); | ||
|
||
final bool success; | ||
final DateTime challengeTimeStamp; | ||
final String hostName; | ||
final double score; | ||
final String action; | ||
final List<String> errorCodes; | ||
|
||
RecaptchaResponse copyWith({ | ||
bool? success, | ||
DateTime? challengeTimeStamp, | ||
String? hostName, | ||
double? score, | ||
String? action, | ||
List<String>? errorCodes, | ||
}) { | ||
return RecaptchaResponse( | ||
success: success ?? this.success, | ||
challengeTimeStamp: challengeTimeStamp ?? this.challengeTimeStamp, | ||
hostName: hostName ?? this.hostName, | ||
score: score ?? this.score, | ||
action: action ?? this.action, | ||
errorCodes: errorCodes ?? this.errorCodes, | ||
); | ||
} | ||
|
||
Map<String, dynamic> toMap() { | ||
return { | ||
'success': success, | ||
'challenge_ts': challengeTimeStamp.millisecondsSinceEpoch, | ||
'hostname': hostName, | ||
'score': score, | ||
'action': action, | ||
'error-codes': errorCodes, | ||
}; | ||
} | ||
|
||
String toJson() => json.encode(toMap()); | ||
|
||
@override | ||
String toString() { | ||
return 'RecaptchaResponse(success: $success, challengeTimeStamp: $challengeTimeStamp, hostName: $hostName, score: $score, action: $action, errorCodes: $errorCodes)'; | ||
} | ||
|
||
@override | ||
bool operator ==(Object other) { | ||
if (identical(this, other)) return true; | ||
|
||
return other is RecaptchaResponse && | ||
other.success == success && | ||
other.challengeTimeStamp == challengeTimeStamp && | ||
other.hostName == hostName && | ||
other.score == score && | ||
other.action == action && | ||
listEquals(other.errorCodes, errorCodes); | ||
} | ||
|
||
@override | ||
int get hashCode { | ||
return success.hashCode ^ | ||
challengeTimeStamp.hashCode ^ | ||
hostName.hashCode ^ | ||
score.hashCode ^ | ||
action.hashCode ^ | ||
errorCodes.hashCode; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
import 'dart:developer'; | ||
|
||
import 'package:g_recaptcha_v3/g_recaptcha_v3.dart'; | ||
import 'package:http/http.dart' as http; | ||
import 'package:site/data/constants/constants_api.dart'; | ||
import 'package:site/data/services/recaptcha/recaptcha.dart'; | ||
|
||
class RecaptchaService { | ||
RecaptchaService._(); | ||
|
||
static Future<void> initiate() async => | ||
await GRecaptchaV3.ready(ConstantsAPI.recaptchaPublicKey); | ||
|
||
static Future<bool> isNotABot() async { | ||
final verificationResponse = await _getVerificationResponse(); | ||
|
||
if (verificationResponse == null) { | ||
return false; | ||
} | ||
|
||
final score = verificationResponse.score; | ||
return score >= 0.5 && score < 1; | ||
} | ||
|
||
static Future<RecaptchaResponse?> _getVerificationResponse() async { | ||
try { | ||
final token = await GRecaptchaV3.execute('submit') ?? ''; | ||
|
||
if (token.isNotEmpty) { | ||
final response = await http.post( | ||
ConstantsAPI.recaptchaUrl, | ||
body: { | ||
'secret': ConstantsAPI.recaptchaSecretKey, | ||
'response': token, | ||
}, | ||
headers: { | ||
'Access-Control-Allow-Origin': '*', | ||
}, | ||
); | ||
final body = response.body; | ||
return RecaptchaResponse.fromJson(body); | ||
} else { | ||
log('RecaptchaService._getVerificationResponse, token is empty'); | ||
} | ||
} catch (e, s) { | ||
log( | ||
'RecaptchaService._getVerificationResponse, error: $e, stackTrace: $s', | ||
); | ||
} | ||
|
||
return null; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
import 'package:envied/envied.dart'; | ||
|
||
part 'env.g.dart'; | ||
|
||
// Rename and / or create .env file in the root of the project | ||
// (already has a .env.example file to help) | ||
// - Add the following variables. | ||
// And run the following commands: | ||
// dart run build_runner clean | ||
// dart run build_runner build --delete-conflicting-outputs | ||
|
||
@Envied(path: '.env') | ||
final class Env { | ||
@EnviedField(varName: 'RECAPTCHA_PUBLIC_KEY', obfuscate: true) | ||
static final String recaptchaPublicKey = _Env.recaptchaPublicKey; | ||
|
||
@EnviedField(varName: 'RECAPTCHA_SECRET_KEY', obfuscate: true) | ||
static final String recaptchaSecretKey = _Env.recaptchaSecretKey; | ||
|
||
@EnviedField(varName: 'API_SEND_MAIL', obfuscate: true) | ||
static final String apiSendMail = _Env.apiSendMail; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,17 +1,32 @@ | ||
import 'dart:async'; | ||
import 'dart:developer'; | ||
|
||
import 'package:flutter/foundation.dart'; | ||
import 'package:flutter/material.dart'; | ||
|
||
import 'package:url_strategy/url_strategy.dart'; | ||
|
||
import 'package:site/app/app_widget.dart'; | ||
import 'package:site/app/core/injections/injections.dart'; | ||
import 'package:site/data/services/firebase/firebase.dart'; | ||
import 'package:site/data/services/recaptcha/recaptcha.dart'; | ||
|
||
Future<void> main() async { | ||
WidgetsFlutterBinding.ensureInitialized(); | ||
await FirebaseServiceImpl().setUpInitialization(); | ||
setPathUrlStrategy(); | ||
configureDependencies(); | ||
runApp( | ||
AppWidget(), | ||
); | ||
await runZonedGuarded(() async { | ||
WidgetsFlutterBinding.ensureInitialized(); | ||
await FirebaseServiceImpl().setUpInitialization(); | ||
|
||
if (kIsWeb) { | ||
await RecaptchaService.initiate(); | ||
} | ||
|
||
setPathUrlStrategy(); | ||
configureDependencies(); | ||
runApp( | ||
AppWidget(), | ||
); | ||
}, (error, stackTrace) { | ||
log('runZonedGuarded: Caught error: $error'); | ||
log('runZonedGuarded: StackTrace: $stackTrace'); | ||
}); | ||
} |
Oops, something went wrong.