//
// Copyright (c) 2002
// Ronald Kevin Burton
//
// Z poniższym kodem nie jest związana żadna gwarancja poprawności działania.
// Program został dołączony do książki ".NET CLR. Księga eksperta" w celu
// ilustracji koncepcji i zasad przedstawionych w tej książce. Program może być 
// używany na własne ryzyko.
//
// Przyznaje się prawo do użycia lub kopiowania tego oprogramowania do dowolnego celu
// bez konieczności ponoszenia żadnych opłat pod warunkiem, że powyższe uwagi zostaną 
// zachowane we wszystkich kopiach. Przyznaje się także prawo do modyfikacji kodu
// i dystrybucji zmodyfikowanego kodu pod warunkiem zachowania powyższych uwag
// oraz dołączenia informacji mówiącej o modyfikacji kodu.
//
// 
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;

using System.Diagnostics;
using System.Security.Principal;
using System.Security.Permissions;
using System.Threading;


namespace CLRUnleashed
{
	/// <summary>
	/// Podsumowanie dla GenericPrincipalForm.
	/// </summary>
	public class GenericPrincipalForm : System.Windows.Forms.Form
	{
		private GenericIdentity currentUser;
		private GenericPrincipal currentContext;
		private System.Windows.Forms.Label usersLabel;
		private System.Windows.Forms.Label userBlabel;
		private System.Windows.Forms.ListBox roleList;
		private System.Windows.Forms.TreeView usersTreeView;
		private System.Windows.Forms.Panel panel1;
		private System.Windows.Forms.Button newUserButton;
		private System.Windows.Forms.TreeView userTreeView;
		private System.Windows.Forms.Label userLabel;
		private System.Windows.Forms.TextBox userName;
		private System.Windows.Forms.Label passwordLabel;
		private System.Windows.Forms.TextBox password;
		private System.Windows.Forms.Button logonButton;
		private System.Windows.Forms.Button newRoleButton;
		private System.Windows.Forms.ErrorProvider errorProvider;
		private System.Windows.Forms.Button authorizeButton;
		/// <summary>
		/// Wymagana zmienna.
		/// </summary>
		private System.ComponentModel.Container components = null;

		public GenericPrincipalForm()
		{
			//
			// Wymagane do obsługi Windows Form Designer
			//
			InitializeComponent();

			errorProvider = new ErrorProvider();
			currentUser = null;
			currentContext = null;
			authorizeButton.Enabled = false;
		}

		/// <summary>
		/// Oczyszczenie używanych zasobów.
		/// </summary>
		protected override void Dispose( bool disposing )
		{
			if( disposing )
			{
				if (components != null) 
				{
					components.Dispose();
				}
			}
			base.Dispose( disposing );
		}

