Making Catalyst calls from the model? - perl

I'm using Catalyst with Catalyst::Plugin::Authentication and
Catalyst::Plugin::Authorization::Roles and am wondering if there is a better
approach to adding an attribute to a model that I'm not seeing.
Each user is permitted to access one or more companies, but there is
always one primary (current) company at a time. The permitted list is
stored in the database, and database access is primarily through DBIC.
My first inclination is to say that it's the user that has a current
company, and thus put it as part of the user model: give the user
package a "sub company { … }" to get/set the user's current company. The
database check is fairly easy; just use "$self->search_related" (a DBIC
method, inherited by the user model).
The problems I run in to are:
The current company needs to persist between requests, but I'd rather
not store it to the database (it should only persist for this
session). The natural place is the session…
There is a role, akin to Unix's root, that allows you to act as
any company, ignoring the list in the database. Checking this role
can be done through the database, but everywhere else in the app uses
$c->assert_user_role and friends.
I've heard its best to keep the models as Catalyst-independent as
possible. It also seems pretty weird to have a model manipulating
$c->session.
Of course, I could move those checks to the controllers, and have the
model accept whatever the controller sends, but that's violating DRY
pretty heavily, and just begging for a security issue if I forget one of
the checks somewhere.
Any suggestions? Or do I just shrug and go ahead and do it in the model?
Thanks, and apologies for the title, I couldn't come up with a good one.

