Commit b5bd4c78 authored by Ilham Maulana's avatar Ilham Maulana 💻

feat: implement secure storage

parent 9a9b7352
import 'dart:convert'; import 'dart:convert';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:http/http.dart' as http; import 'package:http/http.dart' as http;
...@@ -6,11 +8,11 @@ import 'package:library_app/src/models/token.dart'; ...@@ -6,11 +8,11 @@ import 'package:library_app/src/models/token.dart';
import 'package:library_app/src/models/user.dart'; import 'package:library_app/src/models/user.dart';
class AuthProvider with ChangeNotifier { class AuthProvider with ChangeNotifier {
final storage = const FlutterSecureStorage();
String baseUrl = 'http://localhost:8000/api/v1'; String baseUrl = 'http://localhost:8000/api/v1';
Token? token;
User? user; User? user;
bool get isLoggedIn => token != null; bool isLoggedIn = false;
bool invalidUsernameOrPassword = false; bool invalidUsernameOrPassword = false;
List<dynamic>? memberLoans; List<dynamic>? memberLoans;
...@@ -21,6 +23,14 @@ class AuthProvider with ChangeNotifier { ...@@ -21,6 +23,14 @@ class AuthProvider with ChangeNotifier {
bool resetPasswordTokenSended = false; bool resetPasswordTokenSended = false;
bool resetPasswordSucced = false; bool resetPasswordSucced = false;
Future<void> storeAccessToken(String accessToken) async {
await storage.write(key: 'access_token', value: accessToken);
}
Future<String?> getAccessToken() async {
return await storage.read(key: 'access_token');
}
Future<void> signIn(String username, String password) async { Future<void> signIn(String username, String password) async {
try { try {
final response = await http.post( final response = await http.post(
...@@ -31,7 +41,12 @@ class AuthProvider with ChangeNotifier { ...@@ -31,7 +41,12 @@ class AuthProvider with ChangeNotifier {
if (response.statusCode == 200) { if (response.statusCode == 200) {
final data = jsonDecode(response.body); final data = jsonDecode(response.body);
token = Token.fromJson(data); await storeAccessToken(Token.fromJson(data)!.key);
final token = await getAccessToken();
if (token != null) {
isLoggedIn = true;
}
debugPrint("Login successful $token"); debugPrint("Login successful $token");
} else if (response.statusCode == 401) { } else if (response.statusCode == 401) {
...@@ -50,17 +65,20 @@ class AuthProvider with ChangeNotifier { ...@@ -50,17 +65,20 @@ class AuthProvider with ChangeNotifier {
} }
Future<void> signOut() async { Future<void> signOut() async {
final token = await getAccessToken();
try { try {
final response = await http.get( final response = await http.get(
Uri.parse('$baseUrl/auth/logout'), Uri.parse('$baseUrl/auth/logout'),
headers: { headers: {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
'Authorization': 'Bearer ${token?.key}' 'Authorization': 'Bearer $token'
}, },
); );
if (response.statusCode == 200) { if (response.statusCode == 200) {
token = null; await storage.delete(key: 'token');
isLoggedIn = false;
} else { } else {
debugPrint("Logout failed: ${response.statusCode} ${response.body}"); debugPrint("Logout failed: ${response.statusCode} ${response.body}");
} }
...@@ -86,7 +104,13 @@ class AuthProvider with ChangeNotifier { ...@@ -86,7 +104,13 @@ class AuthProvider with ChangeNotifier {
if (response.statusCode == 200) { if (response.statusCode == 200) {
final data = jsonDecode(response.body); final data = jsonDecode(response.body);
token = Token.fromJson(data); storeAccessToken(Token.fromJson(data)!.key);
final token = await getAccessToken();
if (token != null) {
isLoggedIn = true;
}
debugPrint(response.body); debugPrint(response.body);
} else { } else {
debugPrint( debugPrint(
...@@ -100,13 +124,15 @@ class AuthProvider with ChangeNotifier { ...@@ -100,13 +124,15 @@ class AuthProvider with ChangeNotifier {
} }
Future<void> getUserDetail() async { Future<void> getUserDetail() async {
final token = await getAccessToken();
if (token != null) { if (token != null) {
try { try {
final response = await http.get( final response = await http.get(
Uri.parse('$baseUrl/user'), Uri.parse('$baseUrl/user'),
headers: { headers: {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
'Authorization': 'Bearer ${token?.key}' 'Authorization': 'Bearer $token'
}, },
); );
...@@ -132,6 +158,8 @@ class AuthProvider with ChangeNotifier { ...@@ -132,6 +158,8 @@ class AuthProvider with ChangeNotifier {
String? lastName, String? lastName,
bool isStaff, bool isStaff,
) async { ) async {
final token = await getAccessToken();
if (token != null) { if (token != null) {
try { try {
final body = jsonEncode({ final body = jsonEncode({
...@@ -145,7 +173,7 @@ class AuthProvider with ChangeNotifier { ...@@ -145,7 +173,7 @@ class AuthProvider with ChangeNotifier {
body: body, body: body,
headers: { headers: {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
'Authorization': 'Bearer ${token?.key}' 'Authorization': 'Bearer $token'
}, },
); );
...@@ -216,6 +244,8 @@ class AuthProvider with ChangeNotifier { ...@@ -216,6 +244,8 @@ class AuthProvider with ChangeNotifier {
} }
Future<void> getMemberLoan() async { Future<void> getMemberLoan() async {
final token = await getAccessToken();
String url = '$baseUrl/members/${user?.accountId}/loans/'; String url = '$baseUrl/members/${user?.accountId}/loans/';
if (filterByUpcoming) { if (filterByUpcoming) {
url += '?near_outstanding=True'; url += '?near_outstanding=True';
...@@ -230,7 +260,7 @@ class AuthProvider with ChangeNotifier { ...@@ -230,7 +260,7 @@ class AuthProvider with ChangeNotifier {
Uri.parse(url), Uri.parse(url),
headers: { headers: {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
'Authorization': 'Bearer ${token?.key}' 'Authorization': 'Bearer $token'
}, },
); );
...@@ -259,6 +289,8 @@ class AuthProvider with ChangeNotifier { ...@@ -259,6 +289,8 @@ class AuthProvider with ChangeNotifier {
} }
Future<void> createMemberLoan(int memberId, int bookId, int loanDay) async { Future<void> createMemberLoan(int memberId, int bookId, int loanDay) async {
final token = await getAccessToken();
final now = DateTime.now(); final now = DateTime.now();
final dueDate = now.add(Duration(days: loanDay)); final dueDate = now.add(Duration(days: loanDay));
final body = { final body = {
...@@ -274,7 +306,7 @@ class AuthProvider with ChangeNotifier { ...@@ -274,7 +306,7 @@ class AuthProvider with ChangeNotifier {
body: jsonEncode(body), body: jsonEncode(body),
headers: { headers: {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
'Authorization': 'Bearer ${token?.key}' 'Authorization': 'Bearer $token'
}, },
); );
......
...@@ -6,6 +6,10 @@ ...@@ -6,6 +6,10 @@
#include "generated_plugin_registrant.h" #include "generated_plugin_registrant.h"
#include <flutter_secure_storage_linux/flutter_secure_storage_linux_plugin.h>
void fl_register_plugins(FlPluginRegistry* registry) { void fl_register_plugins(FlPluginRegistry* registry) {
g_autoptr(FlPluginRegistrar) flutter_secure_storage_linux_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "FlutterSecureStorageLinuxPlugin");
flutter_secure_storage_linux_plugin_register_with_registrar(flutter_secure_storage_linux_registrar);
} }
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
# #
list(APPEND FLUTTER_PLUGIN_LIST list(APPEND FLUTTER_PLUGIN_LIST
flutter_secure_storage_linux
) )
list(APPEND FLUTTER_FFI_PLUGIN_LIST list(APPEND FLUTTER_FFI_PLUGIN_LIST
......
...@@ -5,8 +5,10 @@ ...@@ -5,8 +5,10 @@
import FlutterMacOS import FlutterMacOS
import Foundation import Foundation
import flutter_secure_storage_macos
import path_provider_foundation import path_provider_foundation
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
FlutterSecureStoragePlugin.register(with: registry.registrar(forPlugin: "FlutterSecureStoragePlugin"))
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin")) PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
} }
...@@ -102,6 +102,54 @@ packages: ...@@ -102,6 +102,54 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "4.0.0" version: "4.0.0"
flutter_secure_storage:
dependency: "direct main"
description:
name: flutter_secure_storage
sha256: "165164745e6afb5c0e3e3fcc72a012fb9e58496fb26ffb92cf22e16a821e85d0"
url: "https://pub.dev"
source: hosted
version: "9.2.2"
flutter_secure_storage_linux:
dependency: transitive
description:
name: flutter_secure_storage_linux
sha256: "4d91bfc23047422cbcd73ac684bc169859ee766482517c22172c86596bf1464b"
url: "https://pub.dev"
source: hosted
version: "1.2.1"
flutter_secure_storage_macos:
dependency: transitive
description:
name: flutter_secure_storage_macos
sha256: "1693ab11121a5f925bbea0be725abfcfbbcf36c1e29e571f84a0c0f436147a81"
url: "https://pub.dev"
source: hosted
version: "3.1.2"
flutter_secure_storage_platform_interface:
dependency: transitive
description:
name: flutter_secure_storage_platform_interface
sha256: cf91ad32ce5adef6fba4d736a542baca9daf3beac4db2d04be350b87f69ac4a8
url: "https://pub.dev"
source: hosted
version: "1.1.2"
flutter_secure_storage_web:
dependency: transitive
description:
name: flutter_secure_storage_web
sha256: f4ebff989b4f07b2656fb16b47852c0aab9fed9b4ec1c70103368337bc1886a9
url: "https://pub.dev"
source: hosted
version: "1.2.1"
flutter_secure_storage_windows:
dependency: transitive
description:
name: flutter_secure_storage_windows
sha256: b20b07cb5ed4ed74fc567b78a72936203f587eba460af1df11281c9326cd3709
url: "https://pub.dev"
source: hosted
version: "3.1.2"
flutter_svg: flutter_svg:
dependency: "direct main" dependency: "direct main"
description: description:
...@@ -115,6 +163,11 @@ packages: ...@@ -115,6 +163,11 @@ packages:
description: flutter description: flutter
source: sdk source: sdk
version: "0.0.0" version: "0.0.0"
flutter_web_plugins:
dependency: transitive
description: flutter
source: sdk
version: "0.0.0"
google_fonts: google_fonts:
dependency: "direct main" dependency: "direct main"
description: description:
...@@ -147,6 +200,14 @@ packages: ...@@ -147,6 +200,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.19.0" version: "0.19.0"
js:
dependency: transitive
description:
name: js
sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3
url: "https://pub.dev"
source: hosted
version: "0.6.7"
leak_tracker: leak_tracker:
dependency: transitive dependency: transitive
description: description:
...@@ -416,6 +477,14 @@ packages: ...@@ -416,6 +477,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.0.0" version: "1.0.0"
win32:
dependency: transitive
description:
name: win32
sha256: a79dbe579cb51ecd6d30b17e0cae4e0ea15e2c0e66f69ad4198f22a6789e94f4
url: "https://pub.dev"
source: hosted
version: "5.5.1"
xdg_directories: xdg_directories:
dependency: transitive dependency: transitive
description: description:
......
...@@ -41,6 +41,7 @@ dependencies: ...@@ -41,6 +41,7 @@ dependencies:
provider: ^6.1.2 provider: ^6.1.2
http: ^1.2.2 http: ^1.2.2
flutter_keychain: ^2.5.0 flutter_keychain: ^2.5.0
flutter_secure_storage: ^9.2.2
dev_dependencies: dev_dependencies:
flutter_test: flutter_test:
......
...@@ -6,6 +6,9 @@ ...@@ -6,6 +6,9 @@
#include "generated_plugin_registrant.h" #include "generated_plugin_registrant.h"
#include <flutter_secure_storage_windows/flutter_secure_storage_windows_plugin.h>
void RegisterPlugins(flutter::PluginRegistry* registry) { void RegisterPlugins(flutter::PluginRegistry* registry) {
FlutterSecureStorageWindowsPluginRegisterWithRegistrar(
registry->GetRegistrarForPlugin("FlutterSecureStorageWindowsPlugin"));
} }
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
# #
list(APPEND FLUTTER_PLUGIN_LIST list(APPEND FLUTTER_PLUGIN_LIST
flutter_secure_storage_windows
) )
list(APPEND FLUTTER_FFI_PLUGIN_LIST list(APPEND FLUTTER_FFI_PLUGIN_LIST
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment