In one of django tutorials it's said that APIViews (comparing with ViewSets) are useful for non-CRUD APIs, to use in customized logic like in authorization process.
The author uses in auth module CreateAPIView, RetrieveUpdateAPIView and ObtainAuthToken.
Now I'm confused, I thought that create and get (user model) are textbook examples of CRUD methods.
Related
We use Symfony 4 + Doctrine + APIPlateform to deliver a HTTP API.
APIPlateform exposes Doctrine entities as API Rest resources (via annotation inside entity class), which (I found) no a good practice, since the business model (exposed by the API) should be the same than the Symfony Doctrine model.
As a result, it more looks like a basic CRUD than a real application.
Am I wrong about that or is it possible to create kind of Doctrine virtual entities in order to use tools like APIPlatform (or even Symfony form)?
It's true that API platform seems to be strongly opinionated towards very simple CRUD cases.
Symfony Form component however will accept any object as the data. We normally use objects like MyThingType (extended from AbstractType) and MyThingDTO (data transfer object) for separating the UI from the business model and persistence layer. Works just fine.
API Platform has kind of a support for DTO's but in my opinion it's not that usable for complex scenarios. For complex application with good separation of concerns and complex business model it would seem that using Symfony controllers/form directly or perhaps with FOS Rest would be more direct way to achieve it.
https://api-platform.com/docs/core/dto/
You can hide some of the internals of your Doctrine entity by serialization groups but it's still not the same as real separation.
I'm converting a Symfony1 application to Symfony2, and I'm trying to follow Symfony2's best practices.
I have a problem with the business logic: In the old app, all the logic was in the controller (very fat controllers). I've moved it to entity repositories, but I'm not sure if this is the correct way (because, aside other things, I need to send emails, and this isn't working).
For example, the save function for a resource reservation manager (calendar) is:
Begin transaction
Validate that the given resource isn't used in the time-lapse I'm trying to save
If the data is correct and the resource is marked as "mandatory confirmation", an email is sent to all the users from the "confirmers" group
An email is sent to the current user telling him that the resource has been reserved correctly (and, if needed, telling that a "confirmer" must approve his reservation)
If all has worked well, commit the transaction. If any error has happened, rollback the transaction
As you can see, there is lots of business logic (this example is one of the easier modules), using multiple kind of entities, users, emailers, etc. So, how can I organize it? Should I put the business logic in an entity repository, or is better to use services? And for the emails, maybe it's better to send them from an event listener? And do you know where can I find some examples about this?
Simply make services to handle these tasks. For example; create a service that you can re-use, that's testable, for sending emails. Make the API as simple as it can be, and then you can use it in your controller.
The way I think about it is that the controller is ONLY there to send information around various services, and to handle what is output to the user. Anything else should be controlled via services, and the responses from those services.
It's not a bad thing to have small classes - your classes should aim to do one thing, and one thing well. If you split them up enough then they'll be easily testable, and easily reusable.
The Symfony Books are excellent resources for this kind of thing:
http://symfony.com/doc/current/book/service_container.html
You might find this article of Martin Fowler's useful. He says…
In general, the more behavior you find in the services, the more likely
you are to be robbing yourself of the benefits of a domain model. If all your logic is in services, you've robbed yourself blind.
I suspect he and Eric Evans would implement your business logic using a DDD approach along the lines of…
class Resource
{
public function isUsedIn(TimePeriod $tp);
public function isMandatoryConfirmation();
}
class ReservationManager
{
public function save(Resource $r, TimePeriod $tp)
{
if (! $r->isUsedIn($tp) || $r->isMandatoryConfirmation()) {
// send email to all the users from the "confirmers" group
// send email to the current user
}
}
}
Unfortunately in my experience with Symfony2, this hasn't been done and the code has ended up inside services. Symfony acknowledge that business logic can be put into Doctrine entities but from my point of view, it is a bit of weasel offer.
Services are container aware and as such can easily access other services to perform other functions like sending emails, logging messages. Doctrine entries cannot access other services which means that like Seer, in our project, we end up using services.
If you like the idea of moving more of your business out from services, it isn't difficult however Doctrine & Symfony do not seem to support it out of the box :-(
I'm building an application in ASP.NET MVC4 as a learning exercise. I'm trying to understand
authentication and authorization. That seems fine, role based authorization seems fine for restricting certain controllers/actions to users who are part of a given role.
What I'm struggling with is how I can apply this to data which belongs to an individual user. Using a forum as a simple example how could the functionality be achieved whereby a user can only edit or remove posts that they have created but can view/add comments to posts of other users. Would this have to be done in code by checking the user associated with the post to be updated against the current user before allowing the update to take place, returning unauthorized if they don't match.
Is there a more elegant solution that can be applied rather than applying this kind of logic to multiple controllers/actions?
There's a wealth of information out there I'm just trying to narrow the search. Can anyone suggest a good tutorial/article on this. I've been looking at Forms authentication and Membership but I'd be interested in something using Identity too. I'm also using Entity Framework.
Thanks
Would this have to be done in code by checking the user associated with the post to be updated against the current user before allowing the update to take place, returning unauthorized if they don't match.
Yes, that's exactly what you do. While role-based authorization is a matter of a simple relation between users and roles, data-access level authorization is usually complex and involve custom business rules.
Of course, it could help a lot to create a thin layer of managers that will be commonly used as guards so that you keep all the code close together:
[HttpPost]
public ActionResult PostFoo( FooModel model )
{
// keep the access manager separate from the
// domain layer. operate on IDs.
if ( new UserAccessManager( this.User ).
CanOperateOnFoo( model.IdSomething, model.IdWhateverElse ) )
{
}
else
// return 403 or a meaningful message
}
or
[HttpPost]
public ActionResult PostFoo( FooModel model )
{
// switch to the domain layer
Foo foo = Mapper.Map( model );
// make the access manager part of the domain layer
if ( foo.CanBeOperatedBy( this.User ) )
{
}
else
// return 403 or a meaningful message
}
Would this have to be done in code by checking the user associated with the post to be updated against the current user before allowing the update to take place, returning unauthorized if they don't match.
No, you want to avoid hard-coding authorization logic into your code. Doing so leads to:
authorization silos
poor visibility
a chance there might be errors in the authorization logic
hard-to-maintain logic
Is there a more elegant solution that can be applied rather than applying this kind of logic to multiple controllers/actions?
Yes, there is. Much like you wouldn't hard-code authentication or logging into your app, you want to externalize authorization. This is called Externalized Authorization Management (EAM). There are several frameworks that help you do that from Spring Security in Java to Claims-based authorization in .NET to XACML-based solutions.
There are 2 fundamental authorization models you want to consider:
role-based access control (RBAC)
attribute-based access control (ABAC)
You can read about both on NIST's website (RBAC | ABAC).
Given the sample rule you gave:
A user can only edit or remove posts that they have created but can view/add comments to posts of other users.
RBAC will not be enough. You will need to use ABAC (and XACML) to be able to implement the relationship between the user and the data requested. XACML, the eXtensible Access Control Markup Language is a standard that provides you with:
a standard architecture.
a request/response scheme, and
a policy language.
With the XACML policy language, you can rewrite your example as:
A user can do the action==edit or the action==remove if and only if the post.owner==user.id
A user can do the action==view on any post
A user can do the action==comment on any post
Then, from your code, all you have to do is send an authorization request: Can Alice view post #123?. The authorization engine (also called policy decision point or PDP) will determine who owns the post and will reach a decision, either of a Deny or a Permit.
A key benefit to using externalized authorization and XACML is that you can apply the same consistent authorization to any layer (presentation tier, business tier, ESB, APIs, databases...) and any technology (Java, .NET, Python...).
Other benefits include:
modular architecture
configuration-driven authorization that is easy to grow as requirements change
easy-to-audit authorization
centrally-managed authorization
cheaper to develop and onboard new applications than writing code over and over again
standards-based.
There are several open-source and vendor solutions out there that address this market. Have a look at Axiomatics (disclaimer: I work for Axiomatics) or SunXACML (open source).
HTH,
David.
I'm quite new to Symfony 2 and I'm moving to advanced topics like services. When should an object be a service?
For example, say that you have a facade object for making a call to a REST service. This class needs a username and password. Would it be correct modeling that class as a global service? Even if it's used only in a portion of the whole project?
# app/config/config.yml
parameters:
my_proxy.username: username
my_proxy.password: password
services:
my_proxy:
class: Acme\TestBundle\MyProxy
arguments: [%my_proxy.username%, %my_proxy.password%]
Definition taken from the Symfony2 glossary:
A Service is a generic term for any PHP object that performs a specific task. A service is usually used "globally", such as a database connection object or an object that delivers email messages. In Symfony2, services are often configured and retrieved from the service container. An application that has many decoupled services is said to follow a service-oriented architecture.
I think your example is a perfect candidate for a service.
You don't want to copy construction code to all places you need your API client. It's better to delegate this task to the dependency injection container.
This way it's easier to maintain (as construction happens in one place and it's configurable).
It's also more flexible as you can easily change the API client class without affecting code which uses it (as long as it implements the same interface).
I don't think there's a golden rule. But basically all classes implementing a task are good candidates for a service. Entities on the other hand are not as they're most often just data holders.
I always recommend Fabien's series of articles on the subject: http://fabien.potencier.org/article/11/what-is-dependency-injection
Yes, because this will spare you the configuration part. You're not going to fetch the username and password and give it to the constructor each time you need this class.
I am building an application using asp.net mvc, DI, IoC, TDD as a bit of a learning exercise.
For my data access I am using the repository pattern. Now I am looking at membership and how this can work with the repository pattern. I am currently using a Linq to Sql repository but don't want to be tied to SQL Server for membership.
Secondly, I am looking to split out membership into a number of services:
AuthenticationService - identify the user
AuthorizationService - what can they do
PersonalizationService - profile
The personalization service will be what really defines a "customer" in my application and each customer will have a unique id/username that ties back to the AuthenticationService - thus, allowing me to use the default ASP.NET Membership provider, roll my own or use something like Open ID.
Is this a good approach? I don't want to reinvent the wheel but would rather these important parts of my application follow the same patterns as the rest.
Thanks
Ben
Take a look at the RIA Authentication, Roles, and Profiles services.. no need to reinvent the wheel.
To be honest, to achieve what I wanted was quite a simple process. I haven't implemented the AuthorizationService yet but this will follow a similar pattern.
My authentication service is quite simple:
public interface IAuthenticationService
{
bool IsValidLogin(string username, string password);
}
There will be a CreateUser method but I haven't implemented this yet.
Creating an authentication service using the standard membership provider is a simple task:
public class AspNetAuthenticationService : IAuthenticationService
{
public bool IsValidLogin(string username, string password)
{
return Membership.ValidateUser(username, password);
}
}
If I want to swap out the default SqlMembershipProvider with my own then I just need to change web.config. In order to support different types of authentication (perhaps forms auth and open id) I can just create a controller action for each and call the appropriate IAuthenticationService.ValidateUser implementation before setting an auth cookie.
The authentication process if for identifying the "user". In order to get the "Customer" I am using a PersonalizationService. The interface for this is again quite simple:
public interface IPersonalizationService {
Customer GetCustomer(string username);
}
This returns my customer (with addresses, past orders - the stuff we really care about). The GetCustomer method will create a customer object if one doesn't exist with the passed in username. So if using standard forms auth a customer will be created anyway during registration. If using something like OpenID, the first time they login a customer object will be created and linked to their OpenID username (hence the reason for separating what an authenticated "user" is from a "customer".
This process also works well for anonymous checkout since I can create an in memory customer object for "guest" customers, and finally persist this to the database if they make a purchase. In this case, I don't have a user (cause they didn't authenticate) but I do have a customer.
I am quite happy with this implementation. I think I will roll my own Membership Provider (since it's not really that difficult) and I would like to use the repository pattern for the data access. Interested to hear any opinions / suggestions on this approach.
Some resources I have used:
http://noahblu.wordpress.com/2009/02/19/custom-membershipprovider-using-repository-dependency-injection-pattern-magic/
http://davidhayden.com/blog/dave/archive/2007/10/11/CreateCustomMembershipProviderASPNETWebsiteSecurity.aspx
http://pbdj.sys-con.com/node/837990/mobile
http://mattwrock.com/post/2009/10/14/Implementing-custom-Membership-Provider-and-Role-Provider-for-Authinticating-ASPNET-MVC-Applications.aspx