Browse Source

nextcloud,neon: Fix login and user name mess

pull/149/head
jld3103 2 years ago
parent
commit
0b0181fd06
No known key found for this signature in database
GPG Key ID: 9062417B9E8EB7B3
  1. 12
      packages/neon/integration_test/screenshot_test.dart
  2. 1
      packages/neon/lib/main.dart
  3. 7
      packages/neon/lib/src/blocs/accounts.dart
  4. 2
      packages/neon/lib/src/blocs/push_notifications.dart
  5. 60
      packages/neon/lib/src/models/account.dart
  6. 6
      packages/neon/lib/src/models/account.g.dart
  7. 51
      packages/neon/lib/src/pages/login.dart
  8. 15
      packages/nextcloud/lib/src/client.dart
  9. 2
      packages/nextcloud/test/helper.dart

12
packages/neon/integration_test/screenshot_test.dart

@ -119,7 +119,6 @@ Future pumpAppPage(
AppStorage('accounts', sharedPreferences),
sharedPreferences,
globalOptions,
packageInfo,
allAppImplementations,
);
if (account != null) {
@ -227,9 +226,10 @@ Future main() async {
packageInfo = await PackageInfo.fromPlatform();
account = Account(
serverURL: 'http://10.0.2.2',
loginName: 'user1',
username: 'user1',
password: 'user1',
)..setupClient(packageInfo);
);
await SystemChrome.setEnabledSystemUIMode(SystemUiMode.manual, overlays: []);
});
@ -462,14 +462,12 @@ Future main() async {
});
testWidgets('notifications', (final tester) async {
await (Account(
await Account(
serverURL: 'http://10.0.2.2',
loginName: 'admin',
username: 'admin',
password: 'admin',
)..setupClient(packageInfo))
.client
.notifications
.sendAdminNotification(
).client.notifications.sendAdminNotification(
userId: account.username,
shortMessage: 'Notifications demo',
longMessage: 'This is a notifications demo of the Neon app',

1
packages/neon/lib/main.dart

@ -46,7 +46,6 @@ Future main() async {
AppStorage('accounts', sharedPreferences),
sharedPreferences,
globalOptions,
packageInfo,
allAppImplementations,
);
final pushNotificationsBloc = PushNotificationsBloc(

7
packages/neon/lib/src/blocs/accounts.dart

@ -7,7 +7,6 @@ import 'package:neon/src/blocs/user_details.dart';
import 'package:neon/src/blocs/user_status.dart';
import 'package:neon/src/models/account.dart';
import 'package:neon/src/neon.dart';
import 'package:package_info_plus/package_info_plus.dart';
import 'package:rxdart/rxdart.dart';
import 'package:shared_preferences/shared_preferences.dart';
@ -30,7 +29,6 @@ class AccountsBloc extends Bloc implements AccountsBlocEvents, AccountsBlocState
this._storage,
this._sharedPreferences,
this._globalOptions,
this._packageInfo,
this._allAppImplementations,
) {
accounts.listen((final as) async {
@ -42,7 +40,7 @@ class AccountsBloc extends Bloc implements AccountsBlocEvents, AccountsBlocState
accounts.add(
_storage
.getStringList(_keyAccounts)!
.map((final a) => (Account.fromJson(json.decode(a) as Map<String, dynamic>))..setupClient(_packageInfo))
.map((final a) => Account.fromJson(json.decode(a) as Map<String, dynamic>))
.toList(),
);
}
@ -69,7 +67,6 @@ class AccountsBloc extends Bloc implements AccountsBlocEvents, AccountsBlocState
final SharedPreferences _sharedPreferences;
final GlobalOptions _globalOptions;
final List<AppImplementation> _allAppImplementations;
final PackageInfo _packageInfo;
final _keyAccounts = 'accounts';
final _keyLastUsedAccount = 'last-used-account';
@ -102,7 +99,6 @@ class AccountsBloc extends Bloc implements AccountsBlocEvents, AccountsBlocState
@override
void addAccount(final Account account) {
account.setupClient(_packageInfo);
if (activeAccount.valueOrNull == null) {
setActiveAccount(account);
}
@ -140,7 +136,6 @@ class AccountsBloc extends Bloc implements AccountsBlocEvents, AccountsBlocState
@override
void updateAccount(final Account account) {
account.setupClient(_packageInfo);
final as = accounts.value;
final index = as.indexWhere((final a) => a.id == account.id);
if (index == -1) {

2
packages/neon/lib/src/blocs/push_notifications.dart

@ -134,7 +134,7 @@ class PushNotificationsBloc extends Bloc implements PushNotificationsBlocEvents,
Future _registerUnifiedPushInstances(final List<Account> accounts) async {
// Notifications will only work on accounts with app password
for (final account in accounts.where((final a) => a.appPassword != null)) {
for (final account in accounts.where((final a) => a.password != null)) {
await UnifiedPush.registerApp(account.client.id);
}
}

60
packages/neon/lib/src/models/account.dart

@ -7,6 +7,29 @@ import 'package:package_info_plus/package_info_plus.dart';
part 'account.g.dart';
Future<Account> getAccount(
final PackageInfo packageInfo,
final String serverURL,
final String loginName,
final String password,
) async {
final username = (await NextcloudClient(
serverURL,
loginName: loginName,
password: password,
).provisioningApi.getCurrentUser())
.ocs
.data
.id;
return Account(
serverURL: serverURL,
loginName: loginName,
username: username,
password: password,
userAgent: userAgent(packageInfo),
);
}
String userAgent(final PackageInfo packageInfo) {
var buildNumber = packageInfo.buildNumber;
if (buildNumber == '') {
@ -19,30 +42,30 @@ String userAgent(final PackageInfo packageInfo) {
class Account {
Account({
required this.serverURL,
required this.loginName,
required this.username,
this.password,
this.appPassword,
}) : assert(
(password != null && appPassword == null) || (password == null && appPassword != null),
'Either password or appPassword has to be set',
);
this.userAgent,
});
factory Account.fromJson(final Map<String, dynamic> json) => _$AccountFromJson(json);
Map<String, dynamic> toJson() => _$AccountToJson(this);
final String serverURL;
final String loginName;
final String username;
final String? password;
final String? appPassword;
final String? userAgent;
@override
// ignore: avoid_equals_and_hash_code_on_mutable_classes
bool operator ==(final Object other) =>
other is Account &&
other.serverURL == serverURL &&
other.loginName == loginName &&
other.username == username &&
other.password == password &&
other.appPassword == appPassword;
other.userAgent == userAgent;
@override
// ignore: avoid_equals_and_hash_code_on_mutable_classes
@ -52,22 +75,13 @@ class Account {
NextcloudClient? _client;
void setupClient(final PackageInfo packageInfo) {
_client ??= NextcloudClient(
serverURL,
username: username,
password: appPassword ?? password,
userAgentOverride: userAgent(packageInfo),
);
}
NextcloudClient get client {
if (_client == null) {
throw Exception('You need to call setupClient() first');
}
return _client!;
}
NextcloudClient get client => _client ??= NextcloudClient(
serverURL,
loginName: loginName,
username: username,
password: password,
userAgentOverride: userAgent,
);
}
Map<String, String> _idCache = {};

6
packages/neon/lib/src/models/account.g.dart

@ -8,14 +8,16 @@ part of 'account.dart';
Account _$AccountFromJson(Map<String, dynamic> json) => Account(
serverURL: json['serverURL'] as String,
loginName: json['loginName'] as String,
username: json['username'] as String,
password: json['password'] as String?,
appPassword: json['appPassword'] as String?,
userAgent: json['userAgent'] as String?,
);
Map<String, dynamic> _$AccountToJson(Account instance) => <String, dynamic>{
'serverURL': instance.serverURL,
'loginName': instance.loginName,
'username': instance.username,
'password': instance.password,
'appPassword': instance.appPassword,
'userAgent': instance.userAgent,
};

51
packages/neon/lib/src/pages/login.dart

@ -48,31 +48,38 @@ class _LoginPageState extends State<LoginPage> {
_loginBloc.loginFlowResult.listen((final result) async {
if (result != null) {
final account = Account(
serverURL: result.server,
username: result.loginName,
appPassword: result.appPassword,
)..setupClient(await PackageInfo.fromPlatform());
if (!mounted) {
return;
}
try {
final account = await getAccount(
_packageInfo,
result.server,
result.loginName,
result.appPassword,
);
if (!mounted) {
return;
}
final accountsBloc = Provider.of<AccountsBloc>(context, listen: false);
if (widget.serverURL != null) {
accountsBloc.updateAccount(account);
Navigator.of(context).pop();
} else {
for (final a in accountsBloc.accounts.value) {
if (a.id == account.id) {
ExceptionWidget.showSnackbar(context, AppLocalizations.of(context).errorAccountAlreadyExists);
await _loginBloc.refresh();
return;
if (widget.serverURL != null) {
_accountsBloc.updateAccount(account);
Navigator.of(context).pop();
} else {
for (final a in _accountsBloc.accounts.value) {
if (a.id == account.id) {
ExceptionWidget.showSnackbar(context, AppLocalizations.of(context).errorAccountAlreadyExists);
await _loginBloc.refresh();
return;
}
}
_accountsBloc
..addAccount(account)
..setActiveAccount(account);
}
accountsBloc
..addAccount(account)
..setActiveAccount(account);
} catch (e, s) {
debugPrint(e.toString());
debugPrint(s.toString());
ExceptionWidget.showSnackbar(context, e);
await _loginBloc.refresh();
}
}
});

15
packages/nextcloud/lib/src/client.dart

@ -5,6 +5,7 @@ class NextcloudClient extends Client {
// ignore: public_member_api_docs
NextcloudClient(
super.baseURL, {
this.loginName,
this.username,
final String? password,
final String? language,
@ -19,20 +20,24 @@ class NextcloudClient extends Client {
}..removeWhere((final _, final value) => value == null))
.cast<String, String>(),
userAgent: userAgentOverride ?? appType.userAgent,
authentication: username != null && password != null
authentication: loginName != null && password != null
? HttpBasicAuthentication(
username: username,
username: loginName,
password: password,
)
: null,
);
/// Username used for all operations. Necessary for accessing WebDAV resources
/// Identifier used for authentication. This can be the username or email or something else.
final String? loginName;
/// Username of the user on the server, it needs to be set for using WebDAV.
/// It can be obtained via the provisioning_api.
final String? username;
WebDavClient? _webdav;
/// Client for WebDAV. Will be null if no username is set for the client
/// Client for WebDAV. Username needs to be set in order to use it
WebDavClient get webdav {
if (_webdav != null) {
return _webdav!;
@ -43,7 +48,7 @@ class NextcloudClient extends Client {
return _webdav = WebDavClient(
this,
'/remote.php/dav/files/${(super.authentication! as HttpBasicAuthentication).username}',
'/remote.php/dav/files/$username',
);
}
}

2
packages/nextcloud/test/helper.dart

@ -86,6 +86,7 @@ class DockerContainer {
class TestNextcloudClient extends NextcloudClient {
TestNextcloudClient(
super.baseURL, {
super.loginName,
super.username,
super.password,
super.language,
@ -135,6 +136,7 @@ Future<TestNextcloudClient> getTestClient(
final client = TestNextcloudClient(
'http://localhost:${container.port}',
loginName: username,
username: username,
password: clientPassword,
appType: appType,

Loading…
Cancel
Save