Compare commits
117 Commits
bugfix/dev
...
f0f92c5400
| Author | SHA1 | Date | |
|---|---|---|---|
| f0f92c5400 | |||
| 7e34f01f6a | |||
| f449767bf9 | |||
| f8ec6065c2 | |||
| fabfe80666 | |||
| bdb3863c07 | |||
| e5295b8302 | |||
| 00a9cf06da | |||
| 1b387238e8 | |||
| bda4f3dbef | |||
| 2458d0c07a | |||
| a72cbab195 | |||
| bcf4e63f7c | |||
| 5aabeb4510 | |||
| 32edc6474d | |||
| 71bfe3b323 | |||
| 089d2bd1cb | |||
| 65c72bcf77 | |||
| 2d8375f26a | |||
| a7cfb099fa | |||
| 7a0d4e2fa7 | |||
| 3955ee9f39 | |||
| 9bdf24d7d5 | |||
| 993ca82596 | |||
| ce9958a8b1 | |||
| 6c54473d5a | |||
| 9ad4352e02 | |||
| 90031db6a5 | |||
| bc07af9622 | |||
| 4caf8cd192 | |||
| 5423d5317b | |||
| 6c8c8f22a3 | |||
| 5100504f16 | |||
| 15f8baf54c | |||
| 4e847fa737 | |||
| 53ff48dc3c | |||
| ab67b3fba2 | |||
| 3855a8fa1e | |||
| 052da02bd0 | |||
| 53a9a3e3eb | |||
| c2ab18e184 | |||
| 8f845e8a9a | |||
| 7af934ea19 | |||
| b65367fb6d | |||
| 25c31108cb | |||
| 4083833b19 | |||
| f53bc65acf | |||
| 070d9be00c | |||
| 6f7b04a26e | |||
| 473358e2b9 | |||
| 8f3aa69cbf | |||
| eededeb1f1 | |||
| 737774f077 | |||
| 69499273cc | |||
| ead33ab2e7 | |||
| d1e2840617 | |||
| a39ef6a0e2 | |||
| 7d620988d8 | |||
| cc4a7d8c20 | |||
| 0b8068f926 | |||
| 9fd7a68798 | |||
| d6e2690bb8 | |||
| f04385a03c | |||
| c88e7b2b9e | |||
| 0ee7ec82d6 | |||
| a6d6dc8c4d | |||
| ab038df8b9 | |||
| 302249451b | |||
| a4082fca45 | |||
| f3ae8a9c49 | |||
| d6058c41d0 | |||
| 79d093c492 | |||
| 56c65b6fbb | |||
| 2af18842c4 | |||
| 41e0d4691b | |||
| 64e0a4f749 | |||
| 4cf54d36b9 | |||
| 020cecabf3 | |||
| 40c899e47e | |||
| bae62c7c08 | |||
| 41dde6f016 | |||
| c5b167f0d4 | |||
| a70faebde6 | |||
| 3e01052579 | |||
| f49b907574 | |||
| 86ed96ae76 | |||
| 9dbfdaa15e | |||
| 9d66f1d19e | |||
| 14cef05d02 | |||
| bdfb973d55 | |||
| 15a18b1bfd | |||
| 6fac1cd96a | |||
| 79d2636c14 | |||
| 2172ce8203 | |||
| 51ab9fb094 | |||
| d8a002cd22 | |||
| e36684820e | |||
| 2a5d953623 | |||
| 0aba9e91e2 | |||
| 1a0973075b | |||
| b8fd26611c | |||
| 0ca372bf45 | |||
| 5230076d5d | |||
| b28084bf19 | |||
| cbc983e070 | |||
| 3b06f3fdac | |||
| a12d74871d | |||
| 45b715ed74 | |||
| 9d5e2e6ad2 | |||
| c5d2d79563 | |||
| 15d4573321 | |||
| eb46590c1d | |||
| c93c32307a | |||
| 41cca7fa64 | |||
| b01c17ab18 | |||
| c8834dc3be | |||
| e385fdda95 |
@@ -1,424 +0,0 @@
|
|||||||
# EnvelopeGenerator — AI Context Reference
|
|
||||||
|
|
||||||
## Purpose
|
|
||||||
Digital document signing system with **unified Blazor WASM frontend** for both Senders and Receivers. Senders create envelopes and place signature fields. Receivers view PDFs, sign documents, export stamped PDFs.
|
|
||||||
|
|
||||||
**Primary Libraries:** DevExpress + PDF.js (PSPDFKit removed)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Deployment Architecture
|
|
||||||
|
|
||||||
**Two Presentation Projects (Both Required):**
|
|
||||||
|
|
||||||
1. **EnvelopeGenerator.API** (ASP.NET Core Web API)
|
|
||||||
- Runs independently (development & production)
|
|
||||||
- **YARP Reverse Proxy** configured via `yarp.json`
|
|
||||||
- Proxies requests to:
|
|
||||||
- `EnvelopeGenerator.ReceiverUI` (Blazor WASM)
|
|
||||||
- External Auth.API service
|
|
||||||
- Serves as single entry point for all requests
|
|
||||||
|
|
||||||
2. **EnvelopeGenerator.ReceiverUI** (Blazor WebAssembly)
|
|
||||||
- Runs on separate host/port
|
|
||||||
- Accessed **only through API proxy** (not directly)
|
|
||||||
- Serves static files (HTML, JS, CSS, WASM)
|
|
||||||
|
|
||||||
**Request Flow:**
|
|
||||||
```
|
|
||||||
Client ? API:8088 (YARP Proxy) ? ReceiverUI:52936 (Blazor WASM)
|
|
||||||
? Auth.API:9090 (External Auth Service)
|
|
||||||
```
|
|
||||||
|
|
||||||
**Configuration:** `EnvelopeGenerator.API/yarp.json`
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## ReceiverUI Route Structure
|
|
||||||
|
|
||||||
### Root Route
|
|
||||||
| Route | File | Purpose |
|
|
||||||
|---|---|---|
|
|
||||||
| `/` | `Index.razor` | Application entry point (landing page). |
|
|
||||||
|
|
||||||
### Sender Routes
|
|
||||||
| Route | File | Purpose |
|
|
||||||
|---|---|---|
|
|
||||||
| `/sender/login` | `LoginSenderPage.razor` | Username/password authentication |
|
|
||||||
| `/sender` | `EnvelopeSenderPage.razor` | Sender dashboard (envelope list) |
|
|
||||||
|
|
||||||
### Receiver Routes
|
|
||||||
| Route | File | Purpose |
|
|
||||||
|---|---|---|
|
|
||||||
| `/envelope/login/{EnvelopeKey}` | `LoginReceiverPage.razor` | Access code authentication for specific envelope |
|
|
||||||
| `/envelope/{EnvelopeKey}` | `EnvelopeReceiverPage.razor` | View & sign envelope (PDF.js viewer) |
|
|
||||||
|
|
||||||
**Multi-Envelope Support:** Receivers can login to multiple envelopes simultaneously (per-envelope cookie authentication).
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Architecture Evolution
|
|
||||||
|
|
||||||
### Old Architecture (Deprecated)
|
|
||||||
- **Sender UI:** `EnvelopeGenerator.Web` (Razor Pages + PSPDFKit)
|
|
||||||
- **Receiver UI:** `EnvelopeGenerator.ReceiverUI` (Blazor WASM + PDF.js)
|
|
||||||
- **Backend:** `EnvelopeGenerator.API`
|
|
||||||
|
|
||||||
### Current Architecture
|
|
||||||
- **Unified Frontend:** `EnvelopeGenerator.ReceiverUI` (Blazor WASM) — **Both Senders & Receivers**
|
|
||||||
- **Backend:** `EnvelopeGenerator.API` — **Both Senders & Receivers**
|
|
||||||
- **Libraries:** DevExpress + PDF.js
|
|
||||||
- **PSPDFKit:** **REMOVED**
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Solution Structure
|
|
||||||
|
|
||||||
| Project | Target | Purpose |
|
|
||||||
|---|---|---|
|
|
||||||
| `EnvelopeGenerator.API` | net8.0 | ASP.NET Core Web API. Backend for **both Senders & Receivers**. Auth, PDF serving, signature endpoints. |
|
|
||||||
| `EnvelopeGenerator.ReceiverUI` | net8.0 WASM | **Unified Blazor WebAssembly Frontend**. UI for **both Senders & Receivers**. YARP proxy to API. |
|
|
||||||
| `EnvelopeGenerator.Web` | net7/8/9 | **DEPRECATED.** Legacy Razor Pages (Sender UI). No longer used. |
|
|
||||||
| `EnvelopeGenerator.Application` | multi | MediatR CQRS handlers. Business logic. |
|
|
||||||
| `EnvelopeGenerator.Domain` | multi | Domain models, constants, interfaces. |
|
|
||||||
| `EnvelopeGenerator.Infrastructure` | multi | EF Core repos, DB context. |
|
|
||||||
| `EnvelopeGenerator.PdfEditor` | multi | iText7 utilities (NOT used in ReceiverUI). |
|
|
||||||
| `EnvelopeGenerator.DependencyInjection` | multi | DI registration helpers. |
|
|
||||||
| **VB.NET projects** (Service/Form/BBTests) | net462 | **Legacy. Do NOT touch.** |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Key Files & Routes
|
|
||||||
|
|
||||||
| File | Route/Purpose |
|
|
||||||
|---|---|
|
|
||||||
| `ReceiverUI/Pages/Index.razor` | `/` — Application entry point (landing page). |
|
|
||||||
| `ReceiverUI/Pages/EnvelopeSenderPage.razor` | `/sender` — Sender dashboard (envelope list). |
|
|
||||||
| `ReceiverUI/Pages/EnvelopeReceiverPage.razor` | `/envelope/{key}` — Receiver PDF viewer & signing. |
|
|
||||||
| `ReceiverUI/Pages/LoginSenderPage.razor` | `/sender/login` — Sender username/password auth. |
|
|
||||||
| `ReceiverUI/Pages/LoginReceiverPage.razor` | `/envelope/login/{EnvelopeKey}` — Receiver access code auth. |
|
|
||||||
| `ReceiverUI/wwwroot/js/pdf-viewer.js` | PDF.js wrapper (zoom, pagination, thumbnails). |
|
|
||||||
| `ReceiverUI/wwwroot/js/receiver-signature.js` | Signature pad (draw/type/image). |
|
|
||||||
| `ReceiverUI/wwwroot/css/envelope-viewer.css` | EnvelopeViewer styles. |
|
|
||||||
| `ReceiverUI/Services/AuthService.cs` | Receiver + Sender authentication. |
|
|
||||||
| `ReceiverUI/Services/SignatureCacheService.cs` | Signature caching (Redis/SQL). |
|
|
||||||
| `API/Controllers/CacheController.cs` | Signature cache endpoints. |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Coordinate System — CRITICAL
|
|
||||||
|
|
||||||
**Database Format:** INCHES (GdPicture14 native)
|
|
||||||
**Origin:** Top-left corner
|
|
||||||
**Axes:** X right, Y down
|
|
||||||
|
|
||||||
### Conversion Formulas
|
|
||||||
|
|
||||||
| From INCHES to | Formula | Example |
|
|
||||||
|---|---|---|
|
|
||||||
| **DevExpress DX** | `x_DX = x_inches * 100` | 1.5" ? 150 DX |
|
|
||||||
| **PDF Points** | `x_pt = x_inches * 72` | 1.5" ? 108 pt |
|
|
||||||
| **PDF.js Pixels** | Normalize ? scale | `(x_inches / pageWidth) * canvasWidth * scale` |
|
|
||||||
|
|
||||||
**A4 Dimensions:**
|
|
||||||
- Width: 8.27" = 595pt = 827 DX
|
|
||||||
- Height: 11.69" = 842pt = 1169 DX
|
|
||||||
|
|
||||||
### Unit Systems
|
|
||||||
|
|
||||||
| System | Unit | Origin | Y-Axis |
|
|
||||||
|---|---|---|---|
|
|
||||||
| **Database (GdPicture14)** | Inches | Top-left | Down |
|
|
||||||
| PDF.js | Pixels | Top-left | Down |
|
|
||||||
| iText7 PDF | Points (1/72") | **Bottom-left** | **Up** (flip required) |
|
|
||||||
| ~~PSPDFKit~~ | ~~Points~~ | ~~Top-left~~ | **REMOVED** |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## EnvelopeReceiver — PDF.js Viewer & Signing
|
|
||||||
|
|
||||||
**Route:** `/envelope/{EnvelopeKey}`
|
|
||||||
**Tech:** PDF.js 3.11.174 + Blazor WASM + configurable quality
|
|
||||||
**File:** `ReceiverUI/Pages/EnvelopeReceiverPage.razor`
|
|
||||||
|
|
||||||
### Key Features
|
|
||||||
1. HiDPI/Retina support (4x quality)
|
|
||||||
2. Configurable quality (`appsettings.json`)
|
|
||||||
3. Unlimited zoom (50%-300%)
|
|
||||||
4. Ctrl+Wheel global zoom
|
|
||||||
5. Resizable thumbnail sidebar (150-400px, localStorage)
|
|
||||||
6. Responsive (desktop/mobile)
|
|
||||||
|
|
||||||
### Configuration
|
|
||||||
**File:** `ReceiverUI/wwwroot/appsettings.json`
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"PdfViewer": {
|
|
||||||
"ThumbnailBaseScale": 0.75,
|
|
||||||
"ThumbnailEnableHiDPI": true,
|
|
||||||
"MainCanvasEnableHiDPI": true,
|
|
||||||
"ZoomStepPercentage": 5
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### JavaScript API
|
|
||||||
**File:** `ReceiverUI/wwwroot/js/pdf-viewer.js`
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
window.pdfViewer = {
|
|
||||||
initialize(canvasId, pdfDataUrl, dotNetRef),
|
|
||||||
renderPage(num),
|
|
||||||
renderSignatureButtons(signatures, pageNum, dotNetRef),
|
|
||||||
applySignature(signatureId, dataUrl, fullName, position, place),
|
|
||||||
zoomIn(), zoomOut(), dispose()
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Signature Workflow — EnvelopeReceiver
|
|
||||||
|
|
||||||
**IMPORTANT:** iText7 NOT used (GPL license issue). Client-side overlay system only.
|
|
||||||
|
|
||||||
### Workflow Steps
|
|
||||||
|
|
||||||
1. **Page Load:**
|
|
||||||
- Check `SignatureCacheService` for cached signature
|
|
||||||
- If cached ? skip popup, load signature
|
|
||||||
- If not ? show automatic popup (mandatory)
|
|
||||||
|
|
||||||
2. **Signature Popup (DxPopup):**
|
|
||||||
- **Cannot close** (no X, no ESC, no outside-click)
|
|
||||||
- **3 Tabs:** Draw (canvas) / Text (font select) / Image (upload)
|
|
||||||
- **Required:** Full name, Place
|
|
||||||
- **Optional:** Position
|
|
||||||
- **Save ?** Store in `_capturedSignature`, cache via API
|
|
||||||
|
|
||||||
3. **Signature Buttons:**
|
|
||||||
- Render purple "Unterschreiben" buttons at signature field positions
|
|
||||||
- Coordinates: INCHES ? POINTS ? Pixels (scaled)
|
|
||||||
- File: `pdf-viewer.js` ? `renderSignatureButtons()`
|
|
||||||
|
|
||||||
4. **Apply Signature (Click "Unterschreiben"):**
|
|
||||||
- JS: Remove button, create HTML overlay
|
|
||||||
- Format: Image + separator + text (Name, Position, Place, Date)
|
|
||||||
- **NOT stamped on PDF bytes** (visual overlay only)
|
|
||||||
|
|
||||||
5. **Re-rendering:**
|
|
||||||
- Zoom/Page change ? recalculate button positions
|
|
||||||
- Session state: `_capturedSignature` (lost on refresh)
|
|
||||||
|
|
||||||
### Data Model
|
|
||||||
**File:** `ReceiverUI/Models/SignatureCaptureDto.cs`
|
|
||||||
|
|
||||||
```csharp
|
|
||||||
public sealed record SignatureCaptureDto {
|
|
||||||
public required string DataUrl { get; init; } // base64 PNG
|
|
||||||
public required string FullName { get; init; }
|
|
||||||
public string Position { get; init; } = ""; // Optional
|
|
||||||
public required string Place { get; init; }
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Signature Caching
|
|
||||||
|
|
||||||
**Purpose:** Persist signature across page refreshes (distributed cache: Redis/SQL)
|
|
||||||
|
|
||||||
### API Endpoints
|
|
||||||
**Controller:** `API/Controllers/CacheController.cs`
|
|
||||||
|
|
||||||
- `POST /api/Cache/SignatureCapture/{envelopeKey}` — Save
|
|
||||||
- `GET /api/Cache/SignatureCapture/{envelopeKey}` — Load
|
|
||||||
- `DELETE /api/Cache/SignatureCapture/{envelopeKey}` — Delete
|
|
||||||
|
|
||||||
**Cache Key Format:**
|
|
||||||
```
|
|
||||||
signature:91751687-8ae6-4777-bf5f-b8846085e62e:{envelopeKey}
|
|
||||||
```
|
|
||||||
|
|
||||||
**Configuration:** `appsettings.json`
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"Cache": {
|
|
||||||
"SignatureCacheExpiration": null // or "02:00:00" for 2h
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Service
|
|
||||||
**File:** `ReceiverUI/Services/SignatureCacheService.cs`
|
|
||||||
|
|
||||||
```csharp
|
|
||||||
public class SignatureCacheService {
|
|
||||||
Task SaveSignatureAsync(string envelopeKey, SignatureCaptureDto signature);
|
|
||||||
Task<SignatureCaptureDto?> GetSignatureAsync(string envelopeKey);
|
|
||||||
Task DeleteSignatureAsync(string envelopeKey);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**Error Handling:** Fire-and-forget saves, graceful degradation on load failure.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Sender Login
|
|
||||||
|
|
||||||
**Route:** `/sender/login`
|
|
||||||
**File:** `ReceiverUI/Pages/LoginSenderPage.razor`
|
|
||||||
**Tech:** Bootstrap 5 + DevExpress Blazing Berry theme
|
|
||||||
|
|
||||||
### AuthService Extension
|
|
||||||
**File:** `ReceiverUI/Services/AuthService.cs`
|
|
||||||
|
|
||||||
```csharp
|
|
||||||
public enum SenderLoginResult { Success, InvalidCredentials, Error }
|
|
||||||
|
|
||||||
public async Task<SenderLoginResult> LoginSenderAsync(string username, string password) {
|
|
||||||
var response = await http.PostAsJsonAsync(
|
|
||||||
$"{_api.BaseUrl}/api/auth?cookie=true",
|
|
||||||
new { username, password });
|
|
||||||
|
|
||||||
return response.StatusCode switch {
|
|
||||||
HttpStatusCode.OK => SenderLoginResult.Success,
|
|
||||||
HttpStatusCode.Unauthorized => SenderLoginResult.InvalidCredentials,
|
|
||||||
_ => SenderLoginResult.Error
|
|
||||||
};
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### API Integration
|
|
||||||
**Endpoint:** `POST /api/auth?cookie=true`
|
|
||||||
|
|
||||||
**Request:**
|
|
||||||
```json
|
|
||||||
{ "username": "TekH", "password": "***" }
|
|
||||||
```
|
|
||||||
|
|
||||||
**Response:**
|
|
||||||
- `200 OK` ? Cookie set, redirect to `/sender`
|
|
||||||
- `401 Unauthorized` ? Show error: "Ungültige Anmeldedaten"
|
|
||||||
- Other ? Show error: "Serverfehler"
|
|
||||||
|
|
||||||
**Cookie:** HTTP-only, Secure (HTTPS), SameSite=Strict
|
|
||||||
|
|
||||||
### UI Flow
|
|
||||||
1. User enters username + password
|
|
||||||
2. Click "Anmelden" or press Enter
|
|
||||||
3. Call `AuthService.LoginSenderAsync()`
|
|
||||||
4. Success ? `Navigation.NavigateTo("/sender", forceLoad: true)`
|
|
||||||
5. Error ? Display alert
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Receiver Login
|
|
||||||
|
|
||||||
**Route:** `/envelope/login/{EnvelopeKey}`
|
|
||||||
**File:** `ReceiverUI/Pages/LoginReceiverPage.razor`
|
|
||||||
|
|
||||||
**Multi-Envelope Support:** Cookies are stored per-envelope (e.g., `AuthTokenSignFLOWReceiver.{envelopeKey}`), allowing simultaneous authentication for multiple envelopes in the same browser session.
|
|
||||||
|
|
||||||
### AuthService Method
|
|
||||||
```csharp
|
|
||||||
public enum EnvelopeLoginResult { Success, InvalidCode, NotFound, Error }
|
|
||||||
|
|
||||||
public async Task<EnvelopeLoginResult> LoginEnvelopeReceiverAsync(string key, string accessCode) {
|
|
||||||
var form = new MultipartFormDataContent();
|
|
||||||
form.Add(new StringContent(accessCode), "AccessCode");
|
|
||||||
|
|
||||||
var response = await http.PostAsync(
|
|
||||||
$"{_api.BaseUrl}/api/Auth/envelope-receiver/{Uri.EscapeDataString(key)}", form);
|
|
||||||
|
|
||||||
return response.StatusCode switch {
|
|
||||||
HttpStatusCode.OK => EnvelopeLoginResult.Success,
|
|
||||||
HttpStatusCode.Unauthorized => EnvelopeLoginResult.InvalidCode,
|
|
||||||
HttpStatusCode.NotFound => EnvelopeLoginResult.NotFound,
|
|
||||||
_ => EnvelopeLoginResult.Error
|
|
||||||
};
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**Success:** Redirect to `/envelope/{key}`
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## NuGet Packages (ReceiverUI)
|
|
||||||
|
|
||||||
| Package | Version | Purpose |
|
|
||||||
|---|---|---|
|
|
||||||
| `DevExpress.Blazor.*` | 25.2.3 | UI components (grids, popups, etc.) |
|
|
||||||
| `SkiaSharp.*` | 3.119.1 | WASM rendering |
|
|
||||||
| ~~`itext`~~ | ~~8.0.5~~ | **NOT USED** (GPL license) |
|
|
||||||
|
|
||||||
**External CDN:**
|
|
||||||
- PDF.js 3.11.174: `https://cdnjs.cloudflare.com/ajax/libs/pdf.js/3.11.174/pdf.min.js`
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Mistakes History — Do NOT Repeat
|
|
||||||
|
|
||||||
| Mistake | Why Wrong |
|
|
||||||
|---|---|
|
|
||||||
| Using iText7 in EnvelopeReceiver | GPL license issue. Use overlay system instead. |
|
|
||||||
| Using PSPDFKit | Removed from architecture. Use PDF.js + DevExpress. |
|
|
||||||
| Hardcoded quality values in PDF.js | Use `appsettings.json` for configurability. |
|
|
||||||
| Complex toolbar layouts | User wants simplicity. Keep horizontal layout. |
|
|
||||||
| Over-designed UI (gradients/badges) | User prefers simple text labels. |
|
|
||||||
| Ignoring "revert" instructions | Revert HTML structure, not just CSS. |
|
|
||||||
| `BottomMarginBand` for signatures | Repeats on every page. Use DetailBand. |
|
|
||||||
| `imageY = (page-1) * 1169 + ann.Y` | Inflates DetailBand. Calculate per-page. |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Development Notes
|
|
||||||
|
|
||||||
### Deprecated Projects
|
|
||||||
**DO NOT USE:**
|
|
||||||
- `EnvelopeGenerator.Web` (Razor Pages) — Replaced by unified ReceiverUI
|
|
||||||
- PSPDFKit — Removed, use PDF.js + DevExpress instead
|
|
||||||
|
|
||||||
### Legacy Projects (VB.NET)
|
|
||||||
**DO NOT TOUCH:** `EnvelopeGenerator.Service`, `EnvelopeGenerator.Form`, `EnvelopeGenerator.BBTests`
|
|
||||||
|
|
||||||
### Signature Coordinate Evidence
|
|
||||||
**File:** `EnvelopeGenerator.Form/frmFieldEditor.vb` (VB.NET)
|
|
||||||
|
|
||||||
```vb
|
|
||||||
Private Const SIGNATURE_WIDTH As Single = 1.77 ' inches
|
|
||||||
Private Const SIGNATURE_HEIGHT As Single = 1.96 ' inches
|
|
||||||
|
|
||||||
Sub LoadAnnotation(pElement As Signature, ...)
|
|
||||||
oAnnotation.Left = CSng(pElement.X) ' Direct INCHES assignment
|
|
||||||
oAnnotation.Top = CSng(pElement.Y)
|
|
||||||
End Sub
|
|
||||||
```
|
|
||||||
|
|
||||||
Proves database uses INCHES natively.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Quick Reference
|
|
||||||
|
|
||||||
### When working with coordinates:
|
|
||||||
1. **Database ? UI:** INCHES × 72 = PDF Points
|
|
||||||
2. **UI ? Display:** Points × scale = Pixels
|
|
||||||
3. **iText7 stamping:** Flip Y-axis (top-down ? bottom-up)
|
|
||||||
|
|
||||||
### When adding features:
|
|
||||||
1. Check `Mistakes History` first
|
|
||||||
2. Prefer simplicity over complexity
|
|
||||||
3. Use `appsettings.json` for configuration
|
|
||||||
4. Keep consistent with existing design (Bootstrap 5 + Blazing Berry)
|
|
||||||
5. **Unified frontend:** ReceiverUI serves both Senders and Receivers
|
|
||||||
|
|
||||||
### When debugging:
|
|
||||||
1. **Coordinates:** Always check unit system (inches/points/pixels)
|
|
||||||
2. **Authentication:** Check cookie name/domain/SameSite
|
|
||||||
3. **Cache:** Check Redis/SQL connection + key format
|
|
||||||
4. **Frontend confusion:** Only use ReceiverUI (Web is deprecated)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
**Last Updated:** Session 19 (Razor file naming convention + Index route proxy)
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
namespace EnvelopeGenerator.API;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public static class AuthScheme
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Scheme name used for per-envelope receiver JWT authentication.
|
|
||||||
/// </summary>
|
|
||||||
public const string Receiver = "EnvelopeGenerator.API.ReceiverJWT";
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Scheme name used for per-envelope sender JWT authentication.
|
|
||||||
/// </summary>
|
|
||||||
public const string Sender = "EnvelopeGenerator.API.SenderJWT";
|
|
||||||
}
|
|
||||||
@@ -1,14 +1,12 @@
|
|||||||
using DigitalData.Core.Abstraction.Application.DTO;
|
using DigitalData.Core.Abstraction.Application.DTO;
|
||||||
using DigitalData.Core.Exceptions;
|
using DigitalData.Core.Exceptions;
|
||||||
using EnvelopeGenerator.API.Extensions;
|
|
||||||
using EnvelopeGenerator.Application.Common.Dto;
|
|
||||||
using EnvelopeGenerator.Application.Common.Extensions;
|
using EnvelopeGenerator.Application.Common.Extensions;
|
||||||
using EnvelopeGenerator.Application.Common.Interfaces.Services;
|
using EnvelopeGenerator.Application.Common.Interfaces.Services;
|
||||||
using EnvelopeGenerator.Application.Common.Notifications.DocSigned;
|
using EnvelopeGenerator.Application.Common.Notifications.DocSigned;
|
||||||
using EnvelopeGenerator.Application.Common.Notifications.RemoveSignature;
|
|
||||||
using EnvelopeGenerator.Application.EnvelopeReceivers.Queries;
|
using EnvelopeGenerator.Application.EnvelopeReceivers.Queries;
|
||||||
using EnvelopeGenerator.Application.Histories.Queries;
|
using EnvelopeGenerator.Application.Histories.Queries;
|
||||||
using EnvelopeGenerator.Domain.Constants;
|
using EnvelopeGenerator.Domain.Constants;
|
||||||
|
using EnvelopeGenerator.API.Extensions;
|
||||||
using MediatR;
|
using MediatR;
|
||||||
using Microsoft.AspNetCore.Authentication;
|
using Microsoft.AspNetCore.Authentication;
|
||||||
using Microsoft.AspNetCore.Authentication.Cookies;
|
using Microsoft.AspNetCore.Authentication.Cookies;
|
||||||
@@ -61,8 +59,8 @@ public class AnnotationController : ControllerBase
|
|||||||
[Obsolete("PSPDF Kit will no longer be used.")]
|
[Obsolete("PSPDF Kit will no longer be used.")]
|
||||||
public async Task<IActionResult> CreateOrUpdate([FromBody] PsPdfKitAnnotation? psPdfKitAnnotation = null, CancellationToken cancel = default)
|
public async Task<IActionResult> CreateOrUpdate([FromBody] PsPdfKitAnnotation? psPdfKitAnnotation = null, CancellationToken cancel = default)
|
||||||
{
|
{
|
||||||
var signature = User.ReceiverSignature();
|
var signature = User.GetReceiverSignatureOfReceiver();
|
||||||
var uuid = User.EnvelopeUuid();
|
var uuid = User.GetEnvelopeUuidOfReceiver();
|
||||||
|
|
||||||
var envelopeReceiver = await _mediator.ReadEnvelopeReceiverAsync(uuid, signature, cancel).ThrowIfNull(Exceptions.NotFound);
|
var envelopeReceiver = await _mediator.ReadEnvelopeReceiverAsync(uuid, signature, cancel).ThrowIfNull(Exceptions.NotFound);
|
||||||
|
|
||||||
@@ -74,24 +72,12 @@ public class AnnotationController : ControllerBase
|
|||||||
else if (await _mediator.AnyHistoryAsync(uuid, new[] { EnvelopeStatus.EnvelopeRejected, EnvelopeStatus.DocumentRejected }, cancel))
|
else if (await _mediator.AnyHistoryAsync(uuid, new[] { EnvelopeStatus.EnvelopeRejected, EnvelopeStatus.DocumentRejected }, cancel))
|
||||||
return Problem(statusCode: StatusCodes.Status423Locked);
|
return Problem(statusCode: StatusCodes.Status423Locked);
|
||||||
|
|
||||||
var envelopeReceiverDto = await _mediator.ReadEnvelopeReceiverAsync(uuid, signature, cancel);
|
var docSignedNotification = await _mediator
|
||||||
var docSignedNotification = envelopeReceiverDto is not null
|
.ReadEnvelopeReceiverAsync(uuid, signature, cancel)
|
||||||
? new DocSignedNotification { EnvelopeReceiver = envelopeReceiverDto, PsPdfKitAnnotation = psPdfKitAnnotation }
|
.ToDocSignedNotification(psPdfKitAnnotation)
|
||||||
: throw new NotFoundException("Envelope receiver is not found.");
|
?? throw new NotFoundException("Envelope receiver is not found.");
|
||||||
|
|
||||||
try
|
await _mediator.PublishSafely(docSignedNotification, cancel);
|
||||||
{
|
|
||||||
await _mediator.Publish(docSignedNotification, cancel);
|
|
||||||
}
|
|
||||||
catch (Exception)
|
|
||||||
{
|
|
||||||
await _mediator.Publish(new RemoveSignatureNotification()
|
|
||||||
{
|
|
||||||
EnvelopeId = docSignedNotification.EnvelopeReceiver.EnvelopeId,
|
|
||||||
ReceiverId = docSignedNotification.EnvelopeReceiver.ReceiverId
|
|
||||||
}, cancel);
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
|
await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
|
||||||
|
|
||||||
return Ok();
|
return Ok();
|
||||||
@@ -106,9 +92,9 @@ public class AnnotationController : ControllerBase
|
|||||||
[Obsolete("Use MediatR")]
|
[Obsolete("Use MediatR")]
|
||||||
public async Task<IActionResult> Reject([FromBody] string? reason = null)
|
public async Task<IActionResult> Reject([FromBody] string? reason = null)
|
||||||
{
|
{
|
||||||
var signature = User.ReceiverSignature();
|
var signature = User.GetReceiverSignatureOfReceiver();
|
||||||
var uuid = User.EnvelopeUuid();
|
var uuid = User.GetEnvelopeUuidOfReceiver();
|
||||||
var mail = User.ReceiverMail();
|
var mail = User.GetReceiverMailOfReceiver();
|
||||||
|
|
||||||
var envRcvRes = await _envelopeReceiverService.ReadByUuidSignatureAsync(uuid: uuid, signature: signature);
|
var envRcvRes = await _envelopeReceiverService.ReadByUuidSignatureAsync(uuid: uuid, signature: signature);
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
using DigitalData.Auth.Claims;
|
|
||||||
using EnvelopeGenerator.API.Controllers.Interfaces;
|
using EnvelopeGenerator.API.Controllers.Interfaces;
|
||||||
using EnvelopeGenerator.API.Models;
|
using EnvelopeGenerator.API.Models;
|
||||||
using EnvelopeGenerator.Domain.Constants;
|
using EnvelopeGenerator.Domain.Constants;
|
||||||
@@ -74,44 +73,4 @@ public partial class AuthController(IOptions<AuthTokenKeys> authTokenKeyOptions,
|
|||||||
=> role is not null && !User.IsInRole(role)
|
=> role is not null && !User.IsInRole(role)
|
||||||
? Unauthorized()
|
? Unauthorized()
|
||||||
: Ok();
|
: Ok();
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Checks whether the caller holds a valid per-envelope receiver token for the given envelope key.
|
|
||||||
/// The request must carry a cookie named <c>AuthTokenSignFLOWReceiver.{envelopeKey}</c>.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="envelopeKey">The unique envelope key extracted from the route.</param>
|
|
||||||
/// <response code="200">Valid per-envelope token found.</response>
|
|
||||||
/// <response code="401">Token is missing, expired or invalid.</response>
|
|
||||||
[ProducesResponseType(typeof(void), StatusCodes.Status200OK)]
|
|
||||||
[ProducesResponseType(typeof(void), StatusCodes.Status401Unauthorized)]
|
|
||||||
[Authorize(Policy = AuthPolicy.Receiver)]
|
|
||||||
[HttpGet("check/envelope/{envelopeKey}")]
|
|
||||||
public IActionResult CheckEnvelopeReceiver([FromRoute] string envelopeKey) => Ok();
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Removes the per-envelope receiver cookie for the given envelope key.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="envelopeKey">The unique envelope key whose cookie should be deleted.</param>
|
|
||||||
/// <response code="200">Cookie successfully deleted.</response>
|
|
||||||
[ProducesResponseType(typeof(void), StatusCodes.Status200OK)]
|
|
||||||
[HttpPost("logout/envelope/{envelopeKey}")]
|
|
||||||
public IActionResult LogoutEnvelopeReceiver([FromRoute] string envelopeKey)
|
|
||||||
{
|
|
||||||
var cookieName = CookieNames.GetEnvelopeReceiverCookieName(authTokenKeys.Cookie, envelopeKey);
|
|
||||||
Response.Cookies.Delete(cookieName);
|
|
||||||
return Ok();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Removes all per-envelope receiver cookies from the current request.
|
|
||||||
/// </summary>
|
|
||||||
/// <response code="200">All envelope receiver cookies successfully deleted.</response>
|
|
||||||
[ProducesResponseType(typeof(void), StatusCodes.Status200OK)]
|
|
||||||
[HttpPost("logout/envelope")]
|
|
||||||
public IActionResult LogoutAllEnvelopeReceivers()
|
|
||||||
{
|
|
||||||
foreach (var cookieName in Request.Cookies.Keys.Where(k => CookieNames.IsEnvelopeReceiverCookie(k, authTokenKeys.Cookie)))
|
|
||||||
Response.Cookies.Delete(cookieName);
|
|
||||||
return Ok();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -1,84 +0,0 @@
|
|||||||
using Microsoft.AspNetCore.Authorization;
|
|
||||||
using Microsoft.AspNetCore.Mvc;
|
|
||||||
using Microsoft.Extensions.Caching.Distributed;
|
|
||||||
using Microsoft.Extensions.Options;
|
|
||||||
using System.Text.Json;
|
|
||||||
using EnvelopeGenerator.API.Options;
|
|
||||||
using EnvelopeGenerator.Domain.Constants;
|
|
||||||
using EnvelopeGenerator.API.Extensions;
|
|
||||||
|
|
||||||
namespace EnvelopeGenerator.API.Controllers;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Manages cached data for receivers using distributed cache.
|
|
||||||
/// </summary>
|
|
||||||
[ApiController]
|
|
||||||
[Route("api/[controller]")]
|
|
||||||
[Authorize(Policy = AuthPolicy.Receiver)]
|
|
||||||
public class CacheController(
|
|
||||||
IDistributedCache cache,
|
|
||||||
IOptions<CacheOptions> cacheOptions) : ControllerBase
|
|
||||||
{
|
|
||||||
private const string SignatureCacheKeyPrefix = "envelope-generator.receiver-ui.signature:";
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Stores a receiver's signature in cache for the specified envelope.
|
|
||||||
/// </summary>
|
|
||||||
[Authorize(Policy = AuthPolicy.Receiver)]
|
|
||||||
[HttpPost("SignatureCapture/{envelopeKey}")]
|
|
||||||
public async Task<IActionResult> SaveSignature(
|
|
||||||
[FromRoute] string envelopeKey,
|
|
||||||
[FromBody] SignatureCacheRequest request,
|
|
||||||
CancellationToken cancel)
|
|
||||||
{
|
|
||||||
var cacheKey = $"{SignatureCacheKeyPrefix}{User.ReceiverSignature()}";
|
|
||||||
var json = JsonSerializer.Serialize(request);
|
|
||||||
|
|
||||||
var options = cacheOptions.Value.SignatureCacheExpiration.HasValue
|
|
||||||
? new DistributedCacheEntryOptions { AbsoluteExpirationRelativeToNow = cacheOptions.Value.SignatureCacheExpiration.Value }
|
|
||||||
: null;
|
|
||||||
|
|
||||||
await cache.SetStringAsync(cacheKey, json, options ?? new DistributedCacheEntryOptions(), cancel);
|
|
||||||
|
|
||||||
return Ok();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Retrieves a cached signature for the specified envelope.
|
|
||||||
/// </summary>
|
|
||||||
[Authorize(Policy = AuthPolicy.Receiver)]
|
|
||||||
[HttpGet("SignatureCapture/{envelopeKey}")]
|
|
||||||
public async Task<IActionResult> GetSignature([FromRoute] string envelopeKey, CancellationToken cancel)
|
|
||||||
{
|
|
||||||
var cacheKey = $"{SignatureCacheKeyPrefix}{User.ReceiverSignature()}";
|
|
||||||
var json = await cache.GetStringAsync(cacheKey, cancel);
|
|
||||||
|
|
||||||
if (json is null)
|
|
||||||
return NotFound();
|
|
||||||
|
|
||||||
var signature = JsonSerializer.Deserialize<SignatureCacheRequest>(json);
|
|
||||||
return Ok(signature);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Deletes a cached signature for the specified envelope.
|
|
||||||
/// </summary>
|
|
||||||
[Authorize(Policy = AuthPolicy.Receiver)]
|
|
||||||
[HttpDelete("SignatureCapture/{envelopeKey}")]
|
|
||||||
public async Task<IActionResult> DeleteSignature([FromRoute] string envelopeKey, CancellationToken cancel)
|
|
||||||
{
|
|
||||||
var cacheKey = $"{SignatureCacheKeyPrefix}{User.ReceiverSignature()}";
|
|
||||||
await cache.RemoveAsync(cacheKey, cancel);
|
|
||||||
|
|
||||||
return Ok();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Request model for caching signature data.
|
|
||||||
/// </summary>
|
|
||||||
public sealed record SignatureCacheRequest(
|
|
||||||
string DataUrl,
|
|
||||||
string FullName,
|
|
||||||
string Place,
|
|
||||||
string? Position = null);
|
|
||||||
@@ -1,4 +1,3 @@
|
|||||||
using DigitalData.Auth.Claims;
|
|
||||||
using EnvelopeGenerator.API.Controllers.Interfaces;
|
using EnvelopeGenerator.API.Controllers.Interfaces;
|
||||||
using EnvelopeGenerator.API.Extensions;
|
using EnvelopeGenerator.API.Extensions;
|
||||||
using EnvelopeGenerator.Application.Documents.Queries;
|
using EnvelopeGenerator.Application.Documents.Queries;
|
||||||
@@ -15,9 +14,10 @@ namespace EnvelopeGenerator.API.Controllers;
|
|||||||
/// <remarks>
|
/// <remarks>
|
||||||
/// Initializes a new instance of the <see cref="DocumentController"/> class.
|
/// Initializes a new instance of the <see cref="DocumentController"/> class.
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
|
[Authorize]
|
||||||
[ApiController]
|
[ApiController]
|
||||||
[Route("api/[controller]")]
|
[Route("api/[controller]")]
|
||||||
public class DocumentController(IMediator mediator, IAuthorizationService authService, ILogger<DocumentController> logger) : ControllerBase, IAuthController
|
public class DocumentController(IMediator mediator, IAuthorizationService authService) : ControllerBase, IAuthController
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
///
|
||||||
@@ -51,7 +51,7 @@ public class DocumentController(IMediator mediator, IAuthorizationService authSe
|
|||||||
if (query is not null)
|
if (query is not null)
|
||||||
return BadRequest("Query parameters are not allowed for receiver role.");
|
return BadRequest("Query parameters are not allowed for receiver role.");
|
||||||
|
|
||||||
var envelopeId = User.EnvelopeId();
|
var envelopeId = User.GetEnvelopeIdOfReceiver();
|
||||||
var receiverDoc = await mediator.Send(new ReadDocumentQuery { EnvelopeId = envelopeId }, cancel);
|
var receiverDoc = await mediator.Send(new ReadDocumentQuery { EnvelopeId = envelopeId }, cancel);
|
||||||
return receiverDoc.ByteData is byte[] receiverDocByte
|
return receiverDoc.ByteData is byte[] receiverDocByte
|
||||||
? File(receiverDocByte, "application/octet-stream")
|
? File(receiverDocByte, "application/octet-stream")
|
||||||
@@ -60,25 +60,4 @@ public class DocumentController(IMediator mediator, IAuthorizationService authSe
|
|||||||
|
|
||||||
return Unauthorized();
|
return Unauthorized();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the document for the specified envelope key.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="envelopeKey"></param>
|
|
||||||
/// <param name="cancel"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
[Authorize(Policy = AuthPolicy.Receiver)]
|
|
||||||
[HttpGet("{envelopeKey}")]
|
|
||||||
public async Task<IActionResult> GetDocumentOfReceiver(string envelopeKey, CancellationToken cancel)
|
|
||||||
{
|
|
||||||
int envelopeId = User.EnvelopeId();
|
|
||||||
|
|
||||||
var senderDoc = await mediator.Send(new ReadDocumentQuery() { EnvelopeId = envelopeId }, cancel);
|
|
||||||
|
|
||||||
if (senderDoc.ByteData is not byte[] senderDocByte)
|
|
||||||
return NotFound("Document is empty.");
|
|
||||||
|
|
||||||
Response.Headers.ContentDisposition = $"inline; filename=\"{envelopeKey}.pdf\"";
|
|
||||||
return File(senderDocByte, "application/pdf");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -51,7 +51,7 @@ public class EnvelopeController : ControllerBase
|
|||||||
/// <response code="401">Der Benutzer ist nicht authentifiziert.</response>
|
/// <response code="401">Der Benutzer ist nicht authentifiziert.</response>
|
||||||
/// <response code="403">Der Benutzer hat keine Berechtigung, auf die Ressource zuzugreifen.</response>
|
/// <response code="403">Der Benutzer hat keine Berechtigung, auf die Ressource zuzugreifen.</response>
|
||||||
/// <response code="500">Ein unerwarteter Fehler ist aufgetreten.</response>
|
/// <response code="500">Ein unerwarteter Fehler ist aufgetreten.</response>
|
||||||
[Authorize(AuthenticationSchemes = AuthScheme.Sender)]
|
[Authorize]
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
public async Task<IActionResult> GetAsync([FromQuery] ReadEnvelopeQuery envelope)
|
public async Task<IActionResult> GetAsync([FromQuery] ReadEnvelopeQuery envelope)
|
||||||
{
|
{
|
||||||
@@ -71,6 +71,7 @@ public class EnvelopeController : ControllerBase
|
|||||||
[HttpGet("doc-result")]
|
[HttpGet("doc-result")]
|
||||||
public async Task<IActionResult> GetDocResultAsync([FromQuery] ReadEnvelopeQuery query, [FromQuery] bool view = false)
|
public async Task<IActionResult> GetDocResultAsync([FromQuery] ReadEnvelopeQuery query, [FromQuery] bool view = false)
|
||||||
{
|
{
|
||||||
|
query.IncludeDocResult = true;
|
||||||
var envelopes = await _mediator.Send(query.Authorize(User.GetId()));
|
var envelopes = await _mediator.Send(query.Authorize(User.GetId()));
|
||||||
var envelope = envelopes.FirstOrDefault();
|
var envelope = envelopes.FirstOrDefault();
|
||||||
|
|
||||||
@@ -98,7 +99,7 @@ public class EnvelopeController : ControllerBase
|
|||||||
[HttpPost]
|
[HttpPost]
|
||||||
public async Task<IActionResult> CreateAsync([FromBody] CreateEnvelopeCommand command)
|
public async Task<IActionResult> CreateAsync([FromBody] CreateEnvelopeCommand command)
|
||||||
{
|
{
|
||||||
var res = await _mediator.Send(command.WithAuth(User.GetId()));
|
var res = await _mediator.Send(command.Authorize(User.GetId()));
|
||||||
|
|
||||||
if (res is null)
|
if (res is null)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ using EnvelopeGenerator.Application.Common.SQL;
|
|||||||
using EnvelopeGenerator.Application.Common.Dto.Receiver;
|
using EnvelopeGenerator.Application.Common.Dto.Receiver;
|
||||||
using EnvelopeGenerator.Application.Common.Interfaces.SQLExecutor;
|
using EnvelopeGenerator.Application.Common.Interfaces.SQLExecutor;
|
||||||
using EnvelopeGenerator.API.Extensions;
|
using EnvelopeGenerator.API.Extensions;
|
||||||
using EnvelopeGenerator.Domain.Constants;
|
|
||||||
|
|
||||||
namespace EnvelopeGenerator.API.Controllers;
|
namespace EnvelopeGenerator.API.Controllers;
|
||||||
|
|
||||||
@@ -74,24 +73,6 @@ public class EnvelopeReceiverController : ControllerBase
|
|||||||
return Ok(result);
|
return Ok(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="envelopeKey"></param>
|
|
||||||
/// <param name="cancel"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
[Authorize(Policy = AuthPolicy.Receiver)]
|
|
||||||
[HttpGet("{envelopeKey}")]
|
|
||||||
public async Task<IActionResult> GetEnvelopeReceiverOfReceiver([FromRoute] string envelopeKey, CancellationToken cancel)
|
|
||||||
{
|
|
||||||
var er = await _mediator.Send(new ReadEnvelopeReceiverQuery()
|
|
||||||
{
|
|
||||||
Key = envelopeKey
|
|
||||||
}, cancel);
|
|
||||||
|
|
||||||
return Ok(er.SingleOrDefault());
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Ruft den Namen des zuletzt verwendeten Empfängers basierend auf der angegebenen E-Mail-Adresse ab.
|
/// Ruft den Namen des zuletzt verwendeten Empfängers basierend auf der angegebenen E-Mail-Adresse ab.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -200,7 +181,7 @@ public class EnvelopeReceiverController : ControllerBase
|
|||||||
SELECT @OUT_SUCCESS as [@OUT_SUCCESS];";
|
SELECT @OUT_SUCCESS as [@OUT_SUCCESS];";
|
||||||
|
|
||||||
foreach (var rcv in res.SentReceiver)
|
foreach (var rcv in res.SentReceiver)
|
||||||
foreach (var sign in request.Receivers.Where(r => r.EmailAddress == rcv.EmailAddress).FirstOrDefault()?.DocReceiverElements ?? Enumerable.Empty<Application.EnvelopeReceivers.Commands.DocReceiverElementCreateDto>())
|
foreach (var sign in request.Receivers.Where(r => r.EmailAddress == rcv.EmailAddress).FirstOrDefault()?.Signatures ?? Enumerable.Empty<Application.EnvelopeReceivers.Commands.Signature>())
|
||||||
{
|
{
|
||||||
using SqlConnection conn = new(_cnnStr);
|
using SqlConnection conn = new(_cnnStr);
|
||||||
conn.Open();
|
conn.Open();
|
||||||
|
|||||||
@@ -41,14 +41,14 @@ public class ReadOnlyController : ControllerBase
|
|||||||
[Obsolete("Use MediatR")]
|
[Obsolete("Use MediatR")]
|
||||||
public async Task<IActionResult> CreateAsync([FromBody] EnvelopeReceiverReadOnlyCreateDto createDto)
|
public async Task<IActionResult> CreateAsync([FromBody] EnvelopeReceiverReadOnlyCreateDto createDto)
|
||||||
{
|
{
|
||||||
var authReceiverMail = User.ReceiverMail();
|
var authReceiverMail = User.GetReceiverMailOfReceiver();
|
||||||
if (authReceiverMail is null)
|
if (authReceiverMail is null)
|
||||||
{
|
{
|
||||||
_logger.LogError("EmailAddress claim is not found in envelope-receiver-read-only creation process. Create DTO is:\n {dto}", JsonConvert.SerializeObject(createDto));
|
_logger.LogError("EmailAddress claim is not found in envelope-receiver-read-only creation process. Create DTO is:\n {dto}", JsonConvert.SerializeObject(createDto));
|
||||||
return Unauthorized();
|
return Unauthorized();
|
||||||
}
|
}
|
||||||
|
|
||||||
var envelopeId = User.EnvelopeId();
|
var envelopeId = User.GetEnvelopeIdOfReceiver();
|
||||||
|
|
||||||
createDto.AddedWho = authReceiverMail;
|
createDto.AddedWho = authReceiverMail;
|
||||||
createDto.EnvelopeId = envelopeId;
|
createDto.EnvelopeId = envelopeId;
|
||||||
|
|||||||
@@ -1,57 +0,0 @@
|
|||||||
using EnvelopeGenerator.API.Extensions;
|
|
||||||
using EnvelopeGenerator.Application.Common.Dto;
|
|
||||||
using EnvelopeGenerator.Application.Common.Extensions;
|
|
||||||
using EnvelopeGenerator.Application.Documents.Queries;
|
|
||||||
using EnvelopeGenerator.Domain.Constants;
|
|
||||||
using MediatR;
|
|
||||||
using Microsoft.AspNetCore.Authorization;
|
|
||||||
using Microsoft.AspNetCore.Mvc;
|
|
||||||
|
|
||||||
namespace EnvelopeGenerator.API.Controllers;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
[Authorize(Policy = AuthPolicy.Receiver)]
|
|
||||||
[ApiController]
|
|
||||||
[Route("api/[controller]")]
|
|
||||||
public class SignatureController : ControllerBase
|
|
||||||
{
|
|
||||||
private readonly IMediator _mediator;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Initializes a new instance of <see cref="SignatureController"/>.
|
|
||||||
/// </summary>
|
|
||||||
public SignatureController(IMediator mediator)
|
|
||||||
{
|
|
||||||
_mediator = mediator;
|
|
||||||
}
|
|
||||||
|
|
||||||
//TODO: update to use signature query
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="envelopeKey"></param>
|
|
||||||
/// <param name="cancel"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
[Authorize(Policy = AuthPolicy.Receiver)]
|
|
||||||
[HttpGet("{envelopeKey}")]
|
|
||||||
public async Task<IActionResult> Get(string envelopeKey, CancellationToken cancel)
|
|
||||||
{
|
|
||||||
int envelopeId = User.EnvelopeId();
|
|
||||||
|
|
||||||
int receiverId = User.ReceiverId();
|
|
||||||
|
|
||||||
var doc = await _mediator.Send(new ReadDocumentQuery() { EnvelopeId = envelopeId }, cancel);
|
|
||||||
|
|
||||||
if (doc.Elements is not IEnumerable<DocReceiverElementDto> docSignatures)
|
|
||||||
return NotFound("Document is empty.");
|
|
||||||
|
|
||||||
var rcvSignatures = docSignatures.Where(s => s.ReceiverId == receiverId).ToList();
|
|
||||||
|
|
||||||
if (rcvSignatures is null)
|
|
||||||
return NotFound("No signatures found for the current receiver.");
|
|
||||||
else
|
|
||||||
return Ok(rcvSignatures);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -16,12 +16,6 @@ public sealed class AuthProxyDocumentFilter : IDocumentFilter
|
|||||||
/// <param name="swaggerDoc"></param>
|
/// <param name="swaggerDoc"></param>
|
||||||
/// <param name="context"></param>
|
/// <param name="context"></param>
|
||||||
public void Apply(OpenApiDocument swaggerDoc, DocumentFilterContext context)
|
public void Apply(OpenApiDocument swaggerDoc, DocumentFilterContext context)
|
||||||
{
|
|
||||||
AddLoginOperation(swaggerDoc, context);
|
|
||||||
AddEnvelopeReceiverLoginOperation(swaggerDoc, context);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void AddLoginOperation(OpenApiDocument swaggerDoc, DocumentFilterContext context)
|
|
||||||
{
|
{
|
||||||
const string path = "/api/auth";
|
const string path = "/api/auth";
|
||||||
|
|
||||||
@@ -73,51 +67,4 @@ public sealed class AuthProxyDocumentFilter : IDocumentFilter
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void AddEnvelopeReceiverLoginOperation(OpenApiDocument swaggerDoc, DocumentFilterContext context)
|
|
||||||
{
|
|
||||||
const string path = "/api/Auth/envelope-receiver/{key}";
|
|
||||||
|
|
||||||
var bodySchema = context.SchemaGenerator.GenerateSchema(typeof(EnvelopeReceiverLogin), context.SchemaRepository);
|
|
||||||
|
|
||||||
var operation = new OpenApiOperation
|
|
||||||
{
|
|
||||||
Summary = "Envelope receiver login (auth-hub proxy)",
|
|
||||||
Description = "Proxies the envelope receiver login to the auth service. " +
|
|
||||||
"The `cookie` query parameter is always forwarded as `true` so the auth service sets the per-envelope cookie automatically.",
|
|
||||||
Tags = [new() { Name = "Auth" }],
|
|
||||||
Parameters =
|
|
||||||
{
|
|
||||||
new OpenApiParameter
|
|
||||||
{
|
|
||||||
Name = "key",
|
|
||||||
In = ParameterLocation.Path,
|
|
||||||
Required = true,
|
|
||||||
Schema = new OpenApiSchema { Type = "string" },
|
|
||||||
Description = "The unique envelope receiver key."
|
|
||||||
}
|
|
||||||
},
|
|
||||||
RequestBody = new OpenApiRequestBody
|
|
||||||
{
|
|
||||||
Required = false,
|
|
||||||
Content =
|
|
||||||
{
|
|
||||||
["multipart/form-data"] = new OpenApiMediaType { Schema = bodySchema }
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Responses =
|
|
||||||
{
|
|
||||||
["200"] = new OpenApiResponse { Description = "OK – per-envelope cookie set by auth service." },
|
|
||||||
["401"] = new OpenApiResponse { Description = "Unauthorized – invalid or missing access code." }
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
swaggerDoc.Paths[path] = new OpenApiPathItem
|
|
||||||
{
|
|
||||||
Operations =
|
|
||||||
{
|
|
||||||
[OperationType.Post] = operation
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
17
EnvelopeGenerator.API/EnvelopeClaimTypes.cs
Normal file
17
EnvelopeGenerator.API/EnvelopeClaimTypes.cs
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
namespace EnvelopeGenerator.API;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Provides custom claim types for envelope-related information.
|
||||||
|
/// </summary>
|
||||||
|
public static class EnvelopeClaimTypes
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Claim type for the title of an envelope.
|
||||||
|
/// </summary>
|
||||||
|
public static readonly string Title = $"Envelope{nameof(Title)}";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Claim type for the ID of an envelope.
|
||||||
|
/// </summary>
|
||||||
|
public static readonly string Id = $"Envelope{nameof(Id)}";
|
||||||
|
}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFrameworks>net8.0</TargetFrameworks>
|
<TargetFrameworks>net9.0</TargetFrameworks>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||||
@@ -10,9 +10,9 @@
|
|||||||
<Authors>Digital Data GmbH</Authors>
|
<Authors>Digital Data GmbH</Authors>
|
||||||
<Company>Digital Data GmbH</Company>
|
<Company>Digital Data GmbH</Company>
|
||||||
<Product>EnvelopeGenerator.GeneratorAPI</Product>
|
<Product>EnvelopeGenerator.GeneratorAPI</Product>
|
||||||
<Version>1.4.0</Version>
|
<Version>1.2.3</Version>
|
||||||
<FileVersion>1.4.0</FileVersion>
|
<FileVersion>1.2.3</FileVersion>
|
||||||
<AssemblyVersion>1.4.0</AssemblyVersion>
|
<AssemblyVersion>1.2.3</AssemblyVersion>
|
||||||
<PackageOutputPath>Copyright © 2025 Digital Data GmbH. All rights reserved.</PackageOutputPath>
|
<PackageOutputPath>Copyright © 2025 Digital Data GmbH. All rights reserved.</PackageOutputPath>
|
||||||
<DocumentationFile>bin\$(Configuration)\$(TargetFramework)\$(AssemblyName).xml</DocumentationFile>
|
<DocumentationFile>bin\$(Configuration)\$(TargetFramework)\$(AssemblyName).xml</DocumentationFile>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
@@ -30,17 +30,11 @@
|
|||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="AspNetCore.Scalar" Version="1.1.8" />
|
<PackageReference Include="AspNetCore.Scalar" Version="1.1.8" />
|
||||||
<PackageReference Include="DigitalData.Auth.Claims" Version="1.0.3" />
|
|
||||||
<PackageReference Include="DigitalData.Auth.Client" Version="1.3.7" />
|
<PackageReference Include="DigitalData.Auth.Client" Version="1.3.7" />
|
||||||
<PackageReference Include="DigitalData.Core.API" Version="2.2.1" />
|
<PackageReference Include="DigitalData.Core.API" Version="2.2.1" />
|
||||||
<PackageReference Include="HtmlSanitizer" Version="9.0.892" />
|
<PackageReference Include="HtmlSanitizer" Version="9.0.892" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Caching.SqlServer" Version="8.0.11" Condition="'$(TargetFramework)' == 'net8.0'" />
|
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="9.0.4" />
|
||||||
<PackageReference Include="itext" Version="8.0.5" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="9.0.6" />
|
||||||
<PackageReference Include="itext.bouncy-castle-adapter" Version="8.0.5" />
|
|
||||||
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="9.0.4" Condition="'$(TargetFramework)' == 'net9.0'" />
|
|
||||||
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="8.0.11" Condition="'$(TargetFramework)' == 'net8.0'" />
|
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="9.0.6" Condition="'$(TargetFramework)' == 'net9.0'" />
|
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="8.0.17" Condition="'$(TargetFramework)' == 'net8.0'" />
|
|
||||||
<PackageReference Include="Microsoft.Identity.Client" Version="4.82.1" />
|
<PackageReference Include="Microsoft.Identity.Client" Version="4.82.1" />
|
||||||
<PackageReference Include="NLog" Version="5.2.5" />
|
<PackageReference Include="NLog" Version="5.2.5" />
|
||||||
<PackageReference Include="NLog.Web.AspNetCore" Version="5.3.0" />
|
<PackageReference Include="NLog.Web.AspNetCore" Version="5.3.0" />
|
||||||
@@ -77,7 +71,6 @@
|
|||||||
<ProjectReference Include="..\EnvelopeGenerator.Application\EnvelopeGenerator.Application.csproj" />
|
<ProjectReference Include="..\EnvelopeGenerator.Application\EnvelopeGenerator.Application.csproj" />
|
||||||
<ProjectReference Include="..\EnvelopeGenerator.Domain\EnvelopeGenerator.Domain.csproj" />
|
<ProjectReference Include="..\EnvelopeGenerator.Domain\EnvelopeGenerator.Domain.csproj" />
|
||||||
<ProjectReference Include="..\EnvelopeGenerator.Infrastructure\EnvelopeGenerator.Infrastructure.csproj" />
|
<ProjectReference Include="..\EnvelopeGenerator.Infrastructure\EnvelopeGenerator.Infrastructure.csproj" />
|
||||||
<ProjectReference Include="..\EnvelopeGenerator.PdfEditor\EnvelopeGenerator.PdfEditor.csproj" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
using DigitalData.Auth.Claims;
|
using System.Linq;
|
||||||
using Microsoft.IdentityModel.JsonWebTokens;
|
|
||||||
using System.Security.Claims;
|
using System.Security.Claims;
|
||||||
|
using EnvelopeGenerator.Application.Common.Dto.EnvelopeReceiver;
|
||||||
|
using Microsoft.AspNetCore.Authentication;
|
||||||
|
using Microsoft.AspNetCore.Authentication.Cookies;
|
||||||
|
|
||||||
namespace EnvelopeGenerator.API.Extensions;
|
namespace EnvelopeGenerator.API.Extensions;
|
||||||
|
|
||||||
@@ -9,14 +11,7 @@ namespace EnvelopeGenerator.API.Extensions;
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public static class ReceiverClaimExtensions
|
public static class ReceiverClaimExtensions
|
||||||
{
|
{
|
||||||
/// <summary>
|
private static string GetRequiredClaimOfReceiver(this ClaimsPrincipal user, string claimType)
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="user"></param>
|
|
||||||
/// <param name="claimType"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
/// <exception cref="InvalidOperationException"></exception>
|
|
||||||
private static string GetRequiredClaimValue(this ClaimsPrincipal user, string claimType)
|
|
||||||
{
|
{
|
||||||
var value = user.FindFirstValue(claimType);
|
var value = user.FindFirstValue(claimType);
|
||||||
if (value is not null)
|
if (value is not null)
|
||||||
@@ -32,65 +27,75 @@ public static class ReceiverClaimExtensions
|
|||||||
throw new InvalidOperationException(message);
|
throw new InvalidOperationException(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string GetRequiredClaimValue(this ClaimsPrincipal user, params string[] claimTypes)
|
|
||||||
{
|
|
||||||
foreach (var claimType in claimTypes.Where(t => !string.IsNullOrWhiteSpace(t)).Distinct())
|
|
||||||
{
|
|
||||||
var value = user.FindFirstValue(claimType);
|
|
||||||
if (!string.IsNullOrWhiteSpace(value))
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
var identity = user.Identity;
|
|
||||||
var principalName = identity?.Name ?? "(anonymous)";
|
|
||||||
var authType = identity?.AuthenticationType ?? "(none)";
|
|
||||||
var availableClaims = string.Join(", ", user.Claims.Select(c => $"{c.Type}={c.Value}"));
|
|
||||||
var message = $"Required claim(s) '{string.Join("', '", claimTypes)}' are missing for user '{principalName}' (auth: {authType}). Available claims: [{availableClaims}].";
|
|
||||||
throw new InvalidOperationException(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the authenticated envelope UUID from the claims.
|
/// Gets the authenticated envelope UUID from the claims.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static string EnvelopeUuid(this ClaimsPrincipal user)
|
public static string GetEnvelopeUuidOfReceiver(this ClaimsPrincipal user) => user.GetRequiredClaimOfReceiver(ClaimTypes.NameIdentifier);
|
||||||
=> user.GetRequiredClaimValue(EnvelopeClaimNames.EnvelopeUuid);
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the authenticated receiver signature from the claims.
|
/// Gets the authenticated receiver signature from the claims.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static string ReceiverSignature(this ClaimsPrincipal user)
|
public static string GetReceiverSignatureOfReceiver(this ClaimsPrincipal user) => user.GetRequiredClaimOfReceiver(ClaimTypes.Hash);
|
||||||
=> user.GetRequiredClaimValue(EnvelopeClaimNames.ReceiverSignature);
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the authenticated receiver display name from the claims.
|
||||||
|
/// </summary>
|
||||||
|
public static string GetReceiverNameOfReceiver(this ClaimsPrincipal user) => user.GetRequiredClaimOfReceiver(ClaimTypes.Name);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the authenticated receiver email address from the claims.
|
/// Gets the authenticated receiver email address from the claims.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static string ReceiverMail(this ClaimsPrincipal user)
|
public static string GetReceiverMailOfReceiver(this ClaimsPrincipal user) => user.GetRequiredClaimOfReceiver(ClaimTypes.Email);
|
||||||
=> user.GetRequiredClaimValue(JwtRegisteredClaimNames.Email);
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the authenticated envelope title from the claims.
|
||||||
|
/// </summary>
|
||||||
|
public static string GetEnvelopeTitleOfReceiver(this ClaimsPrincipal user) => user.GetRequiredClaimOfReceiver(EnvelopeClaimTypes.Title);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the authenticated envelope identifier from the claims.
|
/// Gets the authenticated envelope identifier from the claims.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static int EnvelopeId(this ClaimsPrincipal user)
|
public static int GetEnvelopeIdOfReceiver(this ClaimsPrincipal user)
|
||||||
{
|
{
|
||||||
var envIdStr = user.GetRequiredClaimValue(EnvelopeClaimNames.EnvelopeId);
|
var envIdStr = user.GetRequiredClaimOfReceiver(EnvelopeClaimTypes.Id);
|
||||||
if (int.TryParse(envIdStr, out var envId))
|
if (!int.TryParse(envIdStr, out var envId))
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException($"Claim '{EnvelopeClaimTypes.Id}' is not a valid integer.");
|
||||||
|
}
|
||||||
|
|
||||||
return envId;
|
return envId;
|
||||||
else
|
|
||||||
throw new InvalidOperationException($"Claim '{EnvelopeClaimNames.EnvelopeId}' is not a valid integer.");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the authenticated receiver identifier from the claims.
|
/// Signs in an envelope receiver using cookie authentication and attaches envelope claims.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="user"></param>
|
/// <param name="context">The current HTTP context.</param>
|
||||||
/// <returns></returns>
|
/// <param name="envelopeReceiver">Envelope receiver DTO to extract claims from.</param>
|
||||||
/// <exception cref="InvalidOperationException"></exception>
|
/// <param name="receiverRole">Role to attach to the authentication ticket.</param>
|
||||||
public static int ReceiverId(this ClaimsPrincipal user)
|
public static async Task SignInEnvelopeAsync(this HttpContext context, EnvelopeReceiverDto envelopeReceiver, string receiverRole)
|
||||||
{
|
{
|
||||||
var rcvIdStr = user.GetRequiredClaimValue(EnvelopeClaimNames.ReceiverId);
|
var claims = new List<Claim>
|
||||||
if (int.TryParse(rcvIdStr, out var rcvId))
|
{
|
||||||
return rcvId;
|
new(ClaimTypes.NameIdentifier, envelopeReceiver.Envelope!.Uuid),
|
||||||
else
|
new(ClaimTypes.Hash, envelopeReceiver.Receiver!.Signature),
|
||||||
throw new InvalidOperationException($"Claim '{EnvelopeClaimNames.ReceiverId}' is not a valid integer.");
|
new(ClaimTypes.Name, envelopeReceiver.Name ?? string.Empty),
|
||||||
|
new(ClaimTypes.Email, envelopeReceiver.Receiver.EmailAddress),
|
||||||
|
new(EnvelopeClaimTypes.Title, envelopeReceiver.Envelope.Title),
|
||||||
|
new(EnvelopeClaimTypes.Id, envelopeReceiver.Envelope.Id.ToString()),
|
||||||
|
new(ClaimTypes.Role, receiverRole)
|
||||||
|
};
|
||||||
|
|
||||||
|
var claimsIdentity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme);
|
||||||
|
|
||||||
|
var authProperties = new AuthenticationProperties
|
||||||
|
{
|
||||||
|
AllowRefresh = false,
|
||||||
|
IsPersistent = false
|
||||||
|
};
|
||||||
|
|
||||||
|
await context.SignInAsync(
|
||||||
|
CookieAuthenticationDefaults.AuthenticationScheme,
|
||||||
|
new ClaimsPrincipal(claimsIdentity),
|
||||||
|
authProperties);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
namespace EnvelopeGenerator.API.Models;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Request body for the envelope-receiver login endpoint.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="AccessCode">The access code sent to the receiver.</param>
|
|
||||||
public record EnvelopeReceiverLogin(string? AccessCode = null);
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
namespace EnvelopeGenerator.API.Options;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Configuration options for distributed caching.
|
|
||||||
/// </summary>
|
|
||||||
public sealed class CacheOptions
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Configuration section name in appsettings.json.
|
|
||||||
/// </summary>
|
|
||||||
public const string SectionName = "Cache";
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Signature cache expiration time.
|
|
||||||
/// If null, signatures will not expire automatically.
|
|
||||||
/// </summary>
|
|
||||||
public TimeSpan? SignatureCacheExpiration { get; set; }
|
|
||||||
}
|
|
||||||
@@ -17,11 +17,8 @@ using Microsoft.AspNetCore.Authentication.JwtBearer;
|
|||||||
using Microsoft.IdentityModel.Tokens;
|
using Microsoft.IdentityModel.Tokens;
|
||||||
using DigitalData.Core.Abstractions.Security.Extensions;
|
using DigitalData.Core.Abstractions.Security.Extensions;
|
||||||
using EnvelopeGenerator.API.Middleware;
|
using EnvelopeGenerator.API.Middleware;
|
||||||
using EnvelopeGenerator.API.Options;
|
|
||||||
using NLog.Web;
|
using NLog.Web;
|
||||||
using NLog;
|
using NLog;
|
||||||
using DigitalData.Auth.Claims;
|
|
||||||
using EnvelopeGenerator.API;
|
|
||||||
|
|
||||||
var logger = LogManager.Setup().LoadConfigurationFromAppSettings().GetCurrentClassLogger();
|
var logger = LogManager.Setup().LoadConfigurationFromAppSettings().GetCurrentClassLogger();
|
||||||
logger.Info("Logging initialized!");
|
logger.Info("Logging initialized!");
|
||||||
@@ -113,11 +110,9 @@ try
|
|||||||
|
|
||||||
options.DocumentFilter<EnvelopeGenerator.API.Documentation.AuthProxyDocumentFilter>();
|
options.DocumentFilter<EnvelopeGenerator.API.Documentation.AuthProxyDocumentFilter>();
|
||||||
});
|
});
|
||||||
#if NET9_0_OR_GREATER
|
|
||||||
builder.Services.AddOpenApi();
|
builder.Services.AddOpenApi();
|
||||||
#endif
|
|
||||||
|
|
||||||
//Add EF Core dbcontext
|
//AddEF Core dbcontext
|
||||||
var useDbMigration = Environment.GetEnvironmentVariable("MIGRATION_TEST_MODE") == true.ToString() || config.GetValue<bool>("UseDbMigration");
|
var useDbMigration = Environment.GetEnvironmentVariable("MIGRATION_TEST_MODE") == true.ToString() || config.GetValue<bool>("UseDbMigration");
|
||||||
var cnnStrName = useDbMigration ? "DbMigrationTest" : "Default";
|
var cnnStrName = useDbMigration ? "DbMigrationTest" : "Default";
|
||||||
var connStr = config.GetConnectionString(cnnStrName)
|
var connStr = config.GetConnectionString(cnnStrName)
|
||||||
@@ -136,7 +131,7 @@ try
|
|||||||
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
|
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
|
||||||
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
|
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
|
||||||
})
|
})
|
||||||
.AddJwtBearer(AuthScheme.Sender, opt =>
|
.AddJwtBearer(opt =>
|
||||||
{
|
{
|
||||||
opt.TokenValidationParameters = new TokenValidationParameters
|
opt.TokenValidationParameters = new TokenValidationParameters
|
||||||
{
|
{
|
||||||
@@ -168,61 +163,6 @@ try
|
|||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
})
|
|
||||||
// Per-envelope receiver scheme: reads the JWT from the cookie named
|
|
||||||
// AuthTokenSignFLOWReceiver.{envelope_key} where envelope_key is the
|
|
||||||
// last path segment of the request URL.
|
|
||||||
// This enables simultaneous authentication for multiple envelopes
|
|
||||||
// within the same browser session.
|
|
||||||
.AddJwtBearer(AuthScheme.Receiver, opt =>
|
|
||||||
{
|
|
||||||
opt.TokenValidationParameters = new TokenValidationParameters
|
|
||||||
{
|
|
||||||
ValidateIssuerSigningKey = true,
|
|
||||||
IssuerSigningKeyResolver = (token, securityToken, identifier, parameters) =>
|
|
||||||
{
|
|
||||||
var clientParams = deferredProvider.GetOptions<ClientParams>();
|
|
||||||
var publicKey = clientParams!.PublicKeys.Get(authTokenKeys.Issuer, authTokenKeys.Audience);
|
|
||||||
return [publicKey.SecurityKey];
|
|
||||||
},
|
|
||||||
ValidateIssuer = true,
|
|
||||||
ValidIssuer = authTokenKeys.Issuer,
|
|
||||||
ValidateAudience = true,
|
|
||||||
ValidAudience = authTokenKeys.Audience,
|
|
||||||
};
|
|
||||||
|
|
||||||
opt.Events = new JwtBearerEvents
|
|
||||||
{
|
|
||||||
OnMessageReceived = context =>
|
|
||||||
{
|
|
||||||
var paths = context.Request.Path.Value?.Split('/', StringSplitOptions.RemoveEmptyEntries);
|
|
||||||
|
|
||||||
// Derive the envelope key from the last route segment: /{envelope_key}
|
|
||||||
var envelopeKey = paths?.LastOrDefault();
|
|
||||||
|
|
||||||
if (envelopeKey is not null)
|
|
||||||
{
|
|
||||||
var cookieName = CookieNames.GetEnvelopeReceiverCookieName(authTokenKeys.Cookie, envelopeKey);
|
|
||||||
if (context.Request.Cookies.TryGetValue(cookieName, out var cookieToken) && cookieToken is not null)
|
|
||||||
context.Token = cookieToken;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Task.CompletedTask;
|
|
||||||
},
|
|
||||||
OnTokenValidated = context =>
|
|
||||||
{
|
|
||||||
var paths = context.Request.Path.Value?.Split('/', StringSplitOptions.RemoveEmptyEntries);
|
|
||||||
var envelopeKey = paths?.LastOrDefault();
|
|
||||||
|
|
||||||
var sub = context.Principal?.FindFirst(System.Security.Claims.ClaimTypes.NameIdentifier)?.Value
|
|
||||||
?? context.Principal?.FindFirst("sub")?.Value;
|
|
||||||
|
|
||||||
if (envelopeKey is null || sub != envelopeKey)
|
|
||||||
context.Fail("Envelope key in the path does not match the token subject.");
|
|
||||||
|
|
||||||
return Task.CompletedTask;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Authentication
|
// Authentication
|
||||||
@@ -238,16 +178,14 @@ try
|
|||||||
});
|
});
|
||||||
|
|
||||||
builder.Services.AddAuthorizationBuilder()
|
builder.Services.AddAuthorizationBuilder()
|
||||||
.AddPolicy(AuthPolicy.SenderOrReceiver, policy => policy.RequireRole(Role.Sender, Role.Receiver.Full))
|
.AddPolicy(AuthPolicy.SenderOrReceiver, policy =>
|
||||||
|
policy.RequireRole(Role.Sender, Role.Receiver.Full))
|
||||||
.AddPolicy(AuthPolicy.Sender, policy => policy
|
.AddPolicy(AuthPolicy.Sender, policy =>
|
||||||
.RequireRole(Role.Sender)
|
policy.RequireRole(Role.Sender))
|
||||||
.AddAuthenticationSchemes(AuthScheme.Sender))
|
.AddPolicy(AuthPolicy.Receiver, policy =>
|
||||||
.AddPolicy(AuthPolicy.Receiver, policy => policy
|
policy.RequireRole(Role.Receiver.Full))
|
||||||
.AddAuthenticationSchemes(AuthScheme.Receiver)
|
.AddPolicy(AuthPolicy.ReceiverTFA, policy =>
|
||||||
.RequireAuthenticatedUser()
|
policy.RequireRole(Role.Receiver.TFA));
|
||||||
.RequireRole(Role.Receiver.Full, "receiver"))
|
|
||||||
.AddPolicy(AuthPolicy.ReceiverTFA, policy => policy.RequireRole(Role.Receiver.TFA));
|
|
||||||
|
|
||||||
// User manager
|
// User manager
|
||||||
#pragma warning disable CS0618 // Type or member is obsolete
|
#pragma warning disable CS0618 // Type or member is obsolete
|
||||||
@@ -261,20 +199,6 @@ try
|
|||||||
// Localizer
|
// Localizer
|
||||||
builder.Services.AddCookieBasedLocalizer();
|
builder.Services.AddCookieBasedLocalizer();
|
||||||
|
|
||||||
// Cache options
|
|
||||||
builder.Services.Configure<CacheOptions>(config.GetSection(CacheOptions.SectionName));
|
|
||||||
|
|
||||||
// Distributed Cache - SQL Server
|
|
||||||
builder.Services.AddDistributedSqlServerCache(options =>
|
|
||||||
{
|
|
||||||
config.GetSection("Cache:SqlServer").Bind(options);
|
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(options.ConnectionString))
|
|
||||||
{
|
|
||||||
options.ConnectionString = connStr;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Envelope generator serives
|
// Envelope generator serives
|
||||||
#pragma warning disable CS0618 // Type or member is obsolete
|
#pragma warning disable CS0618 // Type or member is obsolete
|
||||||
builder.Services
|
builder.Services
|
||||||
@@ -300,9 +224,7 @@ try
|
|||||||
|
|
||||||
app.UseMiddleware<ExceptionHandlingMiddleware>();
|
app.UseMiddleware<ExceptionHandlingMiddleware>();
|
||||||
|
|
||||||
#if NET9_0_OR_GREATER
|
|
||||||
app.MapOpenApi();
|
app.MapOpenApi();
|
||||||
#endif
|
|
||||||
|
|
||||||
// Configure the HTTP request pipeline.
|
// Configure the HTTP request pipeline.
|
||||||
if (app.Environment.IsDevelopment() || (app.IsDevOrDiP() && config.GetValue<bool>("UseSwagger")))
|
if (app.Environment.IsDevelopment() || (app.IsDevOrDiP() && config.GetValue<bool>("UseSwagger")))
|
||||||
@@ -336,10 +258,8 @@ try
|
|||||||
app.UseAuthentication();
|
app.UseAuthentication();
|
||||||
app.UseAuthorization();
|
app.UseAuthorization();
|
||||||
|
|
||||||
app.MapControllers();
|
|
||||||
|
|
||||||
// Catch-all YARP proxy — only forward requests that are not swagger/scalar/openapi paths.
|
|
||||||
app.MapReverseProxy();
|
app.MapReverseProxy();
|
||||||
|
app.MapControllers();
|
||||||
|
|
||||||
app.Run();
|
app.Run();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,20 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!--
|
|
||||||
https://go.microsoft.com/fwlink/?LinkID=208121.
|
|
||||||
-->
|
|
||||||
<Project>
|
|
||||||
<PropertyGroup>
|
|
||||||
<WebPublishMethod>Package</WebPublishMethod>
|
|
||||||
<LastUsedBuildConfiguration>Release</LastUsedBuildConfiguration>
|
|
||||||
<LastUsedPlatform>Any CPU</LastUsedPlatform>
|
|
||||||
<SiteUrlToLaunchAfterPublish />
|
|
||||||
<LaunchSiteAfterPublish>true</LaunchSiteAfterPublish>
|
|
||||||
<ExcludeApp_Data>false</ExcludeApp_Data>
|
|
||||||
<ProjectGuid>5e0e17c0-ff5a-4246-bf87-1add85376a27</ProjectGuid>
|
|
||||||
<DesktopBuildPackageLocation>M:\App&Service\0 DD - Smart UP\signFLOW\API\net8\$(Version)\EnvelopeGenerator.API.zip</DesktopBuildPackageLocation>
|
|
||||||
<PackageAsSingleFile>true</PackageAsSingleFile>
|
|
||||||
<DeployIisAppPath>EnvelopeGenerator</DeployIisAppPath>
|
|
||||||
<_TargetId>IISWebDeployPackage</_TargetId>
|
|
||||||
<TargetFramework>net8.0</TargetFramework>
|
|
||||||
</PropertyGroup>
|
|
||||||
</Project>
|
|
||||||
@@ -1,21 +1,10 @@
|
|||||||
{
|
{
|
||||||
"Logging": {
|
"Logging": {
|
||||||
"LogLevel": {
|
"LogLevel": {
|
||||||
"Default": "Information",
|
"Default": "Information",
|
||||||
"Microsoft.AspNetCore": "Warning"
|
"Microsoft.AspNetCore": "Warning"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"ReverseProxy": {
|
|
||||||
"Clusters": {
|
|
||||||
"receiver-ui": {
|
|
||||||
"Destinations": {
|
|
||||||
"primary": {
|
|
||||||
"Address": "https://localhost:52936"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"AuthClientParams": {
|
"AuthClientParams": {
|
||||||
"Url": "http://172.24.12.39:9090/auth-hub",
|
"Url": "http://172.24.12.39:9090/auth-hub",
|
||||||
"PublicKeys": [
|
"PublicKeys": [
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"UseSwagger": true,
|
"UseSwagger": true,
|
||||||
"UseDbMigration": false,
|
"UseDbMigration": true,
|
||||||
"DiPMode": true,
|
"DiPMode": true,
|
||||||
"Logging": {
|
"Logging": {
|
||||||
"LogLevel": {
|
"LogLevel": {
|
||||||
@@ -174,14 +174,6 @@
|
|||||||
"Receiver": [],
|
"Receiver": [],
|
||||||
"EmailTemplate": [ "TBSIG_EMAIL_TEMPLATE_AFT_UPD" ]
|
"EmailTemplate": [ "TBSIG_EMAIL_TEMPLATE_AFT_UPD" ]
|
||||||
},
|
},
|
||||||
"Cache": {
|
|
||||||
"SignatureCacheExpiration": null,
|
|
||||||
"SqlServer": {
|
|
||||||
"ConnectionString": null,
|
|
||||||
"SchemaName": "dbo",
|
|
||||||
"TableName": "TBDD_CACHE"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"MainPageTitle": null,
|
"MainPageTitle": null,
|
||||||
"AnnotationParams": {
|
"AnnotationParams": {
|
||||||
"Background": {
|
"Background": {
|
||||||
|
|||||||
@@ -1,144 +1,6 @@
|
|||||||
{
|
{
|
||||||
"ReverseProxy": {
|
"ReverseProxy": {
|
||||||
"Routes": {
|
"Routes": {
|
||||||
"receiver-ui-root": {
|
|
||||||
"ClusterId": "receiver-ui",
|
|
||||||
"Order": 300,
|
|
||||||
"Match": {
|
|
||||||
"Path": "/",
|
|
||||||
"Methods": [ "GET", "HEAD" ]
|
|
||||||
},
|
|
||||||
"Transforms": [
|
|
||||||
{ "PathSet": "/index.html" }
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"receiver-ui-sender": {
|
|
||||||
"ClusterId": "receiver-ui",
|
|
||||||
"Order": 100,
|
|
||||||
"Match": {
|
|
||||||
"Path": "/sender/{**catch-all}",
|
|
||||||
"Methods": [ "GET", "HEAD" ]
|
|
||||||
},
|
|
||||||
"Transforms": [
|
|
||||||
{ "PathSet": "/index.html" }
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"receiver-ui-envelope": {
|
|
||||||
"ClusterId": "receiver-ui",
|
|
||||||
"Order": 100,
|
|
||||||
"Match": {
|
|
||||||
"Path": "/envelope/{EnvelopeKey}",
|
|
||||||
"Methods": [ "GET", "HEAD" ]
|
|
||||||
},
|
|
||||||
"Transforms": [
|
|
||||||
{ "PathSet": "/index.html" }
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"receiver-ui-envelope-dxreportviewer": {
|
|
||||||
"ClusterId": "receiver-ui",
|
|
||||||
"Order": 90,
|
|
||||||
"Match": {
|
|
||||||
"Path": "/envelope/{EnvelopeKey}/DxReportViewer",
|
|
||||||
"Methods": [ "GET", "HEAD" ]
|
|
||||||
},
|
|
||||||
"Transforms": [
|
|
||||||
{ "PathSet": "/index.html" }
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"receiver-ui-blazor-framework": {
|
|
||||||
"ClusterId": "receiver-ui",
|
|
||||||
"Order": 50,
|
|
||||||
"Match": {
|
|
||||||
"Path": "/_framework/{**catch-all}",
|
|
||||||
"Methods": [ "GET", "HEAD" ]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"receiver-ui-blazor-content": {
|
|
||||||
"ClusterId": "receiver-ui",
|
|
||||||
"Order": 50,
|
|
||||||
"Match": {
|
|
||||||
"Path": "/_content/{**catch-all}",
|
|
||||||
"Methods": [ "GET", "HEAD" ]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"receiver-ui-static-css": {
|
|
||||||
"ClusterId": "receiver-ui",
|
|
||||||
"Order": 200,
|
|
||||||
"Match": {
|
|
||||||
"Path": "/css/{**catch-all}",
|
|
||||||
"Methods": [ "GET", "HEAD" ]
|
|
||||||
},
|
|
||||||
"Transforms": [
|
|
||||||
{
|
|
||||||
"ResponseHeader": "Cache-Control",
|
|
||||||
"Set": "no-cache, no-store, must-revalidate",
|
|
||||||
"When": "Always"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"receiver-ui-static-js": {
|
|
||||||
"ClusterId": "receiver-ui",
|
|
||||||
"Order": 200,
|
|
||||||
"Match": {
|
|
||||||
"Path": "/js/{**catch-all}",
|
|
||||||
"Methods": [ "GET", "HEAD" ]
|
|
||||||
},
|
|
||||||
"Transforms": [
|
|
||||||
{
|
|
||||||
"ResponseHeader": "Cache-Control",
|
|
||||||
"Set": "no-cache, no-store, must-revalidate",
|
|
||||||
"When": "Always"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"receiver-ui-fake-data": {
|
|
||||||
"ClusterId": "receiver-ui",
|
|
||||||
"Order": 200,
|
|
||||||
"Match": {
|
|
||||||
"Path": "/fake-data/{**catch-all}",
|
|
||||||
"Methods": [ "GET", "HEAD" ]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"receiver-ui-appsettings": {
|
|
||||||
"ClusterId": "receiver-ui",
|
|
||||||
"Order": 50,
|
|
||||||
"Match": {
|
|
||||||
"Path": "/appsettings.json",
|
|
||||||
"Methods": [ "GET", "HEAD" ]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"receiver-ui-appsettings-dev": {
|
|
||||||
"ClusterId": "receiver-ui",
|
|
||||||
"Order": 50,
|
|
||||||
"Match": {
|
|
||||||
"Path": "/appsettings.Development.json",
|
|
||||||
"Methods": [ "GET", "HEAD" ]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"receiver-ui-styles": {
|
|
||||||
"ClusterId": "receiver-ui",
|
|
||||||
"Order": 50,
|
|
||||||
"Match": {
|
|
||||||
"Path": "/EnvelopeGenerator.ReceiverUI.styles.css",
|
|
||||||
"Methods": [ "GET", "HEAD" ]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"receiver-ui-fonts": {
|
|
||||||
"ClusterId": "receiver-ui",
|
|
||||||
"Order": 200,
|
|
||||||
"Match": {
|
|
||||||
"Path": "/fonts/{**catch-all}",
|
|
||||||
"Methods": [ "GET", "HEAD" ]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"receiver-ui-images": {
|
|
||||||
"ClusterId": "receiver-ui",
|
|
||||||
"Order": 200,
|
|
||||||
"Match": {
|
|
||||||
"Path": "/images/{**catch-all}",
|
|
||||||
"Methods": [ "GET", "HEAD" ]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"auth-login": {
|
"auth-login": {
|
||||||
"ClusterId": "auth-hub",
|
"ClusterId": "auth-hub",
|
||||||
"Match": {
|
"Match": {
|
||||||
@@ -148,30 +10,9 @@
|
|||||||
"Transforms": [
|
"Transforms": [
|
||||||
{ "PathSet": "/api/auth/sign-flow" }
|
{ "PathSet": "/api/auth/sign-flow" }
|
||||||
]
|
]
|
||||||
},
|
|
||||||
"auth-envelope-receiver-login": {
|
|
||||||
"ClusterId": "auth-hub",
|
|
||||||
"Match": {
|
|
||||||
"Path": "/api/Auth/envelope-receiver/{key}",
|
|
||||||
"Methods": [ "POST" ]
|
|
||||||
},
|
|
||||||
"Transforms": [
|
|
||||||
{ "PathPattern": "/api/auth/envelope-receiver/{key}" },
|
|
||||||
{
|
|
||||||
"QueryValueParameter": "cookie",
|
|
||||||
"Set": "true"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"Clusters": {
|
"Clusters": {
|
||||||
"receiver-ui": {
|
|
||||||
"Destinations": {
|
|
||||||
"primary": {
|
|
||||||
"Address": "https://localhost:52936"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"auth-hub": {
|
"auth-hub": {
|
||||||
"Destinations": {
|
"Destinations": {
|
||||||
"primary": {
|
"primary": {
|
||||||
@@ -182,4 +23,3 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
13
EnvelopeGenerator.Application/Common/CacheKey.cs
Normal file
13
EnvelopeGenerator.Application/Common/CacheKey.cs
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
namespace EnvelopeGenerator.Application.Common;
|
||||||
|
|
||||||
|
// TODO: merge other cache keys here as well, e.g. for templates, etc.
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
public static class CacheKey
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
public static readonly Guid DefaultConfig = Guid.NewGuid();
|
||||||
|
}
|
||||||
@@ -8,77 +8,42 @@ public record AnnotationCreateDto
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
///
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public long Id { get; set; }
|
public int ElementId { get; init; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
///
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Obsolete("Not required for DevExpress")]
|
public string Name { get; init; } = null!;
|
||||||
public int ElementId { get; init; } = -1;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
///
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Obsolete("Not required for DevExpress")]
|
public string Value { get; init; } = null!;
|
||||||
public string Name { get; init; } = string.Empty;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
///
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Obsolete("Not required for DevExpress")]
|
public string Type { get; init; } = null!;
|
||||||
public string Value { get; init; } = string.Empty;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
///
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Obsolete("Not required for DevExpress")]
|
|
||||||
public string Type { get; init; } = string.Empty;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Horizontal position of the signature field on the page.
|
|
||||||
/// <br/><br/>
|
|
||||||
/// <b>Unit:</b> INCHES (GdPicture14 native), origin at the <b>top-left</b> corner of the page, X increases to the right.
|
|
||||||
/// <br/>
|
|
||||||
/// <b>Conversion to DevExpress:</b> Multiply by 100 (DX uses 1/100 inch).
|
|
||||||
/// Convert: <c>xDX = xInches * 100.0</c>
|
|
||||||
/// <br/>
|
|
||||||
/// <b>Conversion to PDF Points:</b> Multiply by 72 (PSPDFKit, iText7 use 1/72 inch).
|
|
||||||
/// Convert: <c>xPt = xInches * 72.0</c>
|
|
||||||
/// </summary>
|
|
||||||
public double? X { get; init; }
|
public double? X { get; init; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Vertical position of the signature field on the page.
|
///
|
||||||
/// <br/><br/>
|
|
||||||
/// <b>Unit:</b> INCHES (GdPicture14 native), origin at the <b>top-left</b> corner of the page, Y increases downward.
|
|
||||||
/// <br/>
|
|
||||||
/// <b>Conversion to DevExpress:</b> Multiply by 100 (DX uses 1/100 inch).
|
|
||||||
/// Convert: <c>yDX = yInches * 100.0</c>
|
|
||||||
/// <br/>
|
|
||||||
/// <b>Conversion to PDF Points (top-left origin):</b> Multiply by 72.
|
|
||||||
/// Convert: <c>yPt = yInches * 72.0</c>
|
|
||||||
/// <br/>
|
|
||||||
/// <b>Conversion to PDF Points (bottom-left origin - iText7):</b> Y-flip required.
|
|
||||||
/// Convert: <c>yPt = (pageHeightInches - yInches - elemHeightInches) * 72.0</c>
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public double? Y { get; init; }
|
public double? Y { get; init; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
///
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Obsolete("Not required for DevExpress")]
|
|
||||||
public double? Width { get; init; }
|
public double? Width { get; init; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
///
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Obsolete("Not required for DevExpress")]
|
|
||||||
public double? Height { get; init; }
|
public double? Height { get; init; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Added to eliminate the need for SignatureDto in DevExpress
|
|
||||||
/// </summary>
|
|
||||||
public int? Page { get; init; }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -8,6 +8,11 @@ namespace EnvelopeGenerator.Application.Common.Dto;
|
|||||||
[ApiExplorerSettings(IgnoreApi = true)]
|
[ApiExplorerSettings(IgnoreApi = true)]
|
||||||
public class ConfigDto
|
public class ConfigDto
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the default document path.
|
||||||
|
/// </summary>
|
||||||
|
public string? DocumentPath { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the sending profile identifier.
|
/// Gets or sets the sending profile identifier.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -26,5 +31,30 @@ public class ConfigDto
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the path where exports will be saved.
|
/// Gets or sets the path where exports will be saved.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string? ExportPath { get; set; }
|
public string ExportPath { get; set; } = null!;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the creation timestamp.
|
||||||
|
/// </summary>
|
||||||
|
public DateTime AddedWhen { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the last update timestamp.
|
||||||
|
/// </summary>
|
||||||
|
public DateTime? ChangedWhen { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the legacy tinyint GUID field.
|
||||||
|
/// </summary>
|
||||||
|
public byte Guid { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets whether default TFA is enabled.
|
||||||
|
/// </summary>
|
||||||
|
public bool DefTfaEnabled { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets whether default TFA uses phone.
|
||||||
|
/// </summary>
|
||||||
|
public bool DefTfaWithPhone { get; set; }
|
||||||
}
|
}
|
||||||
@@ -31,5 +31,5 @@ public class DocumentDto
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the collection of elements associated with the document for receiver interactions, if any.
|
/// Gets or sets the collection of elements associated with the document for receiver interactions, if any.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public IEnumerable<DocReceiverElementDto>? Elements { get; set; }
|
public IEnumerable<SignatureDto>? Elements { get; set; }
|
||||||
}
|
}
|
||||||
@@ -1,12 +1,10 @@
|
|||||||
using DigitalData.EmailProfilerDispatcher.Abstraction.Attributes;
|
using DigitalData.EmailProfilerDispatcher.Abstraction.Attributes;
|
||||||
using DigitalData.UserManager.Application.DTOs.User;
|
using DigitalData.UserManager.Application.DTOs.User;
|
||||||
using EnvelopeGenerator.Application.Common.Dto.EnvelopeReceiver;
|
using EnvelopeGenerator.Application.Common.Dto.EnvelopeReceiver;
|
||||||
using EnvelopeGenerator.Application.Common.Dto.Receiver;
|
|
||||||
using EnvelopeGenerator.Domain.Constants;
|
using EnvelopeGenerator.Domain.Constants;
|
||||||
using EnvelopeGenerator.Domain.Entities;
|
using EnvelopeGenerator.Domain.Entities;
|
||||||
using EnvelopeGenerator.Domain.Interfaces;
|
using EnvelopeGenerator.Domain.Interfaces;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using System.Text.Json.Serialization;
|
|
||||||
|
|
||||||
namespace EnvelopeGenerator.Application.Common.Dto;
|
namespace EnvelopeGenerator.Application.Common.Dto;
|
||||||
|
|
||||||
@@ -47,6 +45,16 @@ public record EnvelopeDto : IEnvelope
|
|||||||
[TemplatePlaceholder("[MESSAGE]")]
|
[TemplatePlaceholder("[MESSAGE]")]
|
||||||
public string Message { get; set; } = string.Empty;
|
public string Message { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
public DateTime? ExpiresWhen { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
public DateTime? ExpiresWarningWhen { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
///
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -63,6 +71,11 @@ public record EnvelopeDto : IEnvelope
|
|||||||
[TemplatePlaceholder("[DOCUMENT_TITLE]")]
|
[TemplatePlaceholder("[DOCUMENT_TITLE]")]
|
||||||
public string Title { get; set; } = string.Empty;
|
public string Title { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Default value is string.Empty
|
||||||
|
/// </summary>
|
||||||
|
public string? Comment { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
///
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -76,14 +89,27 @@ public record EnvelopeDto : IEnvelope
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
///
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int? EnvelopeTypeId { get; set; }
|
public bool SendReminderEmails { get; set; }
|
||||||
|
|
||||||
// TODO: use ReadAndConfirm property name
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
///
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Obsolete("Use EnvelopeExtensions.IsReadAndConfirm extension metot instead.")]
|
public int? FirstReminderDays { get; set; }
|
||||||
public bool ReadOnly => this.IsReadAndConfirm();
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
public int? ReminderIntervalDays { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
public int? EnvelopeTypeId { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
public bool ReadOnly => EnvelopeTypeId == 2;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
///
|
||||||
@@ -95,6 +121,26 @@ public record EnvelopeDto : IEnvelope
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public bool UseAccessCode { get; set; } = true;
|
public bool UseAccessCode { get; set; } = true;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
public int? FinalEmailToCreator { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
public int? FinalEmailToReceivers { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
public int? ExpiresWhenDays { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
public int? ExpiresWarningWhenDays { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
///
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -133,5 +179,5 @@ public record EnvelopeDto : IEnvelope
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
///
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public IEnumerable<ReceiverDto>? Receivers { get; set; }
|
public IEnumerable<EnvelopeReceiverDto>? EnvelopeReceivers { get; set; }
|
||||||
}
|
}
|
||||||
@@ -23,10 +23,10 @@ public class MappingProfile : Profile
|
|||||||
{
|
{
|
||||||
// Entity to DTO mappings
|
// Entity to DTO mappings
|
||||||
CreateMap<Config, ConfigDto>();
|
CreateMap<Config, ConfigDto>();
|
||||||
CreateMap<DocReceiverElement, DocReceiverElementDto>();
|
CreateMap<Signature, SignatureDto>();
|
||||||
CreateMap<DocumentStatus, DocumentStatusDto>();
|
CreateMap<DocumentStatus, DocumentStatusDto>();
|
||||||
CreateMap<EmailTemplate, EmailTemplateDto>();
|
CreateMap<EmailTemplate, EmailTemplateDto>();
|
||||||
CreateMap<Envelope, EnvelopeDto>().ForMember(dest => dest.Receivers, opt => opt.MapFrom(src => src.EnvelopeReceivers.Select(er => er.Receiver)));
|
CreateMap<Envelope, EnvelopeDto>();
|
||||||
CreateMap<Document, DocumentDto>();
|
CreateMap<Document, DocumentDto>();
|
||||||
CreateMap<Domain.Entities.History, HistoryDto>().ForMember(dest => dest.ActionDate, opt => opt.MapFrom(src => src.ChangedWhen));
|
CreateMap<Domain.Entities.History, HistoryDto>().ForMember(dest => dest.ActionDate, opt => opt.MapFrom(src => src.ChangedWhen));
|
||||||
CreateMap<Domain.Entities.History, HistoryCreateDto>().ForMember(dest => dest.ActionDate, opt => opt.MapFrom(src => src.ChangedWhen));
|
CreateMap<Domain.Entities.History, HistoryCreateDto>().ForMember(dest => dest.ActionDate, opt => opt.MapFrom(src => src.ChangedWhen));
|
||||||
@@ -39,10 +39,7 @@ public class MappingProfile : Profile
|
|||||||
|
|
||||||
// DTO to Entity mappings
|
// DTO to Entity mappings
|
||||||
CreateMap<ConfigDto, Config>();
|
CreateMap<ConfigDto, Config>();
|
||||||
CreateMap<DocReceiverElementDto, DocReceiverElement>();
|
CreateMap<SignatureDto, Signature>();
|
||||||
CreateMap<Signature, DocReceiverElement>()
|
|
||||||
.ForMember(dest => dest.Ink, opt => opt.MapFrom(src => src.DataUrl.MapDataUrlToRequiredBytes()))
|
|
||||||
.MapChangedWhen();
|
|
||||||
CreateMap<DocumentStatusDto, DocumentStatus>();
|
CreateMap<DocumentStatusDto, DocumentStatus>();
|
||||||
CreateMap<EmailTemplateDto, EmailTemplate>();
|
CreateMap<EmailTemplateDto, EmailTemplate>();
|
||||||
CreateMap<EnvelopeDto, Envelope>();
|
CreateMap<EnvelopeDto, Envelope>();
|
||||||
|
|||||||
@@ -1,11 +0,0 @@
|
|||||||
using System.Dynamic;
|
|
||||||
|
|
||||||
namespace EnvelopeGenerator.Application.Common.Dto;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Represents PSPDFKit annotation data.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="Instant">Instant annotation data.</param>
|
|
||||||
/// <param name="Structured">Structured annotation data.</param>
|
|
||||||
[Obsolete("The PSPDFKit library is deprecated.")]
|
|
||||||
public record PsPdfKitAnnotation(ExpandoObject Instant, IEnumerable<AnnotationCreateDto> Structured);
|
|
||||||
@@ -1,65 +0,0 @@
|
|||||||
namespace EnvelopeGenerator.Application.Common.Dto;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Represents a captured signature with metadata created by the receiver in the signature popup.
|
|
||||||
/// This model holds the signature image (as base64 data URL) along with signer information
|
|
||||||
/// used for rendering applied signatures on the PDF canvas.
|
|
||||||
/// </summary>
|
|
||||||
/// <remarks>
|
|
||||||
/// <b>Used in:</b> EnvelopeViewer.razor signature popup workflow
|
|
||||||
/// <br/>
|
|
||||||
/// <b>Creation:</b> User draws/types/uploads signature and fills required fields
|
|
||||||
/// </remarks>
|
|
||||||
public sealed record Signature
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// TBDD_DOCUMENT_RECEIVER_ELEMENT.ID - identifies the specific signature field on the PDF page.
|
|
||||||
/// </summary>
|
|
||||||
public required int Id { get; init; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Base64-encoded data URL of the signature image.
|
|
||||||
/// <br/>
|
|
||||||
/// <b>Format:</b> <c>data:image/png;base64,iVBORw0KG...</c>
|
|
||||||
/// <br/>
|
|
||||||
/// <b>Source:</b> Canvas.toDataURL() from signature pad (draw/text/image tabs)
|
|
||||||
/// <br/>
|
|
||||||
/// <b>Usage:</b> Set as <c>img.src</c> in applied signature overlay
|
|
||||||
/// </summary>
|
|
||||||
public required string DataUrl { get; init; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Full name of the signer (first and last name).
|
|
||||||
/// <br/>
|
|
||||||
/// <b>Required:</b> Yes (validated in popup)
|
|
||||||
/// <br/>
|
|
||||||
/// <b>Example:</b> "Max Mustermann"
|
|
||||||
/// </summary>
|
|
||||||
public required string FullName { get; init; }
|
|
||||||
|
|
||||||
private readonly string? _position = null;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Job title or position of the signer.
|
|
||||||
/// <br/>
|
|
||||||
/// <b>Required:</b> No (optional field)
|
|
||||||
/// <br/>
|
|
||||||
/// <b>Example:</b> "Geschäftsführer" or empty string
|
|
||||||
/// </summary>
|
|
||||||
public string? Position
|
|
||||||
{
|
|
||||||
get => _position;
|
|
||||||
init => _position = string.IsNullOrWhiteSpace(value) ? value : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Location/place where the signature was created.
|
|
||||||
/// <br/>
|
|
||||||
/// <b>Required:</b> Yes (validated in popup)
|
|
||||||
/// <br/>
|
|
||||||
/// <b>Display:</b> Shown with current date in German format (dd.MM.yyyy)
|
|
||||||
/// <br/>
|
|
||||||
/// <b>Example:</b> "Berlin" ? rendered as "Berlin, 26.01.2025"
|
|
||||||
/// </summary>
|
|
||||||
public required string Place { get; init; }
|
|
||||||
}
|
|
||||||
@@ -1,7 +1,5 @@
|
|||||||
using EnvelopeGenerator.Domain.Constants;
|
using EnvelopeGenerator.Domain.Interfaces;
|
||||||
using EnvelopeGenerator.Domain.Interfaces;
|
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using System.ComponentModel.DataAnnotations.Schema;
|
|
||||||
|
|
||||||
namespace EnvelopeGenerator.Application.Common.Dto;
|
namespace EnvelopeGenerator.Application.Common.Dto;
|
||||||
|
|
||||||
@@ -9,7 +7,7 @@ namespace EnvelopeGenerator.Application.Common.Dto;
|
|||||||
/// Data Transfer Object representing a positioned element assigned to a document receiver.
|
/// Data Transfer Object representing a positioned element assigned to a document receiver.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[ApiExplorerSettings(IgnoreApi = true)]
|
[ApiExplorerSettings(IgnoreApi = true)]
|
||||||
public class DocReceiverElementDto : IDocReceiverElement
|
public class SignatureDto : ISignature
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the unique identifier of the element.
|
/// Gets or sets the unique identifier of the element.
|
||||||
@@ -95,34 +93,4 @@ public class DocReceiverElementDto : IDocReceiverElement
|
|||||||
/// Gets or sets the left position of the element (in layout terms).
|
/// Gets or sets the left position of the element (in layout terms).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public double Left => X;
|
public double Left => X;
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public IEnumerable<AnnotationDto>? Annotations { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public SenderAppType SenderAppType { get; set; } = SenderAppType.LegacyFormApp;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public string? FullName { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public string? Position { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public string? Place { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public byte[]? Ink { get; set; }
|
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
using AutoMapper;
|
using AutoMapper;
|
||||||
using EnvelopeGenerator.Domain.Interfaces.Auditing;
|
using EnvelopeGenerator.Domain.Interfaces.Auditing;
|
||||||
using System;
|
|
||||||
|
|
||||||
namespace EnvelopeGenerator.Application.Common.Extensions;
|
namespace EnvelopeGenerator.Application.Common.Extensions;
|
||||||
|
|
||||||
@@ -14,29 +13,12 @@ public static class AutoMapperAuditingExtensions
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public static IMappingExpression<TSource, TDestination> MapAddedWhen<TSource, TDestination>(this IMappingExpression<TSource, TDestination> expression)
|
public static IMappingExpression<TSource, TDestination> MapAddedWhen<TSource, TDestination>(this IMappingExpression<TSource, TDestination> expression)
|
||||||
where TDestination : IHasAddedWhen
|
where TDestination : IHasAddedWhen
|
||||||
=> expression.ForMember(dest => dest.AddedWhen, opt => opt.MapFrom(_ => DateTime.Now));
|
=> expression.ForMember(dest => dest.AddedWhen, opt => opt.MapFrom(_ => DateTime.UtcNow));
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Maps <see cref="IHasChangedWhen.ChangedWhen"/> to the current UTC time.
|
/// Maps <see cref="IHasChangedWhen.ChangedWhen"/> to the current UTC time.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static IMappingExpression<TSource, TDestination> MapChangedWhen<TSource, TDestination>(this IMappingExpression<TSource, TDestination> expression)
|
public static IMappingExpression<TSource, TDestination> MapChangedWhen<TSource, TDestination>(this IMappingExpression<TSource, TDestination> expression)
|
||||||
where TDestination : IHasChangedWhen
|
where TDestination : IHasChangedWhen
|
||||||
=> expression.ForMember(dest => dest.ChangedWhen, opt => opt.MapFrom(_ => DateTime.Now));
|
=> expression.ForMember(dest => dest.ChangedWhen, opt => opt.MapFrom(_ => DateTime.UtcNow));
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Converts a base64 data URL string to a byte array.
|
|
||||||
/// Handles data URLs in the format: "data:image/png;base64,iVBORw0KG..."
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="dataUrl">The base64 data URL string from Canvas.toDataURL()</param>
|
|
||||||
/// <returns>The decoded byte array, or null if the input is null or empty</returns>
|
|
||||||
public static byte[]? MapDataUrlToRequiredBytes(this string dataUrl)
|
|
||||||
{
|
|
||||||
// Remove data URL prefix (e.g., "data:image/png;base64,")
|
|
||||||
var base64Index = dataUrl.IndexOf(',', StringComparison.Ordinal);
|
|
||||||
if (base64Index == -1)
|
|
||||||
throw new ArgumentException("Invalid data URL format. Unable to extract base64 data.", nameof(dataUrl));
|
|
||||||
|
|
||||||
var base64Data = dataUrl[(base64Index + 1)..];
|
|
||||||
return Convert.FromBase64String(base64Data);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -6,6 +6,6 @@ namespace EnvelopeGenerator.Application.Common.Interfaces.Repositories;
|
|||||||
///
|
///
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Obsolete("Use IRepository")]
|
[Obsolete("Use IRepository")]
|
||||||
public interface IDocumentReceiverElementRepository : ICRUDRepository<DocReceiverElement, int>
|
public interface IDocumentReceiverElementRepository : ICRUDRepository<Signature, int>
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@@ -8,6 +8,6 @@ namespace EnvelopeGenerator.Application.Common.Interfaces.Services;
|
|||||||
///
|
///
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Obsolete("Use MediatR")]
|
[Obsolete("Use MediatR")]
|
||||||
public interface IDocumentReceiverElementService : IBasicCRUDService<DocReceiverElementDto, DocReceiverElement, int>
|
public interface IDocumentReceiverElementService : IBasicCRUDService<SignatureDto, Signature, int>
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@@ -1,37 +1,88 @@
|
|||||||
using EnvelopeGenerator.Application.Common.Dto;
|
using EnvelopeGenerator.Application.Common.Dto;
|
||||||
using EnvelopeGenerator.Application.Common.Dto.EnvelopeReceiver;
|
using EnvelopeGenerator.Application.Common.Dto.EnvelopeReceiver;
|
||||||
using EnvelopeGenerator.Application.Common.Extensions;
|
using EnvelopeGenerator.Application.Common.Extensions;
|
||||||
|
using EnvelopeGenerator.Application.Common.Notifications.RemoveSignature;
|
||||||
using EnvelopeGenerator.Domain.Constants;
|
using EnvelopeGenerator.Domain.Constants;
|
||||||
using MediatR;
|
using MediatR;
|
||||||
|
using System.Dynamic;
|
||||||
|
|
||||||
namespace EnvelopeGenerator.Application.Common.Notifications.DocSigned;
|
namespace EnvelopeGenerator.Application.Common.Notifications.DocSigned;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Notification raised when a document is signed by a receiver.
|
///
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Obsolete("This notification is deprecated. Use Signature.Commands.SignCommand instead.")]
|
/// <param name="Instant"></param>
|
||||||
public record DocSignedNotification : INotification, ISendMailNotification
|
/// <param name="Structured"></param>
|
||||||
|
public record PsPdfKitAnnotation(ExpandoObject Instant, IEnumerable<AnnotationCreateDto> Structured);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="Original"></param>
|
||||||
|
public record DocSignedNotification(EnvelopeReceiverDto Original) : EnvelopeReceiverDto(Original), INotification, ISendMailNotification
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The envelope receiver information.
|
///
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public required EnvelopeReceiverDto EnvelopeReceiver { get; init; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The PSPDFKit annotation data.
|
|
||||||
/// </summary>
|
|
||||||
[Obsolete("The PSPDFKit library is deprecated.")]
|
|
||||||
public PsPdfKitAnnotation? PsPdfKitAnnotation { get; init; }
|
public PsPdfKitAnnotation? PsPdfKitAnnotation { get; init; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the email template type.
|
///
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public EmailTemplateType TemplateType => EmailTemplateType.DocumentSigned;
|
public EmailTemplateType TemplateType => EmailTemplateType.DocumentSigned;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the email address of the receiver.
|
///
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string EmailAddress => EnvelopeReceiver.Receiver?.EmailAddress
|
public string EmailAddress => Receiver?.EmailAddress
|
||||||
?? throw new InvalidOperationException($"Receiver is null." +
|
?? throw new InvalidOperationException($"Receiver is null." +
|
||||||
$"DocSignedNotification:\n{this.ToJson(Format.Json.ForDiagnostics)}");
|
$"DocSignedNotification:\n{this.ToJson(Format.Json.ForDiagnostics)}");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
public static class DocSignedNotificationExtensions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Converts an <see cref="EnvelopeReceiverDto"/> to a <see cref="DocSignedNotification"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="dto">The DTO to convert.</param>
|
||||||
|
/// <param name="psPdfKitAnnotation"></param>
|
||||||
|
/// <returns>A new <see cref="DocSignedNotification"/> instance.</returns>
|
||||||
|
public static DocSignedNotification ToDocSignedNotification(this EnvelopeReceiverDto dto, PsPdfKitAnnotation psPdfKitAnnotation)
|
||||||
|
=> new(dto) { PsPdfKitAnnotation = psPdfKitAnnotation };
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="dtoTask"></param>
|
||||||
|
/// <param name="psPdfKitAnnotation"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static async Task<DocSignedNotification?> ToDocSignedNotification(this Task<EnvelopeReceiverDto?> dtoTask, PsPdfKitAnnotation? psPdfKitAnnotation)
|
||||||
|
=> await dtoTask is EnvelopeReceiverDto dto ? new(dto) { PsPdfKitAnnotation = psPdfKitAnnotation } : null;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="publisher"></param>
|
||||||
|
/// <param name="notification"></param>
|
||||||
|
/// <param name="cancel"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static async Task PublishSafely(this IPublisher publisher, DocSignedNotification notification, CancellationToken cancel = default)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await publisher.Publish(notification, cancel);
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
await publisher.Publish(new RemoveSignatureNotification()
|
||||||
|
{
|
||||||
|
EnvelopeId = notification.EnvelopeId,
|
||||||
|
ReceiverId = notification.ReceiverId
|
||||||
|
}, cancel);
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
using DigitalData.Core.Abstraction.Application.Repository;
|
using DigitalData.Core.Abstraction.Application.Repository;
|
||||||
using EnvelopeGenerator.Domain.Entities;
|
using EnvelopeGenerator.Domain.Entities;
|
||||||
using EnvelopeGenerator.Application.Common.Dto;
|
|
||||||
using MediatR;
|
using MediatR;
|
||||||
|
|
||||||
namespace EnvelopeGenerator.Application.Common.Notifications.DocSigned.Handlers;
|
namespace EnvelopeGenerator.Application.Common.Notifications.DocSigned.Handlers;
|
||||||
@@ -8,7 +7,6 @@ namespace EnvelopeGenerator.Application.Common.Notifications.DocSigned.Handlers;
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
///
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Obsolete("The PSPDFKit library is deprecated.")]
|
|
||||||
public class AnnotationHandler : INotificationHandler<DocSignedNotification>
|
public class AnnotationHandler : INotificationHandler<DocSignedNotification>
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
using EnvelopeGenerator.Application.DocStatus.Commands;
|
using EnvelopeGenerator.Application.DocStatus.Commands;
|
||||||
using EnvelopeGenerator.Application.Common.Dto;
|
|
||||||
using EnvelopeGenerator.Domain.Constants;
|
using EnvelopeGenerator.Domain.Constants;
|
||||||
using MediatR;
|
using MediatR;
|
||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
@@ -9,7 +8,6 @@ namespace EnvelopeGenerator.Application.Common.Notifications.DocSigned.Handlers;
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
///
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Obsolete("This notification is deprecated. Use Signature.Commands.SignCommand instead.")]
|
|
||||||
public class DocStatusHandler : INotificationHandler<DocSignedNotification>
|
public class DocStatusHandler : INotificationHandler<DocSignedNotification>
|
||||||
{
|
{
|
||||||
private const string BlankAnnotationJson = "{}";
|
private const string BlankAnnotationJson = "{}";
|
||||||
@@ -31,11 +29,10 @@ public class DocStatusHandler : INotificationHandler<DocSignedNotification>
|
|||||||
/// <param name="notification"></param>
|
/// <param name="notification"></param>
|
||||||
/// <param name="cancel"></param>
|
/// <param name="cancel"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
[Obsolete("This notification is deprecated. Use Signature.Commands.SignCommand instead.")]
|
|
||||||
public Task Handle(DocSignedNotification notification, CancellationToken cancel) => _sender.Send(new CreateDocStatusCommand()
|
public Task Handle(DocSignedNotification notification, CancellationToken cancel) => _sender.Send(new CreateDocStatusCommand()
|
||||||
{
|
{
|
||||||
EnvelopeId = notification.EnvelopeReceiver.EnvelopeId,
|
EnvelopeId = notification.EnvelopeId,
|
||||||
ReceiverId = notification.EnvelopeReceiver.ReceiverId,
|
ReceiverId = notification.ReceiverId,
|
||||||
Value = notification.PsPdfKitAnnotation is PsPdfKitAnnotation annot
|
Value = notification.PsPdfKitAnnotation is PsPdfKitAnnotation annot
|
||||||
? JsonSerializer.Serialize(annot.Instant, Format.Json.ForAnnotations)
|
? JsonSerializer.Serialize(annot.Instant, Format.Json.ForAnnotations)
|
||||||
: BlankAnnotationJson
|
: BlankAnnotationJson
|
||||||
|
|||||||
@@ -29,13 +29,13 @@ public class HistoryHandler : INotificationHandler<DocSignedNotification>
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public async Task Handle(DocSignedNotification notification, CancellationToken cancel)
|
public async Task Handle(DocSignedNotification notification, CancellationToken cancel)
|
||||||
{
|
{
|
||||||
if (notification.EnvelopeReceiver.Receiver is null)
|
if (notification.Receiver is null)
|
||||||
throw new InvalidOperationException($"Receiver information is missing in the notification. DocSignedNotification:\n {notification.ToJson(Format.Json.ForDiagnostics)}");
|
throw new InvalidOperationException($"Receiver information is missing in the notification. DocSignedNotification:\n {notification.ToJson(Format.Json.ForDiagnostics)}");
|
||||||
|
|
||||||
await _sender.Send(new CreateHistoryCommand()
|
await _sender.Send(new CreateHistoryCommand()
|
||||||
{
|
{
|
||||||
EnvelopeId = notification.EnvelopeReceiver.EnvelopeId,
|
EnvelopeId = notification.EnvelopeId,
|
||||||
UserReference = notification.EnvelopeReceiver.Receiver.EmailAddress,
|
UserReference = notification.Receiver.EmailAddress,
|
||||||
Status = EnvelopeStatus.DocumentSigned,
|
Status = EnvelopeStatus.DocumentSigned,
|
||||||
}, cancel);
|
}, cancel);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ public class SendSignedMailHandler : SendMailHandler<DocSignedNotification>
|
|||||||
protected override void ConfigureEmailOut(DocSignedNotification notification, EmailOut emailOut)
|
protected override void ConfigureEmailOut(DocSignedNotification notification, EmailOut emailOut)
|
||||||
{
|
{
|
||||||
emailOut.ReferenceString = notification.EmailAddress;
|
emailOut.ReferenceString = notification.EmailAddress;
|
||||||
emailOut.ReferenceId = notification.EnvelopeReceiver.ReceiverId;
|
emailOut.ReferenceId = notification.ReceiverId;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -42,11 +42,11 @@ public class SendSignedMailHandler : SendMailHandler<DocSignedNotification>
|
|||||||
{
|
{
|
||||||
var placeHolders = new Dictionary<string, string>()
|
var placeHolders = new Dictionary<string, string>()
|
||||||
{
|
{
|
||||||
{ "[NAME_RECEIVER]", notification.EnvelopeReceiver.Name ?? string.Empty },
|
{ "[NAME_RECEIVER]", notification.Name ?? string.Empty },
|
||||||
{ "[DOCUMENT_TITLE]", notification.EnvelopeReceiver.Envelope?.Title ?? string.Empty },
|
{ "[DOCUMENT_TITLE]", notification.Envelope?.Title ?? string.Empty },
|
||||||
};
|
};
|
||||||
|
|
||||||
if (notification.EnvelopeReceiver.Envelope.IsReadAndConfirm())
|
if (notification.Envelope.IsReadAndConfirm())
|
||||||
{
|
{
|
||||||
placeHolders["[SIGNATURE_TYPE]"] = "Lesen und bestätigen";
|
placeHolders["[SIGNATURE_TYPE]"] = "Lesen und bestätigen";
|
||||||
placeHolders["[DOCUMENT_PROCESS]"] = string.Empty;
|
placeHolders["[DOCUMENT_PROCESS]"] = string.Empty;
|
||||||
|
|||||||
@@ -113,7 +113,7 @@ public abstract class SendMailHandler<TNotification> : INotificationHandler<TNot
|
|||||||
EmailAddress = notification.EmailAddress,
|
EmailAddress = notification.EmailAddress,
|
||||||
EmailBody = temp.Body,
|
EmailBody = temp.Body,
|
||||||
EmailSubj = temp.Subject,
|
EmailSubj = temp.Subject,
|
||||||
AddedWhen = DateTime.Now,
|
AddedWhen = DateTime.UtcNow,
|
||||||
AddedWho = DispatcherParams.AddedWho,
|
AddedWho = DispatcherParams.AddedWho,
|
||||||
SendingProfile = DispatcherParams.SendingProfile,
|
SendingProfile = DispatcherParams.SendingProfile,
|
||||||
ReminderTypeId = DispatcherParams.ReminderTypeId,
|
ReminderTypeId = DispatcherParams.ReminderTypeId,
|
||||||
|
|||||||
@@ -14,4 +14,10 @@ public record EnvelopeQueryBase
|
|||||||
/// Die universell eindeutige Kennung des Umschlags.
|
/// Die universell eindeutige Kennung des Umschlags.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public virtual string? Uuid { get; set; }
|
public virtual string? Uuid { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Wenn gesetzt, wird das DocResult-Feld in der Abfrage einbezogen.
|
||||||
|
/// Standardmäßig wird DocResult nicht geladen, um große Binärdaten zu vermeiden.
|
||||||
|
/// </summary>
|
||||||
|
public bool IncludeDocResult { get; set; } = false;
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,69 @@
|
|||||||
|
using AutoMapper;
|
||||||
|
using DigitalData.Core.Abstraction.Application.Repository;
|
||||||
|
using DigitalData.Core.Exceptions;
|
||||||
|
using EnvelopeGenerator.Application.Common;
|
||||||
|
using EnvelopeGenerator.Application.Common.Dto;
|
||||||
|
using EnvelopeGenerator.Domain.Entities;
|
||||||
|
using MediatR;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.Extensions.Caching.Distributed;
|
||||||
|
using Microsoft.Extensions.Caching.Memory;
|
||||||
|
|
||||||
|
namespace EnvelopeGenerator.Application.Configuration.Queries;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
public record ReadDefaultConfigQuery : IRequest<ConfigDto>
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
public bool EnforceSingleResult { get; init; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
public class ReadDefaultConfigQueryHandler : IRequestHandler<ReadDefaultConfigQuery, ConfigDto>
|
||||||
|
{
|
||||||
|
private readonly IRepository<Config> _repo;
|
||||||
|
|
||||||
|
private readonly IMapper _mapper;
|
||||||
|
|
||||||
|
private readonly IMemoryCache _cache;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="repo"></param>
|
||||||
|
/// <param name="mapper"></param>
|
||||||
|
/// <param name="cache"></param>
|
||||||
|
public ReadDefaultConfigQueryHandler(IRepository<Config> repo, IMapper mapper, IMemoryCache cache)
|
||||||
|
{
|
||||||
|
_repo = repo;
|
||||||
|
_mapper = mapper;
|
||||||
|
_cache = cache;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="request"></param>
|
||||||
|
/// <param name="cancel"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
/// <exception cref="InvalidOperationException"></exception>
|
||||||
|
public async Task<ConfigDto> Handle(ReadDefaultConfigQuery request, CancellationToken cancel)
|
||||||
|
{
|
||||||
|
var config = await _cache.GetOrCreateAsync(CacheKey.DefaultConfig, entry =>
|
||||||
|
{
|
||||||
|
entry.AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(30);
|
||||||
|
return request.EnforceSingleResult
|
||||||
|
? _repo.Query.SingleOrDefaultAsync(cancel)
|
||||||
|
: _repo.Query.FirstOrDefaultAsync(cancel)
|
||||||
|
?? throw new NotFoundException("Default configuration could not be found. Ensure at least one configuration record exists in the database.");
|
||||||
|
});
|
||||||
|
|
||||||
|
return _mapper.Map<ConfigDto>(config);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -7,9 +7,6 @@ using Microsoft.Extensions.DependencyInjection;
|
|||||||
using Microsoft.Extensions.DependencyInjection.Extensions;
|
using Microsoft.Extensions.DependencyInjection.Extensions;
|
||||||
using QRCoder;
|
using QRCoder;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using MediatR;
|
|
||||||
using EnvelopeGenerator.Application.DocReceiverElements.Commands;
|
|
||||||
using EnvelopeGenerator.Application.DocReceiverElements.Behaviors;
|
|
||||||
|
|
||||||
namespace EnvelopeGenerator.Application;
|
namespace EnvelopeGenerator.Application;
|
||||||
|
|
||||||
@@ -59,22 +56,6 @@ public static class DependencyInjection
|
|||||||
services.AddMediatR(cfg =>
|
services.AddMediatR(cfg =>
|
||||||
{
|
{
|
||||||
cfg.RegisterServicesFromAssembly(Assembly.GetExecutingAssembly());
|
cfg.RegisterServicesFromAssembly(Assembly.GetExecutingAssembly());
|
||||||
|
|
||||||
// Register SignCommand pipeline behaviors in execution order
|
|
||||||
// 0. EnvelopeReceiverResolutionBehavior - Resolves EnvelopeReceiver from query parameters (executes FIRST)
|
|
||||||
cfg.AddBehavior<IPipelineBehavior<SigningCommand, Unit>, EnvelopeReceiverResolutionBehavior>();
|
|
||||||
|
|
||||||
// 1. AnnotationBehavior - Saves annotations (executes second)
|
|
||||||
cfg.AddBehavior<IPipelineBehavior<SigningCommand, Unit>, AnnotationBehavior>();
|
|
||||||
|
|
||||||
// 2. DocStatusBehavior - Creates document status (executes third)
|
|
||||||
cfg.AddBehavior<IPipelineBehavior<SigningCommand, Unit>, DocStatusBehavior>();
|
|
||||||
|
|
||||||
// 3. HistoryBehavior - Records history (executes fourth)
|
|
||||||
cfg.AddBehavior<IPipelineBehavior<SigningCommand, Unit>, HistoryBehavior>();
|
|
||||||
|
|
||||||
// 4. SendSignedMailBehavior - Sends notification email (executes LAST, only if all previous succeed)
|
|
||||||
cfg.AddBehavior<IPipelineBehavior<SigningCommand, Unit>, SendSignedMailBehavior>();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return services;
|
return services;
|
||||||
|
|||||||
@@ -1,50 +0,0 @@
|
|||||||
using DigitalData.Core.Abstraction.Application.Repository;
|
|
||||||
using DigitalData.Core.Exceptions;
|
|
||||||
using EnvelopeGenerator.Application.Common.Dto;
|
|
||||||
using EnvelopeGenerator.Application.DocReceiverElements.Commands;
|
|
||||||
using EnvelopeGenerator.Domain.Entities;
|
|
||||||
using MediatR;
|
|
||||||
|
|
||||||
namespace EnvelopeGenerator.Application.DocReceiverElements.Behaviors;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Pipeline behavior that saves annotations.
|
|
||||||
/// Executes first in the signing process.
|
|
||||||
/// </summary>
|
|
||||||
[Obsolete("The PSPDFKit library is deprecated.")]
|
|
||||||
public class AnnotationBehavior : IPipelineBehavior<SigningCommand, Unit>
|
|
||||||
{
|
|
||||||
private readonly IRepository<ElementAnnotation> _repo;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Initializes a new instance of the <see cref="AnnotationBehavior"/> class.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="repository"></param>
|
|
||||||
public AnnotationBehavior(IRepository<ElementAnnotation> repository)
|
|
||||||
{
|
|
||||||
_repo = repository;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="request"></param>
|
|
||||||
/// <param name="next"></param>
|
|
||||||
/// <param name="cancel"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
public async Task<Unit> Handle(SigningCommand request, RequestHandlerDelegate<Unit> next, CancellationToken cancel)
|
|
||||||
{
|
|
||||||
if(request.ReceiverAppType != ReceiverAppType.LegacyWeb)
|
|
||||||
if(request.PsPdfKitAnnotation is null)
|
|
||||||
return await next(cancel);
|
|
||||||
else
|
|
||||||
throw new BadRequestException("PsPdfKit Annotation are only supported for the legacy web receiver type.");
|
|
||||||
|
|
||||||
if (request.PsPdfKitAnnotation is PsPdfKitAnnotation annot)
|
|
||||||
await _repo.CreateAsync(annot.Structured, cancel);
|
|
||||||
else
|
|
||||||
throw new BadRequestException("Annotation data is missing or invalid.");
|
|
||||||
|
|
||||||
return await next(cancel);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,50 +0,0 @@
|
|||||||
using EnvelopeGenerator.Application.Common.Dto;
|
|
||||||
using EnvelopeGenerator.Application.DocStatus.Commands;
|
|
||||||
using EnvelopeGenerator.Application.DocReceiverElements.Commands;
|
|
||||||
using EnvelopeGenerator.Domain.Constants;
|
|
||||||
using MediatR;
|
|
||||||
using System.Text.Json;
|
|
||||||
|
|
||||||
namespace EnvelopeGenerator.Application.DocReceiverElements.Behaviors;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Pipeline behavior that creates document status.
|
|
||||||
/// Executes second in the signing process.
|
|
||||||
/// </summary>
|
|
||||||
public class DocStatusBehavior : IPipelineBehavior<SigningCommand, Unit>
|
|
||||||
{
|
|
||||||
private const string BlankAnnotationJson = "{}";
|
|
||||||
|
|
||||||
private readonly ISender _sender;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="sender"></param>
|
|
||||||
public DocStatusBehavior(ISender sender)
|
|
||||||
{
|
|
||||||
_sender = sender;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="request"></param>
|
|
||||||
/// <param name="next"></param>
|
|
||||||
/// <param name="cancellationToken"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
[Obsolete("This notification is deprecated. Use Signature.Commands.SignCommand instead.")]
|
|
||||||
public async Task<Unit> Handle(SigningCommand request, RequestHandlerDelegate<Unit> next, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
await _sender.Send(new CreateDocStatusCommand()
|
|
||||||
{
|
|
||||||
EnvelopeId = request.EnvelopeReceiver.EnvelopeId,
|
|
||||||
ReceiverId = request.EnvelopeReceiver.ReceiverId,
|
|
||||||
Value = request.PsPdfKitAnnotation is PsPdfKitAnnotation annot
|
|
||||||
? JsonSerializer.Serialize(annot.Instant, Format.Json.ForAnnotations)
|
|
||||||
: BlankAnnotationJson
|
|
||||||
}, cancellationToken);
|
|
||||||
|
|
||||||
return await next(cancellationToken);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,54 +0,0 @@
|
|||||||
using AutoMapper;
|
|
||||||
using DigitalData.Core.Abstraction.Application.Repository;
|
|
||||||
using DigitalData.Core.Exceptions;
|
|
||||||
using EnvelopeGenerator.Application.Common.Dto.EnvelopeReceiver;
|
|
||||||
using EnvelopeGenerator.Application.Common.Extensions;
|
|
||||||
using EnvelopeGenerator.Application.DocReceiverElements.Commands;
|
|
||||||
using EnvelopeGenerator.Domain.Entities;
|
|
||||||
using MediatR;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
|
|
||||||
namespace EnvelopeGenerator.Application.DocReceiverElements.Behaviors;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Pipeline behavior that resolves and validates EnvelopeReceiver.
|
|
||||||
/// Executes FIRST in the signing process - before all other behaviors.
|
|
||||||
/// If EnvelopeReceiver is not provided, it queries the database using EnvelopeReceiverQueryBase parameters.
|
|
||||||
/// </summary>
|
|
||||||
public class EnvelopeReceiverResolutionBehavior : IPipelineBehavior<SigningCommand, Unit>
|
|
||||||
{
|
|
||||||
private readonly IRepository<EnvelopeReceiver> _erRepo;
|
|
||||||
private readonly IMapper _mapper;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="erRepo"></param>
|
|
||||||
/// <param name="mapper"></param>
|
|
||||||
public EnvelopeReceiverResolutionBehavior(IRepository<EnvelopeReceiver> erRepo, IMapper mapper)
|
|
||||||
{
|
|
||||||
_erRepo = erRepo;
|
|
||||||
_mapper = mapper;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="request"></param>
|
|
||||||
/// <param name="next"></param>
|
|
||||||
/// <param name="cancellationToken"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
public async Task<Unit> Handle(SigningCommand request, RequestHandlerDelegate<Unit> next, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
// If EnvelopeReceiver is not provided, query it from database
|
|
||||||
if (request.EnvelopeReceiver is null)
|
|
||||||
{
|
|
||||||
var er = await _erRepo.Query.Where(request, notnull: true).SingleOrDefaultAsync(cancellationToken)
|
|
||||||
?? throw new NotFoundException("EnvelopeReceiver not found");
|
|
||||||
|
|
||||||
request.SetEnvelopeReceiver(_mapper.Map<EnvelopeReceiverDto>(er));
|
|
||||||
}
|
|
||||||
|
|
||||||
return await next(cancellationToken);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,47 +0,0 @@
|
|||||||
using EnvelopeGenerator.Application.Common.Extensions;
|
|
||||||
using EnvelopeGenerator.Application.Histories.Commands;
|
|
||||||
using EnvelopeGenerator.Application.DocReceiverElements.Commands;
|
|
||||||
using EnvelopeGenerator.Domain.Constants;
|
|
||||||
using MediatR;
|
|
||||||
|
|
||||||
namespace EnvelopeGenerator.Application.DocReceiverElements.Behaviors;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Pipeline behavior that records history.
|
|
||||||
/// Executes third in the signing process.
|
|
||||||
/// </summary>
|
|
||||||
public class HistoryBehavior : IPipelineBehavior<SigningCommand, Unit>
|
|
||||||
{
|
|
||||||
private readonly ISender _sender;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="sender"></param>
|
|
||||||
public HistoryBehavior(ISender sender)
|
|
||||||
{
|
|
||||||
_sender = sender;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="request"></param>
|
|
||||||
/// <param name="next"></param>
|
|
||||||
/// <param name="cancellationToken"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
public async Task<Unit> Handle(SigningCommand request, RequestHandlerDelegate<Unit> next, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
if (request.EnvelopeReceiver.Receiver is null)
|
|
||||||
throw new InvalidOperationException($"Receiver information is missing in the notification. SignCommand:\n {request.ToJson(Format.Json.ForDiagnostics)}");
|
|
||||||
|
|
||||||
await _sender.Send(new CreateHistoryCommand()
|
|
||||||
{
|
|
||||||
EnvelopeId = request.EnvelopeReceiver.EnvelopeId,
|
|
||||||
UserReference = request.EnvelopeReceiver.Receiver.EmailAddress,
|
|
||||||
Status = EnvelopeStatus.DocumentSigned,
|
|
||||||
}, cancellationToken);
|
|
||||||
|
|
||||||
return await next(cancellationToken);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,70 +0,0 @@
|
|||||||
using AutoMapper;
|
|
||||||
using DigitalData.Core.Abstraction.Application.Repository;
|
|
||||||
using DigitalData.Core.Exceptions;
|
|
||||||
using EnvelopeGenerator.Application.Common.Dto;
|
|
||||||
using EnvelopeGenerator.Application.DocReceiverElements.Commands;
|
|
||||||
using EnvelopeGenerator.Domain.Entities;
|
|
||||||
using MediatR;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
|
|
||||||
namespace EnvelopeGenerator.Application.DocReceiverElements.Behaviors;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Pipeline behavior that creates document status.
|
|
||||||
/// Executes second in the signing process.
|
|
||||||
/// </summary>
|
|
||||||
public class SaveSignatureBehavior : IPipelineBehavior<SigningCommand, Unit>
|
|
||||||
{
|
|
||||||
private readonly ISender _sender;
|
|
||||||
|
|
||||||
private readonly IRepository<DocReceiverElement> _elementRepo;
|
|
||||||
|
|
||||||
private readonly IMapper _mapper;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="sender"></param>
|
|
||||||
/// <param name="elementRepo"></param>
|
|
||||||
/// <param name="mapper"></param>
|
|
||||||
public SaveSignatureBehavior(ISender sender, IRepository<DocReceiverElement> elementRepo, IMapper mapper)
|
|
||||||
{
|
|
||||||
_sender = sender;
|
|
||||||
_elementRepo = elementRepo;
|
|
||||||
_elementRepo = elementRepo;
|
|
||||||
_mapper = mapper;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="request"></param>
|
|
||||||
/// <param name="next"></param>
|
|
||||||
/// <param name="cancel"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
public async Task<Unit> Handle(SigningCommand request, RequestHandlerDelegate<Unit> next, CancellationToken cancel)
|
|
||||||
{
|
|
||||||
if (request.ReceiverAppType == ReceiverAppType.LegacyWeb)
|
|
||||||
return await next(cancel);
|
|
||||||
else if(request.Signatures is not IEnumerable<Signature> signatures)
|
|
||||||
throw new BadRequestException($"Signatures are required for saving signature behavior.");
|
|
||||||
|
|
||||||
var elements = await _elementRepo
|
|
||||||
.Where(e => e.Document.EnvelopeId == request.Envelope.Id)
|
|
||||||
.Where(e => e.ReceiverId == request.Receiver.Id)
|
|
||||||
.ToListAsync(cancel);
|
|
||||||
|
|
||||||
foreach (var element in elements)
|
|
||||||
{
|
|
||||||
var signatures = request.Signatures.Where(s => s.Id == element.Id).ToList();
|
|
||||||
if(signatures.Count == 0)
|
|
||||||
throw new BadRequestException("No signature found for element with id {element.Id}.");
|
|
||||||
else if(signatures.Count > 1)
|
|
||||||
throw new BadRequestException("Multiple signatures found for element with id {element.Id}.");
|
|
||||||
|
|
||||||
await _elementRepo.UpdateAsync(signatures.First(), e => e.Id == element.Id, cancel);
|
|
||||||
}
|
|
||||||
|
|
||||||
return await next(cancel);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,122 +0,0 @@
|
|||||||
using DigitalData.Core.Abstraction.Application.Repository;
|
|
||||||
using DigitalData.EmailProfilerDispatcher.Abstraction.Entities;
|
|
||||||
using EnvelopeGenerator.Application.Common.Configurations;
|
|
||||||
using EnvelopeGenerator.Application.Common.Extensions;
|
|
||||||
using EnvelopeGenerator.Application.DocReceiverElements.Commands;
|
|
||||||
using EnvelopeGenerator.Domain.Constants;
|
|
||||||
using EnvelopeGenerator.Domain.Entities;
|
|
||||||
using EnvelopeGenerator.Domain.Interfaces;
|
|
||||||
using MediatR;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
using Microsoft.Extensions.Options;
|
|
||||||
using Newtonsoft.Json;
|
|
||||||
|
|
||||||
namespace EnvelopeGenerator.Application.DocReceiverElements.Behaviors;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Pipeline behavior that sends signed mail notification.
|
|
||||||
/// Executes LAST in the signing process - only if all previous behaviors succeed.
|
|
||||||
/// </summary>
|
|
||||||
public class SendSignedMailBehavior : IPipelineBehavior<SigningCommand, Unit>
|
|
||||||
{
|
|
||||||
private readonly IRepository<EmailTemplate> _tempRepo;
|
|
||||||
private readonly IRepository<EmailOut> _emailOutRepo;
|
|
||||||
private readonly MailParams _mailParams;
|
|
||||||
private readonly DispatcherParams _dispatcherParams;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="tempRepo"></param>
|
|
||||||
/// <param name="emailOutRepo"></param>
|
|
||||||
/// <param name="mailParamsOptions"></param>
|
|
||||||
/// <param name="dispatcherParamsOptions"></param>
|
|
||||||
public SendSignedMailBehavior(
|
|
||||||
IRepository<EmailTemplate> tempRepo,
|
|
||||||
IRepository<EmailOut> emailOutRepo,
|
|
||||||
IOptions<MailParams> mailParamsOptions,
|
|
||||||
IOptions<DispatcherParams> dispatcherParamsOptions)
|
|
||||||
{
|
|
||||||
_tempRepo = tempRepo;
|
|
||||||
_emailOutRepo = emailOutRepo;
|
|
||||||
_mailParams = mailParamsOptions.Value;
|
|
||||||
_dispatcherParams = dispatcherParamsOptions.Value;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="request"></param>
|
|
||||||
/// <param name="next"></param>
|
|
||||||
/// <param name="cancellationToken"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
public async Task<Unit> Handle(SigningCommand request, RequestHandlerDelegate<Unit> next, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
var placeHolders = CreatePlaceHolders(request);
|
|
||||||
|
|
||||||
var temp = await _tempRepo
|
|
||||||
.Where(x => x.Name == EmailTemplateType.DocumentSigned.ToString())
|
|
||||||
.SingleOrDefaultAsync(cancellationToken)
|
|
||||||
?? throw new InvalidOperationException($"Email template not found. SignCommand:\n {request.ToJson(Format.Json.ForDiagnostics)}");
|
|
||||||
|
|
||||||
temp.Subject = ReplacePlaceHolders(temp.Subject, placeHolders, _mailParams.Placeholders);
|
|
||||||
temp.Body = ReplacePlaceHolders(temp.Body, placeHolders, _mailParams.Placeholders);
|
|
||||||
|
|
||||||
var emailOut = new EmailOut
|
|
||||||
{
|
|
||||||
EmailAddress = request.EnvelopeReceiver.Receiver!.EmailAddress,
|
|
||||||
EmailBody = temp.Body,
|
|
||||||
EmailSubj = temp.Subject,
|
|
||||||
AddedWhen = DateTime.Now,
|
|
||||||
AddedWho = _dispatcherParams.AddedWho,
|
|
||||||
SendingProfile = _dispatcherParams.SendingProfile,
|
|
||||||
ReminderTypeId = _dispatcherParams.ReminderTypeId,
|
|
||||||
EmailAttmt1 = _dispatcherParams.EmailAttmt1,
|
|
||||||
WfId = (int)EnvelopeStatus.MessageConfirmationSent,
|
|
||||||
ReferenceString = request.EnvelopeReceiver.Receiver!.EmailAddress,
|
|
||||||
ReferenceId = request.EnvelopeReceiver.ReceiverId
|
|
||||||
};
|
|
||||||
|
|
||||||
await _emailOutRepo.CreateAsync(emailOut, cancellationToken);
|
|
||||||
|
|
||||||
return await next(cancellationToken);
|
|
||||||
}
|
|
||||||
|
|
||||||
private Dictionary<string, string> CreatePlaceHolders(SigningCommand request)
|
|
||||||
{
|
|
||||||
var placeHolders = new Dictionary<string, string>()
|
|
||||||
{
|
|
||||||
{ "[NAME_RECEIVER]", request.EnvelopeReceiver.Name ?? string.Empty },
|
|
||||||
{ "[DOCUMENT_TITLE]", request.EnvelopeReceiver.Envelope?.Title ?? string.Empty },
|
|
||||||
};
|
|
||||||
|
|
||||||
if (request.EnvelopeReceiver.Envelope.IsReadAndConfirm())
|
|
||||||
{
|
|
||||||
placeHolders["[SIGNATURE_TYPE]"] = "Lesen und bestätigen";
|
|
||||||
placeHolders["[DOCUMENT_PROCESS]"] = string.Empty;
|
|
||||||
placeHolders["[FINAL_STATUS]"] = "Lesebestätigung";
|
|
||||||
placeHolders["[FINAL_ACTION]"] = "Empfänger bestätigt";
|
|
||||||
placeHolders["[REJECTED_BY_OTHERS]"] = "anderen Empfänger abgelehnt!";
|
|
||||||
placeHolders["[RECEIVER_ACTION]"] = "bestätigt";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
placeHolders["[SIGNATURE_TYPE]"] = "Signieren";
|
|
||||||
placeHolders["[DOCUMENT_PROCESS]"] = " und elektronisch unterschreiben";
|
|
||||||
placeHolders["[FINAL_STATUS]"] = "Signatur";
|
|
||||||
placeHolders["[FINAL_ACTION]"] = "Vertragspartner unterzeichnet";
|
|
||||||
placeHolders["[REJECTED_BY_OTHERS]"] = "anderen Vertragspartner abgelehnt! Ihre notwendige Unterzeichnung wurde verworfen.";
|
|
||||||
placeHolders["[RECEIVER_ACTION]"] = "unterschrieben";
|
|
||||||
}
|
|
||||||
|
|
||||||
return placeHolders;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static string ReplacePlaceHolders(string text, params Dictionary<string, string>[] placeHoldersList)
|
|
||||||
{
|
|
||||||
foreach (var placeHolders in placeHoldersList)
|
|
||||||
foreach (var ph in placeHolders)
|
|
||||||
text = text.Replace(ph.Key, ph.Value);
|
|
||||||
return text;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,78 +0,0 @@
|
|||||||
using MediatR;
|
|
||||||
using EnvelopeGenerator.Application.Common.Dto;
|
|
||||||
using EnvelopeGenerator.Application.Common.Dto.EnvelopeReceiver;
|
|
||||||
using EnvelopeGenerator.Application.Common.Query;
|
|
||||||
|
|
||||||
namespace EnvelopeGenerator.Application.DocReceiverElements.Commands;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Command to sign a document by a receiver.
|
|
||||||
/// </summary>
|
|
||||||
public record SigningCommand : EnvelopeReceiverQueryBase, IRequest
|
|
||||||
{
|
|
||||||
private EnvelopeReceiverDto? _envelopeReceiver;
|
|
||||||
|
|
||||||
internal void SetEnvelopeReceiver(EnvelopeReceiverDto envelopeReceiver)
|
|
||||||
{
|
|
||||||
_envelopeReceiver = envelopeReceiver;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The envelope receiver information.
|
|
||||||
/// </summary>
|
|
||||||
public EnvelopeReceiverDto EnvelopeReceiver
|
|
||||||
{
|
|
||||||
get => _envelopeReceiver!;
|
|
||||||
init => _envelopeReceiver = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The PSPDFKit annotation data.
|
|
||||||
/// </summary>
|
|
||||||
[Obsolete("This notification is deprecated. Use Signature.Commands.SignCommand instead.")]
|
|
||||||
public PsPdfKitAnnotation? PsPdfKitAnnotation { get; init; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public IEnumerable<Signature>? Signatures { get; init; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public ReceiverAppType ReceiverAppType { get; init; } = ReceiverAppType.ReceiverUI;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Handles the sign command. All work is done by pipeline behaviors.
|
|
||||||
/// This handler is intentionally empty - behaviors handle all the processing.
|
|
||||||
/// </summary>
|
|
||||||
public class SignCommandHandler : IRequestHandler<SigningCommand>
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Executes the signing command. Pipeline behaviors handle all processing.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="request"></param>
|
|
||||||
/// <param name="cancellationToken"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
public Task Handle(SigningCommand request, CancellationToken cancellationToken = default)
|
|
||||||
{
|
|
||||||
return Task.CompletedTask;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public enum ReceiverAppType
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
ReceiverUI = 0,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
LegacyWeb = 1,
|
|
||||||
}
|
|
||||||
@@ -1,66 +0,0 @@
|
|||||||
using AutoMapper;
|
|
||||||
using EnvelopeGenerator.Application.Common.Dto;
|
|
||||||
using EnvelopeGenerator.Application.Common.Query;
|
|
||||||
using EnvelopeGenerator.Domain.Entities;
|
|
||||||
using MediatR;
|
|
||||||
using EnvelopeGenerator.Application.Common.Extensions;
|
|
||||||
using DigitalData.Core.Abstraction.Application.Repository;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
|
|
||||||
namespace EnvelopeGenerator.Application.DocReceiverElements.Queries;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public record ReadDocReceiverElementQuery : EnvelopeReceiverQueryBase, IRequest<IEnumerable<DocReceiverElementDto>>
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public class ReadDocReceiverElementQueryHandler : IRequestHandler<ReadDocReceiverElementQuery, IEnumerable<DocReceiverElementDto>>
|
|
||||||
{
|
|
||||||
private readonly IRepository<DocReceiverElement> _repository;
|
|
||||||
|
|
||||||
private readonly IMapper _mapper;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="repository"></param>
|
|
||||||
/// <param name="mapper"></param>
|
|
||||||
public ReadDocReceiverElementQueryHandler(IRepository<DocReceiverElement> repository, IMapper mapper)
|
|
||||||
{
|
|
||||||
_repository = repository;
|
|
||||||
_mapper = mapper;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="request"></param>
|
|
||||||
/// <param name="cancellationToken"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
/// <exception cref="NotImplementedException"></exception>
|
|
||||||
public async Task<IEnumerable<DocReceiverElementDto>> Handle(ReadDocReceiverElementQuery request, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
var q = _repository.Query;
|
|
||||||
|
|
||||||
if(request.Envelope.Id is int envelopeId)
|
|
||||||
q = q.Where(e => e.Document.EnvelopeId == envelopeId);
|
|
||||||
|
|
||||||
if (request.Envelope.Uuid is string envelopeUuid)
|
|
||||||
q = q.Where(e => e.Document.Envelope.Uuid == envelopeUuid);
|
|
||||||
|
|
||||||
if (request.Receiver.Id is int receiverId)
|
|
||||||
q = q.Where(e => e.ReceiverId == receiverId);
|
|
||||||
|
|
||||||
if (request.Receiver.Signature is string signature)
|
|
||||||
q = q.Where(e => e.Receiver.Signature == signature);
|
|
||||||
|
|
||||||
var elements = await q.ToListAsync(cancellationToken);
|
|
||||||
|
|
||||||
return _mapper.Map<IEnumerable<DocReceiverElementDto>>(elements);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -27,7 +27,7 @@ public class MappingProfile : Profile
|
|||||||
CreateMap<UpdateDocStatusCommand, DocumentStatus>()
|
CreateMap<UpdateDocStatusCommand, DocumentStatus>()
|
||||||
.ForMember(dest => dest.Envelope, opt => opt.Ignore())
|
.ForMember(dest => dest.Envelope, opt => opt.Ignore())
|
||||||
.ForMember(dest => dest.Receiver, opt => opt.Ignore())
|
.ForMember(dest => dest.Receiver, opt => opt.Ignore())
|
||||||
.ForMember(dest => dest.StatusChangedWhen, opt => opt.MapFrom(src => DateTime.Now))
|
.ForMember(dest => dest.StatusChangedWhen, opt => opt.MapFrom(src => DateTime.UtcNow))
|
||||||
.MapChangedWhen();
|
.MapChangedWhen();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -53,17 +53,14 @@ public class ReadDocumentQueryHandler : IRequestHandler<ReadDocumentQuery, Docum
|
|||||||
/// </exception>
|
/// </exception>
|
||||||
public async Task<DocumentDto> Handle(ReadDocumentQuery query, CancellationToken cancel)
|
public async Task<DocumentDto> Handle(ReadDocumentQuery query, CancellationToken cancel)
|
||||||
{
|
{
|
||||||
var docQuery = _repo.Query.Include(doc => doc.Elements).ThenInclude(e => e.Annotations);
|
|
||||||
|
|
||||||
if (query.Id is not null)
|
if (query.Id is not null)
|
||||||
{
|
{
|
||||||
var doc = await docQuery.Where(d => d.Id == query.Id).FirstOrDefaultAsync(cancel);
|
var doc = await _repo.Query.Where(d => d.Id == query.Id).FirstOrDefaultAsync(cancel);
|
||||||
|
|
||||||
return _mapper.Map<DocumentDto>(doc);
|
return _mapper.Map<DocumentDto>(doc);
|
||||||
}
|
}
|
||||||
else if (query.EnvelopeId is not null)
|
else if (query.EnvelopeId is not null)
|
||||||
{
|
{
|
||||||
var doc = await docQuery.Where(d => d.EnvelopeId == query.EnvelopeId).FirstOrDefaultAsync(cancel);
|
var doc = await _repo.Query.Where(d => d.EnvelopeId == query.EnvelopeId).FirstOrDefaultAsync(cancel);
|
||||||
return _mapper.Map<DocumentDto>(doc);
|
return _mapper.Map<DocumentDto>(doc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -41,7 +41,7 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup Condition="'$(TargetFramework)' == 'net9.0'">
|
<ItemGroup Condition="'$(TargetFramework)' == 'net9.0'">
|
||||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="9.0.5" />
|
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="9.0.6" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
@@ -81,6 +81,7 @@
|
|||||||
<ItemGroup Condition="'$(TargetFramework)' == 'net7.0'">
|
<ItemGroup Condition="'$(TargetFramework)' == 'net7.0'">
|
||||||
<PackageReference Include="AutoMapper" Version="13.0.1" />
|
<PackageReference Include="AutoMapper" Version="13.0.1" />
|
||||||
<PackageReference Include="Microsoft.Data.SqlClient" Version="5.2.2" />
|
<PackageReference Include="Microsoft.Data.SqlClient" Version="5.2.2" />
|
||||||
|
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="7.0.20" />
|
||||||
<PackageReference Include="CommandDotNet">
|
<PackageReference Include="CommandDotNet">
|
||||||
<Version>7.0.5</Version>
|
<Version>7.0.5</Version>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
@@ -88,6 +89,7 @@
|
|||||||
|
|
||||||
<ItemGroup Condition="'$(TargetFramework)' == 'net8.0'">
|
<ItemGroup Condition="'$(TargetFramework)' == 'net8.0'">
|
||||||
<PackageReference Include="AutoMapper" Version="14.0.0" />
|
<PackageReference Include="AutoMapper" Version="14.0.0" />
|
||||||
|
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="8.0.17" />
|
||||||
<PackageReference Include="CommandDotNet">
|
<PackageReference Include="CommandDotNet">
|
||||||
<Version>8.1.1</Version>
|
<Version>8.1.1</Version>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
@@ -95,6 +97,7 @@
|
|||||||
|
|
||||||
<ItemGroup Condition="'$(TargetFramework)' == 'net9.0'">
|
<ItemGroup Condition="'$(TargetFramework)' == 'net9.0'">
|
||||||
<PackageReference Include="AutoMapper" Version="14.0.0" />
|
<PackageReference Include="AutoMapper" Version="14.0.0" />
|
||||||
|
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="9.0.6" />
|
||||||
<PackageReference Include="CommandDotNet">
|
<PackageReference Include="CommandDotNet">
|
||||||
<Version>8.1.1</Version>
|
<Version>8.1.1</Version>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ public record CreateEnvelopeReceiverCommand : CreateEnvelopeCommand, IRequest<Cr
|
|||||||
/// <param name="X">X-Position</param>
|
/// <param name="X">X-Position</param>
|
||||||
/// <param name="Y">Y-Position</param>
|
/// <param name="Y">Y-Position</param>
|
||||||
/// <param name="Page">Seite, auf der sie sich befindet</param>
|
/// <param name="Page">Seite, auf der sie sich befindet</param>
|
||||||
public record DocReceiverElementCreateDto([Required] double X, [Required] double Y, [Required] int Page);
|
public record Signature([Required] double X, [Required] double Y, [Required] int Page);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// DTO für Empfänger, die erstellt oder abgerufen werden sollen.
|
/// DTO für Empfänger, die erstellt oder abgerufen werden sollen.
|
||||||
@@ -41,7 +41,7 @@ public class ReceiverGetOrCreateCommand
|
|||||||
/// Unterschriften auf Dokumenten.
|
/// Unterschriften auf Dokumenten.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Required]
|
[Required]
|
||||||
public List<DocReceiverElementCreateDto> DocReceiverElements { get; init; } = new();
|
public List<Signature> Signatures { get; init; } = new();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Der Name, mit dem der Empfänger angesprochen werden soll.
|
/// Der Name, mit dem der Empfänger angesprochen werden soll.
|
||||||
|
|||||||
@@ -1,127 +0,0 @@
|
|||||||
using AutoMapper;
|
|
||||||
using DigitalData.Core.Abstraction.Application.Repository;
|
|
||||||
using EnvelopeGenerator.Application.Envelopes.Queries;
|
|
||||||
using EnvelopeGenerator.Application.Receivers.Queries;
|
|
||||||
using MediatR;
|
|
||||||
using EnvelopeGenerator.Domain.Entities;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
using EnvelopeGenerator.Application.Common.Dto.EnvelopeReceiver;
|
|
||||||
using EnvelopeGenerator.Application.Common.Query;
|
|
||||||
using EnvelopeGenerator.Application.Common.Extensions;
|
|
||||||
|
|
||||||
namespace EnvelopeGenerator.Application.EnvelopeReceivers.Queries;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Represents a query for reading an envelope receiver including sensitive fields
|
|
||||||
/// (access code, phone number) that are excluded from the standard <see cref="ReadEnvelopeReceiverQuery"/>.
|
|
||||||
/// </summary>
|
|
||||||
/// <remarks>
|
|
||||||
/// Returns a single <see cref="EnvelopeReceiverSecretDto"/> matched by UUID and receiver signature.
|
|
||||||
/// Equivalent to the legacy <c>ReadWithSecretByUuidSignatureAsync</c> service method.
|
|
||||||
/// </remarks>
|
|
||||||
public record ReadEnvelopeReceiverSecretQuery
|
|
||||||
: EnvelopeReceiverQueryBase<ReadEnvelopeQuery, ReadReceiverQuery>,
|
|
||||||
IRequest<EnvelopeReceiverSecretDto?>;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Extension methods for dispatching <see cref="ReadEnvelopeReceiverSecretQuery"/> via <see cref="IMediator"/>.
|
|
||||||
/// </summary>
|
|
||||||
public static class ReadEnvelopeReceiverSecretQueryExtensions
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Sends a <see cref="ReadEnvelopeReceiverSecretQuery"/> using the composite key (uuid::signature).
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="mediator">The mediator instance.</param>
|
|
||||||
/// <param name="key">Composite key in the format <c>uuid::signature</c>.</param>
|
|
||||||
/// <param name="cancel">Cancellation token.</param>
|
|
||||||
/// <returns>The matching <see cref="EnvelopeReceiverSecretDto"/>, or <c>null</c> if not found.</returns>
|
|
||||||
public static Task<EnvelopeReceiverSecretDto?> ReadEnvelopeReceiverSecretAsync(
|
|
||||||
this IMediator mediator,
|
|
||||||
string key,
|
|
||||||
CancellationToken cancel = default)
|
|
||||||
=> mediator.Send(new ReadEnvelopeReceiverSecretQuery { Key = key }, cancel);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Sends a <see cref="ReadEnvelopeReceiverSecretQuery"/> using UUID and receiver signature.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="mediator">The mediator instance.</param>
|
|
||||||
/// <param name="uuid">Envelope UUID.</param>
|
|
||||||
/// <param name="signature">Receiver signature.</param>
|
|
||||||
/// <param name="cancel">Cancellation token.</param>
|
|
||||||
/// <returns>The matching <see cref="EnvelopeReceiverSecretDto"/>, or <c>null</c> if not found.</returns>
|
|
||||||
public static Task<EnvelopeReceiverSecretDto?> ReadEnvelopeReceiverSecretAsync(
|
|
||||||
this IMediator mediator,
|
|
||||||
string uuid,
|
|
||||||
string signature,
|
|
||||||
CancellationToken cancel = default)
|
|
||||||
{
|
|
||||||
var q = new ReadEnvelopeReceiverSecretQuery();
|
|
||||||
q.Envelope.Uuid = uuid;
|
|
||||||
q.Receiver.Signature = signature;
|
|
||||||
return mediator.Send(q, cancel);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Handles <see cref="ReadEnvelopeReceiverSecretQuery"/> and returns a
|
|
||||||
/// <see cref="EnvelopeReceiverSecretDto"/> containing sensitive fields.
|
|
||||||
/// </summary>
|
|
||||||
public class ReadEnvelopeReceiverSecretQueryHandler
|
|
||||||
: IRequestHandler<ReadEnvelopeReceiverSecretQuery, EnvelopeReceiverSecretDto?>
|
|
||||||
{
|
|
||||||
private readonly IRepository<EnvelopeReceiver> _repo;
|
|
||||||
private readonly IRepository<Receiver> _rcvRepo;
|
|
||||||
private readonly IMapper _mapper;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Initializes a new instance of <see cref="ReadEnvelopeReceiverSecretQueryHandler"/>.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="envelopeReceiver">Repository for <see cref="EnvelopeReceiver"/>.</param>
|
|
||||||
/// <param name="rcvRepo">Repository for <see cref="Receiver"/>.</param>
|
|
||||||
/// <param name="mapper">AutoMapper instance.</param>
|
|
||||||
public ReadEnvelopeReceiverSecretQueryHandler(
|
|
||||||
IRepository<EnvelopeReceiver> envelopeReceiver,
|
|
||||||
IRepository<Receiver> rcvRepo,
|
|
||||||
IMapper mapper)
|
|
||||||
{
|
|
||||||
_repo = envelopeReceiver;
|
|
||||||
_rcvRepo = rcvRepo;
|
|
||||||
_mapper = mapper;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Handles the query and returns the matching <see cref="EnvelopeReceiverSecretDto"/>.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="request">The query containing filter criteria.</param>
|
|
||||||
/// <param name="cancel">Cancellation token.</param>
|
|
||||||
/// <returns>
|
|
||||||
/// The matched <see cref="EnvelopeReceiverSecretDto"/>, or <c>null</c> if no record is found.
|
|
||||||
/// </returns>
|
|
||||||
public async Task<EnvelopeReceiverSecretDto?> Handle(
|
|
||||||
ReadEnvelopeReceiverSecretQuery request,
|
|
||||||
CancellationToken cancel)
|
|
||||||
{
|
|
||||||
var q = _repo.Query.Where(request, notnull: false);
|
|
||||||
|
|
||||||
var envRcvs = await q
|
|
||||||
.Include(er => er.Envelope).ThenInclude(e => e!.Documents!).ThenInclude(d => d.Elements)
|
|
||||||
.Include(er => er.Envelope).ThenInclude(e => e!.Histories)
|
|
||||||
.Include(er => er.Envelope).ThenInclude(e => e!.User)
|
|
||||||
.Include(er => er.Receiver)
|
|
||||||
.ToListAsync(cancel);
|
|
||||||
|
|
||||||
if (request.Receiver.HasAnyCriteria && envRcvs.Count != 0)
|
|
||||||
{
|
|
||||||
var receiver = await _rcvRepo.Query.Where(request.Receiver).FirstAsync(cancel);
|
|
||||||
|
|
||||||
foreach (var item in envRcvs)
|
|
||||||
item.Envelope?.Documents?.FirstOrDefault()?.Elements?.RemoveAll(s => s.ReceiverId != receiver.Id);
|
|
||||||
}
|
|
||||||
|
|
||||||
var envRcv = envRcvs.FirstOrDefault();
|
|
||||||
if (envRcv is null)
|
|
||||||
return null;
|
|
||||||
|
|
||||||
return _mapper.Map<EnvelopeReceiverSecretDto>(envRcv);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -40,10 +40,10 @@ public record CreateEnvelopeCommand : IRequest<EnvelopeDto?>
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="userId"></param>
|
/// <param name="userId"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public CreateEnvelopeCommand WithAuth(int userId)
|
public bool Authorize(int userId)
|
||||||
{
|
{
|
||||||
UserId = userId;
|
UserId = userId;
|
||||||
return this;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -22,7 +22,13 @@ public record ReadEnvelopeQuery : EnvelopeQueryBase, IRequest<IEnumerable<Envelo
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Optionaler Benutzerfilter; wenn gesetzt, werden nur Umschläge des Benutzers geladen.
|
/// Optionaler Benutzerfilter; wenn gesetzt, werden nur Umschläge des Benutzers geladen.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal int? UserId { get; init; }
|
public int? UserId { get; init; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Optionaler Zeitfilter in Minuten; wenn gesetzt, werden nur Umschläge zurückgegeben,
|
||||||
|
/// deren letzte Änderung mindestens diese Anzahl an Minuten zurückliegt.
|
||||||
|
/// </summary>
|
||||||
|
public int? MinMinutesSinceLastChange { get; init; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Setzt den Benutzerkontext für die Abfrage.
|
/// Setzt den Benutzerkontext für die Abfrage.
|
||||||
@@ -132,8 +138,14 @@ public class ReadEnvelopeQueryHandler : IRequestHandler<ReadEnvelopeQuery, IEnum
|
|||||||
query = query.Where(e => !status.Ignore.Contains(e.Status));
|
query = query.Where(e => !status.Ignore.Contains(e.Status));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (request.MinMinutesSinceLastChange is int minMinutesSinceLastChange)
|
||||||
|
{
|
||||||
|
query = query.Where(e => e.ChangedWhen.HasValue
|
||||||
|
&& EF.Functions.DateDiffMinute(e.ChangedWhen.Value, DateTime.Now) >= minMinutesSinceLastChange);
|
||||||
|
}
|
||||||
|
|
||||||
var envelopes = await query
|
var envelopes = await query
|
||||||
.Include(e => e.EnvelopeReceivers).ThenInclude(er => er.Receiver)
|
.Include(e => e.Documents)
|
||||||
.ToListAsync(cancel);
|
.ToListAsync(cancel);
|
||||||
|
|
||||||
return _mapper.Map<IEnumerable<EnvelopeDto>>(envelopes);
|
return _mapper.Map<IEnumerable<EnvelopeDto>>(envelopes);
|
||||||
|
|||||||
@@ -0,0 +1,48 @@
|
|||||||
|
using MediatR;
|
||||||
|
using EnvelopeGenerator.Application.Common.Dto;
|
||||||
|
using DigitalData.Core.Exceptions;
|
||||||
|
|
||||||
|
namespace EnvelopeGenerator.Application.Envelopes.Queries;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Repräsentiert eine Abfrage für Umschläge.
|
||||||
|
/// </summary>
|
||||||
|
public record ReadSingleEnvelopeDocResultQuery() : IRequest<byte[]>
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
public ReadSingleEnvelopeQuery Envelope { get; set; } = null!;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Verarbeitet <see cref="ReadEnvelopeQuery"/> und liefert passende <see cref="EnvelopeDto"/>-Ergebnisse.
|
||||||
|
/// </summary>
|
||||||
|
public class ReadSingleEnvelopeDocResultQueryHandler : IRequestHandler<ReadSingleEnvelopeDocResultQuery, byte[]>
|
||||||
|
{
|
||||||
|
private readonly IMediator _mediator;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="mediator"></param>
|
||||||
|
public ReadSingleEnvelopeDocResultQueryHandler(IMediator mediator)
|
||||||
|
{
|
||||||
|
_mediator = mediator;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="request"></param>
|
||||||
|
/// <param name="cancellationToken"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public async Task<byte[]> Handle(ReadSingleEnvelopeDocResultQuery request, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
request.Envelope.IncludeDocResult = true;
|
||||||
|
var result = await _mediator.Send(request.Envelope, cancellationToken);
|
||||||
|
return result.DocResult is byte[] docResult && docResult.Length > 0
|
||||||
|
? docResult
|
||||||
|
: throw new NotFoundException($"Document for Envelope with ID {request.Envelope.Id} not found");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,78 @@
|
|||||||
|
using MediatR;
|
||||||
|
using EnvelopeGenerator.Application.Common.Query;
|
||||||
|
using EnvelopeGenerator.Application.Common.Dto;
|
||||||
|
using AutoMapper;
|
||||||
|
using DigitalData.Core.Abstraction.Application.Repository;
|
||||||
|
using EnvelopeGenerator.Domain.Entities;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using DigitalData.Core.Exceptions;
|
||||||
|
|
||||||
|
namespace EnvelopeGenerator.Application.Envelopes.Queries;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Repräsentiert eine Abfrage für einen einzelnen Umschlag.
|
||||||
|
/// </summary>
|
||||||
|
public record ReadSingleEnvelopeQuery : EnvelopeQueryBase, IRequest<EnvelopeDto>
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Optionaler Benutzerfilter; wenn gesetzt, werden nur Umschläge des Benutzers geladen.
|
||||||
|
/// </summary>
|
||||||
|
public int? UserId { get; init; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Setzt den Benutzerkontext für die Abfrage.
|
||||||
|
/// </summary>
|
||||||
|
public ReadSingleEnvelopeQuery Authorize(int userId) => this with { UserId = userId };
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Verarbeitet <see cref="ReadSingleEnvelopeQuery"/> und liefert ein einzelnes <see cref="EnvelopeDto"/>-Ergebnis.
|
||||||
|
/// </summary>
|
||||||
|
public class ReadSingleEnvelopeQueryHandler : IRequestHandler<ReadSingleEnvelopeQuery, EnvelopeDto>
|
||||||
|
{
|
||||||
|
private readonly IRepository<Envelope> _repository;
|
||||||
|
private readonly IMapper _mapper;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="repository"></param>
|
||||||
|
/// <param name="mapper"></param>
|
||||||
|
public ReadSingleEnvelopeQueryHandler(IRepository<Envelope> repository, IMapper mapper)
|
||||||
|
{
|
||||||
|
_repository = repository;
|
||||||
|
_mapper = mapper;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="request"></param>
|
||||||
|
/// <param name="cancel"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public async Task<EnvelopeDto> Handle(ReadSingleEnvelopeQuery request, CancellationToken cancel)
|
||||||
|
{
|
||||||
|
var query = _repository.Query;
|
||||||
|
|
||||||
|
if (request.UserId is int userId)
|
||||||
|
query = query.Where(e => e.UserId == userId);
|
||||||
|
|
||||||
|
if (request.Id is int id)
|
||||||
|
query = query.Where(e => e.Id == id);
|
||||||
|
|
||||||
|
if (request.Uuid is string uuid)
|
||||||
|
query = query.Where(e => e.Uuid == uuid);
|
||||||
|
|
||||||
|
var envelopes = await query
|
||||||
|
.Include(e => e.Documents)
|
||||||
|
.Take(2)
|
||||||
|
.ToListAsync(cancel);
|
||||||
|
|
||||||
|
if (envelopes.Count > 1)
|
||||||
|
throw new BadRequestException($"Multiple envelopes found for the given criteria: Id={request.Id}, Uuid={request.Uuid}, UserId={request.UserId}");
|
||||||
|
|
||||||
|
return envelopes.SingleOrDefault() is Envelope envelope
|
||||||
|
? _mapper.Map<EnvelopeDto>(envelope)
|
||||||
|
: throw new NotFoundException($"Envelope with Id={request.Id}, Uuid={request.Uuid} not found");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -34,7 +34,7 @@ public record CreateHistoryCommand : EnvelopeReceiverQueryBase, IRequest<History
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
///
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public DateTime AddedWhen { get; } = DateTime.Now;
|
public DateTime AddedWhen { get; } = DateTime.UtcNow;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
///
|
||||||
|
|||||||
@@ -448,7 +448,7 @@
|
|||||||
<value>Document has been reset.</value>
|
<value>Document has been reset.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="DocumentSuccessfullyConfirmed" xml:space="preserve">
|
<data name="DocumentSuccessfullyConfirmed" xml:space="preserve">
|
||||||
<value>Document successfully read and confirmed!</value>
|
<value>Document successfully red and confirmed!</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="DocumentConfirmedConfirmationMessage" xml:space="preserve">
|
<data name="DocumentConfirmedConfirmationMessage" xml:space="preserve">
|
||||||
<value>You have read and confirmed the document. You will receive a written confirmation afterwards.</value>
|
<value>You have read and confirmed the document. You will receive a written confirmation afterwards.</value>
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ using Microsoft.Extensions.Logging;
|
|||||||
using EnvelopeGenerator.Application.Common.Dto;
|
using EnvelopeGenerator.Application.Common.Dto;
|
||||||
using EnvelopeGenerator.Application.Common.Interfaces.Repositories;
|
using EnvelopeGenerator.Application.Common.Interfaces.Repositories;
|
||||||
using EnvelopeGenerator.Application.Common.Interfaces.Services;
|
using EnvelopeGenerator.Application.Common.Interfaces.Services;
|
||||||
|
using EnvelopeGenerator.Application.Common;
|
||||||
|
|
||||||
namespace EnvelopeGenerator.Application.Services;
|
namespace EnvelopeGenerator.Application.Services;
|
||||||
|
|
||||||
@@ -16,8 +17,6 @@ namespace EnvelopeGenerator.Application.Services;
|
|||||||
[Obsolete("Use MediatR")]
|
[Obsolete("Use MediatR")]
|
||||||
public class ConfigService : ReadService<IConfigRepository, ConfigDto, Config, int>, IConfigService
|
public class ConfigService : ReadService<IConfigRepository, ConfigDto, Config, int>, IConfigService
|
||||||
{
|
{
|
||||||
private static readonly Guid DefaultConfigCacheId = Guid.NewGuid();
|
|
||||||
|
|
||||||
private readonly IMemoryCache _cache;
|
private readonly IMemoryCache _cache;
|
||||||
|
|
||||||
private readonly ILogger<ConfigService> _logger;
|
private readonly ILogger<ConfigService> _logger;
|
||||||
@@ -62,7 +61,7 @@ public class ConfigService : ReadService<IConfigRepository, ConfigDto, Config, i
|
|||||||
/// </exception>
|
/// </exception>
|
||||||
public async Task<ConfigDto> ReadDefaultAsync()
|
public async Task<ConfigDto> ReadDefaultAsync()
|
||||||
{
|
{
|
||||||
var config = await _cache.GetOrCreateAsync(DefaultConfigCacheId, _ => ReadFirstAsync().ThenAsync(
|
var config = await _cache.GetOrCreateAsync(CacheKey.DefaultConfig, _ => ReadFirstAsync().ThenAsync(
|
||||||
Success: config => config,
|
Success: config => config,
|
||||||
Fail: (mssg, ntc) =>
|
Fail: (mssg, ntc) =>
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
using AutoMapper;
|
using AutoMapper;
|
||||||
using DigitalData.Core.Application;
|
using DigitalData.Core.Application;
|
||||||
|
using EnvelopeGenerator.Domain.Entities;
|
||||||
using EnvelopeGenerator.Application.Common.Dto;
|
using EnvelopeGenerator.Application.Common.Dto;
|
||||||
using EnvelopeGenerator.Application.Common.Interfaces.Repositories;
|
using EnvelopeGenerator.Application.Common.Interfaces.Repositories;
|
||||||
using EnvelopeGenerator.Application.Common.Interfaces.Services;
|
using EnvelopeGenerator.Application.Common.Interfaces.Services;
|
||||||
using EnvelopeGenerator.Domain.Entities;
|
|
||||||
|
|
||||||
namespace EnvelopeGenerator.Application.Services;
|
namespace EnvelopeGenerator.Application.Services;
|
||||||
|
|
||||||
@@ -11,7 +11,7 @@ namespace EnvelopeGenerator.Application.Services;
|
|||||||
///
|
///
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Obsolete("Use MediatR")]
|
[Obsolete("Use MediatR")]
|
||||||
public class DocumentReceiverElementService : BasicCRUDService<IDocumentReceiverElementRepository, DocReceiverElementDto, DocReceiverElement, int>, IDocumentReceiverElementService
|
public class DocumentReceiverElementService : BasicCRUDService<IDocumentReceiverElementRepository, SignatureDto, Signature, int>, IDocumentReceiverElementService
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
///
|
||||||
|
|||||||
@@ -487,6 +487,10 @@
|
|||||||
<Project>{6EA0C51F-C2B1-4462-8198-3DE0B32B74F8}</Project>
|
<Project>{6EA0C51F-C2B1-4462-8198-3DE0B32B74F8}</Project>
|
||||||
<Name>EnvelopeGenerator.CommonServices</Name>
|
<Name>EnvelopeGenerator.CommonServices</Name>
|
||||||
</ProjectReference>
|
</ProjectReference>
|
||||||
|
<ProjectReference Include="..\EnvelopeGenerator.CommonServices\EnvelopeGenerator.CommonServices.vbproj">
|
||||||
|
<Project>{6ea0c51f-c2b1-4462-8198-3de0b32b74f8}</Project>
|
||||||
|
<Name>EnvelopeGenerator.CommonServices</Name>
|
||||||
|
</ProjectReference>
|
||||||
<ProjectReference Include="..\EnvelopeGenerator.Domain\EnvelopeGenerator.Domain.csproj">
|
<ProjectReference Include="..\EnvelopeGenerator.Domain\EnvelopeGenerator.Domain.csproj">
|
||||||
<Project>{4f32a98d-e6f0-4a09-bd97-1cf26107e837}</Project>
|
<Project>{4f32a98d-e6f0-4a09-bd97-1cf26107e837}</Project>
|
||||||
<Name>EnvelopeGenerator.Domain</Name>
|
<Name>EnvelopeGenerator.Domain</Name>
|
||||||
|
|||||||
12
EnvelopeGenerator.BBTests/frmFinalizePDF.Designer.vb
generated
12
EnvelopeGenerator.BBTests/frmFinalizePDF.Designer.vb
generated
@@ -27,7 +27,6 @@ Partial Class frmFinalizePDF
|
|||||||
Me.Label2 = New System.Windows.Forms.Label()
|
Me.Label2 = New System.Windows.Forms.Label()
|
||||||
Me.Button1 = New System.Windows.Forms.Button()
|
Me.Button1 = New System.Windows.Forms.Button()
|
||||||
Me.Button2 = New System.Windows.Forms.Button()
|
Me.Button2 = New System.Windows.Forms.Button()
|
||||||
Me.Button3 = New System.Windows.Forms.Button()
|
|
||||||
Me.txtResult = New System.Windows.Forms.TextBox()
|
Me.txtResult = New System.Windows.Forms.TextBox()
|
||||||
Me.txtEnvelope = New System.Windows.Forms.TextBox()
|
Me.txtEnvelope = New System.Windows.Forms.TextBox()
|
||||||
Me.SuspendLayout()
|
Me.SuspendLayout()
|
||||||
@@ -76,15 +75,6 @@ Partial Class frmFinalizePDF
|
|||||||
Me.Button2.Text = "Merge Json"
|
Me.Button2.Text = "Merge Json"
|
||||||
Me.Button2.UseVisualStyleBackColor = True
|
Me.Button2.UseVisualStyleBackColor = True
|
||||||
'
|
'
|
||||||
'Button3
|
|
||||||
'
|
|
||||||
Me.Button3.Location = New System.Drawing.Point(15, 160)
|
|
||||||
Me.Button3.Name = "Button3"
|
|
||||||
Me.Button3.Size = New System.Drawing.Size(166, 23)
|
|
||||||
Me.Button3.TabIndex = 5
|
|
||||||
Me.Button3.Text = "Full Finalize Test"
|
|
||||||
Me.Button3.UseVisualStyleBackColor = True
|
|
||||||
'
|
|
||||||
'txtResult
|
'txtResult
|
||||||
'
|
'
|
||||||
Me.txtResult.Location = New System.Drawing.Point(333, 12)
|
Me.txtResult.Location = New System.Drawing.Point(333, 12)
|
||||||
@@ -107,7 +97,6 @@ Partial Class frmFinalizePDF
|
|||||||
Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
|
Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
|
||||||
Me.ClientSize = New System.Drawing.Size(800, 450)
|
Me.ClientSize = New System.Drawing.Size(800, 450)
|
||||||
Me.Controls.Add(Me.txtResult)
|
Me.Controls.Add(Me.txtResult)
|
||||||
Me.Controls.Add(Me.Button3)
|
|
||||||
Me.Controls.Add(Me.Button2)
|
Me.Controls.Add(Me.Button2)
|
||||||
Me.Controls.Add(Me.Button1)
|
Me.Controls.Add(Me.Button1)
|
||||||
Me.Controls.Add(Me.Label2)
|
Me.Controls.Add(Me.Label2)
|
||||||
@@ -127,6 +116,5 @@ Partial Class frmFinalizePDF
|
|||||||
Friend WithEvents Label2 As Label
|
Friend WithEvents Label2 As Label
|
||||||
Friend WithEvents Button1 As Button
|
Friend WithEvents Button1 As Button
|
||||||
Friend WithEvents Button2 As Button
|
Friend WithEvents Button2 As Button
|
||||||
Friend WithEvents Button3 As Button
|
|
||||||
Friend WithEvents txtResult As TextBox
|
Friend WithEvents txtResult As TextBox
|
||||||
End Class
|
End Class
|
||||||
|
|||||||
@@ -8,8 +8,6 @@ Imports Newtonsoft.Json.Linq
|
|||||||
Imports EnvelopeGenerator.Infrastructure
|
Imports EnvelopeGenerator.Infrastructure
|
||||||
Imports Microsoft.EntityFrameworkCore
|
Imports Microsoft.EntityFrameworkCore
|
||||||
Imports DigitalData.Core.Abstractions
|
Imports DigitalData.Core.Abstractions
|
||||||
Imports DigitalData.Core.Abstraction.Application.Repository
|
|
||||||
Imports EnvelopeGenerator.Domain.Entities
|
|
||||||
|
|
||||||
Public Class frmFinalizePDF
|
Public Class frmFinalizePDF
|
||||||
Private Const CONNECTIONSTRING = "Server=sDD-VMP04-SQL17\DD_DEVELOP01;Database=DD_ECM;User Id=sa;Password=+bk8oAbbQP1AzoHtvZUbd+Mbok2f8Fl4miEx1qssJ5yEaEWoQJ9prg4L14fURpPnqi1WMNs9fE4=;" + "Encrypt=True;TrustServerCertificate=True;"
|
Private Const CONNECTIONSTRING = "Server=sDD-VMP04-SQL17\DD_DEVELOP01;Database=DD_ECM;User Id=sa;Password=+bk8oAbbQP1AzoHtvZUbd+Mbok2f8Fl4miEx1qssJ5yEaEWoQJ9prg4L14fURpPnqi1WMNs9fE4=;" + "Encrypt=True;TrustServerCertificate=True;"
|
||||||
@@ -126,86 +124,4 @@ Public Class frmFinalizePDF
|
|||||||
|
|
||||||
txtResult.Text = oJObject1.ToString()
|
txtResult.Text = oJObject1.ToString()
|
||||||
End Sub
|
End Sub
|
||||||
|
|
||||||
Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click
|
|
||||||
Try
|
|
||||||
Dim envelopeId As Integer = CInt(txtEnvelope.Text)
|
|
||||||
Dim log As New System.Text.StringBuilder()
|
|
||||||
|
|
||||||
' 1. Load annotation JSON data (same as Service)
|
|
||||||
Dim oTable = LoadAnnotationDataForEnvelope()
|
|
||||||
Dim oJsonList = oTable.Rows.
|
|
||||||
Cast(Of DataRow).
|
|
||||||
Select(Function(r As DataRow) r.Item("VALUE").ToString()).
|
|
||||||
ToList()
|
|
||||||
log.AppendLine($"Annotation JSON count: {oJsonList.Count}")
|
|
||||||
|
|
||||||
' 2. Load document bytes (same as Service)
|
|
||||||
Dim oBuffer As Byte() = ReadEnvelope(envelopeId)
|
|
||||||
log.AppendLine($"Document bytes: {oBuffer.Length}")
|
|
||||||
|
|
||||||
' 3. Check what BurnAnnotsToPDF will do internally
|
|
||||||
Using scope = Factory.Shared.ScopeFactory.CreateScope()
|
|
||||||
Dim envRepo = scope.ServiceProvider.Repository(Of Envelope)()
|
|
||||||
Dim envelope = envRepo.Where(Function(env) env.Id = envelopeId).FirstOrDefault()
|
|
||||||
|
|
||||||
If envelope Is Nothing Then
|
|
||||||
log.AppendLine("ERROR: Envelope not found in EF Core!")
|
|
||||||
txtResult.Text = log.ToString()
|
|
||||||
Return
|
|
||||||
End If
|
|
||||||
|
|
||||||
log.AppendLine($"Envelope found: Id={envelope.Id}, EnvelopeTypeId={envelope.EnvelopeTypeId}")
|
|
||||||
log.AppendLine($"ReadOnly (IsReadAndConfirm): {envelope.ReadOnly}")
|
|
||||||
|
|
||||||
If envelope.ReadOnly Then
|
|
||||||
log.AppendLine(">>> EARLY RETURN: ReadOnly=True, original PDF returned without burning")
|
|
||||||
txtResult.Text = log.ToString()
|
|
||||||
Return
|
|
||||||
End If
|
|
||||||
|
|
||||||
Dim sigRepo = scope.ServiceProvider.Repository(Of DocReceiverElement)()
|
|
||||||
Dim elements = sigRepo _
|
|
||||||
.Where(Function(sig) sig.Document.EnvelopeId = envelopeId) _
|
|
||||||
.Include(Function(sig) sig.Annotations) _
|
|
||||||
.ToList()
|
|
||||||
|
|
||||||
log.AppendLine($"Elements (Signature) count: {elements.Count}")
|
|
||||||
|
|
||||||
If elements.Any() Then
|
|
||||||
log.AppendLine(">>> PATH: BurnElementAnnotsToPDF (new element-based path)")
|
|
||||||
For Each elem In elements
|
|
||||||
Dim annotCount = If(elem.Annotations IsNot Nothing, elem.Annotations.Count(), 0)
|
|
||||||
log.AppendLine($" Element Id={elem.Id}, Page={elem.Page}, X={elem.X}, Y={elem.Y}, W={elem.Width}, H={elem.Height}, Annotations={annotCount}")
|
|
||||||
If elem.Annotations IsNot Nothing Then
|
|
||||||
For Each annot In elem.Annotations
|
|
||||||
log.AppendLine($" Annot: Name={annot.Name}, Type={annot.Type}, X={annot.X}, Y={annot.Y}, W={annot.Width}, H={annot.Height}")
|
|
||||||
Next
|
|
||||||
End If
|
|
||||||
Next
|
|
||||||
Else
|
|
||||||
log.AppendLine(">>> PATH: BurnInstantJSONAnnotsToPDF (old JSON-based path)")
|
|
||||||
End If
|
|
||||||
End Using
|
|
||||||
|
|
||||||
' 4. Actually call BurnAnnotsToPDF (same as Service)
|
|
||||||
log.AppendLine("")
|
|
||||||
log.AppendLine("Calling BurnAnnotsToPDF...")
|
|
||||||
Dim oNewBuffer = PDFBurner.BurnAnnotsToPDF(oBuffer, oJsonList, envelopeId)
|
|
||||||
log.AppendLine($"Result bytes: {oNewBuffer.Length}")
|
|
||||||
log.AppendLine($"Same as input: {oBuffer.Length = oNewBuffer.Length AndAlso oBuffer.SequenceEqual(oNewBuffer)}")
|
|
||||||
|
|
||||||
' 5. Write output
|
|
||||||
Dim desktopPath As String = Environment.GetFolderPath(Environment.SpecialFolder.Desktop)
|
|
||||||
Dim oNewPath = Path.Combine(desktopPath, $"E{txtEnvelope.Text}_FullTest.burned.pdf")
|
|
||||||
File.WriteAllBytes(oNewPath, oNewBuffer)
|
|
||||||
log.AppendLine($"Output: {oNewPath}")
|
|
||||||
|
|
||||||
txtResult.Text = log.ToString()
|
|
||||||
Process.Start(oNewPath)
|
|
||||||
|
|
||||||
Catch ex As Exception
|
|
||||||
txtResult.Text = $"ERROR: {ex.Message}{vbCrLf}{vbCrLf}{ex.ToString()}"
|
|
||||||
End Try
|
|
||||||
End Sub
|
|
||||||
End Class
|
End Class
|
||||||
@@ -15,13 +15,13 @@
|
|||||||
<package id="DigitalData.Modules.Messaging" version="1.9.8" targetFramework="net462" />
|
<package id="DigitalData.Modules.Messaging" version="1.9.8" targetFramework="net462" />
|
||||||
<package id="DocumentFormat.OpenXml" version="3.2.0" targetFramework="net462" />
|
<package id="DocumentFormat.OpenXml" version="3.2.0" targetFramework="net462" />
|
||||||
<package id="DocumentFormat.OpenXml.Framework" version="3.2.0" targetFramework="net462" />
|
<package id="DocumentFormat.OpenXml.Framework" version="3.2.0" targetFramework="net462" />
|
||||||
<package id="EntityFramework" version="6.4.4" targetFramework="net462" />
|
<package id="EntityFramework" version="6.5.1" targetFramework="net462" />
|
||||||
<package id="EntityFramework.Firebird" version="6.4.0" targetFramework="net462" />
|
<package id="EntityFramework.Firebird" version="6.4.0" targetFramework="net462" />
|
||||||
<package id="FirebirdSql.Data.FirebirdClient" version="7.5.0" targetFramework="net462" />
|
<package id="FirebirdSql.Data.FirebirdClient" version="7.5.0" targetFramework="net462" />
|
||||||
<package id="GdPicture" version="14.3.3" targetFramework="net462" />
|
<package id="GdPicture" version="14.3.3" targetFramework="net462" />
|
||||||
<package id="GdPicture.runtimes.windows" version="14.3.3" targetFramework="net462" />
|
<package id="GdPicture.runtimes.windows" version="14.3.3" targetFramework="net462" />
|
||||||
<package id="Microsoft.AspNet.WebApi.Client" version="6.0.0" targetFramework="net462" />
|
<package id="Microsoft.AspNet.WebApi.Client" version="6.0.0" targetFramework="net462" />
|
||||||
<package id="Microsoft.Bcl.AsyncInterfaces" version="8.0.0" targetFramework="net462" />
|
<package id="Microsoft.Bcl.AsyncInterfaces" version="9.0.0" targetFramework="net462" />
|
||||||
<package id="Microsoft.Bcl.Cryptography" version="9.0.0" targetFramework="net462" />
|
<package id="Microsoft.Bcl.Cryptography" version="9.0.0" targetFramework="net462" />
|
||||||
<package id="Microsoft.Bcl.HashCode" version="1.1.1" targetFramework="net462" />
|
<package id="Microsoft.Bcl.HashCode" version="1.1.1" targetFramework="net462" />
|
||||||
<package id="Microsoft.CSharp" version="4.7.0" targetFramework="net462" />
|
<package id="Microsoft.CSharp" version="4.7.0" targetFramework="net462" />
|
||||||
@@ -62,10 +62,10 @@
|
|||||||
<package id="protobuf-net.Core" version="3.2.46" targetFramework="net462" />
|
<package id="protobuf-net.Core" version="3.2.46" targetFramework="net462" />
|
||||||
<package id="RtfPipe" version="2.0.7677.4303" targetFramework="net462" />
|
<package id="RtfPipe" version="2.0.7677.4303" targetFramework="net462" />
|
||||||
<package id="S22.Imap" version="3.6.0.0" targetFramework="net462" />
|
<package id="S22.Imap" version="3.6.0.0" targetFramework="net462" />
|
||||||
<package id="System.Buffers" version="4.6.0" targetFramework="net462" />
|
<package id="System.Buffers" version="4.6.1" targetFramework="net462" />
|
||||||
<package id="System.ClientModel" version="1.8.0" targetFramework="net462" />
|
<package id="System.ClientModel" version="1.8.0" targetFramework="net462" />
|
||||||
<package id="System.CodeDom" version="8.0.0" targetFramework="net462" />
|
<package id="System.CodeDom" version="9.0.0" targetFramework="net462" />
|
||||||
<package id="System.Collections.Immutable" version="8.0.0" targetFramework="net462" />
|
<package id="System.Collections.Immutable" version="9.0.0" targetFramework="net462" />
|
||||||
<package id="System.ComponentModel.Annotations" version="4.7.0" targetFramework="net462" />
|
<package id="System.ComponentModel.Annotations" version="4.7.0" targetFramework="net462" />
|
||||||
<package id="System.Data.Common" version="4.3.0" targetFramework="net462" />
|
<package id="System.Data.Common" version="4.3.0" targetFramework="net462" />
|
||||||
<package id="System.Data.Odbc" version="6.0.1" targetFramework="net462" />
|
<package id="System.Data.Odbc" version="6.0.1" targetFramework="net462" />
|
||||||
@@ -74,23 +74,23 @@
|
|||||||
<package id="System.Formats.Asn1" version="10.0.3" targetFramework="net462" />
|
<package id="System.Formats.Asn1" version="10.0.3" targetFramework="net462" />
|
||||||
<package id="System.IdentityModel.Tokens.Jwt" version="7.7.1" targetFramework="net462" />
|
<package id="System.IdentityModel.Tokens.Jwt" version="7.7.1" targetFramework="net462" />
|
||||||
<package id="System.IO.FileSystem.AccessControl" version="5.0.0" targetFramework="net462" />
|
<package id="System.IO.FileSystem.AccessControl" version="5.0.0" targetFramework="net462" />
|
||||||
<package id="System.IO.Packaging" version="8.0.1" targetFramework="net462" />
|
<package id="System.IO.Packaging" version="9.0.0" targetFramework="net462" />
|
||||||
<package id="System.IO.Pipelines" version="9.0.0" targetFramework="net462" />
|
<package id="System.IO.Pipelines" version="9.0.0" targetFramework="net462" />
|
||||||
<package id="System.Management" version="8.0.0" targetFramework="net462" />
|
<package id="System.Management" version="9.0.0" targetFramework="net462" />
|
||||||
<package id="System.Memory" version="4.6.0" targetFramework="net462" />
|
<package id="System.Memory" version="4.6.3" targetFramework="net462" />
|
||||||
<package id="System.Memory.Data" version="8.0.1" targetFramework="net462" />
|
<package id="System.Memory.Data" version="8.0.1" targetFramework="net462" />
|
||||||
<package id="System.Numerics.Vectors" version="4.6.0" targetFramework="net462" />
|
<package id="System.Numerics.Vectors" version="4.6.1" targetFramework="net462" />
|
||||||
<package id="System.Runtime.CompilerServices.Unsafe" version="6.1.0" targetFramework="net462" />
|
<package id="System.Runtime.CompilerServices.Unsafe" version="6.1.2" targetFramework="net462" />
|
||||||
<package id="System.Security.AccessControl" version="6.0.1" targetFramework="net462" />
|
<package id="System.Security.AccessControl" version="6.0.1" targetFramework="net462" />
|
||||||
<package id="System.Security.Cryptography.Algorithms" version="4.3.1" targetFramework="net462" />
|
<package id="System.Security.Cryptography.Algorithms" version="4.3.1" targetFramework="net462" />
|
||||||
<package id="System.Security.Cryptography.Cng" version="5.0.0" targetFramework="net462" />
|
<package id="System.Security.Cryptography.Cng" version="5.0.0" targetFramework="net462" />
|
||||||
<package id="System.Security.Cryptography.Pkcs" version="8.0.1" targetFramework="net462" />
|
<package id="System.Security.Cryptography.Pkcs" version="9.0.0" targetFramework="net462" />
|
||||||
<package id="System.Security.Cryptography.Primitives" version="4.3.0" targetFramework="net462" />
|
<package id="System.Security.Cryptography.Primitives" version="4.3.0" targetFramework="net462" />
|
||||||
<package id="System.Security.Cryptography.ProtectedData" version="4.5.0" targetFramework="net462" />
|
<package id="System.Security.Cryptography.ProtectedData" version="4.5.0" targetFramework="net462" />
|
||||||
<package id="System.Security.Principal.Windows" version="5.0.0" targetFramework="net462" />
|
<package id="System.Security.Principal.Windows" version="5.0.0" targetFramework="net462" />
|
||||||
<package id="System.Text.Encodings.Web" version="8.0.0" targetFramework="net462" />
|
<package id="System.Text.Encodings.Web" version="9.0.0" targetFramework="net462" />
|
||||||
<package id="System.Text.Json" version="8.0.6" targetFramework="net462" />
|
<package id="System.Text.Json" version="9.0.0" targetFramework="net462" />
|
||||||
<package id="System.Text.RegularExpressions" version="4.3.1" targetFramework="net462" />
|
<package id="System.Text.RegularExpressions" version="4.3.1" targetFramework="net462" />
|
||||||
<package id="System.Threading.Tasks.Extensions" version="4.5.4" targetFramework="net462" />
|
<package id="System.Threading.Tasks.Extensions" version="4.6.0" targetFramework="net462" />
|
||||||
<package id="System.ValueTuple" version="4.5.0" targetFramework="net462" />
|
<package id="System.ValueTuple" version="4.6.1" targetFramework="net462" />
|
||||||
</packages>
|
</packages>
|
||||||
@@ -15,7 +15,6 @@ Imports DigitalData.Core.Abstraction.Application
|
|||||||
Imports EnvelopeGenerator.Infrastructure
|
Imports EnvelopeGenerator.Infrastructure
|
||||||
Imports Microsoft.EntityFrameworkCore
|
Imports Microsoft.EntityFrameworkCore
|
||||||
Imports DigitalData.Core.Abstractions
|
Imports DigitalData.Core.Abstractions
|
||||||
Imports EnvelopeGenerator.Domain.Interfaces
|
|
||||||
|
|
||||||
Namespace Jobs
|
Namespace Jobs
|
||||||
Public Class FinalizeDocumentJob
|
Public Class FinalizeDocumentJob
|
||||||
@@ -231,29 +230,6 @@ Namespace Jobs
|
|||||||
|
|
||||||
Return Task.FromResult(True)
|
Return Task.FromResult(True)
|
||||||
End Function
|
End Function
|
||||||
|
|
||||||
#Region "From BBTests"
|
|
||||||
Private Function ReadEnvelope(pEnvID As Integer) As Byte()
|
|
||||||
Dim strSql As String = "Select [BYTE_DATA] from [TBSIG_ENVELOPE_DOCUMENT] WHERE ENVELOPE_ID = " & pEnvID
|
|
||||||
Dim obyteDB = Database.GetScalarValue(strSql)
|
|
||||||
If Not IsDBNull(obyteDB) Then
|
|
||||||
Dim fileData As Byte() = DirectCast(Database.GetScalarValue(strSql), Byte())
|
|
||||||
If fileData IsNot Nothing Then
|
|
||||||
Return fileData
|
|
||||||
End If
|
|
||||||
End If
|
|
||||||
|
|
||||||
Throw New InvalidOperationException($"Byte data is null. Envelope ID: {pEnvID}")
|
|
||||||
|
|
||||||
End Function
|
|
||||||
|
|
||||||
Private Function LoadAnnotationDataForEnvelope(pEnvID As Integer) As DataTable
|
|
||||||
Dim oSql = $"SELECT VALUE FROM [TBSIG_DOCUMENT_STATUS] WHERE ENVELOPE_ID = {pEnvID}"
|
|
||||||
Return Database.GetDatatable(oSql)
|
|
||||||
|
|
||||||
End Function
|
|
||||||
#End Region
|
|
||||||
|
|
||||||
Private Sub Update_File_DB(pFilePath As String, pEnvelopeID As Long)
|
Private Sub Update_File_DB(pFilePath As String, pEnvelopeID As Long)
|
||||||
Dim SqlCom As SqlCommand
|
Dim SqlCom As SqlCommand
|
||||||
Dim imageData As Byte()
|
Dim imageData As Byte()
|
||||||
@@ -351,7 +327,7 @@ Namespace Jobs
|
|||||||
Logger.Warn($"No SendFinalEmailToCreator - oMailToCreator [{oMailToCreator}] <> [{FinalEmailType.No}] ")
|
Logger.Warn($"No SendFinalEmailToCreator - oMailToCreator [{oMailToCreator}] <> [{FinalEmailType.No}] ")
|
||||||
End If
|
End If
|
||||||
|
|
||||||
If oMailToReceivers <> FinalEmailType.No And pEnvelope.IsReadAndSign() Then
|
If oMailToReceivers <> FinalEmailType.No Then
|
||||||
Logger.Debug("Sending emails to receivers..")
|
Logger.Debug("Sending emails to receivers..")
|
||||||
SendFinalEmailToReceivers(pEnvelope) ', pAttachment
|
SendFinalEmailToReceivers(pEnvelope) ', pAttachment
|
||||||
Else
|
Else
|
||||||
@@ -442,18 +418,7 @@ Namespace Jobs
|
|||||||
End Try
|
End Try
|
||||||
End If
|
End If
|
||||||
|
|
||||||
#Region "From BBTests"
|
Return PDFBurner.BurnAnnotsToPDF(oInputDocumentBuffer, oAnnotations, pEnvelopeData.EnvelopeId)
|
||||||
Dim oTable = LoadAnnotationDataForEnvelope(pEnvelopeId)
|
|
||||||
Dim oJsonList = oTable.Rows.
|
|
||||||
Cast(Of DataRow).
|
|
||||||
Select(Function(r As DataRow) r.Item("VALUE").ToString()).
|
|
||||||
ToList()
|
|
||||||
|
|
||||||
Dim oBuffer As Byte() = ReadEnvelope(pEnvelopeId)
|
|
||||||
|
|
||||||
#End Region
|
|
||||||
|
|
||||||
Return PDFBurner.BurnAnnotsToPDF(oBuffer, oJsonList, pEnvelopeId)
|
|
||||||
End Function
|
End Function
|
||||||
|
|
||||||
Private Function GetEnvelopeData(pEnvelopeId As Integer) As EnvelopeData
|
Private Function GetEnvelopeData(pEnvelopeId As Integer) As EnvelopeData
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ Namespace Jobs.FinalizeDocument
|
|||||||
Return pSourceBuffer
|
Return pSourceBuffer
|
||||||
End If
|
End If
|
||||||
|
|
||||||
Dim sigRepo = scope.ServiceProvider.Repository(Of DocReceiverElement)()
|
Dim sigRepo = scope.ServiceProvider.Repository(Of Signature)()
|
||||||
Dim elements = sigRepo _
|
Dim elements = sigRepo _
|
||||||
.Where(Function(sig) sig.Document.EnvelopeId = envelopeId) _
|
.Where(Function(sig) sig.Document.EnvelopeId = envelopeId) _
|
||||||
.Include(Function(sig) sig.Annotations) _
|
.Include(Function(sig) sig.Annotations) _
|
||||||
@@ -58,7 +58,7 @@ Namespace Jobs.FinalizeDocument
|
|||||||
End Using
|
End Using
|
||||||
End Function
|
End Function
|
||||||
|
|
||||||
Public Function BurnElementAnnotsToPDF(pSourceBuffer As Byte(), elements As List(Of DocReceiverElement)) As Byte()
|
Public Function BurnElementAnnotsToPDF(pSourceBuffer As Byte(), elements As List(Of Signature)) As Byte()
|
||||||
' Add background
|
' Add background
|
||||||
Using doc As Pdf(Of MemoryStream, MemoryStream) = Pdf.FromMemory(pSourceBuffer)
|
Using doc As Pdf(Of MemoryStream, MemoryStream) = Pdf.FromMemory(pSourceBuffer)
|
||||||
'TODO: take the length from the largest y
|
'TODO: take the length from the largest y
|
||||||
@@ -85,37 +85,16 @@ Namespace Jobs.FinalizeDocument
|
|||||||
|
|
||||||
'Add annotations
|
'Add annotations
|
||||||
For Each element In elements
|
For Each element In elements
|
||||||
If element Is Nothing Then
|
|
||||||
Continue For
|
|
||||||
End If
|
|
||||||
|
|
||||||
Dim elementAnnotations = If(element.Annotations, Enumerable.Empty(Of ElementAnnotation)())
|
|
||||||
If Not elementAnnotations.Any() Then
|
|
||||||
Continue For
|
|
||||||
End If
|
|
||||||
|
|
||||||
Dim frameX = (element.Left - 0.7 - margin)
|
Dim frameX = (element.Left - 0.7 - margin)
|
||||||
|
|
||||||
Dim frame = elementAnnotations.FirstOrDefault(Function(a) a.Name = "frame")
|
Dim frame = element.Annotations.FirstOrDefault(Function(a) a.Name = "frame")
|
||||||
Dim frameY = element.Top - 0.5 - margin
|
Dim frameY = element.Top - 0.5 - margin
|
||||||
Dim frameYShift As Double = 0
|
Dim frameYShift = frame.Y - frameY * inchFactor
|
||||||
Dim frameXShift As Double = 0
|
Dim frameXShift = frame.X - frameX * inchFactor
|
||||||
|
|
||||||
If frame IsNot Nothing Then
|
|
||||||
frameYShift = frame.Y - frameY * inchFactor
|
|
||||||
frameXShift = frame.X - frameX * inchFactor
|
|
||||||
End If
|
|
||||||
|
|
||||||
For Each annot In elementAnnotations
|
|
||||||
If annot Is Nothing Then
|
|
||||||
Continue For
|
|
||||||
End If
|
|
||||||
|
|
||||||
Dim yOffsetofFF As Double = 0
|
|
||||||
If Not String.IsNullOrEmpty(annot.Name) Then
|
|
||||||
yOffsetsOfFF.TryGetValue(annot.Name, yOffsetofFF)
|
|
||||||
End If
|
|
||||||
|
|
||||||
|
For Each annot In element.Annotations
|
||||||
|
Dim yOffsetofFF As Double = If(yOffsetsOfFF.TryGetValue(annot.Name, yOffsetofFF), yOffsetofFF, 0)
|
||||||
Dim y = frameY + yOffsetofFF
|
Dim y = frameY + yOffsetofFF
|
||||||
|
|
||||||
If annot.Type = AnnotationType.FormField Then
|
If annot.Type = AnnotationType.FormField Then
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ Public Class PDFMerger
|
|||||||
|
|
||||||
' Convert to PDF/A
|
' Convert to PDF/A
|
||||||
oMergedPDF.ConvertToPDFA(oFinalStream, PDFAConformanceLevel, ALLOW_VECTORIZATION, ALLOW_RASTERIZATION)
|
oMergedPDF.ConvertToPDFA(oFinalStream, PDFAConformanceLevel, ALLOW_VECTORIZATION, ALLOW_RASTERIZATION)
|
||||||
oStatus = oMergedPDF.GetStat()
|
oStatus = oDocumentPDF.GetStat()
|
||||||
If oStatus <> GdPictureStatus.OK Then
|
If oStatus <> GdPictureStatus.OK Then
|
||||||
Throw New MergeDocumentException($"Document could not be converted to PDF/A: {oStatus}")
|
Throw New MergeDocumentException($"Document could not be converted to PDF/A: {oStatus}")
|
||||||
End If
|
End If
|
||||||
|
|||||||
@@ -10,8 +10,8 @@ Public Class ElementModel
|
|||||||
MyBase.New(pState)
|
MyBase.New(pState)
|
||||||
End Sub
|
End Sub
|
||||||
|
|
||||||
Private Function ToElement(pRow As DataRow) As DocReceiverElement
|
Private Function ToElement(pRow As DataRow) As Signature
|
||||||
Return New DocReceiverElement() With {
|
Return New Signature() With {
|
||||||
.Id = pRow.ItemEx("GUID", 0),
|
.Id = pRow.ItemEx("GUID", 0),
|
||||||
.DocumentId = pRow.ItemEx("DOCUMENT_ID", 0),
|
.DocumentId = pRow.ItemEx("DOCUMENT_ID", 0),
|
||||||
.ReceiverId = pRow.ItemEx("RECEIVER_ID", 0),
|
.ReceiverId = pRow.ItemEx("RECEIVER_ID", 0),
|
||||||
@@ -24,7 +24,7 @@ Public Class ElementModel
|
|||||||
}
|
}
|
||||||
End Function
|
End Function
|
||||||
|
|
||||||
Private Function ToElements(pTable As DataTable) As List(Of DocReceiverElement)
|
Private Function ToElements(pTable As DataTable) As List(Of Signature)
|
||||||
Return pTable?.Rows.Cast(Of DataRow).
|
Return pTable?.Rows.Cast(Of DataRow).
|
||||||
Select(AddressOf ToElement).
|
Select(AddressOf ToElement).
|
||||||
ToList()
|
ToList()
|
||||||
@@ -80,7 +80,7 @@ Public Class ElementModel
|
|||||||
End Try
|
End Try
|
||||||
End Function
|
End Function
|
||||||
|
|
||||||
Public Function List(pDocumentId As Integer) As List(Of DocReceiverElement)
|
Public Function List(pDocumentId As Integer) As List(Of Signature)
|
||||||
Try
|
Try
|
||||||
Dim oSql = $"SELECT * FROM [dbo].[TBSIG_DOCUMENT_RECEIVER_ELEMENT] WHERE DOCUMENT_ID = {pDocumentId} ORDER BY PAGE ASC"
|
Dim oSql = $"SELECT * FROM [dbo].[TBSIG_DOCUMENT_RECEIVER_ELEMENT] WHERE DOCUMENT_ID = {pDocumentId} ORDER BY PAGE ASC"
|
||||||
Dim oTable = Database.GetDatatable(oSql)
|
Dim oTable = Database.GetDatatable(oSql)
|
||||||
@@ -93,7 +93,7 @@ Public Class ElementModel
|
|||||||
End Try
|
End Try
|
||||||
End Function
|
End Function
|
||||||
|
|
||||||
Public Function List(pDocumentId As Integer, pReceiverId As Integer) As List(Of DocReceiverElement)
|
Public Function List(pDocumentId As Integer, pReceiverId As Integer) As List(Of Signature)
|
||||||
Try
|
Try
|
||||||
Dim oReceiverConstraint = ""
|
Dim oReceiverConstraint = ""
|
||||||
If pReceiverId > 0 Then
|
If pReceiverId > 0 Then
|
||||||
@@ -111,7 +111,7 @@ Public Class ElementModel
|
|||||||
End Try
|
End Try
|
||||||
End Function
|
End Function
|
||||||
|
|
||||||
Public Function Insert(pElement As DocReceiverElement) As Boolean
|
Public Function Insert(pElement As Signature) As Boolean
|
||||||
Try
|
Try
|
||||||
Dim oSql = "INSERT INTO [dbo].[TBSIG_DOCUMENT_RECEIVER_ELEMENT]
|
Dim oSql = "INSERT INTO [dbo].[TBSIG_DOCUMENT_RECEIVER_ELEMENT]
|
||||||
([DOCUMENT_ID]
|
([DOCUMENT_ID]
|
||||||
@@ -161,7 +161,7 @@ Public Class ElementModel
|
|||||||
End Try
|
End Try
|
||||||
End Function
|
End Function
|
||||||
|
|
||||||
Public Function Update(pElement As DocReceiverElement) As Boolean
|
Public Function Update(pElement As Signature) As Boolean
|
||||||
Try
|
Try
|
||||||
Dim oSql = "UPDATE [dbo].[TBSIG_DOCUMENT_RECEIVER_ELEMENT]
|
Dim oSql = "UPDATE [dbo].[TBSIG_DOCUMENT_RECEIVER_ELEMENT]
|
||||||
SET [POSITION_X] = @POSITION_X
|
SET [POSITION_X] = @POSITION_X
|
||||||
@@ -185,7 +185,7 @@ Public Class ElementModel
|
|||||||
End Try
|
End Try
|
||||||
End Function
|
End Function
|
||||||
|
|
||||||
Private Function GetElementId(pElement As DocReceiverElement) As Integer
|
Private Function GetElementId(pElement As Signature) As Integer
|
||||||
Try
|
Try
|
||||||
Return Database.GetScalarValue($"SELECT MAX(GUID) FROM TBSIG_DOCUMENT_RECEIVER_ELEMENT
|
Return Database.GetScalarValue($"SELECT MAX(GUID) FROM TBSIG_DOCUMENT_RECEIVER_ELEMENT
|
||||||
WHERE DOCUMENT_ID = {pElement.DocumentId} AND RECEIVER_ID = {pElement.ReceiverId}")
|
WHERE DOCUMENT_ID = {pElement.DocumentId} AND RECEIVER_ID = {pElement.ReceiverId}")
|
||||||
@@ -196,7 +196,7 @@ Public Class ElementModel
|
|||||||
End Try
|
End Try
|
||||||
End Function
|
End Function
|
||||||
|
|
||||||
Public Function DeleteElement(pElement As DocReceiverElement) As Boolean
|
Public Function DeleteElement(pElement As Signature) As Boolean
|
||||||
Try
|
Try
|
||||||
Dim oSql = $"DELETE FROM TBSIG_DOCUMENT_RECEIVER_ELEMENT WHERE GUID = {pElement.Id}"
|
Dim oSql = $"DELETE FROM TBSIG_DOCUMENT_RECEIVER_ELEMENT WHERE GUID = {pElement.Id}"
|
||||||
Return Database.ExecuteNonQuery(oSql)
|
Return Database.ExecuteNonQuery(oSql)
|
||||||
|
|||||||
@@ -270,26 +270,12 @@ Public Class ReceiverModel
|
|||||||
Private Function GetSignedDate(pEmailAddress As String, pEnvelopeId As Integer) As Date
|
Private Function GetSignedDate(pEmailAddress As String, pEnvelopeId As Integer) As Date
|
||||||
Try
|
Try
|
||||||
Dim oStatusInt As Integer = EnvelopeStatus.DocumentSigned
|
Dim oStatusInt As Integer = EnvelopeStatus.DocumentSigned
|
||||||
Dim value = Database.GetScalarValue($"SELECT ACTION_DATE FROM [DD_ECM].[dbo].[TBSIG_ENVELOPE_HISTORY] WHERE ENVELOPE_ID = {pEnvelopeId}
|
Return Database.GetScalarValue($"SELECT ACTION_DATE FROM [DD_ECM].[dbo].[TBSIG_ENVELOPE_HISTORY] WHERE ENVELOPE_ID = {pEnvelopeId}
|
||||||
And USER_REFERENCE = '{pEmailAddress}' AND [STATUS] = {oStatusInt}")
|
And USER_REFERENCE = '{pEmailAddress}' AND [STATUS] = {oStatusInt}")
|
||||||
|
|
||||||
If value Is Nothing OrElse value Is DBNull.Value Then
|
|
||||||
Return DateTime.MinValue
|
|
||||||
End If
|
|
||||||
|
|
||||||
If TypeOf value Is DateTime Then
|
|
||||||
Return DirectCast(value, DateTime)
|
|
||||||
End If
|
|
||||||
|
|
||||||
Dim parsedDate As DateTime
|
|
||||||
If DateTime.TryParse(value.ToString(), parsedDate) Then
|
|
||||||
Return parsedDate
|
|
||||||
End If
|
|
||||||
|
|
||||||
Return DateTime.MinValue
|
|
||||||
Catch ex As Exception
|
Catch ex As Exception
|
||||||
Logger.Error(ex)
|
Logger.Error(ex)
|
||||||
Return DateTime.MinValue
|
Return Nothing
|
||||||
End Try
|
End Try
|
||||||
End Function
|
End Function
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
'------------------------------------------------------------------------------
|
'------------------------------------------------------------------------------
|
||||||
' <auto-generated>
|
' <auto-generated>
|
||||||
' This code was generated by a tool.
|
' Dieser Code wurde von einem Tool generiert.
|
||||||
' Runtime Version:4.0.30319.42000
|
' Laufzeitversion:4.0.30319.42000
|
||||||
'
|
'
|
||||||
' Changes to this file may cause incorrect behavior and will be lost if
|
' Änderungen an dieser Datei können falsches Verhalten verursachen und gehen verloren, wenn
|
||||||
' the code is regenerated.
|
' der Code erneut generiert wird.
|
||||||
' </auto-generated>
|
' </auto-generated>
|
||||||
'------------------------------------------------------------------------------
|
'------------------------------------------------------------------------------
|
||||||
|
|
||||||
@@ -15,12 +15,12 @@ Imports System
|
|||||||
|
|
||||||
Namespace My.Resources
|
Namespace My.Resources
|
||||||
|
|
||||||
'This class was auto-generated by the StronglyTypedResourceBuilder
|
'Diese Klasse wurde von der StronglyTypedResourceBuilder automatisch generiert
|
||||||
'class via a tool like ResGen or Visual Studio.
|
'-Klasse über ein Tool wie ResGen oder Visual Studio automatisch generiert.
|
||||||
'To add or remove a member, edit your .ResX file then rerun ResGen
|
'Um einen Member hinzuzufügen oder zu entfernen, bearbeiten Sie die .ResX-Datei und führen dann ResGen
|
||||||
'with the /str option, or rebuild your VS project.
|
'mit der /str-Option erneut aus, oder Sie erstellen Ihr VS-Projekt neu.
|
||||||
'''<summary>
|
'''<summary>
|
||||||
''' A strongly-typed resource class, for looking up localized strings, etc.
|
''' Eine stark typisierte Ressourcenklasse zum Suchen von lokalisierten Zeichenfolgen usw.
|
||||||
'''</summary>
|
'''</summary>
|
||||||
<Global.System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0"), _
|
<Global.System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0"), _
|
||||||
Global.System.Diagnostics.DebuggerNonUserCodeAttribute(), _
|
Global.System.Diagnostics.DebuggerNonUserCodeAttribute(), _
|
||||||
@@ -37,7 +37,7 @@ Namespace My.Resources
|
|||||||
End Sub
|
End Sub
|
||||||
|
|
||||||
'''<summary>
|
'''<summary>
|
||||||
''' Returns the cached ResourceManager instance used by this class.
|
''' Gibt die zwischengespeicherte ResourceManager-Instanz zurück, die von dieser Klasse verwendet wird.
|
||||||
'''</summary>
|
'''</summary>
|
||||||
<Global.System.ComponentModel.EditorBrowsableAttribute(Global.System.ComponentModel.EditorBrowsableState.Advanced)> _
|
<Global.System.ComponentModel.EditorBrowsableAttribute(Global.System.ComponentModel.EditorBrowsableState.Advanced)> _
|
||||||
Public Shared ReadOnly Property ResourceManager() As Global.System.Resources.ResourceManager
|
Public Shared ReadOnly Property ResourceManager() As Global.System.Resources.ResourceManager
|
||||||
@@ -51,8 +51,8 @@ Namespace My.Resources
|
|||||||
End Property
|
End Property
|
||||||
|
|
||||||
'''<summary>
|
'''<summary>
|
||||||
''' Overrides the current thread's CurrentUICulture property for all
|
''' Überschreibt die CurrentUICulture-Eigenschaft des aktuellen Threads für alle
|
||||||
''' resource lookups using this strongly typed resource class.
|
''' Ressourcenzuordnungen, die diese stark typisierte Ressourcenklasse verwenden.
|
||||||
'''</summary>
|
'''</summary>
|
||||||
<Global.System.ComponentModel.EditorBrowsableAttribute(Global.System.ComponentModel.EditorBrowsableState.Advanced)> _
|
<Global.System.ComponentModel.EditorBrowsableAttribute(Global.System.ComponentModel.EditorBrowsableState.Advanced)> _
|
||||||
Public Shared Property Culture() As Global.System.Globalization.CultureInfo
|
Public Shared Property Culture() As Global.System.Globalization.CultureInfo
|
||||||
@@ -65,7 +65,7 @@ Namespace My.Resources
|
|||||||
End Property
|
End Property
|
||||||
|
|
||||||
'''<summary>
|
'''<summary>
|
||||||
''' Looks up a localized string similar to Zugriffscode korrekt eingegeben.
|
''' Sucht eine lokalisierte Zeichenfolge, die Zugriffscode korrekt eingegeben ähnelt.
|
||||||
'''</summary>
|
'''</summary>
|
||||||
Public Shared ReadOnly Property AccessCodeCorrect() As String
|
Public Shared ReadOnly Property AccessCodeCorrect() As String
|
||||||
Get
|
Get
|
||||||
@@ -74,7 +74,7 @@ Namespace My.Resources
|
|||||||
End Property
|
End Property
|
||||||
|
|
||||||
'''<summary>
|
'''<summary>
|
||||||
''' Looks up a localized string similar to Zugriffscode falsch eingegeben.
|
''' Sucht eine lokalisierte Zeichenfolge, die Zugriffscode falsch eingegeben ähnelt.
|
||||||
'''</summary>
|
'''</summary>
|
||||||
Public Shared ReadOnly Property AccessCodeIncorrect() As String
|
Public Shared ReadOnly Property AccessCodeIncorrect() As String
|
||||||
Get
|
Get
|
||||||
@@ -83,7 +83,7 @@ Namespace My.Resources
|
|||||||
End Property
|
End Property
|
||||||
|
|
||||||
'''<summary>
|
'''<summary>
|
||||||
''' Looks up a localized string similar to Zugriffscode angefordert.
|
''' Sucht eine lokalisierte Zeichenfolge, die Zugriffscode angefordert ähnelt.
|
||||||
'''</summary>
|
'''</summary>
|
||||||
Public Shared ReadOnly Property AccessCodeRequested() As String
|
Public Shared ReadOnly Property AccessCodeRequested() As String
|
||||||
Get
|
Get
|
||||||
@@ -92,7 +92,7 @@ Namespace My.Resources
|
|||||||
End Property
|
End Property
|
||||||
|
|
||||||
'''<summary>
|
'''<summary>
|
||||||
''' Looks up a localized string similar to Fortgeschrittene Elektronische Signatur.
|
''' Sucht eine lokalisierte Zeichenfolge, die Fortgeschrittene Elektronische Signatur ähnelt.
|
||||||
'''</summary>
|
'''</summary>
|
||||||
Public Shared ReadOnly Property AdvancedElectronicSignature() As String
|
Public Shared ReadOnly Property AdvancedElectronicSignature() As String
|
||||||
Get
|
Get
|
||||||
@@ -101,7 +101,7 @@ Namespace My.Resources
|
|||||||
End Property
|
End Property
|
||||||
|
|
||||||
'''<summary>
|
'''<summary>
|
||||||
''' Looks up a localized string similar to Abgeschlossen.
|
''' Sucht eine lokalisierte Zeichenfolge, die Abgeschlossen ähnelt.
|
||||||
'''</summary>
|
'''</summary>
|
||||||
Public Shared ReadOnly Property Completed() As String
|
Public Shared ReadOnly Property Completed() As String
|
||||||
Get
|
Get
|
||||||
@@ -110,16 +110,7 @@ Namespace My.Resources
|
|||||||
End Property
|
End Property
|
||||||
|
|
||||||
'''<summary>
|
'''<summary>
|
||||||
''' Looks up a localized string similar to Vollständig bestätigt.
|
''' Sucht eine lokalisierte Zeichenfolge, die Vollständig Signiert ähnelt.
|
||||||
'''</summary>
|
|
||||||
Public Shared ReadOnly Property CompletelyConfirmed() As String
|
|
||||||
Get
|
|
||||||
Return ResourceManager.GetString("CompletelyConfirmed", resourceCulture)
|
|
||||||
End Get
|
|
||||||
End Property
|
|
||||||
|
|
||||||
'''<summary>
|
|
||||||
''' Looks up a localized string similar to Vollständig signiert.
|
|
||||||
'''</summary>
|
'''</summary>
|
||||||
Public Shared ReadOnly Property CompletelySigned() As String
|
Public Shared ReadOnly Property CompletelySigned() As String
|
||||||
Get
|
Get
|
||||||
@@ -128,25 +119,7 @@ Namespace My.Resources
|
|||||||
End Property
|
End Property
|
||||||
|
|
||||||
'''<summary>
|
'''<summary>
|
||||||
''' Looks up a localized string similar to Lesebestätigung.
|
''' Sucht eine lokalisierte Zeichenfolge, die Vertrag ähnelt.
|
||||||
'''</summary>
|
|
||||||
Public Shared ReadOnly Property Confirmation() As String
|
|
||||||
Get
|
|
||||||
Return ResourceManager.GetString("Confirmation", resourceCulture)
|
|
||||||
End Get
|
|
||||||
End Property
|
|
||||||
|
|
||||||
'''<summary>
|
|
||||||
''' Looks up a localized string similar to Gelesen und Bestätigt.
|
|
||||||
'''</summary>
|
|
||||||
Public Shared ReadOnly Property Confirmed() As String
|
|
||||||
Get
|
|
||||||
Return ResourceManager.GetString("Confirmed", resourceCulture)
|
|
||||||
End Get
|
|
||||||
End Property
|
|
||||||
|
|
||||||
'''<summary>
|
|
||||||
''' Looks up a localized string similar to Vertrag.
|
|
||||||
'''</summary>
|
'''</summary>
|
||||||
Public Shared ReadOnly Property Contract() As String
|
Public Shared ReadOnly Property Contract() As String
|
||||||
Get
|
Get
|
||||||
@@ -155,7 +128,7 @@ Namespace My.Resources
|
|||||||
End Property
|
End Property
|
||||||
|
|
||||||
'''<summary>
|
'''<summary>
|
||||||
''' Looks up a localized string similar to Erstellt.
|
''' Sucht eine lokalisierte Zeichenfolge, die Erstellt ähnelt.
|
||||||
'''</summary>
|
'''</summary>
|
||||||
Public Shared ReadOnly Property Created() As String
|
Public Shared ReadOnly Property Created() As String
|
||||||
Get
|
Get
|
||||||
@@ -164,16 +137,7 @@ Namespace My.Resources
|
|||||||
End Property
|
End Property
|
||||||
|
|
||||||
'''<summary>
|
'''<summary>
|
||||||
''' Looks up a localized string similar to Dokument gelesen und bestätigt.
|
''' Sucht eine lokalisierte Zeichenfolge, die Dokument Rotation geändert ähnelt.
|
||||||
'''</summary>
|
|
||||||
Public Shared ReadOnly Property DocumentConfirmed() As String
|
|
||||||
Get
|
|
||||||
Return ResourceManager.GetString("DocumentConfirmed", resourceCulture)
|
|
||||||
End Get
|
|
||||||
End Property
|
|
||||||
|
|
||||||
'''<summary>
|
|
||||||
''' Looks up a localized string similar to Dokument Rotation geändert.
|
|
||||||
'''</summary>
|
'''</summary>
|
||||||
Public Shared ReadOnly Property DocumentMod_Rotation() As String
|
Public Shared ReadOnly Property DocumentMod_Rotation() As String
|
||||||
Get
|
Get
|
||||||
@@ -182,7 +146,7 @@ Namespace My.Resources
|
|||||||
End Property
|
End Property
|
||||||
|
|
||||||
'''<summary>
|
'''<summary>
|
||||||
''' Looks up a localized string similar to Dokument geöffnet.
|
''' Sucht eine lokalisierte Zeichenfolge, die Dokument geöffnet ähnelt.
|
||||||
'''</summary>
|
'''</summary>
|
||||||
Public Shared ReadOnly Property DocumentOpened() As String
|
Public Shared ReadOnly Property DocumentOpened() As String
|
||||||
Get
|
Get
|
||||||
@@ -191,7 +155,7 @@ Namespace My.Resources
|
|||||||
End Property
|
End Property
|
||||||
|
|
||||||
'''<summary>
|
'''<summary>
|
||||||
''' Looks up a localized string similar to Unterzeichnung abgelehnt.
|
''' Sucht eine lokalisierte Zeichenfolge, die Unterzeichnung abgelehnt ähnelt.
|
||||||
'''</summary>
|
'''</summary>
|
||||||
Public Shared ReadOnly Property DocumentRejected() As String
|
Public Shared ReadOnly Property DocumentRejected() As String
|
||||||
Get
|
Get
|
||||||
@@ -200,16 +164,7 @@ Namespace My.Resources
|
|||||||
End Property
|
End Property
|
||||||
|
|
||||||
'''<summary>
|
'''<summary>
|
||||||
''' Looks up a localized string similar to Lesebestätigung abgelehnt.
|
''' Sucht eine lokalisierte Zeichenfolge, die Dokument unterzeichnet ähnelt.
|
||||||
'''</summary>
|
|
||||||
Public Shared ReadOnly Property DocumentRejectedRaC() As String
|
|
||||||
Get
|
|
||||||
Return ResourceManager.GetString("DocumentRejectedRaC", resourceCulture)
|
|
||||||
End Get
|
|
||||||
End Property
|
|
||||||
|
|
||||||
'''<summary>
|
|
||||||
''' Looks up a localized string similar to Dokument unterzeichnet.
|
|
||||||
'''</summary>
|
'''</summary>
|
||||||
Public Shared ReadOnly Property DocumentSigned() As String
|
Public Shared ReadOnly Property DocumentSigned() As String
|
||||||
Get
|
Get
|
||||||
@@ -218,7 +173,7 @@ Namespace My.Resources
|
|||||||
End Property
|
End Property
|
||||||
|
|
||||||
'''<summary>
|
'''<summary>
|
||||||
''' Looks up a localized string similar to Entwurf.
|
''' Sucht eine lokalisierte Zeichenfolge, die Entwurf ähnelt.
|
||||||
'''</summary>
|
'''</summary>
|
||||||
Public Shared ReadOnly Property Draft() As String
|
Public Shared ReadOnly Property Draft() As String
|
||||||
Get
|
Get
|
||||||
@@ -227,7 +182,7 @@ Namespace My.Resources
|
|||||||
End Property
|
End Property
|
||||||
|
|
||||||
'''<summary>
|
'''<summary>
|
||||||
''' Looks up a localized string similar to Archiviert.
|
''' Sucht eine lokalisierte Zeichenfolge, die Archiviert ähnelt.
|
||||||
'''</summary>
|
'''</summary>
|
||||||
Public Shared ReadOnly Property EnvelopeArchived() As String
|
Public Shared ReadOnly Property EnvelopeArchived() As String
|
||||||
Get
|
Get
|
||||||
@@ -236,16 +191,7 @@ Namespace My.Resources
|
|||||||
End Property
|
End Property
|
||||||
|
|
||||||
'''<summary>
|
'''<summary>
|
||||||
''' Looks up a localized string similar to Vollständig bestätigt.
|
''' Sucht eine lokalisierte Zeichenfolge, die Vollständig signiert ähnelt.
|
||||||
'''</summary>
|
|
||||||
Public Shared ReadOnly Property EnvelopeCompletelyConfirmed() As String
|
|
||||||
Get
|
|
||||||
Return ResourceManager.GetString("EnvelopeCompletelyConfirmed", resourceCulture)
|
|
||||||
End Get
|
|
||||||
End Property
|
|
||||||
|
|
||||||
'''<summary>
|
|
||||||
''' Looks up a localized string similar to Vollständig signiert.
|
|
||||||
'''</summary>
|
'''</summary>
|
||||||
Public Shared ReadOnly Property EnvelopeCompletelySigned() As String
|
Public Shared ReadOnly Property EnvelopeCompletelySigned() As String
|
||||||
Get
|
Get
|
||||||
@@ -254,7 +200,7 @@ Namespace My.Resources
|
|||||||
End Property
|
End Property
|
||||||
|
|
||||||
'''<summary>
|
'''<summary>
|
||||||
''' Looks up a localized string similar to Umschlag Erstellt.
|
''' Sucht eine lokalisierte Zeichenfolge, die Umschlag Erstellt ähnelt.
|
||||||
'''</summary>
|
'''</summary>
|
||||||
Public Shared ReadOnly Property EnvelopeCreated() As String
|
Public Shared ReadOnly Property EnvelopeCreated() As String
|
||||||
Get
|
Get
|
||||||
@@ -263,7 +209,7 @@ Namespace My.Resources
|
|||||||
End Property
|
End Property
|
||||||
|
|
||||||
'''<summary>
|
'''<summary>
|
||||||
''' Looks up a localized string similar to Umschlag Gelöscht.
|
''' Sucht eine lokalisierte Zeichenfolge, die Umschlag Gelöscht ähnelt.
|
||||||
'''</summary>
|
'''</summary>
|
||||||
Public Shared ReadOnly Property EnvelopeDeleted() As String
|
Public Shared ReadOnly Property EnvelopeDeleted() As String
|
||||||
Get
|
Get
|
||||||
@@ -272,16 +218,7 @@ Namespace My.Resources
|
|||||||
End Property
|
End Property
|
||||||
|
|
||||||
'''<summary>
|
'''<summary>
|
||||||
''' Looks up a localized string similar to Teil-Bestätigt.
|
''' Sucht eine lokalisierte Zeichenfolge, die Teil-Signiert ähnelt.
|
||||||
'''</summary>
|
|
||||||
Public Shared ReadOnly Property EnvelopePartlyConfirmed() As String
|
|
||||||
Get
|
|
||||||
Return ResourceManager.GetString("EnvelopePartlyConfirmed", resourceCulture)
|
|
||||||
End Get
|
|
||||||
End Property
|
|
||||||
|
|
||||||
'''<summary>
|
|
||||||
''' Looks up a localized string similar to Teil-Signiert.
|
|
||||||
'''</summary>
|
'''</summary>
|
||||||
Public Shared ReadOnly Property EnvelopePartlySigned() As String
|
Public Shared ReadOnly Property EnvelopePartlySigned() As String
|
||||||
Get
|
Get
|
||||||
@@ -290,7 +227,7 @@ Namespace My.Resources
|
|||||||
End Property
|
End Property
|
||||||
|
|
||||||
'''<summary>
|
'''<summary>
|
||||||
''' Looks up a localized string similar to Umschlag in Queue.
|
''' Sucht eine lokalisierte Zeichenfolge, die Umschlag in Queue ähnelt.
|
||||||
'''</summary>
|
'''</summary>
|
||||||
Public Shared ReadOnly Property EnvelopeQueued() As String
|
Public Shared ReadOnly Property EnvelopeQueued() As String
|
||||||
Get
|
Get
|
||||||
@@ -299,7 +236,7 @@ Namespace My.Resources
|
|||||||
End Property
|
End Property
|
||||||
|
|
||||||
'''<summary>
|
'''<summary>
|
||||||
''' Looks up a localized string similar to Umschlag abgelehnt.
|
''' Sucht eine lokalisierte Zeichenfolge, die Umschlag abgelehnt ähnelt.
|
||||||
'''</summary>
|
'''</summary>
|
||||||
Public Shared ReadOnly Property EnvelopeRejected() As String
|
Public Shared ReadOnly Property EnvelopeRejected() As String
|
||||||
Get
|
Get
|
||||||
@@ -308,7 +245,7 @@ Namespace My.Resources
|
|||||||
End Property
|
End Property
|
||||||
|
|
||||||
'''<summary>
|
'''<summary>
|
||||||
''' Looks up a localized string similar to Signierungszertifikat erstellt.
|
''' Sucht eine lokalisierte Zeichenfolge, die Signierungszertifikat erstellt ähnelt.
|
||||||
'''</summary>
|
'''</summary>
|
||||||
Public Shared ReadOnly Property EnvelopeReportCreated() As String
|
Public Shared ReadOnly Property EnvelopeReportCreated() As String
|
||||||
Get
|
Get
|
||||||
@@ -317,16 +254,7 @@ Namespace My.Resources
|
|||||||
End Property
|
End Property
|
||||||
|
|
||||||
'''<summary>
|
'''<summary>
|
||||||
''' Looks up a localized string similar to Lesebestätigungszertifikat erstellt.
|
''' Sucht eine lokalisierte Zeichenfolge, die Gespeichert ähnelt.
|
||||||
'''</summary>
|
|
||||||
Public Shared ReadOnly Property EnvelopeReportCreatedRaC() As String
|
|
||||||
Get
|
|
||||||
Return ResourceManager.GetString("EnvelopeReportCreatedRaC", resourceCulture)
|
|
||||||
End Get
|
|
||||||
End Property
|
|
||||||
|
|
||||||
'''<summary>
|
|
||||||
''' Looks up a localized string similar to Gespeichert.
|
|
||||||
'''</summary>
|
'''</summary>
|
||||||
Public Shared ReadOnly Property EnvelopeSaved() As String
|
Public Shared ReadOnly Property EnvelopeSaved() As String
|
||||||
Get
|
Get
|
||||||
@@ -335,7 +263,7 @@ Namespace My.Resources
|
|||||||
End Property
|
End Property
|
||||||
|
|
||||||
'''<summary>
|
'''<summary>
|
||||||
''' Looks up a localized string similar to Gesendet.
|
''' Sucht eine lokalisierte Zeichenfolge, die Gesendet ähnelt.
|
||||||
'''</summary>
|
'''</summary>
|
||||||
Public Shared ReadOnly Property EnvelopeSent() As String
|
Public Shared ReadOnly Property EnvelopeSent() As String
|
||||||
Get
|
Get
|
||||||
@@ -344,7 +272,7 @@ Namespace My.Resources
|
|||||||
End Property
|
End Property
|
||||||
|
|
||||||
'''<summary>
|
'''<summary>
|
||||||
''' Looks up a localized string similar to Umschlag zurückgezogen.
|
''' Sucht eine lokalisierte Zeichenfolge, die Umschlag zurückgezogen ähnelt.
|
||||||
'''</summary>
|
'''</summary>
|
||||||
Public Shared ReadOnly Property EnvelopeWithdrawn() As String
|
Public Shared ReadOnly Property EnvelopeWithdrawn() As String
|
||||||
Get
|
Get
|
||||||
@@ -353,7 +281,7 @@ Namespace My.Resources
|
|||||||
End Property
|
End Property
|
||||||
|
|
||||||
'''<summary>
|
'''<summary>
|
||||||
''' Looks up a localized string similar to Zugriffscode versendet.
|
''' Sucht eine lokalisierte Zeichenfolge, die Zugriffscode versendet ähnelt.
|
||||||
'''</summary>
|
'''</summary>
|
||||||
Public Shared ReadOnly Property MessageAccessCodeSent() As String
|
Public Shared ReadOnly Property MessageAccessCodeSent() As String
|
||||||
Get
|
Get
|
||||||
@@ -362,7 +290,7 @@ Namespace My.Resources
|
|||||||
End Property
|
End Property
|
||||||
|
|
||||||
'''<summary>
|
'''<summary>
|
||||||
''' Looks up a localized string similar to Abschlussemail versendet.
|
''' Sucht eine lokalisierte Zeichenfolge, die Abschlussemail versendet ähnelt.
|
||||||
'''</summary>
|
'''</summary>
|
||||||
Public Shared ReadOnly Property MessageCompletionSent() As String
|
Public Shared ReadOnly Property MessageCompletionSent() As String
|
||||||
Get
|
Get
|
||||||
@@ -371,7 +299,7 @@ Namespace My.Resources
|
|||||||
End Property
|
End Property
|
||||||
|
|
||||||
'''<summary>
|
'''<summary>
|
||||||
''' Looks up a localized string similar to Signaturbestätigung versendet.
|
''' Sucht eine lokalisierte Zeichenfolge, die Signaturbestätigung versendet ähnelt.
|
||||||
'''</summary>
|
'''</summary>
|
||||||
Public Shared ReadOnly Property MessageConfirmationSent() As String
|
Public Shared ReadOnly Property MessageConfirmationSent() As String
|
||||||
Get
|
Get
|
||||||
@@ -380,16 +308,7 @@ Namespace My.Resources
|
|||||||
End Property
|
End Property
|
||||||
|
|
||||||
'''<summary>
|
'''<summary>
|
||||||
''' Looks up a localized string similar to Lesebestätigung versendet.
|
''' Sucht eine lokalisierte Zeichenfolge, die Löschinformation versendet ähnelt.
|
||||||
'''</summary>
|
|
||||||
Public Shared ReadOnly Property MessageConfirmationSentRaC() As String
|
|
||||||
Get
|
|
||||||
Return ResourceManager.GetString("MessageConfirmationSentRaC", resourceCulture)
|
|
||||||
End Get
|
|
||||||
End Property
|
|
||||||
|
|
||||||
'''<summary>
|
|
||||||
''' Looks up a localized string similar to Löschinformation versendet.
|
|
||||||
'''</summary>
|
'''</summary>
|
||||||
Public Shared ReadOnly Property MessageDeletionSent() As String
|
Public Shared ReadOnly Property MessageDeletionSent() As String
|
||||||
Get
|
Get
|
||||||
@@ -398,7 +317,7 @@ Namespace My.Resources
|
|||||||
End Property
|
End Property
|
||||||
|
|
||||||
'''<summary>
|
'''<summary>
|
||||||
''' Looks up a localized string similar to Dokumentenlink versendet.
|
''' Sucht eine lokalisierte Zeichenfolge, die Dokumentenlink versendet ähnelt.
|
||||||
'''</summary>
|
'''</summary>
|
||||||
Public Shared ReadOnly Property MessageInvitationSent() As String
|
Public Shared ReadOnly Property MessageInvitationSent() As String
|
||||||
Get
|
Get
|
||||||
@@ -407,7 +326,7 @@ Namespace My.Resources
|
|||||||
End Property
|
End Property
|
||||||
|
|
||||||
'''<summary>
|
'''<summary>
|
||||||
''' Looks up a localized string similar to Nein.
|
''' Sucht eine lokalisierte Zeichenfolge, die Nein ähnelt.
|
||||||
'''</summary>
|
'''</summary>
|
||||||
Public Shared ReadOnly Property No() As String
|
Public Shared ReadOnly Property No() As String
|
||||||
Get
|
Get
|
||||||
@@ -416,16 +335,7 @@ Namespace My.Resources
|
|||||||
End Property
|
End Property
|
||||||
|
|
||||||
'''<summary>
|
'''<summary>
|
||||||
''' Looks up a localized string similar to Teil-Bestätigt.
|
''' Sucht eine lokalisierte Zeichenfolge, die Teil-Signiert ähnelt.
|
||||||
'''</summary>
|
|
||||||
Public Shared ReadOnly Property PartlyConfirmed() As String
|
|
||||||
Get
|
|
||||||
Return ResourceManager.GetString("PartlyConfirmed", resourceCulture)
|
|
||||||
End Get
|
|
||||||
End Property
|
|
||||||
|
|
||||||
'''<summary>
|
|
||||||
''' Looks up a localized string similar to Teil-Signiert.
|
|
||||||
'''</summary>
|
'''</summary>
|
||||||
Public Shared ReadOnly Property PartlySigned() As String
|
Public Shared ReadOnly Property PartlySigned() As String
|
||||||
Get
|
Get
|
||||||
@@ -434,7 +344,7 @@ Namespace My.Resources
|
|||||||
End Property
|
End Property
|
||||||
|
|
||||||
'''<summary>
|
'''<summary>
|
||||||
''' Looks up a localized string similar to Qualifizierte Signatur.
|
''' Sucht eine lokalisierte Zeichenfolge, die Qualifizierte Signatur ähnelt.
|
||||||
'''</summary>
|
'''</summary>
|
||||||
Public Shared ReadOnly Property QualifiedSignature() As String
|
Public Shared ReadOnly Property QualifiedSignature() As String
|
||||||
Get
|
Get
|
||||||
@@ -443,7 +353,7 @@ Namespace My.Resources
|
|||||||
End Property
|
End Property
|
||||||
|
|
||||||
'''<summary>
|
'''<summary>
|
||||||
''' Looks up a localized string similar to Lesebestätigung.
|
''' Sucht eine lokalisierte Zeichenfolge, die Arbeitsanweisung ähnelt.
|
||||||
'''</summary>
|
'''</summary>
|
||||||
Public Shared ReadOnly Property ReadAndSign() As String
|
Public Shared ReadOnly Property ReadAndSign() As String
|
||||||
Get
|
Get
|
||||||
@@ -452,7 +362,7 @@ Namespace My.Resources
|
|||||||
End Property
|
End Property
|
||||||
|
|
||||||
'''<summary>
|
'''<summary>
|
||||||
''' Looks up a localized string similar to Wollen Sie die 2-Faktor Definition für diesen Empfänger zurücksetzen. Der Empfänger muss sich dann neu identifizieren!.
|
''' Sucht eine lokalisierte Zeichenfolge, die Wollen Sie die 2-Faktor Definition für diesen Empfänger zurücksetzen. Der Empfänger muss sich dann neu identifizieren! ähnelt.
|
||||||
'''</summary>
|
'''</summary>
|
||||||
Public Shared ReadOnly Property ResetTOTPUser() As String
|
Public Shared ReadOnly Property ResetTOTPUser() As String
|
||||||
Get
|
Get
|
||||||
@@ -461,7 +371,7 @@ Namespace My.Resources
|
|||||||
End Property
|
End Property
|
||||||
|
|
||||||
'''<summary>
|
'''<summary>
|
||||||
''' Looks up a localized string similar to Gespeichert.
|
''' Sucht eine lokalisierte Zeichenfolge, die Gespeichert ähnelt.
|
||||||
'''</summary>
|
'''</summary>
|
||||||
Public Shared ReadOnly Property Saved() As String
|
Public Shared ReadOnly Property Saved() As String
|
||||||
Get
|
Get
|
||||||
@@ -470,7 +380,7 @@ Namespace My.Resources
|
|||||||
End Property
|
End Property
|
||||||
|
|
||||||
'''<summary>
|
'''<summary>
|
||||||
''' Looks up a localized string similar to Gesendet.
|
''' Sucht eine lokalisierte Zeichenfolge, die Gesendet ähnelt.
|
||||||
'''</summary>
|
'''</summary>
|
||||||
Public Shared ReadOnly Property Sent() As String
|
Public Shared ReadOnly Property Sent() As String
|
||||||
Get
|
Get
|
||||||
@@ -479,7 +389,7 @@ Namespace My.Resources
|
|||||||
End Property
|
End Property
|
||||||
|
|
||||||
'''<summary>
|
'''<summary>
|
||||||
''' Looks up a localized string similar to Signatur.
|
''' Sucht eine lokalisierte Zeichenfolge, die Signatur ähnelt.
|
||||||
'''</summary>
|
'''</summary>
|
||||||
Public Shared ReadOnly Property Signature() As String
|
Public Shared ReadOnly Property Signature() As String
|
||||||
Get
|
Get
|
||||||
@@ -488,7 +398,7 @@ Namespace My.Resources
|
|||||||
End Property
|
End Property
|
||||||
|
|
||||||
'''<summary>
|
'''<summary>
|
||||||
''' Looks up a localized string similar to Abschluss bestätigt.
|
''' Sucht eine lokalisierte Zeichenfolge, die Signatur bestätigt ähnelt.
|
||||||
'''</summary>
|
'''</summary>
|
||||||
Public Shared ReadOnly Property SignatureConfirmed() As String
|
Public Shared ReadOnly Property SignatureConfirmed() As String
|
||||||
Get
|
Get
|
||||||
@@ -497,7 +407,7 @@ Namespace My.Resources
|
|||||||
End Property
|
End Property
|
||||||
|
|
||||||
'''<summary>
|
'''<summary>
|
||||||
''' Looks up a localized string similar to Signiert.
|
''' Sucht eine lokalisierte Zeichenfolge, die Signiert ähnelt.
|
||||||
'''</summary>
|
'''</summary>
|
||||||
Public Shared ReadOnly Property Signed() As String
|
Public Shared ReadOnly Property Signed() As String
|
||||||
Get
|
Get
|
||||||
@@ -506,7 +416,7 @@ Namespace My.Resources
|
|||||||
End Property
|
End Property
|
||||||
|
|
||||||
'''<summary>
|
'''<summary>
|
||||||
''' Looks up a localized string similar to Erfolgreich! Dialog wird geschlossen..
|
''' Sucht eine lokalisierte Zeichenfolge, die Erfolgreich! Dialog wird geschlossen. ähnelt.
|
||||||
'''</summary>
|
'''</summary>
|
||||||
Public Shared ReadOnly Property Success_FormClose() As String
|
Public Shared ReadOnly Property Success_FormClose() As String
|
||||||
Get
|
Get
|
||||||
@@ -515,7 +425,7 @@ Namespace My.Resources
|
|||||||
End Property
|
End Property
|
||||||
|
|
||||||
'''<summary>
|
'''<summary>
|
||||||
''' Looks up a localized string similar to Unsigniert.
|
''' Sucht eine lokalisierte Zeichenfolge, die Unsigniert ähnelt.
|
||||||
'''</summary>
|
'''</summary>
|
||||||
Public Shared ReadOnly Property Unsigned() As String
|
Public Shared ReadOnly Property Unsigned() As String
|
||||||
Get
|
Get
|
||||||
@@ -524,7 +434,7 @@ Namespace My.Resources
|
|||||||
End Property
|
End Property
|
||||||
|
|
||||||
'''<summary>
|
'''<summary>
|
||||||
''' Looks up a localized string similar to Ja.
|
''' Sucht eine lokalisierte Zeichenfolge, die Ja ähnelt.
|
||||||
'''</summary>
|
'''</summary>
|
||||||
Public Shared ReadOnly Property Yes() As String
|
Public Shared ReadOnly Property Yes() As String
|
||||||
Get
|
Get
|
||||||
@@ -533,7 +443,7 @@ Namespace My.Resources
|
|||||||
End Property
|
End Property
|
||||||
|
|
||||||
'''<summary>
|
'''<summary>
|
||||||
''' Looks up a localized string similar to Ja, mit Anhang.
|
''' Sucht eine lokalisierte Zeichenfolge, die Ja, mit Anhang ähnelt.
|
||||||
'''</summary>
|
'''</summary>
|
||||||
Public Shared ReadOnly Property YesWithAttachment() As String
|
Public Shared ReadOnly Property YesWithAttachment() As String
|
||||||
Get
|
Get
|
||||||
|
|||||||
@@ -132,27 +132,12 @@
|
|||||||
<data name="Completed" xml:space="preserve">
|
<data name="Completed" xml:space="preserve">
|
||||||
<value>Completed</value>
|
<value>Completed</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="CompletelyConfirmed" xml:space="preserve">
|
|
||||||
<value>Completely confirmed</value>
|
|
||||||
</data>
|
|
||||||
<data name="CompletelySigned" xml:space="preserve">
|
|
||||||
<value>Completely signed</value>
|
|
||||||
</data>
|
|
||||||
<data name="Confirmation" xml:space="preserve">
|
|
||||||
<value>Read Confirmation</value>
|
|
||||||
</data>
|
|
||||||
<data name="Confirmed" xml:space="preserve">
|
|
||||||
<value>Read and signed</value>
|
|
||||||
</data>
|
|
||||||
<data name="Contract" xml:space="preserve">
|
<data name="Contract" xml:space="preserve">
|
||||||
<value>Contract</value>
|
<value>Contract</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Created" xml:space="preserve">
|
<data name="Created" xml:space="preserve">
|
||||||
<value>Created</value>
|
<value>Created</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="DocumentConfirmed" xml:space="preserve">
|
|
||||||
<value>Document read and confirmed</value>
|
|
||||||
</data>
|
|
||||||
<data name="DocumentMod_Rotation" xml:space="preserve">
|
<data name="DocumentMod_Rotation" xml:space="preserve">
|
||||||
<value>Document rotation adapted</value>
|
<value>Document rotation adapted</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -162,9 +147,6 @@
|
|||||||
<data name="DocumentRejected" xml:space="preserve">
|
<data name="DocumentRejected" xml:space="preserve">
|
||||||
<value>Signing rejected</value>
|
<value>Signing rejected</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="DocumentRejectedRaC" xml:space="preserve">
|
|
||||||
<value>Read confirmation rejected</value>
|
|
||||||
</data>
|
|
||||||
<data name="DocumentSigned" xml:space="preserve">
|
<data name="DocumentSigned" xml:space="preserve">
|
||||||
<value>Document signed</value>
|
<value>Document signed</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -174,9 +156,6 @@
|
|||||||
<data name="EnvelopeArchived" xml:space="preserve">
|
<data name="EnvelopeArchived" xml:space="preserve">
|
||||||
<value>Archived</value>
|
<value>Archived</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="EnvelopeCompletelyConfirmed" xml:space="preserve">
|
|
||||||
<value>Completely confirmed</value>
|
|
||||||
</data>
|
|
||||||
<data name="EnvelopeCompletelySigned" xml:space="preserve">
|
<data name="EnvelopeCompletelySigned" xml:space="preserve">
|
||||||
<value>Completely signed</value>
|
<value>Completely signed</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -186,11 +165,8 @@
|
|||||||
<data name="EnvelopeDeleted" xml:space="preserve">
|
<data name="EnvelopeDeleted" xml:space="preserve">
|
||||||
<value>Envelope Deleted</value>
|
<value>Envelope Deleted</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="EnvelopePartlyConfirmed" xml:space="preserve">
|
|
||||||
<value>Partially confirmed</value>
|
|
||||||
</data>
|
|
||||||
<data name="EnvelopePartlySigned" xml:space="preserve">
|
<data name="EnvelopePartlySigned" xml:space="preserve">
|
||||||
<value>Partially signed</value>
|
<value>Partly signed</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="EnvelopeQueued" xml:space="preserve">
|
<data name="EnvelopeQueued" xml:space="preserve">
|
||||||
<value>Envelope Queued</value>
|
<value>Envelope Queued</value>
|
||||||
@@ -201,9 +177,6 @@
|
|||||||
<data name="EnvelopeReportCreated" xml:space="preserve">
|
<data name="EnvelopeReportCreated" xml:space="preserve">
|
||||||
<value>Signature certificate created</value>
|
<value>Signature certificate created</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="EnvelopeReportCreatedRaC" xml:space="preserve">
|
|
||||||
<value>Read Confirmation Certificate Created</value>
|
|
||||||
</data>
|
|
||||||
<data name="EnvelopeSaved" xml:space="preserve">
|
<data name="EnvelopeSaved" xml:space="preserve">
|
||||||
<value>Saved</value>
|
<value>Saved</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -222,9 +195,6 @@
|
|||||||
<data name="MessageConfirmationSent" xml:space="preserve">
|
<data name="MessageConfirmationSent" xml:space="preserve">
|
||||||
<value>Confirmation Sent</value>
|
<value>Confirmation Sent</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="MessageConfirmationSentRaC" xml:space="preserve">
|
|
||||||
<value>Read Confirmation Sent</value>
|
|
||||||
</data>
|
|
||||||
<data name="MessageDeletionSent" xml:space="preserve">
|
<data name="MessageDeletionSent" xml:space="preserve">
|
||||||
<value>Deletion Notice Sent</value>
|
<value>Deletion Notice Sent</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -234,12 +204,6 @@
|
|||||||
<data name="No" xml:space="preserve">
|
<data name="No" xml:space="preserve">
|
||||||
<value>No</value>
|
<value>No</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="PartlyConfirmed" xml:space="preserve">
|
|
||||||
<value>Partially confirmed</value>
|
|
||||||
</data>
|
|
||||||
<data name="PartlySigned" xml:space="preserve">
|
|
||||||
<value>Partially signed</value>
|
|
||||||
</data>
|
|
||||||
<data name="QualifiedSignature" xml:space="preserve">
|
<data name="QualifiedSignature" xml:space="preserve">
|
||||||
<value>Qualified Signature</value>
|
<value>Qualified Signature</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -259,7 +223,7 @@
|
|||||||
<value>Signature</value>
|
<value>Signature</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="SignatureConfirmed" xml:space="preserve">
|
<data name="SignatureConfirmed" xml:space="preserve">
|
||||||
<value>Finalization confirmed</value>
|
<value>Signature confirmed</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Signed" xml:space="preserve">
|
<data name="Signed" xml:space="preserve">
|
||||||
<value>Signed</value>
|
<value>Signed</value>
|
||||||
|
|||||||
@@ -132,17 +132,8 @@
|
|||||||
<data name="Completed" xml:space="preserve">
|
<data name="Completed" xml:space="preserve">
|
||||||
<value>Abgeschlossen</value>
|
<value>Abgeschlossen</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="CompletelyConfirmed" xml:space="preserve">
|
|
||||||
<value>Vollständig bestätigt</value>
|
|
||||||
</data>
|
|
||||||
<data name="CompletelySigned" xml:space="preserve">
|
<data name="CompletelySigned" xml:space="preserve">
|
||||||
<value>Vollständig signiert</value>
|
<value>Vollständig Signiert</value>
|
||||||
</data>
|
|
||||||
<data name="Confirmation" xml:space="preserve">
|
|
||||||
<value>Lesebestätigung</value>
|
|
||||||
</data>
|
|
||||||
<data name="Confirmed" xml:space="preserve">
|
|
||||||
<value>Gelesen und Bestätigt</value>
|
|
||||||
</data>
|
</data>
|
||||||
<data name="Contract" xml:space="preserve">
|
<data name="Contract" xml:space="preserve">
|
||||||
<value>Vertrag</value>
|
<value>Vertrag</value>
|
||||||
@@ -150,9 +141,6 @@
|
|||||||
<data name="Created" xml:space="preserve">
|
<data name="Created" xml:space="preserve">
|
||||||
<value>Erstellt</value>
|
<value>Erstellt</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="DocumentConfirmed" xml:space="preserve">
|
|
||||||
<value>Dokument gelesen und bestätigt</value>
|
|
||||||
</data>
|
|
||||||
<data name="DocumentMod_Rotation" xml:space="preserve">
|
<data name="DocumentMod_Rotation" xml:space="preserve">
|
||||||
<value>Dokument Rotation geändert</value>
|
<value>Dokument Rotation geändert</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -162,9 +150,6 @@
|
|||||||
<data name="DocumentRejected" xml:space="preserve">
|
<data name="DocumentRejected" xml:space="preserve">
|
||||||
<value>Unterzeichnung abgelehnt</value>
|
<value>Unterzeichnung abgelehnt</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="DocumentRejectedRaC" xml:space="preserve">
|
|
||||||
<value>Lesebestätigung abgelehnt</value>
|
|
||||||
</data>
|
|
||||||
<data name="DocumentSigned" xml:space="preserve">
|
<data name="DocumentSigned" xml:space="preserve">
|
||||||
<value>Dokument unterzeichnet</value>
|
<value>Dokument unterzeichnet</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -174,9 +159,6 @@
|
|||||||
<data name="EnvelopeArchived" xml:space="preserve">
|
<data name="EnvelopeArchived" xml:space="preserve">
|
||||||
<value>Archiviert</value>
|
<value>Archiviert</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="EnvelopeCompletelyConfirmed" xml:space="preserve">
|
|
||||||
<value>Vollständig bestätigt</value>
|
|
||||||
</data>
|
|
||||||
<data name="EnvelopeCompletelySigned" xml:space="preserve">
|
<data name="EnvelopeCompletelySigned" xml:space="preserve">
|
||||||
<value>Vollständig signiert</value>
|
<value>Vollständig signiert</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -186,9 +168,6 @@
|
|||||||
<data name="EnvelopeDeleted" xml:space="preserve">
|
<data name="EnvelopeDeleted" xml:space="preserve">
|
||||||
<value>Umschlag Gelöscht</value>
|
<value>Umschlag Gelöscht</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="EnvelopePartlyConfirmed" xml:space="preserve">
|
|
||||||
<value>Teil-Bestätigt</value>
|
|
||||||
</data>
|
|
||||||
<data name="EnvelopePartlySigned" xml:space="preserve">
|
<data name="EnvelopePartlySigned" xml:space="preserve">
|
||||||
<value>Teil-Signiert</value>
|
<value>Teil-Signiert</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -201,9 +180,6 @@
|
|||||||
<data name="EnvelopeReportCreated" xml:space="preserve">
|
<data name="EnvelopeReportCreated" xml:space="preserve">
|
||||||
<value>Signierungszertifikat erstellt</value>
|
<value>Signierungszertifikat erstellt</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="EnvelopeReportCreatedRaC" xml:space="preserve">
|
|
||||||
<value>Lesebestätigungszertifikat erstellt</value>
|
|
||||||
</data>
|
|
||||||
<data name="EnvelopeSaved" xml:space="preserve">
|
<data name="EnvelopeSaved" xml:space="preserve">
|
||||||
<value>Gespeichert</value>
|
<value>Gespeichert</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -222,9 +198,6 @@
|
|||||||
<data name="MessageConfirmationSent" xml:space="preserve">
|
<data name="MessageConfirmationSent" xml:space="preserve">
|
||||||
<value>Signaturbestätigung versendet</value>
|
<value>Signaturbestätigung versendet</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="MessageConfirmationSentRaC" xml:space="preserve">
|
|
||||||
<value>Lesebestätigung versendet</value>
|
|
||||||
</data>
|
|
||||||
<data name="MessageDeletionSent" xml:space="preserve">
|
<data name="MessageDeletionSent" xml:space="preserve">
|
||||||
<value>Löschinformation versendet</value>
|
<value>Löschinformation versendet</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -234,9 +207,6 @@
|
|||||||
<data name="No" xml:space="preserve">
|
<data name="No" xml:space="preserve">
|
||||||
<value>Nein</value>
|
<value>Nein</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="PartlyConfirmed" xml:space="preserve">
|
|
||||||
<value>Teil-Bestätigt</value>
|
|
||||||
</data>
|
|
||||||
<data name="PartlySigned" xml:space="preserve">
|
<data name="PartlySigned" xml:space="preserve">
|
||||||
<value>Teil-Signiert</value>
|
<value>Teil-Signiert</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -244,7 +214,7 @@
|
|||||||
<value>Qualifizierte Signatur</value>
|
<value>Qualifizierte Signatur</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="ReadAndSign" xml:space="preserve">
|
<data name="ReadAndSign" xml:space="preserve">
|
||||||
<value>Lesebestätigung</value>
|
<value>Arbeitsanweisung</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="ResetTOTPUser" xml:space="preserve">
|
<data name="ResetTOTPUser" xml:space="preserve">
|
||||||
<value>Wollen Sie die 2-Faktor Definition für diesen Empfänger zurücksetzen. Der Empfänger muss sich dann neu identifizieren!</value>
|
<value>Wollen Sie die 2-Faktor Definition für diesen Empfänger zurücksetzen. Der Empfänger muss sich dann neu identifizieren!</value>
|
||||||
@@ -259,7 +229,7 @@
|
|||||||
<value>Signatur</value>
|
<value>Signatur</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="SignatureConfirmed" xml:space="preserve">
|
<data name="SignatureConfirmed" xml:space="preserve">
|
||||||
<value>Abschluss bestätigt</value>
|
<value>Signatur bestätigt</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Signed" xml:space="preserve">
|
<data name="Signed" xml:space="preserve">
|
||||||
<value>Signiert</value>
|
<value>Signiert</value>
|
||||||
|
|||||||
@@ -1,145 +0,0 @@
|
|||||||
using Microsoft.Extensions.Configuration;
|
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
|
||||||
using EnvelopeGenerator.Application;
|
|
||||||
using EnvelopeGenerator.Application.Common.Interfaces.Services;
|
|
||||||
using EnvelopeGenerator.Application.Services;
|
|
||||||
using EnvelopeGenerator.Infrastructure;
|
|
||||||
using DigitalData.EmailProfilerDispatcher;
|
|
||||||
using DigitalData.UserManager.DependencyInjection;
|
|
||||||
|
|
||||||
namespace EnvelopeGenerator.DependencyInjection;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Controls which optional services are registered by <see cref="DependencyInjection.AddEnvelopeGenerator"/>.
|
|
||||||
/// All flags default to <c>true</c>. Set a flag to <c>false</c> if the consuming project
|
|
||||||
/// already registers that service itself or simply does not need it.
|
|
||||||
/// </summary>
|
|
||||||
public sealed class EnvelopeGeneratorOptions
|
|
||||||
{
|
|
||||||
/// <summary>Calls <c>AddHttpContextAccessor()</c>. Default: <c>true</c>.</summary>
|
|
||||||
public bool AddHttpContextAccessor { get; set; } = true;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Calls <c>AddDistributedSqlServerCache()</c> with the supplied <see cref="SqlCacheOptions"/>.
|
|
||||||
/// Requires <see cref="SqlCacheOptions"/> to be configured. Default: <c>true</c>.
|
|
||||||
/// </summary>
|
|
||||||
public bool AddDistributedSqlServerCache { get; set; } = true;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Options for the distributed SQL Server cache.
|
|
||||||
/// Required when <see cref="AddDistributedSqlServerCache"/> is <c>true</c>.
|
|
||||||
/// </summary>
|
|
||||||
public SqlCacheOptions? SqlCacheOptions { get; set; }
|
|
||||||
|
|
||||||
/// <summary>Calls <c>AddDispatcher<TDbContext>()</c>. Default: <c>true</c>.</summary>
|
|
||||||
public bool AddDispatcher { get; set; } = true;
|
|
||||||
|
|
||||||
/// <summary>Calls <c>AddMemoryCache()</c>. Default: <c>true</c>.</summary>
|
|
||||||
public bool AddMemoryCache { get; set; } = true;
|
|
||||||
|
|
||||||
/// <summary>Calls <c>AddUserManager<TDbContext>()</c>. Default: <c>true</c>.</summary>
|
|
||||||
public bool AddUserManager { get; set; } = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>Options for <c>AddDistributedSqlServerCache</c>.</summary>
|
|
||||||
public sealed class SqlCacheOptions
|
|
||||||
{
|
|
||||||
/// <summary>SQL Server connection string.</summary>
|
|
||||||
public string ConnectionString { get; set; } = string.Empty;
|
|
||||||
|
|
||||||
/// <summary>Schema name. Default: <c>dbo</c>.</summary>
|
|
||||||
public string SchemaName { get; set; } = "dbo";
|
|
||||||
|
|
||||||
/// <summary>Table name. Default: <c>TBDD_CACHE</c>.</summary>
|
|
||||||
public string TableName { get; set; } = "TBDD_CACHE";
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Extension methods for registering EnvelopeGenerator services into an <see cref="IServiceCollection"/>.
|
|
||||||
/// Use <see cref="AddEnvelopeGenerator{TDbContext}"/> as the single entry-point for projects that need both the
|
|
||||||
/// application layer (MediatR, AutoMapper, CRUD services, configuration sections) and the infrastructure
|
|
||||||
/// layer (repositories, DbContext, SQL executors).
|
|
||||||
/// For projects that do not need a database (e.g. lightweight API gateways or unit-test hosts), use
|
|
||||||
/// <see cref="AddEnvelopeGeneratorCore"/> to register only the application layer.
|
|
||||||
/// </summary>
|
|
||||||
public static class DependencyInjection
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Registers the full EnvelopeGenerator stack using <see cref="EGDbContext"/> as the DbContext type.
|
|
||||||
/// </summary>
|
|
||||||
public static IServiceCollection AddEnvelopeGenerator(
|
|
||||||
this IServiceCollection services,
|
|
||||||
IConfiguration configuration,
|
|
||||||
Action<EnvelopeGenerator.Infrastructure.DependencyInjection.Config>? infrastructureOptions = null,
|
|
||||||
Action<EnvelopeGeneratorOptions>? options = null)
|
|
||||||
{
|
|
||||||
var opt = new EnvelopeGeneratorOptions();
|
|
||||||
options?.Invoke(opt);
|
|
||||||
|
|
||||||
#pragma warning disable CS0618
|
|
||||||
// Application layer: CRUD services, MediatR, AutoMapper, configuration sections.
|
|
||||||
services.AddEnvelopeGeneratorServices(configuration);
|
|
||||||
|
|
||||||
// Infrastructure layer: repositories, DbContext, Dapper type maps, SQL executors.
|
|
||||||
services.AddEnvelopeGeneratorInfrastructureServices(cfg =>
|
|
||||||
{
|
|
||||||
infrastructureOptions?.Invoke(cfg);
|
|
||||||
});
|
|
||||||
#pragma warning restore CS0618
|
|
||||||
|
|
||||||
if (opt.AddHttpContextAccessor)
|
|
||||||
services.AddHttpContextAccessor();
|
|
||||||
|
|
||||||
if (opt.AddDistributedSqlServerCache && opt.SqlCacheOptions is { } cacheOpts)
|
|
||||||
services.AddDistributedSqlServerCache(o =>
|
|
||||||
{
|
|
||||||
o.ConnectionString = cacheOpts.ConnectionString;
|
|
||||||
o.SchemaName = cacheOpts.SchemaName;
|
|
||||||
o.TableName = cacheOpts.TableName;
|
|
||||||
});
|
|
||||||
|
|
||||||
if (opt.AddDispatcher)
|
|
||||||
services.AddDispatcher<EGDbContext>();
|
|
||||||
|
|
||||||
if (opt.AddMemoryCache)
|
|
||||||
services.AddMemoryCache();
|
|
||||||
|
|
||||||
#pragma warning disable CS0618
|
|
||||||
if (opt.AddUserManager)
|
|
||||||
services.AddUserManager<EGDbContext>();
|
|
||||||
#pragma warning restore CS0618
|
|
||||||
|
|
||||||
return services;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Registers only the <em>application</em> layer services (MediatR handlers, AutoMapper profiles,
|
|
||||||
/// CRUD services, configuration sections) without any infrastructure / database dependencies.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="services">Service collection to register services into.</param>
|
|
||||||
/// <param name="configuration">Application configuration used to bind application-level option sections.</param>
|
|
||||||
/// <returns>The updated <see cref="IServiceCollection"/>.</returns>
|
|
||||||
#pragma warning disable CS0618
|
|
||||||
public static IServiceCollection AddEnvelopeGeneratorCore(
|
|
||||||
this IServiceCollection services,
|
|
||||||
IConfiguration configuration)
|
|
||||||
{
|
|
||||||
services.AddEnvelopeGeneratorServices(configuration);
|
|
||||||
return services;
|
|
||||||
}
|
|
||||||
#pragma warning restore CS0618
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Registers <see cref="EnvelopeMailService"/> as the <see cref="IEnvelopeMailService"/> scoped
|
|
||||||
/// implementation.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="services">Service collection to register services into.</param>
|
|
||||||
/// <returns>The updated <see cref="IServiceCollection"/>.</returns>
|
|
||||||
#pragma warning disable CS0618
|
|
||||||
public static IServiceCollection AddEnvelopeMailService(this IServiceCollection services)
|
|
||||||
{
|
|
||||||
services.AddScoped<IEnvelopeMailService, EnvelopeMailService>();
|
|
||||||
return services;
|
|
||||||
}
|
|
||||||
#pragma warning restore CS0618
|
|
||||||
}
|
|
||||||
@@ -1,176 +0,0 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
|
||||||
|
|
||||||
<PropertyGroup>
|
|
||||||
<TargetFrameworks>net7.0;net8.0;net9.0</TargetFrameworks>
|
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
|
||||||
<Nullable>enable</Nullable>
|
|
||||||
|
|
||||||
<!-- NuGet package metadata -->
|
|
||||||
<PackageId>EnvelopeGenerator</PackageId>
|
|
||||||
<Authors>Digital Data GmbH</Authors>
|
|
||||||
<Company>Digital Data GmbH</Company>
|
|
||||||
<Product>EnvelopeGenerator</Product>
|
|
||||||
<Description>
|
|
||||||
Envelope Generator ist eine Bibliothek zur Verwaltung und Verarbeitung digitaler Umschläge (Envelopes).
|
|
||||||
Dieses Paket enthält die Dependency-Injection-Erweiterungsmethoden und bündelt die Application-
|
|
||||||
sowie Infrastructure-Schicht in einer einzigen NuGet-Referenz.
|
|
||||||
</Description>
|
|
||||||
<Copyright>Copyright 2024 Digital Data GmbH</Copyright>
|
|
||||||
<RepositoryUrl>http://git.dd:3000/AppStd/EnvelopeGenerator.git</RepositoryUrl>
|
|
||||||
<PackageTags>digital data envelope generator di dependency injection</PackageTags>
|
|
||||||
<PackageRequireLicenseAcceptance>false</PackageRequireLicenseAcceptance>
|
|
||||||
<Version>1.2.0.3</Version>
|
|
||||||
<AssemblyVersion>1.2.0.3</AssemblyVersion>
|
|
||||||
<FileVersion>1.2.0.3</FileVersion>
|
|
||||||
<GeneratePackageOnBuild>false</GeneratePackageOnBuild>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
<!-- ASP.NET Core shared framework (AddHttpContextAccessor, AddMemoryCache, etc.) -->
|
|
||||||
<ItemGroup>
|
|
||||||
<FrameworkReference Include="Microsoft.AspNetCore.App" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<!--
|
|
||||||
All dependencies are declared here.
|
|
||||||
Because Application and Infrastructure DLLs are bundled via PrivateAssets=all,
|
|
||||||
their PackageReferences have been moved to this project so that the correct
|
|
||||||
dependencies are written to the nuspec and a consuming project works with
|
|
||||||
a single package install.
|
|
||||||
-->
|
|
||||||
<ItemGroup>
|
|
||||||
<!-- DigitalData BaGet packages -->
|
|
||||||
<PackageReference Include="DigitalData.Core.Abstraction.Application" Version="1.6.0" />
|
|
||||||
<PackageReference Include="DigitalData.Core.Application" Version="3.4.0" />
|
|
||||||
<PackageReference Include="DigitalData.Core.Client" Version="2.1.0" />
|
|
||||||
<PackageReference Include="DigitalData.Core.Exceptions" Version="1.1.0" />
|
|
||||||
<PackageReference Include="DigitalData.Core.Infrastructure" Version="2.6.1" />
|
|
||||||
<PackageReference Include="DigitalData.EmailProfilerDispatcher" Version="3.1.1" />
|
|
||||||
<PackageReference Include="UserManager" Version="1.1.3" />
|
|
||||||
|
|
||||||
<!-- ORM / Database -->
|
|
||||||
<PackageReference Include="Dapper" Version="2.1.66" />
|
|
||||||
<PackageReference Include="Microsoft.Data.SqlClient" Version="5.2.2" />
|
|
||||||
|
|
||||||
<!-- Application services -->
|
|
||||||
<PackageReference Include="MediatR" Version="12.5.0" />
|
|
||||||
<PackageReference Include="QRCoder" Version="1.6.0" />
|
|
||||||
<PackageReference Include="QRCoder-ImageSharp" Version="0.10.0" />
|
|
||||||
<PackageReference Include="QuestPDF" Version="2025.7.1" />
|
|
||||||
<PackageReference Include="Otp.NET" Version="1.4.0" />
|
|
||||||
|
|
||||||
<!-- Security / Identity -->
|
|
||||||
<PackageReference Include="Microsoft.Identity.Client" Version="4.82.1" />
|
|
||||||
|
|
||||||
<!-- Utilities -->
|
|
||||||
<PackageReference Include="HtmlSanitizer" Version="9.0.892" />
|
|
||||||
<PackageReference Include="SixLabors.ImageSharp" Version="3.1.12" />
|
|
||||||
<PackageReference Include="System.Formats.Asn1" Version="10.0.3" />
|
|
||||||
<PackageReference Include="System.Security.AccessControl" Version="6.0.1" />
|
|
||||||
|
|
||||||
<!-- DI abstractions -->
|
|
||||||
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="9.0.6" />
|
|
||||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="9.0.6" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<!-- TFM-specific packages -->
|
|
||||||
<ItemGroup Condition="'$(TargetFramework)' == 'net7.0'">
|
|
||||||
<PackageReference Include="AutoMapper" Version="13.0.1" />
|
|
||||||
<PackageReference Include="CommandDotNet" Version="7.0.5" />
|
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="7.0.20" />
|
|
||||||
<PackageReference Include="Microsoft.Extensions.Caching.SqlServer" Version="7.0.20" />
|
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="7.0.20" />
|
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="7.0.20" />
|
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="7.0.20" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup Condition="'$(TargetFramework)' == 'net8.0'">
|
|
||||||
<PackageReference Include="AutoMapper" Version="14.0.0" />
|
|
||||||
<PackageReference Include="CommandDotNet" Version="8.1.1" />
|
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="8.0.17" />
|
|
||||||
<PackageReference Include="Microsoft.Extensions.Caching.SqlServer" Version="8.0.17" />
|
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.17" />
|
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="8.0.17" />
|
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="8.0.17" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup Condition="'$(TargetFramework)' == 'net9.0'">
|
|
||||||
<PackageReference Include="AutoMapper" Version="14.0.0" />
|
|
||||||
<PackageReference Include="CommandDotNet" Version="8.1.1" />
|
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="9.0.6" />
|
|
||||||
<PackageReference Include="Microsoft.Extensions.Caching.SqlServer" Version="9.0.6" />
|
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="9.0.6" />
|
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="9.0.6" />
|
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="9.0.6" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<ProjectReference Include="..\EnvelopeGenerator.Application\EnvelopeGenerator.Application.csproj">
|
|
||||||
<PrivateAssets>all</PrivateAssets>
|
|
||||||
</ProjectReference>
|
|
||||||
<ProjectReference Include="..\EnvelopeGenerator.Domain\EnvelopeGenerator.Domain.csproj">
|
|
||||||
<PrivateAssets>all</PrivateAssets>
|
|
||||||
</ProjectReference>
|
|
||||||
<ProjectReference Include="..\EnvelopeGenerator.Infrastructure\EnvelopeGenerator.Infrastructure.csproj">
|
|
||||||
<PrivateAssets>all</PrivateAssets>
|
|
||||||
</ProjectReference>
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<!-- Bundle dependency DLLs into the package lib folder -->
|
|
||||||
<Target Name="IncludeDependencyDlls" BeforeTargets="_GetPackageFiles">
|
|
||||||
<ItemGroup>
|
|
||||||
<_DepDlls Include="
 ..\EnvelopeGenerator.Application\bin\$(Configuration)\%(ProjectReference.TargetFramework)\EnvelopeGenerator.Application.dll;
 ..\EnvelopeGenerator.Domain\bin\$(Configuration)\%(ProjectReference.TargetFramework)\EnvelopeGenerator.Domain.dll;
 ..\EnvelopeGenerator.Infrastructure\bin\$(Configuration)\%(ProjectReference.TargetFramework)\EnvelopeGenerator.Infrastructure.dll" />
|
|
||||||
</ItemGroup>
|
|
||||||
</Target>
|
|
||||||
|
|
||||||
<!--
|
|
||||||
Rebuild all dependency projects for every TFM before packing so that
|
|
||||||
the DLLs bundled into the package are always up-to-date.
|
|
||||||
Run with: dotnet pack -c Release
|
|
||||||
-->
|
|
||||||
<Target Name="RebuildDependenciesBeforePack" BeforeTargets="GenerateNuspec">
|
|
||||||
<MSBuild Projects="..\EnvelopeGenerator.Application\EnvelopeGenerator.Application.csproj"
|
|
||||||
Targets="Build"
|
|
||||||
Properties="Configuration=$(Configuration);TargetFramework=net7.0" />
|
|
||||||
<MSBuild Projects="..\EnvelopeGenerator.Application\EnvelopeGenerator.Application.csproj"
|
|
||||||
Targets="Build"
|
|
||||||
Properties="Configuration=$(Configuration);TargetFramework=net8.0" />
|
|
||||||
<MSBuild Projects="..\EnvelopeGenerator.Application\EnvelopeGenerator.Application.csproj"
|
|
||||||
Targets="Build"
|
|
||||||
Properties="Configuration=$(Configuration);TargetFramework=net9.0" />
|
|
||||||
|
|
||||||
<MSBuild Projects="..\EnvelopeGenerator.Domain\EnvelopeGenerator.Domain.csproj"
|
|
||||||
Targets="Build"
|
|
||||||
Properties="Configuration=$(Configuration);TargetFramework=net7.0" />
|
|
||||||
<MSBuild Projects="..\EnvelopeGenerator.Domain\EnvelopeGenerator.Domain.csproj"
|
|
||||||
Targets="Build"
|
|
||||||
Properties="Configuration=$(Configuration);TargetFramework=net8.0" />
|
|
||||||
<MSBuild Projects="..\EnvelopeGenerator.Domain\EnvelopeGenerator.Domain.csproj"
|
|
||||||
Targets="Build"
|
|
||||||
Properties="Configuration=$(Configuration);TargetFramework=net9.0" />
|
|
||||||
|
|
||||||
<MSBuild Projects="..\EnvelopeGenerator.Infrastructure\EnvelopeGenerator.Infrastructure.csproj"
|
|
||||||
Targets="Build"
|
|
||||||
Properties="Configuration=$(Configuration);TargetFramework=net7.0" />
|
|
||||||
<MSBuild Projects="..\EnvelopeGenerator.Infrastructure\EnvelopeGenerator.Infrastructure.csproj"
|
|
||||||
Targets="Build"
|
|
||||||
Properties="Configuration=$(Configuration);TargetFramework=net8.0" />
|
|
||||||
<MSBuild Projects="..\EnvelopeGenerator.Infrastructure\EnvelopeGenerator.Infrastructure.csproj"
|
|
||||||
Targets="Build"
|
|
||||||
Properties="Configuration=$(Configuration);TargetFramework=net9.0" />
|
|
||||||
</Target>
|
|
||||||
|
|
||||||
<Target Name="BundleReferencedDlls" AfterTargets="Build">
|
|
||||||
<ItemGroup>
|
|
||||||
<BuildOutputInPackage Include="..\EnvelopeGenerator.Application\bin\$(Configuration)\net7.0\EnvelopeGenerator.Application.dll" TargetFramework="net7.0" />
|
|
||||||
<BuildOutputInPackage Include="..\EnvelopeGenerator.Application\bin\$(Configuration)\net8.0\EnvelopeGenerator.Application.dll" TargetFramework="net8.0" />
|
|
||||||
<BuildOutputInPackage Include="..\EnvelopeGenerator.Application\bin\$(Configuration)\net9.0\EnvelopeGenerator.Application.dll" TargetFramework="net9.0" />
|
|
||||||
<BuildOutputInPackage Include="..\EnvelopeGenerator.Domain\bin\$(Configuration)\net7.0\EnvelopeGenerator.Domain.dll" TargetFramework="net7.0" />
|
|
||||||
<BuildOutputInPackage Include="..\EnvelopeGenerator.Domain\bin\$(Configuration)\net8.0\EnvelopeGenerator.Domain.dll" TargetFramework="net8.0" />
|
|
||||||
<BuildOutputInPackage Include="..\EnvelopeGenerator.Domain\bin\$(Configuration)\net9.0\EnvelopeGenerator.Domain.dll" TargetFramework="net9.0" />
|
|
||||||
<BuildOutputInPackage Include="..\EnvelopeGenerator.Infrastructure\bin\$(Configuration)\net7.0\EnvelopeGenerator.Infrastructure.dll" TargetFramework="net7.0" />
|
|
||||||
<BuildOutputInPackage Include="..\EnvelopeGenerator.Infrastructure\bin\$(Configuration)\net8.0\EnvelopeGenerator.Infrastructure.dll" TargetFramework="net8.0" />
|
|
||||||
<BuildOutputInPackage Include="..\EnvelopeGenerator.Infrastructure\bin\$(Configuration)\net9.0\EnvelopeGenerator.Infrastructure.dll" TargetFramework="net9.0" />
|
|
||||||
</ItemGroup>
|
|
||||||
</Target>
|
|
||||||
|
|
||||||
</Project>
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
namespace EnvelopeGenerator.Domain.Constants
|
|
||||||
{
|
|
||||||
public enum SenderAppType
|
|
||||||
{
|
|
||||||
LegacyFormApp = 0,
|
|
||||||
ReceiverUIBlazorApp = 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,11 +1,17 @@
|
|||||||
using System.ComponentModel.DataAnnotations;
|
using System.ComponentModel.DataAnnotations;
|
||||||
using System.ComponentModel.DataAnnotations.Schema;
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
|
#if NETFRAMEWORK
|
||||||
|
using System;
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace EnvelopeGenerator.Domain.Entities
|
namespace EnvelopeGenerator.Domain.Entities
|
||||||
{
|
{
|
||||||
[Table("TBSIG_CONFIG", Schema = "dbo")]
|
[Table("TBSIG_CONFIG", Schema = "dbo")]
|
||||||
public class Config
|
public class Config
|
||||||
{
|
{
|
||||||
|
[Column("DOCUMENT_PATH", TypeName = "nvarchar(256)")]
|
||||||
|
public string DocumentPath { get; set; }
|
||||||
|
|
||||||
[Column("SENDING_PROFILE", TypeName = "int")]
|
[Column("SENDING_PROFILE", TypeName = "int")]
|
||||||
[Required]
|
[Required]
|
||||||
public int SendingProfile { get; set; }
|
public int SendingProfile { get; set; }
|
||||||
@@ -19,5 +25,24 @@ namespace EnvelopeGenerator.Domain.Entities
|
|||||||
|
|
||||||
[Column("EXPORT_PATH", TypeName = "nvarchar(256)")]
|
[Column("EXPORT_PATH", TypeName = "nvarchar(256)")]
|
||||||
public string ExportPath { get; set; }
|
public string ExportPath { get; set; }
|
||||||
|
|
||||||
|
[Column("ADDED_WHEN", TypeName = "datetime")]
|
||||||
|
[Required]
|
||||||
|
public DateTime AddedWhen { get; set; }
|
||||||
|
|
||||||
|
[Column("CHANGED_WHEN", TypeName = "datetime")]
|
||||||
|
public DateTime? ChangedWhen { get; set; }
|
||||||
|
|
||||||
|
[Column("GUID", TypeName = "tinyint")]
|
||||||
|
[Required]
|
||||||
|
public byte Guid { get; set; }
|
||||||
|
|
||||||
|
[Column("DEF_TFA_ENABLED", TypeName = "bit")]
|
||||||
|
[Required]
|
||||||
|
public bool DefTfaEnabled { get; set; }
|
||||||
|
|
||||||
|
[Column("DEF_TFA_WITH_PHONE", TypeName = "bit")]
|
||||||
|
[Required]
|
||||||
|
public bool DefTfaWithPhone { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -18,7 +18,7 @@ namespace EnvelopeGenerator.Domain.Entities
|
|||||||
public Document()
|
public Document()
|
||||||
{
|
{
|
||||||
#if NETFRAMEWORK
|
#if NETFRAMEWORK
|
||||||
Elements = Enumerable.Empty<DocReceiverElement>().ToList();
|
Elements = Enumerable.Empty<Signature>().ToList();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -60,7 +60,7 @@ namespace EnvelopeGenerator.Domain.Entities
|
|||||||
FileNameOriginal { get; set; }
|
FileNameOriginal { get; set; }
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
public virtual List<DocReceiverElement>
|
public virtual List<Signature>
|
||||||
#if nullable
|
#if nullable
|
||||||
?
|
?
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ namespace EnvelopeGenerator.Domain.Entities
|
|||||||
[Column("STATUS")]
|
[Column("STATUS")]
|
||||||
public Constants.DocumentStatus Status { get; set; }
|
public Constants.DocumentStatus Status { get; set; }
|
||||||
|
|
||||||
|
[Required]
|
||||||
[Column("STATUS_CHANGED_WHEN", TypeName = "datetime")]
|
[Column("STATUS_CHANGED_WHEN", TypeName = "datetime")]
|
||||||
public DateTime? StatusChangedWhen { get; set; }
|
public DateTime? StatusChangedWhen { get; set; }
|
||||||
|
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ namespace EnvelopeGenerator.Domain.Entities
|
|||||||
ChangedWho { get; set; }
|
ChangedWho { get; set; }
|
||||||
|
|
||||||
[ForeignKey("ElementId")]
|
[ForeignKey("ElementId")]
|
||||||
public virtual DocReceiverElement
|
public virtual Signature
|
||||||
#if nullable
|
#if nullable
|
||||||
?
|
?
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -76,11 +76,14 @@ namespace EnvelopeGenerator.Domain.Entities
|
|||||||
#if nullable
|
#if nullable
|
||||||
?
|
?
|
||||||
#endif
|
#endif
|
||||||
Title
|
Title { get; set; }
|
||||||
{ get; set; }
|
|
||||||
|
|
||||||
[Column("COMMENT", TypeName = "nvarchar(128)")]
|
[Column("COMMENT", TypeName = "nvarchar(128)")]
|
||||||
public string Comment { get; set; }
|
public string
|
||||||
|
#if nullable
|
||||||
|
?
|
||||||
|
#endif
|
||||||
|
Comment { get; set; }
|
||||||
|
|
||||||
[Column("CONTRACT_TYPE")]
|
[Column("CONTRACT_TYPE")]
|
||||||
public int? ContractType { get; set; }
|
public int? ContractType { get; set; }
|
||||||
@@ -94,7 +97,7 @@ namespace EnvelopeGenerator.Domain.Entities
|
|||||||
public string Language { get; set; }
|
public string Language { get; set; }
|
||||||
|
|
||||||
[Column("SEND_REMINDER_EMAILS")]
|
[Column("SEND_REMINDER_EMAILS")]
|
||||||
public bool? SendReminderEmails { get; set; }
|
public bool SendReminderEmails { get; set; }
|
||||||
|
|
||||||
[Column("FIRST_REMINDER_DAYS")]
|
[Column("FIRST_REMINDER_DAYS")]
|
||||||
public int? FirstReminderDays { get; set; }
|
public int? FirstReminderDays { get; set; }
|
||||||
@@ -114,7 +117,7 @@ namespace EnvelopeGenerator.Domain.Entities
|
|||||||
public int? CertificationType { get; set; }
|
public int? CertificationType { get; set; }
|
||||||
|
|
||||||
[Column("USE_ACCESS_CODE")]
|
[Column("USE_ACCESS_CODE")]
|
||||||
public bool? UseAccessCode { get; set; }
|
public bool UseAccessCode { get; set; }
|
||||||
|
|
||||||
[Column("FINAL_EMAIL_TO_CREATOR")]
|
[Column("FINAL_EMAIL_TO_CREATOR")]
|
||||||
public int? FinalEmailToCreator { get; set; }
|
public int? FinalEmailToCreator { get; set; }
|
||||||
@@ -132,12 +135,14 @@ namespace EnvelopeGenerator.Domain.Entities
|
|||||||
public User User { get; set; }
|
public User User { get; set; }
|
||||||
|
|
||||||
[Column("TFA_ENABLED")]
|
[Column("TFA_ENABLED")]
|
||||||
public bool? TfaEnabled { get; set; }
|
public bool TfaEnabled { get; set; }
|
||||||
#if NETFRAMEWORK
|
#if NETFRAMEWORK
|
||||||
= false;
|
= false;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if NETFRAMEWORK
|
||||||
[NotMapped]
|
[NotMapped]
|
||||||
|
#endif
|
||||||
[Column("DOC_RESULT")]
|
[Column("DOC_RESULT")]
|
||||||
public byte[]
|
public byte[]
|
||||||
#if nullable
|
#if nullable
|
||||||
@@ -151,8 +156,7 @@ namespace EnvelopeGenerator.Domain.Entities
|
|||||||
#if nullable
|
#if nullable
|
||||||
?
|
?
|
||||||
#endif
|
#endif
|
||||||
Type
|
Type { get; set; }
|
||||||
{ get; set; }
|
|
||||||
|
|
||||||
#if NETFRAMEWORK
|
#if NETFRAMEWORK
|
||||||
[NotMapped]
|
[NotMapped]
|
||||||
@@ -166,22 +170,26 @@ namespace EnvelopeGenerator.Domain.Entities
|
|||||||
#if nullable
|
#if nullable
|
||||||
?
|
?
|
||||||
#endif
|
#endif
|
||||||
Documents
|
Documents { get; set; }
|
||||||
{ get; set; }
|
|
||||||
|
[NotMapped]
|
||||||
|
public Document
|
||||||
|
#if nullable
|
||||||
|
?
|
||||||
|
#endif
|
||||||
|
DefaultDocument => Documents?.FirstOrDefault();
|
||||||
|
|
||||||
public List<History>
|
public List<History>
|
||||||
#if nullable
|
#if nullable
|
||||||
?
|
?
|
||||||
#endif
|
#endif
|
||||||
Histories
|
Histories { get; set; }
|
||||||
{ get; set; }
|
|
||||||
|
|
||||||
public List<EnvelopeReceiver>
|
public List<EnvelopeReceiver>
|
||||||
#if nullable
|
#if nullable
|
||||||
?
|
?
|
||||||
#endif
|
#endif
|
||||||
EnvelopeReceivers
|
EnvelopeReceivers { get; set; }
|
||||||
{ get; set; }
|
|
||||||
|
|
||||||
//#if NETFRAMEWORK
|
//#if NETFRAMEWORK
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
36
EnvelopeGenerator.Domain/Entities/EnvelopeReport.cs
Normal file
36
EnvelopeGenerator.Domain/Entities/EnvelopeReport.cs
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
using System;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
|
|
||||||
|
namespace EnvelopeGenerator.Domain.Entities
|
||||||
|
{
|
||||||
|
[Table("VWSIG_ENVELOPE_REPORT", Schema = "dbo")]
|
||||||
|
public class EnvelopeReport
|
||||||
|
{
|
||||||
|
[Column("ENVELOPE_ID", TypeName = "int")]
|
||||||
|
[Required]
|
||||||
|
public int EnvelopeId { get; set; }
|
||||||
|
|
||||||
|
[Column("HEAD_UUID", TypeName = "nvarchar(36)")]
|
||||||
|
[Required]
|
||||||
|
public string HeadUuid { get; set; }
|
||||||
|
|
||||||
|
[Column("HEAD_TITLE", TypeName = "nvarchar(128)")]
|
||||||
|
public string HeadTitle { get; set; }
|
||||||
|
|
||||||
|
[Column("HEAD_MESSAGE", TypeName = "nvarchar(max)")]
|
||||||
|
[Required]
|
||||||
|
public string HeadMessage { get; set; }
|
||||||
|
|
||||||
|
[Column("POS_STATUS", TypeName = "int")]
|
||||||
|
[Required]
|
||||||
|
public int PosStatus { get; set; }
|
||||||
|
|
||||||
|
[Column("POS_WHEN", TypeName = "datetime")]
|
||||||
|
public DateTime? PosWhen { get; set; }
|
||||||
|
|
||||||
|
[Column("POS_WHO", TypeName = "nvarchar(128)")]
|
||||||
|
[Required]
|
||||||
|
public string PosWho { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,6 +4,9 @@ using System.ComponentModel;
|
|||||||
using System.ComponentModel.DataAnnotations;
|
using System.ComponentModel.DataAnnotations;
|
||||||
using System.ComponentModel.DataAnnotations.Schema;
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
using EnvelopeGenerator.Domain.Interfaces.Auditing;
|
using EnvelopeGenerator.Domain.Interfaces.Auditing;
|
||||||
|
#if NET
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
#endif
|
||||||
#if NETFRAMEWORK
|
#if NETFRAMEWORK
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
#endif
|
#endif
|
||||||
@@ -11,9 +14,9 @@ using System.Collections.Generic;
|
|||||||
namespace EnvelopeGenerator.Domain.Entities
|
namespace EnvelopeGenerator.Domain.Entities
|
||||||
{
|
{
|
||||||
[Table("TBSIG_DOCUMENT_RECEIVER_ELEMENT", Schema = "dbo")]
|
[Table("TBSIG_DOCUMENT_RECEIVER_ELEMENT", Schema = "dbo")]
|
||||||
public class DocReceiverElement : IDocReceiverElement, IHasReceiver, IHasAddedWhen, IUpdateAuditable
|
public class Signature : ISignature, IHasReceiver, IHasAddedWhen, IUpdateAuditable
|
||||||
{
|
{
|
||||||
public DocReceiverElement()
|
public Signature()
|
||||||
{
|
{
|
||||||
// TODO: * Check the Form App and remove the default value
|
// TODO: * Check the Form App and remove the default value
|
||||||
#if NETFRAMEWORK
|
#if NETFRAMEWORK
|
||||||
@@ -109,50 +112,25 @@ namespace EnvelopeGenerator.Domain.Entities
|
|||||||
#if nullable
|
#if nullable
|
||||||
?
|
?
|
||||||
#endif
|
#endif
|
||||||
Receiver
|
Receiver { get; set; }
|
||||||
{ get; set; }
|
|
||||||
|
|
||||||
public virtual IEnumerable<ElementAnnotation>
|
public virtual IEnumerable<ElementAnnotation>
|
||||||
#if nullable
|
#if nullable
|
||||||
?
|
?
|
||||||
#endif
|
#endif
|
||||||
Annotations
|
Annotations { get; set; }
|
||||||
{ get; set; }
|
|
||||||
|
|
||||||
#if NETFRAMEWORK
|
#if NET
|
||||||
|
[JsonIgnore]
|
||||||
|
#endif
|
||||||
[NotMapped]
|
[NotMapped]
|
||||||
public double Top => Math.Round(Y, 5);
|
public double Top => Math.Round(Y, 5);
|
||||||
|
|
||||||
|
|
||||||
|
#if NET
|
||||||
|
[JsonIgnore]
|
||||||
|
#endif
|
||||||
[NotMapped]
|
[NotMapped]
|
||||||
public double Left => Math.Round(X, 5);
|
public double Left => Math.Round(X, 5);
|
||||||
#endif
|
|
||||||
|
|
||||||
[Column("FULL_NAME", TypeName = "nvarchar(100)")]
|
|
||||||
public string
|
|
||||||
#if nullable
|
|
||||||
?
|
|
||||||
# endif
|
|
||||||
FullName { get; set; }
|
|
||||||
|
|
||||||
[Column("POSITION", TypeName = "nvarchar(100)")]
|
|
||||||
public string
|
|
||||||
#if nullable
|
|
||||||
?
|
|
||||||
#endif
|
|
||||||
Position { get; set; }
|
|
||||||
|
|
||||||
[Column("PLACE", TypeName = "nvarchar(100)")]
|
|
||||||
public string
|
|
||||||
#if nullable
|
|
||||||
?
|
|
||||||
#endif
|
|
||||||
Place { get; set; }
|
|
||||||
|
|
||||||
[Column("INK", TypeName = "varbinary(MAX)")]
|
|
||||||
public byte[]
|
|
||||||
#if nullable
|
|
||||||
?
|
|
||||||
#endif
|
|
||||||
Ink { get; set; }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -11,10 +11,5 @@
|
|||||||
{
|
{
|
||||||
return envelope.EnvelopeTypeId == 2;
|
return envelope.EnvelopeTypeId == 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool IsReadAndSign(this IEnvelope envelope)
|
|
||||||
{
|
|
||||||
return envelope.EnvelopeTypeId != 2;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
namespace EnvelopeGenerator.Domain.Interfaces
|
namespace EnvelopeGenerator.Domain.Interfaces
|
||||||
{
|
{
|
||||||
public interface IDocReceiverElement
|
public interface ISignature
|
||||||
{
|
{
|
||||||
int Page { get; set; }
|
int Page { get; set; }
|
||||||
|
|
||||||
200
EnvelopeGenerator.Domain/Resources/Model.Designer.cs
generated
200
EnvelopeGenerator.Domain/Resources/Model.Designer.cs
generated
@@ -1,10 +1,10 @@
|
|||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// <auto-generated>
|
// <auto-generated>
|
||||||
// This code was generated by a tool.
|
// Dieser Code wurde von einem Tool generiert.
|
||||||
// Runtime Version:4.0.30319.42000
|
// Laufzeitversion:4.0.30319.42000
|
||||||
//
|
//
|
||||||
// Changes to this file may cause incorrect behavior and will be lost if
|
// Änderungen an dieser Datei können falsches Verhalten verursachen und gehen verloren, wenn
|
||||||
// the code is regenerated.
|
// der Code erneut generiert wird.
|
||||||
// </auto-generated>
|
// </auto-generated>
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
@@ -13,12 +13,12 @@ namespace My.Resources {
|
|||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A strongly-typed resource class, for looking up localized strings, etc.
|
/// Eine stark typisierte Ressourcenklasse zum Suchen von lokalisierten Zeichenfolgen usw.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
// This class was auto-generated by the StronglyTypedResourceBuilder
|
// Diese Klasse wurde von der StronglyTypedResourceBuilder automatisch generiert
|
||||||
// class via a tool like ResGen or Visual Studio.
|
// -Klasse über ein Tool wie ResGen oder Visual Studio automatisch generiert.
|
||||||
// To add or remove a member, edit your .ResX file then rerun ResGen
|
// Um einen Member hinzuzufügen oder zu entfernen, bearbeiten Sie die .ResX-Datei und führen dann ResGen
|
||||||
// with the /str option, or rebuild your VS project.
|
// mit der /str-Option erneut aus, oder Sie erstellen Ihr VS-Projekt neu.
|
||||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
|
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
|
||||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||||
@@ -33,7 +33,7 @@ namespace My.Resources {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns the cached ResourceManager instance used by this class.
|
/// Gibt die zwischengespeicherte ResourceManager-Instanz zurück, die von dieser Klasse verwendet wird.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||||
public static global::System.Resources.ResourceManager ResourceManager {
|
public static global::System.Resources.ResourceManager ResourceManager {
|
||||||
@@ -47,8 +47,8 @@ namespace My.Resources {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Overrides the current thread's CurrentUICulture property for all
|
/// Überschreibt die CurrentUICulture-Eigenschaft des aktuellen Threads für alle
|
||||||
/// resource lookups using this strongly typed resource class.
|
/// Ressourcenzuordnungen, die diese stark typisierte Ressourcenklasse verwenden.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||||
public static global::System.Globalization.CultureInfo Culture {
|
public static global::System.Globalization.CultureInfo Culture {
|
||||||
@@ -61,7 +61,7 @@ namespace My.Resources {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to Zugriffscode korrekt eingegeben.
|
/// Sucht eine lokalisierte Zeichenfolge, die Zugriffscode korrekt eingegeben ähnelt.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static string AccessCodeCorrect {
|
public static string AccessCodeCorrect {
|
||||||
get {
|
get {
|
||||||
@@ -70,7 +70,7 @@ namespace My.Resources {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to Zugriffscode falsch eingegeben.
|
/// Sucht eine lokalisierte Zeichenfolge, die Zugriffscode falsch eingegeben ähnelt.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static string AccessCodeIncorrect {
|
public static string AccessCodeIncorrect {
|
||||||
get {
|
get {
|
||||||
@@ -79,7 +79,7 @@ namespace My.Resources {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to Zugriffscode angefordert.
|
/// Sucht eine lokalisierte Zeichenfolge, die Zugriffscode angefordert ähnelt.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static string AccessCodeRequested {
|
public static string AccessCodeRequested {
|
||||||
get {
|
get {
|
||||||
@@ -88,7 +88,7 @@ namespace My.Resources {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to Fortgeschrittene Elektronische Signatur.
|
/// Sucht eine lokalisierte Zeichenfolge, die Fortgeschrittene Elektronische Signatur ähnelt.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static string AdvancedElectronicSignature {
|
public static string AdvancedElectronicSignature {
|
||||||
get {
|
get {
|
||||||
@@ -97,7 +97,7 @@ namespace My.Resources {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to Abgeschlossen.
|
/// Sucht eine lokalisierte Zeichenfolge, die Abgeschlossen ähnelt.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static string Completed {
|
public static string Completed {
|
||||||
get {
|
get {
|
||||||
@@ -106,16 +106,7 @@ namespace My.Resources {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to Vollständig bestätigt.
|
/// Sucht eine lokalisierte Zeichenfolge, die Vollständig Signiert ähnelt.
|
||||||
/// </summary>
|
|
||||||
public static string CompletelyConfirmed {
|
|
||||||
get {
|
|
||||||
return ResourceManager.GetString("CompletelyConfirmed", resourceCulture);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Looks up a localized string similar to Vollständig signiert.
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static string CompletelySigned {
|
public static string CompletelySigned {
|
||||||
get {
|
get {
|
||||||
@@ -124,25 +115,7 @@ namespace My.Resources {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to Lesebestätigung.
|
/// Sucht eine lokalisierte Zeichenfolge, die Vertrag ähnelt.
|
||||||
/// </summary>
|
|
||||||
public static string Confirmation {
|
|
||||||
get {
|
|
||||||
return ResourceManager.GetString("Confirmation", resourceCulture);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Looks up a localized string similar to Gelesen und bestätigt.
|
|
||||||
/// </summary>
|
|
||||||
public static string Confirmed {
|
|
||||||
get {
|
|
||||||
return ResourceManager.GetString("Confirmed", resourceCulture);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Looks up a localized string similar to Vertrag.
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static string Contract {
|
public static string Contract {
|
||||||
get {
|
get {
|
||||||
@@ -151,7 +124,7 @@ namespace My.Resources {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to Erstellt.
|
/// Sucht eine lokalisierte Zeichenfolge, die Erstellt ähnelt.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static string Created {
|
public static string Created {
|
||||||
get {
|
get {
|
||||||
@@ -160,16 +133,7 @@ namespace My.Resources {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to Dokument gelesen und bestätigt.
|
/// Sucht eine lokalisierte Zeichenfolge, die Dokument Rotation geändert ähnelt.
|
||||||
/// </summary>
|
|
||||||
public static string DocumentConfirmed {
|
|
||||||
get {
|
|
||||||
return ResourceManager.GetString("DocumentConfirmed", resourceCulture);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Looks up a localized string similar to Dokument Rotation geändert.
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static string DocumentMod_Rotation {
|
public static string DocumentMod_Rotation {
|
||||||
get {
|
get {
|
||||||
@@ -178,7 +142,7 @@ namespace My.Resources {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to Dokument geöffnet.
|
/// Sucht eine lokalisierte Zeichenfolge, die Dokument geöffnet ähnelt.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static string DocumentOpened {
|
public static string DocumentOpened {
|
||||||
get {
|
get {
|
||||||
@@ -187,7 +151,7 @@ namespace My.Resources {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to Unterzeichnung abgelehnt.
|
/// Sucht eine lokalisierte Zeichenfolge, die Unterzeichnung abgelehnt ähnelt.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static string DocumentRejected {
|
public static string DocumentRejected {
|
||||||
get {
|
get {
|
||||||
@@ -196,16 +160,7 @@ namespace My.Resources {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to Lesebestätigung abgelehnt.
|
/// Sucht eine lokalisierte Zeichenfolge, die Dokument unterzeichnet ähnelt.
|
||||||
/// </summary>
|
|
||||||
public static string DocumentRejectedRaC {
|
|
||||||
get {
|
|
||||||
return ResourceManager.GetString("DocumentRejectedRaC", resourceCulture);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Looks up a localized string similar to Dokument unterzeichnet.
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static string DocumentSigned {
|
public static string DocumentSigned {
|
||||||
get {
|
get {
|
||||||
@@ -214,7 +169,7 @@ namespace My.Resources {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to Entwurf.
|
/// Sucht eine lokalisierte Zeichenfolge, die Entwurf ähnelt.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static string Draft {
|
public static string Draft {
|
||||||
get {
|
get {
|
||||||
@@ -223,7 +178,7 @@ namespace My.Resources {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to Archiviert.
|
/// Sucht eine lokalisierte Zeichenfolge, die Archiviert ähnelt.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static string EnvelopeArchived {
|
public static string EnvelopeArchived {
|
||||||
get {
|
get {
|
||||||
@@ -232,16 +187,7 @@ namespace My.Resources {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to Vollständig gelesen und bestätigt.
|
/// Sucht eine lokalisierte Zeichenfolge, die Vollständig signiert ähnelt.
|
||||||
/// </summary>
|
|
||||||
public static string EnvelopeCompletelyConfirmed {
|
|
||||||
get {
|
|
||||||
return ResourceManager.GetString("EnvelopeCompletelyConfirmed", resourceCulture);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Looks up a localized string similar to Vollständig signiert.
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static string EnvelopeCompletelySigned {
|
public static string EnvelopeCompletelySigned {
|
||||||
get {
|
get {
|
||||||
@@ -250,7 +196,7 @@ namespace My.Resources {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to Umschlag Erstellt.
|
/// Sucht eine lokalisierte Zeichenfolge, die Umschlag Erstellt ähnelt.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static string EnvelopeCreated {
|
public static string EnvelopeCreated {
|
||||||
get {
|
get {
|
||||||
@@ -259,7 +205,7 @@ namespace My.Resources {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to Umschlag Gelöscht.
|
/// Sucht eine lokalisierte Zeichenfolge, die Umschlag Gelöscht ähnelt.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static string EnvelopeDeleted {
|
public static string EnvelopeDeleted {
|
||||||
get {
|
get {
|
||||||
@@ -268,16 +214,7 @@ namespace My.Resources {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to Teil-Bestätigt.
|
/// Sucht eine lokalisierte Zeichenfolge, die Teil-Signiert ähnelt.
|
||||||
/// </summary>
|
|
||||||
public static string EnvelopePartlyConfirmed {
|
|
||||||
get {
|
|
||||||
return ResourceManager.GetString("EnvelopePartlyConfirmed", resourceCulture);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Looks up a localized string similar to Teil-Signiert.
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static string EnvelopePartlySigned {
|
public static string EnvelopePartlySigned {
|
||||||
get {
|
get {
|
||||||
@@ -286,7 +223,7 @@ namespace My.Resources {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to Umschlag in Queue.
|
/// Sucht eine lokalisierte Zeichenfolge, die Umschlag in Queue ähnelt.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static string EnvelopeQueued {
|
public static string EnvelopeQueued {
|
||||||
get {
|
get {
|
||||||
@@ -295,7 +232,7 @@ namespace My.Resources {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to Umschlag abgelehnt.
|
/// Sucht eine lokalisierte Zeichenfolge, die Umschlag abgelehnt ähnelt.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static string EnvelopeRejected {
|
public static string EnvelopeRejected {
|
||||||
get {
|
get {
|
||||||
@@ -304,7 +241,7 @@ namespace My.Resources {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to Signierungszertifikat erstellt.
|
/// Sucht eine lokalisierte Zeichenfolge, die Signierungszertifikat erstellt ähnelt.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static string EnvelopeReportCreated {
|
public static string EnvelopeReportCreated {
|
||||||
get {
|
get {
|
||||||
@@ -313,16 +250,7 @@ namespace My.Resources {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to Lesebestätigungszertifikat erstellt.
|
/// Sucht eine lokalisierte Zeichenfolge, die Gespeichert ähnelt.
|
||||||
/// </summary>
|
|
||||||
public static string EnvelopeReportCreatedRaC {
|
|
||||||
get {
|
|
||||||
return ResourceManager.GetString("EnvelopeReportCreatedRaC", resourceCulture);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Looks up a localized string similar to Gespeichert.
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static string EnvelopeSaved {
|
public static string EnvelopeSaved {
|
||||||
get {
|
get {
|
||||||
@@ -331,7 +259,7 @@ namespace My.Resources {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to Gesendet.
|
/// Sucht eine lokalisierte Zeichenfolge, die Gesendet ähnelt.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static string EnvelopeSent {
|
public static string EnvelopeSent {
|
||||||
get {
|
get {
|
||||||
@@ -340,7 +268,7 @@ namespace My.Resources {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to Umschlag zurückgezogen.
|
/// Sucht eine lokalisierte Zeichenfolge, die Umschlag zurückgezogen ähnelt.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static string EnvelopeWithdrawn {
|
public static string EnvelopeWithdrawn {
|
||||||
get {
|
get {
|
||||||
@@ -349,7 +277,7 @@ namespace My.Resources {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to Zugriffscode versendet.
|
/// Sucht eine lokalisierte Zeichenfolge, die Zugriffscode versendet ähnelt.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static string MessageAccessCodeSent {
|
public static string MessageAccessCodeSent {
|
||||||
get {
|
get {
|
||||||
@@ -358,7 +286,7 @@ namespace My.Resources {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to Abschlussemail versendet.
|
/// Sucht eine lokalisierte Zeichenfolge, die Abschlussemail versendet ähnelt.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static string MessageCompletionSent {
|
public static string MessageCompletionSent {
|
||||||
get {
|
get {
|
||||||
@@ -367,7 +295,7 @@ namespace My.Resources {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to Abschlussbestätigung versendet.
|
/// Sucht eine lokalisierte Zeichenfolge, die Signaturbestätigung versendet ähnelt.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static string MessageConfirmationSent {
|
public static string MessageConfirmationSent {
|
||||||
get {
|
get {
|
||||||
@@ -376,7 +304,7 @@ namespace My.Resources {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to Löschinformation versendet.
|
/// Sucht eine lokalisierte Zeichenfolge, die Löschinformation versendet ähnelt.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static string MessageDeletionSent {
|
public static string MessageDeletionSent {
|
||||||
get {
|
get {
|
||||||
@@ -385,7 +313,7 @@ namespace My.Resources {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to Dokumentenlink versendet.
|
/// Sucht eine lokalisierte Zeichenfolge, die Dokumentenlink versendet ähnelt.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static string MessageInvitationSent {
|
public static string MessageInvitationSent {
|
||||||
get {
|
get {
|
||||||
@@ -394,7 +322,7 @@ namespace My.Resources {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to Nein.
|
/// Sucht eine lokalisierte Zeichenfolge, die Nein ähnelt.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static string No {
|
public static string No {
|
||||||
get {
|
get {
|
||||||
@@ -403,16 +331,7 @@ namespace My.Resources {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to Teil-Bestätigt.
|
/// Sucht eine lokalisierte Zeichenfolge, die Teil-Signiert ähnelt.
|
||||||
/// </summary>
|
|
||||||
public static string PartlyConfirmed {
|
|
||||||
get {
|
|
||||||
return ResourceManager.GetString("PartlyConfirmed", resourceCulture);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Looks up a localized string similar to Teil-Signiert.
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static string PartlySigned {
|
public static string PartlySigned {
|
||||||
get {
|
get {
|
||||||
@@ -421,7 +340,7 @@ namespace My.Resources {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to Qualifizierte Signatur.
|
/// Sucht eine lokalisierte Zeichenfolge, die Qualifizierte Signatur ähnelt.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static string QualifiedSignature {
|
public static string QualifiedSignature {
|
||||||
get {
|
get {
|
||||||
@@ -430,7 +349,7 @@ namespace My.Resources {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to Lesebestätigung.
|
/// Sucht eine lokalisierte Zeichenfolge, die Arbeitsanweisung ähnelt.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static string ReadAndSign {
|
public static string ReadAndSign {
|
||||||
get {
|
get {
|
||||||
@@ -439,7 +358,7 @@ namespace My.Resources {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to Wollen Sie die 2-Faktor Definition für diesen Empfänger zurücksetzen. Der Empfänger muss sich dann neu identifizieren!.
|
/// Sucht eine lokalisierte Zeichenfolge, die Wollen Sie die 2-Faktor Definition für diesen Empfänger zurücksetzen. Der Empfänger muss sich dann neu identifizieren! ähnelt.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static string ResetTOTPUser {
|
public static string ResetTOTPUser {
|
||||||
get {
|
get {
|
||||||
@@ -448,7 +367,7 @@ namespace My.Resources {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to Gespeichert.
|
/// Sucht eine lokalisierte Zeichenfolge, die Gespeichert ähnelt.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static string Saved {
|
public static string Saved {
|
||||||
get {
|
get {
|
||||||
@@ -457,7 +376,7 @@ namespace My.Resources {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to Gesendet.
|
/// Sucht eine lokalisierte Zeichenfolge, die Gesendet ähnelt.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static string Sent {
|
public static string Sent {
|
||||||
get {
|
get {
|
||||||
@@ -466,7 +385,7 @@ namespace My.Resources {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to Signatur.
|
/// Sucht eine lokalisierte Zeichenfolge, die Signatur ähnelt.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static string Signature {
|
public static string Signature {
|
||||||
get {
|
get {
|
||||||
@@ -475,7 +394,7 @@ namespace My.Resources {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to Abschluss bestätigt.
|
/// Sucht eine lokalisierte Zeichenfolge, die Signatur bestätigt ähnelt.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static string SignatureConfirmed {
|
public static string SignatureConfirmed {
|
||||||
get {
|
get {
|
||||||
@@ -484,7 +403,7 @@ namespace My.Resources {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to Signiert.
|
/// Sucht eine lokalisierte Zeichenfolge, die Signiert ähnelt.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static string Signed {
|
public static string Signed {
|
||||||
get {
|
get {
|
||||||
@@ -493,7 +412,7 @@ namespace My.Resources {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to Erfolgreich! Dialog wird geschlossen..
|
/// Sucht eine lokalisierte Zeichenfolge, die Erfolgreich! Dialog wird geschlossen. ähnelt.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static string Success_FormClose {
|
public static string Success_FormClose {
|
||||||
get {
|
get {
|
||||||
@@ -502,16 +421,7 @@ namespace My.Resources {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to Unbestätigt.
|
/// Sucht eine lokalisierte Zeichenfolge, die Unsigniert ähnelt.
|
||||||
/// </summary>
|
|
||||||
public static string Unconfirmed {
|
|
||||||
get {
|
|
||||||
return ResourceManager.GetString("Unconfirmed", resourceCulture);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Looks up a localized string similar to Unsigniert.
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static string Unsigned {
|
public static string Unsigned {
|
||||||
get {
|
get {
|
||||||
@@ -520,7 +430,7 @@ namespace My.Resources {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to Ja.
|
/// Sucht eine lokalisierte Zeichenfolge, die Ja ähnelt.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static string Yes {
|
public static string Yes {
|
||||||
get {
|
get {
|
||||||
@@ -529,7 +439,7 @@ namespace My.Resources {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to Ja, mit Anhang.
|
/// Sucht eine lokalisierte Zeichenfolge, die Ja, mit Anhang ähnelt.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static string YesWithAttachment {
|
public static string YesWithAttachment {
|
||||||
get {
|
get {
|
||||||
|
|||||||
@@ -132,27 +132,15 @@
|
|||||||
<data name="Completed" xml:space="preserve">
|
<data name="Completed" xml:space="preserve">
|
||||||
<value>Completed</value>
|
<value>Completed</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="CompletelyConfirmed" xml:space="preserve">
|
|
||||||
<value>Completely confirmed</value>
|
|
||||||
</data>
|
|
||||||
<data name="CompletelySigned" xml:space="preserve">
|
<data name="CompletelySigned" xml:space="preserve">
|
||||||
<value>Completely signed</value>
|
<value>Completely signed</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Confirmation" xml:space="preserve">
|
|
||||||
<value>Read Confirmation</value>
|
|
||||||
</data>
|
|
||||||
<data name="Confirmed" xml:space="preserve">
|
|
||||||
<value>Read and signed</value>
|
|
||||||
</data>
|
|
||||||
<data name="Contract" xml:space="preserve">
|
<data name="Contract" xml:space="preserve">
|
||||||
<value>Contract</value>
|
<value>Contract</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Created" xml:space="preserve">
|
<data name="Created" xml:space="preserve">
|
||||||
<value>Created</value>
|
<value>Created</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="DocumentConfirmed" xml:space="preserve">
|
|
||||||
<value>Document read and signed</value>
|
|
||||||
</data>
|
|
||||||
<data name="DocumentMod_Rotation" xml:space="preserve">
|
<data name="DocumentMod_Rotation" xml:space="preserve">
|
||||||
<value>Document rotation adapted</value>
|
<value>Document rotation adapted</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -162,9 +150,6 @@
|
|||||||
<data name="DocumentRejected" xml:space="preserve">
|
<data name="DocumentRejected" xml:space="preserve">
|
||||||
<value>Signing rejected</value>
|
<value>Signing rejected</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="DocumentRejectedRaC" xml:space="preserve">
|
|
||||||
<value>Read confirmation rejected</value>
|
|
||||||
</data>
|
|
||||||
<data name="DocumentSigned" xml:space="preserve">
|
<data name="DocumentSigned" xml:space="preserve">
|
||||||
<value>Document signed</value>
|
<value>Document signed</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -174,9 +159,6 @@
|
|||||||
<data name="EnvelopeArchived" xml:space="preserve">
|
<data name="EnvelopeArchived" xml:space="preserve">
|
||||||
<value>Archived</value>
|
<value>Archived</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="EnvelopeCompletelyConfirmed" xml:space="preserve">
|
|
||||||
<value>Completely confirmed</value>
|
|
||||||
</data>
|
|
||||||
<data name="EnvelopeCompletelySigned" xml:space="preserve">
|
<data name="EnvelopeCompletelySigned" xml:space="preserve">
|
||||||
<value>Completely signed</value>
|
<value>Completely signed</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -186,11 +168,8 @@
|
|||||||
<data name="EnvelopeDeleted" xml:space="preserve">
|
<data name="EnvelopeDeleted" xml:space="preserve">
|
||||||
<value>Envelope Deleted</value>
|
<value>Envelope Deleted</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="EnvelopePartlyConfirmed" xml:space="preserve">
|
|
||||||
<value>Partially confirmed</value>
|
|
||||||
</data>
|
|
||||||
<data name="EnvelopePartlySigned" xml:space="preserve">
|
<data name="EnvelopePartlySigned" xml:space="preserve">
|
||||||
<value>Partially signed</value>
|
<value>Partly signed</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="EnvelopeQueued" xml:space="preserve">
|
<data name="EnvelopeQueued" xml:space="preserve">
|
||||||
<value>Envelope Queued</value>
|
<value>Envelope Queued</value>
|
||||||
@@ -201,9 +180,6 @@
|
|||||||
<data name="EnvelopeReportCreated" xml:space="preserve">
|
<data name="EnvelopeReportCreated" xml:space="preserve">
|
||||||
<value>Signature certificate created</value>
|
<value>Signature certificate created</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="EnvelopeReportCreatedRaC" xml:space="preserve">
|
|
||||||
<value>Read confirmartion certificate created</value>
|
|
||||||
</data>
|
|
||||||
<data name="EnvelopeSaved" xml:space="preserve">
|
<data name="EnvelopeSaved" xml:space="preserve">
|
||||||
<value>Saved</value>
|
<value>Saved</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -220,7 +196,7 @@
|
|||||||
<value>Final email sent</value>
|
<value>Final email sent</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="MessageConfirmationSent" xml:space="preserve">
|
<data name="MessageConfirmationSent" xml:space="preserve">
|
||||||
<value>Finalization Confirmation Sent</value>
|
<value>Confirmation Sent</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="MessageDeletionSent" xml:space="preserve">
|
<data name="MessageDeletionSent" xml:space="preserve">
|
||||||
<value>Deletion Notice Sent</value>
|
<value>Deletion Notice Sent</value>
|
||||||
@@ -231,12 +207,6 @@
|
|||||||
<data name="No" xml:space="preserve">
|
<data name="No" xml:space="preserve">
|
||||||
<value>No</value>
|
<value>No</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="PartlyConfirmed" xml:space="preserve">
|
|
||||||
<value>Partially confirmed</value>
|
|
||||||
</data>
|
|
||||||
<data name="PartlySigned" xml:space="preserve">
|
|
||||||
<value>Partially signed</value>
|
|
||||||
</data>
|
|
||||||
<data name="QualifiedSignature" xml:space="preserve">
|
<data name="QualifiedSignature" xml:space="preserve">
|
||||||
<value>Qualified Signature</value>
|
<value>Qualified Signature</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -256,7 +226,7 @@
|
|||||||
<value>Signature</value>
|
<value>Signature</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="SignatureConfirmed" xml:space="preserve">
|
<data name="SignatureConfirmed" xml:space="preserve">
|
||||||
<value>Finalization confirmed</value>
|
<value>Signature confirmed</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Signed" xml:space="preserve">
|
<data name="Signed" xml:space="preserve">
|
||||||
<value>Signed</value>
|
<value>Signed</value>
|
||||||
@@ -264,9 +234,6 @@
|
|||||||
<data name="Success_FormClose" xml:space="preserve">
|
<data name="Success_FormClose" xml:space="preserve">
|
||||||
<value>Successful! Dialog is closed.successful! Dialog is closed.</value>
|
<value>Successful! Dialog is closed.successful! Dialog is closed.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Unconfirmed" xml:space="preserve">
|
|
||||||
<value>Unconfirmed</value>
|
|
||||||
</data>
|
|
||||||
<data name="Unsigned" xml:space="preserve">
|
<data name="Unsigned" xml:space="preserve">
|
||||||
<value>Unsigned</value>
|
<value>Unsigned</value>
|
||||||
</data>
|
</data>
|
||||||
|
|||||||
@@ -132,17 +132,8 @@
|
|||||||
<data name="Completed" xml:space="preserve">
|
<data name="Completed" xml:space="preserve">
|
||||||
<value>Abgeschlossen</value>
|
<value>Abgeschlossen</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="CompletelyConfirmed" xml:space="preserve">
|
|
||||||
<value>Vollständig bestätigt</value>
|
|
||||||
</data>
|
|
||||||
<data name="CompletelySigned" xml:space="preserve">
|
<data name="CompletelySigned" xml:space="preserve">
|
||||||
<value>Vollständig signiert</value>
|
<value>Vollständig Signiert</value>
|
||||||
</data>
|
|
||||||
<data name="Confirmation" xml:space="preserve">
|
|
||||||
<value>Lesebestätigung</value>
|
|
||||||
</data>
|
|
||||||
<data name="Confirmed" xml:space="preserve">
|
|
||||||
<value>Gelesen und bestätigt</value>
|
|
||||||
</data>
|
</data>
|
||||||
<data name="Contract" xml:space="preserve">
|
<data name="Contract" xml:space="preserve">
|
||||||
<value>Vertrag</value>
|
<value>Vertrag</value>
|
||||||
@@ -150,9 +141,6 @@
|
|||||||
<data name="Created" xml:space="preserve">
|
<data name="Created" xml:space="preserve">
|
||||||
<value>Erstellt</value>
|
<value>Erstellt</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="DocumentConfirmed" xml:space="preserve">
|
|
||||||
<value>Dokument gelesen und bestätigt</value>
|
|
||||||
</data>
|
|
||||||
<data name="DocumentMod_Rotation" xml:space="preserve">
|
<data name="DocumentMod_Rotation" xml:space="preserve">
|
||||||
<value>Dokument Rotation geändert</value>
|
<value>Dokument Rotation geändert</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -162,9 +150,6 @@
|
|||||||
<data name="DocumentRejected" xml:space="preserve">
|
<data name="DocumentRejected" xml:space="preserve">
|
||||||
<value>Unterzeichnung abgelehnt</value>
|
<value>Unterzeichnung abgelehnt</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="DocumentRejectedRaC" xml:space="preserve">
|
|
||||||
<value>Lesebestätigung abgelehnt</value>
|
|
||||||
</data>
|
|
||||||
<data name="DocumentSigned" xml:space="preserve">
|
<data name="DocumentSigned" xml:space="preserve">
|
||||||
<value>Dokument unterzeichnet</value>
|
<value>Dokument unterzeichnet</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -174,9 +159,6 @@
|
|||||||
<data name="EnvelopeArchived" xml:space="preserve">
|
<data name="EnvelopeArchived" xml:space="preserve">
|
||||||
<value>Archiviert</value>
|
<value>Archiviert</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="EnvelopeCompletelyConfirmed" xml:space="preserve">
|
|
||||||
<value>Vollständig gelesen und bestätigt</value>
|
|
||||||
</data>
|
|
||||||
<data name="EnvelopeCompletelySigned" xml:space="preserve">
|
<data name="EnvelopeCompletelySigned" xml:space="preserve">
|
||||||
<value>Vollständig signiert</value>
|
<value>Vollständig signiert</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -186,9 +168,6 @@
|
|||||||
<data name="EnvelopeDeleted" xml:space="preserve">
|
<data name="EnvelopeDeleted" xml:space="preserve">
|
||||||
<value>Umschlag Gelöscht</value>
|
<value>Umschlag Gelöscht</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="EnvelopePartlyConfirmed" xml:space="preserve">
|
|
||||||
<value>Teil-Bestätigt</value>
|
|
||||||
</data>
|
|
||||||
<data name="EnvelopePartlySigned" xml:space="preserve">
|
<data name="EnvelopePartlySigned" xml:space="preserve">
|
||||||
<value>Teil-Signiert</value>
|
<value>Teil-Signiert</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -201,9 +180,6 @@
|
|||||||
<data name="EnvelopeReportCreated" xml:space="preserve">
|
<data name="EnvelopeReportCreated" xml:space="preserve">
|
||||||
<value>Signierungszertifikat erstellt</value>
|
<value>Signierungszertifikat erstellt</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="EnvelopeReportCreatedRaC" xml:space="preserve">
|
|
||||||
<value>Lesebestätigungszertifikat erstellt</value>
|
|
||||||
</data>
|
|
||||||
<data name="EnvelopeSaved" xml:space="preserve">
|
<data name="EnvelopeSaved" xml:space="preserve">
|
||||||
<value>Gespeichert</value>
|
<value>Gespeichert</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -220,7 +196,7 @@
|
|||||||
<value>Abschlussemail versendet</value>
|
<value>Abschlussemail versendet</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="MessageConfirmationSent" xml:space="preserve">
|
<data name="MessageConfirmationSent" xml:space="preserve">
|
||||||
<value>Abschlussbestätigung versendet</value>
|
<value>Signaturbestätigung versendet</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="MessageDeletionSent" xml:space="preserve">
|
<data name="MessageDeletionSent" xml:space="preserve">
|
||||||
<value>Löschinformation versendet</value>
|
<value>Löschinformation versendet</value>
|
||||||
@@ -231,9 +207,6 @@
|
|||||||
<data name="No" xml:space="preserve">
|
<data name="No" xml:space="preserve">
|
||||||
<value>Nein</value>
|
<value>Nein</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="PartlyConfirmed" xml:space="preserve">
|
|
||||||
<value>Teil-Bestätigt</value>
|
|
||||||
</data>
|
|
||||||
<data name="PartlySigned" xml:space="preserve">
|
<data name="PartlySigned" xml:space="preserve">
|
||||||
<value>Teil-Signiert</value>
|
<value>Teil-Signiert</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -241,7 +214,7 @@
|
|||||||
<value>Qualifizierte Signatur</value>
|
<value>Qualifizierte Signatur</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="ReadAndSign" xml:space="preserve">
|
<data name="ReadAndSign" xml:space="preserve">
|
||||||
<value>Lesebestätigung</value>
|
<value>Arbeitsanweisung</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="ResetTOTPUser" xml:space="preserve">
|
<data name="ResetTOTPUser" xml:space="preserve">
|
||||||
<value>Wollen Sie die 2-Faktor Definition für diesen Empfänger zurücksetzen. Der Empfänger muss sich dann neu identifizieren!</value>
|
<value>Wollen Sie die 2-Faktor Definition für diesen Empfänger zurücksetzen. Der Empfänger muss sich dann neu identifizieren!</value>
|
||||||
@@ -256,7 +229,7 @@
|
|||||||
<value>Signatur</value>
|
<value>Signatur</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="SignatureConfirmed" xml:space="preserve">
|
<data name="SignatureConfirmed" xml:space="preserve">
|
||||||
<value>Abschluss bestätigt</value>
|
<value>Signatur bestätigt</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Signed" xml:space="preserve">
|
<data name="Signed" xml:space="preserve">
|
||||||
<value>Signiert</value>
|
<value>Signiert</value>
|
||||||
@@ -264,9 +237,6 @@
|
|||||||
<data name="Success_FormClose" xml:space="preserve">
|
<data name="Success_FormClose" xml:space="preserve">
|
||||||
<value>Erfolgreich! Dialog wird geschlossen.</value>
|
<value>Erfolgreich! Dialog wird geschlossen.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Unconfirmed" xml:space="preserve">
|
|
||||||
<value>Unbestätigt</value>
|
|
||||||
</data>
|
|
||||||
<data name="Unsigned" xml:space="preserve">
|
<data name="Unsigned" xml:space="preserve">
|
||||||
<value>Unsigniert</value>
|
<value>Unsigniert</value>
|
||||||
</data>
|
</data>
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ Public Class FieldEditorController
|
|||||||
Inherits BaseController
|
Inherits BaseController
|
||||||
|
|
||||||
Private ReadOnly Document As Document
|
Private ReadOnly Document As Document
|
||||||
Public Property Elements As New List(Of DocReceiverElement)
|
Public Property Elements As New List(Of Signature)
|
||||||
|
|
||||||
Public Class ElementInfo
|
Public Class ElementInfo
|
||||||
Public ReceiverId As Integer
|
Public ReceiverId As Integer
|
||||||
@@ -36,7 +36,7 @@ Public Class FieldEditorController
|
|||||||
}
|
}
|
||||||
End Function
|
End Function
|
||||||
|
|
||||||
Private Function GetElementByPosition(pAnnotation As AnnotationStickyNote, pPage As Integer, pReceiverId As Integer) As DocReceiverElement
|
Private Function GetElementByPosition(pAnnotation As AnnotationStickyNote, pPage As Integer, pReceiverId As Integer) As Signature
|
||||||
Dim oElement = Elements.
|
Dim oElement = Elements.
|
||||||
Where(Function(e)
|
Where(Function(e)
|
||||||
Return e.Left = CSng(Math.Round(pAnnotation.Left, 5)) And
|
Return e.Left = CSng(Math.Round(pAnnotation.Left, 5)) And
|
||||||
@@ -47,12 +47,12 @@ Public Class FieldEditorController
|
|||||||
Return oElement
|
Return oElement
|
||||||
End Function
|
End Function
|
||||||
|
|
||||||
Private Function GetElementByGuid(pGuid As Integer) As DocReceiverElement
|
Private Function GetElementByGuid(pGuid As Integer) As Signature
|
||||||
Dim oElement = Elements.Where(Function(e) pGuid = e.Id).SingleOrDefault()
|
Dim oElement = Elements.Where(Function(e) pGuid = e.Id).SingleOrDefault()
|
||||||
Return oElement
|
Return oElement
|
||||||
End Function
|
End Function
|
||||||
|
|
||||||
Public Function GetElement(pAnnotation As AnnotationStickyNote) As DocReceiverElement
|
Public Function GetElement(pAnnotation As AnnotationStickyNote) As Signature
|
||||||
Dim oInfo = GetElementInfo(pAnnotation.Tag)
|
Dim oInfo = GetElementInfo(pAnnotation.Tag)
|
||||||
|
|
||||||
If oInfo.Guid = -1 Then
|
If oInfo.Guid = -1 Then
|
||||||
@@ -85,7 +85,7 @@ Public Class FieldEditorController
|
|||||||
Else
|
Else
|
||||||
Dim oInfo = GetElementInfo(pAnnotation.Tag)
|
Dim oInfo = GetElementInfo(pAnnotation.Tag)
|
||||||
|
|
||||||
Elements.Add(New DocReceiverElement() With {
|
Elements.Add(New Signature() With {
|
||||||
.ElementType = Constants.ElementType.Signature,
|
.ElementType = Constants.ElementType.Signature,
|
||||||
.Height = oAnnotationHeight,
|
.Height = oAnnotationHeight,
|
||||||
.Width = oAnnotationWidth,
|
.Width = oAnnotationWidth,
|
||||||
@@ -98,7 +98,7 @@ Public Class FieldEditorController
|
|||||||
End If
|
End If
|
||||||
End Sub
|
End Sub
|
||||||
|
|
||||||
Public Function ClearElements(pPage As Integer, pReceiverId As Integer) As IEnumerable(Of DocReceiverElement)
|
Public Function ClearElements(pPage As Integer, pReceiverId As Integer) As IEnumerable(Of Signature)
|
||||||
Return Elements.
|
Return Elements.
|
||||||
Where(Function(e) e.Page <> pPage And e.ReceiverId <> pReceiverId).
|
Where(Function(e) e.Page <> pPage And e.ReceiverId <> pReceiverId).
|
||||||
ToList()
|
ToList()
|
||||||
@@ -120,7 +120,7 @@ Public Class FieldEditorController
|
|||||||
All(Function(pResult) pResult = True)
|
All(Function(pResult) pResult = True)
|
||||||
End Function
|
End Function
|
||||||
|
|
||||||
Public Function SaveElement(pElement As DocReceiverElement) As Boolean
|
Public Function SaveElement(pElement As Signature) As Boolean
|
||||||
Try
|
Try
|
||||||
If pElement.Id > 0 Then
|
If pElement.Id > 0 Then
|
||||||
Return ElementModel.Update(pElement)
|
Return ElementModel.Update(pElement)
|
||||||
@@ -134,11 +134,11 @@ Public Class FieldEditorController
|
|||||||
End Try
|
End Try
|
||||||
End Function
|
End Function
|
||||||
|
|
||||||
Public Function DeleteElement(pElement As DocReceiverElement) As Boolean
|
Public Function DeleteElement(pElement As Signature) As Boolean
|
||||||
Try
|
Try
|
||||||
' Element aus Datenbank löschen
|
' Element aus Datenbank löschen
|
||||||
If ElementModel.DeleteElement(pElement) Then
|
If ElementModel.DeleteElement(pElement) Then
|
||||||
Dim oElement = New List(Of DocReceiverElement)() From {pElement}
|
Dim oElement = New List(Of Signature)() From {pElement}
|
||||||
Elements = Elements.Except(oElement).ToList()
|
Elements = Elements.Except(oElement).ToList()
|
||||||
Return True
|
Return True
|
||||||
Else
|
Else
|
||||||
|
|||||||
@@ -280,7 +280,7 @@ Partial Public Class frmFieldEditor
|
|||||||
End If
|
End If
|
||||||
End Sub
|
End Sub
|
||||||
|
|
||||||
Private Sub LoadAnnotation(pElement As DocReceiverElement, pReceiverId As Integer)
|
Private Sub LoadAnnotation(pElement As Signature, pReceiverId As Integer)
|
||||||
Dim oAnnotation As AnnotationStickyNote = Manager.AddStickyNoteAnnot(0, 0, 0, 0, "SIGNATUR")
|
Dim oAnnotation As AnnotationStickyNote = Manager.AddStickyNoteAnnot(0, 0, 0, 0, "SIGNATUR")
|
||||||
Dim oPage = pElement.Page
|
Dim oPage = pElement.Page
|
||||||
Dim oReceiver = Receivers.Where(Function(r) r.Id = pReceiverId).Single()
|
Dim oReceiver = Receivers.Where(Function(r) r.Id = pReceiverId).Single()
|
||||||
|
|||||||
@@ -74,14 +74,14 @@ namespace EnvelopeGenerator.Infrastructure
|
|||||||
services.AddSQLExecutor<Envelope>();
|
services.AddSQLExecutor<Envelope>();
|
||||||
services.AddSQLExecutor<Receiver>();
|
services.AddSQLExecutor<Receiver>();
|
||||||
services.AddSQLExecutor<Document>();
|
services.AddSQLExecutor<Document>();
|
||||||
services.AddSQLExecutor<DocReceiverElement>();
|
services.AddSQLExecutor<Signature>();
|
||||||
services.AddSQLExecutor<DocumentStatus>();
|
services.AddSQLExecutor<DocumentStatus>();
|
||||||
|
|
||||||
SetDapperTypeMap<Envelope>();
|
SetDapperTypeMap<Envelope>();
|
||||||
SetDapperTypeMap<User>();
|
SetDapperTypeMap<User>();
|
||||||
SetDapperTypeMap<Receiver>();
|
SetDapperTypeMap<Receiver>();
|
||||||
SetDapperTypeMap<Document>();
|
SetDapperTypeMap<Document>();
|
||||||
SetDapperTypeMap<DocReceiverElement>();
|
SetDapperTypeMap<Signature>();
|
||||||
SetDapperTypeMap<DocumentStatus>();
|
SetDapperTypeMap<DocumentStatus>();
|
||||||
|
|
||||||
services.AddScoped<IEnvelopeExecutor, EnvelopeExecutor>();
|
services.AddScoped<IEnvelopeExecutor, EnvelopeExecutor>();
|
||||||
|
|||||||
@@ -45,9 +45,7 @@ public abstract class EGDbContextBase : DbContext
|
|||||||
|
|
||||||
public DbSet<Envelope> Envelopes { get; set; }
|
public DbSet<Envelope> Envelopes { get; set; }
|
||||||
|
|
||||||
public DbSet<DocReceiverElement> DocumentReceiverElements { get; set; }
|
public DbSet<Signature> DocumentReceiverElements { get; set; }
|
||||||
|
|
||||||
public DbSet<ElementAnnotation> DocumentReceiverElementAnnotations { get; set; }
|
|
||||||
|
|
||||||
public DbSet<DocumentStatus> DocumentStatus { get; set; }
|
public DbSet<DocumentStatus> DocumentStatus { get; set; }
|
||||||
|
|
||||||
@@ -81,6 +79,8 @@ public abstract class EGDbContextBase : DbContext
|
|||||||
|
|
||||||
public DbSet<ClientUser> ClientUsers { get; set; }
|
public DbSet<ClientUser> ClientUsers { get; set; }
|
||||||
|
|
||||||
|
public DbSet<EnvelopeReport> EnvelopeReports { get; set; }
|
||||||
|
|
||||||
private readonly DbTriggerParams _triggers;
|
private readonly DbTriggerParams _triggers;
|
||||||
|
|
||||||
private readonly ILogger
|
private readonly ILogger
|
||||||
@@ -154,7 +154,7 @@ public abstract class EGDbContextBase : DbContext
|
|||||||
#endregion EnvelopeDocument
|
#endregion EnvelopeDocument
|
||||||
|
|
||||||
#region DocumentReceiverElement
|
#region DocumentReceiverElement
|
||||||
modelBuilder.Entity<DocReceiverElement>()
|
modelBuilder.Entity<Signature>()
|
||||||
.HasOne(dre => dre.Document)
|
.HasOne(dre => dre.Document)
|
||||||
.WithMany(ed => ed.Elements)
|
.WithMany(ed => ed.Elements)
|
||||||
.HasForeignKey(dre => dre.DocumentId);
|
.HasForeignKey(dre => dre.DocumentId);
|
||||||
@@ -196,12 +196,16 @@ public abstract class EGDbContextBase : DbContext
|
|||||||
#endregion DocumentStatus
|
#endregion DocumentStatus
|
||||||
|
|
||||||
#region Annotation
|
#region Annotation
|
||||||
modelBuilder.Entity<DocReceiverElement>()
|
modelBuilder.Entity<Signature>()
|
||||||
.HasMany(signature => signature.Annotations)
|
.HasMany(signature => signature.Annotations)
|
||||||
.WithOne(annot => annot.Element)
|
.WithOne(annot => annot.Element)
|
||||||
.HasForeignKey(annot => annot.ElementId);
|
.HasForeignKey(annot => annot.ElementId);
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
#region EnvelopeReport
|
||||||
|
modelBuilder.Entity<EnvelopeReport>().HasNoKey();
|
||||||
|
#endregion
|
||||||
|
|
||||||
#region Trigger
|
#region Trigger
|
||||||
// Configure entities to handle database triggers
|
// Configure entities to handle database triggers
|
||||||
void AddTrigger<T>() where T : class => _triggers
|
void AddTrigger<T>() where T : class => _triggers
|
||||||
@@ -217,7 +221,7 @@ public abstract class EGDbContextBase : DbContext
|
|||||||
|
|
||||||
// TODO: call add trigger methods with attributes and reflection
|
// TODO: call add trigger methods with attributes and reflection
|
||||||
AddTrigger<Config>();
|
AddTrigger<Config>();
|
||||||
AddTrigger<DocReceiverElement>();
|
AddTrigger<Signature>();
|
||||||
AddTrigger<DocumentStatus>();
|
AddTrigger<DocumentStatus>();
|
||||||
AddTrigger<EmailTemplate>();
|
AddTrigger<EmailTemplate>();
|
||||||
AddTrigger<Envelope>();
|
AddTrigger<Envelope>();
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ using EnvelopeGenerator.Application.Common.Interfaces.Repositories;
|
|||||||
namespace EnvelopeGenerator.Infrastructure.Repositories;
|
namespace EnvelopeGenerator.Infrastructure.Repositories;
|
||||||
|
|
||||||
[Obsolete("Use IRepository")]
|
[Obsolete("Use IRepository")]
|
||||||
public class DocumentReceiverElementRepository : CRUDRepository<DocReceiverElement, int, EGDbContext>, IDocumentReceiverElementRepository
|
public class DocumentReceiverElementRepository : CRUDRepository<Signature, int, EGDbContext>, IDocumentReceiverElementRepository
|
||||||
{
|
{
|
||||||
public DocumentReceiverElementRepository(EGDbContext dbContext) : base(dbContext, dbContext.DocumentReceiverElements)
|
public DocumentReceiverElementRepository(EGDbContext dbContext) : base(dbContext, dbContext.DocumentReceiverElements)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -103,15 +103,19 @@ namespace EnvelopeGenerator.PdfEditor
|
|||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
public Pdf<TInputStream, TOutputStream> Background<TSignature>(IEnumerable<TSignature> signatures, double widthPx = 1.9500000000000002, double heightPx = 2.52)
|
public Pdf<TInputStream, TOutputStream> Background<TSignature>(IEnumerable<TSignature> signatures, double widthPx = 1.9500000000000002, double heightPx = 2.52)
|
||||||
where TSignature : IDocReceiverElement
|
where TSignature : ISignature
|
||||||
{
|
{
|
||||||
|
// once per page
|
||||||
|
Page(page =>
|
||||||
|
{
|
||||||
|
var canvas = new PdfCanvas(page);
|
||||||
|
canvas.ConcatMatrix(1, 0, 0, -1, 0, page.GetPageSize().GetHeight());
|
||||||
|
});
|
||||||
|
|
||||||
foreach (var signature in signatures)
|
foreach (var signature in signatures)
|
||||||
Page(signature.Page, page =>
|
Page(signature.Page, page =>
|
||||||
{
|
{
|
||||||
var canvas = new PdfCanvas(page);
|
var canvas = new PdfCanvas(page);
|
||||||
canvas.SaveState();
|
|
||||||
canvas.ConcatMatrix(1, 0, 0, -1, 0, page.GetPageSize().GetHeight());
|
|
||||||
|
|
||||||
double inchFactor = 72;
|
double inchFactor = 72;
|
||||||
double magin = .2;
|
double magin = .2;
|
||||||
double x = (signature.X - .7 - magin) * inchFactor;
|
double x = (signature.X - .7 - magin) * inchFactor;
|
||||||
@@ -130,8 +134,6 @@ namespace EnvelopeGenerator.PdfEditor
|
|||||||
canvas.SetFillColor(new DeviceRgb(204, 202, 198))
|
canvas.SetFillColor(new DeviceRgb(204, 202, 198))
|
||||||
.Rectangle(x, y + height - bottomLineLength, width, bottomLineLength)
|
.Rectangle(x, y + height - bottomLineLength, width, bottomLineLength)
|
||||||
.Fill();
|
.Fill();
|
||||||
|
|
||||||
canvas.RestoreState();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
|
|||||||
@@ -1,10 +0,0 @@
|
|||||||
<Router AppAssembly="@typeof(Program).Assembly">
|
|
||||||
<Found Context="routeData">
|
|
||||||
<RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" />
|
|
||||||
</Found>
|
|
||||||
<NotFound>
|
|
||||||
<LayoutView Layout="@typeof(MainLayout)">
|
|
||||||
<p>Sorry, there's nothing at this address.</p>
|
|
||||||
</LayoutView>
|
|
||||||
</NotFound>
|
|
||||||
</Router>
|
|
||||||
@@ -1,44 +0,0 @@
|
|||||||
namespace EnvelopeGenerator.ReceiverUI.Data {
|
|
||||||
public class Adjustment
|
|
||||||
{
|
|
||||||
public static Adjustment CreateBalanceForward(DateTime dt, int random)
|
|
||||||
{
|
|
||||||
var rnd = new DeterministicRandom(random);
|
|
||||||
Adjustment res = new Adjustment();
|
|
||||||
res.currentDateTime = dt;
|
|
||||||
res.currentDescription = "Balance Forward";
|
|
||||||
res.currentAmount = rnd.Random(10, 300) * 10;
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
public static Adjustment CreatePayment(DateTime dt, int random)
|
|
||||||
{
|
|
||||||
var rnd = new DeterministicRandom(random);
|
|
||||||
Adjustment res = new Adjustment();
|
|
||||||
res.currentDateTime = dt;
|
|
||||||
res.currentDescription = "Payment";
|
|
||||||
res.currentAmount = -rnd.Random(1, 40) * 10;
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
public static Adjustment CreateCharge(DateTime dt, int random)
|
|
||||||
{
|
|
||||||
var rnd = new DeterministicRandom(random);
|
|
||||||
Adjustment res = new Adjustment();
|
|
||||||
res.currentDateTime = dt;
|
|
||||||
res.currentDescription = rnd.GetRandomItem(bills);
|
|
||||||
res.currentAmount = rnd.Random(10, 50) * 10;
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
DateTime currentDateTime;
|
|
||||||
string currentDescription = "";
|
|
||||||
double currentAmount = 0;
|
|
||||||
static readonly string[] bills = new string[] { "Bill - Insurance", "Bill - Electricity", "Bill - Rent", "Bill - Phone", "Bill - Office Supplies" };
|
|
||||||
public DateTime Date { get { return currentDateTime; } }
|
|
||||||
public string Description { get { return currentDescription; } }
|
|
||||||
public double Amount { get { return currentAmount; } }
|
|
||||||
|
|
||||||
public Adjustment()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,64 +0,0 @@
|
|||||||
using DevExpress.DataAccess.Sql;
|
|
||||||
using DevExpress.DataAccess.Sql.DataApi;
|
|
||||||
|
|
||||||
namespace EnvelopeGenerator.ReceiverUI.Data {
|
|
||||||
public class Customer {
|
|
||||||
static List<Customer> currentCustomers = new List<Customer>();
|
|
||||||
|
|
||||||
public static List<Customer> Customers { get { return currentCustomers; } }
|
|
||||||
static Customer() {
|
|
||||||
try {
|
|
||||||
SqlDataSource ds = new SqlDataSource("NWindConnectionString");
|
|
||||||
SelectQuery query = SelectQueryFluentBuilder
|
|
||||||
.AddTable("Customers")
|
|
||||||
.SelectAllColumns()
|
|
||||||
.Build("Customers");
|
|
||||||
ds.Queries.Add(query);
|
|
||||||
ds.RebuildResultSchema();
|
|
||||||
ds.Fill();
|
|
||||||
ITable src = ds.Result["Customers"];
|
|
||||||
foreach(var row in src) {
|
|
||||||
currentCustomers.Add(new Customer() {
|
|
||||||
CustomerID = row.GetValue<string>("CustomerID"),
|
|
||||||
Address = row.GetValue<string>("Address"),
|
|
||||||
CompanyName = row.GetValue<string>("CompanyName"),
|
|
||||||
ContactName = row.GetValue<string>("ContactName"),
|
|
||||||
ContactTitle = row.GetValue<string>("ContactTitle"),
|
|
||||||
Country = row.GetValue<string>("Country"),
|
|
||||||
City = row.GetValue<string>("City"),
|
|
||||||
Fax = row.GetValue<string>("Fax"),
|
|
||||||
Phone = row.GetValue<string>("Phone"),
|
|
||||||
PostalCode = row.GetValue<string>("PostalCode"),
|
|
||||||
Region = row.GetValue<string>("Region")
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} catch {
|
|
||||||
currentCustomers.Add(new Customer() {
|
|
||||||
Address = "Obere Str. 57",
|
|
||||||
City = "Berlin",
|
|
||||||
CompanyName = "Alfreds Futterkiste",
|
|
||||||
ContactName = "Maria Anders",
|
|
||||||
ContactTitle = "Sales Representative",
|
|
||||||
Country = "Germany",
|
|
||||||
CustomerID = "ALFKI",
|
|
||||||
Fax = "030-0076545",
|
|
||||||
Phone = "030-0074321",
|
|
||||||
PostalCode = "12209"
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public string CustomerID { get; set; }
|
|
||||||
public string CompanyName { get; set; }
|
|
||||||
public string ContactName { get; set; }
|
|
||||||
public string ContactTitle { get; set; }
|
|
||||||
public string Address { get; set; }
|
|
||||||
public string City { get; set; }
|
|
||||||
public string PostalCode { get; set; }
|
|
||||||
public string Region { get; set; }
|
|
||||||
public string Country { get; set; }
|
|
||||||
public string Phone { get; set; }
|
|
||||||
public string Fax { get; set; }
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,71 +0,0 @@
|
|||||||
namespace EnvelopeGenerator.ReceiverUI.Data {
|
|
||||||
public class DataItem {
|
|
||||||
static readonly string[] accountType = new string[] { "Energy", "Manufacturing", "Estate", "Food", "Services" };
|
|
||||||
public string CustomerID { get; set; }
|
|
||||||
public string CompanyName { get; set; }
|
|
||||||
public string ContactName { get; set; }
|
|
||||||
public string ContactTitle { get; set; }
|
|
||||||
public string Address { get; set; }
|
|
||||||
public string City { get; set; }
|
|
||||||
public string PostalCode { get; set; }
|
|
||||||
public string Region { get; set; }
|
|
||||||
public string Country { get; set; }
|
|
||||||
public string Phone { get; set; }
|
|
||||||
public string Fax { get; set; }
|
|
||||||
public string Email { get; set; }
|
|
||||||
public string Invoice { get; set; }
|
|
||||||
public string CustomerAccount { get; set; }
|
|
||||||
public string CustomerIdentifiers { get; set; }
|
|
||||||
public DateTime BillingDate { get; set; }
|
|
||||||
public DateTime BillingPeriodStart { get; set; }
|
|
||||||
public DateTime BillingPeriodEnd { get; set; }
|
|
||||||
public string Terms { get; set; }
|
|
||||||
public string TermsID { get; set; }
|
|
||||||
public Adjustment[] Adjustments { get; set; }
|
|
||||||
|
|
||||||
public DataItem(int i) {
|
|
||||||
var rnd = new DeterministicRandom(i);
|
|
||||||
Customer c = rnd.GetRandomItem(Customer.Customers);
|
|
||||||
CustomerID = c.CustomerID;
|
|
||||||
CompanyName = c.CompanyName;
|
|
||||||
ContactName = c.ContactName;
|
|
||||||
ContactTitle = c.ContactTitle;
|
|
||||||
Address = c.Address;
|
|
||||||
City = c.City;
|
|
||||||
PostalCode = c.PostalCode;
|
|
||||||
Region = c.Region;
|
|
||||||
Country = c.Country;
|
|
||||||
Phone = c.Phone;
|
|
||||||
Fax = c.Fax;
|
|
||||||
Email = ContactName.Split(' ')[0].Replace(' ', '.').ToLower() + "@" + CompanyName.Split(' ')[0].ToLower() + ".com";
|
|
||||||
Invoice = string.Format("{0}{1}-{2}", rnd.RandomChar, rnd.Random(100, 1000), rnd.Random(100, 1000));
|
|
||||||
CustomerAccount = rnd.GetRandomItem(accountType);
|
|
||||||
CustomerIdentifiers = string.Format("{0}-{1}", rnd.Random(1000, 10000), rnd.Random(10, 100));
|
|
||||||
BillingPeriodStart = rnd.RandomTime();
|
|
||||||
BillingPeriodEnd = rnd.RandomTime(BillingPeriodStart, 7 * 24, 30 * 24);
|
|
||||||
BillingDate = rnd.RandomTime(BillingPeriodEnd, 7 * 24, 30 * 24);
|
|
||||||
Term currentTerm = rnd.GetRandomItem(Term.Terms);
|
|
||||||
Terms = currentTerm.Name;
|
|
||||||
|
|
||||||
int adjustmentsCount = rnd.Random(6) + 4;
|
|
||||||
Adjustments = new Adjustment[adjustmentsCount];
|
|
||||||
int h = (int)((BillingPeriodEnd - BillingPeriodStart).TotalHours / adjustmentsCount);
|
|
||||||
|
|
||||||
Adjustments[0] = Adjustment.CreateBalanceForward(rnd.RandomTime(BillingPeriodStart, 0, h), rnd.Random(10000));
|
|
||||||
|
|
||||||
int[] items = rnd.RandomList(adjustmentsCount - 1, 2);
|
|
||||||
|
|
||||||
for(int j = 1; j < Adjustments.Length; j++) {
|
|
||||||
DateTime nextDate = rnd.RandomTime(BillingPeriodStart.AddHours(h * j), 0, h);
|
|
||||||
switch(items[j - 1]) {
|
|
||||||
case 0:
|
|
||||||
Adjustments[j] = Adjustment.CreateCharge(nextDate, rnd.Random(10000));
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
Adjustments[j] = Adjustment.CreatePayment(nextDate, rnd.Random(10000));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user