- Confirm Password:
+ Confirm:
@@ -142,7 +142,7 @@
private void SetIntegratedSecurity(ChangeEventArgs e)
{
- if (Convert.ToBoolean(e.Value))
+ if (Convert.ToBoolean((string)e.Value))
{
IntegratedSecurityDisplay = "display: none;";
}
@@ -183,7 +183,7 @@
Site site = new Site();
site.TenantId = -1; // will be populated on server
site.Name = "Default Site";
- site.Logo = "oqtane.png";
+ site.LogoFileId = null;
site.DefaultThemeType = Constants.DefaultTheme;
site.DefaultLayoutType = Constants.DefaultLayout;
site.DefaultContainerType = Constants.DefaultContainer;
diff --git a/Oqtane.Client/Shared/Interop.cs b/Oqtane.Client/Shared/Interop.cs
index f5bc53cc..0a21512b 100644
--- a/Oqtane.Client/Shared/Interop.cs
+++ b/Oqtane.Client/Shared/Interop.cs
@@ -87,13 +87,13 @@ namespace Oqtane.Shared
}
}
- public ValueTask GetFiles(string name)
+ public ValueTask GetFiles(string id)
{
try
{
return jsRuntime.InvokeAsync(
"interop.getFiles",
- name);
+ id);
}
catch
{
@@ -101,13 +101,13 @@ namespace Oqtane.Shared
}
}
- public Task UploadFiles(string posturl, string folder, string name)
+ public Task UploadFiles(string posturl, string folder, string id)
{
try
{
jsRuntime.InvokeAsync(
"interop.uploadFiles",
- posturl, folder, name);
+ posturl, folder, id);
return Task.CompletedTask;
}
catch
diff --git a/Oqtane.Client/Startup.cs b/Oqtane.Client/Startup.cs
index b5c57b17..817e36fa 100644
--- a/Oqtane.Client/Startup.cs
+++ b/Oqtane.Client/Startup.cs
@@ -51,12 +51,13 @@ namespace Oqtane.Client
services.AddScoped();
services.AddScoped();
services.AddScoped();
- services.AddScoped();
services.AddScoped();
services.AddScoped();
services.AddScoped();
services.AddScoped();
services.AddScoped();
+ services.AddScoped();
+ services.AddScoped();
// dynamically register module contexts and repository services
Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
diff --git a/Oqtane.Client/Themes/Controls/ControlPanel.razor b/Oqtane.Client/Themes/Controls/ControlPanel.razor
index 3747108b..9a5e2198 100644
--- a/Oqtane.Client/Themes/Controls/ControlPanel.razor
+++ b/Oqtane.Client/Themes/Controls/ControlPanel.razor
@@ -263,7 +263,7 @@
}
else
{
- moduledefinitions = PageState.ModuleDefinitions.Where(item => item.Categories.Contains(e.Value.ToString())).ToList();
+ moduledefinitions = PageState.ModuleDefinitions.Where(item => item.Categories.Contains(category)).ToList();
}
moduledefinitionname = "-";
StateHasChanged();
diff --git a/Oqtane.Client/Themes/Controls/Logo.razor b/Oqtane.Client/Themes/Controls/Logo.razor
index 00ab7f89..afe78f5e 100644
--- a/Oqtane.Client/Themes/Controls/Logo.razor
+++ b/Oqtane.Client/Themes/Controls/Logo.razor
@@ -9,10 +9,10 @@
protected override void OnParametersSet()
{
- if (PageState.Site.Logo != "")
+ if (PageState.Site.LogoFileId != null)
{
Uri uri = new Uri(NavigationManager.Uri);
- logo = " ";
+ logo = " ";
}
}
}
\ No newline at end of file
diff --git a/Oqtane.Client/Themes/ThemeControlBase.cs b/Oqtane.Client/Themes/ThemeControlBase.cs
index 014cd5b6..6e3777dc 100644
--- a/Oqtane.Client/Themes/ThemeControlBase.cs
+++ b/Oqtane.Client/Themes/ThemeControlBase.cs
@@ -52,5 +52,16 @@ namespace Oqtane.Themes
{
return Utilities.EditUrl(PageState.Alias.Path, path, moduleid, action, parameters);
}
+
+ public string ContentUrl(int fileid)
+ {
+ string apiurl = PageState.Uri.Scheme + "://" + PageState.Alias.Name + "/";
+ if (PageState.Alias.Path == "")
+ {
+ apiurl += "~/";
+ }
+ apiurl += "api/File/Download/" + fileid.ToString();
+ return apiurl;
+ }
}
}
diff --git a/Oqtane.Client/wwwroot/js/interop.js b/Oqtane.Client/wwwroot/js/interop.js
index 96ddf060..f2a2421f 100644
--- a/Oqtane.Client/wwwroot/js/interop.js
+++ b/Oqtane.Client/wwwroot/js/interop.js
@@ -62,9 +62,9 @@ window.interop = {
document.body.appendChild(form);
form.submit();
},
- getFiles: function (name) {
+ getFiles: function (id) {
var files = [];
- var fileinput = document.getElementById(name);
+ var fileinput = document.getElementById(id);
if (fileinput !== null) {
for (var i = 0; i < fileinput.files.length; i++) {
files.push(fileinput.files[i].name);
@@ -72,10 +72,10 @@ window.interop = {
}
return files;
},
- uploadFiles: function (posturl, folder, name) {
- var files = document.getElementById(name + 'FileInput').files;
- var progressinfo = document.getElementById(name + 'ProgressInfo');
- var progressbar = document.getElementById(name + 'ProgressBar');
+ uploadFiles: function (posturl, folder, id) {
+ var files = document.getElementById(id + 'FileInput').files;
+ var progressinfo = document.getElementById(id + 'ProgressInfo');
+ var progressbar = document.getElementById(id + 'ProgressBar');
var filename = '';
for (var i = 0; i < files.length; i++) {
diff --git a/Oqtane.Server/wwwroot/Tenants/1/Sites/1/oqtane.png b/Oqtane.Server/Content/Tenants/1/Sites/1/logo.png
similarity index 100%
rename from Oqtane.Server/wwwroot/Tenants/1/Sites/1/oqtane.png
rename to Oqtane.Server/Content/Tenants/1/Sites/1/logo.png
diff --git a/Oqtane.Server/Controllers/FileController.cs b/Oqtane.Server/Controllers/FileController.cs
index 72bf7bcb..eeea4998 100644
--- a/Oqtane.Server/Controllers/FileController.cs
+++ b/Oqtane.Server/Controllers/FileController.cs
@@ -3,12 +3,16 @@ using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Oqtane.Infrastructure;
+using Oqtane.Repository;
+using Oqtane.Models;
using Oqtane.Shared;
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
+using Oqtane.Security;
+using System.Linq;
namespace Oqtane.Controllers
{
@@ -16,53 +20,163 @@ namespace Oqtane.Controllers
public class FileController : Controller
{
private readonly IWebHostEnvironment environment;
+ private readonly IFileRepository Files;
+ private readonly IFolderRepository Folders;
+ private readonly IUserPermissions UserPermissions;
+ private readonly ITenantResolver Tenants;
private readonly ILogManager logger;
private readonly string WhiteList = "jpg,jpeg,jpe,gif,bmp,png,mov,wmv,avi,mp4,mp3,doc,docx,xls,xlsx,ppt,pptx,pdf,txt,zip,nupkg";
- public FileController(IWebHostEnvironment environment, ILogManager logger)
+ public FileController(IWebHostEnvironment environment, IFileRepository Files, IFolderRepository Folders, IUserPermissions UserPermissions, ITenantResolver Tenants, ILogManager logger)
{
this.environment = environment;
+ this.Files = Files;
+ this.Folders = Folders;
+ this.UserPermissions = UserPermissions;
+ this.Tenants = Tenants;
this.logger = logger;
}
// GET: api/?folder=x
[HttpGet]
- public IEnumerable Get(string folder)
+ public IEnumerable Get(string folder)
{
- List files = new List();
- folder = GetFolder(folder);
- if (Directory.Exists(folder))
+ List files = new List();
+ int folderid;
+ if (int.TryParse(folder, out folderid))
{
- foreach (string file in Directory.GetFiles(folder))
+ Folder Folder = Folders.GetFolder(folderid);
+ if (Folder != null && UserPermissions.IsAuthorized(User, "Browse", Folder.Permissions))
{
- files.Add(Path.GetFileName(file));
+ files = Files.GetFiles(folderid).ToList();
+ }
+ }
+ else
+ {
+ if (User.IsInRole(Constants.HostRole))
+ {
+ folder = GetFolderPath(folder);
+ if (Directory.Exists(folder))
+ {
+ foreach (string file in Directory.GetFiles(folder))
+ {
+ files.Add(new Models.File { Name = Path.GetFileName(file), Extension = Path.GetExtension(file).Replace(".","") });
+ }
+ }
}
}
return files;
}
+ // GET api//5
+ [HttpGet("{id}")]
+ public Models.File Get(int id)
+ {
+ return Files.GetFile(id);
+ }
+
+ // PUT api//5
+ [HttpPut("{id}")]
+ [Authorize(Roles = Constants.RegisteredRole)]
+ public Models.File Put(int id, [FromBody] Models.File File)
+ {
+ if (ModelState.IsValid && UserPermissions.IsAuthorized(User, "Folder", File.Folder.FolderId, "Edit"))
+ {
+ File = Files.UpdateFile(File);
+ logger.Log(LogLevel.Information, this, LogFunction.Update, "File Updated {File}", File);
+ }
+ return File;
+ }
+
+ // DELETE api//5
+ [HttpDelete("{id}")]
+ [Authorize(Roles = Constants.RegisteredRole)]
+ public void Delete(int id)
+ {
+ Models.File File = Files.GetFile(id);
+ if (UserPermissions.IsAuthorized(User, "Folder", File.Folder.FolderId, "Edit"))
+ {
+ Files.DeleteFile(id);
+
+ string filepath = Path.Combine(GetFolderPath(File.Folder) + File.Name);
+ if (System.IO.File.Exists(filepath))
+ {
+ System.IO.File.Delete(filepath);
+ }
+ logger.Log(LogLevel.Information, this, LogFunction.Delete, "File Deleted {File}", File);
+ }
+ }
+
+ // GET api//upload?url=x&folderid=y
+ [HttpGet("upload")]
+ public Models.File UploadFile(string url, string folderid)
+ {
+ Models.File file = null;
+ Folder folder = Folders.GetFolder(int.Parse(folderid));
+ if (folder != null && UserPermissions.IsAuthorized(User, "Edit", folder.Permissions))
+ {
+ string folderpath = GetFolderPath(folder);
+ CreateDirectory(folderpath);
+ string filename = url.Substring(url.LastIndexOf("/") + 1);
+ try
+ {
+ var client = new System.Net.WebClient();
+ client.DownloadFile(url, folderpath + filename);
+ FileInfo fileinfo = new FileInfo(folderpath + filename);
+ file = Files.AddFile(new Models.File { Name = filename, FolderId = folder.FolderId, Extension = fileinfo.Extension.Replace(".",""), Size = (int)fileinfo.Length });
+ }
+ catch
+ {
+ logger.Log(LogLevel.Error, this, LogFunction.Create, "File Could Not Be Downloaded From Url {Url}", url);
+ }
+ }
+ return file;
+ }
+
// POST api//upload
[HttpPost("upload")]
- [Authorize(Roles = Constants.AdminRole)]
public async Task UploadFile(string folder, IFormFile file)
{
if (file.Length > 0)
{
- folder = GetFolder(folder);
- if (!Directory.Exists(folder))
+ string folderpath = "";
+ int folderid = -1;
+ if (int.TryParse(folder, out folderid))
{
- Directory.CreateDirectory(folder);
+ Folder Folder = Folders.GetFolder(folderid);
+ if (Folder != null && UserPermissions.IsAuthorized(User, "Edit", Folder.Permissions))
+ {
+ folderpath = GetFolderPath(Folder);
+ }
}
- using (var stream = new FileStream(Path.Combine(folder, file.FileName), FileMode.Create))
+ else
{
- await file.CopyToAsync(stream);
+ if (User.IsInRole(Constants.HostRole))
+ {
+ folderpath = GetFolderPath(folder);
+ }
+ }
+ if (folderpath != "")
+ {
+ CreateDirectory(folderpath);
+ using (var stream = new FileStream(Path.Combine(folderpath, file.FileName), FileMode.Create))
+ {
+ await file.CopyToAsync(stream);
+ }
+ string upload = await MergeFile(folderpath, file.FileName);
+ if (upload != "" && folderid != -1)
+ {
+ FileInfo fileinfo = new FileInfo(folderpath + upload);
+ Files.AddFile(new Models.File { Name = upload, FolderId = folderid, Extension = fileinfo.Extension.Replace(".", ""), Size = (int)fileinfo.Length });
+ }
}
- await MergeFile(folder, file.FileName);
}
}
- private async Task MergeFile(string folder, string filename)
+ private async Task MergeFile(string folder, string filename)
{
+ string merged = "";
+
// parse the filename which is in the format of filename.ext.part_x_y
string token = ".part_";
string parts = Path.GetExtension(filename).Replace(token, ""); // returns "x_y"
@@ -112,6 +226,7 @@ namespace Oqtane.Controllers
System.IO.File.Move(Path.Combine(folder, filename + ".tmp"), Path.Combine(folder, filename));
logger.Log(LogLevel.Information, this, LogFunction.Create, "File Uploaded {File}", Path.Combine(folder, filename));
}
+ merged = filename;
}
}
@@ -125,6 +240,8 @@ namespace Oqtane.Controllers
System.IO.File.Delete(filepart);
}
}
+
+ return merged;
}
private bool CanAccessFiles(string[] files)
@@ -164,24 +281,47 @@ namespace Oqtane.Controllers
return canaccess;
}
- // DELETE api//?folder=x&file=y
- [HttpDelete]
- [Authorize(Roles = Constants.AdminRole)]
- public void Delete(string folder, string file)
+ // GET api//download/5
+ [HttpGet("download/{id}")]
+ public IActionResult Download(int id)
{
- file = Path.Combine(GetFolder(folder) + file);
- if (System.IO.File.Exists(file))
+ Models.File file = Files.GetFile(id);
+ if (file != null && UserPermissions.IsAuthorized(User, "View", file.Folder.Permissions))
{
- System.IO.File.Delete(file);
- logger.Log(LogLevel.Information, this, LogFunction.Delete, "File Deleted {File}", file);
+ byte[] filebytes = System.IO.File.ReadAllBytes(GetFolderPath(file.Folder) + file.Name);
+ return File(filebytes, "application/octet-stream", file.Name);
+ }
+ else
+ {
+ return NotFound();
}
}
- private string GetFolder(string folder)
+ private string GetFolderPath(Folder folder)
+ {
+ return environment.ContentRootPath + "\\Content\\Tenants\\" + Tenants.GetTenant().TenantId.ToString() + "\\Sites\\" + folder.SiteId.ToString() + "\\" + folder.Path;
+ }
+
+ private string GetFolderPath(string folder)
{
- folder = folder.Replace("/", "\\");
- if (folder.StartsWith("\\")) folder = folder.Substring(1);
return Path.Combine(environment.WebRootPath, folder);
}
+
+ private void CreateDirectory(string folderpath)
+ {
+ if (!Directory.Exists(folderpath))
+ {
+ string path = "";
+ string[] folders = folderpath.Split(new char[] { '\\' }, StringSplitOptions.RemoveEmptyEntries);
+ foreach (string folder in folders)
+ {
+ path += folder + "\\";
+ if (!Directory.Exists(path))
+ {
+ Directory.CreateDirectory(path);
+ }
+ }
+ }
+ }
}
}
\ No newline at end of file
diff --git a/Oqtane.Server/Controllers/FolderController.cs b/Oqtane.Server/Controllers/FolderController.cs
index 46bae326..2bc4bc90 100644
--- a/Oqtane.Server/Controllers/FolderController.cs
+++ b/Oqtane.Server/Controllers/FolderController.cs
@@ -52,6 +52,12 @@ namespace Oqtane.Controllers
{
if (ModelState.IsValid && UserPermissions.IsAuthorized(User, "Edit", Folder.Permissions))
{
+ Folder.Path = "";
+ if (string.IsNullOrEmpty(Folder.Path) && Folder.ParentId != null)
+ {
+ Folder parent = Folders.GetFolder(Folder.ParentId.Value);
+ Folder.Path = parent.Path + Folder.Name + "\\";
+ }
Folder = Folders.AddFolder(Folder);
logger.Log(LogLevel.Information, this, LogFunction.Create, "Folder Added {Folder}", Folder);
}
@@ -65,6 +71,12 @@ namespace Oqtane.Controllers
{
if (ModelState.IsValid && UserPermissions.IsAuthorized(User, "Folder", Folder.FolderId, "Edit"))
{
+ Folder.Path = "";
+ if (string.IsNullOrEmpty(Folder.Path) && Folder.ParentId != null)
+ {
+ Folder parent = Folders.GetFolder(Folder.ParentId.Value);
+ Folder.Path = parent.Path + Folder.Name + "\\";
+ }
Folder = Folders.UpdateFolder(Folder);
logger.Log(LogLevel.Information, this, LogFunction.Update, "Folder Updated {Folder}", Folder);
}
diff --git a/Oqtane.Server/Controllers/SiteController.cs b/Oqtane.Server/Controllers/SiteController.cs
index 6d220188..316a7ba3 100644
--- a/Oqtane.Server/Controllers/SiteController.cs
+++ b/Oqtane.Server/Controllers/SiteController.cs
@@ -62,11 +62,6 @@ namespace Oqtane.Controllers
if (authorized)
{
Site = Sites.AddSite(Site);
- string folder = environment.WebRootPath + "\\Tenants\\" + Tenants.GetTenant().TenantId.ToString() + "\\Sites\\" + Site.SiteId.ToString();
- if (!Directory.Exists(folder))
- {
- Directory.CreateDirectory(folder);
- }
logger.Log(LogLevel.Information, this, LogFunction.Create, "Site Added {Site}", Site);
}
}
diff --git a/Oqtane.Server/Controllers/UserController.cs b/Oqtane.Server/Controllers/UserController.cs
index 37038c9a..fb720264 100644
--- a/Oqtane.Server/Controllers/UserController.cs
+++ b/Oqtane.Server/Controllers/UserController.cs
@@ -26,9 +26,10 @@ namespace Oqtane.Controllers
private readonly SignInManager IdentitySignInManager;
private readonly ITenantResolver Tenants;
private readonly INotificationRepository Notifications;
+ private readonly IFolderRepository Folders;
private readonly ILogManager logger;
- public UserController(IUserRepository Users, IRoleRepository Roles, IUserRoleRepository UserRoles, UserManager IdentityUserManager, SignInManager IdentitySignInManager, ITenantResolver Tenants, INotificationRepository Notifications, ILogManager logger)
+ public UserController(IUserRepository Users, IRoleRepository Roles, IUserRoleRepository UserRoles, UserManager IdentityUserManager, SignInManager IdentitySignInManager, ITenantResolver Tenants, INotificationRepository Notifications, IFolderRepository Folders, ILogManager logger)
{
this.Users = Users;
this.Roles = Roles;
@@ -36,12 +37,14 @@ namespace Oqtane.Controllers
this.IdentityUserManager = IdentityUserManager;
this.IdentitySignInManager = IdentitySignInManager;
this.Tenants = Tenants;
+ this.Folders = Folders;
this.Notifications = Notifications;
this.logger = logger;
}
// GET: api/?siteid=x
[HttpGet]
+ [Authorize(Roles = Constants.AdminRole)]
public IEnumerable Get()
{
return Users.GetUsers();
@@ -98,6 +101,8 @@ namespace Oqtane.Controllers
var result = await IdentityUserManager.CreateAsync(identityuser, User.Password);
if (result.Succeeded)
{
+ User.LastLoginOn = null;
+ User.LastIPAddress = "";
user = Users.AddUser(User);
if (!verified)
{
@@ -128,6 +133,14 @@ namespace Oqtane.Controllers
userrole.ExpiryDate = null;
UserRoles.AddUserRole(userrole);
}
+
+ // add folder for user
+ Folder folder = Folders.GetFolder(User.SiteId, "Users\\");
+ if (folder != null)
+ {
+ Folders.AddFolder(new Folder { SiteId = folder.SiteId, ParentId = folder.FolderId, Name = "My Folder", Path = folder.Path + user.UserId.ToString() + "\\", Order = 1, IsSystem = true,
+ Permissions = "[{\"PermissionName\":\"Browse\",\"Permissions\":\"[" + user.UserId.ToString() + "]\"},{\"PermissionName\":\"View\",\"Permissions\":\"All Users\"},{\"PermissionName\":\"Edit\",\"Permissions\":\"[" + user.UserId.ToString() + "]\"}]" });
+ }
}
}
else
@@ -222,6 +235,9 @@ namespace Oqtane.Controllers
if (identityuser.EmailConfirmed)
{
user.IsAuthenticated = true;
+ user.LastLoginOn = DateTime.Now;
+ user.LastIPAddress = HttpContext.Connection.RemoteIpAddress.ToString();
+ Users.UpdateUser(user);
logger.Log(LogLevel.Information, this, LogFunction.Security, "User Login Successful {Username}", User.Username);
if (SetCookie)
{
diff --git a/Oqtane.Server/Repository/FileRepository.cs b/Oqtane.Server/Repository/FileRepository.cs
index 1b85840f..3d51b17d 100644
--- a/Oqtane.Server/Repository/FileRepository.cs
+++ b/Oqtane.Server/Repository/FileRepository.cs
@@ -18,8 +18,8 @@ namespace Oqtane.Repository
public IEnumerable GetFiles(int FolderId)
{
- IEnumerable permissions = Permissions.GetPermissions("Folder", FolderId);
- IEnumerable files = db.File.Where(item => item.FolderId == FolderId);
+ IEnumerable permissions = Permissions.GetPermissions("Folder", FolderId).ToList();
+ IEnumerable files = db.File.Where(item => item.FolderId == FolderId).Include(item => item.Folder);
foreach (File file in files)
{
file.Folder.Permissions = Permissions.EncodePermissions(FolderId, permissions);
@@ -43,10 +43,10 @@ namespace Oqtane.Repository
public File GetFile(int FileId)
{
- File file = db.File.Find(FileId);
+ File file = db.File.Where(item => item.FileId == FileId).Include(item => item.Folder).FirstOrDefault();
if (file != null)
{
- IEnumerable permissions = Permissions.GetPermissions("Folder", file.FolderId);
+ IEnumerable permissions = Permissions.GetPermissions("Folder", file.FolderId).ToList();
file.Folder.Permissions = Permissions.EncodePermissions(file.FolderId, permissions);
}
return file;
diff --git a/Oqtane.Server/Repository/FolderRepository.cs b/Oqtane.Server/Repository/FolderRepository.cs
index 577639b6..3eb81471 100644
--- a/Oqtane.Server/Repository/FolderRepository.cs
+++ b/Oqtane.Server/Repository/FolderRepository.cs
@@ -53,7 +53,18 @@ namespace Oqtane.Repository
Folder folder = db.Folder.Find(FolderId);
if (folder != null)
{
- IEnumerable permissions = Permissions.GetPermissions("Folder", folder.FolderId);
+ IEnumerable permissions = Permissions.GetPermissions("Folder", folder.FolderId).ToList();
+ folder.Permissions = Permissions.EncodePermissions(folder.FolderId, permissions);
+ }
+ return folder;
+ }
+
+ public Folder GetFolder(int SiteId, string Path)
+ {
+ Folder folder = db.Folder.Where(item => item.SiteId == SiteId && item.Path == Path).FirstOrDefault();
+ if (folder != null)
+ {
+ IEnumerable permissions = Permissions.GetPermissions("Folder", folder.FolderId).ToList();
folder.Permissions = Permissions.EncodePermissions(folder.FolderId, permissions);
}
return folder;
diff --git a/Oqtane.Server/Repository/Interfaces/IFolderRepository.cs b/Oqtane.Server/Repository/Interfaces/IFolderRepository.cs
index d5619331..0d809ef1 100644
--- a/Oqtane.Server/Repository/Interfaces/IFolderRepository.cs
+++ b/Oqtane.Server/Repository/Interfaces/IFolderRepository.cs
@@ -10,6 +10,7 @@ namespace Oqtane.Repository
Folder AddFolder(Folder Folder);
Folder UpdateFolder(Folder Folder);
Folder GetFolder(int FolderId);
+ Folder GetFolder(int SiteId, string Path);
void DeleteFolder(int FolderId);
}
}
diff --git a/Oqtane.Server/Repository/JobRepository.cs b/Oqtane.Server/Repository/JobRepository.cs
index 46ffaba4..6c390355 100644
--- a/Oqtane.Server/Repository/JobRepository.cs
+++ b/Oqtane.Server/Repository/JobRepository.cs
@@ -3,21 +3,28 @@ using System.Linq;
using Oqtane.Models;
using Microsoft.EntityFrameworkCore;
using System;
+using Microsoft.Extensions.Caching.Memory;
namespace Oqtane.Repository
{
public class JobRepository : IJobRepository
{
private MasterDBContext db;
+ private readonly IMemoryCache _cache;
- public JobRepository(MasterDBContext context)
+ public JobRepository(MasterDBContext context, IMemoryCache cache)
{
db = context;
+ _cache = cache;
}
public IEnumerable GetJobs()
{
- return db.Job.ToList();
+ return _cache.GetOrCreate("jobs", entry =>
+ {
+ entry.SlidingExpiration = TimeSpan.FromMinutes(30);
+ return db.Job.ToList();
+ });
}
public Job AddJob(Job Job)
diff --git a/Oqtane.Server/Repository/PageModuleRepository.cs b/Oqtane.Server/Repository/PageModuleRepository.cs
index 92ebb732..730d3c4c 100644
--- a/Oqtane.Server/Repository/PageModuleRepository.cs
+++ b/Oqtane.Server/Repository/PageModuleRepository.cs
@@ -56,7 +56,7 @@ namespace Oqtane.Repository
.SingleOrDefault(item => item.PageModuleId == PageModuleId);
if (pagemodule != null)
{
- IEnumerable permissions = Permissions.GetPermissions("Module", pagemodule.ModuleId);
+ IEnumerable permissions = Permissions.GetPermissions("Module", pagemodule.ModuleId).ToList();
pagemodule.Module.Permissions = Permissions.EncodePermissions(pagemodule.ModuleId, permissions);
}
return pagemodule;
@@ -68,7 +68,7 @@ namespace Oqtane.Repository
.SingleOrDefault(item => item.PageId == PageId && item.ModuleId == ModuleId);
if (pagemodule != null)
{
- IEnumerable permissions = Permissions.GetPermissions("Module", pagemodule.ModuleId);
+ IEnumerable permissions = Permissions.GetPermissions("Module", pagemodule.ModuleId).ToList();
pagemodule.Module.Permissions = Permissions.EncodePermissions(pagemodule.ModuleId, permissions);
}
return pagemodule;
diff --git a/Oqtane.Server/Repository/PageRepository.cs b/Oqtane.Server/Repository/PageRepository.cs
index 8ec9d1fd..6e4fc2ff 100644
--- a/Oqtane.Server/Repository/PageRepository.cs
+++ b/Oqtane.Server/Repository/PageRepository.cs
@@ -55,7 +55,7 @@ namespace Oqtane.Repository
Page page = db.Page.Find(PageId);
if (page != null)
{
- IEnumerable permissions = Permissions.GetPermissions("Page", page.PageId);
+ IEnumerable permissions = Permissions.GetPermissions("Page", page.PageId).ToList();
page.Permissions = Permissions.EncodePermissions(page.PageId, permissions);
}
return page;
@@ -73,7 +73,7 @@ namespace Oqtane.Repository
}
if (page != null)
{
- IEnumerable permissions = Permissions.GetPermissions("Page", page.PageId);
+ IEnumerable permissions = Permissions.GetPermissions("Page", page.PageId).ToList();
page.Permissions = Permissions.EncodePermissions(page.PageId, permissions);
}
}
diff --git a/Oqtane.Server/Repository/SiteRepository.cs b/Oqtane.Server/Repository/SiteRepository.cs
index c1233b5d..d206c763 100644
--- a/Oqtane.Server/Repository/SiteRepository.cs
+++ b/Oqtane.Server/Repository/SiteRepository.cs
@@ -15,6 +15,8 @@ namespace Oqtane.Repository
private readonly TenantDBContext db;
private readonly IRoleRepository RoleRepository;
private readonly IProfileRepository ProfileRepository;
+ private readonly IFolderRepository FolderRepository;
+ private readonly IFileRepository FileRepository;
private readonly IPageRepository PageRepository;
private readonly IModuleRepository ModuleRepository;
private readonly IPageModuleRepository PageModuleRepository;
@@ -22,11 +24,13 @@ namespace Oqtane.Repository
private readonly IServiceProvider ServiceProvider;
private readonly List SiteTemplate;
- public SiteRepository(TenantDBContext context, IRoleRepository RoleRepository, IProfileRepository ProfileRepository, IPageRepository PageRepository, IModuleRepository ModuleRepository, IPageModuleRepository PageModuleRepository, IModuleDefinitionRepository ModuleDefinitionRepository, IServiceProvider ServiceProvider)
+ public SiteRepository(TenantDBContext context, IRoleRepository RoleRepository, IProfileRepository ProfileRepository, IFolderRepository FolderRepository, IFileRepository FileRepository, IPageRepository PageRepository, IModuleRepository ModuleRepository, IPageModuleRepository PageModuleRepository, IModuleDefinitionRepository ModuleDefinitionRepository, IServiceProvider ServiceProvider)
{
db = context;
this.RoleRepository = RoleRepository;
this.ProfileRepository = ProfileRepository;
+ this.FolderRepository = FolderRepository;
+ this.FileRepository = FileRepository;
this.PageRepository = PageRepository;
this.ModuleRepository = ModuleRepository;
this.PageModuleRepository = PageModuleRepository;
@@ -40,7 +44,7 @@ namespace Oqtane.Repository
Content = "Oqtane is an open source modular application framework built from the ground up using modern .NET Core technology. It leverages the revolutionary new Blazor component model to create a fully dynamic web development experience which can be executed on a client or server. Whether you are looking for a platform to accelerate your web development efforts, or simply interested in exploring the anatomy of a large-scale Blazor application, Oqtane provides a solid foundation based on proven enterprise architectural principles.
" +
"Join Our Community Clone Our Repo
" +
"Blazor is a single-page app framework that lets you build interactive web applications using C# instead of JavaScript. Client-side Blazor relies on WebAssembly, an open web standard that does not require plugins or code transpilation in order to run natively in a web browser. Server-side Blazor uses SignalR to host your application on a web server and provide a responsive and robust debugging experience. Blazor applications works in all modern web browsers, including mobile browsers.
" +
- "Blazor is a feature of ASP.NET Core 3.0 , the popular cross platform web development framework from Microsoft that extends the .NET developer platform with tools and libraries for building web apps.
"
+ "Blazor is a feature of ASP.NET Core 3 , the popular cross platform web development framework from Microsoft that extends the .NET developer platform with tools and libraries for building web apps.
"
},
new PageTemplateModule { ModuleDefinitionName = "Oqtane.Modules.HtmlText, Oqtane.Client", Title = "MIT License", Pane = "Content", ModulePermissions = "[{\"PermissionName\":\"View\",\"Permissions\":\"All Users;Administrators\"},{\"PermissionName\":\"Edit\",\"Permissions\":\"Administrators\"}]",
Content = "Copyright (c) 2019 .NET Foundation
" +
@@ -168,6 +172,15 @@ namespace Oqtane.Repository
ProfileRepository.AddProfile(new Profile { SiteId = site.SiteId, Name = "PostalCode", Title = "Postal Code", Description = "Postal Code Or Zip Code", Category = "Address", ViewOrder = 7, MaxLength = 50, DefaultValue = "", IsRequired = false, IsPrivate = false });
ProfileRepository.AddProfile(new Profile { SiteId = site.SiteId, Name = "Phone", Title = "Phone Number", Description = "Phone Number", Category = "Contact", ViewOrder = 8, MaxLength = 50, DefaultValue = "", IsRequired = false, IsPrivate = false });
+ Folder folder = FolderRepository.AddFolder(new Folder { SiteId = site.SiteId, ParentId = null, Name = "Root", Path = "", Order = 1, IsSystem = true, Permissions = "[{\"PermissionName\":\"Browse\",\"Permissions\":\"Administrators\"},{\"PermissionName\":\"View\",\"Permissions\":\"All Users\"},{\"PermissionName\":\"Edit\",\"Permissions\":\"Administrators\"}]" });
+ FolderRepository.AddFolder(new Folder { SiteId = site.SiteId, ParentId = folder.FolderId, Name = "Users", Path = "Users\\", Order = 1, IsSystem = true, Permissions = "[{\"PermissionName\":\"Browse\",\"Permissions\":\"Administrators\"},{\"PermissionName\":\"View\",\"Permissions\":\"Administrators\"},{\"PermissionName\":\"Edit\",\"Permissions\":\"Administrators\"}]" });
+ if (site.Name == "Default Site")
+ {
+ File file = FileRepository.AddFile(new File { FolderId = folder.FolderId, Name = "logo.png", Extension = "png", Size = 8192 });
+ site.LogoFileId = file.FileId;
+ UpdateSite(site);
+ }
+
List moduledefinitions = ModuleDefinitionRepository.GetModuleDefinitions(site.SiteId).ToList();
foreach (PageTemplate pagetemplate in SiteTemplate)
{
diff --git a/Oqtane.Server/Scripts/00.00.00.sql b/Oqtane.Server/Scripts/00.00.00.sql
index 93dc05f7..29637d45 100644
--- a/Oqtane.Server/Scripts/00.00.00.sql
+++ b/Oqtane.Server/Scripts/00.00.00.sql
@@ -8,7 +8,7 @@ CREATE TABLE [dbo].[Site](
[SiteId] [int] IDENTITY(1,1) NOT NULL,
[TenantId] [int] NOT NULL,
[Name] [nvarchar](200) NOT NULL,
- [Logo] [nvarchar](50) NOT NULL,
+ [LogoFileId] [int] NULL,
[DefaultThemeType] [nvarchar](200) NOT NULL,
[DefaultLayoutType] [nvarchar](200) NOT NULL,
[DefaultContainerType] [nvarchar](200) NOT NULL,
@@ -96,6 +96,9 @@ CREATE TABLE [dbo].[User](
[Username] [nvarchar](256) NOT NULL,
[DisplayName] [nvarchar](50) NOT NULL,
[Email] [nvarchar](256) NOT NULL,
+ [PhotoFileId] [int] NULL,
+ [LastLoginOn] [datetime] NULL,
+ [LastIPAddress] [nvarchar](50) NOT NULL,
[CreatedBy] [nvarchar](256) NOT NULL,
[CreatedOn] [datetime] NOT NULL,
[ModifiedBy] [nvarchar](256) NOT NULL,
@@ -261,6 +264,7 @@ CREATE TABLE [dbo].[Folder](
[Name] [nvarchar](50) NOT NULL,
[ParentId] [int] NULL,
[Order] [int] NOT NULL,
+ [IsSystem] [bit] NOT NULL,
[CreatedBy] [nvarchar](256) NOT NULL,
[CreatedOn] [datetime] NOT NULL,
[ModifiedBy] [nvarchar](256) NOT NULL,
@@ -278,7 +282,9 @@ GO
CREATE TABLE [dbo].[File](
[FileId] [int] IDENTITY(1,1) NOT NULL,
[FolderId] [int] NOT NULL,
- [Name] [nvarchar](50) NOT NULL,
+ [Name] [nvarchar](250) NOT NULL,
+ [Extension] [nvarchar](50) NOT NULL,
+ [Size] [int] NOT NULL,
[CreatedBy] [nvarchar](256) NOT NULL,
[CreatedOn] [datetime] NOT NULL,
[ModifiedBy] [nvarchar](256) NOT NULL,
diff --git a/Oqtane.Server/Scripts/Master.sql b/Oqtane.Server/Scripts/Master.sql
index 0db09f12..45e474c7 100644
--- a/Oqtane.Server/Scripts/Master.sql
+++ b/Oqtane.Server/Scripts/Master.sql
@@ -139,7 +139,7 @@ GO
SET IDENTITY_INSERT [dbo].[Job] ON
GO
INSERT [dbo].[Job] ([JobId], [Name], [JobType], [Frequency], [Interval], [StartDate], [EndDate], [IsEnabled], [IsStarted], [IsExecuting], [NextExecution], [RetentionHistory], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn])
-VALUES (1, N'Notification Job', N'Oqtane.Infrastructure.NotificationJob, Oqtane.Server', N'm', 1, null, null, 1, 0, 0, null, 10, '', getdate(), '', getdate())
+VALUES (1, N'Notification Job', N'Oqtane.Infrastructure.NotificationJob, Oqtane.Server', N'm', 1, null, null, 0, 0, 0, null, 10, '', getdate(), '', getdate())
GO
SET IDENTITY_INSERT [dbo].[Job] OFF
GO
diff --git a/Oqtane.Server/Startup.cs b/Oqtane.Server/Startup.cs
index 3e65ec1c..2ea27dd4 100644
--- a/Oqtane.Server/Startup.cs
+++ b/Oqtane.Server/Startup.cs
@@ -82,6 +82,9 @@ namespace Oqtane.Server
options.AddPolicy("EditPage", policy => policy.Requirements.Add(new PermissionRequirement("Page", "Edit")));
options.AddPolicy("ViewModule", policy => policy.Requirements.Add(new PermissionRequirement("Module", "View")));
options.AddPolicy("EditModule", policy => policy.Requirements.Add(new PermissionRequirement("Module", "Edit")));
+ options.AddPolicy("ViewFolder", policy => policy.Requirements.Add(new PermissionRequirement("Folder", "View")));
+ options.AddPolicy("EditFolder", policy => policy.Requirements.Add(new PermissionRequirement("Folder", "Edit")));
+ options.AddPolicy("ListFolder", policy => policy.Requirements.Add(new PermissionRequirement("Folder", "List")));
});
// register scoped core services
@@ -101,12 +104,13 @@ namespace Oqtane.Server
services.AddScoped();
services.AddScoped();
services.AddScoped();
- services.AddScoped();
services.AddScoped();
services.AddScoped();
services.AddScoped();
services.AddScoped();
services.AddScoped();
+ services.AddScoped();
+ services.AddScoped();
services.AddSingleton();
@@ -181,6 +185,8 @@ namespace Oqtane.Server
services.AddTransient();
services.AddTransient();
services.AddTransient();
+ services.AddTransient();
+ services.AddTransient();
services.AddOqtaneModules();
services.AddOqtaneThemes();
@@ -329,6 +335,8 @@ namespace Oqtane.Server
services.AddTransient();
services.AddTransient();
services.AddTransient();
+ services.AddTransient();
+ services.AddTransient();
services.AddOqtaneModules();
services.AddOqtaneThemes();
diff --git a/Oqtane.Server/wwwroot/js/interop.js b/Oqtane.Server/wwwroot/js/interop.js
index 96ddf060..f2a2421f 100644
--- a/Oqtane.Server/wwwroot/js/interop.js
+++ b/Oqtane.Server/wwwroot/js/interop.js
@@ -62,9 +62,9 @@ window.interop = {
document.body.appendChild(form);
form.submit();
},
- getFiles: function (name) {
+ getFiles: function (id) {
var files = [];
- var fileinput = document.getElementById(name);
+ var fileinput = document.getElementById(id);
if (fileinput !== null) {
for (var i = 0; i < fileinput.files.length; i++) {
files.push(fileinput.files[i].name);
@@ -72,10 +72,10 @@ window.interop = {
}
return files;
},
- uploadFiles: function (posturl, folder, name) {
- var files = document.getElementById(name + 'FileInput').files;
- var progressinfo = document.getElementById(name + 'ProgressInfo');
- var progressbar = document.getElementById(name + 'ProgressBar');
+ uploadFiles: function (posturl, folder, id) {
+ var files = document.getElementById(id + 'FileInput').files;
+ var progressinfo = document.getElementById(id + 'ProgressInfo');
+ var progressbar = document.getElementById(id + 'ProgressBar');
var filename = '';
for (var i = 0; i < files.length; i++) {
diff --git a/Oqtane.Shared/Models/File.cs b/Oqtane.Shared/Models/File.cs
index 55b8a637..44acbcbd 100644
--- a/Oqtane.Shared/Models/File.cs
+++ b/Oqtane.Shared/Models/File.cs
@@ -7,6 +7,8 @@ namespace Oqtane.Models
public int FileId { get; set; }
public int FolderId { get; set; }
public string Name { get; set; }
+ public string Extension { get; set; }
+ public int Size { get; set; }
public string CreatedBy { get; set; }
public DateTime CreatedOn { get; set; }
diff --git a/Oqtane.Shared/Models/Folder.cs b/Oqtane.Shared/Models/Folder.cs
index c632eac4..5f04f4bb 100644
--- a/Oqtane.Shared/Models/Folder.cs
+++ b/Oqtane.Shared/Models/Folder.cs
@@ -11,6 +11,7 @@ namespace Oqtane.Models
public string Name { get; set; }
public string Path { get; set; }
public int Order { get; set; }
+ public bool IsSystem { get; set; }
public string CreatedBy { get; set; }
public DateTime CreatedOn { get; set; }
diff --git a/Oqtane.Shared/Models/Site.cs b/Oqtane.Shared/Models/Site.cs
index dc7fbf35..439f5131 100644
--- a/Oqtane.Shared/Models/Site.cs
+++ b/Oqtane.Shared/Models/Site.cs
@@ -8,7 +8,7 @@ namespace Oqtane.Models
public int SiteId { get; set; }
public int TenantId { get; set; }
public string Name { get; set; }
- public string Logo { get; set; }
+ public int? LogoFileId { get; set; }
public string DefaultThemeType { get; set; }
public string DefaultLayoutType { get; set; }
public string DefaultContainerType { get; set; }
diff --git a/Oqtane.Shared/Models/User.cs b/Oqtane.Shared/Models/User.cs
index bec8f3e2..e74deef2 100644
--- a/Oqtane.Shared/Models/User.cs
+++ b/Oqtane.Shared/Models/User.cs
@@ -9,6 +9,9 @@ namespace Oqtane.Models
public string Username { get; set; }
public string DisplayName { get; set; }
public string Email { get; set; }
+ public int? PhotoFileId { get; set; }
+ public DateTime? LastLoginOn { get; set; }
+ public string LastIPAddress { get; set; }
[NotMapped]
public int SiteId { get; set; }