I have created clients, restaurants and favorites tables in supabase and linked them using foreign keys, I want to list a client's favorite restaurant if any and also insert favorite restaurants when the client clicks on the favorite icon.
The created schema looks like this
clients
client_id uuid(pk),
name text,
email text,
avatar text,
points float4,
favorite_id uuid(fk),
restaurants
restaurant_id uuid(pk),
name text,
description text,
logo text,
location text,
menu json,
favorites
favorite_id uuid(pk),
created_at now(),
client_id uuid(fk),
restaurant_id uuid(fk),
For inserting a favorite restaurant to a client
final res = await supabase.client
.from('favorites')
.insert({
'client_id': user.id,
'restaurant_id': res.id
})
.execute();
///Which works fine
For querying a favorite restaurant of a client
final res = await supabase.client
.from('restaurants')
.select('*, favorites!inner(*)')
.eq('client_id ', user.id);
///Doesn't work at all`
The following should work!
final res = await supabase.client
.from('clients')
.select('*, restaurants(*)')
.eq('client_id ', user.id);
Related
I have a very strange problem that is driving we up the walls.
I am creating the following table
CREATE TABLE articles(
id BIGINT generated by default as IDENTITY PRIMARY KEY,
user_id uuid references auth.users NOT NULL,
title TEXT,
CONTENT TEXT,
user_email TEXT,
inserted_at TIMESTAMP WITH TIME ZONE DEFAULT timezone('utc'::TEXT,NOW()) NOT NULL
);
ALTER TABLE articles ENABLE ROW LEVEL SECURITY;
CREATE policy "users can create articles" ON articles for
INSERT WITH CHECK(auth.uid() = user_id);
CREATE policy "users can update their own articles" ON articles for
UPDATE USING (auth.uid() = user_id);
CREATE policy "users can delete their own articles" ON articles for
DELETE USING (auth.uid() = user_id);
CREATE policy "users can read their own articles" ON articles for
SELECT USING (auth.uid() = user_id);
I can add data to it through my front-end with:
const { data, error } = await supabaseClient.from("articles").insert(
[{
title: title,
content: content,
user_email: user?.email?.toLowerCase(),
user_id: user?.id,
}]
).single()
and that works. I can verify on supabase that the row has indeed been added.
However, I can't access my data through the front-end since the expression:
auth.uid() = user_id seems to evaluate to false even though it is the same. If I disable Row level security or write TRUE instead everything works as intended.
New to flutter, and first post here!
I am building a mobile app with flutter, using Firebase and Cloud Firestore. Each user, when authenticated (by email and password), is also currently then added to a 'users' collection in Firestore - like this:
sign up method:
Future signUp() async {
if (passwordConfirmed()) {
await FirebaseAuth.instance.createUserWithEmailAndPassword(
email: _emailController.text.trim(),
password: _passwordController.text.trim(),
);
// add user details
addUserDetails(
_firstNameController.text.trim(),
_lastNameController.text.trim(),
_emailController.text.trim(),
_baseStationController.text.trim(),
);
}
}
Future addUserDetails(String firstName, String lastName, String email,
String baseStation) async {
await FirebaseFirestore.instance.collection('users').add({
'first name': firstName,
'last name': lastName,
'email': email,
'base station': baseStation,
});
}
The signup() method is called when they input their information into text fields within a form, and click a button. This works successfully, and my user collection receives the data, and sign in/out works as it should.
Those users have a 'base station' (which is stored as a field within that users document in Firestore) which is their place of work. I want to show a welcome screen when they log in, so that the current users 'base station' is displayed.
I can access their email address using:
final thisUser = FirebaseAuth.instance.currentUser!;
and then for example to show this when they log in:
Text('Hello, ${thisUser.email!}')
this works no problem, however...
I can't work out how their authentication then links to the collection, so I want to show the 'base station' for the 'currentUser' for example when they log in (I don't want them to have to select their base station every time from a picker when they've already provided the information on sign up.
As an aside - I can also (separately) successfully read the data from the collection and (for example) create a listView builder with the users collection information, but this is for all users, and not specifically the 'currentUser' that is logged in.
All help gratefully received, apologies if I have missed anything.
update addUserDetails as follows
Future addUserDetails(String firstName, String lastName, String email,
String baseStation) async {
await FirebaseFirestore.instance.collection('users').doc(FirebaseAuth.instance.currentUser!.uid).set({
'first name': firstName,
'last name': lastName,
'email': email,
'base station': baseStation,
});
if you then want to get specific user detail then use the code as follows
final user = await FirebaseFirestore.instance.collection('users').doc(FirebaseAuth.instance.currentUser!.uid).get();
So my comments are getting added to the correct post when the comment is made by the author on their own post, like so
The Firestore code updated test:
Future<String> postComment(String postId, String text, String authorId,
String name, String profilePic) async {
String res = 'Some Error occurred';
try {
if (text.isNotEmpty) {
String commentId = const Uuid().v1();
await FirebaseFirestore.instance
.collection('posts')
.doc(authorId)
.collection('userPosts')
.doc(postId)
.collection('comments')
.doc(commentId)
.set({
'profilePic': profilePic,
'name': name,
'uid': authorId,
'text': text,
'commentId': commentId,
'datePublished': DateTime.now()
});
res = 'success';
}
} catch (e) {
res = e.toString();
}
return res;
}
The desired structure of how the comments should get added: posts>UID(of poster)> userPosts(List of their posts)>postID>append comment to this postId as a subcollection.
Now, when I try to create a comment on a post made by another user, a new collection gets started with the ID of the post as its collection name. The postId it gets is the CORRECT id, however, the actual comment itself doesn't get added to the collection of THAT post. As you can see from the circle in the second image, the IDs match, however, the comment made doesn't go where it's intended, as it does in the first image. Does anyone know how I can fix this?
Image with new code test, new collection gets made with the UID of the person who's post I am commenting on, doesn't get added to the subcollection of the actual postId
When you're using the following reference:
await FirebaseFirestore.instance
.collection('posts')
.doc(uid)
.collection('userPosts')
.doc(postId)
.collection('comments')
.doc(commentId)
You're always trying to add data inside a document that corresponds to the currently authenticated user. That's the reason why when you are using the above code with another user, it writes the data to another location. Which location, the one that corresponds to that user.
If you want to write the data under a particular location, you have to create a reference that points to that particular location. For instance, if you want a user to write some data, in a document that corresponds to another user, you have to create a reference that contains that UID. That can be simply done, by adding the ID of the user who creates the post inside the document. In that way, doesn't matter which user reads the post, when you want to write the data, you can use the ID of the user who created the post, to construct the correct path.
I want to create multiple tables in sqflite by calling the same function, cause I want to create multiple playlists, playlist name will be the table name, which came from user input,
for this reason, users call the databaseCreate function in multiple time. But its show some error :
Unhandled Exception: DatabaseException(no such table: sports (code 1
SQLITE_ERROR): , while compiling: INSERT INTO sports (title, link, logo,
playlistName) VALUES (?, ?, NULL, ?)) sql 'INSERT INTO sports (title, link, logo,
playlistName)
Database Create Code :
Future open( String name) async {
Directory documentsDirectory = await getApplicationDocumentsDirectory();
final path = join(documentsDirectory.path, 'playlist1.db');
_database = await openDatabase(path, version: 2,
onCreate: (Database db, int version) async {
await db.execute('''
create table $name (
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,playlistName TEXT, link TEXT, title TEXT,
logo TEXT)
''');
});
}
Hare's name comes from the user. At a very fast time, it will be okay but for creating a second playlist it will be crashed
You should prefer use parameterized queries:
await db.execute("
create table ? (
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,playlistName TEXT, link TEXT, title TEXT,
logo TEXT)
", [name]);
UPDATE
If you need to update the database schema, you need to update the version of the database, like this:
return await openDatabase(
path,
version: 2, // <=== Update (increase) this number
onOpen: (db) {},
onCreate: createDatabase,
onUpgrade: upgradeDatabase,
);
Doing this, you ask SQFLite to update the schema. Use onUpgrade to tell the new schema.
You can also uninstall the app when you are in development stage. In this case, new schema should be in onCreate.
If i resume, onCreate is called once when database is created. And onUpgrade is called each time version is increased.
UPDATE 2
For unknown reasons (haven't search more), execute method does not replace the ? by parameter. Perharps for security reasons. In fact using dynamic table name is not a very good design.
So for achive this, you shoult not use parameterized query like i said previously. You should use a concatened string, like this:
await db.rawQuery(
"create table " +
name +
" ( id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,playlistName TEXT, link TEXT, title TEXT, logo TEXT)",[]);
I want to store documentID in my cloud_firestore_database using flutter. I have made a authentication for every User ,so that the data of every User can store individually.Data storing in database in the following way(Student entry => auth(UserId) => vault =>documentID(xj23yvbfvbnbjgkb) => User details)
// collection reference
CollectionReference vaultCollection = Firestore.instance.collection('student entry').document(uid).collection('vault');
vaultCollection.document().setData({
"Entry-time": date,
'image': url,
'fname': name,
'year': year,
'purpose': visiting,
'vehicleno': vehicleno,
'contact': contact,
'Exit-time': "unknown",
'docId'://How can i add documentID ?
});
Use the DocumentReference returned from document(). It contains the randomly generated id before the document is actually added.
DocumentReference doc = vaultCollection.document();
doc.setData({
...
'docId': doc.documentID
});