diff --git a/android/app/build.gradle b/android/app/build.gradle index 3a1d1da..a9a4be3 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -26,7 +26,7 @@ apply plugin: 'kotlin-android' apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" android { - compileSdkVersion flutter.compileSdkVersion + compileSdkVersion 32 ndkVersion flutter.ndkVersion compileOptions { @@ -47,7 +47,7 @@ android { applicationId "com.ab.rkm.rkm" // You can update the following values to match your application needs. // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-build-configuration. - minSdkVersion flutter.minSdkVersion + minSdkVersion 19 targetSdkVersion flutter.targetSdkVersion versionCode flutterVersionCode.toInteger() versionName flutterVersionName diff --git a/assets/images/desenvolvimento.png b/assets/images/desenvolvimento.png new file mode 100644 index 0000000..091cc90 Binary files /dev/null and b/assets/images/desenvolvimento.png differ diff --git a/assets/images/homologacao.png b/assets/images/homologacao.png new file mode 100644 index 0000000..1526f61 Binary files /dev/null and b/assets/images/homologacao.png differ diff --git a/assets/images/loading.gif b/assets/images/loading.gif new file mode 100644 index 0000000..1432922 Binary files /dev/null and b/assets/images/loading.gif differ diff --git a/lib/screens/login_screen.dart b/lib/screens/login_screen.dart index 1e89c93..12e1239 100644 --- a/lib/screens/login_screen.dart +++ b/lib/screens/login_screen.dart @@ -1,5 +1,7 @@ +import 'dart:convert'; import 'package:flutter/material.dart'; import 'package:intl/intl.dart'; +import 'package:rkm/service/url_api_const.dart'; import 'package:rkm/utils/color_palette.dart'; import 'package:rkm/utils/const_variable.dart'; import 'package:rkm/widgets/button_default.dart'; @@ -7,6 +9,8 @@ import 'package:rkm/widgets/dropdown_button_city.dart'; import 'package:rkm/widgets/input_text.dart'; import 'package:rkm/widgets/text_default.dart'; +import '../service/api_get_pass.dart'; +import '../service/encrypt_password.dart'; class LoginScreen extends StatefulWidget { const LoginScreen({Key? key}) : super(key: key); @@ -22,24 +26,45 @@ class _LoginScreenState extends State { String? now; String? selectCity; bool validatorDropDown= false; + int contLogo = 0; + String mode = 'online'; + String url = UrlApiConst.ApiUrlOnline; - checkLogin(){ - // if(inputUser.text.isNotEmpty && inputPassword.text.isNotEmpty && inputUser.text == 'teste' && inputPassword.text == '123'){ - // if(selectCity!=null){ + checkLogin()async{ + if(inputUser.text.isNotEmpty && inputPassword.text.isNotEmpty && inputUser.text.length>3 && inputPassword.text.length>3){ + if(selectCity!=null){ setState(() { error = ''; }); - Navigator.pushNamed(context, '/home'); - // }else{ - // setState(() { - // error = 'Selecione sua cidade'; - // }); - // } - // }else{ - // setState(() { - // error = 'Usuário/senha inválido(s)'; - // }); - // } + await ApiGetPass().apiConect(selectCity,mode,inputUser.text,url).then((response){ + print(response); + print(inputUser.text); + print(inputPassword.text); + if(inputUser.text == inputPassword.text || response['bloqueio']==1){ + setState(() { + error = 'Usuário bloqueado/senha incorreta'; + }); + }else if(response['status']==0) { + setState(() { + error = 'Usuário não encontrado'; + }); + }else if(response['status']==1) { + setState((){ + error = ''; + print(EncryptPassword().encrypt(inputPassword.text,response['userPass'])); + }); + } + }); + }else{ + setState(() { + error = 'Selecione sua cidade'; + }); + } + }else{ + setState(() { + error = 'Usuário/senha inválido(s)'; + }); + } } @override @@ -61,15 +86,15 @@ class _LoginScreenState extends State { centerTitle: true, title: TextDefault(text: 'RKM AB - Carga Inicial',fontSize: ConstVariable().fontSizeTitleAppBar,color: ColorPalette.white), ), - bottomSheet: Container( - color: ColorPalette.secundary, - padding: EdgeInsets.all(8.0), - child: TextDefault( - text: 'Última sincronização $now', - fontSize: 15, - color: ColorPalette.gray, - ), - ), + // bottomSheet: Container( + // color: ColorPalette.secundary, + // padding: EdgeInsets.all(8.0), + // child: TextDefault( + // text: 'Última sincronização $now', + // fontSize: 15, + // color: ColorPalette.gray, + // ), + // ), body: SingleChildScrollView( child: Container( padding: EdgeInsets.only(top: height*0.2), @@ -80,7 +105,27 @@ class _LoginScreenState extends State { mainAxisSize: MainAxisSize.min, mainAxisAlignment: MainAxisAlignment.start, children: [ - Image.asset('assets/images/logo.PNG',width: width*0.4), + GestureDetector( + onTap: ()=>setState((){ + contLogo++; + if(contLogo>=5 && contLogo<=10){ + mode = 'homologacao'; + url = UrlApiConst.ApiUrlHomologacao; + } + if(contLogo>10){ + mode = 'desenvolvimento'; + url = UrlApiConst.ApiUrlDesenvolvimento; + if(contLogo==15){ + contLogo=0; + mode = 'online'; + url = UrlApiConst.ApiUrlOnline; + } + } + }), + child: Image.asset('assets/images/logo.PNG',width: width*0.4) + ), + mode == 'homologacao'?Image.asset('assets/images/homologacao.png',width: width*0.4):Container(), + mode == 'desenvolvimento'?Image.asset('assets/images/desenvolvimento.png',width: width*0.4):Container(), SizedBox(height: 10), Form( autovalidateMode: AutovalidateMode.onUserInteraction, @@ -91,18 +136,22 @@ class _LoginScreenState extends State { children: [ InputText( hint: 'Usuário', - label: 'Usuário', + label: inputUser.text.isNotEmpty?'':'Usuário', error: 'Campo obrigatório', controller: inputUser, - width: width*0.6 + width: width*0.6, + colorBorder: Colors.white, + onChanged: (v)=>setState((){}), ), InputText( - hint: 'Senha', - label: 'Senha', - error: 'Campo obrigatório', - obscure: true, - controller: inputPassword, - width: width*0.6 + hint: 'Senha', + label: inputPassword.text.isNotEmpty?'':'Senha', + error: 'Campo obrigatório', + obscure: true, + controller: inputPassword, + width: width*0.6, + colorBorder: Colors.white, + onChanged: (v)=>setState((){}), ), DropDownButtonCity( error: 'Campo obrigatório', diff --git a/lib/service/api_get_pass.dart b/lib/service/api_get_pass.dart new file mode 100644 index 0000000..2af0cce --- /dev/null +++ b/lib/service/api_get_pass.dart @@ -0,0 +1,20 @@ +import 'dart:convert'; +import 'package:http/http.dart' as http; + +class ApiGetPass{ + Future apiConect(String? selectCity,String mode,String inputUser,String urlApi)async{ + String city = ''; + city = selectCity!.toLowerCase() + .replaceAll('ú', 'u') + .replaceAll('ç', 'c') + .replaceAll('ó', 'o') + .replaceAll('ô', 'o') + .replaceAll('í', 'i') + .replaceAll('ã','a'); + + final url = '$urlApi$mode/$city/pass/$inputUser'; + final response = await http.get(Uri.parse(url)); + final map = json.decode(response.body); + return map; + } +} \ No newline at end of file diff --git a/lib/service/encrypt_password.dart b/lib/service/encrypt_password.dart new file mode 100644 index 0000000..f3c918d --- /dev/null +++ b/lib/service/encrypt_password.dart @@ -0,0 +1,43 @@ +import 'package:gainer_crypto/crypto.dart'; + +class EncryptPassword{ + encrypt(String senhaDigitada,String senhaUsuario) { + // Deixa e senha digitada em maiuscula + var senha = senhaDigitada.toUpperCase(); + // Faz a criptografia da senha inserida + String senhaMD5 = grHashString(GRCryptoType.md5, senha); + // Retira o tipo (1, 2 ou 3) da senha do Usuário + int tipo = int.parse(senhaUsuario.substring(0, 1)); + // Define a possição inicial da quebra da senha + int posI = 0; + int posF = 0; + int posMax = 0; + // Pra cada tipo (1, 2 ou 3) define a posição inicial da quebra da senha + if(tipo == 1){ + posI = 0; + posF = 16; + posMax = 16; + } else if(tipo == 2){ + posI = 16; + posF = 0; + posMax = 16; + } else if(tipo == 3){ + posI = 0; + posF = 31; + posMax = 1; + } + + print('posI $posI posF $posF PosMax $posMax'); + print('inicio ${senhaMD5.substring(0, 16)}'); + print('meio ${senhaMD5.substring(16, 32)}'); + print('fim ${senhaMD5.substring(posF, posMax)}'); + print('senha: ${senhaMD5.substring(posI, posMax) + senha + senhaMD5.substring(posF, posMax)}'); + print('${grHashString(GRCryptoType.sha1, senhaMD5.substring(posI, posMax) + senha + senhaMD5.substring(posF, posMax))}'); + + + // Faz a criptografia e concatena ela com sha1 e md5 + String senhaCriptogradafa = tipo.toString() + '\$'+ grHashString(GRCryptoType.sha1, senhaMD5.substring(posI, posMax) + senha + senhaMD5.substring(posF, posMax)); + // Retorna a senha criptografada + return senhaCriptogradafa; + } +} \ No newline at end of file diff --git a/lib/service/url_api_const.dart b/lib/service/url_api_const.dart new file mode 100644 index 0000000..9f6a69e --- /dev/null +++ b/lib/service/url_api_const.dart @@ -0,0 +1,5 @@ +class UrlApiConst{ + static const String ApiUrlOnline = 'https://saude.rkmsistemas.com.br/api/atb/'; + static const String ApiUrlHomologacao = 'https://app0.rkmsistemas.com.br/api/atb/'; + static const String ApiUrlDesenvolvimento = 'http://192.168.0.42:8010/api/atb/'; +} \ No newline at end of file diff --git a/lib/utils/const_variable.dart b/lib/utils/const_variable.dart index ff111fd..6c9b08d 100644 --- a/lib/utils/const_variable.dart +++ b/lib/utils/const_variable.dart @@ -221,13 +221,18 @@ class ConstVariable{ 'Anhembi', 'Aparecida', 'Batatais', + 'Biritiba Mirim', 'Cabreúva', + 'Cachoeira Paulista', + 'Caconde', 'Casa Branca', + 'Corumbataí', 'Descalvado', 'Extrema', - 'Francisco Morato', 'Franco da Rocha', 'Igaraçu do Tiete', + 'Iracemápolis', + 'Itapeva', 'Itápolis', 'Itirapina', 'Ituverava', @@ -242,7 +247,8 @@ class ConstVariable{ 'Piracicaba', 'Porto Ferreira', 'Santa Rita', - 'Santo Antonio da Alegria', + 'Santo Antônio da Alegria', + 'São Sabastião da Grama', 'Tapiratiba' ]; var backgroundGradient = BoxDecoration( diff --git a/lib/widgets/input_text.dart b/lib/widgets/input_text.dart index b4fae9b..8ef936e 100644 --- a/lib/widgets/input_text.dart +++ b/lib/widgets/input_text.dart @@ -14,6 +14,7 @@ class InputText extends StatelessWidget { TextInputType textInputType; int maxLines; Color colorBorder; + var onChanged; InputText({ required this.controller, @@ -26,7 +27,8 @@ class InputText extends StatelessWidget { this.enable = true, this.textInputType = TextInputType.text, this.maxLines = 1, - this.colorBorder = ColorPalette.black54 + this.colorBorder = ColorPalette.black54, + this.onChanged = null }); @override @@ -38,6 +40,7 @@ class InputText extends StatelessWidget { child: TextFormField( keyboardType: textInputType, maxLines: maxLines, + onChanged: onChanged, validator: (value) { if (value!=null && value!.length==0) { return error; @@ -54,19 +57,19 @@ class InputText extends StatelessWidget { fillColor: ColorPalette.appBar, labelText: label, border: OutlineInputBorder( - borderSide: BorderSide(width: 2,color: colorBorder) + borderSide: BorderSide(width: 1,color: colorBorder) ), focusedBorder: OutlineInputBorder( - borderSide: BorderSide(width: 3, color: colorBorder), - borderRadius: BorderRadius.circular(15), + borderSide: BorderSide(width: 1, color: colorBorder), + borderRadius: BorderRadius.circular(3), ), enabledBorder: OutlineInputBorder( - borderSide: BorderSide(width: 3, color: colorBorder), - borderRadius: BorderRadius.circular(15), + borderSide: BorderSide(width: 1, color: colorBorder), + borderRadius: BorderRadius.circular(3), ), disabledBorder: OutlineInputBorder( - borderSide: BorderSide(width: 3, color: colorBorder), - borderRadius: BorderRadius.circular(15), + borderSide: BorderSide(width: 1, color: colorBorder), + borderRadius: BorderRadius.circular(3), ), hintText: this.hint, enabled: enable, diff --git a/pubspec.lock b/pubspec.lock index ea2f930..dc7bf3a 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -1,6 +1,20 @@ # Generated by pub # See https://dart.dev/tools/pub/glossary#lockfile packages: + args: + dependency: transitive + description: + name: args + url: "https://pub.dartlang.org" + source: hosted + version: "2.4.0" + asn1lib: + dependency: transitive + description: + name: asn1lib + url: "https://pub.dartlang.org" + source: hosted + version: "1.4.0" async: dependency: transitive description: @@ -36,6 +50,20 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.16.0" + convert: + dependency: transitive + description: + name: convert + url: "https://pub.dartlang.org" + source: hosted + version: "3.1.1" + crypto: + dependency: transitive + description: + name: crypto + url: "https://pub.dartlang.org" + source: hosted + version: "3.0.2" cupertino_icons: dependency: "direct main" description: @@ -43,6 +71,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.0.5" + encrypt: + dependency: transitive + description: + name: encrypt + url: "https://pub.dartlang.org" + source: hosted + version: "5.0.1" fake_async: dependency: transitive description: @@ -79,8 +114,15 @@ packages: description: flutter source: sdk version: "0.0.0" + gainer_crypto: + dependency: "direct main" + description: + name: gainer_crypto + url: "https://pub.dartlang.org" + source: hosted + version: "0.0.6" http: - dependency: transitive + dependency: "direct main" description: name: http url: "https://pub.dartlang.org" @@ -170,6 +212,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.1.4" + pointycastle: + dependency: transitive + description: + name: pointycastle + url: "https://pub.dartlang.org" + source: hosted + version: "3.7.2" sky_engine: dependency: transitive description: flutter diff --git a/pubspec.yaml b/pubspec.yaml index 5a00053..f5c75d3 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -15,6 +15,8 @@ dependencies: intl: package_info_plus: ^3.0.2 line_icons: ^2.0.1 + http: + gainer_crypto: ^0.0.6 dev_dependencies: flutter_test: