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