112 Commits

Author SHA1 Message Date
Developer01
286e17a900 layout specihern 2025-07-18 15:42:07 +02:00
Developer01
a21db6d6c5 Button AccessCode manuell versenden 2025-07-15 07:27:01 +02:00
Developer01
fe7030b9d7 Resend AccessCode Manually 2025-07-14 15:19:05 +02:00
Developer01
888c04b5c9 EnvelopeDomain Add Comment 2025-07-14 13:45:14 +02:00
de2cc62f95 Merge branch 'master' of http://git.dd:3000/AppStd/EnvelopeGenerator 2025-07-02 14:26:08 +02:00
0cfa732d87 Fix StatusTranslated property for correct enum translation
Updated the `StatusTranslated` property to cast the `Status` integer to the `Constants.EnvelopeStatus` enum before calling `ToString()`. This ensures accurate string representation based on the enum rather than the integer value.
2025-07-02 14:25:14 +02:00
Developer01
b14d9169f2 Fild editor msgbox 2025-07-02 13:18:01 +02:00
be51ca31dd Add initial migration for database schema setup
This commit introduces the `InitialCreate` migration class, establishing the initial database schema with multiple tables including `TBDD_CLIENT_USER`, `TBDD_GROUPS`, `TBDD_MODULES`, and `TBDD_USER`. Foreign key relationships are defined to ensure referential integrity, and a `Down` method is included for rollback functionality.

Additionally, the `InitialCreate.Designer.cs` file is generated to capture the model snapshot post-migration, while the `EGDbContextModelSnapshot.cs` file is updated to reflect the current state of the database model for future migrations.
2025-07-01 17:22:13 +02:00
bb8d7cd208 Update AddedWho property in EnvelopeReceiverReadOnly
Modified the `AddedWho` property to use `nvarchar(250)`
and increased the string length constraint from 100 to 250
characters, allowing for more extensive data storage.
2025-07-01 17:17:24 +02:00
b6588db615 Increase email address length in data models
Updated `ReceiverMail` and `EmailAddress` columns to
support `nvarchar(250)` for longer email addresses.
Retained `[NotMapped]` attribute for `Envelope` in
`EnvelopeReceiverReadOnly.cs` with a note for future
standardization of `EnvelopeId` data type.
2025-07-01 17:08:30 +02:00
9a9aa2608b Refactor EnvelopeHistory and update DbContext for migrations
Removed Sender and Receiver properties from EnvelopeHistory.
Added ActionDate and Comment properties. Introduced IsMigration
property in EGDbContext to conditionally configure foreign key
relationships for EnvelopeHistory. Updated EGDbContextFactory
to set IsMigration during context creation for migration operations.
2025-07-01 16:38:42 +02:00
349d65d050 Update DbTriggerParams and EF Core package versions
- Changed DbTriggerParams to use ICollection<string> for flexibility.
- Updated Microsoft.EntityFrameworkCore.SqlServer to version 9.0.6.
- Made _logger in EGDbContext nullable and optional in constructor.
- Updated logging statements to prevent null reference exceptions.
- Added Microsoft.EntityFrameworkCore.SqlServer package for net8.0 and net9.0.
- Introduced appsettings.migration.json for connection strings and trigger parameters.
- Added EGDbContextFactory for design-time DbContext creation.
2025-07-01 13:07:40 +02:00
93593226e2 Add conditional DB connection string selection
Updated `Program.cs` to conditionally select the database connection string based on an environment variable or configuration setting. Introduced a new variable `cnnStrName` for determining the use of a migration test database.

Added a new setting `"UseDbMigration": true` in `appsettings.json` to enable the migration test database, and included the corresponding connection string as `"DbMigrationTest"`. Removed the previous `"Dev"` connection string.
2025-06-30 16:19:22 +02:00
351cead423 Update Entity Framework packages and add Design package
The project file `EnvelopeGenerator.Infrastructure.csproj` has been modified to include the `Microsoft.EntityFrameworkCore.Design` package for net7.0, net8.0, and net9.0, with appropriate configurations for `PrivateAssets` and `IncludeAssets`. Additionally, the versions of `Microsoft.EntityFrameworkCore` and `Microsoft.EntityFrameworkCore.Relational` have been updated for net8.0 (from 8.0.15 to 8.0.17) and net9.0 (from 9.0.5 to 9.0.6).
2025-06-30 15:59:35 +02:00
07cab88e0d Refactor service registration with lambda expression 2025-06-30 15:53:38 +02:00
faa019355a Add DbMigrationTest key and update connection logic
Introduced a new static readonly string `DbMigrationTest` in the `Key` class for database migration tests. Updated connection string logic in `Program.cs` to use `DbMigrationTest` when `useDbMigration` is true, allowing for dynamic connection string selection based on environment configuration.
2025-06-30 15:38:01 +02:00
df9bcf3221 Remove IUserReceiverService registration 2025-06-30 15:29:57 +02:00
cda19e2b83 Add migration support and update launch settings
Introduce `useDbMigration` variable in `Program.cs` to conditionally manage database migrations based on environment settings. Update `launchSettings.json` to include a new `httpsDbMigration` profile for testing with Swagger UI. Modify `appsettings.json` to add `UseDbMigration` setting and replace the "Dev" connection string with "DbMigrationTest" for migration testing.
2025-06-30 15:29:47 +02:00
1586009a72 Add development connection string to appsettings.json 2025-06-30 15:07:04 +02:00
408b1e9f0d Merge branch 'refactor/split-common' 2025-06-30 14:59:37 +02:00
9158933333 Refactor security key handling and culture info setup
Updated `IssuerSigningKeyResolver` to use array syntax for returning security keys. Changed supported culture names declaration to use square brackets and modified the creation of the `CultureInfo` list to utilize the spread operator. Adjusted exception handling to throw `InvalidOperationException` when no supported culture is found.
2025-06-30 14:36:55 +02:00
902848958d Refactor empty array initialization 2025-06-30 14:26:26 +02:00
f5418499a7 Refactor envelope generator service registration 2025-06-30 14:25:32 +02:00
47d190d9ea Remove UserReceiver repository registration 2025-06-30 14:23:20 +02:00
35f46d3182 Remove UserReceiver repository and related entities
This commit removes the `IUserReceiverRepository` service registration from `DIExtensions`, indicating it is no longer needed. The `UserReceiver` and `Config` DbSet properties have been eliminated from the `EGDbContext`, along with their initialization in the constructor. Additionally, the `UserReceiver` entity has been removed from the model builder configuration and the associated trigger has been deleted. These changes reflect a refactoring of the data model to simplify the architecture and improve maintainability.
2025-06-30 14:23:00 +02:00
425d21084b Refactor TestSanitizeController for improved clarity
- Updated namespace for consistency.
- Changed constructor and method parameters to non-nullable strings.
- Enhanced method signatures for `Sanitize` and `Encoder`.
- Improved overall class structure and formatting for better readability.
2025-06-30 14:13:36 +02:00
6aeba4d1e7 Deprecate methods and streamline controller code
Added [Obsolete("Use MediatR")] attribute to several methods
across `DocumentController`, `HomeController`,
`TestConfigController`, `TestDocumentReceiverElementController`,
and `TestEnvelopeController` to indicate they should no longer
be used.

Refactored constructors in `TestConfigController` and
`TestEnvelopeController` to remove unnecessary empty blocks.

Improved formatting and structure of the `GetAll` method in
`TestEnvelopeController` for better clarity while maintaining
functionality.

Updated `Program.cs` to suppress warnings about obsolete
types/members during service registrations, indicating a
transition to newer implementations.
2025-06-30 14:11:56 +02:00
6930d7a431 Mark CommandManager as obsolete; add warning suppression
Updated `CommandManager` to mark the `_envelopeReceiverService` field and its constructor as obsolete, recommending the use of `MediatR`. Added a new obsolete property `EnvelopeReceiver` for accessing the service. In `Program.cs`, added warning suppression for the obsolete member during command manager runner registration.
2025-06-30 14:07:39 +02:00
c453a1650a Suppress obsolete warnings and update auth options
Added pragma directives to suppress warnings for obsolete
types when configuring user manager and envelope generator
services. Also set a logout path and enabled sliding
expiration for authentication options.
2025-06-30 14:06:26 +02:00
b9f5ae826a Deprecate user service interfaces in controllers
Added [Obsolete] attributes to _userService in AuthController,
_repository in EmailTemplateController, and _userRepository
in EnvelopeExecutor. These changes guide developers to
transition to using MediatR and IRepository.
2025-06-30 14:05:36 +02:00
532dc41004 Remove DocumentPath, add SignatureHost to Config
Removed the `DocumentPath` property from the `Config` class. Added a new required property `SignatureHost` of type `string`, mapped to the database column `SIGNATURE_HOST` (nvarchar(128)). Other properties remain unchanged.
2025-06-30 14:01:30 +02:00
13899cf70a Refactor ConfigDto class and update properties
- Change namespace to `EnvelopeGenerator.Application.DTOs`
- Remove `DocumentPath` property
- Update `SignatureHost` to be a required string
2025-06-30 13:59:18 +02:00
9756303d6e Refactor repositories and enhance documentation
- Mark `IEmailTemplateRepository` and `_repository` in `ReadEmailTemplateQueryHandler` as obsolete, suggesting the use of `IRepository`.
- Update `ResetEmailTemplateCommand` with additional documentation and examples for `Type`.
- Change return type of `CreateEnvelopeReceiverCommand` to `IRequest<CreateEnvelopeReceiverResponse>`.
- Improve caching methods in `CacheExtensions.cs` for better functionality and clarity.
- Add XML documentation to the `Ok` method in `MappingExtensions`.
- Make `UserReference` property required in `ReadHistoryResponse`.
2025-06-30 13:56:49 +02:00
1c51fafb69 Remove UserReceiver functionality and related components
This commit marks the `IUserReceiverRepository` and `IUserReceiverService` as obsolete and removes their implementations. The `UserReceiverDto`, `UserReceiver`, `UserReceiverService`, and `UserReceiverRepository` classes have been deleted, along with their mappings in the `MappingProfile`. Additionally, the `TestUserReceiverController` has been removed, reflecting the complete removal of user receiver functionality from the codebase.
2025-06-30 13:44:43 +02:00
94d43bce24 Deprecate repositories and update service interfaces
- Marked `IEnvelopeReceiverRepository` and several repository classes as obsolete, recommending the use of `IRepository`.
- Corrected `using` directive in `IReceiverService.cs`.
- Removed `UpdateAsync` method from `IReceiverService`.
- Enhanced `ISmsSender` interface with new properties and methods.
- Updated `ReceiverCreateDto`, `ReceiverReadDto`, and `UserReceiverDto` to enforce non-nullable properties.
- Refactored `TestReceiverController` to suggest using `MediatR`.
2025-06-30 13:37:54 +02:00
f5733228bf Merge branch 'refactor/split-common' 2025-06-30 11:28:32 +02:00
e3cb2ec219 Add new library references and update packages
- Added references to `DigitalData.UserManager.Domain` v3.2.2.0, `System.ComponentModel.Annotations` v4.2.1.0, and `System.Drawing.Common` v4.0.0.2 in `EnvelopeGenerator.Form.vbproj`.
- Updated `packages.config` to include `System.ComponentModel.Annotations` v4.7.0, `System.Drawing.Common` v4.7.3, and `UserManager.Domain` v3.2.2.
2025-06-30 11:27:26 +02:00
Developer01
260c1c174d Merge Master 2025-06-30 11:26:46 +02:00
1c90e693da Deprecate services in favor of MediatR integration
This commit introduces the `[Obsolete("Use MediatR")]` attribute to various service fields and methods across multiple controllers and extension classes, signaling a transition to MediatR for handling requests and commands.

Key changes include:
- Marking `IEnvelopeService`, `IEnvelopeReceiverService`, and `IEnvelopeTypeService` as obsolete in their respective controllers.
- Updating `AddEnvelopeGeneratorInfrastructureServices` to utilize `IRepository`.
- Refactoring `AddCommandManagerRunner` and `CreateHost` methods to indicate obsolescence.
- Replacing `DigitalData.Core.DTO` with `DigitalData.Core.Abstraction.Application.DTO` in using directives.

These changes modernize the codebase and improve command and query handling while cleaning up service dependencies.
2025-06-30 10:05:36 +02:00
e4c6714677 Behebung von Post-Merge-Fehlern.
- CommonServices in den Ordner core verschieben
2025-06-27 14:51:50 +02:00
812b49cfcb Merge master branch 2025-06-27 14:43:47 +02:00
f039437f4c Merge master branch 2025-06-27 14:43:02 +02:00
6f73ba929c Refactor controllers and update envelope status handling
- Updated `TestEnvelopeHistoryController` to use `EnvelopeStatus` for status parameters and marked it as obsolete.
- Modified `TestViewController` with new route attributes, simplified constructor, and improved error handling in HTTP methods.
- Cleaned up `DebugEnvelopes.cshtml` by removing unnecessary using directives and ensuring type safety in envelope grouping.
2025-06-27 13:51:51 +02:00
fcbe956095 Refactor controllers and views for MediatR integration
Updated several C# controllers to use the new
`DigitalData.Core.Abstraction.Application.DTO` namespace
and removed references to `DigitalData.Core.DTO`. Added
`[Obsolete("Use MediatR")]` attributes to indicate a shift
towards MediatR for request handling. Improved error
handling and code organization in key methods. Updated
Razor view files to reflect namespace changes for
consistency across the application.
2025-06-27 13:24:12 +02:00
e628309734 Refactor TestEnvelopeMailController for clarity
Updated using directives, added Obsolete attributes, and improved error handling in SendAccessCode method. Enhanced code clarity while preserving overall structure.
2025-06-27 13:14:14 +02:00
d6cbd0597e Mark TestEnvelopeDocumentController as obsolete
The `TestEnvelopeDocumentController` class has been marked as obsolete, with a recommendation to use MediatR instead. This change reflects a shift in the architecture, promoting the use of MediatR for handling requests and responses in the application.
2025-06-27 13:12:14 +02:00
9d45082bfc Refactor TestEmailTemplateController and update namespaces
- Updated `using` directives to include new namespaces.
- Marked `TestEmailTemplateController` as obsolete with a suggestion to use MediatR.
- Simplified the constructor by removing an empty block.
- Modified `GetAll` method to include `[HttpGet]` and `[Obsolete]` attributes while retaining functionality.
- Added a non-action `GetAll` method that overrides the base implementation.
2025-06-27 13:11:40 +02:00
3304b01d7b Refactor TestDocumentStatusController
Added [Obsolete] attribute to indicate replacement with MediatR. Updated constructor to include logger parameter and removed empty constructor body for clarity.
2025-06-27 13:09:13 +02:00
f5d33846d5 Refactor TestControllerBase and update using directives
Consolidated using directives and removed unnecessary ones.
Added attributes to the namespace declaration for API routing
and deprecation notice. Simplified the class definition by
removing the IUnique<TId> constraint and cleaned up the
constructor by eliminating empty braces.
2025-06-27 12:13:13 +02:00
231140505e Refactor ReadOnlyController to use MediatR
Updated service dependencies to use MediatR, marking
several fields and methods as obsolete. Modified import
statements to include new namespaces and removed old
ones. Adjusted the CreateAsync method to correctly
access IDs and updated the RecordAsync call to use
the new EnvelopeStatus reference. These changes
enhance code maintainability and align with modern
architectural patterns.
2025-06-27 12:08:30 +02:00
62a73e4967 Refactor HomeController for MediatR and domain model
- Added new using directives for domain-driven design.
- Marked several fields and methods as obsolete to transition to MediatR for request handling.
- Updated action methods to use middleware for exception management.
- Changed response type in EnvelopeSigned method for consistency with new domain model.
- Overall improvements for maintainability and adherence to best practices.
2025-06-27 12:06:41 +02:00
dedfb924d8 Refactor EnvelopeController and EnvelopeOldService
Significantly refactored `EnvelopeController.cs` to improve structure, add logging, and enhance error handling in methods. Introduced new private fields and updated constructor parameters, with some marked as obsolete.

Updated `EnvelopeOldService.cs` to add private fields, improve logging, and enhance error handling in key methods. Introduced `ReceiverAlreadySigned` method and marked `GetDocument` as obsolete. Improved overall functionality and maintainability.
2025-06-27 10:59:52 +02:00
08601adc49 Refactor DocumentController for clarity and updates
Updated the DocumentController to use new namespace for constants and added a directive for domain entities. Marked the constructor as obsolete for future MediatR implementation. Refactored Get and Open methods to enhance readability by simplifying error handling. Maintained authorization attributes in their original positions.
2025-06-27 10:26:56 +02:00
2a4255e5a3 Refactor status parameter to use EnvelopeStatus type
Updated IEnvelopeHistoryRepository and IEnvelopeHistoryService
interfaces to replace int? status with Constants.EnvelopeStatus?
status in CountAsync and ReadAsync methods. Adjusted
ReadHistoryQueryHandler and EnvelopeHistoryService methods to
accommodate the new type. Modified EnvelopeHistoryRepository
to accept Constants.EnvelopeStatus? in relevant methods and
marked it as obsolete, suggesting a future refactor.
2025-06-27 09:17:03 +02:00
0800e4d13e refacto(EGUser): rename FormUser 2025-06-26 16:49:56 +02:00
07381e78b4 Refactor name retrieval to use GetFullName method
Updated the `CertificateModel.vb` and `EmailData.vb` files to replace direct access to the `FullName` property with the `GetFullName()` method for retrieving creator, sender, and receiver names. This change enhances flexibility and maintains consistency across the codebase.

Additionally, added a new static `GetFullName` method in the `EGUserExtensions.cs` file to centralize the formatting of user names by concatenating the `Prename` and `Name` properties.
2025-06-26 16:46:55 +02:00
5d29ad889d Refactor EGUser construction and add extension method
Removed constructors from EGUser class and introduced a new
static class EGUserExtensions with a ToEGUser extension method
to facilitate the conversion from User to EGUser. Updated
namespace imports to include DigitalData.UserManager.Domain.Entities.
2025-06-26 16:27:28 +02:00
5ee9efbcd9 Refactor user-related classes and properties
- Added parameterless and user-initializing constructors to `EGUser`.
- Removed unnecessary `using` directives and `#if NETFRAMEWORK` from `EGUser.cs`, `Envelope.cs`, and `EnvelopeHistory.cs`.
- Replaced `EGUser` property with `User` in `Envelope.cs` and `EnvelopeHistory.cs`.
- Retained default value for `CURRENT_WORK_APP` in `Envelope.cs`.
2025-06-26 16:21:22 +02:00
5c48afd8b0 Update package versions and clean up code
- Bump `UserManager` package to version `1.1.1` in
  `EnvelopeGenerator.Application.csproj` and
  `EnvelopeGenerator.Infrastructure.csproj`.
- Add reference to `DigitalData.UserManager.Domain` version
  `3.2.1.0` and `System.ComponentModel.Annotations` version
  `4.7.0` in `EnvelopeGenerator.CommonServices.vbproj`.
- Add reference to `System.Drawing.Common` version `4.7.3`
  in `EnvelopeGenerator.CommonServices.vbproj`.
- Update `UserManager.Domain` package to version `3.2.1`
  in `EnvelopeGenerator.Domain.csproj`.
- Remove unused properties from `EGUser` class in
  `EGUser.cs`.
- Mark `EnvelopeReceiverRepository` as obsolete, suggesting
  to use `Repository` instead.
- Update `packages.config` to include new package versions.
2025-06-26 16:05:16 +02:00
2dbeae24d5 Refactor property name for consistency
Updated the property name `UseridFkIntEcm` to `UserIdFkIntEcm` to adhere to a more consistent naming convention.
2025-06-26 14:27:54 +02:00
ff1e9f27af Replace User class with EGUser across the codebase
This commit introduces the new `EGUser` class, which replaces the existing `User` class in multiple files, including `EnvelopeModel.vb`, `State.vb`, and `UserModel.vb`. The `EGUser` class extends `User`, adding new properties while maintaining existing functionality.

Key changes include:
- Updated property types from `User` to `EGUser` in relevant models.
- Method signatures in `UserModel.vb` modified to accept and return `EGUser`.
- Domain entities in `Envelope.cs` and `EnvelopeHistory.cs` now reference `EGUser`.
- Complete removal of the `User.cs` file.
- Added a new package reference for `UserManager.Domain` in the project file.
- Updated `MYUSER` variable in `ModuleSettings.vb` to use `EGUser`.

These changes enhance the user model to better meet application requirements.
2025-06-26 14:26:21 +02:00
db05183137 Update package versions for UserManager and DigitalData.Core.API
- Updated `UserManager` from `1.0.0` to `1.1.0` in
  `EnvelopeGenerator.Application.csproj` and
  `EnvelopeGenerator.Infrastructure.csproj`.

- Updated `DigitalData.Core.API` from `2.2.0` to `2.2.1` in
  `EnvelopeGenerator.GeneratorAPI.csproj`,
  `EnvelopeGenerator.Tests.Application.csproj`, and
  `EnvelopeGenerator.Web.csproj`.
2025-06-26 14:17:48 +02:00
452077e86a Enhance error reporting for envelope creation failure
Added detailed parameter information to the error message
in `InvalidOperationException` for better debugging context
when envelope creation fails.
2025-06-26 11:56:49 +02:00
f8a7239041 Remove references to EnvelopeGenerator.CommonServices
Refactored multiple files to eliminate dependencies on the
EnvelopeGenerator.CommonServices namespace. This includes
removing using directives in `ReadEmailTemplateQueryHandler.cs`,
`ReadEnvelopeResponse.cs`, and `ReadHistoryResponse.cs`.
Additionally, project references to `EnvelopeGenerator.CommonServices.vbproj`
were removed from both `EnvelopeGenerator.Application.csproj` and
`EnvelopeGenerator.Extensions.csproj`, indicating a shift towards
using only the `EnvelopeGenerator.Domain` project.
2025-06-25 14:24:22 +02:00
Developer01
a1688608ab Exception TFA Null Verweis 2025-06-25 13:49:55 +02:00
72fa6fb258 Refactor EnvelopeReceiverService and update methods
- Changed return type of `ReadLastUsedReceiverNameByMailAsync` to non-nullable string.
- Marked `EnvelopeReceiverService` as obsolete; suggested using MediatR.
- Added new methods for enhanced functionality: `ReadBySignatureAsync`, `ReadByUuidAsync`, `ReadAccessCodeByUuidAsync`, `ReadByUuidSignatureAsync`, `ReadWithSecretByUuidSignatureAsync`, `ReadByEnvelopeReceiverIdAsync`, `VerifyAccessCodeAsync`, and `IsExisting`.
- Improved null handling in `ReadAccessCodeByUuidAsync` and added localized failure messages.
- Overloaded `VerifyAccessCodeAsync` to accept `envelopeReceiverId`.
- Introduced `SendSmsAsync` for sending SMS messages.
- Added `ReadWithSecretByUuidAsync` method (not yet implemented).
- Enhanced error handling in `ReadAccessCodeByIdAsync`.
- Updated `ReadByUsernameAsync` to support additional filtering parameters.
2025-06-25 11:06:19 +02:00
Developer 02
3c60f31050 Refactor: Aktualisierung von APIs und Anwendungsschichten zur Umsetzung von Änderungen im Bereich 2025-05-28 12:55:11 +02:00
Developer01
f1920e16fa MS Job 2025-05-27 14:04:45 +02:00
Developer 02
c1d46b446a refactor(EnvelopeGenerator.Common): umbenennen in EnvelopeGenerator.CommonService 2025-05-26 11:14:12 +02:00
Developer 02
a5261baec5 fix(document-model): Behandle DBNull für BYTE_DATA, um Laufzeit-Cast-Fehler zu vermeiden 2025-05-26 10:50:25 +02:00
Developer 02
3eb11311a7 refactor: DbConfig, ElementStatus, EmailData, EnvelopeReceiver und State nach Models verschieben 2025-05-26 10:49:11 +02:00
Developer 02
10b05d6301 refactor(EnvelopeHistory): ersetzt mitg als Common.Entites.EnvelopeHistory 2025-05-26 10:07:48 +02:00
Developer 02
c6fe039dd8 refactor(EnvelopeHistoryEntry): Umbenennung von EnvelopeHistoryEntry in EnvelopeHistory 2025-05-26 10:02:50 +02:00
Developer 02
1f43dff9f4 refactor(EnvelopeHistory): EnvelopeHistory aktualisiert, um EnvelopeHistoryEntry zu enthalten 2025-05-26 10:01:50 +02:00
Developer 02
dafa4f0409 refactor(Bereich): IEnumerable und ICollections auf List aktualisiert, um Fehler in VB-Projekten zur Compilerzeit zu erhalten 2025-05-26 09:54:45 +02:00
Developer 02
3625508460 refactor(Common.Entities.DocumentReceiverElement): Ersetzt durch Common.Entities.DocumentReceiverElement 2025-05-26 09:49:01 +02:00
Developer 02
7326f03a8d refactor(Common.Entities.EnvelopeDocumentElement): umbenennen in DocumentReceiverElement 2025-05-26 09:44:44 +02:00
Developer 02
35e9f6404c refactor(DocumentReceiverElement): Aktualisiert zur Aufnahme von Common.Entities.DocumentReceiverElement 2025-05-26 09:41:41 +02:00
Developer 02
dd6bc55fd6 refactor(EnvelopeDocument): Aktualisiert zur Aufnahme von Common.Entities.EnvelopeDocument 2025-05-26 09:31:38 +02:00
Developer 02
8e4266fcf6 refactor(EnvelopeDocument): Aktualisiert, um Comon.Entities.EnvelopeDocument zu enthalten 2025-05-23 11:29:20 +02:00
Developer 02
10aa857544 refactor(Form): aktualisierte Importe zur Verwendung von Domain 2025-05-22 18:01:21 +02:00
Developer 02
4fc94fc567 refactor(Common.Entities.EnvelopeType): entfernt und aktualisiert Form, um Domain.Entities.EnvelopeType zu verwenden 2025-05-22 15:39:32 +02:00
Developer 02
b83607d916 refactor(Domain.Entities.EnvelopeType): Aktualisiert, um Common.Entities.EnvelopeType zu enthalten.
- Geändert CertificationType, FinalEmailToCreator und FinalEmailToReceivers verwenden nun Enum-Typen von Constants
- Standardwerte für einige Eigenschaften hinzugefügt, um eine sicherere Initialisierung zu gewährleisten
- Einführung von NotMapped-Eigenschaften (TFA_Enabled, ExpiresWhen, ExpiresWarningWhen, ExpiresWhenDays, ExpiresWarningWhenDays) für zusätzliche Geschäftslogik ohne Datenbank-Mapping
- ToString() überschrieben, um den Titel zur einfacheren Fehlersuche und Anzeige zurückzugeben
2025-05-22 15:37:41 +02:00
Developer 02
a38c2cd956 refactor(Common): Ersetzen Sie Envelope und Receiver durch Domain.Entities 2025-05-22 14:13:08 +02:00
Developer 02
502c607ebd fix(Comon): Mehrdeutigkeiten aufgrund von Domain.Helpers behoben 2025-05-22 10:13:32 +02:00
Developer 02
39c1d3e624 Add helper methods for color conversion and string checksum generation
- Implemented ToColor extension method to convert predefined ColorType enums to HTML hex colors.
- Added GetChecksum extension method to generate a SHA-256 checksum from a string.
- Included conditional directive for .NET Framework compatibility.
2025-05-21 19:52:58 +02:00
Developer 02
39cc30f48b feat(Receiver): Entsprechend aktualisiert, um die Eigenschaften der Formularanwendung einzubeziehen 2025-05-21 19:31:59 +02:00
Developer 02
79204d4f6d refactor(EnvelopeStatus): umbenennen in EnvelopeReceiver 2025-05-21 18:43:48 +02:00
Developer 02
806b990556 refactor(EnvelopeReceiver): unbenutzte Eigenschaften entfernen und in Receiver umbenennen 2025-05-21 18:41:42 +02:00
Developer 02
d34a1016c4 refactor(Envelope): Eigenschaft StatusTranslated hinzufügen 2025-05-21 18:25:10 +02:00
Developer 02
93dbe63fb4 refactor(Domain.Entites.Envelope): Aktualisiert, um Common.Entities.Envelope zu enthalten 2025-05-21 18:18:40 +02:00
Developer 02
55ffe40c46 Hinzufügen des Attributs Obsolete zu ElementStatus und zugehörigen Methoden 2025-05-21 17:05:52 +02:00
Developer 02
be9516d852 refactor(Domain.Entites.DocumentStatus): Ersetzt durch Common.Entites.DocumentStatus 2025-05-21 15:28:10 +02:00
Developer 02
12502bb2de refactor(EmailMetadata): Entfernt 2025-05-21 12:16:45 +02:00
Developer 02
26745e0c37 feat(Domain.EmailTemplate): Ersetzt durch Common.EmailTemplate 2025-05-21 12:12:29 +02:00
Developer 02
2ea5fd7dbb feat(Domain.User): Ersetzt durch Common.User 2025-05-21 12:08:28 +02:00
Developer 02
446aeb00b1 feat(User): Erforderliche Eigenschaften für Formular hinzugefügt 2025-05-21 11:50:58 +02:00
Developer 02
abc3bb7652 refactor(Applciation): Update Microsoft.Data.SqlClient mit bedingter Versionierung abhängig vom Framework 2025-05-21 09:59:35 +02:00
Developer 02
a8a768d7d6 refactor(.Form): Aktualisiert, um die Domain zu verwenden 2025-05-20 17:30:57 +02:00
Developer 02
31c4a8a20f chore(EnvelopeGenerator.Domain): DigitalData.EmailProfilerDispatcher.Abstraction.Attributes hinzufügen.
- Aktualisieren Sie DigitalData.EmailProfilerDispatcher & -.Abstraction in verwandten Projekten.
2025-05-20 16:59:26 +02:00
Developer 02
e98abde5ff refactor(domain): Hinzufügen von bedingten Referenzen für .net framework 2025-05-20 16:01:51 +02:00
Developer 02
49497dafd1 Update project file for framework-specific settings
Added conditional property groups in `EnvelopeGenerator.Domain.csproj` to manage `ImplicitUsings` and `LangVersion` based on the target framework. Set `ImplicitUsings` to `disable` and `LangVersion` to `7.3` for `net462`, while enabling `ImplicitUsings` and using `latest` for `net7.0`, `net8.0`, and `net9.0`.
2025-05-20 15:50:39 +02:00
Developer 02
08e1187124 Refactor namespaces and simplify DTOs
Updated namespaces to align with the new DigitalData.Core structure, replacing `DigitalData.Core.Abstractions` with `DigitalData.Core.Application.Interfaces` and `DigitalData.Core.Client.Interface`. Removed the `IUnique<int>` interface from several DTOs, simplifying their design and altering the handling of entity identification. Updated project files to reflect new dependency versions for improved compatibility and features. Cleaned up using directives to remove obsolete references, enhancing code maintainability.
2025-05-20 15:14:58 +02:00
Developer 02
1b923dc93b Update DigitalData.Core package references
Updated `DigitalData.Core.Abstractions` to version `4.0.0` and `DigitalData.Core.Application` to version `3.3.0` across multiple project files. Also upgraded `DigitalData.Core.Infrastructure` to version `2.1.0` in `Infrastructure.csproj`. These changes may include important bug fixes, new features, and performance improvements.
2025-05-20 10:58:57 +02:00
Developer 02
bdf2527fc1 Refactor using directives and add User entity
- Updated `using` directives in `Config.cs` and `EnvelopeType.cs` to include additional namespaces and removed `DigitalData.Core.Abstractions`.
- Adjusted formatting for `StatusName` and `IsAlreadySent` properties in `Envelope.cs` for consistency.
- Simplified `User` property in `Envelope.cs` by removing the namespace prefix.
- Introduced a new `User` class in `User.cs` with various properties and data annotations for database mapping.
- Removed the `<Nullable>` property from `EnvelopeGenerator.Domain.csproj`, which may impact nullability handling.
2025-05-16 09:56:44 +02:00
Developer 02
1a69478f48 Refactor entity classes for non-nullable properties
Removed nullable types and `init` properties, replacing them with standard getters and setters in various entity classes. Updated properties like `DocumentPath`, `SendingProfile`, and `SignatureHost` to be non-nullable and added required attributes.

