Compare commits

...

No commits in common. "fixes/principal-onboarding" and "main" have entirely different histories.

340 changed files with 43 additions and 138877 deletions

367
.gitignore vendored
View File

@ -1,367 +0,0 @@
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
##
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
# User-specific files
*.rsuser
*.suo
*.user
*.userosscache
*.sln.docstates
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
# Mono auto generated files
mono_crash.*
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
[Ww][Ii][Nn]32/
[Aa][Rr][Mm]/
[Aa][Rr][Mm]64/
bld/
[Bb]in/
[Oo]bj/
[Ll]og/
[Ll]ogs/
# Visual Studio 2015/2017 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/
# Visual Studio 2017 auto generated files
Generated\ Files/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
# NUnit
*.VisualState.xml
TestResult.xml
nunit-*.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
# Benchmark Results
BenchmarkDotNet.Artifacts/
# .NET Core
project.lock.json
project.fragment.lock.json
artifacts/
# ASP.NET Scaffolding
ScaffoldingReadMe.txt
# StyleCop
StyleCopReport.xml
# Files built by Visual Studio
*_i.c
*_p.c
*_h.h
*.ilk
*.meta
*.obj
*.iobj
*.pch
*.pdb
*.ipdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*_wpftmp.csproj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Chutzpah Test files
_Chutzpah*
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
*.VC.db
*.VC.VC.opendb
# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap
# Visual Studio Trace Files
*.e2e
# TFS 2012 Local Workspace
$tf/
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# AxoCover is a Code Coverage Tool
.axoCover/*
!.axoCover/settings.json
# Coverlet is a free, cross platform Code Coverage Tool
coverage*.json
coverage*.xml
coverage*.info
# Visual Studio code coverage results
*.coverage
*.coveragexml
# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*
# MightyMoose
*.mm.*
AutoTest.Net/
# Web workbench (sass)
.sass-cache/
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# Note: Comment the next line if you want to checkin your web deploy settings,
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.publishproj
# Microsoft Azure Web App publish settings. Comment the next line if you want to
# checkin your Azure Web App publish settings, but sensitive information contained
# in these scripts will be unencrypted
PublishScripts/
# NuGet Packages
*.nupkg
# NuGet Symbol Packages
*.snupkg
# The packages folder can be ignored because of Package Restore
**/[Pp]ackages/*
# except build/, which is used as an MSBuild target.
!**/[Pp]ackages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/[Pp]ackages/repositories.config
# NuGet v3's project.json files produces more ignorable files
*.nuget.props
*.nuget.targets
# Microsoft Azure Build Output
csx/
*.build.csdef
# Microsoft Azure Emulator
ecf/
rcf/
# Windows Store app package directories and files
AppPackages/
BundleArtifacts/
Package.StoreAssociation.xml
_pkginfo.txt
*.appx
*.appxbundle
*.appxupload
# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!?*.[Cc]ache/
# Others
ClientBin/
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.jfm
*.pfx
*.publishsettings
orleans.codegen.cs
# Including strong name files can present a security risk
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
#*.snk
# Since there are multiple workflows, uncomment next line to ignore bower_components
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
#bower_components/
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
ServiceFabricBackup/
*.rptproj.bak
# SQL Server files
*.mdf
*.ldf
*.ndf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
*.rptproj.rsuser
*- [Bb]ackup.rdl
*- [Bb]ackup ([0-9]).rdl
*- [Bb]ackup ([0-9][0-9]).rdl
# Microsoft Fakes
FakesAssemblies/
# GhostDoc plugin setting file
*.GhostDoc.xml
# Node.js Tools for Visual Studio
.ntvs_analysis.dat
node_modules/
# Visual Studio 6 build log
*.plg
# Visual Studio 6 workspace options file
*.opt
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
*.vbw
# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions
# Paket dependency manager
.paket/paket.exe
paket-files/
# FAKE - F# Make
.fake/
# CodeRush personal settings
.cr/personal
# Python Tools for Visual Studio (PTVS)
__pycache__/
*.pyc
# Cake - Uncomment if you are using it
# tools/**
# !tools/packages.config
# Tabs Studio
*.tss
# Telerik's JustMock configuration file
*.jmconfig
# BizTalk build output
*.btp.cs
*.btm.cs
*.odx.cs
*.xsd.cs
# OpenCover UI analysis results
OpenCover/
# Azure Stream Analytics local run output
ASALocalRun/
# MSBuild Binary and Structured Log
*.binlog
# NVidia Nsight GPU debugger configuration file
*.nvuser
# MFractors (Xamarin productivity tool) working folder
.mfractor/
# Local History for Visual Studio
.localhistory/
# BeatPulse healthcheck temp database
healthchecksdb
# Backup folder for Package Reference Convert tool in Visual Studio 2017
MigrationBackup/
# Ionide (cross platform F# VS Code tools) working folder
.ionide/
# Fody - auto-generated XML schema
FodyWeavers.xsd
.parcel*/
/EnotaryoPH/EnotaryoPH.Web/wwwroot/dist
/EnotaryoPH/EnotaryoPH.Web/dist/

View File

@ -1,286 +0,0 @@
# Remove the line below if you want to inherit .editorconfig settings from higher directories
root = true
# C# files
[*.cs]
#### Core EditorConfig Options ####
# Indentation and spacing
indent_size = 4
indent_style = space
tab_width = 4
# New line preferences
end_of_line = crlf
insert_final_newline = false
#### .NET Code Actions ####
# Type members
dotnet_hide_advanced_members = false
dotnet_member_insertion_location = with_other_members_of_the_same_kind
dotnet_property_generation_behavior = prefer_auto_properties
# Symbol search
dotnet_search_reference_assemblies = true
#### .NET Coding Conventions ####
# Organize usings
dotnet_separate_import_directive_groups = false
dotnet_sort_system_directives_first = true
file_header_template = unset
# this. and Me. preferences
dotnet_style_qualification_for_event = false
dotnet_style_qualification_for_field = false
dotnet_style_qualification_for_method = false
dotnet_style_qualification_for_property = false
# Language keywords vs BCL types preferences
dotnet_style_predefined_type_for_locals_parameters_members = true
dotnet_style_predefined_type_for_member_access = true
# Parentheses preferences
dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity:error
dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:error
dotnet_style_parentheses_in_other_operators = never_if_unnecessary
dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity:error
# Modifier preferences
dotnet_style_require_accessibility_modifiers = for_non_interface_members
# Expression-level preferences
dotnet_prefer_system_hash_code = true
dotnet_style_coalesce_expression = true:error
dotnet_style_collection_initializer = true:error
dotnet_style_explicit_tuple_names = true:error
dotnet_style_namespace_match_folder = true
dotnet_style_null_propagation = true:error
dotnet_style_object_initializer = true:error
dotnet_style_operator_placement_when_wrapping = beginning_of_line
dotnet_style_prefer_auto_properties = true:error
dotnet_style_prefer_collection_expression = when_types_loosely_match
dotnet_style_prefer_compound_assignment = true
dotnet_style_prefer_conditional_expression_over_assignment = true:suggestion
dotnet_style_prefer_conditional_expression_over_return = true:error
dotnet_style_prefer_foreach_explicit_cast_in_source = when_strongly_typed
dotnet_style_prefer_inferred_anonymous_type_member_names = true:error
dotnet_style_prefer_inferred_tuple_names = true
dotnet_style_prefer_is_null_check_over_reference_equality_method = true:error
dotnet_style_prefer_simplified_boolean_expressions = true:error
dotnet_style_prefer_simplified_interpolation = true
# Field preferences
dotnet_style_readonly_field = true:warning
# Parameter preferences
dotnet_code_quality_unused_parameters = all:warning
# Suppression preferences
dotnet_remove_unnecessary_suppression_exclusions = none
# New line preferences
dotnet_style_allow_multiple_blank_lines_experimental = false:error
dotnet_style_allow_statement_immediately_after_block_experimental = true
#### C# Coding Conventions ####
# var preferences
csharp_style_var_elsewhere = true:suggestion
csharp_style_var_for_built_in_types = true
csharp_style_var_when_type_is_apparent = true:error
# Expression-bodied members
csharp_style_expression_bodied_accessors = true:error
csharp_style_expression_bodied_constructors = true:error
csharp_style_expression_bodied_indexers = true:error
csharp_style_expression_bodied_lambdas = true:error
csharp_style_expression_bodied_local_functions = when_on_single_line:error
csharp_style_expression_bodied_methods = true:error
csharp_style_expression_bodied_operators = true:error
csharp_style_expression_bodied_properties = true:error
# Pattern matching preferences
csharp_style_pattern_matching_over_as_with_null_check = true:error
csharp_style_pattern_matching_over_is_with_cast_check = true:error
csharp_style_prefer_extended_property_pattern = true
csharp_style_prefer_not_pattern = true:error
csharp_style_prefer_pattern_matching = true:error
csharp_style_prefer_switch_expression = true:error
# Null-checking preferences
csharp_style_conditional_delegate_call = true:error
# Modifier preferences
csharp_prefer_static_anonymous_function = true
csharp_prefer_static_local_function = true
csharp_preferred_modifier_order = public,private,protected,internal,file,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,required,volatile,async
csharp_style_prefer_readonly_struct = true:warning
csharp_style_prefer_readonly_struct_member = true
# Code-block preferences
csharp_prefer_braces = true:error
csharp_prefer_simple_using_statement = true:error
csharp_prefer_system_threading_lock = true
csharp_style_namespace_declarations = block_scoped
csharp_style_prefer_method_group_conversion = true:error
csharp_style_prefer_primary_constructors = true
csharp_style_prefer_top_level_statements = true
# Expression-level preferences
csharp_prefer_simple_default_expression = true:error
csharp_style_deconstructed_variable_declaration = true:error
csharp_style_implicit_object_creation_when_type_is_apparent = true:error
csharp_style_inlined_variable_declaration = true:error
csharp_style_prefer_index_operator = true:error
csharp_style_prefer_local_over_anonymous_function = true
csharp_style_prefer_null_check_over_type_check = true:error
csharp_style_prefer_range_operator = true:error
csharp_style_prefer_tuple_swap = true:error
csharp_style_prefer_utf8_string_literals = true
csharp_style_throw_expression = true
csharp_style_unused_value_assignment_preference = discard_variable
csharp_style_unused_value_expression_statement_preference = discard_variable
# 'using' directive preferences
csharp_using_directive_placement = outside_namespace:error
# New line preferences
csharp_style_allow_blank_line_after_colon_in_constructor_initializer_experimental = true
csharp_style_allow_blank_line_after_token_in_arrow_expression_clause_experimental = true
csharp_style_allow_blank_line_after_token_in_conditional_expression_experimental = true
csharp_style_allow_blank_lines_between_consecutive_braces_experimental = false:error
csharp_style_allow_embedded_statements_on_same_line_experimental = true
#### C# Formatting Rules ####
# New line preferences
csharp_new_line_before_catch = true
csharp_new_line_before_else = true
csharp_new_line_before_finally = true
csharp_new_line_before_members_in_anonymous_types = true
csharp_new_line_before_members_in_object_initializers = true
csharp_new_line_before_open_brace = all
csharp_new_line_between_query_expression_clauses = true
# Indentation preferences
csharp_indent_block_contents = true
csharp_indent_braces = false
csharp_indent_case_contents = true
csharp_indent_case_contents_when_block = true
csharp_indent_labels = one_less_than_current
csharp_indent_switch_labels = true
# Space preferences
csharp_space_after_cast = false
csharp_space_after_colon_in_inheritance_clause = true
csharp_space_after_comma = true
csharp_space_after_dot = false
csharp_space_after_keywords_in_control_flow_statements = true
csharp_space_after_semicolon_in_for_statement = true
csharp_space_around_binary_operators = before_and_after
csharp_space_around_declaration_statements = false
csharp_space_before_colon_in_inheritance_clause = true
csharp_space_before_comma = false
csharp_space_before_dot = false
csharp_space_before_open_square_brackets = false
csharp_space_before_semicolon_in_for_statement = false
csharp_space_between_empty_square_brackets = false
csharp_space_between_method_call_empty_parameter_list_parentheses = false
csharp_space_between_method_call_name_and_opening_parenthesis = false
csharp_space_between_method_call_parameter_list_parentheses = false
csharp_space_between_method_declaration_empty_parameter_list_parentheses = false
csharp_space_between_method_declaration_name_and_open_parenthesis = false
csharp_space_between_method_declaration_parameter_list_parentheses = false
csharp_space_between_parentheses = false
csharp_space_between_square_brackets = false
# Wrapping preferences
csharp_preserve_single_line_blocks = true
csharp_preserve_single_line_statements = false
#### Naming styles ####
# Naming rules
dotnet_naming_rule.private_or_internal_readonly_field_should_be_begins_with__.severity = warning
dotnet_naming_rule.private_or_internal_readonly_field_should_be_begins_with__.symbols = private_or_internal_readonly_field
dotnet_naming_rule.private_or_internal_readonly_field_should_be_begins_with__.style = begins_with__
dotnet_naming_rule.private_or_internal_field_should_be_begins_with__.severity = warning
dotnet_naming_rule.private_or_internal_field_should_be_begins_with__.symbols = private_or_internal_field
dotnet_naming_rule.private_or_internal_field_should_be_begins_with__.style = begins_with__
dotnet_naming_rule.private_or_internal_static_field_should_be_begins_with__.severity = warning
dotnet_naming_rule.private_or_internal_static_field_should_be_begins_with__.symbols = private_or_internal_static_field
dotnet_naming_rule.private_or_internal_static_field_should_be_begins_with__.style = begins_with__
dotnet_naming_rule.interface_should_be_begins_with_i.severity = suggestion
dotnet_naming_rule.interface_should_be_begins_with_i.symbols = interface
dotnet_naming_rule.interface_should_be_begins_with_i.style = begins_with_i
dotnet_naming_rule.types_should_be_pascal_case.severity = suggestion
dotnet_naming_rule.types_should_be_pascal_case.symbols = types
dotnet_naming_rule.types_should_be_pascal_case.style = pascal_case
dotnet_naming_rule.non_field_members_should_be_pascal_case.severity = suggestion
dotnet_naming_rule.non_field_members_should_be_pascal_case.symbols = non_field_members
dotnet_naming_rule.non_field_members_should_be_pascal_case.style = pascal_case
dotnet_naming_rule.enum_should_be_ends_with_enum.severity = warning
dotnet_naming_rule.enum_should_be_ends_with_enum.symbols = enum
dotnet_naming_rule.enum_should_be_ends_with_enum.style = ends_with_enum
# Symbol specifications
dotnet_naming_symbols.interface.applicable_kinds = interface
dotnet_naming_symbols.interface.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
dotnet_naming_symbols.interface.required_modifiers =
dotnet_naming_symbols.enum.applicable_kinds = enum
dotnet_naming_symbols.enum.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
dotnet_naming_symbols.enum.required_modifiers =
dotnet_naming_symbols.private_or_internal_field.applicable_kinds = field
dotnet_naming_symbols.private_or_internal_field.applicable_accessibilities = internal, private, private_protected
dotnet_naming_symbols.private_or_internal_field.required_modifiers =
dotnet_naming_symbols.private_or_internal_static_field.applicable_kinds = field
dotnet_naming_symbols.private_or_internal_static_field.applicable_accessibilities = internal, private, private_protected
dotnet_naming_symbols.private_or_internal_static_field.required_modifiers = static
dotnet_naming_symbols.types.applicable_kinds = class, struct, interface, enum
dotnet_naming_symbols.types.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
dotnet_naming_symbols.types.required_modifiers =
dotnet_naming_symbols.non_field_members.applicable_kinds = property, event, method
dotnet_naming_symbols.non_field_members.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
dotnet_naming_symbols.non_field_members.required_modifiers =
dotnet_naming_symbols.private_or_internal_readonly_field.applicable_kinds = field
dotnet_naming_symbols.private_or_internal_readonly_field.applicable_accessibilities = internal, private, private_protected
dotnet_naming_symbols.private_or_internal_readonly_field.required_modifiers = readonly
# Naming styles
dotnet_naming_style.pascal_case.required_prefix =
dotnet_naming_style.pascal_case.required_suffix =
dotnet_naming_style.pascal_case.word_separator =
dotnet_naming_style.pascal_case.capitalization = pascal_case
dotnet_naming_style.begins_with_i.required_prefix = I
dotnet_naming_style.begins_with_i.required_suffix =
dotnet_naming_style.begins_with_i.word_separator =
dotnet_naming_style.begins_with_i.capitalization = pascal_case
dotnet_naming_style.begins_with__.required_prefix = _
dotnet_naming_style.begins_with__.required_suffix =
dotnet_naming_style.begins_with__.word_separator =
dotnet_naming_style.begins_with__.capitalization = camel_case
dotnet_naming_style.ends_with_enum.required_prefix =
dotnet_naming_style.ends_with_enum.required_suffix = Enum
dotnet_naming_style.ends_with_enum.word_separator =
dotnet_naming_style.ends_with_enum.capitalization = pascal_case

View File

@ -1,9 +0,0 @@
namespace EnotaryoPH.Data.Constants
{
public enum DocumentSigningStatus
{
New = 0,
ReadyForSigning = 10,
Signed = 20
}
}

View File

@ -1,8 +0,0 @@
namespace EnotaryoPH.Data.Constants
{
public enum LawyerStatus
{
New = 0,
FingerprintScanned = 5
}
}

View File

@ -1,40 +0,0 @@
namespace EnotaryoPH.Data.Constants
{
public enum NotaryoEvent
{
Unknown = 0,
PrincipalRegistered = 1,
SignatoryRegistered = 2,
WitnessRegistered = 3,
LawyerRegistered = 4,
LawyerFingerprintScanned = 5,
IdentificationDocumentUploaded = 10,
SelfiePassed = 15,
SelfieFailed = 16,
DocumentUploaded = 20,
LawyerSelected = 30,
TransactionSubmitted = 40,
TransactionApproved = 41,
TransactionRejected = 42,
OTPSent = 45,
OTPVerified = 46,
VideoConferenceStarted = 50,
VideoRecordingStarted = 51,
VideoRecordingStopped = 52,
SignatoryApproved = 61,
WitnessApproved = 62,
PaymentReceived = 70,
PaymentFailed = 71,
TransactionCompleted = 100
}
}

View File

@ -1,12 +0,0 @@
namespace EnotaryoPH.Data.Constants
{
public enum SignatoryStatus
{
New = 0,
EmailSent = 1,
Registered = 2,
FaceMatch = 3,
Approved = 4,
Rejected = 5,
}
}

View File

@ -1,9 +0,0 @@
namespace EnotaryoPH.Data.Constants
{
public enum SignatoryType
{
Unknown = 0,
Principal = 1,
Witness = 2
}
}

View File

@ -1,14 +0,0 @@
namespace EnotaryoPH.Data.Constants
{
public enum TransactionState
{
New = 0,
SelfiePassed = 1,
DocumentUploaded = 2,
Submitted = 3,
Accepted = 4,
Approved = 5,
Rejected = 6,
Completed = 100
}
}

View File

@ -1,11 +0,0 @@
namespace EnotaryoPH.Data.Constants
{
public enum UserType
{
Principal = 0,
Witness = 1,
Notary = 2,
SuperUser = 10,
Administrator = 100
}
}

View File

@ -1,11 +0,0 @@
namespace EnotaryoPH.Data.Constants
{
public enum VideoConferenceStatus
{
New = 0,
InProgress = 1,
Expired = 49,
Abandoned = 50,
Completed = 100
}
}

View File

@ -1,10 +0,0 @@
namespace EnotaryoPH.Data.Constants
{
public enum VideoRecordingLocationType
{
Unknown = 0,
LocalFolder = 1,
SharedFolder = 2,
AzureBlob = 3
}
}

View File

@ -1,15 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="9.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="9.0.0" />
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="9.0.2" />
</ItemGroup>
</Project>

View File

@ -1,29 +0,0 @@
using System.ComponentModel.DataAnnotations.Schema;
namespace EnotaryoPH.Data.Entities
{
[Table("ErrorLogs")]
public class ErrorLog
{
[Column("ErrorLogID")]
public int ErrorLogID { get; set; }
[Column("Message")]
public string Message { get; set; }
[Column("CreatedOn")]
public DateTime? CreatedOn { get; set; }
[Column("Severity")]
public string? Severity { get; set; }
[Column("Exception")]
public string? Exception { get; set; }
[Column("Stacktrace")]
public string? Stacktrace { get; set; }
[Column("ErrorLog_UID")]
public Guid? ErrorLog_UID { get; set; }
}
}

View File

@ -1,35 +0,0 @@
using System.ComponentModel.DataAnnotations.Schema;
namespace EnotaryoPH.Data.Entities
{
[Table("EventLogs")]
public class EventLog
{
[Column("EventLogID")]
public int EventLogID { get; set; }
[Column("StreamID")]
public string StreamID { get; set; }
[Column("LogType")]
public string LogType { get; set; }
[Column("LogDate")]
public DateTime? LogDate { get; set; }
[Column("UserID")]
public int? UserID { get; set; }
[Column("Payload")]
public string Payload { get; set; }
[Column("Description")]
public string? Description { get; set; }
[Column("EventLog_UID")]
public Guid? EventLog_UID { get; set; }
[ForeignKey("UserID")]
public User User { get; set; }
}
}

View File

@ -1,52 +0,0 @@
using System.ComponentModel.DataAnnotations.Schema;
namespace EnotaryoPH.Data.Entities
{
[Table("IdentificationDocuments")]
public class IdentificationDocument
{
[Column("IdentificationDocumentID")]
public int IdentificationDocumentID { get; set; }
[Column("Type")]
public string Type { get; set; }
[Column("ExpirationDate")]
public DateTime ExpirationDate { get; set; }
[Column("Filename")]
public string Filename { get; set; }
[Column("File")]
public byte[] File { get; set; }
[Column("UploadedOn")]
public DateTime UploadedOn { get; set; }
[Column("UserID")]
public int UserID { get; set; }
[Column("IsDeleted")]
public bool? IsDeleted { get; set; }
[Column("IdNumber")]
public string IdNumber { get; set; }
[Column("PlaceIssued")]
public string PlaceIssued { get; set; }
[Column("DateIssued")]
public DateTime DateIssued { get; set; }
[Column("CreatedOn")]
public DateTime? CreatedOn { get; set; }
[Column("IdentificationDocument_UID")]
public Guid? IdentificationDocument_UID { get; set; }
[ForeignKey("UserID")]
public User User { get; set; }
public List<TransactionSelfie> TransactionSelfie { get; set; }
}
}

View File

@ -1,61 +0,0 @@
using System.ComponentModel.DataAnnotations.Schema;
namespace EnotaryoPH.Data.Entities
{
[Table("Lawyers")]
public class Lawyer
{
[Column("CommissionExpiration")]
public DateTime? CommissionExpiration { get; set; }
[Column("CommissionLocation")]
public string? CommissionLocation { get; set; }
[Column("CommissionNumber")]
public string? CommissionNumber { get; set; }
[Column("CreatedOn")]
public DateTime? CreatedOn { get; set; }
[Column("IBPNumber")]
public string? IBPNumber { get; set; }
[Column("Lawyer_UID")]
public Guid? Lawyer_UID { get; set; }
[Column("LawyerID")]
public int LawyerID { get; set; }
public List<LawyerVideoConferenceSchedule> LawyerVideoConferenceSchedules { get; set; }
[Column("MCLEComplianceNumber")]
public string? MCLEComplianceNumber { get; set; }
[Column("MCLEDate")]
public DateTime? MCLEDate { get; set; }
[Column("OfficeAddress")]
public string? OfficeAddress { get; set; }
[Column("PTRDate")]
public DateTime? PTRDate { get; set; }
[Column("PTRlocation")]
public string? PTRlocation { get; set; }
[Column("PTRNumber")]
public string? PTRNumber { get; set; }
[Column("Rollnumber")]
public string? Rollnumber { get; set; }
[Column("Status")]
public string? Status { get; set; }
[ForeignKey("UserID")]
public User User { get; set; }
[Column("UserID")]
public int UserID { get; set; }
}
}

View File

@ -1,56 +0,0 @@
using System.ComponentModel.DataAnnotations.Schema;
namespace EnotaryoPH.Data.Entities
{
[Table("LawyerVideoConferenceParticipants")]
public class LawyerVideoConferenceParticipant
{
[Column("CreatedOn")]
public DateTime? CreatedOn { get; set; }
[Column("Device")]
public string? Device { get; set; }
[Column("IPAddress")]
public string? IPAddress { get; set; }
[Column("Latitude")]
public decimal? Latitude { get; set; }
[Column("LawyerVideoConferenceParticipant_UID")]
public Guid? LawyerVideoConferenceParticipant_UID { get; set; }
[Column("LawyerVideoConferenceParticipantID")]
public int LawyerVideoConferenceParticipantID { get; set; }
[ForeignKey("LawyerVideoConferenceScheduleID")]
public LawyerVideoConferenceSchedule LawyerVideoConferenceSchedule { get; set; }
[Column("LawyerVideoConferenceScheduleID")]
public int LawyerVideoConferenceScheduleID { get; set; }
[Column("Longitude")]
public decimal? Longitude { get; set; }
[Column("MeetingRoomTokenID")]
public string? MeetingRoomTokenID { get; set; }
[Column("MeetingRoomUserID")]
public string? MeetingRoomUserID { get; set; }
[Column("OTPEntered")]
public string? OTPEntered { get; set; }
[Column("OTPHash")]
public string? OTPHash { get; set; }
[ForeignKey("ParticipantID")]
public User Participant { get; set; }
[Column("ParticipantID")]
public int? ParticipantID { get; set; }
[Column("Status")]
public string? Status { get; set; }
}
}

View File

@ -1,54 +0,0 @@
using System.ComponentModel.DataAnnotations.Schema;
namespace EnotaryoPH.Data.Entities
{
[Table("LawyerVideoConferenceSchedule")]
public class LawyerVideoConferenceSchedule
{
[Column("CreatedOn")]
public DateTime? CreatedOn { get; set; }
[ForeignKey("LawyerID")]
public Lawyer Lawyer { get; set; }
[Column("LawyerID")]
public int LawyerID { get; set; }
public List<LawyerVideoConferenceParticipant> LawyerVideoConferenceParticipants { get; set; }
[Column("LawyerVideoConferenceSchedule_UID")]
public Guid LawyerVideoConferenceSchedule_UID { get; set; }
[Column("LawyerVideoConferenceScheduleID")]
public int LawyerVideoConferenceScheduleID { get; set; }
[Column("MeetingDate")]
public DateTime MeetingDate { get; set; }
[Column("MeetingRoomID")]
public string? MeetingRoomID { get; set; }
[Column("MeetingRoomTokenID")]
public string? MeetingRoomTokenID { get; set; }
[Column("MeetingRoomUserID")]
public string? MeetingRoomUserID { get; set; }
[Column("RecordingID")]
public string? RecordingID { get; set; }
[Column("ServerCallID")]
public string? ServerCallID { get; set; }
[Column("Status")]
public string? Status { get; set; }
[ForeignKey("TransactionID")]
public Transaction Transaction { get; set; }
[Column("TransactionID")]
public int TransactionID { get; set; }
public VideoRecording VideoRecording { get; set; }
}
}

View File

@ -1,31 +0,0 @@
using System.ComponentModel.DataAnnotations.Schema;
namespace EnotaryoPH.Data.Entities
{
[Table("LookupData")]
public class LookupData
{
[Column("Category")]
public string? Category { get; set; }
[Column("CreatedOn")]
public DateTime? CreatedOn { get; set; }
[Column("Description")]
public string? Description { get; set; }
[Column("LookupData_UID")]
public Guid LookupData_UID { get; set; }
[Column("LookupDataID")]
public int LookupDataID { get; set; }
public List<LookupDataValue> LookupDataValues { get; set; } = [];
[Column("Name")]
public string Name { get; set; }
[Column("ParentCategory")]
public string? ParentCategory { get; set; }
}
}

View File

@ -1,32 +0,0 @@
using System.ComponentModel.DataAnnotations.Schema;
namespace EnotaryoPH.Data.Entities
{
[Table("LookupDataValues")]
public class LookupDataValue
{
[Column("LookupDataValueID")]
public int LookupDataValueID { get; set; }
[Column("LookupDataValue_UID")]
public Guid LookupDataValue_UID { get; set; }
[Column("LookupDataID")]
public int? LookupDataID { get; set; }
[Column("Value")]
public string Value { get; set; }
[Column("Title")]
public string? Title { get; set; }
[Column("SortOrder")]
public int? SortOrder { get; set; }
[Column("CreatedOn")]
public DateTime? CreatedOn { get; set; }
[ForeignKey("LookupDataID")]
public LookupData LookupData { get; set; }
}
}

View File

@ -1,29 +0,0 @@
using System.ComponentModel.DataAnnotations.Schema;
namespace EnotaryoPH.Data.Entities
{
[Table("Templates")]
public class Template
{
[Column("TemplateID")]
public int TemplateID { get; set; }
[Column("Name")]
public string Name { get; set; }
[Column("Description")]
public string? Description { get; set; }
[Column("Pagecount")]
public int? Pagecount { get; set; }
[Column("CreatedOn")]
public DateTime? CreatedOn { get; set; }
[Column("TemplateUrl")]
public string? TemplateUrl { get; set; }
[Column("Template_UID")]
public Guid? Template_UID { get; set; }
}
}

View File

@ -1,52 +0,0 @@
using System.ComponentModel.DataAnnotations.Schema;
namespace EnotaryoPH.Data.Entities
{
[Table("Transactions")]
public class Transaction
{
[Column("CreatedOn")]
public DateTime? CreatedOn { get; set; }
[Column("IsRecorded")]
public bool? IsRecorded { get; set; }
[ForeignKey("LawyerID")]
public Lawyer Lawyer { get; set; }
[Column("LawyerID")]
public int? LawyerID { get; set; }
[ForeignKey("PreferredLawyerID")]
public Lawyer PreferredLawyer { get; set; }
[Column("PreferredLawyerID")]
public int? PreferredLawyerID { get; set; }
[ForeignKey("PrincipalID")]
public User Principal { get; set; }
[Column("PrincipalID")]
public int PrincipalID { get; set; }
public LawyerVideoConferenceSchedule Schedule { get; set; }
[Column("Status")]
public string Status { get; set; }
[Column("Transaction_UID")]
public Guid? Transaction_UID { get; set; }
[Column("TransactionDate")]
public DateTime TransactionDate { get; set; }
public TransactionDocument TransactionDocument { get; set; }
[Column("TransactionID")]
public int TransactionID { get; set; }
public List<TransactionSelfie> TransactionSelfies { get; set; }
public List<TransactionSignatory> TransactionSignatories { get; set; }
}
}

View File

@ -1,26 +0,0 @@
using System.ComponentModel.DataAnnotations.Schema;
namespace EnotaryoPH.Data.Entities
{
[Table("TransactionDeclineReasons")]
public class TransactionDeclineReason
{
[Column("TransactionDeclineReasonID")]
public int TransactionDeclineReasonID { get; set; }
[Column("TransactionID")]
public int TransactionID { get; set; }
[Column("Reason")]
public string Reason { get; set; }
[Column("LawyerID")]
public int LawyerID { get; set; }
[Column("CreatedOn")]
public DateTime? CreatedOn { get; set; }
[Column("TransactionDeclineReason_UID")]
public Guid? TransactionDeclineReason_UID { get; set; }
}
}

View File

@ -1,38 +0,0 @@
using System.ComponentModel.DataAnnotations.Schema;
namespace EnotaryoPH.Data.Entities
{
[Table("TransactionDocuments")]
public class TransactionDocument
{
[Column("CreatedOn")]
public DateTime? CreatedOn { get; set; }
[Column("DocumentType")]
public string DocumentType { get; set; }
[Column("File")]
public byte[] File { get; set; }
[Column("Filename")]
public string Filename { get; set; }
[Column("Notes")]
public string? Notes { get; set; }
[ForeignKey("TransactionID")]
public Transaction Transaction { get; set; }
[Column("TransactionDocument_UID")]
public Guid? TransactionDocument_UID { get; set; }
[Column("TransactionDocumentID")]
public int TransactionDocumentID { get; set; }
[Column("TransactionID")]
public int TransactionID { get; set; }
[Column("UploadedOn")]
public DateTime UploadedOn { get; set; }
}
}

View File

@ -1,47 +0,0 @@
using System.ComponentModel.DataAnnotations.Schema;
namespace EnotaryoPH.Data.Entities
{
[Table("TransactionNotary")]
public class TransactionNotary
{
[Column("TransactionNotaryID")]
public int TransactionNotaryID { get; set; }
[Column("TransactionID")]
public int TransactionID { get; set; }
[Column("DocNumber")]
public string? DocNumber { get; set; }
[Column("BookNumber")]
public string? BookNumber { get; set; }
[Column("PageNumber")]
public string? PageNumber { get; set; }
[Column("Series")]
public string? Series { get; set; }
[Column("SignedOn")]
public DateTime? SignedOn { get; set; }
[Column("Remarks")]
public string? Remarks { get; set; }
[Column("LawyerID")]
public int LawyerID { get; set; }
[Column("CertificateType")]
public string? CertificateType { get; set; }
[Column("TemplateID")]
public int? TemplateID { get; set; }
[Column("PageCount")]
public int? PageCount { get; set; }
[Column("TransactionNotary_UID")]
public Guid? TransactionNotary_UID { get; set; }
}
}

View File

@ -1,50 +0,0 @@
using System.ComponentModel.DataAnnotations.Schema;
namespace EnotaryoPH.Data.Entities
{
[Table("TransactionOTP")]
public class TransactionOTP
{
[Column("TransactionOTPID")]
public int TransactionOTPID { get; set; }
[Column("TransactionID")]
public int TransactionID { get; set; }
[Column("VerifiedOn")]
public DateTime VerifiedOn { get; set; }
[Column("PrintCoords")]
public string PrintCoords { get; set; }
[Column("Status")]
public string Status { get; set; }
[Column("UserID")]
public int UserID { get; set; }
[Column("TransactionOTP_UID")]
public Guid? TransactionOTP_UID { get; set; }
[Column("OTPHash")]
public string OTPHash { get; set; }
[Column("OTPUserInput")]
public string? OTPUserInput { get; set; }
[Column("IPAddress")]
public string? IPAddress { get; set; }
[Column("Longitude")]
public int? Longitude { get; set; }
[Column("Lattitude")]
public int? Lattitude { get; set; }
[Column("Device")]
public string? Device { get; set; }
[Column("File_Liveness")]
public byte[]? File_Liveness { get; set; }
}
}

View File

@ -1,35 +0,0 @@
using System.ComponentModel.DataAnnotations.Schema;
namespace EnotaryoPH.Data.Entities
{
[Table("TransactionSelfies")]
public class TransactionSelfie
{
[Column("TransactionSelfieID")]
public int TransactionSelfieID { get; set; }
[Column("TransactionID")]
public int? TransactionID { get; set; }
[Column("IdentificationDocumentID")]
public int? IdentificationDocumentID { get; set; }
[Column("File")]
public byte[] File { get; set; }
[Column("CreatedOn")]
public DateTime? CreatedOn { get; set; }
[Column("TransactionSelfie_UID")]
public Guid? TransactionSelfie_UID { get; set; }
[Column("UserID")]
public int UserID { get; set; }
[ForeignKey("UserID")]
public User User { get; set; }
[ForeignKey("TransactionID")]
public Transaction Transaction { get; set; }
}
}

View File

@ -1,26 +0,0 @@
using System.ComponentModel.DataAnnotations.Schema;
namespace EnotaryoPH.Data.Entities
{
[Table("TransactionSignatoryDeclineReasons")]
public class TransactionSignatoryDeclineReason
{
[Column("TransactionSignatoryDeclineReasonID")]
public int TransactionSignatoryDeclineReasonID { get; set; }
[Column("UserID")]
public int UserID { get; set; }
[Column("DeclineReason")]
public string DeclineReason { get; set; }
[Column("CreatedOn")]
public DateTime? CreatedOn { get; set; }
[Column("TransactionSignatoryDeclineReason_UID")]
public Guid TransactionSignatoryDeclineReason_UID { get; set; }
[Column("TransactionID")]
public int TransactionID { get; set; }
}
}

View File

@ -1,41 +0,0 @@
using System.ComponentModel.DataAnnotations.Schema;
namespace EnotaryoPH.Data.Entities
{
[Table("TransactionSignatories")]
public class TransactionSignatory
{
[Column("CreatedOn")]
public DateTime? CreatedOn { get; set; }
[Column("Email")]
public string Email { get; set; }
[Column("InvitationCode")]
public string InvitationCode { get; set; }
[Column("Status")]
public string Status { get; set; }
[ForeignKey("TransactionID")]
public Transaction Transaction { get; set; }
[Column("TransactionID")]
public int TransactionID { get; set; }
[Column("TransactionSignatory_UID")]
public Guid? TransactionSignatory_UID { get; set; }
[Column("TransactionSignatoryID")]
public int TransactionSignatoryID { get; set; }
[Column("Type")]
public string Type { get; set; }
[ForeignKey("UserID")]
public User? User { get; set; }
[Column("UserID")]
public int? UserID { get; set; }
}
}

View File

@ -1,58 +0,0 @@
using System.ComponentModel.DataAnnotations.Schema;
namespace EnotaryoPH.Data.Entities
{
[Table("Users")]
public class User
{
[Column("BirthDate")]
public DateTime BirthDate { get; set; }
[Column("CreatedOn")]
public DateTime? CreatedOn { get; set; }
[Column("Email")]
public string Email { get; set; }
public List<EventLog> EventLogs { get; set; }
[Column("Firstname")]
public string? Firstname { get; set; }
[NotMapped]
public string Fullname => $"{Firstname} {Lastname}".Trim();
public List<IdentificationDocument> IdentificationDocuments { get; set; }
[Column("Lastname")]
public string? Lastname { get; set; }
public List<LawyerVideoConferenceParticipant> LawyerVideoConferenceParticipants { get; set; }
[Column("Middlename")]
public string? Middlename { get; set; }
[Column("PasswordHash")]
public string PasswordHash { get; set; }
[Column("PhoneNumber")]
public string? PhoneNumber { get; set; }
[Column("Prefix")]
public string? Prefix { get; set; }
[Column("Role")]
public string? Role { get; set; }
public List<TransactionSignatory> Signatories { get; set; }
[Column("Suffix")]
public string? Suffix { get; set; }
[Column("User_UID")]
public Guid? User_UID { get; set; }
[Column("UserID")]
public int UserID { get; set; }
}
}

View File

@ -1,32 +0,0 @@
using System.ComponentModel.DataAnnotations.Schema;
namespace EnotaryoPH.Data.Entities
{
[Table("VideoRecordings")]
public class VideoRecording
{
[Column("CreatedOn")]
public DateTime? CreatedOn { get; set; }
[Column("LocationType")]
public string? LocationType { get; set; }
[Column("Metadata")]
public string? Metadata { get; set; }
[Column("Path")]
public string? Path { get; set; }
[ForeignKey("VideoConferenceScheduleID")]
public LawyerVideoConferenceSchedule VideoConferenceSchedule { get; set; }
[Column("VideoConferenceScheduleID")]
public int VideoConferenceScheduleID { get; set; }
[Column("VideoRecording_UID")]
public Guid? VideoRecording_UID { get; set; }
[Column("VideoRecordingID")]
public int VideoRecordingID { get; set; }
}
}

View File

@ -1,44 +0,0 @@
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
namespace EnotaryoPH.Data.Extensions
{
public static class ModelBuilderExtension
{
public static ModelBuilder UseValueConverterForType<T>(this ModelBuilder modelBuilder, ValueConverter converter) => modelBuilder.UseValueConverterForType(typeof(T), converter);
public static ModelBuilder UseValueConverterForType(this ModelBuilder modelBuilder, Type type, ValueConverter converter)
{
foreach (var entityType in modelBuilder.Model.GetEntityTypes())
{
// note that entityType.GetProperties() will throw an exception, so we have to use reflection
var properties = entityType.ClrType.GetProperties().Where(p => p.PropertyType == type);
foreach (var property in properties)
{
modelBuilder.Entity(entityType.Name).Property(property.Name)
.HasConversion(converter);
}
}
return modelBuilder;
}
public class DateTimeKindValueConverter : ValueConverter<DateTime, DateTime>
{
public DateTimeKindValueConverter(DateTimeKind kind, ConverterMappingHints mappingHints = null)
: base(
v => v.ToUniversalTime(),
v => DateTime.SpecifyKind(v, kind),
mappingHints)
{
}
}
public static void SetDefaultDateTimeKind(this ModelBuilder modelBuilder, DateTimeKind kind)
{
modelBuilder.UseValueConverterForType<DateTime>(new DateTimeKindValueConverter(kind));
modelBuilder.UseValueConverterForType<DateTime?>(new DateTimeKindValueConverter(kind));
}
}
}

View File

@ -1,55 +0,0 @@
using EnotaryoPH.Data.Entities;
using EnotaryoPH.Data.Extensions;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
namespace EnotaryoPH.Data
{
public class NotaryoDBContext : DbContext
{
private readonly IConfiguration _configuration;
public NotaryoDBContext(IConfiguration configuration, DbContextOptions<NotaryoDBContext> Options) : base(Options) => _configuration = configuration;
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) => optionsBuilder.UseNpgsql(_configuration.GetConnectionString("NotaryoDatabase"));
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.SetDefaultDateTimeKind(DateTimeKind.Utc);
base.OnModelCreating(modelBuilder);
}
public DbSet<ErrorLog> ErrorLogs { get; set; }
public DbSet<EventLog> EventLogs { get; set; }
public DbSet<IdentificationDocument> IdentificationDocuments { get; set; }
public DbSet<Lawyer> Lawyers { get; set; }
public DbSet<LawyerVideoConferenceParticipant> LawyerVideoConferenceParticipants { get; set; }
public DbSet<LawyerVideoConferenceSchedule> LawyerVideoConferenceSchedules { get; set; }
public DbSet<LookupData> LookupData { get; set; }
public DbSet<LookupDataValue> LookupDataValues { get; set; }
public DbSet<Template> Templates { get; set; }
public DbSet<TransactionDeclineReason> TransactionDeclineReasons { get; set; }
public DbSet<TransactionDocument> TransactionDocuments { get; set; }
public DbSet<TransactionNotary> TransactionNotaries { get; set; }
public DbSet<TransactionOTP> TransactionOTPs { get; set; }
public DbSet<Transaction> Transactions { get; set; }
public DbSet<TransactionSelfie> TransactionSelfies { get; set; }
public DbSet<TransactionSignatory> TransactionSignatories { get; set; }
public DbSet<TransactionSignatoryDeclineReason> TransactionSignatoryDeclineReasons { get; set; }
public DbSet<User> Users { get; set; }
public DbSet<VideoRecording> VideoRecordings { get; set; }
public TEntity UpdateOrCreate<TEntity>(TEntity entity) where TEntity : class
{
if (Entry(entity).State == EntityState.Detached)
{
Set<TEntity>().Add(entity);
}
else
{
Set<TEntity>().Update(entity);
}
return entity;
}
}
}

