Base solution for your next web application
Starts in:
01 DAYS
01 HRS
01 MIN
01 SEC

Activities of "OutdoorEd"

Answer

It is working now. Thanks.

Answer

Thanks for the reply. In addition to the aspx Page_Load code

protected void Page_Load(object sender, EventArgs e)
        {
            if (!IocManager.Instance.IocContainer.Resolve<IPermissionChecker>().IsGranted("Pages.Routestore.Routes.Routelist"))
            {
                Response.Redirect("/Views/Error/NotAuthorized.html");
            }
              //Show report otherwise
        }
    }

I added these in as well and it now "respects" Role Permissions.

<ins>AppPermissions.cs</ins>

public const string Pages_Routestore_Routes_Routelist = "Pages.Routestore.Routes.Routelist";

<ins>AppAuthorizationProvider.cs</ins>

pages.CreateChildPermission(AppPermissions.Pages_Routestore_Routes_Routelist, L("Routelist"));

<ins>Tenant.xml</ins>

<text name="Routelist" value="Route List" />

I do see the Permissions Checkbox for this role and when I select it I see that reflected in the database Abp_AppPermissions table

5	Pages.Routestore.Routes.Routelist	True	2018-08-13 04:17:59.800	2	NULL	3	UserPermissionSetting	1
Answer

This approach works for me to prevent anonymous users from logging in. I need to be able to control access via ABP Roles and can't see how to control that from the PageLoad on the ASPX page.

public partial class RouteList : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            if (!IocManager.Instance.IocContainer.Resolve<IPermissionChecker>().IsGranted("Pages.Routestore.Routes.Routelist"))
            {
                Response.Redirect("/Views/Error/NotAuthorized.html");
            }
              //Show report otherwise
        }
    }

One feature I would like to see in Subscriptions is

Number of Active Users

For my SaaS application I allow a client to purchase X number of licenses and then only allow them to have X number of Active Users at any one time. Only Active Users can log in. The client can have more than X users if additional Users beyond X are Inactive. Then they can turn off an Active User and turn on an Inactive User.

In working with an existing database for the MVC Jquery version I used Simon Hughes' EntityFramework Reverse POCO Generator in a separate project just to create the POCOs. One of the nice things in Simon's template is that you can control things like the namespace so even though it was in a separate project, I could generate the correct namespace for my project.

I worked with a wonderful outside developer who laid out the architecture for this (just to admit that I am not smart enough to come up with this myself). Here is how one class was created for my Incident database application. It uses Repositories and separate Configuration files.

I am only showing one database field from the table all the way through and don't show you any of the relationships to other tables to shorten the code. I used generic MVC scaffolding to create the skeleton of the Controller and all the CRUD Views and then replaced things in the Controller with the Repositories.


FOLDER: OE_Tenant.Core\Incidents\Entity\IncidentFile.cs

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Data.Entity.Spatial;
using Abp.Domain.Entities;
using Abp.Domain.Entities.Auditing;

namespace OE_Tenant.Incidents.Entity { [Table("idb_IncidentFile")] public partial class IncidentFile : FullAuditedEntity<Guid>, IMustHaveTenant { public int FileTypeId { get; set; } } }

FOLDER: OE_Tenant.Core\Incident\Repos\IIncidentFileRepository.cs

using Abp.Domain.Repositories; using OE_Tenant.Incidents.Entity; using System; using System.Collections; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks;

namespace OE_Tenant.Incidents.Repos { public interface IIncidentFileRepository : IRepository<IncidentFile, Guid> { } }

FOLDER: OE_Tenant.EntityFramework\EntityConfigurations\IncidentFileConfiguration.cs

using System.ComponentModel.DataAnnotations.Schema; using System.Data.Entity.ModelConfiguration; using OE_Tenant.Incidents.Entity;

namespace OE_Tenant.EntityConfigurations { public class IncidentFileConfiguration : EntityTypeConfiguration<IncidentFile> { public IncidentFileConfiguration() { // Primary Key this.HasKey(t => t.Id);

        // Table & Column Configuration
        this.ToTable("idb_IncidentFile");
        this.Property(t => t.Id).HasColumnName("Id");
        this.Property(t => t.FileTypeId).HasColumnName("FileTypeId");
        this.Property(t => t.TenantId).HasColumnName("TenantId");
    }
}

}


