I am using a single table to store all my data in dynamodb as such:
Partion Key (PK)
Sorting Key (SK)
Attributes
USER#gijoe
PROFILE#gijoe
{ name: "G.I", lastName: "Joe" }
USER#gijoe
CARD#first-card
{ name: "King", picture: "./king.png" }
I am using the preferred_username as a part of the Partition Key, and thus need it to be unique to avoid colliding user data.
How can I garantee that two users in my User Pool cannot have matching preferred_username ?
Edit:
The answer from #Lukas did it. Note that it required me to drop and recreate my cloudformation stack, which is why it failed on my first tries. Now when I try to edit the preferred_username I get the error I was looking for:
{
"message": "Already found an entry for the provided username.",
"code": "AliasExistsException",
"time": "2021-01-19T09:36:47.874Z",
"requestId": "7b52dbc2-58c5-4354-aa51-66d4dc7472a0",
"statusCode": 400,
"retryable": false,
"retryDelay": 85.84051584672932
}
username is unique within single pool. Same with alias. preferred_username may be configured as username alias.
https://docs.aws.amazon.com/cognito/latest/developerguide/user-pool-settings-attributes.html
Key take aways:
Developers can use the preferred_username attribute to give users a username that they can change. For more information, see Overview of Aliases.
The username must be unique within a user pool. A username can be reused, but only after it has been deleted and is no longer in use.
You can allow your end users to sign in with multiple identifiers by using aliases.
The preferred_username attribute provides users the experience of changing their username, when in fact the actual username value for a user is not changeable.
If you want to enable this user experience, submit the new username value as a preferred_username and choose preferred_username as an alias. Then users can sign in with the new value they entered.
If preferred_username is selected as an alias, the value can be provided only when an account is confirmed. The value cannot be provided during registration.
....
Alias values must be unique in a user pool. If an alias is configured for an email address or phone number, the value provided can be in a verified state in only one account. During sign-up, if an email address or phone number is supplied as an alias from a different account that has already been used, registration succeeds. Nevertheless, when a user tries to confirm the account with this email (or phone number) and enters the valid code, an AliasExistsException error is thrown. The error indicates to the user that an account with this email (or phone number) already exists. At this point, the user can abandon the new account creation and can try to reset the password for the old account. If the user continues creating the new account, your app should call the ConfirmSignUp API with the forceAliasCreation option. This moves the alias from the previous account to the newly created account, and it also marks the attribute unverified in the previous account.
Related
I have a list in sharepoint online.
And in this list, i have a person field.
When i call the API endpoint to get all the items in the list, i get an LookupId value for the person field.
I tried to get the user by using the value of the lookupid, but it don't work because the id is not recognized.
The lookupid is a int (eg: 21) instead of a guid.
Is there something missing in the configuration of the person field or in my calls to Microsoft Graph API ?
When a user signs into a SharePoint site collection for the first time, a ListItem is created in a hidden User Information List. The LookupId in a PersonOrGroup field refers to the ListItem in this list. The URL for the User Information List for SharePoint Online should be:
https://{yourTenant}.sharepoint.com/{yourSiteCollection}/_catalogs/users/detail.aspx
Since the User Information List is a generic SharePoint list, you can query the list via Graph. First, get the list id for the User Information List. An easy way to get the list id is to view the source for the User Information Site via Chrome and search for 'listId'. You should find a result like this:
"listId":"{yourListIdIsHere}"
Copy the id. By using the copied id, the id of your root site and the LookupId, you can get the ListItem in the User Information List:
https://graph.microsoft.com/v1.0/sites/{siteId}/lists/{pasteCopiedListId}/items/{lookUpId}?$expand=Fields
The ListItem contains information about the user, such as the email, which can be used to identify the Azure user:
https://graph.microsoft.com/v1.0/users/{eMail}
Question: How could i get the hidden User Information List from Microsoft Graph?
If you do not want to use the 'trick' with Google Chrome to get the id, there is another way to get the site. Typically, if you want to get the id for any site, you would call:
https://graph.microsoft.com/v1.0/sites/{siteId}/lists
However, you will not find the id of the User Information List, even if you include hidden sites. I do not know why. An additional problem seems to be, that you cannot filter lists by their name:
https://graph.microsoft.com/v1.0/sites/{siteId}/lists?$filter=name eq 'users'
The query returns an error, that the provided filter statement is not supported. The only way to get the list without knowing the id seems to by using the property displayName of the list. However, the displayName is based on your localization. So, since I am from Germany, I can get the site by using the query:
https://graph.microsoft.com/v1.0/sites/{siteId}/lists?$filter=displayName eq 'Benutzerinformationsliste'
You will need to replace Benutzerinformationsliste with your localized name. For EN replace it with 'User Information List'.
This returns the expected result:
{
"#odata.context": "https://graph.microsoft.com/v1.0/$metadata#sites('xxx')/lists(id,name,displayName)",
"value": [
{
"#odata.etag": "\"xxx\"",
"id": "xxx",
"name": "users",
"displayName": "Benutzerinformationsliste"
}
]
}
As you can see, the name of the list is 'users', so why the first filter statement does not work is a little mystery to me. Maybe someone here knows and can help out.
Some of the queries above don't work at the moment.
What I finally found as a good solution - after trying many many queries - is that you can do this by following the few steps below:
1- Get the GUID of the user information list.
Using the title of the list "User Information List" or the name "users" in the parameter "$filter" does not work.
Don't forget 'system' among the properties you select if you want to retrieve the hidden system-lists.
GET https://graph.microsoft.com/v1.0/sites('{site_id}')/lists?select=id,name,system
2- Filter the previous result in order to pick up the ID of the targeted list named 'users'.
By the way, applying this restriction "$filter=name eq 'users'" does not work.
You will get an exception. So you must do the filtering part by writing a few lines of code.
3- Once you've got the list identifier, then select all the items you want. And voilĂ ! The word 'Fields' must be in pascal case (uppercase the first letter ).
GET https://graph.microsoft.com/v1.0/sites('{site_id}')/lists('users_list_id')/items?$select=Fields&$expand=Fields
As #QuestionsPS1991 mentioned, the people field in fact refers to the hidden user list. With the lookupid, we can get the user via below methods:
Get user by id
Get user property by expanding lookup field
//////////// updated
By default, MS Graph does not return this user list. You may hard code the list id or follow ##QuestionsPS1991 suggestion. Below is my test:
I'm trying to add an Item, where one of the fields is of type contact (user), to Podio.
I do not have the contact profile_id, only the name, so I need to search the contact to get the profile_id before adding.
The problem is that the /contact/ resources are inaccessible since I'm using app authentication.
The error is: "Authentication as app is not allowed for this method"
What is the recommended way to do this?
Thanks.
As I can see, the tricky part here is that you have just a name of the user. So you need to search this name first.
To be able to search you should be authenticated not as an app, but as a user with appropriate rights. I believe this is because search functions a rate-limited per user. You may authenticate on client side, server side or just by entering user's email and password (see documentation here).
Then, when authenticated, just use search functions with the parameter "ref_type": "profile" to look for the user name within space, organisation or globally. Example for PHP-client:
$attributes = array(
"query" => "John Doe",
"ref_type" => "profile"
);
$results = PodioSearchResult::space( $space_id, $attributes ); // search in space
$results = PodioSearchResult::org( $org_id, $attributes ); // search in organisation
$results = PodioSearchResult::search( $attributes ); // search globally
Functions above will return an array of the most relative results found. There you can get a user id and other user info.
Note that technically several different users may have the same name, so there might be more that one result found. It will be up to you to choose one of them somehow.
I was recently asked this in an interview for a SDE role.
Suppose you have a list of User objects
class User {
String userId;
String email;
String ip_addr;
}
where userId field is unique among all users, while ip_addr and email are not necessarily so.
and you know some users have more than one user account (if any two User objects share a common email OR an ip_addr, you classify them as belonging to the same user).
you are required to write a function, whose signature is given as:
List<List<User>> findDups(User[] userList) {
// code here
}
[EDIT] so for example, if there are 7 users, only 2 of which are unique, the function can return something like the following (not necessarily in this specific order):
{
{user1, ip1, email1},
{user5, ip5, email1},
{user24, ip5, email2}
},
{
{user2, ip2, email2},
{user7, ip2, email7},
{user8, ip2, email0},
{user19, ip19, email7}
}
here, in this first group, the first user (user1) is the same user as the second one (user5) as they share the same email address. We also know that the third user (user24) is also the same user as it shares the same ip address (ip5) as the second user in the list.
[/END EDIT]
what data structure would you use and what would be the time complexity of the proposed solution?
I tried to use disjoint set union (quick union), which would give me linear complexity, however the interviewer constantly tried to steer me away from that and said just the Collection API would be enough (Using Lists and Sets and maps).
What would be your approach and solution and the corresponding time complexity?
I have an LDAP server with my email contacts so that I can lookup contacts by name/email, etc. However, it only seems to search and find the first email address for any contact.
For example, if I have a person:
LastName: Doe
FirstName: John
Email: jdoe#work.com
Email2: johndoe#home.com
Email3: johndoe#fun.com
It only searches through or returns the first email. For example, if I search for "John", it will return only the "jdoe#work.com" even though the other two email addresses have "john" in them. The search filters I've tried are:
//This one will both look through and match the first email but ignores the 2nd/3rd
(|(displayName=*%v*)(mail=*%v*)(uid=*%v*)(givenname=*%v*)(sn=*%v*)(cn=*%v*))
//This one throws an error saying "mail2" and "mail3" are invalid filters.
(|(displayName=*%v*)(mail=*%v*)(mail2=*%v*)(mail3=*%v*)(uid=*%v*)(givenname=*%v*)(sn=*%v*)(cn=*%v*))
What should I be using?
Also, does anyone have a link to some page that lists all the possible filters I can put in an ldap person search?
Exchange does not store additional mailaddresses in fields like mail2 or mail3. All addresses are stored in the multi-valued field "proxyAddresses". This field contains one line for each address in the form of
address-type:address
Example:
smtp:test#contoso.local
SMTP:user#contoso.local
The second entry in the example would be main address for that account, because the SMTP prefix is all uppercase.
So you would search for (proxyAddress=%v) or something like that. I don't know the LDAP search syntax out of my head.
Edit: Another option is to use the ResolveNames operation of the EWS webservices (see http://www.infinitec.de/post/2009/04/13/Resolving-the-primary-email-address-with-Exchange-WebServices-ResolveNames-operation.aspx and http://msdn.microsoft.com/en-us/library/aa563518(v=exchg.140).aspx).
The filter:
(|(displayName=*%v*)(mail=*%v*)(uid=*%v*)(givenname=*%v*)(sn=*%v*)(cn=*%v*))
will not match the entry:
LastName: Doe
FirstName: John
Email: jdoe#work.com
Email2: johndoe#home.com
Email3: johndoe#fun.com
because none of the filter assertions match any of the attribute names in the given entry.
(|(Email=jd*)(Email2=john*)(Email3=john*)(lastName=Do*))
would match. Have you considered using the standard names for the example entry you give?
Active Directory was released with some schema choices that are questionable. Now it is hard to fix them.
One of those is that mail, was flagged as single valued. This should have been a multivalued attribute. Thus the use of proxyAddresses, where it tries to overload a string syntax attribute with more information by using smtp: or x500: or SIP: to indicate a protocol for the address. Then upper case (SMTP) means primary and lower case (smtp) means secondary.
This also occured for telephoneNumber being single valued, and extra values now overflow into the attribute otherPhone.
Same for:
facsimileTelephoneNumber and otherFacsimileTelephoneNumber
labelledUri and url
homePhone and otherHomePhone
pager and otherPager
mobile and otherMobile
If I added data on LDAP in this way:
$ldapserver = "mail";
$ds = ldap_connect($ldapserver);
$r = ldap_bind($ds, $ldaprootun, $ldaprootpw);
add = ldap_add($ds, "cn=$full_name,ou=$domain,o=mygroup.com", $infonew);
Then does that mean that when I log in to my account I will use:
`cn="mynameHere",ou="domainIused",o=mygroup.com`
as my username? Or just my uid?
My account cannot login but I'm sure that it exists in LDAP.
Answers are very much appreciated. =)
Typically in LDAP applications you only ned to login with your UID, not your full X.500 name.
Try calling ldap_bind() with your creds and see what it returns?
Usually, the user provides a simple name. Then the app searches the LDAP source for some attribute that has that value. Then you bind or password compare in your code, as that full DN.
You can use uid which is Unique ID, which is required to be unique. I.e. If you find more than one instance of it, that is an error.
You can try CN, but that can often be multi valued depending on your LDAP implementations schema.
If you know you are going against eDirectory, then uid is fine, or CN just do something if it is multi valued.
If you know you are going against Active Directory, you can assume sAMAccountName is unique since the system enforces uniqueness. userPrinicpalName ought to be unique, but nothing actually enforces it.
You can always use mail, which is the email address pretty uniformly.