View File

@ -1,36 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net9.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<UserSecretsId>d6cabec2-f14e-40aa-b2ef-90a832d8e1e4</UserSecretsId>
</PropertyGroup>
<ItemGroup>
<None Remove="Scripts\01_Schema.sql" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Scripts\04_EventLog_StreamID.sql" />
<EmbeddedResource Include="Scripts\03_UserTracker.sql" />
<EmbeddedResource Include="Scripts\02_SeedLookupData.sql" />
<EmbeddedResource Include="Scripts\01_Schema.sql" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="dbup-core" Version="6.0.4" />
<PackageReference Include="dbup-postgresql" Version="6.0.3" />
<PackageReference Include="Microsoft.Extensions.Configuration" Version="9.0.4" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="9.0.4" />
<PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="9.0.4" />
</ItemGroup>
<ItemGroup>
<None Update="appsettings.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>

View File

@ -1,57 +0,0 @@
using System.Reflection;
using DbUp;
using Microsoft.Extensions.Configuration;
namespace EnotaryoPH.DbMigration
{
internal class Program
{
private static int Main(string[] args)
{
Console.ForegroundColor = ConsoleColor.Yellow;
var config = new ConfigurationBuilder()
.AddJsonFile("appsettings.json")
.Build();
var connectionString =
args.FirstOrDefault()
?? config.GetConnectionString("DbUpConnection");
var upgrader =
DeployChanges.To
.PostgresqlDatabase(connectionString)
.WithVariablesDisabled()
.WithScriptsEmbeddedInAssembly(Assembly.GetExecutingAssembly())
.LogToConsole()
.Build();
if (upgrader.TryConnect(out var err))
{
var result = upgrader.PerformUpgrade();
if (!result.Successful)
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine(result.Error);
Console.ResetColor();
#if DEBUG
Console.ReadLine();
#endif
return -1;
}
}
else
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine($"Cannot Connect: '{err}'");
Console.ResetColor();
return -1;
}
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine("Success!");
Console.ResetColor();
return 0;
}
}
}

View File

@ -1,715 +0,0 @@

CREATE EXTENSION if not EXISTS "uuid-ossp"
SCHEMA "public"
VERSION "1.1";
-- DROP SCHEMA public;
CREATE SCHEMA IF NOT EXISTS public AUTHORIZATION pg_database_owner;
-- DROP SEQUENCE "LawyerVideoConferenceParticip_LawyerVideoConferenceParticip_seq";
CREATE SEQUENCE "LawyerVideoConferenceParticip_LawyerVideoConferenceParticip_seq"
INCREMENT BY 1
MINVALUE 1
MAXVALUE 9223372036854775807
START 1
CACHE 1
NO CYCLE;
-- DROP SEQUENCE "LawyerVideoConferenceSchedule_LawyerVideoConferenceSchedule_seq";
CREATE SEQUENCE "LawyerVideoConferenceSchedule_LawyerVideoConferenceSchedule_seq"
INCREMENT BY 1
MINVALUE 1
MAXVALUE 9223372036854775807
START 1
CACHE 1
NO CYCLE;
-- DROP SEQUENCE "LookupDataValues_LookupDataValueID_seq";
CREATE SEQUENCE "LookupDataValues_LookupDataValueID_seq"
INCREMENT BY 1
MINVALUE 1
MAXVALUE 9223372036854775807
START 1
CACHE 1
NO CYCLE;
-- DROP SEQUENCE "LookupData_LookupDataID_seq";
CREATE SEQUENCE "LookupData_LookupDataID_seq"
INCREMENT BY 1
MINVALUE 1
MAXVALUE 9223372036854775807
START 1
CACHE 1
NO CYCLE;
-- DROP SEQUENCE "TransactionDeclineReasons_TransactionDeclineReasonID_seq";
CREATE SEQUENCE "TransactionDeclineReasons_TransactionDeclineReasonID_seq"
INCREMENT BY 1
MINVALUE 1
MAXVALUE 9223372036854775807
START 1
CACHE 1
NO CYCLE;
-- DROP SEQUENCE "TransactionSelfies_TransactionSelfieID_seq";
CREATE SEQUENCE "TransactionSelfies_TransactionSelfieID_seq"
INCREMENT BY 1
MINVALUE 1
MAXVALUE 9223372036854775807
START 1
CACHE 1
NO CYCLE;
-- DROP SEQUENCE "TransactionSignatoryDeclineRe_TransactionSignatoryDeclineRe_seq";
CREATE SEQUENCE "TransactionSignatoryDeclineRe_TransactionSignatoryDeclineRe_seq"
INCREMENT BY 1
MINVALUE 1
MAXVALUE 9223372036854775807
START 1
CACHE 1
NO CYCLE;
-- DROP SEQUENCE "VideoRecordings_VideoRecordingID_seq";
CREATE SEQUENCE "VideoRecordings_VideoRecordingID_seq"
INCREMENT BY 1
MINVALUE 1
MAXVALUE 9223372036854775807
START 1
CACHE 1
NO CYCLE;
-- DROP SEQUENCE errorlogs_errorlogid_seq;
CREATE SEQUENCE errorlogs_errorlogid_seq
INCREMENT BY 1
MINVALUE 1
MAXVALUE 9223372036854775807
START 1
CACHE 1
NO CYCLE;
-- DROP SEQUENCE eventlogs_eventlogid_seq;
CREATE SEQUENCE eventlogs_eventlogid_seq
INCREMENT BY 1
MINVALUE 1
MAXVALUE 9223372036854775807
START 1
CACHE 1
NO CYCLE;
-- DROP SEQUENCE identificationdocuments_identificationdocumentid_seq;
CREATE SEQUENCE identificationdocuments_identificationdocumentid_seq
INCREMENT BY 1
MINVALUE 1
MAXVALUE 9223372036854775807
START 1
CACHE 1
NO CYCLE;
-- DROP SEQUENCE lawyers_lawyerid_seq;
CREATE SEQUENCE lawyers_lawyerid_seq
INCREMENT BY 1
MINVALUE 1
MAXVALUE 9223372036854775807
START 1
CACHE 1
NO CYCLE;
-- DROP SEQUENCE templates_templateid_seq;
CREATE SEQUENCE templates_templateid_seq
INCREMENT BY 1
MINVALUE 1
MAXVALUE 2147483647
START 1
CACHE 1
NO CYCLE;
-- DROP SEQUENCE transactiondocuments_transactiondocumentid_seq;
CREATE SEQUENCE transactiondocuments_transactiondocumentid_seq
INCREMENT BY 1
MINVALUE 1
MAXVALUE 9223372036854775807
START 1
CACHE 1
NO CYCLE;
-- DROP SEQUENCE transactionnotary_transactionnotaryid_seq;
CREATE SEQUENCE transactionnotary_transactionnotaryid_seq
INCREMENT BY 1
MINVALUE 1
MAXVALUE 9223372036854775807
START 1
CACHE 1
NO CYCLE;
-- DROP SEQUENCE transactionotp_transactionotpid_seq;
CREATE SEQUENCE transactionotp_transactionotpid_seq
INCREMENT BY 1
MINVALUE 1
MAXVALUE 9223372036854775807
START 1
CACHE 1
NO CYCLE;
-- DROP SEQUENCE transactions_transactionid_seq;
CREATE SEQUENCE transactions_transactionid_seq
INCREMENT BY 1
MINVALUE 1
MAXVALUE 9223372036854775807
START 1
CACHE 1
NO CYCLE;
-- DROP SEQUENCE transactionsignatories_transactionsignatoryid_seq;
CREATE SEQUENCE transactionsignatories_transactionsignatoryid_seq
INCREMENT BY 1
MINVALUE 1
MAXVALUE 9223372036854775807
START 1
CACHE 1
NO CYCLE;
-- DROP SEQUENCE users_userid_seq;
CREATE SEQUENCE users_userid_seq
INCREMENT BY 1
MINVALUE 1
MAXVALUE 9223372036854775807
START 1
CACHE 1
NO CYCLE;-- public."ErrorLogs" definition
-- Drop table
-- DROP TABLE "ErrorLogs";
CREATE TABLE "ErrorLogs" (
"ErrorLogID" int8 GENERATED ALWAYS AS IDENTITY( INCREMENT BY 1 MINVALUE 1 MAXVALUE 9223372036854775807 START 1 CACHE 1 NO CYCLE) NOT NULL,
"Message" varchar NOT NULL,
"CreatedOn" timestamp DEFAULT now() NULL,
"Severity" varchar NULL,
"Exception" varchar NULL,
"Stacktrace" varchar NULL,
"ErrorLog_UID" uuid DEFAULT uuid_generate_v4() NULL,
CONSTRAINT errorlogs_pk PRIMARY KEY ("ErrorLogID")
);
CREATE INDEX "ErrorLogs_CreatedOn_IDX" ON public."ErrorLogs" USING btree ("CreatedOn" DESC);
CREATE UNIQUE INDEX "ErrorLogs_ErrorLog_UID_IDX" ON public."ErrorLogs" USING btree ("ErrorLog_UID");
-- public."LookupData" definition
-- Drop table
-- DROP TABLE "LookupData";
CREATE TABLE "LookupData" (
"LookupDataID" int8 GENERATED ALWAYS AS IDENTITY( INCREMENT BY 1 MINVALUE 1 MAXVALUE 9223372036854775807 START 1 CACHE 1 NO CYCLE) NOT NULL,
"LookupData_UID" uuid DEFAULT uuid_generate_v4() NOT NULL,
"Category" varchar NULL,
"ParentCategory" varchar NULL,
"Name" varchar NOT NULL,
"Description" varchar NULL,
"CreatedOn" timestamp DEFAULT now() NULL,
CONSTRAINT "LookupData_pk" PRIMARY KEY ("LookupDataID"),
CONSTRAINT "LookupData_unique" UNIQUE ("LookupData_UID")
);
CREATE UNIQUE INDEX "LookupData_Name_Category_IDX" ON public."LookupData" USING btree ("Name", "Category");
-- public."Templates" definition
-- Drop table
-- DROP TABLE "Templates";
CREATE TABLE "Templates" (
"TemplateID" int4 GENERATED ALWAYS AS IDENTITY( INCREMENT BY 1 MINVALUE 1 MAXVALUE 2147483647 START 1 CACHE 1 NO CYCLE) NOT NULL,
"Name" varchar NOT NULL,
"Description" varchar NULL,
"Pagecount" int4 NULL,
"CreatedOn" timestamp DEFAULT now() NULL,
"TemplateUrl" varchar NULL,
"Template_UID" uuid DEFAULT uuid_generate_v4() NULL,
CONSTRAINT templates_pk PRIMARY KEY ("TemplateID")
);
-- public."Users" definition
-- Drop table
-- DROP TABLE "Users";
CREATE TABLE "Users" (
"UserID" int8 GENERATED ALWAYS AS IDENTITY( INCREMENT BY 1 MINVALUE 1 MAXVALUE 9223372036854775807 START 1 CACHE 1 NO CYCLE) NOT NULL,
"Email" varchar NOT NULL,
"PasswordHash" varchar NOT NULL,
"PhoneNumber" varchar NULL,
"Firstname" varchar NULL,
"Lastname" varchar NULL,
"CreatedOn" timestamp DEFAULT now() NULL,
"User_UID" uuid DEFAULT uuid_generate_v4() NULL,
"Role" varchar DEFAULT 'user'::character varying NULL,
"BirthDate" date NOT NULL,
"Middlename" varchar NULL,
"Suffix" varchar NULL,
"Prefix" varchar NULL,
CONSTRAINT users_pk PRIMARY KEY ("UserID"),
CONSTRAINT users_unique_email UNIQUE ("Email"),
CONSTRAINT users_unique_uid UNIQUE ("User_UID")
);
-- public."EventLogs" definition
-- Drop table
-- DROP TABLE "EventLogs";
CREATE TABLE "EventLogs" (
"EventLogID" int8 GENERATED ALWAYS AS IDENTITY( INCREMENT BY 1 MINVALUE 1 MAXVALUE 9223372036854775807 START 1 CACHE 1 NO CYCLE) NOT NULL,
"StreamID" int8 NOT NULL,
"LogType" varchar NOT NULL,
"LogDate" time DEFAULT now() NULL,
"UserID" int8 NULL,
"Payload" varchar NOT NULL,
"Description" varchar NULL,
"EventLog_UID" uuid DEFAULT uuid_generate_v4() NULL,
CONSTRAINT eventlogs_pk PRIMARY KEY ("EventLogID"),
CONSTRAINT eventlogs_users_fk FOREIGN KEY ("UserID") REFERENCES "Users"("UserID")
);
CREATE UNIQUE INDEX "EventLogs_EventLog_UID_IDX" ON public."EventLogs" USING btree ("EventLog_UID");
CREATE INDEX "EventLogs_LogDate_IDX" ON public."EventLogs" USING btree ("LogDate" DESC);
CREATE INDEX "EventLogs_StreamID_IDX" ON public."EventLogs" USING btree ("StreamID");
CREATE INDEX "EventLogs_UserID_IDX" ON public."EventLogs" USING btree ("UserID");
-- public."IdentificationDocuments" definition
-- Drop table
-- DROP TABLE "IdentificationDocuments";
CREATE TABLE "IdentificationDocuments" (
"IdentificationDocumentID" int8 GENERATED ALWAYS AS IDENTITY( INCREMENT BY 1 MINVALUE 1 MAXVALUE 9223372036854775807 START 1 CACHE 1 NO CYCLE) NOT NULL,
"Type" varchar NOT NULL,
"ExpirationDate" date NOT NULL,
"Filename" varchar NOT NULL,
"File" bytea NOT NULL,
"UserID" int8 NOT NULL,
"IdNumber" varchar NOT NULL,
"PlaceIssued" varchar NOT NULL,
"DateIssued" date NOT NULL,
"CreatedOn" timestamp DEFAULT now() NOT NULL,
"IdentificationDocument_UID" uuid DEFAULT uuid_generate_v4() NOT NULL,
"IsDeleted" bool NULL,
"UploadedOn" timestamp NOT NULL,
CONSTRAINT identificationdocuments_pk PRIMARY KEY ("IdentificationDocumentID"),
CONSTRAINT identificationdocuments_users_fk FOREIGN KEY ("UserID") REFERENCES "Users"("UserID")
);
CREATE UNIQUE INDEX "IdentificationDocuments_IdentificationDocument_UID_IDX" ON public."IdentificationDocuments" USING btree ("IdentificationDocument_UID");
-- public."Lawyers" definition
-- Drop table
-- DROP TABLE "Lawyers";
CREATE TABLE "Lawyers" (
"LawyerID" int8 GENERATED ALWAYS AS IDENTITY( INCREMENT BY 1 MINVALUE 1 MAXVALUE 9223372036854775807 START 1 CACHE 1 NO CYCLE) NOT NULL,
"Rollnumber" varchar NULL,
"IBPNumber" varchar NULL,
"MCLEComplianceNumber" varchar NULL,
"MCLEDate" date NULL,
"PTRNumber" varchar NULL,
"PTRDate" date NULL,
"PTRlocation" varchar NULL,
"OfficeAddress" varchar NULL,
"UserID" int8 NOT NULL,
"Lawyer_UID" uuid DEFAULT uuid_generate_v4() NULL,
"CreatedOn" timestamp DEFAULT now() NULL,
"CommissionNumber" varchar NULL,
"CommissionLocation" varchar NULL,
"CommissionExpiration" date NULL,
"Status" varchar DEFAULT 'Registered'::character varying NULL,
CONSTRAINT lawyers_pk PRIMARY KEY ("LawyerID"),
CONSTRAINT lawyers_users_fk FOREIGN KEY ("UserID") REFERENCES "Users"("UserID")
);
-- public."LookupDataValues" definition
-- Drop table
-- DROP TABLE "LookupDataValues";
CREATE TABLE "LookupDataValues" (
"LookupDataValueID" int8 GENERATED ALWAYS AS IDENTITY( INCREMENT BY 1 MINVALUE 1 MAXVALUE 9223372036854775807 START 1 CACHE 1 NO CYCLE) NOT NULL,
"LookupDataValue_UID" uuid DEFAULT uuid_generate_v4() NOT NULL,
"LookupDataID" int8 NULL,
"Value" varchar NOT NULL,
"Title" varchar NULL,
"SortOrder" int4 NULL,
"CreatedOn" timestamp DEFAULT now() NULL,
CONSTRAINT "LookupDataValues_pk" PRIMARY KEY ("LookupDataValueID"),
CONSTRAINT "LookupDataValues_unique" UNIQUE ("LookupDataValue_UID"),
CONSTRAINT "LookupDataValues_LookupData_FK" FOREIGN KEY ("LookupDataID") REFERENCES "LookupData"("LookupDataID")
);
-- public."Transactions" definition
-- Drop table
-- DROP TABLE "Transactions";
CREATE TABLE "Transactions" (
"TransactionID" int8 GENERATED ALWAYS AS IDENTITY( INCREMENT BY 1 MINVALUE 1 MAXVALUE 9223372036854775807 START 1 CACHE 1 NO CYCLE) NOT NULL,
"TransactionDate" date NOT NULL,
"PrincipalID" int8 NOT NULL,
"Status" varchar NOT NULL,
"CreatedOn" timestamp DEFAULT now() NULL,
"Transaction_UID" uuid DEFAULT uuid_generate_v4() NULL,
"PreferredLawyerID" int8 NULL,
"LawyerID" int8 NULL,
"IsRecorded" bool NULL,
CONSTRAINT transactions_pk PRIMARY KEY ("TransactionID"),
CONSTRAINT "Transactions_Lawyers_FK" FOREIGN KEY ("LawyerID") REFERENCES "Lawyers"("LawyerID"),
CONSTRAINT "Transactions_PreferredLawyers_FK" FOREIGN KEY ("PreferredLawyerID") REFERENCES "Lawyers"("LawyerID"),
CONSTRAINT "Transactions_Users_FK" FOREIGN KEY ("PrincipalID") REFERENCES "Users"("UserID")
);
CREATE INDEX "Transactions_TransactionDate_IDX" ON public."Transactions" USING btree ("TransactionDate" DESC);
CREATE UNIQUE INDEX "Transactions_Transaction_UID_IDX" ON public."Transactions" USING btree ("Transaction_UID");
-- public."LawyerVideoConferenceSchedule" definition
-- Drop table
-- DROP TABLE "LawyerVideoConferenceSchedule";
CREATE TABLE "LawyerVideoConferenceSchedule" (
"LawyerVideoConferenceScheduleID" int8 GENERATED ALWAYS AS IDENTITY( INCREMENT BY 1 MINVALUE 1 MAXVALUE 9223372036854775807 START 1 CACHE 1 NO CYCLE) NOT NULL,
"LawyerID" int8 NOT NULL,
"TransactionID" int8 NOT NULL,
"MeetingDate" timestamp NOT NULL,
"CreatedOn" timestamp DEFAULT now() NULL,
"LawyerVideoConferenceSchedule_UID" uuid DEFAULT uuid_generate_v4() NULL,
"Status" varchar NULL,
"MeetingRoomID" varchar NULL,
"MeetingRoomTokenID" varchar NULL,
"MeetingRoomUserID" varchar NULL,
"ServerCallID" varchar NULL,
"RecordingID" varchar NULL,
CONSTRAINT "LawyerVideoConferenceSchedule_pk" PRIMARY KEY ("LawyerVideoConferenceScheduleID"),
CONSTRAINT "LawyerVideoConferenceSchedule_unique" UNIQUE ("LawyerVideoConferenceSchedule_UID"),
CONSTRAINT "LawyerVideoConferenceSchedule_Lawyers_FK" FOREIGN KEY ("LawyerID") REFERENCES "Lawyers"("LawyerID"),
CONSTRAINT "LawyerVideoConferenceSchedule_Transactions_FK" FOREIGN KEY ("TransactionID") REFERENCES "Transactions"("TransactionID")
);
CREATE INDEX "LawyerVideoConferenceSchedule_RecordingID_IDX" ON public."LawyerVideoConferenceSchedule" USING btree ("RecordingID");
CREATE INDEX "LawyerVideoConferenceSchedule_TransactionID_IDX" ON public."LawyerVideoConferenceSchedule" USING btree ("TransactionID");
-- public."TransactionDeclineReasons" definition
-- Drop table
-- DROP TABLE "TransactionDeclineReasons";
CREATE TABLE "TransactionDeclineReasons" (
"TransactionDeclineReasonID" int8 GENERATED ALWAYS AS IDENTITY( INCREMENT BY 1 MINVALUE 1 MAXVALUE 9223372036854775807 START 1 CACHE 1 NO CYCLE) NOT NULL,
"TransactionID" int8 NOT NULL,
"Reason" varchar NOT NULL,
"LawyerID" int8 NOT NULL,
"CreatedOn" timestamp DEFAULT now() NULL,
"TransactionDeclineReason_UID" uuid DEFAULT uuid_generate_v4() NULL,
CONSTRAINT "TransactionDeclineReasons_pk" PRIMARY KEY ("TransactionDeclineReasonID"),
CONSTRAINT "TransactionDeclineReasons_Lawyers_FK" FOREIGN KEY ("LawyerID") REFERENCES "Lawyers"("LawyerID"),
CONSTRAINT "TransactionDeclineReasons_Transactions_FK" FOREIGN KEY ("TransactionID") REFERENCES "Transactions"("TransactionID")
);
CREATE UNIQUE INDEX "TransactionDeclineReasons_TransactionDeclineReason_UID_IDX" ON public."TransactionDeclineReasons" USING btree ("TransactionDeclineReason_UID");
-- public."TransactionDocuments" definition
-- Drop table
-- DROP TABLE "TransactionDocuments";
CREATE TABLE "TransactionDocuments" (
"TransactionDocumentID" int8 GENERATED ALWAYS AS IDENTITY( INCREMENT BY 1 MINVALUE 1 MAXVALUE 9223372036854775807 START 1 CACHE 1 NO CYCLE) NOT NULL,
"TransactionID" int8 NOT NULL,
"Filename" varchar NOT NULL,
"Notes" varchar NULL,
"File" bytea NOT NULL,
"UploadedOn" timestamp NOT NULL,
"CreatedOn" timestamp DEFAULT now() NULL,
"TransactionDocument_UID" uuid DEFAULT uuid_generate_v4() NULL,
"DocumentType" varchar NOT NULL,
CONSTRAINT transactiondocuments_pk PRIMARY KEY ("TransactionDocumentID"),
CONSTRAINT transactiondocuments_transactions_fk FOREIGN KEY ("TransactionID") REFERENCES "Transactions"("TransactionID")
);
-- public."TransactionNotary" definition
-- Drop table
-- DROP TABLE "TransactionNotary";
CREATE TABLE "TransactionNotary" (
"TransactionNotaryID" int8 GENERATED ALWAYS AS IDENTITY( INCREMENT BY 1 MINVALUE 1 MAXVALUE 9223372036854775807 START 1 CACHE 1 NO CYCLE) NOT NULL,
"TransactionID" int8 NOT NULL,
"DocNumber" varchar NULL,
"BookNumber" varchar NULL,
"PageNumber" varchar NULL,
"Series" varchar NULL,
"SignedOn" date NULL,
"Remarks" varchar NULL,
"LawyerID" int8 NOT NULL,
"CertificateType" varchar NULL,
"TemplateID" int4 NULL,
"PageCount" int4 NULL,
"TransactionNotary_UID" uuid DEFAULT uuid_generate_v4() NULL,
CONSTRAINT transactionnotary_pk PRIMARY KEY ("TransactionNotaryID"),
CONSTRAINT transactionnotary_lawyers_fk FOREIGN KEY ("LawyerID") REFERENCES "Lawyers"("LawyerID"),
CONSTRAINT transactionnotary_templates_fk FOREIGN KEY ("TemplateID") REFERENCES "Templates"("TemplateID"),
CONSTRAINT transactionnotary_transactions_fk FOREIGN KEY ("TransactionID") REFERENCES "Transactions"("TransactionID")
);
-- public."TransactionOTP" definition
-- Drop table
-- DROP TABLE "TransactionOTP";
CREATE TABLE "TransactionOTP" (
"TransactionOTPID" int8 GENERATED ALWAYS AS IDENTITY( INCREMENT BY 1 MINVALUE 1 MAXVALUE 9223372036854775807 START 1 CACHE 1 NO CYCLE) NOT NULL,
"TransactionID" int8 NOT NULL,
"VerifiedOn" time NOT NULL,
"PrintCoords" varchar NOT NULL,
"Status" varchar NOT NULL,
"UserID" int8 NOT NULL,
"TransactionOTP_UID" uuid DEFAULT uuid_generate_v4() NULL,
"OTPHash" varchar NOT NULL,
"OTPUserInput" varchar NULL,
"IPAddress" varchar NULL,
"Longitude" numeric NULL,
"Lattitude" numeric NULL,
"Device" varchar NULL,
"File_Liveness" bytea NULL,
CONSTRAINT transactionotp_pk PRIMARY KEY ("TransactionOTPID"),
CONSTRAINT "TransactionOTP_Users_FK" FOREIGN KEY ("UserID") REFERENCES "Users"("UserID"),
CONSTRAINT transactionotp_transactions_fk FOREIGN KEY ("TransactionID") REFERENCES "Transactions"("TransactionID")
);
CREATE INDEX "TransactionOTP_TransactionID_IDX" ON public."TransactionOTP" USING btree ("TransactionID");
CREATE UNIQUE INDEX "TransactionOTP_TransactionOTP_UID_IDX" ON public."TransactionOTP" USING btree ("TransactionOTP_UID");
-- public."TransactionSelfies" definition
-- Drop table
-- DROP TABLE "TransactionSelfies";
CREATE TABLE "TransactionSelfies" (
"TransactionSelfieID" int8 GENERATED ALWAYS AS IDENTITY( INCREMENT BY 1 MINVALUE 1 MAXVALUE 9223372036854775807 START 1 CACHE 1 NO CYCLE) NOT NULL,
"TransactionID" int8 NULL,
"IdentificationDocumentID" int8 NULL,
"File" bytea NOT NULL,
"CreatedOn" timestamp DEFAULT now() NULL,
"TransactionSelfie_UID" uuid DEFAULT uuid_generate_v4() NULL,
"UserID" int8 NOT NULL,
CONSTRAINT "TransactionSelfies_pk" PRIMARY KEY ("TransactionSelfieID"),
CONSTRAINT "TransactionSelfies_IdentificationDocuments_FK" FOREIGN KEY ("IdentificationDocumentID") REFERENCES "IdentificationDocuments"("IdentificationDocumentID"),
CONSTRAINT "TransactionSelfies_Transactions_FK" FOREIGN KEY ("TransactionID") REFERENCES "Transactions"("TransactionID"),
CONSTRAINT "TransactionSelfies_Users_FK" FOREIGN KEY ("UserID") REFERENCES "Users"("UserID")
);
CREATE UNIQUE INDEX "TransactionSelfies_TransactionSelfie_UID_IDX" ON public."TransactionSelfies" USING btree ("TransactionSelfie_UID");
-- public."TransactionSignatories" definition
-- Drop table
-- DROP TABLE "TransactionSignatories";
CREATE TABLE "TransactionSignatories" (
"TransactionSignatoryID" int8 GENERATED ALWAYS AS IDENTITY( INCREMENT BY 1 MINVALUE 1 MAXVALUE 9223372036854775807 START 1 CACHE 1 NO CYCLE) NOT NULL,
"TransactionID" int8 NOT NULL,
"UserID" int8 NULL,
"CreatedOn" timestamp DEFAULT now() NULL,
"Status" varchar NOT NULL,
"Email" varchar NOT NULL,
"Type" varchar NOT NULL,
"TransactionSignatory_UID" uuid DEFAULT uuid_generate_v4() NULL,
"InvitationCode" varchar NOT NULL,
CONSTRAINT transactionsignatories_pk PRIMARY KEY ("TransactionSignatoryID"),
CONSTRAINT transactionsignatories_transactions_fk FOREIGN KEY ("TransactionID") REFERENCES "Transactions"("TransactionID"),
CONSTRAINT transactionsignatories_users_fk FOREIGN KEY ("UserID") REFERENCES "Users"("UserID")
);
CREATE INDEX "TransactionSignatories_InvitationCode_IDX" ON public."TransactionSignatories" USING btree ("InvitationCode");
CREATE INDEX "TransactionSignatories_TransactionID_IDX" ON public."TransactionSignatories" USING btree ("TransactionID", "Email");
CREATE UNIQUE INDEX "TransactionSignatories_TransactionSignatory_UID_IDX" ON public."TransactionSignatories" USING btree ("TransactionSignatory_UID");
-- public."TransactionSignatoryDeclineReasons" definition
-- Drop table
-- DROP TABLE "TransactionSignatoryDeclineReasons";
CREATE TABLE "TransactionSignatoryDeclineReasons" (
"TransactionSignatoryDeclineReasonID" int8 GENERATED ALWAYS AS IDENTITY( INCREMENT BY 1 MINVALUE 1 MAXVALUE 9223372036854775807 START 1 CACHE 1 NO CYCLE) NOT NULL,
"UserID" int8 NOT NULL,
"DeclineReason" varchar NOT NULL,
"CreatedOn" timestamp DEFAULT now() NULL,
"TransactionSignatoryDeclineReason_UID" uuid DEFAULT uuid_generate_v4() NOT NULL,
"TransactionID" int8 NOT NULL,
"TransactionSignatoryID" int8 NULL,
CONSTRAINT "TransactionSignatoryDeclineReasons_pk" PRIMARY KEY ("TransactionSignatoryDeclineReasonID"),
CONSTRAINT "TransactionSignatoryDeclineReasons_unique" UNIQUE ("TransactionSignatoryDeclineReason_UID"),
CONSTRAINT "TransactionSignatoryDeclineReasons_TransactionSignatories_FK" FOREIGN KEY ("TransactionSignatoryID") REFERENCES "TransactionSignatories"("TransactionSignatoryID"),
CONSTRAINT "TransactionSignatoryDeclineReasons_Users_FK" FOREIGN KEY ("UserID") REFERENCES "Users"("UserID")
);
CREATE INDEX "TransactionSignatoryDeclineReasons_UserID_IDX" ON public."TransactionSignatoryDeclineReasons" USING btree ("UserID", "TransactionID");
-- public."VideoRecordings" definition
-- Drop table
-- DROP TABLE "VideoRecordings";
CREATE TABLE "VideoRecordings" (
"VideoRecordingID" int8 GENERATED ALWAYS AS IDENTITY( INCREMENT BY 1 MINVALUE 1 MAXVALUE 9223372036854775807 START 1 CACHE 1 NO CYCLE) NOT NULL,
"VideoConferenceScheduleID" int8 NOT NULL,
"Path" varchar NOT NULL,
"LocationType" varchar NOT NULL,
"CreatedOn" timestamp DEFAULT now() NULL,
"VideoRecording_UID" uuid DEFAULT uuid_generate_v4() NULL,
CONSTRAINT "VideoRecordings_pk" PRIMARY KEY ("VideoRecordingID"),
CONSTRAINT "VideoRecordings_unique" UNIQUE ("VideoConferenceScheduleID"),
CONSTRAINT "VideoRecordings_unique_UID" UNIQUE ("VideoRecording_UID"),
CONSTRAINT "VideoRecordings_LawyerVideoConferenceSchedule_FK" FOREIGN KEY ("VideoConferenceScheduleID") REFERENCES "LawyerVideoConferenceSchedule"("LawyerVideoConferenceScheduleID")
);
-- public."LawyerVideoConferenceParticipants" definition
-- Drop table
-- DROP TABLE "LawyerVideoConferenceParticipants";
CREATE TABLE "LawyerVideoConferenceParticipants" (
"LawyerVideoConferenceParticipantID" int8 GENERATED ALWAYS AS IDENTITY( INCREMENT BY 1 MINVALUE 1 MAXVALUE 9223372036854775807 START 1 CACHE 1 NO CYCLE) NOT NULL,
"LawyerVideoConferenceScheduleID" int8 NOT NULL,
"ParticipantID" int8 NOT NULL,
"Status" varchar NULL,
"CreatedOn" timestamp DEFAULT now() NULL,
"LawyerVideoConferenceParticipant_UID" uuid DEFAULT uuid_generate_v4() NULL,
"MeetingRoomTokenID" varchar NULL,
"MeetingRoomUserID" varchar NULL,
CONSTRAINT "LawyerVideoConferenceParticipants_pk" PRIMARY KEY ("LawyerVideoConferenceParticipantID"),
CONSTRAINT "LawyerVideoConferenceParticipants_LawyerVideoConferenceSchedule" FOREIGN KEY ("LawyerVideoConferenceScheduleID") REFERENCES "LawyerVideoConferenceSchedule"("LawyerVideoConferenceScheduleID"),
CONSTRAINT "LawyerVideoConferenceParticipants_Users_FK" FOREIGN KEY ("ParticipantID") REFERENCES "Users"("UserID")
);
CREATE UNIQUE INDEX "LawyerVideoConferenceParticipants_LawyerVideoConferenceParticip" ON public."LawyerVideoConferenceParticipants" USING btree ("LawyerVideoConferenceParticipant_UID");
CREATE UNIQUE INDEX "LawyerVideoConferenceParticipants_LawyerVideoConferenceSchedule" ON public."LawyerVideoConferenceParticipants" USING btree ("LawyerVideoConferenceScheduleID", "ParticipantID");
-- DROP FUNCTION public.uuid_generate_v1();
CREATE OR REPLACE FUNCTION public.uuid_generate_v1()
RETURNS uuid
LANGUAGE c
PARALLEL SAFE STRICT
AS '$libdir/uuid-ossp', $function$uuid_generate_v1$function$
;
-- DROP FUNCTION public.uuid_generate_v1mc();
CREATE OR REPLACE FUNCTION public.uuid_generate_v1mc()
RETURNS uuid
LANGUAGE c
PARALLEL SAFE STRICT
AS '$libdir/uuid-ossp', $function$uuid_generate_v1mc$function$
;
-- DROP FUNCTION public.uuid_generate_v3(uuid, text);
CREATE OR REPLACE FUNCTION public.uuid_generate_v3(namespace uuid, name text)
RETURNS uuid
LANGUAGE c
IMMUTABLE PARALLEL SAFE STRICT
AS '$libdir/uuid-ossp', $function$uuid_generate_v3$function$
;
-- DROP FUNCTION public.uuid_generate_v4();
CREATE OR REPLACE FUNCTION public.uuid_generate_v4()
RETURNS uuid
LANGUAGE c
PARALLEL SAFE STRICT
AS '$libdir/uuid-ossp', $function$uuid_generate_v4$function$
;
-- DROP FUNCTION public.uuid_generate_v5(uuid, text);
CREATE OR REPLACE FUNCTION public.uuid_generate_v5(namespace uuid, name text)
RETURNS uuid
LANGUAGE c
IMMUTABLE PARALLEL SAFE STRICT
AS '$libdir/uuid-ossp', $function$uuid_generate_v5$function$
;
-- DROP FUNCTION public.uuid_nil();
CREATE OR REPLACE FUNCTION public.uuid_nil()
RETURNS uuid
LANGUAGE c
IMMUTABLE PARALLEL SAFE STRICT
AS '$libdir/uuid-ossp', $function$uuid_nil$function$
;
-- DROP FUNCTION public.uuid_ns_dns();
CREATE OR REPLACE FUNCTION public.uuid_ns_dns()
RETURNS uuid
LANGUAGE c
IMMUTABLE PARALLEL SAFE STRICT
AS '$libdir/uuid-ossp', $function$uuid_ns_dns$function$
;
-- DROP FUNCTION public.uuid_ns_oid();
CREATE OR REPLACE FUNCTION public.uuid_ns_oid()
RETURNS uuid
LANGUAGE c
IMMUTABLE PARALLEL SAFE STRICT
AS '$libdir/uuid-ossp', $function$uuid_ns_oid$function$
;
-- DROP FUNCTION public.uuid_ns_url();
CREATE OR REPLACE FUNCTION public.uuid_ns_url()
RETURNS uuid
LANGUAGE c
IMMUTABLE PARALLEL SAFE STRICT
AS '$libdir/uuid-ossp', $function$uuid_ns_url$function$
;
-- DROP FUNCTION public.uuid_ns_x500();
CREATE OR REPLACE FUNCTION public.uuid_ns_x500()
RETURNS uuid
LANGUAGE c
IMMUTABLE PARALLEL SAFE STRICT
AS '$libdir/uuid-ossp', $function$uuid_ns_x500$function$
;

