Create new user with more attribute in asmack - smack

I am trying to create new user with more attribute but it is not working.I am using this code with asmack:
ConnectionConfiguration config = new ConnectionConfiguration("SERVER IP", 5222,"localhost");
config.setSecurityMode(SecurityMode.disabled);
XMPPConnection conn2 = new XMPPTCPConnection(config);
conn2.connect();
AccountManager manager =AccountManager.getInstance(conn2);
Map<String, String> attributes = new HashMap<String, String>();
attributes.put("username", "my_user_name");
attributes.put("password", "my_password");
attributes.put("email", "foo#foo.com");
attributes.put("name", "my_full_name");
manager.createAccount("my_user_name", "my_password", attributes);
conn2.login("my_user_name", "my_password");
ChatManager chatmanager = ChatManager.getInstanceFor(conn2);
Log.w("User Name:",""+manager.getAccountAttribute("name"));
But when I try to log with getAccountAttribute all fields are returning null except username and password.
How can I set name,email etc. fields in asmack ?

You can accomplish that with VCard.
To save VCard:
VCard vCard = new VCard();
vCard.setFirstName("foo");
vCard.setEmailHome("foo#foo.com");
vCard.save(conn2);
To load VCard:
VCard vCard = new VCard();
vCard.load(conn2);
String name = vCard.getFirstName();
Note: You have to login first to save VCard.

Related

Exception Azure AD B2C Setting Custom Attribute With GraphServiceClient

