For a school project we have to create an evaluation website that requires a login.
For the database connection I chose LINQ, because it's new and is supposed to be easier/better in use.
I managed to create a login check with the following:
public static Boolean Controle(int id, string wachtwoord)
{
DataClassesDataContext context = new DataClassesDataContext();
var loginGebruiker =
from p in dc.Gebruikers
where p.GebruikerID == id
where p.GebruikerWachtwoord == wachtwoord
select p;
return true;
}
Now I'm trying to create a "forgot password" option, where you enter your id and the password gets returned (later it would be emailed to you, don't know how I would do this either, suggestions?)
I tried with the following code:
public static string Forgot(int id)
{
var context = new DataClassesDataContext();
var wachtwoordLogin = (
from p in dc.Gebruikers
where p.GebruikerID == id
select p.GebruikerWachtwoord);
return wachtwoordLogin.ToString();
}
Code behind the button on the page:
lbl1.Text = Class1.Forgot(Convert.ToInt32(txt1.Text));
Now when I enter the an id of the first user (1), lbl1 becomes this:
SELECT [t0].[GebruikerWachtwoord] FROM
[dbo].[Gebruiker] AS [t0] WHERE
[t0].[GebruikerID] = #p0
I don't know how to solve this and I have been looking everywhere, I hope somebody can help me.
Thanks,
Thomas
LINQ uses delayed execution, so your 'wachtwoordLogin' is really just "how to get your data." Its not until you apply an operator that LINQ will actually attempt to retrieve your data.
Your first statement:
var loginGebruiker = (
from p in dc.Gebruikers
where p.GebruikerID == id
where p.GebruikerWachtwoord == wachtwoord
select p).FirstOrDefault()
if (loginGeruiker != null) {
//Valid login
} else {
// invalid
}
FirstOrDefault means, take the first item in the list, or return none.
In you other case you need the same thing:
user = wachtwoordLogin.FirstOrDefault();
Further reading: MSDN 101 LINQ Samples
For your question about emailing a forgotten password, have you ever thought about implementing the golden questions algorithm instead? Its simplified, and does the same thing.
Basically, at the time of registering just get them to answer some questions, and if they can verify them, allow them to reset the password.
you enter your id and the password gets returned
What, then, is the point of having a password if anybody who knows a username can see it? I know this isn't what you're asking, but for someone getting started in programming I feel a duty to point this out. What you're creating here is essentially a completely broken login model. Nobody should ever use a system like this.
You should never ever display a password. Not on the screen, not in an email, never.
Passwords, if they even need to be stored at all (CodingHorror has had a couple of good posts on this lately, advocating things like OpenID), should be stored in hashed form and essentially unable to be retrieved. When a user logs in, similarly hash the password they provide (immediately upon reaching the application code, before transporting it anywhere else in the system) and compare that to the stored hashed version.
If the user asks for his password, you don't have it. You can't give it to him. This is for his protection. Instead of providing the user with his password, if it's forgotten then you provide the user with a means to reset his password (sending an email to the address on file with a temporarily available URL, a set of "security questions" to verify his identity, etc.) so that he can enter a new one to overwrite the old one. But you shouldn't be able to "show" the user his password because even you as the administrator of the system shouldn't be able to see it in any usable form.
wachwoordLogin will be an IQueryable so you can get this by using FirstOrDefault() which will return null if not found:
(from p in dc.Gebruikers
where p.GebruikerID == id
select p.GebruikerWachtwoord).FirstOrDefault();
Related
Using a kentico 10 website with claims based authentication. We have the facility to update their email address in the external system. So what I want to do is update the user's email address and username by looking up based on the external userid from our sso platform.
var existingUser = UserInfoProvider.GetUsers().Where("ExternalGuid", QueryOperator.Equals, userId).FirstOrDefault();
if (existingUser.IsInSite(SiteContext.CurrentSiteName))
UserInfoProvider.RemoveUserFromSite(existingUser.UserName, SiteContext.CurrentSiteName);
loggingInUser = UserInfoProvider.GetUserInfo(existingUser.UserID);
loggingInUser.UserName = e.UserName;
UserInfoProvider.SetUserInfo(loggingInUser);
I'm getting the error:
The user with code name 'ac.aa#test.com' already exists.
This is happening on that SetUserInfo line. So I'm thinking there must be another way to update the username properly.
You need to do a few things:
Check if the user exists already:
UserInfo ui = UserInfoProvider.GetUserInfo(newUserName);
if (ui != null)
{
// user exists with new username so don't continue
}
Check if the username can be used as a username (no spaces, special characters, etc):
if (!ValidationHelper.IsUserName(newUserName))
{
// username cannot be used as a username
}
Check if the username is reserved or not:
if (UserInfoProvider.NameIsReserved(siteName, newUserName))
{
// reserved username so cannot use it
}
I'm willing to bet the username is reserved or not valid which is why it is not saving. The assignment you have done should work without issue.
It also looks like you're performing this update in a global handler so this could cause problems with a few things. So you may have to perform that username update later on or simply write a record to a custom table and then update it from there based on the event of creating those records in the custom table.
So I'd debug through your code and verify it is working properly by removing it from the global event handler, if it works, then it's an issue with having too many things happen at one time.
Try using SetValue(string columnName, value) method, I just tested this one and it worked fine:
UserInfo updateUser = UserInfoProvider.GetUserInfo("NewUser");
if (updateUser != null)
{
// Updates the user's properties
updateUser.SetValue("UserName", "NewUserName");
// Saves the changes to the database
UserInfoProvider.SetUserInfo(updateUser);
}
For some properties/columns, which are acting like "read only", you need to use the SetValue method like it was a custom field (API examples)
So I would want below functionality;
Connect to GMAIL for Business using service account (Already DONE)
Get emails from gmail (Got some API)
Connect to office 365 using oAuth access token (Will be done, I think no issues in it)
Copy the gmail message to office 365 message.
How can I do it?
Here is the code done so far to download message from Google;
Console.WriteLine("Connect to Google API");
Console.WriteLine("=====================");
String serviceAccountEmail = "3512650851-4tpr9073rju4deqtfjp210j07q52hu2j#developer.gserviceaccount.com";
var certificate = new X509Certificate2(#"My Project-d3e5dda28438.p12", "notasecret", X509KeyStorageFlags.Exportable);
ServiceAccountCredential credential = new ServiceAccountCredential(
new ServiceAccountCredential.Initializer(serviceAccountEmail)
{
User = "<UserEmail for which to download message>",
Scopes = new[] { GmailService.Scope.GmailCompose, GmailService.Scope.GmailModify }
}.FromCertificate(certificate));
var gmailservice = new Google.Apis.Gmail.v1.GmailService(new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = "MyNewProject",
});
try
{
ListMessagesResponse messages = gmailservice.Users.Messages.List("<User Email>").Execute();
IList<Google.Apis.Gmail.v1.Data.Thread> threads = gmailservice.Users.Threads.List("<User Email>").Execute().Threads;
List<Message> responsemessages = new List<Message>();
responsemessages.AddRange(messages.Messages);
foreach(Message msg in responsemessages)
{
Google.Apis.Gmail.v1.UsersResource.MessagesResource.GetRequest gr = gmailservice.Users.Messages.Get("<User Email>", msg.Id);
gr.Format = Google.Apis.Gmail.v1.UsersResource.MessagesResource.GetRequest.FormatEnum.Full;
Message m = gr.Execute();
if (gr.Format == Google.Apis.Gmail.v1.UsersResource.MessagesResource.GetRequest.FormatEnum.Raw)
{
byte[] decodedByte = FromBase64ForUrlString(m.Raw);
string base64Encoded = Convert.ToString(decodedByte);
MailMessage msg2 = new MailMessage();
//msg2.LoadMessage(decodedByte);
}
}
}
catch (Exception ex) { }
Note: The code is very rough for now. Will make it more formal later..
So basically the question is, How can I upload the message row format to office 365 or is there any COPY api?
I am not aware of any C# library/API that handles email synchronization, but maybe Google finds you something.
If not you will have to 'roll your own'. We are doing exactly that with calendar synchronization (in Delphi). The steps to take are:
[Note that I am answering for full synchronization as your question title says]
Analyze the email formats for both systems in detail. Set up data/storage structures that can handle all formats and their differences. You may have to resort to using 'extended/user defined/custom' properties to store properties of system Y in system X, when not present there. You will surely have to use custom properties for storing typical synchronization data: date of last synchronization, date of last change, maybe mutual IDs*
Read emails from both systems over a certain 'synchronization period'.
Do your own comparison looking for differences (added, deleted, modified emails)
Your comparison may have to take configuration/settings into account like Do we synchronize both ways?, When an email is modified on both sides, which one takes precedence?. That's not really necessary, you can define sensible defaults for that. Many synchronisation systems do, they don't ask your for any configuration, but then the user sometimes has to figure out Huh, why did it update this way?).
Write modifications to the external systems.
No small task, I can tell you, so I doubt it fits your your requirement pragmatically ;-) So first invest heavily in searching if someone has already done this.
(And note that asking for libraries is off-topic in SO)
* You will even have to store 'my own ID' as a custom property for each email. If you don't do that you can't distinguish emails that were copied in the external system.
I was just wondering how you would restrict property access to the $owner role only. For instance in my case I have a Joke which has an Author. The Author has User as base. I would like other "Authers" / Users to see who created the Joke, but they should not be able to see the Authers email, only if the Author is the $owner of the Joke itself it should be OK to show their email, just for the sake of this case.
Looking at the built-in User model you can see that they use the hidden feature to hide the password, but using that for their email will also hide their email for the $owner, which is not what I wanted
Let me know if something is not clear.
Thanks in advance
Register beforeRemote hook and check if current user is the $owner.
Joke.boforeRemote('findById', function(context, joke, next) {
// 1. find current user by id, using context.req.accessToken.userId
// 2. check if he is owner or not, by Role.isOwner
// 3. remove email from returned joke instance if user is not $owner
})
Note: it can be a bit complicated to cover all endpoints that return Jokes. But is there another way to do it?
To modify the output/results, you can use the afterRemote hook, as per the docs. The output/results are stored in ctx.result.
'findById' hooks into your GET requests when the call is like GET http://myModel/id. Use 'find' if you are not including the id in your request e.g. GET http://myModel. Just notice that in case of 'find', the returned instance(s) (joke(s)) is usually not just one so it is in an array of objects.
Joke.afterRemote('findById', function(ctx, joke, next) {
//your code
});
Get the id of current logged-in user: var currentUser = context.req.accessToken.userId
Compare the user id of the current logged-in user with that of the joke owner. If both are not the same (i.e. if (!(currentUser == joke.userId))), then:
before calling next(), remove the email attribute from returned joke instance. Because sometimes some ways don't work, here are a few:
delete ctx.result.email;
ctx.result.email = '';
loop through the attributes and transferring them to a new var, except the email, then save that new var the result: ctx.result = newVar;
You can create your own role resolver. See https://github.com/strongloop/loopback-example-access-control/blob/master/server/boot/role-resolver.js for an example. Just add your own logic once you determine the user.
i am using Devise and devise_security_extension.
https://github.com/plataformatec/devise
https://github.com/phatworx/devise_security_extension
I tried to figure out how i could validate a provided password WITHOUT updating a User record.
Validation (password was not used before, password is complex enough ....)
For example:
john = User.find(1)
john.password = "Testing"
john.password_confirmation = "Testing"
result = john.save
Result would return true or false. With result.errors i would get the related error messages (Thats exactly what i want but without really change this user password).
My Problem is that this would really change the password of this user (object). That would cause problems with old_passwords.
Is there any way to do a dry run ? (result = john.save_dry_run)
FYI:
I already tried to change the User password and change it back after i got the result. But this is really ugly and also make much trouble with devise old_passwords table.
I hope my question is clear enough. If you need any further information please let me know !
You should call valid? rather than save in your example. This will only run the model validations without actually saving any data to the database:
john = User.find(1)
john.password = "Testing"
john.password_confirmation = "Testing"
result = john.valid?
You can find more information in the Rails documentation.
I'm not sure if this is an issue, or just a matter of me not knowing how the OrmLiteAuthRepository should work. I'm trying to make an admin screen that allows admins to update users information. I'm using the OrmLiteAuthRepository.UpdateUserAuth method and passing in a null password to update everything but the password. However, validation is ran as if I'm creating a new user and ValidateNewUser requires me to have a password that is not null even though further in the method there are checks to avoid updating the password if a null password is used. I'm I missing something?
Here is a link to the method call
https://github.com/ServiceStack/ServiceStack/blob/master/src/ServiceStack.ServiceInterface/Auth/OrmLiteAuthRepository.cs#L105
Use SaveUserAuth, I believe UpdateUserAuth is for updating password, though could be wrong.
UserAuth user = this.AuthRepository.GetUserAuth("bob")
if (user.Meta == null)
{
user.Meta = new Dictionary<string, string>();
}
user.Meta.Add("message", "hi bob");
this.AuthRepository.SaveUserAuth(user);