View File

@ -1,74 +0,0 @@
DO $$
DECLARE doc_type_id INTEGER;
DECLARE id_type_id INTEGER;
BEGIN
INSERT INTO "LookupData" ("Name")
VALUES
('Document Types'),
('Identification Types');
SELECT "LookupDataID" INTO doc_type_id FROM "LookupData" WHERE "Name" = 'Document Types' LIMIT 1;
-- Now insert into LookupDataValues using the retrieved ID
INSERT INTO "LookupDataValues" ("LookupDataID", "Value")
VALUES (doc_type_id, 'Affidavit of Acknowledgement of a Child'),
(doc_type_id, 'Affidavit of Undertaking'),
(doc_type_id, 'Affidavit of service'),
(doc_type_id, 'Affidavits'),
(doc_type_id, 'Bid docs'),
(doc_type_id, 'Biodata'),
(doc_type_id, 'Certification against non-forum shopping'),
(doc_type_id, 'Certification of Compliance Officer'),
(doc_type_id, 'Contract of Lease'),
(doc_type_id, 'Deed of Absolute Sale'),
(doc_type_id, 'Deed of Assignment'),
(doc_type_id, 'Extrajudicial Partition'),
(doc_type_id, 'FCFS/LCFS'),
(doc_type_id, 'FCIF/LCIF'),
(doc_type_id, 'GIS'),
(doc_type_id, 'LGU business permit application form'),
(doc_type_id, 'Loan Agreement'),
(doc_type_id, 'Personal Data Sheet'),
(doc_type_id, 'Proxy forms'),
(doc_type_id, 'Quitclaims'),
(doc_type_id, 'SALN'),
(doc_type_id, 'Secretarys Certificate'),
(doc_type_id, 'Service Agreements'),
(doc_type_id, 'Settlement Agreement'),
(doc_type_id, 'Special Power of Attorney'),
(doc_type_id, 'Verification of pleadings'),
(doc_type_id, 'Wills');
SELECT "LookupDataID" INTO id_type_id FROM "LookupData" WHERE "Name" = 'Identification Types' LIMIT 1;
-- Now insert into LookupDataValues using the retrieved ID
INSERT INTO "LookupDataValues" ("LookupDataID", "Value")
VALUES (id_type_id, 'Administration (OWWA) ID'),
(id_type_id, 'Alien Certificate of Registration'),
(id_type_id, 'Certification from the National Council for the Welfare of Disabled Persons (NCWDP)'),
(id_type_id, 'Department of Social Welfare and Development (DSWD) certification'),
(id_type_id, 'Driver''s license'),
(id_type_id, 'Government Office ID'),
(id_type_id, 'Government Service and Insurance System (GSIS) e-card'),
(id_type_id, 'Immigrant Certificate of Registration'),
(id_type_id, 'Integrated Bar of the Philippines (IBP) ID'),
(id_type_id, 'National Bureau of Investigation (NBI) clearance'),
(id_type_id, 'Overseas Filipino Worker (OFW) ID'),
(id_type_id, 'Overseas Workers Welfare Administration (OWWA) ID'),
(id_type_id, 'Passport'),
(id_type_id, 'PhilHealth card'),
(id_type_id, 'Police clearance'),
(id_type_id, 'Postal ID'),
(id_type_id, 'Professional Regulations Commission (PRC) ID'),
(id_type_id, 'Seaman''s book'),
(id_type_id, 'Senior citizen card'),
(id_type_id, 'Social Security System (SSS) card'),
(id_type_id, 'Tax Identification Number (TIN) ID'),
(id_type_id, 'Unified Multi-Purpose ID (UMID) Card'),
(id_type_id, 'Voter''s ID');
END $$;

View File

@ -1,45 +0,0 @@
BEGIN TRANSACTION;
ALTER TABLE "LawyerVideoConferenceParticipants"
ADD COLUMN IF NOT EXISTS "Device" VARCHAR(255);
ALTER TABLE "LawyerVideoConferenceParticipants"
ADD COLUMN IF NOT EXISTS "IPAddress" VARCHAR(45);
ALTER TABLE "LawyerVideoConferenceParticipants"
ADD COLUMN IF NOT EXISTS "Latitude" DECIMAL(10, 6);
ALTER TABLE "LawyerVideoConferenceParticipants"
ADD COLUMN IF NOT EXISTS "Longitude" DECIMAL(10, 6);
ALTER TABLE "LawyerVideoConferenceParticipants"
ADD COLUMN IF NOT EXISTS "OTPEntered" VARCHAR(100);
ALTER TABLE "LawyerVideoConferenceParticipants"
ADD COLUMN IF NOT EXISTS "OTPHash" VARCHAR(255);
CREATE TABLE IF NOT EXISTS "UserLogins" (
"UserLoginID" int8 GENERATED ALWAYS AS IDENTITY( INCREMENT BY 1 MINVALUE 1 MAXVALUE 9223372036854775807 START 1 CACHE 1 NO CYCLE) NOT NULL,
"Failed" bool NULL,
"IPAddress" varchar NULL,
"Device" varchar NULL,
"Longitude" float8 NULL,
"Latitude" float8 NULL,
"UsegLogin_UID" uuid DEFAULT uuid_generate_v4() NOT NULL,
"UserID" int8 NULL,
"CreatedOn" timestamp DEFAULT now() NULL,
CONSTRAINT "UserLogins_pk" PRIMARY KEY ("UserLoginID"),
CONSTRAINT "UserLogins_unique" UNIQUE ("UsegLogin_UID")
);
-- public."UserLogins" foreign keys
ALTER TABLE public."UserLogins" ADD CONSTRAINT "UserLogins_Users_FK" FOREIGN KEY ("UserID") REFERENCES "Users"("UserID");
COMMIT TRANSACTION;

