تعیین سطح دسترسی کاربران (بصورت جزئی به اجزا سایت) در MVC

پنجشنبه 22 مرداد 1394

در این مقاله قصد داریم تعیین سطح دسترسی هر کار بر صورت جداگانه به عناصر صفحات و خود صفحات را به صورت داینامیک و در لحظه اجراآموزش دهیم

 تعیین سطح دسترسی کاربران (بصورت جزئی به اجزا سایت) در MVC

برای شروع یک بانک اطلاعاتی به نام Example ایجاد میکنیم

یک جدول برای نگهداری اطلاعات ورود کاربران با نام Users ایجاد میکنیم.

 

سپس یک جدول با نام Permissions برای نگهداری اطلاعات مربوط به کنترل ها و صفحات میسازیم

در این جدول ستون ParentID برای نگهداری والد این رکورد میباشد

مثلا صفحه کاربران چند زیر مجموعه  با عنوان های ثبت کاربر جدید و ویرایش و ... دارد  که با این ستون میتوانیم مشخص کنیم که این Permission برای کدام یک از صفحات یا کنترل اصلی می باشد

سپس یک جدول برای نگهداری دسترسی هر کاربر با نام Users_Permissions می سازیم

را بطه این جدول با Users و Permissions را بر قرار میکنیم

اسکریپت ساخت بانک اطلاعاتی به همراه جداول به شرح ذیل است :

ابتدا بانکی با نام User_Permission_DB بسازید و اسکریپت زیر را روی آن اجرا کنید

GO
/****** Object:  Table [dbo].[Users]    Script Date: 06/13/2015 16:09:29 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[Users](
    [UserID] [int] IDENTITY(1,1) NOT NULL,
    [UserName] [nvarchar](150) NOT NULL,
    [Password] [nvarchar](150) NOT NULL,
 CONSTRAINT [PK_Users] PRIMARY KEY CLUSTERED
(
    [UserID] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
SET IDENTITY_INSERT [dbo].[Users] ON
INSERT [dbo].[Users] ([UserID], [UserName], [Password]) VALUES (1, N'ایمان مدائنی', N'123')
INSERT [dbo].[Users] ([UserID], [UserName], [Password]) VALUES (2, N'برنامه نویسان', N'123')
SET IDENTITY_INSERT [dbo].[Users] OFF
/****** Object:  Table [dbo].[Permissions]    Script Date: 06/13/2015 16:09:29 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[Permissions](
    [PermissionID] [int] IDENTITY(1,1) NOT NULL,
    [PermissionTitle] [nvarchar](150) NOT NULL,
    [ParentID] [int] NULL,
 CONSTRAINT [PK_Permissions] PRIMARY KEY CLUSTERED
(
    [PermissionID] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
SET IDENTITY_INSERT [dbo].[Permissions] ON
INSERT [dbo].[Permissions] ([PermissionID], [PermissionTitle], [ParentID]) VALUES (1, N'پنل مدیریت', NULL)
INSERT [dbo].[Permissions] ([PermissionID], [PermissionTitle], [ParentID]) VALUES (2, N'صفحه مدیریت کاربران', NULL)
INSERT [dbo].[Permissions] ([PermissionID], [PermissionTitle], [ParentID]) VALUES (3, N'افزودن کاربر جدید', 2)
INSERT [dbo].[Permissions] ([PermissionID], [PermissionTitle], [ParentID]) VALUES (4, N'تعیین سطح دسترسی', 2)
SET IDENTITY_INSERT [dbo].[Permissions] OFF
/****** Object:  Table [dbo].[Users_Permissions]    Script Date: 06/13/2015 16:09:29 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[Users_Permissions](
    [UP_ID] [int] IDENTITY(1,1) NOT NULL,
    [UserID] [int] NOT NULL,
    [PermissionID] [int] NOT NULL,
 CONSTRAINT [PK_Users_Permissions] PRIMARY KEY CLUSTERED
(
    [UP_ID] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
SET IDENTITY_INSERT [dbo].[Users_Permissions] ON
INSERT [dbo].[Users_Permissions] ([UP_ID], [UserID], [PermissionID]) VALUES (7, 1, 1)
INSERT [dbo].[Users_Permissions] ([UP_ID], [UserID], [PermissionID]) VALUES (8, 1, 4)
SET IDENTITY_INSERT [dbo].[Users_Permissions] OFF
/****** Object:  ForeignKey [FK_Users_Permissions_Permissions]    Script Date: 06/13/2015 16:09:29 ******/
ALTER TABLE [dbo].[Users_Permissions]  WITH CHECK ADD  CONSTRAINT [FK_Users_Permissions_Permissions] FOREIGN KEY([PermissionID])
REFERENCES [dbo].[Permissions] ([PermissionID])
GO
ALTER TABLE [dbo].[Users_Permissions] CHECK CONSTRAINT [FK_Users_Permissions_Permissions]
GO
/****** Object:  ForeignKey [FK_Users_Permissions_Users]    Script Date: 06/13/2015 16:09:29 ******/
ALTER TABLE [dbo].[Users_Permissions]  WITH CHECK ADD  CONSTRAINT [FK_Users_Permissions_Users] FOREIGN KEY([UserID])
REFERENCES [dbo].[Users] ([UserID])
GO
ALTER TABLE [dbo].[Users_Permissions] CHECK CONSTRAINT [FK_Users_Permissions_Users]
GO

