How to dynamically change the title of only one node - sitemapprovider

In a node, the title should be the name of the user logged into the system.
In addition I would like the result to be cached, because to retrieve the username I have to go to the database since the username is the email.
How to modify the title with the name of the logged in user and cache the result, but so that if another user logs in it will not load a cached page but a new page will be rendered to him.

In v4 you can simply set the title in either your view or controller and it will be request cached for that user (no other user will see it).
#MvcSiteMapProvider.SiteMaps.Current.CurrentNode.Title = "My Username"
Of course, I am using CurrentNode as an example, you can do this with any node by walking the tree.
However, you will need to handle the caching of the username to prevent a database hit per request outside of MvcSiteMapProvider. You can do this by creating a cache item for each user, incorporating the username (as long as it is unique) into the key.
var key = "My Username";
var userName = HttpContext.Current.Cache.Item[key];
if (userName == null)
{
userName = GetUserNameFromDB();
HttpContext.Current.Cache.Item[key] = userName;
}

Related

Meteor - Password recovery / Email confirmation dynamic url

Basically, I'm using the accounts-base package on meteor and on meteor startup, I set up what template the server should use for the password recovery mail, email confirmation mail, etc.
For example, in my server/startup.js on meteor startup I do many things like :
Accounts.urls.verifyEmail = function (token) {
return Meteor.absoluteUrl(`verify-email/${token}`);
};
Accounts.emailTemplates.verifyEmail.html = function (user, url) {
return EmailService.render.email_verification(user, url);
};
The problem is that my app is hosted on multiple host names like company1.domain.com, company2.domain.com, company3.domain.com and if a client wants to reset his password from company1.domain.com, the recovery url provided should be company1.domain.com/recovery.
If another client tried to connect on company2.domain.com, then the recovery url should be company2.domain.com.
From my understanding, this is not really achievable because the method used by the Accounts Package is "Meteor.absoluteUrl()", which returns the server ROOT_URL variable (a single one for the server).
On the client-side, I do many things based on the window.location.href but I cannot seem, when trying to reset a password or when trying to confirm an email address, to send this url to the server.
I'm trying to find a way to dynamically generate the url depending on the host where the client is making the request from, but since the url is generated server-side, I cannot find an elegent way to do so. I'm thinking I could probably call a meteor server method right before trying to reset a password or create an account and dynamically set the ROOT_URL variable there, but that seems unsafe and risky because two people could easily try to reset in the same timeframe and potentially screw things up, or people could abuse it.
Isn't there any way to tell the server, from the client side, that the URL I want generated for the current email has to be the client current's location ? I would love to be able to override some functions from the account-base meteor package and achieve something like :
Accounts.urls.verifyEmail = function (token, clientHost) {
return `${clientHost}/verify-email/${token}`;
};
Accounts.emailTemplates.verifyEmail.html = function (user, url) {
return EmailService.render.email_verification(user, url);
};
But I'm not sure if that's possible, I don't have any real experience when it comes to overriding "behind the scene" functionalities from base packages, I like everything about what is happening EXCEPT that the url generated is always the same.
Okay so I managed to find a way to achieve what I was looking for, it's a bit hack-ish, but hey..
Basically, useraccounts has a feature where any hidden input in the register at-form will be added to the user profile. So I add an hidden field to store the user current location.
AccountsTemplates.addField({
_id: 'signup_location',
type: 'hidden',
});
When the template is rendered, I fill in this hidden input with jQuery.
Template.Register.onRendered(() => {
this.$('#at-field-signup_location').val(window.location.href);
});
And then, when I'm actually sending the emailVerification email, I can look up this value if it is available.
Accounts.urls.verifyEmail = function (token) {
return Meteor.absoluteUrl(`verify-email/${token}`);
};
Accounts.emailTemplates.verifyEmail.html = function (user, url) {
const signupLocation = user.profile.signup_location;
if (signupLocation) {
let newUrl = url.substring(url.indexOf('verify-email'));
newUrl = `${signupLocation}/${newUrl}`;
return EmailService.render.email_verification(user, newUrl);
}
return EmailService.render.email_verification(user, url);
};
So this fixes it for the signUp flow, I may use the a similar concept for resetPassword and resendVerificationUrl since the signupLocation is now in the user profile.
You should probably keep an array of every subdomains in your settings and keep the id of the corresponding one in the user profile, so if your domain changes in the future then the reference will still valid and consistent.

How to reset password in passport-local strategy in Sails.js