FOLDER: OE_Tenant.EntityFramework\Repos\IncidentFileRepository.cs

using OE_Tenant.EntityFramework.Repositories; using OE_Tenant.Incidents.Entity; using OE_Tenant.Incidents.Repos; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Abp.EntityFramework; using OE_Tenant.EntityFramework;

namespace OE_Tenant.Repos { public class IncidentFileRepository : OE_TenantRepositoryBase<IncidentFile, Guid>, IIncidentFileRepository { public IncidentFileRepository(IDbContextProvider<OE_TenantDbContext> dbContextProvider) : base(dbContextProvider) { } } }


FOLDER: OE_Tenant.EntityFramework\OE_TenantDbContext.cs

using System.Data.Common; using System.Data.Entity; using Abp.Zero.EntityFramework; using OE_Tenant.Authorization.Roles; using OE_Tenant.Authorization.Users; using OE_Tenant.Chat; using OE_Tenant.Friendships; using OE_Tenant.MultiTenancy; using OE_Tenant.Storage; using System.Data.Entity.Core.Objects; using System.Data.Entity.Infrastructure; using EntityFramework.Functions; using OE_Tenant.Incidents.Entity; //Added for External Configuration Files using OE_Tenant.EntityConfigurations; //Added for Dynamic Filter using EntityFramework.DynamicFilters; using Abp.Domain.Entities;

namespace OE_Tenant.EntityFramework { public class OE_TenantDbContext : AbpZeroDbContext<Tenant, Role, User> { public virtual DbSet<IncidentFile> IncidentFile { get; set; }

public OE_TenantDbContext() : base("Default") { //Disable initializer to disable Migrations Database.SetInitializer<OE_TenantDbContext>(null); this.Configuration.LazyLoadingEnabled = false; this.Configuration.ProxyCreationEnabled = false; }

    public OE_TenantDbContext(string nameOrConnectionString)
        : base(nameOrConnectionString)
    {
        this.Configuration.LazyLoadingEnabled = false;
        this.Configuration.ProxyCreationEnabled = false;
    }

    public OE_TenantDbContext(DbConnection existingConnection)
        : base(existingConnection, false)
    {
        this.Configuration.LazyLoadingEnabled = false;
        this.Configuration.ProxyCreationEnabled = false;
    }

    public OE_TenantDbContext(DbConnection existingConnection, bool contextOwnsConnection)
        : base(existingConnection, contextOwnsConnection)
    {
        this.Configuration.LazyLoadingEnabled = false;
        this.Configuration.ProxyCreationEnabled = false;
    }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        //Added - NEEDS TO BE IN TO PREVENT MUSTHAVETENANT ERROR
        base.OnModelCreating(modelBuilder);

        modelBuilder.Configurations.Add(new IncidentFileConfiguration());

     }
}

}


FOLDER: OE_Tenant.Web\Areas\Incidents\Models\Dto\IncidentFileDto.cs

using System; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; using System.Web.Mvc; using Abp.Application.Services.Dto; using Abp.AutoMapper; using OE_Tenant.Incidents.Entity;

namespace OE_Tenant.Web.Areas.Incidents.Models.Dto { [AutoMapTo(typeof(IncidentFile))] [AutoMapFrom(typeof(IncidentFile))] public class IncidentFileDto : FullAuditedEntityDto<Guid> { [Display(Name = "File Type", Prompt = "Select the File Type")] [Required(ErrorMessage = "Please select a File Type")] public int FileTypeId { get; set; } } }


FOLDER: OE_Tenant.Web\Areas\Incidents\ViewModels\IncidentFileViewModel.cs

using System; using Abp.AutoMapper; using OE_Tenant.Incidents.Entity; using OE_Tenant.Web.Areas.Configuration.ViewModels;

namespace OE_Tenant.Web.Areas.Incidents.ViewModels { [AutoMapFrom(typeof(IncidentFile))] [AutoMapTo(typeof(IncidentFile))] public class IncidentFileViewModel { public Guid Id { get; set; } public int FileTypeId { get; set; } public int TenantId { get; set; } } }


FOLDER: OE_Tenant.Web\Areas\Incidents\Controllers\IncidentFileController.cs

