mirror of
https://github.com/BradNut/musicle-svelte
synced 2025-09-08 17:40:21 +00:00
Adding username and password flow.
This commit is contained in:
parent
6677001d7f
commit
744e5dad89
9 changed files with 784 additions and 35 deletions
549
.editorconfig
Normal file
549
.editorconfig
Normal file
|
|
@ -0,0 +1,549 @@
|
||||||
|
root = true
|
||||||
|
|
||||||
|
[*]
|
||||||
|
charset = utf-8
|
||||||
|
end_of_line = lf
|
||||||
|
indent_size = 2
|
||||||
|
indent_style = tab
|
||||||
|
insert_final_newline = false
|
||||||
|
max_line_length = 120
|
||||||
|
tab_width = 2
|
||||||
|
ij_continuation_indent_size = 4
|
||||||
|
ij_formatter_off_tag = @formatter:off
|
||||||
|
ij_formatter_on_tag = @formatter:on
|
||||||
|
ij_formatter_tags_enabled = false
|
||||||
|
ij_smart_tabs = false
|
||||||
|
ij_visual_guides = none
|
||||||
|
ij_wrap_on_typing = false
|
||||||
|
|
||||||
|
[*.css]
|
||||||
|
ij_css_align_closing_brace_with_properties = false
|
||||||
|
ij_css_blank_lines_around_nested_selector = 1
|
||||||
|
ij_css_blank_lines_between_blocks = 1
|
||||||
|
ij_css_block_comment_add_space = false
|
||||||
|
ij_css_brace_placement = end_of_line
|
||||||
|
ij_css_enforce_quotes_on_format = false
|
||||||
|
ij_css_hex_color_long_format = false
|
||||||
|
ij_css_hex_color_lower_case = false
|
||||||
|
ij_css_hex_color_short_format = false
|
||||||
|
ij_css_hex_color_upper_case = false
|
||||||
|
ij_css_keep_blank_lines_in_code = 2
|
||||||
|
ij_css_keep_indents_on_empty_lines = false
|
||||||
|
ij_css_keep_single_line_blocks = false
|
||||||
|
ij_css_properties_order = font,font-family,font-size,font-weight,font-style,font-variant,font-size-adjust,font-stretch,line-height,position,z-index,top,right,bottom,left,display,visibility,float,clear,overflow,overflow-x,overflow-y,clip,zoom,align-content,align-items,align-self,flex,flex-flow,flex-basis,flex-direction,flex-grow,flex-shrink,flex-wrap,justify-content,order,box-sizing,width,min-width,max-width,height,min-height,max-height,margin,margin-top,margin-right,margin-bottom,margin-left,padding,padding-top,padding-right,padding-bottom,padding-left,table-layout,empty-cells,caption-side,border-spacing,border-collapse,list-style,list-style-position,list-style-type,list-style-image,content,quotes,counter-reset,counter-increment,resize,cursor,user-select,nav-index,nav-up,nav-right,nav-down,nav-left,transition,transition-delay,transition-timing-function,transition-duration,transition-property,transform,transform-origin,animation,animation-name,animation-duration,animation-play-state,animation-timing-function,animation-delay,animation-iteration-count,animation-direction,text-align,text-align-last,vertical-align,white-space,text-decoration,text-emphasis,text-emphasis-color,text-emphasis-style,text-emphasis-position,text-indent,text-justify,letter-spacing,word-spacing,text-outline,text-transform,text-wrap,text-overflow,text-overflow-ellipsis,text-overflow-mode,word-wrap,word-break,tab-size,hyphens,pointer-events,opacity,color,border,border-width,border-style,border-color,border-top,border-top-width,border-top-style,border-top-color,border-right,border-right-width,border-right-style,border-right-color,border-bottom,border-bottom-width,border-bottom-style,border-bottom-color,border-left,border-left-width,border-left-style,border-left-color,border-radius,border-top-left-radius,border-top-right-radius,border-bottom-right-radius,border-bottom-left-radius,border-image,border-image-source,border-image-slice,border-image-width,border-image-outset,border-image-repeat,outline,outline-width,outline-style,outline-color,outline-offset,background,background-color,background-image,background-repeat,background-attachment,background-position,background-position-x,background-position-y,background-clip,background-origin,background-size,box-decoration-break,box-shadow,text-shadow
|
||||||
|
ij_css_space_after_colon = true
|
||||||
|
ij_css_space_before_opening_brace = true
|
||||||
|
ij_css_use_double_quotes = true
|
||||||
|
ij_css_value_alignment = do_not_align
|
||||||
|
|
||||||
|
[*.less]
|
||||||
|
ij_less_align_closing_brace_with_properties = false
|
||||||
|
ij_less_blank_lines_around_nested_selector = 1
|
||||||
|
ij_less_blank_lines_between_blocks = 1
|
||||||
|
ij_less_block_comment_add_space = false
|
||||||
|
ij_less_brace_placement = 0
|
||||||
|
ij_less_enforce_quotes_on_format = false
|
||||||
|
ij_less_hex_color_long_format = false
|
||||||
|
ij_less_hex_color_lower_case = false
|
||||||
|
ij_less_hex_color_short_format = false
|
||||||
|
ij_less_hex_color_upper_case = false
|
||||||
|
ij_less_keep_blank_lines_in_code = 2
|
||||||
|
ij_less_keep_indents_on_empty_lines = false
|
||||||
|
ij_less_keep_single_line_blocks = false
|
||||||
|
ij_less_line_comment_add_space = false
|
||||||
|
ij_less_line_comment_at_first_column = false
|
||||||
|
ij_less_properties_order = font,font-family,font-size,font-weight,font-style,font-variant,font-size-adjust,font-stretch,line-height,position,z-index,top,right,bottom,left,display,visibility,float,clear,overflow,overflow-x,overflow-y,clip,zoom,align-content,align-items,align-self,flex,flex-flow,flex-basis,flex-direction,flex-grow,flex-shrink,flex-wrap,justify-content,order,box-sizing,width,min-width,max-width,height,min-height,max-height,margin,margin-top,margin-right,margin-bottom,margin-left,padding,padding-top,padding-right,padding-bottom,padding-left,table-layout,empty-cells,caption-side,border-spacing,border-collapse,list-style,list-style-position,list-style-type,list-style-image,content,quotes,counter-reset,counter-increment,resize,cursor,user-select,nav-index,nav-up,nav-right,nav-down,nav-left,transition,transition-delay,transition-timing-function,transition-duration,transition-property,transform,transform-origin,animation,animation-name,animation-duration,animation-play-state,animation-timing-function,animation-delay,animation-iteration-count,animation-direction,text-align,text-align-last,vertical-align,white-space,text-decoration,text-emphasis,text-emphasis-color,text-emphasis-style,text-emphasis-position,text-indent,text-justify,letter-spacing,word-spacing,text-outline,text-transform,text-wrap,text-overflow,text-overflow-ellipsis,text-overflow-mode,word-wrap,word-break,tab-size,hyphens,pointer-events,opacity,color,border,border-width,border-style,border-color,border-top,border-top-width,border-top-style,border-top-color,border-right,border-right-width,border-right-style,border-right-color,border-bottom,border-bottom-width,border-bottom-style,border-bottom-color,border-left,border-left-width,border-left-style,border-left-color,border-radius,border-top-left-radius,border-top-right-radius,border-bottom-right-radius,border-bottom-left-radius,border-image,border-image-source,border-image-slice,border-image-width,border-image-outset,border-image-repeat,outline,outline-width,outline-style,outline-color,outline-offset,background,background-color,background-image,background-repeat,background-attachment,background-position,background-position-x,background-position-y,background-clip,background-origin,background-size,box-decoration-break,box-shadow,text-shadow
|
||||||
|
ij_less_space_after_colon = true
|
||||||
|
ij_less_space_before_opening_brace = true
|
||||||
|
ij_less_use_double_quotes = true
|
||||||
|
ij_less_value_alignment = 0
|
||||||
|
|
||||||
|
[*.sass]
|
||||||
|
ij_sass_align_closing_brace_with_properties = false
|
||||||
|
ij_sass_blank_lines_around_nested_selector = 1
|
||||||
|
ij_sass_blank_lines_between_blocks = 1
|
||||||
|
ij_sass_brace_placement = 0
|
||||||
|
ij_sass_enforce_quotes_on_format = false
|
||||||
|
ij_sass_hex_color_long_format = false
|
||||||
|
ij_sass_hex_color_lower_case = false
|
||||||
|
ij_sass_hex_color_short_format = false
|
||||||
|
ij_sass_hex_color_upper_case = false
|
||||||
|
ij_sass_keep_blank_lines_in_code = 2
|
||||||
|
ij_sass_keep_indents_on_empty_lines = false
|
||||||
|
ij_sass_keep_single_line_blocks = false
|
||||||
|
ij_sass_line_comment_add_space = false
|
||||||
|
ij_sass_line_comment_at_first_column = false
|
||||||
|
ij_sass_properties_order = font,font-family,font-size,font-weight,font-style,font-variant,font-size-adjust,font-stretch,line-height,position,z-index,top,right,bottom,left,display,visibility,float,clear,overflow,overflow-x,overflow-y,clip,zoom,align-content,align-items,align-self,flex,flex-flow,flex-basis,flex-direction,flex-grow,flex-shrink,flex-wrap,justify-content,order,box-sizing,width,min-width,max-width,height,min-height,max-height,margin,margin-top,margin-right,margin-bottom,margin-left,padding,padding-top,padding-right,padding-bottom,padding-left,table-layout,empty-cells,caption-side,border-spacing,border-collapse,list-style,list-style-position,list-style-type,list-style-image,content,quotes,counter-reset,counter-increment,resize,cursor,user-select,nav-index,nav-up,nav-right,nav-down,nav-left,transition,transition-delay,transition-timing-function,transition-duration,transition-property,transform,transform-origin,animation,animation-name,animation-duration,animation-play-state,animation-timing-function,animation-delay,animation-iteration-count,animation-direction,text-align,text-align-last,vertical-align,white-space,text-decoration,text-emphasis,text-emphasis-color,text-emphasis-style,text-emphasis-position,text-indent,text-justify,letter-spacing,word-spacing,text-outline,text-transform,text-wrap,text-overflow,text-overflow-ellipsis,text-overflow-mode,word-wrap,word-break,tab-size,hyphens,pointer-events,opacity,color,border,border-width,border-style,border-color,border-top,border-top-width,border-top-style,border-top-color,border-right,border-right-width,border-right-style,border-right-color,border-bottom,border-bottom-width,border-bottom-style,border-bottom-color,border-left,border-left-width,border-left-style,border-left-color,border-radius,border-top-left-radius,border-top-right-radius,border-bottom-right-radius,border-bottom-left-radius,border-image,border-image-source,border-image-slice,border-image-width,border-image-outset,border-image-repeat,outline,outline-width,outline-style,outline-color,outline-offset,background,background-color,background-image,background-repeat,background-attachment,background-position,background-position-x,background-position-y,background-clip,background-origin,background-size,box-decoration-break,box-shadow,text-shadow
|
||||||
|
ij_sass_space_after_colon = true
|
||||||
|
ij_sass_space_before_opening_brace = true
|
||||||
|
ij_sass_use_double_quotes = true
|
||||||
|
ij_sass_value_alignment = 0
|
||||||
|
|
||||||
|
[*.scss]
|
||||||
|
ij_scss_align_closing_brace_with_properties = false
|
||||||
|
ij_scss_blank_lines_around_nested_selector = 1
|
||||||
|
ij_scss_blank_lines_between_blocks = 1
|
||||||
|
ij_scss_block_comment_add_space = false
|
||||||
|
ij_scss_brace_placement = 0
|
||||||
|
ij_scss_enforce_quotes_on_format = false
|
||||||
|
ij_scss_hex_color_long_format = false
|
||||||
|
ij_scss_hex_color_lower_case = false
|
||||||
|
ij_scss_hex_color_short_format = false
|
||||||
|
ij_scss_hex_color_upper_case = false
|
||||||
|
ij_scss_keep_blank_lines_in_code = 2
|
||||||
|
ij_scss_keep_indents_on_empty_lines = false
|
||||||
|
ij_scss_keep_single_line_blocks = false
|
||||||
|
ij_scss_line_comment_add_space = false
|
||||||
|
ij_scss_line_comment_at_first_column = false
|
||||||
|
ij_scss_properties_order = font,font-family,font-size,font-weight,font-style,font-variant,font-size-adjust,font-stretch,line-height,position,z-index,top,right,bottom,left,display,visibility,float,clear,overflow,overflow-x,overflow-y,clip,zoom,align-content,align-items,align-self,flex,flex-flow,flex-basis,flex-direction,flex-grow,flex-shrink,flex-wrap,justify-content,order,box-sizing,width,min-width,max-width,height,min-height,max-height,margin,margin-top,margin-right,margin-bottom,margin-left,padding,padding-top,padding-right,padding-bottom,padding-left,table-layout,empty-cells,caption-side,border-spacing,border-collapse,list-style,list-style-position,list-style-type,list-style-image,content,quotes,counter-reset,counter-increment,resize,cursor,user-select,nav-index,nav-up,nav-right,nav-down,nav-left,transition,transition-delay,transition-timing-function,transition-duration,transition-property,transform,transform-origin,animation,animation-name,animation-duration,animation-play-state,animation-timing-function,animation-delay,animation-iteration-count,animation-direction,text-align,text-align-last,vertical-align,white-space,text-decoration,text-emphasis,text-emphasis-color,text-emphasis-style,text-emphasis-position,text-indent,text-justify,letter-spacing,word-spacing,text-outline,text-transform,text-wrap,text-overflow,text-overflow-ellipsis,text-overflow-mode,word-wrap,word-break,tab-size,hyphens,pointer-events,opacity,color,border,border-width,border-style,border-color,border-top,border-top-width,border-top-style,border-top-color,border-right,border-right-width,border-right-style,border-right-color,border-bottom,border-bottom-width,border-bottom-style,border-bottom-color,border-left,border-left-width,border-left-style,border-left-color,border-radius,border-top-left-radius,border-top-right-radius,border-bottom-right-radius,border-bottom-left-radius,border-image,border-image-source,border-image-slice,border-image-width,border-image-outset,border-image-repeat,outline,outline-width,outline-style,outline-color,outline-offset,background,background-color,background-image,background-repeat,background-attachment,background-position,background-position-x,background-position-y,background-clip,background-origin,background-size,box-decoration-break,box-shadow,text-shadow
|
||||||
|
ij_scss_space_after_colon = true
|
||||||
|
ij_scss_space_before_opening_brace = true
|
||||||
|
ij_scss_use_double_quotes = true
|
||||||
|
ij_scss_value_alignment = 0
|
||||||
|
|
||||||
|
[.editorconfig]
|
||||||
|
ij_editorconfig_align_group_field_declarations = false
|
||||||
|
ij_editorconfig_space_after_colon = false
|
||||||
|
ij_editorconfig_space_after_comma = true
|
||||||
|
ij_editorconfig_space_before_colon = false
|
||||||
|
ij_editorconfig_space_before_comma = false
|
||||||
|
ij_editorconfig_spaces_around_assignment_operators = true
|
||||||
|
|
||||||
|
[{*.ant,*.fxml,*.jhm,*.jnlp,*.jrxml,*.pom,*.rng,*.tld,*.wadl,*.wsdl,*.xml,*.xsd,*.xsl,*.xslt,*.xul}]
|
||||||
|
ij_xml_align_attributes = true
|
||||||
|
ij_xml_align_text = false
|
||||||
|
ij_xml_attribute_wrap = normal
|
||||||
|
ij_xml_block_comment_add_space = false
|
||||||
|
ij_xml_block_comment_at_first_column = true
|
||||||
|
ij_xml_keep_blank_lines = 2
|
||||||
|
ij_xml_keep_indents_on_empty_lines = false
|
||||||
|
ij_xml_keep_line_breaks = true
|
||||||
|
ij_xml_keep_line_breaks_in_text = true
|
||||||
|
ij_xml_keep_whitespaces = false
|
||||||
|
ij_xml_keep_whitespaces_around_cdata = preserve
|
||||||
|
ij_xml_keep_whitespaces_inside_cdata = false
|
||||||
|
ij_xml_line_comment_at_first_column = true
|
||||||
|
ij_xml_space_after_tag_name = false
|
||||||
|
ij_xml_space_around_equals_in_attribute = false
|
||||||
|
ij_xml_space_inside_empty_tag = false
|
||||||
|
ij_xml_text_wrap = normal
|
||||||
|
ij_xml_use_custom_settings = false
|
||||||
|
|
||||||
|
[{*.ats,*.cts,*.mts,*.ts}]
|
||||||
|
ij_typescript_align_imports = false
|
||||||
|
ij_typescript_align_multiline_array_initializer_expression = false
|
||||||
|
ij_typescript_align_multiline_binary_operation = false
|
||||||
|
ij_typescript_align_multiline_chained_methods = false
|
||||||
|
ij_typescript_align_multiline_extends_list = false
|
||||||
|
ij_typescript_align_multiline_for = true
|
||||||
|
ij_typescript_align_multiline_parameters = true
|
||||||
|
ij_typescript_align_multiline_parameters_in_calls = false
|
||||||
|
ij_typescript_align_multiline_ternary_operation = false
|
||||||
|
ij_typescript_align_object_properties = 0
|
||||||
|
ij_typescript_align_union_types = false
|
||||||
|
ij_typescript_align_var_statements = 0
|
||||||
|
ij_typescript_array_initializer_new_line_after_left_brace = false
|
||||||
|
ij_typescript_array_initializer_right_brace_on_new_line = false
|
||||||
|
ij_typescript_array_initializer_wrap = off
|
||||||
|
ij_typescript_assignment_wrap = off
|
||||||
|
ij_typescript_binary_operation_sign_on_next_line = false
|
||||||
|
ij_typescript_binary_operation_wrap = off
|
||||||
|
ij_typescript_blacklist_imports = rxjs/Rx,node_modules/**,**/node_modules/**,@angular/material,@angular/material/typings/**
|
||||||
|
ij_typescript_blank_lines_after_imports = 1
|
||||||
|
ij_typescript_blank_lines_around_class = 1
|
||||||
|
ij_typescript_blank_lines_around_field = 0
|
||||||
|
ij_typescript_blank_lines_around_field_in_interface = 0
|
||||||
|
ij_typescript_blank_lines_around_function = 1
|
||||||
|
ij_typescript_blank_lines_around_method = 1
|
||||||
|
ij_typescript_blank_lines_around_method_in_interface = 1
|
||||||
|
ij_typescript_block_brace_style = end_of_line
|
||||||
|
ij_typescript_block_comment_add_space = false
|
||||||
|
ij_typescript_block_comment_at_first_column = true
|
||||||
|
ij_typescript_call_parameters_new_line_after_left_paren = false
|
||||||
|
ij_typescript_call_parameters_right_paren_on_new_line = false
|
||||||
|
ij_typescript_call_parameters_wrap = off
|
||||||
|
ij_typescript_catch_on_new_line = false
|
||||||
|
ij_typescript_chained_call_dot_on_new_line = true
|
||||||
|
ij_typescript_class_brace_style = end_of_line
|
||||||
|
ij_typescript_comma_on_new_line = false
|
||||||
|
ij_typescript_do_while_brace_force = never
|
||||||
|
ij_typescript_else_on_new_line = false
|
||||||
|
ij_typescript_enforce_trailing_comma = keep
|
||||||
|
ij_typescript_enum_constants_wrap = on_every_item
|
||||||
|
ij_typescript_extends_keyword_wrap = off
|
||||||
|
ij_typescript_extends_list_wrap = off
|
||||||
|
ij_typescript_field_prefix = _
|
||||||
|
ij_typescript_file_name_style = relaxed
|
||||||
|
ij_typescript_finally_on_new_line = false
|
||||||
|
ij_typescript_for_brace_force = never
|
||||||
|
ij_typescript_for_statement_new_line_after_left_paren = false
|
||||||
|
ij_typescript_for_statement_right_paren_on_new_line = false
|
||||||
|
ij_typescript_for_statement_wrap = off
|
||||||
|
ij_typescript_force_quote_style = false
|
||||||
|
ij_typescript_force_semicolon_style = false
|
||||||
|
ij_typescript_function_expression_brace_style = end_of_line
|
||||||
|
ij_typescript_if_brace_force = never
|
||||||
|
ij_typescript_import_merge_members = global
|
||||||
|
ij_typescript_import_prefer_absolute_path = global
|
||||||
|
ij_typescript_import_sort_members = true
|
||||||
|
ij_typescript_import_sort_module_name = false
|
||||||
|
ij_typescript_import_use_node_resolution = true
|
||||||
|
ij_typescript_imports_wrap = on_every_item
|
||||||
|
ij_typescript_indent_case_from_switch = true
|
||||||
|
ij_typescript_indent_chained_calls = true
|
||||||
|
ij_typescript_indent_package_children = 0
|
||||||
|
ij_typescript_jsdoc_include_types = false
|
||||||
|
ij_typescript_jsx_attribute_value = braces
|
||||||
|
ij_typescript_keep_blank_lines_in_code = 2
|
||||||
|
ij_typescript_keep_first_column_comment = true
|
||||||
|
ij_typescript_keep_indents_on_empty_lines = false
|
||||||
|
ij_typescript_keep_line_breaks = true
|
||||||
|
ij_typescript_keep_simple_blocks_in_one_line = false
|
||||||
|
ij_typescript_keep_simple_methods_in_one_line = false
|
||||||
|
ij_typescript_line_comment_add_space = true
|
||||||
|
ij_typescript_line_comment_at_first_column = false
|
||||||
|
ij_typescript_method_brace_style = end_of_line
|
||||||
|
ij_typescript_method_call_chain_wrap = off
|
||||||
|
ij_typescript_method_parameters_new_line_after_left_paren = false
|
||||||
|
ij_typescript_method_parameters_right_paren_on_new_line = false
|
||||||
|
ij_typescript_method_parameters_wrap = off
|
||||||
|
ij_typescript_object_literal_wrap = on_every_item
|
||||||
|
ij_typescript_parentheses_expression_new_line_after_left_paren = false
|
||||||
|
ij_typescript_parentheses_expression_right_paren_on_new_line = false
|
||||||
|
ij_typescript_place_assignment_sign_on_next_line = false
|
||||||
|
ij_typescript_prefer_as_type_cast = false
|
||||||
|
ij_typescript_prefer_explicit_types_function_expression_returns = false
|
||||||
|
ij_typescript_prefer_explicit_types_function_returns = false
|
||||||
|
ij_typescript_prefer_explicit_types_vars_fields = false
|
||||||
|
ij_typescript_prefer_parameters_wrap = false
|
||||||
|
ij_typescript_reformat_c_style_comments = false
|
||||||
|
ij_typescript_space_after_colon = true
|
||||||
|
ij_typescript_space_after_comma = true
|
||||||
|
ij_typescript_space_after_dots_in_rest_parameter = false
|
||||||
|
ij_typescript_space_after_generator_mult = true
|
||||||
|
ij_typescript_space_after_property_colon = true
|
||||||
|
ij_typescript_space_after_quest = true
|
||||||
|
ij_typescript_space_after_type_colon = true
|
||||||
|
ij_typescript_space_after_unary_not = false
|
||||||
|
ij_typescript_space_before_async_arrow_lparen = true
|
||||||
|
ij_typescript_space_before_catch_keyword = true
|
||||||
|
ij_typescript_space_before_catch_left_brace = true
|
||||||
|
ij_typescript_space_before_catch_parentheses = true
|
||||||
|
ij_typescript_space_before_class_lbrace = true
|
||||||
|
ij_typescript_space_before_class_left_brace = true
|
||||||
|
ij_typescript_space_before_colon = true
|
||||||
|
ij_typescript_space_before_comma = false
|
||||||
|
ij_typescript_space_before_do_left_brace = true
|
||||||
|
ij_typescript_space_before_else_keyword = true
|
||||||
|
ij_typescript_space_before_else_left_brace = true
|
||||||
|
ij_typescript_space_before_finally_keyword = true
|
||||||
|
ij_typescript_space_before_finally_left_brace = true
|
||||||
|
ij_typescript_space_before_for_left_brace = true
|
||||||
|
ij_typescript_space_before_for_parentheses = true
|
||||||
|
ij_typescript_space_before_for_semicolon = false
|
||||||
|
ij_typescript_space_before_function_left_parenth = true
|
||||||
|
ij_typescript_space_before_generator_mult = false
|
||||||
|
ij_typescript_space_before_if_left_brace = true
|
||||||
|
ij_typescript_space_before_if_parentheses = true
|
||||||
|
ij_typescript_space_before_method_call_parentheses = false
|
||||||
|
ij_typescript_space_before_method_left_brace = true
|
||||||
|
ij_typescript_space_before_method_parentheses = false
|
||||||
|
ij_typescript_space_before_property_colon = false
|
||||||
|
ij_typescript_space_before_quest = true
|
||||||
|
ij_typescript_space_before_switch_left_brace = true
|
||||||
|
ij_typescript_space_before_switch_parentheses = true
|
||||||
|
ij_typescript_space_before_try_left_brace = true
|
||||||
|
ij_typescript_space_before_type_colon = false
|
||||||
|
ij_typescript_space_before_unary_not = false
|
||||||
|
ij_typescript_space_before_while_keyword = true
|
||||||
|
ij_typescript_space_before_while_left_brace = true
|
||||||
|
ij_typescript_space_before_while_parentheses = true
|
||||||
|
ij_typescript_spaces_around_additive_operators = true
|
||||||
|
ij_typescript_spaces_around_arrow_function_operator = true
|
||||||
|
ij_typescript_spaces_around_assignment_operators = true
|
||||||
|
ij_typescript_spaces_around_bitwise_operators = true
|
||||||
|
ij_typescript_spaces_around_equality_operators = true
|
||||||
|
ij_typescript_spaces_around_logical_operators = true
|
||||||
|
ij_typescript_spaces_around_multiplicative_operators = true
|
||||||
|
ij_typescript_spaces_around_relational_operators = true
|
||||||
|
ij_typescript_spaces_around_shift_operators = true
|
||||||
|
ij_typescript_spaces_around_unary_operator = false
|
||||||
|
ij_typescript_spaces_within_array_initializer_brackets = false
|
||||||
|
ij_typescript_spaces_within_brackets = false
|
||||||
|
ij_typescript_spaces_within_catch_parentheses = false
|
||||||
|
ij_typescript_spaces_within_for_parentheses = false
|
||||||
|
ij_typescript_spaces_within_if_parentheses = false
|
||||||
|
ij_typescript_spaces_within_imports = false
|
||||||
|
ij_typescript_spaces_within_interpolation_expressions = false
|
||||||
|
ij_typescript_spaces_within_method_call_parentheses = false
|
||||||
|
ij_typescript_spaces_within_method_parentheses = false
|
||||||
|
ij_typescript_spaces_within_object_literal_braces = false
|
||||||
|
ij_typescript_spaces_within_object_type_braces = true
|
||||||
|
ij_typescript_spaces_within_parentheses = false
|
||||||
|
ij_typescript_spaces_within_switch_parentheses = false
|
||||||
|
ij_typescript_spaces_within_type_assertion = false
|
||||||
|
ij_typescript_spaces_within_union_types = true
|
||||||
|
ij_typescript_spaces_within_while_parentheses = false
|
||||||
|
ij_typescript_special_else_if_treatment = true
|
||||||
|
ij_typescript_ternary_operation_signs_on_next_line = false
|
||||||
|
ij_typescript_ternary_operation_wrap = off
|
||||||
|
ij_typescript_union_types_wrap = on_every_item
|
||||||
|
ij_typescript_use_chained_calls_group_indents = false
|
||||||
|
ij_typescript_use_double_quotes = true
|
||||||
|
ij_typescript_use_explicit_js_extension = auto
|
||||||
|
ij_typescript_use_path_mapping = always
|
||||||
|
ij_typescript_use_public_modifier = false
|
||||||
|
ij_typescript_use_semicolon_after_statement = true
|
||||||
|
ij_typescript_var_declaration_wrap = normal
|
||||||
|
ij_typescript_while_brace_force = never
|
||||||
|
ij_typescript_while_on_new_line = false
|
||||||
|
ij_typescript_wrap_comments = false
|
||||||
|
|
||||||
|
[{*.cjs,*.js}]
|
||||||
|
ij_javascript_align_imports = false
|
||||||
|
ij_javascript_align_multiline_array_initializer_expression = false
|
||||||
|
ij_javascript_align_multiline_binary_operation = false
|
||||||
|
ij_javascript_align_multiline_chained_methods = false
|
||||||
|
ij_javascript_align_multiline_extends_list = false
|
||||||
|
ij_javascript_align_multiline_for = true
|
||||||
|
ij_javascript_align_multiline_parameters = true
|
||||||
|
ij_javascript_align_multiline_parameters_in_calls = false
|
||||||
|
ij_javascript_align_multiline_ternary_operation = false
|
||||||
|
ij_javascript_align_object_properties = 0
|
||||||
|
ij_javascript_align_union_types = false
|
||||||
|
ij_javascript_align_var_statements = 0
|
||||||
|
ij_javascript_array_initializer_new_line_after_left_brace = false
|
||||||
|
ij_javascript_array_initializer_right_brace_on_new_line = false
|
||||||
|
ij_javascript_array_initializer_wrap = off
|
||||||
|
ij_javascript_assignment_wrap = off
|
||||||
|
ij_javascript_binary_operation_sign_on_next_line = false
|
||||||
|
ij_javascript_binary_operation_wrap = off
|
||||||
|
ij_javascript_blacklist_imports = rxjs/Rx,node_modules/**,**/node_modules/**,@angular/material,@angular/material/typings/**
|
||||||
|
ij_javascript_blank_lines_after_imports = 1
|
||||||
|
ij_javascript_blank_lines_around_class = 1
|
||||||
|
ij_javascript_blank_lines_around_field = 0
|
||||||
|
ij_javascript_blank_lines_around_function = 1
|
||||||
|
ij_javascript_blank_lines_around_method = 1
|
||||||
|
ij_javascript_block_brace_style = end_of_line
|
||||||
|
ij_javascript_block_comment_add_space = false
|
||||||
|
ij_javascript_block_comment_at_first_column = true
|
||||||
|
ij_javascript_call_parameters_new_line_after_left_paren = false
|
||||||
|
ij_javascript_call_parameters_right_paren_on_new_line = false
|
||||||
|
ij_javascript_call_parameters_wrap = off
|
||||||
|
ij_javascript_catch_on_new_line = false
|
||||||
|
ij_javascript_chained_call_dot_on_new_line = true
|
||||||
|
ij_javascript_class_brace_style = end_of_line
|
||||||
|
ij_javascript_comma_on_new_line = false
|
||||||
|
ij_javascript_do_while_brace_force = never
|
||||||
|
ij_javascript_else_on_new_line = false
|
||||||
|
ij_javascript_enforce_trailing_comma = keep
|
||||||
|
ij_javascript_extends_keyword_wrap = off
|
||||||
|
ij_javascript_extends_list_wrap = off
|
||||||
|
ij_javascript_field_prefix = _
|
||||||
|
ij_javascript_file_name_style = relaxed
|
||||||
|
ij_javascript_finally_on_new_line = false
|
||||||
|
ij_javascript_for_brace_force = never
|
||||||
|
ij_javascript_for_statement_new_line_after_left_paren = false
|
||||||
|
ij_javascript_for_statement_right_paren_on_new_line = false
|
||||||
|
ij_javascript_for_statement_wrap = off
|
||||||
|
ij_javascript_force_quote_style = false
|
||||||
|
ij_javascript_force_semicolon_style = false
|
||||||
|
ij_javascript_function_expression_brace_style = end_of_line
|
||||||
|
ij_javascript_if_brace_force = never
|
||||||
|
ij_javascript_import_merge_members = global
|
||||||
|
ij_javascript_import_prefer_absolute_path = global
|
||||||
|
ij_javascript_import_sort_members = true
|
||||||
|
ij_javascript_import_sort_module_name = false
|
||||||
|
ij_javascript_import_use_node_resolution = true
|
||||||
|
ij_javascript_imports_wrap = on_every_item
|
||||||
|
ij_javascript_indent_case_from_switch = true
|
||||||
|
ij_javascript_indent_chained_calls = true
|
||||||
|
ij_javascript_indent_package_children = 0
|
||||||
|
ij_javascript_jsx_attribute_value = braces
|
||||||
|
ij_javascript_keep_blank_lines_in_code = 2
|
||||||
|
ij_javascript_keep_first_column_comment = true
|
||||||
|
ij_javascript_keep_indents_on_empty_lines = false
|
||||||
|
ij_javascript_keep_line_breaks = true
|
||||||
|
ij_javascript_keep_simple_blocks_in_one_line = false
|
||||||
|
ij_javascript_keep_simple_methods_in_one_line = false
|
||||||
|
ij_javascript_line_comment_add_space = true
|
||||||
|
ij_javascript_line_comment_at_first_column = false
|
||||||
|
ij_javascript_method_brace_style = end_of_line
|
||||||
|
ij_javascript_method_call_chain_wrap = off
|
||||||
|
ij_javascript_method_parameters_new_line_after_left_paren = false
|
||||||
|
ij_javascript_method_parameters_right_paren_on_new_line = false
|
||||||
|
ij_javascript_method_parameters_wrap = off
|
||||||
|
ij_javascript_object_literal_wrap = on_every_item
|
||||||
|
ij_javascript_parentheses_expression_new_line_after_left_paren = false
|
||||||
|
ij_javascript_parentheses_expression_right_paren_on_new_line = false
|
||||||
|
ij_javascript_place_assignment_sign_on_next_line = false
|
||||||
|
ij_javascript_prefer_as_type_cast = false
|
||||||
|
ij_javascript_prefer_explicit_types_function_expression_returns = false
|
||||||
|
ij_javascript_prefer_explicit_types_function_returns = false
|
||||||
|
ij_javascript_prefer_explicit_types_vars_fields = false
|
||||||
|
ij_javascript_prefer_parameters_wrap = false
|
||||||
|
ij_javascript_reformat_c_style_comments = false
|
||||||
|
ij_javascript_space_after_colon = true
|
||||||
|
ij_javascript_space_after_comma = true
|
||||||
|
ij_javascript_space_after_dots_in_rest_parameter = false
|
||||||
|
ij_javascript_space_after_generator_mult = true
|
||||||
|
ij_javascript_space_after_property_colon = true
|
||||||
|
ij_javascript_space_after_quest = true
|
||||||
|
ij_javascript_space_after_type_colon = true
|
||||||
|
ij_javascript_space_after_unary_not = false
|
||||||
|
ij_javascript_space_before_async_arrow_lparen = true
|
||||||
|
ij_javascript_space_before_catch_keyword = true
|
||||||
|
ij_javascript_space_before_catch_left_brace = true
|
||||||
|
ij_javascript_space_before_catch_parentheses = true
|
||||||
|
ij_javascript_space_before_class_lbrace = true
|
||||||
|
ij_javascript_space_before_class_left_brace = true
|
||||||
|
ij_javascript_space_before_colon = true
|
||||||
|
ij_javascript_space_before_comma = false
|
||||||
|
ij_javascript_space_before_do_left_brace = true
|
||||||
|
ij_javascript_space_before_else_keyword = true
|
||||||
|
ij_javascript_space_before_else_left_brace = true
|
||||||
|
ij_javascript_space_before_finally_keyword = true
|
||||||
|
ij_javascript_space_before_finally_left_brace = true
|
||||||
|
ij_javascript_space_before_for_left_brace = true
|
||||||
|
ij_javascript_space_before_for_parentheses = true
|
||||||
|
ij_javascript_space_before_for_semicolon = false
|
||||||
|
ij_javascript_space_before_function_left_parenth = true
|
||||||
|
ij_javascript_space_before_generator_mult = false
|
||||||
|
ij_javascript_space_before_if_left_brace = true
|
||||||
|
ij_javascript_space_before_if_parentheses = true
|
||||||
|
ij_javascript_space_before_method_call_parentheses = false
|
||||||
|
ij_javascript_space_before_method_left_brace = true
|
||||||
|
ij_javascript_space_before_method_parentheses = false
|
||||||
|
ij_javascript_space_before_property_colon = false
|
||||||
|
ij_javascript_space_before_quest = true
|
||||||
|
ij_javascript_space_before_switch_left_brace = true
|
||||||
|
ij_javascript_space_before_switch_parentheses = true
|
||||||
|
ij_javascript_space_before_try_left_brace = true
|
||||||
|
ij_javascript_space_before_type_colon = false
|
||||||
|
ij_javascript_space_before_unary_not = false
|
||||||
|
ij_javascript_space_before_while_keyword = true
|
||||||
|
ij_javascript_space_before_while_left_brace = true
|
||||||
|
ij_javascript_space_before_while_parentheses = true
|
||||||
|
ij_javascript_spaces_around_additive_operators = true
|
||||||
|
ij_javascript_spaces_around_arrow_function_operator = true
|
||||||
|
ij_javascript_spaces_around_assignment_operators = true
|
||||||
|
ij_javascript_spaces_around_bitwise_operators = true
|
||||||
|
ij_javascript_spaces_around_equality_operators = true
|
||||||
|
ij_javascript_spaces_around_logical_operators = true
|
||||||
|
ij_javascript_spaces_around_multiplicative_operators = true
|
||||||
|
ij_javascript_spaces_around_relational_operators = true
|
||||||
|
ij_javascript_spaces_around_shift_operators = true
|
||||||
|
ij_javascript_spaces_around_unary_operator = false
|
||||||
|
ij_javascript_spaces_within_array_initializer_brackets = false
|
||||||
|
ij_javascript_spaces_within_brackets = false
|
||||||
|
ij_javascript_spaces_within_catch_parentheses = false
|
||||||
|
ij_javascript_spaces_within_for_parentheses = false
|
||||||
|
ij_javascript_spaces_within_if_parentheses = false
|
||||||
|
ij_javascript_spaces_within_imports = false
|
||||||
|
ij_javascript_spaces_within_interpolation_expressions = false
|
||||||
|
ij_javascript_spaces_within_method_call_parentheses = false
|
||||||
|
ij_javascript_spaces_within_method_parentheses = false
|
||||||
|
ij_javascript_spaces_within_object_literal_braces = false
|
||||||
|
ij_javascript_spaces_within_object_type_braces = true
|
||||||
|
ij_javascript_spaces_within_parentheses = false
|
||||||
|
ij_javascript_spaces_within_switch_parentheses = false
|
||||||
|
ij_javascript_spaces_within_type_assertion = false
|
||||||
|
ij_javascript_spaces_within_union_types = true
|
||||||
|
ij_javascript_spaces_within_while_parentheses = false
|
||||||
|
ij_javascript_special_else_if_treatment = true
|
||||||
|
ij_javascript_ternary_operation_signs_on_next_line = false
|
||||||
|
ij_javascript_ternary_operation_wrap = off
|
||||||
|
ij_javascript_union_types_wrap = on_every_item
|
||||||
|
ij_javascript_use_chained_calls_group_indents = false
|
||||||
|
ij_javascript_use_double_quotes = true
|
||||||
|
ij_javascript_use_explicit_js_extension = auto
|
||||||
|
ij_javascript_use_path_mapping = always
|
||||||
|
ij_javascript_use_public_modifier = false
|
||||||
|
ij_javascript_use_semicolon_after_statement = true
|
||||||
|
ij_javascript_var_declaration_wrap = normal
|
||||||
|
ij_javascript_while_brace_force = never
|
||||||
|
ij_javascript_while_on_new_line = false
|
||||||
|
ij_javascript_wrap_comments = false
|
||||||
|
|
||||||
|
[{*.har,*.jsb2,*.jsb3,*.json,.babelrc,.eslintrc,.prettierrc,.stylelintrc,bowerrc,jest.config}]
|
||||||
|
ij_json_array_wrapping = split_into_lines
|
||||||
|
ij_json_keep_blank_lines_in_code = 0
|
||||||
|
ij_json_keep_indents_on_empty_lines = false
|
||||||
|
ij_json_keep_line_breaks = true
|
||||||
|
ij_json_keep_trailing_comma = false
|
||||||
|
ij_json_object_wrapping = split_into_lines
|
||||||
|
ij_json_property_alignment = do_not_align
|
||||||
|
ij_json_space_after_colon = true
|
||||||
|
ij_json_space_after_comma = true
|
||||||
|
ij_json_space_before_colon = false
|
||||||
|
ij_json_space_before_comma = false
|
||||||
|
ij_json_spaces_within_braces = false
|
||||||
|
ij_json_spaces_within_brackets = false
|
||||||
|
ij_json_wrap_long_lines = false
|
||||||
|
|
||||||
|
[{*.htm,*.html,*.ng,*.sht,*.shtm,*.shtml}]
|
||||||
|
ij_html_add_new_line_before_tags = body,div,p,form,h1,h2,h3
|
||||||
|
ij_html_align_attributes = true
|
||||||
|
ij_html_align_text = false
|
||||||
|
ij_html_attribute_wrap = normal
|
||||||
|
ij_html_block_comment_add_space = false
|
||||||
|
ij_html_block_comment_at_first_column = true
|
||||||
|
ij_html_do_not_align_children_of_min_lines = 0
|
||||||
|
ij_html_do_not_break_if_inline_tags = title,h1,h2,h3,h4,h5,h6,p
|
||||||
|
ij_html_do_not_indent_children_of_tags = html,body,thead,tbody,tfoot
|
||||||
|
ij_html_enforce_quotes = false
|
||||||
|
ij_html_inline_tags = a,abbr,acronym,b,basefont,bdo,big,br,cite,cite,code,dfn,em,font,i,img,input,kbd,label,q,s,samp,select,small,span,strike,strong,sub,sup,textarea,tt,u,var
|
||||||
|
ij_html_keep_blank_lines = 2
|
||||||
|
ij_html_keep_indents_on_empty_lines = false
|
||||||
|
ij_html_keep_line_breaks = true
|
||||||
|
ij_html_keep_line_breaks_in_text = true
|
||||||
|
ij_html_keep_whitespaces = false
|
||||||
|
ij_html_keep_whitespaces_inside = span,pre,textarea
|
||||||
|
ij_html_line_comment_at_first_column = true
|
||||||
|
ij_html_new_line_after_last_attribute = never
|
||||||
|
ij_html_new_line_before_first_attribute = never
|
||||||
|
ij_html_quote_style = double
|
||||||
|
ij_html_remove_new_line_before_tags = br
|
||||||
|
ij_html_space_after_tag_name = false
|
||||||
|
ij_html_space_around_equality_in_attribute = false
|
||||||
|
ij_html_space_inside_empty_tag = false
|
||||||
|
ij_html_text_wrap = normal
|
||||||
|
|
||||||
|
[{*.markdown,*.md}]
|
||||||
|
ij_markdown_force_one_space_after_blockquote_symbol = true
|
||||||
|
ij_markdown_force_one_space_after_header_symbol = true
|
||||||
|
ij_markdown_force_one_space_after_list_bullet = true
|
||||||
|
ij_markdown_force_one_space_between_words = true
|
||||||
|
ij_markdown_format_tables = true
|
||||||
|
ij_markdown_insert_quote_arrows_on_wrap = true
|
||||||
|
ij_markdown_keep_indents_on_empty_lines = false
|
||||||
|
ij_markdown_keep_line_breaks_inside_text_blocks = true
|
||||||
|
ij_markdown_max_lines_around_block_elements = 1
|
||||||
|
ij_markdown_max_lines_around_header = 1
|
||||||
|
ij_markdown_max_lines_between_paragraphs = 1
|
||||||
|
ij_markdown_min_lines_around_block_elements = 1
|
||||||
|
ij_markdown_min_lines_around_header = 1
|
||||||
|
ij_markdown_min_lines_between_paragraphs = 1
|
||||||
|
ij_markdown_wrap_text_if_long = true
|
||||||
|
ij_markdown_wrap_text_inside_blockquotes = true
|
||||||
|
|
||||||
|
[{*.properties,spring.handlers,spring.schemas}]
|
||||||
|
ij_properties_align_group_field_declarations = false
|
||||||
|
ij_properties_keep_blank_lines = false
|
||||||
|
ij_properties_key_value_delimiter = equals
|
||||||
|
ij_properties_spaces_around_key_value_delimiter = false
|
||||||
|
|
||||||
|
[{*.toml,Cargo.lock,Cargo.toml.orig,Gopkg.lock,Pipfile,poetry.lock}]
|
||||||
|
ij_toml_keep_indents_on_empty_lines = false
|
||||||
|
|
||||||
|
[{*.yaml,*.yml}]
|
||||||
|
ij_yaml_align_values_properties = do_not_align
|
||||||
|
ij_yaml_autoinsert_sequence_marker = true
|
||||||
|
ij_yaml_block_mapping_on_new_line = false
|
||||||
|
ij_yaml_indent_sequence_value = true
|
||||||
|
ij_yaml_keep_indents_on_empty_lines = false
|
||||||
|
ij_yaml_keep_line_breaks = true
|
||||||
|
ij_yaml_sequence_on_new_line = false
|
||||||
|
ij_yaml_space_before_colon = false
|
||||||
|
ij_yaml_spaces_within_braces = true
|
||||||
|
ij_yaml_spaces_within_brackets = true
|
||||||
8
.idea/.gitignore
vendored
Normal file
8
.idea/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
# Default ignored files
|
||||||
|
/shelf/
|
||||||
|
/workspace.xml
|
||||||
|
# Editor-based HTTP Client requests
|
||||||
|
/httpRequests/
|
||||||
|
# Datasource local storage ignored files
|
||||||
|
/dataSources/
|
||||||
|
/dataSources.local.xml
|
||||||
|
|
@ -1,42 +1,40 @@
|
||||||
import { inject, injectable } from '@needle-di/core';
|
import { inject, injectable } from '@needle-di/core';
|
||||||
import { zValidator } from '@hono/zod-validator';
|
import { zValidator } from '@hono/zod-validator';
|
||||||
|
import { openApi } from 'hono-zod-openapi';
|
||||||
import { createLoginRequestDto } from '../iam/login-requests/dtos/create-login-request.dto';
|
import { createLoginRequestDto } from '../iam/login-requests/dtos/create-login-request.dto';
|
||||||
import { LoginRequestsService } from '../iam/login-requests/login-requests.service';
|
import { LoginRequestsService } from '../iam/login-requests/login-requests.service';
|
||||||
import { verifyLoginRequestDto } from '../iam/login-requests/dtos/verify-login-request.dto';
|
import { verifyLoginRequestDto } from '../iam/login-requests/dtos/verify-login-request.dto';
|
||||||
import { SessionsService } from '../iam/sessions/sessions.service';
|
import { SessionsService } from '../iam/sessions/sessions.service';
|
||||||
import { authState } from '../common/middleware/auth.middleware';
|
import { authState } from '../common/middleware/auth.middleware';
|
||||||
import { Controller } from '../common/factories/controllers.factory';
|
import { Controller } from '../common/factories/controllers.factory';
|
||||||
|
import { loginRequestDto } from './login-requests/dtos/login-request.dto';
|
||||||
|
import { signInEmail } from './login-requests/routes/login.routes';
|
||||||
|
|
||||||
@injectable()
|
@injectable()
|
||||||
export class IamController extends Controller {
|
export class IamController extends Controller {
|
||||||
constructor(
|
constructor(
|
||||||
private loginRequestsService = inject(LoginRequestsService),
|
private loginRequestsService = inject(LoginRequestsService),
|
||||||
private sessionsService = inject(SessionsService)
|
private sessionsService = inject(SessionsService),
|
||||||
) {
|
) {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
routes() {
|
routes() {
|
||||||
return this.controller
|
return this.controller
|
||||||
.post(
|
.post('/login', openApi(signInEmail), authState('none'), zValidator('json', loginRequestDto), async (c) => {
|
||||||
'/login/request',
|
const session = await this.loginRequestsService.login(c.req.valid('json'));
|
||||||
authState('none'),
|
await this.sessionsService.setSessionCookie(session);
|
||||||
zValidator('json', createLoginRequestDto),
|
return c.json({ message: 'welcome' });
|
||||||
async (c) => {
|
})
|
||||||
await this.loginRequestsService.sendVerificationCode(c.req.valid('json'));
|
.post('/login/request', authState('none'), zValidator('json', createLoginRequestDto), async (c) => {
|
||||||
return c.json({ message: 'welcome' });
|
await this.loginRequestsService.sendVerificationCode(c.req.valid('json'));
|
||||||
}
|
return c.json({ message: 'welcome' });
|
||||||
)
|
})
|
||||||
.post(
|
.post('/login/verify', authState('none'), zValidator('json', verifyLoginRequestDto), async (c) => {
|
||||||
'/login/verify',
|
const session = await this.loginRequestsService.verify(c.req.valid('json'));
|
||||||
authState('none'),
|
await this.sessionsService.setSessionCookie(session);
|
||||||
zValidator('json', verifyLoginRequestDto),
|
return c.json({ message: 'welcome' });
|
||||||
async (c) => {
|
})
|
||||||
const session = await this.loginRequestsService.verify(c.req.valid('json'));
|
|
||||||
await this.sessionsService.setSessionCookie(session);
|
|
||||||
return c.json({ message: 'welcome' });
|
|
||||||
}
|
|
||||||
)
|
|
||||||
.post('/logout', async (c) => {
|
.post('/logout', async (c) => {
|
||||||
await this.sessionsService.invalidateSession('');
|
await this.sessionsService.invalidateSession('');
|
||||||
this.sessionsService.deleteSessionCookie();
|
this.sessionsService.deleteSessionCookie();
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
import { z } from 'zod';
|
||||||
|
|
||||||
|
export const loginRequestDto = z.object({
|
||||||
|
email: z.string().email(),
|
||||||
|
password: z.string({ required_error: 'Password is required' }),
|
||||||
|
});
|
||||||
|
|
||||||
|
export type LoginRequestDto = z.infer<typeof loginRequestDto>;
|
||||||
|
|
@ -2,7 +2,7 @@ import { inject, injectable } from '@needle-di/core';
|
||||||
import { LoginRequestsRepository } from './login-requests.repository';
|
import { LoginRequestsRepository } from './login-requests.repository';
|
||||||
import { MailerService } from '../../mail/mailer.service';
|
import { MailerService } from '../../mail/mailer.service';
|
||||||
import { LoginVerificationEmail } from '../../mail/templates/login-verification.template';
|
import { LoginVerificationEmail } from '../../mail/templates/login-verification.template';
|
||||||
import { BadRequest } from '../../common/utils/exceptions';
|
import { BadRequest, NotFound } from '../../common/utils/exceptions';
|
||||||
import { WelcomeEmail } from '../../mail/templates/welcome.template';
|
import { WelcomeEmail } from '../../mail/templates/welcome.template';
|
||||||
import { SessionsService } from '../sessions/sessions.service';
|
import { SessionsService } from '../sessions/sessions.service';
|
||||||
import type { VerifyLoginRequestDto } from './dtos/verify-login-request.dto';
|
import type { VerifyLoginRequestDto } from './dtos/verify-login-request.dto';
|
||||||
|
|
@ -10,18 +10,43 @@ import type { CreateLoginRequestDto } from './dtos/create-login-request.dto';
|
||||||
import { UsersService } from '../../users/users.service';
|
import { UsersService } from '../../users/users.service';
|
||||||
import { UsersRepository } from '../../users/users.repository';
|
import { UsersRepository } from '../../users/users.repository';
|
||||||
import { VerificationCodesService } from '../../common/services/verification-codes.service';
|
import { VerificationCodesService } from '../../common/services/verification-codes.service';
|
||||||
|
import type { LoginRequestDto } from './dtos/login-request.dto';
|
||||||
|
import { CredentialsRepository } from '../../users/credentials.repository';
|
||||||
|
|
||||||
@injectable()
|
@injectable()
|
||||||
export class LoginRequestsService {
|
export class LoginRequestsService {
|
||||||
constructor(
|
constructor(
|
||||||
|
private credentialsRepository = inject(CredentialsRepository),
|
||||||
private loginRequestsRepository = inject(LoginRequestsRepository),
|
private loginRequestsRepository = inject(LoginRequestsRepository),
|
||||||
private usersRepository = inject(UsersRepository),
|
private usersRepository = inject(UsersRepository),
|
||||||
private verificationCodesService = inject(VerificationCodesService),
|
private verificationCodesService = inject(VerificationCodesService),
|
||||||
private usersService = inject(UsersService),
|
private usersService = inject(UsersService),
|
||||||
private sessionsService = inject(SessionsService),
|
private sessionsService = inject(SessionsService),
|
||||||
private mailer = inject(MailerService)
|
private mailer = inject(MailerService),
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
|
async login({ email, password }: LoginRequestDto) {
|
||||||
|
const existingUser = await this.usersRepository.findOneByEmail(email);
|
||||||
|
|
||||||
|
if (!existingUser) {
|
||||||
|
throw NotFound('User not found');
|
||||||
|
}
|
||||||
|
|
||||||
|
const credential = await this.credentialsRepository.findPasswordCredentialsByUserId(existingUser.id);
|
||||||
|
|
||||||
|
if (!credential) {
|
||||||
|
throw BadRequest('Invalid credentials');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(await this.tokensService.verifyHashedToken(credential.secret_data, data.password))) {
|
||||||
|
throw BadRequest('Invalid credentials');
|
||||||
|
}
|
||||||
|
|
||||||
|
const totpCredentials = await this.credentialsRepository.findTOTPCredentialsByUserId(existingUser.id);
|
||||||
|
|
||||||
|
return this.authExistingUser({ userId: existingUser.id });
|
||||||
|
}
|
||||||
|
|
||||||
async verify({ email, code }: VerifyLoginRequestDto) {
|
async verify({ email, code }: VerifyLoginRequestDto) {
|
||||||
// find the hashed verification code for the email
|
// find the hashed verification code for the email
|
||||||
const loginRequest = await this.loginRequestsRepository.get(email);
|
const loginRequest = await this.loginRequestsRepository.get(email);
|
||||||
|
|
@ -32,7 +57,7 @@ export class LoginRequestsService {
|
||||||
// verify the code
|
// verify the code
|
||||||
const isValid = await this.verificationCodesService.verify({
|
const isValid = await this.verificationCodesService.verify({
|
||||||
verificationCode: code,
|
verificationCode: code,
|
||||||
hashedVerificationCode: loginRequest.hashedCode
|
hashedVerificationCode: loginRequest.hashedCode,
|
||||||
});
|
});
|
||||||
|
|
||||||
// if the code is invalid, throw an error
|
// if the code is invalid, throw an error
|
||||||
|
|
@ -45,9 +70,7 @@ export class LoginRequestsService {
|
||||||
const existingUser = await this.usersRepository.findOneByEmail(email);
|
const existingUser = await this.usersRepository.findOneByEmail(email);
|
||||||
|
|
||||||
// if the user exists, log them in, otherwise create a new user and log them in
|
// if the user exists, log them in, otherwise create a new user and log them in
|
||||||
return existingUser
|
return existingUser ? this.authExistingUser({ userId: existingUser.id }) : this.authNewUser({ email });
|
||||||
? this.authExistingUser({ userId: existingUser.id })
|
|
||||||
: this.authNewUser({ email });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async sendVerificationCode({ email }: CreateLoginRequestDto) {
|
async sendVerificationCode({ email }: CreateLoginRequestDto) {
|
||||||
|
|
@ -55,19 +78,18 @@ export class LoginRequestsService {
|
||||||
await this.loginRequestsRepository.delete(email);
|
await this.loginRequestsRepository.delete(email);
|
||||||
|
|
||||||
// generate a new verification code and hash
|
// generate a new verification code and hash
|
||||||
const { verificationCode, hashedVerificationCode } =
|
const { verificationCode, hashedVerificationCode } = await this.verificationCodesService.generateCodeWithHash();
|
||||||
await this.verificationCodesService.generateCodeWithHash();
|
|
||||||
|
|
||||||
// create a new login request
|
// create a new login request
|
||||||
await this.loginRequestsRepository.set({
|
await this.loginRequestsRepository.set({
|
||||||
email,
|
email,
|
||||||
hashedCode: hashedVerificationCode
|
hashedCode: hashedVerificationCode,
|
||||||
});
|
});
|
||||||
|
|
||||||
// send the verification email
|
// send the verification email
|
||||||
await this.mailer.send({
|
await this.mailer.send({
|
||||||
to: email,
|
to: email,
|
||||||
template: new LoginVerificationEmail(verificationCode)
|
template: new LoginVerificationEmail(verificationCode),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -78,7 +100,7 @@ export class LoginRequestsService {
|
||||||
// send the welcome email
|
// send the welcome email
|
||||||
await this.mailer.send({
|
await this.mailer.send({
|
||||||
to: email,
|
to: email,
|
||||||
template: new WelcomeEmail()
|
template: new WelcomeEmail(),
|
||||||
});
|
});
|
||||||
|
|
||||||
// create a new session
|
// create a new session
|
||||||
|
|
|
||||||
21
src/lib/server/api/iam/login-requests/routes/login.routes.ts
Normal file
21
src/lib/server/api/iam/login-requests/routes/login.routes.ts
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
import { StatusCodes } from '$lib/utils/status-codes';
|
||||||
|
import { defineOpenApiOperation } from 'hono-zod-openapi';
|
||||||
|
import { createErrorSchema } from 'stoker/openapi/schemas';
|
||||||
|
import { loginRequestDto } from '../dtos/login-request.dto';
|
||||||
|
|
||||||
|
export const signInEmail = defineOpenApiOperation({
|
||||||
|
tags: ['Login'],
|
||||||
|
summary: 'Sign in with email',
|
||||||
|
description: 'Sign in with email',
|
||||||
|
responses: {
|
||||||
|
[StatusCodes.OK]: {
|
||||||
|
description: 'Sign in with username',
|
||||||
|
schema: loginRequestDto,
|
||||||
|
},
|
||||||
|
[StatusCodes.UNPROCESSABLE_ENTITY]: {
|
||||||
|
description: 'The validation error(s)',
|
||||||
|
schema: createErrorSchema(loginRequestDto),
|
||||||
|
mediaType: 'application/json',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
73
src/lib/server/api/users/credentials.repository.ts
Normal file
73
src/lib/server/api/users/credentials.repository.ts
Normal file
|
|
@ -0,0 +1,73 @@
|
||||||
|
import { CredentialsType, credentials_table } from './tables/credentials.table';
|
||||||
|
import { injectable } from '@needle-di/core';
|
||||||
|
import { and, eq, type InferSelectModel } from 'drizzle-orm';
|
||||||
|
import { takeFirstOrThrow } from '../common/utils/drizzle';
|
||||||
|
import { DrizzleRepository } from '../common/factories/drizzle-repository.factory';
|
||||||
|
|
||||||
|
/* -------------------------------------------------------------------------- */
|
||||||
|
/* Types */
|
||||||
|
/* -------------------------------------------------------------------------- */
|
||||||
|
type Create = Pick<InferSelectModel<typeof credentials_table>, 'user_id' | 'type' | 'secret_data'>;
|
||||||
|
type Update = Partial<Create>;
|
||||||
|
|
||||||
|
/* -------------------------------------------------------------------------- */
|
||||||
|
/* Repository */
|
||||||
|
/* -------------------------------------------------------------------------- */
|
||||||
|
@injectable()
|
||||||
|
export class CredentialsRepository extends DrizzleRepository {
|
||||||
|
async findOneByUserId(userId: string, db = this.drizzle.db) {
|
||||||
|
return db.query.credentials_table.findFirst({
|
||||||
|
where: eq(credentials_table.user_id, userId),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async findOneByUserIdAndType(userId: string, type: CredentialsType, db = this.drizzle.db) {
|
||||||
|
return db.query.credentials_table.findFirst({
|
||||||
|
where: and(eq(credentials_table.user_id, userId), eq(credentials_table.type, type)),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async findPasswordCredentialsByUserId(userId: string, db = this.drizzle.db) {
|
||||||
|
return db.query.credentials_table.findFirst({
|
||||||
|
where: and(eq(credentials_table.user_id, userId), eq(credentials_table.type, CredentialsType.PASSWORD)),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async findTOTPCredentialsByUserId(userId: string, db = this.drizzle.db) {
|
||||||
|
return db.query.credentials_table.findFirst({
|
||||||
|
where: and(eq(credentials_table.user_id, userId), eq(credentials_table.type, CredentialsType.TOTP)),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async findOneById(id: string, db = this.drizzle.db) {
|
||||||
|
return db.query.credentials_table.findFirst({
|
||||||
|
where: eq(credentials_table.id, id),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async findOneByIdOrThrow(id: string, db = this.drizzle.db) {
|
||||||
|
const credentials = await this.findOneById(id, db);
|
||||||
|
if (!credentials) throw Error('Credentials not found');
|
||||||
|
return credentials;
|
||||||
|
}
|
||||||
|
|
||||||
|
async create(data: Create, db = this.drizzle.db) {
|
||||||
|
return db.insert(credentials_table).values(data).returning().then(takeFirstOrThrow);
|
||||||
|
}
|
||||||
|
|
||||||
|
async update(id: string, data: Update, db = this.drizzle.db) {
|
||||||
|
return db.update(credentials_table).set(data).where(eq(credentials_table.id, id)).returning().then(takeFirstOrThrow);
|
||||||
|
}
|
||||||
|
|
||||||
|
async delete(id: string, db = this.drizzle.db) {
|
||||||
|
return db.delete(credentials_table).where(eq(credentials_table.id, id));
|
||||||
|
}
|
||||||
|
|
||||||
|
async deleteByUserId(userId: string, db = this.drizzle.db) {
|
||||||
|
return db.delete(credentials_table).where(eq(credentials_table.user_id, userId));
|
||||||
|
}
|
||||||
|
|
||||||
|
async deleteByUserIdAndType(userId: string, type: CredentialsType, db = this.drizzle.db) {
|
||||||
|
return db.delete(credentials_table).where(and(eq(credentials_table.user_id, userId), eq(credentials_table.type, type)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -6,6 +6,7 @@ import { TanstackQueryModule } from './query-module';
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
/* Types */
|
/* Types */
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
|
type RequestUsernamePasswordLogin = Api['iam']['login']['$post'];
|
||||||
type RequestLogin = Api['iam']['login']['request']['$post'];
|
type RequestLogin = Api['iam']['login']['request']['$post'];
|
||||||
type VerifyLogin = Api['iam']['login']['verify']['$post'];
|
type VerifyLogin = Api['iam']['login']['verify']['$post'];
|
||||||
type Logout = Api['iam']['logout']['$post'];
|
type Logout = Api['iam']['logout']['$post'];
|
||||||
|
|
@ -19,6 +20,12 @@ export class IamModule extends TanstackQueryModule<'iam'> {
|
||||||
mutationFn: async () => await this.api.iam.logout.$post().then(parseApiResponse)
|
mutationFn: async () => await this.api.iam.logout.$post().then(parseApiResponse)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
requestUsernamePasswordLogin(): ApiMutation<RequestUsernamePasswordLogin> {
|
||||||
|
return {
|
||||||
|
mutationFn: async (data: InferRequestType<RequestUsernamePasswordLogin>) =>
|
||||||
|
await this.api.iam.login.$post(data).then(parseApiResponse)
|
||||||
|
}
|
||||||
|
}
|
||||||
requestLogin(): ApiMutation<RequestLogin> {
|
requestLogin(): ApiMutation<RequestLogin> {
|
||||||
return {
|
return {
|
||||||
mutationFn: async (data: InferRequestType<RequestLogin>) =>
|
mutationFn: async (data: InferRequestType<RequestLogin>) =>
|
||||||
|
|
|
||||||
|
|
@ -2,9 +2,14 @@
|
||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
|
|
||||||
export const loginSchema = z.object({
|
export const loginSchema = z.object({
|
||||||
email: z.string().email()
|
email: z.string().email(),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const loginPasswordSchema = z.object({
|
||||||
|
email: z.string().email(),
|
||||||
|
password: z.string({ required_error: 'Password is required' }),
|
||||||
|
})
|
||||||
|
|
||||||
export const verifySchema = z.object({
|
export const verifySchema = z.object({
|
||||||
email: z.string().email(),
|
email: z.string().email(),
|
||||||
code: z.string().length(6)
|
code: z.string().length(6)
|
||||||
|
|
@ -27,13 +32,22 @@
|
||||||
const RESEND_VERIFICATION_CODE_COOLDOWN = 60;
|
const RESEND_VERIFICATION_CODE_COOLDOWN = 60;
|
||||||
|
|
||||||
let queryClient = useQueryClient();
|
let queryClient = useQueryClient();
|
||||||
let step = $state<'request' | 'verify'>('request');
|
let step = $state<'login' | 'request' | 'verify'>('request');
|
||||||
let countdownTimer = $state(RESEND_VERIFICATION_CODE_COOLDOWN);
|
let countdownTimer = $state(RESEND_VERIFICATION_CODE_COOLDOWN);
|
||||||
let resendVerificationCodeOnCooldown = $derived(
|
let resendVerificationCodeOnCooldown = $derived(
|
||||||
countdownTimer != RESEND_VERIFICATION_CODE_COOLDOWN
|
countdownTimer != RESEND_VERIFICATION_CODE_COOLDOWN
|
||||||
);
|
);
|
||||||
|
|
||||||
/* ----------------------------------- Api ---------------------------------- */
|
/* ----------------------------------- Api ---------------------------------- */
|
||||||
|
const requestUsernamePasswordLoginMutation = createMutation({
|
||||||
|
...queryHandler().iam.requestUsernamePasswordLogin(),
|
||||||
|
onSuccess(_data, variables, _context) {
|
||||||
|
step = 'verify';
|
||||||
|
$verifyForm.email = variables.json.email;
|
||||||
|
$verifyForm.
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
const requestMutation = createMutation({
|
const requestMutation = createMutation({
|
||||||
...queryHandler().iam.requestLogin(),
|
...queryHandler().iam.requestLogin(),
|
||||||
onSuccess(_data, variables, _context) {
|
onSuccess(_data, variables, _context) {
|
||||||
|
|
@ -58,6 +72,16 @@
|
||||||
});
|
});
|
||||||
|
|
||||||
/* ------------------------------- Login Form ------------------------------- */
|
/* ------------------------------- Login Form ------------------------------- */
|
||||||
|
const sf_login_username_password = superForm(defaults(zod(loginPasswordSchema)), {
|
||||||
|
resetForm: false,
|
||||||
|
SPA: true,
|
||||||
|
validators: zod(loginPasswordSchema),
|
||||||
|
async onUpdated(event) {
|
||||||
|
if (!event.form.valid) return;
|
||||||
|
await $requestUsernamePasswordLogin.mutateAsync({ json: event.form.data });
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
const sf_login = superForm(defaults(zod(loginSchema)), {
|
const sf_login = superForm(defaults(zod(loginSchema)), {
|
||||||
resetForm: false,
|
resetForm: false,
|
||||||
SPA: true,
|
SPA: true,
|
||||||
|
|
@ -78,6 +102,8 @@
|
||||||
$verifyForm.email = event.form.data.email;
|
$verifyForm.email = event.form.data.email;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
const { form: loginPasswordForm, enhance: loginPasswordEnhance, errors: loginPasswordErrors } = sf_login_username_password;
|
||||||
|
|
||||||
const { form: loginForm, enhance: loginEnhance, errors: requestErrors } = sf_login;
|
const { form: loginForm, enhance: loginEnhance, errors: requestErrors } = sf_login;
|
||||||
|
|
||||||
/* ------------------------------- Verify Form ------------------------------ */
|
/* ------------------------------- Verify Form ------------------------------ */
|
||||||
|
|
@ -118,14 +144,51 @@
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
{#if step === 'login'}
|
||||||
|
{@render loginCard()}
|
||||||
|
{/if}
|
||||||
{#if step === 'request'}
|
{#if step === 'request'}
|
||||||
{@render requetsCard()}
|
{@render requestsCard()}
|
||||||
{/if}
|
{/if}
|
||||||
{#if step === 'verify'}
|
{#if step === 'verify'}
|
||||||
{@render verifyCard()}
|
{@render verifyCard()}
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
{#snippet requetsCard()}
|
{#snippet loginCard()}
|
||||||
|
<Card.Root class="mx-auto w-full max-w-sm">
|
||||||
|
<Card.Header>
|
||||||
|
<Card.Title class="text-2xl">Login</Card.Title>
|
||||||
|
<Card.Description>Enter your email below to login to your account</Card.Description>
|
||||||
|
</Card.Header>
|
||||||
|
<Card.Content>
|
||||||
|
<form use:loginEnhance method="POST" class="grid gap-4">
|
||||||
|
<Form.Field form={sf_login_username_password} name="email">
|
||||||
|
<Form.Control>
|
||||||
|
{#snippet children({ props })}
|
||||||
|
<Form.Label>Email</Form.Label>
|
||||||
|
<Input {...props} bind:value={$loginPasswordForm.email} />
|
||||||
|
{/snippet}
|
||||||
|
</Form.Control>
|
||||||
|
<Form.Description />
|
||||||
|
<Form.FieldErrors />
|
||||||
|
</Form.Field>
|
||||||
|
<Form.Field form={sf_login_username_password} name="password">
|
||||||
|
<Form.Control>
|
||||||
|
{#snippet children({ props })}
|
||||||
|
<Form.Label>Password</Form.Label>
|
||||||
|
<Input type="password" {...props} bind:value={$loginPasswordForm.password} />
|
||||||
|
{/snippet}
|
||||||
|
</Form.Control>
|
||||||
|
<Form.Description />
|
||||||
|
<Form.FieldErrors />
|
||||||
|
</Form.Field>
|
||||||
|
<Button type="submit" class="w-full">Continue with Email</Button>
|
||||||
|
</form>
|
||||||
|
</Card.Content>
|
||||||
|
</Card.Root>
|
||||||
|
{/snippet}
|
||||||
|
|
||||||
|
{#snippet requestsCard()}
|
||||||
<Card.Root class="mx-auto w-full max-w-sm">
|
<Card.Root class="mx-auto w-full max-w-sm">
|
||||||
<Card.Header>
|
<Card.Header>
|
||||||
<Card.Title class="text-2xl">Login</Card.Title>
|
<Card.Title class="text-2xl">Login</Card.Title>
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue