Skip to content

Commit 440e339

Browse files
authored
Merge pull request #255 from pticostaricags/development
merge "development" into "main"
2 parents 6519cac + 432807a commit 440e339

File tree

15 files changed

+196
-29
lines changed

15 files changed

+196
-29
lines changed

src/FairPlayCombinedSln/FairPlayAdminPortal/Components/Pages/PromptsEditor.razor

+23-3
Original file line numberDiff line numberDiff line change
@@ -121,11 +121,21 @@
121121
<FluentValidationMessage For="@( () => AnalyzePotentialMatchPrompt.BaseText)"></FluentValidationMessage>
122122
</div>
123123
}
124+
@if (this.ValidateUserSentDataPrompt != null)
125+
{
126+
<div>
127+
<FluentLabel Typo="Typography.Body" Weight="FontWeight.Bold">
128+
@ValidateUserSentDataPrompt.PromptName
129+
</FluentLabel>
130+
<FluentTextArea Rows="10" style="width:100%;" @bind-Value="this.ValidateUserSentDataPrompt.BaseText"></FluentTextArea>
131+
<FluentValidationMessage For="@( () => ValidateUserSentDataPrompt.BaseText)"></FluentValidationMessage>
132+
</div>
133+
}
124134
<div>
125135
<FluentButton Type="ButtonType.Submit"
126-
IconStart="@(new Icons.Regular.Size16.ArrowClockwise())"
127-
Appearance="Appearance.Accent"
128-
Loading="@this.IsBusy">
136+
IconStart="@(new Icons.Regular.Size16.ArrowClockwise())"
137+
Appearance="Appearance.Accent"
138+
Loading="@this.IsBusy">
129139
Save
130140
</FluentButton>
131141
</div>
@@ -165,6 +175,9 @@
165175
private PromptModel? AnalyzePotentialMatchPrompt =>
166176
allPrompts.SingleOrDefault(p => p.PromptName == Constants.PromptsNames.AnalyzePotentialMatch);
167177

178+
private PromptModel? ValidateUserSentDataPrompt =>
179+
allPrompts.SingleOrDefault(p => p.PromptName == Constants.PromptsNames.ValidateUserSentData);
180+
168181
private bool IsBusy { get; set; }
169182
private readonly CancellationTokenSource cancellationTokenSource = new();
170183

@@ -245,6 +258,13 @@
245258
PromptName = Constants.PromptsNames.AnalyzePotentialMatch
246259
});
247260
}
261+
if (this.ValidateUserSentDataPrompt is null)
262+
{
263+
this.allPrompts.Add(new PromptModel()
264+
{
265+
PromptName = Constants.PromptsNames.ValidateUserSentData
266+
});
267+
}
248268
}
249269
catch (Exception ex)
250270
{

src/FairPlayCombinedSln/FairPlayCombined.Common/Constants.cs

+4
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@ public static class ConnectionStringNames
2626
}
2727
public static class PromptsNames
2828
{
29+
#region Users Validation
30+
public const string ValidateUserSentData = nameof(ValidateUserSentData);
31+
#endregion Users Validation
32+
2933
#region FairPlayTube
3034
public const string CreateYouTubeThumbnail = "YouTubeThumbnail";
3135
public const string CreateVideoPassiveIncomeStrategy = nameof(CreateVideoPassiveIncomeStrategy);

src/FairPlayCombinedSln/FairPlayCombined.Common/Identity/ApplicationUser.cs

+2
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ public class ApplicationUser : IdentityUser
2222
[ProtectedPersonalData]
2323
public string? WebsiteUrl { get; set; }
2424
[ProtectedPersonalData]
25+
public string? ReasonToCreateAccount { get; set; }
26+
[ProtectedPersonalData]
2527
public DateTimeOffset? RowCreationDateTime { get; set; }
2628

2729
[ProtectedPersonalData]

src/FairPlayCombinedSln/FairPlayCombined.DataAccess/Data/FairPlayCombinedDbContext.cs

+4-6
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,8 @@ protected override void OnModelCreating(ModelBuilder modelBuilder)
222222
.IsUnique()
223223
.HasFilter("([NormalizedUserName] IS NOT NULL)");
224224

225+
entity.Property(e => e.ReasonToCreateAccount).HasDefaultValue("N/A");
226+
225227
entity.HasMany(d => d.Role).WithMany(p => p.User)
226228
.UsingEntity<Dictionary<string, object>>(
227229
"AspNetUserRoles",
@@ -461,8 +463,6 @@ protected override void OnModelCreating(ModelBuilder modelBuilder)
461463

462464
modelBuilder.Entity<StoreCustomerAddress>(entity =>
463465
{
464-
entity.HasKey(e => e.Id).HasName("PK__StoreCus__3214EC075BC02D37");
465-
466466
entity.Property(e => e.Id).ValueGeneratedNever();
467467
});
468468

@@ -671,11 +671,11 @@ protected override void OnModelCreating(ModelBuilder modelBuilder)
671671
{
672672
entity.HasIndex(e => e.YouTubeVideoId, "UI_VideoInfo_YouTubeVideoId")
673673
.IsUnique()
674-
.HasFilter("([YouTubeVideoId] IS NOT NULL)");
674+
.HasFilter("YouTubeVideoId IS NOT NULL");
675675

676676
entity.Property(e => e.ApplicationUserId).HasComment("Video Owner Id");
677677
entity.Property(e => e.IsVideoGeneratedWithAi).HasDefaultValue(false);
678-
entity.Property(e => e.RowCreationDateTime).HasDefaultValueSql("(getutcdate())");
678+
entity.Property(e => e.RowCreationDateTime).HasDefaultValueSql("GETUTCDATE()");
679679
entity.Property(e => e.RowCreationUser).HasDefaultValue("Unknown");
680680
entity.Property(e => e.SourceApplication).HasDefaultValue("Unknown");
681681
entity.Property(e => e.VideoIndexingProcessingPercentage).HasDefaultValue(0);
@@ -716,8 +716,6 @@ protected override void OnModelCreating(ModelBuilder modelBuilder)
716716

717717
modelBuilder.Entity<VideoJobApplicationStatus>(entity =>
718718
{
719-
entity.HasKey(e => e.VideoJobApplicationStatusId).HasName("PK__VideoJob__3EE88E40F2ABD88A");
720-
721719
entity.Property(e => e.VideoJobApplicationStatusId).ValueGeneratedNever();
722720
});
723721

src/FairPlayCombinedSln/FairPlayCombined.DataAccess/Models/FairPlayBudget/VwBalance.cs

+1-3
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,6 @@ public partial class VwBalance
2525
[Column(TypeName = "money")]
2626
public decimal Amount { get; set; }
2727

28-
[StringLength(10)]
29-
public string TransactionType { get; set; }
30-
3128
public DateTimeOffset DateTime { get; set; }
3229

3330
[Required]
@@ -40,6 +37,7 @@ public partial class VwBalance
4037
[StringLength(50)]
4138
public string Currency { get; set; }
4239

40+
[Required]
4341
[StringLength(150)]
4442
public string MonthlyBudgetDescription { get; set; }
4543
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Text;
5+
using System.Threading.Tasks;
6+
7+
namespace FairPlayCombined.DataAccess.Models.FairPlayBudgetSchema;
8+
public partial class VwBalance
9+
{
10+
public string? TransactionType { get; set; }
11+
}

src/FairPlayCombinedSln/FairPlayCombined.DataAccess/Models/dbo/AspNetUsers.cs

+4
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,10 @@ public partial class AspNetUsers
7070

7171
public string WebsiteUrl { get; set; }
7272

73+
[Required]
74+
[StringLength(1000)]
75+
public string ReasonToCreateAccount { get; set; }
76+
7377
public DateTimeOffset RowCreationDateTime { get; set; }
7478

7579
[Required]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
namespace FairPlayCombined.Interfaces
2+
{
3+
public interface IUserValidationService
4+
{
5+
Task ValidateUserDataAsync(string name, string lastName, string email,
6+
string reasonToCreateAccount, CancellationToken cancellationToken);
7+
}
8+
}

src/FairPlayCombinedSln/FairPlayCombined.Models/Auth/ExternalLogin/InputModel.cs

+4
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,10 @@ public class InputModel
5151
ResourceType = typeof(InputModelLocalizer),
5252
Name = nameof(InputModelLocalizer.DisplayFor_WebsiteUrl))]
5353
public string? WebsiteUrl { get; set; }
54+
55+
[CustomRequired]
56+
[CustomStringLength(1000)]
57+
public string? ReasonToCreateAccount { get; set; }
5458
}
5559

