Compare commits

..

No commits in common. "e4f59dadfb4240ccf1ef6122b2630c3cf629a543" and "5b09333f0dd5f84a2333ff110ca3c645bbca3c2c" have entirely different histories.

9 changed files with 68 additions and 78 deletions

View File

@ -68,10 +68,9 @@ namespace {
{"decryption failed"}); {"decryption failed"});
} }
return { return std::string(
buffer.begin(), buffer.begin(),
std::next(buffer.begin(), static_cast<std::int64_t>(size)), std::next(buffer.begin(), static_cast<std::int64_t>(size)));
};
} }
[[nodiscard]] auto decrypt_value(const repertory::ui::mgmt_app_config *config, [[nodiscard]] auto decrypt_value(const repertory::ui::mgmt_app_config *config,
@ -154,10 +153,7 @@ handlers::handlers(mgmt_app_config *config, httplib::Server *server)
} }
res.set_content(data.dump(), "application/json"); res.set_content(data.dump(), "application/json");
res.status = utils::string::ends_with(data["error"].get<std::string>(), res.status = http_error_codes::internal_error;
"|decryption failed")
? http_error_codes::unauthorized
: http_error_codes::internal_error;
}); });
server->Get("/api/v1/mount", server->Get("/api/v1/mount",

View File

@ -15,8 +15,9 @@ const ringBufferSizeList = ['128', '256', '512', '1024', '2048'];
final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>(); final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();
Sodium? _sodium; Sodium? _sodium;
void setSodium(Sodium sodium) { void setSodium(Sodium sodium) {
_sodium = sodium; _sodium = sodium;
} }
Sodium get sodium => _sodium!; Sodium? get sodium => _sodium;

View File

@ -285,6 +285,10 @@ String encryptValue(String value, SecureKey key) {
} }
final sodium = constants.sodium; final sodium = constants.sodium;
if (sodium == null) {
return value;
}
final crypto = sodium.crypto.aeadXChaCha20Poly1305IETF; final crypto = sodium.crypto.aeadXChaCha20Poly1305IETF;
final nonce = sodium.secureRandom(crypto.nonceBytes).extractBytes(); final nonce = sodium.secureRandom(crypto.nonceBytes).extractBytes();
@ -298,6 +302,45 @@ String encryptValue(String value, SecureKey key) {
return hex.encode(nonce + data); return hex.encode(nonce + data);
} }
Future<String?> promptPassword() async {
if (constants.navigatorKey.currentContext == null) {
return null;
}
String password = '';
return await showDialog(
context: constants.navigatorKey.currentContext!,
builder: (context) {
return AlertDialog(
actions: [
TextButton(
child: const Text('Cancel'),
onPressed: () => Navigator.of(context).pop(null),
),
TextButton(
child: const Text('OK'),
onPressed: () {
if (password.isEmpty) {
return displayErrorMessage(context, "Password is not valid");
}
Navigator.of(context).pop(password);
},
),
],
content: TextField(
autofocus: true,
controller: TextEditingController(text: password),
obscureText: true,
obscuringCharacter: '*',
onChanged: (value) => password = value,
),
title: const Text('Enter Repertory Portal Password'),
);
},
);
}
Map<String, dynamic> getChanged( Map<String, dynamic> getChanged(
Map<String, dynamic> original, Map<String, dynamic> original,
Map<String, dynamic> updated, Map<String, dynamic> updated,

View File

@ -62,7 +62,7 @@ class _MyAppState extends State<MyApp> {
snackBarTheme: snackBarTheme, snackBarTheme: snackBarTheme,
), ),
title: constants.appTitle, title: constants.appTitle,
initialRoute: '/auth', initialRoute: '/',
routes: { routes: {
'/': '/':
(context) => (context) =>
@ -108,14 +108,7 @@ class AuthCheck extends StatelessWidget {
return Consumer<Auth>( return Consumer<Auth>(
builder: (context, auth, __) { builder: (context, auth, __) {
if (!auth.authenticated) { if (!auth.authenticated) {
Future.delayed(Duration(milliseconds: 1), () { Navigator.of(context).pushReplacementNamed('/auth');
if (constants.navigatorKey.currentContext == null) {
return;
}
Navigator.of(
constants.navigatorKey.currentContext!,
).pushNamedAndRemoveUntil('/auth', (Route<dynamic> route) => false);
});
return SizedBox.shrink(); return SizedBox.shrink();
} }

View File

@ -9,14 +9,17 @@ import 'package:sodium_libs/sodium_libs.dart';
class Auth with ChangeNotifier { class Auth with ChangeNotifier {
bool _authenticated = false; bool _authenticated = false;
SecureKey _key = SecureKey.random(constants.sodium, 32); SecureKey? _key;
String _user = ""; String _user = "";
bool get authenticated => _authenticated; bool get authenticated => _authenticated;
SecureKey get key => _key; SecureKey get key => _key!;
Future<void> authenticate(String user, String password) async { Future<void> authenticate(String user, String password) async {
final sodium = constants.sodium; final sodium = constants.sodium;
if (sodium == null) {
return;
}
final keyHash = sodium.crypto.genericHash( final keyHash = sodium.crypto.genericHash(
outLen: sodium.crypto.aeadXChaCha20Poly1305IETF.keyBytes, outLen: sodium.crypto.aeadXChaCha20Poly1305IETF.keyBytes,
@ -37,11 +40,11 @@ class Auth with ChangeNotifier {
); );
if (response.statusCode != 200) { if (response.statusCode != 200) {
logoff();
return ""; return "";
} }
final nonce = jsonDecode(response.body)["nonce"]; final nonce = jsonDecode(response.body)["nonce"];
debugPrint('nonce: $nonce');
return encryptValue('${_user}_$nonce', key); return encryptValue('${_user}_$nonce', key);
} catch (e) { } catch (e) {
debugPrint('$e'); debugPrint('$e');
@ -49,11 +52,4 @@ class Auth with ChangeNotifier {
return ""; return "";
} }
void logoff() {
_authenticated = false;
_user = "";
notifyListeners();
}
} }

View File

@ -40,11 +40,6 @@ class Mount with ChangeNotifier {
), ),
); );
if (response.statusCode == 401) {
_auth.logoff();
return;
}
if (response.statusCode == 404) { if (response.statusCode == 404) {
_mountList?.reset(); _mountList?.reset();
return; return;
@ -76,11 +71,6 @@ class Mount with ChangeNotifier {
), ),
); );
if (response.statusCode == 401) {
_auth.logoff();
return;
}
if (response.statusCode == 404) { if (response.statusCode == 404) {
_mountList?.reset(); _mountList?.reset();
return; return;
@ -112,11 +102,6 @@ class Mount with ChangeNotifier {
), ),
); );
if (response.statusCode == 401) {
_auth.logoff();
return null;
}
if (response.statusCode != 200) { if (response.statusCode != 200) {
return null; return null;
} }
@ -151,12 +136,6 @@ class Mount with ChangeNotifier {
), ),
); );
if (response.statusCode == 401) {
displayAuthError();
_auth.logoff();
return false;
}
if (response.statusCode == 404) { if (response.statusCode == 404) {
_isMounting = false; _isMounting = false;
_mountList?.reset(); _mountList?.reset();
@ -205,13 +184,13 @@ class Mount with ChangeNotifier {
), ),
); );
if (response.statusCode == 401) { if (response.statusCode == 404) {
_auth.logoff(); _mountList?.reset();
return; return;
} }
if (response.statusCode == 404) { if (response.statusCode == 500) {
_mountList?.reset(); displayAuthError();
return; return;
} }

View File

@ -14,11 +14,7 @@ class MountList with ChangeNotifier {
final Auth _auth; final Auth _auth;
MountList(this._auth) { MountList(this._auth) {
_auth.addListener(() { _fetch();
if (_auth.authenticated) {
_fetch();
}
});
} }
List<Mount> _mountList = []; List<Mount> _mountList = [];
@ -60,12 +56,6 @@ class MountList with ChangeNotifier {
Uri.parse('${getBaseUri()}/api/v1/mount_list?auth=$auth'), Uri.parse('${getBaseUri()}/api/v1/mount_list?auth=$auth'),
); );
if (response.statusCode == 401) {
displayAuthError();
_auth.logoff();
return;
}
if (response.statusCode == 404) { if (response.statusCode == 404) {
reset(); reset();
return; return;
@ -143,13 +133,12 @@ class MountList with ChangeNotifier {
case 200: case 200:
ret = true; ret = true;
break; break;
case 401:
displayAuthError();
_auth.logoff();
break;
case 404: case 404:
reset(); reset();
break; break;
case 500:
displayAuthError();
break;
default: default:
displayError(); displayError();
break; break;

View File

@ -43,17 +43,11 @@ class _EditSettingsScreenState extends State<EditSettingsScreen> {
Future<Map<String, dynamic>> _grabSettings() async { Future<Map<String, dynamic>> _grabSettings() async {
try { try {
final authProvider = Provider.of<Auth>(context, listen: false); final auth = await Provider.of<Auth>(context, listen: false).createAuth();
final auth = await authProvider.createAuth();
final response = await http.get( final response = await http.get(
Uri.parse('${getBaseUri()}/api/v1/settings?auth=$auth'), Uri.parse('${getBaseUri()}/api/v1/settings?auth=$auth'),
); );
if (response.statusCode == 401) {
authProvider.logoff();
return {};
}
if (response.statusCode != 200) { if (response.statusCode != 200) {
return {}; return {};
} }

View File

@ -117,18 +117,17 @@ class _UISettingsWidgetState extends State<UISettingsWidget> {
), ),
), ),
); );
if (response.statusCode == 500) {
if (response.statusCode == 401) {
displayAuthError(); displayAuthError();
authProvider.logoff();
return;
} }
} catch (e) { } catch (e) {
debugPrint('$e'); debugPrint('$e');
displayAuthError();
} }
}) })
.catchError((e) { .catchError((e) {
debugPrint('$e'); debugPrint('$e');
displayAuthError();
}); });
} }