Sitecore Custom User Profile - where is it stored how can it be queried - membership

I have created a custom User profile template and object in the core database in Sitecore (as per the Security API Cookbook).
I can select this programmatically (as per the Security API Cookbook) so that my extranet users have an extended profile, that covers all the usual suspects (Address, phone, email format etc.)
However, where is this data stored? And how do I access it if I want to query the database to return a subset of users based on this profile data.
A typical requirement for an extranet member system is to extract a list of users to contact either in an email or a phone type campaign. Can this be done with the Sitecore membership system?
UPDATE>
I'm going to take a guess and say the profile data is stored in aspnet_Profile.PropertyValuesBinary .. which would make it nigh on impossible to query and not suited to my purpose. That is unfortunate. So to extend my question, if that is the case, is it possible to get Sitecore to store those values in the text field so they are searchable?

The standard Microsoft implementation of the SqlProfileProvider (which is used in Sitecore by default) stores the user profile information in the aspnet_Profile table. All the properties are serialized into the PropertyNames / PropertyValuesString columns. The PropertyValuesBinary is used to store the binary data (images). You can find more details if you look at the code of System.Web.Profile.SqlProfileProvider, SetPropertyValues method.
Next, all the custom properties you define in the user profile, are serialized to the SerializedData property of the Profile class, and it is again serialized to the PropertyNames / PropertyValuesString columns like any other property.
Also, couple of properties are stored in aspnet_Membership table (for some reason) - Email and Comment.
So, if you are going to query the users by Email, you can use FindUsersByEmail method of MembershipProvider. Otherwise, if you plan to filter by another property value, I suppose, you'll have to get all users and filter the obtained collection.
Hope this helps.

I faced this exact problem last week, didn't come up with a permanent solution, but to solve my particular issue, I wrote a little helper page and added it as a Sitecore application to be accessed from the CMS interface. All it did was query all users, and determine if they had any of like 5-6 profile properties assigned.
var userList = Sitecore.Security.Accounts.UserManager.GetUsers();
That is the relevant line to grab the users, it returns Sitecore.Common.IFilterable
So if you need to do something where you're grabbing profile info from all users, you cn do something like this:
foreach (Sitecore.Security.Accounts.User user in userList)
{
Sitecore.Security.UserProfile profile = user.Profile;
string whatever = profile["Whatever"];
//add whatever to a list or something
}
This worked out very well for my purposes, but I don't know how feasible it will be in your situation.

Related

Using Graph API to query SharePoint list items and expand user field

I'm trying to query for some SP list items, all is working fine except I can't seem to expand a custom column of type Person.
I can see the createdBy and lastModifiedBy expanded and even includes the AAD user id, which is great and also leads me to think what I want is possible!
But mine is a custom column.
I'm running this and can only seem to get the SP user list id and the user's display name...neither of which are much use.
/items?expand=fields(select=UserLookupId,User)
Ideally I'd like to get the AAD user id as per createdBy and modifiedBy field, but the email would suffice.
Otherwise the only way I can see is to query the User Information List (using the UserLookupId) to get the email?
Thanks
This appears to be correct assumption:
Otherwise the only way I can see is to query the User Information List
(using the UserLookupId) to get the email?
for non-system user fields, it is indeed a way to go, but there are some distinctions whether user field is multi-valued or single-valued.
If Approvers is a multi-valued user field, then the following query:
https://graph.microsoft.com/v1.0/sites/{site-id}/lists/{list-id}/items?$expand=fields($select=Approvers)
returns email and id properties along with displayName property for user field value.
While for single-valued user field only id (available via {userfield}LookupId property) and displayName properties could be requested via items endpoint, for example:
https://graph.microsoft.com/v1.0/sites/{site-id}/lists/{list-id}/items?$expand=fields($select=Approver,ApproverLookupId)
So, indeed User Information List needs to be utilized to request additional user properties, for example:
https://graph.microsoft.com/v1.0/sites/root/lists('User Information List')/items/{item-id}/?$expand=fields($select=Email)
where item-id corresponds to user field lookup id
This was my experience modifying the
Build Angular single-page apps with Microsoft Graph. In the examples below, I changed my id's out with the default text.
Here is
The Finished Project on thier github
In Graph Explorer, this worked. You can verify it at the Microsoft Graph Explorer.
https://graph.microsoft.com/v1.0/sites/{site-id}/lists/{list-id}/items?expand=fields($select=id,Title)
In the app/graph.service.ts in the app, this did not work. Even though you would expect it to based on the graph explorer.
.api('/sites/{site-id}/lists/{list-id}/items?fields($select=id,Title)')
Changing the app/graph.service.ts api call worked.
.api('/sites/{site-id}/lists/{list-id}/items?')
.expand('fields($select=id,Title)')
The result looked like this:
fields: {
#odata.etag: ""d6f5b6ea-9f90-452d-98ba-e838f58d3359,1"",
Title: "IT SPECIALIST (MID)",
id: "20"
}
Here's an example site id:
some.sharepoint.com,9dk062b-2e54-4e4f-b71a-cdb74f42cc44,c6cf6b0a-cc7c-41fd-a76a-ef8f97e8a22f
Here's an example list id.
8eg8c29a-5555-4cfc-bfa4-0e907488f781
The end url won't have any {} in it.

Related objects in activity feed

