Azure AD B2C with Graph API - how to get/set user's email? - azure-active-directory

I add users to Azure AD B2C with Graph API but I don't get it how to store users' email (the primary one). Which field here is the user's primary email address?
As I read here on SO there's no way to populate values in Authentication contact info. It this correct?

Here's how I do it:
public async Task<AdUser> GetUserByObjectId(Guid objectId)
{
string userJson = await SendGraphGetRequest("/users/" + objectId, null);
JObject jUser = JObject.Parse(userJson);
return new AdUser(jUser);
}
internal AdUser(JObject jUser)
{
AccountEnabled = jUser["accountEnabled"].Value<bool>();
CompanyName = jUser["companyName"].Value<string>();
Department = jUser["department"].Value<string>();
DisplayName = jUser["displayName"].Value<string>();
FirstName = jUser["givenName"].Value<string>();
JobTitle = jUser["jobTitle"].Value<string>();
LastName = jUser["surname"].Value<string>();
MailNickname = jUser["mailNickname"].Value<string>();
Mobile = jUser["mobile"].Value<string>();
ObjectId = new Guid(jUser["objectId"].Value<string>());
List<string> mailList = new List<string>(jUser["otherMails"].Count());
mailList.AddRange(jUser["otherMails"].Select(mail => mail.Value<string>()));
OtherMails = mailList.AsReadOnly();
Phone = jUser["telephoneNumber"].Value<string>();
List<(string type, string value)> signInNames = jUser["signInNames"].Select(jToken => (jToken["type"].Value<string>(), jToken["value"].Value<string>())).ToList();
SignInNames = signInNames.AsReadOnly();
UserPrincipalName = jUser["userPrincipalName"].Value<string>();
UserType = jUser["userType"].Value<string>();
}
and here's the Email property of the AdUser:
public string Email
{
get
{
if (SignInNames.Count > 0 && SignInNames[0].type == "emailAddress")
return SignInNames[0].value;
if (OtherMails.Count > 0)
return OtherMails[0];
throw new InvalidOperationException("Don't know where to get user Email");
}
}

You need to make a PATCH request to the users endpoint
{baseurl}/{tenantId}/users?api-version={apiVersion}
Don't forget you access token in the auth header:
Authorization: Bearer {accessToken}
Here's an example model (Java) with methods for calculating and setting the sign-in email on a user object:
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import java.util.ArrayList;
import java.util.List;
#JsonIgnoreProperties(ignoreUnknown = true)
public class GraphApiUserExample{
#JsonProperty("objectId")
private String id;
private Boolean accountEnabled;
private PasswordProfile PasswordProfile;
private List<SignInName> signInNames;
private String surname;
private String displayName;
private String givenName;
#JsonProperty("userPrincipalName")
private String userPrincipalName;
public String getId(){
return id;
}
public void setId(final String id){
this.id = id;
}
public Boolean getAccountEnabled(){
return accountEnabled;
}
public void setAccountEnabled(final Boolean accountEnabled){
this.accountEnabled = accountEnabled;
}
public PasswordProfile getPasswordProfile(){
return passwordProfile;
}
public void setPasswordProfile(final PasswordProfile passwordProfile){
this.passwordProfile = passwordProfile;
}
public List<SignInName> getSignInNames(){
return signInNames;
}
public void setSignInNames(final List<SignInName> signInNames){
this.signInNames = signInNames;
}
public String getSurname(){
return surname;
}
public void setSurname(final String surname){
this.surname = surname;
}
public String getDisplayName(){
return displayName;
}
public void setDisplayName(final String displayName){
this.displayName = displayName;
}
public String getGivenName(){
return givenName;
}
public void setGivenName(final String givenName){
this.givenName = givenName;
}
public String getUserPrincipalName(){
return userPrincipalName;
}
public void setUserPrincipalName(final String userPrincipalName){
this.userPrincipalName = userPrincipalName;
}
#JsonIgnore
public String getSignInEmail(){
String email = "";
if(signInNames != null){
for(SignInName signInName : signInNames){
if(signInName.getType().equals("emailAddress")){
email = signInName.getValue();
break;
}
}
}
return email;
}
#JsonIgnore
public void setSignInEmail(String signInEmail){
if(signInNames == null){
signInNames = new ArrayList<>();
signInNames.add(new SignInName("emailAddress", signInEmail));
return;
}
for(SignInName signInName : signInNames){
if(signInName.getType().equals("emailAddress")){
signInName.setValue(signInEmail);
break;
}
}
}
}
SignInName:
public class SignInName {//userName or emailAddress
private String
type,
value;
public String getType(){
return type;
}
public void setType(final String type){
this.type = type;
}
public String getValue(){
return value;
}
public void setValue(final String value){
this.value = value;
}
}
PasswordProfile:
#JsonIgnoreProperties(ignoreUnknown = true)
public class PasswordProfile {
private String password;
private Boolean forceChangePasswordNextLogin;
public String getPassword(){
return password;
}
public void setPassword(final String password){
this.password = password;
}
public Boolean getForceChangePasswordNextLogin(){
return forceChangePasswordNextLogin;
}
public void setForceChangePasswordNextLogin(final Boolean forceChangePasswordNextLogin){
this.forceChangePasswordNextLogin = forceChangePasswordNextLogin;
}
}

