Thursday, July 19, 2012

Swtching Security Mode in Project Server 2013 Preview (On-premise)


As you know, by default Project Server 2013 has the SharePoint  permission mode which is simplified if we compare it with Project Server mode. Some users, might benefit from it, some more advanced users might want to switch back to Project Server mode.

There is an article on TechNet how to change http://technet.microsoft.com/en-us/library/jj219486(v=office.15).aspx

You have to run a powershell command - Set-SPProjectPermissionMode 


Switching from SharePoint to Project Server mode:


Set-SPPRojectPermissionMode –Url http://projectserver2013/pwa -AdministratorAccount fluentpro\sp-farmadmin -Mode ProjectServer


Switching from Project Server to SharePoint mode:

Set-SPPRojectPermissionMode –Url http://projectserver2013/pwa -AdministratorAccount fluentpro\sp-farmadmin -Mode SharePoint


Replace http://projectserver2013/pwa with you PWA URL and fluentpro\sp-farmadmin with your domain name \ user name.


Why there is no switch in UI as in Project Online? I have no idea, but this would be a good suggestion to Microsoft to add this into Central Administration in PWA settings.


Enjoy!
Read more...

Wednesday, July 18, 2012

Interested in migration from Project Server 2010 to Project Server 2013?


This week Microsoft released the Project Online - a cloud edition of Microsoft Project Server 2013. This means, that companies can start evaluating online edition that offers ways for easy scaling and start saving on investments into hardware and software. You can start paying monthly for resource that you use only, no maintenance, no hardware, no software licenses, no electricity bills.

Companies who currently using Project Server 2010 and considering the Project Online as potential destination should evaluate the the Project Online from different angles:

  • User Interface
  • Usability
  • Scaleability
  • Performance
  • Support of existing configuration
  • Load testing
Some of this can be addressed with just out-of-the box functionality, but companies will face a reasonable issue  - How do we test Project Online with our configuration settings and with our data (projects, resources) from existing Project Server 2010 or Project Server 2010 instance?

FluentPro Software has a solution for this - FluentPro Cloud Migrator that allows migration of configuration and data from Project Server 2010 to Project Online.

There are 2 editions available - Free and Pro; Free Edition migrates everything except project sites content and security, Pro Edition can migrate all settings and data.

You can download FuentPro Cloud Migrator from our website - www.projectmigrator.com.

Read more...

Monday, March 26, 2012

ProjectServer 2010: Create Custom Fields and Lookup Tables from PowerShell

In this post we’ll demonstrate how to create Lookup Table and Custom Fields on PWA from PowerShell.
All you need is create several objects with types from FluentPS.Model namespace and use LookupTableService or CustomFieldService to create items on ProjectServer instance.

See the full source:
$fluentps = Get-FluentPS -PWAUrl "http://localhost/PWA"

$lookup = new-object FluentPS.Model.PSLookupTableInfo
$lookup.Name = "LT Test1"
$lookup.Type = [FluentPS.Enums.PSFieldType]::Text

$lookupsToCreate = New-Object 'System.Collections.Generic.List[FluentPS.Model.PSLookupTableInfo]'
$lookupsToCreate.Add($lookup)

$fluentps.LookupTableService.CreateLookupTables($lookupsToCreate)


$cf = new-object FluentPS.Model.PSCustomFieldInfo
$cf.FieldName = "Test Field 1"

$lcf = new-object FluentPS.Model.PSLookupFieldInfo
$lcf.FieldName = "Test Lookup Field 1"
$lcf.LookupTableName = "LT Test1"

$fieldsToCreate = New-Object 'System.Collections.Generic.List[FluentPS.Model.PSCustomFieldInfo]'
$fieldsToCreate.Add($cf)
$fieldsToCreate.Add($lcf)

$fluentps.CustomFieldService.SaveOrUpdateCustomFields($fieldsToCreate, [FluentPS.Enums.PSEntityType]::Project)

Have fun!

Read more...

Monday, March 12, 2012

Session PC325 at MPC12: Project Server 2010 configuration management, migration, merge and documenting


Wednesday, FluentPro Software co-founder, Anton Kravtsov will presenting on Microsoft Project Conference 2012  about configuration management in Project Server 2010 and how it can be improved and optimized with our product - FluentBooks.