The key is to create an instance of the model class for each request, and then pass in the parts of the request you need. In this case, you probably want to pass in a base resultset. Your model will make all the database calls via $self->resultset->..., and it will "just work" for the current user. (If the current user is root, then you just pass in $schema->resultset("Foo"). If the current user is someone else, then pass in $schema->resultset("Foo")->stuff_that_can_be_seen_by($c->user). Your model then no longer cares.)
I have some slides about this, but they are very outdated:
http://www.jrock.us/doqueue-grr/slide95c.html#end
(See the stuff immediately before and after, also.)
Note that restricted resultsets and web ACLs are orthogonal. You want to make the model as tight as possible (so that your app can't accidentally do something you don't want it to, even if the code says to), but various web-only details will still need to be encoded in ACLs. ("You are not allowed to view this page." is different from "You can only delete your own objects, not everyone's". The ACL handles the first case, the restricted resultset handles the second. Even if you write $rs->delete, since the resultset is restricted, you didn't delete everything in the database. You only deleted the things that you have permission to delete. Convenient!)

Related

Does everything have to be an aggregate? Many-to-Many Link

Say I have two entities
Notifications and Users.
I want to mark that a user has seen a specific notification.
This would commonly be done with a many-to-many relationship
e.g. UserNotification
Because there is no invariant around this relationship (we don't care if "all" users have seen the notification) these users shouldn't be on the notification aggregate.
On the opposite side, the users aggregate doesn't need a list of notifications on it
So that leads to say that the UserNotification (this relationship) is an aggregate of its own.
However, because we are never going to reference this thing by Id, does it really really belong as one? It seems like just adding an aggregate for storing the data.
What should I do here?
Just make an aggregate anyway and ignore the id?
Put these notifications on the user or users on notifications. (does it belong on either, and would putting it on one not add weight and cause concurrency issues?)
just make a crud table?
An aggregate without the id and keep the composite key (is that allowed?)
thanks
Does a Notification have its own lifecycle? Can a Notification exist without a User to be notified?
I could imagine a Notification to simply be a Value Object that gets copied to each affected User.
have you considered modeling User and Notification as aggregates but NOT modelling the association at all?
There is a high probability of not needing to. The only usecase I can come up with is retrieving all notifcations of a user. this can be exposed in an repository interface via getNotifications(user: User): Iterable[Notifications] (scala syntax).
on the write side the saveNotification(notification: Notification, users: List[User]) could save the aggregate as well as populate the n:m table.
EDIT: on afterthought to this - my solution would introduce a source code dependency from notifications to users (at least on the repository) and your intiuition might be right - the notification should not know about the user at all.
But there has to be at least the concept of an Recipient which may perfectly reside in the notification "module" or "package". maybe you are crossing bounded contexts here and the User entity on one side should be translated to an Recipient value object on the other via Anti Corruption Layer.
It's up to you and your domain to decide. In this example it would perfectly make sense that the notification package has some knowledge about a "User". otherwise - what would be notified?

What's the accepted pattern for global, updatable data?

I've gone through several tutorials on Flutter and I find that they cover basics just fine but there are some nagging aspects of good design and good architecture that are consistently missing. I'm writing my first actual (not toy) application in Flutter and find myself running into these missing points.
Global data. Once a person installs the application and tries to use it, I ask them to log in / create an account, since this is an application specifically for managing groups of people. I'm using Firebase on the back end, and the package to do authentication winds up returning Future<FirebaseUser> from everything. So, yes, when it comes to building a Widget that uses the user's data, I can use a FutureBuilder. That said, it seems weird to have to keep typing boilerplate FutureBuilder code to dereference the user every place I want to use the user's ID to look up their data (what groups are they part of, what actions do they have pending, etc.). I really feel like there ought to be a way to invoke the future, get the actual user object, and then store it somewhere so that anything that wants a user ID for a query can just go get it. What's the right solution? I can't believe I'm the only person who has this problem.
Updatable data. I've got a page where I list the groups the current user is a member of. The user, though, can create a new group, join an existing group, or leave a group. When they do that, I need to redraw the page. The list of groups comes from running a Firebase query, so performing an action (join, leave, etc.) should signal the app to redraw the page, which will have the side effect of re-running the query. Conceivably, one might make the page dependent (how?) on the query results and have it redraw whenever they update, and instead have some widget somewhere that keeps track of the query. There's another answer here that hints that this might be the right way to go, but that's really concerned with relatively invariant data (locale doesn't change all that often for a single user). So, again, I can't believe I'm the only one who does this sort of thing. What's the best practice in this case?

design issue when too many derived classes are needed

I am trying to build a badge system that is similar to StackOverflow in my entity-framework code-first application.
I will have around 10 badges in total and each type of badge has its own properties. I am thinking to have base class Badge and derive the other classes from the base class.
For example, there will be Sprinkle badge and it will be automatically assigned to the user if his post is liked 3 times or more. So, I will have Sprinkle class with additional property NumberOfLikes (so that it can be updated later). However, in the database table, there will be only one record for this class. Isn't this weird?
I will have 10 classes like this, and there will be only single record for their corresponding table in the database. I have to have separate classes for each to be able to configure their unique properties.
Is my design choice a poor one?
You may consider to differentiate between the business rule of the badge, that is coded in the derived badge class and the bookkeeping of earned badges of a user. I see no need to have this rule classes be entity framework classes and to store them in the database if it does not have any parameters you want to change frequently. You could store this parameters in other configuration stores (eg. exe.config) or similiar or hardcode it. The (perhaps only one) instance of this classes are purely to execute the business rule. See them as services (DDD) or perhaps strategy pattern or (for evaluation) visitor pattern. They could just be created (perhaps per IoC/Di container that automatically creates all derivations) without storing/loading in the database.
On the other hand you have to bookkeep which user earned which badge (it could be a performance hit to calculate this new on every request). Here it makes sense to have a class that is stored in the database (1:n) and stores the list of badges a user received. So after every change (new post, new like, whatever) or from time to time (nightly run) you run through your badge rule classes and every badge the user does not already have (or if it is possible to loose a batch you take all) is executed for this user to check if it applies. If yes, the marker is created that the user earned the badge.
In your example, you may store in your database the user, his post and the number of likes. The Sprinkle badge could be a result of some business rules (is your post (or user) Sprinkle compatible) and may not be stored in your database?
In other worlds, the Sprinkle badge is a way to see a post (or a user) having more than 3 likes?
Maybe this rules could be stored in your database and parametrized?

Creating an UNDO flow for transacted fields

I've been thinking about the applications for goangular. In the need for immediate storage/database updates, such as a chat application or stocks application etc., I can see how goangular can be extremely useful in the sense of SignalR methodologies. But could it be applied to the traditional form with ten fields and a save button on it? All I could think of, was the traditional form, with ten fields on it -less the save button. If all ten fields are on the scope of the controller, than there would be no need for a save button. Every change of a field would be commemorated to the goinstant storage. Now having said that, how would one UNDO lets say any changes to those ten modified fields? Control+Z ten times? Not so robust. Any ideas on a UNDO all Changes button for such a form? (desperately trying to expand the bonds of real time database transactions)
I'll attempt to answer what I believe to be the spirit of your question first.
Most of the time, when using GoAngular, we're focused on synchronizing application state. Aka: Active clients sharing session data. Inevitably we drift into the territory of long-term persistence. At this point, rigorous validation / sanitization become a necessity, which we can't discuss without some context.
Let's say our user is completing their profile. This profile will be used to create a User model, which we will persist. Now that we have context, it becomes clear that we shouldn't persist a partially complete form, because it wouldn't represent a valid User model. We persist the form once it is complete, and valid.
Implementing this is as simple as creating a custom $scope.onSubmit method and validating the form input before calling $save on our new $scope.user model.
Undo would be easy to implement too, if you use $scope.users.$add, a key will be generated and returned, you could use this key to remove the new user. If you wanted to roll-back a change, you'd need to implement some system for versions, and roll back to the previous version of that User.
Hope I've answered your question in here somewhere :)

RESTful Soft Delete

I'm trying to build a RESTful webapp wherein I utilize GET, POST, PUT, and DELETE. But I had a question about the use of DELETE in this particular app.
A bit of background first:
My webapp manages generic entities that are also managed (and, it happens, always created) in another system. So within my webapp, each entity will be stored in the database with a unique key. But the way we will be accessing them through URLs is with the unique key of the other system.
A simple example will make this clear, I think. Take the URL /entity/1. This will display information for the entity with ID 1 in the other system, and not my own system. In fact, IDs in my system will be completely hidden. There will be no URL scheme for accessing the entity with ID of 1 in my own system.
Alright, so now that we know how my webapp is structured, let's return to deleting those entities.
There will be a way to 'delete' entities in my system, but I put quotes around it because it won't actually be deleting them from the database. Rather, it will flag them with a property that prevents it from appearing when you go to /entity/1.
Because of this, I feel like I should be using PUT ('deleting' in this way will be idempotent), since I am, from the perspective of the data, simply setting a property.
So, the question: does the RESTful approach have fidelity to the data (in which case it is clear that I am PUTing), or the representation of the data in the app (in which case it seems that I am DELETEing)?
You should use DELETE.
What you intend to do with your data is called "soft deleting": you set a flag and avoid flagged items from appearing. This is internal to your webapp and the user doesn't have to know that you're soft deleting instead of deleting or whatever you want to do. This is why you should use the DELETE verb.
I think there is no definitive answer. I'd rely on whether 1. the soft-delete, recover and destroy actions are an actual feature of your api OR 2. soft-delete is merely a "paranoid" database engineering pattern.
The "soft" deletion is transparent for the api client, in which case using the DELETE verb seems like the way to go
Everything is as if the item was to be removed once and for all, but engineers want to keep it somewhere in the database
Api clients have the ability to recover or destroy the soft deleted resource, in which case soft deletion and recovery can use POST on a different action url like /resource/:id/softdelete and the destroy action would be the one using DELETE.
Another way to go may be to use DELETE with no query parameter to soft delete, and add ?destroy=true to actually destroy. But this approach seems less explicit and more prone to errors.
The DELETE method has very specific semantics in HTTP, which must not be overloaded
or stretched by a REST API’s design. Specifically, an API should not distort the intended
meaning of DELETE by mapping it to a lesser action that leaves the resource, and its URI,
available to clients. For example, if an API wishes to provide a “soft” delete or some
other state-changing interaction, it should employ a special controller resource and
direct its clients to use POST instead of DELETE to interact.
Source: Rest-API Desgin Rule book by Mark Massé
Suggestion:
POST: /entity/1/your-soft-delete-controller-name