Skip to content

Commit 4b01772

Browse files
committed
Migrate loginIfRequired() and getKeyFromUserIfRequired() functions to SolidUI
1 parent eb8bd6f commit 4b01772

File tree

5 files changed

+191
-3
lines changed

5 files changed

+191
-3
lines changed

lib/solidui.dart

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,3 +98,6 @@ export 'src/screens/initial_setup_screen_body.dart';
9898
export 'src/screens/initial_setup_widgets/enc_key_input_form.dart';
9999
export 'src/screens/initial_setup_widgets/initial_setup_welcome.dart';
100100
export 'src/screens/initial_setup_widgets/res_create_form_submission.dart';
101+
102+
export 'src/utils/solid_pod_helpers.dart'
103+
show loginIfRequired, getKeyFromUserIfRequired;

lib/src/utils/solid_file_operations_download.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ import 'package:flutter/material.dart';
3535

3636
import 'package:file_picker/file_picker.dart';
3737
import 'package:solidpod/solidpod.dart';
38+
import 'package:solidui/src/utils/solid_pod_helpers.dart';
3839

3940
/// Download operations for SolidUI widgets.
4041
Lines changed: 185 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,185 @@
1+
/// Helper functions for Solid Pod operations requiring user interaction.
2+
///
3+
/// Copyright (C) 2025, Software Innovation Institute, ANU.
4+
///
5+
/// Licensed under the MIT License (the "License").
6+
///
7+
/// License: https://choosealicense.com/licenses/mit/.
8+
//
9+
// Permission is hereby granted, free of charge, to any person obtaining a copy
10+
// of this software and associated documentation files (the "Software"), to deal
11+
// in the Software without restriction, including without limitation the rights
12+
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13+
// copies of the Software, and to permit persons to whom the Software is
14+
// furnished to do so, subject to the following conditions:
15+
//
16+
// The above copyright notice and this permission notice shall be included in
17+
// all copies or substantial portions of the Software.
18+
//
19+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20+
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21+
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22+
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23+
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24+
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25+
// SOFTWARE.
26+
///
27+
/// Authors: Anushka Vidanage, Dawei Chen, Zheyuan Xu, Tony Chen
28+
29+
library;
30+
31+
import 'package:flutter/material.dart';
32+
33+
import 'package:flutter_form_builder/flutter_form_builder.dart';
34+
35+
import 'package:solidpod/solidpod.dart'
36+
show checkLoggedIn, getWebId, KeyManager, verifySecurityKey;
37+
import 'package:solidui/src/widgets/solid_popup_login.dart';
38+
39+
/// Check if the user is logged in and prompt for login if required.
40+
///
41+
/// This function checks whether the user is currently logged in to their
42+
/// Solid Pod. If not logged in, it displays a login dialog to prompt the
43+
/// user to authenticate.
44+
///
45+
/// [context] - The build context for displaying dialogs
46+
/// [child] - The child widget to return to after login
47+
///
48+
/// Returns `true` if the user is logged in or successfully logs in,
49+
/// `false` if the user cancels the login or login fails.
50+
51+
Future<bool> loginIfRequired(
52+
BuildContext context,
53+
Widget child,
54+
) async {
55+
if (await checkLoggedIn()) {
56+
return true;
57+
}
58+
59+
if (!context.mounted) return false;
60+
61+
// Show login popup dialog.
62+
63+
final result = await showDialog<bool>(
64+
context: context,
65+
barrierDismissible: false,
66+
builder: (dialogContext) => const SolidPopupLogin(),
67+
);
68+
69+
// Return whether the login was successful.
70+
71+
return result ?? false;
72+
}
73+
74+
/// Ask for the security key from the user if the security key is not available
75+
/// or cannot be verified using the verification key stored in Pods.
76+
///
77+
/// This function checks if a security key is already cached. If not, it prompts
78+
/// the user to enter their security key and verifies it against the verification
79+
/// key stored in their Pod.
80+
///
81+
/// [context] - The build context for displaying dialogs
82+
/// [child] - The child widget to return to after entering the key
83+
///
84+
/// Returns `true` if the security key is available or successfully entered,
85+
/// `false` if the user cancels the operation.
86+
87+
Future<bool> getKeyFromUserIfRequired(
88+
BuildContext context,
89+
Widget child,
90+
) async {
91+
if (await KeyManager.hasSecurityKey()) {
92+
return true;
93+
}
94+
95+
final verificationKey = await KeyManager.getVerificationKey();
96+
97+
// Get the webId to display in the security key prompt.
98+
99+
final webId = await getWebId();
100+
101+
if (!context.mounted) return false;
102+
103+
// Create a simple security key input dialog.
104+
105+
final keyController = TextEditingController();
106+
final formKey = GlobalKey<FormBuilderState>();
107+
108+
final result = await showDialog<bool>(
109+
context: context,
110+
barrierDismissible: false,
111+
builder: (dialogContext) => AlertDialog(
112+
title: const Text('Security Key Required'),
113+
content: Column(
114+
mainAxisSize: MainAxisSize.min,
115+
crossAxisAlignment: CrossAxisAlignment.start,
116+
children: [
117+
Text(
118+
'Currently logged in as:',
119+
style: Theme.of(dialogContext).textTheme.bodySmall,
120+
),
121+
const SizedBox(height: 4),
122+
Text(
123+
webId ?? 'Not logged in',
124+
style: Theme.of(dialogContext).textTheme.bodyMedium?.copyWith(
125+
color: webId != null ? Colors.green : Colors.red,
126+
fontWeight: FontWeight.bold,
127+
),
128+
),
129+
const SizedBox(height: 16),
130+
const Text(
131+
'Please enter your security key to access encrypted data:',
132+
),
133+
const SizedBox(height: 16),
134+
FormBuilder(
135+
key: formKey,
136+
child: FormBuilderTextField(
137+
name: 'security_key',
138+
controller: keyController,
139+
obscureText: true,
140+
decoration: const InputDecoration(
141+
labelText: 'Security Key',
142+
border: OutlineInputBorder(),
143+
),
144+
validator: (value) {
145+
if (value == null || value.isEmpty) {
146+
return 'Please enter a security key';
147+
}
148+
if (!verifySecurityKey(value, verificationKey)) {
149+
return 'Incorrect security key';
150+
}
151+
return null;
152+
},
153+
),
154+
),
155+
],
156+
),
157+
actions: [
158+
TextButton(
159+
onPressed: () {
160+
Navigator.pop(dialogContext, false);
161+
},
162+
child: const Text('Cancel'),
163+
),
164+
ElevatedButton(
165+
onPressed: () async {
166+
if (formKey.currentState?.saveAndValidate() ?? false) {
167+
final key = keyController.text;
168+
await KeyManager.setSecurityKey(key);
169+
if (dialogContext.mounted) {
170+
Navigator.pop(dialogContext, true);
171+
}
172+
}
173+
},
174+
child: const Text('Submit'),
175+
),
176+
],
177+
),
178+
);
179+
180+
keyController.dispose();
181+
182+
// Return whether the key was successfully entered.
183+
184+
return result ?? false;
185+
}

lib/src/widgets/solid_security_key_central_manager.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ import 'dart:async';
3333
import 'package:flutter/material.dart';
3434

3535
import 'package:solidpod/solidpod.dart';
36+
import 'package:solidui/src/utils/solid_pod_helpers.dart';
3637

3738
/// Central manager for security key operations to prevent duplicate prompts.
3839
///

pubspec.yaml

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,7 @@ dependencies:
2222
shared_preferences: ^2.3.3
2323
# solidpod: ^0.7.14
2424
solidpod:
25-
git:
26-
url: https://github.com/anusii/solidpod.git
27-
ref: dev
25+
path: ../solidpod
2826
url_launcher: ^6.3.1
2927
version_widget: ^1.0.6
3028

0 commit comments

Comments
 (0)