Passport.js provides authentication framework in Node.js. It only deals with Authentication.
Now I would like to enable password reset. Since there is no password field in User model, only passports, how can I reset password in passport-local strategy? I assume that user needs to generate a new password and call something to override the existing hash of the old password. What methods are those and where can I find them?
When the user selects to reset his/her password, what you can do is send an email to the user with a link containing a token associated with the user. Once the user clicks on the link, you validate the user based on the token & email and then show the reset password HTML. Once user enters the new password, in the backend code, you set the password on the User object after hashing and then save it. You can set the token as null too.
A sample code with base64 will be as shown below
user.salt = new Buffer(crypto.randomBytes(16).toString('base64'), 'base64');
user.password = user.hashPassword('newPassword');
user.token = undefined;
user.save(...)
The hashPassword method is as given.
UserSchema.methods.hashPassword = function(password) {
if (this.salt && password) {
return crypto.pbkdf2Sync(password, this.salt, 10000, 64).toString('base64');
} else {
return password;
}
};
The above code is auto-generated with Yeoman

GAS - setTag() - getTag() still not working

I'm creating a webapp which allow :
to log using data stored in a spreadsheet (login and password)
to add some data to this spreadsheet (bet on rubgy matchs)
My problem is to recognize which user is connected.
What i did so far
in the doGet function, where all panels except connection are invisible, I created a label where i'll store the login into the tag
var loginlabel=app.createLabel().setId('loginlabel').setText('test').setVisible(true);
in the connection, I store the login into a invisible label tag
var logintest=e.parameter.logint;
app.getElementById('loginlabel').setTag(logintest);
I want to allow people to change their own password (but I also need to retrieve the login name for other purposes, but let's take this one
When I click on "Modify password" button, I want to get the Tag, but I always get a NULL
var login=app.getElementById('loginlabel').getTag();
I'm free to share my code here or wherever
Maybe it does exist other way to do this, I'm open for advice
In a server handler you can get the tag value using
var tagValue = e.parameter.loginlabel_tag ; // assuming the label has a name = 'loginlabel'
Note that the widget must have a name to be able to retrieve the tag value (see this post among others)

Entity framework - Avoid circular Relationship in serialization

I have two tables : Users & Profiles. A user has one profile (1:1), a profile can be affected to many users, each profile has many modules, each module has many actions.
I'm sending this object from an asmx to a aspx page using a direct service call.
I got an error because of lazy loading ... so I disabled the lazy loading.
this.Configuration.LazyLoadingEnabled = false;
this works fine, I got my user, with the profile null.
To build the menu tree I have to retrieve the profile. I included It :
User user = new User();
using (cduContext db = new cduContext())
{
// get the user
string encryptedPassword = Encryption.Encrypt(password);
user = (from u in db.Users
where u.UserName.Equals(login) &&
u.Password.Equals(encryptedPassword)
select u).FirstOrDefault();
// Include the users profile
user = db.Users.Include("Profile").FirstOrDefault();
}
return user;
I got this error in the javascript call function :
A circular reference was detected while serializing an object of type 'CDU.Entities.Models.User'.
When I made a quick watch on the user object, in asmx ( before sending it ) , I found, that the profile has included the list of the users who had this pofile, each user has his profile loaded ... etc
Any idea please ?
Note, your code should look like this:
using (cduContext db = new cduContext())
{
// get the user
string encryptedPassword = Encryption.Encrypt(password);
var user = from u in db.Users
where u.UserName.Equals(login) &&
u.Password.Equals(encryptedPassword)
select u;
// Include the users profile
return user.Include("Profile").FirstOrDefault();
}
In your code, you were throwing away the first query by overwriting it with the second. And there was no valid reason to create a blank user.
To address your problem, you're going to have make a decision on what you don't want to serialize. In your case, you probably don't want to serialize Profile.Users
You don't mention what serializer you're using. I'm assuming you're using the DataContract serializer?
EDIT:
You would mark your Profile.Users object with the [IgnoreDataMember] Attribute.

Entity framework: string property is empty after calling SaveChanges

I got a mapped entity named User - with username and pass, the pk is the username.
When saving a new user, the username for some reason becomes an empty string.
Here is a code sample:
var newUser = new User() {Username = model.UserName, Password = hashedPassword};
_db.Users.AddObject(newUser);
_db.SaveChanges();
In debug view I see user name is not empty before save and after save it's empty. Whats wrong with me?
The dev server decided to ignore my reset, so I needed to reset it again and it's fine.