5660
[CompilerGenerated]

src/FairPlayCombinedSln/FairPlayCombined.Models/Auth/Register/InputModel.cs

+4
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,10 @@ public class InputModel
6767
ResourceType = typeof(InputModelLocalizer),
6868
Name = nameof(InputModelLocalizer.DisplayFor_WebsiteUrl))]
6969
public string? WebsiteUrl { get; set; }
70+
71+
[CustomRequired]
72+
[CustomStringLength(1000)]
73+
public string? ReasonToCreateAccount { get; set; }
7074
}
7175

7276
[CompilerGenerated]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
using FairPlayCombined.Common;
2+
using FairPlayCombined.Common.CustomExceptions;
3+
using FairPlayCombined.DataAccess.Data;
4+
using FairPlayCombined.Interfaces;
5+
using FairPlayCombined.Interfaces.Common;
6+
using Microsoft.EntityFrameworkCore;
7+
using Microsoft.Extensions.Logging;
8+
using System.Globalization;
9+
using System.Text;
10+
11+
namespace FairPlayCombined.Services.Common;
12+
13+
public class UserValidationService(
14+
IDbContextFactory<FairPlayCombinedDbContext> dbContextFactory,
15+
ILogger<UserValidationService> logger,
16+
IOpenAIService openAIService) : IUserValidationService
17+
{
18+
public async Task ValidateUserDataAsync(string name, string lastName, string email,
19+
string reasonToCreateAccount, CancellationToken cancellationToken)
20+
{
21+
logger.LogInformation(message: "Start of method: {MethodName}", nameof(ValidateUserDataAsync));
22+
var dbContext = await dbContextFactory.CreateDbContextAsync(cancellationToken);
23+
var promptEntity = await dbContext.Prompt
24+
.AsNoTracking()
25+
.SingleAsync(p => p.PromptName == Constants.PromptsNames.ValidateUserSentData,
26+
cancellationToken: cancellationToken);
27+
StringBuilder systemMessage = new();
28+
systemMessage.AppendLine(promptEntity.BaseText);
29+
systemMessage.AppendLine($"Your response must be in the language culture: " +
30+
$"{CultureInfo.CurrentCulture.Name}");
31+
StringBuilder userMessage = new();
32+
userMessage.AppendLine("Properties:");
33+
userMessage.AppendLine($"Name: {name}");
34+
userMessage.AppendLine($"Lastname: {lastName}");
35+
userMessage.AppendLine($"Email: {email}");
36+
userMessage.AppendLine($"Reason To Create Account: {reasonToCreateAccount}");
37+
var response = await openAIService.GenerateChatCompletionAsync(systemMessage.ToString(), userMessage.ToString(), cancellationToken);
38+
var resultText = response!.choices![0].message!.content;
39+
if (resultText!.Contains("$$ERRORS$$"))
40+
{
41+
throw new RuleException(resultText.Replace("$$ERRORS$$", String.Empty));
42+
}
43+
}
44+
}

src/FairPlayCombinedSln/FairPlayCombined.SharedAuth/Components/Account/Pages/ExternalLogin.razor

+50-17
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
@using System.Text.Encodings.Web
77
@using FairPlayCombined.Common.CustomAttributes
88
@using FairPlayCombined.Common.ValidationAttributes
9+
@using FairPlayCombined.Interfaces
910
@using FairPlayCombined.Models.Auth.ExternalLogin
1011
@using Microsoft.AspNetCore.Authentication
1112
@using Microsoft.AspNetCore.Identity
@@ -21,6 +22,7 @@
2122
@inject IdentityRedirectManager RedirectManager
2223
@inject ILogger<ExternalLogin> Logger
2324
@inject IStringLocalizer<ExternalLogin> localizer
25+
@inject IUserValidationService userValidationService
2426

2527
<PageTitle>@localizer[RegisterTextKey]</PageTitle>
2628

@@ -50,7 +52,7 @@
5052
<label for="name" class="@ThemeConfiguration.Labels.DefaultCss">@localizer[NameTextKey]</label>
5153
<InputText @bind-Value="Input.Name"
5254
class="@ThemeConfiguration.GenericControls.DefaultCss" autocomplete="name"
53-
placeholder="@EnterYourNameText" />
55+
placeholder="@EnterYourNameText" />
5456
<ValidationMessage For="() => Input.Name" />
5557
</div>
5658
<div class="@ThemeConfiguration.Divisions.DefaultCss">
@@ -62,40 +64,49 @@
6264
</div>
6365
<div class="@ThemeConfiguration.Divisions.DefaultCss">
6466
<label for="linkedinprofileurl"
65-
class="@ThemeConfiguration.Labels.DefaultCss">@localizer[LinkedInProfileUrlTextKey]</label>
67+
class="@ThemeConfiguration.Labels.DefaultCss">@localizer[LinkedInProfileUrlTextKey]</label>
6668
<InputText @bind-Value="Input.LinkedInProfileUrl"
67-
class="@ThemeConfiguration.GenericControls.DefaultCss"
68-
autocomplete="linkedinprofileurl"
69-
placeholder="@EnterYourLinkedInProfileURL" />
69+
class="@ThemeConfiguration.GenericControls.DefaultCss"
70+
autocomplete="linkedinprofileurl"
71+
placeholder="@EnterYourLinkedInProfileURL" />
7072
<ValidationMessage For="() => Input.LinkedInProfileUrl" />
7173
</div>
7274
<div class="@ThemeConfiguration.Divisions.DefaultCss">
7375
<label for="instagramprofileurl"
74-
class="@ThemeConfiguration.Labels.DefaultCss">@localizer[InstagramProfileUrlTextKey]</label>
76+
class="@ThemeConfiguration.Labels.DefaultCss">@localizer[InstagramProfileUrlTextKey]</label>
7577
<InputText @bind-Value="Input.InstagramProfileUrl"
76-
class="@ThemeConfiguration.GenericControls.DefaultCss"
77-
autocomplete="instagramprofileurl"
78-
placeholder="@EnterYourInstagramProfileUrl" />
78+
class="@ThemeConfiguration.GenericControls.DefaultCss"
79+
autocomplete="instagramprofileurl"
80+
placeholder="@EnterYourInstagramProfileUrl" />
7981
<ValidationMessage For="() => Input.InstagramProfileUrl" />
8082
</div>
8183
<div class="@ThemeConfiguration.Divisions.DefaultCss">
8284
<label for="xformerlytwitterurl"
83-
class="@ThemeConfiguration.Labels.DefaultCss">@localizer[XFormerlyTwitterProfileUrlTextKey]</label>
85+
class="@ThemeConfiguration.Labels.DefaultCss">@localizer[XFormerlyTwitterProfileUrlTextKey]</label>
8486
<InputText @bind-Value="Input.XformerlyTwitterUrl"
85-
class="@ThemeConfiguration.GenericControls.DefaultCss"
86-
autocomplete="xformerlytwitterurl"
87-
placeholder="@EnterYourXFormerlyTwitterProfileUrl" />
87+
class="@ThemeConfiguration.GenericControls.DefaultCss"
88+
autocomplete="xformerlytwitterurl"
89+
placeholder="@EnterYourXFormerlyTwitterProfileUrl" />
8890
<ValidationMessage For="() => Input.XformerlyTwitterUrl" />
8991
</div>
9092
<div class="@ThemeConfiguration.Divisions.DefaultCss">
9193
<label for="websiteurl"
92-
class="@ThemeConfiguration.Labels.DefaultCss">@localizer[WebsiteUrlTextKey]</label>
94+
class="@ThemeConfiguration.Labels.DefaultCss">@localizer[WebsiteUrlTextKey]</label>
9395
<InputText @bind-Value="Input.WebsiteUrl"
94-
class="@ThemeConfiguration.GenericControls.DefaultCss"
95-
autocomplete="websiteurl"
96-
placeholder="@EnterYourWebsiteURL" />
96+
class="@ThemeConfiguration.GenericControls.DefaultCss"
97+
autocomplete="websiteurl"
98+
placeholder="@EnterYourWebsiteURL" />
9799
<ValidationMessage For="() => Input.WebsiteUrl" />
98100
</div>
101+
<div class="@ThemeConfiguration.Divisions.DefaultCss">
102+
<label for="reasontocreateaccount"
103+
class="@ThemeConfiguration.Labels.DefaultCss">@localizer[ReasonToCreateAccountTextKey]</label>
104+
<InputTextArea @bind-Value="Input.ReasonToCreateAccount"
105+
class="@ThemeConfiguration.GenericControls.DefaultCss"
106+
autocomplete="reasontocreateaccount"
107+
placeholder="@EnterYourReasonToCreateAccount" />
108+
<ValidationMessage For="() => Input.ReasonToCreateAccount" />
109+
</div>
99110
<button type="submit" class="w-100 btn btn-lg btn-primary">@localizer[RegisterTextKey]</button>
100111
</EditForm>
101112
</div>
@@ -192,6 +203,22 @@
192203