using System; using System.Collections; using System.Data.Entity; using System.Threading.Tasks; using System.Net; using System.Web.Mvc; using OE_Tenant.Incidents.Entity; using OE_Tenant.Web.Controllers; using Abp.Runtime.Validation; using OE_Tenant.Incidents.Repos; using Abp.Web.Mvc.Authorization; using OE_Tenant.Authorization; using OE_Tenant.Web.Extensions; using OE_Tenant.Web.Areas.Incidents.ViewModels; using OE_Tenant.Web.Areas.Incidents.Models.Dto; using Abp.AutoMapper; using OE_Tenant.Extensions; using System.Linq;

namespace OE_Tenant.Web.Areas.Incidents.Controllers { [AbpMvcAuthorize(AppPermissions.Pages_Files)] public class FilesController : OE_TenantControllerBase { private readonly IIncidentFileRepository _repoIncidentFile; private readonly ILkpFileTypeRepository _repoLkpFileType;

    public FilesController(
        IIncidentFileRepository repoIncidentFile,
        ILkpFileTypeRepository repoLkpFileType
    )
    {
        _repoIncidentFile = repoIncidentFile;
        _repoLkpFileType = repoLkpFileType;
    }

    [AbpMvcAuthorize(AppPermissions.Pages_Files_Index)]
    // GET: Incidents/IncidentFiles
    public ActionResult Index()
    {
        return View();
    }

    [AbpMvcAuthorize(AppPermissions.Pages_Files_Details)]
    // GET: Incidents/IncidentFiles/Details/5
    public async Task&lt;ActionResult&gt; Details(Guid? id)
    {
        if (id == null)
        {
            return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
        }
        IncidentFile incidentFile = await _repoIncidentFile.GetAllIncluding(i => i.LkpFileType).SingleOrDefaultAsync(i => i.Id == id.Value);

        if (incidentFile == null)
        {
            return HttpNotFound();
        }

        var model = incidentFile.MapTo&lt;IncidentFileDto&gt;();

        return View(model);
    }

    [AbpMvcAuthorize(AppPermissions.Pages_Files_Create)]
    // GET: Incidents/IncidentFiles/Create
    public async Task&lt;ActionResult&gt; Create()
    {
        ViewBag.FileTypeId = new SelectList(await _repoLkpFileType.GetAllListAsync(), "Id", "FileType");
        return View();
    }

    // POST: Incidents/IncidentFiles/Create
    [DisableValidation]
    [HttpPost]
    [ValidateAntiForgeryToken]
    public async Task&lt;ActionResult&gt; Create(IncidentFileDto model)
    {
        if (ModelState.IsValid)
        {
            var incidentFileEntity = model.MapTo&lt;IncidentFile&gt;();
            await _repoIncidentFile.InsertAsync(incidentFileEntity);
            return RedirectToAction("Index");
        }
       ViewBag.FileTypeId = new SelectList(await _repoLkpFileType.GetAllListAsync(), "Id", "FileType");
        return View(model);
    }

    [AbpMvcAuthorize(AppPermissions.Pages_Files_Edit)]
    // GET: Incidents/IncidentFiles/Edit/5
    public async Task&lt;ActionResult&gt; Edit(Guid? id)
    {
        if (id == null)
        {
            return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
        }

        IncidentFile incidentFile = await _repoIncidentFile.GetAsync(id.Value);

        if (incidentFile == null)
        {
            return HttpNotFound();
        }

        ViewBag.FileTypeId = new SelectList(await _repoLkpFileType.GetAllListAsync(), "Id", "FileType", incidentFile.FileTypeId);
        var model = incidentFile.MapTo&lt;IncidentFileDto&gt;();

        return View(model);
    }

    // POST: Incidents/IncidentFiles/Edit/5
    [DisableValidation]
    [HttpPost]
    [ValidateAntiForgeryToken]
    public async Task&lt;ActionResult&gt; Edit(IncidentFileDto model)
    {
        if (ModelState.IsValid)
        {
            IncidentFile incidentFile = await _repoIncidentFile.GetAsync(model.Id);

            incidentFile.FileTypeId = model.FileTypeId;

            await _repoIncidentFile.UpdateAsync(incidentFile);
            return RedirectToAction("Index");
        }

        ViewBag.FileTypeId = new SelectList(await _repoLkpFileType.GetAllListAsync(), "Id", "FileType", model.FileTypeId);
        return View(model);

    }