View File

@ -1,19 +0,0 @@
BEGIN TRANSACTION;
-- Create a new column with the desired data type
ALTER TABLE "EventLogs"
ADD COLUMN IF NOT EXISTS "NewStreamID" VARCHAR(255) NOT NULL;
-- Update values in the new column (cast the original int8 to varchar)
UPDATE "EventLogs"
SET "NewStreamID" = CAST("StreamID" AS VARCHAR);
-- Drop the original column (keeping only valid data)
ALTER TABLE "EventLogs"
DROP COLUMN "StreamID";
-- Rename the new column to the original name
ALTER TABLE "EventLogs"
RENAME COLUMN "NewStreamID" TO "StreamID";
COMMIT TRANSACTION;

View File

@ -1,5 +0,0 @@
{
"ConnectionStrings": {
"DbUpConnection": "secret"
}
}

View File

@ -1,301 +0,0 @@
import { AzureCommunicationTokenCredential, createIdentifierFromRawId } from '@azure/communication-common';
import { CallClient, LocalVideoStream, VideoStreamRenderer } from '@azure/communication-calling';
class VideoCall {
constructor() {
//this.isLocalVideoStartedChangedCallback = null;
//this.localVideoStreamsUpdatedCallback = null;
//this.onCreateLocalVideoStreamCallback = null;
this.onGetServerCallIDCallback = null;
//this.remoteParticipantStateChangedCallback = null;
//this.remoteParticipantsUpdatedCallback = null;
//this.remoteVideoIsAvailableChangedCallback = null;
this.stateChangedCallback = null;
this.callEndedCallback = null;
this.participantsJoinedCallback = null;
this.callsUpdatedCallback = null;
this.callAdapter = null;
this.videoContainer = null;
this.displayName = null;
this.roomID = null;
this.token = null;
this.userID = null;
this.onFetchParticipantMenuItemsCallback = null;
this.onFetchCustomButtonPropsCallbacks = [];
this.onAddParticipantCallback = null;
}
async init(options) {
let self = this;
this.stateChangedCallback = options.stateChangedCallback;
/*this.remoteParticipantsUpdatedCallback = options.remoteParticipantsUpdated;*/
/*this.isLocalVideoStartedChangedCallback = options.isLocalVideoStartedChanged;*/
/*this.localVideoStreamsUpdatedCallback = options.localVideoStreamsUpdated;*/
this.idChangedCallback = options.idChanged;
//this.onCreateLocalVideoStreamCallback = options.onCreateLocalVideoStream;
//this.remoteParticipantStateChangedCallback = options.remoteParticipantStateChanged;
//this.remoteVideoIsAvailableChangedCallback = options.remoteVideoIsAvailableChanged;
this.onGetServerCallIDCallback = options.onGetServerCallIDCallback;
this.callEndedCallback = options.callEndedCallback;
this.participantsJoinedCallback = options.participantsJoinedCallback;
this.onFetchParticipantMenuItemsCallback = options.onFetchParticipantMenuItemsCallback;
this.onFetchCustomButtonPropsCallbacks = options.onFetchCustomButtonPropsCallbacks || [];
this.onAddParticipantCallback = options.onAddParticipantCallback;
this.callAdapter = options.callAdapter;
this.videoContainer = options.videoContainer;
this.displayName = options.displayName;
this.roomID = options.roomID;
this.token = options.token;
this.userID = options.userID;
this.serverCallId;
const callControls = {
// Hide all default buttons
cameraButton: true,
endCallButton: false,
microphoneButton: false,
participantsButton: true,
screenShareButton: false,
devicesButton: false,
moreButton: false,
raiseHandButton: false,
reactionButton: false,
dtmfDialerButton: false,
holdButton: false,
peopleButton: false,
exitSpotlightButton: false,
captionsButton: false,
galleryControlsButton: false,
teamsMeetingPhoneCallButton: false,
displayType: 'compact',
// Hide the entire control bar if needed
onFetchCustomButtonProps: this.onFetchCustomButtonPropsCallbacks
};
const isMobile = /iPhone|iPad|iPod|Android/i.test(navigator.userAgent);
const callCompositeProps = {
callControls: callControls,
formFactor: isMobile ? 'mobile' : 'desktop',
onFetchParticipantMenuItems: this.onFetchParticipantMenuItemsCallback,
options: {
callControls: callControls
}
};
const adapterArgs = {
userId: createIdentifierFromRawId(this.userID),
//credential: new AzureCommunicationTokenCredential(this.token),
token: this.token,
displayName: this.displayName,
locator: { roomId: this.roomID },
callAdapterOptions: {},
callCompositeOptions: callCompositeProps
};
this.callAdapter = await callComposite.loadCallComposite(
adapterArgs,
this.videoContainer, // container element,
callCompositeProps
);
//this.callAdapter.callAgent.on("callsUpdated", function (e) {
// e.added.forEach((addedCall) => {
// addedCall.on('stateChanged', (state) => this.stateChanged(addedCall));
// });
//});
this.callAdapter.on("callIdChanged", function (e) {
});
this.callAdapter.onStateChange(state => {
if (state.call?.info && !this.serverCallId) {
state.call.info.getServerCallId().then(result => {
this.serverCallId = result;
this.onGetServerCallIDCallback?.(result);
}).catch(err => {
console.log(err);
});
}
});
this.callAdapter.on("callEnded", function (e) {
self.callEndedCallback?.(e);
});
this.callAdapter.on("participantsJoined", function (e, f) {
self.participantsJoinedCallback?.(e, f);
});
this.callAdapter.on("onAddParticipant", function (e, f) {
self.onAddParticipantCallback?.(e, f);
});
//CallEnded
return this.callAdapter;
}
//stopLocalVideo() {
// if (this.call) {
// this.call.stopVideo(this.localVideoStream);
// }
//}
async joinRoom() {
await this.callAdapter?.joinCall({
microphoneOn: true,
cameraOn: true
});
}
async stopCall(forEveryone = false) {
await this.callAdapter?.leaveCall(forEveryone);
}
//async subscribeToCall(call) {
// try {
// call.on('idChanged', () => {
// this.idChanged?.(call.id);
// });
// call.on('stateChanged', async () => {
// this.stateChangedCallback?.(call.state);
// });
// call.on('isLocalVideoStartedChanged', () => {
// this.isLocalVideoStartedChanged?.(call.isLocalVideoStarted);
// });
// call.on('localVideoStreamsUpdated', e => {
// this.localVideoStreamsUpdated?.(e);
// });
// // Subscribe to the call's 'remoteParticipantsUpdated' event to be
// // notified when new participants are added to the call or removed from the call.
// call.on('remoteParticipantsUpdated', e => {
// this.remoteParticipantsUpdated?.(e);
// e.added.forEach(remoteParticipant => {
// this.subscribeToRemoteParticipant(remoteParticipant)
// });
// // Unsubscribe from participants that are removed from the call
// e.removed.forEach(remoteParticipant => {
// console.log('Remote participant removed from the call.');
// });
// });
// call.localVideoStreams.forEach(async (lvs) => {
// this.localVideoStream = lvs;
// await this.displayLocalVideoStream(lvs);
// });
// // Inspect the call's current remote participants and subscribe to them.
// call.remoteParticipants.forEach(remoteParticipant => {
// this.subscribeToRemoteParticipant(remoteParticipant);
// });
// } catch (error) {
// console.error(error);
// }
//}
//subscribeToRemoteParticipant(remoteParticipant) {
// try {
// // Inspect the initial remoteParticipant.state value.
// console.log(`Remote participant state: ${remoteParticipant.state}`);
// // Subscribe to remoteParticipant's 'stateChanged' event for value changes.
// remoteParticipant.on('stateChanged', () => {
// console.log(`Remote participant state changed: ${remoteParticipant.state}`, JSON.stringify(remoteParticipant));
// this.remoteParticipantStateChanged?.(remoteParticipant.state);
// });
// // Inspect the remoteParticipants's current videoStreams and subscribe to them.
// remoteParticipant.videoStreams.forEach(remoteVideoStream => {
// this.subscribeToRemoteVideoStream(remoteVideoStream);
// });
// // Subscribe to the remoteParticipant's 'videoStreamsUpdated' event to be
// // notified when the remoteParticipant adds new videoStreams and removes video streams.
// remoteParticipant.on('videoStreamsUpdated', e => {
// // Subscribe to new remote participant's video streams that were added.
// e.added.forEach(remoteVideoStream => {
// this.subscribeToRemoteVideoStream(remoteVideoStream);
// });
// // Unsubscribe from remote participant's video streams that were removed.
// e.removed.forEach(remoteVideoStream => {
// console.log('Remote participant video stream was removed.');
// })
// });
// } catch (error) {
// console.error(error);
// }
//}
//async subscribeToRemoteVideoStream(remoteVideoStream) {
// let renderer = new VideoStreamRenderer(remoteVideoStream);
// let view;
// const createView = async () => {
// // Create a renderer view for the remote video stream.
// view = await renderer.createView();
// this.remoteVideoIsAvailableChanged?.({
// isAvailable: remoteVideoStream.isAvailable,
// participantId: remoteVideoStream.tsParticipantId,
// el: view.target
// });
// }
// // Remote participant has switched video on/off
// remoteVideoStream.on('isAvailableChanged', async () => {
// try {
// if (remoteVideoStream.isAvailable) {
// await createView();
// } else {
// view?.dispose();
// }
// } catch (e) {
// console.error(e);
// }
// });
// // Remote participant has video on initially.
// if (remoteVideoStream.isAvailable) {
// try {
// await createView();
// } catch (e) {
// console.error(e);
// }
// }
//}
//async createLocalVideoStream() {
// const camera = (await this.deviceManager.getCameras())[0];
// if (camera) {
// return new LocalVideoStream(camera);
// } else {
// console.error(`No camera device found on the system`);
// }
//}
leaveRoom() {
if (this.call) {
this.call.hangUp();
}
}
//createIdentifierFromRawId(rawId) {
// return createIdentifierFromRawId(rawId);
//}
//async displayLocalVideoStream(lvs) {
// try {
// let localVideoStreamRenderer = new VideoStreamRenderer(lvs);
// const view = await localVideoStreamRenderer.createView();
// this.onCreateLocalVideoStream?.(view.target);
// } catch (error) {
// console.error(error);
// }
//}
}
export default VideoCall;

View File

@ -1,38 +0,0 @@
function _confirm({ message, title, callbackyes, callbackno, yesLabel, noLabel }) {
const dialogTemplate = jfa.page.getDialogTemplate().content;
let spanTitle = dialogTemplate.querySelector(".modal__title__text");
spanTitle.textContent = title || "Confirm";
let bodyMessage = dialogTemplate.querySelector(".modal__body-message");
bodyMessage.textContent = message;
const dialog = dialogTemplate.querySelector("#dialog-container");
const modal = bootstrap.Modal.getOrCreateInstance(dialog);
let buttonNo = dialogTemplate.querySelector(".modal__footer__button-no");
if (noLabel) {
buttonNo.textContent = noLabel;
}
buttonNo.addEventListener("click", function () {
buttonNo.blur();
modal.hide();
callbackno?.();
});
let buttonYes = dialogTemplate.querySelector(".modal__footer__button-yes");
if (yesLabel) {
buttonYes.textContent = yesLabel;
}
buttonYes.addEventListener("click", function () {
buttonYes.blur();
modal.hide();
callbackyes?.();
});
modal.show();
}
export default {
confirm: _confirm
};

View File

@ -1,32 +0,0 @@
 function _getAlertContainer() {
return document.getElementById("ContainerAlert");
}
function _getAlertTemplate() {
return document.getElementById("AlertTemplate").cloneNode(true);
}
function _getAntiForgeryToken() {
return window.top.document.querySelector("[name='__RequestVerificationToken']")?.value;
}
function _getDialogContainer() {
return document.getElementById("ContainerDialog").cloneNode(true);
}
function _getDialogTemplate() {
return document.getElementById("DialogTemplate").cloneNode(true);
}
function reload() {
window.location.reload();
}
export default {
getAlertContainer: _getAlertContainer,
getAlertTemplate: _getAlertTemplate,
getAntiForgeryToken: _getAntiForgeryToken,
getDialogContainer: _getDialogContainer,
getDialogTemplate: _getDialogTemplate,
reload: reload
};

View File

@ -1,36 +0,0 @@

function disable(element) {
if (!element) {
return;
}
element.disabled = true;
}
function enable(element) {
if (!element) {
return;
}
element.disabled = false;
}
function hide(element) {
if (!element) {
return;
}
element.hidden = true;
}
function show(element, suppressEvent) {
if (!element) {
return;
}
element.hidden = false;
}
export default {
disable: disable,
enable: enable,
hide: hide,
show: show
};

View File

@ -1,26 +0,0 @@

async function del(url, data) {
return await _fetch(url, data, "DELETE");
}
async function _fetch(url, data, method) {
const response = await fetch(url, {
method: method,
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'RequestVerificationToken': jfa.page.getAntiForgeryToken()
},
body: data ? JSON.stringify(data) : data
});
return response;
}
async function post(url, data) {
return await _fetch(url, data, "POST");
}
export default {
delete: del,
post: post
};

View File

@ -1,16 +0,0 @@
function getCurrentURL() {
return new URL(window.location.origin + window.location.pathname);
}
function getCurrentURLWithHandler(handler) {
let url = getCurrentURL();
url.searchParams.append("handler", handler);
return url;
}
export default {
getCurrentURL: getCurrentURL,
getCurrentURLWithHandler: getCurrentURLWithHandler
}

View File

@ -1,25 +0,0 @@
"use strict";
import page from "../../Assets/js/Page/_Page.js";
import routing from "../../Assets/js/Utilities/Routing/_Routing.js";
import element from "../../Assets/js/Utilities/Element/_Element.js";
import request from "../../Assets/js/Utilities/Request/_Request.js";
import dialog from "../../Assets/js/Components/Dialog/_Dialog.js";
import videocall from "../../Assets/js/Communication/VideoCall/_VideoCall.js";
const jfa = {
components: {
dialog
},
utilities: {
routing,
element,
request
},
page,
communication: {
videocall: new videocall()
}
};
export default { jfa };
window.jfa = jfa;

View File

@ -1,9 +0,0 @@
namespace EnotaryoPH.Web.Common.Exceptions
{
public class InvalidConfigurationException : Exception
{
public InvalidConfigurationException(string configurationName, object value) : base($"Invalid value '{value}' for configuration '{configurationName}'.")
{
}
}
}

View File

@ -1,39 +0,0 @@
namespace EnotaryoPH.Web.Common.Exceptions
{
public class NoDataException : Exception
{
public NoDataException(string typeName, object id) : base($"No data found for {typeName} with id = '{id}'.")
{
TypeName = typeName;
ID = id;
Key = string.Empty;
}
public NoDataException(string typeName, object id, string key) : base($"No data found for {typeName} with {key} = '{id}'.")
{
TypeName = typeName;
ID = id;
Key = key;
}
public static void ThrowIfNull(object data, string typeName, object id)
{
if (data == null)
{
throw new NoDataException(typeName, id);
}
}
public static void ThrowIfNull(object data, string typeName, object id, string key)
{
if (data == null)
{
throw new NoDataException(typeName, id, key);
}
}
public object ID { get; private set; }
public string Key { get; private set; }
public string TypeName { get; private set; }
}
}

View File

@ -1,9 +0,0 @@
namespace EnotaryoPH.Web.Common.Extensions
{
public static class DateTimeExtensions
{
public static DateTime ToUTC(this DateTime? dte) => dte.GetValueOrDefault().ToUTC();
public static DateTime ToUTC(this DateTime dte) => new(dte.Ticks, DateTimeKind.Utc);
}
}

View File

@ -1,40 +0,0 @@
using System.Buffers.Text;
using System.Runtime.InteropServices;
namespace EnotaryoPH.Web.Common.Extensions
{
public static class GuidExtensions
{
private const char Dash = '-';
private const byte ForwardSlashByte = (byte)'/';
private const byte PlusByte = (byte)'+';
private const char Underscore = '_';
public static string ToBase64String(this Guid guid)
{
Span<byte> guidBytes = stackalloc byte[16];
Span<byte> encodedBytes = stackalloc byte[24];
MemoryMarshal.TryWrite(guidBytes, ref guid); // write bytes from the Guid
Base64.EncodeToUtf8(guidBytes, encodedBytes, out _, out _);
Span<char> chars = stackalloc char[22];
// replace any characters which are not URL safe
// skip the final two bytes as these will be '==' padding we don't need
for (var i = 0; i < 22; i++)
{
chars[i] = encodedBytes[i] switch
{
ForwardSlashByte => Dash,
PlusByte => Underscore,
_ => (char)encodedBytes[i],
};
}
var final = new string(chars);
return final;
}
}
}

View File

@ -1,9 +0,0 @@
namespace EnotaryoPH.Web.Common.Extensions
{
public static class IEnumerableExtensions
{
public static IEnumerable<T> ToSafeEnumerable<T>(this IEnumerable<T> enumerable) => enumerable ?? Enumerable.Empty<T>();
public static List<T> ToSafeList<T>(this IEnumerable<T> enumerable) => enumerable?.ToList() ?? [];
}
}

View File

@ -1,20 +0,0 @@
namespace EnotaryoPH.Web.Common.Extensions
{
public static class IFormFileExtensions
{
public static string ToBase64StringUrl(this IFormFile file) => $"data:image/jpg;base64,{file.ToBase64String()}";
public static string ToBase64String(this IFormFile file)
{
if (file == null || file.Length == 0)
{
throw new ArgumentNullException(nameof(file));
}
using var memoryStream = new MemoryStream();
file.CopyTo(memoryStream);
var fileBytes = memoryStream.ToArray();
return Convert.ToBase64String(fileBytes);
}
}
}

View File

@ -1,11 +0,0 @@
namespace EnotaryoPH.Web.Common.Extensions
{
public static class ObjectExtensions
{
public static int ToInteger(this object obj)
{
int.TryParse(obj.ToString(), out var result);
return result;
}
}
}

View File

@ -1,45 +0,0 @@
namespace EnotaryoPH.Web.Common.Extensions
{
public static class StringExtensions
{
private const char EqualsChar = '=';
private const char Plus = '+';
private const char Slash = '/';
public static string DefaultIfEmpty(this string s, string defaultValue) => !string.IsNullOrWhiteSpace(s) ? s : defaultValue ?? string.Empty;
public static bool IsInList(this string s, params string[] list) => list.Contains(s, StringComparer.OrdinalIgnoreCase);
public static bool IsInList<T>(this string stringValue, IEnumerable<T> listOfEnums) where T : struct, Enum => Enum.TryParse(stringValue, out T enumValue) && listOfEnums.Contains(enumValue);
public static bool IsInList<T>(this string stringValue, params T[] listOfEnums) where T : struct, Enum => Enum.TryParse(stringValue, out T enumValue) && listOfEnums.Contains(enumValue);
public static string NullIfWhiteSpace(this string s) => string.IsNullOrWhiteSpace(s) ? null : s;
public static Guid ToGuidFromBase64(this string s)
{
if (s.Length != 22)
{
return Guid.Empty;
}
var id = s.AsSpan();
Span<char> base64Chars = stackalloc char[24];
for (var i = 0; i < 22; i++)
{
base64Chars[i] = id[i] switch
{
'-' => Slash,
'_' => Plus,
_ => id[i]
};
}
base64Chars[22] = EqualsChar;
base64Chars[23] = EqualsChar;
Span<byte> idBytes = stackalloc byte[16];
Convert.TryFromBase64Chars(base64Chars, idBytes, out _);
return new Guid(idBytes);
}
}
}

View File

@ -1,9 +0,0 @@
using System.Runtime.CompilerServices;
namespace EnotaryoPH.Web.Common.Helpers
{
public static class FullName
{
public static string Of<T>(T _, [CallerArgumentExpression("_")] string fullName = "") => fullName;
}
}

View File

@ -1,9 +0,0 @@
using Microsoft.AspNetCore.SignalR;
namespace EnotaryoPH.Web.Common.Hubs
{
public class NotificationHub : Hub
{
public async Task NotifyUserAsync(string user_UID, string message) => await Clients.All.SendAsync("ReceiveNotaryNotification", user_UID, message);
}
}

View File

@ -1,85 +0,0 @@
using System.Text;
using System.Text.Json;
using Azure.Communication.CallAutomation;
using Azure.Storage.Queues;
using Coravel.Invocable;
using EnotaryoPH.Data;
using EnotaryoPH.Data.Entities;
using EnotaryoPH.Web.Common.Jobs.Models;
namespace EnotaryoPH.Web.Common.Jobs
{
public class CheckRecordingAvailabilityInvocable : IInvocable
{
private readonly QueueClient _queueClient;
private readonly CallAutomationClient _callAutomationClient;
private readonly IConfiguration _configuration;
private readonly IServiceScopeFactory _serviceScopeFactory;
public CheckRecordingAvailabilityInvocable(QueueClient queueClient, CallAutomationClient callAutomationClient, IConfiguration configuration, IServiceScopeFactory serviceScopeFactory)
{
_queueClient = queueClient;
_callAutomationClient = callAutomationClient;
_configuration = configuration;
_serviceScopeFactory = serviceScopeFactory;
}
public async Task Invoke()
{
var message = await _queueClient.ReceiveMessageAsync();
if (message?.Value == null)
{
return;
}
var base64EncodedData = message.Value.Body.ToString();
var base64EncodedBytes = Convert.FromBase64String(base64EncodedData);
var options = new JsonSerializerOptions
{
PropertyNameCaseInsensitive = true
};
var json = Encoding.UTF8.GetString(base64EncodedBytes);
var model = JsonSerializer.Deserialize<RecordingFileStatusUpdatedModel>(json, options);
if (model?.Data?.RecordingStorageInfo?.RecordingChunks?.Count > 0)
{
var dbContext = _serviceScopeFactory.CreateScope().ServiceProvider.GetRequiredService<NotaryoDBContext>();
model.Data.RecordingStorageInfo.RecordingChunks.ForEach(async chunk =>
{
var path = _configuration.GetValue<string>("VideoRecordingsLocation");
if (!Path.Exists(path))
{
Directory.CreateDirectory(path);
}
var fileName = Path.Combine(path, $"{chunk.DocumentId}-{chunk.Index}.mp4");
if (File.Exists(fileName))
{
File.Move(fileName, fileName.Replace(".mp4", $"_{DateTime.UtcNow.ToString("yyyy-MM-dd-HH-mm-dd")}.mp4"));
}
using var memoryStream = new MemoryStream();
await _callAutomationClient
.GetCallRecording().DownloadToAsync(new Uri(chunk.ContentLocation), fileName);
var schedule = dbContext.LawyerVideoConferenceSchedules.FirstOrDefault(sched => sched.RecordingID == model.Data.RecordingId);
if (schedule != null)
{
if (schedule.VideoRecording == null)
{
schedule.VideoRecording = new VideoRecording
{
CreatedOn = DateTime.UtcNow,
LocationType = nameof(VideoRecordingLocationType.LocalFolder),
VideoConferenceScheduleID = schedule.LawyerVideoConferenceScheduleID,
VideoRecording_UID = Guid.CreateVersion7(DateTime.UtcNow)
};
}
schedule.VideoRecording.Path = fileName;
schedule.VideoRecording.Metadata = JsonSerializer.Serialize(json);
dbContext.UpdateOrCreate(schedule);
dbContext.SaveChanges();
}
});
}
await _queueClient.DeleteMessageAsync(message.Value.MessageId, message.Value.PopReceipt);
}
}
}

View File

@ -1,12 +0,0 @@
namespace EnotaryoPH.Web.Common.Jobs.Models
{
public class Data
{
public int RecordingDurationMs { get; set; }
public string RecordingId { get; set; }
public DateTime RecordingStartTime { get; set; }
public RecordingStorageInfo RecordingStorageInfo { get; set; }
public string SessionEndReason { get; set; }
public string StorageType { get; set; }
}
}

View File

@ -1,8 +0,0 @@
namespace EnotaryoPH.Web.Common.Jobs.Models
{
public class OTPEmailModel
{
public Dictionary<Guid, string> ParticipantOTP { get; set; }
public Guid Transaction_UID { get; set; }
}
}

View File

@ -1,12 +0,0 @@
namespace EnotaryoPH.Web.Common.Jobs.Models
{
public class RecordingChunk
{
public string ContentLocation { get; set; }
public string DeleteLocation { get; set; }
public string DocumentId { get; set; }
public string EndReason { get; set; }
public int Index { get; set; }
public string MetadataLocation { get; set; }
}
}

View File

@ -1,14 +0,0 @@
namespace EnotaryoPH.Web.Common.Jobs.Models
{
public class RecordingFileStatusUpdatedModel
{
public Data Data { get; set; }
public string DataVersion { get; set; }
public DateTime EventTime { get; set; }
public string EventType { get; set; }
public string Id { get; set; }
public string MetadataVersion { get; set; }
public string Subject { get; set; }
public string Topic { get; set; }
}
}

View File

@ -1,7 +0,0 @@
namespace EnotaryoPH.Web.Common.Jobs.Models
{
public class RecordingStorageInfo
{
public List<RecordingChunk> RecordingChunks { get; set; }
}
}

View File

@ -1,75 +0,0 @@
using Coravel.Invocable;
using Coravel.Mailer.Mail.Interfaces;
using EnotaryoPH.Data;
using EnotaryoPH.Web.Common.Jobs.Models;
using EnotaryoPH.Web.Common.Models;
using EnotaryoPH.Web.Mailables;
namespace EnotaryoPH.Web.Common.Jobs
{
public class OneTimePasswordInvocable : IInvocable, IInvocableWithPayload<OTPEmailModel>
{
private readonly IMailer _mailer;
private readonly NotaryoDBContext _notaryoDBContext;
private readonly Settings _settings;
private readonly IPasswordService _passwordService;
private readonly IEventService _eventService;
public OneTimePasswordInvocable(IMailer mailer, NotaryoDBContext notaryoDBContext, Settings settings, IPasswordService passwordService, IEventService eventService)
{
_mailer = mailer;
_notaryoDBContext = notaryoDBContext;
_settings = settings;
_passwordService = passwordService;
_eventService = eventService;
}
public OTPEmailModel Payload { get; set; }
public async Task Invoke()
{
var schedule = _notaryoDBContext.LawyerVideoConferenceSchedules
.AsNoTracking()
.Include(sched => sched.Transaction)
.ThenInclude(transaction => transaction.TransactionDocument)
.Include(sched => sched.Transaction)
.ThenInclude(transaction => transaction.Lawyer)
.ThenInclude(lawyer => lawyer.User)
.Include(sched => sched.LawyerVideoConferenceParticipants)
.ThenInclude(participant => participant.Participant)
.FirstOrDefault(sched => sched.Transaction.Transaction_UID == Payload.Transaction_UID);
if (schedule == null)
{
return;
}
var participantDic = schedule.LawyerVideoConferenceParticipants.ToDictionary(p => p.LawyerVideoConferenceParticipant_UID.GetValueOrDefault(), p => p);
foreach (var otp in Payload.ParticipantOTP)
{
if (!participantDic.ContainsKey(otp.Key))
{
continue;
}
var participant = participantDic[otp.Key];
var emailViewModel = new OneTimePasswordViewModel
{
DocumentType = schedule.Transaction.TransactionDocument.DocumentType,
Email = participant.Participant.Email,
OTP = otp.Value,
ParticipantName = participant.Participant.Fullname,
LawyerName = schedule.Transaction.Lawyer.User.Fullname,
MeetingRoomURL = $"{_settings.BaseUrl}/Participant/VideoCall/Room/{schedule.Transaction.Transaction_UID}",
};
await _mailer.SendAsync(new OneTimePasswordMailable(emailViewModel));
await _eventService.LogAsync(NotaryoEvent.OTPSent, Payload.Transaction_UID, new
{
emailViewModel.Email,
emailViewModel.ParticipantName,
emailViewModel.MeetingRoomURL
});
}
}
}
}

View File

@ -1,49 +0,0 @@
using Coravel.Invocable;
using Coravel.Mailer.Mail.Interfaces;
using EnotaryoPH.Data;
using EnotaryoPH.Web.Common.Models;
using EnotaryoPH.Web.Mailables;
namespace EnotaryoPH.Web.Common.Jobs
{
public class SignatoryInvitationInvocable : IInvocable, IInvocableWithPayload<Guid>
{
private readonly IMailer _mailer;
private readonly NotaryoDBContext _notaryoDBContext;
private readonly Settings _settings;
public SignatoryInvitationInvocable(IMailer mailer, NotaryoDBContext notaryoDBContext, Settings settings)
{
_mailer = mailer;
_notaryoDBContext = notaryoDBContext;
_settings = settings;
}
public Guid Payload { get; set; }
public async Task Invoke()
{
var signatory = _notaryoDBContext
.TransactionSignatories
.Include(e => e.Transaction)
.ThenInclude(t => t.Principal)
.FirstOrDefault(e => e.TransactionSignatory_UID == Payload);
var user = signatory.Transaction.Principal;
var name = $"{user.Firstname} {user.Lastname}".NullIfWhiteSpace() ?? user.Email;
var invitationCode = new Guid(signatory.InvitationCode).ToBase64String();
await _mailer.SendAsync(new SignatoryInvitationMailable(new SignatoryViewModel
{
Email = signatory.Email,
InvitationURL = $"{_settings.BaseUrl}/Participant/Registration/{invitationCode}",
MainPrincipalName = name,
SignatoryType = signatory.Type
}));
signatory.Status = nameof(SignatoryStatus.EmailSent);
_notaryoDBContext.TransactionSignatories.Update(signatory);
_notaryoDBContext.SaveChanges();
}
}
}

View File

@ -1,56 +0,0 @@
using System.ComponentModel.DataAnnotations;
using EnotaryoPH.Data.Entities;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Rendering;
namespace EnotaryoPH.Web.Common.Models
{
public class IdentificationDocumentModel
{
public IdentificationDocumentModel()
{ }
public IdentificationDocumentModel(IdentificationDocument document)
{
using var stream = new MemoryStream(document.File);
File = new FormFile(stream, 0, stream.Length, document.Filename, document.Filename);
ExpirationDate = document.ExpirationDate;
DateIssued = document.DateIssued;
PlaceIssued = document.PlaceIssued;
IdNumber = document.IdNumber;
Filename = document.Filename;
ImageBase64Url = File.ToBase64StringUrl();
IdentificationType = document.Type;
IdentificationDocument_UID = document.IdentificationDocument_UID.GetValueOrDefault();
}
[BindProperty]
public DateTime? DateIssued { get; set; }
[BindProperty]
public DateTime? ExpirationDate { get; set; }
[BindProperty, Required]
public IFormFile File { get; set; }
[BindProperty]
public string? Filename { get; set; }
[BindProperty]
public Guid IdentificationDocument_UID { get; set; }
[BindProperty]
public string IdentificationType { get; set; }
public List<SelectListItem>? IdentificationTypes { get; set; }
[BindProperty]
public string IdNumber { get; set; }
[BindProperty]
public string? ImageBase64Url { get; set; }
[BindProperty]
public string PlaceIssued { get; set; }
}
}

View File

@ -1,39 +0,0 @@
using EnotaryoPH.Data.Entities;
namespace EnotaryoPH.Web.Common.Models
{
internal static class IdentificationDocumentModelMapper
{
internal static IdentificationDocument ToEntity(this IdentificationDocumentModel model, int userID)
{
var now = DateTime.UtcNow;
var entity = new IdentificationDocument
{
UploadedOn = now,
UserID = userID,
IdentificationDocument_UID = Guid.CreateVersion7(now),
CreatedOn = now
};
return model.ToEntity(entity);
}
internal static IdentificationDocument ToEntity(this IdentificationDocumentModel model, IdentificationDocument entity)
{
ArgumentNullException.ThrowIfNull(model.File);
entity.ExpirationDate = model.ExpirationDate.ToUTC();
entity.DateIssued = model.DateIssued.ToUTC();
entity.PlaceIssued = model.PlaceIssued;
entity.IdNumber = model.IdNumber;
entity.Type = model.IdentificationType;
var file = model.File;
entity.Filename = file.FileName;
var stream = new MemoryStream((int)file.Length);
file.CopyTo(stream);
entity.File = stream.ToArray();
return entity;
}
}
}

View File

@ -1,7 +0,0 @@
namespace EnotaryoPH.Web.Common.Models
{
public class Settings
{
public string BaseUrl { get; set; }
}
}

View File

@ -1,30 +0,0 @@
using System.Security.Claims;
using System.Security.Principal;
namespace EnotaryoPH.Web.Common.Services
{
public class CurrentUserService : ICurrentUserService
{
private readonly ClaimsIdentity _user;
public CurrentUserService(IPrincipal principal) => _user = principal.Identity as ClaimsIdentity;
public string? GetEmail() => _user.Claims.FirstOrDefault(x => x.Type == ClaimTypes.Email)?.Value;
public string? GetRole() => _user.Claims.FirstOrDefault(x => x.Type == ClaimTypes.Role)?.Value;
public Guid GetUser_UID()
{
if (_user == null)
{
return Guid.Empty;
}
var uid = _user.Claims.FirstOrDefault(x => x.Type == ClaimTypes.NameIdentifier)?.Value;
Guid.TryParse(uid, out var user_UID);
return user_UID;
}
public bool IsAuthenticated() => _user?.IsAuthenticated ?? false;
}
}

View File

@ -1,63 +0,0 @@
using System.Text.Json;
using EnotaryoPH.Data;
using EnotaryoPH.Data.Entities;
namespace EnotaryoPH.Web.Common.Services
{
public class EventService : IEventService
{
private readonly NotaryoDBContext _dBContext;
private readonly INotificationService _notificationService;
public EventService(NotaryoDBContext dBContext, INotificationService notificationService)
{
_dBContext = dBContext;
_notificationService = notificationService;
}
public Task LogAsync(NotaryoEvent notaryoEvent, object entityId) => LogAsync(notaryoEvent, entityId, null);
public async Task LogAsync(NotaryoEvent notaryoEvent, List<object> entityIds, object payLoad)
{
foreach (var entityId in entityIds)
{
await LogAsync(notaryoEvent, entityId, payLoad);
}
}
public async Task LogAsync(NotaryoEvent notaryoEvent, object entityId, object payLoad)
{
var logItem = new EventLog
{
Description = $"Event: {notaryoEvent}, Entity: {entityId}",
EventLog_UID = Guid.CreateVersion7(DateTime.UtcNow),
LogDate = DateTime.UtcNow,
LogType = notaryoEvent.ToString(),
Payload = payLoad != null ? JsonSerializer.Serialize(payLoad) : null,
StreamID = entityId.ToString(),
};
if (notaryoEvent == NotaryoEvent.TransactionApproved)
{
var transaction = _dBContext.Transactions.AsNoTracking()
.Include(t => t.TransactionSignatories)
.ThenInclude(ts => ts.User)
.Include(t => t.Lawyer)
.ThenInclude(l => l.User)
.Include(t => t.Principal)
.Include(t => t.TransactionDocument)
.FirstOrDefault(t => t.TransactionID == entityId.ToInteger());
logItem.Description = $"Transaction {entityId} has been approved.";
if (transaction != null)
{
var message = $"The document {transaction.TransactionDocument.DocumentType} has been approved.";
var allUsers = transaction.TransactionSignatories.ConvertAll(ts => ts.User.Email);
allUsers.Add(transaction.Lawyer.User.Email);
allUsers.Add(transaction.Principal.Email);
await _notificationService.NotifyUsersAsync(message, allUsers.ToArray());
}
}
_dBContext.Add(logItem);
_dBContext.SaveChanges();
}
}
}

View File

@ -1,13 +0,0 @@
namespace EnotaryoPH.Web.Common.Services
{
public interface ICurrentUserService
{
string? GetEmail();
string? GetRole();
Guid GetUser_UID();
bool IsAuthenticated();
}
}

View File

@ -1,11 +0,0 @@
namespace EnotaryoPH.Web.Common.Services
{
public interface IEventService
{
Task LogAsync(NotaryoEvent notaryoEvent, List<object> entityIds, object payLoad);
Task LogAsync(NotaryoEvent notaryoEvent, object entityId);
Task LogAsync(NotaryoEvent notaryoEvent, object entityId, object payLoad);
}
}

View File

@ -1,10 +0,0 @@

namespace EnotaryoPH.Web.Common.Services
{
public interface INotificationService
{
Task NotifyAllAsync(string message);
Task NotifyUserAsync(string message, string userID);
Task NotifyUsersAsync(string message, params string[] userIDs);
}
}

View File

@ -1,9 +0,0 @@
namespace EnotaryoPH.Web.Common.Services
{
public interface IPasswordService
{
string HashPassword(string password);
bool VerifyHashedPassword(string hashedPassword, string providedPassword);
}
}

View File

@ -1,9 +0,0 @@
namespace EnotaryoPH.Web.Common.Services
{
public interface ISignInService
{
Task SignInAsync(UserLogin userLogin);
Task SignOutAsync();
}
}

View File

@ -1,17 +0,0 @@
namespace EnotaryoPH.Web.Common.Services
{
public interface IVideoConferenceService
{
Task ApproveTransactionAsync(Guid transaction_UID);
bool CanStart(Guid transaction_UID);
Guid GetUIDByTransactionUID(Guid transaction_UID);
bool HasExpired(Guid transaction_UID);
Task<Guid> StartAsync(Guid transaction_UID);
Task StartRecordingAsync(Guid transaction_UID, string serverCallID);
}
}

View File

@ -1,18 +0,0 @@
using EnotaryoPH.Web.Common.Hubs;
using Microsoft.AspNetCore.SignalR;
namespace EnotaryoPH.Web.Common.Services
{
public class NotificationService : INotificationService
{
private readonly IHubContext<NotificationHub> _hubContext;
public NotificationService(IHubContext<NotificationHub> hubContext) => _hubContext = hubContext;
public async Task NotifyAllAsync(string message) => await _hubContext.Clients.All.SendAsync("ReceiveUserNotification", message);
public async Task NotifyUserAsync(string message, string userID) => await NotifyUsersAsync(message, userID);
public async Task NotifyUsersAsync(string message, params string[] userIDs) => await _hubContext.Clients.Users(userIDs).SendAsync("ReceiveUserNotification", message);
}
}

View File

@ -1,98 +0,0 @@
using System.Security.Cryptography;
using Microsoft.AspNetCore.Cryptography.KeyDerivation;
namespace EnotaryoPH.Web.Common.Services
{
public class PasswordService : IPasswordService
{
private readonly int _iterCount = 100_000;
private readonly RandomNumberGenerator _rng = RandomNumberGenerator.Create();
public string HashPassword(string password) => Convert.ToBase64String(HashPasswordV3(password, _rng));
public bool VerifyHashedPassword(string hashedPassword, string providedPassword)
{
var decodedHashedPassword = Convert.FromBase64String(hashedPassword);
return VerifyHashedPasswordV3(decodedHashedPassword, providedPassword, out var embeddedIterCount, out var prf);
}
private static byte[] HashPasswordV3(string password, RandomNumberGenerator rng, KeyDerivationPrf prf, int iterCount, int saltSize, int numBytesRequested)
{
// Produce a version 3 (see comment above) text hash.
var salt = new byte[saltSize];
rng.GetBytes(salt);
var subkey = KeyDerivation.Pbkdf2(password, salt, prf, iterCount, numBytesRequested);
var outputBytes = new byte[13 + salt.Length + subkey.Length];
outputBytes[0] = 0x01; // format marker
WriteNetworkByteOrder(outputBytes, 1, (uint)prf);
WriteNetworkByteOrder(outputBytes, 5, (uint)iterCount);
WriteNetworkByteOrder(outputBytes, 9, (uint)saltSize);
Buffer.BlockCopy(salt, 0, outputBytes, 13, salt.Length);
Buffer.BlockCopy(subkey, 0, outputBytes, 13 + saltSize, subkey.Length);
return outputBytes;
}
private static uint ReadNetworkByteOrder(byte[] buffer, int offset)
=> ((uint)(buffer[offset + 0]) << 24)
| ((uint)(buffer[offset + 1]) << 16)
| ((uint)(buffer[offset + 2]) << 8)
| buffer[offset + 3];
private static bool VerifyHashedPasswordV3(byte[] hashedPassword, string password, out int iterCount, out KeyDerivationPrf prf)
{
iterCount = default;
prf = default;
try
{
// Read header information
prf = (KeyDerivationPrf)ReadNetworkByteOrder(hashedPassword, 1);
iterCount = (int)ReadNetworkByteOrder(hashedPassword, 5);
var saltLength = (int)ReadNetworkByteOrder(hashedPassword, 9);
// Read the salt: must be >= 128 bits
if (saltLength < 128 / 8)
{
return false;
}
var salt = new byte[saltLength];
Buffer.BlockCopy(hashedPassword, 13, salt, 0, salt.Length);
// Read the subkey (the rest of the payload): must be >= 128 bits
var subkeyLength = hashedPassword.Length - 13 - salt.Length;
if (subkeyLength < 128 / 8)
{
return false;
}
var expectedSubkey = new byte[subkeyLength];
Buffer.BlockCopy(hashedPassword, 13 + salt.Length, expectedSubkey, 0, expectedSubkey.Length);
// Hash the incoming password and verify it
var actualSubkey = KeyDerivation.Pbkdf2(password, salt, prf, iterCount, subkeyLength);
return CryptographicOperations.FixedTimeEquals(actualSubkey, expectedSubkey);
}
catch
{
// This should never occur except in the case of a malformed payload, where
// we might go off the end of the array. Regardless, a malformed payload
// implies verification failed.
return false;
}
}
private static void WriteNetworkByteOrder(byte[] buffer, int offset, uint value)
{
buffer[offset + 0] = (byte)(value >> 24);
buffer[offset + 1] = (byte)(value >> 16);
buffer[offset + 2] = (byte)(value >> 8);
buffer[offset + 3] = (byte)(value >> 0);
}
private byte[] HashPasswordV3(string password, RandomNumberGenerator rng) => HashPasswordV3(password, rng,
prf: KeyDerivationPrf.HMACSHA512,
iterCount: _iterCount,
saltSize: 128 / 8,
numBytesRequested: 256 / 8);
}
}

View File

