I'm writing an OData / Entity Framework client server app, and can't get Many to Many relationships to update from the client to the server.
The OData server is written using VS2013 in c# using WCF 5.6, and Entity Framework 6.
The database is simply 3 tables, Users, Permissions and a joining table UsersPermissions.
I'm using Entity Framework 6, which abstracts away the joining UsersPermissions table, leaving just the Users and Permissions entities.
From a User I can query their permissions no problem from a client using LINQ. Similarly I can query Users from Permissions, so the many to many relationship is good for reading from.
If I try to create a relationship from the client, say adding a new permission for a user, nothing happens. No traffic to the server, no data is changed in the joining table in the database.
This is the same whether I try to add a permission to a user in my client application, or if I use LinqPad to execute the query against my OData source.
The LINQ I'm using (taken from LinqPad) is:
// Get permission
var Permission = (from p in Permissions
where p.PermissionId == 1
select p).SingleOrDefault();
// Get user
var User = (from u in Users
where u.UserId == 1
select u).SingleOrDefault();
// Add permission to user
User.Permissions.Add(Permission);
SaveChanges();
I have tried creating a completely separate OData server application, and get the same problem.
If I execute the above LINQ within the OData server app, it executes as expected and the entry is added to UsersPermissions.
So it seems that the problem only exists when trying to update a many to many relationship from an OData client?
There is mention at the end of this article that OData has a bug in refreshing many to many relationships, but I can't even create one! http://msdn.microsoft.com/en-us/library/vstudio/bb896317(v=vs.100).aspx
I'd appreciate any help or suggestions towards tracking down why I cant create a many to many relationship from an OData client against an OData server using EF6.0.
To add a relationship between user and permission on client side, Please use DataServiceContext.AddLink
dsc.AddLink(User, "Permissions", Permission)
dsc.SaveChanges()
Related
I have setup an API in Laravel using Passport for authentication and spatie/laravel-permission to add permission functionality. I also have a calling application, again written in Laravel. I can authenticate from the calling app to the api but how do i ensure that the calling app knows the permissions available? What should the user/roles/permissions tables look like at the api and in the calling app?
Essentially i would like to use code like: $user->can('do something') in both applications.
My understanding of the Spatie package is that it allows you to make such code calls as $user->can('do something'), and reading the Github page it looks like it creates tables default named "role" and "permission" when you run the Migration after installing the package. In other words it's a matter of configuring the models and database connections in both of your apps correctly, specifically the User Model and the Permission table for both apps.
To clarify, I think you are asking these questions:
how can a second app know what permissions are available,
how would you be able to use something like "$user->can('do something')" in BOTH applications, touching the exact same data.
Answers:
If the "permission" and "role" tables already exist, then if your API doesn't have some endpoint to ask for the roles or permissions already available, you'd define a new one. For instance, some API call that asks the Permission table "getPermissions" or something and that your second application can call -- it either has to ask the database itself (via the API), or it has to get that from the second application. Which depends on how your two applications interact with each other
you would have to make sure to configure the second application so that the "User" model refers to the same table as the table the first application uses for the User model. Essentially, the model is being used as an interface to the table, so if both applications have a defined User model that references the same table and both are configured to connect to the same database that table is in, Laravel's user model will "just know" the data in question (this is the basis of Laravel's Eloquent for Models).
Additionally, for what it's worth, I haven't used the spatie/laravel-permission package, but in relation to question #1 I did find a function in the docs that might also be used to grab currently made permissions in list form from a "permission table":
Permission Model, getPermissions
And for reference, about Laravel's Eloquent and Models (which may be something you already know, but I'll leave this link anyway):
Laravel Eloquent ORM
We use the IdentityServer3 as our central authentication provider. Now I have a general question about the IdenityServer in an enterprise environment. I try to explain it with the following example:
If a user was successfully authenticated, he get a token from the provider. The token includes the unique ID of the user.
The authenticated user send a request to a WebApi, to create a new item (e.g a new product).
The WebApi extract the unique ID from the token and creates the new product in the database. Additionally the new product was linked with the unique user ID (e.g as creationUserId).
An other user send a request to the WebApi to get all available products.
The WebApi create a database query to retrieve all products. Additionally the WebApi wants to convert the creationUserId of each product to the correlating username. But that is not possible, because username is stored in the identity database which is an other database one than the application database (e.g for the products). Are there some best practices to solve this requirement?
Many thanks for your help!
Regards
Thank you for your answers. I see only one way to realize my requirements:
--> I store the username with the userId in the application database, because a API for translating is to slow.
I have an intranet application for which the URL is as follows
http:\\ServerName]\RunLog\
I am adding another department/tenant/group of users which will utilize the same instance of the application and same database. Their data will be different from the existing users. I am planning to add new column foreign key in each table to identify the specific tenant. I authenticate users windows authentication. I am thinking that the access to the application will be as follows
http:\[ServerName]\Platform1\RunLog
http:\[ServerName]\Platform2\RunLog
So for the above URL, how could I go about achieving that in the Application? I know how to make the table changes in SQL server, Updating the Entities, Updating the linq code in the controllers to pull up respective tennant data. Any help to get me started would be appriciated.
Kindly note that as you have given in your post, it is possible to identify the tenant's based on their URL. The table that contains the tenant details will also contain their url. So you will identify the tenant based on the URL. After identifying the tenant, we can authenticate the user's using the found tenant id / tenant code, get the tenant's configuration or settings using the same tenant id / tenant code.
I hope that you could have all the other entities of the application with a column called as TenantId. This will help you to fetch the data based on tenant. Your only change will be in the data access layer where you will filter the data that you retrieve from the Database.
Let me know if you have any other clarifications regarding the other specifics of this implementation.
I have an exisiting database which I used to create a Model usign the Database first approach. Please refer to the database diagram.
In my solution file, I have a Class Library of the model which has an ADO.NET connection to the database & and I a ASP.NET MVC 3 web application.
The funcitonality that I'm trying to get here is that - the information displayed once a user logs in is different for every user. How do I link the user login page to the 'user' table of the database? Is it directly using the connection string or do I need to go through the model that I created using the Database?
Add a field to your User table called "ProviderUserKey" or MembershipUserID, or something similar of type uniqueidentifier. You then call Membership.GetUser().ProviderUserKey and use that in your where clause of your User Table to select the correct User record based on the logged in user.
I'm working with a Customer Self-service Portal instance in Dynamics 365 and have the possibility of a contact(user) being linked to one or more accounts via a Many-to-Many relationship. I'm trying to find a way to change the out-of-the-box Case entity list to show cases for any account the contact is linked to with this new relationship but so far haven't found anything that will work. I have considered just replacing the entity list view with some custom fetchxml in Liquid code, but I'm thinking the entity permissions for Case would have to be global then, instead of Contact or Account scope? I'm looking for a way to make this work with entity permission at Contact or Account scope.
I tried changing the account entity permission to use the new Many-to-Many relationship I created so that the current contact/user should be able to access all the accounts they are associated with, but I'm missing how to get to the next step of then showing all cases for those accounts.
Any suggestions? thank you!
Ok,I found the missing piece to make this work. Once I had the entity permission to the account entity (let's call it Account of Contact) using the new Many-to-Many relationship (contact to account), I then created another entity permission record for the Case entity with a scope of Parent and selected the "Account of Contact" permission as the parent, and picked the existing incident_customer_account relationship. Once this was parented, I was able to go to the out-of-box support home page and view all cases for accounts my contact was associated with via the Many-to-Many relationship.