Log changes detected to domaincontext based on haschanges and getchanges - silverlight

I have a Silverlight application that is using Entity Framework 4. In the app, it is possible for the user to add/remove string representations of Active Directory group names into the configuration - changes are not saved in the backend until the 'save' button is clicked.
When 'save' is clicked, Entity Framework updates the backend with the changes to the DomainContext. This is working as expected. But I want to log the changes being made and send them out in an email each time before context.SubmitChanges() fires. What is the easiest way to log the changes? I already have code that I can reuse to email the changes to be logged.
I am looking at context.ADGroupRules.EntityContainer.GetChanges() and can see AddedEntities and RemovedEntities properties in there but I'm not sure how to 'get at' the highlighted string in the included snip in order to log it.
if (command == "Save")
{
if (_context.HasChanges)
{
var changeSet = _context.ADGroupRules.EntityContainer.GetChanges();
//log and email changes here
_context.SubmitChanges(OnSubmitCompleted, null);
}
}

I have figured it out.
if (command == "Save")
{
if (_context.HasChanges)
{
var changeSet = _context.ADGroupRules.EntityContainer.GetChanges();
foreach (var entity in changeSet.AddedEntities.OfType<ADGroupRule>())
{
ADGroupRule rule = (ADGroupRule)entity;
Console.WriteLine(rule.ADGroupName);//simulate logging-emailing
}

Related

Laravel 8 Fortify User UUID Login Problem

I am currently setting up a new project using Laravel 8. Out of the box, Laravel is configured to use auto-incrementing ID's for the user's ID. In the past I have overrode this by doing the following.
Updating the ID column in the user table creation migration to
$table->uuid('id');
$table->primary('id');
Adding the following trait
trait UsesUUID
{
protected static function bootUsesUUID()
{
static::creating(function ($model) {
$model->{$model->getKeyName()} = (string) Str::orderedUuid();
});
}
}
Adding the following to the user model file
use UsesUUID;
public $incrementing = false;
protected $primaryKey = 'id';
protected $keyType = 'uuid';
On this new project, I did the same as above. This seems to break the login functionality. When the email and password are entered and submitted, the form clears as though the page has been refreshed. Thing to note is there are no typical validation error messages returned as would be expected if the email and/or password is wrong.
To check that the right account is actually being found and the password is being checked properly, I added the following code to the FortifyServiceProvider boot method. The log file confirms that the user is found and the user object dump is correct too.
Fortify::authenticateUsing(function(Request $request) {
\Log::debug('running login flow...');
$user = User::where('email', $request->email)->first();
if ($user && Hash::check($request->password, $user->password)) {
\Log::debug('user found');
\Log::debug($user);
return $user;
}
\Log::debug('user not found');
return false;
});
Undoing the above changes to the user model fixes the login problem. However, it introduces a new problem that is the login will be successful but it wont be the right account that is logged in. For example, there are 3 accounts, I enter the credentials for the second or third account, but no matter what, the system will always login using the first account.
Anyone have any suggestions or ideas as to what I may be doing wrong, or if anyone has come across the same/similar issue and how you went about resolving it?
Thanks.
After digging around some more, I have found the solution.
Laravel 8 now stores sessions inside the sessions table in the database. The sessions table has got a user_id column that is a foreign key to the id column in the users table.
Looking at the migration file for the sessions table, I found that I had forgot to change the following the problem.
From
$table->foreignId('user_id')->nullable()->index();
To
$table->foreignUuid('user_id')->nullable()->index();
This is because Laravel 8 by default uses auto incrementing ID for user ID. Since I had modified the ID column to the users table to UUID, I had forgotten to update the reference in the sessions table too.

How to validate a related entity still exists in database, on form submit?

I have an entity Activity, with a CRUD in one part of my app.
In another part of the app, I have a form representing a UserData entity, with a #ManyToOne relation to Activity.
When submitting this form, I want to validate that chosen Activity still exists in database (because of CRUD, it could be deleted between the form loading and the form submit).
I dug a lot into symfony core files, and found that this validation is done the Form component, in viewToNorm() method which throw a TransformationFailedException, which is then silenced by the submit() method :
public function submit($submittedData, $clearMissing = true)
{
try {
[...]
// Normalize data to unified representation
$normData = $this->viewToNorm($viewData);
[...]
} catch (TransformationFailedException $e) {
$this->transformationFailure = $e;
// If $viewData was not yet set, set it to $submittedData so that
// the erroneous data is accessible on the form.
// Forms that inherit data never set any data, because the getters
// forward to the parent form's getters anyway.
if (null === $viewData && !$this->config->getInheritData()) {
$viewData = $submittedData;
}
}
}
I tried to build a custom Constraint with a custom Validator, but it doesn't work, because in case of Transformation failure, Symfony reset the data to it's original form value, so my validator receive a NULL value instead of the deleted entity.
I could build a DataTransformer and catch this exception manually, but DataTransformer are not meant to perform validation.
Is there any other way to check a relation still exists in database and at the end, customize the message displayed in FormError ?

Caching product display with Display Cache and still be able to add products

I'm building an eCommerce website using D7, mainly with Commerce and DS. To get a better perfomance I installed Display Cache which is a module that caches the rendered HTML of an entity for anonymous and authenticated users. In my particular case i'm caching the Product Display (a node which references a product and it's variations if any).
After a few hours of configuration I end up with a "good result" in performance. All my entities where cached by rol, in teaser and full mode... but then the problem arises when the user clicks "Add to cart" button because it's not adding products to the cart... nor it is showing an error.
One possible reason is the form token or some form processing function that is invalidating the action because the form is not generating everytime as expected. I read how to disable the form token in the "Add to cart form" (or any form) but it's not working. I set $form['#token'] to false, but still is not adding products to the cart.
Probably the solution is not easy, but I need clues of what I could do or where I could start tackling the problem.
So, thanks for you expertice.
A solution to this combination of modules, in order to have cached display for anonymous & authenticated users and add to cart forms is to disable cache programatically of the requested product in all it's displays... and disable the token of the "add to cart form".
Here is the code for disabling the token:
function YOUR_MODULE_form_alter(&$form, &$form_state, $form_id) {
if (strstr($form_id, 'commerce_cart_add_to_cart_form') || strstr($form_id, 'views_form_commerce_cart_form_default')) {
unset($form['#token']);
}
}
And here is the code to remove caching when a an add to cart button is pressed:
function YOUR_MODULE_init() {
if (isset($_POST['product_id'])) {
$id_product = intval($_POST['product_id']);
$res = views_get_view_result('sys_search_product_display', 'default', $id_product);
foreach ($res as $nid) {
display_cache_flush_cache('node', $nid);
}
}
}
Note that "sys_search_product_display" is just a view which receives the ID of the product and returns the ID of the product display. This can be done in other ways.

how to store login information using onsen ui?

I want to use onsen ui and angularjs to develop a hybird application, but now I meet a problem, this application cannot store user's login information, so user must login everytime after they close the application.
I use $cookies, service, and $rootScope to store user's login information, but all of them can not work at android platform.
Anyone can help me to solve this problem?
On HTML5 mobile framework like Onsenui, I suggest to use localStorage.
You can take a look at these two AngularJs modules:
angular-local-storage
ngStorage
They have very well written instructions and demo codes as references.
use this plugin https://github.com/litehelpers/Cordova-sqlite-storage or something similar to create a sqlite database. Create a table with the information you want to keep (username and password). You can create a hash of the password and store it for better security (md5 or sha1).
You can also keep the timestamp of the login and keep the user logged in for a specific interval of time, so when he opens the app, check if you are inside this interval (e.g. day, week, etc.) from the last login and if yes, log him in automatically else show the login screen again.
if (window.localStorage.getItem("rememberMe") == "true") {
$scope.userEmail = window.localStorage.getItem("userName");
$scope.userPassword = window.localStorage.getItem("password");
document.getElementById("rememberMe").checked = true;
}
else {
document.getElementById("rememberMe").checked = false;
}
if (document.getElementById("rememberMe").checked == true) {
window.localStorage.setItem("rememberMe", "true");
window.localStorage.setItem("userName", $scope.userEmail);
window.localStorage.setItem("password", $scope.userPassword);
}
else if (document.getElementById("rememberMe").checked == false) {
window.localStorage.setItem("rememberMe", "false");
window.localStorage.setItem("userName", "");
window.localStorage.setItem("password", "");
}
Hi! have a look at the above code. It stores in local storage

Update user's email in Orchard

I want to allow users to update their email, so I have controller :
[HttpPost]
public ActionResult ChangeEmail(string newEmail) {
IUser user = _services.WorkContext.CurrentUser;
if (!user.Is<UserPart>())
throw new InvalidCastException();
var userRecord = user.As<UserPart>().Record;
userRecord.Email = newEmail;
return null;
}
Everything builds and runs OK except that the database doesn't update new email.
What should I do ?
Thanks all !
I think your problem is that you are trying to update the Record directly instead of setting the value of the Part and letting Orchard save your changes:
user.As<UserPart>().Email = newEmail;
Your change will be automatically committed to the db at the end of the request.
As a side note the reason your changes are not saving is that when you update a record you need explicitly update it using an injected repository e.g. _userRepository.Update(user.Record) where _userRepository is an injected IRepository<UserPartRecord>, but just updating the part is the way to go.

Resources