حالا یک پروژه با نام Permission_MVC ایجاد میکنیم

حال یک Areas به نام   AdminManager  برای قرار دادن صفحات مدیریت ایجاد میکنیم

حال  یک  کنترل ،از نوع Users  از جنس  Controller with views, using Entity Framework MVC 5   ایجاد میکنیم.

حال از برنامه اجرا گرفته و شروع به ثبت داده کنید

 

حال در این مرحله میخواهیم به با استفاده از  TreeView  به پیاده سازی سطح دسترسی ها بپردازیم

ابتدا یک کلاس به نام Treelist با متغیر های زیر ایجاد میکنیم

 public class Treelist
    {
        public int Id { set; get; }

        public string Name { set; get; }

        public int? ParentId { get; set; }

        public int ExtraID { get; set; }


        public List<Treelist> TreeListItm { get; set; }
        // مخصوص کندو یو آی هستند
        public bool HasChildren { get; set; }

        public bool Checked { get; set; }
        public string imageUrl { get; set; }
    }

حال برای استفاده از TreeView یک کلاس به نام    TreeClasses ایجاد میکنیم 

 public class TreeClasses
    {
        public Treelist LoadTreeByBindingModel(List<Treelist> _Treelist, int RootID)
        {
            Treelist _Treelist_Out = new Treelist();
            #region Check Exites One Parentes
            int CountParent = _Treelist.Where(n => n.Id == RootID).Count();
            if (CountParent != 1)
            {
                return _Treelist_Out;
            }
            #endregion
            #region FillData
            _Treelist_Out = _Treelist.Where(n => n.Id == RootID).FirstOrDefault();
            //_Treelist_Out .Checked ==>Defult Ast 
            //_Treelist_Out.Id ==>Defult Ast 
            //_Treelist_Out.imageUrl ==>Defult Ast 
            //_Treelist_Out.Name==>Defult Ast 
            //_Treelist_Out.ParentId==>Defult Ast 
            //_Treelist_Out.ExtraID ==>Defult ast 
            _Treelist_Out.TreeListItm = TreelistChild(_Treelist, RootID);
            if (_Treelist.Where(n => n.ParentId == RootID).Count() > 0)
            {
                _Treelist_Out.HasChildren = true;
            }
            else
            {
                _Treelist_Out.HasChildren = false;
            }

            #endregion

            return _Treelist_Out;
        }
        private List<Treelist> TreelistChild(List<Treelist> _MainTreeList, int Parent)
        {
            List<Treelist> _ListTreeOut = new List<Treelist>();
            List<Treelist> _ListChild = _MainTreeList.Where(n => n.ParentId == Parent).ToList();
            if (_ListChild.Count > 0)
            {
                foreach (var item in _ListChild)
                {
                    Treelist p1 = new Treelist();
                    p1.Checked = item.Checked;
                    if (_MainTreeList.Where(n => n.ParentId == item.Id).Count() > 0)
                    {
                        p1.HasChildren = true;
                    }
                    else
                    {
                        p1.HasChildren = false;
                    }
                    p1.Id = item.Id;
                    p1.ExtraID = item.ExtraID;
                    p1.imageUrl = item.imageUrl;
                    p1.Name = item.Name;
                    p1.ParentId = item.ParentId;
                    p1.TreeListItm = TreelistChild(_MainTreeList, item.Id);
                    _ListTreeOut.Add(p1);
                }
            }
            return _ListTreeOut;

 

 این کلاس حاوی دومتد که متد   LoadTreeByBindingModel برای لود شدن والد ها و متد TreelistChild برای لود شدن زیر مجموعه ها (Child)  به کار میرود .

حال در کنترلر User رفته و یک متد برای برای ذخیره کاربر و نوع سطح دسترسی آن ایجاد میکنیم

  public ActionResult TreeView(int id)
        {
            var PermissionID = db.Permissions.Find(id);
            ViewBag.PermissionTitle = PermissionID.PermissionTitle;

                    var _TreeLoad = db.Permissions.ToList();
                  
                    List<Treelist> _TreeList = new List<Treelist>();

                    var users = db.Users.First().UserID;
                    foreach (var item in _TreeLoad)
                    {

                        Treelist p = new Treelist();
                        p.Id = item.PermissionID;
                        p.ParentId = item.ParentID;
                        p.Name = item.PermissionTitle;
                        p.Checked = db.Users_Permissions.Where(m=>m.PermissionID==id).Any(n => n.PermissionID == item.PermissionID );
                            //در اینجا ما فرض کردیم تمام گره ها تیک خورده هستند اگر می خواهید بایند شود کافی از روی دیتا بیس چک کنید
                        p.ExtraID = id;
                            //این برای این است که اطلاعات اضافی همراه داشته باشد مثلا این گره مربوط به کدام گروه است 
                        _TreeList.Add(p);
                      
                    }




                    TreeClasses _TreeClasses = new TreeClasses();
                    Treelist _TreelistMain = _TreeClasses.LoadTreeByBindingModel(_TreeList, 1);

                    return View(_TreelistMain);
              
  }

یک ورودی از جنس int به نام id  میگیریم این کار برای گرفتن والد یا (همان ParntID)اصلی است

حال یک View ساخته و کد های زیر را داخل آن مینویسیم

@{
    ViewBag.Title = "Index";
}
@model Permission_MVC.Areas.AdminManager.Models.Treelist
           



@Html.Action("CreatePartialViewByTreeListModel", "Users", new { _Tree = @Model, AddressSelectedNode = "/AdminManager/Users/SaveNodes" });

همان طور که مشاهده میکنید  View را  به متد  CreatePartialViewByTreeListModel ارسال کردیم  در این مرحله به ایجاد متد بالامیپردازیم

   public ActionResult CreatePartialViewByTreeListModel(Treelist _Tree, string AddressSelectedNode)
        {
            ViewBag.AddressSelectedNode = AddressSelectedNode;
            return PartialView(_Tree);

      
  }
 

در واقع کار متد بالا نمایش سطوح دسترسی با treeview است  حال یک view از متد بالا  ایجاد میکنیم

model Permission_MVC.Areas.AdminManager.Models.Treelist
           
<link href="~/Scripts/humane_js_themes/bigbox.css" rel="stylesheet" />
<style>
    .tree li {
        margin: 0px 0;
        list-style-type: none;
        position: relative;
        padding: 5px 50px 0px 5px;
    }

        .tree li::before {
            content: '';
            position: absolute;
            top: 0;
            width: 35px;
            height: 100%;
            left: auto;
            right: -20px;
            border-left: 2px solid #ccc;
            bottom: 50px;
        }

        .tree li::after {
            content: '';
            position: absolute;
            top: 15px;
            width: 35px;
            height: 20px;
            left: auto;
            right: 14px;
            border-top: 2px solid #ccc;
        }

        .tree li a {
            display: inline-block;
            /*border: 1px solid #ccc;*/
            padding: 1px 5px 0 10px;
            text-decoration: none;
            color: #666;
            font-family: bkoodaks,Tahoma,'Open Sans',sans-serif;
            font-size: 14px;
            font-weight: 600;
            border-radius: 5px;
            -webkit-border-radius: 5px;
            -moz-border-radius: 5px;
        }

    /*Remove connectors before root*/
    .tree > ul > li::before, .tree > ul > li::after {
        border: 0;
    }
    /*Remove connectors after last child*/
    .tree li:last-child::before {
        height: 15px;
    }

    /*Time for some hover effects*/
    /*We will apply the hover effect the the lineage of the element also*/
    .tree li a:hover, .tree li a:hover + ul li a {
        background: #dd4814;
        color: #ffffff;
        /*border: 1px solid #dd4814;*/
    }
        /*Connector styles on hover*/
        .tree li a:hover + ul li::after,
        .tree li a:hover + ul li::before,
        .tree li a:hover + ul::before,
        .tree li a:hover + ul ul::before {
            border-color: #dd4814;
        }

    .tree-checkbox {
        margin: 4px !important;
    }


    .tree:before {
        border-left: 1px solid #ccc;
        bottom: 16px;
        content: "";
        display: block;
        right: 0;
        /*position: relative;*/
        top: -21px;
        width: 1px;
        z-index: 1;
    }

    .tree ul:after {
        /*border-top: 1px solid #ccc;*/
        content: "";
        height: 20px;
        right: -29px;
        position: absolute;
        left: auto;
        top: 37px;
        width: 34px;
    }

    *:before, *:after {
        box-sizing: border-box;
    }

    *:before, *:after {
        box-sizing: border-box;
    }

    .tree {
        overflow: auto;
        padding-right: 0px;
        position: relative;
    }

    label {
        float: left;
    }
</style>

<div class="row-fluid">
    <div id="frm-author">
        @using (Html.BeginForm("SaveNodes", "Users", FormMethod.Post, new { encType = "multipart/form-data" }))
        {
            @Html.HiddenFor(model => model.ExtraID)
            <div class="tree">
                @if (1 == 1)
                {
                    <ul>
                        <li>
                            <a>
                                @Html.CheckBoxFor(model => @Model.Checked, new { @class = "tbkh tree-checkbox parent", @id = @Model.Id, @kk = @Model.ExtraID })
                                <label for=@Model.Id>
                                    @Html.DisplayFor(model => @Model.Name)
                                </label>

                            </a>
                            @*------------------Level2--------------------------------------------------------*@
                            @if (@Model.TreeListItm != null && @Model.TreeListItm.Count() > 0)
                            {
                                <ul>
                                    @foreach (var itemChild1 in @Model.TreeListItm)
                                    {
                                        <li>
                                            <a>
                                                @Html.CheckBoxFor(model => itemChild1.Checked, new { @class = "tbkh tree-checkbox node-item", @id = @itemChild1.Id, @kk = @itemChild1.ExtraID })

                                                <label for=@itemChild1.Id>
                                                    @Html.DisplayFor(model => @itemChild1.Name)
                                                </label>

                                            </a>
                                            @*------------------Level3-------------------------------------------------------*@
                                            @if (@itemChild1.TreeListItm.Count() > 0)
                                            {
                                                <ul>
                                                    @foreach (var itemChild3 in @itemChild1.TreeListItm)
                                                    {
                                                        <li>
                                                            <a>
                                                                @Html.CheckBoxFor(model => itemChild3.Checked, new { @class = "tbkh tree-checkbox node-item", @id = @itemChild3.Id, @kk = @itemChild3.ExtraID })

                                                                <label for=@itemChild3.Id>
                                                                    @Html.DisplayFor(model => @itemChild3.Name)
                                                                </label>

                                                            </a>
                                                            @*------------------Level4-------------------------------------------------------*@
                                                            @if (@itemChild3.TreeListItm.Count() > 0)
                                                            {
                                                                <ul>
                                                                    @foreach (var itemChild4 in @itemChild3.TreeListItm)
                                                                    {
                                                                        <li>
                                                                            <a>
                                                                                @Html.CheckBoxFor(model => itemChild4.Checked, new { @class = "tbkh tree-checkbox node-item", @id = @itemChild4.Id, @kk = @itemChild4.ExtraID })

                                                                                <label for=@itemChild4.Id>
                                                                                    @Html.DisplayFor(model => @itemChild4.Name)
                                                                                </label>

                                                                            </a>
                                                                            @*------------------Level5-------------------------------------------------------*@
                                                                            @if (@itemChild4.TreeListItm.Count() > 0)
                                                                            {
                                                                                <ul>
                                                                                    @foreach (var itemChild5 in @itemChild4.TreeListItm)
                                                                                    {
                                                                                        <li>
                                                                                            <a>
                                                                                                @Html.CheckBoxFor(model => itemChild5.Checked, new { @class = "tbkh tree-checkbox node-item", @id = @itemChild5.Id, @kk = @itemChild5.ExtraID })

                                                                                                <label for=@itemChild5.Id>
                                                                                                    @Html.DisplayFor(model => @itemChild5.Name)
                                                                                                </label>

                                                                                            </a>
                                                                                        </li>

                                                                                    }
                                                                                </ul>
                                                                            }
                                                                            @*------------------Level5--------------------------------------------------------*@
                                                                        </li>

                                                                    }
                                                                </ul>
                                                            }
                                                            @*------------------Level4--------------------------------------------------------*@
                                                        </li>

                                                    }
                                                </ul>
                                            }
                                            @*------------------Level3--------------------------------------------------------*@
                                        </li>

                                    }
                                </ul>
                            }
                            @*------------------Level2--------------------------------------------------------*@
                        </li>
                    </ul>
                }

            </div>

        }
        <div class="row-fluid">
            <div class="row-form">
                <button class="btn btn-success pull-left" id="btnSubmit2" onclick="SelectedNodeChecked(1);">
                    ذخیره تغییرات
                </button>
                <a href="/AdminManager/Users/Index" class="btn pull-right">بازگشت به لیست اصلی</a>
            </div>
        </div>
    </div>
</div>
<div id="ModalCreate">
    
</div>
<script src="~/Scripts/humane.min.js"></script>

<script type="text/javascript">

    function SelectedNodeChecked(id) {
        var checked = [];
        $(".tbkh").each(function (index, element) {
            if ($(this).is(":Checked")) {
                var i;
                i = $(this).attr('id');
                checked.push(i);
            }
        });
        var roleId = $("#ExtraID").val();

        $.ajax({
            url: "@ViewBag.AddressSelectedNode",
            type: "POST",
            data: "id=" + checked + "&PermissionID=" + roleId,
            success: function (result) {
                updateSuccess();
                $('#myModal').modal('hide');
                window.location.href = "/AdminManager/Users/Index";

            }

        });
    };
    function updateSuccess(data) {
        $('#ModalCreate').modal('hide');
        humane.log("اطلاعات با موفقیت ثبت گردید");
    }

</script>

 

در این مرحله تا 5 سطر ، دسترسی میتوان تعریف کرد  و ما با استفاده از Ajax قصد داریم وقتی کاربر سطوح دسترسی را انتخاب کرد در بانک ذخیره شود 

در این قسمت کد ثبت را مینوسیم

public ActionResult SaveNodes(string id, string PermissionID)
        {
            if (id.Trim() != "" && PermissionID.Trim() != "")
            {
                var pID = int.Parse(PermissionID);
                var Permissionresult = db.Users_Permissions.Where(m => m.PermissionID == pID).ToList();

                foreach (var item in Permissionresult)
                {
                    db.Users_Permissions.Remove(item);
                }
                db.SaveChanges();
                foreach (string s in id.Split(char.Parse(",")))
                {
                    db.Users_Permissions.Add(new Users_Permissions()
                    {
                        PermissionID = int.Parse(s),
                        UserID = pID
                    });

                }
                db.SaveChanges();

            }

                    return null;
                }

 

اگر به کد Ajax ای که در view نوشتیم دقت کنید دو تا  پارامتر به نام های  id , PermissionID گرفتیم که در متد SaveNodes آن ها رابه عنوان پارامتر ورودی گرفتیم

متغیر PermissionID ، برای پاس دادن ئ به جدول  Users_Permissions و متغیر id برای گرفتن id کاربر به کار میرود

و همان طور که مشاهده میکنید ایتدا تمام سطوح دسترسی را پاک کرده و سپس اضافه میکنیم

فایل های ضمیمه

برنامه نویسان

نویسنده 3355 مقاله در برنامه نویسان

کاربرانی که از نویسنده این مقاله تشکر کرده اند

در صورتی که در رابطه با این مقاله سوالی دارید، در تاپیک های انجمن مطرح کنید