WebFileServer

Много изменений 1) Заготовка системы прав групп. (Реализован

7/22/2019 12:24:17 AM

Changes

.gitignore 1(+1 -0)

Details

.gitignore 1(+1 -0)

diff --git a/.gitignore b/.gitignore
index d9ae6e1..edbe56e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -26,3 +26,4 @@ FileServer/Web/Scripts/*
 !FileServer/Web/Scripts/Tools/
 
 FileServer/Web/Content
+!FileServer/Web/Content/Site.css
diff --git a/FileServer/.vs/FileServer/v15/.suo b/FileServer/.vs/FileServer/v15/.suo
index 6edc2ed..cd5ecb8 100644
Binary files a/FileServer/.vs/FileServer/v15/.suo and b/FileServer/.vs/FileServer/v15/.suo differ
diff --git a/FileServer/BLL/BLL.csproj b/FileServer/BLL/BLL.csproj
index 733abb9..aff73f9 100644
--- a/FileServer/BLL/BLL.csproj
+++ b/FileServer/BLL/BLL.csproj
@@ -51,9 +51,12 @@
   </ItemGroup>
   <ItemGroup>
     <Compile Include="Base\BaseServices.cs" />
+    <Compile Include="Services\FSExplorerServices.cs" />
+    <Compile Include="Services\FS_WathcerServices.cs" />
     <Compile Include="Services\GarbageUploadServices.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />
     <Compile Include="Services\ConfigurationServices.cs" />
+    <Compile Include="Services\PermissionServices.cs" />
     <Compile Include="Services\ScanServices.cs" />
     <Compile Include="Services\UploadServices.cs" />
   </ItemGroup>
diff --git a/FileServer/BLL/Services/ConfigurationServices.cs b/FileServer/BLL/Services/ConfigurationServices.cs
index 1c89670..59871b3 100644
--- a/FileServer/BLL/Services/ConfigurationServices.cs
+++ b/FileServer/BLL/Services/ConfigurationServices.cs
@@ -15,6 +15,9 @@ using Model.Entities.Files.Repo;
 
 namespace BLL.Services
 {
+    /// <summary>
+    /// Сервис, иницилизирующий корень фс в базе на основе файла конфигурации
+    /// </summary>
     public class ConfigurationServices : BaseServices
     {
         const string FolderPrefix = "WorkFolder";
@@ -27,12 +30,12 @@ namespace BLL.Services
             var config = ConfigurationManager.AppSettings;
 
             var folder_values = new LinkedList<string>(config.GetValues(FolderPrefix).First().Split(';'));
-            var db_dir = UOW.Repo_rootDirectory.All;
+            var db_dir = UOW.Repo_SRootDirectory.All;
 
             foreach (var elem in db_dir)
             {
                 if (!folder_values.Contains(elem.PhysicalPath))
-                    UOW.Repo_rootDirectory.DeleteInList(elem);
+                    UOW.Repo_SRootDirectory.DeleteInList(elem);
                 else
                     folder_values.Remove(elem.PhysicalPath);
             }
@@ -42,8 +45,10 @@ namespace BLL.Services
                 var nRoot = new List<SRootDirectory>(folder_values.Count);
 
                 foreach (var elem in folder_values)
-                    nRoot.Add(UOW.Repo_rootDirectory.
+                {
+                    nRoot.Add(UOW.Repo_SRootDirectory.
                         Create(new SRootDirectory(elem, Path.GetFileName(elem))));
+                }
             }
         }       
     }
diff --git a/FileServer/BLL/Services/FS_WathcerServices.cs b/FileServer/BLL/Services/FS_WathcerServices.cs
new file mode 100644
index 0000000..ee0a484
--- /dev/null
+++ b/FileServer/BLL/Services/FS_WathcerServices.cs
@@ -0,0 +1,15 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+using System.IO;
+
+namespace BLL.Services
+{
+    public class FS_WathcerServices
+    {
+       
+    }
+}
diff --git a/FileServer/BLL/Services/FSExplorerServices.cs b/FileServer/BLL/Services/FSExplorerServices.cs
new file mode 100644
index 0000000..fab8c99
--- /dev/null
+++ b/FileServer/BLL/Services/FSExplorerServices.cs
@@ -0,0 +1,29 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+using Model.Entities.Files.FS_Entities;
+using Model.UnitsOfWork;
+
+namespace BLL.Services
+{
+    public class FSExplorerServices : Base.BaseServices
+    {
+        public FSExplorerServices(UOW UOW) : base(UOW) { }
+
+        //public SDirectory GetDirectory(int ID, bool IncludeItems = false, bool IncludeParent = false)
+        //{
+        //    if (ID == -1)
+        //    {
+        //        //UOW.Repo_rootDirectory
+        //    }
+        //    else
+        //    {
+
+        //    }
+        //}
+
+    }
+}
diff --git a/FileServer/BLL/Services/GarbageUploadServices.cs b/FileServer/BLL/Services/GarbageUploadServices.cs
index a5aca85..bffb45f 100644
--- a/FileServer/BLL/Services/GarbageUploadServices.cs
+++ b/FileServer/BLL/Services/GarbageUploadServices.cs
@@ -13,6 +13,9 @@ using Model.Entities.Files.FS_Entities;
 
 namespace BLL.Services
 {
+    /// <summary>
+    /// Сервис для уничтожения метрвых загрузок
+    /// </summary>
     public class GarbageUploadServices : BaseServices
     {
         readonly static TimeSpan UploadDeadTimeout = new TimeSpan(0, 5, 0);
diff --git a/FileServer/BLL/Services/PermissionServices.cs b/FileServer/BLL/Services/PermissionServices.cs
new file mode 100644
index 0000000..4cb358b
--- /dev/null
+++ b/FileServer/BLL/Services/PermissionServices.cs
@@ -0,0 +1,105 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+using Model.Entities.Files;
+using Model.Entities.Files.FS_Entities;
+using Model.Entities.Users;
+using Model.UnitsOfWork;
+
+
+namespace BLL.Services
+{
+    /// <summary>
+    /// Сервис проверки прав пользователя на основе групп
+    /// </summary>
+    public class PermissionServices : Base.BaseServices
+    {
+        public PermissionServices(UOW UOW) : base(UOW) { }
+
+        /// <summary>
+        /// Метод получает права на папку для пользователя
+        /// на основе того, к каким группам он относиться
+        /// </summary>
+        /// <param name="user"></param>
+        /// <param name="rootDirectory"></param>
+        /// <returns></returns>
+        protected Permission GetPermissionForRootDirectory(User user, SRootDirectory rootDirectory)
+        {
+            IEnumerable<Group> groups;
+
+            if (user != null)
+            {
+                groups = user.Groups.ToArray();
+            }
+            else
+            {
+                groups = new List<Group>() { UOW.Repo_Group.GetDefaultGroup(EnumDefaultGroups.Анонимные) };
+            }
+
+            
+
+            if (groups.FirstOrDefault(e => 
+            e.Name == EnumDefaultGroups.Администраторы.ToString()) != null)
+                return new Permission()
+                {
+                    DirectoryID = rootDirectory.ID,
+                    RootDirectory = rootDirectory,
+                    CanDownload = true,
+                    CanUpload = true,
+                    CanOpen = true
+                };
+
+
+            Permission res = new Permission()
+            {
+                DirectoryID = rootDirectory.ID,
+                RootDirectory = rootDirectory,
+                CanDownload = false,
+                CanUpload = false,
+                CanOpen = false
+            };
+
+            foreach (var elem in groups)
+            {
+                var dir_permission = elem.DirectoryPermissions.
+                    Permissions[rootDirectory.ID];
+
+
+                if (!res.CanDownload && dir_permission.CanDownload)
+                    res.CanDownload = true;
+                if (!res.CanOpen && dir_permission.CanOpen)
+                    res.CanOpen = true;
+                if (!res.CanUpload && dir_permission.CanUpload)
+                    res.CanUpload = true;
+            }
+
+            return res;
+        }
+        public Permission GetPermissionForDirectory(User user, SDirectory directory)
+        {
+            if (directory.IsRoot)
+                return GetPermissionForRootDirectory(user, (SRootDirectory)directory);
+            else
+                return GetPermissionForRootDirectory(user, directory.Root);
+        }
+
+        public bool CanDownload(User user, SDirectory directory)
+        {
+            return GetPermissionForDirectory(user, directory).CanDownload;
+        }
+
+        public bool CanUpload(User user, SDirectory directory)
+        {
+            return GetPermissionForDirectory(user, directory).CanUpload;
+        }
+
+        public bool CanOpen(User user, SDirectory directory)
+        {
+            return GetPermissionForDirectory(user, directory).CanOpen;
+        }
+
+    }
+}
diff --git a/FileServer/BLL/Services/ScanServices.cs b/FileServer/BLL/Services/ScanServices.cs
index a92ec84..f43dc13 100644
--- a/FileServer/BLL/Services/ScanServices.cs
+++ b/FileServer/BLL/Services/ScanServices.cs
@@ -14,6 +14,9 @@ using Model.Entities.Files;
 
 namespace BLL.Services
 {
+    /// <summary>
+    /// Сервис выполняет сканирование файловой системы
+    /// </summary>
     public class ScanServices : BaseServices
     {
         public ScanServices(UOW uOW) : base(uOW) { }
@@ -43,7 +46,7 @@ namespace BLL.Services
         {
             await Task.Run(async () =>
             {
-                await RecursScanDirectoryAsync(UOW.Repo_rootDirectory.All.ToArray(), true);//, IsParalle);
+                await RecursScanDirectoryAsync(UOW.Repo_SRootDirectory.All.ToArray(), true);//, IsParalle);
             });
         }
 
@@ -120,12 +123,24 @@ namespace BLL.Services
 
                 foreach (var elem in db.files)
                 {
+                    var file = fs.files.FirstOrDefault(e => e == elem.Name);
+
                     //Если файл из базы не найден в фс
-                    if (!fs.files.Contains(elem.Name))
+                    if (file != null)
                         UOW.Repo_SFile.DeleteInList(elem);
                     //Если файл найден, то удаляем из списка файловой системы
                     else
+                    {
+                        //Проверка что размеры файла совпадают
+                        var size = new FileInfo(file).Length;
+                        if (elem.Size != size)
+                        {
+                            elem._Size = size;
+                            UOW.Repo_SFile.Update(elem);
+                        }
+
                         fs.files.Remove(elem.Name);
+                    }
                 }
 
                 //Если в файловой системе есть файлы, не зафиксированные в базе
@@ -141,7 +156,7 @@ namespace BLL.Services
 
                         //Файл вносится в базу
                         FileInfo file = new FileInfo(Path.Combine(directory.PhysicalPath, elem));
-                        db.files.Add(UOW.Repo_SFile.Create(new SFile(directory, file.Name, file.Length)));
+                        db.files.Add(UOW.Repo_SFile.Create(new SFile(directory, file.Name, file.Length, null)));
                     }
                 }
 
@@ -163,7 +178,7 @@ namespace BLL.Services
                 {
                     foreach (var elem in fs.dirs)
                     {
-                        db.dirs.Add(UOW.Repo_SDirectory.Create(new SDirectory(directory, elem)));
+                        db.dirs.Add(UOW.Repo_SDirectory.Create(new SDirectory(directory, elem, null)));
                     }
                 }
 
diff --git a/FileServer/BLL/Services/UploadServices.cs b/FileServer/BLL/Services/UploadServices.cs
index f08a07b..af029c1 100644
--- a/FileServer/BLL/Services/UploadServices.cs
+++ b/FileServer/BLL/Services/UploadServices.cs
@@ -9,11 +9,14 @@ using BLL.Base;
 using Model.UnitsOfWork;
 using Model.Entities.Files.FS_Entities;
 using Model.Entities.Files.Repo;
+using Model.Entities.Users;
 
 namespace BLL.Services
 {
 
-
+    /// <summary>
+    /// Сервис, контролирующий загрузку файлов
+    /// </summary>
     public class UploadServices : BaseServices
     {
         const int ChunkSize = 102400;
@@ -24,16 +27,17 @@ namespace BLL.Services
             Repo_SFileUpload = UOW.Repo_SFileUpload;
         }
 
-        public SFileUpload StartUpload(SDirectory directory, string Name, long size)
+        public SFileUpload StartUpload(SDirectory directory, string Name, long size, User user)
         {
             var res = Repo_SFileUpload.Create(
-                new SFileUpload(directory, Name, size, ChunkSize));                
+                new SFileUpload(directory, Name, size, ChunkSize, user));                
 
             return res;
         }
         public bool UploadChunk(SFileUpload project, byte[] data)
         {
             project.CurrentChunk = data;
+            project.LastChunkUploaded = DateTime.Now;
 
             Repo_SFileUpload.Update(project);
 
@@ -55,11 +59,12 @@ namespace BLL.Services
         private void Done(SFileUpload project)
         {
             var p = project.Parent;
+            var upload_user = project.User;
 
             Repo_SFileUpload.DeleteInList(project);
 
             UOW.Repo_SFile.Create(
-                new SFile(p, project.Name, (long)project.Size));            
+                new SFile(p, project.Name, (long)project.Size, upload_user));          
         }
 
     }
diff --git a/FileServer/Console/Program.cs b/FileServer/Console/Program.cs
index d887699..ce65d94 100644
--- a/FileServer/Console/Program.cs
+++ b/FileServer/Console/Program.cs
@@ -84,7 +84,7 @@ namespace Console
             configurationServices.ReadConfiguration();
 
 
-            var files = UOW.context.FS_Items.ToList();
+            //var files = UOW.context.FS_Items.ToList();
         }
 
         static void Test2()
@@ -102,18 +102,18 @@ namespace Console
             UploadServices uploadServices = new UploadServices(UOW);
 
 
-            var upload = uploadServices.StartUpload(
-                UOW.Repo_rootDirectory.All.First(), UploadFile.Name, UploadFile.Length);
+            //var upload = uploadServices.StartUpload(
+            //    UOW.Repo_rootDirectory.All.First(), UploadFile.Name, UploadFile.Length);
 
-            using (var stream = new FileStream(UploadFile.FullName, FileMode.Open, FileAccess.Read))
-            {
-                byte[] data = new byte[upload.NextChunkSize];
+            //using (var stream = new FileStream(UploadFile.FullName, FileMode.Open, FileAccess.Read))
+            //{
+            //    byte[] data = new byte[upload.NextChunkSize];
 
-                do
-                {
-                    stream.Read(data, (int)upload.UploadedSize, upload.NextChunkSize);
-                } while (uploadServices.UploadChunk(upload, data));
-            }
+            //    do
+            //    {
+            //        stream.Read(data, (int)upload.UploadedSize, upload.NextChunkSize);
+            //    } while (uploadServices.UploadChunk(upload, data));
+            //}
         }
 
         static void Main(string[] args)
@@ -123,6 +123,8 @@ namespace Console
             var UOW = new UOW();
             new ConfigurationServices(UOW).ReadConfiguration();
             Task.WaitAll(new ScanServices(UOW).ScanAllDirs());
+
+            var dirs = UOW.Repo_SDirectory.All_List;
         }
     }
 }
diff --git a/FileServer/Model/Entities/Base/Base_FS_Repository.cs b/FileServer/Model/Entities/Base/Base_FS_Repository.cs
index ddaef32..b8c631c 100644
--- a/FileServer/Model/Entities/Base/Base_FS_Repository.cs
+++ b/FileServer/Model/Entities/Base/Base_FS_Repository.cs
@@ -12,10 +12,54 @@ namespace Model.Entities.Base
 {
     public abstract class Base_FS_Repository<T> : BaseRepository<T> where T : FS_Item
     {
-        public DbSet<FS_Item> Set_Fs => context.Set<FS_Item>();
+        protected DbSet<FS_Item> Set_Fs => context.Set<FS_Item>();
+        protected readonly Enum_BaseDirectoryEntity RepoType;
 
+        public Base_FS_Repository(UOW UOW, Enum_BaseDirectoryEntity type) : base(UOW)
+        {
+            this.RepoType = type;
+        }
+
+        public override T GetFromDBNoChange(T elem)
+        {
+            using (var context = new Context())
+            {
+                var en = context.Set<FS_Item>().
+                    FirstOrDefault(e => e.ID == elem.ID);//.
+                                                         //Include(e => e.Parent).
+                                                         //FirstOrDefault();
+
+                //context.Entry(en).Reference(e => e.Parent).Load();
+                var p = en.PhysicalPath;
+
+                return (T)en;
+            }
+        }
+
+        public override T Create(T elem)
+        {
+            if (elem.Type != RepoType)
+                throw Repo_Exception<T>.Factory(this, elem, Repo_Exceptions.FSRepo_TypeException);
+
+            return base.Create(elem);
+        }
+
+        public override void Update(T elem)
+        {
+            if (elem.Type != RepoType)
+                throw Repo_Exception<T>.Factory(this, elem, Repo_Exceptions.FSRepo_TypeException);
+
+            base.Update(elem);
+        }
+
+        public override void Delete(T elem)
+        {
+            if (elem.Type != RepoType)
+                throw Repo_Exception<T>.Factory(this, elem, Repo_Exceptions.FSRepo_TypeException);
+
+            base.Delete(elem);
+        }
 
-        public Base_FS_Repository(Context context) : base(context) { }
 
         /// <summary>
         /// Рекурсия
@@ -23,23 +67,21 @@ namespace Model.Entities.Base
         /// Обычно вызывается при сканировании ФС, когда папка/файл из базы не найдена в ФС
         /// </summary>
         /// <param name="elem"></param>
-        public void DeleteInList(FS_Item elem)
+        public virtual void DeleteInList(FS_Item elem)
         {
-            foreach (var item in elem.Items)
-            {
-                _DeleteInList(item);
-            }
-
-            Set_Fs.Remove(elem);
+            _DeleteInList(elem);
             context.SaveChanges();
         }
 
         private void _DeleteInList(FS_Item elem)
         {
-            foreach (var item in elem.Items)
+            var items = elem.Items;
+            //При foreach вылетает exception изменение коллекции
+            for (int i = 0; i < items.Count; i++)
             {
-                DeleteInList(item);
+                DeleteInList(items[i]);
             }
+
             Set_Fs.Remove(elem);
         }
 
diff --git a/FileServer/Model/Entities/Base/BaseRepository.cs b/FileServer/Model/Entities/Base/BaseRepository.cs
index f1e0e7b..465a96b 100644
--- a/FileServer/Model/Entities/Base/BaseRepository.cs
+++ b/FileServer/Model/Entities/Base/BaseRepository.cs
@@ -5,6 +5,7 @@ using System.Text;
 using System.Threading.Tasks;
 
 using System.Data.Entity;
+using System.Data.Entity.Infrastructure;
 
 using Model.Entities.Base;
 using Model.Entities.Files;
@@ -15,11 +16,14 @@ namespace Model.Entities.Base
 {
     public abstract class BaseRepository<T> where T : BaseEntity
     {
-        public readonly Context context;
 
-        public BaseRepository(Context context)
+        protected readonly UOW UOW;
+        protected Context context => UOW.context;
+
+        public BaseRepository(UOW UOW)
         {
-            this.context = context;
+            //this.context = context;
+            this.UOW = UOW;
         }
 
 
@@ -31,6 +35,29 @@ namespace Model.Entities.Base
         public List<T> All_NoTrack_List => Set.AsNoTracking().ToList();
 
 
+        public DbEntityEntry<T> GetEntry(T elem)
+        {
+            return context.Entry<T>(elem);
+        }
+        /// <summary>
+        /// Используется чтобы запросить из базы сущность до модификации
+        /// Есть некоторын проблемы с подрузкой связанных свойств см. Base_FS_Repository
+        /// Общий вопрос: каким образом получить сущность до изменений (С запросом или без запроса к базе)?
+        /// Context Entry позволяет отследить список измененнных свойсв связанных с базой, но не вычисляемых свойств.
+        /// </summary>
+        /// <param name="elem"></param>
+        /// <returns></returns>
+        public virtual T GetFromDBNoChange(T elem)
+        {
+            using (var context = new Context())
+            {
+                return context.Set<T>().
+                    FirstOrDefault(e => e.ID == elem.ID);
+            }
+        }
+
+
+
         protected abstract void Validation_Create(T elem);
         public virtual T Create(T elem)
         {
@@ -45,15 +72,15 @@ namespace Model.Entities.Base
 
         protected abstract void Validation_Update(T old, T elem);
         public virtual void Update(T elem)
-        {           
-            var change_entity = Set.FirstOrDefault(e => e.ID == elem.ID);
+        {
+            var change_entity = GetFromDBNoChange(elem);
 
             if (change_entity == null)
                 throw new Exception("old value not found");
 
             Validation_Update(change_entity, elem);
 
-            context.Entry(change_entity).CurrentValues.SetValues(elem);
+
             context.SaveChanges();
         }
 
diff --git a/FileServer/Model/Entities/Base/Repo_Exception.cs b/FileServer/Model/Entities/Base/Repo_Exception.cs
index 13e2943..1a9a8d2 100644
--- a/FileServer/Model/Entities/Base/Repo_Exception.cs
+++ b/FileServer/Model/Entities/Base/Repo_Exception.cs
@@ -45,7 +45,8 @@ namespace Model.Entities.Base
         Elem_items_not_empty,
         Name_cant_change,
         File_not_found,
-        Size_not_equils
+        Size_not_equils,
+        FSRepo_TypeException
     }
 
     #endregion
diff --git a/FileServer/Model/Entities/Files/FS_Entities/SDirectory.cs b/FileServer/Model/Entities/Files/FS_Entities/SDirectory.cs
index 0e0fd90..3d69ccd 100644
--- a/FileServer/Model/Entities/Files/FS_Entities/SDirectory.cs
+++ b/FileServer/Model/Entities/Files/FS_Entities/SDirectory.cs
@@ -9,6 +9,7 @@ using System.Numerics;
 using System.ComponentModel.DataAnnotations.Schema;
 
 using Model.Entities.Base;
+using Model.Entities.Users;
 
 namespace Model.Entities.Files.FS_Entities
 {
@@ -32,7 +33,14 @@ namespace Model.Entities.Files.FS_Entities
         [Obsolete]
         public SDirectory() { }
 
-        public SDirectory(SDirectory parent, string Name) : base(Enum_BaseDirectoryEntity.Directory, parent, Name) { }
-        protected SDirectory(Enum_BaseDirectoryEntity type, SDirectory parent, string Name) : base(type, parent, Name) { }
+        public SDirectory(SDirectory parent, string Name, User user) : base(Enum_BaseDirectoryEntity.Directory, parent, Name, user) { }
+
+        /// <summary>
+        /// For SRootDirectory
+        /// </summary>
+        /// <param name="type"></param>
+        /// <param name="parent"></param>
+        /// <param name="Name"></param>
+        protected SDirectory(Enum_BaseDirectoryEntity type, SDirectory parent, string Name) : base(type, parent, Name, null) { }
     }
 }
diff --git a/FileServer/Model/Entities/Files/FS_Entities/SFile.cs b/FileServer/Model/Entities/Files/FS_Entities/SFile.cs
index 783e334..3dd271f 100644
--- a/FileServer/Model/Entities/Files/FS_Entities/SFile.cs
+++ b/FileServer/Model/Entities/Files/FS_Entities/SFile.cs
@@ -6,9 +6,12 @@ using System.Threading.Tasks;
 
 using System.IO;
 using System.ComponentModel.DataAnnotations.Schema;
+using System.Numerics;
+
 
 using Model.Entities.Base;
-using System.Numerics;
+using Model.Entities.Users;
+
 
 namespace Model.Entities.Files.FS_Entities
 {
@@ -42,11 +45,11 @@ namespace Model.Entities.Files.FS_Entities
         [Obsolete]
         public SFile() { }
 
-        public SFile(SDirectory parent, string Name, long size) : base(Enum_BaseDirectoryEntity.File, parent, Name)
+        public SFile(SDirectory parent, string Name, long size, User user) : base(Enum_BaseDirectoryEntity.File, parent, Name, user)
         {
             this._Size = size;
         }
-        protected SFile(Enum_BaseDirectoryEntity type, SDirectory parent, string Name, long size) : base(type, parent, Name)
+        protected SFile(Enum_BaseDirectoryEntity type, SDirectory parent, string Name, long size, User user) : base(type, parent, Name, user)
         {
             this._Size = size;
         }
diff --git a/FileServer/Model/Entities/Files/FS_Entities/SFileUpload.cs b/FileServer/Model/Entities/Files/FS_Entities/SFileUpload.cs
index 1a915eb..68e2bbf 100644
--- a/FileServer/Model/Entities/Files/FS_Entities/SFileUpload.cs
+++ b/FileServer/Model/Entities/Files/FS_Entities/SFileUpload.cs
@@ -9,6 +9,7 @@ using System.ComponentModel.DataAnnotations.Schema;
 
 using Model.Entities.Base;
 using Model.Entities.Files.FS_Entities;
+using Model.Entities.Users;
 
 namespace Model.Entities.Files.FS_Entities
 {
@@ -42,7 +43,7 @@ namespace Model.Entities.Files.FS_Entities
         public SFileUpload() { }
 
 
-        public SFileUpload(SDirectory parent, string name, long size, int ChunkSize) : base(Enum_BaseDirectoryEntity.UploadFile, parent, name, size)
+        public SFileUpload(SDirectory parent, string name, long size, int ChunkSize, User user) : base(Enum_BaseDirectoryEntity.UploadFile, parent, name, size, user)
         {
             this.ChunkSize = ChunkSize;
         }
diff --git a/FileServer/Model/Entities/Files/FS_Entities/SRootDirectory.cs b/FileServer/Model/Entities/Files/FS_Entities/SRootDirectory.cs
index d1644e5..252c770 100644
--- a/FileServer/Model/Entities/Files/FS_Entities/SRootDirectory.cs
+++ b/FileServer/Model/Entities/Files/FS_Entities/SRootDirectory.cs
@@ -13,45 +13,7 @@ using Model.Entities.Users;
 
 namespace Model.Entities.Files.FS_Entities
 {
-    public class Permission
-    {
-        public int GroupID { set; get; }
-        [XmlIgnore]
-        public Group Group { set; get; }
-
-        public bool CanRead { set; get; }
-        public bool CanWrite { set; get; }
-        public bool CanOpen { set; get; }
-    }
-
-    public class DirectoryPermissions
-    {
-        public List<Permission> Permissions { private set; get; } = new List<Permission>();
-
-        public string Export()
-        {
-            XmlSerializer formatter = new XmlSerializer(typeof(Permission[]));
-
-            using (StringWriter wr = new StringWriter())
-            {
-                formatter.Serialize(wr, Permissions.ToArray());
-                return wr.ToString();
-            }
-        }
-        public void Import(string val)
-        {
-            XmlSerializer formatter = new XmlSerializer(typeof(Permission[]));
-
-            using (StringReader rd = new StringReader(val))
-            {
-                Permissions = new List<Permission>(
-                    (Permission[])formatter.Deserialize(rd));
-            }
-        }
-    }
-
-
-
+    
     public class SRootDirectory : SDirectory
     {
         /// <summary>
@@ -60,15 +22,6 @@ namespace Model.Entities.Files.FS_Entities
         public string _PhysicalPath { set; get; }
 
 
-        [Column("XML_Permissions")]
-        public string XML_Permissions
-        {
-            set => DirectoryPermissions.Import(value);
-            get => DirectoryPermissions.Export();
-        }
-        public DirectoryPermissions DirectoryPermissions = new DirectoryPermissions();
-
-
         public override string PhysicalPath => _PhysicalPath;
         public override string LogicPath => Path.Combine("\\", Name);
 
diff --git a/FileServer/Model/Entities/Files/FS_Item.cs b/FileServer/Model/Entities/Files/FS_Item.cs
index 95d4da5..fc46620 100644
--- a/FileServer/Model/Entities/Files/FS_Item.cs
+++ b/FileServer/Model/Entities/Files/FS_Item.cs
@@ -12,6 +12,7 @@ using System.ComponentModel.DataAnnotations;
 
 using Model.Entities.Base;
 using Model.Entities.Files.FS_Entities;
+using Model.Entities.Users;
 
 namespace Model.Entities.Files
 {
@@ -50,6 +51,11 @@ namespace Model.Entities.Files
         public string Name { private set; get; }
 
 
+        [ForeignKey("User")]
+        public int? UserID { set; get; }        
+        public virtual User User { private set; get; }
+
+
         /// <summary>
         /// Коренная папка для данного элемента
         /// </summary>
@@ -65,7 +71,7 @@ namespace Model.Entities.Files
         [ForeignKey("Parent")]
         public int? Parent_ID { private set; get; }
         //[InverseProperty("")]
-        public virtual SDirectory Parent { private set; get; }
+        public virtual SDirectory Parent { set; get; }
         
         /// <summary>
         /// Содержимое папки
@@ -115,7 +121,7 @@ namespace Model.Entities.Files
 
 
         [NotMapped]
-        public IEnumerable<SFile> Files { get { return (IEnumerable<SFile>)Items.Where(e => e.Type == Enum_BaseDirectoryEntity.File).Cast<SFile>(); } }
+        public IEnumerable<SFile> Files { get { return Items.Where(e => e.Type == Enum_BaseDirectoryEntity.File).Cast<SFile>(); } }
         [NotMapped]
         public IEnumerable<SDirectory> Directories => Items.Where(e => e.Type == Enum_BaseDirectoryEntity.Directory).Cast<SDirectory>();
         [NotMapped]
@@ -132,10 +138,11 @@ namespace Model.Entities.Files
 
         [Obsolete]
         public FS_Item() { }
-        protected FS_Item(Enum_BaseDirectoryEntity type, SDirectory parent, string Name)
+        protected FS_Item(Enum_BaseDirectoryEntity type, SDirectory parent, string Name, User user)
         {
             this.Type = type;
             this.Parent = parent;
+            this.User = user;
             if (Parent != null)
             {
                 Root_ID = (parent.IsRoot) ? parent.ID : parent.Root_ID;
diff --git a/FileServer/Model/Entities/Files/Repo/Repo_SDirectory.cs b/FileServer/Model/Entities/Files/Repo/Repo_SDirectory.cs
index 8641ea0..a896500 100644
--- a/FileServer/Model/Entities/Files/Repo/Repo_SDirectory.cs
+++ b/FileServer/Model/Entities/Files/Repo/Repo_SDirectory.cs
@@ -14,7 +14,7 @@ namespace Model.Entities.Files.Repo
 {
     public class Repo_SDirectory : Base_FS_Repository<SDirectory>
     {
-        public Repo_SDirectory(Context context) : base(context) { }
+        public Repo_SDirectory(UOW uOW) : base(uOW, Enum_BaseDirectoryEntity.Directory) { }
 
         protected override void Validation_Create(SDirectory elem)
         {
@@ -24,6 +24,9 @@ namespace Model.Entities.Files.Repo
             if (elem.Parent == null)
                 throw Repo_Exception<SDirectory>.Factory(this, elem, Repo_Exceptions.Parent_is_null);
 
+            if (elem.Parent.ID == elem.ID)
+                throw new Exception();
+
             if (elem.Parent.ContainsName(elem))
                 throw Repo_Exception<SDirectory>.Factory(this, elem, Repo_Exceptions.Name_already_exists_in_parents);
 
@@ -42,10 +45,12 @@ namespace Model.Entities.Files.Repo
             if (elem.Parent == null)
                 throw Repo_Exception<SDirectory>.Factory(this, elem, Repo_Exceptions.Parent_is_null);
 
-            if (old.Name != elem.Name)
+            if (elem.Parent.ID == elem.ID)
+                throw new Exception();
+
+            if (old.Parent != elem.Parent)
             {
                 if (elem.Parent.ContainsName(elem))
-                    if (elem.Parent.ContainsName(elem))
                         throw Repo_Exception<SDirectory>.Factory(this, elem, Repo_Exceptions.Name_already_exists_in_parents);
 
                 try
diff --git a/FileServer/Model/Entities/Files/Repo/Repo_SFile.cs b/FileServer/Model/Entities/Files/Repo/Repo_SFile.cs
index 7918fb5..8bf8723 100644
--- a/FileServer/Model/Entities/Files/Repo/Repo_SFile.cs
+++ b/FileServer/Model/Entities/Files/Repo/Repo_SFile.cs
@@ -14,7 +14,7 @@ namespace Model.Entities.Files.Repo
 {
     public class Repo_SFile : Base_FS_Repository<SFile>
     {
-        public Repo_SFile(Context context) : base(context) { }
+        public Repo_SFile(UOW UOW) : base(UOW, Enum_BaseDirectoryEntity.File) { }
 
 
         protected override void Validation_Create(SFile elem)
@@ -37,13 +37,28 @@ namespace Model.Entities.Files.Repo
             if (elem.Parent == null)
                 throw new Exception();
 
-            if (old.Name != elem.Name)
+            //Перемещение
+            if (old.Parent != elem.Parent)
             {
+                //В данной папке уже есть элемент с таким именем
                 if (elem.Parent.ContainsName(elem))
                     throw new Exception();
 
-                File.Move(old.PhysicalPath, elem.PhysicalPath);
+                try
+                {
+                    File.Move(old.PhysicalPath, elem.PhysicalPath);
+                }
+                catch (Exception ex)
+                {
+                    throw ex;
+                }
             }
+
+            //if (old.Name != elem.Name)
+            //{
+            //    if (elem.Parent.ContainsName(elem))
+            //        throw new Exception();
+            //}
         }
 
         protected override void Validation_Delete(SFile elem)
diff --git a/FileServer/Model/Entities/Files/Repo/Repo_SFileUpload.cs b/FileServer/Model/Entities/Files/Repo/Repo_SFileUpload.cs
index 0bee131..121da22 100644
--- a/FileServer/Model/Entities/Files/Repo/Repo_SFileUpload.cs
+++ b/FileServer/Model/Entities/Files/Repo/Repo_SFileUpload.cs
@@ -15,7 +15,7 @@ namespace Model.Entities.Files.Repo
     public class Repo_SFileUpload : Base_FS_Repository<SFileUpload>
     {
 
-        public Repo_SFileUpload(Context context) : base(context) { }
+        public Repo_SFileUpload(UOW UOW) : base(UOW, Enum_BaseDirectoryEntity.UploadFile) { }
 
         protected override void Validation_Create(SFileUpload elem)
         {
diff --git a/FileServer/Model/Entities/Files/Repo/Repo_SRootDirectory.cs b/FileServer/Model/Entities/Files/Repo/Repo_SRootDirectory.cs
index c2a595d..392fb74 100644
--- a/FileServer/Model/Entities/Files/Repo/Repo_SRootDirectory.cs
+++ b/FileServer/Model/Entities/Files/Repo/Repo_SRootDirectory.cs
@@ -16,7 +16,7 @@ namespace Model.Entities.Files.Repo
 
     public class Repo_SRootDirectory : Base_FS_Repository<SRootDirectory>
     {
-        public Repo_SRootDirectory(Context context) : base(context) { }
+        public Repo_SRootDirectory(UOW UOW) : base(UOW, Enum_BaseDirectoryEntity.RootDirectory) { }
 
 
         protected override void Validation_Create(SRootDirectory elem)
@@ -28,7 +28,7 @@ namespace Model.Entities.Files.Repo
                 throw Repo_Exception<SRootDirectory>.Factory(this, elem, Repo_Exceptions.Parent_is_null);
 
             if (All.FirstOrDefault(e => e.Name == elem.Name) != null)
-                throw new Repo_Exception<SRootDirectory>(this, elem, "Root directory name already exist");
+                throw Repo_Exception<SRootDirectory>.Factory(this, elem, Repo_Exceptions.Name_already_exists_in_parents);
 
             try
             {
@@ -39,25 +39,44 @@ namespace Model.Entities.Files.Repo
                 throw ex;
             }
         }
-
-        protected override void Validation_Update(SRootDirectory old, SRootDirectory elem)
+        public override SRootDirectory Create(SRootDirectory elem)
         {
-            if (elem.Parent != null)
-                throw new Exception();
+            var dir = base.Create(elem);
 
-            if (old.Name != elem.Name && All.FirstOrDefault(e => e.Name == elem.Name) != null)
-            {                
-                throw new Exception();
-            }
-
-            try
-            {
-                Directory.Move(old.PhysicalPath, elem.PhysicalPath);
-            }
-            catch (Exception ex)
+            var groups = UOW.Repo_Group.All_List;
+            foreach (var e in groups)
             {
-                throw ex;
+                var permission = (e.Name == EnumDefaultGroups.Администраторы.ToString()) 
+                    ? Permission.Factory_AllPermission(dir) 
+                    : Permission.Factory_NoPermission(dir);
+
+                e.DirectoryPermissions.Permissions.Add(dir.ID, permission);
+                UOW.Repo_Group.Update(e);
             }
+
+            return dir;
+        }
+
+        protected override void Validation_Update(SRootDirectory old, SRootDirectory elem)
+        {
+            throw new Exception();
+
+            //if (elem.Parent != null)
+            //    throw new Exception();
+
+            //if (old.Name != elem.Name && All.FirstOrDefault(e => e.Name == elem.Name) != null)
+            //{                
+            //    throw new Exception();
+            //}
+
+            //try
+            //{
+            //    Directory.Move(old.PhysicalPath, elem.PhysicalPath);
+            //}
+            //catch (Exception ex)
+            //{
+            //    throw ex;
+            //}
         }
 
         protected override void Validation_Delete(SRootDirectory elem)
@@ -74,23 +93,31 @@ namespace Model.Entities.Files.Repo
                 throw ex;
             }
         }
-        public void DeleteInList()
+        public override void Delete(SRootDirectory elem)
         {
+            var id = elem.ID;
+            base.Delete(elem);
 
+            var groups = UOW.Repo_Group.All_List;
+            foreach (var e in groups)
+            {
+                e.DirectoryPermissions.Permissions.Remove(id);
+                UOW.Repo_Group.Update(e);
+            }
         }
 
 
-        public void UploadGroups(DirectoryPermissions permissions)
+        public override void DeleteInList(FS_Item elem)
         {
-            var Group_ID = permissions.Permissions.
-                Select(e => e.GroupID);
+            var id = elem.ID;
+            base.DeleteInList(elem);
 
-            //Select Groups from groups repo
-            IEnumerable<Group> groups = context.Groups.Where(e => Group_ID.Contains(e.ID));
-
-            foreach (var elem in permissions.Permissions)            
-                elem.Group = groups.
-                    FirstOrDefault(e => e.ID == elem.GroupID);            
+            var groups = UOW.Repo_Group.All_List;
+            foreach (var e in groups)
+            {
+                e.DirectoryPermissions.Permissions.Remove(id);
+                UOW.Repo_Group.Update(e);
+            }           
         }
 
     }
diff --git a/FileServer/Model/Entities/Users/Group.cs b/FileServer/Model/Entities/Users/Group.cs
index 9b40872..b5ca3b3 100644
--- a/FileServer/Model/Entities/Users/Group.cs
+++ b/FileServer/Model/Entities/Users/Group.cs
@@ -5,6 +5,9 @@ using System.Text;
 using System.Threading.Tasks;
 
 using System.ComponentModel.DataAnnotations.Schema;
+using System.ComponentModel.DataAnnotations;
+using System.IO;
+using System.Xml.Serialization;
 
 using Model.Entities.Base;
 using Model.Entities.Files.FS_Entities;
@@ -12,32 +15,92 @@ using Model.Entities.Files.FS_Entities;
 namespace Model.Entities.Users
 {
 
-    //public class Permission
-    //{
-    //    public bool Accesse { set; get; }
-    //    public bool Read { set; get; }
-    //    public bool Write { set; get; }
-    //}
+    [Serializable]
+    public class Permission
+    {
+        public int DirectoryID { set; get; }
+        [XmlIgnore]
+        public SRootDirectory RootDirectory { set; get; }
+
+        public bool CanDownload { set; get; }
+        public bool CanUpload { set; get; }
+        public bool CanOpen { set; get; }
+
 
-    //public class PermissionsManager
-    //{
-    //    List<Permission> Permissions = new List<Permission>();
+        public static Permission Factory_AllPermission(SRootDirectory directory)
+        {
+            return new Permission()
+            {
+                DirectoryID = directory.ID,
+                RootDirectory = directory,
+                CanDownload = true,
+                CanOpen = true,
+                CanUpload = true
+            };
+        }
 
-    //    [NonSerialized]
-    //    List<SRootDirectory> sRootDirectories = new List<SRootDirectory>();
-    //    List<int> sRootDirectories_ID = new List<int>();
+        public static Permission Factory_NoPermission(SRootDirectory directory)
+        {
+            return new Permission()
+            {
+                DirectoryID = directory.ID,
+                RootDirectory = directory,
+                CanDownload = false,
+                CanOpen = false,
+                CanUpload = false
+            };
+        }
 
-    //}
+    }
+
+    [Serializable]
+    public class DirectoryPermissions
+    {
+        /// <summary>
+        /// key - GroupID
+        /// </summary>
+        public Dictionary<int, Permission> Permissions { private set; get; } = new Dictionary<int, Permission>();
 
+        public string Export()
+        {
+            XmlSerializer formatter = new XmlSerializer(typeof(Permission[]));
+
+            using (StringWriter wr = new StringWriter())
+            {
+                formatter.Serialize(wr, Permissions.Values.ToArray());
+                return wr.ToString();
+            }
+        }
+        public void Import(string val)
+        {
+            XmlSerializer formatter = new XmlSerializer(typeof(Permission[]));
+
+            using (StringReader rd = new StringReader(val))
+            {
+                var data = (Permission[])formatter.Deserialize(rd);
+                Permissions.Clear();
+                foreach (var elem in data)
+                    Permissions.Add(elem.DirectoryID, elem);
+            }
+        }
+
+    }
 
 
     public class Group : BaseEntity
     {
+        [Required]
         public string Name { set; get; }
-        //[Column("XML_Permissions")]
-        //public string XML_Permissions { set; get; }
 
-        [InverseProperty("Groups")]
-        public virtual IEnumerable<User> Users { set; get; }
+        public virtual List<User> Users { set; get; } = new List<User>();
+
+        [NotMapped]
+        public DirectoryPermissions DirectoryPermissions { private set; get; } = new DirectoryPermissions();
+        [Column("XML_Permissions")]
+        public string XML_Permissions
+        {
+            set => DirectoryPermissions.Import(value);
+            get => DirectoryPermissions.Export();
+        }
     }
 }
diff --git a/FileServer/Model/Entities/Users/Repo/Repo_Group.cs b/FileServer/Model/Entities/Users/Repo/Repo_Group.cs
index 0e30899..3b66aa5 100644
--- a/FileServer/Model/Entities/Users/Repo/Repo_Group.cs
+++ b/FileServer/Model/Entities/Users/Repo/Repo_Group.cs
@@ -4,6 +4,8 @@ using System.Linq;
 using System.Text;
 using System.Threading.Tasks;
 
+
+using Model.Entities.Files.Repo;
 using Model.Entities.Base;
 using Model.UnitsOfWork;
 
@@ -21,12 +23,14 @@ namespace Model.Entities.Users
     {
         public readonly static string[] DefaultGroupsNames = new string[]
         {
-        EnumDefaultGroups.Администраторы.ToString(),
-        EnumDefaultGroups.Модераторы.ToString(),
-        EnumDefaultGroups.Пользователи.ToString(),
-        EnumDefaultGroups.Анонимные.ToString()
+            EnumDefaultGroups.Администраторы.ToString(),
+            EnumDefaultGroups.Модераторы.ToString(),
+            EnumDefaultGroups.Пользователи.ToString(),
+            EnumDefaultGroups.Анонимные.ToString()
         };
 
+        public Repo_Group(UOW UOW) : base(UOW) { }
+
         public Group GetDefaultGroup(EnumDefaultGroups en)
         {
             var group = All.FirstOrDefault(e => e.Name == en.ToString());
@@ -39,27 +43,46 @@ namespace Model.Entities.Users
 
             return group;
         }
-  
 
 
-        public Repo_Group(Context context) : base(context) { }
-
         protected override void Validation_Create(Group elem)
         {
             if (All_NoTrack.FirstOrDefault(e => e.Name == elem.Name) != null)
                 throw new Exception();
         }
+        public override Group Create(Group elem)
+        {
+            UOW.Repo_SRootDirectory.All_NoTrack_List.ForEach(e =>
+            {
+                elem.DirectoryPermissions.Permissions.Add(e.ID, Permission.Factory_NoPermission(e));
+            });            
+
+            return base.Create(elem);
+        }
+
+        protected override void Validation_Update(Group old, Group elem)
+        {
+            //Изменение названия
+            if (old.Name != elem.Name)
+            {
+                //Не менять название дефолтных групп
+                if (DefaultGroupsNames.Contains(elem.Name))
+                    throw new Exception();
+
+                //Группа с таким именем уже существует
+                if (All_NoTrack.FirstOrDefault(e => e.Name == elem.Name) != null)
+                    throw new Exception();
+            }
+        }
 
         protected override void Validation_Delete(Group elem)
         {
             if (DefaultGroupsNames.Contains(elem.Name))
                 throw new Exception();
-        }
 
-        protected override void Validation_Update(Group old, Group elem)
-        {
-            throw new NotImplementedException();
+            elem.Users.Clear();
         }
+
     }
 }
 
diff --git a/FileServer/Model/Entities/Users/Repo/Repo_User.cs b/FileServer/Model/Entities/Users/Repo/Repo_User.cs
index fec2d2b..c3ea78a 100644
--- a/FileServer/Model/Entities/Users/Repo/Repo_User.cs
+++ b/FileServer/Model/Entities/Users/Repo/Repo_User.cs
@@ -11,12 +11,15 @@ namespace Model.Entities.Users
 {
     public class Repo_User : BaseRepository<User>
     {
-        public Repo_User(Context context) : base(context) { }
+        public Repo_User(UOW UOW) : base(UOW) { }
 
         protected override void Validation_Create(User elem)
         {
             if (All_NoTrack.FirstOrDefault(e => e.Login == elem.Login) != null)
-                throw new Exception();                
+                throw new Exception();
+
+            if (elem.Groups.Count() == 0)
+                throw new Exception();
         }
 
         protected override void Validation_Delete(User elem)
@@ -26,7 +29,8 @@ namespace Model.Entities.Users
 
         protected override void Validation_Update(User old, User elem)
         {
-            throw new NotImplementedException();
+            if (All_NoTrack.FirstOrDefault(e => e.Login == elem.Login) != null)
+                throw new Exception();
         }
     }
 }
diff --git a/FileServer/Model/Entities/Users/User.cs b/FileServer/Model/Entities/Users/User.cs
index bfbe111..9ed95d7 100644
--- a/FileServer/Model/Entities/Users/User.cs
+++ b/FileServer/Model/Entities/Users/User.cs
@@ -5,21 +5,36 @@ using System.Text;
 using System.Threading.Tasks;
 
 using System.ComponentModel.DataAnnotations.Schema;
+using System.ComponentModel.DataAnnotations;
 
 using Model.Entities.Base;
+using Model.Entities.Files;
 
 namespace Model.Entities.Users
 {
     public class User : BaseEntity
     {
-        //[Index]
+        [Required]
         public string Login { set; get; }
+        [Required]
         public string Password { set; get; }
         public bool IsActive { set; get; }
 
+        public bool IsAdmin
+        {
+            get
+            {
+                EnumDefaultGroups res;
+                return Groups.FirstOrDefault(e => Enum.TryParse<EnumDefaultGroups>(e.Name, out res)) != null;
+            }
+        }
 
-        [InverseProperty("Users")]
-        public virtual IEnumerable<Group> Groups { set; get; }
+
+
+
+    public virtual List<Group> Groups { set; get; } = new List<Group>();
+
+        public virtual List<FS_Item> FS_Items { set; get; } = new List<FS_Item>();
 
     }
 }
diff --git a/FileServer/Model/UnitsOfWork/UOW.cs b/FileServer/Model/UnitsOfWork/UOW.cs
index 4605fb6..3c9ac69 100644
--- a/FileServer/Model/UnitsOfWork/UOW.cs
+++ b/FileServer/Model/UnitsOfWork/UOW.cs
@@ -16,11 +16,11 @@ namespace Model.UnitsOfWork
     {
         public readonly Context context = new Context();
 
-        public readonly Repo_SRootDirectory Repo_rootDirectory;
+        public readonly Repo_SRootDirectory Repo_SRootDirectory;
         public readonly Repo_SDirectory Repo_SDirectory;
         public readonly Repo_SFile Repo_SFile;
         public readonly Repo_SFileUpload Repo_SFileUpload;
-
+        public IQueryable<FS_Item> FS_Items => context.FS_Items;
 
         public readonly Repo_User Repo_User;
         public readonly Repo_Group Repo_Group;
@@ -37,14 +37,14 @@ namespace Model.UnitsOfWork
 
         public UOW()
         {
-            Repo_rootDirectory = new Repo_SRootDirectory(context);
-            Repo_SDirectory = new Repo_SDirectory(context);
-            Repo_SFile = new Repo_SFile(context);
-            Repo_SFileUpload = new Repo_SFileUpload(context);
-
-            Repo_Group = new Repo_Group(context);
-            Repo_User = new Repo_User(context);
+            Repo_Group = new Repo_Group(this);
+            Repo_User = new Repo_User(this);
 
+            Repo_SRootDirectory = new Repo_SRootDirectory(this);
+            Repo_SDirectory = new Repo_SDirectory(this);
+            Repo_SFile = new Repo_SFile(this);
+            Repo_SFileUpload = new Repo_SFileUpload(this);
+            
 
             if (Repo_User.All_NoTrack.Count() == 0)
             {
@@ -60,5 +60,64 @@ namespace Model.UnitsOfWork
                 });              
             }
         }
+
+
+        public FS_Item Create(FS_Item elem)
+        {
+            switch (elem.Type)
+            {
+                case Enum_BaseDirectoryEntity.File:
+                    return Repo_SFile.Create((SFile)elem);
+                case Enum_BaseDirectoryEntity.Directory:
+                    return Repo_SDirectory.Create((SDirectory)elem);
+                case Enum_BaseDirectoryEntity.RootDirectory:
+                    return Repo_SRootDirectory.Create((SRootDirectory)elem);
+                case Enum_BaseDirectoryEntity.UploadFile:
+                    return Repo_SFileUpload.Create((SFileUpload)elem);
+                default:
+                    throw new Exception();
+            }
+        }
+        public void Update(FS_Item elem)
+        {
+            switch (elem.Type)
+            {
+                case Enum_BaseDirectoryEntity.File:
+                    Repo_SFile.Update((SFile)elem);
+                    return;
+                case Enum_BaseDirectoryEntity.Directory:
+                    Repo_SDirectory.Update((SDirectory)elem);
+                    return;
+                case Enum_BaseDirectoryEntity.RootDirectory:
+                    Repo_SRootDirectory.Update((SRootDirectory)elem);
+                    return;
+                case Enum_BaseDirectoryEntity.UploadFile:
+                    Repo_SFileUpload.Update((SFileUpload)elem);
+                    return;
+                default:
+                    throw new Exception();
+            }
+        }
+        public void Delete(FS_Item elem)
+        {
+            switch (elem.Type)
+            {
+                case Enum_BaseDirectoryEntity.File:
+                    Repo_SFile.Delete((SFile)elem);
+                    return;
+                case Enum_BaseDirectoryEntity.Directory:
+                    Repo_SDirectory.Delete((SDirectory)elem);
+                    return;
+                case Enum_BaseDirectoryEntity.RootDirectory:
+                    Repo_SRootDirectory.Delete((SRootDirectory)elem);
+                    return;
+                case Enum_BaseDirectoryEntity.UploadFile:
+                    Repo_SFileUpload.Delete((SFileUpload)elem);
+                    return;
+                default:
+                    throw new Exception();
+            }
+        }
+
     }
 }
diff --git a/FileServer/Model/ViewModel/Files/UploadBlob.cs b/FileServer/Model/ViewModel/Files/UploadBlob.cs
index 132b0da..3d7c13f 100644
--- a/FileServer/Model/ViewModel/Files/UploadBlob.cs
+++ b/FileServer/Model/ViewModel/Files/UploadBlob.cs
@@ -9,11 +9,11 @@ namespace Model.ViewModel.Files
     public class UploadBlob
     {
         public int ID { set; get; }
-        public string Data { set; get; }
+        public string chunk { set; get; }
 
         public byte[] ToByte()
         {
-            var base64 = Data.Substring(@"data:application/octet-stream;base64,".Length);
+            var base64 = chunk.Substring(@"data:application/octet-stream;base64,".Length);
             return Convert.FromBase64String(base64);
         }
     }
diff --git a/FileServer/Web/Controllers/API/ExplorerController.cs b/FileServer/Web/Controllers/API/ExplorerController.cs
index ce1a786..b8b2433 100644
--- a/FileServer/Web/Controllers/API/ExplorerController.cs
+++ b/FileServer/Web/Controllers/API/ExplorerController.cs
@@ -7,6 +7,7 @@ using System.Web.Mvc;
 using System.IO;
 using System.Threading.Tasks;
 using System.Data.Entity;
+using System.Data;
 
 using Web.Models.Base;
 
@@ -29,10 +30,10 @@ namespace Web.Controllers
 
         public List<ViewModelItem> items = new List<ViewModelItem>();
 
-        public ViewModelItems(bool Successe, string ResMessage)     
+        public ViewModelItems(bool Successe, string ResMessage)
             : base(Successe, ResMessage, "GetDirectoryItems") { }
 
-    } 
+    }
     class ViewModelItem
     {
         public int ID { set; get; }
@@ -47,18 +48,21 @@ namespace Web.Controllers
              : base(Successe, ResMessage, "DeleteFile") { }
     }
 
-    public class ExplorerController : BaseController
+    public class ExplorerController : BaseApiController
     {
-
-
         [HttpGet]
         public JsonResult GetDirectoryItems(int ID)
         {
+            ViewModelItems json;
+
             if (ID == -1)
             {
-                var data = UOW.Repo_rootDirectory.All_NoTrack_List;
+                //#Data #Permission
+                //Выбрать корренные папки, к которым имеет доступ текущий пользователь
+                var data = UOW.Repo_SRootDirectory.All_NoTrack_List.
+                    Where(e => permissionServices.CanOpen(CurrentUser, e)).ToList();
 
-                var json = new ViewModelItems(true, "")
+                json = new ViewModelItems(true, "")
                 {
                     ParentID = -1,
                     LogicPath = @"\",
@@ -80,13 +84,27 @@ namespace Web.Controllers
             }
             else
             {
-                var data = UOW.context.FS_Items.
+                //#Data
+                var data = UOW.Repo_SDirectory.All_NoTrack.
                     Where(e => e.ID == ID).
-                    AsNoTracking().
+                    Include(e => e.Root).
                     Include("_Items").
                     First();
 
-                var json = new ViewModelItems(true, "")
+                //#Permission
+                if (!permissionServices.CanOpen(CurrentUser, data))
+                {
+                    var json_PError = new ViewModelItems(false, "CanOpen permission error")
+                    {
+                        PermissionError = true
+                    };
+
+                    return Json(json_PError, JsonRequestBehavior.AllowGet);
+                }
+
+
+
+                json = new ViewModelItems(true, "")
                 {
                     ParentID = data.IsRoot ? -1 : data.Parent_ID.Value,
                     LogicPath = data.LogicPath,
@@ -115,7 +133,18 @@ namespace Web.Controllers
         [HttpGet]
         public FileResult GetFile(int ID)
         {
-            var file = UOW.Repo_SFile.All_NoTrack.FirstOrDefault(e => e.ID == ID);
+            //#Data
+            var file = UOW.Repo_SFile.All_NoTrack.
+                FirstOrDefault(e => e.ID == ID);
+
+            //#Permission
+            if (!permissionServices.CanDownload(CurrentUser, file.Root))
+            {
+                MemoryStream res = new MemoryStream();
+
+                return File(res, "application/octet-stream", "CanDownload permission error");
+            }
+
 
             return File(file.Info.Open(FileMode.Open, FileAccess.Read), "application/octet-stream", file.Name);
         }
@@ -123,43 +152,58 @@ namespace Web.Controllers
         [HttpPost]
         public JsonResult DeleteFile(int ID)
         {
-            try
-            {
-                var file = UOW.Repo_SFile.All.FirstOrDefault(e => e.ID == ID);
-                UOW.Repo_SFile.Delete(file);
-            }
-            catch (Exception ex)
-            {
-                var json_err = new DeleteResult(false, ex.Message);
+            //try
+            //{
+                //#Data
+                var file = UOW.FS_Items.FirstOrDefault(e => e.ID == ID);
 
-                return Json(json_err, JsonRequestBehavior.AllowGet);
-            }
+                //#Permission
+                if (!permissionServices.CanUpload(CurrentUser, file.Root))
+                {
+                    var json_PError = new ViewModelItems(false, "CanOpen permission error")
+                    {
+                        PermissionError = true
+                    };
+
+                    return Json(json_PError);
+                }
+
+                UOW.Delete(file);
+            //}
+            //catch (Exception ex)
+            //{
+                //var json_err = new DeleteResult(false, ex.Message);
+
+                //return Json(json_err, JsonRequestBehavior.AllowGet);
+           // }
 
             var json = new DeleteResult(true, "");
 
-            return Json(json, JsonRequestBehavior.AllowGet);
+            return Json(json);
         }
 
+
+
         [HttpGet]
         public async Task<JsonResult> ScanDirectory(int ID)
         {
             if (ID == -1)
             {
-                var dir = UOW.Repo_rootDirectory.All_List;
+                var dir = UOW.Repo_SRootDirectory.All_List;
                 new ConfigurationServices(UOW).
                     ReadConfiguration();
                 await new ScanServices(UOW).ScanAllDirs();
             }
             else
             {
-                var dir = UOW.context.FS_Items.
+                var dir = UOW.Repo_SDirectory.All.
                     FirstOrDefault(e => e.ID == ID);
                 await new ScanServices(UOW).
                     RecursScanDirectoryAsync((SDirectory)dir, false);
 
 
-                var items = UOW.context.FS_Items.
-                    FirstOrDefault(e => e.ID == ID).Items.ToList();
+                //var items = UOW.context.FS_Items.
+                //    FirstOrDefault(e => e.ID == ID).Items.ToList();
             }
 
 
@@ -167,15 +211,45 @@ namespace Web.Controllers
         }
 
 
+
+        [HttpPost]
+        public JsonResult MoveElement(int ID, int NewParent)
+        {
+            //Перемещаемый элемент
+            var elem = UOW.FS_Items.FirstOrDefault(e => e.ID == ID);
+            //Папка в которую будет выполняться перемещение
+            var new_parent = UOW.Repo_SDirectory.All.FirstOrDefault(e => e.ID == NewParent);
+
+
+            if (permissionServices.CanUpload(CurrentUser, elem.Parent) &&
+                permissionServices.CanUpload(CurrentUser, new_parent))
+            {
+                return Json(false);
+            }
+
+            elem.Parent = new_parent;
+            UOW.Update(elem);
+
+            return Json(true);
+        }
+
+        [HttpPost]
         public JsonResult CreateDirectory(int ParentID, string Name)
         {
-            var parent = UOW.context.FS_Items.
+            //#Data
+            var parent = UOW.Repo_SDirectory.All.
                 FirstOrDefault(e => e.ID == ParentID);
 
+            //#Permission
+            if (!permissionServices.CanUpload(CurrentUser, parent))
+            {
+                return Json(false);
+            }
+
             UOW.Repo_SDirectory.
-                Create(new SDirectory((SDirectory)parent, Name));
+                Create(new SDirectory((SDirectory)parent, Name, CurrentUser));
 
-            return Json(true, JsonRequestBehavior.AllowGet);
+            return Json(true);
         }
 
     }
diff --git a/FileServer/Web/Controllers/API/TestController.cs b/FileServer/Web/Controllers/API/TestController.cs
new file mode 100644
index 0000000..928ceb9
--- /dev/null
+++ b/FileServer/Web/Controllers/API/TestController.cs
@@ -0,0 +1,39 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Web;
+using System.Web.Mvc;
+
+namespace Web.Controllers
+{
+
+    public class Entity
+    {
+        public int id { set; get; }
+        public string name { set; get; }
+    }
+
+    public class TestController : BaseApiController
+    {
+        [HttpPost]
+        public void Test(int id, string name)
+        {
+
+
+        }
+
+        //[HttpPost]
+        //public void Test()
+        //{
+        //    var data = GetJson<Entity>();
+
+        //    //using (var stream = HttpContext.Request.InputStream)
+        //    //{
+        //    //    stream.read
+        //    //}
+
+        //    int a = 2;
+
+        //}
+    }
+}
\ No newline at end of file
diff --git a/FileServer/Web/Controllers/API/UploadFilesController.cs b/FileServer/Web/Controllers/API/UploadFilesController.cs
index c743eeb..5a4eb7a 100644
--- a/FileServer/Web/Controllers/API/UploadFilesController.cs
+++ b/FileServer/Web/Controllers/API/UploadFilesController.cs
@@ -6,6 +6,7 @@ using System.Web.Mvc;
 
 using Model.Entities.Base;
 using Model.Entities.Files.FS_Entities;
+using Model.Entities.Users;
 using Model.UnitsOfWork;
 using BLL.Services;
 
@@ -22,14 +23,8 @@ namespace Web.Controllers
     }
 
 
-    public class UploadFilesController : BaseController
+    public class UploadFilesController : BaseApiController
     {
-        
-        //[HttpGet]
-        //public ActionResult UploadPage()
-        //{
-        //    return View();
-        //}
 
         [HttpPost]
         public JsonResult StartUpload(int ParentID, string Name, long size)
@@ -38,8 +33,8 @@ namespace Web.Controllers
 
             try
             {
-                var parent = UOW.context.FS_Items.FirstOrDefault(e => e.ID == ParentID);
-                var proj = uploadServices.StartUpload((SDirectory)parent, Name, size);
+                var parent = UOW.Repo_SDirectory.All.FirstOrDefault(e => e.ID == ParentID);
+                var proj = uploadServices.StartUpload(parent, Name, size, CurrentUser);
 
                 ID = proj.ID;
             }
@@ -59,16 +54,13 @@ namespace Web.Controllers
             });
         }
 
+
+
         [HttpPost]
-        public JsonResult UploadBlob()
+        public JsonResult UploadBlob(UploadBlob model)
         {
-            UploadBlob model = new UploadBlob();
-
             try
             {
-                model.ID = int.Parse(Request.Form["ID"]);
-                model.Data = Request.Unvalidated.Form["chunk"];
-
                 var prog = UOW.Repo_SFileUpload.All.
                     FirstOrDefault(e => e.ID == model.ID);
 
@@ -100,5 +92,6 @@ namespace Web.Controllers
             return Json(true);
         }
 
+
     }
 }
\ No newline at end of file
diff --git a/FileServer/Web/Controllers/API/UserController.cs b/FileServer/Web/Controllers/API/UserController.cs
index 92cad53..6e3124d 100644
--- a/FileServer/Web/Controllers/API/UserController.cs
+++ b/FileServer/Web/Controllers/API/UserController.cs
@@ -5,6 +5,7 @@ using System.Web;
 using System.Web.Mvc;
 
 using Model.Entities.Users;
+using Web.Models.Base;
 
 namespace Web.Controllers
 {
@@ -19,7 +20,7 @@ namespace Web.Controllers
     }
 
 
-    public class UserController : BaseController
+    public class UserController : BaseApiController
     {
 
         /// <summary>
@@ -29,7 +30,7 @@ namespace Web.Controllers
         /// <param name="Password"></param>
         /// <returns></returns>
         /// 
-        [HttpGet]
+        [HttpPost]
         public JsonResult Auth(string Login, string Password)
         {
             var user = UOW.Repo_User.All_NoTrack.
@@ -60,6 +61,32 @@ namespace Web.Controllers
 
 
 
+        [HttpPost]
+        public JsonResult UserInfo()
+        {
+            if (CurrentUser != null)
+            {
+                return Json(new AuthResult()
+                {
+                    Successe = true,
+
+                    Token = CurrentUser.ID.ToString(),
+                    UserName = CurrentUser.Login
+                }, JsonRequestBehavior.AllowGet);
+            }
+            else
+            {
+                return Json(new AuthResult()
+                {
+                    Successe = false,
+                    ResMsg = "Пользователь не найден или заблокирован",
+
+                    Token = ""
+                }, JsonRequestBehavior.AllowGet);
+            }
+        }
+
+        [HttpPost]
         public JsonResult CreateUser(string Login, string Password)
         {
             UOW.Repo_User.Create(new User()
@@ -77,5 +104,48 @@ namespace Web.Controllers
         }
 
 
+        [HttpPost]
+        public JsonResult UserList()
+        {
+            UserListMode json;
+
+            if (CurrentUser.IsAdmin)
+            {
+                var data = UOW.Repo_User.All_NoTrack_List;
+                data.ForEach(e => e.Password = "");
+
+                json = new UserListMode(true)
+                {
+                    Users = data
+                };
+                
+            }
+            else
+            {
+                json = new UserListMode(false)
+                {
+                    PermissionError = true,
+                    ResMessage = "Need admin"                    
+                };
+            }
+
+            return Json(json);
+        }
+
+        [HttpPost]
+        public JsonResult UserList(List<User> users)
+        {
+
+            return Json(true);
+        }
+
+        public class UserListMode : BaseApiResult
+        {
+            public UserListMode(bool Successe) : base(Successe, "", "UserList") { }
+
+            public List<User> Users;
+        }
+
+
     }
 }
\ No newline at end of file
diff --git a/FileServer/Web/Controllers/Base/BaseApiController.cs b/FileServer/Web/Controllers/Base/BaseApiController.cs
new file mode 100644
index 0000000..fc95d7d
--- /dev/null
+++ b/FileServer/Web/Controllers/Base/BaseApiController.cs
@@ -0,0 +1,71 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Web;
+using System.Web.Mvc;
+
+using System.Web.Routing;
+using System.Web.Security;
+using System.Configuration;
+using System.IO;
+using System.Web.Script.Serialization;
+
+using BLL.Services;
+using Model.Entities.Users;
+
+namespace Web.Controllers
+{
+    public abstract class BaseApiController : BaseController
+    {
+        protected User CurrentUser { private set; get; }
+        protected readonly PermissionServices permissionServices;
+
+        /// <summary>
+        /// Http Post Json request
+        /// </summary>
+        /// <typeparam name="T"></typeparam>
+        /// <returns></returns>
+        protected T GetJson<T>()
+        {
+            using (var stream = HttpContext.Request.InputStream)
+            {
+                using (StreamReader rd = new StreamReader(stream))
+                {
+                    return new JavaScriptSerializer().
+                        Deserialize<T>(rd.ReadToEnd());
+                }
+            }
+        }
+
+
+        protected BaseApiController()
+        {
+            permissionServices = new PermissionServices(UOW);
+        }
+
+        protected override void Initialize(RequestContext requestContext)
+        {
+            base.Initialize(requestContext);
+
+            var cookie = HttpContext.Request.Cookies;
+
+            if (cookie.AllKeys.Contains("AuthToken"))
+            {
+                var auth = cookie.Get("AuthToken");
+
+                if (auth.Value.Count() != 0)
+                {
+                    int ID = -1;
+
+                    if (int.TryParse(auth.Value.First().ToString(), out ID))
+                    {
+                        CurrentUser = UOW.Repo_User.All.
+                            FirstOrDefault(e => e.ID == ID);
+                    }
+                }
+
+            }
+
+        }
+    }
+}
\ No newline at end of file
diff --git a/FileServer/Web/Global.asax.cs b/FileServer/Web/Global.asax.cs
index 2d1dfa9..1c5b04b 100644
--- a/FileServer/Web/Global.asax.cs
+++ b/FileServer/Web/Global.asax.cs
@@ -26,10 +26,11 @@ namespace Web
             RouteConfig.RegisterRoutes(RouteTable.Routes);
             BundleConfig.RegisterBundles(BundleTable.Bundles);
 
-            
+            //Для обработки POST json запросов
+            ValueProviderFactories.Factories.Add(new JsonValueProviderFactory());
 
             //Очистить базу данных
-            //new Context(true);
+            new Context(true);
             var UOW = new UOW();
             //Прочитать корневые папки
             new ConfigurationServices(UOW).ReadConfiguration();
diff --git a/FileServer/Web/Models/Base/BaseApiResult.cs b/FileServer/Web/Models/Base/BaseApiResult.cs
index 46f992a..8f78432 100644
--- a/FileServer/Web/Models/Base/BaseApiResult.cs
+++ b/FileServer/Web/Models/Base/BaseApiResult.cs
@@ -11,6 +11,9 @@ namespace Web.Models.Base
         public string ResMessage { set; get; }
         public string ActionName { set; get; }
 
+
+        public bool PermissionError { set; get; }
+
         public BaseApiResult(bool Successe, string ResMessage, string ActionName)
         {
             this.Successe = Successe;
diff --git a/FileServer/Web/Scripts/React/Controls/MenuControl.jsx b/FileServer/Web/Scripts/React/Controls/MenuControl.jsx
new file mode 100644
index 0000000..9f6f45c
--- /dev/null
+++ b/FileServer/Web/Scripts/React/Controls/MenuControl.jsx
@@ -0,0 +1,49 @@
+
+
+
+class MenuControl extends React.Component {
+
+    constructor(props) {
+        super(props);
+        console.log('MenuControl start');
+
+        //this.state = { counter: 0 };
+        this.userServices = new UserServices();
+
+        this.OnAuthChange = this.OnAuthChange.bind(this);
+    }
+
+    OnAuthChange() {
+        this.forceUpdate();
+    }
+
+    render() {
+        return (
+            <div>
+
+                <table>
+                    <tr>
+                        <th>Menu:</th>
+                        <th>
+                            <Link to={`/`}>
+                                <button>FS</button>
+                            </Link>
+                        </th>
+
+                        {this.userServices.IsAuth()
+                            ?
+                            <th>
+                                <Link to={`/Admin`}>
+                                    <button>Admin</button>
+                                </Link>
+                            </th>
+                            : ""
+                        }                        
+                    </tr>
+                </table>
+
+            </div>
+        );
+    }
+}
+
diff --git a/FileServer/Web/Scripts/React/Pages/AdministratorPage.jsx b/FileServer/Web/Scripts/React/Pages/AdministratorPage.jsx
new file mode 100644
index 0000000..cf54d76
--- /dev/null
+++ b/FileServer/Web/Scripts/React/Pages/AdministratorPage.jsx
@@ -0,0 +1,28 @@
+
+
+
+class AdministratorPage extends React.Component {
+
+    constructor(props) {
+        super(props);
+        console.log('AdministratorPage start');
+
+    }
+
+    OnAuthChange() {
+        this.refs.MenuControl.OnAuthChange();
+    }
+
+    render() {
+        return (
+            <div>
+                <hr />
+                <MenuControl ref="MenuControl"
+                    ParentComponent={this}
+                />
+
+            </div>
+        );
+    }
+}
+
diff --git a/FileServer/Web/Scripts/React/Pages/FileExplorerPage.jsx b/FileServer/Web/Scripts/React/Pages/FileExplorerPage.jsx
new file mode 100644
index 0000000..5abf9aa
--- /dev/null
+++ b/FileServer/Web/Scripts/React/Pages/FileExplorerPage.jsx
@@ -0,0 +1,92 @@
+
+
+class FileExplorerPage extends React.Component {
+
+    constructor(props) {
+        super(props);
+        console.log('FileExplorerPage start');
+
+        //this.state = { counter: 0 };
+
+        this.OnAuthChange = this.OnAuthChange.bind(this);
+        this.OnItemsChange = this.OnItemsChange.bind(this);
+
+        this.SetID = this.SetID.bind(this);
+        this.GetID = this.GetID.bind(this);
+
+        //Получить ID из url
+        var Url_ID = new URL(window.location.href).
+            searchParams.get("ID");
+
+        if (Url_ID != null)
+            this.SetID(Url_ID);
+        //if (this.props.match != undefined
+        //    && this.props.match.params != undefined
+        //    && this.props.match.params.ID != undefined)
+        //    this.SetID(this.props.match.params.ID);
+        //Получить id от родительского компонента
+        else
+            this.SetID(-1);
+    }
+
+
+    OnAuthChange() {
+        this.OnItemsChange();
+        this.refs.MenuControl.OnAuthChange();
+    }
+    OnItemsChange() {
+        this.refs.FileExplorerControl.
+            LoadDirectory();
+    }
+
+    SetID(val) {
+        this.CurrentID = val;
+        console.log(this.CurrentID);
+    }
+
+    GetID() {
+        return this.CurrentID;
+    }
+
+
+    render() {
+        return (
+            <div>
+                <hr />
+                <MenuControl ref="MenuControl"
+                    ParentComponent={this}
+                />
+                <hr />
+                <UserControl ref="UserControl"
+                    ParentComponent={this}
+                />
+
+                <hr />
+                <FileExplorerControl ref="FileExplorerControl"
+                    ParentComponent={this}
+                    ShoSelect={true}
+                />
+                <hr />
+                {this.GetID() != -1
+                    ?
+                    <div>                        
+                        <ExplorerActionsControl ref="ExplorerActionsControl"
+                            ParentComponent={this}
+                        />
+                        <hr />
+                        <UploaderControl ref="UploaderControl"
+                            ParentComponent={this}
+                        />
+                        <hr />
+                    </div>
+                    : ""
+                }
+                <BootstrapControl
+                />
+                <hr />
+
+            </div>
+        );
+    }
+}
+
diff --git a/FileServer/Web/Scripts/React/RouteSystem.jsx b/FileServer/Web/Scripts/React/RouteSystem.jsx
index 2835f46..a042675 100644
--- a/FileServer/Web/Scripts/React/RouteSystem.jsx
+++ b/FileServer/Web/Scripts/React/RouteSystem.jsx
@@ -6,14 +6,17 @@ class RouteSystem extends React.Component {
     constructor(props) {
         super(props);
         console.log('RouteSystem start');
+
+
     }
 
     render() {
         return (
             <Router>
                 <Switch>
-                    <Route path="/" component={() => <App ID="-1" />} />
-                    <Route path="/?ID=:ID" component={App} />
+                    <Route ref="CurrentPage" exact path="/" component={FileExplorerPage} />
+                    <Route ref="CurrentPage" path="/?ID=:ID" component={FileExplorerPage} />
+                    <Route ref="CurrentPage" path="/Admin" component={AdministratorPage} />
                 </Switch>
             </Router>
         );
diff --git a/FileServer/Web/Scripts/Services/FileExplorerServices.js b/FileServer/Web/Scripts/Services/FileExplorerServices.js
index fdcefc3..e8625fe 100644
--- a/FileServer/Web/Scripts/Services/FileExplorerServices.js
+++ b/FileServer/Web/Scripts/Services/FileExplorerServices.js
@@ -5,11 +5,11 @@ class FileExplorerServices {
         this.URL_DirectoryItems = "/Explorer/GetDirectoryItems?ID=";
         this.URL_ScanDirectory = "/Explorer/ScanDirectory?ID=";
 
-        this.URL_Delete = "/Explorer/DeleteFile?ID=";
+        this.URL_Delete = "/Explorer/DeleteFile";
+        this.URL_Move = "/Explorer/MoveElement";
         this.URL_Download = "/Explorer/GetFile?ID=";
         this.URL_CreateDirectory = "/Explorer/CreateDirectory?";
 
-
     }
 
 
@@ -19,28 +19,55 @@ class FileExplorerServices {
         return fetch(
             url,
             {
-                ID: ID
+                credentials: 'include'
             })
     }
 
     async ScanDirectoryAsync(ID) {
         let url = this.URL_ScanDirectory + ID;
 
-        return fetch(url);
+        return fetch(url,
+            {
+                credentials: 'include'
+            }
+        );
     }
 
-
     async DeleteAsync(ID) {
-        let url = this.URL_Delete + ID;
 
         return fetch(
-            url,
+            this.URL_Delete,
             {
-                method: 'POST'
+                method: 'POST',
+                headers: {
+                    'Content-Type': 'application/json'
+                },
+                credentials: 'include',
+                body: JSON.stringify({
+                    ID: ID
+                })
             }
         )
     }
 
+    async MoveAsync(elemID, directoryID) {
+        return fetch(
+            this.URL_Move,
+            {
+                method: 'POST',
+                headers: {
+                    'Content-Type': 'application/json'
+                },
+                credentials: 'include',
+                body: JSON.stringify({
+                    ID: elemID,
+                    NewParent: directoryID
+                })
+            }
+        )
+    }
+
+
     OpenDownload(ID) {
         let url = this.URL_Download + ID;
 
@@ -48,10 +75,19 @@ class FileExplorerServices {
     }
 
     async CreateDirectoryAsync(dirname, id) {
-        let url = this.URL_CreateDirectory+"ParentID = " + id
-            + "&Name=" + dirname;
-
-        return fetch(url);
+        return fetch(this.URL_CreateDirectory,
+            {
+                method: 'POST',
+                headers: {
+                    'Content-Type': 'application/json'
+                },
+                credentials: 'include',
+                body: JSON.stringify({
+                    ParentID: id,
+                    Name: dirname
+                })
+            }
+        );
     }
 
 }
\ No newline at end of file
diff --git a/FileServer/Web/Scripts/Services/UploadServices.js b/FileServer/Web/Scripts/Services/UploadServices.js
index a930cb2..6b91660 100644
--- a/FileServer/Web/Scripts/Services/UploadServices.js
+++ b/FileServer/Web/Scripts/Services/UploadServices.js
@@ -46,21 +46,38 @@ class UploadServices {
 
     //Сообщает серверу о начале загрузки файла, получает ID загрузки
     async _StartUploadAsync() {
-        return await $.post(this.URL_Start,
+        let res;
+
+        await fetch(
+            this.URL_Start,
             {
-                //ID папки
-                'ParentID': this._ParentID,
-                //Имя файла
-                'Name': this._file.name,
-                //Размеры
-                'Size': this._file.size
+                method: "Post",
+                headers: {
+                    'Content-Type': 'application/json'
+                },
+                body: JSON.stringify({
+                    //ID папки
+                    ParentID: this._ParentID,
+                    //Имя файла
+                    Name: this._file.name,
+                    //Размеры
+                    Size: this._file.size
+                })
             }
-        );
+        ).then(function (response) {
+            return response.json();
+        }).then(function (data) {
+            res = data;
+        }.bind(this));
+
+        return res;
     }
 
     //Выполняет загрузка блока
     async _UploadBlobAsync(bin_data, ChunkNumb) {
 
+        console.log("_UploadBlobAsync");
+
         if (!this._ContinueDownload)
             return { State: true };
 
@@ -68,18 +85,31 @@ class UploadServices {
         if (bin_data != '') {
             console.log(this.URL_Upload + ChunkNumb);
 
-            var state = await $.post(this.URL_Upload,
+            let res;
+
+            await fetch(
+                this.URL_Upload,
                 {
-                    //ID загрузки
-                    'ID': this.ID,
-                    //Кусок файла
-                    'chunk': bin_data,
-                    //Номер куска
-                    //'ChunkNumb': ChunkNumb
+                    method: "Post",
+                    headers: {
+                        'Content-Type': 'application/json'
+                    },
+                    body: JSON.stringify({
+                        //ID загрузки
+                        ID: this.ID,
+                        //Кусок файла
+                        chunk: bin_data
+                        //Номер куска
+                        //'ChunkNumb': ChunkNumb
+                    })
                 }
-            )
+            ).then(function (response) {
+                return response.json();
+            }).then(function (data) {
+                res = data;
+            }.bind(this));
 
-            return state;
+            return res;
         }
     }
 
@@ -110,6 +140,7 @@ class UploadServices {
             let bin_data = await this._ReadBlobAsync(pos, pos + this.upload_chunk_size);
             let state = await this._UploadBlobAsync(bin_data, ChunkNumb);
 
+
             if (!state.State) {
                 //alert('Загрузка прервана');
 
@@ -135,13 +166,22 @@ class UploadServices {
         //Костыль задержка, чтобы асинхронный загрузчик точно прервал работу
         //и не попытался получить доступ к ужаленному проекту загрузки
         //Возможно зависит от размера блока
-        setTimeout(function () { 
-            $.post(this.URL_Cansel,
+        setTimeout(function () {
+
+            fetch(
+                this.URL_Cansel,
                 {
-                    //Имя файла
-                    'ID': this.ID,
+                    method: "Post",
+                    headers: {
+                        'Content-Type': 'application/json'
+                    },
+                    body: JSON.stringify({
+                        //ID файла
+                        ID: this.ID,
+                    })
                 }
-            )
+            );
+
         }.bind(this),
             500);        
     }
diff --git a/FileServer/Web/Scripts/Services/UserServices.js b/FileServer/Web/Scripts/Services/UserServices.js
index cf8f52c..0713979 100644
--- a/FileServer/Web/Scripts/Services/UserServices.js
+++ b/FileServer/Web/Scripts/Services/UserServices.js
@@ -3,21 +3,37 @@ class UserServices {
 
     constructor() {
 
-        this.URL_Auth = "/User/Auth?";
+        this.URL_Auth = "/User/Auth";
+        this.URL_UserInfo = "/User/UserInfo"
+
+        this.AuthCoockieName = "AuthToken";
 
     }
 
 
 
-    Auth(login, password) {
+    AuthAsync(login, password) {
 
-        let url = this.URL_Auth + "Login=" + login + "&Password=" + password;
+        return fetch(
+            this.URL_Auth,
+            {
+                method: "Post",
+                headers: {
+                    'Content-Type': 'application/json'
+                },
+                body: JSON.stringify({               
+                    Login: login,
+                    Password: password
+                })
+            });
+    }
 
+    GetUserInfoAsync() {
         return fetch(
-            url,
+            this.URL_UserInfo,            
             {
-                //Login: login,
-                //Password: password
+                method: "Post",
+                credentials: 'include'
             });
     }
 
@@ -36,11 +52,11 @@ class UserServices {
 
     //Токен авторизации
     GetTocken() {
-        return this._getCookie("AuthToken");
+        return this._getCookie(this.AuthCoockieName);
     }
     //задать токен
     SetTocken(val) {
-        document.cookie = "AuthToken=" + val;
+        document.cookie = this.AuthCoockieName + "=" + val;
     }
 
     //Возвращает true если пользователь авторизован
diff --git a/FileServer/Web/Scripts/Tools/PromisesParallel.js b/FileServer/Web/Scripts/Tools/PromisesParallel.js
new file mode 100644
index 0000000..c68578e
--- /dev/null
+++ b/FileServer/Web/Scripts/Tools/PromisesParallel.js
@@ -0,0 +1,19 @@
+
+
+//Функция для облегчения работы с множественными запросами
+//Возможно есть более удобный вариант
+//Запросы => Ждем окончания => Вытащить json => Ждем окончания => Вернуть результат
+async function PromisesParallelAsync(promises) {
+
+    //Выполнить все запросы
+    var responses = await Promise.all(promises);
+
+    //Promise json
+    let json_promises = responses.map((e) => {
+        return e.json();
+    });
+
+    //Получить json результаты
+    return await Promise.all(json_promises);
+}
+
diff --git a/FileServer/Web/Views/Home/Index.cshtml b/FileServer/Web/Views/Home/Index.cshtml
index 8bf9f77..fed28a7 100644
--- a/FileServer/Web/Views/Home/Index.cshtml
+++ b/FileServer/Web/Views/Home/Index.cshtml
@@ -39,31 +39,36 @@
         @* BootstrapComponents *@
         const ButtonToolbar = ReactBootstrap.ButtonToolbar;
         const Button = ReactBootstrap.Button;
+        const Modal = ReactBootstrap.Modal;
+        const Form = ReactBootstrap.Form;
     </script>
 
 
     @* Application scripts *@
     @Scripts.RenderFormat("<script type ='text/babel' src='{0}' defer></script>",
 
-    "/Scripts/React/BootstrapControl.jsx?" + DateTime.Now,
+    "/Scripts/React/Controls/BootstrapControl.jsx?" + DateTime.Now,
 
 
     "/Scripts/Services/UserServices.js?" + DateTime.Now,
-    "/Scripts/React/UserControl.jsx?" + DateTime.Now,
+    "/Scripts/React/Controls/UserControl.jsx?" + DateTime.Now,
 
 
     "/Scripts/Services/UploadServices.js?" + DateTime.Now,
-    "/Scripts/React/UploaderControl.jsx?" + DateTime.Now,
+    "/Scripts/React/Controls/UploaderControl.jsx?" + DateTime.Now,
 
 
     "/Scripts/Tools/Sort.js?" + DateTime.Now,
+    "/Scripts/Tools/PromisesParallel.js?" + DateTime.Now,
     "/Scripts/Services/FileExplorerServices.js?" + DateTime.Now,
-    "/Scripts/React/FileExplorerRow.jsx?" + DateTime.Now,
-    "/Scripts/React/FileExplorerControl.jsx?" + DateTime.Now,
-    "/Scripts/React/ExplorerActionsControl.jsx?" + DateTime.Now,
+    "/Scripts/React/Controls/FileExplorerRow.jsx?" + DateTime.Now,
+    "/Scripts/React/Controls/FileExplorerControl.jsx?" + DateTime.Now,
+    "/Scripts/React/Controls/ExplorerActionsControl.jsx?" + DateTime.Now,
 
+    "/Scripts/React/Controls/MenuControl.jsx?" + DateTime.Now,
 
-    "/Scripts/React/App.jsx?" + DateTime.Now,
+    "/Scripts/React/Pages/FileExplorerPage.jsx?" + DateTime.Now,
+    "/Scripts/React/Pages/AdministratorPage.jsx?" + DateTime.Now,
     "/Scripts/React/RouteSystem.jsx?" + DateTime.Now
     )
 }
diff --git a/FileServer/Web/Web.config b/FileServer/Web/Web.config
index e7310eb..ba2400b 100644
--- a/FileServer/Web/Web.config
+++ b/FileServer/Web/Web.config
@@ -20,7 +20,7 @@
     <add key="webpages:Enabled" value="false" />
     <add key="ClientValidationEnabled" value="true" />
     <add key="UnobtrusiveJavaScriptEnabled" value="true" />
-    <add key="WorkFolder" value="C:\Users\cccc1808\source\repos\FileServer\Console\bin\Debug\Dir1;C:\Users\cccc1808\source\repos\FileServer\Console\bin\Debug\Dir2" />
+    <add key="WorkFolder" value="D:\GIT\WebFileServer\FileServer\Console\bin\Debug\Dir1;D:\GIT\WebFileServer\FileServer\Console\bin\Debug\Dir2" />
   </appSettings>
   <!--
     Описание изменений web.config см. по адресу http://go.microsoft.com/fwlink/?LinkId=235367.
diff --git a/FileServer/Web/Web.csproj b/FileServer/Web/Web.csproj
index 7ee4ecc..ecd8b24 100644
--- a/FileServer/Web/Web.csproj
+++ b/FileServer/Web/Web.csproj
@@ -142,6 +142,8 @@
     <Compile Include="App_Start\RouteConfig.cs" />
     <Compile Include="App_Start\WebApiConfig.cs" />
     <Compile Include="BackgroundWorkers\GarbageUploadsWorker.cs" />
+    <Compile Include="Controllers\API\TestController.cs" />
+    <Compile Include="Controllers\Base\BaseApiController.cs" />
     <Compile Include="Controllers\Base\BaseController.cs" />
     <Compile Include="Controllers\API\ExplorerController.cs" />
     <Compile Include="Controllers\HomeController.cs" />
@@ -198,8 +200,11 @@
     <Content Include="Scripts\jquery.validate.min.js" />
     <Content Include="Scripts\jquery.validate.unobtrusive.js" />
     <Content Include="Scripts\jquery.validate.unobtrusive.min.js" />
-    <Content Include="Scripts\React\BootstrapControl.jsx" />
-    <Content Include="Scripts\React\ExplorerActionsControl.jsx" />
+    <Content Include="Scripts\React\Controls\BootstrapControl.jsx" />
+    <Content Include="Scripts\React\Controls\ExplorerActionsControl.jsx" />
+    <Content Include="Scripts\React\Controls\MenuControl.jsx" />
+    <Content Include="Scripts\React\Pages\AdministratorPage.jsx" />
+    <Content Include="Scripts\React\Pages\FileExplorerPage.jsx" />
     <Content Include="Scripts\Services\FileExplorerServices.js" />
     <Content Include="Scripts\Services\UserServices.js" />
     <Content Include="Scripts\modernizr-2.8.3.js" />
@@ -208,12 +213,13 @@
     <Content Include="Scripts\popper.js" />
     <Content Include="Scripts\popper.min.js" />
     <Content Include="Scripts\React\App.jsx" />
-    <Content Include="Scripts\React\FileExplorerControl.jsx" />
-    <Content Include="Scripts\React\FileExplorerRow.jsx" />
+    <Content Include="Scripts\React\Controls\FileExplorerControl.jsx" />
+    <Content Include="Scripts\React\Controls\FileExplorerRow.jsx" />
     <Content Include="Scripts\React\RouteSystem.jsx" />
-    <Content Include="Scripts\React\UploaderControl.jsx" />
-    <Content Include="Scripts\React\UserControl.jsx" />
+    <Content Include="Scripts\React\Controls\UploaderControl.jsx" />
+    <Content Include="Scripts\React\Controls\UserControl.jsx" />
     <Content Include="Scripts\Services\UploadServices.js" />
+    <Content Include="Scripts\Tools\PromisesParallel.js" />
     <Content Include="Scripts\Tools\Sort.js" />
     <Content Include="Scripts\umd\popper-utils.js" />
     <Content Include="Scripts\umd\popper-utils.min.js" />
@@ -247,6 +253,8 @@
   </ItemGroup>
   <ItemGroup>
     <Folder Include="App_Data\" />
+    <Folder Include="Views\BaseApi\" />
+    <Folder Include="Views\Test\" />
   </ItemGroup>
   <ItemGroup>
     <None Include="packages.config" />
diff --git "a/\320\224\320\270\320\260\320\263\321\200\320\260\320\274\320\274\321\213/\320\224\320\270\320\260\320\263\321\200\320\260\320\274\320\274\320\2601.graphml" "b/\320\224\320\270\320\260\320\263\321\200\320\260\320\274\320\274\321\213/\320\224\320\270\320\260\320\263\321\200\320\260\320\274\320\274\320\2601.graphml"
new file mode 100644
index 0000000..90984d3
--- /dev/null
+++ "b/\320\224\320\270\320\260\320\263\321\200\320\260\320\274\320\274\321\213/\320\224\320\270\320\260\320\263\321\200\320\260\320\274\320\274\320\2601.graphml"
@@ -0,0 +1,650 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<graphml xmlns="http://graphml.graphdrawing.org/xmlns" xmlns:java="http://www.yworks.com/xml/yfiles-common/1.0/java" xmlns:sys="http://www.yworks.com/xml/yfiles-common/markup/primitives/2.0" xmlns:x="http://www.yworks.com/xml/yfiles-common/markup/2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:y="http://www.yworks.com/xml/graphml" xmlns:yed="http://www.yworks.com/xml/yed/3" xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns http://www.yworks.com/xml/schema/graphml/1.1/ygraphml.xsd">
+  <!--Created by yEd 3.16.2.1-->
+  <key attr.name="Description" attr.type="string" for="graph" id="d0"/>
+  <key for="port" id="d1" yfiles.type="portgraphics"/>
+  <key for="port" id="d2" yfiles.type="portgeometry"/>
+  <key for="port" id="d3" yfiles.type="portuserdata"/>
+  <key attr.name="url" attr.type="string" for="node" id="d4"/>
+  <key attr.name="description" attr.type="string" for="node" id="d5"/>
+  <key for="node" id="d6" yfiles.type="nodegraphics"/>
+  <key for="graphml" id="d7" yfiles.type="resources"/>
+  <key attr.name="url" attr.type="string" for="edge" id="d8"/>
+  <key attr.name="description" attr.type="string" for="edge" id="d9"/>
+  <key for="edge" id="d10" yfiles.type="edgegraphics"/>
+  <graph edgedefault="directed" id="G">
+    <data key="d0"/>
+    <node id="n0" yfiles.foldertype="group">
+      <data key="d6">
+        <y:ProxyAutoBoundsNode>
+          <y:Realizers active="0">
+            <y:GenericGroupNode configuration="DemoGroup">
+              <y:Geometry height="288.701171875" width="524.0919999999999" x="658.0" y="0.0"/>
+              <y:Fill color="#68B0E3" color2="#3C679B" transparent="false"/>
+              <y:BorderStyle color="#000000" type="line" width="1.0"/>
+              <y:NodeLabel alignment="center" autoSizePolicy="content" borderDistance="0.0" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" horizontalTextPosition="center" iconTextGap="4" modelName="internal" modelPosition="tl" textColor="#FFFFFF" verticalTextPosition="bottom" visible="true" width="161.62890625" x="0.0" y="0.0">Структура хранения данных</y:NodeLabel>
+              <y:State autoResize="true" closed="false" closedHeight="50.0" closedWidth="50.0"/>
+              <y:Insets bottom="15" bottomF="15.0" left="15" leftF="15.0" right="15" rightF="15.0" top="15" topF="15.0"/>
+              <y:BorderInsets bottom="0" bottomF="0.0" left="5" leftF="5.218953124999871" right="12" rightF="11.757476562499733" top="0" topF="0.0"/>
+            </y:GenericGroupNode>
+            <y:GenericGroupNode configuration="DemoGroup">
+              <y:Geometry height="50.0" width="50.0" x="658.0" y="0.0"/>
+              <y:Fill color="#68B0E3" color2="#3C679B" transparent="false"/>
+              <y:BorderStyle color="#000000" type="line" width="1.0"/>
+              <y:NodeLabel alignment="center" autoSizePolicy="content" borderDistance="0.0" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" horizontalTextPosition="center" iconTextGap="4" modelName="internal" modelPosition="tl" textColor="#FFFFFF" verticalTextPosition="bottom" visible="true" width="10.673828125" x="0.0" y="0.0">5</y:NodeLabel>
+              <y:State autoResize="true" closed="true" closedHeight="50.0" closedWidth="50.0"/>
+              <y:Insets bottom="15" bottomF="15.0" left="15" leftF="15.0" right="15" rightF="15.0" top="15" topF="15.0"/>
+              <y:BorderInsets bottom="0" bottomF="0.0" left="0" leftF="0.0" right="0" rightF="0.0" top="0" topF="0.0"/>
+            </y:GenericGroupNode>
+          </y:Realizers>
+        </y:ProxyAutoBoundsNode>
+      </data>
+      <graph edgedefault="directed" id="n0:">
+        <node id="n0::n0">
+          <data key="d6">
+            <y:ShapeNode>
+              <y:Geometry height="30.0" width="30.0" x="678.2189531249999" y="173.701171875"/>
+              <y:Fill color="#FFCC00" transparent="false"/>
+              <y:BorderStyle color="#000000" raised="false" type="line" width="1.0"/>
+              <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="27.337890625" x="1.3310546875" y="5.6494140625">Item<y:LabelModel>
+                  <y:SmartNodeLabelModel distance="4.0"/>
+                </y:LabelModel>
+                <y:ModelParameter>
+                  <y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
+                </y:ModelParameter>
+              </y:NodeLabel>
+              <y:Shape type="ellipse"/>
+            </y:ShapeNode>
+          </data>
+        </node>
+        <node id="n0::n1">
+          <data key="d6">
+            <y:ShapeNode>
+              <y:Geometry height="30.0" width="30.0" x="760.7189531249999" y="173.701171875"/>
+              <y:Fill color="#FFCC00" transparent="false"/>
+              <y:BorderStyle color="#000000" raised="false" type="line" width="1.0"/>
+              <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="27.337890625" x="1.3310546875" y="5.6494140625">Item<y:LabelModel>
+                  <y:SmartNodeLabelModel distance="4.0"/>
+                </y:LabelModel>
+                <y:ModelParameter>
+                  <y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
+                </y:ModelParameter>
+              </y:NodeLabel>
+              <y:Shape type="ellipse"/>
+            </y:ShapeNode>
+          </data>
+        </node>
+        <node id="n0::n2">
+          <data key="d6">
+            <y:ShapeNode>
+              <y:Geometry height="30.0" width="30.0" x="860.5" y="173.701171875"/>
+              <y:Fill color="#FFCC00" transparent="false"/>
+              <y:BorderStyle color="#000000" raised="false" type="line" width="1.0"/>
+              <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="27.337890625" x="1.3310546875" y="5.6494140625">Item<y:LabelModel>
+                  <y:SmartNodeLabelModel distance="4.0"/>
+                </y:LabelModel>
+                <y:ModelParameter>
+                  <y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
+                </y:ModelParameter>
+              </y:NodeLabel>
+              <y:Shape type="ellipse"/>
+            </y:ShapeNode>
+          </data>
+        </node>
+        <node id="n0::n3">
+          <data key="d6">
+            <y:ShapeNode>
+              <y:Geometry height="30.0" width="30.0" x="1000.5" y="243.701171875"/>
+              <y:Fill color="#FFCC00" transparent="false"/>
+              <y:BorderStyle color="#000000" raised="false" type="line" width="1.0"/>
+              <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="27.337890625" x="1.3310546875" y="5.6494140625">Item<y:LabelModel>
+                  <y:SmartNodeLabelModel distance="4.0"/>
+                </y:LabelModel>
+                <y:ModelParameter>
+                  <y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
+                </y:ModelParameter>
+              </y:NodeLabel>
+              <y:Shape type="ellipse"/>
+            </y:ShapeNode>
+          </data>
+        </node>
+        <node id="n0::n4">
+          <data key="d6">
+            <y:ShapeNode>
+              <y:Geometry height="30.0" width="30.0" x="1000.5" y="173.701171875"/>
+              <y:Fill color="#FFCC00" transparent="false"/>
+              <y:BorderStyle color="#000000" raised="false" type="line" width="1.0"/>
+              <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="27.337890625" x="1.3310546875" y="5.6494140625">Item<y:LabelModel>
+                  <y:SmartNodeLabelModel distance="4.0"/>
+                </y:LabelModel>
+                <y:ModelParameter>
+                  <y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
+                </y:ModelParameter>
+              </y:NodeLabel>
+              <y:Shape type="ellipse"/>
+            </y:ShapeNode>
+          </data>
+        </node>
+        <node id="n0::n5">
+          <data key="d6">
+            <y:ShapeNode>
+              <y:Geometry height="30.0" width="30.0" x="795.7189531249999" y="243.701171875"/>
+              <y:Fill color="#FFCC00" transparent="false"/>
+              <y:BorderStyle color="#000000" raised="false" type="line" width="1.0"/>
+              <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="27.337890625" x="1.3310546875" y="5.6494140625">Item<y:LabelModel>
+                  <y:SmartNodeLabelModel distance="4.0"/>
+                </y:LabelModel>
+                <y:ModelParameter>
+                  <y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
+                </y:ModelParameter>
+              </y:NodeLabel>
+              <y:Shape type="ellipse"/>
+            </y:ShapeNode>
+          </data>
+        </node>
+        <node id="n0::n6">
+          <data key="d6">
+            <y:ShapeNode>
+              <y:Geometry height="30.0" width="96.59199999999987" x="1058.7425234375003" y="108.6015625"/>
+              <y:Fill color="#FFCC00" transparent="false"/>
+              <y:BorderStyle color="#000000" raised="false" type="line" width="1.0"/>
+              <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="81.373046875" x="7.609476562500049" y="5.6494140625">Virtual folder 3<y:LabelModel>
+                  <y:SmartNodeLabelModel distance="4.0"/>
+                </y:LabelModel>
+                <y:ModelParameter>
+                  <y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
+                </y:ModelParameter>
+              </y:NodeLabel>
+              <y:Shape type="rectangle"/>
+            </y:ShapeNode>
+          </data>
+        </node>
+        <node id="n0::n7">
+          <data key="d6">
+            <y:ShapeNode>
+              <y:Geometry height="30.0" width="30.0" x="725.7189531249999" y="243.701171875"/>
+              <y:Fill color="#FFCC00" transparent="false"/>
+              <y:BorderStyle color="#000000" raised="false" type="line" width="1.0"/>
+              <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="27.337890625" x="1.3310546875" y="5.6494140625">Item<y:LabelModel>
+                  <y:SmartNodeLabelModel distance="4.0"/>
+                </y:LabelModel>
+                <y:ModelParameter>
+                  <y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
+                </y:ModelParameter>
+              </y:NodeLabel>
+              <y:Shape type="ellipse"/>
+            </y:ShapeNode>
+          </data>
+        </node>
+        <node id="n0::n8">
+          <data key="d6">
+            <y:ShapeNode>
+              <y:Geometry height="30.0" width="30.0" x="1092.0385234375" y="173.701171875"/>
+              <y:Fill color="#FFCC00" transparent="false"/>
+              <y:BorderStyle color="#000000" raised="false" type="line" width="1.0"/>
+              <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="27.337890625" x="1.3310546875" y="5.6494140625">Item<y:LabelModel>
+                  <y:SmartNodeLabelModel distance="4.0"/>
+                </y:LabelModel>
+                <y:ModelParameter>
+                  <y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
+                </y:ModelParameter>
+              </y:NodeLabel>
+              <y:Shape type="ellipse"/>
+            </y:ShapeNode>
+          </data>
+        </node>
+        <node id="n0::n9">
+          <data key="d6">
+            <y:ShapeNode>
+              <y:Geometry height="30.0" width="96.59199999999987" x="897.2040000000001" y="103.701171875"/>
+              <y:Fill color="#FFCC00" transparent="false"/>
+              <y:BorderStyle color="#000000" raised="false" type="line" width="1.0"/>
+              <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="81.373046875" x="7.609476562499935" y="5.6494140625">Virtual folder 2<y:LabelModel>
+                  <y:SmartNodeLabelModel distance="4.0"/>
+                </y:LabelModel>
+                <y:ModelParameter>
+                  <y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
+                </y:ModelParameter>
+              </y:NodeLabel>
+              <y:Shape type="rectangle"/>
+            </y:ShapeNode>
+          </data>
+        </node>
+        <node id="n0::n10">
+          <data key="d6">
+            <y:ShapeNode>
+              <y:Geometry height="30.0" width="30.0" x="930.5" y="33.701171875"/>
+              <y:Fill color="#33CCCC" transparent="false"/>
+              <y:BorderStyle color="#000000" raised="false" type="dashed" width="1.0"/>
+              <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="14.669921875" x="7.6650390625" y="5.6494140625">-1<y:LabelModel>
+                  <y:SmartNodeLabelModel distance="4.0"/>
+                </y:LabelModel>
+                <y:ModelParameter>
+                  <y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
+                </y:ModelParameter>
+              </y:NodeLabel>
+              <y:Shape type="rectangle"/>
+            </y:ShapeNode>
+          </data>
+        </node>
+        <node id="n0::n11">
+          <data key="d6">
+            <y:ShapeNode>
+              <y:Geometry height="30.0" width="30.0" x="930.5" y="173.701171875"/>
+              <y:Fill color="#FFCC00" transparent="false"/>
+              <y:BorderStyle color="#000000" raised="false" type="line" width="1.0"/>
+              <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="27.337890625" x="1.3310546875" y="5.6494140625">Item<y:LabelModel>
+                  <y:SmartNodeLabelModel distance="4.0"/>
+                </y:LabelModel>
+                <y:ModelParameter>
+                  <y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
+                </y:ModelParameter>
+              </y:NodeLabel>
+              <y:Shape type="ellipse"/>
+            </y:ShapeNode>
+          </data>
+        </node>
+        <node id="n0::n12">
+          <data key="d6">
+            <y:ShapeNode>
+              <y:Geometry height="30.0" width="96.59199999999987" x="719.4689531249999" y="103.701171875"/>
+              <y:Fill color="#FFCC00" transparent="false"/>
+              <y:BorderStyle color="#000000" raised="false" type="line" width="1.0"/>
+              <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="81.373046875" x="7.609476562499935" y="5.6494140625">Virtual folder 1<y:LabelModel>
+                  <y:SmartNodeLabelModel distance="4.0"/>
+                </y:LabelModel>
+                <y:ModelParameter>
+                  <y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
+                </y:ModelParameter>
+              </y:NodeLabel>
+              <y:Shape type="rectangle"/>
+            </y:ShapeNode>
+          </data>
+        </node>
+      </graph>
+    </node>
+    <node id="n1" yfiles.foldertype="group">
+      <data key="d6">
+        <y:ProxyAutoBoundsNode>
+          <y:Realizers active="0">
+            <y:GenericGroupNode configuration="PanelNode">
+              <y:Geometry height="290.6015625" width="379.77599999999984" x="1205.2810468750001" y="0.0"/>
+              <y:Fill color="#68B0E3" transparent="false"/>
+              <y:BorderStyle hasColor="false" type="line" width="1.0"/>
+              <y:NodeLabel alignment="right" autoSizePolicy="node_width" borderDistance="0.0" fontFamily="Dialog" fontSize="16" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="23.6015625" horizontalTextPosition="center" iconTextGap="4" modelName="internal" modelPosition="t" textColor="#FFFFFF" verticalTextPosition="bottom" visible="true" width="379.77599999999984" x="0.0" y="0.0">Группы пользователей - права доступа</y:NodeLabel>
+              <y:StyleProperties>
+                <y:Property class="java.awt.Color" name="headerBackground" value="#68b0e3"/>
+              </y:StyleProperties>
+              <y:State autoResize="true" closed="false" closedHeight="50.0" closedWidth="50.0"/>
+              <y:Insets bottom="15" bottomF="15.0" left="15" leftF="15.0" right="15" rightF="15.0" top="15" topF="15.0"/>
+              <y:BorderInsets bottom="0" bottomF="0.0" left="0" leftF="0.0" right="0" rightF="0.0" top="0" topF="0.0"/>
+            </y:GenericGroupNode>
+            <y:GenericGroupNode configuration="PanelNode">
+              <y:Geometry height="53.6015625" width="50.0" x="640.5999999999999" y="-91.5"/>
+              <y:Fill color="#68B0E3" transparent="false"/>
+              <y:BorderStyle hasColor="false" type="line" width="1.0"/>
+              <y:NodeLabel alignment="right" autoSizePolicy="node_width" borderDistance="0.0" fontFamily="Dialog" fontSize="16" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="23.6015625" horizontalTextPosition="center" iconTextGap="4" modelName="internal" modelPosition="t" textColor="#FFFFFF" verticalTextPosition="bottom" visible="true" width="50.0" x="0.0" y="0.0">4</y:NodeLabel>
+              <y:StyleProperties>
+                <y:Property class="java.awt.Color" name="headerBackground" value="#68b0e3"/>
+              </y:StyleProperties>
+              <y:State autoResize="true" closed="false" closedHeight="50.0" closedWidth="50.0"/>
+              <y:Insets bottom="15" bottomF="15.0" left="15" leftF="15.0" right="15" rightF="15.0" top="15" topF="15.0"/>
+              <y:BorderInsets bottom="0" bottomF="0.0" left="0" leftF="0.0" right="0" rightF="0.0" top="0" topF="0.0"/>
+            </y:GenericGroupNode>
+          </y:Realizers>
+        </y:ProxyAutoBoundsNode>
+      </data>
+      <graph edgedefault="directed" id="n1:">
+        <node id="n1::n0">
+          <data key="d6">
+            <y:ShapeNode>
+              <y:Geometry height="30.0" width="96.59199999999987" x="1473.4650468749999" y="108.6015625"/>
+              <y:Fill color="#FFCC00" transparent="false"/>
+              <y:BorderStyle color="#000000" raised="false" type="line" width="1.0"/>
+              <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="81.373046875" x="7.609476562500049" y="5.6494140625">Virtual folder 3<y:LabelModel>
+                  <y:SmartNodeLabelModel distance="4.0"/>
+                </y:LabelModel>
+                <y:ModelParameter>
+                  <y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
+                </y:ModelParameter>
+              </y:NodeLabel>
+              <y:Shape type="rectangle"/>
+            </y:ShapeNode>
+          </data>
+        </node>
+        <node id="n1::n1">
+          <data key="d6">
+            <y:ShapeNode>
+              <y:Geometry height="30.0" width="30.0" x="1380.1690468749998" y="38.6015625"/>
+              <y:Fill color="#33CCCC" transparent="false"/>
+              <y:BorderStyle color="#000000" raised="false" type="dashed" width="1.0"/>
+              <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="14.669921875" x="7.6650390625" y="5.6494140625">-1<y:LabelModel>
+                  <y:SmartNodeLabelModel distance="4.0"/>
+                </y:LabelModel>
+                <y:ModelParameter>
+                  <y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
+                </y:ModelParameter>
+              </y:NodeLabel>
+              <y:Shape type="rectangle"/>
+            </y:ShapeNode>
+          </data>
+        </node>
+        <node id="n1::n2">
+          <data key="d6">
+            <y:ShapeNode>
+              <y:Geometry height="30.0" width="96.59199999999987" x="1346.873046875" y="108.6015625"/>
+              <y:Fill color="#FFCC00" transparent="false"/>
+              <y:BorderStyle color="#000000" raised="false" type="line" width="1.0"/>
+              <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="81.373046875" x="7.609476562499822" y="5.6494140625">Virtual folder 2<y:LabelModel>
+                  <y:SmartNodeLabelModel distance="4.0"/>
+                </y:LabelModel>
+                <y:ModelParameter>
+                  <y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
+                </y:ModelParameter>
+              </y:NodeLabel>
+              <y:Shape type="rectangle"/>
+            </y:ShapeNode>
+          </data>
+        </node>
+        <node id="n1::n3">
+          <data key="d6">
+            <y:ShapeNode>
+              <y:Geometry height="30.0" width="96.59199999999987" x="1220.2810468750001" y="108.6015625"/>
+              <y:Fill color="#FFCC00" transparent="false"/>
+              <y:BorderStyle color="#000000" raised="false" type="line" width="1.0"/>
+              <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="81.373046875" x="7.609476562500049" y="5.6494140625">Virtual folder 1<y:LabelModel>
+                  <y:SmartNodeLabelModel distance="4.0"/>
+                </y:LabelModel>
+                <y:ModelParameter>
+                  <y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
+                </y:ModelParameter>
+              </y:NodeLabel>
+              <y:Shape type="rectangle"/>
+            </y:ShapeNode>
+          </data>
+        </node>
+        <node id="n1::n4">
+          <data key="d6">
+            <y:ShapeNode>
+              <y:Geometry height="54.0" width="96.59199999999987" x="1473.465046875" y="156.6015625"/>
+              <y:Fill color="#FFCC00" transparent="false"/>
+              <y:BorderStyle color="#000000" raised="false" type="line" width="1.0"/>
+              <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="63.349609375" x="16.62119531249982" y="17.6494140625">Permission<y:LabelModel>
+                  <y:SmartNodeLabelModel distance="4.0"/>
+                </y:LabelModel>
+                <y:ModelParameter>
+                  <y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
+                </y:ModelParameter>
+              </y:NodeLabel>
+              <y:Shape type="star6"/>
+            </y:ShapeNode>
+          </data>
+        </node>
+        <node id="n1::n5">
+          <data key="d6">
+            <y:ShapeNode>
+              <y:Geometry height="54.0" width="96.59199999999987" x="1220.2810468750004" y="161.701171875"/>
+              <y:Fill color="#FFCC00" transparent="false"/>
+              <y:BorderStyle color="#000000" raised="false" type="line" width="1.0"/>
+              <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="63.349609375" x="16.62119531249982" y="17.6494140625">Permission<y:LabelModel>
+                  <y:SmartNodeLabelModel distance="4.0"/>
+                </y:LabelModel>
+                <y:ModelParameter>
+                  <y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
+                </y:ModelParameter>
+              </y:NodeLabel>
+              <y:Shape type="star6"/>
+            </y:ShapeNode>
+          </data>
+        </node>
+        <node id="n1::n6">
+          <data key="d6">
+            <y:ShapeNode>
+              <y:Geometry height="54.0" width="96.59199999999987" x="1346.873046875" y="161.6015625"/>
+              <y:Fill color="#FFCC00" transparent="false"/>
+              <y:BorderStyle color="#000000" raised="false" type="line" width="1.0"/>
+              <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="63.349609375" x="16.62119531249982" y="17.6494140625">Permission<y:LabelModel>
+                  <y:SmartNodeLabelModel distance="4.0"/>
+                </y:LabelModel>
+                <y:ModelParameter>
+                  <y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
+                </y:ModelParameter>
+              </y:NodeLabel>
+              <y:Shape type="star6"/>
+            </y:ShapeNode>
+          </data>
+        </node>
+        <node id="n1::n7">
+          <data key="d6">
+            <y:ShapeNode>
+              <y:Geometry height="30.0" width="55.0" x="1367.6690468749998" y="245.6015625"/>
+              <y:Fill color="#FFCC00" transparent="false"/>
+              <y:BorderStyle color="#000000" raised="false" type="line" width="1.0"/>
+              <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="37.3515625" x="8.82421875" y="5.6494140625">Group<y:LabelModel>
+                  <y:SmartNodeLabelModel distance="4.0"/>
+                </y:LabelModel>
+                <y:ModelParameter>
+                  <y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
+                </y:ModelParameter>
+              </y:NodeLabel>
+              <y:Shape type="roundrectangle"/>
+            </y:ShapeNode>
+          </data>
+        </node>
+      </graph>
+    </node>
+    <edge id="n1::e0" source="n1::n7" target="n1::n5">
+      <data key="d10">
+        <y:PolyLineEdge>
+          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
+          <y:LineStyle color="#000000" type="line" width="1.0"/>
+          <y:Arrows source="none" target="standard"/>
+          <y:BendStyle smoothed="false"/>
+        </y:PolyLineEdge>
+      </data>
+    </edge>
+    <edge id="n1::e1" source="n1::n7" target="n1::n4">
+      <data key="d10">
+        <y:PolyLineEdge>
+          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
+          <y:LineStyle color="#000000" type="line" width="1.0"/>
+          <y:Arrows source="none" target="standard"/>
+          <y:BendStyle smoothed="false"/>
+        </y:PolyLineEdge>
+      </data>
+    </edge>
+    <edge id="n1::e2" source="n1::n1" target="n1::n3">
+      <data key="d10">
+        <y:PolyLineEdge>
+          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
+          <y:LineStyle color="#000000" type="line" width="1.0"/>
+          <y:Arrows source="none" target="standard"/>
+          <y:BendStyle smoothed="false"/>
+        </y:PolyLineEdge>
+      </data>
+    </edge>
+    <edge id="n1::e3" source="n1::n1" target="n1::n2">
+      <data key="d10">
+        <y:PolyLineEdge>
+          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
+          <y:LineStyle color="#000000" type="line" width="1.0"/>
+          <y:Arrows source="none" target="standard"/>
+          <y:BendStyle smoothed="false"/>
+        </y:PolyLineEdge>
+      </data>
+    </edge>
+    <edge id="n1::e4" source="n1::n1" target="n1::n0">
+      <data key="d10">
+        <y:PolyLineEdge>
+          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
+          <y:LineStyle color="#000000" type="line" width="1.0"/>
+          <y:Arrows source="none" target="standard"/>
+          <y:BendStyle smoothed="false"/>
+        </y:PolyLineEdge>
+      </data>
+    </edge>
+    <edge id="n1::e5" source="n1::n6" target="n1::n2">
+      <data key="d10">
+        <y:PolyLineEdge>
+          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
+          <y:LineStyle color="#000000" type="line" width="1.0"/>
+          <y:Arrows source="none" target="standard"/>
+          <y:BendStyle smoothed="false"/>
+        </y:PolyLineEdge>
+      </data>
+    </edge>
+    <edge id="n1::e6" source="n1::n4" target="n1::n0">
+      <data key="d10">
+        <y:PolyLineEdge>
+          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
+          <y:LineStyle color="#000000" type="line" width="1.0"/>
+          <y:Arrows source="none" target="standard"/>
+          <y:BendStyle smoothed="false"/>
+        </y:PolyLineEdge>
+      </data>
+    </edge>
+    <edge id="n1::e7" source="n1::n5" target="n1::n3">
+      <data key="d10">
+        <y:PolyLineEdge>
+          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
+          <y:LineStyle color="#000000" type="line" width="1.0"/>
+          <y:Arrows source="none" target="standard"/>
+          <y:BendStyle smoothed="false"/>
+        </y:PolyLineEdge>
+      </data>
+    </edge>
+    <edge id="n1::e8" source="n1::n7" target="n1::n6">
+      <data key="d10">
+        <y:PolyLineEdge>
+          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
+          <y:LineStyle color="#000000" type="line" width="1.0"/>
+          <y:Arrows source="none" target="standard"/>
+          <y:BendStyle smoothed="false"/>
+        </y:PolyLineEdge>
+      </data>
+    </edge>
+    <edge id="n0::e0" source="n0::n1" target="n0::n7">
+      <data key="d10">
+        <y:PolyLineEdge>
+          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
+          <y:LineStyle color="#000000" type="line" width="1.0"/>
+          <y:Arrows source="none" target="standard"/>
+          <y:BendStyle smoothed="false"/>
+        </y:PolyLineEdge>
+      </data>
+    </edge>
+    <edge id="n0::e1" source="n0::n1" target="n0::n5">
+      <data key="d10">
+        <y:PolyLineEdge>
+          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
+          <y:LineStyle color="#000000" type="line" width="1.0"/>
+          <y:Arrows source="none" target="standard"/>
+          <y:BendStyle smoothed="false"/>
+        </y:PolyLineEdge>
+      </data>
+    </edge>
+    <edge id="n0::e2" source="n0::n4" target="n0::n3">
+      <data key="d10">
+        <y:PolyLineEdge>
+          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
+          <y:LineStyle color="#000000" type="line" width="1.0"/>
+          <y:Arrows source="none" target="standard"/>
+          <y:BendStyle smoothed="false"/>
+        </y:PolyLineEdge>
+      </data>
+    </edge>
+    <edge id="n0::e3" source="n0::n6" target="n0::n8">
+      <data key="d10">
+        <y:PolyLineEdge>
+          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
+          <y:LineStyle color="#000000" type="line" width="1.0"/>
+          <y:Arrows source="none" target="standard"/>
+          <y:BendStyle smoothed="false"/>
+        </y:PolyLineEdge>
+      </data>
+    </edge>
+    <edge id="n0::e4" source="n0::n9" target="n0::n2">
+      <data key="d10">
+        <y:PolyLineEdge>
+          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
+          <y:LineStyle color="#000000" type="line" width="1.0"/>
+          <y:Arrows source="none" target="standard"/>
+          <y:BendStyle smoothed="false"/>
+        </y:PolyLineEdge>
+      </data>
+    </edge>
+    <edge id="n0::e5" source="n0::n9" target="n0::n11">
+      <data key="d10">
+        <y:PolyLineEdge>
+          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
+          <y:LineStyle color="#000000" type="line" width="1.0"/>
+          <y:Arrows source="none" target="standard"/>
+          <y:BendStyle smoothed="false"/>
+        </y:PolyLineEdge>
+      </data>
+    </edge>
+    <edge id="n0::e6" source="n0::n9" target="n0::n4">
+      <data key="d10">
+        <y:PolyLineEdge>
+          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
+          <y:LineStyle color="#000000" type="line" width="1.0"/>
+          <y:Arrows source="none" target="standard"/>
+          <y:BendStyle smoothed="false"/>
+        </y:PolyLineEdge>
+      </data>
+    </edge>
+    <edge id="n0::e7" source="n0::n10" target="n0::n12">
+      <data key="d10">
+        <y:PolyLineEdge>
+          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
+          <y:LineStyle color="#000000" type="line" width="1.0"/>
+          <y:Arrows source="none" target="standard"/>
+          <y:BendStyle smoothed="false"/>
+        </y:PolyLineEdge>
+      </data>
+    </edge>
+    <edge id="n0::e8" source="n0::n10" target="n0::n9">
+      <data key="d10">
+        <y:PolyLineEdge>
+          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
+          <y:LineStyle color="#000000" type="line" width="1.0"/>
+          <y:Arrows source="none" target="standard"/>
+          <y:BendStyle smoothed="false"/>
+        </y:PolyLineEdge>
+      </data>
+    </edge>
+    <edge id="n0::e9" source="n0::n10" target="n0::n6">
+      <data key="d10">
+        <y:PolyLineEdge>
+          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
+          <y:LineStyle color="#000000" type="line" width="1.0"/>
+          <y:Arrows source="none" target="standard"/>
+          <y:BendStyle smoothed="false"/>
+        </y:PolyLineEdge>
+      </data>
+    </edge>
+    <edge id="n0::e10" source="n0::n12" target="n0::n0">
+      <data key="d10">
+        <y:PolyLineEdge>
+          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
+          <y:LineStyle color="#000000" type="line" width="1.0"/>
+          <y:Arrows source="none" target="standard"/>
+          <y:BendStyle smoothed="false"/>
+        </y:PolyLineEdge>
+      </data>
+    </edge>
+    <edge id="n0::e11" source="n0::n12" target="n0::n1">
+      <data key="d10">
+        <y:PolyLineEdge>
+          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
+          <y:LineStyle color="#000000" type="line" width="1.0"/>
+          <y:Arrows source="none" target="standard"/>
+          <y:BendStyle smoothed="false"/>
+        </y:PolyLineEdge>
+      </data>
+    </edge>
+  </graph>
+  <data key="d7">
+    <y:Resources/>
+  </data>
+</graphml>