<commit_before>﻿/*
 * Authors:
 *   钟峰(<NAME>) <<EMAIL>>
 *
 * Copyright (C) 2010-2015 Zongsoft Corporation <http://www.zongsoft.com>
 *
 * This file is part of Zongsoft.Security.
 *
 * Zongsoft.Security is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * Zongsoft.Security is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with Zongsoft.Security; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 */

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;

using Zongsoft.Data;

namespace Zongsoft.Security.Membership
{
	internal static class MembershipHelper
	{
		#region 常量定义
		internal const string DATA_CONTAINER_NAME = "Security";

		internal const string DATA_COMMAND_GETROLES = DATA_CONTAINER_NAME + ".GetRoles";
		internal const string DATA_COMMAND_GETMEMBERS = DATA_CONTAINER_NAME + ".GetMembers";

		internal const string DATA_ENTITY_USER = DATA_CONTAINER_NAME + ".User";
		internal const string DATA_ENTITY_ROLE = DATA_CONTAINER_NAME + ".Role";
		internal const string DATA_ENTITY_MEMBER = DATA_CONTAINER_NAME + ".Member";
		internal const string DATA_ENTITY_PERMISSION = DATA_CONTAINER_NAME + ".Permission";
		internal const string DATA_ENTITY_PERMISSION_FILTER = DATA_CONTAINER_NAME + ".PermissionFilter";

		internal const int MINIMUM_ID = 100000;

		internal const string SEQUENCE_USERID = "Zongsoft.Security.Membership.User.ID";
		internal const string SEQUENCE_ROLEID = "Zongsoft.Security.Membership.Role.ID";
		#endregion

		#region 公共方法
		public static bool GetPassword(IDataAccess dataAccess, int userId, out byte[] password, out byte[] passwordSalt)
		{
			return GetPasswordCore(dataAccess, new Condition("UserId", userId), out password, out passwordSalt) != 0;
		}

		public static int? GetPassword(IDataAccess dataAccess, string identity, string @namespace, out byte[] password, out byte[] passwordSalt)
		{
			var conditions = new ConditionCollection(ConditionCombine.And, MembershipHelper.GetUserIdentityConditions(identity, @namespace));
			return GetPasswordCore(dataAccess, conditions, out password, out passwordSalt);
		}

		public static User GetUser(IDataAccess dataAccess, int userId)
		{
			if(dataAccess == null)
				throw new ArgumentNullException("dataAccess");

			return dataAccess.Select<User>(DATA_ENTITY_USER, new Condition("UserId", userId)).FirstOrDefault();
		}
		#endregion

		#region 内部方法
		internal static Condition[] GetUserIdentityConditions(string identity, string @namespace)
		{
			if(string.IsNullOrWhiteSpace(identity))
				throw new ArgumentNullException("identity");

			string text;
			var conditions = new Condition[2];
			conditions[0] = new Condition("Namespace", TrimNamespace(@namespace));

			if(Zongsoft.Text.TextRegular.Web.Email.IsMatch(identity, out text))
				conditions[1] = new Condition("Email", text);
			else if(Zongsoft.Text.TextRegular.Chinese.Cellphone.IsMatch(identity, out text))
				conditions[1] = new Condition("PhoneNumber", text);
			else
				conditions[1] = new Condition("Name", identity);

			return conditions;
		}

		internal static string TrimNamespace(string @namespace)
		{
			return string.IsNullOrWhiteSpace(@namespace) ? null : @namespace.Trim();
		}

		internal static void EnsureName(string name)
		{
			if(string.IsNullOrWhiteSpace(name))
				throw new InvalidOperationException("The value of 'Name' property cann't is null or empty.");

			name = name.Trim();

			if(name.Length < 2)
				throw new InvalidOperationException("The value of 'Name' property length must greater than 1.");

			var firstChar = name[0];

			if(firstChar < 'A' || (firstChar > 'Z' && firstChar < 'a') || firstChar > 'z')
				throw new InvalidOperationException("The value of 'Name' property first character must is letters of an alphabet");

			if(Censorship.Names.IsBlocked(name))
				throw new InvalidOperationException(string.Format("The '{0}' name is blocked.", name));
		}
		#endregion

		#region 私有方法
		private static int? GetPasswordCore(IDataAccess dataAccess, ICondition condition, out byte[] password, out byte[] passwordSalt)
		{
			if(dataAccess == null)
				throw new ArgumentNullException("dataAccess");

			if(condition == null)
				throw new ArgumentNullException("condition");

			password = null;
			passwordSalt = null;
<commit_msg>移除对单词审查的检测。 :-1:<commit_after>﻿/*
 * Authors:
 *   钟峰(<NAME>) <<EMAIL>>
 *
 * Copyright (C) 2010-2015 Zongsoft Corporation <http://www.zongsoft.com>
 *
 * This file is part of Zongsoft.Security.
 *
 * Zongsoft.Security is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * Zongsoft.Security is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with Zongsoft.Security; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 */

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;

using Zongsoft.Data;

namespace Zongsoft.Security.Membership
{
	internal static class MembershipHelper
	{
		#region 常量定义
		internal const string DATA_CONTAINER_NAME = "Security";

		internal const string DATA_COMMAND_GETROLES = DATA_CONTAINER_NAME + ".GetRoles";
		internal const string DATA_COMMAND_GETMEMBERS = DATA_CONTAINER_NAME + ".GetMembers";

		internal const string DATA_ENTITY_USER = DATA_CONTAINER_NAME + ".User";
		internal const string DATA_ENTITY_ROLE = DATA_CONTAINER_NAME + ".Role";
		internal const string DATA_ENTITY_MEMBER = DATA_CONTAINER_NAME + ".Member";
		internal const string DATA_ENTITY_PERMISSION = DATA_CONTAINER_NAME + ".Permission";
		internal const string DATA_ENTITY_PERMISSION_FILTER = DATA_CONTAINER_NAME + ".PermissionFilter";

		internal const int MINIMUM_ID = 100000;

		internal const string SEQUENCE_USERID = "Zongsoft.Security.Membership.User.ID";
		internal const string SEQUENCE_ROLEID = "Zongsoft.Security.Membership.Role.ID";
		#endregion

		#region 公共方法
		public static bool GetPassword(IDataAccess dataAccess, int userId, out byte[] password, out byte[] passwordSalt)
		{
			return GetPasswordCore(dataAccess, new Condition("UserId", userId), out password, out passwordSalt) != 0;
		}

		public static int? GetPassword(IDataAccess dataAccess, string identity, string @namespace, out byte[] password, out byte[] passwordSalt)
		{
			var conditions = new ConditionCollection(ConditionCombine.And, MembershipHelper.GetUserIdentityConditions(identity, @namespace));
			return GetPasswordCore(dataAccess, conditions, out password, out passwordSalt);
		}

		public static User GetUser(IDataAccess dataAccess, int userId)
		{
			if(dataAccess == null)
				throw new ArgumentNullException("dataAccess");

			return dataAccess.Select<User>(DATA_ENTITY_USER, new Condition("UserId", userId)).FirstOrDefault();
		}
		#endregion

		#region 内部方法
		internal static Condition[] GetUserIdentityConditions(string identity, string @namespace)
		{
			if(string.IsNullOrWhiteSpace(identity))
				throw new ArgumentNullException("identity");

			string text;
			var conditions = new Condition[2];
			conditions[0] = new Condition("Namespace", TrimNamespace(@namespace));

			if(Zongsoft.Text.TextRegular.Web.Email.IsMatch(identity, out text))
				conditions[1] = new Condition("Email", text);
			else if(Zongsoft.Text.TextRegular.Chinese.Cellphone.IsMatch(identity, out text))
				conditions[1] = new Condition("PhoneNumber", text);
			else
				conditions[1] = new Condition("Name", identity);

			return conditions;
		}

		internal static string TrimNamespace(string @namespace)
		{
			return string.IsNullOrWhiteSpace(@namespace) ? null : @namespace.Trim();
		}

		internal static void EnsureName(string name)
		{
			if(string.IsNullOrWhiteSpace(name))
				throw new InvalidOperationException("The value of 'Name' property cann't is null or empty.");

			name = name.Trim();

			if(name.Length < 2)
				throw new InvalidOperationException("The value of 'Name' property length must greater than 1.");

			var firstChar = name[0];

			if(firstChar < 'A' || (firstChar > 'Z' && firstChar < 'a') || firstChar > 'z')
				throw new InvalidOperationException("The value of 'Name' property first character must is letters of an alphabet");
		}
		#endregion

		#region 私有方法
		private static int? GetPasswordCore(IDataAccess dataAccess, ICondition condition, out byte[] password, out byte[] passwordSalt)
		{
			if(dataAccess == null)
				throw new ArgumentNullException("dataAccess");

			if(condition == null)
				throw new ArgumentNullException("condition");

			password = <PASSWORD>;
			passwordSalt = <PASSWORD>;

{'fraction_non_alphanumeric': 0.09425895765472313, 'fraction_numerical': 0.00753257328990228, 'mean_word_length': 4.827402135231317, 'pattern_counts': {'":': 0, '<': 21, '<?xml version=': 0, '>': 19, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4104264', 'n_tokens_mistral': 3103, 'n_tokens_neox': 2768, 'n_words': 904}