Link to session: Session PC325

When: Wednesday, March 21,  5:00PM,  North 223

We would be glad to see you there! Read more...

Monday, February 27, 2012

How to use Secure Store Id for Impersonation programmatically

Sometimes you run into issue that Application Pool Account doesn’t have access to Reporting Database or to another database but you should configure credential to access Reporting Database or other databases in your application. To achieve this Microsoft SharePoint 2010 has new service - Secure Store Service. You can provide account credential and set permission for users who can manage those credentials.

This article will describe how to configure Secure Store and how to work with it from code.

First step is configuring Secure Store Id:

  1. Navigate to Central Administration -> Application Management -> Manage service applications -> Secure Store Service

  2. Click New button on the ribbon, fill out form and click Next

  3. Click Next button without any changes

  4. Provide Target Application Administrators, Members and click OK

  5. Choose just created Secure Store in the list and click Set Credentials button on the ribbon

  6. Provide account name and password


You successfully completed Secure Store Id configuration. Next step is to read account credential programmatically. The following class read credential from provided Security Store Id and returns IdentityInfo.

public class IdentityInfo
{
    public string Domain { get; set; }
    public string Username { get; set; }
    public string Password { get; set; } 
}

public class SPSecureStoreService 
{
    public IdentityInfo GetCredentials(string targetApplicationId)
    {
        var credentials = GetWindowsCredentials(targetApplicationId);
        return ParseSecureStoreCredentials(credentials);
    }

    private IdentityInfo ParseSecureStoreCredentials(Dictionary<SecureStoreCredentialType, string> credentials)
    {
        if (!credentials.ContainsKey(SecureStoreCredentialType.WindowsUserName))
            throw new ArgumentNullException("credentials", "WindowsUserName field not defined");

        if (!credentials.ContainsKey(SecureStoreCredentialType.WindowsPassword))
            throw new ArgumentNullException("credentials", "WindowsPassword field not defined");
            
        string windowsUserName = credentials[SecureStoreCredentialType.WindowsUserName];
        string windowsPassword = credentials[SecureStoreCredentialType.WindowsPassword];

        var identityInfo = new IdentityInfo();
        identityInfo.Password = windowsPassword;

        if (string.IsNullOrEmpty(windowsUserName))
            throw new ArgumentNullException("credentials", "windowsUserName not defined");
            
        // treat domain\username
        if (windowsUserName.Contains("\\"))
        {
            var parts = windowsUserName.Split('\\');

            identityInfo.Domain = parts[0];
            identityInfo.Username = parts[1];
        }
        // treat username@domain
        else if (windowsUserName.Contains("@"))
        {
            var parts = windowsUserName.Split('@');

            identityInfo.Username = parts[0];
            identityInfo.Domain = parts[1];
        }
        else
        {
            identityInfo.Username = windowsUserName;
        }

        return identityInfo;
    }

    private Dictionary<SecureStoreCredentialType, string> GetWindowsCredentials(string targetApplicationId)
    {
        var serviceContext = SPServiceContext.Current;
        var secureStoreProvider = new SecureStoreProvider { Context = serviceContext };
        var credentialMap = new Dictionary<SecureStoreCredentialType, string>();

        using (var credentials = secureStoreProvider.GetCredentials(targetApplicationId))
        {
            var fields = secureStoreProvider.GetTargetApplicationFields(targetApplicationId);
            for (var i = 0; i < fields.Count; i++)
            {
                var field = fields[i];

                var credential = credentials[i];
                var decryptedCredential = ToClrString(credential.Credential);

                credentialMap.Add(field.CredentialType, decryptedCredential);
            }
        }

        return credentialMap;
    }

    private string ToClrString(SecureString secureString)
    {
        var ptr = Marshal.SecureStringToBSTR(secureString);

        try
        {
            return Marshal.PtrToStringBSTR(ptr);
        }
        finally
        {
            Marshal.FreeBSTR(ptr);
        }
    }
}

After you get credentials you will able to impersonate to the user. The following code does impersonation:

public class Impersonator : IDisposable
{
    #region Public methods.
    // ------------------------------------------------------------------

    public Impersonator(
        string userName,
        string domainName,
        string password)
    {
        ImpersonateValidUser(userName, domainName, password);
    }

    // ------------------------------------------------------------------
    #endregion

