Saturday, July 16, 2011

Dynamics CRM 2011 : Security Role Article Publishing Privilege Not Working

  
While browsing Microsoft Dynamics CRM Development Forums, i have found an interesting security privilege issue post “Both the CSR Manager and Customer Service Representative can publish articles” , after performing a test i found that the security permissions are not working regardless of the Published Article Privileges. So i decided to write up a solution that will fix the issue to help the Microsoft Dynamics CRM customers.

Microsoft Dynamics CRM 2011 (On-Premise & Online) Solution Download & Installation Steps:

1. Click here to download solution file (ArticlePublishingSecurityPrivilegeFix_1_0_0_0.zip)

2. In CRM 2011, go to Settings -> Customization -> Solutions

3. Click on Import button and Browse for the ArticlePublishingSecurityPrivilegeFix_1_0_0_0.zip file

4. During wizard, in Import Options screen makes sure to select option “Activate any process and enable
any SDK message processing steps included in the solution.”

5. Now you can verify Article Publishing Privileges
[Plugin: C# Code]


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Metadata;
using Microsoft.Crm.Sdk;
using Microsoft.Crm.Sdk.Messages;
using Microsoft.Xrm.Sdk.Query;
using Microsoft.Xrm.Sdk.Messages;

namespace wod.Crm.Article.Publishing.Fix
{
    public class wod_Plugin : IPlugin
    {
        public void Execute(IServiceProvider serviceProvider)
        {
            #region Variable Declaration

            // Obtain the execution context from the service provider.
            Microsoft.Xrm.Sdk.IPluginExecutionContext context =  
            (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));

            IOrganizationServiceFactory wod_serviceFactory = null;

            IOrganizationService wod_CrmService = null;

            RetrieveUserPrivilegesRequest lclRetrieveUserPrivilegesRequest = null;

            RetrieveUserPrivilegesResponse lclRetrieveUserPrivilegesResponse = null;

            Entity wod_ArticlePublishPrivEntity = null;

            #endregion

            try
            {
                // Check if SetState message is triggered on kbarticle entity
                if (context.InputParameters.Contains("EntityMoniker")
                    && context.InputParameters["EntityMoniker"] is EntityReference
                    && ((EntityReference)context.InputParameters["EntityMoniker"]).LogicalName == "kbarticle")
                {
                    switch (context.MessageName)
                    {
                        case "SetStateDynamicEntity":

                            #region Article Publishing Privileges Checking Code


                            // check if input parameter contains status
                            if (context.InputParameters.Contains("Status"))
                            {
                                // Check if status paramter value is Published Article code
                                if (((OptionSetValue)context.InputParameters["Status"]).Value == -1)
                                {

                                    // Obtain the service factory to get the service object
                                    wod_serviceFactory = (IOrganizationServiceFactory)serviceProvider
                                                         .GetService(typeof(IOrganizationServiceFactory));

                                    // Obtain service object Imporsonated as plugin calling user
                                    wod_CrmService =
                                    wod_serviceFactory.CreateOrganizationService(context.UserId);

                                    // Retrieve Article publishing privilege Id
                                    wod_ArticlePublishPrivEntity = RetrieveEntityByAttribute(ref wod_CrmService,
                                   "privilege"
                                    , new string[] { "privilegeid" }, new string[] { "name" }
                                    , new object[] { "prvPublishArticle" });

                                    if (wod_ArticlePublishPrivEntity != null)
                                    {
                                        lclRetrieveUserPrivilegesRequest = new RetrieveUserPrivilegesRequest();

                                        // Pass current user id to for retrieving all privileges
                                        lclRetrieveUserPrivilegesRequest.UserId = context.InitiatingUserId;

                                        // Retrieve user all privileges
                                        lclRetrieveUserPrivilegesResponse = (RetrieveUserPrivilegesResponse)
                                        wod_CrmService.Execute(lclRetrieveUserPrivilegesRequest);

                                        // Search if user has privileges of publishing article
                                        RolePrivilege wod_UserArticlePublishPriv =
                                        lclRetrieveUserPrivilegesResponse.RolePrivileges
                                        ToList<RolePrivilege>().Find(delegate(RolePrivilege lclPublishPriv)
                                        {
                                            return lclPublishPriv.PrivilegeId == wod_ArticlePublishPrivEntity.Id
                                                && lclPublishPriv.BusinessUnitId == context.BusinessUnitId;
                                        });

                                        // If user does not have privileges then throw error and abort execution
                                        if (wod_UserArticlePublishPriv == null)
                                        {
                                            throw new InvalidPluginExecutionException("Not enough privileges to Publish article.");
                                        }
                                    }
                                }
                            }

                            #endregion

                            break;
                    }
                }

            }

            catch (System.Web.Services.Protocols.SoapException ex)
            {
                throw new InvalidPluginExecutionException(ex.Detail.InnerText);
            }
            catch (Exception ex)
            {
                throw new InvalidPluginExecutionException(ex.Message);
            }
        }

        #region Helper Method
       #region Helper Method

        // Helper method used to fetch entity record by column searching
        private Entity RetrieveEntityByAttribute(ref IOrganizationService CrmWebService, string EntityName
                                               , string[] RetrieveColumns, string[] FilterByColumns
                                               , object[] FilterByColumnsValue)
        {
            QueryByAttribute wod_Query = null;
            RetrieveMultipleRequest wod_Request = null;
            RetrieveMultipleResponse wod_Response = null;
            EntityCollection wod_RtrnEntyCollection = null;
            Entity wod_RtrnEntity = null;

            try
            {
                if (EntityName != string.Empty || RetrieveColumns != null || FilterByColumnsValue != null || FilterByColumnsValue != null)
                {
                    wod_Query = new QueryByAttribute();

                    wod_Request = new RetrieveMultipleRequest();

                    wod_Query.EntityName = EntityName;

                    wod_Query.ColumnSet = new ColumnSet(RetrieveColumns);

                    wod_Query.Attributes.AddRange(FilterByColumns);

                    wod_Query.Values.AddRange(FilterByColumnsValue);

                    wod_Request.Query = wod_Query;

                    wod_Response = (RetrieveMultipleResponse)CrmWebService.Execute(wod_Request);

                    wod_RtrnEntyCollection = wod_Response.EntityCollection;

                    if (wod_RtrnEntyCollection != null && wod_RtrnEntyCollection.Entities.Count > 0)
                    {
                        wod_RtrnEntity = (Entity)wod_RtrnEntyCollection.Entities[0];
                    }
                }
            }

            catch (System.Web.Services.Protocols.SoapException _sopEx)
            {
                throw new Exception(_sopEx.Detail.InnerText);
            }
            catch (Exception ex)
            {
                throw ex;
            }

            return wod_RtrnEntity;
        }

        #endregion
    }
}



