Skip to content

Commit

Permalink
Update to v4.2.0
Browse files Browse the repository at this point in the history
* Show confirmation dialog (#221)

* Added `showConfirmation` to replace native JS alert using `MessageBox.ts`

* Validations and bug fixes

* Don't use showConfirmation at deleteFile (modal inside modal)

* Missing jjmasterdata.js

* Load Additional ConnectionStrings from IOptions (#220)

AdditionalConnectionStrings

* Encryption fixes

* UI and rename `showConfirmation` to `showConfirmationMessage`

* Create _ConnectionStringModel.cshtml

* Created `jj-list-group` CSS class

* Fixed `ExpressionTagHelper` at FloatingLabel

* `IconPickerTagHelper` bug fix

* _Menu `ms-auto`

* Better NCalc extension method with pre-configured options (#223)

* Message toast (#224)

A simple toast message

* Added `GetDataSet` methods to `DataAccess` (#226)

* Add `GetDataSet` to `IEntityRepository`

* Invert `MessageBox.ts` `showConfirmationMessage` buttons

* Fix CodeMirror not looking good at Dark Mode

* Added `GetDataSetAsync`

* Update docs

* Update to NCalc v13 (#230)

* Update to NCalc v13

* Added --md-sticky-top-height variable

* Change `GetDataSetAsync` CommandBehavior

* Delete unused class

* Remove unused `DeleteSelectedRowsAction`

* `ModelStateWrapper` now allow empty `ModelStateDictionary`

* Adjust the log layout

* Breadcrumb Component

* Added `TypeIdentifier` to `FormElement`

* Use Breadcrumb component

* Added `Content` init accessor to `BreadcrumbItem`

* Breadcrumb development

* Support FormElement Identifier

* Add default padding to `_MasterDataLayout`

* Adjust Horizontal Layout

* `ViewBag.IsForm` conditionals

* Added `ExpressionDataAccessCommandFactory`

* Added ModelState support to `ValidationSummary` taghelper

* Added `JJOffcanvas`

* Remove dependencies from About

* Allow `JJDataPanel` at `PageState.Filter` (#232)

* Fix `DbLogger` eventId and added `LogGridViewDataSourceException`

* Move Floating Labels to `FormElementOptions`

* Added `GridRenderingTemplate`

* l10n and missing `JsonProperty`

* Fix `PdfWriter.cs`

* `loadFieldDetails` bug fix

* Fix `list-group-item` at dark theme.

* Use `ExpressionHelper` for `GridRenderingTemplate`

* Fix `DataItem.Command.Sql` editor

* Add `ViewBag.IsForm` to `_FieldLayout.cshtml`

* Update Directory.Build.props

* fix Settings breadcrumb

* bugfix: Add `IFloatingLabelControl` to handle more floating label components

* bugfix: Add `small` CSS class to selected items at `GridPagination`

* Remove unnecesary async keyword at OffcanvasHelper.ts

* Remove unnecessary `SetsRequiredMembersAttribute`

* Added `MessageToastTagHelper` and `MessageToast.ts`

* Update NCalc to v4 - Now without Antlr!

* Update Core.csproj

* Added actions to `JJTitle` and allow editing element from /Render

* Improve `JJDataPanel` debug by using `Task<List<HtmlBuilder>>` instead of `IAsyncEnumerable<HtmlBuilder>`

* bugfix: `DataPanel` not respecting `AutoReloadFormFields`

* bugfix: `Modal.ts` not using `getMasterDataForm()`

* Improve debug by removing `System.Linq.Async` from `JJMasterData.Commons`

* Improve HtmlBuilder performance (dotnet/runtime/issues/57748)

* Fix `InsertAtGridView` DataPanel `AutoReloadFormFields` behavior.

* Hide `BackAction` when `IsChildFormView`

* Remove redundant value

* Remove More from `_Menu`

* Remove preview from package version and update plugins

---------

Co-authored-by: Gustavo Mauricio de Barros <[email protected]>
  • Loading branch information
LucioPelinson and gumbarros authored May 27, 2024
1 parent 6efea7a commit ad3e577
Show file tree
Hide file tree
Showing 224 changed files with 3,319 additions and 1,936 deletions.
2 changes: 1 addition & 1 deletion Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<PackageProjectUrl>https://www.github.com/JJConsulting/JJMasterData</PackageProjectUrl>
<RepositoryUrl>https://www.github.com/JJConsulting/JJMasterData</RepositoryUrl>
<PackageIcon>JJMasterData.png</PackageIcon>
<Version>4.1.11</Version>
<Version>4.2.0</Version>
<PackageReadmeFile>README.NuGet.md</PackageReadmeFile>
<PackageVersion>$(Version)</PackageVersion>
<AssemblyVersion>$(Version)</AssemblyVersion>
Expand Down
62 changes: 24 additions & 38 deletions doc/Documentation/articles/authorization.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,15 @@ JJMasterData uses 2 areas on your routes:
- **DataDictionary** It's used to manage forms that only the admin should access;
- **MasterData** Is used to render a form, you must check if user has access;

> [!IMPORTANT]
> You must create your own policies for *DataDictionary* and *MasterData* areas.
> [!IMPORTANT]
> If a user has the claim DataDictionary, we will enable a button to edit the FormElement at /Render route.
Keep in mind that the end-user only access the MasterData Area.<br>

You can also inject your custom attributes or policy for routes using:
You can also inject your custom authorization requirements for routes using:

```cs
app.UseAuthentication();
Expand All @@ -23,23 +29,15 @@ app.MapJJMasterData()
If you are not familiarized with the concept of policies, please check
this [link](https://learn.microsoft.com/en-us/aspnet/core/security/authorization/policies?view=aspnetcore-6.0).

You will need in your application, implement a **authentication** service, before implementing a **authorization** one.
You will need in your application, implement an **authentication** service, before implementing an **authorization** one.
Please
check [ASP.NET Core docs](https://learn.microsoft.com/en-us/aspnet/core/security/authentication/?view=aspnetcore-6.0)
for more information.
<br>
In the example bellow, I'm using a basic cookie authentication to simplify the process.
<br>
You can use any supported authentication service.

```cs
builder.Services.AddAuthentication(options =>
{
options.DefaultScheme = "SharedCookie";
}).AddCookie("SharedCookie");
```
You can use any supported authentication service, like Microsoft Identity.

To apply your authorization rules on these policies, use the example bellow in your .NET 6 application Program.cs.
To apply your authorization rules on these policies, use the example bellow in your .NET application Program.cs.

```cs
builder.Services.AddAuthorization(options =>
Expand All @@ -51,38 +49,27 @@ builder.Services.AddAuthorization(options =>
});
```

MasterDataPermissionRequirement class example:
In the example below, we create an `MasterDataPermissionRequirement` to see if a user has access to a specific element:

```csharp
using System.Security.Claims;
using Microsoft.AspNetCore.Authorization;

namespace JJMasterData.WebExample.Authorization;

public class MasterDataPermissionRequirement : AuthorizationHandler<IAuthorizationRequirement>, IAuthorizationRequirement
public sealed class MasterDataPermissionRequirement : AuthorizationHandler<IAuthorizationRequirement>, IAuthorizationRequirement
{
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, IAuthorizationRequirement requirement)
{
var filterContext = context.Resource as DefaultHttpContext;
var routeData = filterContext?.HttpContext.GetRouteData();

if (routeData == null)
{
context.Fail();
return Task.CompletedTask;
}
var filterContext = (DefaultHttpContext)context.Resource!;
var routeData = filterContext.HttpContext.GetRouteData();

string? area = null;
if (routeData.Values.ContainsKey("area"))
area = routeData.Values["area"]!.ToString();

string? dictionaryName = null;
if (routeData.Values.ContainsKey("id"))
dictionaryName = routeData.Values["id"]!.ToString();

if (routeData.Values.TryGetValue("area", out var areaValue))
area = areaValue!.ToString()?.ToLowerInvariant();
string? elementName = null;
if (routeData.Values.TryGetValue("elementName", out var elementNameValue))
elementName = elementNameValue!.ToString();
if ("MasterData".Equals(area, StringComparison.InvariantCultureIgnoreCase))
{
if (HasDictionaryAccess(dictionaryName, context.User))
if (CanAccessElement(elementName, context.User))
{
context.Succeed(requirement);
return Task.CompletedTask;
Expand All @@ -93,11 +80,10 @@ public class MasterDataPermissionRequirement : AuthorizationHandler<IAuthorizati
//TODO: admin required
}

context.Fail();
context.Succeed(this);
return Task.CompletedTask;
}

private bool HasDictionaryAccess(string? dictionaryName, ClaimsPrincipal user)
private static bool CanAccessElement(string? elementName, ClaimsPrincipal user)
{
// Code omitted for brevity
return true;
Expand Down
3 changes: 2 additions & 1 deletion doc/Documentation/articles/expressions.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,8 @@ Building an expression<br>
- {IsUpdate} = 1 | 0
- {IsDelete} = 1 | 0
- {IsImport} = 1 | 0
- {ComponentName} = Name of the component that triggered the AutoPostBack event
- {ComponentName} = Name of the component that the field resides
- {FieldName} = Name of the field that triggered the AutoPostBack event
- {UserId} = Identifier of the authenticated user, can be recovered from UserValues, Session or Claims

Dynamic values will be recovered in the following order:
Expand Down
1 change: 0 additions & 1 deletion src/Commons/Commons.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@
</PackageReference>
<PackageReference Include="System.Collections.Immutable" Version="8.0.0" />
<PackageReference Include="System.Diagnostics.EventLog" Version="6.0.0" />
<PackageReference Include="System.Linq.Async" Version="6.0.1" />
<PackageReference Include="System.Threading.Channels" Version="7.0.0" />
</ItemGroup>
<ItemGroup>
Expand Down
14 changes: 13 additions & 1 deletion src/Commons/Configuration/MasterDataServiceBuilder.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
using System;
using System.Collections.Generic;
using System.Linq;
using JJMasterData.Commons.Configuration.Options;
using JJMasterData.Commons.Data;
using JJMasterData.Commons.Data.Entity.Models;
using JJMasterData.Commons.Data.Entity.Providers;
using JJMasterData.Commons.Data.Entity.Repository.Abstractions;
using JJMasterData.Commons.Tasks;
Expand Down Expand Up @@ -33,7 +36,7 @@ public MasterDataServiceBuilder WithEntityProvider(string connectionString, Data
Services.TryAddTransient<SqlServerScripts>();
WithEntityProvider<SqlServerProvider>();
break;
case DataAccessProvider.SqLite:
case DataAccessProvider.SQLite:
WithEntityProvider<SQLiteProvider>();
break;
case DataAccessProvider.Oracle:
Expand Down Expand Up @@ -65,4 +68,13 @@ public MasterDataServiceBuilder WithEntityRepository(
Services.Replace(ServiceDescriptor.Transient(implementationFactory));
return this;
}

public MasterDataServiceBuilder WithConnectionStrings(List<ConnectionString> connectionStrings)
{
Services.PostConfigure<MasterDataCommonsOptions>(options =>
{
options.AdditionalConnectionStrings = connectionStrings;
});
return this;
}
}
20 changes: 20 additions & 0 deletions src/Commons/Configuration/Options/ConnectionString.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#nullable enable
using System;
using System.Diagnostics.CodeAnalysis;

namespace JJMasterData.Commons.Configuration.Options;

public class ConnectionString()
{
[SetsRequiredMembers]
public ConnectionString(string connectionString, string connectionProvider) : this()
{
Connection = connectionString;
ConnectionProvider = connectionProvider;
}

public Guid Guid { get; init; } = Guid.NewGuid();
public required string? Name { get; init; }
public required string Connection { get; init; }
public required string ConnectionProvider { get; init; }
}
32 changes: 26 additions & 6 deletions src/Commons/Configuration/Options/MasterDataCommonsOptions.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
#nullable enable

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Runtime.InteropServices;
using JJMasterData.Commons.Data;
using JJMasterData.Commons.Data.Entity.Models;
using JJMasterData.Commons.Exceptions;
using Microsoft.Extensions.Configuration;
using Newtonsoft.Json;

Expand All @@ -24,8 +28,9 @@ namespace JJMasterData.Commons.Configuration.Options;
public sealed class MasterDataCommonsOptions
{
public string? ConnectionString { get; set; }

public DataAccessProvider ConnectionProvider { get; set; }

public List<ConnectionString> AdditionalConnectionStrings { get; set; } = [];

/// <summary>
/// Default value: tb_masterdata_resources <br></br>
Expand Down Expand Up @@ -54,6 +59,19 @@ public sealed class MasterDataCommonsOptions
[JsonIgnore]
public static bool IsNetFramework => RuntimeInformation.FrameworkDescription.StartsWith(".NET Framework");

public ConnectionString GetConnectionString(Guid? guid)
{
if (guid is null)
return new ConnectionString(ConnectionString!, ConnectionProvider.GetAdoNetTypeName());

var connectionString = AdditionalConnectionStrings.FirstOrDefault(c => c.Guid == guid);

if (connectionString is null)
throw new JJMasterDataException($"ConnectionString {guid} does not exist.");

return connectionString;
}

public string GetReadProcedureName(Element element)
{
if (!string.IsNullOrEmpty(element.ReadProcedureName))
Expand All @@ -76,24 +94,26 @@ public string GetWriteProcedureName(Element element)

public string GetReadProcedureName(string tableName)
{
var dicName = RemovePrefixChars(tableName);
var dicName = RemoveTbPrefix(tableName);

return ReadProcedurePattern.Replace("{tablename}", dicName);
}

public string GetWriteProcedureName(string tableName)
{
var dicName = RemovePrefixChars(tableName);
var dicName = RemoveTbPrefix(tableName);

return WriteProcedurePattern.Replace("{tablename}", dicName);
}

private static string RemovePrefixChars(string tableName)
public static string RemoveTbPrefix(string tableName)
{
if (tableName.ToLower().StartsWith("tb_"))
var loweredTableName = tableName.ToLowerInvariant();

if (loweredTableName.StartsWith("tb_"))
return tableName[3..];

if (tableName.ToLower().StartsWith("tb"))
if (loweredTableName.StartsWith("tb"))
return tableName[2..];

return tableName;
Expand Down
9 changes: 9 additions & 0 deletions src/Commons/Data/ConnectionResult.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#nullable enable

namespace JJMasterData.Commons.Data;

public class ConnectionResult(bool isConnectionSuccessful, string? errorMessage)
{
public bool? IsConnectionSuccessful { get; } = isConnectionSuccessful;
public string? ErrorMessage { get; } = errorMessage;
}
Loading

0 comments on commit ad3e577

Please sign in to comment.