Monday, December 19, 2011

Sharepoint 2010 Managed Account feature

Fantastic new feature in SP 2010. Read more about it here: http://blogs.technet.com/b/wbaer/archive/2010/04/11/managed-accounts.aspx

To make it easier, here's the relevant excerpt from the blog article:

Microsoft SharePoint Server 2010 provides a number of compelling improvements designed especially for the system administrator, of these, commonly overlooked, are Managed Accounts. A Managed Account is effectively an Active Directory user account whose credentials are managed by and contained within SharePoint. In addition to storing the credentials of the object, Microsoft SharePoint Server 2010 can also leverage Active Directory Domain Policies to automatically reset passwords while meeting the requirements established by policy.

How credentials are stored…

Managed Account credentials are encrypted using a farm encryption key that is specified when you run PSConfig[ui].exe at farm creation based on the passphrase. The passphrase is stored in a secure registry location so that it can only be accessed by the farm account and encrypted so that only the farm account has access (we won’t get into the encryption specifics here). The farm encryption key subsequently, is stored in the Configuration Database. This scenario is what enables farm administrators to join machines to the farm without specifying the credentials as had to be done in previous versions of the product.

The last sentence of the paragraph above illustrates one of immediate benefits of using Managed Accounts, for example, suppose an administrator would like to create a new Web application using Windows PowerShell and/or SharePoint Central Administration – the administrator only needs to specify the Application Pool account (Windows PowerShell) or select the account in the SharePoint Central Administration user interface as opposed to both having to know the domain\username and associated password.

Example (Windows PowerShell)
$provider = New-SPAuthenticationProvider -ASPNETMembershipProvider "LdapMember" -ASPNETRoleProviderName "LdapRole"
$webApp = New-SPWebApplication -Name "Claims" -ApplicationPool "Claims Application Pool" -ApplicationPoolAccount "CONTOSO\administrator"
-Url
http://claims.contoso.com -Port 80 -AuthenticationProvider $provider

Get Managed Accounts (SharePoint Central Administration)
  1. To view existing Managed Accounts using SharePoint Central Administration, select Security from the SharePoint Central Administration homepage.
  2. On the Security page select Configure managed accounts under General Security.
  3. The Managed Accounts page will list all Managed Accounts registered in SharePoint.
Register Managed Accounts (SharePoint Central Administration)
  1. To register new Managed Accounts using SharePoint Central Administration, select Security from the SharePoint Central Administration homepage.
  2. On the Security page select Configure managed accounts under General Security.
  3. On the Managed Accounts page select Register Managed Account.
  4. On the Register Managed Account page (see illustration below) specify the credentials and select the password change policies as desired.
CA

Tuesday, June 28, 2011

Creating a Records Center in SharePoint 2010

Today I found a fantastic article on how to create a Records Center in SP 2010. Here's the link:
http://blogs.msdn.com/b/mcsnoiwb/archive/2009/11/05/sharepoint-2010-records-management.aspx

If you're lost while reading the article, fear now. Just create a Records Center site in SP 2010. On the landing page, you'll get a web part that shows you how to start:


After this, click on Site Actions -> Manage Records Center to get a step-by-step description on how to get going. These are the steps I followed to get started:

1.       Created site with records center template
2.    I was asked to activate site collection level features such as in-place records management & document ID service.
3.    Create the content types that you are going to use to filter documents by, or are going to assign to  records
4.       Create a destination for your records – I created a record library. Can one also create other types of libraries though?
5.       Next, you need to create content organizer rules, but before doing that, ensure that your target libraries have the Content Types that you created, included in them.

Once you've created the Content Organizer rules, you're all set. You can upload documents to the drop-off library and associate the content type with the document. The document will then be routed to the approprate library and folder that you've chosen. The document will also become a record that will be locked and read-only. You wont be able to delete or edit it.

Thursday, June 23, 2011

RoleDefinition and RoleAssignments

The concept is pretty simple. You have users who you want to assign unique permissions on your web site. You create a RoleDefinition where you specify the unique permissions that make up the role that you want to create [say you were defining the contribute role], and also give a unique name for the role definition.

Then you'd create a RoleAssignment object. This is a object that takes in

  1. The user that you want to associate with the RoleDefinition above
  2. In the RoleDefinitionBindings collection, you add one or more RoleDefinitions that you want to associate with the user - like Reader, Contributor etc. This is where you would add in the new RoleDefinition object that you created above.
  3. Add this RoleAssignment object to the collection obtained from SPWeb.RoleAssignments
I'll try to illustrate this tomorrow by adding a diagram that shows how it all comes together

Tuesday, February 22, 2011

How to manage processes in poweshell

Have you needed to automate little things on your PC. I have a fixed set of things to run in the morning when I start my laptop at work, things like Outlook, IE with yahoo, gmail & facebook, my work diary etc. I find that powershell is very handy at doing this sort of thing. Here's a little script that I use:

[System.Diagnostics.Process]::Start("outlook")
$ie=new-object -com internetexplorer.application
$url1 = "www.google.com/mail/"
$url2 = "www.yahoo.com/mail"
$url3 = "www.facebook.com/yourURL"
$ie.visible=$true
$ie.navigate($url1)
$ie.navigate($url2,0x0800)
$ie.navigate($url3,0x0800)
[System.Diagnostics.Process]::Start("winword.exe", "Full Path to your doc")
[System.Diagnostics.Process]::Start("explorer")

Additionally, check out the following link which explains starting processes in detail:
http://blogs.msdn.com/b/powershell/archive/2007/01/16/managing-processes-in-powershell.aspx

Monday, February 14, 2011

Getting Intellisense with Visual Studio (& a little wiser with your life)

So if you're out there creating a content type programmatically, you know you're up against something formidable. You have to write a bunch of XML & you dont get any help from Visual Studio. Seriously, SharePoint development has to use more classes & less XML.

Fret not though, use the following link to add intellisense to creating SharePoint XML through Visual Studio:

http://www.andrewconnell.com/blog/archive/2006/10/20/4944.aspx

Basically, you just refer to wss.xsd found at 12\Templates\XML\wss.xsd in the schemas property of the XML file in Visual Studio.

Next tip, you know that content types form the base of everything in SharePoint, so if you ever need to find all the content types that SharePoint ships with, here's where you need to look:

12\Template\Features\ctypes\ctypeswss.xml

Easy to remember, if you're looking for the schema, go to hive\templates\XML\wss.xsd & if you're looking for content types definitions, go to hive\temples\features\ctypes & find ctypeswss.xml.

Looking at the content types defined, I realized that many of the fields that we assume exist with a content type, are created because they are defined in this ctypeswss.xml. For e.g. I always wondered about where the created_by & modified_by & modified_date fields were defined with the document library items. I realized that they exist, because they are FieldsRefs by the content type & that they are hidden by definition.

Last tip, if you ever need to find SP logs, they exist at Hive\Logs.

That brings me to getting wiser in life ... it's simple ... in the mad rush of our fast paced lives, you need to find that time of the day where you're alone & calm & then think ... have patience, this too shall pass.

Friday, February 11, 2011

SPListItem SystemUpdate()

SPListItem.SystemUpdate() is an exciting new function that I've learned about today.

SystemUpdate() allows you to update a list item without changing the following fields:
1. Modified Date
2. Modified By
3. And optionally - version of the list item

I just tried this function & it actually works. I will be trying to see if this can work with the document libraries as well as with attachments in a list item (the SPFile object). I've tried to add/delete attachments of a list item with this function, & the results are as the documentation claims it should be.

Thursday, February 10, 2011

Identity and Principal

What's Identity and Principal in .NET terms? What is the significance of something like




AppDomain.CurrentDomain.SetPrinicpalPolicy(PrincipalPolicy.WindowsPrincipal)



I've just started to investigate this while Identity & Principal thing & found the following link to be quite useful:
http://www.codeguru.com/Csharp/.NET/net_security/authentication/article.php/c7415/

Quite a few things from the post below are taken from Klaus' link above, so thanks to Klaus for an excellent article.

Just a few things about what I've learnt from that article:

  1. Identity is who you are. It's used in authentication
  2. Principal = Identity + groups of which you are a member of. Used for authorization.
The IPrincipal has a property that exposes the IIdentity interface as well as the method IsInRole(). This makes it clear that the Principal object can be used to get the identity of the user running the app, as well as the roles that he/she is in.

Now coming to the significance of the line above: Thread.CurrentPrinicpal gives you access to the current principal assigned to the executing thread. By default, this will be an unauthenticated principal. The framework provides two different types of principals, a Windows principal (WindowsPrincipal) and a generic principal (GenericPrincipal).

By calling SetPrincipalPolicy on the current AppDomain, you tell the framework which principal needs to be attached to this thread. You need to set this before you access the principal the first time.

Calling Thread.CurrentPrincipal returns the principal bound to the executing thread. The first time, this tells the framework to go off and query for the Windows user information, create a Windows identity, and then a Windows principal, and bind it to this thread. From the Windows principal, you then can access the Windows identity.

Another way to do this is as follows:

WindowsIdentity Identity = WindowsIdentity.GetCurrent();


WindowsIdentity.GetCurrent() goes off and queries the Windows user information and creates a Windows identity object representing that user. With that, you can create a new Windows principal passing along the Windows identity. The disadvantage of that approach is that each time it goes off and queries for the Windows user information and creates a new principal and identity object. The first approach reuses the same Windows principal and identity each time.

Now the best thing about the Identity & Principal objects, is that it allows you to use the same methods to for different types of identity & principals. For e.g. if you have authentication against a database, then you can use custom identity & principal objects & extend the concept from WindowsPrincipal to your own custom prinicpal. You can create your own Principal & Identity objects & then assign that principal to the current thread:

public class SecurityPrincipal : IPrincipal ...

//assign this principal to the current thread
Thread.CurrentPrincipal = TheSecurityPrincipal;

See Klaus' article for an excellent coverage of how to extend the .NET Identity & Principal concepts to custom principals.

Wednesday, February 9, 2011

Programmatically iterating through discussion lists

On further testing, I've discovered that my last post wasnt quite accurate.

Each post in a discussion thread is actually a folder. Replies to that post are kept in that folder. So if you do a recursive CAML query by ID on the entire list, for some strange reason, you get back all the replies - for other posts as well.

So the better way of doing it is to iterate through the posts by iterating through the ListItemCollection on the discussion list - which gives you all the posts. To get all the replies, use the following simple code:

foreach (int topicID in topics)
{
SPQuery q = new SPQuery();

SPListItem item = list.GetItemById(topicID);
q.Folder = item.Folder;


SPListItemCollection replies = null;

replies = list.GetItems(q);

foreach (SPListItem reply in replies)
{
//There's usually no subject, just the body
Console.WriteLine(reply["Body"].ToString());


Console.WriteLine();
Console.WriteLine();
}
}

Friday, February 4, 2011

Programmatically retrieving discussion list items

I spent the entire day yesterday, trying to figure out how to programmatically retrieve discussion lists. While this is still work in progress, here's some sample code that can help you do this.

using (SPSite site = new SPSite(Constants.siteCollectionURL))
{
using (SPWeb web = site.RootWeb)
{
SPList list = web.Lists["Team Discussion"];

//Get the items in the list
SPListItemCollection listItemCollection = list.GetItems(new SPQuery());

//Either you can get the topics this way or the Query method above. Both work fine.
//SPListItemCollection listItemCollection = list.Folders;

//Store all the topics in a list
List topics = new List();

//Iterate through the items
foreach (SPListItem listItem in listItemCollection)
{
//Display the subject and the body of the topic
Console.WriteLine(listItem["Subject"].ToString());
Console.WriteLine(listItem["Body"].ToString());


if (listItem["Parent Folder Id"] != null)
{
Console.WriteLine(listItem["Parent Folder Id"].ToString());
}
else
{
//Store the topic ID for later
topics.Add((Int32)listItem["ID"]);

}


}


//For each topic get all the replies
foreach (int topicID in topics)
{
//Get all the replies
String strQ = @" @TOKEN";
string sTopicID = Convert.ToString(topicID);
strQ = strQ.Replace("@TOKEN", sTopicID);
SPQuery q = new SPQuery();
q.ViewAttributes = "Scope=\"Recursive\"";
q.Query = strQ;

SPListItemCollection replies = list.GetItems(q);

foreach (SPListItem reply in replies)
{
//There's usually o subject, just the body
Console.WriteLine(reply["Body"].ToString());
}
}

}
}