Accessing Collections - collections

Can i ask for help??
so i have this relationship with bank accounts + the user who can access it
return $this->belongsToMany('App\BankAccount', 'permissions', 'user_id',
'account_id');
and then ill pass it to my view
$view->with('access', User::where('id', $user->id)->with('bankAccounts')->get());
this is how i access it
#foreach($access as $account)
<li>{{ $account->bankAccounts }}</a></li>
#endforeach
it gives me this output
[{"id":1,"account_name":"MBTC Mambaling","type":"1","branch":"Mambaling","account_number":"331-7-331504366","contact_person":"Armand Dela Cruz","contact_number":null,"created_at":"2017-06-26 03:16:13","updated_at":"2017-06-26 03:16:13","pivot":{"user_id":2,"account_id":1,"created_at":"2017-06-26 03:16:39","updated_at":"2017-06-26 03:16:39"}}]
how can i access each of the data present in the collection??
thanks for answering in advance guys

You are returning a collection of users with the following query
User::where('id', $user->id)->with('bankAccounts')->get()
I would suggest altering this to something like the following:
User::find($user->id)->bankAccounts()
This will return the users attached bankAccounts as a collection. You can then access the properties like so:
#foreach($access as $account)
<li>{{ $account->account_name}}</a></li>
#endforeach

Related

Firestore Database security Rules: Problem with collection restriction based on array from another collection

