mirror of
https://gitlab.com/famedly/fluffychat.git
synced 2024-11-16 17:09:31 +01:00
feat: Implement registration with email
This commit is contained in:
parent
48bf1169bc
commit
19616f3457
@ -1357,6 +1357,16 @@
|
|||||||
"fileName": {}
|
"fileName": {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"invalidEmail": "Invalid email",
|
||||||
|
"@invalidEmail": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders": {}
|
||||||
|
},
|
||||||
|
"optionalAddEmail": "(Optional) Your email address",
|
||||||
|
"@optionalAddEmail": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders": {}
|
||||||
|
},
|
||||||
"pleaseChooseAUsername": "Please choose a username",
|
"pleaseChooseAUsername": "Please choose a username",
|
||||||
"@pleaseChooseAUsername": {
|
"@pleaseChooseAUsername": {
|
||||||
"type": "text",
|
"type": "text",
|
||||||
|
7
lib/utils/get_client_secret.dart
Normal file
7
lib/utils/get_client_secret.dart
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
import 'dart:math';
|
||||||
|
|
||||||
|
const _chars = 'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz1234567890';
|
||||||
|
Random _rnd = Random();
|
||||||
|
|
||||||
|
String getClientSecret(int length) => String.fromCharCodes(Iterable.generate(
|
||||||
|
length, (_) => _chars.codeUnitAt(_rnd.nextInt(_chars.length))));
|
@ -1,6 +1,9 @@
|
|||||||
|
import 'package:adaptive_dialog/adaptive_dialog.dart';
|
||||||
import 'package:adaptive_page_layout/adaptive_page_layout.dart';
|
import 'package:adaptive_page_layout/adaptive_page_layout.dart';
|
||||||
|
import 'package:email_validator/email_validator.dart';
|
||||||
|
|
||||||
import 'package:famedlysdk/famedlysdk.dart';
|
import 'package:famedlysdk/famedlysdk.dart';
|
||||||
|
import 'package:fluffychat/utils/get_client_secret.dart';
|
||||||
import 'package:fluffychat/views/ui/sign_up_password_ui.dart';
|
import 'package:fluffychat/views/ui/sign_up_password_ui.dart';
|
||||||
|
|
||||||
import 'package:fluffychat/views/widgets/matrix.dart';
|
import 'package:fluffychat/views/widgets/matrix.dart';
|
||||||
@ -19,7 +22,9 @@ class SignUpPassword extends StatefulWidget {
|
|||||||
|
|
||||||
class SignUpPasswordController extends State<SignUpPassword> {
|
class SignUpPasswordController extends State<SignUpPassword> {
|
||||||
final TextEditingController passwordController = TextEditingController();
|
final TextEditingController passwordController = TextEditingController();
|
||||||
|
final TextEditingController emailController = TextEditingController();
|
||||||
String passwordError;
|
String passwordError;
|
||||||
|
String emailError;
|
||||||
bool loading = false;
|
bool loading = false;
|
||||||
bool showPassword = true;
|
bool showPassword = true;
|
||||||
|
|
||||||
@ -30,7 +35,7 @@ class SignUpPasswordController extends State<SignUpPassword> {
|
|||||||
if (passwordController.text.isEmpty) {
|
if (passwordController.text.isEmpty) {
|
||||||
setState(() => passwordError = L10n.of(context).pleaseEnterYourPassword);
|
setState(() => passwordError = L10n.of(context).pleaseEnterYourPassword);
|
||||||
} else {
|
} else {
|
||||||
setState(() => passwordError = null);
|
setState(() => passwordError = emailError = null);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (passwordController.text.isEmpty) {
|
if (passwordController.text.isEmpty) {
|
||||||
@ -39,6 +44,31 @@ class SignUpPasswordController extends State<SignUpPassword> {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
setState(() => loading = true);
|
setState(() => loading = true);
|
||||||
|
if (emailController.text.isNotEmpty) {
|
||||||
|
emailController.text = emailController.text.trim();
|
||||||
|
if (!EmailValidator.validate(emailController.text)) {
|
||||||
|
setState(() => emailError = L10n.of(context).invalidEmail);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
matrix.currentClientSecret = getClientSecret(30);
|
||||||
|
Logs().d('Request email token');
|
||||||
|
matrix.currentThreepidCreds = await matrix.client.requestEmailToken(
|
||||||
|
emailController.text,
|
||||||
|
matrix.currentClientSecret,
|
||||||
|
1,
|
||||||
|
);
|
||||||
|
if (OkCancelResult.ok !=
|
||||||
|
await showOkCancelAlertDialog(
|
||||||
|
context: context,
|
||||||
|
message: L10n.of(context).weSentYouAnEmail,
|
||||||
|
okLabel: L10n.of(context).confirm,
|
||||||
|
cancelLabel: L10n.of(context).cancel,
|
||||||
|
)) {
|
||||||
|
matrix.currentClientSecret = matrix.currentThreepidCreds = null;
|
||||||
|
setState(() => loading = false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
final waitForLogin = matrix.client.onLoginStateChanged.stream.first;
|
final waitForLogin = matrix.client.onLoginStateChanged.stream.first;
|
||||||
await matrix.client.uiaRequestBackground((auth) => matrix.client.register(
|
await matrix.client.uiaRequestBackground((auth) => matrix.client.register(
|
||||||
username: widget.username,
|
username: widget.username,
|
||||||
@ -46,13 +76,22 @@ class SignUpPasswordController extends State<SignUpPassword> {
|
|||||||
initialDeviceDisplayName: PlatformInfos.clientName,
|
initialDeviceDisplayName: PlatformInfos.clientName,
|
||||||
auth: auth,
|
auth: auth,
|
||||||
));
|
));
|
||||||
|
if (matrix.currentClientSecret != null &&
|
||||||
|
matrix.currentThreepidCreds != null) {
|
||||||
|
Logs().d('Add third party identifier');
|
||||||
|
await matrix.client.addThirdPartyIdentifier(
|
||||||
|
matrix.currentClientSecret,
|
||||||
|
matrix.currentThreepidCreds.sid,
|
||||||
|
);
|
||||||
|
}
|
||||||
await waitForLogin;
|
await waitForLogin;
|
||||||
} catch (exception) {
|
} catch (exception) {
|
||||||
setState(() => passwordError = exception.toString());
|
setState(() => emailError = exception.toString());
|
||||||
return setState(() => loading = false);
|
return setState(() => loading = false);
|
||||||
}
|
}
|
||||||
await matrix.client.onLoginStateChanged.stream
|
await matrix.client.onLoginStateChanged.stream
|
||||||
.firstWhere((l) => l == LoginState.logged);
|
.firstWhere((l) => l == LoginState.logged);
|
||||||
|
// tchncs.de
|
||||||
try {
|
try {
|
||||||
await matrix.client
|
await matrix.client
|
||||||
.setDisplayname(matrix.client.userID, widget.displayname);
|
.setDisplayname(matrix.client.userID, widget.displayname);
|
||||||
|
@ -47,6 +47,21 @@ class SignUpPasswordUI extends StatelessWidget {
|
|||||||
labelText: L10n.of(context).password),
|
labelText: L10n.of(context).password),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.all(12.0),
|
||||||
|
child: TextField(
|
||||||
|
controller: controller.emailController,
|
||||||
|
readOnly: controller.loading,
|
||||||
|
autocorrect: false,
|
||||||
|
keyboardType: TextInputType.emailAddress,
|
||||||
|
onSubmitted: (_) => controller.signUpAction,
|
||||||
|
decoration: InputDecoration(
|
||||||
|
prefixIcon: Icon(Icons.mail_outline_outlined),
|
||||||
|
errorText: controller.emailError,
|
||||||
|
hintText: 'email@example.com',
|
||||||
|
labelText: L10n.of(context).optionalAddEmail),
|
||||||
|
),
|
||||||
|
),
|
||||||
SizedBox(height: 12),
|
SizedBox(height: 12),
|
||||||
Hero(
|
Hero(
|
||||||
tag: 'loginButton',
|
tag: 'loginButton',
|
||||||
|
@ -121,7 +121,11 @@ class MatrixState extends State<Matrix> with WidgetsBindingObserver {
|
|||||||
|
|
||||||
set cachedPassword(String p) => _cachedPassword = p;
|
set cachedPassword(String p) => _cachedPassword = p;
|
||||||
|
|
||||||
|
String currentClientSecret;
|
||||||
|
RequestTokenResponse currentThreepidCreds;
|
||||||
|
|
||||||
void _onUiaRequest(UiaRequest uiaRequest) async {
|
void _onUiaRequest(UiaRequest uiaRequest) async {
|
||||||
|
try {
|
||||||
if (uiaRequest.state != UiaRequestState.waitForUser ||
|
if (uiaRequest.state != UiaRequestState.waitForUser ||
|
||||||
uiaRequest.nextStages.isEmpty) return;
|
uiaRequest.nextStages.isEmpty) return;
|
||||||
final stage = uiaRequest.nextStages.first;
|
final stage = uiaRequest.nextStages.first;
|
||||||
@ -153,6 +157,30 @@ class MatrixState extends State<Matrix> with WidgetsBindingObserver {
|
|||||||
identifier: AuthenticationUserIdentifier(user: client.userID),
|
identifier: AuthenticationUserIdentifier(user: client.userID),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
case AuthenticationTypes.emailIdentity:
|
||||||
|
if (currentClientSecret == null || currentThreepidCreds == null) {
|
||||||
|
return uiaRequest
|
||||||
|
.cancel(Exception('This server requires an email address'));
|
||||||
|
}
|
||||||
|
final auth = AuthenticationThreePidCreds(
|
||||||
|
session: uiaRequest.session,
|
||||||
|
type: AuthenticationTypes.emailIdentity,
|
||||||
|
threepidCreds: [
|
||||||
|
ThreepidCreds(
|
||||||
|
sid: currentThreepidCreds.sid,
|
||||||
|
clientSecret: currentClientSecret,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
currentThreepidCreds = currentClientSecret = null;
|
||||||
|
return uiaRequest.completeStage(auth);
|
||||||
|
case AuthenticationTypes.dummy:
|
||||||
|
return uiaRequest.completeStage(
|
||||||
|
AuthenticationData(
|
||||||
|
type: AuthenticationTypes.dummy,
|
||||||
|
session: uiaRequest.session,
|
||||||
|
),
|
||||||
|
);
|
||||||
default:
|
default:
|
||||||
await launch(
|
await launch(
|
||||||
client.homeserver.toString() +
|
client.homeserver.toString() +
|
||||||
@ -173,6 +201,10 @@ class MatrixState extends State<Matrix> with WidgetsBindingObserver {
|
|||||||
return uiaRequest.cancel();
|
return uiaRequest.cancel();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} catch (e, s) {
|
||||||
|
Logs().e('Error while background UIA', e, s);
|
||||||
|
return uiaRequest.cancel(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool webHasFocus = true;
|
bool webHasFocus = true;
|
||||||
@ -422,3 +454,27 @@ class MatrixState extends State<Matrix> with WidgetsBindingObserver {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class FixedThreepidCreds extends ThreepidCreds {
|
||||||
|
FixedThreepidCreds({
|
||||||
|
String sid,
|
||||||
|
String clientSecret,
|
||||||
|
String idServer,
|
||||||
|
String idAccessToken,
|
||||||
|
}) : super(
|
||||||
|
sid: sid,
|
||||||
|
clientSecret: clientSecret,
|
||||||
|
idServer: idServer,
|
||||||
|
idAccessToken: idAccessToken,
|
||||||
|
);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
final data = <String, dynamic>{};
|
||||||
|
data['sid'] = sid;
|
||||||
|
data['client_secret'] = clientSecret;
|
||||||
|
if (idServer != null) data['id_server'] = idServer;
|
||||||
|
if (idAccessToken != null) data['id_access_token'] = idAccessToken;
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user