Why can't i access my s3 objects in amplify flutter? - flutter

Message displayed on chrome
Function to get the S3 URL
Future<String> getUrlS3(String UploadKey) async {
try {
GetUrlResult result =
await Amplify.Storage.getUrl(key: UploadKey);
return(result.url);
} on StorageException catch (e) {
return(e.message);
}
}
Function to get url
Future<void> cet() async {
String store = await S3Helper.getUrlS3('cover807c3f99-2bcb-44e3-be80-4899ea2355d8Attac');
print(store);
}
When I click on the link I get the access denied page.
The only way i can see the Objects are if i make the specific object public, also i am logged in via Auth Cognito so i should have the permissions to view them

I think you need to pass accesslevel option to your getUrlS3.
something like this
S3DownloadFileOptions options = S3UploadFileOptions(
accessLevel: StorageAccessLevel.protected,
metadata: metadata,
);

Related

AWS Cognito deleteUser in flutter not working

I am trying to implement deleteUser function in cognito which allows the user to delete their own account information by using this code
void deleteUser() async {
try {
await Amplify.Auth.deleteUser();
final state = AuthState(authFlowStatus: AuthFlowStatus.none);
authStateController.add(state);
print('Delete user succeeded');
} on AmplifyException catch (e) {
print('Delete user failed with error: $e');
}
}
However, this code of course is not working for some reason and I don't know why. I also have the user's database in Amplify datastore graphql so I tried deleting the user's datastore data first before getting rid of the user's congnito data but it still does not work. This is the code that I am using to delete user's data from datastore. Please help me out by telling me how I can delete a user's cognito and datastore data.
void deleteUser (DeleteUserData data) async {
(await Amplify.DataStore.query(User.classType, where: User.EMAIL.eq(data.email)))
.forEach((element) async {
try {
await Amplify.DataStore.delete(element);
print('Deleted a user');
} on DataStoreException catch (e) {
print('Delete failed: $e');
}
});
}
Please help me out.
I was facing the same problem, I took a look into the insides of deleteUser method in the AWS api, something I strongly recommend, and I discovered that this API is only available in iOS.
screenshot
I was using amplify_auth_cognito: 0.4.5 and amplify_flutter: 0.4.5.
Upgraded the libraries to 0.5.1 and the warning has disappeared, maybe you can try using a different version of yours (I'm not using Amplify, just simple Cognito).
Cheers.

Flutter: Google cloud storage not giving me access despite my rules

I have looked through every tutorial and the steps in retrieving the directories are more or less the same however I hit a snag and there doesn't seem to be anyone encountering this. So in my application, I have a button that calls a function
onPressed: () async {
isListing
? _showMyDialog()
: setState(() {
isListing = !isListing;
});
try {
directories=await firebaseAPI.list(
'${widget.level}/${widget.value}');
setState(() {
isListing = !isListing;
prefs.setBool('isInitialized', true);
});
_showNotification();
prefs.setBool('isInitialized', true);
Navigator.pushNamedAndRemoveUntil(
context, Dashboard.id, (route) => false);
} catch (error) {}
}
And here's the code for the list function
Future<firebase_storage.ListResult> downloadFiles(url) async {
final ref =
firebase_storage.FirebaseStorage.instance.ref(url);
final result = await ref.listAll();
print(result);
return result;
}
The function gets called but doesn't print or return anything it just gives me this:
W/NetworkRequest(13843): no auth token for request
W/StorageUtil(13843): no auth token for request
W/NetworkRequest(13843): No App Check token for request.
Which I don't get since I changed my rules to this:
rules_version = '2';
service firebase.storage {
match /b/{bucket}/o {
match /{allPaths=**} {
allow read, allow write: if true;
}
}
}
Do I have to change the rules further? or is there a different way of accessing google cloud storage?
I figured it out. I just did a cold boot of my emulator and now it's able to access it
Firestore storage needs authentication in order to upload data, so you need to use firebase_auth or you need to change the rules to: allow read, write;

How to pass ACL properties to flutter amplify while uploading file to S3?

Or How to upload an image to s3 with public access by Flutter Amplify?
In my current flutter project, I can't pass ACL:public-read property while uploading files to S3 using amplify.
And because of this, whenever I'm uploading a new file to s3, I need to make it public manually.
So I just want to upload a new file with public read access for everyone.
I found some solutions for the Javascript project but not in the Flutter project.
Below is a method, I'm using to upload.
Future<String> uploadFile(String fileName, File local) async {
try {
Map<String, String> metadata = <String, String>{};
metadata['name'] = 'filename';
metadata['desc'] = 'A file';
S3UploadFileOptions options = S3UploadFileOptions(accessLevel: StorageAccessLevel.guest, metadata: metadata);
UploadFileResult result = await Amplify.Storage.uploadFile(key: fileName, local: local, options: options);
return result.key;
} catch (e) {
print('UploadFile Err: ' + e.toString());
}
return null;
}
I think you should be using Dio for declaring the client object that will be used for posting the request
You can find an example code in the following answer
So far Flutter Amplify is not giving any option to upload images with public access.
It always uploads with private read access.
So I updated a few things in my project as described below.
Before Amplify integration I was uploading images to S3 and storing that URL to my server, and wherever I have to display, I'm just fetching URL from my server and loading images.
But now I'm storing key(that is used to upload images to S3 by Amplify) to my server.
And to display the image I'm getting the image URL from Amplify using that key(which is stored in my server).
Amplify adds a token to the image URL with a default validity of 7 days
Future<String> getUrl(String key) async {
try {
S3GetUrlOptions options = S3GetUrlOptions(accessLevel: StorageAccessLevel.guest, expires: 10000);
GetUrlResult result = await Amplify.Storage.getUrl(key: key, options: options);
String url = result.url;
return url;
} catch (e) {
print('GetUrl Err: ' + e.toString());
}
return null;
}
So it can be displayed by ImageView.

How can I catch errors in my firebase function when setting a document fails?

I have a firebase cloud function to create a user document with user data whenever a user registers. How would I return an error when the set() fails? Since this is not an http request (an I don't want to use an http request in this case) I have no response. So how would I catch errors?
export const onUserCreated = functions.region('europe-west1').auth.user().onCreate(async user => {
const privateUserData = {
phoneNumber: user.phoneNumber
}
const publicUserData = {
name: 'Nameless'
}
try
{
await firestore.doc('users').collection('private').doc('data').set(privateUserData);
}catch(error)
{
//What do I put here?
}
try
{
await firestore.doc('users').collection('public').doc('data').set(publicUserData);
}catch(error)
{
//What do I put here?
}
});
You can't "return" an error, since the client doesn't even "know" about this function running, there is nobody to respond to.
You can make a registration collection, and in your function make a document there for the current user (using the uid as the document id). In that document, you can put any information you'd like your user to know (status, errors, etc).
So your clients would have to add a listener to this document to learn about their registration.
In your particular code, I think the error is in doc('users'). I guess you meant doc('users/'+user.uid).
Your catch -block will receive errors that occur on your set -call:
try {
await firestore.doc('users').collection('public').doc('data').set(publicUserData);
} catch (error) {
// here you have the error info.
}

Using Navigator without context

I have a class that wraps http calls (get, post, delete).
What I need to achieve is a way to check every api response to be able to force a logout if, for example, a token is expired.
Let's say I'm logged in my app and my token expires; I then try to list my posts with a call like this:
var results = api.get('http://api.site.com/user/123/posts')
get(String endpoint) async {
return http.get(endpoint,
headers: headers(),
).then((response) {
var result = json.decode(response.body);
if (result['force_logout'] == true) {
UserServices.logout(); // delete secure storage data and other stuff
Navigator.of(context).pushNamedAndRemoveUntil('/login', (Route<dynamic> route) => false);
}
return result;
});
}
Inside my api get method I would like to be able to perform the user logout and navigate to the login screen, but how can I do it without having a context?