    [AbpMvcAuthorize(AppPermissions.Pages_Files_Delete)]
    // GET: Incidents/IncidentFiles/Delete/5
    public async Task&lt;ActionResult&gt; Delete(Guid? id)
    {
        if (id == null)
        {
            return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
        }

        IncidentFile incidentFile = await _repoIncidentFile.GetAllIncluding(i => i.LkpFileType).SingleOrDefaultAsync(i => i.Id == id.Value);

        if (incidentFile == null)
        {
            return HttpNotFound();
        }

        var model = incidentFile.MapTo&lt;IncidentFileDto&gt;();

        return View(model);

    }

    // POST: Incidents/IncidentFiles/Delete/5
    [HttpPost, ActionName("Delete")]
    [ValidateAntiForgeryToken]
    public async Task&lt;ActionResult&gt; DeleteConfirmed(Guid id)
    {
        await _repoIncidentFile.DeleteAsync(id);
        return RedirectToAction("Index");
    }

    protected override void Dispose(bool disposing)
    {
        if (disposing)
        {
            //db.Dispose();
        }
        base.Dispose(disposing);
    }
}

}

Metronic is the underlying ASPNETZERO theme using CSS & JS. It's built by a separate company, <a class="postlink" href="http://www.keenthemes.com">www.keenthemes.com</a> and licensed to ASPNETZERO. Because the Metronic theme features are huge (as you can see if you look at their demos) there are lots of things that aren't necessarily used in ASPNETZERO.

Some of the modal dialogs and edit boxes in the backend are coming from Metronic. It would be really helpful if ASPNETZERO would give us a whitelist of the specific JS libraries that are required and then users could remove unnecessary components. It's probably too hard to identify the CSS to be removed.

The other question is whether Datamap is needed in your app. Looking at the description in the README.md for Datamap

Interactive maps for data visualizations. Bundled into a single Javascript file.

Datamaps is intended to provide some data visualizations based on geographical data. It's SVG-based, can scale to any screen size, and includes everything inside of 1 script file. It heavily relies on the amazing [D3.js](<a class="postlink" href="https://github.com/mbostock/d3">https://github.com/mbostock/d3</a>) library.

This looks like it is one of the components bundled with the Metronic Theme. If you don't need to display maps in your app, it is possible this can be removed.

<ins>If the NetZero Staff can weigh in whether they use it anywhere in the Backend that would be helpful to avoid breaking things.</ins>

I really LOVE the Metronic Theme. It is really well built and incredibly complete in it's feature set, but it is very DENSE. Having used it in a number of projects I find I need only about 20% of the features, but I am stuck with lots of code I don't need and it's really difficult to strip it down since it would take too much time studying their documentation and dependencies.

Depending on what version, I just moved ASP.NET MVC 5 up to 5.1 and noticed that there are some location differences in SweetAlert from my previous version. Take a look at App_Start\Bundling\ScriptPaths.cs and see if SweetAlert is mapping to the correct location.

When I do a Security Scan of my site hosted on Azure using <a class="postlink" href="https://asafaweb.com">https://asafaweb.com</a> I get two warnings:

1. HTTP only cookies: Warning It looks like a cookie is being set without the "HttpOnly" flag being set (name : value):

Abp.Localization.CultureName : en

Unless the cookie legitimately needs to be read by JavaScript on the client, the "HttpOnly" flag should always be set to ensure it cannot be read by the client and used in an XSS attack.

Question: Is this cookie only being read by Javascript on the client? If not, how can it be changed to be HTTPS cookie?

2. Secure cookies: Warning It looks like 3 cookies are being served over HTTPS without the "secure" flag being set (name : value):

Abp.Localization.CultureName : en ASP.NET_SessionId : 0q ARRAffinity : 8*******************************f

Unless the cookie needs to be sent over an insecure connection, the "secure" flag should always be set to ensure it can only be sent with an HTTPS request.

Appreciate any guidance in securing the cookies.

I have a SaaS application that contains sensitive client data. If the client ever decides to cancel their contract I need to remove all of their data. To test this out in pre-production I have created a Cascade Delete from AbpTenant to the Client's data so that deleting a Tenant in AbpTenant from SSMS removes all the Client's data. It does leave the Tenant in all of the other Abp Tables (since it is a soft delete). What is the best way to remove all the other references to that Tenant? I don't want to disable the Tenant Soft Delete. Should this just be a SQL script I need to generate?

Showing 41 to 50 of 73 entries