Rewrote autologin to default to authorized
This is prevents the current route from being reset, when reloading the tab and also prevents the welcome screen from showing (when running on slow connections) NOTE: This also means that the home screen will be loaded even if the client has never been logged in. This means that some functions might return null
This commit is contained in:
parent
63155fc6bb
commit
31a84b5ec7
5 changed files with 109 additions and 78 deletions
|
@ -1,7 +1,7 @@
|
|||
import 'package:http/http.dart' as http;
|
||||
import 'dart:convert';
|
||||
import './resolve_url.dart';
|
||||
import './storage.dart';
|
||||
import './user.dart';
|
||||
|
||||
enum Result {
|
||||
ok,
|
||||
|
@ -29,11 +29,11 @@ Future<Response> postWithCreadentials(
|
|||
{required OutbagServer target,
|
||||
String path = '',
|
||||
required Map<String, dynamic> body,
|
||||
required LoginDetails credentials}) async {
|
||||
required User credentials}) async {
|
||||
Map<String, String> headers = {
|
||||
"Content-Type": "application/json",
|
||||
'Authorization':
|
||||
'Digest name=${credentials.username} server=${target.base} accountKey=${credentials.password}'
|
||||
'Digest name=${credentials.username} server=${target.tag} accountKey=${credentials.password}'
|
||||
};
|
||||
return await usePostApi(
|
||||
target: target, path: path, headers: headers, body: body);
|
||||
|
|
|
@ -2,6 +2,8 @@ import 'package:localstore/localstore.dart';
|
|||
import 'package:http/http.dart' as http;
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:outbag_app/main.dart';
|
||||
|
||||
const String wellKnownPath = "/.well-known/outbag/server";
|
||||
const int defaultPort = 7223;
|
||||
|
||||
|
@ -21,7 +23,7 @@ class OutbagServer {
|
|||
final String tag;
|
||||
|
||||
const OutbagServer(
|
||||
{required this.host,
|
||||
{required this.host,
|
||||
required this.port,
|
||||
required this.path,
|
||||
required this.tag});
|
||||
|
@ -35,23 +37,28 @@ class OutbagServer {
|
|||
).toString();
|
||||
}
|
||||
|
||||
void toDisk() async {
|
||||
factory OutbagServer.fromMap(Map<String, dynamic> data) {
|
||||
return OutbagServer(
|
||||
tag: data['tag'],
|
||||
host: data['host'],
|
||||
path: data['path'],
|
||||
port: data['port']);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toMap() {
|
||||
return {'host': host, 'port': port, 'path': path, 'tag': tag};
|
||||
}
|
||||
|
||||
Future<void> toDisk() async {
|
||||
final db = Localstore.instance;
|
||||
await db
|
||||
.collection('meta')
|
||||
.doc('server')
|
||||
.set({'host': host, 'port': port, 'path': path, 'tag': tag});
|
||||
await db.collection('meta').doc('server').set(toMap());
|
||||
}
|
||||
|
||||
static Future<OutbagServer> fromDisk() async {
|
||||
final db = Localstore.instance;
|
||||
final data = await db.collection('meta').doc('server').get();
|
||||
|
||||
return OutbagServer(
|
||||
tag: data?['tag'],
|
||||
host: data?['host'],
|
||||
path: data?['path'],
|
||||
port: data?['port']);
|
||||
return OutbagServer.fromMap(data!);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -63,18 +70,18 @@ Future<OutbagServer> getOutbagServerUrl(String tag) async {
|
|||
try {
|
||||
final uri = await fetchWellKnown(rootUri.host, rootUri.port);
|
||||
return OutbagServer(
|
||||
host: rootUri.host,
|
||||
port: uri.port,
|
||||
path: uri.path,
|
||||
tag: onRoot ? rootUri.host : '$rootUri.host:$uri.port');
|
||||
host: rootUri.host,
|
||||
port: uri.port,
|
||||
path: uri.path,
|
||||
tag: onRoot ? rootUri.host : '${rootUri.host}:${uri.port}');
|
||||
} catch (_) {
|
||||
if (onRoot) {
|
||||
final uri = await fetchWellKnown(rootUri.host, defaultPort);
|
||||
return OutbagServer(
|
||||
host: rootUri.host,
|
||||
port: uri.port,
|
||||
path: uri.path,
|
||||
tag: onRoot ? rootUri.host : '$rootUri.host:$uri.port');
|
||||
host: rootUri.host,
|
||||
port: uri.port,
|
||||
path: uri.path,
|
||||
tag: onRoot ? rootUri.host : '${rootUri.host}:${uri.port}');
|
||||
}
|
||||
}
|
||||
throw Error();
|
||||
|
|
|
@ -1,38 +0,0 @@
|
|||
import 'package:localstore/localstore.dart';
|
||||
import './resolve_url.dart';
|
||||
|
||||
class LoginDetails {
|
||||
const LoginDetails(
|
||||
{required this.username, required this.password, required this.server});
|
||||
|
||||
final String username;
|
||||
final String password;
|
||||
final OutbagServer server;
|
||||
|
||||
void toDisk() async {
|
||||
final db = Localstore.instance;
|
||||
await db
|
||||
.collection('meta')
|
||||
.doc('auth')
|
||||
.set({'username': username, 'password': password});
|
||||
server.toDisk();
|
||||
}
|
||||
|
||||
static Future<LoginDetails> fromDisk() async {
|
||||
final db = Localstore.instance;
|
||||
final data = await db.collection('meta').doc('auth').get();
|
||||
final server = await OutbagServer.fromDisk();
|
||||
|
||||
return LoginDetails(
|
||||
username: data?['username'],
|
||||
password: data?['password'],
|
||||
server: server,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// obtain room list
|
||||
Future<Map<String, dynamic>?> getRooms() async {
|
||||
final db = Localstore.instance;
|
||||
return await db.collection('rooms').get();
|
||||
}
|
38
lib/backend/user.dart
Normal file
38
lib/backend/user.dart
Normal file
|
@ -0,0 +1,38 @@
|
|||
import 'package:localstore/localstore.dart';
|
||||
import './resolve_url.dart';
|
||||
|
||||
class User {
|
||||
const User(
|
||||
{required this.username, required this.password, required this.server});
|
||||
|
||||
final String username;
|
||||
final String password;
|
||||
final OutbagServer server;
|
||||
|
||||
Future<void> toDisk() async {
|
||||
final db = Localstore.instance;
|
||||
await db
|
||||
.collection('meta')
|
||||
.doc('auth')
|
||||
.set({'username': username, 'password': password});
|
||||
await server.toDisk();
|
||||
}
|
||||
|
||||
static Future<User> fromDisk() async {
|
||||
final db = Localstore.instance;
|
||||
final data = await db.collection('meta').doc('auth').get();
|
||||
final server = await OutbagServer.fromDisk();
|
||||
|
||||
return User(
|
||||
username: data?['username'],
|
||||
password: data?['password'],
|
||||
server: server,
|
||||
);
|
||||
}
|
||||
|
||||
static listen(Function(Map<String, dynamic>) cb) async {
|
||||
final db = Localstore.instance;
|
||||
final stream = db.collection('meta').stream;
|
||||
stream.listen(cb);
|
||||
}
|
||||
}
|
|
@ -1,22 +1,13 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:outbag_app/backend/storage.dart';
|
||||
import 'package:outbag_app/backend/user.dart';
|
||||
import 'package:outbag_app/screens/room/new.dart';
|
||||
import './screens/home.dart';
|
||||
import './screens/welcome.dart';
|
||||
import './screens/room.dart';
|
||||
import './screens/auth.dart';
|
||||
import './backend/request.dart';
|
||||
import 'package:routemaster/routemaster.dart';
|
||||
import 'package:localstore/localstore.dart';
|
||||
|
||||
// routes when user is logged in
|
||||
final routesLoggedIn = RouteMap(routes: {
|
||||
'/': (_) => const MaterialPage(child: HomePage()),
|
||||
'/r/:server/:tag/:page': (info) => MaterialPage(
|
||||
child: RoomPage(info.pathParameters['server'] ?? "",
|
||||
info.pathParameters['tag'] ?? "",
|
||||
page: info.pathParameters['page'] ?? ""),
|
||||
)
|
||||
}, onUnknownRoute: (_) => const Redirect('/'));
|
||||
// routes when user is not logged in
|
||||
final routesUnauthorized = RouteMap(routes: {
|
||||
'/welcome/': (_) => const MaterialPage(child: WelcomePage()),
|
||||
|
@ -24,7 +15,23 @@ final routesUnauthorized = RouteMap(routes: {
|
|||
'/signupOTA': (_) =>
|
||||
const MaterialPage(child: AuthPage(mode: Mode.signupOTA)),
|
||||
'/signin': (_) => const MaterialPage(child: AuthPage(mode: Mode.signin)),
|
||||
}, onUnknownRoute: (_) => const Redirect('/welcome'));
|
||||
}, onUnknownRoute: (_) => const MaterialPage(child: WelcomePage()));
|
||||
|
||||
// routes when user is logged in
|
||||
final routesLoggedIn = RouteMap(routes: {
|
||||
'/': (_) => const MaterialPage(child: HomePage()),
|
||||
'/new': (_) => const MaterialPage(child: NewRoomPage()),
|
||||
'/r/:server/:tag/:page?': (info) => MaterialPage(
|
||||
child: RoomPage(info.pathParameters['server'] ?? "",
|
||||
info.pathParameters['tag'] ?? "",
|
||||
page: info.pathParameters['page'] ?? ""),
|
||||
),
|
||||
'/r/:server/:tag/': (info) => MaterialPage(
|
||||
child: RoomPage(info.pathParameters['server'] ?? "",
|
||||
info.pathParameters['tag'] ?? "",
|
||||
page: 'list'),
|
||||
),
|
||||
}, onUnknownRoute: (_) => const Redirect('/'));
|
||||
|
||||
void main() {
|
||||
WidgetsFlutterBinding.ensureInitialized();
|
||||
|
@ -39,7 +46,10 @@ class OutbagApp extends StatefulWidget {
|
|||
}
|
||||
|
||||
class _OutbagAppState extends State {
|
||||
bool isAuthorized = false;
|
||||
// assume user is logged in
|
||||
// unless not userdata is found
|
||||
// or the userdata turns out to be wrong
|
||||
bool isAuthorized = true;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
|
@ -49,8 +59,18 @@ class _OutbagAppState extends State {
|
|||
// with existing details
|
||||
|
||||
(() async {
|
||||
User credentials;
|
||||
try {
|
||||
credentials = await User.fromDisk();
|
||||
} catch (_) {
|
||||
// invalid credentials
|
||||
// log out
|
||||
setState(() {
|
||||
isAuthorized = false;
|
||||
});
|
||||
return;
|
||||
}
|
||||
try {
|
||||
final credentials = await LoginDetails.fromDisk();
|
||||
final resp = await postUnauthorized(
|
||||
target: credentials.server,
|
||||
path: 'signin',
|
||||
|
@ -63,6 +83,12 @@ class _OutbagAppState extends State {
|
|||
setState(() {
|
||||
isAuthorized = true;
|
||||
});
|
||||
} else {
|
||||
// credentials are wrong
|
||||
// log out
|
||||
setState(() {
|
||||
isAuthorized = true;
|
||||
});
|
||||
}
|
||||
} catch (_) {
|
||||
// user is currently offline
|
||||
|
@ -76,11 +102,9 @@ class _OutbagAppState extends State {
|
|||
})();
|
||||
|
||||
// wait for user to be authorized
|
||||
final db = Localstore.instance;
|
||||
final stream = db.collection('meta').stream;
|
||||
stream.listen((data) async {
|
||||
User.listen((data) async {
|
||||
try {
|
||||
await LoginDetails.fromDisk();
|
||||
await User.fromDisk();
|
||||
setState(() {
|
||||
isAuthorized = true;
|
||||
});
|
||||
|
|
Loading…
Reference in a new issue