Modified the project file to include `net462` as a target framework and added a reference for `System.ComponentModel.Annotations`. Removed the `IUnique<int>` interface from several classes to simplify uniqueness management.

These changes improve data integrity and usability across the entity classes.
2025-05-14 09:16:02 +02:00
Developer 02
83d29bf78d Add EmailProfilerDispatcher and enhance logging
Included the DigitalData.EmailProfilerDispatcher namespace in Program.cs for email profiling functionality. Removed Microsoft.Extensions.DependencyInjection namespace to streamline dependency management. Enhanced logging configuration by adding EnableDetailedErrors() for improved error messages during development while retaining EnableSensitiveDataLogging().
2025-05-13 13:44:13 +02:00
Developer 02
bc45aadf27 Refactor RecordAsync object initialization
Updated the `RecordAsync` method in the `EnvelopeHistoryService` class to use an explicit object initializer with braces for creating a new object in the `CreateAsync` method. This change improves code clarity while maintaining the same functionality.
2025-05-13 11:21:01 +02:00
Developer 02
7e66cd4dae Refactor DTOs for improved structure and documentation
Transitioned from records to classes for flexibility, added XML documentation for clarity, and updated property definitions to use standard getters and setters. Introduced the `required` keyword for essential properties, removed unnecessary constructors, and enhanced property descriptions for better readability. Additionally, overridden `GetHashCode` in `ReceiverReadDto` for proper collection behavior.
2025-05-13 11:05:43 +02:00
Developer 02
cc11d70a27 Refactor DTOs to classes with enhanced properties
Changed `EnvelopeReceiverReadOnlyDto` and `EnvelopeReceiverReadOnlyUpdateDto` from records to classes, converting properties to standard get/set accessors and adding documentation comments. Introduced a default value for `ChangedWhen` in `EnvelopeReceiverReadOnlyUpdateDto`.

Modified `ReceiverCreateDto` to a class structure, updating properties to use init-only accessors and encapsulating SHA256 hash logic in a private field. Retained the `AddedWhen` property with its default value.
2025-05-13 09:56:56 +02:00
Developer 02
02aeaea8a9 Refactor EnvelopeHistoryDto to use properties
The EnvelopeHistoryDto class has been changed from a record type with positional parameters to a traditional class structure with explicit properties. This refactor improves readability and maintainability, and includes XML documentation for each property. The GetHashCode method has also been overridden to ensure uniqueness based on the Id property.
2025-05-12 16:36:21 +02:00
Developer 02
05867cc645 Update DIExtensions for enhanced DbContext configuration
Modified the `AddEnvelopeGeneratorInfrastructureServices` method to accept a service provider, allowing for more complex DbContext configurations. Added a using directive for `Microsoft.Extensions.DependencyInjection` in `Program.cs`. Updated the method call to utilize the new signature, enabling logging of SQL commands and sensitive data during database operations.
2025-05-12 16:35:48 +02:00
304 changed files with 11479 additions and 2900 deletions

View File

@@ -1,19 +1,33 @@
namespace EnvelopeGenerator.Application.Configurations
namespace EnvelopeGenerator.Application.Configurations;
/// <summary>
///
/// </summary>
public class AuthenticatorParams
{
public class AuthenticatorParams
{
public string CharPool { get; init; } = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz01234567890123456789012345678901234567890123456789";
/// <summary>
/// Default value is 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz01234567890123456789012345678901234567890123456789'
/// </summary>
public string CharPool { get; init; } = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz01234567890123456789012345678901234567890123456789";
//TODO: Increase the DefaultTotpSecretKeyLength (e.g. to 32) but make sure that the QR code is generated correctly and can be scanned by the authenticator.
public int DefaultTotpSecretKeyLength { get; init; } = 20;
//TODO: Increase the DefaultTotpSecretKeyLength (e.g. to 32) but make sure that the QR code is generated correctly and can be scanned by the authenticator.
/// <summary>
/// Default value is 20
/// </summary>
public int DefaultTotpSecretKeyLength { get; init; } = 20;
public string TotpIssuer { get; init; } = "signFlow";
/// <summary>
/// Default value is
/// </summary>
public string TotpIssuer { get; init; } = "signFlow";
/// <summary>
/// 0 is user email, 1 is secret key and 2 is issuer.
/// </summary>
public string TotpUrlFormat { get; init; } = "otpauth://totp/{0}?secret={1}&issuer={2}";
/// <summary>
/// 0 is user email, 1 is secret key and 2 is issuer.
/// </summary>
public string TotpUrlFormat { get; init; } = "otpauth://totp/{0}?secret={1}&issuer={2}";
public int TotpQRPixelsPerModule { get; init; } = 20;
}
/// <summary>
/// Default value is 20.
/// </summary>
public int TotpQRPixelsPerModule { get; init; } = 20;
}

View File

@@ -1,5 +1,8 @@
namespace EnvelopeGenerator.Application.Configurations;
public class DbTriggerParams : Dictionary<string, IEnumerable<string>>
/// <summary>
///
/// </summary>
public class DbTriggerParams : Dictionary<string, ICollection<string>>
{
}
}

View File

@@ -1,12 +1,27 @@
namespace EnvelopeGenerator.Application.Configurations;
/// <summary>
///
/// </summary>
public class DispatcherParams
{
/// <summary>
/// Default value is 1
/// </summary>
public int SendingProfile { get; init; } = 1;
/// <summary>
/// Defalt value is 'DDEnvelopGenerator'
/// </summary>
public string AddedWho { get; init; } = "DDEnvelopGenerator";
/// <summary>
/// Default value is 202377
/// </summary>
public int ReminderTypeId { get; init; } = 202377;
/// <summary>
/// Default value is string.Empty
/// </summary>
public string EmailAttmt1 { get; init; } = string.Empty;
}

View File

@@ -1,4 +1,4 @@
using DigitalData.Core.Abstractions.Client;
using DigitalData.Core.Client.Interface;
namespace EnvelopeGenerator.Application.Configurations;
/// <summary>
@@ -6,15 +6,32 @@ namespace EnvelopeGenerator.Application.Configurations;
/// </summary>
public class GtxMessagingParams : IHttpClientOptions
{
/// <summary>
///
/// </summary>
public required string Uri { get; init; }
/// <summary>
///
/// </summary>
public string? Path { get; init; }
/// <summary>
///
/// </summary>
public Dictionary<string, object>? Headers { get; init; }
/// <summary>
///
/// </summary>
public Dictionary<string, object?>? QueryParams { get; init; }
/// <summary>
/// Default value is 'to'
/// </summary>
public string RecipientQueryParamName { get; init; } = "to";
/// <summary>
/// Default value is 'text'
/// </summary>
public string MessageQueryParamName { get; init; } = "text";
}

View File

@@ -1,6 +1,12 @@
namespace EnvelopeGenerator.Application.Configurations;
/// <summary>
///
/// </summary>
public class MailParams
{
/// <summary>
///
/// </summary>
public required Dictionary<string, string> Placeholders { get; init; }
}

View File

@@ -1,49 +1,81 @@
using OtpNet;
using System.Globalization;
namespace EnvelopeGenerator.Application.Configurations
namespace EnvelopeGenerator.Application.Configurations;
/// <summary>
///
/// </summary>
public class TotpSmsParams
{
public class TotpSmsParams
/// <summary>
/// The unit is second.
/// </summary>
public int TotpStep { get; init; } = 90;
/// <summary>
/// Default value is 'Ihr 2FA-Passwort lautet {0}. Gültig bis {1}'
/// </summary>
public string Format { get; init; } = "Ihr 2FA-Passwort lautet {0}. Gültig bis {1}";
/// <summary>
///
/// </summary>
public ExpirationHandler Expiration { get; init; } = new();
/// <summary>
/// Default value is VerificationWindow.RfcSpecifiedNetworkDelay
/// </summary>
public VerificationWindow? TotpVerificationWindow { get; private init; } = VerificationWindow.RfcSpecifiedNetworkDelay;
private IEnumerable<int>? _tvwParams;
/// <summary>
///
/// </summary>
public IEnumerable<int>? TotpVerificationWindowParams
{
/// <summary>
/// The unit is second.
/// </summary>
public int TotpStep { get; init; } = 90;
public string Format { get; init; } = "Ihr 2FA-Passwort lautet {0}. Gültig bis {1}";
public ExpirationHandler Expiration { get; init; } = new();
public VerificationWindow? TotpVerificationWindow { get; private init; } = VerificationWindow.RfcSpecifiedNetworkDelay;
private IEnumerable<int>? _tvwParams;
public IEnumerable<int>? TotpVerificationWindowParams
get => _tvwParams;
init
{
get => _tvwParams;
init
{
_tvwParams = value;
if(_tvwParams is not null)
TotpVerificationWindow = new(previous: _tvwParams.ElementAtOrDefault(0), future: _tvwParams.ElementAtOrDefault(0));
}
}
public class ExpirationHandler
{
public string CacheKeyFormat { get; init; } = "e{0}_r{1}_sms_code_expiration";
public string Format { get; init; } = "HH:mm:ss";
public string CultureName
{
get => _cultureInfo.Name;
init => _cultureInfo = new(value);
}
private CultureInfo _cultureInfo = new("de-DE");
public CultureInfo CultureInfo => _cultureInfo;
_tvwParams = value;
if(_tvwParams is not null)
TotpVerificationWindow = new(previous: _tvwParams.ElementAtOrDefault(0), future: _tvwParams.ElementAtOrDefault(0));
}
}
/// <summary>
///
/// </summary>
public class ExpirationHandler
{
/// <summary>
/// Default value is 'e{0}_r{1}_sms_code_expiration'
/// </summary>
public string CacheKeyFormat { get; init; } = "e{0}_r{1}_sms_code_expiration";
/// <summary>
/// Default value is HH:mm:ss
/// </summary>
public string Format { get; init; } = "HH:mm:ss";
/// <summary>
/// Default value is 'de-DE'
/// </summary>
public string CultureName
{
get => _cultureInfo.Name;
init => _cultureInfo = new(value);
}
/// <summary>
/// Default value is 'de-DE'
/// </summary>
private CultureInfo _cultureInfo = new("de-DE");
/// <summary>
/// Default value is 'de-DE'
/// </summary>
public CultureInfo CultureInfo => _cultureInfo;
}
}

View File

@@ -1,9 +1,17 @@
using DigitalData.Core.Abstractions.Infrastructure;
using DigitalData.Core.Abstraction.Application.Repository;
using EnvelopeGenerator.Domain.Entities;
namespace EnvelopeGenerator.Application.Contracts.Repositories;
/// <summary>
///
/// </summary>
[Obsolete("Use IRepository")]
public interface IConfigRepository : ICRUDRepository<Config, int>
{
/// <summary>
///
/// </summary>
/// <returns></returns>
Task<Config?> ReadFirstAsync();
}

View File

@@ -1,8 +1,11 @@
using DigitalData.Core.Abstractions.Infrastructure;
using DigitalData.Core.Abstraction.Application.Repository;
using EnvelopeGenerator.Domain.Entities;
namespace EnvelopeGenerator.Application.Contracts.Repositories;
/// <summary>
///
/// </summary>
[Obsolete("Use IRepository")]
public interface IDocumentReceiverElementRepository : ICRUDRepository<DocumentReceiverElement, int>
{
}

View File

@@ -1,8 +1,12 @@
using DigitalData.Core.Abstractions.Infrastructure;
using DigitalData.Core.Abstraction.Application.Repository;
using EnvelopeGenerator.Domain.Entities;
namespace EnvelopeGenerator.Application.Contracts.Repositories;
/// <summary>
///
/// </summary>
[Obsolete("Use IRepository")]
public interface IDocumentStatusRepository : ICRUDRepository<DocumentStatus, int>
{
}

View File

@@ -1,10 +1,19 @@
using DigitalData.Core.Abstractions.Infrastructure;
using DigitalData.Core.Abstraction.Application.Repository;
using EnvelopeGenerator.Domain.Entities;
using static EnvelopeGenerator.Common.Constants;
using static EnvelopeGenerator.Domain.Constants;
namespace EnvelopeGenerator.Application.Contracts.Repositories;
/// <summary>
///
/// </summary>
[Obsolete("Use IRepository")]
public interface IEmailTemplateRepository : ICRUDRepository<EmailTemplate, int>
{
/// <summary>
///
/// </summary>
/// <param name="type"></param>
/// <returns></returns>
Task<EmailTemplate?> ReadByNameAsync(EmailTemplateType type);
}

View File

@@ -1,8 +1,12 @@
using DigitalData.Core.Abstractions.Infrastructure;
using DigitalData.Core.Abstraction.Application.Repository;
using EnvelopeGenerator.Domain.Entities;
namespace EnvelopeGenerator.Application.Contracts.Repositories;
/// <summary>
///
/// </summary>
[Obsolete("Use Read-method returning IReadQuery<TEntity> instead.")]
public interface IEnvelopeCertificateRepository : ICRUDRepository<EnvelopeCertificate, int>
{
}

View File

@@ -1,8 +1,12 @@
using DigitalData.Core.Abstractions.Infrastructure;
using DigitalData.Core.Abstraction.Application.Repository;
using EnvelopeGenerator.Domain.Entities;
namespace EnvelopeGenerator.Application.Contracts.Repositories;
/// <summary>
///
/// </summary>
[Obsolete("Use IRepository")]
public interface IEnvelopeDocumentRepository : ICRUDRepository<EnvelopeDocument, int>
{
}

View File

@@ -1,11 +1,32 @@
using DigitalData.Core.Abstractions.Infrastructure;
using DigitalData.Core.Abstraction.Application.Repository;
using EnvelopeGenerator.Domain;
using EnvelopeGenerator.Domain.Entities;
namespace EnvelopeGenerator.Application.Contracts.Repositories;
/// <summary>
///
/// </summary>
[Obsolete("Use IRepository")]
public interface IEnvelopeHistoryRepository : ICRUDRepository<EnvelopeHistory, long>
{
Task<int> CountAsync(int? envelopeId = null, string? userReference = null, int? status = null);
/// <summary>
///
/// </summary>
/// <param name="envelopeId"></param>
/// <param name="userReference"></param>
/// <param name="status"></param>
/// <returns></returns>
Task<int> CountAsync(int? envelopeId = null, string? userReference = null, Constants.EnvelopeStatus? status = null);
Task<IEnumerable<EnvelopeHistory>> ReadAsync(int? envelopeId = null, string? userReference = null, int? status = null, bool withSender = false, bool withReceiver = false);
/// <summary>
///
/// </summary>
/// <param name="envelopeId"></param>
/// <param name="userReference"></param>
/// <param name="status"></param>
/// <param name="withSender"></param>
/// <param name="withReceiver"></param>
/// <returns></returns>
Task<IEnumerable<EnvelopeHistory>> ReadAsync(int? envelopeId = null, string? userReference = null, Constants.EnvelopeStatus? status = null, bool withSender = false, bool withReceiver = false);
}

View File

@@ -1,8 +1,12 @@
using DigitalData.Core.Abstractions.Infrastructure;
using DigitalData.Core.Abstraction.Application.Repository;
using EnvelopeGenerator.Domain.Entities;
namespace EnvelopeGenerator.Application.Contracts.Repositories;
/// <summary>
///
/// </summary>
[Obsolete("Use IRepository")]
public interface IEnvelopeReceiverReadOnlyRepository : ICRUDRepository<EnvelopeReceiverReadOnly, long>
{
}

View File

@@ -1,25 +1,96 @@
using DigitalData.Core.Abstractions.Infrastructure;
using DigitalData.Core.Abstraction.Application.Repository;
using EnvelopeGenerator.Domain.Entities;
namespace EnvelopeGenerator.Application.Contracts.Repositories;
/// <summary>
///
/// </summary>
[Obsolete("Use IRepository")]
public interface IEnvelopeReceiverRepository : ICRUDRepository<EnvelopeReceiver, (int Envelope, int Receiver)>
{
/// <summary>
///
/// </summary>
/// <param name="uuid"></param>
/// <param name="withEnvelope"></param>
/// <param name="withReceiver"></param>
/// <param name="readOnly"></param>
/// <returns></returns>
Task<IEnumerable<EnvelopeReceiver>> ReadByUuidAsync(string uuid, bool withEnvelope = true, bool withReceiver = false, bool readOnly = true);
/// <summary>
///
/// </summary>
/// <param name="signature"></param>
/// <param name="withEnvelope"></param>
/// <param name="withReceiver"></param>
/// <param name="readOnly"></param>
/// <returns></returns>
Task<IEnumerable<EnvelopeReceiver>> ReadBySignatureAsync(string signature, bool withEnvelope = false, bool withReceiver = true, bool readOnly = true);
/// <summary>
///
/// </summary>
/// <param name="uuid"></param>
/// <param name="signature"></param>
/// <param name="withEnvelope"></param>
/// <param name="withReceiver"></param>
/// <param name="readOnly"></param>
/// <returns></returns>
Task<EnvelopeReceiver?> ReadByUuidSignatureAsync(string uuid, string signature, bool withEnvelope = true, bool withReceiver = true, bool readOnly = true);
/// <summary>
///
/// </summary>
/// <param name="uuid"></param>
/// <param name="signature"></param>
/// <param name="readOnly"></param>
/// <returns></returns>
Task<string?> ReadAccessCodeAsync(string uuid, string signature, bool readOnly = true);
/// <summary>
///
/// </summary>
/// <param name="uuid"></param>
/// <param name="signature"></param>
/// <returns></returns>
Task<int> CountAsync(string uuid, string signature);
/// <summary>
///
/// </summary>
/// <param name="envelopeId"></param>
/// <param name="receiverId"></param>
/// <param name="readOnly"></param>
/// <returns></returns>
Task<EnvelopeReceiver?> ReadByIdAsync(int envelopeId, int receiverId, bool readOnly = true);
/// <summary>
///
/// </summary>
/// <param name="envelopeId"></param>
/// <param name="receiverId"></param>
/// <param name="readOnly"></param>
/// <returns></returns>
Task<string?> ReadAccessCodeByIdAsync(int envelopeId, int receiverId, bool readOnly = true);
/// <summary>
///
/// </summary>
/// <param name="username"></param>
/// <param name="min_status"></param>
/// <param name="max_status"></param>
/// <param name="ignore_statuses"></param>
/// <returns></returns>
Task<IEnumerable<EnvelopeReceiver>> ReadByUsernameAsync(string username, int? min_status = null, int? max_status = null, params int[] ignore_statuses);
/// <summary>
///
/// </summary>
/// <param name="email"></param>
/// <param name="id"></param>
/// <param name="signature"></param>
/// <returns></returns>
Task<EnvelopeReceiver?> ReadLastByReceiverAsync(string? email = null, int? id = null, string? signature = null);
}

View File

@@ -1,13 +1,42 @@
using DigitalData.Core.Abstractions.Infrastructure;
using DigitalData.Core.Abstraction.Application.Repository;
using EnvelopeGenerator.Domain.Entities;
namespace EnvelopeGenerator.Application.Contracts.Repositories;
/// <summary>
///
/// </summary>
[Obsolete("Use IRepository")]
public interface IEnvelopeRepository : ICRUDRepository<Envelope, int>
{
/// <summary>
///
/// </summary>
/// <param name="documents"></param>
/// <param name="history"></param>
/// <param name="documentReceiverElement"></param>
/// <returns></returns>
Task<IEnumerable<Envelope>> ReadAllWithAsync(bool documents = false, bool history = false, bool documentReceiverElement = false);
/// <summary>
///
/// </summary>
/// <param name="uuid"></param>
/// <param name="withDocuments"></param>
/// <param name="withHistory"></param>
/// <param name="withDocumentReceiverElement"></param>
/// <param name="withUser"></param>
/// <param name="withAll"></param>
/// <returns></returns>
Task<Envelope?> ReadByUuidAsync(string uuid, bool withDocuments = false, bool withHistory = false, bool withDocumentReceiverElement = false, bool withUser = false, bool withAll = false);
/// <summary>
///
/// </summary>
/// <param name="userId"></param>
/// <param name="min_status"></param>
/// <param name="max_status"></param>
/// <param name="ignore_statuses"></param>
/// <returns></returns>
Task<IEnumerable<Envelope>> ReadByUserAsync(int userId, int? min_status = null, int? max_status = null, params int[] ignore_statuses);
}

View File

@@ -1,8 +1,12 @@
using DigitalData.Core.Abstractions.Infrastructure;
using DigitalData.Core.Abstraction.Application.Repository;
using EnvelopeGenerator.Domain.Entities;
namespace EnvelopeGenerator.Application.Contracts.Repositories;
/// <summary>
///
/// </summary>
[Obsolete("Use IRepository")]
public interface IEnvelopeTypeRepository : ICRUDRepository<EnvelopeType, int>
{
}
}

View File

@@ -1,9 +1,19 @@
using DigitalData.Core.Abstractions.Infrastructure;
using DigitalData.Core.Abstraction.Application.Repository;
using EnvelopeGenerator.Domain.Entities;
namespace EnvelopeGenerator.Application.Contracts.Repositories;
/// <summary>
///
/// </summary>
[Obsolete("Use IRepository")]
public interface IReceiverRepository : ICRUDRepository<Receiver, int>
{
/// <summary>
///
/// </summary>
/// <param name="emailAddress"></param>
/// <param name="signature"></param>
/// <returns></returns>
Task<Receiver?> ReadByAsync(string? emailAddress = null, string? signature = null);
}

View File

@@ -1,8 +0,0 @@
using DigitalData.Core.Abstractions.Infrastructure;
using EnvelopeGenerator.Domain.Entities;
namespace EnvelopeGenerator.Application.Contracts.Repositories;
public interface IUserReceiverRepository : ICRUDRepository<UserReceiver, int>
{
}

View File