		#region Windows Form Designer generated code
		/// <summary>
		/// Metoda wymagana do obsługi Designera - nie należy modyfikować
		/// zawartości tej metody przy użyciu edytora kodu.
		/// </summary>
		private void InitializeComponent()
		{
			this.usersLabel = new System.Windows.Forms.Label();
			this.userBlabel = new System.Windows.Forms.Label();
			this.roleList = new System.Windows.Forms.ListBox();
			this.usersTreeView = new System.Windows.Forms.TreeView();
			this.panel1 = new System.Windows.Forms.Panel();
			this.newUserButton = new System.Windows.Forms.Button();
			this.userTreeView = new System.Windows.Forms.TreeView();
			this.userLabel = new System.Windows.Forms.Label();
			this.userName = new System.Windows.Forms.TextBox();
			this.passwordLabel = new System.Windows.Forms.Label();
			this.password = new System.Windows.Forms.TextBox();
			this.logonButton = new System.Windows.Forms.Button();
			this.newRoleButton = new System.Windows.Forms.Button();
			this.errorProvider = new System.Windows.Forms.ErrorProvider();
			this.authorizeButton = new System.Windows.Forms.Button();
			this.SuspendLayout();
			// 
			// usersLabel
			// 
			this.usersLabel.Location = new System.Drawing.Point(8, 8);
			this.usersLabel.Name = "usersLabel";
			this.usersLabel.TabIndex = 0;
			this.usersLabel.Text = "Użytkownicy";
			// 
			// userBlabel
			// 
			this.userBlabel.Location = new System.Drawing.Point(144, 8);
			this.userBlabel.Name = "userBlabel";
			this.userBlabel.TabIndex = 2;
			this.userBlabel.Text = "Role";
			// 
			// roleList
			// 
			this.roleList.ItemHeight = 22;
			this.roleList.Location = new System.Drawing.Point(144, 40);
			this.roleList.Name = "roleList";
			this.roleList.Size = new System.Drawing.Size(120, 180);
			this.roleList.TabIndex = 3;
			this.roleList.MouseDown += new System.Windows.Forms.MouseEventHandler(this.OnMouseDown);
			// 
			// usersTreeView
			// 
			this.usersTreeView.AllowDrop = true;
			this.usersTreeView.ImageIndex = -1;
			this.usersTreeView.Location = new System.Drawing.Point(8, 40);
			this.usersTreeView.Name = "usersTreeView";
			this.usersTreeView.SelectedImageIndex = -1;
			this.usersTreeView.Size = new System.Drawing.Size(121, 184);
			this.usersTreeView.TabIndex = 1;
			this.usersTreeView.DragEnter += new System.Windows.Forms.DragEventHandler(this.OnDragEnter);
			this.usersTreeView.DragDrop += new System.Windows.Forms.DragEventHandler(this.OnDragDrop);
			// 
			// panel1
			// 
			this.panel1.BackColor = System.Drawing.SystemColors.ControlText;
			this.panel1.Location = new System.Drawing.Point(280, 8);
			this.panel1.Name = "panel1";
			this.panel1.Size = new System.Drawing.Size(24, 296);
			this.panel1.TabIndex = 5;
			// 
			// newUserButton
			// 
			this.newUserButton.Location = new System.Drawing.Point(16, 240);
			this.newUserButton.Name = "newUserButton";
			this.newUserButton.Size = new System.Drawing.Size(96, 32);
			this.newUserButton.TabIndex = 4;
			this.newUserButton.Text = "Nowy użytkownik";
			this.newUserButton.Click += new System.EventHandler(this.OnNewUser);
			// 
			// userTreeView
			// 
			this.userTreeView.ImageIndex = -1;
			this.userTreeView.Location = new System.Drawing.Point(480, 32);
			this.userTreeView.Name = "userTreeView";
			this.userTreeView.SelectedImageIndex = -1;
			this.userTreeView.Size = new System.Drawing.Size(121, 192);
			this.userTreeView.TabIndex = 11;
			// 
			// userLabel
			// 
			this.userLabel.Location = new System.Drawing.Point(320, 40);
			this.userLabel.Name = "userLabel";
			this.userLabel.TabIndex = 6;
			this.userLabel.Text = "Nazwa użytkownika";
			// 
			// userName
			// 
			this.userName.Location = new System.Drawing.Point(320, 72);
			this.userName.Name = "userName";
			this.userName.Size = new System.Drawing.Size(144, 26);
			this.userName.TabIndex = 7;
			this.userName.Text = "";
			// 
			// passwordLabel
			// 
			this.passwordLabel.Location = new System.Drawing.Point(320, 120);
			this.passwordLabel.Name = "passwordLabel";
			this.passwordLabel.TabIndex = 8;
			this.passwordLabel.Text = "Hasło";
			// 
			// password
			// 
			this.password.Location = new System.Drawing.Point(320, 152);
			this.password.Name = "password";
			this.password.PasswordChar = '*';
			this.password.Size = new System.Drawing.Size(144, 26);
			this.password.TabIndex = 9;
			this.password.Text = "";
			// 
			// logonButton
			// 
			this.logonButton.Location = new System.Drawing.Point(320, 240);
			this.logonButton.Name = "logonButton";
			this.logonButton.Size = new System.Drawing.Size(96, 32);
			this.logonButton.TabIndex = 10;
			this.logonButton.Text = "Logowanie";
			this.logonButton.Click += new System.EventHandler(this.OnLogon);
			// 
			// newRoleButton
			// 
			this.newRoleButton.Location = new System.Drawing.Point(152, 240);
			this.newRoleButton.Name = "newRoleButton";
			this.newRoleButton.Size = new System.Drawing.Size(96, 32);
			this.newRoleButton.TabIndex = 5;
			this.newRoleButton.Text = "Nowa rola";
			this.newRoleButton.Click += new System.EventHandler(this.OnNewRole);
			// 
			// authorizeButton
			// 
			this.authorizeButton.Location = new System.Drawing.Point(456, 240);
			this.authorizeButton.Name = "authorizeButton";
			this.authorizeButton.Size = new System.Drawing.Size(168, 32);
			this.authorizeButton.TabIndex = 12;
			this.authorizeButton.Text = "Zobacz autoryzację";
			this.authorizeButton.Click += new System.EventHandler(this.OnAuthorizeView);
			// 
			// GenericPrincipalForm
			// 
			this.AutoScaleBaseSize = new System.Drawing.Size(8, 19);
			this.ClientSize = new System.Drawing.Size(640, 310);
			this.Controls.AddRange(new System.Windows.Forms.Control[] {
																		  this.authorizeButton,
																		  this.newRoleButton,
																		  this.logonButton,
																		  this.password,
																		  this.passwordLabel,
																		  this.userName,
																		  this.userLabel,
																		  this.userTreeView,
																		  this.newUserButton,
																		  this.panel1,
																		  this.usersTreeView,
																		  this.roleList,
																		  this.userBlabel,
																		  this.usersLabel});
			this.Font = new System.Drawing.Font("Trebuchet MS", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((System.Byte)(0)));
			this.Name = "GenericPrincipalForm";
			this.Text = "Generic Principal";
			this.ResumeLayout(false);

		}
		#endregion

		/// <summary>
		/// Główny punkt wejścia dla aplikacji.
		/// </summary>
		[STAThread]
		static void Main() 
		{
			Application.Run(new GenericPrincipalForm());
		}

		private void OnNewRole(object sender, System.EventArgs e)
		{
			NewRoleForm nr = new NewRoleForm();
			DialogResult result = nr.ShowDialog(this);
			if(result == DialogResult.OK)
			{
				roleList.Items.Add(nr.Role);
			}
			nr.Dispose();		
		}

		private void OnNewUser(object sender, System.EventArgs e)
		{
			NewUserForm nu = new NewUserForm();
			DialogResult result = nu.ShowDialog(this);
			if(result == DialogResult.OK)
			{	TreeNode tn = new TreeNode(nu.User);
				tn.Tag = nu.Password;
				usersTreeView.Nodes.Add(tn);
			}
			nu.Dispose();
		}

		private void OnDragEnter(object sender, System.Windows.Forms.DragEventArgs e)
		{
			TreeView tv = sender as TreeView;
			if(tv == null)
				return;
			if (e.Data.GetDataPresent(DataFormats.Text) &&
				tv.Nodes.Count > 0) 
				e.Effect = DragDropEffects.Copy;
			else
				e.Effect = DragDropEffects.None;		
		}

		private void OnDragDrop(object sender, System.Windows.Forms.DragEventArgs e)
		{
			TreeView tv = sender as TreeView;
			if(tv == null)
				return;
			string text = e.Data.GetData(DataFormats.Text).ToString();

			Point p = tv.PointToClient(new Point(e.X, e.Y));
			TreeNode tn = tv.GetNodeAt(p);
			if(tn != null)
			{
				if(tn.Parent == null)
					tn.Nodes.Add(new TreeNode(text));
			}
		}

		private void OnMouseDown(object sender, System.Windows.Forms.MouseEventArgs e)
		{
			ListBox lb = sender as ListBox;
			if(lb == null)
				return;
			int index = lb.IndexFromPoint(new Point(e.X, e.Y));
			DragDropEffects ddResult = lb.DoDragDrop(lb.Items[index], DragDropEffects.Copy);
		}

		private void OnLogon(object sender, System.EventArgs e)
		{
			Button b = sender as Button;
			if(b == null)
				return;
			if(b.Text == "Logowanie")
			{
				bool authenticated = false;
				ArrayList roles = new ArrayList();
				foreach(TreeNode tn in usersTreeView.Nodes)
				{
					if(tn.Text == userName.Text)
					{
						if(tn.Tag != null &&
						   (string)tn.Tag == password.Text)
						{
							b.Text = "Wylogowanie";
							authenticated = true;
							currentUser = new GenericIdentity(tn.Text);
							foreach(TreeNode role in tn.Nodes)
							{
								roles.Add(role.Text);
							}
							string [] roleNames = (string [])roles.ToArray(typeof(string));
							currentContext = new GenericPrincipal(currentUser, roleNames);
							Thread.CurrentPrincipal = currentContext;
							authorizeButton.Enabled = true;
						}
					}
				}
				if(!authenticated)
				{
					errorProvider.SetError(userName, string.Format("Zalogowanie jako {0} nie jest możliwe", userName.Text));
					authorizeButton.Enabled = false;
				}
				else
				{
					errorProvider.SetError(userName, "");
				}
				return;
			}
			if(b.Text == "Wylogowanie")
			{
				userTreeView.Nodes.Clear();
				currentUser = null;
				currentContext = null;
				Thread.CurrentPrincipal = null;
				authorizeButton.Enabled = false;
				b.Text = "Logowanie";
				return;
			}
		}

		private bool CheckAuthorization(PrincipalPermission perm)
		{
			bool result = false;
			try
			{
				perm.Demand();
				result = true;
			}
			catch(Exception)
			{
				result = false;
			}
			return result;
		}

		private void OnAuthorizeView(object sender, System.EventArgs e)
		{
			userTreeView.Nodes.Clear();

			TreeNode userNode = new TreeNode(Thread.CurrentPrincipal.Identity.Name);
			userTreeView.Nodes.Add(userNode);

			PrincipalPermission perm;

			foreach(object role in roleList.Items)
			{
				perm = new PrincipalPermission(Thread.CurrentPrincipal.Identity.Name, (string)role);
				if(CheckAuthorization(perm))
				{
					userNode.Nodes.Add(new TreeNode((string)role));
				}
			}
		}
	}
}
