所有源码在 https://github.com/luqizheng/Qi4Net

 

看Demo

 

和一个持久化对象自动绑定

//持久化对象
//Qi4Net\src\Qi\MvcTest\Models\User.cs
public class User : DomainObject<Guid>
    {
        public string LoginId { getset; }
        public string Name { getset; }
        public string Password { getset; }
        public override int GetHashCode()
        {
            return (Name + Password).GetHashCode();
        }
    }

 

Post上来的数据会自动set到User里面,而且是自动匹配类型(其实就是NHibernate.Type.IType,提供的方法进行转换) 。NHibernateBinder会自动忽略只有Get的方法,另外IList,ISet是不支持的,因为不能简单地Clear and Add.所以只能靠手工了

//D:\GitQi\Qi4Net\src\Qi\MvcTest\Controllers\UserController.cs
[HttpPost,Session]
public ActionResult Edit([ModelBinder(typeof(NHModelBinder))]User user)
        {
            SessionManager.Instance.CurrentSession.SaveOrUpdate(user); 
            return RedirectToAction("Index");
        }

 

第二种,持久化对象是某个对象的其中一个。

 

是ChangeUserPasswordModel,而不是ChangePasswordModel,不太严谨,请见谅。

 

//\Qi4Net\src\Qi\MvcTest\Models\ChangeUserPasswordModel.cs
public class ChangeUserPasswordModel
    {
        [Required]
        public User User { getset; }

        [Required]
        [StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)]
        [DataType(DataType.Password)]
        [Display(Name = "New password")]
        public string NewPassword { getset; }

        [DataType(DataType.Password)]
        [Display(Name = "Confirm new password")]
        [Compare("NewPassword", ErrorMessage = "The new password and confirmation password do not match.")]
        public string ConfirmPassword { getset; }
    }

 

View要做稍稍处理,用HiddenFor是不行的。我用了

@Html.Hidden("User"this.Model.User.Id),其中"User"和

ChangeUserPasswordModel.User 名称是一样的。

 

//Qi4Net\src\Qi\MvcTest\Views\User\ChangePassword.cshtml
@using (Html.BeginForm())
{
    @Html.ValidationSummary(true)
    <fieldset>
        <legend>ChangeUserPasswordModel</legend>
        @*请留意这里*@
        @Html.Hidden("User"this.Model.User.Id) 
        <div class="editor-label">
            @Html.LabelFor(model => model.NewPassword)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.NewPassword)
            @Html.ValidationMessageFor(model => model.NewPassword)
        </div>
        <div class="editor-label">
            @Html.LabelFor(model => model.ConfirmPassword)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.ConfirmPassword)
            @Html.ValidationMessageFor(model => model.ConfirmPassword)
        </div>
        <p>
            <input type="submit" value="Save" />
        </p>
    </fieldset>
}

 

 

NHModelBinder默认的情况下,是用Id进行查询的. 如果不是,那么就要对Model做一些处理,如

 

  public class ChangeUserPasswordModel
    {
        [Required]             

        [Qi.Web.Mvc.NhModelFounder("LoginId",true)]
        public User User { getset; }
        .....
       
    }


假设User是使用LoginId进行查询的,那么就用NhModelFounderAttribute告诉NhModelBinder, 这个Property使用LoginId,进行查询的,后面的True告诉查询结构集合石唯一的,还是有多个,如果多个就用拿第一个。

 

当然也可以用 Hql,如:

        [Required]
        [NhModelFounder("From User u where u.Id=:User", "Guid")]
        public User User { get; set; }        
 

 

暂时如下,程序可能还有bug,请大家见谅。

 

posted @ 2012-02-02 14:45 沉默的糕点 阅读(106) 评论(0) 编辑

上一篇介绍的是某个类型,如User,Role这样,相当于C#中的Class的权限控制,现在这篇讲的是,某个特定的实例,如 var a=new User() 中的 a。 现在以Ornament.Message.Info 为例,无需要对某种类型Info作出权限控制,例如现在有3中InfoType,如System系统的信息,Account关于账号本身的,User关于每个User本身的操作。

 

  1. 定义操作

  2. 定义资源信息

  3. 制作许可证界面

  4. 生成许可证

  5. 派发许可证给角色

 

参考源码中的这几个项目。

image

定义操作

[Flags]
    public enum InfoOperator
    {
        None = 0,
        Read = 1,
        Add = 3,
        Edit = 4 | 1,
        Delete = 8 | 1 | 4,

    }

 

      操作就是由enum组成,其中Edit=4|1的意思,就是Edit 前提条件是必须有Read这个操作。这样定义好处是,在判断是否拥有Read这个操作的代码,同样也适用于只有Edit操作的User。

定义资源信息

由于使用NH作为持久层,所以扩展资源也是需要NH的配置的, 请看项目Ornament.Messages.Core InfoTypeResource.hbm.xml

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"  namespace="Ornament.MemberShip.Permissions" assembly="Ornament.MemberShip.Core">

  <subclass name="Ornament.MemberShip.Permissions.GenericResourceInfo`1[Ornament.Messages.InfoType,Ornament.Messages.Core]"
            extends="ResourceInfo" discriminator-value="Info">

    <many-to-one name="ResourceKey" lazy="false"
                 class="Ornament.Messages.InfoType,Ornament.Messages.Core" column="InfoTypeId"></many-to-one>
  </subclass>

</hibernate-mapping>

这样就声明了一种以Ornament.Message.InfoType资源了,

 


把权限应用于Web项目中

制作许可证界面

生成许可证

派发许可证

 

使用ResourceAuthorizeAttribute进行Action验证,代码如下:

public class UserController
{
        [ResourceAuthorize(UserOperator.Modify,"User")]
        public void Save(User user)
        {
             //some code.
         }
}
 

UserOperator 是一个User的一个Enum,而“User”是Ornament.MemberShip.Permissions.ResourceInfo的一个实例,代表用户资源。代码的意思是,拥有UserOperaotr.Modify的User才能使用这个

Action

 
posted @ 2011-09-09 16:38 沉默的糕点 阅读(19) 评论(4) 编辑

 

Message各个关键类如下图:

 

 

为User资源创建相关的Message信息。

 

在Ornament中,有很多关于User的系统信息,如“某某用户测试了,请求批准”,"某某用户已经修改了Email",或者"某某用户已经被锁定”,而这类信息。那么为了创建特定User的信息,我们需要做以下的操作

 

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"  assembly="Ornament.Core" namespace="Ornament.Messages">
   <subclass
    name="Ornament.Messages.Contents.GenericContent`1[Ornament.MemberShip.User,Ornament.MemberShip.Core]"
            extends="IContent" discriminator-value="Reader">
    <many-to-one name="Value" column="UserId"  class="Ornament.MemberShip.User,Ornament.MemberShip.Core" cascade="save-update">
      <meta attribute="Id of User"></meta>
    </many-to-one>
  </subclass>
</hibernate-mapping>
posted @ 2011-09-09 16:38 沉默的糕点 阅读(4) 评论(0) 编辑

Excel Date to C# date,来自这里的
public static DateTime ConvertToDateTime(double excelDate)
{
    if (excelDate < 1)
    {
        throw new ArgumentException("Excel dates cannot be smaller than 0.");
    }
    DateTime dateOfReference = new DateTime(1900, 1, 1);
    if (excelDate > 60d)
    {
        excelDate = excelDate - 2;
    }
    else
    {
        excelDate = excelDate - 1;
    }
    return dateOfReference.AddDays(excelDate);
}
posted @ 2011-08-16 14:02 沉默的糕点 阅读(14) 评论(0) 编辑

   单一类型就是,从系统又开始就已经只有一种类型,并不会在系统运作工程中产生,例如User, 因为我们并不需要对某一个特定User进行权限控制,因此可以把User 类型作为一种类型开始设定。

 

 

定义操作
    [Flags]
    public enum UserOperator
    {
        None = 0,
        Read = 1,
        Modify = 2 | 1,
        Lock = 4 | 1 | 2,
        Approve = 8 | 2 | 1,
        SetPassword = 16 | 1 | 2 | 4 | 8
    }

定义资源

由于没有设定UI,因此在 Ornament.MVCWebFrame\Models\BaseDataInit.cs 文件中加入。

GenericResourceInfo<string> userResource = new GenericResourceInfo<string>("User", typeof(UserOperator))
            {
                Name = "UserResource"
            };

 var resDao = OrnamentContext.Current.MemberShipFactory.CreateResourceDao();
 resDao.SaveOrUpdate(userResource);
创建许可证的资源选择器

因为创建许可证是可以由管理员创建的,因此需要制定一个UI给他们对相同类型的资源进行选择。

在Ornament中,已经有关于TypeResource的选择器,了参考Ornament.MVCWebFrame/Areas/MemberShips/Views/Permissions/TypeResourcesSelector.ascx。因此我们要告诉Ornament,这个选择器的位置,所以要在Ornament.MVCWebFrame/Config/WebCfg.config中设定。

创建一个ResourceDescription对象,xml的意思,请参考Castle的IOC容器,非常简单,不懂看也没有关系得。

<component id="resType" type="Ornament.Web.ResourceDescription,Ornament.Web.Core">
      <parameters>
        <ValueType>System.String,mscorlib</ValueType>
        <Path>~/Areas/MemberShips/Views/Permissions/TypeResourcesSelector.ascx</Path>
        <Name>类型资源</Name>
      </parameters>
</component>
然后加入到容器中,请留意${resType} 和 上面xml中的 id,他们是相同的。
<component id="Configuration"
               type="Ornament.Web.Configuration,Ornament.Web.Core">
      <parameters>
        <resources>
          <list>
            <item>${resType}</item>
            <item>${resInfo}</item>
          </list>
        </resources>
      </parameters>
 </component>
创建Permission

输入URL /MemberShips/Permissions,或者在菜单“权限”->权限设定->许可设定,就会出现下面URL,然后点击添加,安装wizard一步步做就可以了

image

为Role分配Permission

输入URL,MemberShips/Role, 或者菜单中选择,”权限”-“角色”,然后就可以看到下面列表,点击编辑之后,就可以为角色分配有那几个Permission了。

image

posted @ 2011-05-23 14:58 沉默的糕点 阅读(28) 评论(0) 编辑

     Ornament中权限是用RBAC的概念进行划分的,也就是多用户对多角色,其中用户和角色不多讲,请参考其他RBAC的文章。

     Permission在Ornament中,我把它叫做许可证。他对应的关系式:

 

     许可证(Permission)=角色(Role)+资源(Resource)+操作(Operator)

 

     一个许可证只能对一种资源,而操作是属于资源的,每种不同的资源都有它自己所属的操作,如查看系统日志和查看用户信息的“查看”操作是两个不同的操作。按权限控制粒度划分,就会得下面这个图:

 

image

       从图中可以知道,操作是Ornament中最小的权限单元。而最大的粒度是角色。在ASP.net中,已经提供了基于角色的访问控制,而Ornament只是继续细化这种管理方法,提供了操作这种更小的单元,所以在基于Ornament开发中,应该把所权限的控制粒度控制在操作这一级别,而不是角色。 例如过去的ASP.net全新模型中,检查是否拥有Delete user这个权限的代码可能如下:

 

     DeleteButton.Visable = HttpContext.User.IsInRole("RoleWithDeleteUserPermission");

 

而使用Ornament 就应该如下:

 

     DeleteButton.Visable = ornamentUser.HasRight(UserOperator.Deleted,”UserResource”);

 

只有在每个功能模块下都按照操作去编写代码,那么角色,用户就会更加灵活。

posted @ 2011-05-17 16:53 沉默的糕点 阅读(16) 评论(0) 编辑
摘要: 关于ProjectManager的代码可以通过SVN,从http://projectlifecycle4ornament.googlecode.com/svn/trunk checkout。 关于Ornament的源码,可以通过svn 从 http://ornamentframework.googlecode.com/svn/trunk checkout。 为什么要分开两个源码库,ProjectManager主要是介绍如何应用Ornament权限控制的。因此全部分开,避免一次阅读太多源码。 运行ProjectManager和Ornament是一样的,以ProjectManager为例: 1) 阅读全文
posted @ 2011-05-09 15:53 沉默的糕点 阅读(33) 评论(0) 编辑
摘要: 访问Https的Web services 加入下面代码,什么证书都接受。 static WebServices() { ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(CheckValidationResult); }private static b...阅读全文
posted @ 2011-03-10 15:05 沉默的糕点 阅读(24) 评论(0) 编辑
摘要: en 进入特权模式 config terminal 启动配置 1) 设置特权模式的密码 password <密码> 2) 全局密码 enable secret <密码>,启动之后,使用en命令,就需要你输入这个密码。 3) 设置远程telnet密码 Switcher(config)# line vty0 4 进入虚拟线程配置模式,在这个模式里可对telnet功能进行配置Switcher(c...阅读全文
posted @ 2011-02-17 17:59 沉默的糕点 阅读(21) 评论(0) 编辑
摘要: 方法一: 1) 设定 增加file type和变量,其中 %property 是对应GloalContext.Proerties,现在变量是a <file type="log4net.Util.PatternString" value="log/%property{a}Log.txt" /> 2)在程序的开头,也是没有调用任何log4net方法之前,加入 GlobalContext.Properties["a"]="OKTest""3) 开始写日志。方法二:只对RollingFileAppen阅读全文
posted @ 2011-01-12 12:38 沉默的糕点 阅读(85) 评论(0) 编辑