    #region IDisposable member.
    // ------------------------------------------------------------------

    public void Dispose()
    {
        UndoImpersonation();
    }

    // ------------------------------------------------------------------
    #endregion

    #region P/Invoke.
    // ------------------------------------------------------------------

    [DllImport("advapi32.dll", SetLastError = true)]
    private static extern int LogonUser(
        string lpszUserName,
        string lpszDomain,
        string lpszPassword,
        int dwLogonType,
        int dwLogonProvider,
        ref IntPtr phToken);

    [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    private static extern int DuplicateToken(
        IntPtr hToken,
        int impersonationLevel,
        ref IntPtr hNewToken);

    [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    private static extern bool RevertToSelf();

    [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
    private static extern bool CloseHandle(
        IntPtr handle);

    private const int LOGON32_LOGON_INTERACTIVE = 2;
    private const int LOGON32_PROVIDER_DEFAULT = 0;

    // ------------------------------------------------------------------
    #endregion

    #region Private member.
    // ------------------------------------------------------------------

    private void ImpersonateValidUser(
        string userName,
        string domain,
        string password)
    {
        WindowsIdentity tempWindowsIdentity = null;
        IntPtr token = IntPtr.Zero;
        IntPtr tokenDuplicate = IntPtr.Zero;

        try
        {
            if (RevertToSelf())
            {
                if (LogonUser(
                    userName,
                    domain,
                    password,
                    LOGON32_LOGON_INTERACTIVE,
                    LOGON32_PROVIDER_DEFAULT,
                    ref token) != 0)
                {
                    if (DuplicateToken(token, 2, ref tokenDuplicate) != 0)
                    {
                        tempWindowsIdentity = new WindowsIdentity(tokenDuplicate);
                        impersonationContext = tempWindowsIdentity.Impersonate();
                    }
                    else
                    {
                        throw new Win32Exception(Marshal.GetLastWin32Error());
                    }
                }
                else
                {
                    throw new Win32Exception(Marshal.GetLastWin32Error());
                }
            }
            else
            {
                throw new Win32Exception(Marshal.GetLastWin32Error());
            }
        }
        finally
        {
            if (token != IntPtr.Zero)
            {
                CloseHandle(token);
            }
            if (tokenDuplicate != IntPtr.Zero)
            {
                CloseHandle(tokenDuplicate);
            }
        }
    }

    private void UndoImpersonation()
    {
        if (impersonationContext != null)
        {
            impersonationContext.Undo();
        }
    }

    private WindowsImpersonationContext impersonationContext = null;

    // ------------------------------------------------------------------
    #endregion
}

Now you can work with your databases or other objects under user configured via Secure Store and no credentials are used directly in the code.

Enjoy!

Read more...

Wednesday, February 22, 2012

FluentPro Workspaces - New life for project sites in Microsoft Project Server 2010


Project Sites.
  • Tired of grey, static and not-visually appealing project sites?
  •  Don't like that information is in many places and I have to switch to see it?
We are tired of them too. So - we've developed a product for our customers that in its nature is a modified project site template that will change your experience with Project Sites in MS Project Server 2010.
  • Microsoft Metro-style design with home pages based on tiles that every user can customize
  • Easy access via links to native Project Web App pages - My Tasks, Timesheets, Project Schedule PDP
  • Visualized and improved risks, issues, change request and action items lists
  • Easy customization and re-use - add your own lists, pages, sub-sites (Wiki, Blog and other) and standard / customer webparts without any restrictions, save as project site template and distribute inside of your organization for different project types - this is just a native Project Site Template.



Video preview:




Visit our booth #209 at Project Conference 2012 and take a closer look on this amazing product.

Product will be launched at Project Conference 2012 and will be available for purchase.

EPM partners: Have your own products and would like to incorporate this product into your solutions? Let's talk.
Read more...

Tuesday, February 7, 2012

FluentPro Audit Lite if available for Free download


FluentPro Audit Lite is available for FREE download from our website.

Quick overview of functionality:
  • Audit changes in Enterprise Custom Fields
  • Audit changes in Enterprise Lookup Tables
  • Project creation and deletion
  • Audit changes in projects (Project level custom fields, tasks add / delete)
  • Application tracks Who, What and When
Enjoy!
Read more...