27 comments:

  1. Jehanzeb Javeed,

    I'm not sure if you saw the third-to-last comment I left on the forum, but I just wanted to check to see if you are aware of this last minor issue. Here is the post again:

    "The new solution file works great, except for one small detail which may have not been addressed in enough detail in the original question I posed at the start of the forum. I created a set of Security Roles to meet the KCS multi-tiered article development strategy as I mentioned in the first question posed. Our KCS 1 role corresponds to most employees who can read published articles, comment and add notes when the article needs improvement, and create articles if necessary, and your plug-in supports that fully. However, we want another role (our KCS 2) to correspond to the editor user that can edit all articles (which is granted through the Write privilege and currently supported through your plug-in) and submit them for approval so that another higher security-level user can approve them for company use. Could you edit your solution to make it so the Write privilege (which we are giving to our editors) allows them to submit drafts for approval (in other words, make it so they don't need the Publish privilege to submit an article for approval, they just need the Write privilege)?"

    Thank you for your time.

    ReplyDelete
  2. Hi,

    I did not check the post on forum, i will get back to you soon on this issue.

    ReplyDelete
  3. Jehanzeb,

    Hello. Were you able to fix the issue that only those with the Publish privilege can submit articles for approval? We want those who have Write abilities to also be able to submit articles for approval. If you could either supply me with another updated solution or briefly explain how I could go about fixing that, it would be greatly appreciated.

    Thank you

    ReplyDelete
  4. Can the solution be updated so that we add restriction to the security roles to let only the owner of the article check it.

    ReplyDelete
  5. Hi all,

    I need to add a clarification .
    Can we let only one team see certain articles.
    I can do it through security roles because i can't assign in for "Business Unit"

    Thank you,

    ReplyDelete
  6. thanks
    this is the code of Equal Condition
    wod_ArticlePublishPrivEntity = RetrieveEntityByAttribute(ref wod_CrmService,
    "privilege"
    , new string[] { "privilegeid" }, new string[] { "name" }
    , new object[] { "prvPublishArticle" });

    but if we need not Equal Condition .so how is that possible in Crm 4?

    ReplyDelete
  7. Hi to every body, it's my first pay a quick visit of this
    webpage; this website includes awesome and truly good information for readers.


    Also visit my web blog - sale konferencyjne kielce

    ReplyDelete
  8. Choose whether any of your constraints are holding you back or whether you could employ the aid of others to
    pack in the spaces. Make the process of ordering be stress-free to complete at all times as possible.
    SEO is the most prominent tool to drive a
    huge traffic rate, as search engines really give closest attention to well-optimized
    pages.

    Look at my blog post - plus.google.com ()

    ReplyDelete
  9. Having read this I believed it was rather enlightening.
    I appreciate you taking the time and energy to put this informative article together.
    I once again find myself personally spending
    a significant amount of time both reading and leaving comments.

    But so what, it was still worth it!

    Have a look at my site - vlc player (freevlcmediaplayerdownload.Blogspot.com)

    ReplyDelete
  10. Basically oxidation enables life but also slowly kills us.
    To deal with them requires a lot of strength and help from
    a psychotherapist. Regardlessof whether one has
    dementia, through this article we've been in a
    position to see that the benefits of getting adequate nutrition can improve physical well-being and can help to boost functionality
    and improve the quality of life. In short vitamins are very essential for every individual.


    Also visit my website :: Procera AVH pills

    ReplyDelete
  11. Let me first begin by introducing too. I am Mei a person can call me anything you just like.

    Her husband and her live in Kentucky and or even she
    doesn't plan place in changing it. It's not a common thing but what she likes doing
    is to read comics and he or s he is working to make it a profession. I used to be unemployed but now I am an office
    clerk on the additional hand plan on changing the device.
    He's been perfecting his website for a few days now. Find out about
    it here: Mia Airport Parking

    Review my web blog ... Mia Parking

    ReplyDelete
  12. مكافحة حشرات ابوظبى 0567410494 التاج الملكى


    شركتنا التاج الملكى تعتبر
    افضل شركة مكافحة حشرات ابوظبى
    ، حيث تعمل على أبادة جميع الحشرات سواء الحشرات الزاحفة أو الحشرات الطائرة، وجميع الحشرات تضر بصحة الإنسان خاصة الأطفال لذا لابد التخلص من جميع الحشرات التي تؤذي صحة الإنسان، حيث أن
    شركة مكافحة الفئران ابوظبى
    تستخدم شركتنا العديد من المبيدات الحشرية الغير مضرة بصحة الإنسان لأنها مصرح بها من وزارة الصحة بابوظبي، لذا فأنها أمنة جداً ولا يوجد بها ضرر، لذا لابد أن نتخلص من جميع الحشرات حتى لا يحدث للإنسان أي مكروب وذلك لم يحدث إلا عن طريق
    شركة مكافحة حشرات ابوظبى
    .
    أهم المميزات التي تقدمها
    شركة مكافحة البق ابوظبى

    شركة مكافحة حشرات فى ابوظبى

    شركتنا تعمل على مكافحة جميع الحشرات، حيث تعتبر أحسن
    شركة مكافحة النمل الابيض ابوظبى
    ، وتعتبر أفضل
    شركة مكافحة الثعابين ابوظبى
    ، من ثم نعرض لكم جميع المميزات التي تخص
    شركة مكافحة الرمة ابوظبى

    ReplyDelete


  13. الحشرات تكثر الحشرات في الدول العربيّة بسبب ارتفاع درجات الحرارة وارتفاع نسبة الرطوبة في العديد من المناطق التي تطلّ على المسطّحات المائية، وتُسبّب تلك الحشرات والآفات الكثير من الضرر في حال تواجدها في المنازل أو منشآت الأعمال، خاصّةً التي تختصّ بالمنتجات الغذائية، ومن أهمّ المشاكل التي تسبّبها الحشرات في المنازل الأمراض التي تصيب قاطني المنزل خاصّةً الأطفال، والعفونة التي تصيب الأثاث والملابس المحفوظة في الخزائن.






    شركة مكافحة حشرات بجازان

    شركة مكافحة حشرات بخميس مشيط

    شركة تنظيف خزانات بالطائف

    شركة عزل اسطح بالطائف

    شركة كشف تسربات المياه بالطائف

    شركة نقل اثاث بالطائف

    شركة مكافحة حشرات بابها





    ReplyDelete
  14. سئو برای برند ها و کسب و کار های اینترنتی من مهدی پدرام مشاور سئو و سئوکار حرفه ای هستم با هشت سال سابقه راهبری تیم های دیجیتال مارکتینگ pedramseo.ir

    شرکت تابلو سازی آریو پاسارگاد در سال 1381 فعالیت خود را در زمینه تابلو سازی و اجرای نمای ساختمان آغاز نمود.از افتخارات شرکت آریو پاسارگاد دریافت لوح تقدیر از دبیر کل اجلاس صنایع ملی ایران به جهت حسن انجام فعالیت و نوآوری در زمینه تابلو سازی و کسب رتبه نخست تابلوسازی سال 95 کشور می باشد.www.tpasargad.ir

    اتوبار و باربری تهران همتا بار ارائه دهنده خدمات باربری و اتوبار در استان
    تهران می باشد که شما عزیزان می توانید با تکیه بر روزمه قابل اجرای شرکت
    باربری تهران همتا بار این اطمینان را برای خودتان به وجود بیاورید که
    اسباب کشی شما را با تخصصی که در عرصه باربری داریم به مقصد مورد نظرتان برسانیم.tehranfreight.com

    ReplyDelete