Compare commits
No commits in common. "main" and "fixes/principal-onboarding" have entirely different histories.
main
...
fixes/prin
367
.gitignore
vendored
Normal file
367
.gitignore
vendored
Normal file
@ -0,0 +1,367 @@
|
|||||||
|
## 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/
|
286
EnotaryoPH/.editorconfig
Normal file
286
EnotaryoPH/.editorconfig
Normal file
@ -0,0 +1,286 @@
|
|||||||
|
# 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
|
@ -0,0 +1,9 @@
|
|||||||
|
namespace EnotaryoPH.Data.Constants
|
||||||
|
{
|
||||||
|
public enum DocumentSigningStatus
|
||||||
|
{
|
||||||
|
New = 0,
|
||||||
|
ReadyForSigning = 10,
|
||||||
|
Signed = 20
|
||||||
|
}
|
||||||
|
}
|
8
EnotaryoPH/EnotaryoPH.Data/Constants/LawyerStatus.cs
Normal file
8
EnotaryoPH/EnotaryoPH.Data/Constants/LawyerStatus.cs
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
namespace EnotaryoPH.Data.Constants
|
||||||
|
{
|
||||||
|
public enum LawyerStatus
|
||||||
|
{
|
||||||
|
New = 0,
|
||||||
|
FingerprintScanned = 5
|
||||||
|
}
|
||||||
|
}
|
40
EnotaryoPH/EnotaryoPH.Data/Constants/NotaryoEvent.cs
Normal file
40
EnotaryoPH/EnotaryoPH.Data/Constants/NotaryoEvent.cs
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
12
EnotaryoPH/EnotaryoPH.Data/Constants/SignatoryStatus.cs
Normal file
12
EnotaryoPH/EnotaryoPH.Data/Constants/SignatoryStatus.cs
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
namespace EnotaryoPH.Data.Constants
|
||||||
|
{
|
||||||
|
public enum SignatoryStatus
|
||||||
|
{
|
||||||
|
New = 0,
|
||||||
|
EmailSent = 1,
|
||||||
|
Registered = 2,
|
||||||
|
FaceMatch = 3,
|
||||||
|
Approved = 4,
|
||||||
|
Rejected = 5,
|
||||||
|
}
|
||||||
|
}
|
9
EnotaryoPH/EnotaryoPH.Data/Constants/SignatoryType.cs
Normal file
9
EnotaryoPH/EnotaryoPH.Data/Constants/SignatoryType.cs
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
namespace EnotaryoPH.Data.Constants
|
||||||
|
{
|
||||||
|
public enum SignatoryType
|
||||||
|
{
|
||||||
|
Unknown = 0,
|
||||||
|
Principal = 1,
|
||||||
|
Witness = 2
|
||||||
|
}
|
||||||
|
}
|
14
EnotaryoPH/EnotaryoPH.Data/Constants/TransactionState.cs
Normal file
14
EnotaryoPH/EnotaryoPH.Data/Constants/TransactionState.cs
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
namespace EnotaryoPH.Data.Constants
|
||||||
|
{
|
||||||
|
public enum TransactionState
|
||||||
|
{
|
||||||
|
New = 0,
|
||||||
|
SelfiePassed = 1,
|
||||||
|
DocumentUploaded = 2,
|
||||||
|
Submitted = 3,
|
||||||
|
Accepted = 4,
|
||||||
|
Approved = 5,
|
||||||
|
Rejected = 6,
|
||||||
|
Completed = 100
|
||||||
|
}
|
||||||
|
}
|
11
EnotaryoPH/EnotaryoPH.Data/Constants/UserType.cs
Normal file
11
EnotaryoPH/EnotaryoPH.Data/Constants/UserType.cs
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
namespace EnotaryoPH.Data.Constants
|
||||||
|
{
|
||||||
|
public enum UserType
|
||||||
|
{
|
||||||
|
Principal = 0,
|
||||||
|
Witness = 1,
|
||||||
|
Notary = 2,
|
||||||
|
SuperUser = 10,
|
||||||
|
Administrator = 100
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,11 @@
|
|||||||
|
namespace EnotaryoPH.Data.Constants
|
||||||
|
{
|
||||||
|
public enum VideoConferenceStatus
|
||||||
|
{
|
||||||
|
New = 0,
|
||||||
|
InProgress = 1,
|
||||||
|
Expired = 49,
|
||||||
|
Abandoned = 50,
|
||||||
|
Completed = 100
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,10 @@
|
|||||||
|
namespace EnotaryoPH.Data.Constants
|
||||||
|
{
|
||||||
|
public enum VideoRecordingLocationType
|
||||||
|
{
|
||||||
|
Unknown = 0,
|
||||||
|
LocalFolder = 1,
|
||||||
|
SharedFolder = 2,
|
||||||
|
AzureBlob = 3
|
||||||
|
}
|
||||||
|
}
|
15
EnotaryoPH/EnotaryoPH.Data/EnotaryoPH.Data.csproj
Normal file
15
EnotaryoPH/EnotaryoPH.Data/EnotaryoPH.Data.csproj
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
<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>
|
29
EnotaryoPH/EnotaryoPH.Data/Entities/ErrorLog.cs
Normal file
29
EnotaryoPH/EnotaryoPH.Data/Entities/ErrorLog.cs
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
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; }
|
||||||
|
}
|
||||||
|
}
|
35
EnotaryoPH/EnotaryoPH.Data/Entities/EventLog.cs
Normal file
35
EnotaryoPH/EnotaryoPH.Data/Entities/EventLog.cs
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
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; }
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,52 @@
|
|||||||
|
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; }
|
||||||
|
}
|
||||||
|
}
|
61
EnotaryoPH/EnotaryoPH.Data/Entities/Lawyer.cs
Normal file
61
EnotaryoPH/EnotaryoPH.Data/Entities/Lawyer.cs
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
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; }
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,56 @@
|
|||||||
|
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; }
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,54 @@
|
|||||||
|
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; }
|
||||||
|
}
|
||||||
|
}
|
31
EnotaryoPH/EnotaryoPH.Data/Entities/LookupData.cs
Normal file
31
EnotaryoPH/EnotaryoPH.Data/Entities/LookupData.cs
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
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; }
|
||||||
|
}
|
||||||
|
}
|
32
EnotaryoPH/EnotaryoPH.Data/Entities/LookupDataValue.cs
Normal file
32
EnotaryoPH/EnotaryoPH.Data/Entities/LookupDataValue.cs
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
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; }
|
||||||
|
}
|
||||||
|
}
|
29
EnotaryoPH/EnotaryoPH.Data/Entities/Template.cs
Normal file
29
EnotaryoPH/EnotaryoPH.Data/Entities/Template.cs
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
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; }
|
||||||
|
}
|
||||||
|
}
|
52
EnotaryoPH/EnotaryoPH.Data/Entities/Transaction.cs
Normal file
52
EnotaryoPH/EnotaryoPH.Data/Entities/Transaction.cs
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
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; }
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,26 @@
|
|||||||
|
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; }
|
||||||
|
}
|
||||||
|
}
|
38
EnotaryoPH/EnotaryoPH.Data/Entities/TransactionDocument.cs
Normal file
38
EnotaryoPH/EnotaryoPH.Data/Entities/TransactionDocument.cs
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
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; }
|
||||||
|
}
|
||||||
|
}
|
47
EnotaryoPH/EnotaryoPH.Data/Entities/TransactionNotary.cs
Normal file
47
EnotaryoPH/EnotaryoPH.Data/Entities/TransactionNotary.cs
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
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; }
|
||||||
|
}
|
||||||
|
}
|
50
EnotaryoPH/EnotaryoPH.Data/Entities/TransactionOTP.cs
Normal file
50
EnotaryoPH/EnotaryoPH.Data/Entities/TransactionOTP.cs
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
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; }
|
||||||
|
}
|
||||||
|
}
|
35
EnotaryoPH/EnotaryoPH.Data/Entities/TransactionSelfie.cs
Normal file
35
EnotaryoPH/EnotaryoPH.Data/Entities/TransactionSelfie.cs
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
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; }
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,26 @@
|
|||||||
|
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; }
|
||||||
|
}
|
||||||
|
}
|
41
EnotaryoPH/EnotaryoPH.Data/Entities/Transactionsignatory.cs
Normal file
41
EnotaryoPH/EnotaryoPH.Data/Entities/Transactionsignatory.cs
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
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; }
|
||||||
|
}
|
||||||
|
}
|
58
EnotaryoPH/EnotaryoPH.Data/Entities/User.cs
Normal file
58
EnotaryoPH/EnotaryoPH.Data/Entities/User.cs
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
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; }
|
||||||
|
}
|
||||||
|
}
|
32
EnotaryoPH/EnotaryoPH.Data/Entities/VideoRecording.cs
Normal file
32
EnotaryoPH/EnotaryoPH.Data/Entities/VideoRecording.cs
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
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; }
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,44 @@
|
|||||||
|
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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
55
EnotaryoPH/EnotaryoPH.Data/NotaryoDBContext.cs
Normal file
55
EnotaryoPH/EnotaryoPH.Data/NotaryoDBContext.cs
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,36 @@
|
|||||||
|
<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>
|
57
EnotaryoPH/EnotaryoPH.DbMigration/Program.cs
Normal file
57
EnotaryoPH/EnotaryoPH.DbMigration/Program.cs
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
715
EnotaryoPH/EnotaryoPH.DbMigration/Scripts/01_Schema.sql
Normal file
715
EnotaryoPH/EnotaryoPH.DbMigration/Scripts/01_Schema.sql
Normal file
@ -0,0 +1,715 @@
|
|||||||
|
|
||||||
|
|
||||||
|
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$
|
||||||
|
;
|
@ -0,0 +1,74 @@
|
|||||||
|
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, 'Secretary’s 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 $$;
|
45
EnotaryoPH/EnotaryoPH.DbMigration/Scripts/03_UserTracker.sql
Normal file
45
EnotaryoPH/EnotaryoPH.DbMigration/Scripts/03_UserTracker.sql
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
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;
|
@ -0,0 +1,19 @@
|
|||||||
|
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;
|
5
EnotaryoPH/EnotaryoPH.DbMigration/appsettings.json
Normal file
5
EnotaryoPH/EnotaryoPH.DbMigration/appsettings.json
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"ConnectionStrings": {
|
||||||
|
"DbUpConnection": "secret"
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,301 @@
|
|||||||
|
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;
|
@ -0,0 +1,38 @@
|
|||||||
|
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
|
||||||
|
};
|
32
EnotaryoPH/EnotaryoPH.Web/Assets/js/Page/_Page.js
Normal file
32
EnotaryoPH/EnotaryoPH.Web/Assets/js/Page/_Page.js
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
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
|
||||||
|
};
|
@ -0,0 +1,36 @@
|
|||||||
|
|
||||||
|
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
|
||||||
|
};
|
@ -0,0 +1,26 @@
|
|||||||
|
|
||||||
|
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
|
||||||
|
};
|
@ -0,0 +1,16 @@
|
|||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
|
25
EnotaryoPH/EnotaryoPH.Web/Assets/js/_Jfa.js
Normal file
25
EnotaryoPH/EnotaryoPH.Web/Assets/js/_Jfa.js
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
"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;
|
@ -0,0 +1,9 @@
|
|||||||
|
namespace EnotaryoPH.Web.Common.Exceptions
|
||||||
|
{
|
||||||
|
public class InvalidConfigurationException : Exception
|
||||||
|
{
|
||||||
|
public InvalidConfigurationException(string configurationName, object value) : base($"Invalid value '{value}' for configuration '{configurationName}'.")
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,39 @@
|
|||||||
|
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; }
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,40 @@
|
|||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
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() ?? [];
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,20 @@
|
|||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,11 @@
|
|||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,45 @@
|
|||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
9
EnotaryoPH/EnotaryoPH.Web/Common/Helpers/FullName.cs
Normal file
9
EnotaryoPH/EnotaryoPH.Web/Common/Helpers/FullName.cs
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
|
namespace EnotaryoPH.Web.Common.Helpers
|
||||||
|
{
|
||||||
|
public static class FullName
|
||||||
|
{
|
||||||
|
public static string Of<T>(T _, [CallerArgumentExpression("_")] string fullName = "") => fullName;
|
||||||
|
}
|
||||||
|
}
|
9
EnotaryoPH/EnotaryoPH.Web/Common/Hubs/NotificationHub.cs
Normal file
9
EnotaryoPH/EnotaryoPH.Web/Common/Hubs/NotificationHub.cs
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,85 @@
|
|||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
12
EnotaryoPH/EnotaryoPH.Web/Common/Jobs/Models/Data.cs
Normal file
12
EnotaryoPH/EnotaryoPH.Web/Common/Jobs/Models/Data.cs
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
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; }
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,8 @@
|
|||||||
|
namespace EnotaryoPH.Web.Common.Jobs.Models
|
||||||
|
{
|
||||||
|
public class OTPEmailModel
|
||||||
|
{
|
||||||
|
public Dictionary<Guid, string> ParticipantOTP { get; set; }
|
||||||
|
public Guid Transaction_UID { get; set; }
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,12 @@
|
|||||||
|
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; }
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,14 @@
|
|||||||
|
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; }
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,7 @@
|
|||||||
|
namespace EnotaryoPH.Web.Common.Jobs.Models
|
||||||
|
{
|
||||||
|
public class RecordingStorageInfo
|
||||||
|
{
|
||||||
|
public List<RecordingChunk> RecordingChunks { get; set; }
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,75 @@
|
|||||||
|
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
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,49 @@
|
|||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,56 @@
|
|||||||
|
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; }
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,39 @@
|
|||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
7
EnotaryoPH/EnotaryoPH.Web/Common/Models/Settings.cs
Normal file
7
EnotaryoPH/EnotaryoPH.Web/Common/Models/Settings.cs
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
namespace EnotaryoPH.Web.Common.Models
|
||||||
|
{
|
||||||
|
public class Settings
|
||||||
|
{
|
||||||
|
public string BaseUrl { get; set; }
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,30 @@
|
|||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
63
EnotaryoPH/EnotaryoPH.Web/Common/Services/EventService.cs
Normal file
63
EnotaryoPH/EnotaryoPH.Web/Common/Services/EventService.cs
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,13 @@
|
|||||||
|
namespace EnotaryoPH.Web.Common.Services
|
||||||
|
{
|
||||||
|
public interface ICurrentUserService
|
||||||
|
{
|
||||||
|
string? GetEmail();
|
||||||
|
|
||||||
|
string? GetRole();
|
||||||
|
|
||||||
|
Guid GetUser_UID();
|
||||||
|
|
||||||
|
bool IsAuthenticated();
|
||||||
|
}
|
||||||
|
}
|
11
EnotaryoPH/EnotaryoPH.Web/Common/Services/IEventService.cs
Normal file
11
EnotaryoPH/EnotaryoPH.Web/Common/Services/IEventService.cs
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,10 @@
|
|||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
namespace EnotaryoPH.Web.Common.Services
|
||||||
|
{
|
||||||
|
public interface IPasswordService
|
||||||
|
{
|
||||||
|
string HashPassword(string password);
|
||||||
|
|
||||||
|
bool VerifyHashedPassword(string hashedPassword, string providedPassword);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
namespace EnotaryoPH.Web.Common.Services
|
||||||
|
{
|
||||||
|
public interface ISignInService
|
||||||
|
{
|
||||||
|
Task SignInAsync(UserLogin userLogin);
|
||||||
|
|
||||||
|
Task SignOutAsync();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,17 @@
|
|||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,18 @@
|
|||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
98
EnotaryoPH/EnotaryoPH.Web/Common/Services/PasswordService.cs
Normal file
98
EnotaryoPH/EnotaryoPH.Web/Common/Services/PasswordService.cs
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
38
EnotaryoPH/EnotaryoPH.Web/Common/Services/SignInService.cs
Normal file
38
EnotaryoPH/EnotaryoPH.Web/Common/Services/SignInService.cs
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
9
EnotaryoPH/EnotaryoPH.Web/Common/Services/UserLogin.cs
Normal file
9
EnotaryoPH/EnotaryoPH.Web/Common/Services/UserLogin.cs
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
namespace EnotaryoPH.Web.Common.Services
|
||||||
|
{
|
||||||
|
public class UserLogin
|
||||||
|
{
|
||||||
|
public string Email { get; set; }
|
||||||
|
public string Role { get; set; }
|
||||||
|
public Guid User_UID { get; set; }
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,285 @@
|
|||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
44
EnotaryoPH/EnotaryoPH.Web/EnotaryoPH.Web.csproj
Normal file
44
EnotaryoPH/EnotaryoPH.Web/EnotaryoPH.Web.csproj
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
<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>
|
@ -0,0 +1,16 @@
|
|||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,12 @@
|
|||||||
|
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; }
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,16 @@
|
|||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
10
EnotaryoPH/EnotaryoPH.Web/Mailables/SignatoryViewModel.cs
Normal file
10
EnotaryoPH/EnotaryoPH.Web/Mailables/SignatoryViewModel.cs
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
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; }
|
||||||
|
}
|
||||||
|
}
|
32
EnotaryoPH/EnotaryoPH.Web/Pages/404.cshtml
Normal file
32
EnotaryoPH/EnotaryoPH.Web/Pages/404.cshtml
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
@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>
|
32
EnotaryoPH/EnotaryoPH.Web/Pages/500.cshtml
Normal file
32
EnotaryoPH/EnotaryoPH.Web/Pages/500.cshtml
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
@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>
|
8
EnotaryoPH/EnotaryoPH.Web/Pages/About.cshtml
Normal file
8
EnotaryoPH/EnotaryoPH.Web/Pages/About.cshtml
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
@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>
|
12
EnotaryoPH/EnotaryoPH.Web/Pages/About.cshtml.cs
Normal file
12
EnotaryoPH/EnotaryoPH.Web/Pages/About.cshtml.cs
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.AspNetCore.Mvc.RazorPages;
|
||||||
|
|
||||||
|
namespace EnotaryoPH.Web.Pages
|
||||||
|
{
|
||||||
|
public class AboutModel : PageModel
|
||||||
|
{
|
||||||
|
public void OnGet()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,32 @@
|
|||||||
|
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; }
|
||||||
|
}
|
||||||
|
}
|
148
EnotaryoPH/EnotaryoPH.Web/Pages/BaseTakeSelfiePageModel.cs
Normal file
148
EnotaryoPH/EnotaryoPH.Web/Pages/BaseTakeSelfiePageModel.cs
Normal file
@ -0,0 +1,148 @@
|
|||||||
|
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
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
26
EnotaryoPH/EnotaryoPH.Web/Pages/Error.cshtml
Normal file
26
EnotaryoPH/EnotaryoPH.Web/Pages/Error.cshtml
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
@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>
|
38
EnotaryoPH/EnotaryoPH.Web/Pages/Error.cshtml.cs
Normal file
38
EnotaryoPH/EnotaryoPH.Web/Pages/Error.cshtml.cs
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
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; }
|
||||||
|
}
|
||||||
|
}
|
4
EnotaryoPH/EnotaryoPH.Web/Pages/ForgotPassword.cshtml
Normal file
4
EnotaryoPH/EnotaryoPH.Web/Pages/ForgotPassword.cshtml
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
@page
|
||||||
|
@model EnotaryoPH.Web.Pages.ForgotPasswordModel
|
||||||
|
@{
|
||||||
|
}
|
12
EnotaryoPH/EnotaryoPH.Web/Pages/ForgotPassword.cshtml.cs
Normal file
12
EnotaryoPH/EnotaryoPH.Web/Pages/ForgotPassword.cshtml.cs
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.AspNetCore.Mvc.RazorPages;
|
||||||
|
|
||||||
|
namespace EnotaryoPH.Web.Pages
|
||||||
|
{
|
||||||
|
public class ForgotPasswordModel : PageModel
|
||||||
|
{
|
||||||
|
public void OnGet()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
133
EnotaryoPH/EnotaryoPH.Web/Pages/Index.cshtml
Normal file
133
EnotaryoPH/EnotaryoPH.Web/Pages/Index.cshtml
Normal file
@ -0,0 +1,133 @@
|
|||||||
|
@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>
|
48
EnotaryoPH/EnotaryoPH.Web/Pages/Index.cshtml.cs
Normal file
48
EnotaryoPH/EnotaryoPH.Web/Pages/Index.cshtml.cs
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
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("/");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
36
EnotaryoPH/EnotaryoPH.Web/Pages/Login.cshtml
Normal file
36
EnotaryoPH/EnotaryoPH.Web/Pages/Login.cshtml
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
@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>
|
69
EnotaryoPH/EnotaryoPH.Web/Pages/Login.cshtml.cs
Normal file
69
EnotaryoPH/EnotaryoPH.Web/Pages/Login.cshtml.cs
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
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
Loading…
x
Reference in New Issue
Block a user