I'm building an activity feed application, where a user can like/comments on each activity feed. I went through GetStream.io documentation and looks like I'll have to send the activity with object ids.
{
id:"ef696c12-69ab-11e4-8080-80003644b625",
actor:"User:1",
object:"Comment:12",
started_at:"2014-11-11T15:06:16+01:00",
target:"Feed:100",
time:"2014-11-11T14:06:30.494",
verb:"add"
}
User:1 and Feed:12 are the objects in my application database? Does it mean that, while retrieving activities, I'll have to hit my database to retrieve the complete feeds?
Say the Feed:12 had few likes and comments earlier from other users. How do I get the complete set of likes/comments on user timeline feed?
What if I want to customize the view, say I want to show all users (image, name, the profile like etc) along with comment with timestamp similar to FB? Do I need to send these attributes as additional parameters for each feed?
Thanks,
Yes, when you fetch a feed from Stream and we give you back these references like user:1 or comment:12, we expect that you'd "enrich" those details from your database.
Typically what our users do is track the name of the model (eg, user) and the user_id (eg, 1). When you get the feed and put it into a hash map, you'll iterate over the activities, pull out all of the actor attributes, and do a single lookup like select * from user where id in (1,3,5,6,9,12) so that you're only hitting your database one time for all user objects or all comment objects or whatever. Then, replace those activities in your hash map so now you'd have actor: <object for User 9> and any other attributes you'd need for your UI presentment.
Then do the same for other references you pass in the activity, and so on.
Things we DON'T recommend are putting in string references for things that could change on your side. For example, if you had actor: "user:ian" instead of my user_id, if I ever change my username later then things probably wouldn't work properly on your side.

(Nintex) Query User Profile returns missing values

Working in Nintex, I have a workflow that is kicked off when a form is saved. The workflow generates a PDF version of the Nintex form (we need actual signatures - digital in the future, fingers crossed). This is done by updating a word template, then converting to PDF.
When the word document is updated, the 'assigned to:' field is getting an AD account name instead of the user's First, Last name (which is expected). Now I'm trying to format it so it's more appropriate to the Hard Copy (in the Nintex form, it shows as Last, First).
I used a Query User Profile action, passed it the same variable I was using to hold the form's 'assigned to' value, and then used the drop down menu to choose the user profile variables I wanted (First, Last, also: username, account name, Distinguish name). All values are generating empty strings.
I've incrementally tried handing the values to variables that are of type String, Person, or Collection. I also handed it my username instead of the variable and set my account info for the login. I've always selected values, so I don't think it's a typo.
I'm at a loss... the workflow emails the user at the end, so it's getting the data. I hope that's enough info, I'm new to SP/Nintex so it could be a rookie mistake. Any help is appreciated.
Thank you!
I've seen issues where the User Profile Service properties have not been configured adequately, which leads to a lot of empty variables when running an LDAP Query action for AD attributes.
If this is the case, then one approach is to get the Farm admin (if you don't have access) to take a look at Manage User Profiles in Central Admin and see what AD attributes are mapped to the user profile. If mappings are changed you'll need to run a full sync to bring over the values. It can be inconsistent in my experience as well.

How do we make a crystal report print only specific fields based off of the user running the report?

We use a construction software, Viewpoint. We need a report to print the GL Accounts associated only with the user running the report. I was wondering if anyone had any ideas on how I could easily and efficiently achieve this? My "last-resort alternative" is just creating separate reports for each GL that pulls only that GL's info.
It depends on how the accounts are associated to the user. If there is a link, you can simply create a user parameter that asks for the user name. Then in the record select of the report you only pull accounts that match the user name in the parameter.
So, for example your parameter is called {?userName}. In the Record Select the formula would something like {Accounts.Salesman} = {?userName}, where {Accounts.Salesman} would be the field that links the user with the account.
You can get the current user name and use it to filter the records in your report. There are 2 ways to do this :
create a parameter, hide it and automatically fill the value. You
will need a special viewer for this scenario. Let me know if this is
what would you prefer I can give you some links. If you leave the
parameter visible the user can insert any value and view any records
use an UFL . For example this one:
http://www.viksoe.dk/code/u2lwin32.htm provides a function LoginName
which will return currently logged user. There are other UFLs which
support similar functionality, check if your company is already
using something . This one is free. You need to register the UFL on
each system which will run the report . Once registered the
available functions will become available for formulas.
I personally prefer the viewer solution because it is more flexible and will cover other scenarios too. However if you need just the username UFL will be a better approach.

Sharepoint custom user and document library specific properties

Is there a standard way to associate custom properties with a user? I need to store the number of items per page a user selected in a grid of a document library separately for each user and document library.
Edit:
Sorry about this vagueness, I wanted to do it programmatically. It seems like I've found the solution, it is UserProfileManager class, though I'm now looking into whether there is a limitation on the number of properties you can save this way for a user, because the easiest way of saving page sizes on per user+document library basis seems to be using GUIDs of Views as property names and numbers of pages as values. Though I don't know if it is more efficient or not, depends on how sharepoint stores these properties.
No, you would need to create custom code to store the data.
Given the potential amount of data created, it may be wise to store it in a separate database.
This would give greater flexibility in the way the data can be manipulated and retrieved.
Your question is a bit vague. Are you looking to do any custom code? You could do this many ways so it is difficult without knowing more of what you want.
Using custom code you could set up a workflow or event handler to respond to item events and record the information and store it using the User's Profile or as an SPPersistedObject.
If you want a less developer centric way to do it you can use auditing and simply do reporting on your audit results.
You could set up a list to store the selection data, then use events/AJAX on the document list to push tick/untick items into the selection list (store user, library and document as a minimum.
If you don't want a separate list, you could create a field in your document library that stores which users have a given document tagged... You'll still need some kind of event/AJAX to update the list when a user ticks/unticks the box. Crude :)

Resources