Related

Is there a way to create an object with foreign key being null at first and then to set it later in spring boot JPA?

I have a one to one relation between two classes. I want to create phase items without having to insert candidate Id with it, because I get candidates afterwards so they basically don't exist.
Right now I'm getting the error:
could not execute statement; SQL [n/a]; constraint [null];
because i'm not sending candidateId with it.
This is the first class :
public class PhaseItems {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "phaseI_id")
private long id;
private String PhaseItem;
#ManyToMany(fetch = FetchType.LAZY,
mappedBy = "items")
#JsonIgnore
private List<PhaseTemplate> template = new ArrayList<>();
#OneToOne(fetch = FetchType.LAZY, optional = true)
#JoinColumn(name = "candidate_id", nullable = true)
private Candidate candidate;
public PhaseItems() {
super();
}
public PhaseItems(long id, String phaseItem) {
super();
this.id = id;
PhaseItem = phaseItem;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getPhaseItem() {
return PhaseItem;
}
public void setPhaseItem(String phaseItem) {
PhaseItem = phaseItem;
}
public List<PhaseTemplate> getTemplate() {
return template;
}
public void setTemplate(List<PhaseTemplate> template) {
this.template = template;
}
public Candidate getCandidate() {
return candidate;
}
public void setCandidate(Candidate candidate) {
this.candidate = candidate;
}
#Override
public String toString() {
return "PhaseItems [id=" + id + ", PhaseItem=" + PhaseItem + ", template=" + template + "]";
}
This is the second class:
#Entity
#Table(name= "candidats")
public class Candidate {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "candidate_id")
private long id;
private String fullname;
private String username;
#Column(nullable = false, unique = true, length = 45)
private String email;
private String adress;
private String phoneNumber;
private String password;
#Column(name = "status")
private String status;
#OneToOne(fetch = FetchType.LAZY,
cascade = CascadeType.ALL,
mappedBy = "candidate")
private PhaseItems phases;
public Candidate(){
}
public Candidate(String fullname,String username,String email, String adress, String phoneNumber, String password,
List<JobApplication> appliedJobs) {
super();
this.fullname = fullname;
this.username = username;
this.email = email;
this.adress = adress;
this.phoneNumber = phoneNumber;
this.password = password;
this.appliedJobs = appliedJobs;
}
public Candidate(String fullname,String username, String email, String adress, String phoneNumber, String password) {
super();
this.fullname = fullname;
this.username = username;
this.email = email;
this.adress = adress;
this.phoneNumber = phoneNumber;
this.password = password;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getFullname() {
return fullname;
}
public void setFullname(String fullname) {
this.fullname = fullname;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getAdress() {
return adress;
}
public void setAdress(String adress) {
this.adress = adress;
}
public String getPhoneNumber() {
return phoneNumber;
}
public void setPhoneNumber(String phoneNumber) {
this.phoneNumber = phoneNumber;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public List<JobApplication> getAppliedJobs() {
return appliedJobs;
}
public void setAppliedJobs(List<JobApplication> appliedJobs) {
this.appliedJobs = appliedJobs;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
Set column candidate_id as nullable in your database. Java attribute nullable = true of #JoinColumn annotation is ignored.
Is your column « candidate_id » from table phase_items nullable in your schema ?

Why are Collection properties indexed in objectify, sometimes?

In objectify, when I define a collection property with String datatype,
#IgnoreSave(IfEmpty.class)
private Set<String> collectionProperty = new HashSet<>();
and then look at a record in datastore, it appears indexed even though I have not annotated it with #Index.
Contrary, when I use a complex Object instead String, it does not appear as indexed.
Why are Collection properties indexed sometimes and sometimes not? And is there a way to determine this?
--
Unmodified code and screenshot from admin console/datastore:
#Entity
#Cache(expirationSeconds = 900)
public class Item extends StringId implements Serializable {
private static final Logger log = Logger.getLogger(Item.class.getSimpleName());
private static final long serialVersionUID = 1;
// Constructors
private Item() {}
#Nonnull
private static Item create(#Nonnull String itemId) {
Item item = (Item) new Item().setId(itemId);
item.piecesFromId();
log.info("item = " + JsonHelper.logToJson(item));
return item;
}
#Nonnull
public static Item create(#Nonnull String provider, #Nonnull String type, #Nonnull String identifier) {
String itemId = IdHelper.createItemId(provider, type, identifier);
Item item = ((Item) new Item().setId(itemId))
.setProvider(provider)
.setType(type)
.setIdentifier(identifier);
log.info("item = " + JsonHelper.logToJson(item));
return item;
}
#Nonnull
public static Item loadOrCreate(#Nonnull String itemId) {
Item item = ofy().load().type(Item.class).id(itemId).now();
if (item == null) {
item = Item.create(itemId);
}
return item;
}
#Nullable
public static Item load(#Nonnull String itemId) {
return ofy().load().type(Item.class).id(itemId).now();
}
#OnLoad
private void piecesFromId() {
provider = IdHelper.getProvider(id);
type = IdHelper.getType(id);
identifier = IdHelper.getIdentifier(id);
}
public Item save() {
ofy().defer().save().entity(this);
return this;
}
#OnSave
private void integrity() {
if (id == null) { throw new RuntimeException("Id must not be null."); }
if (itemPreview == null) { throw new RuntimeException("itemPreview must not be null."); }
if (provider == null || type == null || identifier == null) { throw new RuntimeException("provider, type and identifier must not be null."); }
if (!id.equals(IdHelper.createItemId(provider, type, identifier))) { throw new RuntimeException("id does not coincide with provider, type and identifier."); }
if (!id.equals(itemPreview.getItemId())) { throw new RuntimeException("id does not coincide with id in itemPreview."); }
}
#OnSave
private void timestamp() {
if (created == null) {
created = System.currentTimeMillis();
}
}
// Properties
#Ignore
private String provider;
#Ignore
private String type;
#Ignore
private String identifier;
#Ignore // json
private ItemPreview itemPreview;
#ApiResourceProperty(ignored = AnnotationBoolean.TRUE)
#IgnoreSave(IfEmpty.class)
private Set<String> subscribedUserIds = new HashSet<>();
#ApiResourceProperty(ignored = AnnotationBoolean.TRUE)
#IgnoreSave(IfEmpty.class)
private Set<String> notifyUserIds = new HashSet<>();
#ApiResourceProperty(ignored = AnnotationBoolean.TRUE)
#IgnoreSave(IfEmpty.class)
private Set<String> blacklistingUserIds = new HashSet<>();
#ApiResourceProperty(ignored = AnnotationBoolean.TRUE)
private Long created;
#ApiResourceProperty(ignored = AnnotationBoolean.TRUE)
#IgnoreSave(IfDefault.class)
#Index
private Status status = Status.ACTIVE;
#ApiResourceProperty(ignored = AnnotationBoolean.TRUE)
#IgnoreSave(IfNull.class)
private String suspensionNotice;
// Json
#ApiResourceProperty(ignored = AnnotationBoolean.TRUE)
#IgnoreSave(IfNull.class)
private String itemPreviewJson;
private static Type itemPreviewType = new TypeToken<ItemPreview>(){}.getType();
#OnLoad
private void itemPreviewFromJson() {
if (itemPreviewJson != null) {
itemPreview = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create()
.fromJson(itemPreviewJson, itemPreviewType);
}
}
#OnSave
private void itemPreviewToJson() {
itemPreviewJson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create()
.toJson(itemPreview, itemPreviewType);
}
// Accessors
public String getProvider() {
return provider;
}
public Item setProvider(String provider) {
this.provider = provider;
return this;
}
public String getType() {
return type;
}
public Item setType(String type) {
this.type = type;
return this;
}
public String getIdentifier() {
return identifier;
}
public Item setIdentifier(String identifier) {
this.identifier = identifier;
return this;
}
public ItemPreview getItemPreview() {
return itemPreview;
}
public Item setItemPreview(ItemPreview itemPreview) {
this.itemPreview = itemPreview;
return this;
}
public Set<String> getSubscribedUserIds() {
return subscribedUserIds;
}
public Item setSubscribedUserIds(Set<String> subscribedUserIds) {
this.subscribedUserIds = subscribedUserIds;
return this;
}
public Set<String> getNotifyUserIds() {
return notifyUserIds;
}
public Item setNotifyUserIds(Set<String> notifyUserIds) {
this.notifyUserIds = notifyUserIds;
return this;
}
public Set<String> getBlacklistingUserIds() {
return blacklistingUserIds;
}
public Item setBlacklistingUserIds(Set<String> blacklistingUserIds) {
this.blacklistingUserIds = blacklistingUserIds;
return this;
}
public Long getCreated() {
return created;
}
public Item setCreated(Long created) {
this.created = created;
return this;
}
public Status getStatus() {
return status;
}
public Item setStatus(Status status) {
this.status = status;
return this;
}
public String getSuspensionNotice() {
return suspensionNotice;
}
public Item setSuspensionNotice(String suspensionNotice) {
this.suspensionNotice = suspensionNotice;
return this;
}
// Collections
public static Map<String, Item> loadAll(Set<String> itemIds) {
return ofy().load().type(Item.class).ids(itemIds);
}
}

Spring MVC + AngularJs: JSON/Model values set to null

I am trying submit json data to a Spring MVC controller mapped with a model. Instead of getting the json values, the values of the fields of the model are all NULL.
IDE debugger:
Chrome:
Exception:
org.springframework.dao.InvalidDataAccessApiUsageException: The given id must not be null!; nested exception is java.lang.IllegalArgumentException: The given id must not be null!
Controller:
#RequestMapping(value = "/update", method = RequestMethod.POST)
#ResponseBody
public PostResponse update(Setting setting, BindingResult bindingResult) {
return settingService.processUpdate(setting, bindingResult, messageSource);
}
JSON data:
{
"updatedAt":1460600207000,
"id":1,
"createdBy":null,
"description":"This is a setting",
"code":"MY_SETTING",
"value":"{\"id\":\"1018\",\"title\":\"Another setting\",\"code\":\"220-203-10-101\"}"
}
Model:
#Entity
#JsonIgnoreProperties(ignoreUnknown = true)
public class Setting {
#Id
#GeneratedValue
#Column
private Integer id;
#Column(unique = true)
private String code;
#Column
private String description;
#Column
private String value;
#Temporal(TemporalType.TIMESTAMP)
#Column(nullable = false)
private Date createdAt;
#Temporal(TemporalType.TIMESTAMP)
#Column(nullable = false)
private Date updatedAt;
#NotFound(action = NotFoundAction.IGNORE)
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name="FK_createdByUserId")
private User createdBy;
public Setting() {}
public Setting(String code, String description, String value, Date createdAt, Date updatedAt, User createdBy) {
this.code = code;
this.description = description;
this.value = value;
this.createdAt = createdAt;
this.updatedAt = updatedAt;
this.createdBy = createdBy;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public Date getCreatedAt() {
return createdAt;
}
public void setCreatedAt(Date createdAt) {
this.createdAt = createdAt;
}
public Date getUpdatedAt() {
return updatedAt;
}
public void setUpdatedAt(Date updatedAt) {
this.updatedAt = updatedAt;
}
public User getCreatedBy() {
return createdBy;
}
public void setCreatedBy(User createdBy) {
this.createdBy = createdBy;
}
I guess that the setting bean is not mapped at all.
You need to tell spring how to map the http request to the method arguments. If you're posting data, the best way is to add #RequestBody annotation to the relevant method argument (setting in your case)
Modify your controller method like this:
#RequestMapping(value = "/update", method = RequestMethod.POST)
#ResponseBody
public PostResponse update(#RequestBody Setting setting, BindingResult bindingResult) {
return settingService.processUpdate(setting, bindingResult, messageSource);
}

JsonMappingException: Infinite recursion in Cloud Endpoints

I created an app server using Google Endpoints, it is a backend for an instant messaging app. Every user has a list of friends.
When I create a new friend, I am adding users to each other's friend list using the method below. However, it is giving me following error when I add a friend, because of circular dependency.
I looked at other questions and solutions posted. Most of them are structured differently and they didn't solve my problem.
One answer in this website recommends adding #JSONIgnore, but I don't have any field to add that. I tried to put #JsonManagedReference but I couldn't figure out where to put #JSONBackReference. Other examples on this website, usually have another field that refers to parent, but I don't have it.
Thanks for your help in advance.
Error 500 com.google.appengine.repackaged.org.codehaus.jackson.map.JsonMappingException:
Infinite recursion (StackOverflowError) (through reference chain: com.google.common.collect.TransformingRandomAccessList[0]-
>com.net.myapplication.backend.model.User[\"friends\"]->com.google.common.collect.TransformingRandomAccessList[0]-
>com.net.myapplication.backend.model.User[\"friends\"]-
addFriend method
#ApiMethod(name = "addFriend", httpMethod = "post")
public User addFriend(#Named("regId") String regId, #Named("email") String email) {
User user = findRecord(regId);
User friend = findRecordByEmail(email);
if (user == null){
log.info("User " + regId + " is not registered.");
} else{
if (friend == null){
log.info("User " + email + " is not registered.");
} else{
if (hasFriend(user, friend)){
log.info("User " + email + " is already a friend.");
} else {
user.getFriendsRef().add(Ref.create(friend));
friend.getFriendsRef().add(Ref.create(user));
ofy().save().entity(friend).now();
ofy().save().entity(user).now();
return friend;
}
}
}
return null;
}
User model
#Entity
public class User {
#Id
Long id;
#Index
private String regId;
private String firstName;
private String lastName;
#Index
private String email;
private Language language;
#Load
private List<Ref<User>> friends = new ArrayList<>();
public User() {}
public User(Long id, String regId, String firstName, String lastName, String email, Language language, List<Ref<User>> friends) {
this.id = id;
this.regId = regId;
this.firstName = firstName;
this.lastName = lastName;
this.email = email;
this.language = language;
this.friends = friends;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getRegId() {
return regId;
}
public void setRegId(String regId) {
this.regId = regId;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public Language getLanguage() {
return language;
}
public void setLanguage(Language language) {
this.language = language;
}
public List<User> getFriends() {
return Deref.deref(friends);
}
#ApiResourceProperty(ignored = AnnotationBoolean.TRUE)
public List<Ref<User>> getFriendsRef(){
return friends;
}
public void setFriends(ArrayList<Ref<User>> friends) {
this.friends = friends;
}
}
It sounds like this question is: "How do I return data structures with cycles through Cloud Endpoints?"
If it serializes data with vanilla Jackson (Jackson 1.x, from the look of that stacktrace), you can't. Jackson 2 has support for JSOG, but that would mean abandoning Cloud Endpoints:
https://github.com/jsog/jsog
https://github.com/jsog/jsog-jackson

Children are not fetch with Parent in jdo

i am using gwt with jdo datanucleus. i have requirement to get child with parent. but i am not getting child when access parent.
my code is as following
my parent class is
#PersistenceCapable(identityType = IdentityType.APPLICATION, table = "user")
public class User implements Serializable {
private static final long serialVersionUID = 2660867968471555842L;
#PrimaryKey
#Persistent
private String email;
#Persistent(defaultFetchGroup = "true",mappedBy="user")
private UserProfile profile;
public User() {}
public User(String email) {
this.email = email;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public UserProfile getProfile() {
return profile;
}
public void setProfile(UserProfile profile) {
this.profile = profile;
}
}
and my child class is
#PersistenceCapable(identityType = IdentityType.APPLICATION,table = "user_profile")
public class UserProfile implements Serializable {
private static final long serialVersionUID = -6818036410894395030L;
#PrimaryKey
#Persistent(defaultFetchGroup="true")
private User user;
#Persistent
private String name;
public UserProfile() {}
public UserProfile(User user) {
this.user = user;
user.setProfile(this);
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
i am fetching data by following query
PersistenceManager pm = PMF.get().getPersistenceManager();
User user=null;
try{
String userId ="abc#abc.com";
Query userQuery = pm.newQuery(User.class);
userQuery.setFilter("email == '" + userId + "'");
userQuery.setUnique(true);
user = (User) userQuery.execute();
} catch (Exception e) {
throw new IllegalAccessError("Failed to get the User..");
}finally{
pm.close();
}
but i am getting userprofile null in object user.
where is the problem ?
how to load children with parent ?
I'm not sure if you found your answer, but for those that stumble across this I just wanted to share how I got it working.
#PersistenceCapable(detachable = "true")
#FetchGroup(name = "fooGroup", members = { #Persistent(name = "list") })
public class ParentClass {
#Persistent(mappedBy = "parent")
#Element(dependent = "true") //can not exist without parent
private List<ChildClass> list;
}
#PersistenceCapable(detachable = "true")
public class ChildClass {
#Persistent
private ParentClass parent;
}
and then to do the fetching:
PersistenceManager pm = PMF.get("eventual-reads-shortdeadlines").getPersistenceManager();
pm.setDetachAllOnCommit(true);
pm.getFetchPlan().addGroup("fooGroup");
Transaction tx = pm.currentTransaction();
try {
tx.begin();
Query query = pm.newQuery(ParentClass.class);
list = (List<ParentClass>) query.execute();
tx.commit();
} catch (Exception ex) {
...
} finally {
if (pm != null) {
if(pm.currentTransaction().isActive()){
pm.currentTransaction().rollback();
}
pm.close();
}
}
Your ParentClass's should now have all the ChildClass's for each. Hope that helps!

Resources