we got some problems with our security rules settings.
Our code looks like this
service cloud.firestore {
match /databases/{database}/documents {
function sameCompany(){
return get(/databases/$(database)/documents/users/$(request.auth.uid)).data.companyId == resource.data.companyId
&& request.auth.uid in get(/databases/$(database)/documents/companies/$(resource.data.companyId)).data.users;
}
match /orders/{orderId} {
allow read: if request.auth != null && sameCompany();
}}
The collections have the following structure:
orders/{orderId}
users/{userId}
companies/{companyId}
each doc in orders has one companyId.
each doc in users has one companyId.
each doc in companies has an array containing the userIds that are in the company
Only users that have the same companyId as the order and also if their userId is in the array from the company should be able to read the orders.
This is to have a double security that users cant change their companyId to read orders from another company
The first part before the && works just fine. If I manually put an Array after "request.auth.uid in " that contains the userId that is querying it also works fine, but somehow it doesnt work like this and I cant find the issue here.
Can someone help? Thank you for your time!
Edit1:
Thank you for your responses so far.
So the query looks like this:
query(
collection(db, "orders"),
where("companyId", "==", user.companyId)
)
We save in local Storage the user with the companyId. Without the second part after the && the data is retrieved like it should be, but with it nothing is shown. We want to double check if the users has the same companyId and is in the users array in the company in case someone tries to guess the companyId from another company and somehow can access the data. Like this you would need to know the companyId and the userId.
The data could simply look like this:
users doc with uId1:
{companyId: cId1, ...}
orders doc with dId1:
{companyId: cId1, ...}
companies with cId1:
{users: [uId1], ...}

firestore security rules : deny profile update but allow rating update

I have collection called 'services' inside every document I have 4 fields :
name
description
userID
Rating
and I want to give only the user to change his profile except rating I want to make it accessible (can update) to everyone , I check some problem like that and I get one solution that is create sub collection in profile doc I call it "rating" that contain a doc with the name "rate" and I make only this sub collection accessible to update from everyone ,
but I don't know how to to get subcollection data from a doc any solution plz with this rating problem :
My security rules after creation a sub collection for rating :
match /{category}/{serviceid} {
allow read,create;
allow update : if resource.data.userID == request.auth.uid;
match /rating/rate {
allow read,write;
}
}
I get all services with const docs =db.collection("categoryname").get() :
and I fetch every item data like that :
docs.foreach(doc => doc.data().name)
How can I get subcollection("rating") data from the doc?
You realize that with these rules, you allow everyone access? Even people unauthenticated would be able to make unlimited writes. Is that what you really want?
To answer your question, to access to the /rating/rate document you could just do:
let category = "categoryname";
db.collection(category).get()
.then(function(querySnapshot) {
querySnapshot.foreach(
function(doc) {
let serviceid = doc.id;
db.collection(category).doc(serviceid).collection("rating").doc("rate").get()
.then(function(doc) {
... // do whatever
}
}
)
}
You can also check the Official Documentation to get a document.

Firestore data duplication

I'm trying to setup a friend system in Firestore. My data model looks like this at the moment:
collection("users") ->
document("user1")
document("user2")
...
A document in the users collection contains data like the name, email... of the user. I'd like to enable a user to have friends now, but I'm unsure about the best way to model this.
So, I'd for sure add a friends field in the documents of the users, but what should this field contain? My first thought was a pointer to a new collection called friends in which the documents are users. Something like this:
collection("users") {
document("user1") {
name:user1,
friends: -> collection("friends") {
document("user2"),
...
}
}
}
This seems reasonable, but that'd mean that I'd have a lot of duplicate data in my database because each user that has friends will be duplicated in a friends collection. Should I worry about this or is this normal in a Firestore database structure?
Would it perhaps be possible to point to a document in the users collection from the friends collection? Something like:
collection("users") {
document("user1") {
name:user1,
friends: -> collection("friends") {
document, -----
... |
} |
}, |
document("user2")<-
}
Or should I throw away the thought of using a collection for friends and just keep a list with uids of all friends of the user?
Seems you are using two separate collections for users and friends first all you can do it by one collection. But I don't want to go there may be there was another scenario.
As your separate collection way, you can design your friends collection model to meet no duplication:
{
name : 'Name',
email : 'email#mail.com'
has_connected : {
'user1' : true // here you can use anyother unique key from user
}
}
The thing is that firestore recommend this types of design for query and for faster performance you can make that has_connected key as index.
In this approach, you have to check during adding new friend by email or any other unique key. if exists then just put another key into has_connected with the respective user. e.g user2 : true.
Finally, for fetching all friends for a user you have to do a query like this: e.g: in javascript
let ref = firebase.firestore().collection("friends");
ref
.where(`has_connected.${username}`, "==", true)
.get()
.then(//do your logic)
.catch()
Thanks

Create a last visited list with Symfony & Twig

I want to create a “last visited pages” list with Symfony and Twig.
For that purpose I wrote a history service which saves the last visited routes in the session.
But I just have the route name no alias for the user experience.
So the route country_info should hold a string like “Country Information”.
Is it possible to define a alias in the routing.yml?
No, it's not possible to define route aliases in routing.yml. The routing system is not meant to do that.
If you have a fixed number of pages you could just read the session values in your Controller and translate each route name in order to print it with Twig later.
Supposing you are storing last visited pages routes in an array, you can try the following:
In your Controller action:
// Read session
$page_routes = $session->get('last_visited_routes_array');
$output_array=array();
foreach ($page_routes as $route){
// Translate route to name
switch($route){
case "country_info":
$output_array['country_info'] = "Country Information";
break;
// ... Add more Cases here ...
}
}
// Return generated array so it can be used by Twig
return array('output_array' => $output_array);
In your Twig template:
{% for page_route, page_name in output_array %}
{{page_name}}
{% endfor %}
Hope it helps.

Get Meteor collection by name

Suppose I write:
new Meteor.Collection("foos");
new Meteor.Collection("bars");
Is there an API for accessing those collections by name? Something like Meteor.Collection.get(name), where name is "foos" or "bars"? I know I could write something like
var MyCollections = {
foos: new Meteor.Collection("foos");
bars: new Meteor.Collection("bars");
}
and then use MyCollections[name], but I'd prefer to use an existing API if one exists.
Based on Shane Donelley's mongoinspector
https://github.com/shanedonnelly1/mongoinspector
getCollection = function (string) {
for (var globalObject in window) {
if (window[globalObject] instanceof Meteor.Collection) {
if (globalObject === string) {
return (window[globalObject]);
break;
};
}
}
return undefined; // if none of the collections match
};
I've just found that package : https://github.com/dburles/mongo-collection-instances/
It allow you to
Foo1 = new Mongo.Collection('foo'); // local
Foo2 = new Mongo.Collection('foo', { connection: connection });
Mongo.Collection.get('foo') // returns instance of Foo1
Mongo.Collection.get('foo', { connection: connection });
// returns instance of Foo2
Hope it will help
This feature was added to Meteor in Feb 2016: "Provide a way to access collections from stores on the client"
It works like this:
Meteor.connection._stores['tasks']._getCollection();
And I was using it as follows to test inserts using the javascript console:
Meteor.connection._stores['tasks']._getCollection().insert({text:'test'});
For the insert it required the insecure package to still be installed otherwise got an access denied message.
As far as I can see in the collection.js source there currently is no way in the api to get an existing Collection by name, once it has already been initialized on the server. It probably wouldn't be hard to add that feature.
So, why not fork Meteor and submit a patch or create a smart package and share it I'm sure there are others out there who'd like the same feature.
With https://github.com/dburles/mongo-collection-instances you can use Mongo.Collection.get('collectionname')
Note that the parameter you're inserting is the same one you use when creating the collection. So if you're using const Products = new Mongo.Collection('products') then you should use get('products') (lowercase).
Note that they have a return value, so you can just do
var Patterns = new Meteor.Collection("patterns");
and use Patterns everywhere.
And when you need to subscribe to server updates, provide "patterns" to Meteor.subscribe().
If you have the same code for multiple collections, the chance is high that you're doing something wrong from a software engineering viewpoint; why not use a single collection with a type field (or something else that differentiates the documents) and use that instead of using multiple collections?
Rather than looking, I've just been doing:
Foos = new Meteor.Collection("foos");
or possibly put it inside another object. I haven't really been making a Collections collection object.
It seems there is no way to get at the wrapped Meteor.Collection object without saving it at creation time, as others have mentioned.
But there is at least a way to list all created collections, and actually access the corresponding Mongo LocalCollection object. They are available from any Meteor Collection object, so to keep it generalistic you can create a dummy collection just for this. Use a method as such (CoffeeScript):
dummy = new Meteor.Collection 'dummy'
getCollection = (name) ->
dummy._driver.collections[name]
These objects do have all the find, findOne, update et al methods, and even some that Meteor doesn't seem to expose, like pauseObservers and resumeObservers which seem interesting. But I haven't tried fiddling with this mongo LocalCollection reference directly to knowif it will update the server collection accordingly.
var bars = new Meteor.Collection("foos");
Judging by what the collection.js does, the line we use to instantiate the collection object opens a connection to the database and looks for the collection matching the name we give. So in this case a connection is made and the collection 'foos' is bound to the Meteor.Collection object 'bars'. See collection.js AND remote_collection_driver.js within the mongo-livedata package.
As is the way with MongoDB, whilst you can, you don't have to explicitly create collections. As stated in the MongoDB documentation:
A collection is created when the first document is inserted.
So, I think what you're after is what you already have - unless I've totally misunderstood what you're intentions are.
You can always roll your own automatic collection getter.
Say you have a couple of collections called "Businesses" and "Clients". Put a reference each into some "collections" object and register a Handlebars helper to access those "collections" by collections["name"].
i.e. put something like this on the client-side main.js:
collections = collections || {};
collections.Businesses = Businesses;
collections.Clients = Clients;
Handlebars.registerHelper("getCollection", function(coll) {
return collections[coll].find();
});
Then in your HTML, just refer to the collection by name:
{{#each getCollection 'Businesses'}}
<div> Business: {{_id}} </div>
{{/each}}
{{#each getCollection 'Clients'}}
<div> Client: {{_id}} </div>
{{/each}}
Look ma, no more generic "list all records" boilerplate js required!

Resources