I am developing an application under Groovy using scafoldig.
We are using the Acegi plugin for security.
We have a class called ChangeManagement defined as follows (simplified version)
class ChangeManagement {
static constraints = {
company(nullable:false)
lastModifiedByUser(nullable:false)
}
Company company
static belongsToCompany = [company:Company]
User lastModifiedByUser
static belongsToUser = [lastModifiedByUser:User]
}
When I address the create method I will get a pull-down menu
with the label "Last Modified By" with all the users from the table Users,
which is the standard behaviour.
Instead of this I would like to have directly the user who is already logged in and
no pull down menu. I've already generate the create template and I can modify it.
I am assuming that I have to get the username from the session.
If my assumption is true, how to get this username? and if I am wrong then from where can I get the username of the current user?
Thanks in advance.
See this question for details on how to get the current username.
I'd also suggest looking into Grails Filters for one way to easily stuff the user into the model after all controller calls and make it available in the view. I use this on my app to put the name of the logged in user in the upper right hand corner of the screen.
Related
How does Sharepoint retrieve the user's actual name as displayed in the top right corner? e.g Welcome John Smith
I need to call this name as a variable or parameter on custom code in the XSL editor but I can't figure out how I can retrieve it, is it a global variable?
You can get a user's account name using the server variable LOGON_USER. However, this doesn't return a user's Display name.
I was able to get something working which a combination of web parts to display their name:
Add a UserContextFilterWebPart (you may need to enable this web part in the web part gallery).
Add a DataView webpart which queries the GetUserInfo method (part of the UserGroup.asmx web service).
a. Click "Connect to a web service..." in the Data Source Library pane under XML Web Services
b. Enter the Service description location (the URL to the UserGroup web service). Ex: http://server/sites/SiteCollection/SubSite/_vti_bin/UserGroup.asmx?WSDL
c. Click Connect (or reconnect)
d. Choose GetUserInfo for the Operation dropdown (the other dropdowns should be ok)
e. Modify the userLoginName parameter and check the box to allow the value to be set via web part connection. I also added a default value to test (ex: domain\login).
f. Click OK.
g. Click on the data source and click Show Data
h. Choose the columns you need and then drag them onto the page
Connect them together using web part connections (UserContext provided to the DataView).
If you want to use SPServices (which is great, btw):
function getCurrentUsersName(){
var firstName = $().SPServices.SPGetCurrentUser({
fieldName: "FirstName",
debug: false
});
return firstName;
}
function getCurrentUsersLastName(){
var lastName = $().SPServices.SPGetCurrentUser({
fieldName: "LastName",
debug: false
});
return lastName;
}
You can look up a host of other similar fieldnames here:
I believe it's coming in through NTLM Authentication/Active Directory. I ususally get login name DOMAIN/User in the HttpContext.Current.User.Identity.Name field, and then match against Active Directory and bring back the actual name of the user.
SPContext.Current.Web.CurrentUser.LoginName will give you the value for the login name of the current user, as displayed in the top right of a standard portal.
If you want to use this with XSLT, you need to find a way of assigning this to an XSL parameter value at run-time.
I'm just starting to use sharepoint designer and realised there's a lot that can be done to extend the basic features in sharepoint. We have an email alert sent out when a new task is created (by the user) and I want to customise the email so that it also includes a link called 'Assign'. When clicked, I want this link to automatically update the task with the assigned to field for the person that clicked it.
So I think the way to do this would be to hard-code the assign to value in the url behind this link, but I have no idea if this is possible or if there is an easier/better way to do this.
Any advice would be appreciated as I'm a complete beginner.
thanks.
I will not cover "How to modify the contents of an eamil alert" here as that is a seperate question and there are a lot of articles that cover that already.
For the Assigned link :-
You would need to create a custom page (or web part on an existing page) as the destination of your Assign link - this would take the Task ID as a query string param and then update the assigned to with the current user.
You could make this flexible by also taking the ListID but you may want to think about how this could be abused and put appropriate measures in place.
EDIT - in response to comment.
This is top of my head, not checked in compiler. This would have to sit on the same server as SharePoint to work as its using the OM - if you want to use a different server (why would you though) then look in the web services.
private void updateAssignedTo(Guid listId, int itemID)
{
SPWeb web = SPContent.Current.Web();
SPList list = web.Lists[listId];
SPListItem item = list.GetItemById(itemID);
item["Assigned To"] = web.CurrentUser;
item.Update();
}
You're going to have to work out how to get this code into to page or web part (SharePoint Designer is not going to cut it I think, you need Visual Studio) but its a starting point.
I have a list with the fields: Title, Client, Project, Description.
There is a view for analysts with the fields visible: Title, Project, Description.
All is fine so far as the analysts work with their views and not with the lists. But when they need to modify the records clicking on Edit, they see and able to modify the 'Client' field too.
How to prevent 'Client' field to be available for editing by the group? is there a way in WSS or I need to look for 3rd party list components?
All fields have a set of properties that determine their visibility in forms, such as "ShowInNewForm", "ShowInEditForm", and "ShowInDisplayForm". There's also some for the file dialog, the list settings page, and a few other places, but that's getting past it. Short answer, yes, you can make the field not show up in the edit form with WSS without needing any 3rd party components.
If you need a field that cannot be seen in the Edit Form by anyone (that is, no one should be able to have it in their form), then you need to modify "ShowInEditForm" to be true. This can't be modified directly through the SharePoint UI, but it is extremely simple using the object model.
If you need certain people to edit it at some point through the SharePoint UI, then you'll instead have to create a custom edit form. That's a bit more complex, so I'll hold off on providing that instruction unless you state you need to go down that route (or someone else passes by this answer and requests it). Nevertheless, it is fully possible with WSS 3.0.
EDIT
If you know already know how to insert inline C# code into an ASPX page, you can perform this very simply using SharePoint Designer. First, follow the instructions from this article, especially make sure you don't delete the default list form web part. Now, in the custom list form you added, make it include every field which anyone will be capable of editing. The last step is to make the form hide those fields for certain people. Let's default them to Visible=false, and flip this switch if the user is allowed them. You can do this either by checking if the current user is part of specified groups, or by checking if the user has a certain permission level only held by people of those groups. You'll basically write some code like the following, I'll use checking for a specified group as the example.
using (SPWeb web = this.Web)
{
SPUser currUser = web.CurrentUser;
string[] listOfGroups = { "Group1Name", "Group2Name", "Group3Name" };
foreach (string groupName in listOfGroups)
{
if (currUser.Groups.Contains(groupName))
{
//Repeat this for each Control, refer to them by their ID. For example, this is for a control with the ID txtTitle.
txtTitle.Visible = true;
}
}
}
If you don't know inline code, you'll have to write a custom ASPX page with a code-behind. Copy EditForm.aspx into a new file - you should do this after setting up a Custom List Form as per the article. You could also build a new ASPX page from scratch, but make sure you include all of the necessary Content placeholders for SharePoint pages. Now, the page currently inherits from Microsoft.SharePoint.WebPartPages.WebPartPage. We need to create custom code that inherits from that class, and change the page to inherit that new custom code instead. In the custom code, override one of the OnLoad or OnInit methods, and include your check for the user's permissions there as detailed earlier. Compile the code, deploy it to your SharePoint server, and it should be functional.
If you want to set fields hidden or display them in new form or edit form page of the list...
Go to the list settings.
In Advanced Settings, enable "Allow management of content types"
By doing so, you will get a List name Link on the List Setting Page.
Open the link and select the fields that you want to hide or uhide using add or remove option.
After saving this, again disable "Allow management of content types" in Advanced Setting...
Thats it :)))
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.
I have a customer request to create a number of announcements based on some data from another database. Most of it seems easy enough but the new elements should be created by the user (login) specified in the input data.
I was planning to add the announcements using the list web services but I sure would like to avoid using impersonation in order to get the create user right. Is there a way to assign the correct user as the creator without using impersonation?
This may not be the answer you are looking for, but impersonation is pretty easy if you have code running in the GAC on a SharePoint server. You don't need to know any password which many do not realize, so I'll continue assuming that this was the reason you did not want to do impersonation. Here's how to do it.
You can connect to SharePoint using the typical constructor you use for SPSite and find the appropriate SPUser object. Once you do that, you can get the UserToken property for that SPUser. Then you'll need to use the SPSite constructor again, but use the overload that provides the SPUserToken. Then anything you do in SharePoint will be done via impersonation. No need to run with elevated privileges.
OK, now that I've said it in words, I'll try to guess at the code. It should be something like:
// Just determine the user token for a particular user
SPUserToken userToken = null;
using (SPSite tempSite = new SPSite("http://sharepointurl"))
{
using (SPWeb tempWeb = tempSite.OpenWeb())
{
// I think this next line works, but I'm going from memory
// I believe the user needs to have already logged into the site at least once
SPUser user = tempWeb.AllUsers["username"];
userToken = user.UserToken;
}
}
// Now do whatever we want impersonating that user
using (SPSite site = new SPSite("http://sharepointurl", userToken))
{
using (SPWeb web = site.OpenWeb())
{
// Do whatever you want here
}
}
I don't think that there is a method to archive this.
But perhaps this workaround might help. I have to admit I never tested this, it's only an idea how you might solve your problem.
You could try this. Create the new announcement with an admin user or with RunWithElevatedPrivileges(). After that use the RunWithElevatedPrivileges() method again and set the "created by" field to the user who should be the actual creator of the announcement. By this way only the "edited by" field should show the "wrong" user.
I know this is not a very elegant solution but it might work. ;)
I just realized that that my requirement was actually to circumvent the audit trail in SharePoint so I sure hope that it can't be done :-)
I came up with another solution: I added a new user or group field to the announcement list, and copy the AD-user logon into this field. Any report or view that previously used the "created by" field should now use the new field.
How about the situation where a real user enters a new element in the announcement list then? That will not update the new field with the logged in user!
Well, the only solution I could come up with is to add a ListItem Add trigger on the list. When a new element is added I check whether the new field contains a value, is not then I update the new field with the ID of the logged in user. That way the new field should always contain a valid userID.
I know this is not an elegant solution, but for the time being it is the best I can think of.
As alluded to in the answer's code comments, if the user has not visited the site at least one time, then there is no user metadata available from which to derive a proper usertoken.
With SharePoint 2010, you can simulate a user visit, with the EnsureUser method available from the SPWeb class (this snippet creates the user and also tweaks their profile a bit):
SPUser alice = web.EnsureUser(#"MYDOMAIN\alice");
SPList userInfo = web.SiteUserInfoList; //metadata storage of user info
SPListItem item = userInfo.GetItemById(alice.ID);
item["About Me"] = "I am Alice from Mel's Diner";
item.Update();