@ -1,38 +0,0 @@
using System.Security.Claims;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
namespace EnotaryoPH.Web.Common.Services
{
public class SignInService : ISignInService
{
private readonly IHttpContextAccessor _httpContextAccessor;
public SignInService(IHttpContextAccessor httpContextAccessor) => _httpContextAccessor = httpContextAccessor;
public async Task SignInAsync(UserLogin userLogin)
{
ArgumentException.ThrowIfNullOrWhiteSpace(userLogin.Email);
ArgumentException.ThrowIfNullOrWhiteSpace(userLogin.Role);
ArgumentOutOfRangeException.ThrowIfEqual(Guid.Empty, userLogin.User_UID);
var claims = new List<Claim>
{
new(ClaimTypes.NameIdentifier, userLogin.User_UID.ToString()),
new(ClaimTypes.Name, userLogin.Email),
new(ClaimTypes.Email, userLogin.Email),
new(ClaimTypes.Role, userLogin.Role!)
};
var claimsIdentity = new ClaimsIdentity(
claims, CookieAuthenticationDefaults.AuthenticationScheme);
var authProperties = new AuthenticationProperties();
await _httpContextAccessor.HttpContext.SignInAsync(
CookieAuthenticationDefaults.AuthenticationScheme,
new ClaimsPrincipal(claimsIdentity),
authProperties);
}
public async Task SignOutAsync() => await _httpContextAccessor.HttpContext.SignOutAsync();
}
}

View File

@ -1,9 +0,0 @@
namespace EnotaryoPH.Web.Common.Services
{
public class UserLogin
{
public string Email { get; set; }
public string Role { get; set; }
public Guid User_UID { get; set; }
}
}

View File

@ -1,285 +0,0 @@
using System.Security.Cryptography;
using Azure;
using Azure.Communication;
using Azure.Communication.CallAutomation;
using Azure.Communication.Identity;
using Azure.Communication.Rooms;
using Coravel.Queuing.Interfaces;
using EnotaryoPH.Data;
using EnotaryoPH.Data.Entities;
using EnotaryoPH.Web.Common.Jobs;
using EnotaryoPH.Web.Common.Jobs.Models;
namespace EnotaryoPH.Web.Common.Services
{
public class VideoConferenceService : IVideoConferenceService
{
private const int VideoConferenceExpirationInHours = 2;
private readonly CallAutomationClient _callAutomationClient;
private readonly CommunicationIdentityClient _communicationIdentityClient;
private readonly IConfiguration _configuration;
private readonly NotaryoDBContext _dbContext;
private readonly IEventService _eventService;
private readonly IPasswordService _passwordService;
private readonly IQueue _queue;
private readonly RoomsClient _roomsClient;
public VideoConferenceService(NotaryoDBContext dbContext, CommunicationIdentityClient communicationIdentityClient, RoomsClient roomsClient, CallAutomationClient callAutomationClient, IConfiguration configuration, IEventService eventService, IPasswordService passwordService, IQueue queue)
{
_dbContext = dbContext;
_communicationIdentityClient = communicationIdentityClient;
_roomsClient = roomsClient;
_callAutomationClient = callAutomationClient;
_configuration = configuration;
_eventService = eventService;
_passwordService = passwordService;
_queue = queue;
}
public async Task ApproveTransactionAsync(Guid transaction_UID)
{
var transaction = _dbContext.Transactions
.Include(t => t.TransactionSignatories)
.ThenInclude(ts => ts.User)
.Include(t => t.Schedule)
.Include(t => t.Lawyer)
.ThenInclude(l => l.User)
.Include(t => t.Principal)
.FirstOrDefault(t => t.Transaction_UID == transaction_UID);
NoDataException.ThrowIfNull(transaction, nameof(Transaction), transaction_UID);
transaction.Status = nameof(TransactionState.Approved);
transaction.TransactionSignatories.ForEach(ts => ts.Status = nameof(SignatoryStatus.Approved));
transaction.Schedule.Status = nameof(VideoConferenceStatus.Completed);
_dbContext.Update(transaction);
_dbContext.SaveChanges();
await Task.WhenAll(
_eventService.LogAsync(NotaryoEvent.TransactionApproved, transaction_UID),
StopRecordingAsync(transaction.Schedule)
);
}
public bool CanStart(Guid transaction_UID)
{
if (transaction_UID == Guid.Empty)
{
return false;
}
var transactionEntity = _dbContext.Transactions
.AsNoTracking()
.Include(t => t.TransactionSignatories)
.FirstOrDefault(t => t.Transaction_UID == transaction_UID);
if (transactionEntity == null)
{
return false;
}
var isReadyForVideoCall = transactionEntity.TransactionSignatories.All(signatory => signatory.Status == nameof(SignatoryStatus.FaceMatch));
var isAcceptedByLawyer = transactionEntity.Status == nameof(TransactionState.Accepted) && transactionEntity.LawyerID > 0;
return isReadyForVideoCall && isAcceptedByLawyer;
}
public Guid GetUIDByTransactionUID(Guid transaction_UID)
{
var transactionEntity = _dbContext.Transactions
.AsNoTracking()
.FirstOrDefault(t => t.Transaction_UID == transaction_UID);
if (transactionEntity == null)
{
return Guid.Empty;
}
var schedule = _dbContext.LawyerVideoConferenceSchedules.AsNoTracking().FirstOrDefault(sched => sched.TransactionID == transactionEntity.TransactionID);
return schedule == null ? Guid.Empty : schedule.LawyerVideoConferenceSchedule_UID;
}
public bool HasExpired(Guid transaction_UID)
{
var transactionEntity = _dbContext.Transactions
.Include(t => t.TransactionSignatories)
.FirstOrDefault(t => t.Transaction_UID == transaction_UID);
if (transactionEntity == null)
{
return false;
}
var schedule = _dbContext.LawyerVideoConferenceSchedules.FirstOrDefault(sched => sched.TransactionID == transactionEntity.TransactionID);
if (schedule == null)
{
return false;
}
if (schedule.Status == nameof(VideoConferenceStatus.Expired))
{
return true;
}
if ((DateTime.UtcNow - schedule.MeetingDate).TotalHours > VideoConferenceExpirationInHours)
{
if (!schedule.Status?.IsInList(VideoConferenceStatus.Abandoned, VideoConferenceStatus.Completed) ?? false)
{
schedule.Status = nameof(VideoConferenceStatus.Expired);
_dbContext.Update(schedule);
_dbContext.SaveChanges();
}
return true;
}
return false;
}
public async Task<Guid> StartAsync(Guid transaction_UID)
{
if (!CanStart(transaction_UID))
{
throw new ArgumentException("Transaction is not ready for video conference.");
}
var schedule = GetOrCreateNewSchedule(transaction_UID);
if (schedule.Status == nameof(VideoConferenceStatus.New))
{
await CreateMeetingRoomAsync(schedule);
await CreateAndEmailOTPAsync(schedule);
_dbContext.UpdateOrCreate(schedule);
_dbContext.SaveChanges();
}
return schedule.LawyerVideoConferenceSchedule_UID;
}
public async Task StartRecordingAsync(Guid transaction_UID, string serverCallID)
{
var transactionEntity = _dbContext.Transactions
.Include(t => t.TransactionSignatories)
.Single(t => t.Transaction_UID == transaction_UID);
NoDataException.ThrowIfNull(transactionEntity, nameof(Transaction), transaction_UID);
var schedule = _dbContext.LawyerVideoConferenceSchedules
.FirstOrDefault(sched => sched.TransactionID == transactionEntity.TransactionID);
NoDataException.ThrowIfNull(schedule, nameof(LawyerVideoConferenceSchedule), transactionEntity.TransactionID, FullName.Of(transactionEntity.TransactionID));
if (string.IsNullOrEmpty(schedule.RecordingID))
{
schedule.RecordingID = await StartRecordingAsync(serverCallID);
schedule.ServerCallID = serverCallID;
_dbContext.Update(schedule);
_dbContext.SaveChanges();
}
}
private async Task CreateAndEmailOTPAsync(LawyerVideoConferenceSchedule schedule)
{
var participantOTP = new Dictionary<Guid, string>();
const string validChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
foreach (var participant in schedule.LawyerVideoConferenceParticipants)
{
var otp = RandomNumberGenerator.GetString(validChars, 5);
participant.OTPHash = _passwordService.HashPassword(otp);
participantOTP.Add(participant.LawyerVideoConferenceParticipant_UID.GetValueOrDefault(), otp);
}
_queue.QueueInvocableWithPayload<OneTimePasswordInvocable, OTPEmailModel>(new OTPEmailModel
{
ParticipantOTP = participantOTP,
Transaction_UID = schedule.Transaction.Transaction_UID.GetValueOrDefault()
});
}
private async Task CreateMeetingRoomAsync(LawyerVideoConferenceSchedule schedule)
{
var roomParticipants = new List<RoomParticipant>();
foreach (var participant in schedule.LawyerVideoConferenceParticipants.ToSafeList())
{
var attendee = await _communicationIdentityClient.CreateUserAsync();
participant.MeetingRoomTokenID = await GetTokenResponseAsync(attendee);
participant.MeetingRoomUserID = attendee.Value.Id;
roomParticipants.Add(new RoomParticipant(attendee) { Role = ParticipantRole.Attendee });
}
var presenter = await _communicationIdentityClient.CreateUserAsync();
schedule.MeetingRoomTokenID = await GetTokenResponseAsync(presenter);
schedule.MeetingRoomUserID = presenter.Value.Id;
roomParticipants.Add(new RoomParticipant(presenter) { Role = ParticipantRole.Presenter });
CommunicationRoom room = await _roomsClient.CreateRoomAsync(DateTime.Now, DateTime.Now.AddHours(2), roomParticipants);
schedule.MeetingRoomID = room.Id;
schedule.Status = nameof(VideoConferenceStatus.InProgress);
}
private LawyerVideoConferenceSchedule GetOrCreateNewSchedule(Guid transaction_UID)
{
var transactionEntity = _dbContext.Transactions
.Include(t => t.TransactionSignatories)
.Single(t => t.Transaction_UID == transaction_UID);
var schedule = _dbContext.LawyerVideoConferenceSchedules
.Include(sched => sched.Transaction)
.FirstOrDefault(sched => sched.TransactionID == transactionEntity.TransactionID);
if (schedule != null)
{
return schedule;
}
schedule = new LawyerVideoConferenceSchedule
{
LawyerVideoConferenceSchedule_UID = Guid.CreateVersion7(DateTime.UtcNow),
CreatedOn = DateTime.UtcNow,
LawyerID = transactionEntity.LawyerID.GetValueOrDefault(),
TransactionID = transactionEntity.TransactionID,
Status = nameof(VideoConferenceStatus.New)
};
var participants = transactionEntity.TransactionSignatories.ConvertAll(signatory => new LawyerVideoConferenceParticipant
{
CreatedOn = DateTime.UtcNow,
Status = nameof(VideoConferenceStatus.New),
LawyerVideoConferenceParticipant_UID = Guid.CreateVersion7(DateTime.UtcNow),
ParticipantID = signatory.UserID
});
participants.Add(new LawyerVideoConferenceParticipant
{
CreatedOn = DateTime.UtcNow,
Status = nameof(VideoConferenceStatus.New),
LawyerVideoConferenceParticipant_UID = Guid.CreateVersion7(DateTime.UtcNow),
ParticipantID = transactionEntity.PrincipalID,
});
schedule.MeetingDate = DateTime.UtcNow;
schedule.LawyerVideoConferenceParticipants = participants.ToList();
schedule.Transaction = transactionEntity;
return schedule;
}
private async Task<string> GetTokenResponseAsync(Response<CommunicationUserIdentifier> user)
{
var tokenResponse = await _communicationIdentityClient.GetTokenAsync(user, new[] { CommunicationTokenScope.VoIP });
return tokenResponse.Value.Token;
}
private async Task<string> StartRecordingAsync(string serverCallID)
{
ArgumentException.ThrowIfNullOrWhiteSpace(serverCallID);
CallLocator callLocator = new ServerCallLocator(serverCallID);
var uri = _configuration.GetValue<string>("UriRecordingBlobContainer") ?? string.Empty;
var recordingResult = await _callAutomationClient
.GetCallRecording().StartAsync(new StartRecordingOptions(callLocator)
{
RecordingContent = RecordingContent.AudioVideo,
RecordingStorage = RecordingStorage.CreateAzureBlobContainerRecordingStorage(new Uri(uri)),
RecordingFormat = RecordingFormat.Mp4
});
return recordingResult.Value.RecordingId;
}
private async Task StopRecordingAsync(LawyerVideoConferenceSchedule schedule)
{
if (string.IsNullOrEmpty(schedule.ServerCallID))
{
Console.WriteLine("ServerCallID is not set for this transaction.");
return;
}
if (string.IsNullOrEmpty(schedule.RecordingID))
{
Console.WriteLine("Recording ID is not set for this transaction.");
return;
}
await _callAutomationClient.GetCallRecording().StopAsync(schedule.RecordingID);
}
}
}

View File

@ -1,44 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<UserSecretsId>4082ec67-5a76-4239-b16a-4ab16e73b32a</UserSecretsId>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Azure.Communication.CallAutomation" Version="1.3.0" />
<PackageReference Include="Azure.Communication.Identity" Version="1.3.1" />
<PackageReference Include="Azure.Communication.Rooms" Version="1.1.1" />
<PackageReference Include="Azure.Storage.Queues" Version="12.22.0" />
<PackageReference Include="CompreFace.NET.Sdk" Version="1.0.2" />
<PackageReference Include="Coravel" Version="6.0.2" />
<PackageReference Include="Coravel.Mailer" Version="7.1.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation" Version="8.0.14" />
<PackageReference Include="Microsoft.AspNetCore.SignalR" Version="1.2.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="9.0.1" />
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="9.0.1" />
<PackageReference Include="MimeKit" Version="4.9.0" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="9.0.3" />
<PackageReference Include="Syncfusion.DocIO.Net.Core" Version="28.2.12" />
<PackageReference Include="Syncfusion.EJ2.AspNet.Core" Version="28.2.12" />
<PackageReference Include="Syncfusion.EJ2.PdfViewer.AspNet.Core" Version="28.2.12" />
<PackageReference Include="Syncfusion.Licensing" Version="28.2.12" />
<PackageReference Include="System.Text.Json" Version="9.0.1" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\EnotaryoPH.Data\EnotaryoPH.Data.csproj" />
</ItemGroup>
<ItemGroup>
<Folder Include="wwwroot\lib\jquery.unobtrusive-ajax\" />
<Folder Include="wwwroot\lib\signalr\" />
</ItemGroup>
<Target Name="ParcelBuild" BeforeTargets="Build">
<Exec Command="npm run build" />
</Target>
</Project>

View File

@ -1,16 +0,0 @@
using Coravel.Mailer.Mail;
namespace EnotaryoPH.Web.Mailables
{
public class OneTimePasswordMailable : Mailable<OneTimePasswordViewModel>
{
private readonly OneTimePasswordViewModel _model;
public OneTimePasswordMailable(OneTimePasswordViewModel model) => _model = model;
public override void Build() => this
.To(_model.Email)
.From("noreply@enotaryoph.com")
.View("~/Views/Mail/OneTimePassword.cshtml", _model);
}
}

View File

@ -1,12 +0,0 @@
namespace EnotaryoPH.Web.Mailables
{
public class OneTimePasswordViewModel
{
public string DocumentType { get; set; }
public string Email { get; set; }
public string LawyerName { get; set; }
public string MeetingRoomURL { get; set; }
public string OTP { get; set; }
public string ParticipantName { get; set; }
}
}

View File

@ -1,16 +0,0 @@
using Coravel.Mailer.Mail;
namespace EnotaryoPH.Web.Mailables
{
public class SignatoryInvitationMailable : Mailable<SignatoryViewModel>
{
private readonly SignatoryViewModel _model;
public SignatoryInvitationMailable(SignatoryViewModel model) => _model = model;
public override void Build() => this
.To(_model.Email)
.From("noreply@enotaryoph.com")
.View("~/Views/Mail/SignatoryInvitation.cshtml", _model);
}
}

View File

@ -1,10 +0,0 @@
namespace EnotaryoPH.Web.Mailables
{
public class SignatoryViewModel
{
public string Email { get; set; }
public string InvitationURL { get; set; }
public string MainPrincipalName { get; set; }
public string SignatoryType { get; set; }
}
}

View File

@ -1,32 +0,0 @@
@page
@{
Layout = "_Blank";
}
<body>
<header></header>
<div class="container" style="max-width: 1000px;font-weight: bold;">
<nav class="navbar navbar-expand-md bg-body py-3">
<div class="container">
<a class="navbar-brand d-flex align-items-center" href="/">
<span class="bs-icon-sm bs-icon-rounded d-flex justify-content-center align-items-center bs-icon" style="border-radius: 0px;">
<svg class="bi bi-pen-fill" xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" fill="currentColor" viewBox="0 0 16 16">
<path d="m13.498.795.149-.149a1.207 1.207 0 1 1 1.707 1.708l-.149.148a1.5 1.5 0 0 1-.059 2.059L4.854 14.854a.5.5 0 0 1-.233.131l-4 1a.5.5 0 0 1-.606-.606l1-4a.5.5 0 0 1 .131-.232l9.642-9.642a.5.5 0 0 0-.642.056L6.854 4.854a.5.5 0 1 1-.708-.708L9.44.854A1.5 1.5 0 0 1 11.5.796a1.5 1.5 0 0 1 1.998-.001"></path>
</svg>
</span><span>eNotaryo PH</span>
</a>
</div>
</nav>
<div class="text-center">
<div class="row text-center pt-4">
<div class="col col-12 col-lg-10 mx-auto">
<div class="text-center position-relative"><img class="img-fluid" src="images/404.jpg" /></div>
</div>
</div>
</div>
</div>
<footer class="mt-5">
<div class="container" style="max-width: 1000px;">
<p class="text-center text-md-start">Copyright <span style="color: rgba(18, 22, 67, 0.75);">©</span> 2025 eNotaryoPH</p>
</div>
</footer>
</body>

View File

@ -1,32 +0,0 @@
@page
@{
Layout = "_Blank";
}
<body>
<header></header>
<div class="container" style="max-width: 1000px;font-weight: bold;">
<nav class="navbar navbar-expand-md bg-body py-3">
<div class="container">
<a class="navbar-brand d-flex align-items-center" href="/">
<span class="bs-icon-sm bs-icon-rounded d-flex justify-content-center align-items-center bs-icon" style="border-radius: 0px;">
<svg class="bi bi-pen-fill" xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" fill="currentColor" viewBox="0 0 16 16">
<path d="m13.498.795.149-.149a1.207 1.207 0 1 1 1.707 1.708l-.149.148a1.5 1.5 0 0 1-.059 2.059L4.854 14.854a.5.5 0 0 1-.233.131l-4 1a.5.5 0 0 1-.606-.606l1-4a.5.5 0 0 1 .131-.232l9.642-9.642a.5.5 0 0 0-.642.056L6.854 4.854a.5.5 0 1 1-.708-.708L9.44.854A1.5 1.5 0 0 1 11.5.796a1.5 1.5 0 0 1 1.998-.001"></path>
</svg>
</span><span>eNotaryo PH</span>
</a><button class="navbar-toggler" data-bs-toggle="collapse"><span class="visually-hidden">Toggle navigation</span><span class="navbar-toggler-icon"></span></button>
</div>
</nav>
<div class="text-center">
<div class="row text-center pt-4">
<div class="col col-12 col-lg-10 mx-auto">
<div class="text-center position-relative"><img class="img-fluid" src="images/500.jpg" /></div>
</div>
</div>
</div>
</div>
<footer class="mt-5">
<div class="container" style="max-width: 1000px;">
<p class="text-center text-md-start">Copyright <span style="color: rgba(18, 22, 67, 0.75);">©</span> 2025 eNotaryoPH</p>
</div>
</footer>
</body>

View File

@ -1,8 +0,0 @@
@page
@model EnotaryoPH.Web.Pages.AboutModel
@{
}
<div class="container text-center p-5 my-auto" style="max-width: 1000px;font-weight: bold;">
<h2>This website is brought to you with ❤️ by <a href="https://jfaquinojr.com">Mang Jose</a>.</h2>
</div>

View File

@ -1,12 +0,0 @@
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
namespace EnotaryoPH.Web.Pages
{
public class AboutModel : PageModel
{
public void OnGet()
{
}
}
}

View File

@ -1,32 +0,0 @@
using EnotaryoPH.Data;
using EnotaryoPH.Web.Common.Models;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
namespace EnotaryoPH.Web.Pages
{
public abstract class BaseIdentificationDocumentPageModel : PageModel
{
protected readonly NotaryoDBContext _notaryoDBContext;
protected BaseIdentificationDocumentPageModel(NotaryoDBContext notaryoDBContext) => _notaryoDBContext = notaryoDBContext;
protected void CreateIdentificationDocument(Guid user_UID)
{
ArgumentOutOfRangeException.ThrowIfEqual(Guid.Empty, user_UID);
var user = _notaryoDBContext.Users.AsNoTracking().FirstOrDefault(u => u.User_UID == user_UID) ?? throw new ArgumentException("User does not exist.");
var entity = NewIdentificationDocument.ToEntity(user.UserID);
_notaryoDBContext.Add(entity);
_notaryoDBContext.SaveChanges();
}
[BindProperty(SupportsGet = true)]
public Guid IdentificationDocument_UID { get; set; }
[BindProperty]
public IdentificationDocumentModel NewIdentificationDocument { get; set; }
[BindProperty]
public bool UploadNewIdentification { get; set; }
}
}

View File

@ -1,148 +0,0 @@
using EnotaryoPH.Data;
using EnotaryoPH.Data.Entities;
using Exadel.Compreface.Clients.CompreFaceClient;
using Exadel.Compreface.DTOs.FaceVerificationDTOs.FaceVerification;
using Exadel.Compreface.Services;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
namespace EnotaryoPH.Web.Pages
{
public class BaseTakeSelfiePageModel : PageModel
{
protected readonly NotaryoDBContext _notaryoDBContext;
private readonly ICompreFaceClient _compreFaceClient;
private readonly IConfiguration _configuration;
private readonly ICurrentUserService _currentUserService;
private Transaction _transactionEntity;
private User _user;
public BaseTakeSelfiePageModel(NotaryoDBContext notaryoDBContext, ICurrentUserService currentUserService, ICompreFaceClient compreFaceClient, IConfiguration configuration)
{
_notaryoDBContext = notaryoDBContext;
_currentUserService = currentUserService;
_compreFaceClient = compreFaceClient;
_configuration = configuration;
}
protected async Task<bool> PostAsync()
{
var selfieImage = Convert.FromBase64String(SelfieBase64Image.Split(",")[1]) ?? [];
var identificationDocument = _notaryoDBContext.IdentificationDocuments.First(e => e.UserID == CurrentUser.UserID);
var faceMatches = await VerifySelfieAsync(selfieImage, identificationDocument);
var isMatchSuccess = faceMatches.Any();
if (isMatchSuccess)
{
var signatory = _notaryoDBContext.TransactionSignatories.Include(ts => ts.Transaction).FirstOrDefault(x => x.UserID == CurrentUser.UserID);
if (signatory != null)
{
signatory.Status = nameof(SignatoryStatus.FaceMatch);
_notaryoDBContext.Update(signatory);
_transactionEntity = signatory.Transaction;
Transaction_UID = _transactionEntity.Transaction_UID.Value;
}
else if (!CurrentUser.Role.IsInList(nameof(UserType.Principal), nameof(UserType.SuperUser), nameof(UserType.Administrator)))
{
return false;
}
if (CurrentTransaction.TransactionID == 0)
{
var newTransaction = new Transaction
{
Transaction_UID = Guid.CreateVersion7(DateTime.UtcNow),
CreatedOn = DateTime.UtcNow,
TransactionDate = DateTime.UtcNow,
Status = nameof(TransactionState.New),
PrincipalID = CurrentUser.UserID
};
_notaryoDBContext.Add(CurrentTransaction);
}
var selfieEntity = CreateOrUpdateSelfie(selfieImage);
selfieEntity.Transaction = CurrentTransaction;
selfieEntity.IdentificationDocumentID = identificationDocument.IdentificationDocumentID;
_notaryoDBContext.UpdateOrCreate(selfieEntity);
_notaryoDBContext.SaveChanges();
}
return isMatchSuccess;
}
private TransactionSelfie CreateOrUpdateSelfie(byte[] selfieImage)
{
TransactionSelfie selfieEntity;
if (TransactionSelfie_UID == Guid.Empty)
{
selfieEntity = new TransactionSelfie
{
CreatedOn = DateTime.UtcNow,
TransactionSelfie_UID = Guid.CreateVersion7(DateTime.UtcNow),
UserID = CurrentUser.UserID,
TransactionID = CurrentTransaction.TransactionID,
};
TransactionSelfie_UID = selfieEntity.TransactionSelfie_UID.Value;
}
else
{
selfieEntity = _notaryoDBContext.TransactionSelfies.FirstOrDefault(e => e.TransactionSelfie_UID == TransactionSelfie_UID);
}
selfieEntity.File = Convert.FromBase64String(SelfieBase64Image.Split(",")[1]);
return selfieEntity;
}
private async Task<IEnumerable<FaceMatches>> VerifySelfieAsync(byte[] selfieImage, IdentificationDocument identificationDocument)
{
var selfiePath = Path.Combine(Path.GetTempPath(), "Selfies");
if (!Directory.Exists(selfiePath))
{
Directory.CreateDirectory(selfiePath);
}
var identificationDocumentPath = Path.Combine(selfiePath, $"{identificationDocument.IdentificationDocument_UID}.jpg");
var apiKey = _configuration.GetValue<string>("CompreFaceConfig:APIKey");
var client = _compreFaceClient.GetCompreFaceService<VerificationService>(apiKey);
var faceVerificationRequest = new FaceVerificationRequestByBytes()
{
SourceImageInBytes = selfieImage,
TargetImageInBytes = identificationDocument.File,
DetProbThreshold = 0.81m,
Limit = 1,
Status = false,
FacePlugins = []
};
try
{
var result = await client.VerifyAsync(faceVerificationRequest);
var faceMatches = result.Result.SelectMany(x => x.FaceMatches);
return faceMatches;
}
catch (Exception)
{
return Enumerable.Empty<FaceMatches>();
}
}
[BindProperty]
public string SelfieBase64Image { get; set; }
[BindProperty(SupportsGet = true)]
public Guid Transaction_UID { get; set; }
[BindProperty(SupportsGet = true)]
public Guid TransactionSelfie_UID { get; set; }
protected User CurrentUser => _user ??= _notaryoDBContext.Users.AsNoTracking().First(x => x.User_UID == _currentUserService.GetUser_UID());
protected Transaction CurrentTransaction => _transactionEntity
??= _notaryoDBContext.Transactions.AsNoTracking().FirstOrDefault(x => x.Transaction_UID == Transaction_UID)
?? new Transaction
{
Transaction_UID = Guid.CreateVersion7(DateTime.UtcNow),
CreatedOn = DateTime.UtcNow,
TransactionDate = DateTime.UtcNow,
Status = nameof(TransactionState.New),
PrincipalID = CurrentUser.UserID
};
}
}

View File

@ -1,26 +0,0 @@
@page "{statusCode}"
@model ErrorModel
@{
ViewData["Title"] = "Error";
}
<h1 class="text-danger">Error.</h1>
<h2 class="text-danger">An error occurred while processing your request.</h2>
@if (Model.ShowRequestId)
{
<p>
<strong>Request ID:</strong> <code>@Model.RequestId</code>
</p>
}
<h3>Development Mode</h3>
<p>
Swapping to the <strong>Development</strong> environment displays detailed information about the error that occurred.
</p>
<p>
<strong>The Development environment shouldn't be enabled for deployed applications.</strong>
It can result in displaying sensitive information from exceptions to end users.
For local debugging, enable the <strong>Development</strong> environment by setting the <strong>ASPNETCORE_ENVIRONMENT</strong> environment variable to <strong>Development</strong>
and restarting the app.
</p>

View File

@ -1,38 +0,0 @@
using System.Diagnostics;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
namespace EnotaryoPH.Web.Pages
{
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
[IgnoreAntiforgeryToken]
public class ErrorModel : PageModel
{
private readonly ILogger<ErrorModel> _logger;
public ErrorModel(ILogger<ErrorModel> logger) => _logger = logger;
public IActionResult OnGet()
{
RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier;
if (StatusCode == "404")
{
return Redirect("/404");
}
else if (StatusCode == "500")
{
return Redirect("/500");
}
return Page();
}
public string? RequestId { get; set; }
public bool ShowRequestId => !string.IsNullOrEmpty(RequestId);
[FromRoute]
public string StatusCode { get; set; }
}
}

View File

@ -1,4 +0,0 @@
@page
@model EnotaryoPH.Web.Pages.ForgotPasswordModel
@{
}

View File

@ -1,12 +0,0 @@
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
namespace EnotaryoPH.Web.Pages
{
public class ForgotPasswordModel : PageModel
{
public void OnGet()
{
}
}
}

View File

@ -1,133 +0,0 @@
@page
@model IndexModel
@{
ViewData["Title"] = "Notarize Documents Online";
Layout = "_Blank";
}
<header></header>
<div class="container" style="max-width: 1000px;font-weight: bold;">
<nav class="navbar navbar-expand-md bg-body py-3">
<div class="container">
<a class="navbar-brand d-flex align-items-center" href="#">
<span class="bs-icon-sm bs-icon-rounded d-flex justify-content-center align-items-center bs-icon" style="border-radius: 0px;">
<svg class="bi bi-pen-fill" xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" fill="currentColor" viewBox="0 0 16 16">
<path d="m13.498.795.149-.149a1.207 1.207 0 1 1 1.707 1.708l-.149.148a1.5 1.5 0 0 1-.059 2.059L4.854 14.854a.5.5 0 0 1-.233.131l-4 1a.5.5 0 0 1-.606-.606l1-4a.5.5 0 0 1 .131-.232l9.642-9.642a.5.5 0 0 0-.642.056L6.854 4.854a.5.5 0 1 1-.708-.708L9.44.854A1.5 1.5 0 0 1 11.5.796a1.5 1.5 0 0 1 1.998-.001"></path>
</svg>
</span><span>eNotaryo PH</span>
</a><button class="navbar-toggler" data-bs-toggle="collapse" data-bs-target="#navcol-3"><span class="visually-hidden">Toggle navigation</span><span class="navbar-toggler-icon"></span></button>
<div id="navcol-3" class="collapse navbar-collapse">
<ul class="navbar-nav mx-auto">
<li class="nav-item"><a class="nav-link active" href="/">Home</a></li>
<li class="nav-item"></li>
<li class="nav-item"><a class="nav-link" href="#HowItWorks">How it works</a></li>
<li class="nav-item"><a class="nav-link" href="#Contact">Contact</a></li>
</ul>
<a href="/login" class="btn btn-primary">Login</a>
</div>
</div>
</nav>
<div class="text-center">
<div class="row text-center pt-4">
<div class="col mx-auto col-md-8">
<h1 class="display-4 fw-bold mb-5"><strong><span style="color: rgb(18, 22, 67);">Notarize your documents from the </span></strong><span class="underline">comfort</span><strong><span style="color: rgb(18, 22, 67);"> of your home or office </span></strong></h1>
<div></div>
<p class="fs-5 text-muted mb-5">Subscribe to our newsletter to get the latest updates.</p>
<form class="d-flex justify-content-center flex-wrap">
<div class="shadow-lg mb-3"><input class="form-control" type="email" placeholder="Your Email" /></div>
<div class="shadow-lg mb-3"><button class="btn btn-primary disabled" type="button">Subscribe</button></div>
</form>
</div>
<div class="col col-12 col-lg-10 mx-auto">
<div class="text-center position-relative"><img class="img-fluid" src="images/landing_02.png" /></div>
</div>
</div>
</div>
</div>
<section class="mt-5">
<div class="container" style="max-width: 1000px;">
<h3 id="HowItWorks" class="display-6 fw-bold text-center">How Does It Work?</h3>
<div class="row">
<div class="col d-flex">
<div class="card">
<div class="card-body m-4">
<div class="text-start py-3">
<svg class="bi bi-camera fs-1 text-start" xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" fill="currentColor" viewBox="0 0 16 16">
<path d="M15 12a1 1 0 0 1-1 1H2a1 1 0 0 1-1-1V6a1 1 0 0 1 1-1h1.172a3 3 0 0 0 2.12-.879l.83-.828A1 1 0 0 1 6.827 3h2.344a1 1 0 0 1 .707.293l.828.828A3 3 0 0 0 12.828 5H14a1 1 0 0 1 1 1zM2 4a2 2 0 0 0-2 2v6a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V6a2 2 0 0 0-2-2h-1.172a2 2 0 0 1-1.414-.586l-.828-.828A2 2 0 0 0 9.172 2H6.828a2 2 0 0 0-1.414.586l-.828.828A2 2 0 0 1 3.172 4z"></path>
<path d="M8 11a2.5 2.5 0 1 1 0-5 2.5 2.5 0 0 1 0 5m0 1a3.5 3.5 0 1 0 0-7 3.5 3.5 0 0 0 0 7M3 6.5a.5.5 0 1 1-1 0 .5.5 0 0 1 1 0"></path>
</svg>
</div>
<h4 class="card-title">Take a Selfie</h4>
<h6 class="text-muted card-subtitle mb-2">Use your phone or web camera</h6>
<p class="card-text">Sit back and relax while our facial recognition system analyze your identification.</p><a class="card-link btn-sm" href="#">
Learn More
<svg class="bi bi-arrow-right" xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" fill="currentColor" viewBox="0 0 16 16">
<path fill-rule="evenodd" d="M1 8a.5.5 0 0 1 .5-.5h11.793l-3.147-3.146a.5.5 0 0 1 .708-.708l4 4a.5.5 0 0 1 0 .708l-4 4a.5.5 0 0 1-.708-.708L13.293 8.5H1.5A.5.5 0 0 1 1 8"></path>
</svg>
</a>
</div>
</div>
</div>
<div class="col d-flex">
<div class="card">
<div class="card-body m-4">
<div class="text-start py-3">
<svg class="bi bi-cloud-upload fs-1 text-start" xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" fill="currentColor" viewBox="0 0 16 16">
<path fill-rule="evenodd" d="M4.406 1.342A5.53 5.53 0 0 1 8 0c2.69 0 4.923 2 5.166 4.579C14.758 4.804 16 6.137 16 7.773 16 9.569 14.502 11 12.687 11H10a.5.5 0 0 1 0-1h2.688C13.979 10 15 8.988 15 7.773c0-1.216-1.02-2.228-2.313-2.228h-.5v-.5C12.188 2.825 10.328 1 8 1a4.53 4.53 0 0 0-2.941 1.1c-.757.652-1.153 1.438-1.153 2.055v.448l-.445.049C2.064 4.805 1 5.952 1 7.318 1 8.785 2.23 10 3.781 10H6a.5.5 0 0 1 0 1H3.781C1.708 11 0 9.366 0 7.318c0-1.763 1.266-3.223 2.942-3.593.143-.863.698-1.723 1.464-2.383z"></path>
<path fill-rule="evenodd" d="M7.646 4.146a.5.5 0 0 1 .708 0l3 3a.5.5 0 0 1-.708.708L8.5 5.707V14.5a.5.5 0 0 1-1 0V5.707L5.354 7.854a.5.5 0 1 1-.708-.708z"></path>
</svg>
</div>
<h4 class="card-title">Upload the document</h4>
<h6 class="text-muted card-subtitle mb-2">PDF and MS Word Documents</h6>
<p class="card-text">Simply upload your document and enter the necessary information and we will book an available notary public for you.</p><a class="card-link btn-sm" href="#">
Learn More
<svg class="bi bi-arrow-right" xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" fill="currentColor" viewBox="0 0 16 16">
<path fill-rule="evenodd" d="M1 8a.5.5 0 0 1 .5-.5h11.793l-3.147-3.146a.5.5 0 0 1 .708-.708l4 4a.5.5 0 0 1 0 .708l-4 4a.5.5 0 0 1-.708-.708L13.293 8.5H1.5A.5.5 0 0 1 1 8"></path>
</svg>
</a>
</div>
</div>
</div>
<div class="col d-flex">
<div class="card">
<div class="card-body m-4">
<div class="text-start py-3">
<svg class="bi bi-camera-video fs-1 text-start" xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" fill="currentColor" viewBox="0 0 16 16">
<path fill-rule="evenodd" d="M0 5a2 2 0 0 1 2-2h7.5a2 2 0 0 1 1.983 1.738l3.11-1.382A1 1 0 0 1 16 4.269v7.462a1 1 0 0 1-1.406.913l-3.111-1.382A2 2 0 0 1 9.5 13H2a2 2 0 0 1-2-2zm11.5 5.175 3.5 1.556V4.269l-3.5 1.556zM2 4a1 1 0 0 0-1 1v6a1 1 0 0 0 1 1h7.5a1 1 0 0 0 1-1V5a1 1 0 0 0-1-1z"></path>
</svg>
</div>
<h4 class="card-title">Video Conference</h4>
<h6 class="text-muted card-subtitle mb-2">Meet with Notary Public</h6>
<p class="card-text">The final step is to talk to our notary public team. Once payment has been settled, you can now download the notarized document.</p><a class="card-link btn-sm" href="#">
Learn More
<svg class="bi bi-arrow-right" xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" fill="currentColor" viewBox="0 0 16 16">
<path fill-rule="evenodd" d="M1 8a.5.5 0 0 1 .5-.5h11.793l-3.147-3.146a.5.5 0 0 1 .708-.708l4 4a.5.5 0 0 1 0 .708l-4 4a.5.5 0 0 1-.708-.708L13.293 8.5H1.5A.5.5 0 0 1 1 8"></path>
</svg>
</a>
</div>
</div>
</div>
</div>
</div>
</section>
<section class="mt-5">
<div class="container" style="max-width: 1000px;">
<h3 id="Contact" class="display-6 fw-bold text-center">Got Any Questions?</h3>
<div class="row">
<div class="col col-md-8 col-xl-6 mx-auto text-center">
<form class="p-3 p-xl-4">
<div class="mb-3"><input class="form-control shadow" type="text" placeholder="Name" /></div>
<div class="mb-3"><input class="form-control shadow" type="email" placeholder="Email" /></div>
<div class="mb-3"><textarea class="form-control shadow" placeholder="Message" rows="4"></textarea></div>
<div><button class="btn btn-primary d-block w-100 shadow-lg" type="button">Submit</button></div>
</form>
</div>
</div>
</div>
</section>
<footer class="mt-5">
<div class="container" style="max-width: 1000px;">
<p class="text-center text-md-start">Copyright <span style="color: rgba(18, 22, 67, 0.75);">©</span> 2025 eNotaryoPH</p>
</div>
</footer>

View File

@ -1,48 +0,0 @@
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
namespace EnotaryoPH.Web.Pages
{
public class IndexModel : PageModel
{
private readonly ICurrentUserService _currentUserService;
private readonly INotificationService _notificationService;
private readonly IEventService _eventService;
public IndexModel(ICurrentUserService currentUserService, INotificationService notificationService, IEventService eventService)
{
_currentUserService = currentUserService;
_notificationService = notificationService;
_eventService = eventService;
}
public IActionResult OnGet()
{
if (_currentUserService.IsAuthenticated() == false)
{
return Page();
}
var role = _currentUserService.GetRole();
if (role == nameof(UserType.Principal))
{
return RedirectToPage("/Principal/Dashboard/Dashboard");
}
else if (role == nameof(UserType.Notary))
{
return RedirectToPage("/Notary/Dashboard/Dashboard");
}
return Page();
}
public async Task<IActionResult> OnPostAsync()
{
var message = new { Message = "the quick brown fox jumps over the lazy dog." };
await _eventService.LogAsync(NotaryoEvent.TransactionApproved, new Guid("0195dfd2-9048-77f1-9d9d-974828cb3e68"));
//await _notificationService.NotifyUserAsync("admin@enotaryo.ph", JsonSerializer.Serialize(message));
return Redirect("/");
}
}
}

View File

@ -1,36 +0,0 @@
@page
@model EnotaryoPH.Web.Pages.LoginModel
@{
}
<div class="container">
<h1 class="my-4">Login</h1>
<div class="row">
<div class="col">
<div class="alert alert-danger alert-validation">
@Html.ValidationSummary()
</div>
</div>
</div>
<div class="row">
<div class="col-12 col-md-8 col-lg-6 col-xl-5">
<form method="post">
<div class="row">
<div class="col"><label class="form-label" for="Email">Email</label><input id="Email" class="form-control mb-3" type="email" asp-for="Email" required /></div>
</div>
<div class="row">
<div class="col"><label class="form-label" for="Password">Password</label><input id="Password" class="form-control mb-3" type="password" asp-for="Password" required /></div>
</div>
<div class="row mt-3 mb-0">
<div class="col">
<button class="btn btn-primary btn-lg" type="submit">Login</button>
<a href="/Register" class="btn btn-outline-primary btn-lg ms-1" type="button">Register </a>
</div>
</div>
<div class="row mb-5 mt-2">
<div class="col"><a href="#">Forgot password?</a></div>
</div>
</form>
</div>
</div>
</div>

View File

@ -1,69 +0,0 @@
using System.ComponentModel.DataAnnotations;
using EnotaryoPH.Data;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
namespace EnotaryoPH.Web.Pages
{
public class LoginModel : PageModel
{
private readonly NotaryoDBContext _notaryoDBContext;
private readonly ISignInService _signInService;
private readonly IPasswordService _passwordService;
public LoginModel(IPasswordService passwordService, NotaryoDBContext notaryoDBContext, ISignInService signInService)
{
_passwordService = passwordService;
_notaryoDBContext = notaryoDBContext;
_signInService = signInService;
}
public async Task<IActionResult> OnGetAsync() => Page();
public async Task<IActionResult> OnGetLogoutAsync()
{
await _signInService.SignOutAsync();
return RedirectToPage("/Login");
}
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
var user = _notaryoDBContext.Users.FirstOrDefault(u => EF.Functions.Like(u.Email, Email));
if (user == null)
{
ModelState.AddModelError("", "Invalid Email or Password");
return Page();
}
if (!_passwordService.VerifyHashedPassword(user.PasswordHash, Password))
{
ModelState.AddModelError("", "Invalid Email or Password");
return Page();
}
await _signInService.SignInAsync(new UserLogin
{
Email = user.Email,
Role = user.Role,
User_UID = user.User_UID.Value
});
var returnUrl = Request.Query["ReturnUrl"].ToString() ?? string.Empty;
return Redirect(string.IsNullOrEmpty(returnUrl) ? "/" : returnUrl);
}
[Required]
[EmailAddress]
[BindProperty]
public string Email { get; set; }
[Required]
[BindProperty]
public string Password { get; set; }
}
}

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