@@ -2,17 +2,62 @@
namespace EnvelopeGenerator.Application.Contracts.Services;
/// <summary>
///
/// </summary>
public interface IAuthenticator
{
/// <summary>
///
/// </summary>
/// <param name="length"></param>
/// <returns></returns>
string GenerateCode(int length);
/// <summary>
///
/// </summary>
/// <param name="length"></param>
/// <returns></returns>
string GenerateTotpSecretKey(int? length = null);
/// <summary>
///
/// </summary>
/// <param name="userEmail"></param>
/// <param name="secretKey"></param>
/// <param name="issuer"></param>
/// <param name="totpUrlFormat"></param>
/// <param name="pixelsPerModule"></param>
/// <returns></returns>
byte[] GenerateTotpQrCode(string userEmail, string secretKey, string? issuer = null, string? totpUrlFormat = null, int? pixelsPerModule = null);
/// <summary>
///
/// </summary>
/// <param name="userEmail"></param>
/// <param name="length"></param>
/// <param name="issuer"></param>
/// <param name="totpUrlFormat"></param>
/// <param name="pixelsPerModule"></param>
/// <returns></returns>
byte[] GenerateTotpQrCode(string userEmail, int? length = null, string? issuer = null, string? totpUrlFormat = null, int? pixelsPerModule = null);
/// <summary>
///
/// </summary>
/// <param name="secretKey"></param>
/// <param name="step"></param>
/// <returns></returns>
string GenerateTotp(string secretKey, int step = 30);
/// <summary>
///
/// </summary>
/// <param name="totpCode"></param>
/// <param name="secretKey"></param>
/// <param name="step"></param>
/// <param name="window"></param>
/// <returns></returns>
bool VerifyTotp(string totpCode, string secretKey, int step = 30, VerificationWindow? window = null);
}

View File

@@ -1,16 +1,31 @@
using DigitalData.Core.Abstractions.Application;
using DigitalData.Core.DTO;
using DigitalData.Core.Abstraction.Application;
using DigitalData.Core.Abstraction.Application.DTO;
using EnvelopeGenerator.Application.DTOs;
using EnvelopeGenerator.Domain.Entities;
namespace EnvelopeGenerator.Application.Contracts.Services;
/// <summary>
///
/// </summary>
[Obsolete("Use MediatR")]
public interface IConfigService : IReadService<ConfigDto, Config, int>
{
/// <summary>
///
/// </summary>
/// <returns></returns>
Task<DataResult<ConfigDto>> ReadFirstAsync();
/// <summary>
///
/// </summary>
/// <returns></returns>
Task<ConfigDto> ReadDefaultAsync();
/// <summary>
///
/// </summary>
/// <returns></returns>
Task<string> ReadDefaultSignatureHost();
}

View File

@@ -1,9 +1,13 @@
using DigitalData.Core.Abstractions.Application;
using DigitalData.Core.Abstraction.Application;
using EnvelopeGenerator.Application.DTOs;
using EnvelopeGenerator.Domain.Entities;
namespace EnvelopeGenerator.Application.Contracts.Services;
/// <summary>
///
/// </summary>
[Obsolete("Use MediatR")]
public interface IDocumentReceiverElementService : IBasicCRUDService<DocumentReceiverElementDto, DocumentReceiverElement, int>
{
}

View File

@@ -1,8 +1,12 @@
using DigitalData.Core.Abstractions.Application;
using DigitalData.Core.Abstraction.Application;
using EnvelopeGenerator.Application.DTOs;
using EnvelopeGenerator.Domain.Entities;
namespace EnvelopeGenerator.Application.Contracts.Services;
/// <summary>
///
/// </summary>
[Obsolete("Use MediatR")]
public interface IDocumentStatusService : IBasicCRUDService<DocumentStatusDto, DocumentStatus, int>
{
}

View File

@@ -1,12 +1,21 @@
using DigitalData.Core.Abstractions.Application;
using DigitalData.Core.DTO;
using DigitalData.Core.Abstraction.Application;
using DigitalData.Core.Abstraction.Application.DTO;
using EnvelopeGenerator.Application.DTOs;
using EnvelopeGenerator.Domain.Entities;
using static EnvelopeGenerator.Common.Constants;
using static EnvelopeGenerator.Domain.Constants;
namespace EnvelopeGenerator.Application.Contracts.Services;
/// <summary>
///
/// </summary>
[Obsolete("Use MediatR")]
public interface IEmailTemplateService : IBasicCRUDService<EmailTemplateDto, EmailTemplate, int>
{
/// <summary>
///
/// </summary>
/// <param name="type"></param>
/// <returns></returns>
Task<DataResult<EmailTemplateDto>> ReadByNameAsync(EmailTemplateType type);
}

View File

@@ -1,9 +1,13 @@
using DigitalData.Core.Abstractions.Application;
using DigitalData.Core.Abstraction.Application;
using EnvelopeGenerator.Application.DTOs;
using EnvelopeGenerator.Domain.Entities;
namespace EnvelopeGenerator.Application.Contracts.Services;
/// <summary>
///
/// </summary>
[Obsolete("Use MediatR")]
public interface IEnvelopeCertificateService : IBasicCRUDService<EnvelopeCertificateDto, EnvelopeCertificate, int>
{
}

View File

@@ -1,9 +1,13 @@
using DigitalData.Core.Abstractions.Application;
using DigitalData.Core.Abstraction.Application;
using EnvelopeGenerator.Application.DTOs;
using EnvelopeGenerator.Domain.Entities;
namespace EnvelopeGenerator.Application.Contracts.Services;
/// <summary>
///
/// </summary>
[Obsolete("Use MediatR")]
public interface IEnvelopeDocumentService : IBasicCRUDService<EnvelopeDocumentDto, EnvelopeDocument, int>
{
}

View File

@@ -1,27 +1,85 @@
using DigitalData.Core.Abstractions.Application;
using DigitalData.Core.DTO;
using DigitalData.Core.Abstraction.Application;
using DigitalData.Core.Abstraction.Application.DTO;
using EnvelopeGenerator.Application.DTOs.EnvelopeHistory;
using EnvelopeGenerator.Application.DTOs.Receiver;
using EnvelopeGenerator.Domain.Entities;
using static EnvelopeGenerator.Common.Constants;
using static EnvelopeGenerator.Domain.Constants;
namespace EnvelopeGenerator.Application.Contracts.Services;
/// <summary>
///
/// </summary>
[Obsolete("Use MediatR")]
public interface IEnvelopeHistoryService : ICRUDService<EnvelopeHistoryCreateDto, EnvelopeHistoryDto, EnvelopeHistory, long>
{
Task<int> CountAsync(int? envelopeId = null, string? userReference = null, int? status = null);
/// <summary>
///
/// </summary>
/// <param name="envelopeId"></param>
/// <param name="userReference"></param>
/// <param name="status"></param>
/// <returns></returns>
Task<int> CountAsync(int? envelopeId = null, string? userReference = null, EnvelopeStatus? status = null);
/// <summary>
///
/// </summary>
/// <param name="envelopeId"></param>
/// <param name="userReference"></param>
/// <returns></returns>
Task<bool> AccessCodeAlreadyRequested(int envelopeId, string userReference);
/// <summary>
///
/// </summary>
/// <param name="envelopeId"></param>
/// <param name="userReference"></param>
/// <returns></returns>
Task<bool> IsSigned(int envelopeId, string userReference);
/// <summary>
///
/// </summary>
/// <param name="envelopeId"></param>
/// <param name="userReference"></param>
/// <returns></returns>
Task<bool> IsRejected(int envelopeId, string? userReference = null);
Task<IEnumerable<EnvelopeHistoryDto>> ReadAsync(int? envelopeId = null, string? userReference = null, ReferenceType? referenceType = null, int? status = null, bool withSender = false, bool withReceiver = false);
/// <summary>
///
/// </summary>
/// <param name="envelopeId"></param>
/// <param name="userReference"></param>
/// <param name="referenceType"></param>
/// <param name="status"></param>
/// <param name="withSender"></param>
/// <param name="withReceiver"></param>
/// <returns></returns>
Task<IEnumerable<EnvelopeHistoryDto>> ReadAsync(int? envelopeId = null, string? userReference = null, ReferenceType? referenceType = null, EnvelopeStatus? status = null, bool withSender = false, bool withReceiver = false);
/// <summary>
///
/// </summary>
/// <param name="envelopeId"></param>
/// <param name="userReference"></param>
/// <returns></returns>
Task<IEnumerable<EnvelopeHistoryDto>> ReadRejectedAsync(int envelopeId, string? userReference = null);
/// <summary>
///
/// </summary>
/// <param name="envelopeId"></param>
/// <returns></returns>
Task<IEnumerable<ReceiverReadDto>> ReadRejectingReceivers(int envelopeId);
/// <summary>
///
/// </summary>
/// <param name="envelopeId"></param>
/// <param name="userReference"></param>
/// <param name="status"></param>
/// <param name="comment"></param>
/// <returns></returns>
Task<DataResult<long>> RecordAsync(int envelopeId, string userReference, EnvelopeStatus status, string? comment = null);
}

View File

@@ -1,18 +1,45 @@
using DigitalData.Core.DTO;
using DigitalData.Core.Abstraction.Application.DTO;
using DigitalData.EmailProfilerDispatcher.Abstraction.Contracts;
using EnvelopeGenerator.Application.DTOs.EnvelopeReceiver;
using EnvelopeGenerator.Application.DTOs.EnvelopeReceiverReadOnly;
using EnvelopeGenerator.Common;
using EnvelopeGenerator.Domain;
namespace EnvelopeGenerator.Application.Contracts.Services;
/// <summary>
///
/// </summary>
[Obsolete("Use MediatR")]
public interface IEnvelopeMailService : IEmailOutService
{
/// <summary>
///
/// </summary>
/// <param name="envelopeReceiverDto"></param>
/// <param name="tempType"></param>
/// <param name="optionalPlaceholders"></param>
/// <returns></returns>
Task<DataResult<int>> SendAsync(EnvelopeReceiverDto envelopeReceiverDto, Constants.EmailTemplateType tempType, Dictionary<string, object>? optionalPlaceholders = null);
/// <summary>
///
/// </summary>
/// <param name="dto"></param>
/// <param name="optionalPlaceholders"></param>
/// <returns></returns>
Task<DataResult<int>> SendAsync(EnvelopeReceiverReadOnlyDto dto, Dictionary<string, object>? optionalPlaceholders = null);
/// <summary>
///
/// </summary>
/// <param name="envelopeReceiverDto"></param>
/// <returns></returns>
Task<DataResult<int>> SendAccessCodeAsync(EnvelopeReceiverDto envelopeReceiverDto);
/// <summary>
///
/// </summary>
/// <param name="envelopeReceiverDto"></param>
/// <returns></returns>
Task<DataResult<int>> SendTFAQrCodeAsync(EnvelopeReceiverDto envelopeReceiverDto);
}

View File

@@ -1,9 +1,13 @@
using DigitalData.Core.Abstractions.Application;
using DigitalData.Core.Abstraction.Application;
using EnvelopeGenerator.Application.DTOs.EnvelopeReceiverReadOnly;
using EnvelopeGenerator.Domain.Entities;
namespace EnvelopeGenerator.Application.Contracts.Services;
/// <summary>
///
/// </summary>
[Obsolete("Use MediatR")]
public interface IEnvelopeReceiverReadOnlyService : ICRUDService<EnvelopeReceiverReadOnlyCreateDto, EnvelopeReceiverReadOnlyDto, EnvelopeReceiverReadOnly, long>
{
}

View File

@@ -1,6 +1,6 @@
using CommandDotNet;
using DigitalData.Core.Abstractions.Application;
using DigitalData.Core.DTO;
using DigitalData.Core.Abstraction.Application;
using DigitalData.Core.Abstraction.Application.DTO;
using EnvelopeGenerator.Application.DTOs.EnvelopeReceiver;
using EnvelopeGenerator.Application.DTOs.Messaging;
using EnvelopeGenerator.Application.Envelopes;
@@ -9,34 +9,140 @@ using EnvelopeGenerator.Domain.Entities;
namespace EnvelopeGenerator.Application.Contracts.Services;
/// <summary>
///
/// </summary>
[Obsolete("Use MediatR")]
public interface IEnvelopeReceiverService : IBasicCRUDService<EnvelopeReceiverDto, EnvelopeReceiver, (int Envelope, int Receiver)>
{
/// <summary>
///
/// </summary>
/// <param name="uuid"></param>
/// <param name="withEnvelope"></param>
/// <param name="withReceiver"></param>
/// <param name="readOnly"></param>
/// <returns></returns>
Task<DataResult<IEnumerable<EnvelopeReceiverDto>>> ReadByUuidAsync(string uuid, bool withEnvelope = true, bool withReceiver = false, bool readOnly = true);
/// <summary>
///
/// </summary>
/// <param name="uuid"></param>
/// <param name="withEnvelope"></param>
/// <param name="withReceiver"></param>
/// <returns></returns>
Task<DataResult<IEnumerable<string?>>> ReadAccessCodeByUuidAsync(string uuid, bool withEnvelope = false, bool withReceiver = true);
/// <summary>
///
/// </summary>
/// <param name="signature"></param>
/// <param name="withEnvelope"></param>
/// <param name="withReceiver"></param>
/// <param name="readOnly"></param>
/// <returns></returns>
Task<DataResult<IEnumerable<EnvelopeReceiverDto>>> ReadBySignatureAsync(string signature, bool withEnvelope = false, bool withReceiver = true, bool readOnly = true);
/// <summary>
///
/// </summary>
/// <param name="uuid"></param>
/// <param name="signature"></param>
/// <param name="withEnvelope"></param>
/// <param name="withReceiver"></param>
/// <param name="readOnly"></param>
/// <returns></returns>
Task<DataResult<EnvelopeReceiverDto>> ReadByUuidSignatureAsync(string uuid, string signature, bool withEnvelope = true, bool withReceiver = true, bool readOnly = true);
/// <summary>
///
/// </summary>
/// <param name="uuid"></param>
/// <param name="signature"></param>
/// <param name="withEnvelope"></param>
/// <param name="withReceiver"></param>
/// <param name="readOnly"></param>
/// <returns></returns>
Task<DataResult<EnvelopeReceiverSecretDto>> ReadWithSecretByUuidSignatureAsync(string uuid, string signature, bool withEnvelope = true, bool withReceiver = true, bool readOnly = true);
/// <summary>
///
/// </summary>
/// <param name="envelopeReceiverId"></param>
/// <param name="withEnvelope"></param>
/// <param name="withReceiver"></param>
/// <param name="readOnly"></param>
/// <returns></returns>
Task<DataResult<EnvelopeReceiverDto>> ReadByEnvelopeReceiverIdAsync(string envelopeReceiverId, bool withEnvelope = true, bool withReceiver = true, bool readOnly = true);
/// <summary>
///
/// </summary>
/// <param name="envelopeId"></param>
/// <param name="receiverId"></param>
/// <returns></returns>
Task<DataResult<string>> ReadAccessCodeByIdAsync(int envelopeId, int receiverId);
/// <summary>
///
/// </summary>
/// <param name="uuid"></param>
/// <param name="signature"></param>
/// <param name="accessCode"></param>
/// <returns></returns>
Task<DataResult<bool>> VerifyAccessCodeAsync(string uuid, string signature, string accessCode);
/// <summary>
///
/// </summary>
/// <param name="envelopeReceiverId"></param>
/// <param name="accessCode"></param>
/// <returns></returns>
[Command("verify-access-code-async-by-id")]
Task<DataResult<bool>> VerifyAccessCodeAsync(string envelopeReceiverId, string accessCode);
/// <summary>
///
/// </summary>
/// <param name="envelopeReceiverId"></param>
/// <returns></returns>
Task<DataResult<bool>> IsExisting(string envelopeReceiverId);
/// <summary>
///
/// </summary>
/// <param name="username"></param>
/// <param name="min_status"></param>
/// <param name="max_status"></param>
/// <param name="envelopeQuery"></param>
/// <param name="receiverQuery"></param>
/// <param name="ignore_statuses"></param>
/// <returns></returns>
Task<DataResult<IEnumerable<EnvelopeReceiverDto>>> ReadByUsernameAsync(string username, int? min_status = null, int? max_status = null, EnvelopeQuery? envelopeQuery = null, ReadReceiverQuery? receiverQuery = null, params int[] ignore_statuses);
Task<DataResult<string?>> ReadLastUsedReceiverNameByMailAsync(string? mail = null, int? id = null, string? signature = null);
/// <summary>
///
/// </summary>
/// <param name="mail"></param>
/// <param name="id"></param>
/// <param name="signature"></param>
/// <returns></returns>
Task<DataResult<string>> ReadLastUsedReceiverNameByMailAsync(string? mail = null, int? id = null, string? signature = null);
/// <summary>
///
/// </summary>
/// <param name="envelopeReceiverId"></param>
/// <param name="message"></param>
/// <returns></returns>
Task<DataResult<SmsResponse>> SendSmsAsync(string envelopeReceiverId, string message);
/// <summary>
///
/// </summary>
/// <param name="uuid"></param>
/// <returns></returns>
Task<DataResult<IEnumerable<EnvelopeReceiverSecretDto>>> ReadWithSecretByUuidAsync(string uuid);
}

View File

@@ -1,15 +1,44 @@
using DigitalData.Core.Abstractions.Application;
using DigitalData.Core.DTO;
using DigitalData.Core.Abstraction.Application;
using DigitalData.Core.Abstraction.Application.DTO;
using EnvelopeGenerator.Application.DTOs;
using EnvelopeGenerator.Domain.Entities;
namespace EnvelopeGenerator.Application.Contracts.Services;
/// <summary>
///
/// </summary>
[Obsolete("Use MediatR")]
public interface IEnvelopeService : IBasicCRUDService<EnvelopeDto, Envelope, int>
{
/// <summary>
///
/// </summary>
/// <param name="documents"></param>
/// <param name="history"></param>
/// <param name="documentReceiverElement"></param>
/// <returns></returns>
Task<DataResult<IEnumerable<EnvelopeDto>>> ReadAllWithAsync(bool documents = false, bool history = false, bool documentReceiverElement = false);
/// <summary>
///
/// </summary>
/// <param name="uuid"></param>
/// <param name="withDocuments"></param>
/// <param name="withHistory"></param>
/// <param name="withDocumentReceiverElement"></param>
/// <param name="withUser"></param>
/// <param name="withAll"></param>
/// <returns></returns>
Task<DataResult<EnvelopeDto>> ReadByUuidAsync(string uuid, bool withDocuments = false, bool withHistory = false, bool withDocumentReceiverElement = false, bool withUser = false, bool withAll = false);
/// <summary>
///
/// </summary>
/// <param name="userId"></param>
/// <param name="min_status"></param>
/// <param name="max_status"></param>
/// <param name="ignore_statuses"></param>
/// <returns></returns>
Task<DataResult<IEnumerable<EnvelopeDto>>> ReadByUserAsync(int userId, int? min_status = null, int? max_status = null, params int[] ignore_statuses);
}

View File

@@ -3,6 +3,9 @@ using EnvelopeGenerator.Application.DTOs.Messaging;
namespace EnvelopeGenerator.Application.Contracts.Services;
/// <summary>
///
/// </summary>
public interface IEnvelopeSmsHandler
{
/// <summary>
@@ -13,5 +16,11 @@ public interface IEnvelopeSmsHandler
/// <returns></returns>
Task<(SmsResponse? SmsResponse, DateTime Expiration)> SendTotpAsync(EnvelopeReceiverSecretDto er_secret, CancellationToken cToken = default);
/// <summary>
///
/// </summary>
/// <param name="totpCode"></param>
/// <param name="secretKey"></param>
/// <returns></returns>
bool VerifyTotp(string totpCode, string secretKey);
}

View File

@@ -1,9 +1,13 @@
using DigitalData.Core.Abstractions.Application;
using DigitalData.Core.Abstraction.Application;
using EnvelopeGenerator.Application.DTOs;
using EnvelopeGenerator.Domain.Entities;
namespace EnvelopeGenerator.Application.Contracts.Services;
/// <summary>
///
/// </summary>
[Obsolete("Use MediatR")]
public interface IEnvelopeTypeService : IBasicCRUDService<EnvelopeTypeDto, EnvelopeType, int>
{
}

View File

@@ -1,16 +1,29 @@
using DigitalData.Core.Abstractions;
using DigitalData.Core.Abstractions.Application;
using DigitalData.Core.DTO;
using DigitalData.Core.Abstraction.Application;
using DigitalData.Core.Abstraction.Application.DTO;
using EnvelopeGenerator.Application.DTOs.Receiver;
using EnvelopeGenerator.Domain.Entities;
namespace EnvelopeGenerator.Application.Contracts.Services;
/// <summary>
///
/// </summary>
[Obsolete("Use MediatR")]
public interface IReceiverService : ICRUDService<ReceiverCreateDto, ReceiverReadDto, Receiver, int>
{
/// <summary>
///
/// </summary>
/// <param name="emailAddress"></param>
/// <param name="signature"></param>
/// <returns></returns>
Task<DataResult<ReceiverReadDto>> ReadByAsync(string? emailAddress = null, string? signature = null);
/// <summary>
///
/// </summary>
/// <param name="emailAddress"></param>
/// <param name="signature"></param>
/// <returns></returns>
Task<Result> DeleteByAsync(string? emailAddress = null, string? signature = null);
Task<Result> UpdateAsync<TUpdateDto>(TUpdateDto updateDto) where TUpdateDto : IUnique<int>;
}

View File

@@ -3,9 +3,21 @@
namespace EnvelopeGenerator.Application.Contracts.Services;
//TODO: move to DigitalData.Core
/// <summary>
///
/// </summary>
public interface ISmsSender
{
/// <summary>
///
/// </summary>
string ServiceProvider { get; }
/// <summary>
///
/// </summary>
/// <param name="recipient"></param>
/// <param name="message"></param>
/// <returns></returns>
Task<SmsResponse> SendSmsAsync(string recipient, string message);
}

View File

@@ -1,9 +0,0 @@
using DigitalData.Core.Abstractions.Application;
using EnvelopeGenerator.Application.DTOs;
using EnvelopeGenerator.Domain.Entities;
namespace EnvelopeGenerator.Application.Contracts.Services;
public interface IUserReceiverService : IBasicCRUDService<UserReceiverDto, UserReceiver, int>
{
}

View File

@@ -1,21 +1,30 @@
using DigitalData.Core.Abstractions;
using Microsoft.AspNetCore.Mvc;
using System.ComponentModel.DataAnnotations.Schema;
using System.Text.Json.Serialization;
using Microsoft.AspNetCore.Mvc;
namespace EnvelopeGenerator.Application.DTOs
namespace EnvelopeGenerator.Application.DTOs;
/// <summary>
/// Data Transfer Object representing configuration settings.
/// </summary>
[ApiExplorerSettings(IgnoreApi = true)]
public class ConfigDto
{
[ApiExplorerSettings(IgnoreApi = true)]
public record ConfigDto(
string DocumentPath,
int SendingProfile,
string SignatureHost,
string ExternalProgramName,
string ExportPath) : IUnique<int>
{
[NotMapped]
[JsonIgnore]
[Obsolete("Configuration does not have an ID; it represents a single table in the database.")]
public int Id => throw new InvalidOperationException("This configuration does not support an ID as it represents a single row in the database.");
};
/// <summary>
/// Gets or sets the sending profile identifier.
/// </summary>
public int SendingProfile { get; set; }
/// <summary>
/// Gets or sets the signature host URL or name.
/// </summary>
public required string SignatureHost { get; set; }
/// <summary>
/// Gets or sets the name of the external program.
/// </summary>
public string? ExternalProgramName { get; set; }
/// <summary>
/// Gets or sets the path where exports will be saved.
/// </summary>
public string? ExportPath { get; set; }
}

View File

@@ -1,26 +1,95 @@
using DigitalData.Core.Abstractions;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc;
namespace EnvelopeGenerator.Application.DTOs
namespace EnvelopeGenerator.Application.DTOs;
/// <summary>
/// Data Transfer Object representing a positioned element assigned to a document receiver.
/// </summary>
[ApiExplorerSettings(IgnoreApi = true)]
public class DocumentReceiverElementDto
{
[ApiExplorerSettings(IgnoreApi = true)]
public record DocumentReceiverElementDto(
int Id,
int DocumentId,
int ReceiverId,
int ElementType,
double X,
double Y,
double Width,
double Height,
int Page,
bool Required,
string? Tooltip,
bool ReadOnly,
int AnnotationIndex,
DateTime AddedWhen,
DateTime? ChangedWhen,
double Top,
double Left
): IUnique<int>;
/// <summary>
/// Gets or sets the unique identifier of the element.
/// </summary>
public int Id { get; set; }
/// <summary>
/// Gets or sets the identifier of the associated document.
/// </summary>
public int DocumentId { get; set; }
/// <summary>
/// Gets or sets the identifier of the receiver.
/// </summary>
public int ReceiverId { get; set; }
/// <summary>
/// Gets or sets the type of the element.
/// </summary>
public int ElementType { get; set; }
/// <summary>
/// Gets or sets the X coordinate of the element.
/// </summary>
public double X { get; set; }
/// <summary>
/// Gets or sets the Y coordinate of the element.
/// </summary>
public double Y { get; set; }
/// <summary>
/// Gets or sets the width of the element.
/// </summary>
public double Width { get; set; }
/// <summary>
/// Gets or sets the height of the element.
/// </summary>
public double Height { get; set; }
/// <summary>
/// Gets or sets the page number where the element appears.
/// </summary>
public int Page { get; set; }
/// <summary>
/// Gets or sets a value indicating whether the element is required.
/// </summary>
public bool Required { get; set; }
/// <summary>
/// Gets or sets the tooltip text for the element.
/// </summary>
public string? Tooltip { get; set; }
/// <summary>
/// Gets or sets a value indicating whether the element is read-only.
/// </summary>
public bool ReadOnly { get; set; }
/// <summary>
/// Gets or sets the annotation index for ordering or reference.
/// </summary>
public int AnnotationIndex { get; set; }
/// <summary>
/// Gets or sets the timestamp when the element was added.
/// </summary>
public DateTime AddedWhen { get; set; }
/// <summary>
/// Gets or sets the timestamp when the element was last changed, if applicable.
/// </summary>
public DateTime? ChangedWhen { get; set; }
/// <summary>
/// Gets or sets the top position of the element (in layout terms).
/// </summary>
public double Top { get; set; }
/// <summary>
/// Gets or sets the left position of the element (in layout terms).
/// </summary>
public double Left { get; set; }
}

View File

@@ -1,18 +1,50 @@
using DigitalData.Core.Abstractions;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc;
namespace EnvelopeGenerator.Application.DTOs
namespace EnvelopeGenerator.Application.DTOs;
/// <summary>
/// Data Transfer Object representing the status of a document for a specific receiver.
/// </summary>
[ApiExplorerSettings(IgnoreApi = true)]
public class DocumentStatusDto
{
[ApiExplorerSettings(IgnoreApi = true)]
public record DocumentStatusDto(
int Id,
int EnvelopeId,
int ReceiverId,
int Status,
DateTime? StatusChangedWhen,
DateTime AddedWhen,
DateTime? ChangedWhen) : IUnique<int>
{
public string? Value { get; set; }
};
/// <summary>
/// Gets or sets the unique identifier of the document status entry.
/// </summary>
public int Id { get; set; }
/// <summary>
/// Gets or sets the ID of the associated envelope.
/// </summary>
public int EnvelopeId { get; set; }
/// <summary>
/// Gets or sets the ID of the receiver associated with this status.
/// </summary>
public int ReceiverId { get; set; }
/// <summary>
/// Gets or sets the current status code.
/// </summary>
public int Status { get; set; }
/// <summary>
/// Gets or sets the timestamp when the status was changed.
/// </summary>
public DateTime? StatusChangedWhen { get; set; }
/// <summary>
/// Gets or sets the timestamp when this record was added.
/// </summary>
public DateTime AddedWhen { get; set; }
/// <summary>
/// Gets or sets the timestamp when this record was last changed.
/// </summary>
public DateTime? ChangedWhen { get; set; }
/// <summary>
/// Gets or sets the display value associated with the status.
/// </summary>
public string? Value { get; set; }
}