Following directions from here: https://learn.microsoft.com/en-us/azure/active-directory-b2c/user-flow-custom-attributes?pivots=b2c-user-flow
I am able to create and get users fine:
// This works!
var graphServiceClient = new GraphServiceClient(
$"https://graph.microsoft.com/beta",
AuthenticationProvider);
var user = await graphClient.Users[userId].Request().GetAsync();
if (user.AdditionalData == null)
user.AdditionalData = new Dictionary<string, object>();
user.AdditionalData[$"extension_xxxxxxx_Apps] = "TestValue";
// this does not work!
result = await graphClient.Users[user.Id].Request().UpdateAsync(msGraphUser);
For xxxxxxx I tried both the Client ID and Object Id from the b2c-extensions-app in my tenant.
Exception:
Microsoft.Graph.ServiceException: 'Code: Request_BadRequest
Message: The following extension properties are not available: extension_xxxxxxx_Apps.
what am I missing? How can I set a custom attribute from GraphServiceClient?
Thank you
Try creating a "new" user rather getting the existing one. When you call UpdateAsync, B2C will only set the properties that you provide (it won't overwrite the other props with null). This may or may not help, but the thing is, we're doing the same thing you do above except with a "new" User, and it works for us.
User b2cUser = await this.GetOurUser(userId);
var additionalData = new Dictionary<string, object>();
additionalData["extension_id-of-extensions-app-here_Foo"] = "Ice Cream Cone";
var updatedB2cUser = new User
{
AdditionalData = additionalData
};
await this.GraphServiceClient.Users[b2cUser.Id].Request().UpdateAsync(updatedB2cUser);
In practice, we include additional props such as Identities, because we use B2C as an identity provider...so the above is some pared-down code from our B2C wrapper showing just the "custom property" part.
Update
Actually, you may just need to remove the hyphens from your extension-app ID and double-check which one you're using.

Is it possible to create a message using Microsoft Graph with a different sent/received date?

I'm working on an application that needs to be able to insert messages into an O365 mailbox with particular dates (similar to a mail migration). I created a version using IMAP with MailKit, and that was a simple matter of setting the date property on the message object:
MimeMessage message = new MimeMessage();
message.From.Add(new MailboxAddress(NameGenerator.AnyName(), EmailAddressGenerator.AnyEmailAddress()));
message.To.Add(new MailboxAddress(m_O365UserID));
message.Subject = StringGenerator.AnyStringOfSizeAndCase(NumberGenerator.RandomNumberBetween(20, 100), CaseType.TitleCase);
BodyBuilder builder = new BodyBuilder
{
HtmlBody = LipsumGenerator.GenerateHtml(NumberGenerator.RandomNumberBetween(3, 10))
};
message.Body = builder.ToMessageBody();
DateTime t = DateTimeGenerator.AnyDateBetween(m_startDate, DateTime.Now);
t = t.Add(DateTimeGenerator.AnyTime());
DateTimeOffset dto = new DateTimeOffset(t);
message.Date = dto;
I was also able to do this in the past with EWS, but I needed to set some extended properties to do it, like this:
ExtendedPropertyDefinition deliveryTime = new Microsoft.Exchange.WebServices.Data.ExtendedPropertyDefinition(0x0E06, MapiPropertyType.SystemTime);
ExtendedPropertyDefinition clientSubmitTime = new Microsoft.Exchange.WebServices.Data.ExtendedPropertyDefinition(0x0039, MapiPropertyType.SystemTime);
ExtendedPropertyDefinition flags = new Microsoft.Exchange.WebServices.Data.ExtendedPropertyDefinition(3591, MapiPropertyType.Integer);
EmailMessage m = new EmailMessage(m_exchangeService);
m.From = EmailAddressGenerator.AnyEmailAddress();
m.ToRecipients.Add(m_emailAddress);
DateTime t = DateTimeGenerator.AnyDateBetween(startDate, DateTime.Now);
t = t.Add(DateTimeGenerator.AnyTime());
m.SetExtendedProperty(deliveryTime, t);
m.SetExtendedProperty(clientSubmitTime, t);
m.SetExtendedProperty(flags, 1);
Both of these approaches can backdate a message to any point that I need. In this case I'm just populating a mailbox with test data to validate the API calls. Trying to do the same thing in graph like this:
Microsoft.Graph.Message message = new Microsoft.Graph.Message();
message.From = new Recipient { EmailAddress = new EmailAddress { Address = EmailAddressGenerator.AnyEmailAddress(), Name = NameGenerator.AnyName() } };
message.ToRecipients = new List<Recipient>();
message.ToRecipients.Append(new Recipient { EmailAddress = new EmailAddress { Address = m_O365UserID } });
message.Subject = StringGenerator.AnyStringOfSizeAndCase(NumberGenerator.RandomNumberBetween(20, 100), CaseType.TitleCase);
DateTime t = DateTimeGenerator.AnyDateBetween(m_startDate, DateTime.Now);
t = t.Add(DateTimeGenerator.AnyTime());
DateTimeOffset dto = new DateTimeOffset(t);
message.ReceivedDateTime = dto;
message.SentDateTime = dto;
message.CreatedDateTime = dto;
message.LastModifiedDateTime = dto;
timestamps the message as of the submission time. I thought I needed to set the same Mapi properties on the message as with EWS, but so far I haven't found a way to do that. I looked into extended properties as outlined here, which says they can be referenced by a type and MAPI property tag. This page says that extended properties can be created on new objects:
To create one or more extended properties in a new resource instance, use the same REST request as creating the instance, and include the properties of the new resource instance and extended property in the request body.
I tried that like this:
Dictionary<string, object> extendedProperties = new Dictionary<string, object>();
extendedProperties.Add("SystemTime 0x0E06",dto.DateTime);
extendedProperties.Add("SystemTime 0x0039", dto.DateTime);
extendedProperties.Add("Integer 0x3591",1);
message.Body = new ItemBody { ContentType = BodyType.Html, Content = LipsumGenerator.GenerateHtml(NumberGenerator.RandomNumberBetween(3, 10)), AdditionalData=extendedProperties};
Which throws an exception:
The property 'SystemTime 0x0E06' does not exist on type 'Microsoft.OutlookServices.ItemBody'. Make sure to only use property names that are defined by the type or mark the type as open type.
I also can't directly create anything on message.SingleValueExtendedProperties, and the same exception happens if I omit SystemTime and just try to set the property with the hex value. I'd like to be able to support Graph for this application-is there any way that anyone knows of to create messages with custom send/receive dates? If I was able to do it in EWS, I'd expect that the newer API should be able to do the same thing.
Edit
#Glen's answer works. I'd tried the same thing, but still had a second definition of the property that I was trying to add to the message body, which was what actually caused the exception. The only other thing to add to his answer is that the time format for the property needs to be in a very specific format, so you can format a standard DateTimeOffset to a mapi compatible time like this:
string mapiTime = $"{dto.UtcDateTime.Year}-{dto.UtcDateTime.Month.ToString("D2")}-{dto.UtcDateTime.Day.ToString("D2")}T{dto.UtcDateTime.TimeOfDay.ToString()}.0{dto.Offset.Hours.ToString("D2")}:00";
message.SingleValueExtendedProperties = new MessageSingleValueExtendedPropertiesCollectionPage()
{
new SingleValueLegacyExtendedProperty {Id = "Integer 0x0E07",Value = "1" },
new SingleValueLegacyExtendedProperty {Id = "SystemTime 0x0039", Value = mapiTime },
new SingleValueLegacyExtendedProperty {Id = "SystemTime 0x0E06",Value = mapiTime }
};
You should be able to do something like
Microsoft.Graph.Message message = new Microsoft.Graph.Message();
message.From = new Recipient { EmailAddress = new EmailAddress { Address = "blah#blah.com", Name = "blah" } };
message.ToRecipients = new List<Recipient>() { new Recipient { EmailAddress = new EmailAddress { Address = "ToBalh#blah.com" } } };
message.Subject = "Blah";
message.SingleValueExtendedProperties = new MessageSingleValueExtendedPropertiesCollectionPage()
{
new SingleValueLegacyExtendedProperty {Id = "Integer 0x0E07",Value = "1" },
new SingleValueLegacyExtendedProperty {Id = "SystemTime 0x0039", Value = "2020-05-12T10:10:47.2048+10:00" },
new SingleValueLegacyExtendedProperty {Id = "SystemTime 0x0E06",Value = "2020-05-12T10:10:47.2048+10:00" }
};
var SaveMessage = graphClient.Me.MailFolders["Inbox"].Messages.Request().AddAsync(message).Result;
works for me okay

Updating user data - ASP.NET Identity

I've added custom fields to the ApplicationUser class
I've also created a form through which the user can enter/edit the fields.
However for some reason I'm not able to update the fields in the database.
[HttpPost]
[ActionName("Edit")]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Manage(EditProfileViewModel model)
{
if (ModelState.IsValid)
{
// Get the current application user
var user = User.Identity.GetApplicationUser();
// Update the details
user.Name = new Name { First = model.FirstName, Last = model.LastName, Nickname = model.NickName };
user.Birthday = model.Birthdate;
// This is the part that doesn't work
var result = await UserManager.UpdateAsync(user);
// However, it always succeeds inspite of not updating the database
if (!result.Succeeded)
{
AddErrors(result);
}
}
return RedirectToAction("Manage");
}
My problem is similar to MVC5 ApplicationUser custom properties, but that seems to use an older version of Identity because the IdentityManager class doesn't seem to exist.
Can someone guide me on how to update User info in the database?
UPDATE:
If I include all the fields in the register form, all the values are stored in the appropriate field in a new record of the Users table from the database.
I don't know to make changes to the fields of an existing user (row in the users table). UserManager.UpdateAsync(user) doesn't work.
Also note my issue is more Identity oriented than EntityFramework
OK... I spent hours trying to figure why userManager.updateAsync would not persist the user data that we edit ... until I reached the following conclusion:
The confusion arises from the fact that we create the UserManager in one line like this:
var manager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(new MyDbContext()));
...then we use manager.UpdateAsync( user ); but that will update the user in the context, and then we will need to save changes to the dbcontext of the Identity. So, the question is how to get the Identity DBcontext in the easiest way.
To solve this, we should not create the UserManager in one line ... and here is how I do it:
var store = new UserStore<ApplicationUser>(new MyDbContext());
var manager = new UserManager(store);
then after updating the user by calling
manager.UpdateAsync(user);
then you go to the context
var ctx = store.context;
then
ctx.saveChanges();
wahooooooo...persisted :)
Hope this will help someone who pulled their hair for a few hours :P
If you leave any of the fields for ApplicationUser OR IdentityUser null the update will come back as successful but wont save the data in the database.
Example solution:
ApplicationUser model = UserManager.FindById(User.Identity.GetUserId())
Add the newly updated fields:
model.Email = AppUserViewModel.Email;
model.FName = AppUserViewModel.FName;
model.LName = AppUserViewModel.LName;
model.DOB = AppUserViewModel.DOB;
model.Gender = AppUserViewModel.Gender;
Call UpdateAsync
IdentityResult result = await UserManager.UpdateAsync(model);
I have tested this and it works.
The OWIN context allows you to get the db context. Seems to be working fine so far me, and after all, I got the idea from the ApplciationUserManager class which does the same thing.
internal void UpdateEmail(HttpContext context, string userName, string email)
{
var manager = context.GetOwinContext().GetUserManager<ApplicationUserManager>();
var user = manager.FindByName(userName);
user.Email = email;
user.EmailConfirmed = false;
manager.Update(user);
context.GetOwinContext().Get<ApplicationDbContext>().SaveChanges();
}
The UserManager did not work, and As #Kevin Junghans wrote,
UpdateAsync just commits the update to the context, you still need to save the context for it to commit to the database
Here is quick solution (prior to new features in ASP.net identity v2) I used in a web forms projetc. The
class AspNetUser :IdentityUser
Was migrated from SqlServerMembership aspnet_Users. And the context is defined:
public partial class MyContext : IdentityDbContext<AspNetUser>
I apologize for the reflection and synchronous code--if you put this in an async method, use await for the async calls and remove the Tasks and Wait()s. The arg, props, contains the names of properties to update.
public static void UpdateAspNetUser(AspNetUser user, string[] props)
{
MyContext context = new MyContext();
UserStore<AspNetUser> store = new UserStore<AspNetUser>(context);
Task<AspNetUser> cUser = store.FindByIdAsync(user.Id);
cUser.Wait();
AspNetUser oldUser = cUser.Result;
foreach (var prop in props)
{
PropertyInfo pi = typeof(AspNetUser).GetProperty(prop);
var val = pi.GetValue(user);
pi.SetValue(oldUser, val);
}
Task task = store.UpdateAsync(oldUser);
task.Wait();
context.SaveChanges();
}
I also had problems using UpdateAsync when developing a version of SimpleSecurity that uses ASP.NET Identity. For example, I added a feature to do a password reset that needed to add a password reset token to the user information. At first I tried using UpdateAsync and it got the same results as you did. I ended up wrapping the user entity in a repository pattern and got it to work. You can look at the SimpleSecurity project for an example. After working with ASP.NET Identity more (documentation is still non-existent) I think that UpdateAsync just commits the update to the context, you still need to save the context for it to commit to the database.
I have tried the functionality in the same way and when i call UserManager.Updateasync method it succeeds but there is no update in the database. After spending some time i found another solution to update the data in aspnetusers table which is following:
1) you need to create UserDbContext class inheriting from IdentityDbContext class like this:
public class UserDbContext:IdentityDbContext<UserInfo>
{
public UserDbContext():
base("DefaultConnection")
{
this.Configuration.ProxyCreationEnabled = false;
}
}
2) then in Account controller update user information like this:
UserDbContext userDbContext = new UserDbContext();
userDbContext.Entry(user).State = System.Data.Entity.EntityState.Modified;
await userDbContext.SaveChangesAsync();
where user is your updated entity.
hope this will help you.
Excellent!!!
IdentityResult result = await UserManager.UpdateAsync(user);
Based on your question and also noted in comment.
Can someone guide me on how to update User info in the database?
Yes, the code is correct for updating any ApplicationUser to the database.
IdentityResult result = await UserManager.UpdateAsync(user);
Check for constrains of all field's required values
Check for UserManager is created using ApplicationUser.
UserManager<ApplicationUser> UserManager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(new ApplicationDbContext()));
This works for me. I'm using Identity 2.0, it looks like GetApplicationUser isn't there anymore.
var user = await UserManager.FindByIdAsync(User.Identity.GetUserId());
if (!string.IsNullOrEmpty(form["FirstName"]))
{
user.FirstName = form["FirstName"];
}
if (!string.IsNullOrEmpty(form["LastName"]))
{
user.LastName = form["LastName"];
}
IdentityResult result = await UserManager.UpdateAsync(user);
I am using the new EF & Identity Core and I have the same issue, with the addition that I've got this error:
The instance of entity type cannot be tracked because another instance
of this type with the same key is already being tracked.
With the new DI model I added the constructor's Controller the context to the DB.
I tried to see what are the conflict with _conext.ChangeTracker.Entries() and adding AsNoTracking() to my calls without success.
I only need to change the state of my object (in this case Identity)
_context.Entry(user).State = EntityState.Modified;
var result = await _userManager.UpdateAsync(user);
And worked without create another store or object and mapping.
I hope someone else is useful my two cents.
Add the following code to your Startup.Auth.cs file under the static constructor:
UserManagerFactory = () => new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(new ApplicationDbContext()));
OAuthOptions = new OAuthAuthorizationServerOptions
{
TokenEndpointPath = new PathString("/Token"),
Provider = new ApplicationOAuthProvider(PublicClientId, UserManagerFactory),
AuthorizeEndpointPath = new PathString("/api/Account/ExternalLogin"),
AccessTokenExpireTimeSpan = TimeSpan.FromDays(14),
AllowInsecureHttp = true
};
The UserManagerFactory setting line of code is what you use to associate your custom DataContext with the UserManager. Once you have done that, then you can get an instance of the UserManager in your ApiController and the UserManager.UpdateAsync(user) method will work because it is using your DataContext to save the extra properties you've added to your custom application user.
I am using .Net Core 3.1 or higher version.Please follow the solution:
public class UpdateAssignUserRole
{
public string username { get; set; }
public string rolename { get; set; }
public bool IsEdit { get; set; }
}
private async Task UpdateSeedUsers(UserManager<IdentityUser> userManager, UpdateAssignUserRole updateassignUsername)
{
IList<Users> Users = await FindByUserName(updateassignUsername.username);
if (await userManager.FindByNameAsync(updateassignUsername.username) != null)
{
var user = new IdentityUser
{
UserName = updateassignUsername.username,
Email = Users[0].Email,
};
var result = await userManager.FindByNameAsync(updateassignUsername.username);
if (result != null)
{
IdentityResult deletionResult = await userManager.RemoveFromRolesAsync(result, await userManager.GetRolesAsync(result));
if (deletionResult != null)
{
await userManager.AddToRoleAsync(result, updateassignUsername.rolename);
}
}
}
}

