Add an API to reset the password
This commit is contained in:
parent
20b2f7df0a
commit
469381f595
1
.env
Normal file
1
.env
Normal file
@ -0,0 +1 @@
|
|||||||
|
SOFTPLAYER_BACKEND_URL=https://softplayer-backend.badhouseplants.net:8080
|
@ -1,7 +1,4 @@
|
|||||||
# Environemnt to install flutter and build web
|
|
||||||
FROM debian:latest AS build-env
|
FROM debian:latest AS build-env
|
||||||
|
|
||||||
# install all needed stuff
|
|
||||||
RUN apt-get update
|
RUN apt-get update
|
||||||
RUN apt-get install -y curl tar xz-utils git
|
RUN apt-get install -y curl tar xz-utils git
|
||||||
|
|
||||||
@ -13,12 +10,11 @@ ARG APP=/app/
|
|||||||
|
|
||||||
RUN curl -l -o /tmp/flutter.tar.xz https://storage.googleapis.com/flutter_infra_release/releases/stable/linux/flutter_linux_${FLUTTER_VERSION}-stable.tar.xz
|
RUN curl -l -o /tmp/flutter.tar.xz https://storage.googleapis.com/flutter_infra_release/releases/stable/linux/flutter_linux_${FLUTTER_VERSION}-stable.tar.xz
|
||||||
RUN tar -xf /tmp/flutter.tar.xz -C /usr/local
|
RUN tar -xf /tmp/flutter.tar.xz -C /usr/local
|
||||||
|
|
||||||
ENV PATH="$FLUTTER_SDK/bin:$FLUTTER_SDK/bin/cache/dart-sdk/bin:${PATH}"
|
ENV PATH="$FLUTTER_SDK/bin:$FLUTTER_SDK/bin/cache/dart-sdk/bin:${PATH}"
|
||||||
|
|
||||||
RUN mkdir $APP
|
|
||||||
COPY . $APP
|
|
||||||
WORKDIR $APP
|
WORKDIR $APP
|
||||||
|
COPY . $APP
|
||||||
|
|
||||||
RUN flutter build web --release
|
RUN flutter build web --release
|
||||||
|
|
||||||
# once heare the app will be compiled and ready to deploy
|
# once heare the app will be compiled and ready to deploy
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import 'package:grpc/grpc_web.dart';
|
import 'package:grpc/grpc_web.dart';
|
||||||
import 'package:softplayer_dart_proto/accounts/accounts_v1.pbgrpc.dart';
|
|
||||||
import 'package:softplayer_dart_proto/main.dart';
|
import 'package:softplayer_dart_proto/main.dart';
|
||||||
|
|
||||||
class AccountLocalData {
|
class AccountLocalData {
|
||||||
@ -57,4 +56,33 @@ class AccountsGrpc {
|
|||||||
rethrow;
|
rethrow;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<Empty> resetPassword(String username, String email) async {
|
||||||
|
final request = AccountData(
|
||||||
|
name: username,
|
||||||
|
email: email,
|
||||||
|
);
|
||||||
|
try {
|
||||||
|
final response = await accountsStub.resetPassword(request);
|
||||||
|
return response;
|
||||||
|
} catch (e) {
|
||||||
|
rethrow;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<Empty> newPassword(
|
||||||
|
String username, String code, String newPassword) async {
|
||||||
|
final request = AccountWithPasswordAndCode(
|
||||||
|
data: AccountData(
|
||||||
|
name: username,
|
||||||
|
),
|
||||||
|
code: code,
|
||||||
|
password: AccountPassword(password: newPassword));
|
||||||
|
try {
|
||||||
|
final response = await accountsStub.newPassword(request);
|
||||||
|
return response;
|
||||||
|
} catch (e) {
|
||||||
|
rethrow;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -53,8 +53,8 @@ class _EnvirnomentCardState extends State<EnvirnomentCard> {
|
|||||||
position: RelativeRect.fromSize(Rect.largest, Size.infinite),
|
position: RelativeRect.fromSize(Rect.largest, Size.infinite),
|
||||||
context: context,
|
context: context,
|
||||||
items: [
|
items: [
|
||||||
PopupMenuItem(child: Text("test")),
|
const PopupMenuItem(child: Text("test")),
|
||||||
PopupMenuItem(child: Text("text")),
|
const PopupMenuItem(child: Text("text")),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
onTap: () => showDialog(
|
onTap: () => showDialog(
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/widgets.dart';
|
|
||||||
import 'package:softplayer_web/api/grpc/environments.dart';
|
import 'package:softplayer_web/api/grpc/environments.dart';
|
||||||
import 'package:softplayer_web/helpers/providers/common.dart';
|
import 'package:softplayer_web/helpers/providers/common.dart';
|
||||||
|
|
||||||
@ -61,7 +60,7 @@ class _EnvirnomentPreviewState extends State<EnvirnomentPreiview> {
|
|||||||
]),
|
]),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
Divider(),
|
const Divider(),
|
||||||
Table(
|
Table(
|
||||||
border: const TableBorder(
|
border: const TableBorder(
|
||||||
bottom: BorderSide.none,
|
bottom: BorderSide.none,
|
||||||
@ -69,13 +68,13 @@ class _EnvirnomentPreviewState extends State<EnvirnomentPreiview> {
|
|||||||
right: BorderSide.none,
|
right: BorderSide.none,
|
||||||
top: BorderSide.none,
|
top: BorderSide.none,
|
||||||
),
|
),
|
||||||
children: [
|
children: const [
|
||||||
TableRow(children: [
|
TableRow(children: [
|
||||||
const Text("Price per hour"),
|
Text("Price per hour"),
|
||||||
Text("0.52"),
|
Text("0.52"),
|
||||||
]),
|
]),
|
||||||
TableRow(children: [
|
TableRow(children: [
|
||||||
const Text("Current usage"),
|
Text("Current usage"),
|
||||||
Text("10.5"),
|
Text("10.5"),
|
||||||
]),
|
]),
|
||||||
],
|
],
|
||||||
@ -84,8 +83,8 @@ class _EnvirnomentPreviewState extends State<EnvirnomentPreiview> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
actions: [
|
actions: [
|
||||||
TextButton(onPressed: () => print("lala"), child: Text("test")),
|
TextButton(onPressed: () => print("lala"), child: const Text("test")),
|
||||||
TextButton(onPressed: () => print("lala"), child: Text("test")),
|
TextButton(onPressed: () => print("lala"), child: const Text("test")),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,7 @@ class LoginForm extends StatefulWidget {
|
|||||||
State<StatefulWidget> createState() => _LoginFormState();
|
State<StatefulWidget> createState() => _LoginFormState();
|
||||||
}
|
}
|
||||||
|
|
||||||
enum Action { singIn, signUp }
|
enum Action { singIn, signUp, resetPassword }
|
||||||
|
|
||||||
class _LoginFormState extends State<LoginForm> {
|
class _LoginFormState extends State<LoginForm> {
|
||||||
final _formKey = GlobalKey<FormState>();
|
final _formKey = GlobalKey<FormState>();
|
||||||
@ -25,9 +25,11 @@ class _LoginFormState extends State<LoginForm> {
|
|||||||
final passwordCtrl = TextEditingController();
|
final passwordCtrl = TextEditingController();
|
||||||
final passwordVerifyCtrl = TextEditingController();
|
final passwordVerifyCtrl = TextEditingController();
|
||||||
final emailCtrl = TextEditingController();
|
final emailCtrl = TextEditingController();
|
||||||
|
final codeCtrl = TextEditingController();
|
||||||
|
|
||||||
late AccountsGrpc accountsGrpc;
|
late AccountsGrpc accountsGrpc;
|
||||||
Action action = Action.singIn;
|
Action action = Action.singIn;
|
||||||
|
bool codeEnabled = false;
|
||||||
static const dialogName = "Login";
|
static const dialogName = "Login";
|
||||||
|
|
||||||
void submitSignUp() {
|
void submitSignUp() {
|
||||||
@ -71,7 +73,6 @@ class _LoginFormState extends State<LoginForm> {
|
|||||||
widget.notifyParent();
|
widget.notifyParent();
|
||||||
// Navigator.of(context, rootNavigator: true).pop();
|
// Navigator.of(context, rootNavigator: true).pop();
|
||||||
}).catchError((e) {
|
}).catchError((e) {
|
||||||
print(e);
|
|
||||||
GrpcError error = e;
|
GrpcError error = e;
|
||||||
String msg;
|
String msg;
|
||||||
if (error.message != null) {
|
if (error.message != null) {
|
||||||
@ -90,6 +91,61 @@ class _LoginFormState extends State<LoginForm> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void subminResetPassword() {
|
||||||
|
// Validate returns true if the form is valid, or false otherwise.
|
||||||
|
if (_formKey.currentState!.validate()) {
|
||||||
|
final username = usernameCtrl.text;
|
||||||
|
final password = passwordCtrl.text;
|
||||||
|
final code = codeCtrl.text;
|
||||||
|
accountsGrpc.newPassword(username, code, password).then((rs) {
|
||||||
|
action = Action.singIn;
|
||||||
|
// Navigator.of(context, rootNavigator: true).pop();
|
||||||
|
}).catchError((e) {
|
||||||
|
GrpcError error = e;
|
||||||
|
String msg;
|
||||||
|
if (error.message != null) {
|
||||||
|
msg = error.message!;
|
||||||
|
} else {
|
||||||
|
msg = error.toString();
|
||||||
|
}
|
||||||
|
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
|
||||||
|
content: Text(msg),
|
||||||
|
backgroundColor: Colors.red,
|
||||||
|
showCloseIcon: true,
|
||||||
|
behavior: SnackBarBehavior.floating,
|
||||||
|
));
|
||||||
|
passwordCtrl.clear();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void sendCode() {
|
||||||
|
if (_formKey.currentState!.validate()) {
|
||||||
|
final username = usernameCtrl.text;
|
||||||
|
final email = emailCtrl.text;
|
||||||
|
accountsGrpc
|
||||||
|
.resetPassword(username, email)
|
||||||
|
.then((_) => setState(() {
|
||||||
|
codeEnabled = true;
|
||||||
|
}))
|
||||||
|
.catchError((e) {
|
||||||
|
GrpcError error = e;
|
||||||
|
String msg;
|
||||||
|
if (error.message != null) {
|
||||||
|
msg = error.message!;
|
||||||
|
} else {
|
||||||
|
msg = error.toString();
|
||||||
|
}
|
||||||
|
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
|
||||||
|
content: Text(msg),
|
||||||
|
backgroundColor: Colors.red,
|
||||||
|
showCloseIcon: true,
|
||||||
|
behavior: SnackBarBehavior.floating,
|
||||||
|
));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Widget signInForm() => SizedBox(
|
Widget signInForm() => SizedBox(
|
||||||
width: 420,
|
width: 420,
|
||||||
height: 280,
|
height: 280,
|
||||||
@ -122,6 +178,11 @@ class _LoginFormState extends State<LoginForm> {
|
|||||||
cursorHeight: 18,
|
cursorHeight: 18,
|
||||||
cursorRadius: const Radius.circular(10),
|
cursorRadius: const Radius.circular(10),
|
||||||
),
|
),
|
||||||
|
TextButton(
|
||||||
|
onPressed: () => setState(() {
|
||||||
|
action = Action.resetPassword;
|
||||||
|
}),
|
||||||
|
child: const Text("reset yomakeur password")),
|
||||||
]))));
|
]))));
|
||||||
|
|
||||||
List<Widget> signInActions() => [
|
List<Widget> signInActions() => [
|
||||||
@ -142,13 +203,33 @@ class _LoginFormState extends State<LoginForm> {
|
|||||||
onPressed: () => setState(() {
|
onPressed: () => setState(() {
|
||||||
action = Action.singIn;
|
action = Action.singIn;
|
||||||
}),
|
}),
|
||||||
child: const Text('Sing In'),
|
child: const Text('Sign In'),
|
||||||
),
|
),
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: submitSignUp,
|
onPressed: submitSignUp,
|
||||||
child: const Text('OK'),
|
child: const Text('OK'),
|
||||||
),
|
),
|
||||||
];
|
];
|
||||||
|
|
||||||
|
List<Widget> resetPasswordActions() => [
|
||||||
|
TextButton(
|
||||||
|
onPressed: () => setState(() {
|
||||||
|
action = Action.singIn;
|
||||||
|
}),
|
||||||
|
child: const Text('Sign In'),
|
||||||
|
),
|
||||||
|
TextButton(
|
||||||
|
onPressed: () => setState(() {
|
||||||
|
action = Action.signUp;
|
||||||
|
}),
|
||||||
|
child: const Text('Sing Up'),
|
||||||
|
),
|
||||||
|
TextButton(
|
||||||
|
onPressed: subminResetPassword,
|
||||||
|
child: const Text('OK'),
|
||||||
|
),
|
||||||
|
];
|
||||||
|
|
||||||
Widget signUpForm() => SizedBox(
|
Widget signUpForm() => SizedBox(
|
||||||
width: 420,
|
width: 420,
|
||||||
height: 280,
|
height: 280,
|
||||||
@ -207,6 +288,86 @@ class _LoginFormState extends State<LoginForm> {
|
|||||||
cursorRadius: const Radius.circular(10),
|
cursorRadius: const Radius.circular(10),
|
||||||
),
|
),
|
||||||
]))));
|
]))));
|
||||||
|
Widget resetPasswordForm() => SizedBox(
|
||||||
|
width: 420,
|
||||||
|
height: 420,
|
||||||
|
child: Form(
|
||||||
|
key: _formKey,
|
||||||
|
child: Center(
|
||||||
|
child: Column(children: [
|
||||||
|
TextFormField(
|
||||||
|
// onFieldSubmitted: (value) => submitSignUp(),
|
||||||
|
autofocus: true,
|
||||||
|
controller: usernameCtrl,
|
||||||
|
decoration: const InputDecoration(
|
||||||
|
hintText: "Enter your username",
|
||||||
|
icon: Icon(Icons.account_circle),
|
||||||
|
label: Text("Username"),
|
||||||
|
),
|
||||||
|
cursorWidth: 1,
|
||||||
|
cursorHeight: 18,
|
||||||
|
cursorRadius: const Radius.circular(10),
|
||||||
|
),
|
||||||
|
TextFormField(
|
||||||
|
// onFieldSubmitted: (value) => submitSignUp(),
|
||||||
|
controller: emailCtrl,
|
||||||
|
autofocus: true,
|
||||||
|
decoration: const InputDecoration(
|
||||||
|
hintText: "Enter your email",
|
||||||
|
icon: Icon(Icons.email),
|
||||||
|
label: Text("Email"),
|
||||||
|
),
|
||||||
|
cursorWidth: 1,
|
||||||
|
cursorHeight: 18,
|
||||||
|
cursorRadius: const Radius.circular(10),
|
||||||
|
),
|
||||||
|
TextButton(
|
||||||
|
onPressed: () => sendCode(), child: const Text("send code to email")),
|
||||||
|
TextFormField(
|
||||||
|
// onFieldSubmitted: (value) => submitSignUp(),
|
||||||
|
controller: codeCtrl,
|
||||||
|
autofocus: false,
|
||||||
|
enabled: codeEnabled,
|
||||||
|
decoration: const InputDecoration(
|
||||||
|
hintText: "Enter code that you've received via the email",
|
||||||
|
icon: Icon(Icons.numbers),
|
||||||
|
label: Text("Code"),
|
||||||
|
),
|
||||||
|
cursorWidth: 1,
|
||||||
|
cursorHeight: 18,
|
||||||
|
cursorRadius: const Radius.circular(10),
|
||||||
|
),
|
||||||
|
TextFormField(
|
||||||
|
// onFieldSubmitted: (value) => submitSignUp(),
|
||||||
|
controller: passwordCtrl,
|
||||||
|
autofocus: false,
|
||||||
|
enabled: codeEnabled,
|
||||||
|
obscureText: true,
|
||||||
|
decoration: const InputDecoration(
|
||||||
|
hintText: "Enter a new password",
|
||||||
|
icon: Icon(Icons.password),
|
||||||
|
label: Text("Password"),
|
||||||
|
),
|
||||||
|
cursorWidth: 1,
|
||||||
|
cursorHeight: 18,
|
||||||
|
cursorRadius: const Radius.circular(10),
|
||||||
|
),
|
||||||
|
TextFormField(
|
||||||
|
// onFieldSubmitted: (value) => submitSignUp(),
|
||||||
|
controller: passwordVerifyCtrl,
|
||||||
|
autofocus: false,
|
||||||
|
enabled: codeEnabled,
|
||||||
|
obscureText: true,
|
||||||
|
decoration: const InputDecoration(
|
||||||
|
hintText: "Enter a new password",
|
||||||
|
icon: Icon(Icons.password),
|
||||||
|
label: Text("Password"),
|
||||||
|
),
|
||||||
|
cursorWidth: 1,
|
||||||
|
cursorHeight: 18,
|
||||||
|
cursorRadius: const Radius.circular(10),
|
||||||
|
),
|
||||||
|
]))));
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
@ -217,8 +378,26 @@ class _LoginFormState extends State<LoginForm> {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) => AlertDialog(
|
Widget build(BuildContext context) => AlertDialog(
|
||||||
title: const Text(dialogName),
|
title: const Text(dialogName),
|
||||||
content: action == Action.singIn ? signInForm() : signUpForm(),
|
// content: action == Action.singIn ? signInForm() : signUpForm(),
|
||||||
actions: action == Action.singIn ? signInActions() : signUpActions(),
|
content: () {
|
||||||
);
|
switch (action) {
|
||||||
|
case Action.signUp:
|
||||||
|
return signUpForm();
|
||||||
|
case Action.resetPassword:
|
||||||
|
return resetPasswordForm();
|
||||||
|
default:
|
||||||
|
return signInForm();
|
||||||
|
}
|
||||||
|
}(),
|
||||||
|
actions: () {
|
||||||
|
switch (action) {
|
||||||
|
case Action.signUp:
|
||||||
|
return signUpActions();
|
||||||
|
case Action.resetPassword:
|
||||||
|
return resetPasswordActions();
|
||||||
|
default:
|
||||||
|
return signInActions();
|
||||||
|
}
|
||||||
|
}());
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import 'dart:html';
|
import 'dart:html';
|
||||||
|
|
||||||
|
import 'package:flutter_dotenv/flutter_dotenv.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:grpc/grpc_web.dart';
|
import 'package:grpc/grpc_web.dart';
|
||||||
import 'package:softplayer_web/api/grpc/accounts.dart';
|
import 'package:softplayer_web/api/grpc/accounts.dart';
|
||||||
@ -9,10 +10,8 @@ import 'package:softplayer_web/components/environments.dart';
|
|||||||
import 'package:softplayer_web/components/login_form.dart';
|
import 'package:softplayer_web/components/login_form.dart';
|
||||||
|
|
||||||
void main() async {
|
void main() async {
|
||||||
const String backendURL = String.fromEnvironment(
|
await dotenv.load(fileName: ".env");
|
||||||
'SOFTPLAYER_BACKEND_URL',
|
String backendURL = dotenv.env['SOFTPLAYER_BACKEND_URL']!;
|
||||||
defaultValue: 'https://softplayer-backend.badhouseplants.net:8080',
|
|
||||||
);
|
|
||||||
GrpcWebClientChannel grpcChannel =
|
GrpcWebClientChannel grpcChannel =
|
||||||
GrpcWebClientChannel.xhr(Uri.parse(backendURL));
|
GrpcWebClientChannel.xhr(Uri.parse(backendURL));
|
||||||
|
|
||||||
|
14
pubspec.lock
14
pubspec.lock
@ -5,10 +5,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: archive
|
name: archive
|
||||||
sha256: "0763b45fa9294197a2885c8567927e2830ade852e5c896fd4ab7e0e348d0f373"
|
sha256: ecf4273855368121b1caed0d10d4513c7241dfc813f7d3c8933b36622ae9b265
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.5.0"
|
version: "3.5.1"
|
||||||
args:
|
args:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -102,6 +102,14 @@ packages:
|
|||||||
description: flutter
|
description: flutter
|
||||||
source: sdk
|
source: sdk
|
||||||
version: "0.0.0"
|
version: "0.0.0"
|
||||||
|
flutter_dotenv:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: flutter_dotenv
|
||||||
|
sha256: "9357883bdd153ab78cbf9ffa07656e336b8bbb2b5a3ca596b0b27e119f7c7d77"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "5.1.0"
|
||||||
flutter_lints:
|
flutter_lints:
|
||||||
dependency: "direct dev"
|
dependency: "direct dev"
|
||||||
description:
|
description:
|
||||||
@ -245,7 +253,7 @@ packages:
|
|||||||
description:
|
description:
|
||||||
path: "."
|
path: "."
|
||||||
ref: main
|
ref: main
|
||||||
resolved-ref: "3bf6e1bef80350848f0f0407685e4eaf868d4c7e"
|
resolved-ref: "5ee911c92eee4ee7db58a2da0407da4f7db2f994"
|
||||||
url: "https://git.badhouseplants.net/softplayer/softplayer-dart-proto.git"
|
url: "https://git.badhouseplants.net/softplayer/softplayer-dart-proto.git"
|
||||||
source: git
|
source: git
|
||||||
version: "1.0.0+1"
|
version: "1.0.0+1"
|
||||||
|
@ -18,6 +18,7 @@ dependencies:
|
|||||||
grpc: ^3.2.4
|
grpc: ^3.2.4
|
||||||
http: ^1.2.1
|
http: ^1.2.1
|
||||||
dio: ^5.4.2
|
dio: ^5.4.2
|
||||||
|
flutter_dotenv: ^5.1.0
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
@ -28,3 +29,4 @@ flutter:
|
|||||||
uses-material-design: true
|
uses-material-design: true
|
||||||
assets:
|
assets:
|
||||||
- assets/
|
- assets/
|
||||||
|
- .env
|
Loading…
Reference in New Issue
Block a user