View File

@@ -1,5 +1,4 @@
using DigitalData.Core.Abstractions;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc;
namespace EnvelopeGenerator.Application.DTOs
{
@@ -7,7 +6,7 @@ namespace EnvelopeGenerator.Application.DTOs
///
/// </summary>
[ApiExplorerSettings(IgnoreApi = true)]
public record EmailTemplateDto : IUnique<int>
public record EmailTemplateDto
{
/// <summary>
///

View File

@@ -1,16 +1,50 @@
using DigitalData.Core.Abstractions;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc;
namespace EnvelopeGenerator.Application.DTOs
namespace EnvelopeGenerator.Application.DTOs;
/// <summary>
/// Data Transfer Object representing certificate information for an envelope.
/// </summary>
[ApiExplorerSettings(IgnoreApi = true)]
public class EnvelopeCertificateDto
{
[ApiExplorerSettings(IgnoreApi = true)]
public record EnvelopeCertificateDto(
int Id,
int EnvelopeId,
string EnvelopeUuid,
string EnvelopeSubject,
int CreatorId,
string CreatorName,
string CreatorEmail,
int EnvelopeStatus) : IUnique<int>;
/// <summary>
/// Gets the unique identifier of the certificate.
/// </summary>
public int Id { get; init; }
/// <summary>
/// Gets the envelope ID associated with the certificate.
/// </summary>
public int EnvelopeId { get; init; }
/// <summary>
/// Gets the UUID of the envelope.
/// </summary>
public string EnvelopeUuid { get; init; } = string.Empty;
/// <summary>
/// Gets the subject of the envelope.
/// </summary>
public string EnvelopeSubject { get; init; } = string.Empty;
/// <summary>
/// Gets the ID of the creator of the envelope.
/// </summary>
public int CreatorId { get; init; }
/// <summary>
/// Gets the name of the creator.
/// </summary>
public string CreatorName { get; init; } = string.Empty;
/// <summary>
/// Gets the email address of the creator.
/// </summary>
public string CreatorEmail { get; init; } = string.Empty;
/// <summary>
/// Gets the current status of the envelope.
/// </summary>
public int EnvelopeStatus { get; init; }
}

View File

@@ -1,15 +1,35 @@
using DigitalData.Core.Abstractions;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc;
namespace EnvelopeGenerator.Application.DTOs
namespace EnvelopeGenerator.Application.DTOs;
/// <summary>
/// Data Transfer Object representing a document within an envelope, including optional binary data and form elements.
/// </summary>
[ApiExplorerSettings(IgnoreApi = true)]
public class EnvelopeDocumentDto
{
[ApiExplorerSettings(IgnoreApi = true)]
public record EnvelopeDocumentDto
(
int Id,
int EnvelopeId,
DateTime AddedWhen,
byte[]? ByteData = null,
IEnumerable<DocumentReceiverElementDto>? Elements = null
) : IUnique<int>;
/// <summary>
/// Gets or sets the unique identifier of the document.
/// </summary>
public int Id { get; set; }
/// <summary>
/// Gets or sets the envelope ID to which the document belongs.
/// </summary>
public int EnvelopeId { get; set; }
/// <summary>
/// Gets or sets the date and time when the document was added.
/// </summary>
public DateTime AddedWhen { get; set; }
/// <summary>
/// Gets or sets the binary data of the document, if available.
/// </summary>
public byte[]? ByteData { get; set; }
/// <summary>
/// Gets or sets the collection of elements associated with the document for receiver interactions, if any.
/// </summary>
public IEnumerable<DocumentReceiverElementDto>? Elements { get; set; }
}

View File

@@ -1,56 +1,120 @@
using DigitalData.Core.Abstractions;
using DigitalData.EmailProfilerDispatcher.Abstraction.Attributes;
using DigitalData.EmailProfilerDispatcher.Abstraction.Attributes;
using DigitalData.UserManager.Application.DTOs.User;
using EnvelopeGenerator.Domain.Entities;
using Microsoft.AspNetCore.Mvc;
namespace EnvelopeGenerator.Application.DTOs
namespace EnvelopeGenerator.Application.DTOs;
/// <summary>
///
/// </summary>
[ApiExplorerSettings(IgnoreApi = true)]
public record EnvelopeDto
{
[ApiExplorerSettings(IgnoreApi = true)]
public record EnvelopeDto() : IUnique<int>
{
public int Id { get; set; }
/// <summary>
///
/// </summary>
public int Id { get; set; }
public int UserId { get; set; }
/// <summary>
///
/// </summary>
public int UserId { get; set; }
public int Status { get; set; }
/// <summary>
///
/// </summary>
public int Status { get; set; }
public string StatusName { get; set; }
/// <summary>
/// Default value is string.Empty
/// </summary>
public string StatusName { get; set; } = string.Empty;
public string Uuid { get; set; }
/// <summary>
/// Default value is string.Empty
/// </summary>
public string Uuid { get; set; } = string.Empty;
[TemplatePlaceholder("[MESSAGE]")]
public string Message { get; set; }
/// <summary>
/// Default value is string.Empty
/// </summary>
[TemplatePlaceholder("[MESSAGE]")]
public string Message { get; set; } = string.Empty;
public DateTime AddedWhen { get; set; }
/// <summary>
///
/// </summary>
public DateTime AddedWhen { get; set; }
public DateTime? ChangedWhen { get; set; }
/// <summary>
///
/// </summary>
public DateTime? ChangedWhen { get; set; }
[TemplatePlaceholder("[DOCUMENT_TITLE]")]
public string Title { get; set; }
/// <summary>
/// Default value is string.Empty
/// </summary>
[TemplatePlaceholder("[DOCUMENT_TITLE]")]
public string Title { get; set; } = string.Empty;
public int? ContractType { get; set; }
/// <summary>
///
/// </summary>
public int? ContractType { get; set; }
public string Language { get; set; }
/// <summary>
/// Default value is 'de-DE'
/// </summary>
public string Language { get; set; } = "de-DE";
public int? EnvelopeTypeId { get; set; }
/// <summary>
///
/// </summary>
public int? EnvelopeTypeId { get; set; }
public int? CertificationType { get; set; }
/// <summary>
///
/// </summary>
public int? CertificationType { get; set; }
public bool? UseAccessCode { get; set; }
/// <summary>
///
/// </summary>
public bool? UseAccessCode { get; set; }
public bool TFAEnabled { get; init; }
/// <summary>
///
/// </summary>
public bool TFAEnabled { get; init; }
public UserReadDto? User { get; set; }
/// <summary>
///
/// </summary>
public UserReadDto? User { get; set; }
public EnvelopeType? EnvelopeType { get; set; }
/// <summary>
///
/// </summary>
public EnvelopeType? EnvelopeType { get; set; }
public string? EnvelopeTypeTitle { get; set; }
/// <summary>
///
/// </summary>
public string? EnvelopeTypeTitle { get; set; }
public bool IsAlreadySent { get; set; }
/// <summary>
///
/// </summary>
public bool IsAlreadySent { get; set; }
public byte[]? DocResult { get; init; }
/// <summary>
///
/// </summary>
public byte[]? DocResult { get; init; }
public IEnumerable<EnvelopeDocumentDto>? Documents { get; set; }
}
/// <summary>
///
/// </summary>
public IEnumerable<EnvelopeDocumentDto>? Documents { get; set; }
}

View File

@@ -1,12 +1,34 @@
using Microsoft.AspNetCore.Mvc;
namespace EnvelopeGenerator.Application.DTOs.EnvelopeHistory
namespace EnvelopeGenerator.Application.DTOs.EnvelopeHistory;
/// <summary>
/// Data Transfer Object for creating a new envelope history record.
/// </summary>
public class EnvelopeHistoryCreateDto
{
[ApiExplorerSettings(IgnoreApi = true)]
public record EnvelopeHistoryCreateDto(
int EnvelopeId,
string UserReference,
int Status,
DateTime? ActionDate,
string? Comment = null);
/// <summary>
/// Gets or sets the identifier of the envelope.
/// </summary>
public int EnvelopeId { get; set; }
/// <summary>
/// Gets or sets the user reference associated with the action.
/// </summary>
public required string UserReference { get; set; }
/// <summary>
/// Gets or sets the status of the envelope at the time of the action.
/// </summary>
public int Status { get; set; }
/// <summary>
/// Gets or sets the date and time when the action occurred.
/// </summary>
public DateTime? ActionDate { get; set; }
/// <summary>
/// Gets or sets an optional comment related to the action.
/// </summary>
public string? Comment { get; set; }
}

View File

@@ -1,36 +1,69 @@
using DigitalData.Core.Abstractions;
using DigitalData.Core.DTO;
using DigitalData.UserManager.Application.DTOs.User;
using DigitalData.UserManager.Application.DTOs.User;
using EnvelopeGenerator.Application.DTOs.Receiver;
using Microsoft.AspNetCore.Mvc;
using static EnvelopeGenerator.Common.Constants;
using static EnvelopeGenerator.Domain.Constants;
namespace EnvelopeGenerator.Application.DTOs.EnvelopeHistory;
/// <summary>
///
/// Data Transfer Object representing the history of an envelope, including status, sender, receiver, and related metadata.
/// </summary>
/// <param name="Id"></param>
/// <param name="EnvelopeId"></param>
/// <param name="UserReference"></param>
/// <param name="Status"></param>
/// <param name="StatusName"></param>
/// <param name="AddedWhen"></param>
/// <param name="ActionDate"></param>
/// <param name="Sender"></param>
/// <param name="Receiver"></param>
/// <param name="ReferenceType"></param>
/// <param name="Comment"></param>
[ApiExplorerSettings(IgnoreApi = true)]
public record EnvelopeHistoryDto(
long Id,
int EnvelopeId,
string UserReference,
int Status,
string? StatusName,
DateTime AddedWhen,
DateTime? ActionDate,
UserCreateDto? Sender,
ReceiverReadDto? Receiver,
ReferenceType ReferenceType,
string? Comment = null) : BaseDTO<long>(Id), IUnique<long>;
public record EnvelopeHistoryDto
{
/// <summary>
/// Unique identifier for the envelope history entry.
/// </summary>
public long Id { get; set; }
/// <summary>
/// Identifier of the associated envelope.
/// </summary>
public int EnvelopeId { get; set; }
/// <summary>
/// Reference string for the user related to this history entry.
/// </summary>
public required string UserReference { get; set; }
/// <summary>
/// Status code of the envelope at this history point.
/// </summary>
public int Status { get; set; }
/// <summary>
/// Human-readable name of the status.
/// </summary>
public string? StatusName { get; set; }
/// <summary>
/// Date and time when this history entry was added.
/// </summary>
public DateTime AddedWhen { get; set; }
/// <summary>
/// Date and time when an action was performed, if applicable.
/// </summary>
public DateTime? ActionDate { get; set; }
/// <summary>
/// Information about the sender associated with this history entry.
/// </summary>
public UserCreateDto? Sender { get; set; }
/// <summary>
/// Information about the receiver associated with this history entry.
/// </summary>
public ReceiverReadDto? Receiver { get; set; }
/// <summary>
/// Type of reference for this history entry.
/// </summary>
public ReferenceType ReferenceType { get; set; }
/// <summary>
/// Optional comment related to this history entry.
/// </summary>
public string? Comment { get; set; }
/// <inheritdoc/>
public override int GetHashCode() => Id.GetHashCode();
};

View File

@@ -1,33 +1,67 @@
using DigitalData.Core.Abstractions;
using DigitalData.EmailProfilerDispatcher.Abstraction.Attributes;
using DigitalData.EmailProfilerDispatcher.Abstraction.Attributes;
using Microsoft.AspNetCore.Mvc;
namespace EnvelopeGenerator.Application.DTOs.EnvelopeReceiver
namespace EnvelopeGenerator.Application.DTOs.EnvelopeReceiver;
/// <summary>
///
/// </summary>
[ApiExplorerSettings(IgnoreApi = true)]
public record EnvelopeReceiverBasicDto
{
[ApiExplorerSettings(IgnoreApi = true)]
public record EnvelopeReceiverBasicDto() : IUnique<(int Envelope, int Receiver)>
{
public (int Envelope, int Receiver) Id => (Envelope: EnvelopeId, Receiver: ReceiverId);
/// <summary>
///
/// </summary>
public (int Envelope, int Receiver) Id => (Envelope: EnvelopeId, Receiver: ReceiverId);
public int EnvelopeId { get; init; }
/// <summary>
///
/// </summary>
public int EnvelopeId { get; init; }
public int ReceiverId { get; init; }
/// <summary>
///
/// </summary>
public int ReceiverId { get; init; }
public int Sequence { get; init; }
/// <summary>
///
/// </summary>
public int Sequence { get; init; }
[TemplatePlaceholder("[NAME_RECEIVER]")]
public string? Name { get; init; }
/// <summary>
///
/// </summary>
[TemplatePlaceholder("[NAME_RECEIVER]")]
public string? Name { get; init; }
public string? JobTitle { get; init; }
/// <summary>
///
/// </summary>
public string? JobTitle { get; init; }
public string? CompanyName { get; init; }
/// <summary>
///
/// </summary>
public string? CompanyName { get; init; }
public string? PrivateMessage { get; init; }
/// <summary>
///
/// </summary>
public string? PrivateMessage { get; init; }
public DateTime AddedWhen { get; init; }
/// <summary>
///
/// </summary>
public DateTime AddedWhen { get; init; }
public DateTime? ChangedWhen { get; init; }
/// <summary>
///
/// </summary>
public DateTime? ChangedWhen { get; init; }
public bool HasPhoneNumber { get; init; }
}
/// <summary>
///
/// </summary>
public bool HasPhoneNumber { get; init; }
}

View File

@@ -1,13 +1,22 @@
using EnvelopeGenerator.Application.DTOs.Receiver;
using Microsoft.AspNetCore.Mvc;
namespace EnvelopeGenerator.Application.DTOs.EnvelopeReceiver
{
[ApiExplorerSettings(IgnoreApi = true)]
public record EnvelopeReceiverDto() : EnvelopeReceiverBasicDto()
{
public EnvelopeDto? Envelope { get; set; }
namespace EnvelopeGenerator.Application.DTOs.EnvelopeReceiver;
public ReceiverReadDto? Receiver { get; set; }
}
/// <summary>
///
/// </summary>
[ApiExplorerSettings(IgnoreApi = true)]
public record EnvelopeReceiverDto() : EnvelopeReceiverBasicDto()
{
/// <summary>
///
/// </summary>
public EnvelopeDto? Envelope { get; set; }
/// <summary>
///
/// </summary>
public ReceiverReadDto? Receiver { get; set; }
}

View File

@@ -1,12 +1,20 @@
using Microsoft.AspNetCore.Mvc;
namespace EnvelopeGenerator.Application.DTOs.EnvelopeReceiver
{
[ApiExplorerSettings(IgnoreApi = true)]
public record EnvelopeReceiverSecretDto() : EnvelopeReceiverDto()
{
public string? AccessCode { get; init; }
namespace EnvelopeGenerator.Application.DTOs.EnvelopeReceiver;
public string? PhoneNumber { get; init; }
}
/// <summary>
///
/// </summary>
[ApiExplorerSettings(IgnoreApi = true)]
public record EnvelopeReceiverSecretDto : EnvelopeReceiverDto
{
/// <summary>
///
/// </summary>
public string? AccessCode { get; init; }
/// <summary>
///
/// </summary>
public string? PhoneNumber { get; init; }
}

View File

@@ -2,23 +2,38 @@
using System.ComponentModel.DataAnnotations;
using System.Text.Json.Serialization;
namespace EnvelopeGenerator.Application.DTOs.EnvelopeReceiverReadOnly
namespace EnvelopeGenerator.Application.DTOs.EnvelopeReceiverReadOnly;
/// <summary>
///
/// </summary>
/// <param name="DateValid"></param>
[ApiExplorerSettings(IgnoreApi = true)]
public record EnvelopeReceiverReadOnlyCreateDto(
DateTime DateValid)
{
[ApiExplorerSettings(IgnoreApi = true)]
public record EnvelopeReceiverReadOnlyCreateDto(
DateTime DateValid)
{
[EmailAddress]
[Required]
public required string ReceiverMail { get; init; }
/// <summary>
///
/// </summary>
[EmailAddress]
[Required]
public required string ReceiverMail { get; init; }
[JsonIgnore]
public long? EnvelopeId { get; set; } = null;
/// <summary>
/// Default value is null
/// </summary>
[JsonIgnore]
public long? EnvelopeId { get; set; } = null;
[JsonIgnore]
public string? AddedWho { get; set; }
/// <summary>
///
/// </summary>
[JsonIgnore]
public string? AddedWho { get; set; }
[JsonIgnore]
public DateTime AddedWhen { get; } = DateTime.Now;
};
}
/// <summary>
/// Default value is DateTime.Now
/// </summary>
[JsonIgnore]
public DateTime AddedWhen { get; } = DateTime.Now;
};

View File

@@ -1,18 +1,63 @@
using EnvelopeGenerator.Application.DTOs.Receiver;
using Microsoft.AspNetCore.Mvc;
namespace EnvelopeGenerator.Application.DTOs.EnvelopeReceiverReadOnly
namespace EnvelopeGenerator.Application.DTOs.EnvelopeReceiverReadOnly;
/// <summary>
/// Represents a read-only Data Transfer Object (DTO) for an envelope receiver.
/// Contains information about the receiver, associated envelope, and audit details.
/// </summary>
[ApiExplorerSettings(IgnoreApi = true)]
public class EnvelopeReceiverReadOnlyDto
{
[ApiExplorerSettings(IgnoreApi = true)]
public record EnvelopeReceiverReadOnlyDto(
long Id,
long EnvelopeId,
string ReceiverMail,
DateTime DateValid,
DateTime AddedWhen,
string AddedWho,
EnvelopeDto? Envelope = null,
string? ChangedWho = null,
DateTime? ChangedWhen = null,
ReceiverReadDto? Receiver = null);
/// <summary>
/// Gets or inits the unique identifier of the envelope receiver.
/// </summary>
public long Id { get; init; }
/// <summary>
/// Gets or inits the identifier of the associated envelope.
/// </summary>
public long EnvelopeId { get; init; }
/// <summary>
/// Gets or inits the email address of the receiver.
/// </summary>
public required string ReceiverMail { get; set; }
/// <summary>
/// Gets or inits the date until which the receiver is valid.
/// </summary>
public DateTime DateValid { get; set; }
/// <summary>
/// Gets or inits the date and time when the receiver was added.
/// </summary>
public DateTime AddedWhen { get; init; }
/// <summary>
/// Gets or inits the user who added the receiver.
/// Default value is 'unknown'.
/// </summary>
public string AddedWho { get; init; } = "Unknown";
/// <summary>
/// Gets or inits the associated envelope details.
/// </summary>
public EnvelopeDto? Envelope { get; set; }
/// <summary>
/// Gets or inits the user who last changed the receiver, if any.
/// </summary>
public string? ChangedWho { get; set; }
/// <summary>
/// Gets or inits the date and time when the receiver was last changed, if any.
/// </summary>
public DateTime? ChangedWhen { get; set; }
/// <summary>
/// Gets or inits the associated receiver details.
/// </summary>
public ReceiverReadDto? Receiver { get; set; }
}

View File

@@ -1,14 +1,31 @@
using DigitalData.Core.Abstractions;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc;
namespace EnvelopeGenerator.Application.DTOs.EnvelopeReceiverReadOnly
namespace EnvelopeGenerator.Application.DTOs.EnvelopeReceiverReadOnly;
/// <summary>
/// Data Transfer Object for updating a read-only envelope receiver.
/// </summary>
[ApiExplorerSettings(IgnoreApi = true)]
public class EnvelopeReceiverReadOnlyUpdateDto
{
[ApiExplorerSettings(IgnoreApi = true)]
public record EnvelopeReceiverReadOnlyUpdateDto(
long Id,
DateTime DateValid,
string ChangedWho) : IUnique<long>
{
public DateTime ChangedWhen { get; } = DateTime.Now;
};
/// <summary>
/// Gets or sets the unique identifier of the envelope receiver.
/// </summary>
public long Id { get; init; }
/// <summary>
/// Gets or sets the date when the envelope receiver becomes valid.
/// </summary>
public DateTime DateValid { get; set; }
/// <summary>
/// Gets or sets the name of the user who made the change.
/// Default value is unknown.
/// </summary>
public string ChangedWho { get; set; } = "Unknown";
/// <summary>
/// Gets or sets the date and time when the change was made.
/// </summary>
public DateTime ChangedWhen { get; set; } = DateTime.Now;
}

View File

@@ -1,23 +1,85 @@
using DigitalData.Core.Abstractions;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc;
namespace EnvelopeGenerator.Application.DTOs
namespace EnvelopeGenerator.Application.DTOs;
/// <summary>
/// Data Transfer Object representing a type of envelope with its configuration settings.
/// </summary>
[ApiExplorerSettings(IgnoreApi = true)]
public class EnvelopeTypeDto
{
[ApiExplorerSettings(IgnoreApi = true)]
public record EnvelopeTypeDto(
int Id,
string Title,
string Language,
int? ExpiresDays,
int? CertificationType,
bool? UseAccessCode,
int? FinalEmailToCreator,
int? FinalEmailToReceivers,
DateTime AddedWhen,
DateTime? ChangedWhen,
int? ExpiresWarningDays,
bool? SendReminderEmails,
int? FirstReminderDays,
int? ReminderIntervalDays,
int? ContractType) : IUnique<int>;
/// <summary>
/// Gets or sets the unique identifier of the envelope type.
/// </summary>
public int Id { get; set; }
/// <summary>
/// Gets or sets the title of the envelope type.
/// </summary>
public string Title { get; set; } = string.Empty;
/// <summary>
/// Gets or sets the language code used in this envelope type.
/// </summary>
public string Language { get; set; } = "de-DE";
/// <summary>
/// Gets or sets the number of days after which the envelope expires.
/// </summary>
public int? ExpiresDays { get; set; }
/// <summary>
/// Gets or sets the certification type identifier.
/// </summary>
public int? CertificationType { get; set; }
/// <summary>
/// Gets or sets a value indicating whether an access code is required.
/// </summary>
public bool? UseAccessCode { get; set; }
/// <summary>
/// Gets or sets the final email template ID to be sent to the creator.
/// </summary>
public int? FinalEmailToCreator { get; set; }
/// <summary>
/// Gets or sets the final email template ID to be sent to the receivers.
/// </summary>
public int? FinalEmailToReceivers { get; set; }
/// <summary>
/// Gets or sets the timestamp when this envelope type was added.
/// </summary>
public DateTime AddedWhen { get; set; }
/// <summary>
/// Gets or sets the timestamp when this envelope type was last changed.
/// </summary>
public DateTime? ChangedWhen { get; set; }
/// <summary>
/// Gets or sets the number of days before expiry when a warning should be sent.
/// </summary>
public int? ExpiresWarningDays { get; set; }
/// <summary>
/// Gets or sets a value indicating whether reminder emails should be sent.
/// </summary>
public bool? SendReminderEmails { get; set; }
/// <summary>
/// Gets or sets the number of days before the first reminder is sent.
/// </summary>
public int? FirstReminderDays { get; set; }
/// <summary>
/// Gets or sets the interval in days between reminder emails.
/// </summary>
public int? ReminderIntervalDays { get; set; }
/// <summary>
/// Gets or sets the contract type associated with the envelope type.
/// </summary>
public int? ContractType { get; set; }
}

View File

@@ -37,7 +37,6 @@ public class MappingProfile : Profile
CreateMap<Domain.Entities.Receiver, ReceiverReadDto>();
CreateMap<Domain.Entities.Receiver, ReceiverCreateDto>();
CreateMap<Domain.Entities.Receiver, ReceiverUpdateDto>();
CreateMap<UserReceiver, UserReceiverDto>();
CreateMap<Domain.Entities.EnvelopeReceiverReadOnly, EnvelopeReceiverReadOnlyDto>();
// DTO to Entity mappings
@@ -55,7 +54,6 @@ public class MappingProfile : Profile
CreateMap<ReceiverReadDto, Domain.Entities.Receiver>().ForMember(rcv => rcv.EnvelopeReceivers, rcvReadDto => rcvReadDto.Ignore());
CreateMap<ReceiverCreateDto, Domain.Entities.Receiver>();
CreateMap<ReceiverUpdateDto, Domain.Entities.Receiver>();
CreateMap<UserReceiverDto, UserReceiver>();
CreateMap<EnvelopeReceiverBase, EnvelopeReceiverBasicDto>();
CreateMap<EnvelopeReceiverReadOnlyCreateDto, Domain.Entities.EnvelopeReceiverReadOnly>();
CreateMap<EnvelopeReceiverReadOnlyUpdateDto, Domain.Entities.EnvelopeReceiverReadOnly>();

View File

@@ -1,7 +1,9 @@
using Microsoft.AspNetCore.Mvc;
namespace EnvelopeGenerator.Application.DTOs.Messaging
{
[ApiExplorerSettings(IgnoreApi = true)]
public class GtxMessagingResponse : Dictionary<string, object?> { }
}
namespace EnvelopeGenerator.Application.DTOs.Messaging;
/// <summary>
///
/// </summary>
[ApiExplorerSettings(IgnoreApi = true)]
public class GtxMessagingResponse : Dictionary<string, object?> { }

View File

@@ -1,14 +1,25 @@
using Microsoft.AspNetCore.Mvc;
namespace EnvelopeGenerator.Application.DTOs.Messaging
namespace EnvelopeGenerator.Application.DTOs.Messaging;
/// <summary>
///
/// </summary>
[ApiExplorerSettings(IgnoreApi = true)]
public record SmsResponse
{
[ApiExplorerSettings(IgnoreApi = true)]
public record SmsResponse
{
public required bool Ok { get; init; }
/// <summary>
///
/// </summary>
public required bool Ok { get; init; }
public bool Failed => !Ok;
/// <summary>
/// Returns !Ok
/// </summary>
public bool Failed => !Ok;
public dynamic? Errors { get; init; }
}
/// <summary>
///
/// </summary>
public dynamic? Errors { get; init; }
}

View File

@@ -3,21 +3,51 @@ using System.ComponentModel.DataAnnotations;
using System.Security.Cryptography;
using System.Text;
namespace EnvelopeGenerator.Application.DTOs.Receiver
{
[ApiExplorerSettings(IgnoreApi = true)]
public record ReceiverCreateDto([EmailAddress] string EmailAddress, string? TotpSecretkey = null)
{
public string Signature => sha256HexOfMail.Value;
namespace EnvelopeGenerator.Application.DTOs.Receiver;
private readonly Lazy<string> sha256HexOfMail = new(() =>
/// <summary>
///
/// </summary>
[ApiExplorerSettings(IgnoreApi = true)]
public record ReceiverCreateDto
{
/// <summary>
///
/// </summary>
public ReceiverCreateDto()
{
_sha256HexOfMail = new(() =>
{
var bytes_arr = Encoding.UTF8.GetBytes(EmailAddress.ToUpper());
var bytes_arr = Encoding.UTF8.GetBytes(EmailAddress!.ToUpper());
var hash_arr = SHA256.HashData(bytes_arr);
var hexa_str = BitConverter.ToString(hash_arr);
return hexa_str.Replace("-", string.Empty);
});
}
public DateTime AddedWhen { get; } = DateTime.Now;
};
}
/// <summary>
///
/// </summary>
[EmailAddress]
public required string EmailAddress { get; init; }
/// <summary>
///
/// </summary>
public string? TotpSecretkey { get; init; }
/// <summary>
/// var bytes_arr = Encoding.UTF8.GetBytes(EmailAddress.ToUpper());<br/>
/// var hash_arr = SHA256.HashData(bytes_arr);
/// var hexa_str = BitConverter.ToString(hash_arr);
/// return hexa_str.Replace("-", string.Empty);
/// </summary>
public string Signature => _sha256HexOfMail.Value;
private readonly Lazy<string> _sha256HexOfMail;
/// <summary>
/// Default value is DateTime.Now
/// </summary>
public DateTime AddedWhen { get; } = DateTime.Now;
};

View File

@@ -1,25 +1,62 @@
using DigitalData.Core.Abstractions;
using DigitalData.Core.DTO;
using EnvelopeGenerator.Application.DTOs.EnvelopeReceiver;
using EnvelopeGenerator.Application.DTOs.EnvelopeReceiver;
using Microsoft.AspNetCore.Mvc;
using System.Text.Json.Serialization;
namespace EnvelopeGenerator.Application.DTOs.Receiver;
/// <summary>
///
/// </summary>
[ApiExplorerSettings(IgnoreApi = true)]
public record ReceiverReadDto(
int Id,
string EmailAddress,
string Signature,
DateTime AddedWhen
) : BaseDTO<int>(Id), IUnique<int>
public class ReceiverReadDto
{
[JsonIgnore]
public IEnumerable<EnvelopeReceiverBasicDto>? EnvelopeReceivers { get; init; }
/// <summary>
///
/// </summary>
public int Id { get; set; }
/// <summary>
///
/// </summary>
public required string EmailAddress { get; set; }
/// <summary>
///
/// </summary>
public required string Signature { get; set; }
/// <summary>
///
/// </summary>
public DateTime AddedWhen { get; set; }
/// <summary>
///
/// </summary>
[JsonIgnore]
public IEnumerable<EnvelopeReceiverBasicDto>? EnvelopeReceivers { get; set; }
/// <summary>
///
/// </summary>
public string? LastUsedName => EnvelopeReceivers?.LastOrDefault()?.Name;
/// <summary>
///
/// </summary>
public string? TotpSecretkey { get; set; } = null;
/// <summary>
///
/// </summary>
public DateTime? TfaRegDeadline { get; set; }
};
/// <summary>
///
/// </summary>
/// <returns></returns>
public override int GetHashCode()
{
return Id.GetHashCode();
}
}

View File

@@ -1,7 +1,27 @@
using DigitalData.Core.Abstractions;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc;
namespace EnvelopeGenerator.Application.DTOs.Receiver;
/// <summary>
/// Data Transfer Object for updating a receiver's information.
/// </summary>
[ApiExplorerSettings(IgnoreApi = true)]
public record ReceiverUpdateDto(int Id, string? TotpSecretkey = null, DateTime? TfaRegDeadline = null) : IUnique<int>;
public class ReceiverUpdateDto
{
/// <summary>
/// Gets or sets the unique identifier of the receiver.
/// </summary>
public int Id { get; set; }
/// <summary>
/// Gets or sets the TOTP (Time-based One-Time Password) secret key.
/// Optional.
/// </summary>
public string? TotpSecretkey { get; set; }
/// <summary>
/// Gets or sets the deadline for two-factor authentication registration.
/// Optional.
/// </summary>
public DateTime? TfaRegDeadline { get; set; }
}

View File

@@ -1,15 +0,0 @@
using DigitalData.Core.Abstractions;
using Microsoft.AspNetCore.Mvc;
namespace EnvelopeGenerator.Application.DTOs
{
[ApiExplorerSettings(IgnoreApi = true)]
public record UserReceiverDto(
int Id,
int UserId,
int ReceiverId,
string Name,
string CompanyName,
string JobTitle,
DateTime AddedWhen) : IUnique<int>;
}

View File

@@ -22,6 +22,7 @@ public static class DependencyInjection
/// <param name="services"></param>
/// <param name="config"></param>
/// <returns></returns>
[Obsolete("Use MediatR")]
public static IServiceCollection AddEnvelopeGeneratorServices(this IServiceCollection services, IConfiguration config)
{
//Inject CRUD Service and repositoriesad
@@ -37,7 +38,6 @@ public static class DependencyInjection
services.TryAddScoped<IEnvelopeReceiverService, EnvelopeReceiverService>();
services.TryAddScoped<IEnvelopeTypeService, EnvelopeTypeService>();
services.TryAddScoped<IReceiverService, ReceiverService>();
services.TryAddScoped<IUserReceiverService, UserReceiverService>();
services.TryAddScoped<IEnvelopeReceiverReadOnlyService, EnvelopeReceiverReadOnlyService>();
//Auto mapping profiles

View File

@@ -1,4 +1,4 @@
using DigitalData.Core.Abstractions.Infrastructure;
using DigitalData.Core.Abstraction.Application.Repository;
using EnvelopeGenerator.Domain.Entities;
using MediatR;
@@ -34,6 +34,7 @@ public class ReadDocumentQueryHandler : IRequestHandler<ReadDocumentQuery, ReadD
/// <exception cref="InvalidOperationException">
/// Thrown when neither <see cref="ReadDocumentQuery.Id"/> nor <see cref="ReadDocumentQuery.EnvelopeId"/> is provided.
/// </exception>
[Obsolete("Use MediatR")]
public async Task<ReadDocumentResponse?> Handle(ReadDocumentQuery query, CancellationToken cancellationToken)
{
if (query.Id is not null)

View File

@@ -1,24 +1,23 @@
using EnvelopeGenerator.Common;
using EnvelopeGenerator.Domain;
using MediatR;
namespace EnvelopeGenerator.Application.EmailTemplates.Commands.Reset;
/// <summary>
/// Ein Befehl zum Zurücksetzen einer E-Mail-Vorlage auf die Standardwerte.
/// Erbt von <see cref="EmailTemplateQuery"/> und ermöglicht die Angabe einer optionalen ID und eines Typs der E-Mail-Vorlage.
/// Erbt von <see cref="EmailTemplateQuery"/> und ermöglicht die Angabe einer optionalen ID und eines Typs der E-Mail-Vorlage.<br/><br/>
/// Beispiele:<br/>
/// 0 - DocumentReceived: Benachrichtigung über den Empfang eines Dokuments.<br/>
/// 1 - DocumentSigned: Benachrichtigung über die Unterzeichnung eines Dokuments.<br/>
/// 2 - DocumentDeleted: Benachrichtigung über das Löschen eines Dokuments.<br/>
/// 3 - DocumentCompleted: Benachrichtigung über den Abschluss eines Dokuments.<br/>
/// 4 - DocumentAccessCodeReceived: Benachrichtigung über den Erhalt eines Zugangscodes.<br/>
/// 5 - DocumentShared: Benachrichtigung über das Teilen eines Dokuments.<br/>
/// 6 - TotpSecret: Benachrichtigung über ein TOTP-Geheimnis.<br/>
/// 7 - DocumentRejected_ADM (Für den Absender): Mail an den Absender, wenn das Dokument abgelehnt wird.<br/>
/// 8 - DocumentRejected_REC (Für den ablehnenden Empfänger): Mail an den ablehnenden Empfänger, wenn das Dokument abgelehnt wird.<br/>
/// 9 - DocumentRejected_REC_2 (Für sonstige Empfänger): Mail an andere Empfänger (Brief), wenn das Dokument abgelehnt wird.<br/>
/// </summary>
/// Beispiele:
/// 0 - DocumentReceived: Benachrichtigung über den Empfang eines Dokuments.
/// 1 - DocumentSigned: Benachrichtigung über die Unterzeichnung eines Dokuments.
/// 2 - DocumentDeleted: Benachrichtigung über das Löschen eines Dokuments.
/// 3 - DocumentCompleted: Benachrichtigung über den Abschluss eines Dokuments.
/// 4 - DocumentAccessCodeReceived: Benachrichtigung über den Erhalt eines Zugangscodes.
/// 5 - DocumentShared: Benachrichtigung über das Teilen eines Dokuments.
/// 6 - TotpSecret: Benachrichtigung über ein TOTP-Geheimnis.
/// 7 - DocumentRejected_ADM (Für den Absender): Mail an den Absender, wenn das Dokument abgelehnt wird.
/// 8 - DocumentRejected_REC (Für den ablehnenden Empfänger): Mail an den ablehnenden Empfänger, wenn das Dokument abgelehnt wird.
/// 9 - DocumentRejected_REC_2 (Für sonstige Empfänger): Mail an andere Empfänger (Brief), wenn das Dokument abgelehnt wird.
/// </param>
public record ResetEmailTemplateCommand : EmailTemplateQuery, IRequest
{
/// <summary>
@@ -34,8 +33,8 @@ public record ResetEmailTemplateCommand : EmailTemplateQuery, IRequest
///
/// </summary>
/// <param name="Id">Die optionale ID der E-Mail-Vorlage, die zurückgesetzt werden soll.</param>
/// <param name="Type">Der Typ der E-Mail-Vorlage, z. B. <see cref="Constants.EmailTemplateType"/> (optional).
/// <param name="Type">Der Typ der E-Mail-Vorlage, z. B. <see cref="Constants.EmailTemplateType"/> (optional).</param>
public ResetEmailTemplateCommand(int? Id = null, Constants.EmailTemplateType? Type = null) : base(Id, Type)
{
}
};
};

View File

@@ -1,6 +1,5 @@
using DigitalData.Core.Abstractions.Infrastructure;
using DigitalData.Core.Abstraction.Application.Repository;
using EnvelopeGenerator.Application.DTOs;
using EnvelopeGenerator.Application.EmailTemplates.Queries.Read;
using EnvelopeGenerator.Domain.Entities;
using MediatR;
@@ -28,13 +27,14 @@ public class ResetEmailTemplateCommandHandler : IRequestHandler<ResetEmailTempla
/// <param name="request"></param>
/// <param name="cancel"></param>
/// <returns></returns>
[Obsolete("Use Read-method returning IReadQuery<TEntity> instead.")]
public async Task Handle(ResetEmailTemplateCommand request, CancellationToken cancel)
{
var temps = request.Id is not null
? await _repository.ReadAllAsync<EmailTemplateDto>(t => t.Id == request.Id, cancel)
: request.Type is not null
? await _repository.ReadAllAsync<EmailTemplateDto>(t => t.Name == request.Type.ToString(), cancel)
: await _repository.ReadAllAsync<EmailTemplateDto>(ct: cancel);
: await _repository.ReadAllAsync<EmailTemplateDto>(cancellation: cancel);
foreach (var temp in temps)
{
@@ -70,7 +70,7 @@ public class ResetEmailTemplateCommandHandler : IRequestHandler<ResetEmailTempla
new(){
Id = 4,
Name = "DocumentCompleted",
Body = "Guten Tag [NAME_RECEIVER],<br />\r\n<br />\r\nDer Signaturvorgang <B><I>'[DOCUMENT_TITLE]'</I></B> wurde erfolgreich abgeschlossen.<br />\r\n<br />\r\nSie erhalten das Dokument mit einem detaillierten Ergebnisbericht als Anhang zu dieser Email.<br />\r\n<br />\r\nMit freundlichen Grüßen<br />\r\n<br />\r\n[NAME_PORTAL]",
Body = "Guten Tag [NAME_RECEIVER],<br />\r\n<br />\r\nDer Signaturvorgang <B><I>'[DOCUMENT_TITLE]'</I></B> wurde erfolgreich abgeschlossen.<br />\r\n<br />\r\nSie erhalten das Dokument mit einem detaillierten Ergebnisbericht als Anhang zu dieser EmailAddress.<br />\r\n<br />\r\nMit freundlichen Grüßen<br />\r\n<br />\r\n[NAME_PORTAL]",
Subject = "Umschlag abgeschlossen: '[DOCUMENT_TITLE]'"
},
new(){

View File

@@ -1,6 +1,7 @@
using DigitalData.Core.Abstractions.Infrastructure;
using DigitalData.Core.Abstraction.Application.Repository;
using EnvelopeGenerator.Application.DTOs;
using EnvelopeGenerator.Application.Exceptions;
using EnvelopeGenerator.Domain;
using EnvelopeGenerator.Domain.Entities;
using MediatR;
@@ -30,6 +31,7 @@ public class UpdateEmailTemplateCommandHandler : IRequestHandler<UpdateEmailTemp
/// <returns></returns>
/// <exception cref="InvalidOperationException"></exception>
/// <exception cref="NotFoundException"></exception>
[Obsolete("Use Read-method returning IReadQuery<TEntity> instead.")]
public async Task Handle(UpdateEmailTemplateCommand request, CancellationToken cancel)
{
EmailTemplateDto? temp;
@@ -38,7 +40,7 @@ public class UpdateEmailTemplateCommandHandler : IRequestHandler<UpdateEmailTemp
{
temp = await _repository.ReadOrDefaultAsync<EmailTemplateDto>(t => t.Id == id, single: false, cancel);
}
else if (request!.EmailTemplateQuery!.Type is Common.Constants.EmailTemplateType type)
else if (request!.EmailTemplateQuery!.Type is Constants.EmailTemplateType type)
{
temp = await _repository.ReadOrDefaultAsync<EmailTemplateDto>(t => t.Name == type.ToString(), single: false, cancel);
}

View File

@@ -1,4 +1,4 @@
using EnvelopeGenerator.Common;
using EnvelopeGenerator.Domain;
namespace EnvelopeGenerator.Application.EmailTemplates;
@@ -21,4 +21,4 @@ namespace EnvelopeGenerator.Application.EmailTemplates;
/// </param>
public record EmailTemplateQuery(int? Id = null, Constants.EmailTemplateType? Type = null)
{
}
}

View File

@@ -1,10 +1,7 @@
using AutoMapper;
using EnvelopeGenerator.Application.Contracts.Repositories;
using EnvelopeGenerator.Application.DTOs;
using EnvelopeGenerator.Common;
using EnvelopeGenerator.Domain;
using MediatR;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
namespace EnvelopeGenerator.Application.EmailTemplates.Queries.Read;
@@ -15,6 +12,7 @@ public class ReadEmailTemplateQueryHandler : IRequestHandler<ReadEmailTemplateQu
{
private readonly IMapper _mapper;
[Obsolete("Use Read-method returning IReadQuery<TEntity> instead.")]
private readonly IEmailTemplateRepository _repository;
/// <summary>
@@ -24,6 +22,7 @@ public class ReadEmailTemplateQueryHandler : IRequestHandler<ReadEmailTemplateQu
/// <param name="repository">
/// Die AutoMapper-Instanz, die zum Zuordnen von Objekten verwendet wird.
/// </param>
[Obsolete("Use Read-method returning IReadQuery<TEntity> instead.")]
public ReadEmailTemplateQueryHandler(IMapper mapper, IEmailTemplateRepository repository)
{
_mapper = mapper;
@@ -37,6 +36,7 @@ public class ReadEmailTemplateQueryHandler : IRequestHandler<ReadEmailTemplateQu
/// <param name="cancellationToken"></param>
/// <returns></returns>
/// <exception cref="InvalidOperationException"></exception>
[Obsolete("Use IRepository")]
public async Task<ReadEmailTemplateResponse?> Handle(ReadEmailTemplateQuery request, CancellationToken cancellationToken)
{
var temp = request.Id is int id
@@ -49,4 +49,4 @@ public class ReadEmailTemplateQueryHandler : IRequestHandler<ReadEmailTemplateQu
return res;
}
}
}

View File

@@ -14,24 +14,20 @@
<ItemGroup>
<PackageReference Include="Dapper" Version="2.1.66" />
<PackageReference Include="DigitalData.Core.Abstractions" Version="3.6.0" />
<PackageReference Include="DigitalData.Core.Application" Version="3.2.1" />
<PackageReference Include="DigitalData.Core.Client" Version="2.0.3" />
<PackageReference Include="DigitalData.Core.DTO" Version="2.0.1" />
<PackageReference Include="DigitalData.EmailProfilerDispatcher" Version="3.0.0" />
<PackageReference Include="DigitalData.Core.Abstraction.Application" Version="1.0.0" />
<PackageReference Include="DigitalData.Core.Application" Version="3.3.4" />
<PackageReference Include="DigitalData.Core.Client" Version="2.1.0" />
<PackageReference Include="DigitalData.EmailProfilerDispatcher" Version="3.1.1" />
<PackageReference Include="MediatR" Version="12.5.0" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="7.0.18" />
<PackageReference Include="Microsoft.Data.SqlClient" Version="5.1.1" />
<PackageReference Include="Microsoft.Data.SqlClient" Version="6.0.2" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="9.0.4" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="9.0.5" />
<PackageReference Include="Otp.NET" Version="1.4.0" />
<PackageReference Include="QRCoder" Version="1.6.0" />
<PackageReference Include="QRCoder-ImageSharp" Version="0.10.0" />
<PackageReference Include="UserManager" Version="1.0.0" />
<PackageReference Include="UserManager" Version="1.1.1" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\EnvelopeGenerator.Common\EnvelopeGenerator.Common.vbproj" />
<ProjectReference Include="..\EnvelopeGenerator.Domain\EnvelopeGenerator.Domain.csproj" />
<ProjectReference Include="..\EnvelopeGenerator.Extensions\EnvelopeGenerator.Extensions.csproj" />
</ItemGroup>
@@ -65,6 +61,7 @@
<ItemGroup Condition="'$(TargetFramework)' == 'net7.0'">
<PackageReference Include="AutoMapper" Version="13.0.1" />
<PackageReference Include="Microsoft.Data.SqlClient" Version="5.2.3" />
<PackageReference Include="CommandDotNet">
<Version>7.0.5</Version>
</PackageReference>
@@ -72,6 +69,7 @@
<ItemGroup Condition="'$(TargetFramework)' == 'net8.0'">
<PackageReference Include="AutoMapper" Version="14.0.0" />
<PackageReference Include="Microsoft.Data.SqlClient" Version="6.0.2" />
<PackageReference Include="CommandDotNet">
<Version>8.1.1</Version>
</PackageReference>
@@ -79,6 +77,7 @@
<ItemGroup Condition="'$(TargetFramework)' == 'net9.0'">
<PackageReference Include="AutoMapper" Version="14.0.0" />
<PackageReference Include="Microsoft.Data.SqlClient" Version="6.0.2" />
<PackageReference Include="CommandDotNet">
<Version>8.1.1</Version>
</PackageReference>

View File

@@ -18,4 +18,4 @@ public record CreateEnvelopeReceiverCommand(
[Required] DocumentCreateCommand Document,
[Required] IEnumerable<ReceiverGetOrCreateCommand> Receivers,
bool TFAEnabled = false
) : CreateEnvelopeCommand(Title, Message, TFAEnabled), IRequest<CreateEnvelopeReceiverResponse?>;
) : CreateEnvelopeCommand(Title, Message, TFAEnabled), IRequest<CreateEnvelopeReceiverResponse>;

View File

@@ -64,4 +64,4 @@ public class CreateEnvelopeReceiverCommandHandler : IRequestHandler<CreateEnvelo
res.SentReceiver = _mapper.Map<IEnumerable<ReceiverReadDto>>(sentRecipients);
return res;
}
}
}

View File

@@ -1,4 +1,4 @@
using EnvelopeGenerator.Common;
using EnvelopeGenerator.Domain;
namespace EnvelopeGenerator.Application.Envelopes.Queries.Read;

View File

@@ -1,131 +1,222 @@
using Microsoft.Extensions.Caching.Distributed;
namespace EnvelopeGenerator.Application.Extensions
namespace EnvelopeGenerator.Application.Extensions;
/// <summary>
///
/// </summary>
public static class CacheExtensions
{
public static class CacheExtensions
/// <summary>
///
/// </summary>
/// <param name="cache"></param>
/// <param name="key"></param>
/// <param name="value"></param>
/// <param name="options"></param>
/// <param name="cToken"></param>
/// <returns></returns>
public static Task SetLongAsync(this IDistributedCache cache, string key, long value, DistributedCacheEntryOptions? options = null, CancellationToken cToken = default)
=> options is null
? cache.SetAsync(key, BitConverter.GetBytes(value), token: cToken)
: cache.SetAsync(key, BitConverter.GetBytes(value), options: options, token: cToken);
/// <summary>
///
/// </summary>
/// <param name="cache"></param>
/// <param name="key"></param>
/// <param name="cToken"></param>
/// <returns></returns>
public static async Task<long?> GetLongAsync(this IDistributedCache cache, string key, CancellationToken cToken = default)
{
public static Task SetLongAsync(this IDistributedCache cache, string key, long value, DistributedCacheEntryOptions? options = null, CancellationToken cToken = default)
=> options is null
? cache.SetAsync(key, BitConverter.GetBytes(value), token: cToken)
: cache.SetAsync(key, BitConverter.GetBytes(value), options: options, token: cToken);
public static async Task<long?> GetLongAsync(this IDistributedCache cache, string key, CancellationToken cToken = default)
{
var value = await cache.GetAsync(key, cToken);
return value is null ? null : BitConverter.ToInt64(value, 0);
}
public static Task SetDateTimeAsync(this IDistributedCache cache, string key, DateTime value, DistributedCacheEntryOptions? options = null, CancellationToken cToken = default)
=> cache.SetLongAsync(key: key, value: value.Ticks, options: options, cToken: cToken);
public static async Task<DateTime?> GetDateTimeAsync(this IDistributedCache cache, string key, CancellationToken cToken = default)
{
var value = await cache.GetAsync(key, cToken);
return value is null ? null : new(BitConverter.ToInt64(value, 0));
}
public static Task SetTimeSpanAsync(this IDistributedCache cache, string key, TimeSpan value, DistributedCacheEntryOptions? options = null, CancellationToken cToken = default)
=> cache.SetLongAsync(key: key, value: value.Ticks, options: options, cToken);
public static async Task<TimeSpan?> GetTimeSpanAsync(this IDistributedCache cache, string key, CancellationToken cToken = default)
{
var value = await cache.GetAsync(key, cToken);
return value is null ? null : new(BitConverter.ToInt64(value, 0));
}
//TODO: use code generator
#region GetOrSetAsync
#region string
public static async Task<string> GetOrSetAsync(this IDistributedCache cache, string key, Func<string> factory, DistributedCacheEntryOptions? options = null, bool cacheInBackground = false, CancellationToken cToken = default)
{
var value = await cache.GetStringAsync(key, cToken);
if (value is null)
{
// create new and save
value = factory();
Task CacheAsync() => options is null
? cache.SetStringAsync(key, value, cToken)
: cache.SetStringAsync(key, value, options, cToken);
if (cacheInBackground)
_ = Task.Run(async () => await CacheAsync(), cToken);
else
await CacheAsync();
}
return value;
}
public static async Task<string> GetOrSetAsync(this IDistributedCache cache, string key, Func<Task<string>> factoryAsync, DistributedCacheEntryOptions? options = null, bool cacheInBackground = false, CancellationToken cToken = default)
{
var value = await cache.GetStringAsync(key, cToken);
if(value is null)
{
// create new and save
value = await factoryAsync();
Task CacheAsync() => options is null
? cache.SetStringAsync(key: key, value: value, token: cToken)
: cache.SetStringAsync(key: key, value: value, options: options, token: cToken);
if (cacheInBackground)
_ = Task.Run(async () => await CacheAsync(), cToken);
else
await CacheAsync();
}
return value;
}
#endregion
#region DateTime
public static async Task<DateTime> GetOrSetAsync(this IDistributedCache cache, string key, Func<DateTime> factory, DistributedCacheEntryOptions? options = null, bool cacheInBackground = false, CancellationToken cToken = default)
{
if (await cache.GetDateTimeAsync(key, cToken) is DateTime dateTimeValue)
return dateTimeValue;
else
{
// create new and save
var newValue = factory();
Task CacheAsync() => options is null
? cache.SetDateTimeAsync(key, newValue, cToken: cToken)
: cache.SetDateTimeAsync(key, newValue, options, cToken);
if (cacheInBackground)
_ = Task.Run(async () => await CacheAsync(), cToken);
else
await CacheAsync();
return newValue;
}
}
public static async Task<DateTime> GetOrSetAsync(this IDistributedCache cache, string key, Func<Task<DateTime>> factory, DistributedCacheEntryOptions? options = null, bool cacheInBackground = false, CancellationToken cToken = default)
{
if (await cache.GetDateTimeAsync(key, cToken) is DateTime dateTimeValue)
return dateTimeValue;
else
{
// create new and save
var newValue = await factory();
Task CacheAsync() => options is null
? cache.SetDateTimeAsync(key, newValue, cToken: cToken)
: cache.SetDateTimeAsync(key, newValue, options, cToken);
if (cacheInBackground)
_ = Task.Run(async () => await CacheAsync(), cToken);
else
await CacheAsync();
return newValue;
}
}
#endregion
#endregion
var value = await cache.GetAsync(key, cToken);
return value is null ? null : BitConverter.ToInt64(value, 0);
}
/// <summary>
///
/// </summary>
/// <param name="cache"></param>
/// <param name="key"></param>
/// <param name="value"></param>
/// <param name="options"></param>
/// <param name="cToken"></param>
/// <returns></returns>
public static Task SetDateTimeAsync(this IDistributedCache cache, string key, DateTime value, DistributedCacheEntryOptions? options = null, CancellationToken cToken = default)
=> cache.SetLongAsync(key: key, value: value.Ticks, options: options, cToken: cToken);
/// <summary>
///
/// </summary>
/// <param name="cache"></param>
/// <param name="key"></param>
/// <param name="cToken"></param>
/// <returns></returns>
public static async Task<DateTime?> GetDateTimeAsync(this IDistributedCache cache, string key, CancellationToken cToken = default)
{
var value = await cache.GetAsync(key, cToken);
return value is null ? null : new(BitConverter.ToInt64(value, 0));
}
/// <summary>
///
/// </summary>
/// <param name="cache"></param>
/// <param name="key"></param>
/// <param name="value"></param>
/// <param name="options"></param>
/// <param name="cToken"></param>
/// <returns></returns>
public static Task SetTimeSpanAsync(this IDistributedCache cache, string key, TimeSpan value, DistributedCacheEntryOptions? options = null, CancellationToken cToken = default)
=> cache.SetLongAsync(key: key, value: value.Ticks, options: options, cToken);
/// <summary>
///
/// </summary>
/// <param name="cache"></param>
/// <param name="key"></param>
/// <param name="cToken"></param>
/// <returns></returns>
public static async Task<TimeSpan?> GetTimeSpanAsync(this IDistributedCache cache, string key, CancellationToken cToken = default)
{
var value = await cache.GetAsync(key, cToken);
return value is null ? null : new(BitConverter.ToInt64(value, 0));
}
//TODO: use code generator
#region GetOrSetAsync
#region string
/// <summary>
///
/// </summary>
/// <param name="cache"></param>
/// <param name="key"></param>
/// <param name="factory"></param>
/// <param name="options"></param>
/// <param name="cacheInBackground"></param>
/// <param name="cToken"></param>
/// <returns></returns>
public static async Task<string> GetOrSetAsync(this IDistributedCache cache, string key, Func<string> factory, DistributedCacheEntryOptions? options = null, bool cacheInBackground = false, CancellationToken cToken = default)
{
var value = await cache.GetStringAsync(key, cToken);
if (value is null)
{
// create new and save
value = factory();
Task CacheAsync() => options is null
? cache.SetStringAsync(key, value, cToken)
: cache.SetStringAsync(key, value, options, cToken);
if (cacheInBackground)
_ = Task.Run(async () => await CacheAsync(), cToken);
else
await CacheAsync();
}
return value;
}
/// <summary>
///
/// </summary>
/// <param name="cache"></param>
/// <param name="key"></param>
/// <param name="factoryAsync"></param>
/// <param name="options"></param>
/// <param name="cacheInBackground"></param>
/// <param name="cToken"></param>
/// <returns></returns>
public static async Task<string> GetOrSetAsync(this IDistributedCache cache, string key, Func<Task<string>> factoryAsync, DistributedCacheEntryOptions? options = null, bool cacheInBackground = false, CancellationToken cToken = default)
{
var value = await cache.GetStringAsync(key, cToken);
if(value is null)
{
// create new and save
value = await factoryAsync();
Task CacheAsync() => options is null
? cache.SetStringAsync(key: key, value: value, token: cToken)
: cache.SetStringAsync(key: key, value: value, options: options, token: cToken);
if (cacheInBackground)
_ = Task.Run(async () => await CacheAsync(), cToken);
else
await CacheAsync();
}
return value;
}
#endregion
#region DateTime
/// <summary>
///
/// </summary>
/// <param name="cache"></param>
/// <param name="key"></param>
/// <param name="factory"></param>
/// <param name="options"></param>
/// <param name="cacheInBackground"></param>
/// <param name="cToken"></param>
/// <returns></returns>
public static async Task<DateTime> GetOrSetAsync(this IDistributedCache cache, string key, Func<DateTime> factory, DistributedCacheEntryOptions? options = null, bool cacheInBackground = false, CancellationToken cToken = default)
{
if (await cache.GetDateTimeAsync(key, cToken) is DateTime dateTimeValue)
return dateTimeValue;
else
{
// create new and save
var newValue = factory();
Task CacheAsync() => options is null
? cache.SetDateTimeAsync(key, newValue, cToken: cToken)
: cache.SetDateTimeAsync(key, newValue, options, cToken);
if (cacheInBackground)
_ = Task.Run(async () => await CacheAsync(), cToken);
else
await CacheAsync();
return newValue;
}
}
/// <summary>
///
/// </summary>
/// <param name="cache"></param>
/// <param name="key"></param>
/// <param name="factory"></param>
/// <param name="options"></param>
/// <param name="cacheInBackground"></param>
/// <param name="cToken"></param>
/// <returns></returns>
public static async Task<DateTime> GetOrSetAsync(this IDistributedCache cache, string key, Func<Task<DateTime>> factory, DistributedCacheEntryOptions? options = null, bool cacheInBackground = false, CancellationToken cToken = default)
{
if (await cache.GetDateTimeAsync(key, cToken) is DateTime dateTimeValue)
return dateTimeValue;
else
{
// create new and save
var newValue = await factory();
Task CacheAsync() => options is null
? cache.SetDateTimeAsync(key, newValue, cToken: cToken)
: cache.SetDateTimeAsync(key, newValue, options, cToken);
if (cacheInBackground)
_ = Task.Run(async () => await CacheAsync(), cToken);
else
await CacheAsync();
return newValue;
}
}
#endregion
#endregion
}

View File

@@ -1,14 +1,27 @@
using EnvelopeGenerator.Application.DTOs.Messaging;
namespace EnvelopeGenerator.Application.Extensions
{
public static class MappingExtensions
{
public static bool Ok(this GtxMessagingResponse gtxMessagingResponse)
=> gtxMessagingResponse.TryGetValue("message-status", out var status)
&& status?.ToString()?.ToLower() == "ok";
namespace EnvelopeGenerator.Application.Extensions;
public static string ToBase64String(this byte[] bytes)
=> Convert.ToBase64String(bytes);
}
/// <summary>
/// Provides extension methods for common mapping and conversion operations.
/// </summary>
public static class MappingExtensions
{
/// <summary>
/// Determines whether the response indicates a successful "OK" message status.
/// </summary>
/// <param name="gtxMessagingResponse">The response object to evaluate.</param>
/// <returns><see langword="true"/> if the response contains a "message-status" key with a value of "ok" (case-insensitive);
/// otherwise, <see langword="false"/>.</returns>
public static bool Ok(this GtxMessagingResponse gtxMessagingResponse)
=> gtxMessagingResponse.TryGetValue("message-status", out var status)
&& status?.ToString()?.ToLower() == "ok";
/// <summary>
/// Converts the specified byte array to its equivalent string representation encoded in base-64.
/// </summary>
/// <param name="bytes">The byte array to encode.</param>
/// <returns>A base-64 encoded string representation of the input byte array.</returns>
public static string ToBase64String(this byte[] bytes)
=> Convert.ToBase64String(bytes);
}

View File

@@ -1,4 +1,4 @@
using EnvelopeGenerator.Common;
using EnvelopeGenerator.Domain;
using MediatR;
using System.ComponentModel.DataAnnotations;

View File

@@ -10,6 +10,7 @@ namespace EnvelopeGenerator.Application.Histories.Queries.Read;
/// </summary>
public class ReadHistoryQueryHandler : IRequestHandler<ReadHistoryQuery, IEnumerable<ReadHistoryResponse>>
{
[Obsolete("Use IRepository")]
private readonly IEnvelopeHistoryRepository _repository;
private readonly IMapper _mapper;
@@ -19,6 +20,7 @@ public class ReadHistoryQueryHandler : IRequestHandler<ReadHistoryQuery, IEnumer
/// </summary>
/// <param name="repository"></param>
/// <param name="mapper"></param>
[Obsolete("Use IRepository")]
public ReadHistoryQueryHandler(IEnvelopeHistoryRepository repository, IMapper mapper)
{
_repository = repository;
@@ -34,11 +36,11 @@ public class ReadHistoryQueryHandler : IRequestHandler<ReadHistoryQuery, IEnumer
/// <exception cref="NotFoundException"></exception>
public async Task<IEnumerable<ReadHistoryResponse>> Handle(ReadHistoryQuery request, CancellationToken cancellationToken)
{
var hists = await _repository.ReadAsync(request.EnvelopeId, status: request.Status is null ? null : (int) request.Status);
var hists = await _repository.ReadAsync(request.EnvelopeId, status: request.Status is null ? null : request.Status);
if (!hists.Any())
throw new NotFoundException();
return _mapper.Map<IEnumerable<ReadHistoryResponse>>(hists);
}
}
}

View File

@@ -1,4 +1,4 @@
using EnvelopeGenerator.Common;
using EnvelopeGenerator.Domain;
namespace EnvelopeGenerator.Application.Histories.Queries.Read;
@@ -20,7 +20,7 @@ public class ReadHistoryResponse
/// <summary>
/// Gets or sets the reference identifier of the user who performed the action.
/// </summary>
public string UserReference { get; set; }
public required string UserReference { get; set; }
/// <summary>
/// Gets or sets the status code of the envelope.
@@ -30,7 +30,7 @@ public class ReadHistoryResponse
/// <summary>
///
/// </summary>
public Common.Constants.ReferenceType ReferenceType => Status.ToString().FirstOrDefault() switch
public Constants.ReferenceType ReferenceType => Status.ToString().FirstOrDefault() switch
{
'1' => Constants.ReferenceType.Sender,
'2' => Constants.ReferenceType.Receiver,

View File

@@ -1,20 +1,82 @@
namespace EnvelopeGenerator.Application
namespace EnvelopeGenerator.Application;
/// <summary>
///
/// </summary>
public static class Key
{
public static class Key
{
public static readonly string InnerServiceError = nameof(InnerServiceError);
public static readonly string EnvelopeNotFound = nameof(EnvelopeNotFound);
public static readonly string EnvelopeReceiverNotFound = nameof(EnvelopeReceiverNotFound);
public static readonly string AccessCodeNull = nameof(AccessCodeNull);
public static readonly string WrongAccessCode = nameof(WrongAccessCode);
public static readonly string DataIntegrityIssue = nameof(DataIntegrityIssue);
public static readonly string SecurityBreachOrDataIntegrity = nameof(SecurityBreachOrDataIntegrity);
public static readonly string PossibleDataIntegrityIssue = nameof(PossibleDataIntegrityIssue);
public static readonly string SecurityBreach = nameof(SecurityBreach);
public static readonly string PossibleSecurityBreach = nameof(PossibleSecurityBreach);
public static readonly string WrongEnvelopeReceiverId = nameof(WrongEnvelopeReceiverId);
public static readonly string EnvelopeOrReceiverNonexists = nameof(EnvelopeOrReceiverNonexists);
public static readonly string PhoneNumberNonexists = nameof(PhoneNumberNonexists);
public static readonly string Default = nameof(Default);
}
/// <summary>
///
/// </summary>
public static readonly string InnerServiceError = nameof(InnerServiceError);
/// <summary>
///
/// </summary>
public static readonly string EnvelopeNotFound = nameof(EnvelopeNotFound);
/// <summary>
///
/// </summary>
public static readonly string EnvelopeReceiverNotFound = nameof(EnvelopeReceiverNotFound);
/// <summary>
///
/// </summary>
public static readonly string AccessCodeNull = nameof(AccessCodeNull);
/// <summary>
///
/// </summary>
public static readonly string WrongAccessCode = nameof(WrongAccessCode);
/// <summary>
///
/// </summary>
public static readonly string DataIntegrityIssue = nameof(DataIntegrityIssue);
/// <summary>
///
/// </summary>
public static readonly string SecurityBreachOrDataIntegrity = nameof(SecurityBreachOrDataIntegrity);
/// <summary>
///
/// </summary>
public static readonly string PossibleDataIntegrityIssue = nameof(PossibleDataIntegrityIssue);
/// <summary>
///
/// </summary>
public static readonly string SecurityBreach = nameof(SecurityBreach);
/// <summary>
///
/// </summary>
public static readonly string PossibleSecurityBreach = nameof(PossibleSecurityBreach);
/// <summary>
///
/// </summary>
public static readonly string WrongEnvelopeReceiverId = nameof(WrongEnvelopeReceiverId);
/// <summary>
///
/// </summary>
public static readonly string EnvelopeOrReceiverNonexists = nameof(EnvelopeOrReceiverNonexists);
/// <summary>
///
/// </summary>
public static readonly string PhoneNumberNonexists = nameof(PhoneNumberNonexists);
/// <summary>
///
/// </summary>
public static readonly string Default = nameof(Default);
/// <summary>
///
/// </summary>
public static readonly string DbMigrationTest = nameof(DbMigrationTest);
}

View File

@@ -5,67 +5,123 @@ using OtpNet;
using QRCoder;
using System.Text;
namespace EnvelopeGenerator.Application.Services
namespace EnvelopeGenerator.Application.Services;
/// <summary>
///
/// </summary>
public class Authenticator : IAuthenticator
{
public class Authenticator : IAuthenticator
/// <summary>
///
/// </summary>
public static Lazy<Authenticator> LazyStatic => new(() => new Authenticator(Options.Create<AuthenticatorParams>(new()), new QRCodeGenerator()));
/// <summary>
///
/// </summary>
public static Authenticator Static => LazyStatic.Value;
private readonly AuthenticatorParams _params;
private readonly QRCodeGenerator _qrCodeGenerator;
/// <summary>
///
/// </summary>
/// <param name="options"></param>
/// <param name="qrCodeGenerator"></param>
public Authenticator(IOptions<AuthenticatorParams> options, QRCodeGenerator qrCodeGenerator)
{
public static Lazy<Authenticator> LazyStatic => new(() => new Authenticator(Options.Create<AuthenticatorParams>(new()), new QRCodeGenerator()));
public static Authenticator Static => LazyStatic.Value;
private readonly AuthenticatorParams _params;
private readonly QRCodeGenerator _qrCodeGenerator;
public Authenticator(IOptions<AuthenticatorParams> options, QRCodeGenerator qrCodeGenerator)
{
_params = options.Value;
_qrCodeGenerator = qrCodeGenerator;
}
public string GenerateCode(int length)
{
//TODO: Inject Random as a singleton to support multithreading to improve performance.
Random random = new();
if (length <= 0)
throw new ArgumentException("Password length must be greater than 0.");
var passwordBuilder = new StringBuilder(length);
for (int i = 0; i < length; i++)
passwordBuilder.Append(_params.CharPool[random.Next(_params.CharPool.Length)]);
return passwordBuilder.ToString();
}
public string GenerateTotpSecretKey(int? length = null)
=> Base32Encoding.ToString(KeyGeneration.GenerateRandomKey(length ?? _params.DefaultTotpSecretKeyLength));
public byte[] GenerateTotpQrCode(string userEmail, string secretKey, string? issuer = null, string? totpUrlFormat = null, int? pixelsPerModule = null)
{
var url = string.Format(totpUrlFormat ?? _params.TotpUrlFormat,
Uri.EscapeDataString(userEmail),
Uri.EscapeDataString(secretKey),
Uri.EscapeDataString(issuer ?? _params.TotpIssuer));
using var qrCodeData = _qrCodeGenerator.CreateQrCode(url, QRCodeGenerator.ECCLevel.Q);
using var qrCode = new BitmapByteQRCode(qrCodeData);
return qrCode.GetGraphic(pixelsPerModule ?? _params.TotpQRPixelsPerModule);
}
public byte[] GenerateTotpQrCode(string userEmail, int? length = null, string? issuer = null, string? totpUrlFormat = null, int? pixelsPerModule = null)
{
return GenerateTotpQrCode(
userEmail: userEmail,
secretKey: GenerateTotpSecretKey(length: length),
issuer: issuer,
totpUrlFormat: totpUrlFormat,
pixelsPerModule: pixelsPerModule);
}
public string GenerateTotp(string secretKey, int step = 30) => new Totp(Base32Encoding.ToBytes(secretKey), step).ComputeTotp();
public bool VerifyTotp(string totpCode, string secretKey, int step = 30, VerificationWindow? window = null)
=> new Totp(Base32Encoding.ToBytes(secretKey), step).VerifyTotp(totpCode, out _, window);
_params = options.Value;
_qrCodeGenerator = qrCodeGenerator;
}
/// <summary>
///
/// </summary>
/// <param name="length"></param>
/// <returns></returns>
/// <exception cref="ArgumentException"></exception>
public string GenerateCode(int length)
{
//TODO: Inject Random as a singleton to support multithreading to improve performance.
Random random = new();
if (length <= 0)
throw new ArgumentException("Password length must be greater than 0.");
var passwordBuilder = new StringBuilder(length);
for (int i = 0; i < length; i++)
passwordBuilder.Append(_params.CharPool[random.Next(_params.CharPool.Length)]);
return passwordBuilder.ToString();
}
/// <summary>
///
/// </summary>
/// <param name="length"></param>
/// <returns></returns>
public string GenerateTotpSecretKey(int? length = null)
=> Base32Encoding.ToString(KeyGeneration.GenerateRandomKey(length ?? _params.DefaultTotpSecretKeyLength));
/// <summary>
///
/// </summary>
/// <param name="userEmail"></param>
/// <param name="secretKey"></param>
/// <param name="issuer"></param>
/// <param name="totpUrlFormat"></param>
/// <param name="pixelsPerModule"></param>
/// <returns></returns>
public byte[] GenerateTotpQrCode(string userEmail, string secretKey, string? issuer = null, string? totpUrlFormat = null, int? pixelsPerModule = null)
{
var url = string.Format(totpUrlFormat ?? _params.TotpUrlFormat,
Uri.EscapeDataString(userEmail),
Uri.EscapeDataString(secretKey),
Uri.EscapeDataString(issuer ?? _params.TotpIssuer));
using var qrCodeData = _qrCodeGenerator.CreateQrCode(url, QRCodeGenerator.ECCLevel.Q);
using var qrCode = new BitmapByteQRCode(qrCodeData);
return qrCode.GetGraphic(pixelsPerModule ?? _params.TotpQRPixelsPerModule);
}
/// <summary>
///
/// </summary>
/// <param name="userEmail"></param>
/// <param name="length"></param>
/// <param name="issuer"></param>
/// <param name="totpUrlFormat"></param>
/// <param name="pixelsPerModule"></param>
/// <returns></returns>
public byte[] GenerateTotpQrCode(string userEmail, int? length = null, string? issuer = null, string? totpUrlFormat = null, int? pixelsPerModule = null)
{
return GenerateTotpQrCode(
userEmail: userEmail,
secretKey: GenerateTotpSecretKey(length: length),
issuer: issuer,
totpUrlFormat: totpUrlFormat,
pixelsPerModule: pixelsPerModule);
}
/// <summary>
///
/// </summary>
/// <param name="secretKey"></param>
/// <param name="step"></param>
/// <returns></returns>
public string GenerateTotp(string secretKey, int step = 30) => new Totp(Base32Encoding.ToBytes(secretKey), step).ComputeTotp();
/// <summary>
///
/// </summary>
/// <param name="totpCode"></param>
/// <param name="secretKey"></param>
/// <param name="step"></param>
/// <param name="window"></param>
/// <returns></returns>
public bool VerifyTotp(string totpCode, string secretKey, int step = 30, VerificationWindow? window = null)
=> new Totp(Base32Encoding.ToBytes(secretKey), step).VerifyTotp(totpCode, out _, window);
}

View File

@@ -1,26 +1,44 @@
using AutoMapper;
using DigitalData.Core.Application;
using DigitalData.Core.DTO;
using DigitalData.Core.Abstraction.Application.DTO;
using EnvelopeGenerator.Application.Contracts.Services;
using EnvelopeGenerator.Application.DTOs;
using EnvelopeGenerator.Domain.Entities;
using EnvelopeGenerator.Application.Contracts.Repositories;
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.Logging;
namespace EnvelopeGenerator.Application.Services;
/// <summary>
///
/// </summary>
[Obsolete("Use MediatR")]
public class ConfigService : ReadService<IConfigRepository, ConfigDto, Config, int>, IConfigService
{
private static readonly Guid DefaultConfigCacheId = Guid.NewGuid();
private static readonly Guid DefaultConfigCacheId = Guid.NewGuid();
private readonly IMemoryCache _cache;
private readonly IMemoryCache _cache;
private readonly ILogger<ConfigService> _logger;
public ConfigService(IConfigRepository repository, IMapper mapper, IMemoryCache memoryCache, ILogger<ConfigService> logger) : base(repository, mapper)
/// <summary>
///
/// </summary>
/// <param name="repository"></param>
/// <param name="mapper"></param>
/// <param name="memoryCache"></param>
/// <param name="logger"></param>
public ConfigService(IConfigRepository repository, IMapper mapper, IMemoryCache memoryCache, ILogger<ConfigService> logger) : base(repository, mapper)
{
_cache = memoryCache;
_cache = memoryCache;
_logger = logger;
}
/// <summary>
///
/// </summary>
/// <returns></returns>
public async Task<DataResult<ConfigDto>> ReadFirstAsync()
{
var config = await _repository.ReadFirstAsync();
@@ -29,31 +47,36 @@ public class ConfigService : ReadService<IConfigRepository, ConfigDto, Config, i
: Result.Success(_mapper.Map<ConfigDto>(config));
}
/// <summary>
/// Reads the default configuration asynchronously.
/// </summary>
/// <remarks>
/// The configuration is cached in memory upon the first retrieval. If the configuration is updated,
/// the application needs to be restarted for the changes to take effect as the memory cache will not be updated automatically.
/// </remarks>
/// <returns>
/// A task that represents the asynchronous read operation. The task result contains the default configuration as a <see cref="ConfigDto"/>.
/// </returns>
/// <exception cref="InvalidOperationException">
/// Thrown when the default configuration cannot be found.
/// </exception>
public async Task<ConfigDto> ReadDefaultAsync()
/// <summary>
/// Reads the default configuration asynchronously.
/// </summary>
/// <remarks>
/// The configuration is cached in memory upon the first retrieval. If the configuration is updated,
/// the application needs to be restarted for the changes to take effect as the memory cache will not be updated automatically.
/// </remarks>
/// <returns>
/// A task that represents the asynchronous read operation. The task result contains the default configuration as a <see cref="ConfigDto"/>.
/// </returns>
/// <exception cref="InvalidOperationException">
/// Thrown when the default configuration cannot be found.
/// </exception>
public async Task<ConfigDto> ReadDefaultAsync()
{
var config = await _cache.GetOrCreateAsync(DefaultConfigCacheId, _ => ReadFirstAsync().ThenAsync(
Success: config => config,
Fail: (mssg, ntc) =>
{
_logger.LogNotice(ntc);
throw new InvalidOperationException("Default configuration cannot find.");
}));
Success: config => config,
Fail: (mssg, ntc) =>
{
_logger.LogNotice(ntc);
throw new InvalidOperationException("Default configuration cannot find.");
})
);
return config!;
}
/// <summary>
///
/// </summary>
/// <returns></returns>
public async Task<string> ReadDefaultSignatureHost() => (await ReadDefaultAsync()).SignatureHost;
}

View File

@@ -7,8 +7,18 @@ using EnvelopeGenerator.Application.Contracts.Repositories;
namespace EnvelopeGenerator.Application.Services;
/// <summary>
///
/// </summary>
[Obsolete("Use MediatR")]
public class DocumentReceiverElementService : BasicCRUDService<IDocumentReceiverElementRepository, DocumentReceiverElementDto, DocumentReceiverElement, int>, IDocumentReceiverElementService
{
/// <summary>
///
/// </summary>
/// <param name="repository"></param>
/// <param name="mapper"></param>
[Obsolete("Use MediatR")]
public DocumentReceiverElementService(IDocumentReceiverElementRepository repository, IMapper mapper)
: base(repository, mapper)
{

View File

@@ -7,10 +7,19 @@ using EnvelopeGenerator.Application.Contracts.Repositories;
namespace EnvelopeGenerator.Application.Services;
/// <summary>
///
/// </summary>
[Obsolete("Use MediatR")]
public class DocumentStatusService : BasicCRUDService<IDocumentStatusRepository, DocumentStatusDto, DocumentStatus, int>, IDocumentStatusService
{
public DocumentStatusService(IDocumentStatusRepository repository, IMapper mapper)
: base(repository, mapper)
/// <summary>
///
/// </summary>
/// <param name="repository"></param>
/// <param name="mapper"></param>
[Obsolete("Use MediatR")]
public DocumentStatusService(IDocumentStatusRepository repository, IMapper mapper) : base(repository, mapper)
{
}
}

View File

@@ -3,20 +3,34 @@ using DigitalData.Core.Application;
using EnvelopeGenerator.Application.DTOs;
using EnvelopeGenerator.Domain.Entities;
using EnvelopeGenerator.Application.Contracts.Repositories;
using static EnvelopeGenerator.Common.Constants;
using DigitalData.Core.DTO;
using static EnvelopeGenerator.Domain.Constants;
using DigitalData.Core.Abstraction.Application.DTO;
using Microsoft.Extensions.Logging;
using EnvelopeGenerator.Application.Contracts.Services;
namespace EnvelopeGenerator.Application.Services;
/// <summary>
///
/// </summary>
[Obsolete("Use MediatR")]
public class EmailTemplateService : BasicCRUDService<IEmailTemplateRepository, EmailTemplateDto, EmailTemplate, int>, IEmailTemplateService
{
/// <summary>
///
/// </summary>
/// <param name="repository"></param>
/// <param name="mapper"></param>
public EmailTemplateService(IEmailTemplateRepository repository, IMapper mapper)
: base(repository, mapper)
{
}
/// <summary>
///
/// </summary>
/// <param name="type"></param>
/// <returns></returns>
public async Task<DataResult<EmailTemplateDto>> ReadByNameAsync(EmailTemplateType type)
{
var temp = await _repository.ReadByNameAsync(type);

View File

@@ -1,6 +1,5 @@
using AutoMapper;
using DigitalData.Core.Application;
using Microsoft.Extensions.Localization;
using EnvelopeGenerator.Application.DTOs;
using EnvelopeGenerator.Domain.Entities;
using EnvelopeGenerator.Application.Contracts.Repositories;
@@ -8,8 +7,17 @@ using EnvelopeGenerator.Application.Contracts.Services;
namespace EnvelopeGenerator.Application.Services;
/// <summary>
///
/// </summary>
[Obsolete("Use MediatR")]
public class EnvelopeCertificateService : BasicCRUDService<IEnvelopeCertificateRepository, EnvelopeCertificateDto, EnvelopeCertificate, int>, IEnvelopeCertificateService
{
/// <summary>
///
/// </summary>
/// <param name="repository"></param>
/// <param name="mapper"></param>
public EnvelopeCertificateService(IEnvelopeCertificateRepository repository, IMapper mapper)
: base(repository, mapper)
{

View File

@@ -7,8 +7,18 @@ using EnvelopeGenerator.Application.Contracts.Repositories;
namespace EnvelopeGenerator.Application.Services;
/// <summary>
///
/// </summary>
[Obsolete("Use MediatR")]
public class EnvelopeDocumentService : BasicCRUDService<IEnvelopeDocumentRepository, EnvelopeDocumentDto, EnvelopeDocument, int>, IEnvelopeDocumentService
{
/// <summary>
///
/// </summary>
/// <param name="repository"></param>
/// <param name="mapper"></param>
[Obsolete("Use MediatR")]
public EnvelopeDocumentService(IEnvelopeDocumentRepository repository, IMapper mapper) : base(repository, mapper)
{
}

View File

@@ -2,37 +2,72 @@
using DigitalData.Core.Application;
using EnvelopeGenerator.Domain.Entities;
using EnvelopeGenerator.Application.Contracts.Repositories;
using static EnvelopeGenerator.Common.Constants;
using DigitalData.Core.DTO;
using static EnvelopeGenerator.Domain.Constants;
using EnvelopeGenerator.Application.DTOs.EnvelopeHistory;
using EnvelopeGenerator.Application.DTOs.Receiver;
using EnvelopeGenerator.Application.Contracts.Services;
using DigitalData.Core.Abstraction.Application.DTO;
namespace EnvelopeGenerator.Application.Services;
/// <summary>
///
/// </summary>
[Obsolete("Use MediatR")]
public class EnvelopeHistoryService : CRUDService<IEnvelopeHistoryRepository, EnvelopeHistoryCreateDto, EnvelopeHistoryDto, EnvelopeHistory, long>, IEnvelopeHistoryService
{
/// <summary>
///
/// </summary>
/// <param name="repository"></param>
/// <param name="mapper"></param>
public EnvelopeHistoryService(IEnvelopeHistoryRepository repository, IMapper mapper)
: base(repository, mapper)
{
}
public async Task<int> CountAsync(int? envelopeId = null, string? userReference = null, int? status = null) => await _repository.CountAsync(envelopeId: envelopeId, userReference: userReference, status: status);
/// <summary>
/// /
/// </summary>
/// <param name="envelopeId"></param>
/// <param name="userReference"></param>
/// <param name="status"></param>
/// <returns></returns>
public async Task<int> CountAsync(int? envelopeId = null, string? userReference = null, EnvelopeStatus? status = null) => await _repository.CountAsync(envelopeId: envelopeId, userReference: userReference, status: status);
/// <summary>
///
/// </summary>
/// <param name="status"></param>
/// <param name="envelopeId"></param>
/// <param name="userReference"></param>
/// <returns></returns>
public async Task<bool> HasStatus(EnvelopeStatus status, int envelopeId, string userReference) => await _repository.CountAsync(
envelopeId: envelopeId,
userReference: userReference,
status: (int) status) > 0;
status: status) > 0;
/// <summary>
///
/// </summary>
/// <param name="envelopeId"></param>
/// <param name="userReference"></param>
/// <returns></returns>
public async Task<bool> AccessCodeAlreadyRequested(int envelopeId, string userReference) => await _repository.CountAsync(
envelopeId: envelopeId,
userReference:userReference,
status: (int) EnvelopeStatus.AccessCodeRequested) > 0;
status: EnvelopeStatus.AccessCodeRequested) > 0;
/// <summary>
///
/// </summary>
/// <param name="envelopeId"></param>
/// <param name="userReference"></param>
/// <returns></returns>
public async Task<bool> IsSigned(int envelopeId, string userReference) => await _repository.CountAsync(
envelopeId: envelopeId,
userReference: userReference,
status: (int) EnvelopeStatus.DocumentSigned) > 0;
status: EnvelopeStatus.DocumentSigned) > 0;
/// <summary>
/// Checks if the specified envelope has been rejected.
@@ -46,10 +81,20 @@ public class EnvelopeHistoryService : CRUDService<IEnvelopeHistoryRepository, En
return await _repository.CountAsync(
envelopeId: envelopeId,
userReference: userReference,
status: (int)EnvelopeStatus.DocumentRejected) > 0;
status: EnvelopeStatus.DocumentRejected) > 0;
}
public async Task<IEnumerable<EnvelopeHistoryDto>> ReadAsync(int? envelopeId = null, string? userReference = null, ReferenceType? referenceType = null, int? status = null, bool withSender = false, bool withReceiver = false)
/// <summary>
///
/// </summary>
/// <param name="envelopeId"></param>
/// <param name="userReference"></param>
/// <param name="referenceType"></param>
/// <param name="status"></param>
/// <param name="withSender"></param>
/// <param name="withReceiver"></param>
/// <returns></returns>
public async Task<IEnumerable<EnvelopeHistoryDto>> ReadAsync(int? envelopeId = null, string? userReference = null, ReferenceType? referenceType = null, EnvelopeStatus? status = null, bool withSender = false, bool withReceiver = false)
{
var histDTOs = _mapper.Map<IEnumerable<EnvelopeHistoryDto>>(
await _repository.ReadAsync(
@@ -61,24 +106,50 @@ public class EnvelopeHistoryService : CRUDService<IEnvelopeHistoryRepository, En
return referenceType is null ? histDTOs : histDTOs.Where(h => h.ReferenceType == referenceType);
}
/// <summary>
///
/// </summary>
/// <param name="envelopeId"></param>
/// <param name="userReference"></param>
/// <returns></returns>
public async Task<IEnumerable<EnvelopeHistoryDto>> ReadRejectedAsync(int envelopeId, string? userReference = null) =>
await ReadAsync(envelopeId: envelopeId, userReference: userReference, status: (int)EnvelopeStatus.DocumentRejected, withReceiver:true);
await ReadAsync(envelopeId: envelopeId, userReference: userReference, status: EnvelopeStatus.DocumentRejected, withReceiver:true);
//TODO: use IQueryable in repository to incerease the performance
public async Task<IEnumerable<ReceiverReadDto>> ReadRejectingReceivers(int envelopeId)
{
var envelopes = await ReadRejectedAsync(envelopeId);
return envelopes is null
? Enumerable.Empty<ReceiverReadDto>()
: envelopes
.Where(eh => eh?.Receiver != null)
.Select(eh => eh.Receiver!);
}
//TODO: use IQueryable in repository to incerease the performance
/// <summary>
///
/// </summary>
/// <param name="envelopeId"></param>
/// <returns></returns>
public async Task<IEnumerable<ReceiverReadDto>> ReadRejectingReceivers(int envelopeId)
{
var envelopes = await ReadRejectedAsync(envelopeId);
return envelopes is null
? Enumerable.Empty<ReceiverReadDto>()
: envelopes
.Where(eh => eh?.Receiver != null)
.Select(eh => eh.Receiver!);
}
public async Task<DataResult<long>> RecordAsync(int envelopeId, string userReference, EnvelopeStatus status, string? comment = null) =>
await CreateAsync(new (EnvelopeId: envelopeId, UserReference: userReference, Status: (int)status, ActionDate: DateTime.Now, Comment: comment))
.ThenAsync(
Success: id => Result.Success(id),
Fail: (mssg, ntc) => Result.Fail<long>().Message(mssg).Notice(ntc)
);
/// <summary>
///
/// </summary>
/// <param name="envelopeId"></param>
/// <param name="userReference"></param>
/// <param name="status"></param>
/// <param name="comment"></param>
/// <returns></returns>
public async Task<DataResult<long>> RecordAsync(int envelopeId, string userReference, EnvelopeStatus status, string? comment = null) =>
await CreateAsync(new ()
{
EnvelopeId = envelopeId,
UserReference = userReference,
Status = (int) status,
ActionDate = DateTime.Now,
Comment = comment
})
.ThenAsync(
Success: dto => Result.Success(dto.Id),
Fail: (mssg, ntc) => Result.Fail<long>().Message(mssg).Notice(ntc)
);
}

View File

@@ -1,175 +1,213 @@
using AutoMapper;
using DigitalData.Core.DTO;
using DigitalData.EmailProfilerDispatcher.Abstraction.Contracts;
using DigitalData.EmailProfilerDispatcher.Abstraction.DTOs.EmailOut;
using DigitalData.EmailProfilerDispatcher.Abstraction.Services;
using EnvelopeGenerator.Application.DTOs.EnvelopeReceiver;
using EnvelopeGenerator.Common;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using static EnvelopeGenerator.Common.Constants;
using static EnvelopeGenerator.Domain.Constants;
using EnvelopeGenerator.Extensions;
using EnvelopeGenerator.Application.DTOs.EnvelopeReceiverReadOnly;
using EnvelopeGenerator.Application.Configurations;
using EnvelopeGenerator.Application.Extensions;
using Newtonsoft.Json;
using EnvelopeGenerator.Application.Contracts.Services;
using DigitalData.Core.Abstraction.Application.DTO;
using EnvelopeGenerator.Domain;
namespace EnvelopeGenerator.Application.Services
namespace EnvelopeGenerator.Application.Services;
/// <summary>
///
/// </summary>
[Obsolete("Use MediatR")]
public class EnvelopeMailService : EmailOutService, IEnvelopeMailService
{
public class EnvelopeMailService : EmailOutService, IEnvelopeMailService
private readonly IEmailTemplateService _tempService;
private readonly IEnvelopeReceiverService _envRcvService;
private readonly DispatcherParams _dConfig;
private readonly IConfigService _configService;
private readonly Dictionary<string, string> _placeholders;
private readonly IAuthenticator _authenticator;
/// <summary>
///
/// </summary>
/// <param name="repository"></param>
/// <param name="mapper"></param>
/// <param name="tempService"></param>
/// <param name="envelopeReceiverService"></param>
/// <param name="dispatcherConfigOptions"></param>
/// <param name="configService"></param>
/// <param name="mailConfig"></param>
/// <param name="authenticator"></param>
public EnvelopeMailService(IEmailOutRepository repository, IMapper mapper, IEmailTemplateService tempService, IEnvelopeReceiverService envelopeReceiverService, IOptions<DispatcherParams> dispatcherConfigOptions, IConfigService configService, IOptions<MailParams> mailConfig, IAuthenticator authenticator) : base(repository, mapper)
{
private readonly IEmailTemplateService _tempService;
private readonly IEnvelopeReceiverService _envRcvService;
private readonly DispatcherParams _dConfig;
private readonly IConfigService _configService;
private readonly Dictionary<string, string> _placeholders;
private readonly IAuthenticator _authenticator;
_tempService = tempService;
_envRcvService = envelopeReceiverService;
_dConfig = dispatcherConfigOptions.Value;
_configService = configService;
_placeholders = mailConfig.Value.Placeholders;
_authenticator = authenticator;
}
public EnvelopeMailService(IEmailOutRepository repository, IMapper mapper, IEmailTemplateService tempService, IEnvelopeReceiverService envelopeReceiverService, IOptions<DispatcherParams> dispatcherConfigOptions, IConfigService configService, IOptions<MailParams> mailConfig, IAuthenticator authenticator) : base(repository, mapper)
private async Task<Dictionary<string, string>> CreatePlaceholders(string? accessCode = null, EnvelopeReceiverDto? envelopeReceiverDto = null)
{
if (accessCode is not null)
_placeholders["[DOCUMENT_ACCESS_CODE]"] = accessCode;
if(envelopeReceiverDto?.Envelope is not null && envelopeReceiverDto.Receiver is not null)
{
var erId = (envelopeReceiverDto.Envelope.Uuid, envelopeReceiverDto.Receiver.Signature).EncodeEnvelopeReceiverId();
var sigHost = await _configService.ReadDefaultSignatureHost();
var linkToDoc = $"{sigHost}/EnvelopeKey/{erId}";
_placeholders["[LINK_TO_DOCUMENT]"] = linkToDoc;
_placeholders["[LINK_TO_DOCUMENT_TEXT]"] = linkToDoc[..Math.Min(40, linkToDoc.Length)] + "..";
}
return _placeholders;
}
private async Task<Dictionary<string, string>> CreatePlaceholders(EnvelopeReceiverReadOnlyDto? readOnlyDto = null)
{
if (readOnlyDto?.Envelope is not null && readOnlyDto.Receiver is not null)
{
_tempService = tempService;
_envRcvService = envelopeReceiverService;
_dConfig = dispatcherConfigOptions.Value;
_configService = configService;
_placeholders = mailConfig.Value.Placeholders;
_authenticator = authenticator;
_placeholders["[NAME_RECEIVER]"] = await _envRcvService.ReadLastUsedReceiverNameByMailAsync(readOnlyDto.AddedWho).ThenAsync(res => res, (msg, ntc) => string.Empty) ?? string.Empty;
var erReadOnlyId = (readOnlyDto.Id).EncodeEnvelopeReceiverId();
var sigHost = await _configService.ReadDefaultSignatureHost();
var linkToDoc = $"{sigHost}/EnvelopeKey/{erReadOnlyId}";
_placeholders["[LINK_TO_DOCUMENT]"] = linkToDoc;
_placeholders["[LINK_TO_DOCUMENT_TEXT]"] = linkToDoc[..Math.Min(40, linkToDoc.Length)] + "..";
}
private async Task<Dictionary<string, string>> CreatePlaceholders(string? accessCode = null, EnvelopeReceiverDto? envelopeReceiverDto = null)
{
if (accessCode is not null)
_placeholders["[DOCUMENT_ACCESS_CODE]"] = accessCode;
return _placeholders;
}
/// <summary>
///
/// </summary>
/// <param name="dto"></param>
/// <param name="tempType"></param>
/// <param name="optionalPlaceholders"></param>
/// <returns></returns>
public async Task<DataResult<int>> SendAsync(EnvelopeReceiverDto dto, EmailTemplateType tempType, Dictionary<string, object>? optionalPlaceholders = null)
{
var tempSerResult = await _tempService.ReadByNameAsync(tempType);
if (tempSerResult.IsFailed)
return tempSerResult.ToFail<int>().Notice(LogLevel.Error, DigitalData.Core.Abstraction.Application.DTO.Flag.DataIntegrityIssue, $"The email cannot send because '{tempType}' template cannot found.");
var temp = tempSerResult.Data;
if(envelopeReceiverDto?.Envelope is not null && envelopeReceiverDto.Receiver is not null)
{
var erId = (envelopeReceiverDto.Envelope.Uuid, envelopeReceiverDto.Receiver.Signature).EncodeEnvelopeReceiverId();
var sigHost = await _configService.ReadDefaultSignatureHost();
var linkToDoc = $"{sigHost}/EnvelopeKey/{erId}";
_placeholders["[LINK_TO_DOCUMENT]"] = linkToDoc;
_placeholders["[LINK_TO_DOCUMENT_TEXT]"] = linkToDoc[..Math.Min(40, linkToDoc.Length)] + "..";
}
var mail = new EmailOutCreateDto()
{
EmailAddress = dto.Receiver!.EmailAddress,
EmailSubj = temp.Subject,
EmailBody = temp.Body,
//email_type = envelope_status,
//message = envelope_message,
ReferenceId = dto.EnvelopeId, //REFERENCE_ID = ENVELOPE_ID
ReferenceString = dto!.Envelope!.Uuid, //REFERENCE_STRING = ENVELOPE_UUID
//receiver_name = receiver.name,
//receiver_access_code = receiver.access_code,
//sender_adress = envelope.user.email,
//sender_name = envelope.user.full_name,
//envelope_title = envelope.title,
ReminderTypeId = _dConfig.ReminderTypeId,
SendingProfile = _dConfig.SendingProfile,
EntityId = null,
WfId = (int) EnvelopeStatus.MessageAccessCodeSent,
WfReference = null,
AddedWho = _dConfig.AddedWho,
EmailAttmt1 = _dConfig.EmailAttmt1
};
return _placeholders;
}
private async Task<Dictionary<string, string>> CreatePlaceholders(EnvelopeReceiverReadOnlyDto? readOnlyDto = null)
{
if (readOnlyDto?.Envelope is not null && readOnlyDto.Receiver is not null)
{
_placeholders["[NAME_RECEIVER]"] = await _envRcvService.ReadLastUsedReceiverNameByMailAsync(readOnlyDto.AddedWho).ThenAsync(res => res, (msg, ntc) => string.Empty) ?? string.Empty;
var erReadOnlyId = (readOnlyDto.Id).EncodeEnvelopeReceiverId();
var sigHost = await _configService.ReadDefaultSignatureHost();
var linkToDoc = $"{sigHost}/EnvelopeKey/{erReadOnlyId}";
_placeholders["[LINK_TO_DOCUMENT]"] = linkToDoc;
_placeholders["[LINK_TO_DOCUMENT_TEXT]"] = linkToDoc[..Math.Min(40, linkToDoc.Length)] + "..";
}
return _placeholders;
}
//get acccess code
var acResult = await _envRcvService.ReadAccessCodeByIdAsync(envelopeId: dto.EnvelopeId, receiverId: dto.ReceiverId);
if (acResult.IsFailed)
return acResult.ToFail<int>().Notice(LogLevel.Error, "Therefore, access code cannot be sent");
var accessCode = acResult.Data;
public async Task<DataResult<int>> SendAsync(EnvelopeReceiverDto dto, EmailTemplateType tempType, Dictionary<string, object>? optionalPlaceholders = null)
var placeholders = await CreatePlaceholders(accessCode: accessCode, envelopeReceiverDto: dto);
// Add optional place holders.
if (optionalPlaceholders is not null)
foreach (var oph in optionalPlaceholders)
placeholders[oph.Key] = oph.Value.ToString() ?? "NULL";
//TODO: remove the requirement to add the models using reflections
return await CreateWithTemplateAsync(createDto: mail,placeholders: placeholders,
dto, dto.Envelope.User!, dto.Envelope);
}
/// <summary>
///
/// </summary>
/// <param name="dto"></param>
/// <param name="optionalPlaceholders"></param>
/// <returns></returns>
public async Task<DataResult<int>> SendAsync(EnvelopeReceiverReadOnlyDto dto, Dictionary<string, object>? optionalPlaceholders = null)
{
var tempSerResult = await _tempService.ReadByNameAsync(EmailTemplateType.DocumentShared);
if (tempSerResult.IsFailed)
return tempSerResult.ToFail<int>().Notice(LogLevel.Error, Flag.DataIntegrityIssue, $"The email cannot send because '{Constants.EmailTemplateType.DocumentShared}' template cannot found.");
var temp = tempSerResult.Data;
var mail = new EmailOutCreateDto()
{
var tempSerResult = await _tempService.ReadByNameAsync(tempType);
if (tempSerResult.IsFailed)
return tempSerResult.ToFail<int>().Notice(LogLevel.Error, Flag.DataIntegrityIssue, $"The email cannot send because '{tempType}' template cannot found.");
var temp = tempSerResult.Data;
EmailAddress = dto.ReceiverMail,
EmailSubj = temp.Subject,
EmailBody = temp.Body,
//TODO: remove int casting when all
ReferenceId = (int) dto.EnvelopeId, //REFERENCE_ID = ENVELOPE_ID
ReferenceString = dto.Envelope!.Uuid, //REFERENCE_STRING = ENVELOPE_UUID
//receiver_name = receiver.name,
//receiver_access_code = receiver.access_code,
//sender_adress = envelope.user.email,
//sender_name = envelope.user.full_name,
//envelope_title = envelope.title,
ReminderTypeId = _dConfig.ReminderTypeId,
SendingProfile = _dConfig.SendingProfile,
EntityId = null,
WfId = (int)EnvelopeStatus.EnvelopeShared,
WfReference = null,
AddedWho = _dConfig.AddedWho,
EmailAttmt1 = _dConfig.EmailAttmt1
};
var mail = new EmailOutCreateDto()
{
EmailAddress = dto.Receiver!.EmailAddress,
EmailSubj = temp.Subject,
EmailBody = temp.Body,
//email_type = envelope_status,
//message = envelope_message,
ReferenceId = dto.EnvelopeId, //REFERENCE_ID = ENVELOPE_ID
ReferenceString = dto!.Envelope!.Uuid, //REFERENCE_STRING = ENVELOPE_UUID
//receiver_name = receiver.name,
//receiver_access_code = receiver.access_code,
//sender_adress = envelope.user.email,
//sender_name = envelope.user.full_name,
//envelope_title = envelope.title,
ReminderTypeId = _dConfig.ReminderTypeId,
SendingProfile = _dConfig.SendingProfile,
EntityId = null,
WfId = (int) EnvelopeStatus.MessageAccessCodeSent,
WfReference = null,
AddedWho = _dConfig.AddedWho,
EmailAttmt1 = _dConfig.EmailAttmt1
};
var placeholders = await CreatePlaceholders(readOnlyDto: dto);
//get acccess code
var acResult = await _envRcvService.ReadAccessCodeByIdAsync(envelopeId: dto.EnvelopeId, receiverId: dto.ReceiverId);
if (acResult.IsFailed)
return acResult.ToFail<int>().Notice(LogLevel.Error, "Therefore, access code cannot be sent");
var accessCode = acResult.Data;
var placeholders = await CreatePlaceholders(accessCode: accessCode, envelopeReceiverDto: dto);
// Add optional place holders.
if (optionalPlaceholders is not null)
foreach (var oph in optionalPlaceholders)
placeholders[oph.Key] = oph.Value.ToString() ?? "NULL";
// Add optional place holders.
if (optionalPlaceholders is not null)
foreach (var oph in optionalPlaceholders)
placeholders[oph.Key] = oph.Value.ToString() ?? "NULL";
return await CreateWithTemplateAsync(createDto: mail, placeholders: placeholders, dto.Envelope);
}
//TODO: remove the requirement to add the models using reflections
return await CreateWithTemplateAsync(createDto: mail,placeholders: placeholders,
dto, dto.Envelope.User!, dto.Envelope);
}
/// <summary>
///
/// </summary>
/// <param name="dto"></param>
/// <returns></returns>
public async Task<DataResult<int>> SendAccessCodeAsync(EnvelopeReceiverDto dto) => await SendAsync(dto: dto, tempType: EmailTemplateType.DocumentAccessCodeReceived);
public async Task<DataResult<int>> SendAsync(EnvelopeReceiverReadOnlyDto dto, Dictionary<string, object>? optionalPlaceholders = null)
{
var tempSerResult = await _tempService.ReadByNameAsync(EmailTemplateType.DocumentShared);
if (tempSerResult.IsFailed)
return tempSerResult.ToFail<int>().Notice(LogLevel.Error, Flag.DataIntegrityIssue, $"The email cannot send because '{Constants.EmailTemplateType.DocumentShared}' template cannot found.");
var temp = tempSerResult.Data;
/// <summary>
///
/// </summary>
/// <param name="dto"></param>
/// <returns></returns>
/// <exception cref="ArgumentNullException"></exception>
public Task<DataResult<int>> SendTFAQrCodeAsync(EnvelopeReceiverDto dto)
{
// Check if receiver or secret key is null
if (dto.Receiver is null)
throw new ArgumentNullException(nameof(dto), $"TFA Qr Code cannot sent. Receiver information is missing. Envelope receiver dto is {JsonConvert.SerializeObject(dto)}");
if (dto.Receiver.TotpSecretkey is null)
throw new ArgumentNullException(nameof(dto), $"TFA Qr Code cannot sent. Receiver.TotpSecretKey is null. Envelope receiver dto is {JsonConvert.SerializeObject(dto)}");
var mail = new EmailOutCreateDto()
{
EmailAddress = dto.ReceiverMail,
EmailSubj = temp.Subject,
EmailBody = temp.Body,
//TODO: remove int casting when all
ReferenceId = (int) dto.EnvelopeId, //REFERENCE_ID = ENVELOPE_ID
ReferenceString = dto.Envelope!.Uuid, //REFERENCE_STRING = ENVELOPE_UUID
//receiver_name = receiver.name,
//receiver_access_code = receiver.access_code,
//sender_adress = envelope.user.email,
//sender_name = envelope.user.full_name,
//envelope_title = envelope.title,
ReminderTypeId = _dConfig.ReminderTypeId,
SendingProfile = _dConfig.SendingProfile,
EntityId = null,
WfId = (int)EnvelopeStatus.EnvelopeShared,
WfReference = null,
AddedWho = _dConfig.AddedWho,
EmailAttmt1 = _dConfig.EmailAttmt1
};
var placeholders = await CreatePlaceholders(readOnlyDto: dto);
// Add optional place holders.
if (optionalPlaceholders is not null)
foreach (var oph in optionalPlaceholders)
placeholders[oph.Key] = oph.Value.ToString() ?? "NULL";
return await CreateWithTemplateAsync(createDto: mail, placeholders: placeholders, dto.Envelope);
}
public async Task<DataResult<int>> SendAccessCodeAsync(EnvelopeReceiverDto dto) => await SendAsync(dto: dto, tempType: EmailTemplateType.DocumentAccessCodeReceived);
public Task<DataResult<int>> SendTFAQrCodeAsync(EnvelopeReceiverDto dto)
{
// Check if receiver or secret key is null
if (dto.Receiver is null)
throw new ArgumentNullException(nameof(dto), $"TFA Qr Code cannot sent. Receiver information is missing. Envelope receiver dto is {JsonConvert.SerializeObject(dto)}");
if (dto.Receiver.TotpSecretkey is null)
throw new ArgumentNullException(nameof(dto), $"TFA Qr Code cannot sent. Receiver.TotpSecretKey is null. Envelope receiver dto is {JsonConvert.SerializeObject(dto)}");
var totp_qr_64 = _authenticator.GenerateTotpQrCode(userEmail: dto.Receiver.EmailAddress, secretKey: dto.Receiver.TotpSecretkey).ToBase64String();
return SendAsync(dto, EmailTemplateType.TotpSecret, new()
{
{"[TFA_QR_CODE]", totp_qr_64 },
});
}
var totp_qr_64 = _authenticator.GenerateTotpQrCode(userEmail: dto.Receiver.EmailAddress, secretKey: dto.Receiver.TotpSecretkey).ToBase64String();
return SendAsync(dto, EmailTemplateType.TotpSecret, new()
{
{"[TFA_QR_CODE]", totp_qr_64 },
});
}
}

View File

@@ -7,8 +7,17 @@ using EnvelopeGenerator.Application.Contracts.Repositories;
namespace EnvelopeGenerator.Application.Services;
/// <summary>
///
/// </summary>
[Obsolete("Use MediatR")]
public class EnvelopeReceiverReadOnlyService : CRUDService<IEnvelopeReceiverReadOnlyRepository, EnvelopeReceiverReadOnlyCreateDto, EnvelopeReceiverReadOnlyDto, EnvelopeReceiverReadOnly, long>, IEnvelopeReceiverReadOnlyService
{
/// <summary>
///
/// </summary>
/// <param name="repository"></param>
/// <param name="mapper"></param>
public EnvelopeReceiverReadOnlyService(IEnvelopeReceiverReadOnlyRepository repository, IMapper mapper) : base(repository, mapper)
{
}

View File

@@ -1,6 +1,6 @@
using AutoMapper;
using DigitalData.Core.Application;
using DigitalData.Core.DTO;
using DigitalData.Core.Abstraction.Application.DTO;
using EnvelopeGenerator.Application.DTOs.EnvelopeReceiver;
using EnvelopeGenerator.Application.Resources;
using EnvelopeGenerator.Domain.Entities;
@@ -15,12 +15,23 @@ using EnvelopeGenerator.Application.Receivers.Queries.Read;
namespace EnvelopeGenerator.Application.Services;
/// <summary>
///
/// </summary>
[Obsolete("Use MediatR")]
public class EnvelopeReceiverService : BasicCRUDService<IEnvelopeReceiverRepository, EnvelopeReceiverDto, EnvelopeReceiver, (int Envelope, int Receiver)>, IEnvelopeReceiverService
{
private readonly IStringLocalizer<Resource> _localizer;
private readonly ISmsSender _smsSender;
/// <summary>
///
/// </summary>
/// <param name="repository"></param>
/// <param name="localizer"></param>
/// <param name="mapper"></param>
/// <param name="smsSender"></param>
public EnvelopeReceiverService(IEnvelopeReceiverRepository repository, IStringLocalizer<Resource> localizer, IMapper mapper, ISmsSender smsSender)
: base(repository, mapper)
{
@@ -28,24 +39,59 @@ public class EnvelopeReceiverService : BasicCRUDService<IEnvelopeReceiverReposit
_smsSender = smsSender;
}
/// <summary>
///
/// </summary>
/// <param name="signature"></param>
/// <param name="withEnvelope"></param>
/// <param name="withReceiver"></param>
/// <param name="readOnly"></param>
/// <returns></returns>
public async Task<DataResult<IEnumerable<EnvelopeReceiverDto>>> ReadBySignatureAsync(string signature, bool withEnvelope = false, bool withReceiver = true, bool readOnly = true)
{
var env_rcvs = await _repository.ReadBySignatureAsync(signature: signature, withEnvelope: withEnvelope, withReceiver: withReceiver, readOnly: readOnly);
return Result.Success(_mapper.Map<IEnumerable<EnvelopeReceiverDto>>(env_rcvs));
}
/// <summary>
///
/// </summary>
/// <param name="uuid"></param>
/// <param name="withEnvelope"></param>
/// <param name="withReceiver"></param>
/// <param name="readOnly"></param>
/// <returns></returns>
public async Task<DataResult<IEnumerable<EnvelopeReceiverDto>>> ReadByUuidAsync(string uuid, bool withEnvelope = true, bool withReceiver = false, bool readOnly = true)
{
var env_rcvs = await _repository.ReadByUuidAsync(uuid: uuid, withEnvelope: withEnvelope, withReceiver: withReceiver, readOnly: readOnly);
return Result.Success(_mapper.Map<IEnumerable<EnvelopeReceiverDto>>(env_rcvs));
}
/// <summary>
///
/// </summary>
/// <param name="uuid"></param>
/// <param name="withEnvelope"></param>
/// <param name="withReceiver"></param>
/// <returns></returns>
public async Task<DataResult<IEnumerable<string?>>> ReadAccessCodeByUuidAsync(string uuid, bool withEnvelope = false, bool withReceiver = true)
{
var env_rcvs = await _repository.ReadByUuidAsync(uuid: uuid, withEnvelope: withEnvelope, withReceiver: withReceiver);
return Result.Success(env_rcvs.Select(er => er.AccessCode));
if( env_rcvs is null || !env_rcvs.Any())
return Result.Fail<IEnumerable<string?>>()
.Message(_localizer[Key.EnvelopeReceiverNotFound]);
return Result.Success(env_rcvs.Select(er => er.AccessCode) ?? Enumerable.Empty<string?>());
}
/// <summary>
///
/// </summary>
/// <param name="uuid"></param>
/// <param name="signature"></param>
/// <param name="withEnvelope"></param>
/// <param name="withReceiver"></param>
/// <param name="readOnly"></param>
/// <returns></returns>
public async Task<DataResult<EnvelopeReceiverDto>> ReadByUuidSignatureAsync(string uuid, string signature, bool withEnvelope = true, bool withReceiver = true, bool readOnly = true)
{
var env_rcv = await _repository.ReadByUuidSignatureAsync(uuid: uuid, signature: signature, withEnvelope: withEnvelope, withReceiver: withReceiver, readOnly: readOnly);
@@ -56,6 +102,15 @@ public class EnvelopeReceiverService : BasicCRUDService<IEnvelopeReceiverReposit
return Result.Success(_mapper.Map<EnvelopeReceiverDto>(env_rcv));
}
/// <summary>
///
/// </summary>
/// <param name="uuid"></param>
/// <param name="signature"></param>
/// <param name="withEnvelope"></param>
/// <param name="withReceiver"></param>
/// <param name="readOnly"></param>
/// <returns></returns>
public async Task<DataResult<EnvelopeReceiverSecretDto>> ReadWithSecretByUuidSignatureAsync(string uuid, string signature, bool withEnvelope = true, bool withReceiver = true, bool readOnly = true)
{
var env_rcv = await _repository.ReadByUuidSignatureAsync(uuid: uuid, signature: signature, withEnvelope: withEnvelope, withReceiver: withReceiver, readOnly: readOnly);
@@ -66,6 +121,14 @@ public class EnvelopeReceiverService : BasicCRUDService<IEnvelopeReceiverReposit
return Result.Success(_mapper.Map<EnvelopeReceiverSecretDto>(env_rcv));
}
/// <summary>
///
/// </summary>
/// <param name="envelopeReceiverId"></param>
/// <param name="withEnvelope"></param>
/// <param name="withReceiver"></param>
/// <param name="readOnly"></param>
/// <returns></returns>
public async Task<DataResult<EnvelopeReceiverDto>> ReadByEnvelopeReceiverIdAsync(string envelopeReceiverId, bool withEnvelope = true, bool withReceiver = true, bool readOnly = true)
{
(string? uuid, string? signature) = envelopeReceiverId.DecodeEnvelopeReceiverId();
@@ -80,6 +143,13 @@ public class EnvelopeReceiverService : BasicCRUDService<IEnvelopeReceiverReposit
return await ReadByUuidSignatureAsync(uuid: uuid, signature: signature, withEnvelope: withEnvelope, withReceiver: withReceiver, readOnly: readOnly);
}
/// <summary>
///
/// </summary>
/// <param name="uuid"></param>
/// <param name="signature"></param>
/// <param name="accessCode"></param>
/// <returns></returns>
public async Task<DataResult<bool>> VerifyAccessCodeAsync(string uuid, string signature, string accessCode)
{
var er = await _repository.ReadByUuidSignatureAsync(uuid: uuid, signature: signature);
@@ -106,6 +176,12 @@ public class EnvelopeReceiverService : BasicCRUDService<IEnvelopeReceiverReposit
return Result.Success(true);
}
/// <summary>
///
/// </summary>
/// <param name="envelopeReceiverId"></param>
/// <param name="accessCode"></param>
/// <returns></returns>
public async Task<DataResult<bool>> VerifyAccessCodeAsync(string envelopeReceiverId, string accessCode)
{
(string? uuid, string? signature) = envelopeReceiverId.DecodeEnvelopeReceiverId();
@@ -120,6 +196,11 @@ public class EnvelopeReceiverService : BasicCRUDService<IEnvelopeReceiverReposit
return await VerifyAccessCodeAsync(uuid: uuid, signature: signature, accessCode: accessCode);
}
/// <summary>
///
/// </summary>
/// <param name="envelopeReceiverId"></param>
/// <returns></returns>
public async Task<DataResult<bool>> IsExisting(string envelopeReceiverId)
{
(string? uuid, string? signature) = envelopeReceiverId.DecodeEnvelopeReceiverId();
@@ -131,14 +212,30 @@ public class EnvelopeReceiverService : BasicCRUDService<IEnvelopeReceiverReposit
return Result.Success(count > 0);
}
public async Task<DataResult<string>> ReadAccessCodeByIdAsync(int envelopeId, int receiverId)
{
var code = await _repository.ReadAccessCodeByIdAsync(envelopeId: envelopeId, receiverId: receiverId);
return code is null ?
Result.Fail<string>().Notice(LogLevel.Error, Flag.DataIntegrityIssue, $"Access code is null. Envelope ID is {envelopeId} and receiver ID {receiverId}")
: Result.Success(code);
}
/// <summary>
///
/// </summary>
/// <param name="envelopeId"></param>
/// <param name="receiverId"></param>
/// <returns></returns>
public async Task<DataResult<string>> ReadAccessCodeByIdAsync(int envelopeId, int receiverId)
{
var code = await _repository.ReadAccessCodeByIdAsync(envelopeId: envelopeId, receiverId: receiverId);
return code is null ?
Result.Fail<string>().Notice(LogLevel.Error, Flag.DataIntegrityIssue, $"Access code is null. Envelope ID is {envelopeId} and receiver ID {receiverId}")
: Result.Success(code);
}
/// <summary>
///
/// </summary>
/// <param name="username"></param>
/// <param name="min_status"></param>
/// <param name="max_status"></param>
/// <param name="envelopeQuery"></param>
/// <param name="receiverQuery"></param>
/// <param name="ignore_statuses"></param>
/// <returns></returns>
public async Task<DataResult<IEnumerable<EnvelopeReceiverDto>>> ReadByUsernameAsync(string username, int? min_status = null, int? max_status = null, EnvelopeQuery? envelopeQuery = null, ReadReceiverQuery? receiverQuery = null, params int[] ignore_statuses)
{
var er_list = await _repository.ReadByUsernameAsync(username: username, min_status: min_status, max_status: max_status, ignore_statuses: ignore_statuses);
@@ -162,12 +259,25 @@ public class EnvelopeReceiverService : BasicCRUDService<IEnvelopeReceiverReposit
return Result.Success(dto_list);
}
public async Task<DataResult<string?>> ReadLastUsedReceiverNameByMailAsync(string? mail = null, int? id = null, string? signature = null)
/// <summary>
///
/// </summary>
/// <param name="mail"></param>
/// <param name="id"></param>
/// <param name="signature"></param>
/// <returns></returns>
public async Task<DataResult<string>> ReadLastUsedReceiverNameByMailAsync(string? mail = null, int? id = null, string? signature = null)
{
var er = await _repository.ReadLastByReceiverAsync(mail, id, signature);
return er is null ? Result.Fail<string?>().Notice(LogLevel.None, Flag.NotFound) : Result.Success(er.Name);
return er is null ? Result.Fail<string>().Notice(LogLevel.None, Flag.NotFound) : Result.Success(er.Name);
}
/// <summary>
///
/// </summary>
/// <param name="envelopeReceiverId"></param>
/// <param name="message"></param>
/// <returns></returns>
public async Task<DataResult<SmsResponse>> SendSmsAsync(string envelopeReceiverId, string message)
{
(string? uuid, string? signature) = envelopeReceiverId.DecodeEnvelopeReceiverId();
@@ -194,6 +304,12 @@ public class EnvelopeReceiverService : BasicCRUDService<IEnvelopeReceiverReposit
return Result.Success(res);
}
/// <summary>
///
/// </summary>
/// <param name="uuid"></param>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
public Task<DataResult<IEnumerable<EnvelopeReceiverSecretDto>>> ReadWithSecretByUuidAsync(string uuid)
{
throw new NotImplementedException();

View File

@@ -1,6 +1,6 @@
using AutoMapper;
using DigitalData.Core.Application;
using DigitalData.Core.DTO;
using DigitalData.Core.Abstraction.Application.DTO;
using EnvelopeGenerator.Application.Contracts.Services;
using EnvelopeGenerator.Application.DTOs;
using EnvelopeGenerator.Domain.Entities;
@@ -8,13 +8,29 @@ using EnvelopeGenerator.Application.Contracts.Repositories;
namespace EnvelopeGenerator.Application.Services;
/// <summary>
///
/// </summary>
[Obsolete("Use MediatR")]
public class EnvelopeService : BasicCRUDService<IEnvelopeRepository, EnvelopeDto, Envelope, int>, IEnvelopeService
{
/// <summary>
///
/// </summary>
/// <param name="repository"></param>
/// <param name="mapper"></param>
public EnvelopeService(IEnvelopeRepository repository, IMapper mapper)
: base(repository, mapper)
{
}
/// <summary>
///
/// </summary>
/// <param name="documents"></param>
/// <param name="history"></param>
/// <param name="documentReceiverElement"></param>
/// <returns></returns>
public async Task<DataResult<IEnumerable<EnvelopeDto>>> ReadAllWithAsync(bool documents = false, bool history = false, bool documentReceiverElement = false)
{
var envelopes = await _repository.ReadAllWithAsync(documents: documents, history: history, documentReceiverElement: documentReceiverElement);
@@ -22,6 +38,16 @@ public class EnvelopeService : BasicCRUDService<IEnvelopeRepository, EnvelopeDto
return Result.Success(readDto);
}
/// <summary>
///
/// </summary>
/// <param name="uuid"></param>
/// <param name="withDocuments"></param>
/// <param name="withHistory"></param>
/// <param name="withDocumentReceiverElement"></param>
/// <param name="withUser"></param>
/// <param name="withAll"></param>
/// <returns></returns>
public async Task<DataResult<EnvelopeDto>> ReadByUuidAsync(string uuid, bool withDocuments = false, bool withHistory = false, bool withDocumentReceiverElement = false, bool withUser = false, bool withAll = false)
{
var envelope = await _repository.ReadByUuidAsync(uuid: uuid, withDocuments: withDocuments, withHistory: withHistory, withDocumentReceiverElement: withDocumentReceiverElement, withUser:withUser, withAll:withAll);
@@ -33,6 +59,14 @@ public class EnvelopeService : BasicCRUDService<IEnvelopeRepository, EnvelopeDto
return Result.Success(readDto);
}
/// <summary>
///
/// </summary>
/// <param name="userId"></param>
/// <param name="min_status"></param>
/// <param name="max_status"></param>
/// <param name="ignore_statuses"></param>
/// <returns></returns>
public async Task<DataResult<IEnumerable<EnvelopeDto>>> ReadByUserAsync(int userId, int? min_status = null, int? max_status = null, params int[] ignore_statuses)
{
var users = await _repository.ReadByUserAsync(userId: userId, min_status: min_status, max_status: max_status, ignore_statuses: ignore_statuses);

View File

@@ -8,6 +8,9 @@ using Microsoft.Extensions.Options;
namespace EnvelopeGenerator.Application.Services;
/// <summary>
///
/// </summary>
public class EnvelopeSmsHandler : IEnvelopeSmsHandler
{
private readonly ISmsSender _sender;
@@ -18,6 +21,13 @@ public class EnvelopeSmsHandler : IEnvelopeSmsHandler
private readonly IAuthenticator _authenticator;
/// <summary>
///
/// </summary>
/// <param name="sender"></param>
/// <param name="totpSmsParamsOptions"></param>
/// <param name="distributedCache"></param>
/// <param name="authenticator"></param>
public EnvelopeSmsHandler(ISmsSender sender, IOptions<TotpSmsParams> totpSmsParamsOptions, IDistributedCache distributedCache, IAuthenticator authenticator)
{
_sender = sender;
@@ -49,6 +59,12 @@ public class EnvelopeSmsHandler : IEnvelopeSmsHandler
}
}
/// <summary>
///
/// </summary>
/// <param name="totpCode"></param>
/// <param name="secretKey"></param>
/// <returns></returns>
public bool VerifyTotp(string totpCode, string secretKey) => _authenticator
.VerifyTotp(totpCode, secretKey, _totpSmsParams.TotpStep, _totpSmsParams.TotpVerificationWindow);
}

View File

@@ -4,24 +4,38 @@ using EnvelopeGenerator.Application.DTOs;
using EnvelopeGenerator.Domain.Entities;
using EnvelopeGenerator.Application.Contracts.Repositories;
using Microsoft.Extensions.Caching.Memory;
using DigitalData.Core.DTO;
using Microsoft.Extensions.Logging;
using EnvelopeGenerator.Application.Contracts.Services;
using DigitalData.Core.Abstraction.Application.DTO;
namespace EnvelopeGenerator.Application.Services;
/// <summary>
///
/// </summary>
[Obsolete("Use MediatR")]
public class EnvelopeTypeService : BasicCRUDService<IEnvelopeTypeRepository, EnvelopeTypeDto, EnvelopeType, int>, IEnvelopeTypeService
{
private static readonly Guid CacheKey = Guid.NewGuid();
private readonly IMemoryCache _cache;
/// <summary>
///
/// </summary>
/// <param name="repository"></param>
/// <param name="mapper"></param>
/// <param name="cache"></param>
public EnvelopeTypeService(IEnvelopeTypeRepository repository, IMapper mapper, IMemoryCache cache)
: base(repository, mapper)
{
_cache = cache;
}
/// <summary>
///
/// </summary>
/// <returns></returns>
public override async Task<DataResult<IEnumerable<EnvelopeTypeDto>>> ReadAllAsync()
=> await _cache.GetOrCreateAsync(CacheKey, async entry => await base.ReadAllAsync())
?? Result.Fail<IEnumerable<EnvelopeTypeDto>>().Notice(LogLevel.Error, Flag.NotFound, "No cached envelope types are available in the database. If you have added any envelope types after the server started, please restart the server.");

View File

@@ -1,5 +1,5 @@
using AutoMapper;
using DigitalData.Core.Abstractions.Client;
using DigitalData.Core.Client.Interface;
using DigitalData.Core.Client;
using EnvelopeGenerator.Application.Configurations;
using EnvelopeGenerator.Application.Contracts.Services;
@@ -9,6 +9,9 @@ using Microsoft.Extensions.Options;
namespace EnvelopeGenerator.Application.Services;
//TODO: move to DigitalData.Core
/// <summary>
///
/// </summary>
public class GTXSmsSender : ISmsSender
{
private readonly IHttpClientService<GtxMessagingParams> _smsClient;
@@ -17,8 +20,17 @@ public class GTXSmsSender : ISmsSender
private readonly IMapper _mapper;
/// <summary>
///
/// </summary>
public string ServiceProvider { get; }
/// <summary>
///
/// </summary>
/// <param name="smsClient"></param>
/// <param name="smsParamsOptions"></param>
/// <param name="mapper"></param>
public GTXSmsSender(IHttpClientService<GtxMessagingParams> smsClient, IOptions<GtxMessagingParams> smsParamsOptions, IMapper mapper)
{
_smsClient = smsClient;
@@ -27,6 +39,12 @@ public class GTXSmsSender : ISmsSender
ServiceProvider = GetType().Name.Replace("Service", string.Empty);
}
/// <summary>
///
/// </summary>
/// <param name="recipient"></param>
/// <param name="message"></param>
/// <returns></returns>
public async Task<SmsResponse> SendSmsAsync(string recipient, string message)
{
return await _smsClient.FetchAsync(queryParams: new Dictionary<string, object?>()

View File

@@ -3,20 +3,33 @@ using DigitalData.Core.Application;
using EnvelopeGenerator.Domain.Entities;
using EnvelopeGenerator.Application.Contracts.Repositories;
using EnvelopeGenerator.Application.DTOs.Receiver;
using DigitalData.Core.DTO;
using DigitalData.Core.Abstractions;
using Microsoft.Extensions.Logging;
using DigitalData.Core.Abstraction.Application.DTO;
using EnvelopeGenerator.Application.Contracts.Services;
namespace EnvelopeGenerator.Application.Services;
/// <summary>
///
/// </summary>
[Obsolete("Use MediatR")]
public class ReceiverService : CRUDService<IReceiverRepository, ReceiverCreateDto, ReceiverReadDto, Receiver, int>, IReceiverService
{
/// <summary>
///
/// </summary>
/// <param name="repository"></param>
/// <param name="mapper"></param>
public ReceiverService(IReceiverRepository repository, IMapper mapper)
: base(repository, mapper)
{
}
/// <summary>
///
/// </summary>
/// <param name="emailAddress"></param>
/// <param name="signature"></param>
/// <returns></returns>
public async Task<DataResult<ReceiverReadDto>> ReadByAsync(string? emailAddress = null, string? signature = null)
{
var rcv = await _repository.ReadByAsync(emailAddress: emailAddress, signature: signature);
@@ -27,6 +40,12 @@ public class ReceiverService : CRUDService<IReceiverRepository, ReceiverCreateDt
return Result.Success(_mapper.Map<ReceiverReadDto>(rcv));
}
/// <summary>
///
/// </summary>
/// <param name="emailAddress"></param>
/// <param name="signature"></param>
/// <returns></returns>
public async Task<Result> DeleteByAsync(string? emailAddress = null, string? signature = null)
{
var rcv = await _repository.ReadByAsync(emailAddress: emailAddress, signature: signature);
@@ -36,16 +55,4 @@ public class ReceiverService : CRUDService<IReceiverRepository, ReceiverCreateDt
return await _repository.DeleteAsync(rcv) ? Result.Success() : Result.Fail();
}
public virtual async Task<Result> UpdateAsync<TUpdateDto>(TUpdateDto updateDto) where TUpdateDto : IUnique<int>
{
var val = await _repository.ReadByIdAsync(updateDto.Id);
if (val == null)
{
return Result.Fail().Notice(LogLevel.Warning, Flag.NotFound, $"{updateDto.Id} is not found in update process of {GetType()} entity.");
}
var entity = _mapper.Map(updateDto, val);
return (await _repository.UpdateAsync(entity)) ? Result.Success() : Result.Fail();
}
}

View File

@@ -1,16 +0,0 @@
using AutoMapper;
using DigitalData.Core.Application;
using EnvelopeGenerator.Application.Contracts.Services;
using EnvelopeGenerator.Application.DTOs;
using EnvelopeGenerator.Domain.Entities;
using EnvelopeGenerator.Application.Contracts.Repositories;
namespace EnvelopeGenerator.Application.Services;
public class UserReceiverService : BasicCRUDService<IUserReceiverRepository, UserReceiverDto, UserReceiver, int>, IUserReceiverService
{
public UserReceiverService(IUserReceiverRepository repository, IMapper mapper)
: base(repository, mapper)
{
}
}

View File

@@ -100,8 +100,8 @@
<Reference Include="EntityFramework.SqlServer, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL">
<HintPath>..\packages\EntityFramework.6.4.4\lib\net45\EntityFramework.SqlServer.dll</HintPath>
</Reference>
<Reference Include="EnvelopeGenerator.Common">
<HintPath>..\EnvelopeGenerator.Common\bin\Debug\EnvelopeGenerator.Common.dll</HintPath>
<Reference Include="EnvelopeGenerator.CommonServices">
<HintPath>..\EnvelopeGenerator.CommonServices\bin\Debug\EnvelopeGenerator.CommonServices.dll</HintPath>
</Reference>
<Reference Include="FirebirdSql.Data.FirebirdClient, Version=7.5.0.0, Culture=neutral, PublicKeyToken=3750abcc3150b00c, processorArchitecture=MSIL">
<HintPath>..\packages\FirebirdSql.Data.FirebirdClient.7.5.0\lib\net452\FirebirdSql.Data.FirebirdClient.dll</HintPath>
@@ -350,9 +350,13 @@
</None>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\EnvelopeGenerator.Common\EnvelopeGenerator.Common.vbproj">
<ProjectReference Include="..\EnvelopeGenerator.CommonServices\EnvelopeGenerator.CommonServices.vbproj">
<Project>{6EA0C51F-C2B1-4462-8198-3DE0B32B74F8}</Project>
<Name>EnvelopeGenerator.Common</Name>
<Name>EnvelopeGenerator.CommonServices</Name>
</ProjectReference>
<ProjectReference Include="..\EnvelopeGenerator.Domain\EnvelopeGenerator.Domain.csproj">
<Project>{4F32A98D-E6F0-4A09-BD97-1CF26107E837}</Project>
<Name>EnvelopeGenerator.Domain</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>

View File

@@ -2,9 +2,9 @@
Imports DigitalData.Modules.Logging
Imports GdPicture14
Imports Newtonsoft.Json.Linq
Imports EnvelopeGenerator.Common.Jobs
Imports EnvelopeGenerator.CommonServices.Jobs
Imports System.IO
Imports EnvelopeGenerator.Common.Jobs.FinalizeDocument
Imports EnvelopeGenerator.CommonServices.Jobs.FinalizeDocument
Public Class frmFinalizePDF
Private Const CONNECTIONSTRING = "Server=sDD-VMP04-SQL17\DD_DEVELOP01;Database=DD_ECM;User Id=sa;Password=+bk8oAbbQP1AzoHtvZUbd+Mbok2f8Fl4miEx1qssJ5yEaEWoQJ9prg4L14fURpPnqi1WMNs9fE4=;"

View File

@@ -2,7 +2,7 @@
Imports DigitalData.Modules.Database
Imports DigitalData.Modules.Config
Imports DigitalData.Modules.Base
Imports EnvelopeGenerator.Common
Imports EnvelopeGenerator.CommonServices
Public Class frmReportViewer
Private LogConfig As LogConfig

View File

@@ -1,152 +0,0 @@
Public Class Constants
#Region "Status Fields"
'http://wiki.dd/xwiki13/bin/view/Anwendungen/Produkt-Handbuch/Sonstiges/SignFlow/Envelope%20Status/
Public Enum EnvelopeStatus
Invalid = 0
EnvelopeCreated = 1001
EnvelopeSaved = 1002
EnvelopeQueued = 1003
EnvelopeSent = 1004 ' Nicht verwendet
EnvelopePartlySigned = 1005
EnvelopeCompletelySigned = 1006
EnvelopeReportCreated = 1007
EnvelopeArchived = 1008
EnvelopeDeleted = 1009
EnvelopeRejected = 10007
EnvelopeWithdrawn = 10009
AccessCodeRequested = 2001
AccessCodeCorrect = 2002
AccessCodeIncorrect = 2003
DocumentOpened = 2004
DocumentSigned = 2005
DocumentForwarded = 2006
DocumentRejected = 2007
EnvelopeShared = 2008
EnvelopeViewed = 2009
MessageInvitationSent = 3001 ' Wird von Trigger verwendet
MessageAccessCodeSent = 3002
MessageConfirmationSent = 3003
MessageDeletionSent = 3004
MessageCompletionSent = 3005
DocumentMod_Rotation = 4001
End Enum
Public Class Status
Public Shared ReadOnly NonHist As IReadOnlyList(Of EnvelopeStatus) = New List(Of EnvelopeStatus) From {
EnvelopeStatus.Invalid,
EnvelopeStatus.EnvelopeSaved,
EnvelopeStatus.EnvelopeSent,
EnvelopeStatus.EnvelopePartlySigned
}
Public Shared ReadOnly RelatedToFormApp As IReadOnlyList(Of EnvelopeStatus) = New List(Of EnvelopeStatus) From {
EnvelopeStatus.EnvelopeCreated,
EnvelopeStatus.DocumentMod_Rotation
}
End Class
'TODO: standardize in xwiki
Public Enum ReferenceType
Sender = 1
Receiver
System
Unknown
End Enum
Public Enum ElementStatus
Created = 0
End Enum
Public Enum DocumentStatus
Created = 0
Signed = 1
End Enum
Public Enum ReceiverStatus
Unsigned = 0
Signed = 1
End Enum
#End Region
#Region "Type Fields"
Public Enum ElementType
Signature = 1
End Enum
Public Enum ContractType
Contract = 1
ReadAndSign = 2
End Enum
Public Enum ColorType
ReceiverColor1 = 1
ReceiverColor2 = 2
ReceiverColor3 = 3
ReceiverColor4 = 4
ReceiverColor5 = 5
ReceiverColor6 = 6
ReceiverColor7 = 7
ReceiverColor8 = 8
ReceiverColor9 = 9
ReceiverColor10 = 10
End Enum
Public Enum CertificationType
AdvancedElectronicSignature = 1
'ElectronicSignature = 1
'QualifiedSignature = 2
End Enum
Public Enum FinalEmailType
No = 0
Yes = 1
YesWithAttachment = 2
End Enum
Public Enum PageOrientation
Portrait = 0
Landscape = 1
End Enum
Public Enum EmailTemplateType
DocumentReceived = 0
DocumentSigned
DocumentDeleted
DocumentCompleted
DocumentAccessCodeReceived
DocumentShared
TotpSecret
DocumentRejected_ADM
DocumentRejected_REC
DocumentRejected_REC_2
End Enum
Public Enum EncodeType
EnvelopeReceiver
EnvelopeReceiverReadOnly
Undefined
DocumentForwarded
DocumentShared
End Enum
#End Region
#Region "Role"
Public NotInheritable Class ReceiverRole
Public Const PreAuth As String = "PreAuth"
Public Const FullyAuth As String = "FullyAuth"
End Class
#End Region
#Region "Constants"
Public Const DATABASE = "DATABASE"
Public Const LOGCONFIG = "LOGCONFIG"
Public Const GDPICTURE = "GDPICTURE"
Public Const PDF_BURNER_PARAMS = "PDFBurnerParams"
Public Const GREEN_300 = "#bbf7d0"
Public Const RED_300 = "#fecaca"
Public Const ORANGE_300 = "#fed7aa"
#End Region
End Class

View File

@@ -1,10 +0,0 @@
Public Class DocumentStatus
Public Property Id As Integer
Public Property EnvelopeId As Integer
Public Property ReceiverId As Integer
Public Property Value As String
Public Property Status As Constants.DocumentStatus = Constants.DocumentStatus.Created
Public Property StatusChangedWhen As Date
End Class

View File

@@ -1,4 +0,0 @@
Public Class ElementMetadata
Public Property Index As Integer
Public Property Page As Integer
End Class

View File

@@ -1,8 +0,0 @@
Public Class EmailTemplate
Public Property Id As Integer
Public Property Name As String
Public Property Body As String
Public Property Subject As String
End Class

Some files were not shown because too many files have changed in this diff Show More