save form values through script file in umbraco

hello i want to save the value of umbraco form in database for this i have made script file and in this script file i have created function to save data and called this function in same script file and this script file is used in macro and i have called this macro in template of my page but it is not working will this approach is proper or i have to something else my basic aim is to save data in database without creating my usercontrol
code is
#functions
{
public void AddToCart()
{
string con = System.Configuration.ConfigurationManager.AppSettings["umbracoDbDSN"].ToString();
SqlConnection OnCon = new SqlConnection(System.Configuration.ConfigurationManager.AppSettings["umbracoDbDSN"].ToString());
ItemsDataContext db = new ItemsDataContext(con);
var request = HttpContext.Current.Request;
string itemcode= request.Form["ItemCode"].ToString();
string itemname = request.Form["ItemName"].ToString();
string itemcategory = Request.Form["ItemCategory"].ToString();
string userid = "Pallavi";
db.sp_AddItems(userid, itemcode, itemcategory, itemname, 0);
HttpContext.Current.Session["UserId"] = "Pallavi";
}
}
#if (!IsPost)
{
AddToCart();
}
and called this macro on template
<umbraco:Macro Alias="Uc_Cart" runat="server"></umbraco:Macro>
You approach is wrong. You must use the methods that Umbraco provides in their API and do not try to write data into the database directly.
Try this code to create an new document from Razor code:
#using umbraco.BusinessLogic;
#using umbraco.cms.businesslogic.web;
#{
DocumentType dt = DocumentType.GetByAlias("Textpage");
User author = umbraco.BusinessLogic.User.GetUser(0);
Document doc = Document.MakeNew("My new document", dt, author, parentID);
}
The example above is for Umbraco 4.x. If you're using Umbraco v6.x you could also use the new API methods:
#{
// get an instance of the contentService
var contentService = ApplicationContext.Services.ContentService;
// create new content, the last param is the userId and is optional [default = 0]
IContent newContent = contentService.CreateContent("My new document", parentID, "Textpage", 0);
// set property values
newContent.SetValue("propertyAlias", "Value");
// save (or save and publish)
contentService.Save(newContent);
}

