|
After Width: | Height: | Size: 16 KiB |
@ -0,0 +1,114 @@ |
|||
# Using Blob Storage with ABP |
|||
ABP Framework provides a comprehensive solution to meet the needs of modern application development, while addressing the important requirement of BLOB Storing. ABP Framework [provides an easy integration for Blob Storing](https://docs.abp.io/en/abp/latest/Blob-Storing) and offers many storage services that you can easily integrate. In addition to efficiently storing large files, these services offer significant advantages such as scalability, security and backup. |
|||
|
|||
## What is Blob Storage ? |
|||
|
|||
Blob Storage is a service for storing unstructured data. It is becoming increasingly important to efficiently store and manage large data types (e.g. images, videos, documents). Blob Storage was developed to meet these needs and offers a secure solution with the advantages of scalability, durability and low cost. |
|||
|
|||
 |
|||
|
|||
|
|||
## How to use Blob Storage ? |
|||
|
|||
I would like to explain this to you with an example.For example, storing large files such as user profile pictures in the database negatively affects the performance and database.You can store this data using Blob storage. One of the advantages of storing user profile pictures in blob storage is that it improves database performance. Blob storage is a more efficient option than storing large size files in the database and allows database queries to run faster. Furthermore, blob storage provides scalability, so that the number of profile pictures can grow with the number of users, but without storage issues. This approach also maintains database normalization and makes the database design cleaner. |
|||
|
|||
How do we store user profile pictures with Blob Storage using ABP Framework? |
|||
|
|||
- #### Step 1: Configure the Blob Container |
|||
|
|||
Define a Blob Container named `profile-pictures` using the `[BlobContainerName("profile-pictures")]` attribute. |
|||
|
|||
````csharp |
|||
[BlobContainerName("profile-pictures")] |
|||
public class ProfilePictureContainer |
|||
{ |
|||
|
|||
} |
|||
```` |
|||
- #### Step 2: Create the ProfileAppService (Saving & Reading BLOBs) |
|||
|
|||
Create the `ProfileAppService` class and derive it from the `ApplicationService` class. This class will perform the necessary operations to store and retrieve profile pictures. |
|||
|
|||
````csharp |
|||
using Volo.Abp.Application.Services; |
|||
|
|||
public class ProfileAppService : ApplicationService |
|||
{ |
|||
// Code snippets will come here |
|||
} |
|||
```` |
|||
|
|||
- #### Step 3: Inject the `IBlobContainer` Service |
|||
|
|||
Inject the `IBlobContainer` service, in the constructor of the `ProfileAppService` class. The `IBlobContainer` is the main interface to store and read BLOB and is used to interact with the container. |
|||
|
|||
````csharp |
|||
private readonly IBlobContainer<ProfilePictureContainer> _blobContainer; |
|||
|
|||
public ProfileAppService(IBlobContainer<ProfilePictureContainer> blobContainer) |
|||
{ |
|||
_blobContainer = blobContainer; |
|||
} |
|||
```` |
|||
|
|||
- #### Step 4: Save Profile Picture |
|||
|
|||
The SaveProfilePictureAsync method is used to store the user's profile picture. A unique name is generated based on the user's credentials and the profile picture byte array with this name is saved in the Blob Container. |
|||
|
|||
````csharp |
|||
public async Task SaveProfilePictureAsync(byte[] bytes) |
|||
{ |
|||
var blobName = CurrentUser.GetId().ToString(); |
|||
await _blobContainer.SaveAsync(blobName, bytes); |
|||
} |
|||
```` |
|||
|
|||
- #### Step 5: Getting Profile Picture |
|||
|
|||
The GetProfilePictureAsync method is used to get the user's profile picture. A profile picture byte array is retrieved from the Blob Container with a specified name based on the user's credential. |
|||
|
|||
````csharp |
|||
public async Task<byte[]> GetProfilePictureAsync() |
|||
{ |
|||
var blobName = CurrentUser.GetId().ToString(); |
|||
return await _blobContainer.GetAllBytesOrNullAsync(blobName); |
|||
} |
|||
```` |
|||
|
|||
|
|||
Finally, add controls in the user interface that will allow users to upload and view their profile pictures. These controls will perform the operations by calling the corresponding methods in the ProfileAppService class. |
|||
|
|||
These steps cover the basic steps to store user profile pictures with Blob Storage using the ABP Framework. [Check out the documentation for more information.](https://docs.abp.io/en/abp/latest/Blob-Storing) |
|||
|
|||
|
|||
## What are the Advantages/Disadvantages of Keeping the BLOBs in a Database? |
|||
|
|||
#### Advantages: |
|||
|
|||
- Data Integrity and Relational Model: To ensure data integrity and preserve the relational model, it is important to store blob data in the database. This approach preserves the relationships between data and maintains the structural integrity of the database. |
|||
|
|||
- A Single Storage Location: Storing blob data in the database allows you to collect all data in a single storage location. This simplifies the management of data and increases data integrity. |
|||
|
|||
- Advanced Security Controls: Database systems often offer advanced security controls. Storing blob data in a database allows you to take advantage of these security features and ensures that data is accessed by authorized users. |
|||
|
|||
#### Disadvantages: |
|||
|
|||
- Performance Issues: Storing blob data in a database can negatively impact database performance. Oversized blob data can slow down query processing and reduce database performance. |
|||
|
|||
- Storage Space Issue: Storing blob data in the database can increase the size of the database and require more storage space. This can increase storage costs and complicate infrastructure requirements. |
|||
|
|||
- Backup and Recovery Challenges: Storing blob data in a database can make backup and recovery difficult. The large size of blob data can make backup and recovery time-consuming and data recovery difficult. |
|||
|
|||
|
|||
## Other Blob Storage Providers |
|||
|
|||
ABP Framework provides developers with a variety of options and flexibility by offering integration infrastructure for multiple cloud providers. This makes it easy for users to choose between different cloud platforms and select the most suitable solution for their business needs. |
|||
|
|||
|
|||
- Azure Blob Storage: A cloud storage service offered on the Microsoft Azure platform. It is used to store and access large amounts of data. It supports various data types such as files, images, videos and provides high scalability. ABP Framework provides integration with [Azure Blob Storage](https://docs.abp.io/en/abp/latest/Blob-Storing-Azure). |
|||
|
|||
- Aliyun Object Storage Service (OSS): OSS, Alibaba Cloud's cloud storage service, is an ideal solution for use cases such as big data storage, backup and media storage. It offers flexible storage options and provides a high level of security. ABP Framework interfaces with [Aliyun Blob Storage](https://docs.abp.io/en/abp/latest/Blob-Storing-Aliyun), making it easier for developers to manage data storage and access. |
|||
|
|||
- MinIO: MinIO is known as an open source object storage system and offers an Amazon S3 compatible cloud storage solution. It is a high-performance, scalable and fast storage service. ABP Framework integrates with [MinIO Blob Storage](https://docs.abp.io/en/abp/latest/Blob-Storing-Minio) to provide developers with cloud-based file and object storage. |
|||
|
|||
- Amazon Simple Storage Service (S3): Amazon S3 is a cloud storage service offered on the Amazon Web Services (AWS) platform. It can be used to store virtually unlimited amounts of data. It provides high durability, scalability and low cost.ABP Framework integrates with [Amazon S3 Blob Storage](https://docs.abp.io/en/abp/latest/Blob-Storing-Aws) to provide developers with cloud-based file and object storage. |
|||
|
Before Width: | Height: | Size: 77 KiB After Width: | Height: | Size: 61 KiB |
|
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 17 KiB |
|
Before Width: | Height: | Size: 51 KiB After Width: | Height: | Size: 48 KiB |
@ -0,0 +1,336 @@ |
|||
# Sentiment Analysis Within ABP-Based Application |
|||
|
|||
In this article, first I will briefly explain what sentiment analysis is and then show you how you can apply sentiment analysis in an ABP-Based application (or any kind of .NET application). |
|||
|
|||
We will use ML.NET Framework, which is an open-source machine learning framework created by the dotnet team and also we will create a layered ABP Solution by using the application template and finally we will use CMS Kit's Comment Feature and extend its behavior by adding spam detection while creating or updating a comment, at that point we will make sentiment analysis. |
|||
|
|||
## Sentiment Analysis |
|||
|
|||
[Sentiment Analysis (or opinion mining)](https://en.wikipedia.org/wiki/Sentiment_analysis) refers to determining the emotion from the given input. The primary goal of sentiment analysis is to identify, extract, and categorize (positive, negative, or neutral) the sentiments expressed in textual data. |
|||
|
|||
To understand it better, let's check the following figure and examine the comments: |
|||
|
|||
 |
|||
|
|||
* If you look at these comments, you will notice that comments have ratings and it's easy to understand the emotion or thoughts of the users who commented about the related product. |
|||
* But even if there was not any rating specified for the given comments we still can get the emotion of the users. Because, as you can see, the comments specified some obvious words that express emotions, for example, in the first comment, the user says **he/she liked the product**, **it's easy to use** and **its battery is good**, and therefore this is obviously a positive comment. |
|||
* On the other hand, if we look at the second comment, we will notice some negative statements such as **useless phone**, **cannot maintain any data connection** and the user suggests **do not buy this phone**. Actually, this is what sentiment analysis is all about, abstracting the emotion from a given input, it's comment in that case but it can be any kind of input or input-group. |
|||
|
|||
## Demo: Spam Detection (Applying Sentiment Analysis) |
|||
|
|||
> You can get the source code of the demo from [https://github.com/EngincanV/SentimentAnalysisDemo](https://github.com/EngincanV/SentimentAnalysisDemo). |
|||
|
|||
In this demo application, we will create an [ABP-based application](https://docs.abp.io/en/abp/8.1/Startup-Templates/Application) and integrate the [ABP's CMS Kit Module's Comment Feature](https://docs.abp.io/en/abp/latest/Modules/Cms-Kit/Comments), which provides a comment system to add a comment to any kind of resource, such as blog posts or products. |
|||
|
|||
By default, CMS Kit's Comment Feature does not provide spam detection and therefore in this sample application, we will add [spam detection](https://github.com/EngincanV/SentimentAnalysisDemo/blob/master/src/SentimentAnalysisDemo.Application/ML/SpamDetector.cs) while creating or updating a comment. Thus, whenever a comment is being added or updated, the spam detection service will validate the comment and reject it if it contains spam content otherwise it will make the other validations and save the comment: |
|||
|
|||
 |
|||
|
|||
To get started, we will first create an application, and add the CMS Kit Module to the solution and then we will enable the Comment Feature of the CMS Kit Module, and finally, we will add the Comment Component to the homepage and add spam detection by extending the behavior. Let's start with creating the application! |
|||
|
|||
### Creating an ABP-Based Application |
|||
|
|||
You can use the following command to create a layered ABP solution (with MongoDB as the database option): |
|||
|
|||
```bash |
|||
abp new SentimentAnalysisDemo -t app -d mongodb --version 8.1.1 |
|||
``` |
|||
|
|||
### Installing the CMS Kit Module |
|||
|
|||
After creating the project, we can add the CMS Kit module to our project. [ABP CLI](https://docs.abp.io/en/abp/latest/CLI) provides the `add-module` command to install a specific module to a solution. |
|||
|
|||
You can use the following command to install the CMS Kit module into your application (run this command in the solution directory): |
|||
|
|||
```bash |
|||
abp add-module Volo.CmsKit --skip-db-migrations |
|||
``` |
|||
|
|||
After this command is executed, all related CMS Kit packages will be added to the correct layers and then you can enable any CMS Kit feature you want. |
|||
|
|||
### Enabling the Comment Feature |
|||
|
|||
By default, CMS Kit features are disabled. Therefore, you need to enable the features you want, before starting to use it. You can either enable all of them or enable them one by one. In our demo application, we only need the **Comment Feature**, therefore we can only enable it. |
|||
|
|||
To enable the Comment Feature, you can open the `SentimentAnalysisDemoGlobalFeatureConfigurator` class (under the `*.Domain.Shared` project) and update it as follows: |
|||
|
|||
```csharp |
|||
using Volo.Abp.GlobalFeatures; |
|||
using Volo.Abp.Threading; |
|||
|
|||
namespace SentimentAnalysisDemo; |
|||
|
|||
public static class SentimentAnalysisDemoGlobalFeatureConfigurator |
|||
{ |
|||
private static readonly OneTimeRunner OneTimeRunner = new OneTimeRunner(); |
|||
|
|||
public static void Configure() |
|||
{ |
|||
OneTimeRunner.Run(() => |
|||
{ |
|||
GlobalFeatureManager.Instance.Modules.CmsKit(cmsKit => |
|||
{ |
|||
cmsKit.Comments.Enable(); |
|||
}); |
|||
}); |
|||
} |
|||
} |
|||
``` |
|||
|
|||
After enabling the feature, now we can make the final configurations and directly use it in our application. |
|||
|
|||
### Configurations for Comment Feature |
|||
|
|||
Open the `SentimentAnalysisDemoDomainModule` class and add the following code-block into the `ConfigureServices` method: |
|||
|
|||
```csharp |
|||
Configure<CmsKitCommentOptions>(options => |
|||
{ |
|||
options.EntityTypes.Add(new CommentEntityTypeDefinition("Comment")); |
|||
options.IsRecaptchaEnabled = true; |
|||
}); |
|||
``` |
|||
|
|||
Here, we simply defining what should be the entity-type name of our comment and also enable the reCaptcha for the comment system. After this configuration, now we can open the `Index.cshtml` file in the `*.Web` project and invoke the `CommentingViewComponent` as below: |
|||
|
|||
```html |
|||
@page |
|||
@using Microsoft.AspNetCore.Mvc.Localization |
|||
@using SentimentAnalysisDemo.Localization |
|||
@using Volo.CmsKit.Public.Web.Pages.CmsKit.Shared.Components.Commenting |
|||
@model SentimentAnalysisDemo.Web.Pages.IndexModel |
|||
|
|||
<div class="container"> |
|||
<h5 class="display-5">Comments:</h5> |
|||
|
|||
@await Component.InvokeAsync(typeof(CommentingViewComponent), new |
|||
{ |
|||
entityType = "Comment", |
|||
entityId = "SentimentAnalysisDemo", |
|||
isReadOnly = false |
|||
}) |
|||
</div> |
|||
|
|||
``` |
|||
|
|||
After adding the related component, now you can run the web project and see the comment component if you want. |
|||
|
|||
### Applying Sentiment Analysis (Creating the Spam Detection Service) |
|||
|
|||
By default, CMS Kit's Comment Feature does not provide a spam detection system. In this demo application, we will override the `CommentPublicAppService`'s `CreateAsync` and `UpdateAsync` methods and then will add the spam detection control whenever a new comment has been submitted or an existing one is being updated. |
|||
|
|||
To override the `CommentPublicAppService` and extend its use-case implementations, create a `MyCommentAppService` class and update its content as below: |
|||
|
|||
```csharp |
|||
using System; |
|||
using System.Threading.Tasks; |
|||
using Microsoft.Extensions.Options; |
|||
using SentimentAnalysisDemo.ML; |
|||
using Volo.Abp.DependencyInjection; |
|||
using Volo.Abp.EventBus.Distributed; |
|||
using Volo.CmsKit.Comments; |
|||
using Volo.CmsKit.Public.Comments; |
|||
using Volo.CmsKit.Users; |
|||
|
|||
namespace SentimentAnalysisDemo.Volo.CmsKit.Public.Comments; |
|||
|
|||
[Dependency(ReplaceServices = true)] |
|||
[ExposeServices(typeof(ICommentPublicAppService), typeof(CommentPublicAppService), typeof(MyCommentAppService))] |
|||
public class MyCommentAppService : CommentPublicAppService |
|||
{ |
|||
protected ISpamDetector SpamDetector { get; } |
|||
|
|||
public MyCommentAppService( |
|||
ICommentRepository commentRepository, |
|||
ICmsUserLookupService cmsUserLookupService, |
|||
IDistributedEventBus distributedEventBus, |
|||
CommentManager commentManager, |
|||
IOptionsSnapshot<CmsKitCommentOptions> cmsCommentOptions, |
|||
ISpamDetector spamDetector |
|||
) |
|||
: base(commentRepository, cmsUserLookupService, distributedEventBus, commentManager, cmsCommentOptions) |
|||
{ |
|||
SpamDetector = spamDetector; |
|||
} |
|||
|
|||
public override async Task<CommentDto> CreateAsync(string entityType, string entityId, CreateCommentInput input) |
|||
{ |
|||
//Check message: spam or ham. |
|||
await SpamDetector.CheckAsync(input.Text); |
|||
|
|||
return await base.CreateAsync(entityType, entityId, input); |
|||
} |
|||
|
|||
public override async Task<CommentDto> UpdateAsync(Guid id, UpdateCommentInput input) |
|||
{ |
|||
//Check message: spam or ham. |
|||
await SpamDetector.CheckAsync(input.Text); |
|||
|
|||
return await base.UpdateAsync(id, input); |
|||
} |
|||
} |
|||
``` |
|||
|
|||
Here, we simply just inject the `ISpamDetector` service, which we will create in a minute, and use its `CheckAsync` method to make a spam check before the comment is created or updated. |
|||
|
|||
Now, we can create the `ISpamDetector` service in the `*.Application.Contracts` project as follows: |
|||
|
|||
```csharp |
|||
using System.Threading.Tasks; |
|||
|
|||
namespace SentimentAnalysisDemo.ML; |
|||
|
|||
public interface ISpamDetector |
|||
{ |
|||
Task CheckAsync(string text); |
|||
} |
|||
``` |
|||
|
|||
Then, we can create the `SpamDetector` and implement the `ISpamDetector` interface (in the `*.Application` project): |
|||
|
|||
```csharp |
|||
using System; |
|||
using System.IO; |
|||
using System.Threading.Tasks; |
|||
using Microsoft.ML; |
|||
using SentimentAnalysisDemo.ML.Model; |
|||
using Volo.Abp; |
|||
using Volo.Abp.DependencyInjection; |
|||
|
|||
namespace SentimentAnalysisDemo.ML; |
|||
|
|||
public class SpamDetector : ISpamDetector, ITransientDependency |
|||
{ |
|||
public async Task CheckAsync(string text) |
|||
{ |
|||
//check if the text contains a spam content or not... |
|||
|
|||
} |
|||
} |
|||
``` |
|||
|
|||
The `CheckAsync` method is where we need to make the sentiment analysis and detect if the comment contains spam content or not. If it's spam, then we should throw a [UserFriendlyException](https://docs.abp.io/en/abp/latest/Exception-Handling#user-friendly-exception) and notify the user that the comment should be updated and should not contain any spam content. |
|||
|
|||
#### Spam Detection |
|||
|
|||
Before, making the spam check, we should have a dataset to train a machine-learning model and add `Microsoft.ML` package into our project. For that purpose, I searched in [Kaggle](https://www.kaggle.com/) for spam datasets, found the **Spam-Mail-Detection-Dataset** from Kaggle, and downloaded the csv file to use in my application. Therefore, [you should also download the dataset from the link and put it under the **/ML/Data/spam_data.csv** directory of the `*.Web` project](https://github.com/EngincanV/SentimentAnalysisDemo/blob/master/src/SentimentAnalysisDemo.Web/ML/Data/spam_data.csv). |
|||
|
|||
Here is what our dataset looks like (**0 -> not spam / 1 -> spam**): |
|||
|
|||
| Category | Message | |
|||
|----------|---------| |
|||
| 0 | Is that seriously how you spell his name? | |
|||
| 1 | Free entry in 2 a wkly comp to win FA Cup final tkts 21st May 2005. Text FA to 87121 to receive entry question(std txt rate)T&C's apply 08452810075over18's | |
|||
| . | . | |
|||
| . | . | |
|||
| . | . | |
|||
|
|||
> **Note:** This dataset is not ready-to use in a real-world solution. It's for mail spam detection but for the simplicity of the sample, it's not important and can be used for development purposes. |
|||
|
|||
After, downloading the dataset and putting it in the directory of **/ML/Data**, now we can add the `Microsoft.ML` package into our `*.Application` project: |
|||
|
|||
```bash |
|||
dotnet add package Microsoft.ML |
|||
``` |
|||
|
|||
Finally, we can implement the `CheckAsync` method and use sentiment analysis to make spam checks as follows: |
|||
|
|||
```csharp |
|||
|
|||
public async Task CheckAsync(string text) |
|||
{ |
|||
var dataPath = Path.Combine(Environment.CurrentDirectory, "ML", "Data", "spam_data.csv"); |
|||
|
|||
var mlContext = new MLContext(); |
|||
|
|||
//Step 1: Load Data 👇 |
|||
IDataView dataView = mlContext.Data.LoadFromTextFile<SentimentAnalyzeInput>(dataPath, hasHeader: true, separatorChar: ','); |
|||
|
|||
//Step 2: Split data to train-test data 👇 |
|||
DataOperationsCatalog.TrainTestData trainTestSplit = mlContext.Data.TrainTestSplit(dataView, testFraction: 0.2); |
|||
IDataView trainingData = trainTestSplit.TrainSet; //80% of the data. |
|||
IDataView testData = trainTestSplit.TestSet; //20% of the data. |
|||
|
|||
//Step 3: Common data process configuration with pipeline data transformations + choose and set the training algorithm 👇 |
|||
var estimator = mlContext.Transforms.Text.FeaturizeText(outputColumnName: "Features", inputColumnName: nameof(SentimentAnalyzeInput.Message)) |
|||
.Append(mlContext.BinaryClassification.Trainers.SdcaLogisticRegression(labelColumnName: "Label", featureColumnName: "Features")); |
|||
|
|||
//Step 4: Train the model 👇 |
|||
ITransformer model = estimator.Fit(trainingData); |
|||
|
|||
//Step 5: Predict 👇 |
|||
var sentimentAnalyzeInput = new SentimentAnalyzeInput |
|||
{ |
|||
Message = text |
|||
}; |
|||
|
|||
var predictionEngine = mlContext.Model.CreatePredictionEngine<SentimentAnalyzeInput, SentimentAnalyzeResult>(model); |
|||
var result = predictionEngine.Predict(sentimentAnalyzeInput); |
|||
if (IsSpam(result)) |
|||
{ |
|||
throw new UserFriendlyException("Spam detected! Please update the message!"); |
|||
} |
|||
} |
|||
|
|||
private static bool IsSpam(SentimentAnalyzeResult result) |
|||
{ |
|||
//1 -> spam / 0 -> ham (for 'Prediction' column) |
|||
return result is { Prediction: true, Probability: >= 0.5f }; |
|||
} |
|||
|
|||
``` |
|||
|
|||
Here, we have done the following things: |
|||
|
|||
1. **First, we loaded the data**: For that reason, we created a `MLContext` object, which is a main class for all ML.NET operations. Then, we used its `LoadFromTextFile` method and specified the dataset path in our application. Also, we mapped the dataset columns to the `SentimentAnalyzeInput` class, which we will create later on. |
|||
2. **For the second step, we split the data as training and testing data**: To be able to train a machine learning model and then evaluate its accuracy, we should not use all the data for training purposes, instead, we should split the data as training and testing data and after training the model, compare the training data accuracy with the testing data. |
|||
3. **For the third step, we should make data transformation, convert the text-based data into numeric vectors and then choose a training algorithm**: After splitting the data for training and testing purposes, now we can apply some data transformations for the *Message* column in our dataset. Because, as you would see, messages are text-based inputs and machine-learning algorithms work best with the numeric vectors. So, we are making data transformations and representing the data as numeric values. Then, we can apply `BinaryClassification` with the **SdcaLogicticRegression** algorithm to our training data. |
|||
4. **Train the model**: Since we make the data transformations and chose the correct algorithm for our model, now we can train the model. |
|||
5. **Predict the sample data**: Finally, we can pass a comment to this method and make spam check and either approve our reject the comment according to the predicted result. (To make predictions, we need to create a **PredictionEngine** and get the final results in the output class that we specified, `SentimentAnalyzeResult` in our example) |
|||
|
|||
Let's create the `SentimentAnalyzeInput` and `SentimentAnalyzeResult` classes as follows. |
|||
|
|||
**SentimentAnalyzeInput.cs:** |
|||
|
|||
```csharp |
|||
using Microsoft.ML.Data; |
|||
|
|||
namespace SentimentAnalysisDemo.ML.Model; |
|||
|
|||
public class SentimentAnalyzeInput |
|||
{ |
|||
[LoadColumn(0), ColumnName("Label")] |
|||
public bool Category { get; set; } |
|||
|
|||
[LoadColumn(1), ColumnName("Message")] |
|||
public string Message { get; set; } |
|||
} |
|||
``` |
|||
|
|||
**SentimentAnalyzeResult.cs:** |
|||
|
|||
```csharp |
|||
using Microsoft.ML.Data; |
|||
|
|||
namespace SentimentAnalysisDemo.ML.Model; |
|||
|
|||
public class SentimentAnalyzeResult |
|||
{ |
|||
[ColumnName("PredictedLabel")] |
|||
public bool Prediction { get; set; } |
|||
|
|||
public float Probability { get; set; } |
|||
|
|||
public float Score { get; set; } |
|||
} |
|||
``` |
|||
|
|||
Then, finally we can run the application to see the final results: |
|||
|
|||
 |
|||
|
|||
## Conclusion |
|||
|
|||
In this article, I briefly explain what sentiment analysis is, created a sample ABP-based application, integrated the CMS Kit Module and finally, applied sentiment analysis to make spam checks whenever a new comment has been submitted or updated. You can get the source code of the demo from [https://github.com/EngincanV/SentimentAnalysisDemo](https://github.com/EngincanV/SentimentAnalysisDemo) |
|||
|
|||
Thanks for reading :) |
|||
|
After Width: | Height: | Size: 348 KiB |
|
After Width: | Height: | Size: 774 KiB |
|
After Width: | Height: | Size: 29 KiB |
|
After Width: | Height: | Size: 103 KiB |
@ -1,3 +1,31 @@ |
|||
# Microservice Solution: Authentication |
|||
|
|||
*TODO* |
|||
The [microservice solution template](index.md) is fully configured for authentication. All the services and applications are configured to use the [OpenIddict](https://documentation.openiddict.com) library for authentication and authorization. They are configured in a common way for authentication. This document explains that common authentication structure. |
|||
|
|||
## OpenIddict |
|||
|
|||
[OpenIddict](https://documentation.openiddict.com) is an open-source library that provides a simple and easy way to implement an OpenID Connect server in your application. ABP has built-in modules ([OpenIddict](../../modules/openiddict.md), [OpenIddict UI](../../modules/openiddict-pro.md)) to integrate OpenIddict into the solution. |
|||
|
|||
## Identity Service |
|||
|
|||
The microservice solution template has the [identity](microservices.md#identity-microservice) service that is responsible for the OpenIddict definitions (Applications, Scopes, etc.). Also, it provides the *OpenIddictDataSeeder* class to seed the initial data. It creates the default clients(applications) and scopes for the solution. Each microservice has its own scope and the web applications use these scopes to get access to the microservices, so when you add a new microservice, you should add a new scope and add the allowed scopes for related clients(applications). |
|||
|
|||
The [OpenIddict UI](../../modules/openiddict-pro.md) module gonna be added to the identity service only if you choose the OpenIddict UI module while creating the solution. |
|||
|
|||
 |
|||
|
|||
The OpenIddict UI module provides a user interface to manage the OpenIddict entities such as applications, scopes, etc. You can manage these entities from application. |
|||
|
|||
 |
|||
|
|||
## Authentication Server |
|||
|
|||
The solution has an authentication server(auth-server) application to provide the token generation, validation and login page. Additionally, it adds the [account](../../modules/account-pro.md) module to the auth-server application to provide the such as register, forgot password and etc features. |
|||
|
|||
Also, the [account](../../modules/account-pro.md) module provides the [social logins](../../modules/account-pro.md#social--external-logins) (Google, Facebook, etc.) feature. You can enable/disable and configure the social logins from the application UI. |
|||
|
|||
 |
|||
|
|||
## Authentication Flow |
|||
|
|||
The applications use several flows to authenticate users based on the application type. The MVC UI web application uses the [hybrid flow](https://openid.net/specs/openid-connect-core-1_0.html#HybridFlowAuth) (OpenID Connect Authentication) to authenticate users, while the SPA and Swagger applications use the [authorization code flow](https://openid.net/specs/openid-connect-core-1_0.html#CodeFlowAuth) to authenticate users. After the user logs into the system and receives the token from the authentication server, the applications (microservices) use [JWT Bearer Authentication](https://jwt.io/introduction/) to authorize users. |
|||
|
|||
|
After Width: | Height: | Size: 30 KiB |
|
After Width: | Height: | Size: 353 KiB |
|
After Width: | Height: | Size: 74 KiB |
|
After Width: | Height: | Size: 97 KiB |
@ -0,0 +1,62 @@ |
|||
# Microservice Solution: Monitoring |
|||
|
|||
In a distributed system it is important to monitor the health of the system and the services. Monitoring helps to detect issues before they become problems and helps to understand the system's behavior. All the services, applications and gateways are configured to use the [Prometheus](https://prometheus.io/) and [Grafana](https://grafana.com/) libraries for monitoring. They are configured in a common way for monitoring. This document explains that common monitoring structure. |
|||
|
|||
## Configuration |
|||
|
|||
The monitoring configuration is done in the each *Module* class of the project. The `OnApplicationInitialization` method of the module class is used to set the monitoring system. We're adding the `prometheus-net.AspNetCore` package to the project to use Prometheus. The `prometheus-net.AspNetCore` package is a library that provides a middleware to expose metrics for Prometheus. The `app.UseHttpMetrics();` line is collect the HTTP request metrics. The `endpoints.MapMetrics();` line is used to expose the metrics to the `/metrics` endpoint. Existing templates includes the prometheus and grafana configurations in the `docker-compose` file. So, you can visit the `http://localhost:9090` to see the [Prometheus](https://prometheus.io/) dashboard and `http://localhost:3001` to see the [Grafana](https://grafana.com/) dashboard. |
|||
|
|||
> Default username and password for Grafana is `admin` and `admin`. You can change the password after the first login. |
|||
|
|||
After you login to the Grafana dashboard, you can add a new data source to connect to the Prometheus server and create a new dashboard to monitor the system. |
|||
|
|||
 |
|||
|
|||
## Custom Metrics |
|||
|
|||
To create custom metrics, you can use the [IMeterFactory](https://learn.microsoft.com/en-us/dotnet/api/system.diagnostics.metrics.imeterfactory) interface. Basically, you can follow the steps in the [official documentation](https://learn.microsoft.com/en-us/dotnet/core/diagnostics/metrics-instrumentation) to create custom metrics. For example, you can create a custom metric to monitor the number of requests to a specific endpoint. |
|||
|
|||
```csharp |
|||
public class AdministrationMetrics : ISingletonDependency |
|||
{ |
|||
private readonly Counter<int> _demoRequested; |
|||
|
|||
public AdministrationMetrics(IMeterFactory meterFactory) |
|||
{ |
|||
var meter = meterFactory.Create("Microservice.Administration"); |
|||
_demoRequested = meter.CreateCounter<int>("demo_controller.requested"); |
|||
} |
|||
|
|||
public void DemoRequested() |
|||
{ |
|||
_demoRequested.Add(1); |
|||
} |
|||
} |
|||
``` |
|||
|
|||
In the demo controller, you can inject the `AdministrationMetrics` class and use the `DemoRequested` method to increase the counter. |
|||
|
|||
```csharp |
|||
[Route("api/administration/demo")] |
|||
public class DemoController : AbpController |
|||
{ |
|||
public AdministrationMetrics AdministrationMetrics { get; } |
|||
|
|||
public DemoController(AdministrationMetrics administrationMetrics) |
|||
{ |
|||
AdministrationMetrics = administrationMetrics; |
|||
} |
|||
|
|||
[HttpGet] |
|||
[Route("requested")] |
|||
public Task DemoRequested() |
|||
{ |
|||
AdministrationMetrics.DemoRequested(); |
|||
return Task.CompletedTask; |
|||
} |
|||
} |
|||
``` |
|||
|
|||
## Kubernetes Monitoring |
|||
|
|||
If you check the *Kubernetes Configuration* option during project creation, the monitoring system is automatically configured for Kubernetes. The `prometheus` and `grafana` configurations are added to the `helm` chart. |
|||
@ -1,376 +0,0 @@ |
|||
# ABP Studio CLI |
|||
|
|||
ABP Studio CLI is a command line tool that extends [ABP CLI](../cli) by adding more commands to perform operations of ABP Studio features. |
|||
|
|||
## Installation |
|||
|
|||
ABP Studio CLI is installed automatically when you install ABP Studio. |
|||
|
|||
## Commands |
|||
|
|||
As ABP Studio CLI extends [ABP CLI](../cli), all commands provided by [ABP CLI](../cli) is also valid for ABP Studio CLI. Here, is the list of additional commands before explaining their details: |
|||
|
|||
* new-solution: Generates a new solution based on the ABP Studio [startup templates](../solution-templates). |
|||
* new-module: Generates a new module based on the given template. |
|||
* new-package: Generates a new package based on the given template. |
|||
* add-package-ref: Adds package to given project. |
|||
* add-source: Downloads the source code and replaces package references with project references. |
|||
* init-solution: Creates ABP Studio configuration files for a given solution. |
|||
* install-local-module: Installs a local module to given module. |
|||
* install-module: Installs a module to given module via NuGet packages. |
|||
* upgrade: Upgrades solution with Pro modules |
|||
* kube-connect: Connects to kubernetes environment. |
|||
* kube-intercept: Intercepts a service running in Kubernetes environment. |
|||
|
|||
### new-solution |
|||
|
|||
Generates a new solution based on the ABP Studio [startup templates](../solution-templates). |
|||
|
|||
````bash |
|||
abpc new-solution <solution-name> [options] |
|||
```` |
|||
|
|||
Example: |
|||
|
|||
````bash |
|||
abpc new-solution Acme.BookStore |
|||
```` |
|||
|
|||
* `Acme.BookStore` is the solution name here. |
|||
* Common convention is to name a solution is like *YourCompany.YourProject*. However, you can use different naming like *YourProject* (single level namespacing) or *YourCompany.YourProduct.YourModule* (three levels namespacing). |
|||
|
|||
#### options |
|||
|
|||
* `--template` or `-t`: Specifies the template name. Default template name is `empty`, which generates a empty solution. Available templates: |
|||
* **`empty`**: Empty solution template. |
|||
* **`app-pro`**: Application template. Additional options: |
|||
* `--ui` or `-u`: Specifies the UI framework. Default framework is `mvc`. Available frameworks: |
|||
* `mvc`: ASP.NET Core MVC. There are some additional options for this template: |
|||
* `--tiered`: Creates a tiered solution where Web and Http API layers are physically separated. If not specified, it creates a layered solution which is less complex and suitable for most scenarios. |
|||
* `angular`: Angular UI. There are some additional options for this template: |
|||
* `--separate-auth-server`: The Auth Server project comes as a separate project and runs at a different endpoint. It separates the Auth Server from the API Host application. If not specified, you will have a single endpoint in the server side. |
|||
* `--pwa`: Specifies the project as Progressive Web Application. |
|||
* `blazor`: Blazor UI. There are some additional options for this template: |
|||
* `--separate-auth-server`The Auth Server project comes as a separate project and runs at a different endpoint. It separates the Auth Server from the API Host application. If not specified, you will have a single endpoint in the server side. |
|||
* `--pwa`: Specifies the project as Progressive Web Application. |
|||
* `blazor-server`: Blazor Server UI. There are some additional options for this template: |
|||
* `--tiered`: The Auth Server and the API Host project comes as separate projects and run at different endpoints. It has 3 startup projects: *HttpApi.Host*, *AuthServer* and *Blazor* and and each runs on different endpoints. If not specified, you will have a single endpoint for your web project. |
|||
* `maui-blazor`: Blazor Maui UI. There are some additional options for this template: |
|||
* `--tiered`: The Auth Server and the API Host project comes as separate projects and run at different endpoints. It has 3 startup projects: *HttpApi.Host*, *AuthServer* and *Blazor* and and each runs on different endpoints. If not specified, you will have a single endpoint for your web project. |
|||
* `no-ui`: Without UI. No front-end layer will be created. There are some additional options for this template: |
|||
* `--separate-auth-server`: The Auth Server project comes as a separate project and runs at a different endpoint. It separates the Auth Server from the API Host application. If not specified, you will have a single endpoint in the server side. |
|||
* `--mobile` or `-m`: Specifies the mobile application framework. Default value is `react-native`. Available frameworks: |
|||
* `none`: Without any mobile application. |
|||
* `react-native`: React Native. |
|||
* `maui`: MAUI. |
|||
* `--database-provider` or `-d`: Specifies the database provider. Default provider is `ef`. Available providers: |
|||
* `ef`: Entity Framework Core. |
|||
* `mongodb`: MongoDB. |
|||
* `--connection-string` or `-cs`: Overwrites the default connection strings in all `appsettings.json` files. The default connection string is `Server=localhost;Database=MyProjectName;Trusted_Connection=True` for EF Core and it is configured to use the SQL Server. If you want to use the EF Core, but need to change the DBMS, you can change it as [described here](../framework/data/entity-framework-core/other-dbms.md) (after creating the solution). |
|||
* `--theme`: Specifes the theme. Default theme is `leptonx`. Available themes: |
|||
* `leptonx`: LeptonX Theme. |
|||
* `basic`: Basic Theme. |
|||
|
|||
* **`app-nolayers-pro`**: Single-layer application template. Additional options: |
|||
* `--ui` or `-u`: Specifies the UI framework. Default framework is `mvc`. Available frameworks: |
|||
* `mvc`: ASP.NET Core MVC. There are some additional options for this template: |
|||
* `angular`: Angular UI. There are some additional options for this template: |
|||
* `blazor`: Blazor UI. There are some additional options for this template: |
|||
* `blazor-server`: Blazor Server UI. There are some additional options for this template: |
|||
* `no-ui`: Without UI. No front-end layer will be created. There are some additional options for this template: |
|||
* `--database-provider` or `-d`: Specifies the database provider. Default provider is `ef`. Available providers: |
|||
* `ef`: Entity Framework Core. |
|||
* `mongodb`: MongoDB. |
|||
* `--connection-string` or `-cs`: Overwrites the default connection strings in all `appsettings.json` files. The default connection string is `Server=localhost;Database=MyProjectName;Trusted_Connection=True` for EF Core and it is configured to use the SQL Server. If you want to use the EF Core, but need to change the DBMS, you can change it as [described here](../framework/data/entity-framework-core/other-dbms.md) (after creating the solution). |
|||
* `--theme`: Specifes the theme. Default theme is `leptonx`. Available themes: |
|||
* `leptonx`: LeptonX Theme. |
|||
* `basic`: Basic Theme. |
|||
|
|||
* **`microservice-pro`**: Microservice solution template. Additional options: |
|||
* `--ui` or `-u`: Specifies the UI framework. Default framework is `mvc`. Available frameworks: |
|||
* `mvc`: ASP.NET Core MVC. There are some additional options for this template: |
|||
* `angular`: Angular UI. There are some additional options for this template: |
|||
* `blazor`: Blazor UI. There are some additional options for this template: |
|||
* `blazor-server`: Blazor Server UI. There are some additional options for this template: |
|||
* `maui-blazor`: Blazor Maui UI. There are some additional options for this template: |
|||
* `no-ui`: Without UI. No front-end layer will be created. There are some additional options for this template: |
|||
* `--mobile` or `-m`: Specifies the mobile application framework. Default value is `react-native`. Available frameworks: |
|||
* `none`: Without any mobile application. |
|||
* `react-native`: React Native. |
|||
* `maui`: MAUI. |
|||
* `--database-provider` or `-d`: Specifies the database provider. Default provider is `ef`. Available providers: |
|||
* `ef`: Entity Framework Core. |
|||
* `mongodb`: MongoDB. |
|||
* `--theme`: Specifes the theme. Default theme is `leptonx`. Available themes: |
|||
* `leptonx`: LeptonX Theme. |
|||
* `basic`: Basic Theme. |
|||
* `--output-folder` or `-o`: Specifies the output folder. Default value is the current directory. |
|||
* `--database-management-system` or `-dbms`: Sets the database management system. Default is **SQL Server**. Supported DBMS's: |
|||
* `SqlServer` |
|||
* `MySQL` |
|||
* `PostgreSQL` |
|||
* `SQLite` (`app-pro` & `app-nolayers-pro`) |
|||
* `Oracle` (`app-pro` & `app-nolayers-pro`) |
|||
* `Oracle-Devart` (`app-pro` & `app-nolayers-pro`) |
|||
* `--dont-run-install-libs`: Skip installing client side packages. |
|||
* `--dont-run-bundling`: Skip bundling for Blazor packages. |
|||
* `--no-kubernetes-configuration` or `-nkc`: Skips the Kubernetes configuration files. |
|||
* *Module Options*: You can skip some modules if you don't want to add them to your solution. Available commands: |
|||
* `-no-saas`: Skips the Saas module. |
|||
* `-no-gdpr`: Skips the GDPR module. |
|||
* `-no-openiddict-admin-ui`: Skips the OpenIddict Admin UI module. |
|||
* `-no-audit-logging`: Skips the Audit Logging module. |
|||
* `-no-file-management`: Skips the File Management module. |
|||
* `-no-language-management`: Skips the Language Management module. |
|||
* `-no-text-template-management`: Skips the Text Template Management module. |
|||
* `-no-chat`: Skips the Chat module. |
|||
### new-module |
|||
|
|||
Generates a new module. |
|||
|
|||
````bash |
|||
abpc new-module <module-name> [options] |
|||
```` |
|||
|
|||
Example: |
|||
|
|||
````bash |
|||
abpc new-module Acme.BookStore -t module:ddd |
|||
```` |
|||
|
|||
#### options |
|||
|
|||
* `--template` or `-t`: Specifies the template name. Default template name is `empty`, which generates a empty module. Module templates are provided by the main template, see their own startup template documentation for available modules. `empty` and `module:ddd` template is available for all solution structure. |
|||
* `--output-folder` or `-o`: Specifies the output folder. Default value is the current directory. |
|||
* `--target-solution` or `-ts`: If set, the new module will be added to the given solution. Otherwise the new module will added to the closest solution in the file system. If no solution found, it will throw an error. |
|||
* `--solution-folder` or `-sf`: Specifies the target folder in the [Solution Explorer](./solution-explorer.md#folder) virtual folder system. |
|||
* `--database-provider` or `-d`: Specifies the database provider. Default provider is `ef`. This option is only available if the module template supports it. You can add multiple values separated by commas, such as `ef, mongodb` if the module template supports it. Available providers: |
|||
* `ef`: Entity Framework Core. |
|||
* `mongodb`: MongoDB. |
|||
* `--ui-framework` or `-u`: Specifies the UI framework. Default framework is `mvc`. This option is only available if the module template supports it. You can add multiple values separated by commas, such as `mvc,angular` if the module template supports it. Available frameworks: |
|||
* `mvc`: ASP.NET Core MVC. |
|||
* `angular`: Angular UI. |
|||
* `blazor`: Blazor UI. |
|||
* `blazor-server`: Blazor Server UI. |
|||
|
|||
### new-package |
|||
|
|||
Generates a new package. |
|||
|
|||
````bash |
|||
abpc new-package [options] |
|||
```` |
|||
|
|||
Example: |
|||
|
|||
````bash |
|||
abpc new-package --name Acme.BookStore.Domain --template lib.domain |
|||
```` |
|||
|
|||
#### options |
|||
|
|||
* `--template` or `-t`: Specifies the template name. This parameter doesn't have a default value and must be set. Available templates and their sub-options: |
|||
* `lib.class-library` |
|||
* `lib.domain-shared` |
|||
* `lib.domain` |
|||
* `lib.application-contracts` |
|||
* `lib.application` |
|||
* `--with-automapper`: Adds automapper configuration. |
|||
* `lib.ef` |
|||
* `--include-migrations`: Allows migration operations on this package. |
|||
* `--connection-string-name`: Default value is the last part of the package's namespace (or package name simply). |
|||
* `--connection-string`: Connection string value. Defaut value is null. You can set it alter. |
|||
* `lib.mongodb` |
|||
* `lib.http-api` |
|||
* `lib.http-api-client` |
|||
* `lib.mvc` |
|||
* `lib.blazor` |
|||
* `lib.blazor-wasm` |
|||
* `lib.blazor-server` |
|||
* `host.http-api` |
|||
* `--with-serilog`: Includes Serilog configuration. |
|||
* `--with-swagger`: Includes Swagger configuration. |
|||
* `host.mvc` |
|||
* `--with-serilog`: Includes Serilog configuration. |
|||
* `--with-swagger`: Includes Swagger configuration. |
|||
* `host.blazor-wasm` |
|||
* `--backend`: Name of the backend project in the module (not path). |
|||
* `host.blazor-server` |
|||
* `csharp.console` |
|||
* `csharp.library` |
|||
* `--module-file` or `-m`: If set, the new package will be added to the given module. Otherwise the new package will added to the closest module in the file system. If no module found, it will throw an error. |
|||
* `--name` or `-n`: Specifies the name of the package. If not set, a name based on the template type and module name will be generated. |
|||
* `--folder` or `-f`: Specifies the target folder in the target module's virtual folder system. |
|||
|
|||
|
|||
### add-package-ref |
|||
|
|||
Adds one or more package reference to target project, also adds ABP module dependency. Both reference and target projects must belong to same module. |
|||
|
|||
````bash |
|||
abpc add-package-ref <package-names> [options] |
|||
```` |
|||
|
|||
Example: |
|||
|
|||
````bash |
|||
abpc add-package-ref Acme.BookStore.Domain |
|||
abpc add-package-ref "Acme.BookStore.Domain Acme.BookStore.Domain.Shared" -t Acme.BookStore.Web |
|||
```` |
|||
|
|||
#### options |
|||
|
|||
* `--target-project` or `-t`: Name of the project that reference will be added. If not set, project in the current directory will be used. |
|||
|
|||
### add-source |
|||
|
|||
Downloads the source code of a module and replaces package references with project references. This command only works if your ABP License has source-code access, or if source-code of the target module is free to all type of ABP Licenses. |
|||
|
|||
````bash |
|||
abpc add-source <module-name> [options] |
|||
```` |
|||
|
|||
Example: |
|||
|
|||
````bash |
|||
abpc add-source Volo.Chat --add-to-solution-file |
|||
```` |
|||
|
|||
#### options |
|||
|
|||
* `--target-module` or `-t`: The module that will refer the downloaded source code. If not set, the module in the current directory will be used. |
|||
* `--add-to-solution-file`: Adds the downloaded source code to C# solution file and ABP Studio solution file. |
|||
|
|||
### init-solution |
|||
|
|||
Creates necessary files for a solution to be readable by ABP Studio. If the solution is generated via ABP Studio, you don't need this command. But it is not generated by ABP Studio, you need this command to make it work with ABP Studio. |
|||
|
|||
````bash |
|||
abpc init-solution [options] |
|||
```` |
|||
|
|||
Example: |
|||
|
|||
````bash |
|||
abpc init-solution --name Acme.BookStore |
|||
```` |
|||
|
|||
#### options |
|||
|
|||
* `--name` or `-n`: Name for the solution. If not set, it will be the same as the name of closest c# solution in the file system. |
|||
|
|||
### install-local-module |
|||
|
|||
Installs one module to another. Project relations are created according the types of the projects. For example: a `lib.domain-shared` project is added to `lib.domain-shared` project |
|||
|
|||
````bash |
|||
abpc install-local-module <module-path> [options] |
|||
```` |
|||
|
|||
Example: |
|||
|
|||
````bash |
|||
abpc install-local-module Acme.OrderManagement |
|||
|
|||
abpc install-local-module Acme.OrderManagement -t "modules/crm/Acme.Crm.abpmdl" |
|||
```` |
|||
|
|||
#### options |
|||
|
|||
* `--target-module` or `-t`: Path (or folder path) of the target module that the other module will be installed to. If not set, the closest module to the current directory will be used. |
|||
|
|||
### install-module |
|||
|
|||
Installs a module, that is published as nuget packages, to a local module. Project relations are created according the types of the projects. For example: a `lib.domain-shared` project is added to `lib.domain-shared` project |
|||
|
|||
````bash |
|||
abpc install-module <module-name> [options] |
|||
```` |
|||
|
|||
Example: |
|||
|
|||
````bash |
|||
abpc install-module Volo.Blogging |
|||
|
|||
abpc install-module Volo.Blogging -t "modules/crm/Acme.Crm.abpmdl" |
|||
```` |
|||
|
|||
#### options |
|||
|
|||
* `--target-module` or `-t`: Path (or folder path) of the target module that the other module will be installed to. If not set, the closest module to the current directory will be used. |
|||
* `--version` or `-v`: Nuget version of the module to be installed. |
|||
|
|||
### upgrade |
|||
|
|||
Upgrades the solution with Pro modules. Especially designed for users who already started their development before having a license. Therefore this command requires license. For more info, see the related document. |
|||
|
|||
````bash |
|||
abpc upgrade [options] |
|||
```` |
|||
|
|||
Example: |
|||
|
|||
````bash |
|||
abpc upgrade -t app |
|||
|
|||
abpc upgrade -t app-nolayers |
|||
```` |
|||
|
|||
#### options |
|||
|
|||
* `--template` or `-t`: The template type of the solution. Only `app` and `app-nolayers` are valid currently. |
|||
|
|||
### kube-connect |
|||
|
|||
Connects to Kubernetes cluster. Press `ctrl+c` to disconnect. |
|||
|
|||
````bash |
|||
abpc kube-connect [options] |
|||
```` |
|||
|
|||
Example: |
|||
|
|||
````bash |
|||
abpc kube-connect |
|||
|
|||
abpc kube-connect -p Default.abpk8s.json |
|||
|
|||
abpc kube-connect -c docker-desktop -ns mycrm-local |
|||
```` |
|||
|
|||
#### options |
|||
|
|||
* `--profile` or `-p`: Kubernetes Profile path or name to be used. Path can be relative (to current directory) or full path, or you can simply give the name of profile if you run this command in same directory with the solution or profile. This parameter is not needed if you use `--namespace` and `--context` parameters. |
|||
* `--namespace` or `-ns`: The namespace that services running on. |
|||
* `--context` or `-c`: The context that services running in. |
|||
* `--wireguard-password` or `-wp`: Wireguard password for the profile. This is not needed if you already set it on the ABP Studio user interface. |
|||
* `--solution-id` or `-si`: Id of the solution. If not set, the closest solution in file system will be used. |
|||
|
|||
### kube-intercept |
|||
|
|||
Intercepts a service running in Kubernetes environment. Press `ctrl+c` to stop interception. |
|||
|
|||
````bash |
|||
abpc kube-intercept <service-name> [options] |
|||
```` |
|||
|
|||
Example: |
|||
|
|||
````bash |
|||
abpc kube-intercept mycrm-product-service -ns mycrm-local |
|||
|
|||
abpc kube-intercept mycrm-product-service -ns mycrm-local -a MyCrm.ProductService.HttpApi.Host.csproj |
|||
|
|||
abpc kube-intercept mycrm-product-service -ns mycrm-local -a MyCrm.ProductService.HttpApi.Host.csproj -pm 8080:80,8081:443 |
|||
```` |
|||
|
|||
#### options |
|||
|
|||
* `--application` or `-a`: Relative or full path of the project that will intercept the service. If not set, the project in the current directory will be used. |
|||
* `--namespace` or `-ns`: The namespace that service running on. |
|||
* `--context` or `-sc`: The context that service running in. Default value is `docker-desktop`. |
|||
* `--port-mappings` or `-pm`: Port mappings for the service. |
|||
|
|||
## See Also |
|||
|
|||
* [ABP CLI](../cli) |
|||
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 16 KiB |
@ -0,0 +1,35 @@ |
|||
using System.Linq; |
|||
using System.Security.Claims; |
|||
using System.Threading.Tasks; |
|||
using Microsoft.AspNetCore.Authentication; |
|||
using Microsoft.Extensions.Options; |
|||
|
|||
namespace Volo.Abp.AspNetCore.Security.Claims; |
|||
|
|||
public class AbpClaimsTransformation : IClaimsTransformation |
|||
{ |
|||
protected IOptions<AbpClaimsMapOptions> AbpClaimsMapOptions { get; } |
|||
|
|||
public AbpClaimsTransformation(IOptions<AbpClaimsMapOptions> abpClaimsMapOptions) |
|||
{ |
|||
AbpClaimsMapOptions = abpClaimsMapOptions; |
|||
} |
|||
|
|||
public virtual Task<ClaimsPrincipal> TransformAsync(ClaimsPrincipal principal) |
|||
{ |
|||
var mapClaims = principal.Claims.Where(claim => AbpClaimsMapOptions.Value.Maps.Keys.Contains(claim.Type)); |
|||
|
|||
principal.AddIdentity(new ClaimsIdentity(mapClaims.Select( |
|||
claim => new Claim( |
|||
AbpClaimsMapOptions.Value.Maps[claim.Type](), |
|||
claim.Value, |
|||
claim.ValueType, |
|||
claim.Issuer |
|||
) |
|||
) |
|||
) |
|||
); |
|||
|
|||
return Task.FromResult(principal); |
|||
} |
|||
} |
|||
@ -0,0 +1,68 @@ |
|||
using System; |
|||
using System.Security.Claims; |
|||
using System.Text.Encodings.Web; |
|||
using System.Threading.Tasks; |
|||
using DeviceDetectorNET; |
|||
using Microsoft.AspNetCore.Authentication; |
|||
using Microsoft.Extensions.Logging; |
|||
using Microsoft.Extensions.Options; |
|||
|
|||
namespace Volo.Abp.AspNetCore.Mvc; |
|||
|
|||
public static class FakeAuthenticationSchemeDefaults |
|||
{ |
|||
public static string Scheme => "FakeAuthenticationScheme"; |
|||
} |
|||
|
|||
public static class FakeAuthenticationBuilderExtensions |
|||
{ |
|||
public static AuthenticationBuilder AddFakeAuthentication(this AuthenticationBuilder builder) |
|||
{ |
|||
return builder.AddScheme<FakeAuthenticationOptions, FakeAuthenticationHandler>(FakeAuthenticationSchemeDefaults.Scheme, _ => { }); |
|||
} |
|||
} |
|||
|
|||
public class FakeAuthenticationOptions : AuthenticationSchemeOptions |
|||
{ |
|||
|
|||
} |
|||
|
|||
public class FakeAuthenticationHandler : AuthenticationHandler<FakeAuthenticationOptions> |
|||
{ |
|||
private readonly FakeUserClaims _fakeUserClaims; |
|||
|
|||
[Obsolete] |
|||
public FakeAuthenticationHandler( |
|||
IOptionsMonitor<FakeAuthenticationOptions> options, |
|||
ILoggerFactory logger, |
|||
UrlEncoder encoder, |
|||
ISystemClock clock, |
|||
FakeUserClaims fakeUserClaims) : base(options, logger, encoder, clock) |
|||
{ |
|||
_fakeUserClaims = fakeUserClaims; |
|||
} |
|||
|
|||
public FakeAuthenticationHandler( |
|||
IOptionsMonitor<FakeAuthenticationOptions> options, |
|||
ILoggerFactory logger, |
|||
UrlEncoder encoder, |
|||
FakeUserClaims fakeUserClaims) |
|||
: base(options, logger, encoder) |
|||
{ |
|||
_fakeUserClaims = fakeUserClaims; |
|||
} |
|||
|
|||
protected override Task<AuthenticateResult> HandleAuthenticateAsync() |
|||
{ |
|||
if (_fakeUserClaims.Claims.Any()) |
|||
{ |
|||
return Task.FromResult(AuthenticateResult.Success( |
|||
new AuthenticationTicket( |
|||
new ClaimsPrincipal(new ClaimsIdentity(_fakeUserClaims.Claims, |
|||
FakeAuthenticationSchemeDefaults.Scheme)), |
|||
FakeAuthenticationSchemeDefaults.Scheme))); |
|||
} |
|||
|
|||
return Task.FromResult(AuthenticateResult.NoResult()); |
|||
} |
|||
} |
|||