193204
private async Task OnValidSubmitAsync()
194205
{
206+
try
207+
{
208+
await userValidationService.ValidateUserDataAsync(name: Input.Name, lastName: Input.Lastname, email: Input.Email,
209+
reasonToCreateAccount: Input.ReasonToCreateAccount!, CancellationToken.None);
210+
}
211+
catch (Exception ex)
212+
{
213+
IdentityError identityError = new()
214+
{
215+
Code = "N/A",
216+
Description = ex.Message
217+
};
218+
message = $"Error: {ex.Message}";
219+
return;
220+
}
221+
195222
var emailStore = GetEmailStore();
196223
var user = CreateUser();
197224
user.Name = Input.Name;
@@ -212,6 +239,7 @@
212239
{
213240
user.WebsiteUrl = Input.WebsiteUrl;
214241
}
242+
user.ReasonToCreateAccount = Input.ReasonToCreateAccount;
215243
await UserStore.SetUserNameAsync(user, Input.Email, CancellationToken.None);
216244
await emailStore.SetEmailAsync(user, Input.Email, CancellationToken.None);
217245

@@ -312,6 +340,11 @@
312340
[ResourceKey(defaultValue: "Please enter your Website URL")]
313341
public const string EnterYourWebsiteURLTextKey = "EnterYourWebsiteURLText";
314342
private string EnterYourWebsiteURL => localizer[EnterYourWebsiteURLTextKey];
343+
[ResourceKey(defaultValue: "Reason to create account")]
344+
public const string ReasonToCreateAccountTextKey = "ReasonToCreateAccountText";
345+
[ResourceKey("Enter your reason to create account")]
346+
public const string EnterYourReasonToCreateAccountTextKey = "EnterYourReasonToCreateAccountText";
347+
private string EnterYourReasonToCreateAccount => localizer[EnterYourReasonToCreateAccountTextKey];
315348
[ResourceKey(defaultValue: "Error from external provider")]
316349
public const string ErrorFromExternalProviderTextKey = "ErrorFromExternalProviderText";
317350
[ResourceKey(defaultValue: "Error loading external login information")]

0 commit comments

Comments
 (0)