Find method throws value cannot be null. parameter name key entity framework

I use EF 4.
Having this code to test the functionality of my model.
using (var context = new CamelotDB())
{
Console.WriteLine("Starting User Repository Testing{0}",Environment.NewLine);
Console.WriteLine("Creating Test User");
DomainEntity userToAdd = new User()
{
EntityName = "Test User",
EntityType = DomainEntity.eEntityType.User,
Username = "TestUser",
Password = "123",
Email = "TestUser#Test.org",
FirstName = "Test",
LastName = "User",
Phone = "123456789",
EntityParentID = null,
};
Console.WriteLine("Saving user to database...");
userToAdd = context.DomainEntities.Add(userToAdd);
context.SaveChanges();
Console.WriteLine("Fetching user from database...");
int userID = userToAdd.EntityID;
DomainEntity userToDelete = context.DomainEntities.Find(userID);
Console.WriteLine("Removing the user...");
context.DomainEntities.Remove(userToDelete);
context.SaveChanges();
}
The user adds successfully to the DB and i get back the userID.
When I try to use the Find() method in
DomainEntity userToDelete = context.DomainEntities.Find(userID);
I get the following error: value cannot be null. parameter name key
I event tried to call the follwing:
DomainEntity userToDelete = context.DomainEntities.Find(2);
Knowing that the userID 2 exists in the DB but still got the same Exception.
Got it fixed somehow... just removed the key property from the EDMX and added it again the save changes and everything went back to normal guess it was something to do with the EDMX generation...

Resources