mirror of https://github.com/halo-dev/halo
Refactor checkstyle (#1241)
* Refactor checkstyle.xml and add .editorconfig * Optimized imports * Rearrange codes * Fix check sytle error in source codes * Reformat test codes * Fix check style error in test codes * Config checkstyle plugin * Fix merge conflictspull/1242/head
parent
de5e968025
commit
feab7c4b5f
|
@ -0,0 +1,510 @@
|
|||
[*]
|
||||
charset = utf-8
|
||||
end_of_line = lf
|
||||
indent_size = 4
|
||||
indent_style = space
|
||||
insert_final_newline = false
|
||||
max_line_length = 120
|
||||
tab_width = 4
|
||||
ij_continuation_indent_size = 8
|
||||
ij_formatter_off_tag = @formatter:off
|
||||
ij_formatter_on_tag = @formatter:on
|
||||
ij_formatter_tags_enabled = false
|
||||
ij_smart_tabs = false
|
||||
ij_wrap_on_typing = false
|
||||
|
||||
[*.java]
|
||||
max_line_length = 100
|
||||
ij_continuation_indent_size = 4
|
||||
ij_java_align_consecutive_assignments = false
|
||||
ij_java_align_consecutive_variable_declarations = false
|
||||
ij_java_align_group_field_declarations = false
|
||||
ij_java_align_multiline_annotation_parameters = false
|
||||
ij_java_align_multiline_array_initializer_expression = false
|
||||
ij_java_align_multiline_assignment = false
|
||||
ij_java_align_multiline_binary_operation = false
|
||||
ij_java_align_multiline_chained_methods = false
|
||||
ij_java_align_multiline_extends_list = false
|
||||
ij_java_align_multiline_for = true
|
||||
ij_java_align_multiline_method_parentheses = false
|
||||
ij_java_align_multiline_parameters = false
|
||||
ij_java_align_multiline_parameters_in_calls = false
|
||||
ij_java_align_multiline_parenthesized_expression = false
|
||||
ij_java_align_multiline_records = true
|
||||
ij_java_align_multiline_resources = true
|
||||
ij_java_align_multiline_ternary_operation = false
|
||||
ij_java_align_multiline_text_blocks = false
|
||||
ij_java_align_multiline_throws_list = false
|
||||
ij_java_align_subsequent_simple_methods = false
|
||||
ij_java_align_throws_keyword = false
|
||||
ij_java_annotation_parameter_wrap = off
|
||||
ij_java_array_initializer_new_line_after_left_brace = false
|
||||
ij_java_array_initializer_right_brace_on_new_line = false
|
||||
ij_java_array_initializer_wrap = normal
|
||||
ij_java_assert_statement_colon_on_next_line = false
|
||||
ij_java_assert_statement_wrap = normal
|
||||
ij_java_assignment_wrap = normal
|
||||
ij_java_binary_operation_sign_on_next_line = false
|
||||
ij_java_binary_operation_wrap = normal
|
||||
ij_java_blank_lines_after_anonymous_class_header = 0
|
||||
ij_java_blank_lines_after_class_header = 0
|
||||
ij_java_blank_lines_after_imports = 1
|
||||
ij_java_blank_lines_after_package = 1
|
||||
ij_java_blank_lines_around_class = 1
|
||||
ij_java_blank_lines_around_field = 0
|
||||
ij_java_blank_lines_around_field_in_interface = 0
|
||||
ij_java_blank_lines_around_initializer = 1
|
||||
ij_java_blank_lines_around_method = 1
|
||||
ij_java_blank_lines_around_method_in_interface = 1
|
||||
ij_java_blank_lines_before_class_end = 0
|
||||
ij_java_blank_lines_before_imports = 0
|
||||
ij_java_blank_lines_before_method_body = 0
|
||||
ij_java_blank_lines_before_package = 1
|
||||
ij_java_block_brace_style = end_of_line
|
||||
ij_java_block_comment_at_first_column = false
|
||||
ij_java_call_parameters_new_line_after_left_paren = false
|
||||
ij_java_call_parameters_right_paren_on_new_line = false
|
||||
ij_java_call_parameters_wrap = normal
|
||||
ij_java_case_statement_on_separate_line = true
|
||||
ij_java_catch_on_new_line = false
|
||||
ij_java_class_annotation_wrap = split_into_lines
|
||||
ij_java_class_brace_style = end_of_line
|
||||
ij_java_class_count_to_use_import_on_demand = 999
|
||||
ij_java_class_names_in_javadoc = 1
|
||||
ij_java_do_not_indent_top_level_class_members = false
|
||||
ij_java_do_not_wrap_after_single_annotation = false
|
||||
ij_java_do_while_brace_force = always
|
||||
ij_java_doc_add_blank_line_after_description = true
|
||||
ij_java_doc_add_blank_line_after_param_comments = false
|
||||
ij_java_doc_add_blank_line_after_return = false
|
||||
ij_java_doc_add_p_tag_on_empty_lines = true
|
||||
ij_java_doc_align_exception_comments = true
|
||||
ij_java_doc_align_param_comments = false
|
||||
ij_java_doc_do_not_wrap_if_one_line = false
|
||||
ij_java_doc_enable_formatting = true
|
||||
ij_java_doc_enable_leading_asterisks = true
|
||||
ij_java_doc_indent_on_continuation = false
|
||||
ij_java_doc_keep_empty_lines = true
|
||||
ij_java_doc_keep_empty_parameter_tag = true
|
||||
ij_java_doc_keep_empty_return_tag = true
|
||||
ij_java_doc_keep_empty_throws_tag = true
|
||||
ij_java_doc_keep_invalid_tags = true
|
||||
ij_java_doc_param_description_on_new_line = false
|
||||
ij_java_doc_preserve_line_breaks = false
|
||||
ij_java_doc_use_throws_not_exception_tag = true
|
||||
ij_java_else_on_new_line = false
|
||||
ij_java_enum_constants_wrap = normal
|
||||
ij_java_extends_keyword_wrap = normal
|
||||
ij_java_extends_list_wrap = normal
|
||||
ij_java_field_annotation_wrap = split_into_lines
|
||||
ij_java_finally_on_new_line = false
|
||||
ij_java_for_brace_force = always
|
||||
ij_java_for_statement_new_line_after_left_paren = false
|
||||
ij_java_for_statement_right_paren_on_new_line = false
|
||||
ij_java_for_statement_wrap = normal
|
||||
ij_java_generate_final_locals = false
|
||||
ij_java_generate_final_parameters = false
|
||||
ij_java_if_brace_force = always
|
||||
ij_java_imports_layout = $*, |, *, |, *
|
||||
ij_java_indent_case_from_switch = true
|
||||
ij_java_insert_inner_class_imports = false
|
||||
ij_java_insert_override_annotation = true
|
||||
ij_java_keep_blank_lines_before_right_brace = 2
|
||||
ij_java_keep_blank_lines_between_package_declaration_and_header = 2
|
||||
ij_java_keep_blank_lines_in_code = 2
|
||||
ij_java_keep_blank_lines_in_declarations = 2
|
||||
ij_java_keep_control_statement_in_one_line = true
|
||||
ij_java_keep_first_column_comment = true
|
||||
ij_java_keep_indents_on_empty_lines = false
|
||||
ij_java_keep_line_breaks = true
|
||||
ij_java_keep_multiple_expressions_in_one_line = false
|
||||
ij_java_keep_simple_blocks_in_one_line = false
|
||||
ij_java_keep_simple_classes_in_one_line = false
|
||||
ij_java_keep_simple_lambdas_in_one_line = false
|
||||
ij_java_keep_simple_methods_in_one_line = false
|
||||
ij_java_label_indent_absolute = false
|
||||
ij_java_label_indent_size = 0
|
||||
ij_java_lambda_brace_style = end_of_line
|
||||
ij_java_layout_static_imports_separately = true
|
||||
ij_java_line_comment_add_space = true
|
||||
ij_java_line_comment_at_first_column = false
|
||||
ij_java_method_annotation_wrap = split_into_lines
|
||||
ij_java_method_brace_style = end_of_line
|
||||
ij_java_method_call_chain_wrap = normal
|
||||
ij_java_method_parameters_new_line_after_left_paren = false
|
||||
ij_java_method_parameters_right_paren_on_new_line = false
|
||||
ij_java_method_parameters_wrap = normal
|
||||
ij_java_modifier_list_wrap = false
|
||||
ij_java_names_count_to_use_import_on_demand = 999
|
||||
ij_java_new_line_after_lparen_in_record_header = false
|
||||
ij_java_parameter_annotation_wrap = normal
|
||||
ij_java_parentheses_expression_new_line_after_left_paren = false
|
||||
ij_java_parentheses_expression_right_paren_on_new_line = false
|
||||
ij_java_place_assignment_sign_on_next_line = false
|
||||
ij_java_prefer_longer_names = true
|
||||
ij_java_prefer_parameters_wrap = false
|
||||
ij_java_record_components_wrap = normal
|
||||
ij_java_repeat_synchronized = true
|
||||
ij_java_replace_instanceof_and_cast = false
|
||||
ij_java_replace_null_check = true
|
||||
ij_java_replace_sum_lambda_with_method_ref = true
|
||||
ij_java_resource_list_new_line_after_left_paren = false
|
||||
ij_java_resource_list_right_paren_on_new_line = false
|
||||
ij_java_resource_list_wrap = normal
|
||||
ij_java_rparen_on_new_line_in_record_header = false
|
||||
ij_java_space_after_closing_angle_bracket_in_type_argument = false
|
||||
ij_java_space_after_colon = true
|
||||
ij_java_space_after_comma = true
|
||||
ij_java_space_after_comma_in_type_arguments = true
|
||||
ij_java_space_after_for_semicolon = true
|
||||
ij_java_space_after_quest = true
|
||||
ij_java_space_after_type_cast = true
|
||||
ij_java_space_before_annotation_array_initializer_left_brace = false
|
||||
ij_java_space_before_annotation_parameter_list = false
|
||||
ij_java_space_before_array_initializer_left_brace = true
|
||||
ij_java_space_before_catch_keyword = true
|
||||
ij_java_space_before_catch_left_brace = true
|
||||
ij_java_space_before_catch_parentheses = true
|
||||
ij_java_space_before_class_left_brace = true
|
||||
ij_java_space_before_colon = true
|
||||
ij_java_space_before_colon_in_foreach = true
|
||||
ij_java_space_before_comma = false
|
||||
ij_java_space_before_do_left_brace = true
|
||||
ij_java_space_before_else_keyword = true
|
||||
ij_java_space_before_else_left_brace = true
|
||||
ij_java_space_before_finally_keyword = true
|
||||
ij_java_space_before_finally_left_brace = true
|
||||
ij_java_space_before_for_left_brace = true
|
||||
ij_java_space_before_for_parentheses = true
|
||||
ij_java_space_before_for_semicolon = false
|
||||
ij_java_space_before_if_left_brace = true
|
||||
ij_java_space_before_if_parentheses = true
|
||||
ij_java_space_before_method_call_parentheses = false
|
||||
ij_java_space_before_method_left_brace = true
|
||||
ij_java_space_before_method_parentheses = false
|
||||
ij_java_space_before_opening_angle_bracket_in_type_parameter = false
|
||||
ij_java_space_before_quest = true
|
||||
ij_java_space_before_switch_left_brace = true
|
||||
ij_java_space_before_switch_parentheses = true
|
||||
ij_java_space_before_synchronized_left_brace = true
|
||||
ij_java_space_before_synchronized_parentheses = true
|
||||
ij_java_space_before_try_left_brace = true
|
||||
ij_java_space_before_try_parentheses = true
|
||||
ij_java_space_before_type_parameter_list = false
|
||||
ij_java_space_before_while_keyword = true
|
||||
ij_java_space_before_while_left_brace = true
|
||||
ij_java_space_before_while_parentheses = true
|
||||
ij_java_space_inside_one_line_enum_braces = false
|
||||
ij_java_space_within_empty_array_initializer_braces = false
|
||||
ij_java_space_within_empty_method_call_parentheses = false
|
||||
ij_java_space_within_empty_method_parentheses = false
|
||||
ij_java_spaces_around_additive_operators = true
|
||||
ij_java_spaces_around_assignment_operators = true
|
||||
ij_java_spaces_around_bitwise_operators = true
|
||||
ij_java_spaces_around_equality_operators = true
|
||||
ij_java_spaces_around_lambda_arrow = true
|
||||
ij_java_spaces_around_logical_operators = true
|
||||
ij_java_spaces_around_method_ref_dbl_colon = false
|
||||
ij_java_spaces_around_multiplicative_operators = true
|
||||
ij_java_spaces_around_relational_operators = true
|
||||
ij_java_spaces_around_shift_operators = true
|
||||
ij_java_spaces_around_type_bounds_in_type_parameters = true
|
||||
ij_java_spaces_around_unary_operator = false
|
||||
ij_java_spaces_within_angle_brackets = false
|
||||
ij_java_spaces_within_annotation_parentheses = false
|
||||
ij_java_spaces_within_array_initializer_braces = false
|
||||
ij_java_spaces_within_braces = false
|
||||
ij_java_spaces_within_brackets = false
|
||||
ij_java_spaces_within_cast_parentheses = false
|
||||
ij_java_spaces_within_catch_parentheses = false
|
||||
ij_java_spaces_within_for_parentheses = false
|
||||
ij_java_spaces_within_if_parentheses = false
|
||||
ij_java_spaces_within_method_call_parentheses = false
|
||||
ij_java_spaces_within_method_parentheses = false
|
||||
ij_java_spaces_within_parentheses = false
|
||||
ij_java_spaces_within_switch_parentheses = false
|
||||
ij_java_spaces_within_synchronized_parentheses = false
|
||||
ij_java_spaces_within_try_parentheses = false
|
||||
ij_java_spaces_within_while_parentheses = false
|
||||
ij_java_special_else_if_treatment = true
|
||||
ij_java_subclass_name_suffix = Impl
|
||||
ij_java_ternary_operation_signs_on_next_line = false
|
||||
ij_java_ternary_operation_wrap = normal
|
||||
ij_java_test_name_suffix = Test
|
||||
ij_java_throws_keyword_wrap = normal
|
||||
ij_java_throws_list_wrap = normal
|
||||
ij_java_use_external_annotations = false
|
||||
ij_java_use_fq_class_names = false
|
||||
ij_java_use_relative_indents = false
|
||||
ij_java_use_single_class_imports = true
|
||||
ij_java_variable_annotation_wrap = normal
|
||||
ij_java_visibility = public
|
||||
ij_java_while_brace_force = always
|
||||
ij_java_while_on_new_line = false
|
||||
ij_java_wrap_comments = false
|
||||
ij_java_wrap_first_method_in_call_chain = false
|
||||
ij_java_wrap_long_lines = true
|
||||
|
||||
[*.properties]
|
||||
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
|
||||
|
||||
[.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, *.jspx, *.pom, *.rng, *.tagx, *.tld, *.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_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
|
||||
|
||||
[{*.bash, *.sh, *.zsh}]
|
||||
indent_size = 2
|
||||
tab_width = 2
|
||||
ij_shell_binary_ops_start_line = false
|
||||
ij_shell_keep_column_alignment_padding = false
|
||||
ij_shell_minify_program = false
|
||||
ij_shell_redirect_followed_by_space = false
|
||||
ij_shell_switch_cases_indented = false
|
||||
|
||||
[{*.gant, *.gradle, *.groovy, *.gy}]
|
||||
ij_groovy_align_group_field_declarations = false
|
||||
ij_groovy_align_multiline_array_initializer_expression = false
|
||||
ij_groovy_align_multiline_assignment = false
|
||||
ij_groovy_align_multiline_binary_operation = false
|
||||
ij_groovy_align_multiline_chained_methods = false
|
||||
ij_groovy_align_multiline_extends_list = false
|
||||
ij_groovy_align_multiline_for = true
|
||||
ij_groovy_align_multiline_list_or_map = true
|
||||
ij_groovy_align_multiline_method_parentheses = false
|
||||
ij_groovy_align_multiline_parameters = true
|
||||
ij_groovy_align_multiline_parameters_in_calls = false
|
||||
ij_groovy_align_multiline_resources = true
|
||||
ij_groovy_align_multiline_ternary_operation = false
|
||||
ij_groovy_align_multiline_throws_list = false
|
||||
ij_groovy_align_named_args_in_map = true
|
||||
ij_groovy_align_throws_keyword = false
|
||||
ij_groovy_array_initializer_new_line_after_left_brace = false
|
||||
ij_groovy_array_initializer_right_brace_on_new_line = false
|
||||
ij_groovy_array_initializer_wrap = off
|
||||
ij_groovy_assert_statement_wrap = off
|
||||
ij_groovy_assignment_wrap = off
|
||||
ij_groovy_binary_operation_wrap = off
|
||||
ij_groovy_blank_lines_after_class_header = 0
|
||||
ij_groovy_blank_lines_after_imports = 1
|
||||
ij_groovy_blank_lines_after_package = 1
|
||||
ij_groovy_blank_lines_around_class = 1
|
||||
ij_groovy_blank_lines_around_field = 0
|
||||
ij_groovy_blank_lines_around_field_in_interface = 0
|
||||
ij_groovy_blank_lines_around_method = 1
|
||||
ij_groovy_blank_lines_around_method_in_interface = 1
|
||||
ij_groovy_blank_lines_before_imports = 1
|
||||
ij_groovy_blank_lines_before_method_body = 0
|
||||
ij_groovy_blank_lines_before_package = 0
|
||||
ij_groovy_block_brace_style = end_of_line
|
||||
ij_groovy_block_comment_at_first_column = true
|
||||
ij_groovy_call_parameters_new_line_after_left_paren = false
|
||||
ij_groovy_call_parameters_right_paren_on_new_line = false
|
||||
ij_groovy_call_parameters_wrap = off
|
||||
ij_groovy_catch_on_new_line = false
|
||||
ij_groovy_class_annotation_wrap = split_into_lines
|
||||
ij_groovy_class_brace_style = end_of_line
|
||||
ij_groovy_class_count_to_use_import_on_demand = 5
|
||||
ij_groovy_do_while_brace_force = never
|
||||
ij_groovy_else_on_new_line = false
|
||||
ij_groovy_enum_constants_wrap = off
|
||||
ij_groovy_extends_keyword_wrap = off
|
||||
ij_groovy_extends_list_wrap = off
|
||||
ij_groovy_field_annotation_wrap = split_into_lines
|
||||
ij_groovy_finally_on_new_line = false
|
||||
ij_groovy_for_brace_force = never
|
||||
ij_groovy_for_statement_new_line_after_left_paren = false
|
||||
ij_groovy_for_statement_right_paren_on_new_line = false
|
||||
ij_groovy_for_statement_wrap = off
|
||||
ij_groovy_if_brace_force = never
|
||||
ij_groovy_import_annotation_wrap = 2
|
||||
ij_groovy_indent_case_from_switch = true
|
||||
ij_groovy_indent_label_blocks = true
|
||||
ij_groovy_insert_inner_class_imports = false
|
||||
ij_groovy_keep_blank_lines_before_right_brace = 2
|
||||
ij_groovy_keep_blank_lines_in_code = 2
|
||||
ij_groovy_keep_blank_lines_in_declarations = 2
|
||||
ij_groovy_keep_control_statement_in_one_line = true
|
||||
ij_groovy_keep_first_column_comment = true
|
||||
ij_groovy_keep_indents_on_empty_lines = false
|
||||
ij_groovy_keep_line_breaks = true
|
||||
ij_groovy_keep_multiple_expressions_in_one_line = false
|
||||
ij_groovy_keep_simple_blocks_in_one_line = false
|
||||
ij_groovy_keep_simple_classes_in_one_line = true
|
||||
ij_groovy_keep_simple_lambdas_in_one_line = true
|
||||
ij_groovy_keep_simple_methods_in_one_line = true
|
||||
ij_groovy_label_indent_absolute = false
|
||||
ij_groovy_label_indent_size = 0
|
||||
ij_groovy_lambda_brace_style = end_of_line
|
||||
ij_groovy_layout_static_imports_separately = true
|
||||
ij_groovy_line_comment_add_space = false
|
||||
ij_groovy_line_comment_at_first_column = true
|
||||
ij_groovy_method_annotation_wrap = split_into_lines
|
||||
ij_groovy_method_brace_style = end_of_line
|
||||
ij_groovy_method_call_chain_wrap = off
|
||||
ij_groovy_method_parameters_new_line_after_left_paren = false
|
||||
ij_groovy_method_parameters_right_paren_on_new_line = false
|
||||
ij_groovy_method_parameters_wrap = off
|
||||
ij_groovy_modifier_list_wrap = false
|
||||
ij_groovy_names_count_to_use_import_on_demand = 3
|
||||
ij_groovy_parameter_annotation_wrap = off
|
||||
ij_groovy_parentheses_expression_new_line_after_left_paren = false
|
||||
ij_groovy_parentheses_expression_right_paren_on_new_line = false
|
||||
ij_groovy_prefer_parameters_wrap = false
|
||||
ij_groovy_resource_list_new_line_after_left_paren = false
|
||||
ij_groovy_resource_list_right_paren_on_new_line = false
|
||||
ij_groovy_resource_list_wrap = off
|
||||
ij_groovy_space_after_assert_separator = true
|
||||
ij_groovy_space_after_colon = true
|
||||
ij_groovy_space_after_comma = true
|
||||
ij_groovy_space_after_comma_in_type_arguments = true
|
||||
ij_groovy_space_after_for_semicolon = true
|
||||
ij_groovy_space_after_quest = true
|
||||
ij_groovy_space_after_type_cast = true
|
||||
ij_groovy_space_before_annotation_parameter_list = false
|
||||
ij_groovy_space_before_array_initializer_left_brace = false
|
||||
ij_groovy_space_before_assert_separator = false
|
||||
ij_groovy_space_before_catch_keyword = true
|
||||
ij_groovy_space_before_catch_left_brace = true
|
||||
ij_groovy_space_before_catch_parentheses = true
|
||||
ij_groovy_space_before_class_left_brace = true
|
||||
ij_groovy_space_before_closure_left_brace = true
|
||||
ij_groovy_space_before_colon = true
|
||||
ij_groovy_space_before_comma = false
|
||||
ij_groovy_space_before_do_left_brace = true
|
||||
ij_groovy_space_before_else_keyword = true
|
||||
ij_groovy_space_before_else_left_brace = true
|
||||
ij_groovy_space_before_finally_keyword = true
|
||||
ij_groovy_space_before_finally_left_brace = true
|
||||
ij_groovy_space_before_for_left_brace = true
|
||||
ij_groovy_space_before_for_parentheses = true
|
||||
ij_groovy_space_before_for_semicolon = false
|
||||
ij_groovy_space_before_if_left_brace = true
|
||||
ij_groovy_space_before_if_parentheses = true
|
||||
ij_groovy_space_before_method_call_parentheses = false
|
||||
ij_groovy_space_before_method_left_brace = true
|
||||
ij_groovy_space_before_method_parentheses = false
|
||||
ij_groovy_space_before_quest = true
|
||||
ij_groovy_space_before_switch_left_brace = true
|
||||
ij_groovy_space_before_switch_parentheses = true
|
||||
ij_groovy_space_before_synchronized_left_brace = true
|
||||
ij_groovy_space_before_synchronized_parentheses = true
|
||||
ij_groovy_space_before_try_left_brace = true
|
||||
ij_groovy_space_before_try_parentheses = true
|
||||
ij_groovy_space_before_while_keyword = true
|
||||
ij_groovy_space_before_while_left_brace = true
|
||||
ij_groovy_space_before_while_parentheses = true
|
||||
ij_groovy_space_in_named_argument = true
|
||||
ij_groovy_space_in_named_argument_before_colon = false
|
||||
ij_groovy_space_within_empty_array_initializer_braces = false
|
||||
ij_groovy_space_within_empty_method_call_parentheses = false
|
||||
ij_groovy_spaces_around_additive_operators = true
|
||||
ij_groovy_spaces_around_assignment_operators = true
|
||||
ij_groovy_spaces_around_bitwise_operators = true
|
||||
ij_groovy_spaces_around_equality_operators = true
|
||||
ij_groovy_spaces_around_lambda_arrow = true
|
||||
ij_groovy_spaces_around_logical_operators = true
|
||||
ij_groovy_spaces_around_multiplicative_operators = true
|
||||
ij_groovy_spaces_around_regex_operators = true
|
||||
ij_groovy_spaces_around_relational_operators = true
|
||||
ij_groovy_spaces_around_shift_operators = true
|
||||
ij_groovy_spaces_within_annotation_parentheses = false
|
||||
ij_groovy_spaces_within_array_initializer_braces = false
|
||||
ij_groovy_spaces_within_braces = true
|
||||
ij_groovy_spaces_within_brackets = false
|
||||
ij_groovy_spaces_within_cast_parentheses = false
|
||||
ij_groovy_spaces_within_catch_parentheses = false
|
||||
ij_groovy_spaces_within_for_parentheses = false
|
||||
ij_groovy_spaces_within_gstring_injection_braces = false
|
||||
ij_groovy_spaces_within_if_parentheses = false
|
||||
ij_groovy_spaces_within_list_or_map = false
|
||||
ij_groovy_spaces_within_method_call_parentheses = false
|
||||
ij_groovy_spaces_within_method_parentheses = false
|
||||
ij_groovy_spaces_within_parentheses = false
|
||||
ij_groovy_spaces_within_switch_parentheses = false
|
||||
ij_groovy_spaces_within_synchronized_parentheses = false
|
||||
ij_groovy_spaces_within_try_parentheses = false
|
||||
ij_groovy_spaces_within_tuple_expression = false
|
||||
ij_groovy_spaces_within_while_parentheses = false
|
||||
ij_groovy_special_else_if_treatment = true
|
||||
ij_groovy_ternary_operation_wrap = off
|
||||
ij_groovy_throws_keyword_wrap = off
|
||||
ij_groovy_throws_list_wrap = off
|
||||
ij_groovy_use_flying_geese_braces = false
|
||||
ij_groovy_use_fq_class_names = false
|
||||
ij_groovy_use_fq_class_names_in_javadoc = true
|
||||
ij_groovy_use_relative_indents = false
|
||||
ij_groovy_use_single_class_imports = true
|
||||
ij_groovy_variable_annotation_wrap = off
|
||||
ij_groovy_while_brace_force = never
|
||||
ij_groovy_while_on_new_line = false
|
||||
ij_groovy_wrap_long_lines = false
|
||||
|
||||
[{*.har, *.json}]
|
||||
indent_size = 2
|
||||
ij_json_keep_blank_lines_in_code = 0
|
||||
ij_json_keep_indents_on_empty_lines = false
|
||||
ij_json_keep_line_breaks = true
|
||||
ij_json_space_after_colon = true
|
||||
ij_json_space_after_comma = true
|
||||
ij_json_space_before_colon = true
|
||||
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, *.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_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
|
||||
|
||||
[{*.yaml, *.yml}]
|
||||
indent_size = 2
|
||||
ij_yaml_keep_indents_on_empty_lines = false
|
||||
ij_yaml_keep_line_breaks = true
|
|
@ -5,4 +5,4 @@ patreon: halo_dev
|
|||
open_collective: # Replace with a single Open Collective username
|
||||
ko_fi: # Replace with a single Ko-fi username
|
||||
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
|
||||
custom: ['https://afdian.net/@halo-dev','https://sponsor.halo.run']
|
||||
custom: [ 'https://afdian.net/@halo-dev','https://sponsor.halo.run' ]
|
||||
|
|
151
CHANGELOG.md
151
CHANGELOG.md
|
@ -247,6 +247,7 @@
|
|||
# 1.2.0
|
||||
|
||||
## Feature
|
||||
|
||||
- 支持自定义后台管理页面的地址,详细操作参见下方注意事项。
|
||||
- 图库支持分页查询。#361
|
||||
- 支持博客备份。
|
||||
|
@ -264,9 +265,11 @@
|
|||
- 自定义页面支持设置摘要。
|
||||
|
||||
## Change
|
||||
|
||||
- 移除 CDN 加速的设置选项。
|
||||
|
||||
## Fixed
|
||||
|
||||
- 修复文章路径包含特殊字符时,访问文章 404 的问题。
|
||||
- 修复文章路径包含中文时,预览地址不正确的问题。
|
||||
- 修复上传 ico 后缀文件错误的问题。
|
||||
|
@ -279,7 +282,8 @@
|
|||
## 其他
|
||||
|
||||
### 升级注意
|
||||
1. 如果你之前更新过 `1.2.0-beta.x`,更新到此版本需要先去数据库清空 `flyway_schema_history` 表,然后再进行升级操作。
|
||||
|
||||
1. 如果你之前更新过 `1.2.0-beta.x`,更新到此版本需要先去数据库清空 `flyway_schema_history` 表,然后再进行升级操作。
|
||||
2. 更新完毕后请在关于 Halo 页面查看版本号,如 Admin 版本不是最新,请手动点击右上角更新 Admin。
|
||||
3. 如果有使用 CDN 全站加速,请更新完毕后,刷新全站缓存,并清空浏览器缓存。
|
||||
4. 如果 Github 中的安装包下载太慢,请到 <https://dl.halo.run> 下载。
|
||||
|
@ -337,16 +341,21 @@ halo:
|
|||
第二步,点击 `设置`,关闭开发者选项的按钮并保存。
|
||||
|
||||
# 1.1.1
|
||||
|
||||
## New features
|
||||
|
||||
- 支持友情链接排序。@mrdong916
|
||||
|
||||
## Fixed
|
||||
|
||||
- 修复安全漏洞。#311
|
||||
|
||||
# 1.1.0
|
||||
|
||||
## New features
|
||||
- 编辑器支持图片上传功能,包括截图粘贴上传(可以把刀拿开了么?🌚)。 @guqing
|
||||
- 文章编辑支持自定义发布时间(刀拿开了么?🌚)。@guqing
|
||||
|
||||
- 编辑器支持图片上传功能,包括截图粘贴上传(可以把刀拿开了么?🌚)。 @guqing
|
||||
- 文章编辑支持自定义发布时间(刀拿开了么?🌚)。@guqing
|
||||
- 支持选择分类或者页面添加到菜单。
|
||||
- 新增百度云 BOS 云存储。@secondarycoder
|
||||
- 新增腾讯云 COS 云存储。@secondarycoder
|
||||
|
@ -370,35 +379,42 @@ halo:
|
|||
- 支持文章加密,即私密文章。
|
||||
|
||||
## Changes
|
||||
|
||||
- 文章列表改为从创建时间排序。
|
||||
- 从附件库选择或复制附件链接进行编码处理,否则可能会导致附件访问不到的情况。
|
||||
- 编辑器从 [mavonEditor](https://github.com/hinesboy/mavonEditor) 改为 [halo-editor](https://github.com/halo-dev/halo-editor),基于 mavonEditor 开发,非常感谢 @hinesboy 做出的贡献。
|
||||
- 编辑器从 [mavonEditor](https://github.com/hinesboy/mavonEditor)
|
||||
改为 [halo-editor](https://github.com/halo-dev/halo-editor),基于 mavonEditor 开发,非常感谢 @hinesboy 做出的贡献。
|
||||
- 抽离 PostSetting 组件,解决打开掉帧的问题。
|
||||
- 废弃自动保存文章的功能,由于该功能导致了大量的性能消耗,且可能会导致很多错误,所以暂时废弃。代替方案为:支持 Ctrl+S(windows or linux),Command+S(macOS)快捷键保存为草稿,以防止正在编辑的文章被丢失。
|
||||
- 废弃自动保存文章的功能,由于该功能导致了大量的性能消耗,且可能会导致很多错误,所以暂时废弃。代替方案为:支持 Ctrl+S(windows or linux),Command+S(macOS)
|
||||
快捷键保存为草稿,以防止正在编辑的文章被丢失。
|
||||
- 后台发表文章之后跳转到文章列表。
|
||||
- 重构上传组件,支持设定同时上传数与同时并行上传数,减少出错率。
|
||||
- 重构附件上传生成缩略图的代码,修复内存占用导致的异常。@JohnNiang
|
||||
- 重构附件上传生成缩略图的代码,修复内存占用导致的异常。@JohnNiang
|
||||
- 优化后台部分 UI。
|
||||
|
||||
## Fixed
|
||||
|
||||
- 修复文章选择缩略图显示异常的问题(没有处理路径转码)。
|
||||
- 修复第一次安装报【该博客还没初始化】的错误提示。
|
||||
- 修复文章选择缩略图显示异常的问题。
|
||||
- 修复多级菜单删除父菜单,会导致子菜单无法显示的问题。
|
||||
- 修复删除又拍云附件失败的问题。@Darkcolth
|
||||
- 修复迁移服务器之后不会恢复默认主题的问题。@jinqilin721
|
||||
- 修复文章路径中包含 & 字符会导致站点地图出现错误。 #264 @JohnNiang
|
||||
- 修复文章路径中包含 & 字符会导致站点地图出现错误。 #264 @JohnNiang
|
||||
- 修复编辑主题模板的报错。
|
||||
- 修复文章路径带英文逗号不能访问的问题。#280
|
||||
- 修复文章标签和分类无法修改的问题。#279
|
||||
|
||||
## 升级注意
|
||||
|
||||
- 因为支持了更好的设置选项组件,请在更新 Halo 之后,同时更新主题。
|
||||
- 更新完毕后请在关于 Halo 页面查看版本号,是否都为 1.1.0,如 Admin 版本有异常,请手动点击右上角更新 Admin。
|
||||
- 如果有使用 CDN 全站加速,请更新完毕后,刷新全站缓存。
|
||||
|
||||
# 1.1.0-beta.3
|
||||
|
||||
## New features
|
||||
|
||||
- 后台新增首屏加载动画。
|
||||
- 后台布局补充更多选项。
|
||||
- 支持在后台登录页重置密码,呼出方式:SHIFT+ALT+H。#208
|
||||
|
@ -407,30 +423,40 @@ halo:
|
|||
- 支持文章加密,即私密文章。
|
||||
|
||||
## Changes
|
||||
|
||||
- 后台文章发表之后跳转到文章列表。
|
||||
|
||||
## Fixed
|
||||
|
||||
- 修复日志管理的部分问题。
|
||||
- 修复文章路径带英文逗号不能访问的问题。#280
|
||||
- 修复文章标签和分类无法修改的问题。#279
|
||||
- 修复 Docker 的构建问题。
|
||||
|
||||
# 1.1.0-beta.2
|
||||
|
||||
## New features
|
||||
|
||||
- 文章设置支持设置首页文章排序规则。
|
||||
- 支持设置文章置顶。
|
||||
- 主题设置支持 预览模式,实现边设置边预览(仅对当前激活的主题有效)。
|
||||
- 编辑主题支持选择主题进行编辑。
|
||||
|
||||
## Changes
|
||||
|
||||
- 移除无用代码和依赖,优化打包体积。
|
||||
- 优化文章列表的评论数和点击量的样式。
|
||||
|
||||
## Fixed
|
||||
|
||||
- 修复编辑主题模板的报错。
|
||||
|
||||
# 1.1.0-beta.1
|
||||
|
||||
## New features
|
||||
- 编辑器支持图片上传功能,包括截图粘贴上传(可以把刀拿开了么?🌚)。 @guqing
|
||||
- 文章编辑支持自定义发布时间(刀拿开了么?🌚)。@guqing
|
||||
|
||||
- 编辑器支持图片上传功能,包括截图粘贴上传(可以把刀拿开了么?🌚)。 @guqing
|
||||
- 文章编辑支持自定义发布时间(刀拿开了么?🌚)。@guqing
|
||||
- 支持选择分类或者页面添加到菜单。
|
||||
- 新增百度云 BOS 云存储。@secondarycoder
|
||||
- 新增腾讯云 COS 云存储。@secondarycoder
|
||||
|
@ -444,23 +470,29 @@ halo:
|
|||
- 支持菜单分组,即支持多菜单。
|
||||
|
||||
## Changes
|
||||
|
||||
- 文章列表改为从创建时间排序。
|
||||
- 从附件库选择或复制附件链接进行编码处理,否则可能会导致附件访问不到的情况。
|
||||
- 编辑器从 [mavonEditor](https://github.com/hinesboy/mavonEditor) 改为 [halo-editor](https://github.com/halo-dev/halo-editor),基于 mavonEditor 开发,非常感谢 @hinesboy 做出的贡献。
|
||||
- 编辑器从 [mavonEditor](https://github.com/hinesboy/mavonEditor)
|
||||
改为 [halo-editor](https://github.com/halo-dev/halo-editor),基于 mavonEditor 开发,非常感谢 @hinesboy 做出的贡献。
|
||||
- 抽离 PostSetting 组件,解决打开掉帧的问题。
|
||||
- 废弃自动保存文章的功能,由于该功能导致了大量的性能消耗,且可能会导致很多错误,所以暂时废弃。代替方案为:支持 Ctrl+S(windows or linux),Command+S(macOS)快捷键保存为草稿,以防止正在编辑的文章被丢失。
|
||||
- 废弃自动保存文章的功能,由于该功能导致了大量的性能消耗,且可能会导致很多错误,所以暂时废弃。代替方案为:支持 Ctrl+S(windows or linux),Command+S(macOS)
|
||||
快捷键保存为草稿,以防止正在编辑的文章被丢失。
|
||||
|
||||
## Fixed
|
||||
|
||||
- 修复文章选择缩略图显示异常的问题(没有处理路径转码)。
|
||||
- 修复第一次安装报【该博客还没初始化】的错误提示。
|
||||
- 修复文章选择缩略图显示异常的问题。
|
||||
- 修复多级菜单删除父菜单,会导致子菜单无法显示的问题。
|
||||
- 修复删除又拍云附件失败的问题。@Darkcolth
|
||||
- 修复迁移服务器之后不会恢复默认主题的问题。@jinqilin721
|
||||
- 修复文章路径中包含 & 字符会导致站点地图出现错误。 #264 @JohnNiang
|
||||
- 修复文章路径中包含 & 字符会导致站点地图出现错误。 #264 @JohnNiang
|
||||
|
||||
# 1.0.3
|
||||
|
||||
## New features
|
||||
|
||||
- 首次安装自动设置头像为 [Gravatar](http://cn.gravatar.com) 头像。
|
||||
- 主题列表默认将已启用的主题放在第一位。
|
||||
- 关于页面支持复制环境信息。
|
||||
|
@ -474,12 +506,15 @@ halo:
|
|||
- 支持映射自定义静态资源,需要手动在 `~/.halo/static` 中添加文件。
|
||||
|
||||
## Changes
|
||||
|
||||
- 修改拼写错误,Gavatar -> Gravatar
|
||||
- 将文章默认标题改为时间戳。@johnniang
|
||||
- 移除站点验证的设置选项(百度,Google,360,必应的站点验证)。
|
||||
- 更换 Markdown 解析器 [commonmark-java](https://github.com/atlassian/commonmark-java) 为 [flexmark](https://github.com/vsch/flexmark-java)。
|
||||
- 更换 Markdown 解析器 [commonmark-java](https://github.com/atlassian/commonmark-java)
|
||||
为 [flexmark](https://github.com/vsch/flexmark-java)。
|
||||
|
||||
## Fixed
|
||||
|
||||
- 修复附件链接包含中文时,图片无法正常显示的问题。
|
||||
- 修复回复页面的评论会失败的问题。
|
||||
- 修复页面评论列表的标题列无法显示的问题。@johnniang
|
||||
|
@ -490,6 +525,7 @@ halo:
|
|||
- 修复评论模块头像显示不正常的问题,需要同时更新主题。
|
||||
|
||||
## 升级注意
|
||||
|
||||
- 由于此次更新删除了百度,Google,360,必应的站点验证设置选项,所以更新前请备份你之前的设置,更新之后你可以在博客设置中的其他设置里面,将原先的内容放在自定义 head 中。
|
||||
- 此次更新修改了 Gravatar 的拼写错误,更新之后请重新在博客设置里面设置默认头像。
|
||||
- 请在更新 Halo 之后,同时更新主题。
|
||||
|
@ -497,30 +533,38 @@ halo:
|
|||
- 如果有使用 CDN 全站加速,请更新完毕后,刷新全站缓存。
|
||||
|
||||
# 1.0.2
|
||||
|
||||
## New features
|
||||
|
||||
- 支持打包成 War,部署到外部容器。
|
||||
- 支持自定义博客的 head 信息。
|
||||
- 提供在线更新 [halo-admin](https://github.com/halo-dev/halo-admin) 的接口。@johnniang
|
||||
|
||||
## Fixed
|
||||
- 修复 404 请求被重定向至 /404。#186
|
||||
|
||||
- 修复 404 请求被重定向至 /404。#186
|
||||
- 修复导入 Markdown 文档时,标签判断完没有加break,导致标签会继续走分类的逻辑。@wuzhi1234
|
||||
- 修复导入 Markdown 文件时,slug 为空时初始化赋值。@wuzhi1234
|
||||
|
||||
# 1.0.2-beta.1
|
||||
|
||||
- 主要修复在 `Windows` 上无法删除主题的 bug 以及其他小 bug;
|
||||
- 脱敏日志(密码);
|
||||
- 更新 Lombok 插件。
|
||||
|
||||
# 1.0.1
|
||||
|
||||
## Changes
|
||||
|
||||
- 修改 `Content api` 的参数 `api_token` 为 `api_access_key`。
|
||||
|
||||
## Fixed
|
||||
|
||||
- 修复文章无评论时一直转圈圈的问题。
|
||||
- 修复使用 MySQL 启动时索引创建失败的问题。
|
||||
|
||||
# 1.0.0
|
||||
|
||||
## 🎉 Halo v1.0 发布啦。
|
||||
|
||||
## Features
|
||||
|
@ -541,39 +585,54 @@ halo:
|
|||
14. 还有…
|
||||
|
||||
# 0.4.4
|
||||
|
||||
## Fixed
|
||||
|
||||
- 修复导出博客数据的问题。
|
||||
|
||||
## Tips
|
||||
|
||||
> 此版本为 0.x 最后一个版本,不支持直接升级到 v1.0 版本。如需从 0.x 升级为 v1.0,请参考 https://halo.run/archives/install-migrate-from-044
|
||||
|
||||
# 0.4.3
|
||||
|
||||
## New features
|
||||
|
||||
- 支持备份全站数据,包括设置项,文章,分类,标签,评论等。
|
||||
|
||||
## Tips
|
||||
|
||||
> 重要版本,请尽快升级。
|
||||
|
||||
# 0.4.2
|
||||
|
||||
## Changes
|
||||
|
||||
- 修改rss/sitemap的渲染方式,新增html形式的sitemap以及atom格式的feed。
|
||||
- 重构 Service 层的代码。 by @JohnNiang
|
||||
- 重构 Api 的代码。 by @JohnNiang
|
||||
- 重构 Service 层的代码。 by @JohnNiang
|
||||
- 重构 Api 的代码。 by @JohnNiang
|
||||
- 文章缩略图统一改为绝对路径。
|
||||
|
||||
## Fixed
|
||||
|
||||
- 修复附件删除失败的问题
|
||||
- 修复图库删除图片导致页面报错的问题。#97
|
||||
- 修复 Material 主题文章页面链接错误的问题。
|
||||
|
||||
# 0.4.1
|
||||
|
||||
## New features
|
||||
|
||||
- 支持文章加密
|
||||
|
||||
## Changes
|
||||
- 更换 Markdown 编辑器为 [EasyMDE](https://github.com/Ionaru/easy-markdown-editor),这是 [SimpleMDE](https://github.com/sparksuite/simplemde-markdown-editor/) 的一个分支,在继续维护。
|
||||
|
||||
- 更换 Markdown
|
||||
编辑器为 [EasyMDE](https://github.com/Ionaru/easy-markdown-editor),这是 [SimpleMDE](https://github.com/sparksuite/simplemde-markdown-editor/)
|
||||
的一个分支,在继续维护。
|
||||
|
||||
## Fixed
|
||||
|
||||
- 修复使用 MySQL 导致时区不正确的问题。
|
||||
- 修复 Docker 自动构建的镜像,主题无法使用的问题。
|
||||
- 修复搜索框的 XSS 漏洞。
|
||||
|
@ -581,52 +640,70 @@ halo:
|
|||
- 修复使用oss时,选择图片路径不正确的问题
|
||||
|
||||
# 0.4.0
|
||||
|
||||
## New features
|
||||
|
||||
- 支持后台管理界面的盒子布局背景自定义。
|
||||
- 支持文章备份带上元数据,也就是说,在某天你要抛弃 Halo 的时候,你可以导出文章直接放到 Hexo 等博客,并且带有文章分类信息,标签信息,发布时间,更新时间,文章标题等数据。
|
||||
- Material 主题支持文章搜索,MathJax,以及代码高亮。
|
||||
- 发布新主题 [Pinghsu](https://github.com/ruibaby/pinghsu-halo),非常感谢该主题的作者 [chakhsu](https://github.com/chakhsu) 制作出如此优秀的主题。需要注意的是,使用该主题,必须升级到当前版本。
|
||||
- 发布新主题 [Pinghsu](https://github.com/ruibaby/pinghsu-halo),非常感谢该主题的作者 [chakhsu](https://github.com/chakhsu)
|
||||
制作出如此优秀的主题。需要注意的是,使用该主题,必须升级到当前版本。
|
||||
|
||||
## Changes
|
||||
|
||||
- 升级 AdminLTE 的版本。
|
||||
|
||||
## Fixed
|
||||
|
||||
- 修复若干Bug。
|
||||
|
||||
# 0.3.0
|
||||
|
||||
## :tada:2019,Happy New Year!
|
||||
|
||||
## New features
|
||||
|
||||
- Docker 部署支持自定义 `H2Database` 数据库用户名和密码。
|
||||
|
||||
## Changes
|
||||
|
||||
- 后台管理的 pjax 插件更换为 MoOx Pjax,体验更加顺畅。
|
||||
|
||||
## Fixed
|
||||
|
||||
- 修复若干Bug。
|
||||
|
||||
> 祝大家新年快乐。
|
||||
|
||||
# 0.2.2
|
||||
|
||||
## Fixed
|
||||
|
||||
- 修复后台菜单管理的问题。
|
||||
|
||||
# 0.2.1
|
||||
|
||||
## Fixed
|
||||
|
||||
- 修复后台菜单管理的排序问题。
|
||||
- 修复安全问题。
|
||||
|
||||
# 0.2.0
|
||||
|
||||
## New features
|
||||
|
||||
- 支持 Markdown 文档(Hexo/Jekyll)导入
|
||||
|
||||
## Changes
|
||||
|
||||
- 修改 `static` 目录的文件结构。
|
||||
|
||||
## Fixed
|
||||
|
||||
- 修复多文件上传失败的问题,以及图片选择框翻页之后无法选择的问题。
|
||||
|
||||
## 注意:
|
||||
|
||||
> 本次更新修改了静态资源路径,更新到该版本需要到数据库执行下面两条 SQL 语句,如果某些静态资源还是无法访问,重启 Halo 即可。
|
||||
|
||||
```sql
|
||||
|
@ -636,38 +713,47 @@ UPDATE HALO_COMMENT SET COMMENT_CONTENT = replace(COMMENT_CONTENT, '/static/plug
|
|||
```
|
||||
|
||||
# 0.1.1
|
||||
|
||||
## New features
|
||||
|
||||
- 新增后台管理切换页面的过渡动画。
|
||||
- 支持又拍云/七牛云图片上传(感谢[@ywms](https://github.com/ywms))。
|
||||
- Markdown 编辑器支持数学公式渲染。
|
||||
- 支持 Docker Compose 部署,真正意义上的一键部署。自动配置好 Nginx 反向代理,SSL证书。
|
||||
|
||||
## Changes
|
||||
|
||||
- 仪表盘最新文章/最新评论的时间格式改为几...前,如:1天前,36分钟前。
|
||||
- Markdown 文章渲染改为由后端渲染,使用的库为 [commonmark-java](https://github.com/atlassian/commonmark-java)。
|
||||
- 支持文章修改发布时间。
|
||||
- 取消自动备份功能。
|
||||
|
||||
## Fixed
|
||||
|
||||
- 修复安装主题之后不关闭弹窗的问题。
|
||||
- 修复使用 MySQL 时,报时区错误的问题。
|
||||
- 修复使用 Docker 部署时,时间不正常的问题。
|
||||
- 修复修改标签/分类目录时,文章信息没有刷新缓存的问题。
|
||||
|
||||
# 0.1
|
||||
|
||||
## New features
|
||||
|
||||
- 支持Docker部署。
|
||||
- 新增Api Token验证,防止接口被恶意调用。
|
||||
- 支持自定义页面选择指定模板渲染,模板文件名格式`page_xxx.ftl`。
|
||||
|
||||
## Changes
|
||||
|
||||
- 后台管理页面代码结构优化。
|
||||
- 更换数据库连接池为性能更好的[HikariCP](https://github.com/brettwooldridge/HikariCP),更新的时候需要修改配置文件。
|
||||
|
||||
## Fixed
|
||||
|
||||
- 解决文章备份失败的问题。
|
||||
|
||||
## 注意
|
||||
|
||||
因为更换了数据库连接池,所以需要修改配置文件(老版本升级,新部署不需要),否则会启动失败。
|
||||
|
||||
```yaml
|
||||
|
@ -678,10 +764,13 @@ spring:
|
|||
```
|
||||
|
||||
# 0.0.9
|
||||
|
||||
## New features
|
||||
|
||||
- 评论支持换行显示。
|
||||
|
||||
## Changes
|
||||
|
||||
- 弃用`Apache common Lang3`的相关方法,使用`hutool`代替。
|
||||
- 后台管理主题列表中的主题名改为仅首字母大写,如`ANATOLE`改为`Anatole`。
|
||||
- 新增自动备份的开关。
|
||||
|
@ -694,28 +783,35 @@ spring:
|
|||
- 更改主题设置页面的代码结构,封装`theme_option_marco`,方便调用。
|
||||
|
||||
## Fixed
|
||||
|
||||
- 修复网站名称为空时,页面的错误。
|
||||
|
||||
# 0.0.8
|
||||
|
||||
## New features
|
||||
|
||||
- 发布文章的时候,没有缩略图会自动添加一张。
|
||||
- 支持i18n,并带有英文语言包,后台可自行切换语言。
|
||||
- 新增各大搜索平台验证代码的入口,需要主题支持。
|
||||
- 全局美化checkbox和radio。
|
||||
|
||||
## Changes
|
||||
|
||||
- 后台Favicon更新。
|
||||
- 更改附件目录为用户目录下的`halo/upload`,需要将原来的附件目录`upload`移动到用户目录下的`halo`文件夹。
|
||||
- 更换编辑器,由editor.md更换为simplemde,支持图片拖动上传。
|
||||
- 下载的主题不需要再更改为指定文件夹名才能上传。
|
||||
|
||||
## Fixed
|
||||
|
||||
- 修复评论框在某些主题下样式错乱的问题。
|
||||
- 修复编辑文章的时候,分类目录不回显的问题。
|
||||
- 修复Material主题第一次使用样式混乱的问题。
|
||||
|
||||
## 注意
|
||||
|
||||
因为支持了i18n,所以更新的时候需要修改`application.yaml`配置文件。
|
||||
|
||||
```yaml
|
||||
server:
|
||||
port: 8090
|
||||
|
@ -774,18 +870,23 @@ spring:
|
|||
logging:
|
||||
file: ./logs/log.log
|
||||
```
|
||||
|
||||
如上代码,修改的地方有:
|
||||
|
||||
1. expose-spring-macro-helpers: false(原),现为true。
|
||||
2. 在`freemarker`添加了`settings:auto_import: /spring.ftl as spring`(注意按照上面的格式)。
|
||||
3. 在`spring`节点添加了`messages:basename: i18n/messages`(注意按照上面的格式)。
|
||||
|
||||
### 修改方法
|
||||
|
||||
1. 将原有的`application.yaml`备份(重命名)。
|
||||
2. 复制新的`application.yaml`文件到`resources`下。
|
||||
3. 按照原来的配置文件修改`application.yaml`文件,需要修改端口号,数据库配置等。
|
||||
|
||||
# 0.0.7
|
||||
|
||||
## New features
|
||||
|
||||
- 新增可选是否需要审核评论的选项。
|
||||
- 新增一键脚本部署方式。
|
||||
- 新增NexT主题和Story主题。
|
||||
|
@ -796,11 +897,13 @@ logging:
|
|||
- 新增主题在线安装和在线更新的功能(需要安装Git)。
|
||||
|
||||
## Changes
|
||||
|
||||
- 使用枚举方式替换大量重复字符串。
|
||||
- 更改Anatole社交账号的填写方式,现在只需要填写相关账号。
|
||||
- 暂时下线文章自动保存的功能,但是可以使用Ctrl+S进行保存。
|
||||
|
||||
## Fixed
|
||||
|
||||
- 修复文章页面会出现横向滚动条的问题。
|
||||
- 修复自定义页面不显示评论条数的问题。
|
||||
- 修复后台评论管理样式混乱的问题。
|
||||
|
@ -810,7 +913,9 @@ logging:
|
|||
- 修复删除主题再上传相同主题时,会出现又删除上传的主题的问题。
|
||||
|
||||
# 0.0.6
|
||||
|
||||
## New features
|
||||
|
||||
- 使用Ehcache缓存。
|
||||
- Anatole可在主题设置中添加自定义css。
|
||||
- 新增Anatole主题的表格样式。
|
||||
|
@ -818,6 +923,7 @@ logging:
|
|||
- 新增评论的时候可以选择表情。
|
||||
|
||||
## Changes
|
||||
|
||||
- 删除Editor.md插件中一些无用的资源。
|
||||
- 规范后台界面的部分命名。
|
||||
- 压缩后台的代码。
|
||||
|
@ -826,13 +932,16 @@ logging:
|
|||
- 修改评论的展示方式,改变为盖楼(嵌套)的方式。
|
||||
|
||||
## Fixed
|
||||
|
||||
- 修复文章状态不为发布的时候也可以通过链接访问的问题。
|
||||
- 修复使用MySQL初始化博客失败的问题。
|
||||
- 修复前台标签下可现实草稿文章的问题。
|
||||
- 修复附件的大小和尺寸显示不正确的问题。
|
||||
|
||||
# 0.0.5
|
||||
|
||||
## New features
|
||||
|
||||
- 使用[Hutool](https://github.com/looly/hutool)的encode方法来防止xss攻击。
|
||||
- 新增备份功能,支持备份resources目录,数据库,以及导出文章。并且可以提供下载和发送到邮箱。
|
||||
- 新增自动备份功能,每天凌晨一点会自动备份一次,超过10个备份将删除之前的备份并新建一个备份。
|
||||
|
@ -843,18 +952,21 @@ logging:
|
|||
- 后台登录支持保存登录名。
|
||||
|
||||
## Changes
|
||||
|
||||
- 优化后台登录逻辑,登录失败超过5次,将10分钟不能登录。
|
||||
- 后台管理页面支持高亮菜单。
|
||||
- 压缩了Anatole主题的资源文件。
|
||||
- 修改上传附件时候的压缩方式,这种方式更加完美,平均压缩之后只有几k到十几k。
|
||||
|
||||
## Fixed
|
||||
|
||||
- 修复后台favicon获取不到的问题,会导致每刷新一次就获取一次,拖慢速度。
|
||||
- 修复后台登录的xss漏洞。
|
||||
- 修复上传主题之后会产生`__MACOSX`目录的问题。
|
||||
- 修复附件的大小和尺寸显示不正确的问题。
|
||||
|
||||
# 0.0.4
|
||||
|
||||
更新汇总:
|
||||
|
||||
1. 修复第一次安装完成启动后首页报错的bug
|
||||
|
@ -869,16 +981,19 @@ logging:
|
|||
10. 更换web容器为undertow
|
||||
|
||||
# 0.0.3
|
||||
|
||||
完整包:[halo-0.0.3.zip](https://pan.baidu.com/s/1kqNKwSlveqC4gS6TIF5mGQ)
|
||||
更新包:[halo-0.0.3-update.zip](https://pan.baidu.com/s/1S6CNlFaZ5hvNEqQ2a50mNg)
|
||||
|
||||
# 0.0.2
|
||||
|
||||
完整包:[halo-0.0.2.zip](http://io.ryanc.cc/index.php?share/file&user=1&sid=ecShv8rB)
|
||||
更新包:[halo-0.0.2-update.zip](http://io.ryanc.cc/index.php?share/file&user=1&sid=a2zx3v6I)
|
||||
|
||||
> 注意:为了防止配置文件被覆盖,更新包里面的配置文件被改成了application.template.yaml。如果更新之后只能进入安装页面的话,请手动在数据表`HALO_OPTIONS`里面添加`is_install`字段,值为`true`。
|
||||
|
||||
# 0.0.1
|
||||
|
||||
[网盘下载地址](http://io.ryanc.cc/index.php?share/file&user=1&sid=YUHisTCV)
|
||||
注:第一次发布版本,所以把依赖jar包也压缩进去了,以后发布的版本会有两个,一个是完整版(带有依赖),一个是增量版(不带有依赖,直接上传覆盖就可以更新)。
|
||||
安装教程请看:[https://halo-doc.ryanc.cc](https://halo-doc.ryanc.cc)和[https://ryanc.cc](https://ryanc.cc)
|
|
@ -60,6 +60,7 @@ java -jar halo-latest.jar
|
|||
> Halo 使用 GPL-v3.0 协议开源,请尽量遵守开源协议。
|
||||
|
||||
## 贡献
|
||||
|
||||
参考 [CONTRIBUTING](./CONTRIBUTING.md)。
|
||||
|
||||
## 捐赠
|
||||
|
|
12
SECURITY.md
12
SECURITY.md
|
@ -3,7 +3,9 @@
|
|||
## Supported Versions
|
||||
|
||||
Halo currently supports the versions listed below, where as:
|
||||
- :white_check_mark: indicates an active development roadmap, is therefore maintaining, and **will** receive Security Vulnerability Report.
|
||||
|
||||
- :white_check_mark: indicates an active development roadmap, is therefore maintaining, and **will** receive Security
|
||||
Vulnerability Report.
|
||||
- :x: indicates such version has already deprecated and **will not** be receiving Security Vulnerability Report.
|
||||
|
||||
| Version | Supported |
|
||||
|
@ -11,14 +13,16 @@ Halo currently supports the versions listed below, where as:
|
|||
| 0.x | :x: |
|
||||
| 1.x | :white_check_mark: |
|
||||
|
||||
|
||||
## Reporting a Vulnerability
|
||||
|
||||
We first appreciate and are very thankful that you've found a vulnerability issue in Halo! By disclosing such issue to Halo development team you are helping Halo to become a much more safer project than before! ;)
|
||||
We first appreciate and are very thankful that you've found a vulnerability issue in Halo! By disclosing such issue to
|
||||
Halo development team you are helping Halo to become a much more safer project than before! ;)
|
||||
|
||||
To protect the existing users of Halo, we kindly ask you to not disclose the vulnerability to anyone except the Halo development team before a fix has been rolled out.
|
||||
To protect the existing users of Halo, we kindly ask you to not disclose the vulnerability to anyone except the Halo
|
||||
development team before a fix has been rolled out.
|
||||
|
||||
To Report a Vulnerability, please complete the form below, and send such report by email to `hi@halo.run`.
|
||||
|
||||
```
|
||||
Vulnerability has been observed in...
|
||||
- Docker? [n/y]:
|
||||
|
|
|
@ -14,6 +14,12 @@ java {
|
|||
sourceCompatibility = JavaVersion.VERSION_11
|
||||
}
|
||||
|
||||
checkstyle {
|
||||
toolVersion = "8.39"
|
||||
showViolations = false
|
||||
ignoreFailures = false
|
||||
}
|
||||
|
||||
repositories {
|
||||
mavenLocal()
|
||||
maven {
|
||||
|
|
|
@ -1,100 +1,364 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<?xml version="1.0"?>
|
||||
<!DOCTYPE module PUBLIC
|
||||
"-//Puppy Crawl//DTD Check Configuration 1.3//EN"
|
||||
"-//Checkstyle//DTD Checkstyle Configuration 1.3//EN"
|
||||
"https://checkstyle.org/dtds/configuration_1_3.dtd">
|
||||
<!--Refer http://checkstyle.sourceforge.net/reports/google-java-style.html#s2.2-file-encoding -->
|
||||
|
||||
<!--
|
||||
Checkstyle configuration that checks the Google coding conventions from Google Java Style
|
||||
that can be found at https://google.github.io/styleguide/javaguide.html
|
||||
|
||||
Checkstyle is very configurable. Be sure to read the documentation at
|
||||
http://checkstyle.org (or in your downloaded distribution).
|
||||
|
||||
To completely disable a check, just comment it out or delete it from the file.
|
||||
To suppress certain violations please review suppression filters.
|
||||
|
||||
Authors: Max Vetrenko, Ruslan Diachenko, Roman Ivanov.
|
||||
-->
|
||||
|
||||
<module name="Checker">
|
||||
<property name="charset" value="UTF-8"/>
|
||||
|
||||
<property name="localeLanguage" value="en"/>
|
||||
<property name="severity" value="error"/>
|
||||
|
||||
<!--To configure the check to report on the first instance in each file-->
|
||||
<module name="FileTabCharacter"/>
|
||||
|
||||
<module name="RegexpSingleline">
|
||||
<property name="format" value="^.*System\.(out|err).*$"/>
|
||||
<property name="message" value="Don't use System.out/err, use SLF4J instead."/>
|
||||
<property name="fileExtensions" value="java, properties, xml"/>
|
||||
<!-- Excludes all 'module-info.java' files -->
|
||||
<!-- See https://checkstyle.org/config_filefilters.html -->
|
||||
<module name="BeforeExecutionExclusionFileFilter">
|
||||
<property name="fileNamePattern" value="module\-info\.java$"/>
|
||||
</module>
|
||||
<!-- https://checkstyle.org/config_filters.html#SuppressionFilter -->
|
||||
<module name="SuppressionFilter">
|
||||
<property name="file" value="${org.checkstyle.google.suppressionfilter.config}"
|
||||
default="checkstyle-suppressions.xml"/>
|
||||
<property name="optional" value="true"/>
|
||||
</module>
|
||||
|
||||
<module name="FileLength">
|
||||
<property name="max" value="3000"/>
|
||||
<!-- Checks for whitespace -->
|
||||
<!-- See http://checkstyle.org/config_whitespace.html -->
|
||||
<module name="FileTabCharacter">
|
||||
<property name="eachLine" value="true"/>
|
||||
</module>
|
||||
|
||||
<module name="LineLength">
|
||||
<property name="fileExtensions" value="java"/>
|
||||
<property name="max" value="100"/>
|
||||
<property name="ignorePattern" value="^package.*|^import.*|a href|href|http://|https://|ftp://"/>
|
||||
</module>
|
||||
|
||||
<module name="TreeWalker">
|
||||
<property name="tabWidth" value="4"/>
|
||||
<module name="CommentsIndentation"/>
|
||||
<module name="SuppressionCommentFilter">
|
||||
<property name="offCommentFormat" value="CS:OFF:BEGIN"/>
|
||||
<property name="onCommentFormat" value="CS:OFF:END"/>
|
||||
<property name="checkFormat" value=".*"/>
|
||||
<module name="SuppressionCommentFilter"/>
|
||||
<module name="OuterTypeFilename"/>
|
||||
<module name="IllegalTokenText">
|
||||
<property name="tokens" value="STRING_LITERAL, CHAR_LITERAL"/>
|
||||
<property name="format"
|
||||
value="\\u00(09|0(a|A)|0(c|C)|0(d|D)|22|27|5(C|c))|\\(0(10|11|12|14|15|42|47)|134)"/>
|
||||
<property name="message"
|
||||
value="Consider using special escape sequence instead of octal value or Unicode escaped value."/>
|
||||
</module>
|
||||
<module name="UnusedImports">
|
||||
<property name="processJavadoc" value="true"/>
|
||||
<module name="AvoidEscapedUnicodeCharacters">
|
||||
<property name="allowEscapesForControlCharacters" value="true"/>
|
||||
<property name="allowByTailComment" value="true"/>
|
||||
<property name="allowNonPrintableEscapes" value="true"/>
|
||||
</module>
|
||||
|
||||
<module name="RedundantImport"/>
|
||||
|
||||
<!--Checks that classes that override equals() also override hashCode()-->
|
||||
<module name="EqualsHashCode"/>
|
||||
<!--Checks for over-complicated boolean expressions. Currently finds code like if (topic == true), topic || true, !false, etc.-->
|
||||
<module name="SimplifyBooleanExpression"/>
|
||||
<module name="OneStatementPerLine"/>
|
||||
<module name="UnnecessaryParentheses"/>
|
||||
<!--Checks for over-complicated boolean return statements. For example the following code-->
|
||||
<module name="SimplifyBooleanReturn"/>
|
||||
|
||||
<!--Check that the default is after all the cases in producerGroup switch statement-->
|
||||
<module name="DefaultComesLast"/>
|
||||
<!--Detects empty statements (standalone ";" semicolon)-->
|
||||
<module name="EmptyStatement"/>
|
||||
<!--Checks that long constants are defined with an upper ell-->
|
||||
<module name="UpperEll"/>
|
||||
<module name="ConstantName">
|
||||
<property name="format" value="(^[A-Z][A-Z0-9]*(_[A-Z0-9]+)*$)|(^logger)"/>
|
||||
<module name="AvoidStarImport"/>
|
||||
<module name="OneTopLevelClass"/>
|
||||
<module name="NoLineWrap">
|
||||
<property name="tokens" value="PACKAGE_DEF, IMPORT, STATIC_IMPORT"/>
|
||||
</module>
|
||||
<!--Checks that local, non-final variable names conform to producerGroup format specified by the format property-->
|
||||
<module name="LocalVariableName"/>
|
||||
<!--Validates identifiers for local, final variables, including catch parameters-->
|
||||
<module name="LocalFinalVariableName"/>
|
||||
<!--Validates identifiers for non-static fields-->
|
||||
<module name="MemberName"/>
|
||||
<!--Validates identifiers for class type parameters-->
|
||||
<module name="ClassTypeParameterName">
|
||||
<property name="format" value="(^[A-Z][A-Z0-9]*(_[A-Z0-9]+)*$)"/>
|
||||
<module name="EmptyBlock">
|
||||
<property name="option" value="TEXT"/>
|
||||
<property name="tokens"
|
||||
value="LITERAL_TRY, LITERAL_FINALLY, LITERAL_IF, LITERAL_ELSE, LITERAL_SWITCH"/>
|
||||
</module>
|
||||
<!--Validates identifiers for method type parameters-->
|
||||
<module name="MethodTypeParameterName">
|
||||
<property name="format" value="(^[A-Z][A-Z0-9]*(_[A-Z0-9]+)*$)"/>
|
||||
<module name="NeedBraces">
|
||||
<property name="tokens"
|
||||
value="LITERAL_DO, LITERAL_ELSE, LITERAL_FOR, LITERAL_IF, LITERAL_WHILE"/>
|
||||
</module>
|
||||
<module name="PackageName">
|
||||
<property name="format" value="^run\.halo(\.[a-zA-Z][a-zA-Z0-9]*)+$"/>
|
||||
<module name="LeftCurly">
|
||||
<property name="tokens"
|
||||
value="ANNOTATION_DEF, CLASS_DEF, CTOR_DEF, ENUM_CONSTANT_DEF, ENUM_DEF,
|
||||
INTERFACE_DEF, LAMBDA, LITERAL_CASE, LITERAL_CATCH, LITERAL_DEFAULT,
|
||||
LITERAL_DO, LITERAL_ELSE, LITERAL_FINALLY, LITERAL_FOR, LITERAL_IF,
|
||||
LITERAL_SWITCH, LITERAL_SYNCHRONIZED, LITERAL_TRY, LITERAL_WHILE, METHOD_DEF,
|
||||
OBJBLOCK, STATIC_INIT, RECORD_DEF, COMPACT_CTOR_DEF"/>
|
||||
</module>
|
||||
<module name="ParameterName"/>
|
||||
<module name="StaticVariableName">
|
||||
<property name="format" value="(^[A-Z][A-Z0-9]*(_[A-Z0-9]+)*$)"/>
|
||||
<module name="RightCurly">
|
||||
<property name="id" value="RightCurlySame"/>
|
||||
<property name="tokens"
|
||||
value="LITERAL_TRY, LITERAL_CATCH, LITERAL_FINALLY, LITERAL_IF, LITERAL_ELSE,
|
||||
LITERAL_DO"/>
|
||||
</module>
|
||||
<module name="TypeName">
|
||||
<property name="format" value="(^[A-Z][a-zA-Z0-9]*$)|(^[A-Z][A-Z0-9]*(_[A-Z0-9]+)*$)"/>
|
||||
<module name="RightCurly">
|
||||
<property name="id" value="RightCurlyAlone"/>
|
||||
<property name="option" value="alone"/>
|
||||
<property name="tokens"
|
||||
value="CLASS_DEF, METHOD_DEF, CTOR_DEF, LITERAL_FOR, LITERAL_WHILE, STATIC_INIT,
|
||||
INSTANCE_INIT, ANNOTATION_DEF, ENUM_DEF, INTERFACE_DEF, RECORD_DEF,
|
||||
COMPACT_CTOR_DEF"/>
|
||||
</module>
|
||||
<module name="SuppressionXpathSingleFilter">
|
||||
<!-- suppresion is required till https://github.com/checkstyle/checkstyle/issues/7541 -->
|
||||
<property name="id" value="RightCurlyAlone"/>
|
||||
<property name="query" value="//RCURLY[parent::SLIST[count(./*)=1]
|
||||
or preceding-sibling::*[last()][self::LCURLY]]"/>
|
||||
</module>
|
||||
<module name="WhitespaceAfter">
|
||||
<property name="tokens"
|
||||
value="COMMA, SEMI, TYPECAST, LITERAL_IF, LITERAL_ELSE,
|
||||
LITERAL_WHILE, LITERAL_DO, LITERAL_FOR, DO_WHILE"/>
|
||||
</module>
|
||||
|
||||
<!--whitespace-->
|
||||
<module name="GenericWhitespace"/>
|
||||
<module name="NoWhitespaceBefore"/>
|
||||
<module name="WhitespaceAfter"/>
|
||||
<module name="WhitespaceAround">
|
||||
<property name="allowEmptyConstructors" value="true"/>
|
||||
<property name="allowEmptyLambdas" value="true"/>
|
||||
<property name="allowEmptyMethods" value="true"/>
|
||||
<property name="allowEmptyTypes" value="true"/>
|
||||
<property name="allowEmptyLoops" value="true"/>
|
||||
<property name="ignoreEnhancedForColon" value="false"/>
|
||||
<property name="tokens"
|
||||
value="ASSIGN, BAND, BAND_ASSIGN, BOR, BOR_ASSIGN, BSR, BSR_ASSIGN, BXOR,
|
||||
BXOR_ASSIGN, COLON, DIV, DIV_ASSIGN, DO_WHILE, EQUAL, GE, GT, LAMBDA, LAND,
|
||||
LCURLY, LE, LITERAL_CATCH, LITERAL_DO, LITERAL_ELSE, LITERAL_FINALLY,
|
||||
LITERAL_FOR, LITERAL_IF, LITERAL_RETURN, LITERAL_SWITCH, LITERAL_SYNCHRONIZED,
|
||||
LITERAL_TRY, LITERAL_WHILE, LOR, LT, MINUS, MINUS_ASSIGN, MOD, MOD_ASSIGN,
|
||||
NOT_EQUAL, PLUS, PLUS_ASSIGN, QUESTION, RCURLY, SL, SLIST, SL_ASSIGN, SR,
|
||||
SR_ASSIGN, STAR, STAR_ASSIGN, LITERAL_ASSERT, TYPE_EXTENSION_AND"/>
|
||||
<message key="ws.notFollowed"
|
||||
value="WhitespaceAround: ''{0}'' is not followed by whitespace. Empty blocks may only be represented as '{}' when not part of a multi-block statement (4.1.3)"/>
|
||||
<message key="ws.notPreceded"
|
||||
value="WhitespaceAround: ''{0}'' is not preceded with whitespace."/>
|
||||
</module>
|
||||
<module name="OneStatementPerLine"/>
|
||||
<module name="MultipleVariableDeclarations"/>
|
||||
<module name="ArrayTypeStyle"/>
|
||||
<module name="MissingSwitchDefault"/>
|
||||
<module name="FallThrough"/>
|
||||
<module name="UpperEll"/>
|
||||
<module name="ModifierOrder"/>
|
||||
<module name="EmptyLineSeparator">
|
||||
<property name="tokens"
|
||||
value="PACKAGE_DEF, IMPORT, STATIC_IMPORT, CLASS_DEF, INTERFACE_DEF, ENUM_DEF,
|
||||
STATIC_INIT, INSTANCE_INIT, METHOD_DEF, CTOR_DEF, VARIABLE_DEF, RECORD_DEF,
|
||||
COMPACT_CTOR_DEF"/>
|
||||
<property name="allowNoEmptyLineBetweenFields" value="true"/>
|
||||
</module>
|
||||
<module name="SeparatorWrap">
|
||||
<property name="id" value="SeparatorWrapDot"/>
|
||||
<property name="tokens" value="DOT"/>
|
||||
<property name="option" value="nl"/>
|
||||
</module>
|
||||
<module name="SeparatorWrap">
|
||||
<property name="id" value="SeparatorWrapComma"/>
|
||||
<property name="tokens" value="COMMA"/>
|
||||
<property name="option" value="EOL"/>
|
||||
</module>
|
||||
<module name="SeparatorWrap">
|
||||
<!-- ELLIPSIS is EOL until https://github.com/google/styleguide/issues/258 -->
|
||||
<property name="id" value="SeparatorWrapEllipsis"/>
|
||||
<property name="tokens" value="ELLIPSIS"/>
|
||||
<property name="option" value="EOL"/>
|
||||
</module>
|
||||
<module name="SeparatorWrap">
|
||||
<!-- ARRAY_DECLARATOR is EOL until https://github.com/google/styleguide/issues/259 -->
|
||||
<property name="id" value="SeparatorWrapArrayDeclarator"/>
|
||||
<property name="tokens" value="ARRAY_DECLARATOR"/>
|
||||
<property name="option" value="EOL"/>
|
||||
</module>
|
||||
<module name="SeparatorWrap">
|
||||
<property name="id" value="SeparatorWrapMethodRef"/>
|
||||
<property name="tokens" value="METHOD_REF"/>
|
||||
<property name="option" value="nl"/>
|
||||
</module>
|
||||
<module name="PackageName">
|
||||
<property name="format" value="^run\.halo(\.[a-z][a-z0-9]*)*$"/>
|
||||
<message key="name.invalidPattern"
|
||||
value="Package name ''{0}'' must match pattern ''{1}''."/>
|
||||
</module>
|
||||
<module name="TypeName">
|
||||
<property name="tokens" value="CLASS_DEF, INTERFACE_DEF, ENUM_DEF,
|
||||
ANNOTATION_DEF, RECORD_DEF"/>
|
||||
<message key="name.invalidPattern"
|
||||
value="Type name ''{0}'' must match pattern ''{1}''."/>
|
||||
</module>
|
||||
<module name="MemberName">
|
||||
<property name="format" value="^[a-z][a-z0-9][a-zA-Z0-9]*$"/>
|
||||
<message key="name.invalidPattern"
|
||||
value="Member name ''{0}'' must match pattern ''{1}''."/>
|
||||
</module>
|
||||
<module name="ParameterName">
|
||||
<property name="format" value="^[a-z]([a-z0-9][a-zA-Z0-9]*)?$"/>
|
||||
<message key="name.invalidPattern"
|
||||
value="Parameter name ''{0}'' must match pattern ''{1}''."/>
|
||||
</module>
|
||||
<module name="LambdaParameterName">
|
||||
<property name="format" value="^[a-z]([a-z0-9][a-zA-Z0-9]*)?$"/>
|
||||
<message key="name.invalidPattern"
|
||||
value="Lambda parameter name ''{0}'' must match pattern ''{1}''."/>
|
||||
</module>
|
||||
<module name="CatchParameterName">
|
||||
<property name="format" value="^[a-z]([a-z0-9][a-zA-Z0-9]*)?$"/>
|
||||
<message key="name.invalidPattern"
|
||||
value="Catch parameter name ''{0}'' must match pattern ''{1}''."/>
|
||||
</module>
|
||||
<module name="LocalVariableName">
|
||||
<property name="severity" value="warning"/>
|
||||
<property name="format" value="^[a-z]([a-z0-9][a-zA-Z0-9]*)?$"/>
|
||||
<message key="name.invalidPattern"
|
||||
value="Local variable name ''{0}'' must match pattern ''{1}''."/>
|
||||
</module>
|
||||
<module name="PatternVariableName">
|
||||
<property name="format" value="^[a-z]([a-z0-9][a-zA-Z0-9]*)?$"/>
|
||||
<message key="name.invalidPattern"
|
||||
value="Pattern variable name ''{0}'' must match pattern ''{1}''."/>
|
||||
</module>
|
||||
<module name="ClassTypeParameterName">
|
||||
<property name="severity" value="warning"/>
|
||||
<property name="format" value="(^[A-Z][0-9]?)$|([A-Z][a-zA-Z0-9]*[T]$)"/>
|
||||
<message key="name.invalidPattern"
|
||||
value="Class type name ''{0}'' must match pattern ''{1}''."/>
|
||||
</module>
|
||||
<module name="RecordTypeParameterName">
|
||||
<property name="format" value="(^[A-Z][0-9]?)$|([A-Z][a-zA-Z0-9]*[T]$)"/>
|
||||
<message key="name.invalidPattern"
|
||||
value="Record type name ''{0}'' must match pattern ''{1}''."/>
|
||||
</module>
|
||||
<module name="MethodTypeParameterName">
|
||||
<property name="format" value="(^[A-Z][0-9]?)$|([A-Z][a-zA-Z0-9]*[T]$)"/>
|
||||
<message key="name.invalidPattern"
|
||||
value="Method type name ''{0}'' must match pattern ''{1}''."/>
|
||||
</module>
|
||||
<module name="InterfaceTypeParameterName">
|
||||
<property name="format" value="(^[A-Z][0-9]?)$|([A-Z][a-zA-Z0-9]*[T]$)"/>
|
||||
<message key="name.invalidPattern"
|
||||
value="Interface type name ''{0}'' must match pattern ''{1}''."/>
|
||||
</module>
|
||||
<module name="NoFinalizer"/>
|
||||
<module name="GenericWhitespace">
|
||||
<message key="ws.followed"
|
||||
value="GenericWhitespace ''{0}'' is followed by whitespace."/>
|
||||
<message key="ws.preceded"
|
||||
value="GenericWhitespace ''{0}'' is preceded with whitespace."/>
|
||||
<message key="ws.illegalFollow"
|
||||
value="GenericWhitespace ''{0}'' should followed by whitespace."/>
|
||||
<message key="ws.notPreceded"
|
||||
value="GenericWhitespace ''{0}'' is not preceded with whitespace."/>
|
||||
</module>
|
||||
<!-- Indentation -->
|
||||
<module name="Indentation">
|
||||
<property name="forceStrictCondition" value="true"/>
|
||||
<property name="throwsIndent" value="8"/>
|
||||
<property name="lineWrappingIndentation" value="8"/>
|
||||
<property name="basicOffset" value="4"/>
|
||||
<property name="braceAdjustment" value="0"/>
|
||||
<property name="caseIndent" value="4"/>
|
||||
<property name="throwsIndent" value="4"/>
|
||||
<property name="lineWrappingIndentation" value="4"/>
|
||||
<property name="arrayInitIndent" value="4"/>
|
||||
</module>
|
||||
<module name="AbbreviationAsWordInName">
|
||||
<property name="severity" value="warning"/>
|
||||
<property name="ignoreFinal" value="false"/>
|
||||
<property name="allowedAbbreviationLength" value="0"/>
|
||||
<property name="tokens"
|
||||
value="CLASS_DEF, INTERFACE_DEF, ENUM_DEF, ANNOTATION_DEF, ANNOTATION_FIELD_DEF,
|
||||
PARAMETER_DEF, VARIABLE_DEF, METHOD_DEF, PATTERN_VARIABLE_DEF, RECORD_DEF,
|
||||
RECORD_COMPONENT_DEF"/>
|
||||
</module>
|
||||
<module name="OverloadMethodsDeclarationOrder"/>
|
||||
<module name="VariableDeclarationUsageDistance">
|
||||
<property name="severity" value="warning"/>
|
||||
</module>
|
||||
<module name="CustomImportOrder">
|
||||
<property name="sortImportsInGroupAlphabetically" value="true"/>
|
||||
<property name="separateLineBetweenGroups" value="true"/>
|
||||
<property name="customImportOrderRules" value="STATIC###THIRD_PARTY_PACKAGE"/>
|
||||
<property name="tokens" value="IMPORT, STATIC_IMPORT, PACKAGE_DEF"/>
|
||||
</module>
|
||||
<module name="MethodParamPad">
|
||||
<property name="tokens"
|
||||
value="CTOR_DEF, LITERAL_NEW, METHOD_CALL, METHOD_DEF,
|
||||
SUPER_CTOR_CALL, ENUM_CONSTANT_DEF, RECORD_DEF"/>
|
||||
</module>
|
||||
<module name="NoWhitespaceBefore">
|
||||
<property name="tokens"
|
||||
value="COMMA, SEMI, POST_INC, POST_DEC, DOT,
|
||||
LABELED_STAT, METHOD_REF"/>
|
||||
<property name="allowLineBreaks" value="true"/>
|
||||
</module>
|
||||
<module name="ParenPad">
|
||||
<property name="tokens"
|
||||
value="ANNOTATION, ANNOTATION_FIELD_DEF, CTOR_CALL, CTOR_DEF, DOT, ENUM_CONSTANT_DEF,
|
||||
EXPR, LITERAL_CATCH, LITERAL_DO, LITERAL_FOR, LITERAL_IF, LITERAL_NEW,
|
||||
LITERAL_SWITCH, LITERAL_SYNCHRONIZED, LITERAL_WHILE, METHOD_CALL,
|
||||
METHOD_DEF, QUESTION, RESOURCE_SPECIFICATION, SUPER_CTOR_CALL, LAMBDA,
|
||||
RECORD_DEF"/>
|
||||
</module>
|
||||
<module name="OperatorWrap">
|
||||
<property name="option" value="NL"/>
|
||||
<property name="tokens"
|
||||
value="BAND, BOR, BSR, BXOR, DIV, EQUAL, GE, GT, LAND, LE, LITERAL_INSTANCEOF, LOR,
|
||||
LT, MINUS, MOD, NOT_EQUAL, PLUS, QUESTION, SL, SR, STAR, METHOD_REF "/>
|
||||
</module>
|
||||
<module name="AnnotationLocation">
|
||||
<property name="id" value="AnnotationLocationMostCases"/>
|
||||
<property name="tokens"
|
||||
value="CLASS_DEF, INTERFACE_DEF, ENUM_DEF, METHOD_DEF, CTOR_DEF,
|
||||
RECORD_DEF, COMPACT_CTOR_DEF"/>
|
||||
</module>
|
||||
<module name="AnnotationLocation">
|
||||
<property name="id" value="AnnotationLocationVariables"/>
|
||||
<property name="tokens" value="VARIABLE_DEF"/>
|
||||
<property name="allowSamelineMultipleAnnotations" value="true"/>
|
||||
</module>
|
||||
<module name="NonEmptyAtclauseDescription"/>
|
||||
<module name="InvalidJavadocPosition"/>
|
||||
<module name="JavadocTagContinuationIndentation">
|
||||
<property name="severity" value="warning"/>
|
||||
</module>
|
||||
<module name="SummaryJavadoc">
|
||||
<property name="severity" value="warning"/>
|
||||
<property name="forbiddenSummaryFragments"
|
||||
value="^@return the *|^This method returns |^A [{]@code [a-zA-Z0-9]+[}]( is a )"/>
|
||||
</module>
|
||||
<module name="JavadocParagraph">
|
||||
<property name="severity" value="warning"/>
|
||||
</module>
|
||||
<module name="RequireEmptyLineBeforeBlockTagGroup"/>
|
||||
<module name="AtclauseOrder">
|
||||
<property name="tagOrder" value="@param, @return, @throws, @deprecated"/>
|
||||
<property name="target"
|
||||
value="CLASS_DEF, INTERFACE_DEF, ENUM_DEF, METHOD_DEF, CTOR_DEF, VARIABLE_DEF"/>
|
||||
</module>
|
||||
<module name="JavadocMethod">
|
||||
<property name="scope" value="public"/>
|
||||
<property name="allowMissingParamTags" value="true"/>
|
||||
<property name="allowMissingReturnTag" value="true"/>
|
||||
<property name="allowedAnnotations" value="Override, Test"/>
|
||||
<property name="tokens" value="METHOD_DEF, CTOR_DEF, ANNOTATION_FIELD_DEF, COMPACT_CTOR_DEF"/>
|
||||
</module>
|
||||
<module name="MissingJavadocMethod">
|
||||
<property name="severity" value="warning"/>
|
||||
<property name="scope" value="public"/>
|
||||
<property name="minLineCount" value="2"/>
|
||||
<property name="allowedAnnotations" value="Override, Test"/>
|
||||
<property name="tokens" value="METHOD_DEF, CTOR_DEF, ANNOTATION_FIELD_DEF,
|
||||
COMPACT_CTOR_DEF"/>
|
||||
</module>
|
||||
<module name="MethodName">
|
||||
<property name="format" value="^[a-z][a-z0-9][a-zA-Z0-9_]*$"/>
|
||||
<message key="name.invalidPattern"
|
||||
value="Method name ''{0}'' must match pattern ''{1}''."/>
|
||||
</module>
|
||||
<module name="SingleLineJavadoc">
|
||||
<property name="ignoreInlineTags" value="false"/>
|
||||
</module>
|
||||
<module name="EmptyCatchBlock">
|
||||
<property name="exceptionVariableName" value="expected"/>
|
||||
</module>
|
||||
<module name="CommentsIndentation">
|
||||
<property name="tokens" value="SINGLE_LINE_COMMENT, BLOCK_COMMENT_BEGIN"/>
|
||||
</module>
|
||||
<!-- https://checkstyle.org/config_filters.html#SuppressionXpathFilter -->
|
||||
<module name="SuppressionXpathFilter">
|
||||
<property name="file" value="${org.checkstyle.google.suppressionxpathfilter.config}"
|
||||
default="checkstyle-xpath-suppressions.xml"/>
|
||||
<property name="optional" value="true"/>
|
||||
</module>
|
||||
<module name="MethodParamPad"/>
|
||||
<module name="ParenPad"/>
|
||||
<module name="TypecastParenPad"/>
|
||||
|
||||
</module>
|
||||
|
||||
</module>
|
||||
|
|
|
@ -15,7 +15,7 @@ public class Application {
|
|||
public static void main(String[] args) {
|
||||
// Customize the spring config location
|
||||
System.setProperty("spring.config.additional-location",
|
||||
"optional:file:${user.home}/.halo/,optional:file:${user.home}/halo-dev/");
|
||||
"optional:file:${user.home}/.halo/,optional:file:${user.home}/halo-dev/");
|
||||
|
||||
// Run application
|
||||
SpringApplication.run(Application.class, args);
|
||||
|
|
|
@ -1,10 +1,13 @@
|
|||
package run.halo.app.annotation;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import org.springframework.core.annotation.AliasFor;
|
||||
import run.halo.app.model.enums.Mode;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* 该注解可以限制某些条件下禁止访问api
|
||||
*
|
||||
|
|
|
@ -1,7 +1,11 @@
|
|||
package run.halo.app.annotation;
|
||||
|
||||
|
||||
import java.lang.annotation.*;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Inherited;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* @author giveup
|
||||
|
|
|
@ -28,13 +28,14 @@ public class DisableOnConditionAspect {
|
|||
this.haloProperties = haloProperties;
|
||||
}
|
||||
|
||||
@Pointcut("execution(* run.halo.app.controller.*.*(..)) && @annotation(run.halo.app.annotation.DisableOnCondition)")
|
||||
@Pointcut("execution(* run.halo.app.controller.*.*(..)) "
|
||||
+ "&& @annotation(run.halo.app.annotation.DisableOnCondition)")
|
||||
public void pointcut() {
|
||||
}
|
||||
|
||||
@Around("pointcut() && @annotation(disableApi)")
|
||||
public Object around(ProceedingJoinPoint joinPoint,
|
||||
DisableOnCondition disableApi) throws Throwable {
|
||||
DisableOnCondition disableApi) throws Throwable {
|
||||
Mode mode = disableApi.mode();
|
||||
if (haloProperties.getMode().equals(mode)) {
|
||||
throw new ForbiddenException("禁止访问");
|
||||
|
|
|
@ -19,7 +19,8 @@ import run.halo.app.security.context.SecurityContextHolder;
|
|||
public class SensitiveConcealAspect {
|
||||
|
||||
|
||||
@Pointcut("execution(* run.halo.app.repository.*.*(..)) && @annotation(run.halo.app.annotation.SensitiveConceal)")
|
||||
@Pointcut("execution(* run.halo.app.repository.*.*(..)) "
|
||||
+ "&& @annotation(run.halo.app.annotation.SensitiveConceal)")
|
||||
public void pointCut() {
|
||||
}
|
||||
|
||||
|
@ -31,27 +32,15 @@ public class SensitiveConcealAspect {
|
|||
return comment;
|
||||
}
|
||||
|
||||
|
||||
@Around("pointCut()")
|
||||
public Object mask(ProceedingJoinPoint joinPoint) throws Throwable {
|
||||
|
||||
Object result = joinPoint.proceed();
|
||||
|
||||
if (SecurityContextHolder.getContext().isAuthenticated()) {
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
if (result instanceof Iterable) {
|
||||
|
||||
((Iterable<?>) result).forEach(this::sensitiveMask);
|
||||
|
||||
}
|
||||
|
||||
return sensitiveMask(result);
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
package run.halo.app.cache;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.lang.NonNull;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
@ -7,10 +10,6 @@ import org.springframework.util.Assert;
|
|||
import run.halo.app.config.properties.HaloProperties;
|
||||
import run.halo.app.utils.DateUtils;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* Abstract cache store.
|
||||
*
|
||||
|
@ -34,7 +33,7 @@ public abstract class AbstractCacheStore<K, V> implements CacheStore<K, V> {
|
|||
/**
|
||||
* Puts the cache wrapper.
|
||||
*
|
||||
* @param key key must not be null
|
||||
* @param key key must not be null
|
||||
* @param cacheWrapper cache wrapper must not be null
|
||||
*/
|
||||
abstract void putInternal(@NonNull K key, @NonNull CacheWrapper<V> cacheWrapper);
|
||||
|
@ -42,19 +41,21 @@ public abstract class AbstractCacheStore<K, V> implements CacheStore<K, V> {
|
|||
/**
|
||||
* Puts the cache wrapper if the key is absent.
|
||||
*
|
||||
* @param key key must not be null
|
||||
* @param key key must not be null
|
||||
* @param cacheWrapper cache wrapper must not be null
|
||||
* @return true if the key is absent and the value is set, false if the key is present before, or null if any other reason
|
||||
* @return true if the key is absent and the value is set, false if the key is present
|
||||
* before, or null if any other reason
|
||||
*/
|
||||
abstract Boolean putInternalIfAbsent(@NonNull K key, @NonNull CacheWrapper<V> cacheWrapper);
|
||||
|
||||
@Override
|
||||
public @NonNull Optional<V> get(@NonNull K key) {
|
||||
public Optional<V> get(K key) {
|
||||
Assert.notNull(key, "Cache key must not be blank");
|
||||
|
||||
return getInternal(key).map(cacheWrapper -> {
|
||||
// Check expiration
|
||||
if (cacheWrapper.getExpireAt() != null && cacheWrapper.getExpireAt().before(run.halo.app.utils.DateUtils.now())) {
|
||||
if (cacheWrapper.getExpireAt() != null
|
||||
&& cacheWrapper.getExpireAt().before(run.halo.app.utils.DateUtils.now())) {
|
||||
// Expired then delete it
|
||||
log.warn("Cache key: [{}] has been expired", key);
|
||||
|
||||
|
@ -70,30 +71,32 @@ public abstract class AbstractCacheStore<K, V> implements CacheStore<K, V> {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void put(@NonNull K key, @NonNull V value, long timeout, @NonNull TimeUnit timeUnit) {
|
||||
public void put(K key, V value, long timeout, TimeUnit timeUnit) {
|
||||
putInternal(key, buildCacheWrapper(value, timeout, timeUnit));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean putIfAbsent(@NonNull K key, @NonNull V value, long timeout, @NonNull TimeUnit timeUnit) {
|
||||
return putInternalIfAbsent(key, buildCacheWrapper(value, timeout, timeUnit));
|
||||
public void put(K key, V value) {
|
||||
putInternal(key, buildCacheWrapper(value, 0, null));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void put(@NonNull K key, @NonNull V value) {
|
||||
putInternal(key, buildCacheWrapper(value, 0, null));
|
||||
public Boolean putIfAbsent(K key, V value, long timeout, TimeUnit timeUnit) {
|
||||
return putInternalIfAbsent(key, buildCacheWrapper(value, timeout, timeUnit));
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds cache wrapper.
|
||||
*
|
||||
* @param value cache value must not be null
|
||||
* @param timeout the key expiry time, if the expiry time is less than 1, the cache won't be expired
|
||||
* @param value cache value must not be null
|
||||
* @param timeout the key expiry time, if the expiry time is less than 1, the cache won't be
|
||||
* expired
|
||||
* @param timeUnit timeout unit must
|
||||
* @return cache wrapper
|
||||
*/
|
||||
@NonNull
|
||||
private CacheWrapper<V> buildCacheWrapper(@NonNull V value, long timeout, @Nullable TimeUnit timeUnit) {
|
||||
private CacheWrapper<V> buildCacheWrapper(@NonNull V value, long timeout,
|
||||
@Nullable TimeUnit timeUnit) {
|
||||
Assert.notNull(value, "Cache value must not be null");
|
||||
Assert.isTrue(timeout >= 0, "Cache expiration timeout must not be less than 1");
|
||||
|
||||
|
|
|
@ -1,16 +1,15 @@
|
|||
package run.halo.app.cache;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import java.io.IOException;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.lang.NonNull;
|
||||
import org.springframework.util.Assert;
|
||||
import run.halo.app.exception.ServiceException;
|
||||
import run.halo.app.utils.JsonUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* String cache store.
|
||||
*
|
||||
|
@ -38,7 +37,8 @@ public abstract class AbstractStringCacheStore extends AbstractCacheStore<String
|
|||
}
|
||||
}
|
||||
|
||||
public <T> void putAny(@NonNull String key, @NonNull T value, long timeout, @NonNull TimeUnit timeUnit) {
|
||||
public <T> void putAny(@NonNull String key, @NonNull T value, long timeout,
|
||||
@NonNull TimeUnit timeUnit) {
|
||||
try {
|
||||
put(key, JsonUtils.objectToJson(value), timeout, timeUnit);
|
||||
} catch (JsonProcessingException e) {
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
package run.halo.app.cache;
|
||||
|
||||
import org.springframework.lang.NonNull;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import org.springframework.lang.NonNull;
|
||||
|
||||
/**
|
||||
* Cache store interface.
|
||||
|
@ -27,32 +26,34 @@ public interface CacheStore<K, V> {
|
|||
/**
|
||||
* Puts a cache which will be expired.
|
||||
*
|
||||
* @param key cache key must not be null
|
||||
* @param value cache value must not be null
|
||||
* @param timeout the key expiration must not be less than 1
|
||||
* @param key cache key must not be null
|
||||
* @param value cache value must not be null
|
||||
* @param timeout the key expiration must not be less than 1
|
||||
* @param timeUnit timeout unit
|
||||
*/
|
||||
void put(@NonNull K key, @NonNull V value, long timeout, @NonNull TimeUnit timeUnit);
|
||||
|
||||
/**
|
||||
* Puts a cache which will be expired if the key is absent.
|
||||
*
|
||||
* @param key cache key must not be null
|
||||
* @param value cache value must not be null
|
||||
* @param timeout the key expiration must not be less than 1
|
||||
* @param timeUnit timeout unit must not be null
|
||||
* @return true if the key is absent and the value is set, false if the key is present before, or null if any other reason
|
||||
*/
|
||||
Boolean putIfAbsent(@NonNull K key, @NonNull V value, long timeout, @NonNull TimeUnit timeUnit);
|
||||
|
||||
/**
|
||||
* Puts a non-expired cache.
|
||||
*
|
||||
* @param key cache key must not be null
|
||||
* @param key cache key must not be null
|
||||
* @param value cache value must not be null
|
||||
*/
|
||||
void put(@NonNull K key, @NonNull V value);
|
||||
|
||||
/**
|
||||
* Puts a cache which will be expired if the key is absent.
|
||||
*
|
||||
* @param key cache key must not be null
|
||||
* @param value cache value must not be null
|
||||
* @param timeout the key expiration must not be less than 1
|
||||
* @param timeUnit timeout unit must not be null
|
||||
* @return true if the key is absent and the value is set, false if the key is present
|
||||
* before, or null if any other reason
|
||||
*/
|
||||
Boolean putIfAbsent(@NonNull K key, @NonNull V value, long timeout, @NonNull TimeUnit timeUnit);
|
||||
|
||||
/**
|
||||
* Delete a key.
|
||||
*
|
||||
|
|
|
@ -1,9 +1,12 @@
|
|||
package run.halo.app.cache;
|
||||
|
||||
import lombok.*;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.ToString;
|
||||
|
||||
/**
|
||||
* Cache wrapper.
|
||||
|
|
|
@ -1,16 +1,15 @@
|
|||
package run.halo.app.cache;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.lang.NonNull;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import javax.annotation.PreDestroy;
|
||||
import java.util.Optional;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
import javax.annotation.PreDestroy;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.lang.NonNull;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* In-memory cache store.
|
||||
|
@ -23,12 +22,13 @@ public class InMemoryCacheStore extends AbstractStringCacheStore {
|
|||
/**
|
||||
* Cleaner schedule period. (ms)
|
||||
*/
|
||||
private final static long PERIOD = 60 * 1000;
|
||||
private static final long PERIOD = 60 * 1000;
|
||||
|
||||
/**
|
||||
* Cache container.
|
||||
*/
|
||||
private final static ConcurrentHashMap<String, CacheWrapper<String>> CACHE_CONTAINER = new ConcurrentHashMap<>();
|
||||
private static final ConcurrentHashMap<String, CacheWrapper<String>> CACHE_CONTAINER =
|
||||
new ConcurrentHashMap<>();
|
||||
|
||||
private final Timer timer;
|
||||
|
||||
|
@ -59,7 +59,8 @@ public class InMemoryCacheStore extends AbstractStringCacheStore {
|
|||
// Put the cache wrapper
|
||||
CacheWrapper<String> putCacheWrapper = CACHE_CONTAINER.put(key, cacheWrapper);
|
||||
|
||||
log.debug("Put [{}] cache result: [{}], original cache wrapper: [{}]", key, putCacheWrapper, cacheWrapper);
|
||||
log.debug("Put [{}] cache result: [{}], original cache wrapper: [{}]", key, putCacheWrapper,
|
||||
cacheWrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -75,7 +76,8 @@ public class InMemoryCacheStore extends AbstractStringCacheStore {
|
|||
Optional<String> valueOptional = get(key);
|
||||
|
||||
if (valueOptional.isPresent()) {
|
||||
log.warn("Failed to put the cache, because the key: [{}] has been present already", key);
|
||||
log.warn("Failed to put the cache, because the key: [{}] has been present already",
|
||||
key);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,8 +1,22 @@
|
|||
package run.halo.app.cache;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
import javax.annotation.PostConstruct;
|
||||
import javax.annotation.PreDestroy;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.iq80.leveldb.*;
|
||||
import org.iq80.leveldb.DB;
|
||||
import org.iq80.leveldb.DBFactory;
|
||||
import org.iq80.leveldb.DBIterator;
|
||||
import org.iq80.leveldb.Options;
|
||||
import org.iq80.leveldb.WriteBatch;
|
||||
import org.iq80.leveldb.impl.Iq80DBFactory;
|
||||
import org.springframework.lang.NonNull;
|
||||
import org.springframework.util.Assert;
|
||||
|
@ -10,13 +24,6 @@ import org.springframework.util.StringUtils;
|
|||
import run.halo.app.config.properties.HaloProperties;
|
||||
import run.halo.app.utils.JsonUtils;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import javax.annotation.PreDestroy;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* level-db cache store
|
||||
* Create by Pencilso on 2020/1/9 7:20 下午
|
||||
|
@ -26,7 +33,7 @@ public class LevelCacheStore extends AbstractStringCacheStore {
|
|||
/**
|
||||
* Cleaner schedule period. (ms)
|
||||
*/
|
||||
private final static long PERIOD = 60 * 1000;
|
||||
private static final long PERIOD = 60 * 1000;
|
||||
|
||||
private static DB LEVEL_DB;
|
||||
|
||||
|
@ -76,7 +83,8 @@ public class LevelCacheStore extends AbstractStringCacheStore {
|
|||
byte[] bytes = LEVEL_DB.get(stringToBytes(key));
|
||||
if (bytes != null) {
|
||||
String valueJson = bytesToString(bytes);
|
||||
return StringUtils.isEmpty(valueJson) ? Optional.empty() : jsonToCacheWrapper(valueJson);
|
||||
return StringUtils.isEmpty(valueJson) ? Optional.empty() :
|
||||
jsonToCacheWrapper(valueJson);
|
||||
}
|
||||
return Optional.empty();
|
||||
}
|
||||
|
@ -92,8 +100,8 @@ public class LevelCacheStore extends AbstractStringCacheStore {
|
|||
Assert.notNull(cacheWrapper, "Cache wrapper must not be null");
|
||||
try {
|
||||
LEVEL_DB.put(
|
||||
stringToBytes(key),
|
||||
stringToBytes(JsonUtils.objectToJson(cacheWrapper))
|
||||
stringToBytes(key),
|
||||
stringToBytes(JsonUtils.objectToJson(cacheWrapper))
|
||||
);
|
||||
return true;
|
||||
} catch (JsonProcessingException e) {
|
||||
|
@ -134,16 +142,19 @@ public class LevelCacheStore extends AbstractStringCacheStore {
|
|||
}
|
||||
|
||||
String valueJson = bytesToString(next.getValue());
|
||||
Optional<CacheWrapper<String>> stringCacheWrapper = StringUtils.isEmpty(valueJson) ? Optional.empty() : jsonToCacheWrapper(valueJson);
|
||||
Optional<CacheWrapper<String>> stringCacheWrapper =
|
||||
StringUtils.isEmpty(valueJson) ? Optional.empty() :
|
||||
jsonToCacheWrapper(valueJson);
|
||||
if (stringCacheWrapper.isPresent()) {
|
||||
//get expireat time
|
||||
long expireAtTime = stringCacheWrapper.map(CacheWrapper::getExpireAt)
|
||||
.map(Date::getTime)
|
||||
.orElse(0L);
|
||||
.map(Date::getTime)
|
||||
.orElse(0L);
|
||||
//if expire
|
||||
if (expireAtTime != 0 && currentTimeMillis > expireAtTime) {
|
||||
writeBatch.delete(next.getKey());
|
||||
log.debug("deleted the cache: [{}] for expiration", bytesToString(next.getKey()));
|
||||
log.debug("deleted the cache: [{}] for expiration",
|
||||
bytesToString(next.getKey()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,9 +1,13 @@
|
|||
package run.halo.app.cache.lock;
|
||||
|
||||
import org.springframework.core.annotation.AliasFor;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Inherited;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import org.springframework.core.annotation.AliasFor;
|
||||
|
||||
/**
|
||||
* Cache lock annotation.
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package run.halo.app.cache.lock;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.aspectj.lang.ProceedingJoinPoint;
|
||||
|
@ -14,8 +15,6 @@ import run.halo.app.exception.FrequentAccessException;
|
|||
import run.halo.app.exception.ServiceException;
|
||||
import run.halo.app.utils.ServletUtils;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
|
||||
/**
|
||||
* Interceptor for cache lock annotation.
|
||||
*
|
||||
|
@ -27,9 +26,9 @@ import java.lang.annotation.Annotation;
|
|||
@Configuration
|
||||
public class CacheLockInterceptor {
|
||||
|
||||
private final static String CACHE_LOCK_PREFOX = "cache_lock_";
|
||||
private static final String CACHE_LOCK_PREFIX = "cache_lock_";
|
||||
|
||||
private final static String CACHE_LOCK_VALUE = "locked";
|
||||
private static final String CACHE_LOCK_VALUE = "locked";
|
||||
|
||||
private final AbstractStringCacheStore cacheStore;
|
||||
|
||||
|
@ -55,10 +54,13 @@ public class CacheLockInterceptor {
|
|||
|
||||
try {
|
||||
// Get from cache
|
||||
Boolean cacheResult = cacheStore.putIfAbsent(cacheLockKey, CACHE_LOCK_VALUE, cacheLock.expired(), cacheLock.timeUnit());
|
||||
Boolean cacheResult = cacheStore
|
||||
.putIfAbsent(cacheLockKey, CACHE_LOCK_VALUE, cacheLock.expired(),
|
||||
cacheLock.timeUnit());
|
||||
|
||||
if (cacheResult == null) {
|
||||
throw new ServiceException("Unknown reason of cache " + cacheLockKey).setErrorData(cacheLockKey);
|
||||
throw new ServiceException("Unknown reason of cache " + cacheLockKey)
|
||||
.setErrorData(cacheLockKey);
|
||||
}
|
||||
|
||||
if (!cacheResult) {
|
||||
|
@ -76,7 +78,8 @@ public class CacheLockInterceptor {
|
|||
}
|
||||
}
|
||||
|
||||
private String buildCacheLockKey(@NonNull CacheLock cacheLock, @NonNull ProceedingJoinPoint joinPoint) {
|
||||
private String buildCacheLockKey(@NonNull CacheLock cacheLock,
|
||||
@NonNull ProceedingJoinPoint joinPoint) {
|
||||
Assert.notNull(cacheLock, "Cache lock must not be null");
|
||||
Assert.notNull(joinPoint, "Proceeding join point must not be null");
|
||||
|
||||
|
@ -84,7 +87,7 @@ public class CacheLockInterceptor {
|
|||
MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
|
||||
|
||||
// Build the cache lock key
|
||||
StringBuilder cacheKeyBuilder = new StringBuilder(CACHE_LOCK_PREFOX);
|
||||
StringBuilder cacheKeyBuilder = new StringBuilder(CACHE_LOCK_PREFIX);
|
||||
|
||||
String delimiter = cacheLock.delimiter();
|
||||
|
||||
|
|
|
@ -1,6 +1,11 @@
|
|||
package run.halo.app.cache.lock;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Inherited;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Cache parameter annotation.
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
package run.halo.app.config;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import java.security.KeyManagementException;
|
||||
import java.security.KeyStoreException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
|
@ -21,10 +24,6 @@ import run.halo.app.config.properties.HaloProperties;
|
|||
import run.halo.app.repository.base.BaseRepositoryImpl;
|
||||
import run.halo.app.utils.HttpClientUtils;
|
||||
|
||||
import java.security.KeyManagementException;
|
||||
import java.security.KeyStoreException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
|
||||
/**
|
||||
* Halo configuration.
|
||||
*
|
||||
|
@ -35,7 +34,8 @@ import java.security.NoSuchAlgorithmException;
|
|||
@EnableScheduling
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@EnableConfigurationProperties(HaloProperties.class)
|
||||
@EnableJpaRepositories(basePackages = "run.halo.app.repository", repositoryBaseClass = BaseRepositoryImpl.class)
|
||||
@EnableJpaRepositories(basePackages = "run.halo.app.repository", repositoryBaseClass =
|
||||
BaseRepositoryImpl.class)
|
||||
public class HaloConfiguration {
|
||||
|
||||
@Autowired
|
||||
|
@ -49,9 +49,10 @@ public class HaloConfiguration {
|
|||
|
||||
@Bean
|
||||
public RestTemplate httpsRestTemplate(RestTemplateBuilder builder)
|
||||
throws NoSuchAlgorithmException, KeyStoreException, KeyManagementException {
|
||||
throws NoSuchAlgorithmException, KeyStoreException, KeyManagementException {
|
||||
RestTemplate httpsRestTemplate = builder.build();
|
||||
httpsRestTemplate.setRequestFactory(new HttpComponentsClientHttpRequestFactory(HttpClientUtils.createHttpsClient(
|
||||
httpsRestTemplate.setRequestFactory(
|
||||
new HttpComponentsClientHttpRequestFactory(HttpClientUtils.createHttpsClient(
|
||||
(int) haloProperties.getDownloadTimeout().toMillis())));
|
||||
return httpsRestTemplate;
|
||||
}
|
||||
|
|
|
@ -1,9 +1,19 @@
|
|||
package run.halo.app.config;
|
||||
|
||||
import static run.halo.app.model.support.HaloConst.FILE_SEPARATOR;
|
||||
import static run.halo.app.utils.HaloUtils.URL_SEPARATOR;
|
||||
import static run.halo.app.utils.HaloUtils.ensureBoth;
|
||||
import static run.halo.app.utils.HaloUtils.ensureSuffix;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import freemarker.core.TemplateClassResolver;
|
||||
import freemarker.template.TemplateException;
|
||||
import freemarker.template.TemplateExceptionHandler;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import javax.servlet.MultipartConfigElement;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
|
||||
|
@ -38,15 +48,6 @@ import run.halo.app.factory.StringToEnumConverterFactory;
|
|||
import run.halo.app.model.support.HaloConst;
|
||||
import run.halo.app.security.resolver.AuthenticationArgumentResolver;
|
||||
|
||||
import javax.servlet.MultipartConfigElement;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import static run.halo.app.model.support.HaloConst.FILE_SEPARATOR;
|
||||
import static run.halo.app.utils.HaloUtils.*;
|
||||
|
||||
/**
|
||||
* Halo mvc configuration.
|
||||
*
|
||||
|
@ -60,19 +61,15 @@ import static run.halo.app.utils.HaloUtils.*;
|
|||
public class HaloMvcConfiguration implements WebMvcConfigurer {
|
||||
|
||||
private static final String FILE_PROTOCOL = "file:///";
|
||||
|
||||
private final PageableHandlerMethodArgumentResolver pageableResolver;
|
||||
private final SortHandlerMethodArgumentResolver sortResolver;
|
||||
private final HaloProperties haloProperties;
|
||||
@Value("${springfox.documentation.swagger-ui.base-url:}")
|
||||
private String swaggerBaseUrl;
|
||||
|
||||
private final PageableHandlerMethodArgumentResolver pageableResolver;
|
||||
|
||||
private final SortHandlerMethodArgumentResolver sortResolver;
|
||||
|
||||
private final HaloProperties haloProperties;
|
||||
|
||||
public HaloMvcConfiguration(PageableHandlerMethodArgumentResolver pageableResolver,
|
||||
SortHandlerMethodArgumentResolver sortResolver,
|
||||
HaloProperties haloProperties) {
|
||||
SortHandlerMethodArgumentResolver sortResolver,
|
||||
HaloProperties haloProperties) {
|
||||
this.pageableResolver = pageableResolver;
|
||||
this.sortResolver = sortResolver;
|
||||
this.haloProperties = haloProperties;
|
||||
|
@ -84,13 +81,17 @@ public class HaloMvcConfiguration implements WebMvcConfigurer {
|
|||
* @return new FreeMarkerConfigurer
|
||||
*/
|
||||
@Bean
|
||||
FreeMarkerConfigurer freemarkerConfig(HaloProperties haloProperties) throws IOException, TemplateException {
|
||||
FreeMarkerConfigurer freemarkerConfig(HaloProperties haloProperties)
|
||||
throws IOException, TemplateException {
|
||||
FreeMarkerConfigurer configurer = new FreeMarkerConfigurer();
|
||||
configurer.setTemplateLoaderPaths(FILE_PROTOCOL + haloProperties.getWorkDir() + "templates/", "classpath:/templates/");
|
||||
configurer
|
||||
.setTemplateLoaderPaths(FILE_PROTOCOL + haloProperties.getWorkDir() + "templates/",
|
||||
"classpath:/templates/");
|
||||
configurer.setDefaultEncoding("UTF-8");
|
||||
|
||||
Properties properties = new Properties();
|
||||
properties.setProperty("auto_import", "/common/macro/common_macro.ftl as common,/common/macro/global_macro.ftl as global");
|
||||
properties.setProperty("auto_import",
|
||||
"/common/macro/common_macro.ftl as common,/common/macro/global_macro.ftl as global");
|
||||
|
||||
configurer.setFreemarkerSettings(properties);
|
||||
|
||||
|
@ -122,7 +123,8 @@ public class HaloMvcConfiguration implements WebMvcConfigurer {
|
|||
resolver.setMaxUploadSize(multipartConfigElement.getMaxRequestSize());
|
||||
resolver.setMaxUploadSizePerFile(multipartConfigElement.getMaxFileSize());
|
||||
|
||||
//lazy multipart parsing, throwing parse exceptions once the application attempts to obtain multipart files
|
||||
//lazy multipart parsing, throwing parse exceptions once the application attempts to
|
||||
// obtain multipart files
|
||||
resolver.setResolveLazily(true);
|
||||
|
||||
return resolver;
|
||||
|
@ -141,16 +143,17 @@ public class HaloMvcConfiguration implements WebMvcConfigurer {
|
|||
@Override
|
||||
public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
|
||||
converters.stream()
|
||||
.filter(c -> c instanceof MappingJackson2HttpMessageConverter)
|
||||
.findFirst()
|
||||
.ifPresent(converter -> {
|
||||
MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter = (MappingJackson2HttpMessageConverter) converter;
|
||||
Jackson2ObjectMapperBuilder builder = Jackson2ObjectMapperBuilder.json();
|
||||
JsonComponentModule module = new JsonComponentModule();
|
||||
module.addSerializer(PageImpl.class, new PageJacksonSerializer());
|
||||
ObjectMapper objectMapper = builder.modules(module).build();
|
||||
mappingJackson2HttpMessageConverter.setObjectMapper(objectMapper);
|
||||
});
|
||||
.filter(c -> c instanceof MappingJackson2HttpMessageConverter)
|
||||
.findFirst()
|
||||
.ifPresent(converter -> {
|
||||
MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter =
|
||||
(MappingJackson2HttpMessageConverter) converter;
|
||||
Jackson2ObjectMapperBuilder builder = Jackson2ObjectMapperBuilder.json();
|
||||
JsonComponentModule module = new JsonComponentModule();
|
||||
module.addSerializer(PageImpl.class, new PageJacksonSerializer());
|
||||
ObjectMapper objectMapper = builder.modules(module).build();
|
||||
mappingJackson2HttpMessageConverter.setObjectMapper(objectMapper);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -164,7 +167,7 @@ public class HaloMvcConfiguration implements WebMvcConfigurer {
|
|||
public void addViewControllers(ViewControllerRegistry registry) {
|
||||
// for backward compatibility
|
||||
registry.addViewController("/swagger-ui.html")
|
||||
.setViewName("redirect:" + swaggerBaseUrl + "/swagger-ui/");
|
||||
.setViewName("redirect:" + swaggerBaseUrl + "/swagger-ui/");
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -178,27 +181,28 @@ public class HaloMvcConfiguration implements WebMvcConfigurer {
|
|||
|
||||
// register /** resource handler.
|
||||
registry.addResourceHandler("/**")
|
||||
.addResourceLocations("classpath:/admin/")
|
||||
.addResourceLocations(workDir + "static/");
|
||||
.addResourceLocations("classpath:/admin/")
|
||||
.addResourceLocations(workDir + "static/");
|
||||
|
||||
// register /themes/** resource handler.
|
||||
registry.addResourceHandler("/themes/**")
|
||||
.addResourceLocations(workDir + "templates/themes/");
|
||||
.addResourceLocations(workDir + "templates/themes/");
|
||||
|
||||
String uploadUrlPattern = ensureBoth(haloProperties.getUploadUrlPrefix(), URL_SEPARATOR) + "**";
|
||||
String uploadUrlPattern =
|
||||
ensureBoth(haloProperties.getUploadUrlPrefix(), URL_SEPARATOR) + "**";
|
||||
String adminPathPattern = ensureSuffix(haloProperties.getAdminPath(), URL_SEPARATOR) + "**";
|
||||
|
||||
registry.addResourceHandler(uploadUrlPattern)
|
||||
.setCacheControl(CacheControl.maxAge(7L, TimeUnit.DAYS))
|
||||
.addResourceLocations(workDir + "upload/");
|
||||
.setCacheControl(CacheControl.maxAge(7L, TimeUnit.DAYS))
|
||||
.addResourceLocations(workDir + "upload/");
|
||||
registry.addResourceHandler(adminPathPattern)
|
||||
.addResourceLocations("classpath:/admin/");
|
||||
.addResourceLocations("classpath:/admin/");
|
||||
|
||||
// If doc is enable
|
||||
registry.addResourceHandler("swagger-ui.html")
|
||||
.addResourceLocations("classpath:/META-INF/resources/");
|
||||
.addResourceLocations("classpath:/META-INF/resources/");
|
||||
registry.addResourceHandler("/webjars/**")
|
||||
.addResourceLocations("classpath:/META-INF/resources/webjars/");
|
||||
.addResourceLocations("classpath:/META-INF/resources/webjars/");
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1,5 +1,15 @@
|
|||
package run.halo.app.config;
|
||||
|
||||
import static run.halo.app.utils.HaloUtils.URL_SEPARATOR;
|
||||
import static run.halo.app.utils.HaloUtils.ensureBoth;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Stream;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.util.AntPathMatcher;
|
||||
|
@ -9,24 +19,13 @@ import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandl
|
|||
import run.halo.app.config.properties.HaloProperties;
|
||||
import run.halo.app.event.StaticStorageChangedEvent;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static run.halo.app.utils.HaloUtils.URL_SEPARATOR;
|
||||
import static run.halo.app.utils.HaloUtils.ensureBoth;
|
||||
|
||||
/**
|
||||
* @author ryanwang
|
||||
* @date 2020-03-24
|
||||
*/
|
||||
@Slf4j
|
||||
public class HaloRequestMappingHandlerMapping extends RequestMappingHandlerMapping
|
||||
implements ApplicationListener<StaticStorageChangedEvent> {
|
||||
implements ApplicationListener<StaticStorageChangedEvent> {
|
||||
|
||||
private final Set<String> blackPatterns = new HashSet<>(16);
|
||||
|
||||
|
@ -41,7 +40,8 @@ public class HaloRequestMappingHandlerMapping extends RequestMappingHandlerMappi
|
|||
}
|
||||
|
||||
@Override
|
||||
protected HandlerMethod lookupHandlerMethod(String lookupPath, HttpServletRequest request) throws Exception {
|
||||
protected HandlerMethod lookupHandlerMethod(String lookupPath, HttpServletRequest request)
|
||||
throws Exception {
|
||||
log.debug("Looking path: [{}]", lookupPath);
|
||||
for (String blackPattern : blackPatterns) {
|
||||
if (this.pathMatcher.match(blackPattern, lookupPath)) {
|
||||
|
@ -53,8 +53,10 @@ public class HaloRequestMappingHandlerMapping extends RequestMappingHandlerMappi
|
|||
}
|
||||
|
||||
private void initBlackPatterns() {
|
||||
String uploadUrlPattern = ensureBoth(haloProperties.getUploadUrlPrefix(), URL_SEPARATOR) + "**";
|
||||
String adminPathPattern = ensureBoth(haloProperties.getAdminPath(), URL_SEPARATOR) + "?*/**";
|
||||
String uploadUrlPattern =
|
||||
ensureBoth(haloProperties.getUploadUrlPrefix(), URL_SEPARATOR) + "**";
|
||||
String adminPathPattern =
|
||||
ensureBoth(haloProperties.getAdminPath(), URL_SEPARATOR) + "?*/**";
|
||||
|
||||
blackPatterns.add("/themes/**");
|
||||
blackPatterns.add("/js/**");
|
||||
|
@ -79,16 +81,17 @@ public class HaloRequestMappingHandlerMapping extends RequestMappingHandlerMappi
|
|||
blackPatterns.clear();
|
||||
initBlackPatterns();
|
||||
rootPathStream.forEach(rootPath -> {
|
||||
if (Files.isDirectory(rootPath)) {
|
||||
String directoryPattern = "/" + rootPath.getFileName().toString() + "/**";
|
||||
blackPatterns.add(directoryPattern);
|
||||
log.debug("Exclude for folder path pattern: [{}]", directoryPattern);
|
||||
} else {
|
||||
String pathPattern = "/" + rootPath.getFileName().toString();
|
||||
blackPatterns.add(pathPattern);
|
||||
log.debug("Exclude for file path pattern: [{}]", pathPattern);
|
||||
}
|
||||
if (Files.isDirectory(rootPath)) {
|
||||
String directoryPattern = "/" + rootPath.getFileName().toString()
|
||||
+ "/**";
|
||||
blackPatterns.add(directoryPattern);
|
||||
log.debug("Exclude for folder path pattern: [{}]", directoryPattern);
|
||||
} else {
|
||||
String pathPattern = "/" + rootPath.getFileName().toString();
|
||||
blackPatterns.add(pathPattern);
|
||||
log.debug("Exclude for file path pattern: [{}]", pathPattern);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
|
|
|
@ -1,7 +1,19 @@
|
|||
package run.halo.app.config;
|
||||
|
||||
import static run.halo.app.model.support.HaloConst.ADMIN_TOKEN_HEADER_NAME;
|
||||
import static run.halo.app.model.support.HaloConst.ADMIN_TOKEN_QUERY_NAME;
|
||||
import static run.halo.app.model.support.HaloConst.API_ACCESS_KEY_HEADER_NAME;
|
||||
import static run.halo.app.model.support.HaloConst.API_ACCESS_KEY_QUERY_NAME;
|
||||
import static run.halo.app.model.support.HaloConst.HALO_VERSION;
|
||||
import static springfox.documentation.schema.AlternateTypeRules.newRule;
|
||||
|
||||
import com.fasterxml.classmate.TypeResolver;
|
||||
import io.swagger.models.auth.In;
|
||||
import java.lang.reflect.Type;
|
||||
import java.time.temporal.Temporal;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
|
@ -15,23 +27,32 @@ import org.springframework.web.bind.annotation.RequestMethod;
|
|||
import run.halo.app.config.properties.HaloProperties;
|
||||
import run.halo.app.model.entity.User;
|
||||
import run.halo.app.security.support.UserDetail;
|
||||
import springfox.documentation.builders.*;
|
||||
import springfox.documentation.builders.AlternateTypeBuilder;
|
||||
import springfox.documentation.builders.AlternateTypePropertyBuilder;
|
||||
import springfox.documentation.builders.ApiInfoBuilder;
|
||||
import springfox.documentation.builders.PathSelectors;
|
||||
import springfox.documentation.builders.RequestHandlerSelectors;
|
||||
import springfox.documentation.builders.ResponseMessageBuilder;
|
||||
import springfox.documentation.schema.AlternateTypeRule;
|
||||
import springfox.documentation.schema.AlternateTypeRuleConvention;
|
||||
import springfox.documentation.service.*;
|
||||
import springfox.documentation.service.ApiInfo;
|
||||
import springfox.documentation.service.ApiKey;
|
||||
import springfox.documentation.service.AuthorizationScope;
|
||||
import springfox.documentation.service.Contact;
|
||||
import springfox.documentation.service.ResponseMessage;
|
||||
import springfox.documentation.service.SecurityReference;
|
||||
import springfox.documentation.service.SecurityScheme;
|
||||
import springfox.documentation.spi.DocumentationType;
|
||||
import springfox.documentation.spi.service.contexts.SecurityContext;
|
||||
import springfox.documentation.spring.web.plugins.Docket;
|
||||
import springfox.documentation.swagger.web.*;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
import java.time.temporal.Temporal;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import static run.halo.app.model.support.HaloConst.*;
|
||||
import static springfox.documentation.schema.AlternateTypeRules.newRule;
|
||||
import springfox.documentation.swagger.web.DocExpansion;
|
||||
import springfox.documentation.swagger.web.ModelRendering;
|
||||
import springfox.documentation.swagger.web.OperationsSorter;
|
||||
import springfox.documentation.swagger.web.SecurityConfiguration;
|
||||
import springfox.documentation.swagger.web.SecurityConfigurationBuilder;
|
||||
import springfox.documentation.swagger.web.TagsSorter;
|
||||
import springfox.documentation.swagger.web.UiConfiguration;
|
||||
import springfox.documentation.swagger.web.UiConfigurationBuilder;
|
||||
|
||||
/**
|
||||
* Swagger configuration.
|
||||
|
@ -41,20 +62,20 @@ import static springfox.documentation.schema.AlternateTypeRules.newRule;
|
|||
@Slf4j
|
||||
@Configuration
|
||||
@ConditionalOnProperty(
|
||||
value = "springfox.documentation.enabled",
|
||||
havingValue = "true",
|
||||
matchIfMissing = true)
|
||||
value = "springfox.documentation.enabled",
|
||||
havingValue = "true",
|
||||
matchIfMissing = true)
|
||||
public class SwaggerConfiguration {
|
||||
|
||||
private final HaloProperties haloProperties;
|
||||
|
||||
private final List<ResponseMessage> globalResponses = Arrays.asList(
|
||||
new ResponseMessageBuilder().code(200).message("Success").build(),
|
||||
new ResponseMessageBuilder().code(400).message("Bad request").build(),
|
||||
new ResponseMessageBuilder().code(401).message("Unauthorized").build(),
|
||||
new ResponseMessageBuilder().code(403).message("Forbidden").build(),
|
||||
new ResponseMessageBuilder().code(404).message("Not found").build(),
|
||||
new ResponseMessageBuilder().code(500).message("Internal server error").build());
|
||||
new ResponseMessageBuilder().code(200).message("Success").build(),
|
||||
new ResponseMessageBuilder().code(400).message("Bad request").build(),
|
||||
new ResponseMessageBuilder().code(401).message("Unauthorized").build(),
|
||||
new ResponseMessageBuilder().code(403).message("Forbidden").build(),
|
||||
new ResponseMessageBuilder().code(404).message("Not found").build(),
|
||||
new ResponseMessageBuilder().code(500).message("Internal server error").build());
|
||||
|
||||
public SwaggerConfiguration(HaloProperties haloProperties) {
|
||||
this.haloProperties = haloProperties;
|
||||
|
@ -63,10 +84,10 @@ public class SwaggerConfiguration {
|
|||
@Bean
|
||||
public Docket haloDefaultApi() {
|
||||
return buildApiDocket("run.halo.app.content.api",
|
||||
"run.halo.app.controller.content.api",
|
||||
"/api/content/**")
|
||||
.securitySchemes(contentApiKeys())
|
||||
.securityContexts(contentSecurityContext());
|
||||
"run.halo.app.controller.content.api",
|
||||
"/api/content/**")
|
||||
.securitySchemes(contentApiKeys())
|
||||
.securityContexts(contentSecurityContext());
|
||||
}
|
||||
|
||||
@Bean
|
||||
|
@ -76,120 +97,124 @@ public class SwaggerConfiguration {
|
|||
}
|
||||
|
||||
return buildApiDocket("run.halo.app.admin.api",
|
||||
"run.halo.app.controller.admin",
|
||||
"/api/admin/**")
|
||||
.securitySchemes(adminApiKeys())
|
||||
.securityContexts(adminSecurityContext());
|
||||
"run.halo.app.controller.admin",
|
||||
"/api/admin/**")
|
||||
.securitySchemes(adminApiKeys())
|
||||
.securityContexts(adminSecurityContext());
|
||||
}
|
||||
|
||||
@Bean
|
||||
SecurityConfiguration security() {
|
||||
return SecurityConfigurationBuilder.builder()
|
||||
.clientId("halo-app-client-id")
|
||||
.clientSecret("halo-app-client-secret")
|
||||
.realm("halo-app-realm")
|
||||
.appName("halo-app")
|
||||
.scopeSeparator(",")
|
||||
.additionalQueryStringParams(null)
|
||||
.useBasicAuthenticationWithAccessCodeGrant(false)
|
||||
.build();
|
||||
.clientId("halo-app-client-id")
|
||||
.clientSecret("halo-app-client-secret")
|
||||
.realm("halo-app-realm")
|
||||
.appName("halo-app")
|
||||
.scopeSeparator(",")
|
||||
.additionalQueryStringParams(null)
|
||||
.useBasicAuthenticationWithAccessCodeGrant(false)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
UiConfiguration uiConfig() {
|
||||
return UiConfigurationBuilder.builder()
|
||||
.deepLinking(true)
|
||||
.displayOperationId(false)
|
||||
.defaultModelsExpandDepth(1)
|
||||
.defaultModelExpandDepth(1)
|
||||
.defaultModelRendering(ModelRendering.EXAMPLE)
|
||||
.displayRequestDuration(false)
|
||||
.docExpansion(DocExpansion.NONE)
|
||||
.filter(false)
|
||||
.maxDisplayedTags(null)
|
||||
.operationsSorter(OperationsSorter.ALPHA)
|
||||
.showExtensions(false)
|
||||
.showCommonExtensions(false)
|
||||
.tagsSorter(TagsSorter.ALPHA)
|
||||
.supportedSubmitMethods(UiConfiguration.Constants.DEFAULT_SUBMIT_METHODS)
|
||||
.validatorUrl(null)
|
||||
.build();
|
||||
.deepLinking(true)
|
||||
.displayOperationId(false)
|
||||
.defaultModelsExpandDepth(1)
|
||||
.defaultModelExpandDepth(1)
|
||||
.defaultModelRendering(ModelRendering.EXAMPLE)
|
||||
.displayRequestDuration(false)
|
||||
.docExpansion(DocExpansion.NONE)
|
||||
.filter(false)
|
||||
.maxDisplayedTags(null)
|
||||
.operationsSorter(OperationsSorter.ALPHA)
|
||||
.showExtensions(false)
|
||||
.showCommonExtensions(false)
|
||||
.tagsSorter(TagsSorter.ALPHA)
|
||||
.supportedSubmitMethods(UiConfiguration.Constants.DEFAULT_SUBMIT_METHODS)
|
||||
.validatorUrl(null)
|
||||
.build();
|
||||
}
|
||||
|
||||
private Docket buildApiDocket(@NonNull String groupName, @NonNull String basePackage, @NonNull String antPattern) {
|
||||
private Docket buildApiDocket(@NonNull String groupName, @NonNull String basePackage,
|
||||
@NonNull String antPattern) {
|
||||
Assert.hasText(groupName, "Group name must not be blank");
|
||||
Assert.hasText(basePackage, "Base package must not be blank");
|
||||
Assert.hasText(antPattern, "Ant pattern must not be blank");
|
||||
|
||||
return new Docket(DocumentationType.SWAGGER_2)
|
||||
.groupName(groupName)
|
||||
.select()
|
||||
.apis(RequestHandlerSelectors.basePackage(basePackage))
|
||||
.paths(PathSelectors.ant(antPattern))
|
||||
.build()
|
||||
.apiInfo(apiInfo())
|
||||
.useDefaultResponseMessages(false)
|
||||
.globalResponseMessage(RequestMethod.GET, globalResponses)
|
||||
.globalResponseMessage(RequestMethod.POST, globalResponses)
|
||||
.globalResponseMessage(RequestMethod.DELETE, globalResponses)
|
||||
.globalResponseMessage(RequestMethod.PUT, globalResponses)
|
||||
.directModelSubstitute(Temporal.class, String.class);
|
||||
.groupName(groupName)
|
||||
.select()
|
||||
.apis(RequestHandlerSelectors.basePackage(basePackage))
|
||||
.paths(PathSelectors.ant(antPattern))
|
||||
.build()
|
||||
.apiInfo(apiInfo())
|
||||
.useDefaultResponseMessages(false)
|
||||
.globalResponseMessage(RequestMethod.GET, globalResponses)
|
||||
.globalResponseMessage(RequestMethod.POST, globalResponses)
|
||||
.globalResponseMessage(RequestMethod.DELETE, globalResponses)
|
||||
.globalResponseMessage(RequestMethod.PUT, globalResponses)
|
||||
.directModelSubstitute(Temporal.class, String.class);
|
||||
}
|
||||
|
||||
private List<SecurityScheme> adminApiKeys() {
|
||||
return Arrays.asList(
|
||||
new ApiKey("Token from header", ADMIN_TOKEN_HEADER_NAME, In.HEADER.name()),
|
||||
new ApiKey("Token from query", ADMIN_TOKEN_QUERY_NAME, In.QUERY.name())
|
||||
new ApiKey("Token from header", ADMIN_TOKEN_HEADER_NAME, In.HEADER.name()),
|
||||
new ApiKey("Token from query", ADMIN_TOKEN_QUERY_NAME, In.QUERY.name())
|
||||
);
|
||||
}
|
||||
|
||||
private List<SecurityContext> adminSecurityContext() {
|
||||
return Collections.singletonList(
|
||||
SecurityContext.builder()
|
||||
.securityReferences(defaultAuth())
|
||||
.forPaths(PathSelectors.regex("/api/admin/.*"))
|
||||
.build()
|
||||
SecurityContext.builder()
|
||||
.securityReferences(defaultAuth())
|
||||
.forPaths(PathSelectors.regex("/api/admin/.*"))
|
||||
.build()
|
||||
);
|
||||
}
|
||||
|
||||
private List<SecurityScheme> contentApiKeys() {
|
||||
return Arrays.asList(
|
||||
new ApiKey("Access key from header", API_ACCESS_KEY_HEADER_NAME, In.HEADER.name()),
|
||||
new ApiKey("Access key from query", API_ACCESS_KEY_QUERY_NAME, In.QUERY.name())
|
||||
new ApiKey("Access key from header", API_ACCESS_KEY_HEADER_NAME, In.HEADER.name()),
|
||||
new ApiKey("Access key from query", API_ACCESS_KEY_QUERY_NAME, In.QUERY.name())
|
||||
);
|
||||
}
|
||||
|
||||
private List<SecurityContext> contentSecurityContext() {
|
||||
return Collections.singletonList(
|
||||
SecurityContext.builder()
|
||||
.securityReferences(contentApiAuth())
|
||||
.forPaths(PathSelectors.regex("/api/content/.*"))
|
||||
.build()
|
||||
SecurityContext.builder()
|
||||
.securityReferences(contentApiAuth())
|
||||
.forPaths(PathSelectors.regex("/api/content/.*"))
|
||||
.build()
|
||||
);
|
||||
}
|
||||
|
||||
private List<SecurityReference> defaultAuth() {
|
||||
AuthorizationScope[] authorizationScopes = {new AuthorizationScope("Admin api", "Access admin api")};
|
||||
AuthorizationScope[] authorizationScopes =
|
||||
{new AuthorizationScope("Admin api", "Access admin api")};
|
||||
return Arrays.asList(new SecurityReference("Token from header", authorizationScopes),
|
||||
new SecurityReference("Token from query", authorizationScopes));
|
||||
new SecurityReference("Token from query", authorizationScopes));
|
||||
}
|
||||
|
||||
private List<SecurityReference> contentApiAuth() {
|
||||
AuthorizationScope[] authorizationScopes = {new AuthorizationScope("content api", "Access content api")};
|
||||
AuthorizationScope[] authorizationScopes =
|
||||
{new AuthorizationScope("content api", "Access content api")};
|
||||
return Arrays.asList(new SecurityReference("Access key from header", authorizationScopes),
|
||||
new SecurityReference("Access key from query", authorizationScopes));
|
||||
new SecurityReference("Access key from query", authorizationScopes));
|
||||
}
|
||||
|
||||
private ApiInfo apiInfo() {
|
||||
return new ApiInfoBuilder()
|
||||
.title("Halo API Documentation")
|
||||
.description("Documentation for Halo API")
|
||||
.version(HALO_VERSION)
|
||||
.termsOfServiceUrl("https://github.com/halo-dev")
|
||||
.contact(new Contact("halo-dev", "https://github.com/halo-dev/halo/issues", "hi@halo.run"))
|
||||
.license("GNU General Public License v3.0")
|
||||
.licenseUrl("https://github.com/halo-dev/halo/blob/master/LICENSE")
|
||||
.build();
|
||||
.title("Halo API Documentation")
|
||||
.description("Documentation for Halo API")
|
||||
.version(HALO_VERSION)
|
||||
.termsOfServiceUrl("https://github.com/halo-dev")
|
||||
.contact(
|
||||
new Contact("halo-dev", "https://github.com/halo-dev/halo/issues", "hi@halo.run"))
|
||||
.license("GNU General Public License v3.0")
|
||||
.licenseUrl("https://github.com/halo-dev/halo/blob/master/LICENSE")
|
||||
.build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
|
@ -203,10 +228,10 @@ public class SwaggerConfiguration {
|
|||
@Override
|
||||
public List<AlternateTypeRule> rules() {
|
||||
return Arrays.asList(
|
||||
newRule(User.class, emptyMixin(User.class)),
|
||||
newRule(UserDetail.class, emptyMixin(UserDetail.class)),
|
||||
newRule(resolver.resolve(Pageable.class), resolver.resolve(pageableMixin())),
|
||||
newRule(resolver.resolve(Sort.class), resolver.resolve(sortMixin())));
|
||||
newRule(User.class, emptyMixin(User.class)),
|
||||
newRule(UserDetail.class, emptyMixin(UserDetail.class)),
|
||||
newRule(resolver.resolve(Pageable.class), resolver.resolve(pageableMixin())),
|
||||
newRule(resolver.resolve(Sort.class), resolver.resolve(sortMixin())));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -221,31 +246,38 @@ public class SwaggerConfiguration {
|
|||
Assert.notNull(clazz, "class type must not be null");
|
||||
|
||||
return new AlternateTypeBuilder()
|
||||
.fullyQualifiedClassName(String.format("%s.generated.%s", clazz.getPackage().getName(), clazz.getSimpleName()))
|
||||
.withProperties(Collections.emptyList())
|
||||
.build();
|
||||
.fullyQualifiedClassName(String
|
||||
.format("%s.generated.%s", clazz.getPackage().getName(), clazz.getSimpleName()))
|
||||
.withProperties(Collections.emptyList())
|
||||
.build();
|
||||
}
|
||||
|
||||
private Type sortMixin() {
|
||||
return new AlternateTypeBuilder()
|
||||
.fullyQualifiedClassName(String.format("%s.generated.%s", Sort.class.getPackage().getName(), Sort.class.getSimpleName()))
|
||||
.withProperties(Collections.singletonList(property(String[].class, "sort")))
|
||||
.build();
|
||||
.fullyQualifiedClassName(String
|
||||
.format("%s.generated.%s", Sort.class.getPackage().getName(),
|
||||
Sort.class.getSimpleName()))
|
||||
.withProperties(Collections.singletonList(property(String[].class, "sort")))
|
||||
.build();
|
||||
}
|
||||
|
||||
private Type pageableMixin() {
|
||||
return new AlternateTypeBuilder()
|
||||
.fullyQualifiedClassName(String.format("%s.generated.%s", Pageable.class.getPackage().getName(), Pageable.class.getSimpleName()))
|
||||
.withProperties(Arrays.asList(property(Integer.class, "page"), property(Integer.class, "size"), property(String[].class, "sort")))
|
||||
.build();
|
||||
.fullyQualifiedClassName(String
|
||||
.format("%s.generated.%s", Pageable.class.getPackage().getName(),
|
||||
Pageable.class.getSimpleName()))
|
||||
.withProperties(Arrays
|
||||
.asList(property(Integer.class, "page"), property(Integer.class, "size"),
|
||||
property(String[].class, "sort")))
|
||||
.build();
|
||||
}
|
||||
|
||||
private AlternateTypePropertyBuilder property(Class<?> type, String name) {
|
||||
return new AlternateTypePropertyBuilder()
|
||||
.withName(name)
|
||||
.withType(type)
|
||||
.withCanRead(true)
|
||||
.withCanWrite(true);
|
||||
.withName(name)
|
||||
.withType(type)
|
||||
.withCanRead(true)
|
||||
.withCanWrite(true);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,14 +1,17 @@
|
|||
package run.halo.app.config.properties;
|
||||
|
||||
import static run.halo.app.model.support.HaloConst.FILE_SEPARATOR;
|
||||
import static run.halo.app.model.support.HaloConst.TEMP_DIR;
|
||||
import static run.halo.app.model.support.HaloConst.USER_HOME;
|
||||
import static run.halo.app.utils.HaloUtils.ensureSuffix;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import lombok.Data;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import run.halo.app.model.enums.Mode;
|
||||
|
||||
import java.time.Duration;
|
||||
|
||||
import static run.halo.app.model.support.HaloConst.*;
|
||||
import static run.halo.app.utils.HaloUtils.ensureSuffix;
|
||||
|
||||
|
||||
/**
|
||||
* Halo configuration properties.
|
||||
|
@ -54,17 +57,20 @@ public class HaloProperties {
|
|||
/**
|
||||
* Halo backup directory.(Not recommended to modify this config);
|
||||
*/
|
||||
private String backupDir = ensureSuffix(TEMP_DIR, FILE_SEPARATOR) + "halo-backup" + FILE_SEPARATOR;
|
||||
private String backupDir =
|
||||
ensureSuffix(TEMP_DIR, FILE_SEPARATOR) + "halo-backup" + FILE_SEPARATOR;
|
||||
|
||||
/**
|
||||
* Halo backup markdown directory.(Not recommended to modify this config);
|
||||
*/
|
||||
private String backupMarkdownDir = ensureSuffix(TEMP_DIR, FILE_SEPARATOR) + "halo-backup-markdown" + FILE_SEPARATOR;
|
||||
private String backupMarkdownDir =
|
||||
ensureSuffix(TEMP_DIR, FILE_SEPARATOR) + "halo-backup-markdown" + FILE_SEPARATOR;
|
||||
|
||||
/**
|
||||
* Halo data export directory.
|
||||
*/
|
||||
private String dataExportDir = ensureSuffix(TEMP_DIR, FILE_SEPARATOR) + "halo-data-export" + FILE_SEPARATOR;
|
||||
private String dataExportDir =
|
||||
ensureSuffix(TEMP_DIR, FILE_SEPARATOR) + "halo-data-export" + FILE_SEPARATOR;
|
||||
|
||||
/**
|
||||
* Upload prefix.
|
||||
|
|
|
@ -1,9 +1,17 @@
|
|||
package run.halo.app.controller.admin.api;
|
||||
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import javax.validation.Valid;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.PutMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import run.halo.app.annotation.DisableOnCondition;
|
||||
import run.halo.app.cache.lock.CacheLock;
|
||||
import run.halo.app.model.dto.EnvironmentDTO;
|
||||
|
@ -19,8 +27,6 @@ import run.halo.app.security.token.AuthToken;
|
|||
import run.halo.app.service.AdminService;
|
||||
import run.halo.app.service.OptionService;
|
||||
|
||||
import javax.validation.Valid;
|
||||
|
||||
/**
|
||||
* Admin controller.
|
||||
*
|
||||
|
@ -45,7 +51,8 @@ public class AdminController {
|
|||
@GetMapping(value = "/is_installed")
|
||||
@ApiOperation("Checks Installation status")
|
||||
public boolean isInstall() {
|
||||
return optionService.getByPropertyOrDefault(PrimaryProperties.IS_INSTALLED, Boolean.class, false);
|
||||
return optionService
|
||||
.getByPropertyOrDefault(PrimaryProperties.IS_INSTALLED, Boolean.class, false);
|
||||
}
|
||||
|
||||
@PostMapping("login/precheck")
|
||||
|
|
|
@ -1,11 +1,24 @@
|
|||
package run.halo.app.controller.admin.api;
|
||||
|
||||
import static org.springframework.data.domain.Sort.Direction.DESC;
|
||||
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import javax.validation.Valid;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.web.PageableDefault;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.PutMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestPart;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import run.halo.app.model.dto.AttachmentDTO;
|
||||
import run.halo.app.model.entity.Attachment;
|
||||
|
@ -14,12 +27,6 @@ import run.halo.app.model.params.AttachmentParam;
|
|||
import run.halo.app.model.params.AttachmentQuery;
|
||||
import run.halo.app.service.AttachmentService;
|
||||
|
||||
import javax.validation.Valid;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import static org.springframework.data.domain.Sort.Direction.DESC;
|
||||
|
||||
/**
|
||||
* Attachment controller.
|
||||
*
|
||||
|
@ -37,8 +44,9 @@ public class AttachmentController {
|
|||
}
|
||||
|
||||
@GetMapping
|
||||
public Page<AttachmentDTO> pageBy(@PageableDefault(sort = "createTime", direction = DESC) Pageable pageable,
|
||||
AttachmentQuery attachmentQuery) {
|
||||
public Page<AttachmentDTO> pageBy(
|
||||
@PageableDefault(sort = "createTime", direction = DESC) Pageable pageable,
|
||||
AttachmentQuery attachmentQuery) {
|
||||
return attachmentService.pageDtosBy(pageable, attachmentQuery);
|
||||
}
|
||||
|
||||
|
@ -52,7 +60,7 @@ public class AttachmentController {
|
|||
@PutMapping("{attachmentId:\\d+}")
|
||||
@ApiOperation("Updates a attachment")
|
||||
public AttachmentDTO updateBy(@PathVariable("attachmentId") Integer attachmentId,
|
||||
@RequestBody @Valid AttachmentParam attachmentParam) {
|
||||
@RequestBody @Valid AttachmentParam attachmentParam) {
|
||||
Attachment attachment = attachmentService.getById(attachmentId);
|
||||
attachmentParam.update(attachment);
|
||||
return new AttachmentDTO().convertFrom(attachmentService.update(attachment));
|
||||
|
|
|
@ -1,12 +1,23 @@
|
|||
package run.halo.app.controller.admin.api;
|
||||
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RequestPart;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import run.halo.app.annotation.DisableOnCondition;
|
||||
import run.halo.app.config.properties.HaloProperties;
|
||||
|
@ -15,10 +26,6 @@ import run.halo.app.model.dto.post.BasePostDetailDTO;
|
|||
import run.halo.app.model.params.PostMarkdownParam;
|
||||
import run.halo.app.service.BackupService;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Backup controller
|
||||
*
|
||||
|
@ -57,25 +64,29 @@ public class BackupController {
|
|||
@GetMapping("work-dir/{fileName:.+}")
|
||||
@ApiOperation("Downloads a work directory backup file")
|
||||
@DisableOnCondition
|
||||
public ResponseEntity<Resource> downloadBackup(@PathVariable("fileName") String fileName, HttpServletRequest request) {
|
||||
public ResponseEntity<Resource> downloadBackup(@PathVariable("fileName") String fileName,
|
||||
HttpServletRequest request) {
|
||||
log.info("Try to download backup file: [{}]", fileName);
|
||||
|
||||
// Load file as resource
|
||||
Resource backupResource = backupService.loadFileAsResource(haloProperties.getBackupDir(), fileName);
|
||||
Resource backupResource =
|
||||
backupService.loadFileAsResource(haloProperties.getBackupDir(), fileName);
|
||||
|
||||
String contentType = MediaType.APPLICATION_OCTET_STREAM_VALUE;
|
||||
// Try to determine file's content type
|
||||
try {
|
||||
contentType = request.getServletContext().getMimeType(backupResource.getFile().getAbsolutePath());
|
||||
contentType =
|
||||
request.getServletContext().getMimeType(backupResource.getFile().getAbsolutePath());
|
||||
} catch (IOException e) {
|
||||
log.warn("Could not determine file type", e);
|
||||
// Ignore this error
|
||||
}
|
||||
|
||||
return ResponseEntity.ok()
|
||||
.contentType(MediaType.parseMediaType(contentType))
|
||||
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + backupResource.getFilename() + "\"")
|
||||
.body(backupResource);
|
||||
.contentType(MediaType.parseMediaType(contentType))
|
||||
.header(HttpHeaders.CONTENT_DISPOSITION,
|
||||
"attachment; filename=\"" + backupResource.getFilename() + "\"")
|
||||
.body(backupResource);
|
||||
}
|
||||
|
||||
@DeleteMapping("work-dir")
|
||||
|
@ -87,7 +98,8 @@ public class BackupController {
|
|||
|
||||
@PostMapping("markdown/import")
|
||||
@ApiOperation("Imports markdown")
|
||||
public BasePostDetailDTO backupMarkdowns(@RequestPart("file") MultipartFile file) throws IOException {
|
||||
public BasePostDetailDTO backupMarkdowns(@RequestPart("file") MultipartFile file)
|
||||
throws IOException {
|
||||
return backupService.importMarkdown(file);
|
||||
}
|
||||
|
||||
|
@ -114,30 +126,35 @@ public class BackupController {
|
|||
@GetMapping("data/{fileName:.+}")
|
||||
@ApiOperation("Downloads a exported data")
|
||||
@DisableOnCondition
|
||||
public ResponseEntity<Resource> downloadExportedData(@PathVariable("fileName") String fileName, HttpServletRequest request) {
|
||||
public ResponseEntity<Resource> downloadExportedData(@PathVariable("fileName") String fileName,
|
||||
HttpServletRequest request) {
|
||||
log.info("Try to download exported data file: [{}]", fileName);
|
||||
|
||||
// Load exported data as resource
|
||||
Resource exportDataResource = backupService.loadFileAsResource(haloProperties.getDataExportDir(), fileName);
|
||||
Resource exportDataResource =
|
||||
backupService.loadFileAsResource(haloProperties.getDataExportDir(), fileName);
|
||||
|
||||
String contentType = MediaType.APPLICATION_OCTET_STREAM_VALUE;
|
||||
// Try to determine file's content type
|
||||
try {
|
||||
contentType = request.getServletContext().getMimeType(exportDataResource.getFile().getAbsolutePath());
|
||||
contentType = request.getServletContext()
|
||||
.getMimeType(exportDataResource.getFile().getAbsolutePath());
|
||||
} catch (IOException e) {
|
||||
log.warn("Could not determine file type", e);
|
||||
}
|
||||
|
||||
return ResponseEntity.ok()
|
||||
.contentType(MediaType.parseMediaType(contentType))
|
||||
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + exportDataResource.getFilename() + "\"")
|
||||
.body(exportDataResource);
|
||||
.contentType(MediaType.parseMediaType(contentType))
|
||||
.header(HttpHeaders.CONTENT_DISPOSITION,
|
||||
"attachment; filename=\"" + exportDataResource.getFilename() + "\"")
|
||||
.body(exportDataResource);
|
||||
}
|
||||
|
||||
@PostMapping("markdown/export")
|
||||
@ApiOperation("Exports markdowns")
|
||||
@DisableOnCondition
|
||||
public BackupDTO exportMarkdowns(@RequestBody PostMarkdownParam postMarkdownParam) throws IOException {
|
||||
public BackupDTO exportMarkdowns(@RequestBody PostMarkdownParam postMarkdownParam)
|
||||
throws IOException {
|
||||
return backupService.exportMarkdowns(postMarkdownParam);
|
||||
}
|
||||
|
||||
|
@ -157,25 +174,29 @@ public class BackupController {
|
|||
@GetMapping("markdown/export/{fileName:.+}")
|
||||
@ApiOperation("Downloads a work markdown backup file")
|
||||
@DisableOnCondition
|
||||
public ResponseEntity<Resource> downloadMarkdown(@PathVariable("fileName") String fileName, HttpServletRequest request) {
|
||||
public ResponseEntity<Resource> downloadMarkdown(@PathVariable("fileName") String fileName,
|
||||
HttpServletRequest request) {
|
||||
log.info("Try to download markdown backup file: [{}]", fileName);
|
||||
|
||||
// Load file as resource
|
||||
Resource backupResource = backupService.loadFileAsResource(haloProperties.getBackupMarkdownDir(), fileName);
|
||||
Resource backupResource =
|
||||
backupService.loadFileAsResource(haloProperties.getBackupMarkdownDir(), fileName);
|
||||
|
||||
String contentType = MediaType.APPLICATION_OCTET_STREAM_VALUE;
|
||||
// Try to determine file's content type
|
||||
try {
|
||||
contentType = request.getServletContext().getMimeType(backupResource.getFile().getAbsolutePath());
|
||||
contentType =
|
||||
request.getServletContext().getMimeType(backupResource.getFile().getAbsolutePath());
|
||||
} catch (IOException e) {
|
||||
log.warn("Could not determine file type", e);
|
||||
// Ignore this error
|
||||
}
|
||||
|
||||
return ResponseEntity.ok()
|
||||
.contentType(MediaType.parseMediaType(contentType))
|
||||
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + backupResource.getFilename() + "\"")
|
||||
.body(backupResource);
|
||||
.contentType(MediaType.parseMediaType(contentType))
|
||||
.header(HttpHeaders.CONTENT_DISPOSITION,
|
||||
"attachment; filename=\"" + backupResource.getFilename() + "\"")
|
||||
.body(backupResource);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1,9 +1,22 @@
|
|||
package run.halo.app.controller.admin.api;
|
||||
|
||||
import static org.springframework.data.domain.Sort.Direction.ASC;
|
||||
import static org.springframework.data.domain.Sort.Direction.DESC;
|
||||
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import java.util.List;
|
||||
import javax.validation.Valid;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.web.SortDefault;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.PutMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import run.halo.app.model.dto.CategoryDTO;
|
||||
import run.halo.app.model.entity.Category;
|
||||
import run.halo.app.model.params.CategoryParam;
|
||||
|
@ -11,12 +24,6 @@ import run.halo.app.model.vo.CategoryVO;
|
|||
import run.halo.app.service.CategoryService;
|
||||
import run.halo.app.service.PostCategoryService;
|
||||
|
||||
import javax.validation.Valid;
|
||||
import java.util.List;
|
||||
|
||||
import static org.springframework.data.domain.Sort.Direction.ASC;
|
||||
import static org.springframework.data.domain.Sort.Direction.DESC;
|
||||
|
||||
/**
|
||||
* Category controller.
|
||||
*
|
||||
|
@ -32,7 +39,7 @@ public class CategoryController {
|
|||
private final PostCategoryService postCategoryService;
|
||||
|
||||
public CategoryController(CategoryService categoryService,
|
||||
PostCategoryService postCategoryService) {
|
||||
PostCategoryService postCategoryService) {
|
||||
this.categoryService = categoryService;
|
||||
this.postCategoryService = postCategoryService;
|
||||
}
|
||||
|
@ -46,8 +53,8 @@ public class CategoryController {
|
|||
@GetMapping
|
||||
@ApiOperation("Lists all categories")
|
||||
public List<? extends CategoryDTO> listAll(
|
||||
@SortDefault(sort = "createTime", direction = DESC) Sort sort,
|
||||
@RequestParam(name = "more", required = false, defaultValue = "false") boolean more) {
|
||||
@SortDefault(sort = "createTime", direction = DESC) Sort sort,
|
||||
@RequestParam(name = "more", required = false, defaultValue = "false") boolean more) {
|
||||
if (more) {
|
||||
return postCategoryService.listCategoryWithPostCountDto(sort);
|
||||
}
|
||||
|
@ -74,7 +81,7 @@ public class CategoryController {
|
|||
@PutMapping("{categoryId:\\d+}")
|
||||
@ApiOperation("Updates category")
|
||||
public CategoryDTO updateBy(@PathVariable("categoryId") Integer categoryId,
|
||||
@RequestBody @Valid CategoryParam categoryParam) {
|
||||
@RequestBody @Valid CategoryParam categoryParam) {
|
||||
Category categoryToUpdate = categoryService.getById(categoryId);
|
||||
categoryParam.update(categoryToUpdate);
|
||||
return categoryService.convertTo(categoryService.update(categoryToUpdate));
|
||||
|
|
|
@ -2,6 +2,11 @@ package run.halo.app.controller.admin.api;
|
|||
|
||||
import cn.hutool.crypto.SecureUtil;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.context.ApplicationEventPublisher;
|
||||
|
@ -19,7 +24,11 @@ import run.halo.app.model.entity.PostComment;
|
|||
import run.halo.app.model.entity.User;
|
||||
import run.halo.app.model.enums.LogType;
|
||||
import run.halo.app.model.enums.PostStatus;
|
||||
import run.halo.app.model.params.*;
|
||||
import run.halo.app.model.params.CategoryParam;
|
||||
import run.halo.app.model.params.InstallParam;
|
||||
import run.halo.app.model.params.MenuParam;
|
||||
import run.halo.app.model.params.PostParam;
|
||||
import run.halo.app.model.params.SheetParam;
|
||||
import run.halo.app.model.properties.BlogProperties;
|
||||
import run.halo.app.model.properties.OtherProperties;
|
||||
import run.halo.app.model.properties.PrimaryProperties;
|
||||
|
@ -27,11 +36,15 @@ import run.halo.app.model.properties.PropertyEnum;
|
|||
import run.halo.app.model.support.BaseResponse;
|
||||
import run.halo.app.model.support.CreateCheck;
|
||||
import run.halo.app.model.vo.PostDetailVO;
|
||||
import run.halo.app.service.*;
|
||||
import run.halo.app.service.CategoryService;
|
||||
import run.halo.app.service.MenuService;
|
||||
import run.halo.app.service.OptionService;
|
||||
import run.halo.app.service.PostCommentService;
|
||||
import run.halo.app.service.PostService;
|
||||
import run.halo.app.service.SheetService;
|
||||
import run.halo.app.service.UserService;
|
||||
import run.halo.app.utils.ValidationUtils;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Installation controller.
|
||||
*
|
||||
|
@ -60,13 +73,13 @@ public class InstallController {
|
|||
private final ApplicationEventPublisher eventPublisher;
|
||||
|
||||
public InstallController(UserService userService,
|
||||
CategoryService categoryService,
|
||||
PostService postService,
|
||||
SheetService sheetService,
|
||||
PostCommentService postCommentService,
|
||||
OptionService optionService,
|
||||
MenuService menuService,
|
||||
ApplicationEventPublisher eventPublisher) {
|
||||
CategoryService categoryService,
|
||||
PostService postService,
|
||||
SheetService sheetService,
|
||||
PostCommentService postCommentService,
|
||||
OptionService optionService,
|
||||
MenuService menuService,
|
||||
ApplicationEventPublisher eventPublisher) {
|
||||
this.userService = userService;
|
||||
this.categoryService = categoryService;
|
||||
this.postService = postService;
|
||||
|
@ -86,7 +99,8 @@ public class InstallController {
|
|||
ValidationUtils.validate(installParam, CreateCheck.class);
|
||||
|
||||
// Check is installed
|
||||
boolean isInstalled = optionService.getByPropertyOrDefault(PrimaryProperties.IS_INSTALLED, Boolean.class, false);
|
||||
boolean isInstalled = optionService
|
||||
.getByPropertyOrDefault(PrimaryProperties.IS_INSTALLED, Boolean.class, false);
|
||||
|
||||
if (isInstalled) {
|
||||
throw new BadRequestException("该博客已初始化,不能再次安装!");
|
||||
|
@ -114,7 +128,7 @@ public class InstallController {
|
|||
createDefaultMenu();
|
||||
|
||||
eventPublisher.publishEvent(
|
||||
new LogEvent(this, user.getId().toString(), LogType.BLOG_INITIALIZED, "博客已成功初始化")
|
||||
new LogEvent(this, user.getId().toString(), LogType.BLOG_INITIALIZED, "博客已成功初始化")
|
||||
);
|
||||
|
||||
return BaseResponse.ok("安装完成!");
|
||||
|
@ -171,7 +185,10 @@ public class InstallController {
|
|||
PostComment comment = new PostComment();
|
||||
comment.setAuthor("Halo");
|
||||
comment.setAuthorUrl("https://halo.run");
|
||||
comment.setContent("欢迎使用 Halo,这是你的第一条评论,头像来自 [Gravatar](https://cn.gravatar.com),你也可以通过注册 [Gravatar](https://cn.gravatar.com) 来显示自己的头像。");
|
||||
comment.setContent(
|
||||
"欢迎使用 Halo,这是你的第一条评论,头像来自 [Gravatar](https://cn.gravatar.com),"
|
||||
+ "你也可以通过注册 [Gravatar]"
|
||||
+ "(https://cn.gravatar.com) 来显示自己的头像。");
|
||||
comment.setEmail("hi@halo.run");
|
||||
comment.setPostId(post.getId());
|
||||
postCommentService.create(comment);
|
||||
|
@ -190,28 +207,29 @@ public class InstallController {
|
|||
postParam.setSlug("hello-halo");
|
||||
postParam.setTitle("Hello Halo");
|
||||
postParam.setStatus(PostStatus.PUBLISHED);
|
||||
postParam.setOriginalContent("## Hello Halo\n" +
|
||||
"\n" +
|
||||
"如果你看到了这一篇文章,那么证明你已经安装成功了,感谢使用 [Halo](https://halo.run) 进行创作,希望能够使用愉快。\n" +
|
||||
"\n" +
|
||||
"## 相关链接\n" +
|
||||
"\n" +
|
||||
"- 官网:[https://halo.run](https://halo.run)\n" +
|
||||
"- 社区:[https://bbs.halo.run](https://bbs.halo.run)\n" +
|
||||
"- 主题仓库:[https://halo.run/p/themes.html](https://halo.run/p/themes.html)\n" +
|
||||
"- 开源地址:[https://github.com/halo-dev/halo](https://github.com/halo-dev/halo)\n" +
|
||||
"\n" +
|
||||
"在使用过程中,有任何问题都可以通过以上链接找寻答案,或者联系我们。\n" +
|
||||
"\n" +
|
||||
"> 这是一篇自动生成的文章,请删除这篇文章之后开始你的创作吧!\n" +
|
||||
"\n");
|
||||
postParam.setOriginalContent("## Hello Halo\n"
|
||||
+ "\n"
|
||||
+ "如果你看到了这一篇文章,那么证明你已经安装成功了,感谢使用 [Halo](https://halo.run) 进行创作,希望能够使用愉快。\n"
|
||||
+ "\n"
|
||||
+ "## 相关链接\n"
|
||||
+ "\n"
|
||||
+ "- 官网:[https://halo.run](https://halo.run)\n"
|
||||
+ "- 社区:[https://bbs.halo.run](https://bbs.halo.run)\n"
|
||||
+ "- 主题仓库:[https://halo.run/p/themes.html](https://halo.run/p/themes.html)\n"
|
||||
+ "- 开源地址:[https://github.com/halo-dev/halo](https://github.com/halo-dev/halo)\n"
|
||||
+ "\n"
|
||||
+ "在使用过程中,有任何问题都可以通过以上链接找寻答案,或者联系我们。\n"
|
||||
+ "\n"
|
||||
+ "> 这是一篇自动生成的文章,请删除这篇文章之后开始你的创作吧!\n"
|
||||
+ "\n");
|
||||
|
||||
Set<Integer> categoryIds = new HashSet<>();
|
||||
if (category != null) {
|
||||
categoryIds.add(category.getId());
|
||||
postParam.setCategoryIds(categoryIds);
|
||||
}
|
||||
return postService.createBy(postParam.convertTo(), Collections.emptySet(), categoryIds, false);
|
||||
return postService
|
||||
.createBy(postParam.convertTo(), Collections.emptySet(), categoryIds, false);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
@ -225,11 +243,12 @@ public class InstallController {
|
|||
sheetParam.setSlug("about");
|
||||
sheetParam.setTitle("关于页面");
|
||||
sheetParam.setStatus(PostStatus.PUBLISHED);
|
||||
sheetParam.setOriginalContent("## 关于页面\n" +
|
||||
"\n" +
|
||||
"这是一个自定义页面,你可以在后台的 `页面` -> `所有页面` -> `自定义页面` 找到它,你可以用于新建关于页面、留言板页面等等。发挥你自己的想象力!\n" +
|
||||
"\n" +
|
||||
"> 这是一篇自动生成的页面,你可以在后台删除它。");
|
||||
sheetParam.setOriginalContent("## 关于页面\n"
|
||||
+ "\n"
|
||||
+ "这是一个自定义页面,你可以在后台的 `页面` -> `所有页面` -> `自定义页面` 找到它,"
|
||||
+ "你可以用于新建关于页面、留言板页面等等。发挥你自己的想象力!\n"
|
||||
+ "\n"
|
||||
+ "> 这是一篇自动生成的页面,你可以在后台删除它。");
|
||||
sheetService.createBy(sheetParam.convertTo(), false);
|
||||
}
|
||||
|
||||
|
@ -258,8 +277,9 @@ public class InstallController {
|
|||
// Update user
|
||||
return userService.update(user);
|
||||
}).orElseGet(() -> {
|
||||
String gravatar = "//cn.gravatar.com/avatar/" + SecureUtil.md5(installParam.getEmail()) +
|
||||
"?s=256&d=mm";
|
||||
String gravatar =
|
||||
"//cn.gravatar.com/avatar/" + SecureUtil.md5(installParam.getEmail())
|
||||
+ "?s=256&d=mm";
|
||||
installParam.setAvatar(gravatar);
|
||||
return userService.createBy(installParam);
|
||||
});
|
||||
|
@ -271,15 +291,20 @@ public class InstallController {
|
|||
properties.put(PrimaryProperties.IS_INSTALLED, Boolean.TRUE.toString());
|
||||
properties.put(BlogProperties.BLOG_LOCALE, installParam.getLocale());
|
||||
properties.put(BlogProperties.BLOG_TITLE, installParam.getTitle());
|
||||
properties.put(BlogProperties.BLOG_URL, StringUtils.isBlank(installParam.getUrl()) ? optionService.getBlogBaseUrl() : installParam.getUrl());
|
||||
properties.put(BlogProperties.BLOG_URL,
|
||||
StringUtils.isBlank(installParam.getUrl()) ? optionService.getBlogBaseUrl() :
|
||||
installParam.getUrl());
|
||||
|
||||
Long birthday = optionService.getByPropertyOrDefault(PrimaryProperties.BIRTHDAY, Long.class, 0L);
|
||||
Long birthday =
|
||||
optionService.getByPropertyOrDefault(PrimaryProperties.BIRTHDAY, Long.class, 0L);
|
||||
|
||||
if (birthday.equals(0L)) {
|
||||
properties.put(PrimaryProperties.BIRTHDAY, String.valueOf(System.currentTimeMillis()));
|
||||
}
|
||||
|
||||
Boolean globalAbsolutePathEnabled = optionService.getByPropertyOrDefault(OtherProperties.GLOBAL_ABSOLUTE_PATH_ENABLED, Boolean.class, null);
|
||||
Boolean globalAbsolutePathEnabled = optionService
|
||||
.getByPropertyOrDefault(OtherProperties.GLOBAL_ABSOLUTE_PATH_ENABLED, Boolean.class,
|
||||
null);
|
||||
|
||||
if (globalAbsolutePathEnabled == null) {
|
||||
properties.put(OtherProperties.GLOBAL_ABSOLUTE_PATH_ENABLED, Boolean.FALSE.toString());
|
||||
|
|
|
@ -1,13 +1,24 @@
|
|||
package run.halo.app.controller.admin.api;
|
||||
|
||||
import static org.springframework.data.domain.Sort.Direction.DESC;
|
||||
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import java.util.List;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.web.PageableDefault;
|
||||
import org.springframework.data.web.SortDefault;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.PutMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import run.halo.app.model.dto.BaseCommentDTO;
|
||||
import run.halo.app.model.entity.JournalComment;
|
||||
import run.halo.app.model.enums.CommentStatus;
|
||||
|
@ -19,10 +30,6 @@ import run.halo.app.model.vo.JournalCommentWithJournalVO;
|
|||
import run.halo.app.service.JournalCommentService;
|
||||
import run.halo.app.service.OptionService;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.springframework.data.domain.Sort.Direction.DESC;
|
||||
|
||||
/**
|
||||
* Journal comment controller.
|
||||
*
|
||||
|
@ -38,42 +45,48 @@ public class JournalCommentController {
|
|||
private final OptionService optionService;
|
||||
|
||||
public JournalCommentController(JournalCommentService journalCommentService,
|
||||
OptionService optionService) {
|
||||
OptionService optionService) {
|
||||
this.journalCommentService = journalCommentService;
|
||||
this.optionService = optionService;
|
||||
}
|
||||
|
||||
@GetMapping
|
||||
@ApiOperation("Lists journal comments")
|
||||
public Page<JournalCommentWithJournalVO> pageBy(@PageableDefault(sort = "createTime", direction = DESC) Pageable pageable,
|
||||
CommentQuery commentQuery) {
|
||||
Page<JournalComment> journalCommentPage = journalCommentService.pageBy(commentQuery, pageable);
|
||||
public Page<JournalCommentWithJournalVO> pageBy(
|
||||
@PageableDefault(sort = "createTime", direction = DESC) Pageable pageable,
|
||||
CommentQuery commentQuery) {
|
||||
Page<JournalComment> journalCommentPage =
|
||||
journalCommentService.pageBy(commentQuery, pageable);
|
||||
|
||||
return journalCommentService.convertToWithJournalVo(journalCommentPage);
|
||||
}
|
||||
|
||||
@GetMapping("latest")
|
||||
@ApiOperation("Lists latest journal comments")
|
||||
public List<JournalCommentWithJournalVO> listLatest(@RequestParam(name = "top", defaultValue = "10") int top,
|
||||
@RequestParam(name = "status", required = false) CommentStatus status) {
|
||||
List<JournalComment> latestComments = journalCommentService.pageLatest(top, status).getContent();
|
||||
public List<JournalCommentWithJournalVO> listLatest(
|
||||
@RequestParam(name = "top", defaultValue = "10") int top,
|
||||
@RequestParam(name = "status", required = false) CommentStatus status) {
|
||||
List<JournalComment> latestComments =
|
||||
journalCommentService.pageLatest(top, status).getContent();
|
||||
return journalCommentService.convertToWithJournalVo(latestComments);
|
||||
}
|
||||
|
||||
@GetMapping("{journalId:\\d+}/tree_view")
|
||||
@ApiOperation("Lists comments with tree view")
|
||||
public Page<BaseCommentVO> listCommentTree(@PathVariable("journalId") Integer journalId,
|
||||
@RequestParam(name = "page", required = false, defaultValue = "0") int page,
|
||||
@SortDefault(sort = "createTime", direction = DESC) Sort sort) {
|
||||
return journalCommentService.pageVosAllBy(journalId, PageRequest.of(page, optionService.getCommentPageSize(), sort));
|
||||
@RequestParam(name = "page", required = false, defaultValue = "0") int page,
|
||||
@SortDefault(sort = "createTime", direction = DESC) Sort sort) {
|
||||
return journalCommentService.pageVosAllBy(journalId,
|
||||
PageRequest.of(page, optionService.getCommentPageSize(), sort));
|
||||
}
|
||||
|
||||
@GetMapping("{journalId:\\d+}/list_view")
|
||||
@ApiOperation("Lists comment with list view")
|
||||
public Page<BaseCommentWithParentVO> listComments(@PathVariable("journalId") Integer journalId,
|
||||
@RequestParam(name = "page", required = false, defaultValue = "0") int page,
|
||||
@SortDefault(sort = "createTime", direction = DESC) Sort sort) {
|
||||
return journalCommentService.pageWithParentVoBy(journalId, PageRequest.of(page, optionService.getCommentPageSize(), sort));
|
||||
@RequestParam(name = "page", required = false, defaultValue = "0") int page,
|
||||
@SortDefault(sort = "createTime", direction = DESC) Sort sort) {
|
||||
return journalCommentService.pageWithParentVoBy(journalId,
|
||||
PageRequest.of(page, optionService.getCommentPageSize(), sort));
|
||||
}
|
||||
|
||||
@PostMapping
|
||||
|
@ -86,9 +99,10 @@ public class JournalCommentController {
|
|||
@PutMapping("{commentId:\\d+}/status/{status}")
|
||||
@ApiOperation("Updates comment status")
|
||||
public BaseCommentDTO updateStatusBy(@PathVariable("commentId") Long commentId,
|
||||
@PathVariable("status") CommentStatus status) {
|
||||
@PathVariable("status") CommentStatus status) {
|
||||
// Update comment status
|
||||
JournalComment updatedJournalComment = journalCommentService.updateStatus(commentId, status);
|
||||
JournalComment updatedJournalComment =
|
||||
journalCommentService.updateStatus(commentId, status);
|
||||
return journalCommentService.convertTo(updatedJournalComment);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,10 +1,22 @@
|
|||
package run.halo.app.controller.admin.api;
|
||||
|
||||
import static org.springframework.data.domain.Sort.Direction.DESC;
|
||||
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import java.util.List;
|
||||
import javax.validation.Valid;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.web.PageableDefault;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.PutMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import run.halo.app.model.dto.JournalDTO;
|
||||
import run.halo.app.model.dto.JournalWithCmtCountDTO;
|
||||
import run.halo.app.model.entity.Journal;
|
||||
|
@ -12,11 +24,6 @@ import run.halo.app.model.params.JournalParam;
|
|||
import run.halo.app.model.params.JournalQuery;
|
||||
import run.halo.app.service.JournalService;
|
||||
|
||||
import javax.validation.Valid;
|
||||
import java.util.List;
|
||||
|
||||
import static org.springframework.data.domain.Sort.Direction.DESC;
|
||||
|
||||
/**
|
||||
* Journal controller.
|
||||
*
|
||||
|
@ -36,15 +43,17 @@ public class JournalController {
|
|||
|
||||
@GetMapping
|
||||
@ApiOperation("Lists journals")
|
||||
public Page<JournalWithCmtCountDTO> pageBy(@PageableDefault(sort = "createTime", direction = DESC) Pageable pageable,
|
||||
JournalQuery journalQuery) {
|
||||
public Page<JournalWithCmtCountDTO> pageBy(
|
||||
@PageableDefault(sort = "createTime", direction = DESC) Pageable pageable,
|
||||
JournalQuery journalQuery) {
|
||||
Page<Journal> journalPage = journalService.pageBy(journalQuery, pageable);
|
||||
return journalService.convertToCmtCountDto(journalPage);
|
||||
}
|
||||
|
||||
@GetMapping("latest")
|
||||
@ApiOperation("Gets latest journals")
|
||||
public List<JournalWithCmtCountDTO> pageLatest(@RequestParam(name = "top", defaultValue = "10") int top) {
|
||||
public List<JournalWithCmtCountDTO> pageLatest(
|
||||
@RequestParam(name = "top", defaultValue = "10") int top) {
|
||||
List<Journal> journals = journalService.pageLatest(top).getContent();
|
||||
return journalService.convertToCmtCountDto(journals);
|
||||
}
|
||||
|
@ -59,7 +68,7 @@ public class JournalController {
|
|||
@PutMapping("{id:\\d+}")
|
||||
@ApiOperation("Updates a Journal")
|
||||
public JournalDTO updateBy(@PathVariable("id") Integer id,
|
||||
@RequestBody @Valid JournalParam journalParam) {
|
||||
@RequestBody @Valid JournalParam journalParam) {
|
||||
Journal journal = journalService.getById(id);
|
||||
journalParam.update(journal);
|
||||
Journal updatedJournal = journalService.updateBy(journal);
|
||||
|
|
|
@ -1,20 +1,26 @@
|
|||
package run.halo.app.controller.admin.api;
|
||||
|
||||
import static org.springframework.data.domain.Sort.Direction.ASC;
|
||||
import static org.springframework.data.domain.Sort.Direction.DESC;
|
||||
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import java.util.List;
|
||||
import javax.validation.Valid;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.web.SortDefault;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.PutMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import run.halo.app.model.dto.LinkDTO;
|
||||
import run.halo.app.model.entity.Link;
|
||||
import run.halo.app.model.params.LinkParam;
|
||||
import run.halo.app.service.LinkService;
|
||||
|
||||
import javax.validation.Valid;
|
||||
import java.util.List;
|
||||
|
||||
import static org.springframework.data.domain.Sort.Direction.ASC;
|
||||
import static org.springframework.data.domain.Sort.Direction.DESC;
|
||||
|
||||
/**
|
||||
* Link Controller
|
||||
*
|
||||
|
@ -53,7 +59,7 @@ public class LinkController {
|
|||
@PutMapping("{id:\\d+}")
|
||||
@ApiOperation("Updates a link")
|
||||
public LinkDTO updateBy(@PathVariable("id") Integer id,
|
||||
@RequestBody @Valid LinkParam linkParam) {
|
||||
@RequestBody @Valid LinkParam linkParam) {
|
||||
Link link = linkService.updateBy(id, linkParam);
|
||||
return new LinkDTO().convertFrom(link);
|
||||
}
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
package run.halo.app.controller.admin.api;
|
||||
|
||||
import static org.springframework.data.domain.Sort.Direction.DESC;
|
||||
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import java.util.List;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.web.PageableDefault;
|
||||
|
@ -12,10 +15,6 @@ import run.halo.app.model.dto.LogDTO;
|
|||
import run.halo.app.model.entity.Log;
|
||||
import run.halo.app.service.LogService;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.springframework.data.domain.Sort.Direction.DESC;
|
||||
|
||||
/**
|
||||
* Log controller.
|
||||
*
|
||||
|
@ -40,7 +39,8 @@ public class LogController {
|
|||
|
||||
@GetMapping
|
||||
@ApiOperation("Lists logs")
|
||||
public Page<LogDTO> pageBy(@PageableDefault(sort = "createTime", direction = DESC) Pageable pageable) {
|
||||
public Page<LogDTO> pageBy(
|
||||
@PageableDefault(sort = "createTime", direction = DESC) Pageable pageable) {
|
||||
Page<Log> logPage = logService.listAll(pageable);
|
||||
return logPage.map(log -> new LogDTO().convertFrom(log));
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package run.halo.app.controller.admin.api;
|
||||
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import javax.validation.Valid;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
|
@ -10,8 +11,6 @@ import run.halo.app.mail.MailService;
|
|||
import run.halo.app.model.params.MailParam;
|
||||
import run.halo.app.model.support.BaseResponse;
|
||||
|
||||
import javax.validation.Valid;
|
||||
|
||||
/**
|
||||
* Mail controller.
|
||||
*
|
||||
|
|
|
@ -1,9 +1,23 @@
|
|||
package run.halo.app.controller.admin.api;
|
||||
|
||||
import static org.springframework.data.domain.Sort.Direction.ASC;
|
||||
import static org.springframework.data.domain.Sort.Direction.DESC;
|
||||
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import javax.validation.Valid;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.web.SortDefault;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.PutMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import run.halo.app.model.dto.MenuDTO;
|
||||
import run.halo.app.model.dto.base.InputConverter;
|
||||
import run.halo.app.model.entity.Menu;
|
||||
|
@ -11,13 +25,6 @@ import run.halo.app.model.params.MenuParam;
|
|||
import run.halo.app.model.vo.MenuVO;
|
||||
import run.halo.app.service.MenuService;
|
||||
|
||||
import javax.validation.Valid;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static org.springframework.data.domain.Sort.Direction.ASC;
|
||||
import static org.springframework.data.domain.Sort.Direction.DESC;
|
||||
|
||||
/**
|
||||
* Menu controller.
|
||||
*
|
||||
|
@ -49,7 +56,9 @@ public class MenuController {
|
|||
|
||||
@GetMapping("team/tree_view")
|
||||
@ApiOperation("Lists menus as tree by team")
|
||||
public List<MenuVO> listDefaultsAsTreeByTeam(@SortDefault(sort = "priority", direction = ASC) Sort sort, @RequestParam(name = "team") String team) {
|
||||
public List<MenuVO> listDefaultsAsTreeByTeam(
|
||||
@SortDefault(sort = "priority", direction = ASC) Sort sort,
|
||||
@RequestParam(name = "team") String team) {
|
||||
return menuService.listByTeamAsTree(team, sort);
|
||||
}
|
||||
|
||||
|
@ -68,17 +77,18 @@ public class MenuController {
|
|||
@PostMapping("/batch")
|
||||
public List<MenuDTO> createBatchBy(@RequestBody @Valid List<MenuParam> menuParams) {
|
||||
List<Menu> menus = menuParams
|
||||
.stream()
|
||||
.map(InputConverter::convertTo)
|
||||
.collect(Collectors.toList());
|
||||
.stream()
|
||||
.map(InputConverter::convertTo)
|
||||
.collect(Collectors.toList());
|
||||
return menuService.createInBatch(menus).stream()
|
||||
.map(menu -> (MenuDTO) new MenuDTO().convertFrom(menu))
|
||||
.collect(Collectors.toList());
|
||||
.map(menu -> (MenuDTO) new MenuDTO().convertFrom(menu))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@PutMapping("{menuId:\\d+}")
|
||||
@ApiOperation("Updates a menu")
|
||||
public MenuDTO updateBy(@PathVariable("menuId") Integer menuId, @RequestBody @Valid MenuParam menuParam) {
|
||||
public MenuDTO updateBy(@PathVariable("menuId") Integer menuId,
|
||||
@RequestBody @Valid MenuParam menuParam) {
|
||||
// Get the menu
|
||||
Menu menu = menuService.getById(menuId);
|
||||
|
||||
|
@ -92,12 +102,12 @@ public class MenuController {
|
|||
@PutMapping("/batch")
|
||||
public List<MenuDTO> updateBatchBy(@RequestBody @Valid List<MenuParam> menuParams) {
|
||||
List<Menu> menus = menuParams
|
||||
.stream()
|
||||
.map(InputConverter::convertTo)
|
||||
.collect(Collectors.toList());
|
||||
.stream()
|
||||
.map(InputConverter::convertTo)
|
||||
.collect(Collectors.toList());
|
||||
return menuService.updateInBatch(menus).stream()
|
||||
.map(menu -> (MenuDTO) new MenuDTO().convertFrom(menu))
|
||||
.collect(Collectors.toList());
|
||||
.map(menu -> (MenuDTO) new MenuDTO().convertFrom(menu))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@DeleteMapping("{menuId:\\d+}")
|
||||
|
@ -118,8 +128,8 @@ public class MenuController {
|
|||
List<Menu> menus = menuService.listAllByIds(menuIds);
|
||||
menuService.removeInBatch(menuIds);
|
||||
return menus.stream()
|
||||
.map(menu -> (MenuDTO) new MenuDTO().convertFrom(menu))
|
||||
.collect(Collectors.toList());
|
||||
.map(menu -> (MenuDTO) new MenuDTO().convertFrom(menu))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@GetMapping("teams")
|
||||
|
|
|
@ -27,7 +27,7 @@ public class MigrateController {
|
|||
private final OptionService optionService;
|
||||
|
||||
public MigrateController(MigrateService migrateService,
|
||||
OptionService optionService) {
|
||||
OptionService optionService) {
|
||||
this.migrateService = migrateService;
|
||||
this.optionService = optionService;
|
||||
}
|
||||
|
@ -35,7 +35,8 @@ public class MigrateController {
|
|||
@PostMapping("halo")
|
||||
@ApiOperation("Migrate from Halo")
|
||||
public void migrateHalo(@RequestPart("file") MultipartFile file) {
|
||||
if (optionService.getByPropertyOrDefault(PrimaryProperties.IS_INSTALLED, Boolean.class, false)) {
|
||||
if (optionService
|
||||
.getByPropertyOrDefault(PrimaryProperties.IS_INSTALLED, Boolean.class, false)) {
|
||||
throw new BadRequestException("无法在博客初始化完成之后迁移数据");
|
||||
}
|
||||
migrateService.migrate(file, MigrateType.HALO);
|
||||
|
|
|
@ -1,10 +1,22 @@
|
|||
package run.halo.app.controller.admin.api;
|
||||
|
||||
import static org.springframework.data.domain.Sort.Direction.DESC;
|
||||
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import javax.validation.Valid;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.web.PageableDefault;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.PutMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import run.halo.app.annotation.DisableOnCondition;
|
||||
import run.halo.app.model.dto.OptionDTO;
|
||||
import run.halo.app.model.dto.OptionSimpleDTO;
|
||||
|
@ -13,12 +25,6 @@ import run.halo.app.model.params.OptionParam;
|
|||
import run.halo.app.model.params.OptionQuery;
|
||||
import run.halo.app.service.OptionService;
|
||||
|
||||
import javax.validation.Valid;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.springframework.data.domain.Sort.Direction.DESC;
|
||||
|
||||
/**
|
||||
* Option Controller.
|
||||
*
|
||||
|
@ -63,8 +69,9 @@ public class OptionController {
|
|||
|
||||
@GetMapping("list_view")
|
||||
@ApiOperation("Lists all options with list view")
|
||||
public Page<OptionSimpleDTO> listAllWithListView(@PageableDefault(sort = "updateTime", direction = DESC) Pageable pageable,
|
||||
OptionQuery optionQuery) {
|
||||
public Page<OptionSimpleDTO> listAllWithListView(
|
||||
@PageableDefault(sort = "updateTime", direction = DESC) Pageable pageable,
|
||||
OptionQuery optionQuery) {
|
||||
return optionService.pageDtosBy(pageable, optionQuery);
|
||||
}
|
||||
|
||||
|
@ -86,7 +93,7 @@ public class OptionController {
|
|||
@ApiOperation("Updates option")
|
||||
@DisableOnCondition
|
||||
public void updateBy(@PathVariable("optionId") Integer optionId,
|
||||
@RequestBody @Valid OptionParam optionParam) {
|
||||
@RequestBody @Valid OptionParam optionParam) {
|
||||
optionService.update(optionId, optionParam);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,23 +1,29 @@
|
|||
package run.halo.app.controller.admin.api;
|
||||
|
||||
import static org.springframework.data.domain.Sort.Direction.DESC;
|
||||
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import java.util.List;
|
||||
import javax.validation.Valid;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.web.PageableDefault;
|
||||
import org.springframework.data.web.SortDefault;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.PutMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import run.halo.app.model.dto.PhotoDTO;
|
||||
import run.halo.app.model.entity.Photo;
|
||||
import run.halo.app.model.params.PhotoParam;
|
||||
import run.halo.app.model.params.PhotoQuery;
|
||||
import run.halo.app.service.PhotoService;
|
||||
|
||||
import javax.validation.Valid;
|
||||
import java.util.List;
|
||||
|
||||
import static org.springframework.data.domain.Sort.Direction.DESC;
|
||||
|
||||
/**
|
||||
* Photo controller
|
||||
*
|
||||
|
@ -36,14 +42,16 @@ public class PhotoController {
|
|||
|
||||
@GetMapping(value = "latest")
|
||||
@ApiOperation("Lists latest photos")
|
||||
public List<PhotoDTO> listPhotos(@SortDefault(sort = "createTime", direction = Sort.Direction.DESC) Sort sort) {
|
||||
public List<PhotoDTO> listPhotos(
|
||||
@SortDefault(sort = "createTime", direction = Sort.Direction.DESC) Sort sort) {
|
||||
return photoService.listDtos(sort);
|
||||
}
|
||||
|
||||
@GetMapping
|
||||
@ApiOperation("Lists photos")
|
||||
public Page<PhotoDTO> pageBy(@PageableDefault(sort = "createTime", direction = DESC) Pageable pageable,
|
||||
PhotoQuery photoQuery) {
|
||||
public Page<PhotoDTO> pageBy(
|
||||
@PageableDefault(sort = "createTime", direction = DESC) Pageable pageable,
|
||||
PhotoQuery photoQuery) {
|
||||
return photoService.pageDtosBy(pageable, photoQuery);
|
||||
}
|
||||
|
||||
|
@ -68,7 +76,7 @@ public class PhotoController {
|
|||
@PutMapping("{photoId:\\d+}")
|
||||
@ApiOperation("Updates a photo")
|
||||
public PhotoDTO updateBy(@PathVariable("photoId") Integer photoId,
|
||||
@RequestBody @Valid PhotoParam photoParam) {
|
||||
@RequestBody @Valid PhotoParam photoParam) {
|
||||
// Get the photo
|
||||
Photo photo = photoService.getById(photoId);
|
||||
|
||||
|
|
|
@ -1,13 +1,25 @@
|
|||
package run.halo.app.controller.admin.api;
|
||||
|
||||
import static org.springframework.data.domain.Sort.Direction.DESC;
|
||||
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import java.util.List;
|
||||
import javax.validation.Valid;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.web.PageableDefault;
|
||||
import org.springframework.data.web.SortDefault;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.PutMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import run.halo.app.model.dto.BaseCommentDTO;
|
||||
import run.halo.app.model.entity.PostComment;
|
||||
import run.halo.app.model.enums.CommentStatus;
|
||||
|
@ -19,11 +31,6 @@ import run.halo.app.model.vo.PostCommentWithPostVO;
|
|||
import run.halo.app.service.OptionService;
|
||||
import run.halo.app.service.PostCommentService;
|
||||
|
||||
import javax.validation.Valid;
|
||||
import java.util.List;
|
||||
|
||||
import static org.springframework.data.domain.Sort.Direction.DESC;
|
||||
|
||||
/**
|
||||
* Post comment controller.
|
||||
*
|
||||
|
@ -40,23 +47,25 @@ public class PostCommentController {
|
|||
private final OptionService optionService;
|
||||
|
||||
public PostCommentController(PostCommentService postCommentService,
|
||||
OptionService optionService) {
|
||||
OptionService optionService) {
|
||||
this.postCommentService = postCommentService;
|
||||
this.optionService = optionService;
|
||||
}
|
||||
|
||||
@GetMapping
|
||||
@ApiOperation("Lists post comments")
|
||||
public Page<PostCommentWithPostVO> pageBy(@PageableDefault(sort = "createTime", direction = DESC) Pageable pageable,
|
||||
CommentQuery commentQuery) {
|
||||
public Page<PostCommentWithPostVO> pageBy(
|
||||
@PageableDefault(sort = "createTime", direction = DESC) Pageable pageable,
|
||||
CommentQuery commentQuery) {
|
||||
Page<PostComment> commentPage = postCommentService.pageBy(commentQuery, pageable);
|
||||
return postCommentService.convertToWithPostVo(commentPage);
|
||||
}
|
||||
|
||||
@GetMapping("latest")
|
||||
@ApiOperation("Pages post latest comments")
|
||||
public List<PostCommentWithPostVO> listLatest(@RequestParam(name = "top", defaultValue = "10") int top,
|
||||
@RequestParam(name = "status", required = false) CommentStatus status) {
|
||||
public List<PostCommentWithPostVO> listLatest(
|
||||
@RequestParam(name = "top", defaultValue = "10") int top,
|
||||
@RequestParam(name = "status", required = false) CommentStatus status) {
|
||||
// Get latest comment
|
||||
List<PostComment> content = postCommentService.pageLatest(top, status).getContent();
|
||||
|
||||
|
@ -67,17 +76,19 @@ public class PostCommentController {
|
|||
@GetMapping("{postId:\\d+}/tree_view")
|
||||
@ApiOperation("Lists post comments with tree view")
|
||||
public Page<BaseCommentVO> listCommentTree(@PathVariable("postId") Integer postId,
|
||||
@RequestParam(name = "page", required = false, defaultValue = "0") int page,
|
||||
@SortDefault(sort = "createTime", direction = DESC) Sort sort) {
|
||||
return postCommentService.pageVosAllBy(postId, PageRequest.of(page, optionService.getCommentPageSize(), sort));
|
||||
@RequestParam(name = "page", required = false, defaultValue = "0") int page,
|
||||
@SortDefault(sort = "createTime", direction = DESC) Sort sort) {
|
||||
return postCommentService
|
||||
.pageVosAllBy(postId, PageRequest.of(page, optionService.getCommentPageSize(), sort));
|
||||
}
|
||||
|
||||
@GetMapping("{postId:\\d+}/list_view")
|
||||
@ApiOperation("Lists post comment with list view")
|
||||
public Page<BaseCommentWithParentVO> listComments(@PathVariable("postId") Integer postId,
|
||||
@RequestParam(name = "page", required = false, defaultValue = "0") int page,
|
||||
@SortDefault(sort = "createTime", direction = DESC) Sort sort) {
|
||||
return postCommentService.pageWithParentVoBy(postId, PageRequest.of(page, optionService.getCommentPageSize(), sort));
|
||||
@RequestParam(name = "page", required = false, defaultValue = "0") int page,
|
||||
@SortDefault(sort = "createTime", direction = DESC) Sort sort) {
|
||||
return postCommentService.pageWithParentVoBy(postId,
|
||||
PageRequest.of(page, optionService.getCommentPageSize(), sort));
|
||||
}
|
||||
|
||||
@PostMapping
|
||||
|
@ -90,7 +101,7 @@ public class PostCommentController {
|
|||
@PutMapping("{commentId:\\d+}/status/{status}")
|
||||
@ApiOperation("Updates post comment status")
|
||||
public BaseCommentDTO updateStatusBy(@PathVariable("commentId") Long commentId,
|
||||
@PathVariable("status") CommentStatus status) {
|
||||
@PathVariable("status") CommentStatus status) {
|
||||
// Update comment status
|
||||
PostComment updatedPostComment = postCommentService.updateStatus(commentId, status);
|
||||
return postCommentService.convertTo(updatedPostComment);
|
||||
|
@ -98,8 +109,9 @@ public class PostCommentController {
|
|||
|
||||
@PutMapping("status/{status}")
|
||||
@ApiOperation("Updates post comment status in batch")
|
||||
public List<BaseCommentDTO> updateStatusInBatch(@PathVariable(name = "status") CommentStatus status,
|
||||
@RequestBody List<Long> ids) {
|
||||
public List<BaseCommentDTO> updateStatusInBatch(
|
||||
@PathVariable(name = "status") CommentStatus status,
|
||||
@RequestBody List<Long> ids) {
|
||||
List<PostComment> comments = postCommentService.updateStatusByIds(ids, status);
|
||||
return postCommentService.convertTo(comments);
|
||||
}
|
||||
|
@ -127,7 +139,7 @@ public class PostCommentController {
|
|||
@PutMapping("{commentId:\\d+}")
|
||||
@ApiOperation("Updates a post comment")
|
||||
public BaseCommentDTO updateBy(@Valid @RequestBody PostCommentParam commentParam,
|
||||
@PathVariable("commentId") Long commentId) {
|
||||
@PathVariable("commentId") Long commentId) {
|
||||
PostComment commentToUpdate = postCommentService.getById(commentId);
|
||||
|
||||
commentParam.update(commentToUpdate);
|
||||
|
|
|
@ -1,11 +1,27 @@
|
|||
package run.halo.app.controller.admin.api;
|
||||
|
||||
import static org.springframework.data.domain.Sort.Direction.DESC;
|
||||
|
||||
import cn.hutool.core.util.IdUtil;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLEncoder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import javax.validation.Valid;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.web.PageableDefault;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.PutMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import run.halo.app.cache.AbstractStringCacheStore;
|
||||
import run.halo.app.model.dto.post.BasePostDetailDTO;
|
||||
import run.halo.app.model.dto.post.BasePostMinimalDTO;
|
||||
|
@ -20,15 +36,6 @@ import run.halo.app.model.vo.PostDetailVO;
|
|||
import run.halo.app.service.OptionService;
|
||||
import run.halo.app.service.PostService;
|
||||
|
||||
import javax.validation.Valid;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLEncoder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import static org.springframework.data.domain.Sort.Direction.DESC;
|
||||
|
||||
/**
|
||||
* Post controller.
|
||||
*
|
||||
|
@ -48,8 +55,8 @@ public class PostController {
|
|||
private final OptionService optionService;
|
||||
|
||||
public PostController(PostService postService,
|
||||
AbstractStringCacheStore cacheStore,
|
||||
OptionService optionService) {
|
||||
AbstractStringCacheStore cacheStore,
|
||||
OptionService optionService) {
|
||||
this.postService = postService;
|
||||
this.cacheStore = cacheStore;
|
||||
this.optionService = optionService;
|
||||
|
@ -57,9 +64,10 @@ public class PostController {
|
|||
|
||||
@GetMapping
|
||||
@ApiOperation("Lists posts")
|
||||
public Page<? extends BasePostSimpleDTO> pageBy(@PageableDefault(sort = {"topPriority", "createTime"}, direction = DESC) Pageable pageable,
|
||||
PostQuery postQuery,
|
||||
@RequestParam(value = "more", defaultValue = "true") Boolean more) {
|
||||
public Page<? extends BasePostSimpleDTO> pageBy(
|
||||
@PageableDefault(sort = {"topPriority", "createTime"}, direction = DESC) Pageable pageable,
|
||||
PostQuery postQuery,
|
||||
@RequestParam(value = "more", defaultValue = "true") Boolean more) {
|
||||
Page<Post> postPage = postService.pageBy(postQuery, pageable);
|
||||
if (more) {
|
||||
return postService.convertToListVo(postPage);
|
||||
|
@ -70,15 +78,17 @@ public class PostController {
|
|||
|
||||
@GetMapping("latest")
|
||||
@ApiOperation("Pages latest post")
|
||||
public List<BasePostMinimalDTO> pageLatest(@RequestParam(name = "top", defaultValue = "10") int top) {
|
||||
public List<BasePostMinimalDTO> pageLatest(
|
||||
@RequestParam(name = "top", defaultValue = "10") int top) {
|
||||
return postService.convertToMinimal(postService.pageLatest(top).getContent());
|
||||
}
|
||||
|
||||
@GetMapping("status/{status}")
|
||||
@ApiOperation("Gets a page of post by post status")
|
||||
public Page<? extends BasePostSimpleDTO> pageByStatus(@PathVariable(name = "status") PostStatus status,
|
||||
@RequestParam(value = "more", required = false, defaultValue = "false") Boolean more,
|
||||
@PageableDefault(sort = "createTime", direction = DESC) Pageable pageable) {
|
||||
public Page<? extends BasePostSimpleDTO> pageByStatus(
|
||||
@PathVariable(name = "status") PostStatus status,
|
||||
@RequestParam(value = "more", required = false, defaultValue = "false") Boolean more,
|
||||
@PageableDefault(sort = "createTime", direction = DESC) Pageable pageable) {
|
||||
Page<Post> posts = postService.pageBy(status, pageable);
|
||||
|
||||
if (more) {
|
||||
|
@ -104,29 +114,33 @@ public class PostController {
|
|||
@PostMapping
|
||||
@ApiOperation("Creates a post")
|
||||
public PostDetailVO createBy(@Valid @RequestBody PostParam postParam,
|
||||
@RequestParam(value = "autoSave", required = false, defaultValue = "false") Boolean autoSave) {
|
||||
@RequestParam(value = "autoSave", required = false, defaultValue = "false")
|
||||
Boolean autoSave) {
|
||||
// Convert to
|
||||
Post post = postParam.convertTo();
|
||||
return postService.createBy(post, postParam.getTagIds(), postParam.getCategoryIds(), postParam.getPostMetas(), autoSave);
|
||||
return postService.createBy(post, postParam.getTagIds(), postParam.getCategoryIds(),
|
||||
postParam.getPostMetas(), autoSave);
|
||||
}
|
||||
|
||||
@PutMapping("{postId:\\d+}")
|
||||
@ApiOperation("Updates a post")
|
||||
public PostDetailVO updateBy(@Valid @RequestBody PostParam postParam,
|
||||
@PathVariable("postId") Integer postId,
|
||||
@RequestParam(value = "autoSave", required = false, defaultValue = "false") Boolean autoSave) {
|
||||
@PathVariable("postId") Integer postId,
|
||||
@RequestParam(value = "autoSave", required = false, defaultValue = "false")
|
||||
Boolean autoSave) {
|
||||
// Get the post info
|
||||
Post postToUpdate = postService.getById(postId);
|
||||
|
||||
postParam.update(postToUpdate);
|
||||
return postService.updateBy(postToUpdate, postParam.getTagIds(), postParam.getCategoryIds(), postParam.getPostMetas(), autoSave);
|
||||
return postService.updateBy(postToUpdate, postParam.getTagIds(), postParam.getCategoryIds(),
|
||||
postParam.getPostMetas(), autoSave);
|
||||
}
|
||||
|
||||
@PutMapping("{postId:\\d+}/status/{status}")
|
||||
@ApiOperation("Updates post status")
|
||||
public BasePostMinimalDTO updateStatusBy(
|
||||
@PathVariable("postId") Integer postId,
|
||||
@PathVariable("status") PostStatus status) {
|
||||
@PathVariable("postId") Integer postId,
|
||||
@PathVariable("status") PostStatus status) {
|
||||
Post post = postService.updateStatus(status, postId);
|
||||
|
||||
return new BasePostMinimalDTO().convertFrom(post);
|
||||
|
@ -135,15 +149,15 @@ public class PostController {
|
|||
@PutMapping("status/{status}")
|
||||
@ApiOperation("Updates post status in batch")
|
||||
public List<Post> updateStatusInBatch(@PathVariable(name = "status") PostStatus status,
|
||||
@RequestBody List<Integer> ids) {
|
||||
@RequestBody List<Integer> ids) {
|
||||
return postService.updateStatusByIds(ids, status);
|
||||
}
|
||||
|
||||
@PutMapping("{postId:\\d+}/status/draft/content")
|
||||
@ApiOperation("Updates draft")
|
||||
public BasePostDetailDTO updateDraftBy(
|
||||
@PathVariable("postId") Integer postId,
|
||||
@RequestBody PostContentParam contentParam) {
|
||||
@PathVariable("postId") Integer postId,
|
||||
@RequestBody PostContentParam contentParam) {
|
||||
// Update draft content
|
||||
Post post = postService.updateDraftContent(contentParam.getContent(), postId);
|
||||
|
||||
|
@ -164,7 +178,8 @@ public class PostController {
|
|||
|
||||
@GetMapping(value = {"preview/{postId:\\d+}", "{postId:\\d+}/preview"})
|
||||
@ApiOperation("Gets a post preview link")
|
||||
public String preview(@PathVariable("postId") Integer postId) throws UnsupportedEncodingException {
|
||||
public String preview(@PathVariable("postId") Integer postId)
|
||||
throws UnsupportedEncodingException {
|
||||
Post post = postService.getById(postId);
|
||||
|
||||
post.setSlug(URLEncoder.encode(post.getSlug(), StandardCharsets.UTF_8.name()));
|
||||
|
@ -186,10 +201,10 @@ public class PostController {
|
|||
|
||||
if (optionService.getPostPermalinkType().equals(PostPermalinkType.ID)) {
|
||||
previewUrl.append("&token=")
|
||||
.append(token);
|
||||
.append(token);
|
||||
} else {
|
||||
previewUrl.append("?token=")
|
||||
.append(token);
|
||||
.append(token);
|
||||
}
|
||||
|
||||
// build preview post url and return
|
||||
|
|
|
@ -1,13 +1,25 @@
|
|||
package run.halo.app.controller.admin.api;
|
||||
|
||||
import static org.springframework.data.domain.Sort.Direction.DESC;
|
||||
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import java.util.List;
|
||||
import javax.validation.Valid;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.web.PageableDefault;
|
||||
import org.springframework.data.web.SortDefault;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.PutMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import run.halo.app.model.dto.BaseCommentDTO;
|
||||
import run.halo.app.model.entity.SheetComment;
|
||||
import run.halo.app.model.enums.CommentStatus;
|
||||
|
@ -19,11 +31,6 @@ import run.halo.app.model.vo.SheetCommentWithSheetVO;
|
|||
import run.halo.app.service.OptionService;
|
||||
import run.halo.app.service.SheetCommentService;
|
||||
|
||||
import javax.validation.Valid;
|
||||
import java.util.List;
|
||||
|
||||
import static org.springframework.data.domain.Sort.Direction.DESC;
|
||||
|
||||
/**
|
||||
* Sheet comment controller.
|
||||
*
|
||||
|
@ -40,23 +47,25 @@ public class SheetCommentController {
|
|||
private final OptionService optionService;
|
||||
|
||||
public SheetCommentController(SheetCommentService sheetCommentService,
|
||||
OptionService optionService) {
|
||||
OptionService optionService) {
|
||||
this.sheetCommentService = sheetCommentService;
|
||||
this.optionService = optionService;
|
||||
}
|
||||
|
||||
@GetMapping
|
||||
@ApiOperation("Lists sheet comments")
|
||||
public Page<SheetCommentWithSheetVO> pageBy(@PageableDefault(sort = "createTime", direction = DESC) Pageable pageable,
|
||||
CommentQuery commentQuery) {
|
||||
public Page<SheetCommentWithSheetVO> pageBy(
|
||||
@PageableDefault(sort = "createTime", direction = DESC) Pageable pageable,
|
||||
CommentQuery commentQuery) {
|
||||
Page<SheetComment> sheetCommentPage = sheetCommentService.pageBy(commentQuery, pageable);
|
||||
return sheetCommentService.convertToWithSheetVo(sheetCommentPage);
|
||||
}
|
||||
|
||||
@GetMapping("latest")
|
||||
@ApiOperation("Lists latest sheet comments")
|
||||
public List<SheetCommentWithSheetVO> listLatest(@RequestParam(name = "top", defaultValue = "10") int top,
|
||||
@RequestParam(name = "status", required = false) CommentStatus status) {
|
||||
public List<SheetCommentWithSheetVO> listLatest(
|
||||
@RequestParam(name = "top", defaultValue = "10") int top,
|
||||
@RequestParam(name = "status", required = false) CommentStatus status) {
|
||||
Page<SheetComment> sheetCommentPage = sheetCommentService.pageLatest(top, status);
|
||||
return sheetCommentService.convertToWithSheetVo(sheetCommentPage.getContent());
|
||||
}
|
||||
|
@ -64,17 +73,19 @@ public class SheetCommentController {
|
|||
@GetMapping("{sheetId:\\d+}/tree_view")
|
||||
@ApiOperation("Lists sheet comments with tree view")
|
||||
public Page<BaseCommentVO> listCommentTree(@PathVariable("sheetId") Integer sheetId,
|
||||
@RequestParam(name = "page", required = false, defaultValue = "0") int page,
|
||||
@SortDefault(sort = "createTime", direction = DESC) Sort sort) {
|
||||
return sheetCommentService.pageVosAllBy(sheetId, PageRequest.of(page, optionService.getCommentPageSize(), sort));
|
||||
@RequestParam(name = "page", required = false, defaultValue = "0") int page,
|
||||
@SortDefault(sort = "createTime", direction = DESC) Sort sort) {
|
||||
return sheetCommentService
|
||||
.pageVosAllBy(sheetId, PageRequest.of(page, optionService.getCommentPageSize(), sort));
|
||||
}
|
||||
|
||||
@GetMapping("{sheetId:\\d+}/list_view")
|
||||
@ApiOperation("Lists sheet comment with list view")
|
||||
public Page<BaseCommentWithParentVO> listComments(@PathVariable("sheetId") Integer sheetId,
|
||||
@RequestParam(name = "page", required = false, defaultValue = "0") int page,
|
||||
@SortDefault(sort = "createTime", direction = DESC) Sort sort) {
|
||||
return sheetCommentService.pageWithParentVoBy(sheetId, PageRequest.of(page, optionService.getCommentPageSize(), sort));
|
||||
@RequestParam(name = "page", required = false, defaultValue = "0") int page,
|
||||
@SortDefault(sort = "createTime", direction = DESC) Sort sort) {
|
||||
return sheetCommentService.pageWithParentVoBy(sheetId,
|
||||
PageRequest.of(page, optionService.getCommentPageSize(), sort));
|
||||
}
|
||||
|
||||
@PostMapping
|
||||
|
@ -87,7 +98,7 @@ public class SheetCommentController {
|
|||
@PutMapping("{commentId:\\d+}/status/{status}")
|
||||
@ApiOperation("Updates sheet comment status")
|
||||
public BaseCommentDTO updateStatusBy(@PathVariable("commentId") Long commentId,
|
||||
@PathVariable("status") CommentStatus status) {
|
||||
@PathVariable("status") CommentStatus status) {
|
||||
// Update comment status
|
||||
SheetComment updatedSheetComment = sheetCommentService.updateStatus(commentId, status);
|
||||
return sheetCommentService.convertTo(updatedSheetComment);
|
||||
|
@ -95,8 +106,9 @@ public class SheetCommentController {
|
|||
|
||||
@PutMapping("status/{status}")
|
||||
@ApiOperation("Updates sheet comment status in batch")
|
||||
public List<BaseCommentDTO> updateStatusInBatch(@PathVariable(name = "status") CommentStatus status,
|
||||
@RequestBody List<Long> ids) {
|
||||
public List<BaseCommentDTO> updateStatusInBatch(
|
||||
@PathVariable(name = "status") CommentStatus status,
|
||||
@RequestBody List<Long> ids) {
|
||||
List<SheetComment> comments = sheetCommentService.updateStatusByIds(ids, status);
|
||||
return sheetCommentService.convertTo(comments);
|
||||
}
|
||||
|
@ -125,7 +137,7 @@ public class SheetCommentController {
|
|||
@PutMapping("{commentId:\\d+}")
|
||||
@ApiOperation("Updates a sheet comment")
|
||||
public BaseCommentDTO updateBy(@Valid @RequestBody SheetCommentParam commentParam,
|
||||
@PathVariable("commentId") Long commentId) {
|
||||
@PathVariable("commentId") Long commentId) {
|
||||
SheetComment commentToUpdate = sheetCommentService.getById(commentId);
|
||||
|
||||
commentParam.update(commentToUpdate);
|
||||
|
|
|
@ -1,11 +1,27 @@
|
|||
package run.halo.app.controller.admin.api;
|
||||
|
||||
import static org.springframework.data.domain.Sort.Direction.DESC;
|
||||
|
||||
import cn.hutool.core.util.IdUtil;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLEncoder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import javax.validation.Valid;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.web.PageableDefault;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.PutMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import run.halo.app.cache.AbstractStringCacheStore;
|
||||
import run.halo.app.model.dto.IndependentSheetDTO;
|
||||
import run.halo.app.model.dto.post.BasePostDetailDTO;
|
||||
|
@ -19,15 +35,6 @@ import run.halo.app.model.vo.SheetListVO;
|
|||
import run.halo.app.service.OptionService;
|
||||
import run.halo.app.service.SheetService;
|
||||
|
||||
import javax.validation.Valid;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLEncoder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import static org.springframework.data.domain.Sort.Direction.DESC;
|
||||
|
||||
/**
|
||||
* Sheet controller.
|
||||
*
|
||||
|
@ -46,8 +53,8 @@ public class SheetController {
|
|||
private final OptionService optionService;
|
||||
|
||||
public SheetController(SheetService sheetService,
|
||||
AbstractStringCacheStore cacheStore,
|
||||
OptionService optionService) {
|
||||
AbstractStringCacheStore cacheStore,
|
||||
OptionService optionService) {
|
||||
this.sheetService = sheetService;
|
||||
this.cacheStore = cacheStore;
|
||||
this.optionService = optionService;
|
||||
|
@ -62,7 +69,8 @@ public class SheetController {
|
|||
|
||||
@GetMapping
|
||||
@ApiOperation("Gets a page of sheet")
|
||||
public Page<SheetListVO> pageBy(@PageableDefault(sort = "createTime", direction = DESC) Pageable pageable) {
|
||||
public Page<SheetListVO> pageBy(
|
||||
@PageableDefault(sort = "createTime", direction = DESC) Pageable pageable) {
|
||||
Page<Sheet> sheetPage = sheetService.pageBy(pageable);
|
||||
return sheetService.convertToListVo(sheetPage);
|
||||
}
|
||||
|
@ -76,17 +84,20 @@ public class SheetController {
|
|||
@PostMapping
|
||||
@ApiOperation("Creates a sheet")
|
||||
public SheetDetailVO createBy(@RequestBody @Valid SheetParam sheetParam,
|
||||
@RequestParam(value = "autoSave", required = false, defaultValue = "false") Boolean autoSave) {
|
||||
Sheet sheet = sheetService.createBy(sheetParam.convertTo(), sheetParam.getSheetMetas(), autoSave);
|
||||
@RequestParam(value = "autoSave", required = false, defaultValue = "false")
|
||||
Boolean autoSave) {
|
||||
Sheet sheet =
|
||||
sheetService.createBy(sheetParam.convertTo(), sheetParam.getSheetMetas(), autoSave);
|
||||
return sheetService.convertToDetailVo(sheet);
|
||||
}
|
||||
|
||||
@PutMapping("{sheetId:\\d+}")
|
||||
@ApiOperation("Updates a sheet")
|
||||
public SheetDetailVO updateBy(
|
||||
@PathVariable("sheetId") Integer sheetId,
|
||||
@RequestBody @Valid SheetParam sheetParam,
|
||||
@RequestParam(value = "autoSave", required = false, defaultValue = "false") Boolean autoSave) {
|
||||
@PathVariable("sheetId") Integer sheetId,
|
||||
@RequestBody @Valid SheetParam sheetParam,
|
||||
@RequestParam(value = "autoSave", required = false, defaultValue = "false")
|
||||
Boolean autoSave) {
|
||||
Sheet sheetToUpdate = sheetService.getById(sheetId);
|
||||
|
||||
sheetParam.update(sheetToUpdate);
|
||||
|
@ -99,8 +110,8 @@ public class SheetController {
|
|||
@PutMapping("{sheetId:\\d+}/{status}")
|
||||
@ApiOperation("Updates a sheet")
|
||||
public void updateStatusBy(
|
||||
@PathVariable("sheetId") Integer sheetId,
|
||||
@PathVariable("status") PostStatus status) {
|
||||
@PathVariable("sheetId") Integer sheetId,
|
||||
@PathVariable("status") PostStatus status) {
|
||||
Sheet sheet = sheetService.getById(sheetId);
|
||||
|
||||
// Set status
|
||||
|
@ -113,8 +124,8 @@ public class SheetController {
|
|||
@PutMapping("{sheetId:\\d+}/status/draft/content")
|
||||
@ApiOperation("Updates draft")
|
||||
public BasePostDetailDTO updateDraftBy(
|
||||
@PathVariable("sheetId") Integer sheetId,
|
||||
@RequestBody PostContentParam contentParam) {
|
||||
@PathVariable("sheetId") Integer sheetId,
|
||||
@RequestBody PostContentParam contentParam) {
|
||||
// Update draft content
|
||||
Sheet sheet = sheetService.updateDraftContent(contentParam.getContent(), sheetId);
|
||||
|
||||
|
@ -130,7 +141,8 @@ public class SheetController {
|
|||
|
||||
@GetMapping("preview/{sheetId:\\d+}")
|
||||
@ApiOperation("Gets a sheet preview link")
|
||||
public String preview(@PathVariable("sheetId") Integer sheetId) throws UnsupportedEncodingException {
|
||||
public String preview(@PathVariable("sheetId") Integer sheetId)
|
||||
throws UnsupportedEncodingException {
|
||||
Sheet sheet = sheetService.getById(sheetId);
|
||||
|
||||
sheet.setSlug(URLEncoder.encode(sheet.getSlug(), StandardCharsets.UTF_8.name()));
|
||||
|
@ -149,8 +161,8 @@ public class SheetController {
|
|||
}
|
||||
|
||||
previewUrl.append(sheetMinimalDTO.getFullPath())
|
||||
.append("?token=")
|
||||
.append(token);
|
||||
.append("?token=")
|
||||
.append(token);
|
||||
|
||||
// build preview post url and return
|
||||
return previewUrl.toString();
|
||||
|
|
|
@ -1,14 +1,21 @@
|
|||
package run.halo.app.controller.admin.api;
|
||||
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import java.util.List;
|
||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.PutMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RequestPart;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import run.halo.app.model.params.StaticContentParam;
|
||||
import run.halo.app.model.support.StaticFile;
|
||||
import run.halo.app.service.StaticStorageService;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Static storage controller.
|
||||
*
|
||||
|
@ -40,21 +47,21 @@ public class StaticStorageController {
|
|||
@PostMapping
|
||||
@ApiOperation("Creates a folder")
|
||||
public void createFolder(String basePath,
|
||||
@RequestParam("folderName") String folderName) {
|
||||
@RequestParam("folderName") String folderName) {
|
||||
staticStorageService.createFolder(basePath, folderName);
|
||||
}
|
||||
|
||||
@PostMapping("upload")
|
||||
@ApiOperation("Uploads static file")
|
||||
public void upload(String basePath,
|
||||
@RequestPart("file") MultipartFile file) {
|
||||
@RequestPart("file") MultipartFile file) {
|
||||
staticStorageService.upload(basePath, file);
|
||||
}
|
||||
|
||||
@PostMapping("rename")
|
||||
@ApiOperation("Renames static file")
|
||||
public void rename(String basePath,
|
||||
String newName) {
|
||||
String newName) {
|
||||
staticStorageService.rename(basePath, newName);
|
||||
}
|
||||
|
||||
|
|
|
@ -2,19 +2,26 @@ package run.halo.app.controller.admin.api;
|
|||
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import io.swagger.annotations.ApiParam;
|
||||
import java.util.List;
|
||||
import javax.validation.Valid;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.web.SortDefault;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.PutMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import run.halo.app.model.dto.TagDTO;
|
||||
import run.halo.app.model.entity.Tag;
|
||||
import run.halo.app.model.params.TagParam;
|
||||
import run.halo.app.service.PostTagService;
|
||||
import run.halo.app.service.TagService;
|
||||
|
||||
import javax.validation.Valid;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Tag controller.
|
||||
*
|
||||
|
@ -31,16 +38,17 @@ public class TagController {
|
|||
private final PostTagService postTagService;
|
||||
|
||||
public TagController(TagService tagService,
|
||||
PostTagService postTagService) {
|
||||
PostTagService postTagService) {
|
||||
this.tagService = tagService;
|
||||
this.postTagService = postTagService;
|
||||
}
|
||||
|
||||
@GetMapping
|
||||
@ApiOperation("Lists tags")
|
||||
public List<? extends TagDTO> listTags(@SortDefault(sort = "createTime", direction = Sort.Direction.DESC) Sort sort,
|
||||
@ApiParam("Return more information(post count) if it is set")
|
||||
@RequestParam(name = "more", required = false, defaultValue = "false") Boolean more) {
|
||||
public List<? extends TagDTO> listTags(
|
||||
@SortDefault(sort = "createTime", direction = Sort.Direction.DESC) Sort sort,
|
||||
@ApiParam("Return more information(post count) if it is set")
|
||||
@RequestParam(name = "more", required = false, defaultValue = "false") Boolean more) {
|
||||
if (more) {
|
||||
return postTagService.listTagWithCountDtos(sort);
|
||||
}
|
||||
|
@ -68,7 +76,7 @@ public class TagController {
|
|||
@PutMapping("{tagId:\\d+}")
|
||||
@ApiOperation("Updates a tag")
|
||||
public TagDTO updateBy(@PathVariable("tagId") Integer tagId,
|
||||
@Valid @RequestBody TagParam tagParam) {
|
||||
@Valid @RequestBody TagParam tagParam) {
|
||||
// Get old tag
|
||||
Tag tag = tagService.getById(tagId);
|
||||
|
||||
|
|
|
@ -1,8 +1,19 @@
|
|||
package run.halo.app.controller.admin.api;
|
||||
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.PutMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RequestPart;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import run.halo.app.annotation.DisableOnCondition;
|
||||
import run.halo.app.cache.lock.CacheLock;
|
||||
|
@ -14,9 +25,6 @@ import run.halo.app.model.support.ThemeFile;
|
|||
import run.halo.app.service.ThemeService;
|
||||
import run.halo.app.service.ThemeSettingService;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Theme controller.
|
||||
*
|
||||
|
@ -32,7 +40,7 @@ public class ThemeController {
|
|||
private final ThemeSettingService themeSettingService;
|
||||
|
||||
public ThemeController(ThemeService themeService,
|
||||
ThemeSettingService themeSettingService) {
|
||||
ThemeSettingService themeSettingService) {
|
||||
this.themeService = themeService;
|
||||
this.themeSettingService = themeSettingService;
|
||||
}
|
||||
|
@ -64,14 +72,16 @@ public class ThemeController {
|
|||
@GetMapping("files/content")
|
||||
@ApiOperation("Gets template content")
|
||||
public BaseResponse<String> getContentBy(@RequestParam(name = "path") String path) {
|
||||
return BaseResponse.ok(HttpStatus.OK.getReasonPhrase(), themeService.getTemplateContent(path));
|
||||
return BaseResponse
|
||||
.ok(HttpStatus.OK.getReasonPhrase(), themeService.getTemplateContent(path));
|
||||
}
|
||||
|
||||
@GetMapping("{themeId}/files/content")
|
||||
@ApiOperation("Gets template content by theme id")
|
||||
public BaseResponse<String> getContentBy(@PathVariable("themeId") String themeId,
|
||||
@RequestParam(name = "path") String path) {
|
||||
return BaseResponse.ok(HttpStatus.OK.getReasonPhrase(), themeService.getTemplateContent(themeId, path));
|
||||
@RequestParam(name = "path") String path) {
|
||||
return BaseResponse
|
||||
.ok(HttpStatus.OK.getReasonPhrase(), themeService.getTemplateContent(themeId, path));
|
||||
}
|
||||
|
||||
@PutMapping("files/content")
|
||||
|
@ -85,20 +95,22 @@ public class ThemeController {
|
|||
@ApiOperation("Updates template content by theme id")
|
||||
@DisableOnCondition
|
||||
public void updateContentBy(@PathVariable("themeId") String themeId,
|
||||
@RequestBody ThemeContentParam param) {
|
||||
@RequestBody ThemeContentParam param) {
|
||||
themeService.saveTemplateContent(themeId, param.getPath(), param.getContent());
|
||||
}
|
||||
|
||||
@GetMapping("activation/template/custom/sheet")
|
||||
@ApiOperation("Gets custom sheet templates")
|
||||
public List<String> customSheetTemplate() {
|
||||
return themeService.listCustomTemplates(themeService.getActivatedThemeId(), ThemeService.CUSTOM_SHEET_PREFIX);
|
||||
return themeService.listCustomTemplates(themeService.getActivatedThemeId(),
|
||||
ThemeService.CUSTOM_SHEET_PREFIX);
|
||||
}
|
||||
|
||||
@GetMapping("activation/template/custom/post")
|
||||
@ApiOperation("Gets custom post templates")
|
||||
public List<String> customPostTemplate() {
|
||||
return themeService.listCustomTemplates(themeService.getActivatedThemeId(), ThemeService.CUSTOM_POST_PREFIX);
|
||||
return themeService.listCustomTemplates(themeService.getActivatedThemeId(),
|
||||
ThemeService.CUSTOM_POST_PREFIX);
|
||||
}
|
||||
|
||||
@PostMapping("{themeId}/activation")
|
||||
|
@ -147,7 +159,7 @@ public class ThemeController {
|
|||
@ApiOperation("Saves theme settings")
|
||||
@CacheLock(prefix = "save_theme_setting_by_themeId")
|
||||
public void saveSettingsBy(@PathVariable("themeId") String themeId,
|
||||
@RequestBody Map<String, Object> settings) {
|
||||
@RequestBody Map<String, Object> settings) {
|
||||
themeSettingService.save(settings, themeId);
|
||||
}
|
||||
|
||||
|
@ -155,7 +167,7 @@ public class ThemeController {
|
|||
@ApiOperation("Deletes a theme")
|
||||
@DisableOnCondition
|
||||
public void deleteBy(@PathVariable("themeId") String themeId,
|
||||
@RequestParam(value = "deleteSettings", defaultValue = "false") Boolean deleteSettings) {
|
||||
@RequestParam(value = "deleteSettings", defaultValue = "false") Boolean deleteSettings) {
|
||||
themeService.deleteTheme(themeId, deleteSettings);
|
||||
}
|
||||
|
||||
|
@ -168,7 +180,7 @@ public class ThemeController {
|
|||
@PostMapping("upload/{themeId}")
|
||||
@ApiOperation("Upgrades theme by file")
|
||||
public ThemeProperty updateThemeByUpload(@PathVariable("themeId") String themeId,
|
||||
@RequestPart("file") MultipartFile file) {
|
||||
@RequestPart("file") MultipartFile file) {
|
||||
return themeService.update(themeId, file);
|
||||
}
|
||||
|
||||
|
@ -192,13 +204,15 @@ public class ThemeController {
|
|||
|
||||
@GetMapping("fetchingRelease")
|
||||
@ApiOperation("Fetches a specific release")
|
||||
public ThemeProperty fetchRelease(@RequestParam("uri") String uri, @RequestParam("tag") String tagName) {
|
||||
public ThemeProperty fetchRelease(@RequestParam("uri") String uri,
|
||||
@RequestParam("tag") String tagName) {
|
||||
return themeService.fetchRelease(uri, tagName);
|
||||
}
|
||||
|
||||
@GetMapping("fetchBranch")
|
||||
@ApiOperation("Fetch specific branch")
|
||||
public ThemeProperty fetchBranch(@RequestParam("uri") String uri, @RequestParam("branch") String branchName) {
|
||||
public ThemeProperty fetchBranch(@RequestParam("uri") String uri,
|
||||
@RequestParam("branch") String branchName) {
|
||||
return themeService.fetchBranch(uri, branchName);
|
||||
}
|
||||
|
||||
|
|
|
@ -4,7 +4,12 @@ import cn.hutool.core.codec.Base64;
|
|||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.extra.qrcode.QrCodeUtil;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import javax.validation.Valid;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PutMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import run.halo.app.annotation.DisableOnCondition;
|
||||
import run.halo.app.cache.lock.CacheLock;
|
||||
import run.halo.app.exception.BadRequestException;
|
||||
|
@ -21,8 +26,6 @@ import run.halo.app.service.UserService;
|
|||
import run.halo.app.utils.TwoFactorAuthUtils;
|
||||
import run.halo.app.utils.ValidationUtils;
|
||||
|
||||
import javax.validation.Valid;
|
||||
|
||||
/**
|
||||
* User controller.
|
||||
*
|
||||
|
@ -62,21 +65,25 @@ public class UserController {
|
|||
@PutMapping("profiles/password")
|
||||
@ApiOperation("Updates user's password")
|
||||
@DisableOnCondition
|
||||
public BaseResponse<String> updatePassword(@RequestBody @Valid PasswordParam passwordParam, User user) {
|
||||
userService.updatePassword(passwordParam.getOldPassword(), passwordParam.getNewPassword(), user.getId());
|
||||
public BaseResponse<String> updatePassword(@RequestBody @Valid PasswordParam passwordParam,
|
||||
User user) {
|
||||
userService.updatePassword(passwordParam.getOldPassword(), passwordParam.getNewPassword(),
|
||||
user.getId());
|
||||
return BaseResponse.ok("密码修改成功");
|
||||
}
|
||||
|
||||
@PutMapping("mfa/generate")
|
||||
@ApiOperation("Generate Multi-Factor Auth qr image")
|
||||
@DisableOnCondition
|
||||
public MultiFactorAuthVO generateMFAQrImage(@RequestBody MultiFactorAuthParam multiFactorAuthParam, User user) {
|
||||
public MultiFactorAuthVO generateMFAQrImage(
|
||||
@RequestBody MultiFactorAuthParam multiFactorAuthParam, User user) {
|
||||
if (MFAType.NONE == user.getMfaType()) {
|
||||
if (MFAType.TFA_TOTP == multiFactorAuthParam.getMfaType()) {
|
||||
String mfaKey = TwoFactorAuthUtils.generateTFAKey();
|
||||
String optAuthUrl = TwoFactorAuthUtils.generateOtpAuthUrl(user.getNickname(), mfaKey);
|
||||
String qrImageBase64 = "data:image/png;base64," +
|
||||
Base64.encode(QrCodeUtil.generatePng(optAuthUrl, 128, 128));
|
||||
String optAuthUrl =
|
||||
TwoFactorAuthUtils.generateOtpAuthUrl(user.getNickname(), mfaKey);
|
||||
String qrImageBase64 = "data:image/png;base64,"
|
||||
+ Base64.encode(QrCodeUtil.generatePng(optAuthUrl, 128, 128));
|
||||
return new MultiFactorAuthVO(qrImageBase64, optAuthUrl, mfaKey, MFAType.TFA_TOTP);
|
||||
} else {
|
||||
throw new BadRequestException("暂不支持的 MFA 认证的方式");
|
||||
|
@ -90,17 +97,23 @@ public class UserController {
|
|||
@ApiOperation("Updates user's Multi Factor Auth")
|
||||
@CacheLock(autoDelete = false, prefix = "mfa")
|
||||
@DisableOnCondition
|
||||
public MultiFactorAuthVO updateMFAuth(@RequestBody @Valid MultiFactorAuthParam multiFactorAuthParam, User user) {
|
||||
if (StrUtil.isNotBlank(user.getMfaKey()) && MFAType.useMFA(multiFactorAuthParam.getMfaType())) {
|
||||
public MultiFactorAuthVO updateMFAuth(
|
||||
@RequestBody @Valid MultiFactorAuthParam multiFactorAuthParam, User user) {
|
||||
if (StrUtil.isNotBlank(user.getMfaKey())
|
||||
&& MFAType.useMFA(multiFactorAuthParam.getMfaType())) {
|
||||
return new MultiFactorAuthVO(MFAType.TFA_TOTP);
|
||||
} else if (StrUtil.isBlank(user.getMfaKey()) && !MFAType.useMFA(multiFactorAuthParam.getMfaType())) {
|
||||
} else if (StrUtil.isBlank(user.getMfaKey())
|
||||
&& !MFAType.useMFA(multiFactorAuthParam.getMfaType())) {
|
||||
return new MultiFactorAuthVO(MFAType.NONE);
|
||||
} else {
|
||||
final String tfaKey = StrUtil.isNotBlank(user.getMfaKey()) ? user.getMfaKey() : multiFactorAuthParam.getMfaKey();
|
||||
final String tfaKey = StrUtil.isNotBlank(user.getMfaKey()) ? user.getMfaKey() :
|
||||
multiFactorAuthParam.getMfaKey();
|
||||
TwoFactorAuthUtils.validateTFACode(tfaKey, multiFactorAuthParam.getAuthcode());
|
||||
}
|
||||
// update MFA key
|
||||
User updateUser = userService.updateMFA(multiFactorAuthParam.getMfaType(), multiFactorAuthParam.getMfaKey(), user.getId());
|
||||
User updateUser = userService
|
||||
.updateMFA(multiFactorAuthParam.getMfaType(), multiFactorAuthParam.getMfaKey(),
|
||||
user.getId());
|
||||
|
||||
return new MultiFactorAuthVO(updateUser.getMfaType());
|
||||
}
|
||||
|
|
|
@ -1,14 +1,28 @@
|
|||
package run.halo.app.controller.content;
|
||||
|
||||
import cn.hutool.core.util.IdUtil;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLEncoder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import run.halo.app.cache.AbstractStringCacheStore;
|
||||
import run.halo.app.cache.lock.CacheLock;
|
||||
import run.halo.app.controller.content.model.*;
|
||||
import run.halo.app.controller.content.model.CategoryModel;
|
||||
import run.halo.app.controller.content.model.JournalModel;
|
||||
import run.halo.app.controller.content.model.LinkModel;
|
||||
import run.halo.app.controller.content.model.PhotoModel;
|
||||
import run.halo.app.controller.content.model.PostModel;
|
||||
import run.halo.app.controller.content.model.SheetModel;
|
||||
import run.halo.app.controller.content.model.TagModel;
|
||||
import run.halo.app.exception.NotFoundException;
|
||||
import run.halo.app.model.dto.post.BasePostMinimalDTO;
|
||||
import run.halo.app.model.entity.Post;
|
||||
|
@ -20,11 +34,6 @@ import run.halo.app.service.OptionService;
|
|||
import run.halo.app.service.PostService;
|
||||
import run.halo.app.service.SheetService;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLEncoder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* @author ryanwang
|
||||
* @date 2020-01-07
|
||||
|
@ -57,16 +66,16 @@ public class ContentContentController {
|
|||
private final AbstractStringCacheStore cacheStore;
|
||||
|
||||
public ContentContentController(PostModel postModel,
|
||||
SheetModel sheetModel,
|
||||
CategoryModel categoryModel,
|
||||
TagModel tagModel,
|
||||
JournalModel journalModel,
|
||||
PhotoModel photoModel,
|
||||
LinkModel linkModel,
|
||||
OptionService optionService,
|
||||
PostService postService,
|
||||
SheetService sheetService,
|
||||
AbstractStringCacheStore cacheStore) {
|
||||
SheetModel sheetModel,
|
||||
CategoryModel categoryModel,
|
||||
TagModel tagModel,
|
||||
JournalModel journalModel,
|
||||
PhotoModel photoModel,
|
||||
LinkModel linkModel,
|
||||
OptionService optionService,
|
||||
PostService postService,
|
||||
SheetService sheetService,
|
||||
AbstractStringCacheStore cacheStore) {
|
||||
this.postModel = postModel;
|
||||
this.sheetModel = sheetModel;
|
||||
this.categoryModel = categoryModel;
|
||||
|
@ -82,8 +91,8 @@ public class ContentContentController {
|
|||
|
||||
@GetMapping("{prefix}")
|
||||
public String content(@PathVariable("prefix") String prefix,
|
||||
@RequestParam(value = "token", required = false) String token,
|
||||
Model model) {
|
||||
@RequestParam(value = "token", required = false) String token,
|
||||
Model model) {
|
||||
if (optionService.getSheetPermalinkType().equals(SheetPermalinkType.ROOT)) {
|
||||
Sheet sheet = sheetService.getBySlug(prefix);
|
||||
return sheetModel.content(sheet, token, model);
|
||||
|
@ -111,8 +120,8 @@ public class ContentContentController {
|
|||
|
||||
@GetMapping("{prefix}/page/{page:\\d+}")
|
||||
public String content(@PathVariable("prefix") String prefix,
|
||||
@PathVariable(value = "page") Integer page,
|
||||
Model model) {
|
||||
@PathVariable(value = "page") Integer page,
|
||||
Model model) {
|
||||
if (optionService.getArchivesPrefix().equals(prefix)) {
|
||||
return postModel.archives(page, model);
|
||||
}
|
||||
|
@ -130,22 +139,24 @@ public class ContentContentController {
|
|||
|
||||
@GetMapping("{prefix}/{slug}")
|
||||
public String content(@PathVariable("prefix") String prefix,
|
||||
@PathVariable("slug") String slug,
|
||||
@RequestParam(value = "token", required = false) String token,
|
||||
Model model) {
|
||||
@PathVariable("slug") String slug,
|
||||
@RequestParam(value = "token", required = false) String token,
|
||||
Model model) {
|
||||
PostPermalinkType postPermalinkType = optionService.getPostPermalinkType();
|
||||
if (optionService.getArchivesPrefix().equals(prefix)) {
|
||||
if (postPermalinkType.equals(PostPermalinkType.DEFAULT)) {
|
||||
Post post = postService.getBySlug(slug);
|
||||
return postModel.content(post, token, model);
|
||||
}
|
||||
if (postPermalinkType.equals(PostPermalinkType.ID_SLUG) && StringUtils.isNumeric(slug)) {
|
||||
if (postPermalinkType.equals(PostPermalinkType.ID_SLUG)
|
||||
&& StringUtils.isNumeric(slug)) {
|
||||
Post post = postService.getById(Integer.parseInt(slug));
|
||||
return postModel.content(post, token, model);
|
||||
}
|
||||
}
|
||||
|
||||
if (optionService.getSheetPermalinkType().equals(SheetPermalinkType.SECONDARY) && optionService.getSheetPrefix().equals(prefix)) {
|
||||
if (optionService.getSheetPermalinkType().equals(SheetPermalinkType.SECONDARY)
|
||||
&& optionService.getSheetPrefix().equals(prefix)) {
|
||||
Sheet sheet = sheetService.getBySlug(slug);
|
||||
return sheetModel.content(sheet, token, model);
|
||||
}
|
||||
|
@ -158,7 +169,8 @@ public class ContentContentController {
|
|||
return tagModel.listPost(model, slug, 1);
|
||||
}
|
||||
|
||||
if (postPermalinkType.equals(PostPermalinkType.YEAR) && prefix.length() == 4 && StringUtils.isNumeric(prefix)) {
|
||||
if (postPermalinkType.equals(PostPermalinkType.YEAR) && prefix.length() == 4
|
||||
&& StringUtils.isNumeric(prefix)) {
|
||||
Post post = postService.getBy(Integer.parseInt(prefix), slug);
|
||||
return postModel.content(post, token, model);
|
||||
}
|
||||
|
@ -168,9 +180,9 @@ public class ContentContentController {
|
|||
|
||||
@GetMapping("{prefix}/{slug}/page/{page:\\d+}")
|
||||
public String content(@PathVariable("prefix") String prefix,
|
||||
@PathVariable("slug") String slug,
|
||||
@PathVariable("page") Integer page,
|
||||
Model model) {
|
||||
@PathVariable("slug") String slug,
|
||||
@PathVariable("page") Integer page,
|
||||
Model model) {
|
||||
if (optionService.getCategoriesPrefix().equals(prefix)) {
|
||||
return categoryModel.listPost(model, slug, page);
|
||||
}
|
||||
|
@ -184,10 +196,10 @@ public class ContentContentController {
|
|||
|
||||
@GetMapping("{year:\\d+}/{month:\\d+}/{slug}")
|
||||
public String content(@PathVariable("year") Integer year,
|
||||
@PathVariable("month") Integer month,
|
||||
@PathVariable("slug") String slug,
|
||||
@RequestParam(value = "token", required = false) String token,
|
||||
Model model) {
|
||||
@PathVariable("month") Integer month,
|
||||
@PathVariable("slug") String slug,
|
||||
@RequestParam(value = "token", required = false) String token,
|
||||
Model model) {
|
||||
PostPermalinkType postPermalinkType = optionService.getPostPermalinkType();
|
||||
if (postPermalinkType.equals(PostPermalinkType.DATE)) {
|
||||
Post post = postService.getBy(year, month, slug);
|
||||
|
@ -199,11 +211,11 @@ public class ContentContentController {
|
|||
|
||||
@GetMapping("{year:\\d+}/{month:\\d+}/{day:\\d+}/{slug}")
|
||||
public String content(@PathVariable("year") Integer year,
|
||||
@PathVariable("month") Integer month,
|
||||
@PathVariable("day") Integer day,
|
||||
@PathVariable("slug") String slug,
|
||||
@RequestParam(value = "token", required = false) String token,
|
||||
Model model) {
|
||||
@PathVariable("month") Integer month,
|
||||
@PathVariable("day") Integer day,
|
||||
@PathVariable("slug") String slug,
|
||||
@RequestParam(value = "token", required = false) String token,
|
||||
Model model) {
|
||||
PostPermalinkType postPermalinkType = optionService.getPostPermalinkType();
|
||||
if (postPermalinkType.equals(PostPermalinkType.DAY)) {
|
||||
Post post = postService.getBy(year, month, day, slug);
|
||||
|
@ -216,7 +228,7 @@ public class ContentContentController {
|
|||
@PostMapping(value = "archives/{slug:.*}/password")
|
||||
@CacheLock(traceRequest = true, expired = 2)
|
||||
public String password(@PathVariable("slug") String slug,
|
||||
@RequestParam(value = "password") String password) throws UnsupportedEncodingException {
|
||||
@RequestParam(value = "password") String password) throws UnsupportedEncodingException {
|
||||
Post post = postService.getBy(PostStatus.INTIMATE, slug);
|
||||
|
||||
post.setSlug(URLEncoder.encode(post.getSlug(), StandardCharsets.UTF_8.name()));
|
||||
|
@ -237,10 +249,10 @@ public class ContentContentController {
|
|||
|
||||
if (optionService.getPostPermalinkType().equals(PostPermalinkType.ID)) {
|
||||
redirectUrl.append("&token=")
|
||||
.append(token);
|
||||
.append(token);
|
||||
} else {
|
||||
redirectUrl.append("?token=")
|
||||
.append(token);
|
||||
.append(token);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,11 @@
|
|||
package run.halo.app.controller.content;
|
||||
|
||||
import static org.springframework.data.domain.Sort.Direction.DESC;
|
||||
|
||||
import freemarker.template.Template;
|
||||
import freemarker.template.TemplateException;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.RegExUtils;
|
||||
import org.springframework.data.domain.Page;
|
||||
|
@ -29,11 +33,6 @@ import run.halo.app.service.OptionService;
|
|||
import run.halo.app.service.PostCategoryService;
|
||||
import run.halo.app.service.PostService;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
import static org.springframework.data.domain.Sort.Direction.DESC;
|
||||
|
||||
/**
|
||||
* @author ryanwang
|
||||
* @date 2019-03-21
|
||||
|
@ -42,11 +41,11 @@ import static org.springframework.data.domain.Sort.Direction.DESC;
|
|||
@Controller
|
||||
public class ContentFeedController {
|
||||
|
||||
private final static String UTF_8_SUFFIX = ";charset=UTF-8";
|
||||
private static final String UTF_8_SUFFIX = ";charset=UTF-8";
|
||||
|
||||
private final static String XML_INVALID_CHAR = "[\\x00-\\x1F\\x7F]";
|
||||
private static final String XML_INVALID_CHAR = "[\\x00-\\x1F\\x7F]";
|
||||
|
||||
private final static String XML_MEDIA_TYPE = MediaType.APPLICATION_XML_VALUE + UTF_8_SUFFIX;
|
||||
private static final String XML_MEDIA_TYPE = MediaType.APPLICATION_XML_VALUE + UTF_8_SUFFIX;
|
||||
|
||||
private final PostService postService;
|
||||
|
||||
|
@ -59,10 +58,10 @@ public class ContentFeedController {
|
|||
private final FreeMarkerConfigurer freeMarker;
|
||||
|
||||
public ContentFeedController(PostService postService,
|
||||
CategoryService categoryService,
|
||||
PostCategoryService postCategoryService,
|
||||
OptionService optionService,
|
||||
FreeMarkerConfigurer freeMarker) {
|
||||
CategoryService categoryService,
|
||||
PostCategoryService postCategoryService,
|
||||
OptionService optionService,
|
||||
FreeMarkerConfigurer freeMarker) {
|
||||
this.postService = postService;
|
||||
this.categoryService = categoryService;
|
||||
this.postCategoryService = postCategoryService;
|
||||
|
@ -90,18 +89,21 @@ public class ContentFeedController {
|
|||
* Get category post rss.
|
||||
*
|
||||
* @param model model
|
||||
* @param slug slug
|
||||
* @param slug slug
|
||||
* @return rss xml content
|
||||
* @throws IOException throw IOException
|
||||
* @throws TemplateException throw TemplateException
|
||||
*/
|
||||
@GetMapping(value = {"feed/categories/{slug}", "feed/categories/{slug}.xml"}, produces = XML_MEDIA_TYPE)
|
||||
@GetMapping(value = {"feed/categories/{slug}",
|
||||
"feed/categories/{slug}.xml"}, produces = XML_MEDIA_TYPE)
|
||||
@ResponseBody
|
||||
public String feed(Model model, @PathVariable(name = "slug") String slug) throws IOException, TemplateException {
|
||||
public String feed(Model model, @PathVariable(name = "slug") String slug)
|
||||
throws IOException, TemplateException {
|
||||
Category category = categoryService.getBySlugOfNonNull(slug);
|
||||
CategoryDTO categoryDTO = categoryService.convertTo(category);
|
||||
model.addAttribute("category", categoryDTO);
|
||||
model.addAttribute("posts", buildCategoryPosts(buildPostPageable(optionService.getRssPageSize()), categoryDTO));
|
||||
model.addAttribute("posts",
|
||||
buildCategoryPosts(buildPostPageable(optionService.getRssPageSize()), categoryDTO));
|
||||
Template template = freeMarker.getConfiguration().getTemplate("common/web/rss.ftl");
|
||||
return FreeMarkerTemplateUtils.processTemplateIntoString(template, model);
|
||||
}
|
||||
|
@ -126,18 +128,21 @@ public class ContentFeedController {
|
|||
* Get category posts atom.xml
|
||||
*
|
||||
* @param model model
|
||||
* @param slug slug
|
||||
* @param slug slug
|
||||
* @return atom xml content
|
||||
* @throws IOException throw IOException
|
||||
* @throws TemplateException throw TemplateException
|
||||
*/
|
||||
@GetMapping(value = {"atom/categories/{slug}", "atom/categories/{slug}.xml"}, produces = XML_MEDIA_TYPE)
|
||||
@GetMapping(value = {"atom/categories/{slug}",
|
||||
"atom/categories/{slug}.xml"}, produces = XML_MEDIA_TYPE)
|
||||
@ResponseBody
|
||||
public String atom(Model model, @PathVariable(name = "slug") String slug) throws IOException, TemplateException {
|
||||
public String atom(Model model, @PathVariable(name = "slug") String slug)
|
||||
throws IOException, TemplateException {
|
||||
Category category = categoryService.getBySlugOfNonNull(slug);
|
||||
CategoryDTO categoryDTO = categoryService.convertTo(category);
|
||||
model.addAttribute("category", categoryDTO);
|
||||
model.addAttribute("posts", buildCategoryPosts(buildPostPageable(optionService.getRssPageSize()), categoryDTO));
|
||||
model.addAttribute("posts",
|
||||
buildCategoryPosts(buildPostPageable(optionService.getRssPageSize()), categoryDTO));
|
||||
Template template = freeMarker.getConfiguration().getTemplate("common/web/atom.ftl");
|
||||
return FreeMarkerTemplateUtils.processTemplateIntoString(template, model);
|
||||
}
|
||||
|
@ -153,7 +158,8 @@ public class ContentFeedController {
|
|||
@GetMapping(value = {"sitemap", "sitemap.xml"}, produces = XML_MEDIA_TYPE)
|
||||
@ResponseBody
|
||||
public String sitemapXml(Model model,
|
||||
@PageableDefault(size = Integer.MAX_VALUE, sort = "createTime", direction = DESC) Pageable pageable) throws IOException, TemplateException {
|
||||
@PageableDefault(size = Integer.MAX_VALUE, sort = "createTime", direction = DESC)
|
||||
Pageable pageable) throws IOException, TemplateException {
|
||||
model.addAttribute("posts", buildPosts(pageable));
|
||||
Template template = freeMarker.getConfiguration().getTemplate("common/web/sitemap_xml.ftl");
|
||||
return FreeMarkerTemplateUtils.processTemplateIntoString(template, model);
|
||||
|
@ -167,7 +173,8 @@ public class ContentFeedController {
|
|||
*/
|
||||
@GetMapping(value = "sitemap.html")
|
||||
public String sitemapHtml(Model model,
|
||||
@PageableDefault(size = Integer.MAX_VALUE, sort = "createTime", direction = DESC) Pageable pageable) {
|
||||
@PageableDefault(size = Integer.MAX_VALUE, sort = "createTime", direction = DESC)
|
||||
Pageable pageable) {
|
||||
model.addAttribute("posts", buildPosts(pageable));
|
||||
return "common/web/sitemap_html";
|
||||
}
|
||||
|
@ -210,8 +217,10 @@ public class ContentFeedController {
|
|||
Page<Post> postPage = postService.pageBy(PostStatus.PUBLISHED, pageable);
|
||||
Page<PostDetailVO> posts = postService.convertToDetailVo(postPage);
|
||||
posts.getContent().forEach(postDetailVO -> {
|
||||
postDetailVO.setFormatContent(RegExUtils.replaceAll(postDetailVO.getFormatContent(), XML_INVALID_CHAR, ""));
|
||||
postDetailVO.setSummary(RegExUtils.replaceAll(postDetailVO.getSummary(), XML_INVALID_CHAR, ""));
|
||||
postDetailVO.setFormatContent(
|
||||
RegExUtils.replaceAll(postDetailVO.getFormatContent(), XML_INVALID_CHAR, ""));
|
||||
postDetailVO
|
||||
.setSummary(RegExUtils.replaceAll(postDetailVO.getSummary(), XML_INVALID_CHAR, ""));
|
||||
});
|
||||
return posts.getContent();
|
||||
}
|
||||
|
@ -223,15 +232,19 @@ public class ContentFeedController {
|
|||
* @param category category
|
||||
* @return list of post detail vo.
|
||||
*/
|
||||
private List<PostDetailVO> buildCategoryPosts(@NonNull Pageable pageable, @NonNull CategoryDTO category) {
|
||||
private List<PostDetailVO> buildCategoryPosts(@NonNull Pageable pageable,
|
||||
@NonNull CategoryDTO category) {
|
||||
Assert.notNull(pageable, "Pageable must not be null");
|
||||
Assert.notNull(category, "Category slug must not be null");
|
||||
|
||||
Page<Post> postPage = postCategoryService.pagePostBy(category.getId(), PostStatus.PUBLISHED, pageable);
|
||||
Page<Post> postPage =
|
||||
postCategoryService.pagePostBy(category.getId(), PostStatus.PUBLISHED, pageable);
|
||||
Page<PostDetailVO> posts = postService.convertToDetailVo(postPage);
|
||||
posts.getContent().forEach(postDetailVO -> {
|
||||
postDetailVO.setFormatContent(RegExUtils.replaceAll(postDetailVO.getFormatContent(), XML_INVALID_CHAR, ""));
|
||||
postDetailVO.setSummary(RegExUtils.replaceAll(postDetailVO.getSummary(), XML_INVALID_CHAR, ""));
|
||||
postDetailVO.setFormatContent(
|
||||
RegExUtils.replaceAll(postDetailVO.getFormatContent(), XML_INVALID_CHAR, ""));
|
||||
postDetailVO
|
||||
.setSummary(RegExUtils.replaceAll(postDetailVO.getSummary(), XML_INVALID_CHAR, ""));
|
||||
});
|
||||
return posts.getContent();
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package run.halo.app.controller.content;
|
||||
|
||||
import java.util.Objects;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
|
@ -12,8 +13,6 @@ import run.halo.app.model.enums.PostPermalinkType;
|
|||
import run.halo.app.service.OptionService;
|
||||
import run.halo.app.service.PostService;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Blog index page controller
|
||||
*
|
||||
|
@ -32,8 +31,8 @@ public class ContentIndexController {
|
|||
private final PostModel postModel;
|
||||
|
||||
public ContentIndexController(PostService postService,
|
||||
OptionService optionService,
|
||||
PostModel postModel) {
|
||||
OptionService optionService,
|
||||
PostModel postModel) {
|
||||
this.postService = postService;
|
||||
this.optionService = optionService;
|
||||
this.postModel = postModel;
|
||||
|
@ -43,7 +42,7 @@ public class ContentIndexController {
|
|||
/**
|
||||
* Render blog index
|
||||
*
|
||||
* @param p post id
|
||||
* @param p post id
|
||||
* @param model model
|
||||
* @return template path: themes/{theme}/index.ftl
|
||||
*/
|
||||
|
@ -64,12 +63,12 @@ public class ContentIndexController {
|
|||
* Render blog index
|
||||
*
|
||||
* @param model model
|
||||
* @param page current page number
|
||||
* @param page current page number
|
||||
* @return template path: themes/{theme}/index.ftl
|
||||
*/
|
||||
@GetMapping(value = "page/{page}")
|
||||
public String index(Model model,
|
||||
@PathVariable(value = "page") Integer page) {
|
||||
@PathVariable(value = "page") Integer page) {
|
||||
return postModel.list(page, model);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package run.halo.app.controller.content;
|
||||
|
||||
import static org.springframework.data.domain.Sort.Direction.DESC;
|
||||
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
|
@ -18,8 +20,6 @@ import run.halo.app.service.OptionService;
|
|||
import run.halo.app.service.PostService;
|
||||
import run.halo.app.service.ThemeService;
|
||||
|
||||
import static org.springframework.data.domain.Sort.Direction.DESC;
|
||||
|
||||
/**
|
||||
* Search controller.
|
||||
*
|
||||
|
@ -36,7 +36,8 @@ public class ContentSearchController {
|
|||
|
||||
private final ThemeService themeService;
|
||||
|
||||
public ContentSearchController(PostService postService, OptionService optionService, ThemeService themeService) {
|
||||
public ContentSearchController(PostService postService, OptionService optionService,
|
||||
ThemeService themeService) {
|
||||
this.postService = postService;
|
||||
this.optionService = optionService;
|
||||
this.themeService = themeService;
|
||||
|
@ -45,28 +46,28 @@ public class ContentSearchController {
|
|||
/**
|
||||
* Render post search page.
|
||||
*
|
||||
* @param model model
|
||||
* @param model model
|
||||
* @param keyword keyword
|
||||
* @return template path : themes/{theme}/search.ftl
|
||||
*/
|
||||
@GetMapping
|
||||
public String search(Model model,
|
||||
@RequestParam(value = "keyword") String keyword) {
|
||||
@RequestParam(value = "keyword") String keyword) {
|
||||
return this.search(model, HtmlUtils.htmlEscape(keyword), 1, Sort.by(DESC, "createTime"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Render post search page.
|
||||
*
|
||||
* @param model model
|
||||
* @param model model
|
||||
* @param keyword keyword
|
||||
* @return template path :themes/{theme}/search.ftl
|
||||
*/
|
||||
@GetMapping(value = "page/{page}")
|
||||
public String search(Model model,
|
||||
@RequestParam(value = "keyword") String keyword,
|
||||
@PathVariable(value = "page") Integer page,
|
||||
@SortDefault(sort = "createTime", direction = DESC) Sort sort) {
|
||||
@RequestParam(value = "keyword") String keyword,
|
||||
@PathVariable(value = "page") Integer page,
|
||||
@SortDefault(sort = "createTime", direction = DESC) Sort sort) {
|
||||
final Pageable pageable = PageRequest.of(page - 1, optionService.getPostPageSize(), sort);
|
||||
final Page<Post> postPage = postService.pageBy(keyword, pageable);
|
||||
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package run.halo.app.controller.content;
|
||||
|
||||
import java.io.IOException;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
|
@ -13,9 +15,6 @@ import run.halo.app.service.OptionService;
|
|||
import run.halo.app.service.UserService;
|
||||
import run.halo.app.utils.HaloUtils;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Main controller.
|
||||
*
|
||||
|
@ -28,12 +27,12 @@ public class MainController {
|
|||
/**
|
||||
* Index redirect uri.
|
||||
*/
|
||||
private final static String INDEX_REDIRECT_URI = "index.html";
|
||||
private static final String INDEX_REDIRECT_URI = "index.html";
|
||||
|
||||
/**
|
||||
* Install redirect uri.
|
||||
*/
|
||||
private final static String INSTALL_REDIRECT_URI = INDEX_REDIRECT_URI + "#install";
|
||||
private static final String INSTALL_REDIRECT_URI = INDEX_REDIRECT_URI + "#install";
|
||||
|
||||
private final UserService userService;
|
||||
|
||||
|
@ -41,7 +40,8 @@ public class MainController {
|
|||
|
||||
private final HaloProperties haloProperties;
|
||||
|
||||
public MainController(UserService userService, OptionService optionService, HaloProperties haloProperties) {
|
||||
public MainController(UserService userService, OptionService optionService,
|
||||
HaloProperties haloProperties) {
|
||||
this.userService = userService;
|
||||
this.optionService = optionService;
|
||||
this.haloProperties = haloProperties;
|
||||
|
@ -49,7 +49,9 @@ public class MainController {
|
|||
|
||||
@GetMapping("${halo.admin-path:admin}")
|
||||
public void admin(HttpServletResponse response) throws IOException {
|
||||
String adminIndexRedirectUri = HaloUtils.ensureBoth(haloProperties.getAdminPath(), HaloUtils.URL_SEPARATOR) + INDEX_REDIRECT_URI;
|
||||
String adminIndexRedirectUri =
|
||||
HaloUtils.ensureBoth(haloProperties.getAdminPath(), HaloUtils.URL_SEPARATOR)
|
||||
+ INDEX_REDIRECT_URI;
|
||||
response.sendRedirect(adminIndexRedirectUri);
|
||||
}
|
||||
|
||||
|
@ -61,13 +63,16 @@ public class MainController {
|
|||
|
||||
@GetMapping("install")
|
||||
public void installation(HttpServletResponse response) throws IOException {
|
||||
String installRedirectUri = StringUtils.appendIfMissing(this.haloProperties.getAdminPath(), "/") + INSTALL_REDIRECT_URI;
|
||||
String installRedirectUri =
|
||||
StringUtils.appendIfMissing(this.haloProperties.getAdminPath(), "/")
|
||||
+ INSTALL_REDIRECT_URI;
|
||||
response.sendRedirect(installRedirectUri);
|
||||
}
|
||||
|
||||
@GetMapping("avatar")
|
||||
public void avatar(HttpServletResponse response) throws IOException {
|
||||
User user = userService.getCurrentUser().orElseThrow(() -> new ServiceException("未查询到博主信息"));
|
||||
User user =
|
||||
userService.getCurrentUser().orElseThrow(() -> new ServiceException("未查询到博主信息"));
|
||||
if (StringUtils.isNotEmpty(user.getAvatar())) {
|
||||
response.sendRedirect(HaloUtils.normalizeUrl(user.getAvatar()));
|
||||
}
|
||||
|
@ -75,7 +80,8 @@ public class MainController {
|
|||
|
||||
@GetMapping("logo")
|
||||
public void logo(HttpServletResponse response) throws IOException {
|
||||
String blogLogo = optionService.getByProperty(BlogProperties.BLOG_LOGO).orElse("").toString();
|
||||
String blogLogo =
|
||||
optionService.getByProperty(BlogProperties.BLOG_LOGO).orElse("").toString();
|
||||
if (StringUtils.isNotEmpty(blogLogo)) {
|
||||
response.sendRedirect(HaloUtils.normalizeUrl(blogLogo));
|
||||
}
|
||||
|
@ -83,7 +89,8 @@ public class MainController {
|
|||
|
||||
@GetMapping("favicon.ico")
|
||||
public void favicon(HttpServletResponse response) throws IOException {
|
||||
String favicon = optionService.getByProperty(BlogProperties.BLOG_FAVICON).orElse("").toString();
|
||||
String favicon =
|
||||
optionService.getByProperty(BlogProperties.BLOG_FAVICON).orElse("").toString();
|
||||
if (StringUtils.isNotEmpty(favicon)) {
|
||||
response.sendRedirect(HaloUtils.normalizeUrl(favicon));
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package run.halo.app.controller.content.api;
|
||||
|
||||
import java.util.List;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
@ -7,8 +8,6 @@ import run.halo.app.model.vo.ArchiveMonthVO;
|
|||
import run.halo.app.model.vo.ArchiveYearVO;
|
||||
import run.halo.app.service.PostService;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Content archive controller.
|
||||
*
|
||||
|
|
|
@ -1,12 +1,19 @@
|
|||
package run.halo.app.controller.content.api;
|
||||
|
||||
import static org.springframework.data.domain.Sort.Direction.DESC;
|
||||
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import java.util.List;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.web.PageableDefault;
|
||||
import org.springframework.data.web.SortDefault;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import run.halo.app.model.dto.CategoryDTO;
|
||||
import run.halo.app.model.entity.Category;
|
||||
import run.halo.app.model.entity.Post;
|
||||
|
@ -16,10 +23,6 @@ import run.halo.app.service.CategoryService;
|
|||
import run.halo.app.service.PostCategoryService;
|
||||
import run.halo.app.service.PostService;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.springframework.data.domain.Sort.Direction.DESC;
|
||||
|
||||
/**
|
||||
* Content category controller.
|
||||
*
|
||||
|
@ -37,8 +40,8 @@ public class CategoryController {
|
|||
private final PostService postService;
|
||||
|
||||
public CategoryController(CategoryService categoryService,
|
||||
PostCategoryService postCategoryService,
|
||||
PostService postService) {
|
||||
PostCategoryService postCategoryService,
|
||||
PostService postService) {
|
||||
this.categoryService = categoryService;
|
||||
this.postCategoryService = postCategoryService;
|
||||
this.postService = postService;
|
||||
|
@ -46,8 +49,9 @@ public class CategoryController {
|
|||
|
||||
@GetMapping
|
||||
@ApiOperation("Lists categories")
|
||||
public List<? extends CategoryDTO> listCategories(@SortDefault(sort = "updateTime", direction = DESC) Sort sort,
|
||||
@RequestParam(name = "more", required = false, defaultValue = "false") Boolean more) {
|
||||
public List<? extends CategoryDTO> listCategories(
|
||||
@SortDefault(sort = "updateTime", direction = DESC) Sort sort,
|
||||
@RequestParam(name = "more", required = false, defaultValue = "false") Boolean more) {
|
||||
if (more) {
|
||||
return postCategoryService.listCategoryWithPostCountDto(sort);
|
||||
}
|
||||
|
@ -57,11 +61,13 @@ public class CategoryController {
|
|||
@GetMapping("{slug}/posts")
|
||||
@ApiOperation("Lists posts by category slug")
|
||||
public Page<PostListVO> listPostsBy(@PathVariable("slug") String slug,
|
||||
@PageableDefault(sort = {"topPriority", "updateTime"}, direction = DESC) Pageable pageable) {
|
||||
@PageableDefault(sort = {"topPriority", "updateTime"}, direction = DESC)
|
||||
Pageable pageable) {
|
||||
// Get category by slug
|
||||
Category category = categoryService.getBySlugOfNonNull(slug);
|
||||
|
||||
Page<Post> postPage = postCategoryService.pagePostBy(category.getId(), PostStatus.PUBLISHED, pageable);
|
||||
Page<Post> postPage =
|
||||
postCategoryService.pagePostBy(category.getId(), PostStatus.PUBLISHED, pageable);
|
||||
return postService.convertToListVo(postPage);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,13 +1,23 @@
|
|||
package run.halo.app.controller.content.api;
|
||||
|
||||
import static org.springframework.data.domain.Sort.Direction.DESC;
|
||||
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.List;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.web.PageableDefault;
|
||||
import org.springframework.data.web.SortDefault;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.util.HtmlUtils;
|
||||
import run.halo.app.cache.lock.CacheLock;
|
||||
import run.halo.app.model.dto.BaseCommentDTO;
|
||||
|
@ -25,11 +35,6 @@ import run.halo.app.service.JournalCommentService;
|
|||
import run.halo.app.service.JournalService;
|
||||
import run.halo.app.service.OptionService;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.List;
|
||||
|
||||
import static org.springframework.data.domain.Sort.Direction.DESC;
|
||||
|
||||
/**
|
||||
* Content journal controller.
|
||||
*
|
||||
|
@ -48,8 +53,8 @@ public class JournalController {
|
|||
private final OptionService optionService;
|
||||
|
||||
public JournalController(JournalService journalService,
|
||||
JournalCommentService journalCommentService,
|
||||
OptionService optionService) {
|
||||
JournalCommentService journalCommentService,
|
||||
OptionService optionService) {
|
||||
this.journalService = journalService;
|
||||
this.journalCommentService = journalCommentService;
|
||||
this.optionService = optionService;
|
||||
|
@ -57,7 +62,8 @@ public class JournalController {
|
|||
|
||||
@GetMapping
|
||||
@ApiOperation("Lists journals")
|
||||
public Page<JournalWithCmtCountDTO> pageBy(@PageableDefault(sort = "createTime", direction = DESC) Pageable pageable) {
|
||||
public Page<JournalWithCmtCountDTO> pageBy(
|
||||
@PageableDefault(sort = "createTime", direction = DESC) Pageable pageable) {
|
||||
Page<Journal> journals = journalService.pageBy(JournalType.PUBLIC, pageable);
|
||||
return journalService.convertToCmtCountDto(journals);
|
||||
}
|
||||
|
@ -70,18 +76,21 @@ public class JournalController {
|
|||
}
|
||||
|
||||
@GetMapping("{journalId:\\d+}/comments/top_view")
|
||||
public Page<CommentWithHasChildrenVO> listTopComments(@PathVariable("journalId") Integer journalId,
|
||||
@RequestParam(name = "page", required = false, defaultValue = "0") int page,
|
||||
@SortDefault(sort = "createTime", direction = DESC) Sort sort) {
|
||||
return journalCommentService.pageTopCommentsBy(journalId, CommentStatus.PUBLISHED, PageRequest.of(page, optionService.getCommentPageSize(), sort));
|
||||
public Page<CommentWithHasChildrenVO> listTopComments(
|
||||
@PathVariable("journalId") Integer journalId,
|
||||
@RequestParam(name = "page", required = false, defaultValue = "0") int page,
|
||||
@SortDefault(sort = "createTime", direction = DESC) Sort sort) {
|
||||
return journalCommentService.pageTopCommentsBy(journalId, CommentStatus.PUBLISHED,
|
||||
PageRequest.of(page, optionService.getCommentPageSize(), sort));
|
||||
}
|
||||
|
||||
@GetMapping("{journalId:\\d+}/comments/{commentParentId:\\d+}/children")
|
||||
public List<BaseCommentDTO> listChildrenBy(@PathVariable("journalId") Integer journalId,
|
||||
@PathVariable("commentParentId") Long commentParentId,
|
||||
@SortDefault(sort = "createTime", direction = DESC) Sort sort) {
|
||||
@PathVariable("commentParentId") Long commentParentId,
|
||||
@SortDefault(sort = "createTime", direction = DESC) Sort sort) {
|
||||
// Find all children comments
|
||||
List<JournalComment> postComments = journalCommentService.listChildrenBy(journalId, commentParentId, CommentStatus.PUBLISHED, sort);
|
||||
List<JournalComment> postComments = journalCommentService
|
||||
.listChildrenBy(journalId, commentParentId, CommentStatus.PUBLISHED, sort);
|
||||
// Convert to base comment dto
|
||||
return journalCommentService.convertTo(postComments);
|
||||
}
|
||||
|
@ -89,17 +98,19 @@ public class JournalController {
|
|||
@GetMapping("{journalId:\\d+}/comments/tree_view")
|
||||
@ApiOperation("Lists comments with tree view")
|
||||
public Page<BaseCommentVO> listCommentsTree(@PathVariable("journalId") Integer journalId,
|
||||
@RequestParam(name = "page", required = false, defaultValue = "0") int page,
|
||||
@SortDefault(sort = "createTime", direction = DESC) Sort sort) {
|
||||
return journalCommentService.pageVosBy(journalId, PageRequest.of(page, optionService.getCommentPageSize(), sort));
|
||||
@RequestParam(name = "page", required = false, defaultValue = "0") int page,
|
||||
@SortDefault(sort = "createTime", direction = DESC) Sort sort) {
|
||||
return journalCommentService
|
||||
.pageVosBy(journalId, PageRequest.of(page, optionService.getCommentPageSize(), sort));
|
||||
}
|
||||
|
||||
@GetMapping("{journalId:\\d+}/comments/list_view")
|
||||
@ApiOperation("Lists comment with list view")
|
||||
public Page<BaseCommentWithParentVO> listComments(@PathVariable("journalId") Integer journalId,
|
||||
@RequestParam(name = "page", required = false, defaultValue = "0") int page,
|
||||
@SortDefault(sort = "createTime", direction = DESC) Sort sort) {
|
||||
return journalCommentService.pageWithParentVoBy(journalId, PageRequest.of(page, optionService.getCommentPageSize(), sort));
|
||||
@RequestParam(name = "page", required = false, defaultValue = "0") int page,
|
||||
@SortDefault(sort = "createTime", direction = DESC) Sort sort) {
|
||||
return journalCommentService.pageWithParentVoBy(journalId,
|
||||
PageRequest.of(page, optionService.getCommentPageSize(), sort));
|
||||
}
|
||||
|
||||
@PostMapping("comments")
|
||||
|
@ -108,7 +119,8 @@ public class JournalController {
|
|||
public BaseCommentDTO comment(@RequestBody JournalCommentParam journalCommentParam) {
|
||||
|
||||
// Escape content
|
||||
journalCommentParam.setContent(HtmlUtils.htmlEscape(journalCommentParam.getContent(), StandardCharsets.UTF_8.displayName()));
|
||||
journalCommentParam.setContent(HtmlUtils
|
||||
.htmlEscape(journalCommentParam.getContent(), StandardCharsets.UTF_8.displayName()));
|
||||
return journalCommentService.convertTo(journalCommentService.createBy(journalCommentParam));
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
package run.halo.app.controller.content.api;
|
||||
|
||||
import static org.springframework.data.domain.Sort.Direction.DESC;
|
||||
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import java.util.List;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.web.SortDefault;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
|
@ -10,10 +13,6 @@ import run.halo.app.model.dto.LinkDTO;
|
|||
import run.halo.app.model.vo.LinkTeamVO;
|
||||
import run.halo.app.service.LinkService;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.springframework.data.domain.Sort.Direction.DESC;
|
||||
|
||||
/**
|
||||
* Content link controller.
|
||||
*
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
package run.halo.app.controller.content.api;
|
||||
|
||||
import static org.springframework.data.domain.Sort.Direction.DESC;
|
||||
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import java.util.List;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.web.SortDefault;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
|
@ -10,10 +13,6 @@ import run.halo.app.model.dto.MenuDTO;
|
|||
import run.halo.app.model.vo.MenuVO;
|
||||
import run.halo.app.service.MenuService;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.springframework.data.domain.Sort.Direction.DESC;
|
||||
|
||||
/**
|
||||
* Content menu controller.
|
||||
*
|
||||
|
@ -39,7 +38,8 @@ public class MenuController {
|
|||
|
||||
@GetMapping(value = "tree_view")
|
||||
@ApiOperation("Lists menus with tree view")
|
||||
public List<MenuVO> listMenusTree(@SortDefault(sort = "createTime", direction = DESC) Sort sort) {
|
||||
public List<MenuVO> listMenusTree(
|
||||
@SortDefault(sort = "createTime", direction = DESC) Sort sort) {
|
||||
return menuService.listAsTree(sort);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,16 +1,19 @@
|
|||
package run.halo.app.controller.content.api;
|
||||
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import run.halo.app.model.dto.OptionDTO;
|
||||
import run.halo.app.model.support.BaseResponse;
|
||||
import run.halo.app.service.OptionService;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import run.halo.app.model.dto.OptionDTO;
|
||||
import run.halo.app.model.support.BaseResponse;
|
||||
import run.halo.app.service.OptionService;
|
||||
|
||||
/**
|
||||
* Content option controller.
|
||||
|
@ -36,7 +39,8 @@ public class OptionController {
|
|||
|
||||
@GetMapping("map_view")
|
||||
@ApiOperation("Lists options with map view")
|
||||
public Map<String, Object> listAllWithMapView(@RequestParam(value = "key", required = false) List<String> keys) {
|
||||
public Map<String, Object> listAllWithMapView(
|
||||
@RequestParam(value = "key", required = false) List<String> keys) {
|
||||
if (CollectionUtils.isEmpty(keys)) {
|
||||
return optionService.listOptions();
|
||||
}
|
||||
|
@ -47,7 +51,8 @@ public class OptionController {
|
|||
@GetMapping("keys/{key}")
|
||||
@ApiOperation("Gets option value by option key")
|
||||
public BaseResponse<Object> getBy(@PathVariable("key") String key) {
|
||||
return BaseResponse.ok(HttpStatus.OK.getReasonPhrase(), optionService.getByKey(key).orElse(null));
|
||||
return BaseResponse
|
||||
.ok(HttpStatus.OK.getReasonPhrase(), optionService.getByKey(key).orElse(null));
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
package run.halo.app.controller.content.api;
|
||||
|
||||
import static org.springframework.data.domain.Sort.Direction.DESC;
|
||||
|
||||
import java.util.List;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Sort;
|
||||
|
@ -12,10 +15,6 @@ import run.halo.app.model.dto.PhotoDTO;
|
|||
import run.halo.app.model.params.PhotoQuery;
|
||||
import run.halo.app.service.PhotoService;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.springframework.data.domain.Sort.Direction.DESC;
|
||||
|
||||
/**
|
||||
* Content photo controller.
|
||||
*
|
||||
|
@ -39,13 +38,15 @@ public class PhotoController {
|
|||
* @return all of photos
|
||||
*/
|
||||
@GetMapping(value = "latest")
|
||||
public List<PhotoDTO> listPhotos(@SortDefault(sort = "updateTime", direction = Sort.Direction.DESC) Sort sort) {
|
||||
public List<PhotoDTO> listPhotos(
|
||||
@SortDefault(sort = "updateTime", direction = Sort.Direction.DESC) Sort sort) {
|
||||
return photoService.listDtos(sort);
|
||||
}
|
||||
|
||||
@GetMapping
|
||||
public Page<PhotoDTO> pageBy(@PageableDefault(sort = "updateTime", direction = DESC) Pageable pageable,
|
||||
PhotoQuery photoQuery) {
|
||||
public Page<PhotoDTO> pageBy(
|
||||
@PageableDefault(sort = "updateTime", direction = DESC) Pageable pageable,
|
||||
PhotoQuery photoQuery) {
|
||||
return photoService.pageDtosBy(pageable, photoQuery);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,13 +1,23 @@
|
|||
package run.halo.app.controller.content.api;
|
||||
|
||||
import static org.springframework.data.domain.Sort.Direction.DESC;
|
||||
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.List;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.web.PageableDefault;
|
||||
import org.springframework.data.web.SortDefault;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.util.HtmlUtils;
|
||||
import run.halo.app.cache.lock.CacheLock;
|
||||
import run.halo.app.exception.NotFoundException;
|
||||
|
@ -18,16 +28,15 @@ import run.halo.app.model.entity.PostComment;
|
|||
import run.halo.app.model.enums.CommentStatus;
|
||||
import run.halo.app.model.enums.PostStatus;
|
||||
import run.halo.app.model.params.PostCommentParam;
|
||||
import run.halo.app.model.vo.*;
|
||||
import run.halo.app.model.vo.BaseCommentVO;
|
||||
import run.halo.app.model.vo.BaseCommentWithParentVO;
|
||||
import run.halo.app.model.vo.CommentWithHasChildrenVO;
|
||||
import run.halo.app.model.vo.PostDetailVO;
|
||||
import run.halo.app.model.vo.PostListVO;
|
||||
import run.halo.app.service.OptionService;
|
||||
import run.halo.app.service.PostCommentService;
|
||||
import run.halo.app.service.PostService;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.List;
|
||||
|
||||
import static org.springframework.data.domain.Sort.Direction.DESC;
|
||||
|
||||
/**
|
||||
* Content post controller.
|
||||
*
|
||||
|
@ -46,8 +55,8 @@ public class PostController {
|
|||
private final OptionService optionService;
|
||||
|
||||
public PostController(PostService postService,
|
||||
PostCommentService postCommentService,
|
||||
OptionService optionService) {
|
||||
PostCommentService postCommentService,
|
||||
OptionService optionService) {
|
||||
this.postService = postService;
|
||||
this.postCommentService = postCommentService;
|
||||
this.optionService = optionService;
|
||||
|
@ -55,7 +64,8 @@ public class PostController {
|
|||
|
||||
@GetMapping
|
||||
@ApiOperation("Lists posts")
|
||||
public Page<PostListVO> pageBy(@PageableDefault(sort = "createTime", direction = DESC) Pageable pageable) {
|
||||
public Page<PostListVO> pageBy(
|
||||
@PageableDefault(sort = "createTime", direction = DESC) Pageable pageable) {
|
||||
Page<Post> postPage = postService.pageBy(PostStatus.PUBLISHED, pageable);
|
||||
return postService.convertToListVo(postPage);
|
||||
}
|
||||
|
@ -63,7 +73,7 @@ public class PostController {
|
|||
@PostMapping(value = "search")
|
||||
@ApiOperation("Lists posts by keyword")
|
||||
public Page<BasePostSimpleDTO> pageBy(@RequestParam(value = "keyword") String keyword,
|
||||
@PageableDefault(sort = "createTime", direction = DESC) Pageable pageable) {
|
||||
@PageableDefault(sort = "createTime", direction = DESC) Pageable pageable) {
|
||||
Page<Post> postPage = postService.pageBy(keyword, pageable);
|
||||
return postService.convertToSimple(postPage);
|
||||
}
|
||||
|
@ -71,8 +81,10 @@ public class PostController {
|
|||
@GetMapping("{postId:\\d+}")
|
||||
@ApiOperation("Gets a post")
|
||||
public PostDetailVO getBy(@PathVariable("postId") Integer postId,
|
||||
@RequestParam(value = "formatDisabled", required = false, defaultValue = "true") Boolean formatDisabled,
|
||||
@RequestParam(value = "sourceDisabled", required = false, defaultValue = "false") Boolean sourceDisabled) {
|
||||
@RequestParam(value = "formatDisabled", required = false, defaultValue = "true")
|
||||
Boolean formatDisabled,
|
||||
@RequestParam(value = "sourceDisabled", required = false, defaultValue = "false")
|
||||
Boolean sourceDisabled) {
|
||||
PostDetailVO postDetailVO = postService.convertToDetailVo(postService.getById(postId));
|
||||
|
||||
if (formatDisabled) {
|
||||
|
@ -90,11 +102,36 @@ public class PostController {
|
|||
return postDetailVO;
|
||||
}
|
||||
|
||||
@GetMapping("/slug")
|
||||
@ApiOperation("Gets a post")
|
||||
public PostDetailVO getBy(@RequestParam("slug") String slug,
|
||||
@RequestParam(value = "formatDisabled", required = false, defaultValue = "true")
|
||||
Boolean formatDisabled,
|
||||
@RequestParam(value = "sourceDisabled", required = false, defaultValue = "false")
|
||||
Boolean sourceDisabled) {
|
||||
PostDetailVO postDetailVO = postService.convertToDetailVo(postService.getBySlug(slug));
|
||||
|
||||
if (formatDisabled) {
|
||||
// Clear the format content
|
||||
postDetailVO.setFormatContent(null);
|
||||
}
|
||||
|
||||
if (sourceDisabled) {
|
||||
// Clear the original content
|
||||
postDetailVO.setOriginalContent(null);
|
||||
}
|
||||
|
||||
postService.publishVisitEvent(postDetailVO.getId());
|
||||
|
||||
return postDetailVO;
|
||||
}
|
||||
|
||||
@GetMapping("{postId:\\d+}/prev")
|
||||
@ApiOperation("Gets previous post by current post id.")
|
||||
public PostDetailVO getPrevPostBy(@PathVariable("postId") Integer postId) {
|
||||
Post post = postService.getById(postId);
|
||||
Post prevPost = postService.getPrevPost(post).orElseThrow(() -> new NotFoundException("查询不到该文章的信息"));
|
||||
Post prevPost =
|
||||
postService.getPrevPost(post).orElseThrow(() -> new NotFoundException("查询不到该文章的信息"));
|
||||
return postService.convertToDetailVo(prevPost);
|
||||
}
|
||||
|
||||
|
@ -102,46 +139,26 @@ public class PostController {
|
|||
@ApiOperation("Gets next post by current post id.")
|
||||
public PostDetailVO getNextPostBy(@PathVariable("postId") Integer postId) {
|
||||
Post post = postService.getById(postId);
|
||||
Post nextPost = postService.getNextPost(post).orElseThrow(() -> new NotFoundException("查询不到该文章的信息"));
|
||||
Post nextPost =
|
||||
postService.getNextPost(post).orElseThrow(() -> new NotFoundException("查询不到该文章的信息"));
|
||||
return postService.convertToDetailVo(nextPost);
|
||||
}
|
||||
|
||||
@GetMapping("/slug")
|
||||
@ApiOperation("Gets a post")
|
||||
public PostDetailVO getBy(@RequestParam("slug") String slug,
|
||||
@RequestParam(value = "formatDisabled", required = false, defaultValue = "true") Boolean formatDisabled,
|
||||
@RequestParam(value = "sourceDisabled", required = false, defaultValue = "false") Boolean sourceDisabled) {
|
||||
PostDetailVO postDetailVO = postService.convertToDetailVo(postService.getBySlug(slug));
|
||||
|
||||
if (formatDisabled) {
|
||||
// Clear the format content
|
||||
postDetailVO.setFormatContent(null);
|
||||
}
|
||||
|
||||
if (sourceDisabled) {
|
||||
// Clear the original content
|
||||
postDetailVO.setOriginalContent(null);
|
||||
}
|
||||
|
||||
postService.publishVisitEvent(postDetailVO.getId());
|
||||
|
||||
return postDetailVO;
|
||||
}
|
||||
|
||||
@GetMapping("{postId:\\d+}/comments/top_view")
|
||||
public Page<CommentWithHasChildrenVO> listTopComments(@PathVariable("postId") Integer postId,
|
||||
@RequestParam(name = "page", required = false, defaultValue = "0") int page,
|
||||
@SortDefault(sort = "createTime", direction = DESC) Sort sort) {
|
||||
return postCommentService.pageTopCommentsBy(postId, CommentStatus.PUBLISHED, PageRequest.of(page, optionService.getCommentPageSize(), sort));
|
||||
@RequestParam(name = "page", required = false, defaultValue = "0") int page,
|
||||
@SortDefault(sort = "createTime", direction = DESC) Sort sort) {
|
||||
return postCommentService.pageTopCommentsBy(postId, CommentStatus.PUBLISHED,
|
||||
PageRequest.of(page, optionService.getCommentPageSize(), sort));
|
||||
}
|
||||
|
||||
|
||||
@GetMapping("{postId:\\d+}/comments/{commentParentId:\\d+}/children")
|
||||
public List<BaseCommentDTO> listChildrenBy(@PathVariable("postId") Integer postId,
|
||||
@PathVariable("commentParentId") Long commentParentId,
|
||||
@SortDefault(sort = "createTime", direction = DESC) Sort sort) {
|
||||
@PathVariable("commentParentId") Long commentParentId,
|
||||
@SortDefault(sort = "createTime", direction = DESC) Sort sort) {
|
||||
// Find all children comments
|
||||
List<PostComment> postComments = postCommentService.listChildrenBy(postId, commentParentId, CommentStatus.PUBLISHED, sort);
|
||||
List<PostComment> postComments = postCommentService
|
||||
.listChildrenBy(postId, commentParentId, CommentStatus.PUBLISHED, sort);
|
||||
// Convert to base comment dto
|
||||
|
||||
return postCommentService.convertTo(postComments);
|
||||
|
@ -150,17 +167,19 @@ public class PostController {
|
|||
@GetMapping("{postId:\\d+}/comments/tree_view")
|
||||
@ApiOperation("Lists comments with tree view")
|
||||
public Page<BaseCommentVO> listCommentsTree(@PathVariable("postId") Integer postId,
|
||||
@RequestParam(name = "page", required = false, defaultValue = "0") int page,
|
||||
@SortDefault(sort = "createTime", direction = DESC) Sort sort) {
|
||||
return postCommentService.pageVosBy(postId, PageRequest.of(page, optionService.getCommentPageSize(), sort));
|
||||
@RequestParam(name = "page", required = false, defaultValue = "0") int page,
|
||||
@SortDefault(sort = "createTime", direction = DESC) Sort sort) {
|
||||
return postCommentService
|
||||
.pageVosBy(postId, PageRequest.of(page, optionService.getCommentPageSize(), sort));
|
||||
}
|
||||
|
||||
@GetMapping("{postId:\\d+}/comments/list_view")
|
||||
@ApiOperation("Lists comment with list view")
|
||||
public Page<BaseCommentWithParentVO> listComments(@PathVariable("postId") Integer postId,
|
||||
@RequestParam(name = "page", required = false, defaultValue = "0") int page,
|
||||
@SortDefault(sort = "createTime", direction = DESC) Sort sort) {
|
||||
return postCommentService.pageWithParentVoBy(postId, PageRequest.of(page, optionService.getCommentPageSize(), sort));
|
||||
@RequestParam(name = "page", required = false, defaultValue = "0") int page,
|
||||
@SortDefault(sort = "createTime", direction = DESC) Sort sort) {
|
||||
return postCommentService.pageWithParentVoBy(postId,
|
||||
PageRequest.of(page, optionService.getCommentPageSize(), sort));
|
||||
}
|
||||
|
||||
@PostMapping("comments")
|
||||
|
@ -170,7 +189,8 @@ public class PostController {
|
|||
postCommentService.validateCommentBlackListStatus();
|
||||
|
||||
// Escape content
|
||||
postCommentParam.setContent(HtmlUtils.htmlEscape(postCommentParam.getContent(), StandardCharsets.UTF_8.displayName()));
|
||||
postCommentParam.setContent(HtmlUtils
|
||||
.htmlEscape(postCommentParam.getContent(), StandardCharsets.UTF_8.displayName()));
|
||||
return postCommentService.convertTo(postCommentService.createBy(postCommentParam));
|
||||
}
|
||||
|
||||
|
|
|
@ -1,13 +1,23 @@
|
|||
package run.halo.app.controller.content.api;
|
||||
|
||||
import static org.springframework.data.domain.Sort.Direction.DESC;
|
||||
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.List;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.web.PageableDefault;
|
||||
import org.springframework.data.web.SortDefault;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.util.HtmlUtils;
|
||||
import run.halo.app.cache.lock.CacheLock;
|
||||
import run.halo.app.model.dto.BaseCommentDTO;
|
||||
|
@ -16,16 +26,15 @@ import run.halo.app.model.entity.SheetComment;
|
|||
import run.halo.app.model.enums.CommentStatus;
|
||||
import run.halo.app.model.enums.PostStatus;
|
||||
import run.halo.app.model.params.SheetCommentParam;
|
||||
import run.halo.app.model.vo.*;
|
||||
import run.halo.app.model.vo.BaseCommentVO;
|
||||
import run.halo.app.model.vo.BaseCommentWithParentVO;
|
||||
import run.halo.app.model.vo.CommentWithHasChildrenVO;
|
||||
import run.halo.app.model.vo.SheetDetailVO;
|
||||
import run.halo.app.model.vo.SheetListVO;
|
||||
import run.halo.app.service.OptionService;
|
||||
import run.halo.app.service.SheetCommentService;
|
||||
import run.halo.app.service.SheetService;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.List;
|
||||
|
||||
import static org.springframework.data.domain.Sort.Direction.DESC;
|
||||
|
||||
/**
|
||||
* Content sheet controller.
|
||||
*
|
||||
|
@ -43,7 +52,8 @@ public class SheetController {
|
|||
|
||||
private final OptionService optionService;
|
||||
|
||||
public SheetController(SheetService sheetService, SheetCommentService sheetCommentService, OptionService optionService) {
|
||||
public SheetController(SheetService sheetService, SheetCommentService sheetCommentService,
|
||||
OptionService optionService) {
|
||||
this.sheetService = sheetService;
|
||||
this.sheetCommentService = sheetCommentService;
|
||||
this.optionService = optionService;
|
||||
|
@ -51,7 +61,8 @@ public class SheetController {
|
|||
|
||||
@GetMapping
|
||||
@ApiOperation("Lists sheets")
|
||||
public Page<SheetListVO> pageBy(@PageableDefault(sort = "createTime", direction = DESC) Pageable pageable) {
|
||||
public Page<SheetListVO> pageBy(
|
||||
@PageableDefault(sort = "createTime", direction = DESC) Pageable pageable) {
|
||||
Page<Sheet> sheetPage = sheetService.pageBy(PostStatus.PUBLISHED, pageable);
|
||||
return sheetService.convertToListVo(sheetPage);
|
||||
}
|
||||
|
@ -59,8 +70,10 @@ public class SheetController {
|
|||
@GetMapping("{sheetId:\\d+}")
|
||||
@ApiOperation("Gets a sheet")
|
||||
public SheetDetailVO getBy(@PathVariable("sheetId") Integer sheetId,
|
||||
@RequestParam(value = "formatDisabled", required = false, defaultValue = "true") Boolean formatDisabled,
|
||||
@RequestParam(value = "sourceDisabled", required = false, defaultValue = "false") Boolean sourceDisabled) {
|
||||
@RequestParam(value = "formatDisabled", required = false, defaultValue = "true")
|
||||
Boolean formatDisabled,
|
||||
@RequestParam(value = "sourceDisabled", required = false, defaultValue = "false")
|
||||
Boolean sourceDisabled) {
|
||||
SheetDetailVO sheetDetailVO = sheetService.convertToDetailVo(sheetService.getById(sheetId));
|
||||
|
||||
if (formatDisabled) {
|
||||
|
@ -81,8 +94,10 @@ public class SheetController {
|
|||
@GetMapping("/slug")
|
||||
@ApiOperation("Gets a sheet by slug")
|
||||
public SheetDetailVO getBy(@RequestParam("slug") String slug,
|
||||
@RequestParam(value = "formatDisabled", required = false, defaultValue = "true") Boolean formatDisabled,
|
||||
@RequestParam(value = "sourceDisabled", required = false, defaultValue = "false") Boolean sourceDisabled) {
|
||||
@RequestParam(value = "formatDisabled", required = false, defaultValue = "true")
|
||||
Boolean formatDisabled,
|
||||
@RequestParam(value = "sourceDisabled", required = false, defaultValue = "false")
|
||||
Boolean sourceDisabled) {
|
||||
SheetDetailVO sheetDetailVO = sheetService.convertToDetailVo(sheetService.getBySlug(slug));
|
||||
|
||||
if (formatDisabled) {
|
||||
|
@ -102,17 +117,19 @@ public class SheetController {
|
|||
|
||||
@GetMapping("{sheetId:\\d+}/comments/top_view")
|
||||
public Page<CommentWithHasChildrenVO> listTopComments(@PathVariable("sheetId") Integer sheetId,
|
||||
@RequestParam(name = "page", required = false, defaultValue = "0") int page,
|
||||
@SortDefault(sort = "createTime", direction = DESC) Sort sort) {
|
||||
return sheetCommentService.pageTopCommentsBy(sheetId, CommentStatus.PUBLISHED, PageRequest.of(page, optionService.getCommentPageSize(), sort));
|
||||
@RequestParam(name = "page", required = false, defaultValue = "0") int page,
|
||||
@SortDefault(sort = "createTime", direction = DESC) Sort sort) {
|
||||
return sheetCommentService.pageTopCommentsBy(sheetId, CommentStatus.PUBLISHED,
|
||||
PageRequest.of(page, optionService.getCommentPageSize(), sort));
|
||||
}
|
||||
|
||||
@GetMapping("{sheetId:\\d+}/comments/{commentParentId:\\d+}/children")
|
||||
public List<BaseCommentDTO> listChildrenBy(@PathVariable("sheetId") Integer sheetId,
|
||||
@PathVariable("commentParentId") Long commentParentId,
|
||||
@SortDefault(sort = "createTime", direction = DESC) Sort sort) {
|
||||
@PathVariable("commentParentId") Long commentParentId,
|
||||
@SortDefault(sort = "createTime", direction = DESC) Sort sort) {
|
||||
// Find all children comments
|
||||
List<SheetComment> sheetComments = sheetCommentService.listChildrenBy(sheetId, commentParentId, CommentStatus.PUBLISHED, sort);
|
||||
List<SheetComment> sheetComments = sheetCommentService
|
||||
.listChildrenBy(sheetId, commentParentId, CommentStatus.PUBLISHED, sort);
|
||||
// Convert to base comment dto
|
||||
return sheetCommentService.convertTo(sheetComments);
|
||||
}
|
||||
|
@ -121,17 +138,19 @@ public class SheetController {
|
|||
@GetMapping("{sheetId:\\d+}/comments/tree_view")
|
||||
@ApiOperation("Lists comments with tree view")
|
||||
public Page<BaseCommentVO> listCommentsTree(@PathVariable("sheetId") Integer sheetId,
|
||||
@RequestParam(name = "page", required = false, defaultValue = "0") int page,
|
||||
@SortDefault(sort = "createTime", direction = DESC) Sort sort) {
|
||||
return sheetCommentService.pageVosBy(sheetId, PageRequest.of(page, optionService.getCommentPageSize(), sort));
|
||||
@RequestParam(name = "page", required = false, defaultValue = "0") int page,
|
||||
@SortDefault(sort = "createTime", direction = DESC) Sort sort) {
|
||||
return sheetCommentService
|
||||
.pageVosBy(sheetId, PageRequest.of(page, optionService.getCommentPageSize(), sort));
|
||||
}
|
||||
|
||||
@GetMapping("{sheetId:\\d+}/comments/list_view")
|
||||
@ApiOperation("Lists comment with list view")
|
||||
public Page<BaseCommentWithParentVO> listComments(@PathVariable("sheetId") Integer sheetId,
|
||||
@RequestParam(name = "page", required = false, defaultValue = "0") int page,
|
||||
@SortDefault(sort = "createTime", direction = DESC) Sort sort) {
|
||||
return sheetCommentService.pageWithParentVoBy(sheetId, PageRequest.of(page, optionService.getCommentPageSize(), sort));
|
||||
@RequestParam(name = "page", required = false, defaultValue = "0") int page,
|
||||
@SortDefault(sort = "createTime", direction = DESC) Sort sort) {
|
||||
return sheetCommentService.pageWithParentVoBy(sheetId,
|
||||
PageRequest.of(page, optionService.getCommentPageSize(), sort));
|
||||
}
|
||||
|
||||
@PostMapping("comments")
|
||||
|
@ -140,7 +159,8 @@ public class SheetController {
|
|||
public BaseCommentDTO comment(@RequestBody SheetCommentParam sheetCommentParam) {
|
||||
|
||||
// Escape content
|
||||
sheetCommentParam.setContent(HtmlUtils.htmlEscape(sheetCommentParam.getContent(), StandardCharsets.UTF_8.displayName()));
|
||||
sheetCommentParam.setContent(HtmlUtils
|
||||
.htmlEscape(sheetCommentParam.getContent(), StandardCharsets.UTF_8.displayName()));
|
||||
return sheetCommentService.convertTo(sheetCommentService.createBy(sheetCommentParam));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,13 +1,20 @@
|
|||
package run.halo.app.controller.content.api;
|
||||
|
||||
import static org.springframework.data.domain.Sort.Direction.DESC;
|
||||
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import io.swagger.annotations.ApiParam;
|
||||
import java.util.List;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.web.PageableDefault;
|
||||
import org.springframework.data.web.SortDefault;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import run.halo.app.model.dto.TagDTO;
|
||||
import run.halo.app.model.entity.Post;
|
||||
import run.halo.app.model.entity.Tag;
|
||||
|
@ -17,10 +24,6 @@ import run.halo.app.service.PostService;
|
|||
import run.halo.app.service.PostTagService;
|
||||
import run.halo.app.service.TagService;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.springframework.data.domain.Sort.Direction.DESC;
|
||||
|
||||
/**
|
||||
* Content tag controller.
|
||||
*
|
||||
|
@ -39,8 +42,8 @@ public class TagController {
|
|||
private final PostService postService;
|
||||
|
||||
public TagController(TagService tagService,
|
||||
PostTagService postTagService,
|
||||
PostService postService) {
|
||||
PostTagService postTagService,
|
||||
PostService postService) {
|
||||
this.tagService = tagService;
|
||||
this.postTagService = postTagService;
|
||||
this.postService = postService;
|
||||
|
@ -48,9 +51,10 @@ public class TagController {
|
|||
|
||||
@GetMapping
|
||||
@ApiOperation("Lists tags")
|
||||
public List<? extends TagDTO> listTags(@SortDefault(sort = "updateTime", direction = DESC) Sort sort,
|
||||
@ApiParam("If the param is true, post count of tag will be returned")
|
||||
@RequestParam(name = "more", required = false, defaultValue = "false") Boolean more) {
|
||||
public List<? extends TagDTO> listTags(
|
||||
@SortDefault(sort = "updateTime", direction = DESC) Sort sort,
|
||||
@ApiParam("If the param is true, post count of tag will be returned")
|
||||
@RequestParam(name = "more", required = false, defaultValue = "false") Boolean more) {
|
||||
if (more) {
|
||||
return postTagService.listTagWithCountDtos(sort);
|
||||
}
|
||||
|
@ -60,12 +64,14 @@ public class TagController {
|
|||
@GetMapping("{slug}/posts")
|
||||
@ApiOperation("Lists posts by tag slug")
|
||||
public Page<PostListVO> listPostsBy(@PathVariable("slug") String slug,
|
||||
@PageableDefault(sort = {"topPriority", "updateTime"}, direction = DESC) Pageable pageable) {
|
||||
@PageableDefault(sort = {"topPriority", "updateTime"}, direction = DESC)
|
||||
Pageable pageable) {
|
||||
// Get tag by slug
|
||||
Tag tag = tagService.getBySlugOfNonNull(slug);
|
||||
|
||||
// Get posts, convert and return
|
||||
Page<Post> postPage = postTagService.pagePostsBy(tag.getId(), PostStatus.PUBLISHED, pageable);
|
||||
Page<Post> postPage =
|
||||
postTagService.pagePostsBy(tag.getId(), PostStatus.PUBLISHED, pageable);
|
||||
return postService.convertToListVo(postPage);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package run.halo.app.controller.content.api;
|
||||
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import java.util.Map;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
@ -8,8 +9,6 @@ import run.halo.app.handler.theme.config.support.ThemeProperty;
|
|||
import run.halo.app.service.ThemeService;
|
||||
import run.halo.app.service.ThemeSettingService;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Content theme controller.
|
||||
*
|
||||
|
|
|
@ -26,6 +26,7 @@ public class UserController {
|
|||
@GetMapping("profile")
|
||||
@ApiOperation("Gets blogger profile")
|
||||
public UserDTO getProfile() {
|
||||
return userService.getCurrentUser().map(user -> (UserDTO) new UserDTO().convertFrom(user)).get();
|
||||
return userService.getCurrentUser().map(user -> (UserDTO) new UserDTO().convertFrom(user))
|
||||
.get();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package run.halo.app.controller.content.model;
|
||||
|
||||
import static org.springframework.data.domain.Sort.Direction.DESC;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
|
@ -12,9 +14,11 @@ import run.halo.app.model.entity.Category;
|
|||
import run.halo.app.model.entity.Post;
|
||||
import run.halo.app.model.enums.PostStatus;
|
||||
import run.halo.app.model.vo.PostListVO;
|
||||
import run.halo.app.service.*;
|
||||
|
||||
import static org.springframework.data.domain.Sort.Direction.DESC;
|
||||
import run.halo.app.service.CategoryService;
|
||||
import run.halo.app.service.OptionService;
|
||||
import run.halo.app.service.PostCategoryService;
|
||||
import run.halo.app.service.PostService;
|
||||
import run.halo.app.service.ThemeService;
|
||||
|
||||
/**
|
||||
* Category Model.
|
||||
|
@ -35,7 +39,9 @@ public class CategoryModel {
|
|||
|
||||
private final OptionService optionService;
|
||||
|
||||
public CategoryModel(CategoryService categoryService, ThemeService themeService, PostCategoryService postCategoryService, PostService postService, OptionService optionService) {
|
||||
public CategoryModel(CategoryService categoryService, ThemeService themeService,
|
||||
PostCategoryService postCategoryService, PostService postService,
|
||||
OptionService optionService) {
|
||||
this.categoryService = categoryService;
|
||||
this.themeService = themeService;
|
||||
this.postCategoryService = postCategoryService;
|
||||
|
@ -60,8 +66,8 @@ public class CategoryModel {
|
|||
* List category posts.
|
||||
*
|
||||
* @param model model
|
||||
* @param slug slug
|
||||
* @param page current page
|
||||
* @param slug slug
|
||||
* @param page current page
|
||||
* @return template name
|
||||
*/
|
||||
public String listPost(Model model, String slug, Integer page) {
|
||||
|
@ -70,9 +76,10 @@ public class CategoryModel {
|
|||
CategoryDTO categoryDTO = categoryService.convertTo(category);
|
||||
|
||||
final Pageable pageable = PageRequest.of(page - 1,
|
||||
optionService.getArchivesPageSize(),
|
||||
Sort.by(DESC, "topPriority", "createTime"));
|
||||
Page<Post> postPage = postCategoryService.pagePostBy(category.getId(), PostStatus.PUBLISHED, pageable);
|
||||
optionService.getArchivesPageSize(),
|
||||
Sort.by(DESC, "topPriority", "createTime"));
|
||||
Page<Post> postPage =
|
||||
postCategoryService.pagePostBy(category.getId(), PostStatus.PUBLISHED, pageable);
|
||||
Page<PostListVO> posts = postService.convertToListVo(postPage);
|
||||
|
||||
// Generate meta description.
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package run.halo.app.controller.content.model;
|
||||
|
||||
import static org.springframework.data.domain.Sort.Direction.DESC;
|
||||
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
|
@ -13,8 +15,6 @@ import run.halo.app.service.JournalService;
|
|||
import run.halo.app.service.OptionService;
|
||||
import run.halo.app.service.ThemeService;
|
||||
|
||||
import static org.springframework.data.domain.Sort.Direction.DESC;
|
||||
|
||||
/**
|
||||
* @author ryanwang
|
||||
* @date 2020-02-11
|
||||
|
@ -29,8 +29,8 @@ public class JournalModel {
|
|||
private final ThemeService themeService;
|
||||
|
||||
public JournalModel(JournalService journalService,
|
||||
OptionService optionService,
|
||||
ThemeService themeService) {
|
||||
OptionService optionService,
|
||||
ThemeService themeService) {
|
||||
this.journalService = journalService;
|
||||
this.optionService = optionService;
|
||||
this.themeService = themeService;
|
||||
|
@ -38,9 +38,12 @@ public class JournalModel {
|
|||
|
||||
public String list(Integer page, Model model) {
|
||||
|
||||
int pageSize = optionService.getByPropertyOrDefault(SheetProperties.JOURNALS_PAGE_SIZE, Integer.class, Integer.parseInt(SheetProperties.JOURNALS_PAGE_SIZE.defaultValue()));
|
||||
int pageSize = optionService
|
||||
.getByPropertyOrDefault(SheetProperties.JOURNALS_PAGE_SIZE, Integer.class,
|
||||
Integer.parseInt(SheetProperties.JOURNALS_PAGE_SIZE.defaultValue()));
|
||||
|
||||
Pageable pageable = PageRequest.of(page >= 1 ? page - 1 : page, pageSize, Sort.by(DESC, "createTime"));
|
||||
Pageable pageable =
|
||||
PageRequest.of(page >= 1 ? page - 1 : page, pageSize, Sort.by(DESC, "createTime"));
|
||||
|
||||
Page<Journal> journals = journalService.pageBy(JournalType.PUBLIC, pageable);
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@ public class LinkModel {
|
|||
private final OptionService optionService;
|
||||
|
||||
public LinkModel(ThemeService themeService,
|
||||
OptionService optionService) {
|
||||
OptionService optionService) {
|
||||
this.themeService = themeService;
|
||||
this.optionService = optionService;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package run.halo.app.controller.content.model;
|
||||
|
||||
import static org.springframework.data.domain.Sort.Direction.DESC;
|
||||
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
|
@ -12,8 +14,6 @@ import run.halo.app.service.OptionService;
|
|||
import run.halo.app.service.PhotoService;
|
||||
import run.halo.app.service.ThemeService;
|
||||
|
||||
import static org.springframework.data.domain.Sort.Direction.DESC;
|
||||
|
||||
/**
|
||||
* @author ryanwang
|
||||
* @date 2020-02-11
|
||||
|
@ -28,8 +28,8 @@ public class PhotoModel {
|
|||
private final OptionService optionService;
|
||||
|
||||
public PhotoModel(PhotoService photoService,
|
||||
ThemeService themeService,
|
||||
OptionService optionService) {
|
||||
ThemeService themeService,
|
||||
OptionService optionService) {
|
||||
this.photoService = photoService;
|
||||
this.themeService = themeService;
|
||||
this.optionService = optionService;
|
||||
|
@ -38,10 +38,11 @@ public class PhotoModel {
|
|||
public String list(Integer page, Model model) {
|
||||
|
||||
int pageSize = optionService.getByPropertyOrDefault(SheetProperties.PHOTOS_PAGE_SIZE,
|
||||
Integer.class,
|
||||
Integer.parseInt(SheetProperties.PHOTOS_PAGE_SIZE.defaultValue()));
|
||||
Integer.class,
|
||||
Integer.parseInt(SheetProperties.PHOTOS_PAGE_SIZE.defaultValue()));
|
||||
|
||||
Pageable pageable = PageRequest.of(page >= 1 ? page - 1 : page, pageSize, Sort.by(DESC, "createTime"));
|
||||
Pageable pageable =
|
||||
PageRequest.of(page >= 1 ? page - 1 : page, pageSize, Sort.by(DESC, "createTime"));
|
||||
|
||||
Page<PhotoDTO> photos = photoService.pageBy(pageable);
|
||||
|
||||
|
|
|
@ -1,5 +1,10 @@
|
|||
package run.halo.app.controller.content.model;
|
||||
|
||||
import static run.halo.app.model.support.HaloConst.POST_PASSWORD_TEMPLATE;
|
||||
import static run.halo.app.model.support.HaloConst.SUFFIX_FTL;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
|
@ -15,15 +20,18 @@ import run.halo.app.model.entity.PostMeta;
|
|||
import run.halo.app.model.entity.Tag;
|
||||
import run.halo.app.model.enums.PostEditorType;
|
||||
import run.halo.app.model.enums.PostStatus;
|
||||
import run.halo.app.model.support.HaloConst;
|
||||
import run.halo.app.model.vo.ArchiveYearVO;
|
||||
import run.halo.app.model.vo.PostListVO;
|
||||
import run.halo.app.service.*;
|
||||
import run.halo.app.service.CategoryService;
|
||||
import run.halo.app.service.OptionService;
|
||||
import run.halo.app.service.PostCategoryService;
|
||||
import run.halo.app.service.PostMetaService;
|
||||
import run.halo.app.service.PostService;
|
||||
import run.halo.app.service.PostTagService;
|
||||
import run.halo.app.service.TagService;
|
||||
import run.halo.app.service.ThemeService;
|
||||
import run.halo.app.utils.MarkdownUtils;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Post Model
|
||||
*
|
||||
|
@ -52,14 +60,14 @@ public class PostModel {
|
|||
private final AbstractStringCacheStore cacheStore;
|
||||
|
||||
public PostModel(PostService postService,
|
||||
ThemeService themeService,
|
||||
PostCategoryService postCategoryService,
|
||||
CategoryService categoryService,
|
||||
PostMetaService postMetaService,
|
||||
PostTagService postTagService,
|
||||
TagService tagService,
|
||||
OptionService optionService,
|
||||
AbstractStringCacheStore cacheStore) {
|
||||
ThemeService themeService,
|
||||
PostCategoryService postCategoryService,
|
||||
CategoryService categoryService,
|
||||
PostMetaService postMetaService,
|
||||
PostTagService postTagService,
|
||||
TagService tagService,
|
||||
OptionService optionService,
|
||||
AbstractStringCacheStore cacheStore) {
|
||||
this.postService = postService;
|
||||
this.themeService = themeService;
|
||||
this.postCategoryService = postCategoryService;
|
||||
|
@ -75,17 +83,18 @@ public class PostModel {
|
|||
|
||||
if (post.getStatus().equals(PostStatus.INTIMATE) && StringUtils.isEmpty(token)) {
|
||||
model.addAttribute("slug", post.getSlug());
|
||||
if (themeService.templateExists(HaloConst.POST_PASSWORD_TEMPLATE + HaloConst.SUFFIX_FTL)) {
|
||||
return themeService.render(HaloConst.POST_PASSWORD_TEMPLATE);
|
||||
if (themeService.templateExists(POST_PASSWORD_TEMPLATE + SUFFIX_FTL)) {
|
||||
return themeService.render(POST_PASSWORD_TEMPLATE);
|
||||
}
|
||||
return "common/template/" + HaloConst.POST_PASSWORD_TEMPLATE;
|
||||
return "common/template/" + POST_PASSWORD_TEMPLATE;
|
||||
}
|
||||
|
||||
if (StringUtils.isEmpty(token)) {
|
||||
post = postService.getBy(PostStatus.PUBLISHED, post.getSlug());
|
||||
} else {
|
||||
// verify token
|
||||
String cachedToken = cacheStore.getAny(token, String.class).orElseThrow(() -> new ForbiddenException("您没有该文章的访问权限"));
|
||||
String cachedToken = cacheStore.getAny(token, String.class)
|
||||
.orElseThrow(() -> new ForbiddenException("您没有该文章的访问权限"));
|
||||
if (!cachedToken.equals(token)) {
|
||||
throw new ForbiddenException("您没有该文章的访问权限");
|
||||
}
|
||||
|
@ -98,8 +107,10 @@ public class PostModel {
|
|||
|
||||
postService.publishVisitEvent(post.getId());
|
||||
|
||||
postService.getPrevPost(post).ifPresent(prevPost -> model.addAttribute("prevPost", postService.convertToDetailVo(prevPost)));
|
||||
postService.getNextPost(post).ifPresent(nextPost -> model.addAttribute("nextPost", postService.convertToDetailVo(nextPost)));
|
||||
postService.getPrevPost(post).ifPresent(
|
||||
prevPost -> model.addAttribute("prevPost", postService.convertToDetailVo(prevPost)));
|
||||
postService.getNextPost(post).ifPresent(
|
||||
nextPost -> model.addAttribute("nextPost", postService.convertToDetailVo(nextPost)));
|
||||
|
||||
List<Category> categories = postCategoryService.listCategoriesBy(post.getId());
|
||||
List<Tag> tags = postTagService.listTagsBy(post.getId());
|
||||
|
@ -109,14 +120,16 @@ public class PostModel {
|
|||
if (StringUtils.isNotEmpty(post.getMetaKeywords())) {
|
||||
model.addAttribute("meta_keywords", post.getMetaKeywords());
|
||||
} else {
|
||||
model.addAttribute("meta_keywords", tags.stream().map(Tag::getName).collect(Collectors.joining(",")));
|
||||
model.addAttribute("meta_keywords",
|
||||
tags.stream().map(Tag::getName).collect(Collectors.joining(",")));
|
||||
}
|
||||
|
||||
// Generate meta description.
|
||||
if (StringUtils.isNotEmpty(post.getMetaDescription())) {
|
||||
model.addAttribute("meta_description", post.getMetaDescription());
|
||||
} else {
|
||||
model.addAttribute("meta_description", postService.generateDescription(post.getFormatContent()));
|
||||
model.addAttribute("meta_description",
|
||||
postService.generateDescription(post.getFormatContent()));
|
||||
}
|
||||
|
||||
model.addAttribute("is_post", true);
|
||||
|
@ -126,7 +139,7 @@ public class PostModel {
|
|||
model.addAttribute("metas", postMetaService.convertToMap(metas));
|
||||
|
||||
if (themeService.templateExists(
|
||||
ThemeService.CUSTOM_POST_PREFIX + post.getTemplate() + HaloConst.SUFFIX_FTL)) {
|
||||
ThemeService.CUSTOM_POST_PREFIX + post.getTemplate() + SUFFIX_FTL)) {
|
||||
return themeService.render(ThemeService.CUSTOM_POST_PREFIX + post.getTemplate());
|
||||
}
|
||||
|
||||
|
@ -136,7 +149,7 @@ public class PostModel {
|
|||
public String list(Integer page, Model model) {
|
||||
int pageSize = optionService.getPostPageSize();
|
||||
Pageable pageable = PageRequest
|
||||
.of(page >= 1 ? page - 1 : page, pageSize, postService.getPostDefaultSort());
|
||||
.of(page >= 1 ? page - 1 : page, pageSize, postService.getPostDefaultSort());
|
||||
|
||||
Page<Post> postPage = postService.pageBy(PostStatus.PUBLISHED, pageable);
|
||||
Page<PostListVO> posts = postService.convertToListVo(postPage);
|
||||
|
@ -151,7 +164,7 @@ public class PostModel {
|
|||
public String archives(Integer page, Model model) {
|
||||
int pageSize = optionService.getArchivesPageSize();
|
||||
Pageable pageable = PageRequest
|
||||
.of(page >= 1 ? page - 1 : page, pageSize, Sort.by(Sort.Direction.DESC, "createTime"));
|
||||
.of(page >= 1 ? page - 1 : page, pageSize, Sort.by(Sort.Direction.DESC, "createTime"));
|
||||
|
||||
Page<Post> postPage = postService.pageBy(PostStatus.PUBLISHED, pageable);
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package run.halo.app.controller.content.model;
|
||||
|
||||
import java.util.List;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.ui.Model;
|
||||
|
@ -17,8 +18,6 @@ import run.halo.app.service.SheetService;
|
|||
import run.halo.app.service.ThemeService;
|
||||
import run.halo.app.utils.MarkdownUtils;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Sheet model.
|
||||
*
|
||||
|
@ -39,10 +38,10 @@ public class SheetModel {
|
|||
private final OptionService optionService;
|
||||
|
||||
public SheetModel(SheetService sheetService,
|
||||
SheetMetaService sheetMetaService,
|
||||
AbstractStringCacheStore cacheStore,
|
||||
ThemeService themeService,
|
||||
OptionService optionService) {
|
||||
SheetMetaService sheetMetaService,
|
||||
AbstractStringCacheStore cacheStore,
|
||||
ThemeService themeService,
|
||||
OptionService optionService) {
|
||||
this.sheetService = sheetService;
|
||||
this.sheetMetaService = sheetMetaService;
|
||||
this.cacheStore = cacheStore;
|
||||
|
@ -64,7 +63,8 @@ public class SheetModel {
|
|||
sheet = sheetService.getBy(PostStatus.PUBLISHED, sheet.getSlug());
|
||||
} else {
|
||||
// verify token
|
||||
String cachedToken = cacheStore.getAny(token, String.class).orElseThrow(() -> new ForbiddenException("您没有该页面的访问权限"));
|
||||
String cachedToken = cacheStore.getAny(token, String.class)
|
||||
.orElseThrow(() -> new ForbiddenException("您没有该页面的访问权限"));
|
||||
if (!cachedToken.equals(token)) {
|
||||
throw new ForbiddenException("您没有该页面的访问权限");
|
||||
}
|
||||
|
@ -93,7 +93,8 @@ public class SheetModel {
|
|||
if (StringUtils.isNotEmpty(sheet.getMetaDescription())) {
|
||||
model.addAttribute("meta_description", sheet.getMetaDescription());
|
||||
} else {
|
||||
model.addAttribute("meta_description", sheetService.generateDescription(sheet.getFormatContent()));
|
||||
model.addAttribute("meta_description",
|
||||
sheetService.generateDescription(sheet.getFormatContent()));
|
||||
}
|
||||
|
||||
// sheet and post all can use
|
||||
|
@ -102,7 +103,8 @@ public class SheetModel {
|
|||
model.addAttribute("is_sheet", true);
|
||||
model.addAttribute("metas", sheetMetaService.convertToMap(metas));
|
||||
|
||||
if (themeService.templateExists(ThemeService.CUSTOM_SHEET_PREFIX + sheet.getTemplate() + HaloConst.SUFFIX_FTL)) {
|
||||
if (themeService.templateExists(
|
||||
ThemeService.CUSTOM_SHEET_PREFIX + sheet.getTemplate() + HaloConst.SUFFIX_FTL)) {
|
||||
return themeService.render(ThemeService.CUSTOM_SHEET_PREFIX + sheet.getTemplate());
|
||||
}
|
||||
return themeService.render("sheet");
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package run.halo.app.controller.content.model;
|
||||
|
||||
import static org.springframework.data.domain.Sort.Direction.DESC;
|
||||
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
|
@ -11,9 +13,11 @@ import run.halo.app.model.entity.Post;
|
|||
import run.halo.app.model.entity.Tag;
|
||||
import run.halo.app.model.enums.PostStatus;
|
||||
import run.halo.app.model.vo.PostListVO;
|
||||
import run.halo.app.service.*;
|
||||
|
||||
import static org.springframework.data.domain.Sort.Direction.DESC;
|
||||
import run.halo.app.service.OptionService;
|
||||
import run.halo.app.service.PostService;
|
||||
import run.halo.app.service.PostTagService;
|
||||
import run.halo.app.service.TagService;
|
||||
import run.halo.app.service.ThemeService;
|
||||
|
||||
/**
|
||||
* Tag Model.
|
||||
|
@ -34,7 +38,8 @@ public class TagModel {
|
|||
|
||||
private final ThemeService themeService;
|
||||
|
||||
public TagModel(TagService tagService, PostService postService, PostTagService postTagService, OptionService optionService, ThemeService themeService) {
|
||||
public TagModel(TagService tagService, PostService postService, PostTagService postTagService,
|
||||
OptionService optionService, ThemeService themeService) {
|
||||
this.tagService = tagService;
|
||||
this.postService = postService;
|
||||
this.postTagService = postTagService;
|
||||
|
@ -54,8 +59,10 @@ public class TagModel {
|
|||
final Tag tag = tagService.getBySlugOfNonNull(slug);
|
||||
TagDTO tagDTO = tagService.convertTo(tag);
|
||||
|
||||
final Pageable pageable = PageRequest.of(page - 1, optionService.getArchivesPageSize(), Sort.by(DESC, "createTime"));
|
||||
Page<Post> postPage = postTagService.pagePostsBy(tag.getId(), PostStatus.PUBLISHED, pageable);
|
||||
final Pageable pageable = PageRequest
|
||||
.of(page - 1, optionService.getArchivesPageSize(), Sort.by(DESC, "createTime"));
|
||||
Page<Post> postPage =
|
||||
postTagService.pagePostsBy(tag.getId(), PostStatus.PUBLISHED, pageable);
|
||||
Page<PostListVO> posts = postService.convertToListVo(postPage);
|
||||
|
||||
model.addAttribute("is_tag", true);
|
||||
|
|
|
@ -1,5 +1,11 @@
|
|||
package run.halo.app.controller.core;
|
||||
|
||||
import static run.halo.app.model.support.HaloConst.DEFAULT_ERROR_PATH;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.boot.autoconfigure.web.ErrorProperties;
|
||||
import org.springframework.boot.autoconfigure.web.ServerProperties;
|
||||
|
@ -21,13 +27,6 @@ import run.halo.app.service.OptionService;
|
|||
import run.halo.app.service.ThemeService;
|
||||
import run.halo.app.utils.FilenameUtils;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
|
||||
import static run.halo.app.model.support.HaloConst.DEFAULT_ERROR_PATH;
|
||||
|
||||
/**
|
||||
* Error page Controller
|
||||
*
|
||||
|
@ -45,7 +44,8 @@ public class CommonController extends AbstractErrorController {
|
|||
|
||||
private static final String ERROR_TEMPLATE = "error.ftl";
|
||||
|
||||
private static final String COULD_NOT_RESOLVE_VIEW_WITH_NAME_PREFIX = "Could not resolve view with name '";
|
||||
private static final String COULD_NOT_RESOLVE_VIEW_WITH_NAME_PREFIX =
|
||||
"Could not resolve view with name '";
|
||||
|
||||
private final ThemeService themeService;
|
||||
|
||||
|
@ -54,9 +54,9 @@ public class CommonController extends AbstractErrorController {
|
|||
private final OptionService optionService;
|
||||
|
||||
public CommonController(ThemeService themeService,
|
||||
ErrorAttributes errorAttributes,
|
||||
ServerProperties serverProperties,
|
||||
OptionService optionService) {
|
||||
ErrorAttributes errorAttributes,
|
||||
ServerProperties serverProperties,
|
||||
OptionService optionService) {
|
||||
super(errorAttributes);
|
||||
this.themeService = themeService;
|
||||
this.errorProperties = serverProperties.getError();
|
||||
|
@ -70,12 +70,14 @@ public class CommonController extends AbstractErrorController {
|
|||
* @return String
|
||||
*/
|
||||
@GetMapping
|
||||
public String handleError(HttpServletRequest request, HttpServletResponse response, Model model) {
|
||||
public String handleError(HttpServletRequest request, HttpServletResponse response,
|
||||
Model model) {
|
||||
handleCustomException(request);
|
||||
|
||||
ErrorAttributeOptions options = getErrorAttributeOptions(request);
|
||||
|
||||
Map<String, Object> errorDetail = Collections.unmodifiableMap(getErrorAttributes(request, options));
|
||||
Map<String, Object> errorDetail =
|
||||
Collections.unmodifiableMap(getErrorAttributes(request, options));
|
||||
model.addAttribute("error", errorDetail);
|
||||
model.addAttribute("meta_keywords", optionService.getSeoKeywords());
|
||||
model.addAttribute("meta_description", optionService.getSeoDescription());
|
||||
|
@ -138,9 +140,9 @@ public class CommonController extends AbstractErrorController {
|
|||
|
||||
StringBuilder path = new StringBuilder();
|
||||
path.append("themes/")
|
||||
.append(themeService.getActivatedTheme().getFolderName())
|
||||
.append('/')
|
||||
.append(FilenameUtils.getBasename(template));
|
||||
.append(themeService.getActivatedTheme().getFolderName())
|
||||
.append('/')
|
||||
.append(FilenameUtils.getBasename(template));
|
||||
|
||||
return path.toString();
|
||||
}
|
||||
|
@ -168,11 +170,13 @@ public class CommonController extends AbstractErrorController {
|
|||
log.error("Caused by", rootCause);
|
||||
}
|
||||
AbstractHaloException haloException = (AbstractHaloException) rootCause;
|
||||
request.setAttribute("javax.servlet.error.status_code", haloException.getStatus().value());
|
||||
request.setAttribute("javax.servlet.error.status_code",
|
||||
haloException.getStatus().value());
|
||||
request.setAttribute("javax.servlet.error.exception", rootCause);
|
||||
request.setAttribute("javax.servlet.error.message", haloException.getMessage());
|
||||
}
|
||||
} else if (StringUtils.startsWithIgnoreCase(throwable.getMessage(), COULD_NOT_RESOLVE_VIEW_WITH_NAME_PREFIX)) {
|
||||
} else if (StringUtils.startsWithIgnoreCase(throwable.getMessage(),
|
||||
COULD_NOT_RESOLVE_VIEW_WITH_NAME_PREFIX)) {
|
||||
log.debug("Captured an exception", throwable);
|
||||
request.setAttribute("javax.servlet.error.status_code", HttpStatus.NOT_FOUND.value());
|
||||
|
||||
|
@ -221,7 +225,8 @@ public class CommonController extends AbstractErrorController {
|
|||
if (include == ErrorProperties.IncludeStacktrace.ALWAYS) {
|
||||
return ErrorAttributeOptions.of(ErrorAttributeOptions.Include.STACK_TRACE);
|
||||
}
|
||||
if (include == ErrorProperties.IncludeStacktrace.ON_TRACE_PARAM && getTraceParameter(request)) {
|
||||
if (include == ErrorProperties.IncludeStacktrace.ON_TRACE_PARAM
|
||||
&& getTraceParameter(request)) {
|
||||
return ErrorAttributeOptions.of(ErrorAttributeOptions.Include.STACK_TRACE);
|
||||
}
|
||||
return ErrorAttributeOptions.defaults();
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package run.halo.app.core;
|
||||
|
||||
import org.springframework.lang.NonNull;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
|
@ -9,6 +9,7 @@ import org.springframework.http.converter.json.AbstractJackson2HttpMessageConver
|
|||
import org.springframework.http.converter.json.MappingJacksonValue;
|
||||
import org.springframework.http.server.ServerHttpRequest;
|
||||
import org.springframework.http.server.ServerHttpResponse;
|
||||
import org.springframework.lang.NonNull;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.web.bind.annotation.ControllerAdvice;
|
||||
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;
|
||||
|
@ -23,18 +24,19 @@ import run.halo.app.model.support.BaseResponse;
|
|||
public class CommonResultControllerAdvice implements ResponseBodyAdvice<Object> {
|
||||
|
||||
@Override
|
||||
public boolean supports(@NonNull MethodParameter returnType, @NonNull Class<? extends HttpMessageConverter<?>> converterType) {
|
||||
public boolean supports(MethodParameter returnType,
|
||||
@NotNull Class<? extends HttpMessageConverter<?>> converterType) {
|
||||
return AbstractJackson2HttpMessageConverter.class.isAssignableFrom(converterType);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NonNull
|
||||
public final Object beforeBodyWrite(@Nullable Object body,
|
||||
@NonNull MethodParameter returnType,
|
||||
@NonNull MediaType contentType,
|
||||
@NonNull Class<? extends HttpMessageConverter<?>> converterType,
|
||||
@NonNull ServerHttpRequest request,
|
||||
@NonNull ServerHttpResponse response) {
|
||||
@NotNull MethodParameter returnType,
|
||||
@NotNull MediaType contentType,
|
||||
@NotNull Class<? extends HttpMessageConverter<?>> converterType,
|
||||
@NotNull ServerHttpRequest request,
|
||||
@NotNull ServerHttpResponse response) {
|
||||
MappingJacksonValue container = getOrCreateContainer(body);
|
||||
// The contain body will never be null
|
||||
beforeBodyWriteInternal(container, contentType, returnType, request, response);
|
||||
|
@ -46,14 +48,15 @@ public class CommonResultControllerAdvice implements ResponseBodyAdvice<Object>
|
|||
* additional serialization instructions) or simply cast it if already wrapped.
|
||||
*/
|
||||
private MappingJacksonValue getOrCreateContainer(Object body) {
|
||||
return body instanceof MappingJacksonValue ? (MappingJacksonValue) body : new MappingJacksonValue(body);
|
||||
return body instanceof MappingJacksonValue ? (MappingJacksonValue) body :
|
||||
new MappingJacksonValue(body);
|
||||
}
|
||||
|
||||
private void beforeBodyWriteInternal(MappingJacksonValue bodyContainer,
|
||||
MediaType contentType,
|
||||
MethodParameter returnType,
|
||||
ServerHttpRequest request,
|
||||
ServerHttpResponse response) {
|
||||
MediaType contentType,
|
||||
MethodParameter returnType,
|
||||
ServerHttpRequest request,
|
||||
ServerHttpResponse response) {
|
||||
// Get return body
|
||||
Object returnBody = bodyContainer.getValue();
|
||||
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package run.halo.app.core;
|
||||
|
||||
import java.util.Map;
|
||||
import javax.validation.ConstraintViolationException;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.dao.DataIntegrityViolationException;
|
||||
import org.springframework.http.HttpStatus;
|
||||
|
@ -20,21 +22,20 @@ import run.halo.app.model.support.BaseResponse;
|
|||
import run.halo.app.utils.ExceptionUtils;
|
||||
import run.halo.app.utils.ValidationUtils;
|
||||
|
||||
import javax.validation.ConstraintViolationException;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Exception handler of controller.
|
||||
*
|
||||
* @author johnniang
|
||||
*/
|
||||
@RestControllerAdvice(value = {"run.halo.app.controller.admin.api", "run.halo.app.controller.content.api"})
|
||||
@RestControllerAdvice(value = {"run.halo.app.controller.admin.api",
|
||||
"run.halo.app.controller.content.api"})
|
||||
@Slf4j
|
||||
public class ControllerExceptionHandler {
|
||||
|
||||
@ExceptionHandler(DataIntegrityViolationException.class)
|
||||
@ResponseStatus(HttpStatus.BAD_REQUEST)
|
||||
public BaseResponse<?> handleDataIntegrityViolationException(DataIntegrityViolationException e) {
|
||||
public BaseResponse<?> handleDataIntegrityViolationException(
|
||||
DataIntegrityViolationException e) {
|
||||
BaseResponse<?> baseResponse = handleBaseException(e);
|
||||
if (e.getCause() instanceof org.hibernate.exception.ConstraintViolationException) {
|
||||
baseResponse = handleBaseException(e.getCause());
|
||||
|
@ -45,9 +46,11 @@ public class ControllerExceptionHandler {
|
|||
|
||||
@ExceptionHandler(MissingServletRequestParameterException.class)
|
||||
@ResponseStatus(HttpStatus.BAD_REQUEST)
|
||||
public BaseResponse<?> handleMissingServletRequestParameterException(MissingServletRequestParameterException e) {
|
||||
public BaseResponse<?> handleMissingServletRequestParameterException(
|
||||
MissingServletRequestParameterException e) {
|
||||
BaseResponse<?> baseResponse = handleBaseException(e);
|
||||
baseResponse.setMessage(String.format("请求字段缺失, 类型为 %s,名称为 %s", e.getParameterType(), e.getParameterName()));
|
||||
baseResponse.setMessage(
|
||||
String.format("请求字段缺失, 类型为 %s,名称为 %s", e.getParameterType(), e.getParameterName()));
|
||||
return baseResponse;
|
||||
}
|
||||
|
||||
|
@ -63,18 +66,21 @@ public class ControllerExceptionHandler {
|
|||
|
||||
@ExceptionHandler(MethodArgumentNotValidException.class)
|
||||
@ResponseStatus(HttpStatus.BAD_REQUEST)
|
||||
public BaseResponse<?> handleMethodArgumentNotValidException(MethodArgumentNotValidException e) {
|
||||
public BaseResponse<?> handleMethodArgumentNotValidException(
|
||||
MethodArgumentNotValidException e) {
|
||||
BaseResponse<Map<String, String>> baseResponse = handleBaseException(e);
|
||||
baseResponse.setStatus(HttpStatus.BAD_REQUEST.value());
|
||||
baseResponse.setMessage("字段验证错误,请完善后重试!");
|
||||
Map<String, String> errMap = ValidationUtils.mapWithFieldError(e.getBindingResult().getFieldErrors());
|
||||
Map<String, String> errMap =
|
||||
ValidationUtils.mapWithFieldError(e.getBindingResult().getFieldErrors());
|
||||
baseResponse.setData(errMap);
|
||||
return baseResponse;
|
||||
}
|
||||
|
||||
@ExceptionHandler(HttpRequestMethodNotSupportedException.class)
|
||||
@ResponseStatus(HttpStatus.BAD_REQUEST)
|
||||
public BaseResponse<?> handleHttpRequestMethodNotSupportedException(HttpRequestMethodNotSupportedException e) {
|
||||
public BaseResponse<?> handleHttpRequestMethodNotSupportedException(
|
||||
HttpRequestMethodNotSupportedException e) {
|
||||
BaseResponse<?> baseResponse = handleBaseException(e);
|
||||
baseResponse.setStatus(HttpStatus.BAD_REQUEST.value());
|
||||
return baseResponse;
|
||||
|
@ -82,7 +88,8 @@ public class ControllerExceptionHandler {
|
|||
|
||||
@ExceptionHandler(HttpMediaTypeNotAcceptableException.class)
|
||||
@ResponseStatus(HttpStatus.NOT_ACCEPTABLE)
|
||||
public BaseResponse<?> handleHttpMediaTypeNotAcceptableException(HttpMediaTypeNotAcceptableException e) {
|
||||
public BaseResponse<?> handleHttpMediaTypeNotAcceptableException(
|
||||
HttpMediaTypeNotAcceptableException e) {
|
||||
BaseResponse<?> baseResponse = handleBaseException(e);
|
||||
baseResponse.setStatus(HttpStatus.NOT_ACCEPTABLE.value());
|
||||
return baseResponse;
|
||||
|
@ -90,7 +97,8 @@ public class ControllerExceptionHandler {
|
|||
|
||||
@ExceptionHandler(HttpMessageNotReadableException.class)
|
||||
@ResponseStatus(HttpStatus.BAD_REQUEST)
|
||||
public BaseResponse<?> handleHttpMessageNotReadableException(HttpMessageNotReadableException e) {
|
||||
public BaseResponse<?> handleHttpMessageNotReadableException(
|
||||
HttpMessageNotReadableException e) {
|
||||
BaseResponse<?> baseResponse = handleBaseException(e);
|
||||
baseResponse.setStatus(HttpStatus.BAD_REQUEST.value());
|
||||
baseResponse.setMessage("缺失请求主体");
|
||||
|
|
|
@ -2,6 +2,10 @@ package run.halo.app.core;
|
|||
|
||||
import cn.hutool.extra.servlet.ServletUtil;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Objects;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.aspectj.lang.ProceedingJoinPoint;
|
||||
import org.aspectj.lang.annotation.Around;
|
||||
|
@ -19,11 +23,6 @@ import org.springframework.web.context.request.ServletRequestAttributes;
|
|||
import org.springframework.web.multipart.MultipartFile;
|
||||
import run.halo.app.utils.JsonUtils;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* @author johnniang
|
||||
*/
|
||||
|
@ -50,7 +49,8 @@ public class ControllerLogAop {
|
|||
Object[] args = joinPoint.getArgs();
|
||||
|
||||
// Get request attribute
|
||||
ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
|
||||
ServletRequestAttributes requestAttributes =
|
||||
(ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
|
||||
HttpServletRequest request = Objects.requireNonNull(requestAttributes).getRequest();
|
||||
|
||||
final StopWatch watch = new StopWatch(request.getRequestURI());
|
||||
|
@ -72,12 +72,13 @@ public class ControllerLogAop {
|
|||
return returnObj;
|
||||
}
|
||||
|
||||
private void printRequestLog(HttpServletRequest request, String clazzName, String methodName, Object[] args) throws JsonProcessingException {
|
||||
private void printRequestLog(HttpServletRequest request, String clazzName, String methodName,
|
||||
Object[] args) throws JsonProcessingException {
|
||||
log.debug("Request URL: [{}], URI: [{}], Request Method: [{}], IP: [{}]",
|
||||
request.getRequestURL(),
|
||||
request.getRequestURI(),
|
||||
request.getMethod(),
|
||||
ServletUtil.getClientIP(request));
|
||||
request.getRequestURL(),
|
||||
request.getRequestURI(),
|
||||
request.getMethod(),
|
||||
ServletUtil.getClientIP(request));
|
||||
|
||||
if (args == null || !log.isDebugEnabled()) {
|
||||
return;
|
||||
|
@ -85,11 +86,11 @@ public class ControllerLogAop {
|
|||
|
||||
boolean shouldNotLog = false;
|
||||
for (Object arg : args) {
|
||||
if (arg == null ||
|
||||
arg instanceof HttpServletRequest ||
|
||||
arg instanceof HttpServletResponse ||
|
||||
arg instanceof MultipartFile ||
|
||||
arg.getClass().isAssignableFrom(MultipartFile[].class)) {
|
||||
if (arg == null
|
||||
|| arg instanceof HttpServletRequest
|
||||
|| arg instanceof HttpServletResponse
|
||||
|| arg instanceof MultipartFile
|
||||
|| arg.getClass().isAssignableFrom(MultipartFile[].class)) {
|
||||
shouldNotLog = true;
|
||||
break;
|
||||
}
|
||||
|
@ -101,8 +102,9 @@ public class ControllerLogAop {
|
|||
}
|
||||
}
|
||||
|
||||
private void printResponseLog(HttpServletRequest request, String className, String methodName, Object returnObj)
|
||||
throws JsonProcessingException {
|
||||
private void printResponseLog(HttpServletRequest request, String className, String methodName,
|
||||
Object returnObj)
|
||||
throws JsonProcessingException {
|
||||
if (log.isDebugEnabled()) {
|
||||
String returnData = "";
|
||||
if (returnObj != null) {
|
||||
|
|
|
@ -3,11 +3,10 @@ package run.halo.app.core;
|
|||
import com.fasterxml.jackson.core.JsonGenerator;
|
||||
import com.fasterxml.jackson.databind.JsonSerializer;
|
||||
import com.fasterxml.jackson.databind.SerializerProvider;
|
||||
import java.io.IOException;
|
||||
import org.springframework.data.domain.Page;
|
||||
import run.halo.app.model.support.CommentPage;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Custom serializer for Page object.
|
||||
*
|
||||
|
@ -17,7 +16,8 @@ import java.io.IOException;
|
|||
public class PageJacksonSerializer extends JsonSerializer<Page> {
|
||||
|
||||
@Override
|
||||
public void serialize(Page page, JsonGenerator generator, SerializerProvider serializers) throws IOException {
|
||||
public void serialize(Page page, JsonGenerator generator, SerializerProvider serializers)
|
||||
throws IOException {
|
||||
generator.writeStartObject();
|
||||
|
||||
generator.writeObjectField("content", page.getContent());
|
||||
|
|
|
@ -5,9 +5,8 @@ import freemarker.template.Configuration;
|
|||
import freemarker.template.SimpleNumber;
|
||||
import freemarker.template.TemplateMethodModelEx;
|
||||
import freemarker.template.TemplateModelException;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.List;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* Freemarker template random method.
|
||||
|
|
|
@ -1,7 +1,17 @@
|
|||
package run.halo.app.core.freemarker.tag;
|
||||
|
||||
import static org.springframework.data.domain.Sort.Direction.DESC;
|
||||
|
||||
import freemarker.core.Environment;
|
||||
import freemarker.template.*;
|
||||
import freemarker.template.Configuration;
|
||||
import freemarker.template.DefaultObjectWrapperBuilder;
|
||||
import freemarker.template.TemplateDirectiveBody;
|
||||
import freemarker.template.TemplateDirectiveModel;
|
||||
import freemarker.template.TemplateException;
|
||||
import freemarker.template.TemplateModel;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.stereotype.Component;
|
||||
import run.halo.app.model.entity.Category;
|
||||
|
@ -9,12 +19,6 @@ import run.halo.app.model.support.HaloConst;
|
|||
import run.halo.app.service.CategoryService;
|
||||
import run.halo.app.service.PostCategoryService;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.springframework.data.domain.Sort.Direction.DESC;
|
||||
|
||||
/**
|
||||
* Freemarker custom tag of category.
|
||||
*
|
||||
|
@ -29,30 +33,35 @@ public class CategoryTagDirective implements TemplateDirectiveModel {
|
|||
private final PostCategoryService postCategoryService;
|
||||
|
||||
public CategoryTagDirective(Configuration configuration,
|
||||
CategoryService categoryService,
|
||||
PostCategoryService postCategoryService) {
|
||||
CategoryService categoryService,
|
||||
PostCategoryService postCategoryService) {
|
||||
this.categoryService = categoryService;
|
||||
this.postCategoryService = postCategoryService;
|
||||
configuration.setSharedVariable("categoryTag", this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Environment env, Map params, TemplateModel[] loopVars, TemplateDirectiveBody body) throws TemplateException, IOException {
|
||||
final DefaultObjectWrapperBuilder builder = new DefaultObjectWrapperBuilder(Configuration.VERSION_2_3_25);
|
||||
public void execute(Environment env, Map params, TemplateModel[] loopVars,
|
||||
TemplateDirectiveBody body) throws TemplateException, IOException {
|
||||
final DefaultObjectWrapperBuilder builder =
|
||||
new DefaultObjectWrapperBuilder(Configuration.VERSION_2_3_25);
|
||||
|
||||
if (params.containsKey(HaloConst.METHOD_KEY)) {
|
||||
String method = params.get(HaloConst.METHOD_KEY).toString();
|
||||
switch (method) {
|
||||
case "list":
|
||||
env.setVariable("categories", builder.build().wrap(postCategoryService.listCategoryWithPostCountDto(Sort.by(DESC, "createTime"))));
|
||||
env.setVariable("categories", builder.build().wrap(postCategoryService
|
||||
.listCategoryWithPostCountDto(Sort.by(DESC, "createTime"))));
|
||||
break;
|
||||
case "tree":
|
||||
env.setVariable("categories", builder.build().wrap(categoryService.listAsTree(Sort.by(DESC, "createTime"))));
|
||||
env.setVariable("categories", builder.build()
|
||||
.wrap(categoryService.listAsTree(Sort.by(DESC, "createTime"))));
|
||||
break;
|
||||
case "listByPostId":
|
||||
Integer postId = Integer.parseInt(params.get("postId").toString());
|
||||
List<Category> categories = postCategoryService.listCategoriesBy(postId);
|
||||
env.setVariable("categories", builder.build().wrap(categoryService.convertTo(categories)));
|
||||
env.setVariable("categories",
|
||||
builder.build().wrap(categoryService.convertTo(categories)));
|
||||
break;
|
||||
case "count":
|
||||
env.setVariable("count", builder.build().wrap(categoryService.count()));
|
||||
|
|
|
@ -1,7 +1,14 @@
|
|||
package run.halo.app.core.freemarker.tag;
|
||||
|
||||
import freemarker.core.Environment;
|
||||
import freemarker.template.*;
|
||||
import freemarker.template.Configuration;
|
||||
import freemarker.template.DefaultObjectWrapperBuilder;
|
||||
import freemarker.template.TemplateDirectiveBody;
|
||||
import freemarker.template.TemplateDirectiveModel;
|
||||
import freemarker.template.TemplateException;
|
||||
import freemarker.template.TemplateModel;
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.stereotype.Component;
|
||||
import run.halo.app.model.entity.PostComment;
|
||||
|
@ -9,9 +16,6 @@ import run.halo.app.model.enums.CommentStatus;
|
|||
import run.halo.app.model.support.HaloConst;
|
||||
import run.halo.app.service.PostCommentService;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Freemarker custom tag of comment.
|
||||
*
|
||||
|
@ -29,16 +33,20 @@ public class CommentTagDirective implements TemplateDirectiveModel {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void execute(Environment env, Map params, TemplateModel[] loopVars, TemplateDirectiveBody body) throws TemplateException, IOException {
|
||||
final DefaultObjectWrapperBuilder builder = new DefaultObjectWrapperBuilder(Configuration.VERSION_2_3_25);
|
||||
public void execute(Environment env, Map params, TemplateModel[] loopVars,
|
||||
TemplateDirectiveBody body) throws TemplateException, IOException {
|
||||
final DefaultObjectWrapperBuilder builder =
|
||||
new DefaultObjectWrapperBuilder(Configuration.VERSION_2_3_25);
|
||||
|
||||
if (params.containsKey(HaloConst.METHOD_KEY)) {
|
||||
String method = params.get(HaloConst.METHOD_KEY).toString();
|
||||
switch (method) {
|
||||
case "latest":
|
||||
int top = Integer.parseInt(params.get("top").toString());
|
||||
Page<PostComment> postComments = postCommentService.pageLatest(top, CommentStatus.PUBLISHED);
|
||||
env.setVariable("comments", builder.build().wrap(postCommentService.convertToWithPostVo(postComments)));
|
||||
Page<PostComment> postComments =
|
||||
postCommentService.pageLatest(top, CommentStatus.PUBLISHED);
|
||||
env.setVariable("comments",
|
||||
builder.build().wrap(postCommentService.convertToWithPostVo(postComments)));
|
||||
break;
|
||||
case "count":
|
||||
env.setVariable("count", builder.build().wrap(postCommentService.count()));
|
||||
|
|
|
@ -1,17 +1,21 @@
|
|||
package run.halo.app.core.freemarker.tag;
|
||||
|
||||
import static org.springframework.data.domain.Sort.Direction.DESC;
|
||||
|
||||
import freemarker.core.Environment;
|
||||
import freemarker.template.*;
|
||||
import freemarker.template.Configuration;
|
||||
import freemarker.template.DefaultObjectWrapperBuilder;
|
||||
import freemarker.template.TemplateDirectiveBody;
|
||||
import freemarker.template.TemplateDirectiveModel;
|
||||
import freemarker.template.TemplateException;
|
||||
import freemarker.template.TemplateModel;
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.stereotype.Component;
|
||||
import run.halo.app.model.support.HaloConst;
|
||||
import run.halo.app.service.LinkService;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.springframework.data.domain.Sort.Direction.DESC;
|
||||
|
||||
/**
|
||||
* Freemarker custom tag of link.
|
||||
*
|
||||
|
@ -29,8 +33,10 @@ public class LinkTagDirective implements TemplateDirectiveModel {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void execute(Environment env, Map params, TemplateModel[] loopVars, TemplateDirectiveBody body) throws TemplateException, IOException {
|
||||
final DefaultObjectWrapperBuilder builder = new DefaultObjectWrapperBuilder(Configuration.VERSION_2_3_25);
|
||||
public void execute(Environment env, Map params, TemplateModel[] loopVars,
|
||||
TemplateDirectiveBody body) throws TemplateException, IOException {
|
||||
final DefaultObjectWrapperBuilder builder =
|
||||
new DefaultObjectWrapperBuilder(Configuration.VERSION_2_3_25);
|
||||
|
||||
if (params.containsKey(HaloConst.METHOD_KEY)) {
|
||||
String method = params.get(HaloConst.METHOD_KEY).toString();
|
||||
|
@ -42,10 +48,12 @@ public class LinkTagDirective implements TemplateDirectiveModel {
|
|||
env.setVariable("links", builder.build().wrap(linkService.listAllByRandom()));
|
||||
break;
|
||||
case "listTeams":
|
||||
env.setVariable("teams", builder.build().wrap(linkService.listTeamVos(Sort.by(DESC, "createTime"))));
|
||||
env.setVariable("teams",
|
||||
builder.build().wrap(linkService.listTeamVos(Sort.by(DESC, "createTime"))));
|
||||
break;
|
||||
case "listTeamsByRandom":
|
||||
env.setVariable("teams", builder.build().wrap(linkService.listTeamVosByRandom(Sort.by(DESC, "createTime"))));
|
||||
env.setVariable("teams", builder.build()
|
||||
.wrap(linkService.listTeamVosByRandom(Sort.by(DESC, "createTime"))));
|
||||
break;
|
||||
case "count":
|
||||
env.setVariable("count", builder.build().wrap(linkService.count()));
|
||||
|
|
|
@ -1,7 +1,16 @@
|
|||
package run.halo.app.core.freemarker.tag;
|
||||
|
||||
import static org.springframework.data.domain.Sort.Direction.DESC;
|
||||
|
||||
import freemarker.core.Environment;
|
||||
import freemarker.template.*;
|
||||
import freemarker.template.Configuration;
|
||||
import freemarker.template.DefaultObjectWrapperBuilder;
|
||||
import freemarker.template.TemplateDirectiveBody;
|
||||
import freemarker.template.TemplateDirectiveModel;
|
||||
import freemarker.template.TemplateException;
|
||||
import freemarker.template.TemplateModel;
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.stereotype.Component;
|
||||
import run.halo.app.model.properties.PrimaryProperties;
|
||||
|
@ -9,11 +18,6 @@ import run.halo.app.model.support.HaloConst;
|
|||
import run.halo.app.service.MenuService;
|
||||
import run.halo.app.service.OptionService;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.springframework.data.domain.Sort.Direction.DESC;
|
||||
|
||||
/**
|
||||
* Freemarker custom tag of menu.
|
||||
*
|
||||
|
@ -29,37 +33,49 @@ public class MenuTagDirective implements TemplateDirectiveModel {
|
|||
|
||||
private final OptionService optionService;
|
||||
|
||||
public MenuTagDirective(Configuration configuration, MenuService menuService, OptionService optionService) {
|
||||
public MenuTagDirective(Configuration configuration, MenuService menuService,
|
||||
OptionService optionService) {
|
||||
this.menuService = menuService;
|
||||
this.optionService = optionService;
|
||||
configuration.setSharedVariable("menuTag", this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Environment env, Map params, TemplateModel[] loopVars, TemplateDirectiveBody body) throws TemplateException, IOException {
|
||||
final DefaultObjectWrapperBuilder builder = new DefaultObjectWrapperBuilder(Configuration.VERSION_2_3_25);
|
||||
public void execute(Environment env, Map params, TemplateModel[] loopVars,
|
||||
TemplateDirectiveBody body) throws TemplateException, IOException {
|
||||
final DefaultObjectWrapperBuilder builder =
|
||||
new DefaultObjectWrapperBuilder(Configuration.VERSION_2_3_25);
|
||||
|
||||
if (params.containsKey(HaloConst.METHOD_KEY)) {
|
||||
String method = params.get(HaloConst.METHOD_KEY).toString();
|
||||
switch (method) {
|
||||
case "list":
|
||||
String listTeam = optionService.getByPropertyOrDefault(PrimaryProperties.DEFAULT_MENU_TEAM, String.class, "");
|
||||
env.setVariable("menus", builder.build().wrap(menuService.listByTeam(listTeam, Sort.by(DESC, "priority"))));
|
||||
String listTeam = optionService
|
||||
.getByPropertyOrDefault(PrimaryProperties.DEFAULT_MENU_TEAM, String.class,
|
||||
"");
|
||||
env.setVariable("menus", builder.build()
|
||||
.wrap(menuService.listByTeam(listTeam, Sort.by(DESC, "priority"))));
|
||||
break;
|
||||
case "tree":
|
||||
String treeTeam = optionService.getByPropertyOrDefault(PrimaryProperties.DEFAULT_MENU_TEAM, String.class, "");
|
||||
env.setVariable("menus", builder.build().wrap(menuService.listByTeamAsTree(treeTeam, Sort.by(DESC, "priority"))));
|
||||
String treeTeam = optionService
|
||||
.getByPropertyOrDefault(PrimaryProperties.DEFAULT_MENU_TEAM, String.class,
|
||||
"");
|
||||
env.setVariable("menus", builder.build()
|
||||
.wrap(menuService.listByTeamAsTree(treeTeam, Sort.by(DESC, "priority"))));
|
||||
break;
|
||||
case "listTeams":
|
||||
env.setVariable("teams", builder.build().wrap(menuService.listTeamVos(Sort.by(DESC, "priority"))));
|
||||
env.setVariable("teams",
|
||||
builder.build().wrap(menuService.listTeamVos(Sort.by(DESC, "priority"))));
|
||||
break;
|
||||
case "listByTeam":
|
||||
String team = params.get("team").toString();
|
||||
env.setVariable("menus", builder.build().wrap(menuService.listByTeam(team, Sort.by(DESC, "priority"))));
|
||||
env.setVariable("menus", builder.build()
|
||||
.wrap(menuService.listByTeam(team, Sort.by(DESC, "priority"))));
|
||||
break;
|
||||
case "treeByTeam":
|
||||
String treeTeamParam = params.get("team").toString();
|
||||
env.setVariable("menus", builder.build().wrap(menuService.listByTeamAsTree(treeTeamParam, Sort.by(DESC, "priority"))));
|
||||
env.setVariable("menus", builder.build().wrap(
|
||||
menuService.listByTeamAsTree(treeTeamParam, Sort.by(DESC, "priority"))));
|
||||
break;
|
||||
case "count":
|
||||
env.setVariable("count", builder.build().wrap(menuService.count()));
|
||||
|
|
|
@ -1,21 +1,25 @@
|
|||
package run.halo.app.core.freemarker.tag;
|
||||
|
||||
import static run.halo.app.model.support.HaloConst.URL_SEPARATOR;
|
||||
|
||||
import cn.hutool.core.util.PageUtil;
|
||||
import freemarker.core.Environment;
|
||||
import freemarker.template.*;
|
||||
import freemarker.template.Configuration;
|
||||
import freemarker.template.DefaultObjectWrapperBuilder;
|
||||
import freemarker.template.TemplateDirectiveBody;
|
||||
import freemarker.template.TemplateDirectiveModel;
|
||||
import freemarker.template.TemplateException;
|
||||
import freemarker.template.TemplateModel;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import org.springframework.stereotype.Component;
|
||||
import run.halo.app.model.support.HaloConst;
|
||||
import run.halo.app.model.support.Pagination;
|
||||
import run.halo.app.model.support.RainbowPage;
|
||||
import run.halo.app.service.OptionService;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static run.halo.app.model.support.HaloConst.URL_SEPARATOR;
|
||||
|
||||
/**
|
||||
* @author ryanwang
|
||||
* @date 2020-03-07
|
||||
|
@ -26,14 +30,16 @@ public class PaginationTagDirective implements TemplateDirectiveModel {
|
|||
private final OptionService optionService;
|
||||
|
||||
public PaginationTagDirective(Configuration configuration,
|
||||
OptionService optionService) {
|
||||
OptionService optionService) {
|
||||
this.optionService = optionService;
|
||||
configuration.setSharedVariable("paginationTag", this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Environment env, Map params, TemplateModel[] loopVars, TemplateDirectiveBody body) throws TemplateException, IOException {
|
||||
final DefaultObjectWrapperBuilder builder = new DefaultObjectWrapperBuilder(Configuration.VERSION_2_3_25);
|
||||
public void execute(Environment env, Map params, TemplateModel[] loopVars,
|
||||
TemplateDirectiveBody body) throws TemplateException, IOException {
|
||||
final DefaultObjectWrapperBuilder builder =
|
||||
new DefaultObjectWrapperBuilder(Configuration.VERSION_2_3_25);
|
||||
if (params.containsKey(HaloConst.METHOD_KEY)) {
|
||||
|
||||
// Get params
|
||||
|
@ -69,15 +75,15 @@ public class PaginationTagDirective implements TemplateDirectiveModel {
|
|||
case "index":
|
||||
|
||||
nextPageFullPath.append("/page/")
|
||||
.append(page + 2)
|
||||
.append(pathSuffix);
|
||||
.append(page + 2)
|
||||
.append(pathSuffix);
|
||||
|
||||
if (page == 1) {
|
||||
prevPageFullPath.append(URL_SEPARATOR);
|
||||
} else {
|
||||
prevPageFullPath.append("/page/")
|
||||
.append(page)
|
||||
.append(pathSuffix);
|
||||
.append(page)
|
||||
.append(pathSuffix);
|
||||
}
|
||||
|
||||
fullPath.append("/page/");
|
||||
|
@ -93,25 +99,24 @@ public class PaginationTagDirective implements TemplateDirectiveModel {
|
|||
case "archives":
|
||||
|
||||
nextPageFullPath.append(URL_SEPARATOR)
|
||||
.append(optionService.getArchivesPrefix());
|
||||
.append(optionService.getArchivesPrefix());
|
||||
prevPageFullPath.append(URL_SEPARATOR)
|
||||
.append(optionService.getArchivesPrefix());
|
||||
.append(optionService.getArchivesPrefix());
|
||||
|
||||
nextPageFullPath.append("/page/")
|
||||
.append(page + 2)
|
||||
.append(pathSuffix);
|
||||
.append(page + 2)
|
||||
.append(pathSuffix);
|
||||
|
||||
if (page == 1) {
|
||||
prevPageFullPath.
|
||||
append(pathSuffix);
|
||||
prevPageFullPath.append(pathSuffix);
|
||||
} else {
|
||||
prevPageFullPath.append("/page/")
|
||||
.append(page)
|
||||
.append(pathSuffix);
|
||||
.append(page)
|
||||
.append(pathSuffix);
|
||||
}
|
||||
|
||||
fullPath.append(URL_SEPARATOR)
|
||||
.append(optionService.getArchivesPrefix());
|
||||
.append(optionService.getArchivesPrefix());
|
||||
|
||||
fullPath.append("/page/");
|
||||
|
||||
|
@ -127,37 +132,38 @@ public class PaginationTagDirective implements TemplateDirectiveModel {
|
|||
String keyword = params.get("keyword").toString();
|
||||
|
||||
nextPageFullPath.append(URL_SEPARATOR)
|
||||
.append("search");
|
||||
.append("search");
|
||||
prevPageFullPath.append(URL_SEPARATOR)
|
||||
.append("search");
|
||||
.append("search");
|
||||
|
||||
nextPageFullPath.append("/page/")
|
||||
.append(page + 2)
|
||||
.append(pathSuffix)
|
||||
.append("?keyword=")
|
||||
.append(keyword);
|
||||
.append(page + 2)
|
||||
.append(pathSuffix)
|
||||
.append("?keyword=")
|
||||
.append(keyword);
|
||||
|
||||
if (page == 1) {
|
||||
prevPageFullPath.append(pathSuffix)
|
||||
.append("?keyword=")
|
||||
.append(keyword);
|
||||
.append("?keyword=")
|
||||
.append(keyword);
|
||||
} else {
|
||||
prevPageFullPath.append("/page/")
|
||||
.append(page)
|
||||
.append(pathSuffix)
|
||||
.append("?keyword=")
|
||||
.append(keyword);
|
||||
.append(page)
|
||||
.append(pathSuffix)
|
||||
.append("?keyword=")
|
||||
.append(keyword);
|
||||
}
|
||||
|
||||
fullPath.append(URL_SEPARATOR)
|
||||
.append("search");
|
||||
.append("search");
|
||||
|
||||
fullPath.append("/page/");
|
||||
|
||||
for (int current : rainbow) {
|
||||
RainbowPage rainbowPage = new RainbowPage();
|
||||
rainbowPage.setPage(current);
|
||||
rainbowPage.setFullPath(fullPath.toString() + current + pathSuffix + "?keyword=" + keyword);
|
||||
rainbowPage.setFullPath(
|
||||
fullPath.toString() + current + pathSuffix + "?keyword=" + keyword);
|
||||
rainbowPage.setIsCurrent(page + 1 == current);
|
||||
rainbowPages.add(rainbowPage);
|
||||
}
|
||||
|
@ -166,30 +172,30 @@ public class PaginationTagDirective implements TemplateDirectiveModel {
|
|||
String tagSlug = params.get("slug").toString();
|
||||
|
||||
nextPageFullPath.append(URL_SEPARATOR)
|
||||
.append(optionService.getTagsPrefix())
|
||||
.append(URL_SEPARATOR)
|
||||
.append(tagSlug);
|
||||
.append(optionService.getTagsPrefix())
|
||||
.append(URL_SEPARATOR)
|
||||
.append(tagSlug);
|
||||
prevPageFullPath.append(URL_SEPARATOR)
|
||||
.append(optionService.getTagsPrefix())
|
||||
.append(URL_SEPARATOR)
|
||||
.append(tagSlug);
|
||||
.append(optionService.getTagsPrefix())
|
||||
.append(URL_SEPARATOR)
|
||||
.append(tagSlug);
|
||||
|
||||
nextPageFullPath.append("/page/")
|
||||
.append(page + 2)
|
||||
.append(pathSuffix);
|
||||
.append(page + 2)
|
||||
.append(pathSuffix);
|
||||
|
||||
if (page == 1) {
|
||||
prevPageFullPath.append(pathSuffix);
|
||||
} else {
|
||||
prevPageFullPath.append("/page/")
|
||||
.append(page)
|
||||
.append(pathSuffix);
|
||||
.append(page)
|
||||
.append(pathSuffix);
|
||||
}
|
||||
|
||||
fullPath.append(URL_SEPARATOR)
|
||||
.append(optionService.getTagsPrefix())
|
||||
.append(URL_SEPARATOR)
|
||||
.append(tagSlug);
|
||||
.append(optionService.getTagsPrefix())
|
||||
.append(URL_SEPARATOR)
|
||||
.append(tagSlug);
|
||||
|
||||
fullPath.append("/page/");
|
||||
|
||||
|
@ -205,30 +211,30 @@ public class PaginationTagDirective implements TemplateDirectiveModel {
|
|||
String categorySlug = params.get("slug").toString();
|
||||
|
||||
nextPageFullPath.append(URL_SEPARATOR)
|
||||
.append(optionService.getCategoriesPrefix())
|
||||
.append(URL_SEPARATOR)
|
||||
.append(categorySlug);
|
||||
.append(optionService.getCategoriesPrefix())
|
||||
.append(URL_SEPARATOR)
|
||||
.append(categorySlug);
|
||||
prevPageFullPath.append(URL_SEPARATOR)
|
||||
.append(optionService.getCategoriesPrefix())
|
||||
.append(URL_SEPARATOR)
|
||||
.append(categorySlug);
|
||||
.append(optionService.getCategoriesPrefix())
|
||||
.append(URL_SEPARATOR)
|
||||
.append(categorySlug);
|
||||
|
||||
nextPageFullPath.append("/page/")
|
||||
.append(page + 2)
|
||||
.append(pathSuffix);
|
||||
.append(page + 2)
|
||||
.append(pathSuffix);
|
||||
|
||||
if (page == 1) {
|
||||
prevPageFullPath.append(pathSuffix);
|
||||
} else {
|
||||
prevPageFullPath.append("/page/")
|
||||
.append(page)
|
||||
.append(pathSuffix);
|
||||
.append(page)
|
||||
.append(pathSuffix);
|
||||
}
|
||||
|
||||
fullPath.append(URL_SEPARATOR)
|
||||
.append(optionService.getCategoriesPrefix())
|
||||
.append(URL_SEPARATOR)
|
||||
.append(categorySlug);
|
||||
.append(optionService.getCategoriesPrefix())
|
||||
.append(URL_SEPARATOR)
|
||||
.append(categorySlug);
|
||||
|
||||
fullPath.append("/page/");
|
||||
|
||||
|
@ -243,24 +249,24 @@ public class PaginationTagDirective implements TemplateDirectiveModel {
|
|||
case "photos":
|
||||
|
||||
nextPageFullPath.append(URL_SEPARATOR)
|
||||
.append(optionService.getPhotosPrefix());
|
||||
.append(optionService.getPhotosPrefix());
|
||||
prevPageFullPath.append(URL_SEPARATOR)
|
||||
.append(optionService.getPhotosPrefix());
|
||||
.append(optionService.getPhotosPrefix());
|
||||
|
||||
nextPageFullPath.append("/page/")
|
||||
.append(page + 2)
|
||||
.append(pathSuffix);
|
||||
.append(page + 2)
|
||||
.append(pathSuffix);
|
||||
|
||||
if (page == 1) {
|
||||
prevPageFullPath.append(pathSuffix);
|
||||
} else {
|
||||
prevPageFullPath.append("/page/")
|
||||
.append(page)
|
||||
.append(pathSuffix);
|
||||
.append(page)
|
||||
.append(pathSuffix);
|
||||
}
|
||||
|
||||
fullPath.append(URL_SEPARATOR)
|
||||
.append(optionService.getPhotosPrefix());
|
||||
.append(optionService.getPhotosPrefix());
|
||||
|
||||
fullPath.append("/page/");
|
||||
|
||||
|
@ -275,24 +281,24 @@ public class PaginationTagDirective implements TemplateDirectiveModel {
|
|||
case "journals":
|
||||
|
||||
nextPageFullPath.append(URL_SEPARATOR)
|
||||
.append(optionService.getJournalsPrefix());
|
||||
.append(optionService.getJournalsPrefix());
|
||||
prevPageFullPath.append(URL_SEPARATOR)
|
||||
.append(optionService.getJournalsPrefix());
|
||||
.append(optionService.getJournalsPrefix());
|
||||
|
||||
nextPageFullPath.append("/page/")
|
||||
.append(page + 2)
|
||||
.append(pathSuffix);
|
||||
.append(page + 2)
|
||||
.append(pathSuffix);
|
||||
|
||||
if (page == 1) {
|
||||
prevPageFullPath.append(pathSuffix);
|
||||
} else {
|
||||
prevPageFullPath.append("/page/")
|
||||
.append(page)
|
||||
.append(pathSuffix);
|
||||
.append(page)
|
||||
.append(pathSuffix);
|
||||
}
|
||||
|
||||
fullPath.append(URL_SEPARATOR)
|
||||
.append(optionService.getJournalsPrefix());
|
||||
.append(optionService.getJournalsPrefix());
|
||||
|
||||
fullPath.append("/page/");
|
||||
|
||||
|
|
|
@ -1,17 +1,21 @@
|
|||
package run.halo.app.core.freemarker.tag;
|
||||
|
||||
import static org.springframework.data.domain.Sort.Direction.DESC;
|
||||
|
||||
import freemarker.core.Environment;
|
||||
import freemarker.template.*;
|
||||
import freemarker.template.Configuration;
|
||||
import freemarker.template.DefaultObjectWrapperBuilder;
|
||||
import freemarker.template.TemplateDirectiveBody;
|
||||
import freemarker.template.TemplateDirectiveModel;
|
||||
import freemarker.template.TemplateException;
|
||||
import freemarker.template.TemplateModel;
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.stereotype.Component;
|
||||
import run.halo.app.model.support.HaloConst;
|
||||
import run.halo.app.service.PhotoService;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.springframework.data.domain.Sort.Direction.DESC;
|
||||
|
||||
/**
|
||||
* Freemarker custom tag of photo.
|
||||
*
|
||||
|
@ -29,8 +33,10 @@ public class PhotoTagDirective implements TemplateDirectiveModel {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void execute(Environment env, Map params, TemplateModel[] loopVars, TemplateDirectiveBody body) throws TemplateException, IOException {
|
||||
final DefaultObjectWrapperBuilder builder = new DefaultObjectWrapperBuilder(Configuration.VERSION_2_3_25);
|
||||
public void execute(Environment env, Map params, TemplateModel[] loopVars,
|
||||
TemplateDirectiveBody body) throws TemplateException, IOException {
|
||||
final DefaultObjectWrapperBuilder builder =
|
||||
new DefaultObjectWrapperBuilder(Configuration.VERSION_2_3_25);
|
||||
|
||||
if (params.containsKey(HaloConst.METHOD_KEY)) {
|
||||
String method = params.get(HaloConst.METHOD_KEY).toString();
|
||||
|
@ -39,11 +45,13 @@ public class PhotoTagDirective implements TemplateDirectiveModel {
|
|||
env.setVariable("photos", builder.build().wrap(photoService.listAll()));
|
||||
break;
|
||||
case "listTeams":
|
||||
env.setVariable("teams", builder.build().wrap(photoService.listTeamVos(Sort.by(DESC, "createTime"))));
|
||||
env.setVariable("teams", builder.build()
|
||||
.wrap(photoService.listTeamVos(Sort.by(DESC, "createTime"))));
|
||||
break;
|
||||
case "listByTeam":
|
||||
String team = params.get("team").toString();
|
||||
env.setVariable("photos", builder.build().wrap(photoService.listByTeam(team, Sort.by(DESC, "createTime"))));
|
||||
env.setVariable("photos", builder.build()
|
||||
.wrap(photoService.listByTeam(team, Sort.by(DESC, "createTime"))));
|
||||
break;
|
||||
case "count":
|
||||
env.setVariable("count", builder.build().wrap(photoService.count()));
|
||||
|
|
|
@ -1,7 +1,15 @@
|
|||
package run.halo.app.core.freemarker.tag;
|
||||
|
||||
import freemarker.core.Environment;
|
||||
import freemarker.template.*;
|
||||
import freemarker.template.Configuration;
|
||||
import freemarker.template.DefaultObjectWrapperBuilder;
|
||||
import freemarker.template.TemplateDirectiveBody;
|
||||
import freemarker.template.TemplateDirectiveModel;
|
||||
import freemarker.template.TemplateException;
|
||||
import freemarker.template.TemplateModel;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import org.springframework.stereotype.Component;
|
||||
import run.halo.app.model.entity.Post;
|
||||
import run.halo.app.model.enums.PostStatus;
|
||||
|
@ -10,10 +18,6 @@ import run.halo.app.service.PostCategoryService;
|
|||
import run.halo.app.service.PostService;
|
||||
import run.halo.app.service.PostTagService;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Freemarker custom tag of post.
|
||||
*
|
||||
|
@ -30,9 +34,9 @@ public class PostTagDirective implements TemplateDirectiveModel {
|
|||
private final PostCategoryService postCategoryService;
|
||||
|
||||
public PostTagDirective(Configuration configuration,
|
||||
PostService postService,
|
||||
PostTagService postTagService,
|
||||
PostCategoryService postCategoryService) {
|
||||
PostService postService,
|
||||
PostTagService postTagService,
|
||||
PostCategoryService postCategoryService) {
|
||||
this.postService = postService;
|
||||
this.postTagService = postTagService;
|
||||
this.postCategoryService = postCategoryService;
|
||||
|
@ -40,44 +44,57 @@ public class PostTagDirective implements TemplateDirectiveModel {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void execute(Environment env, Map params, TemplateModel[] loopVars, TemplateDirectiveBody body) throws TemplateException, IOException {
|
||||
final DefaultObjectWrapperBuilder builder = new DefaultObjectWrapperBuilder(Configuration.VERSION_2_3_25);
|
||||
public void execute(Environment env, Map params, TemplateModel[] loopVars,
|
||||
TemplateDirectiveBody body) throws TemplateException, IOException {
|
||||
final DefaultObjectWrapperBuilder builder =
|
||||
new DefaultObjectWrapperBuilder(Configuration.VERSION_2_3_25);
|
||||
if (params.containsKey(HaloConst.METHOD_KEY)) {
|
||||
String method = params.get(HaloConst.METHOD_KEY).toString();
|
||||
switch (method) {
|
||||
case "latest":
|
||||
int top = Integer.parseInt(params.get("top").toString());
|
||||
env.setVariable("posts", builder.build().wrap(postService.convertToListVo(postService.listLatest(top))));
|
||||
env.setVariable("posts", builder.build()
|
||||
.wrap(postService.convertToListVo(postService.listLatest(top))));
|
||||
break;
|
||||
case "count":
|
||||
env.setVariable("count", builder.build().wrap(postService.countByStatus(PostStatus.PUBLISHED)));
|
||||
env.setVariable("count",
|
||||
builder.build().wrap(postService.countByStatus(PostStatus.PUBLISHED)));
|
||||
break;
|
||||
case "archiveYear":
|
||||
env.setVariable("archives", builder.build().wrap(postService.listYearArchives()));
|
||||
env.setVariable("archives",
|
||||
builder.build().wrap(postService.listYearArchives()));
|
||||
break;
|
||||
case "archiveMonth":
|
||||
env.setVariable("archives", builder.build().wrap(postService.listMonthArchives()));
|
||||
env.setVariable("archives",
|
||||
builder.build().wrap(postService.listMonthArchives()));
|
||||
break;
|
||||
case "archive":
|
||||
String type = params.get("type").toString();
|
||||
env.setVariable("archives", builder.build().wrap("year".equals(type) ? postService.listYearArchives() : postService.listMonthArchives()));
|
||||
env.setVariable("archives", builder.build().wrap(
|
||||
"year".equals(type) ? postService.listYearArchives() :
|
||||
postService.listMonthArchives()));
|
||||
break;
|
||||
case "listByCategoryId":
|
||||
Integer categoryId = Integer.parseInt(params.get("categoryId").toString());
|
||||
env.setVariable("posts", builder.build().wrap(postService.convertToListVo(postCategoryService.listPostBy(categoryId, PostStatus.PUBLISHED))));
|
||||
env.setVariable("posts", builder.build().wrap(postService.convertToListVo(
|
||||
postCategoryService.listPostBy(categoryId, PostStatus.PUBLISHED))));
|
||||
break;
|
||||
case "listByCategorySlug":
|
||||
String categorySlug = params.get("categorySlug").toString();
|
||||
List<Post> posts = postCategoryService.listPostBy(categorySlug, PostStatus.PUBLISHED);
|
||||
env.setVariable("posts", builder.build().wrap(postService.convertToListVo(posts)));
|
||||
List<Post> posts =
|
||||
postCategoryService.listPostBy(categorySlug, PostStatus.PUBLISHED);
|
||||
env.setVariable("posts",
|
||||
builder.build().wrap(postService.convertToListVo(posts)));
|
||||
break;
|
||||
case "listByTagId":
|
||||
Integer tagId = Integer.parseInt(params.get("tagId").toString());
|
||||
env.setVariable("posts", builder.build().wrap(postService.convertToListVo(postTagService.listPostsBy(tagId, PostStatus.PUBLISHED))));
|
||||
env.setVariable("posts", builder.build().wrap(postService
|
||||
.convertToListVo(postTagService.listPostsBy(tagId, PostStatus.PUBLISHED))));
|
||||
break;
|
||||
case "listByTagSlug":
|
||||
String tagSlug = params.get("tagSlug").toString();
|
||||
env.setVariable("posts", builder.build().wrap(postService.convertToListVo(postTagService.listPostsBy(tagSlug, PostStatus.PUBLISHED))));
|
||||
env.setVariable("posts", builder.build().wrap(postService.convertToListVo(
|
||||
postTagService.listPostsBy(tagSlug, PostStatus.PUBLISHED))));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
|
|
@ -1,7 +1,17 @@
|
|||
package run.halo.app.core.freemarker.tag;
|
||||
|
||||
import static org.springframework.data.domain.Sort.Direction.DESC;
|
||||
|
||||
import freemarker.core.Environment;
|
||||
import freemarker.template.*;
|
||||
import freemarker.template.Configuration;
|
||||
import freemarker.template.DefaultObjectWrapperBuilder;
|
||||
import freemarker.template.TemplateDirectiveBody;
|
||||
import freemarker.template.TemplateDirectiveModel;
|
||||
import freemarker.template.TemplateException;
|
||||
import freemarker.template.TemplateModel;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.stereotype.Component;
|
||||
import run.halo.app.model.entity.Tag;
|
||||
|
@ -9,12 +19,6 @@ import run.halo.app.model.support.HaloConst;
|
|||
import run.halo.app.service.PostTagService;
|
||||
import run.halo.app.service.TagService;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.springframework.data.domain.Sort.Direction.DESC;
|
||||
|
||||
/**
|
||||
* Freemarker custom tag of tag.
|
||||
*
|
||||
|
@ -29,22 +33,25 @@ public class TagTagDirective implements TemplateDirectiveModel {
|
|||
private final PostTagService postTagService;
|
||||
|
||||
public TagTagDirective(Configuration configuration,
|
||||
TagService tagService,
|
||||
PostTagService postTagService) {
|
||||
TagService tagService,
|
||||
PostTagService postTagService) {
|
||||
this.tagService = tagService;
|
||||
this.postTagService = postTagService;
|
||||
configuration.setSharedVariable("tagTag", this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Environment env, Map params, TemplateModel[] loopVars, TemplateDirectiveBody body) throws TemplateException, IOException {
|
||||
final DefaultObjectWrapperBuilder builder = new DefaultObjectWrapperBuilder(Configuration.VERSION_2_3_25);
|
||||
public void execute(Environment env, Map params, TemplateModel[] loopVars,
|
||||
TemplateDirectiveBody body) throws TemplateException, IOException {
|
||||
final DefaultObjectWrapperBuilder builder =
|
||||
new DefaultObjectWrapperBuilder(Configuration.VERSION_2_3_25);
|
||||
|
||||
if (params.containsKey(HaloConst.METHOD_KEY)) {
|
||||
String method = params.get(HaloConst.METHOD_KEY).toString();
|
||||
switch (method) {
|
||||
case "list":
|
||||
env.setVariable("tags", builder.build().wrap(postTagService.listTagWithCountDtos(Sort.by(DESC, "createTime"))));
|
||||
env.setVariable("tags", builder.build()
|
||||
.wrap(postTagService.listTagWithCountDtos(Sort.by(DESC, "createTime"))));
|
||||
break;
|
||||
case "listByPostId":
|
||||
Integer postId = Integer.parseInt(params.get("postId").toString());
|
||||
|
|
|
@ -3,12 +3,16 @@ package run.halo.app.core.freemarker.tag;
|
|||
import cn.hutool.core.util.PageUtil;
|
||||
import cn.hutool.core.util.RandomUtil;
|
||||
import freemarker.core.Environment;
|
||||
import freemarker.template.*;
|
||||
import org.springframework.stereotype.Component;
|
||||
import run.halo.app.model.support.HaloConst;
|
||||
|
||||
import freemarker.template.Configuration;
|
||||
import freemarker.template.DefaultObjectWrapperBuilder;
|
||||
import freemarker.template.TemplateDirectiveBody;
|
||||
import freemarker.template.TemplateDirectiveModel;
|
||||
import freemarker.template.TemplateException;
|
||||
import freemarker.template.TemplateModel;
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
import org.springframework.stereotype.Component;
|
||||
import run.halo.app.model.support.HaloConst;
|
||||
|
||||
/**
|
||||
* Freemarker custom tag of tools.
|
||||
|
@ -24,8 +28,10 @@ public class ToolTagDirective implements TemplateDirectiveModel {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void execute(Environment env, Map params, TemplateModel[] loopVars, TemplateDirectiveBody body) throws TemplateException, IOException {
|
||||
final DefaultObjectWrapperBuilder builder = new DefaultObjectWrapperBuilder(Configuration.VERSION_2_3_25);
|
||||
public void execute(Environment env, Map params, TemplateModel[] loopVars,
|
||||
TemplateDirectiveBody body) throws TemplateException, IOException {
|
||||
final DefaultObjectWrapperBuilder builder =
|
||||
new DefaultObjectWrapperBuilder(Configuration.VERSION_2_3_25);
|
||||
|
||||
if (params.containsKey(HaloConst.METHOD_KEY)) {
|
||||
String method = params.get(HaloConst.METHOD_KEY).toString();
|
||||
|
@ -34,7 +40,8 @@ public class ToolTagDirective implements TemplateDirectiveModel {
|
|||
int page = Integer.parseInt(params.get("page").toString());
|
||||
int total = Integer.parseInt(params.get("total").toString());
|
||||
int display = Integer.parseInt(params.get("display").toString());
|
||||
env.setVariable("numbers", builder.build().wrap(PageUtil.rainbow(page, total, display)));
|
||||
env.setVariable("numbers",
|
||||
builder.build().wrap(PageUtil.rainbow(page, total, display)));
|
||||
break;
|
||||
case "random":
|
||||
int min = Integer.parseInt(params.get("min").toString());
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
package run.halo.app.event;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import lombok.Getter;
|
||||
import org.springframework.context.ApplicationEvent;
|
||||
|
||||
import java.nio.file.Path;
|
||||
|
||||
/**
|
||||
* @author ryanwang
|
||||
* @date 2020-03-24
|
||||
|
@ -18,7 +17,7 @@ public class StaticStorageChangedEvent extends ApplicationEvent {
|
|||
* Create a new {@code ApplicationEvent}.
|
||||
*
|
||||
* @param source the object on which the event initially occurred or with
|
||||
* which the event is associated (never {@code null})
|
||||
* which the event is associated (never {@code null})
|
||||
*/
|
||||
public StaticStorageChangedEvent(Object source, Path staticPath) {
|
||||
super(source);
|
||||
|
|
|
@ -20,7 +20,7 @@ public abstract class AbstractCommentBaseEvent extends ApplicationEvent {
|
|||
/**
|
||||
* Create a new ApplicationEvent.
|
||||
*
|
||||
* @param source the object on which the event initially occurred (never {@code null})
|
||||
* @param source the object on which the event initially occurred (never {@code null})
|
||||
* @param commentId comment id
|
||||
*/
|
||||
public AbstractCommentBaseEvent(Object source, @NonNull Long commentId) {
|
||||
|
|
|
@ -13,7 +13,7 @@ public class CommentNewEvent extends AbstractCommentBaseEvent {
|
|||
/**
|
||||
* Create a new ApplicationEvent.
|
||||
*
|
||||
* @param source the object on which the event initially occurred (never {@code null})
|
||||
* @param source the object on which the event initially occurred (never {@code null})
|
||||
* @param commentId comment id
|
||||
*/
|
||||
public CommentNewEvent(Object source, @NonNull Long commentId) {
|
||||
|
|
|
@ -13,7 +13,7 @@ public class CommentReplyEvent extends AbstractCommentBaseEvent {
|
|||
/**
|
||||
* Create a new ApplicationEvent.
|
||||
*
|
||||
* @param source the object on which the event initially occurred (never {@code null})
|
||||
* @param source the object on which the event initially occurred (never {@code null})
|
||||
* @param commentId comment id
|
||||
*/
|
||||
public CommentReplyEvent(Object source, @NonNull Long commentId) {
|
||||
|
|
|
@ -17,7 +17,7 @@ public class LogEvent extends ApplicationEvent {
|
|||
/**
|
||||
* Create a new ApplicationEvent.
|
||||
*
|
||||
* @param source the object on which the event initially occurred (never {@code null})
|
||||
* @param source the object on which the event initially occurred (never {@code null})
|
||||
* @param logParam login param
|
||||
*/
|
||||
public LogEvent(Object source, LogParam logParam) {
|
||||
|
|
|
@ -18,7 +18,7 @@ public abstract class AbstractVisitEvent extends ApplicationEvent {
|
|||
* Create a new ApplicationEvent.
|
||||
*
|
||||
* @param source the object on which the event initially occurred (never {@code null})
|
||||
* @param id id
|
||||
* @param id id
|
||||
*/
|
||||
public AbstractVisitEvent(@NonNull Object source, @NonNull Integer id) {
|
||||
super(source);
|
||||
|
|
|
@ -11,7 +11,7 @@ public class SheetVisitEvent extends AbstractVisitEvent {
|
|||
/**
|
||||
* Create a new ApplicationEvent.
|
||||
*
|
||||
* @param source the object on which the event initially occurred (never {@code null})
|
||||
* @param source the object on which the event initially occurred (never {@code null})
|
||||
* @param sheetId sheet id must not be null
|
||||
*/
|
||||
public SheetVisitEvent(Object source, Integer sheetId) {
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
package run.halo.app.factory;
|
||||
|
||||
import org.springframework.lang.NonNull;
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
import org.springframework.core.convert.converter.ConverterFactory;
|
||||
import org.springframework.lang.NonNull;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
|
@ -19,7 +19,7 @@ public class StringToEnumConverterFactory implements ConverterFactory<String, En
|
|||
}
|
||||
|
||||
private static class StringToEnumConverter<T extends Enum<T>>
|
||||
implements Converter<String, T> {
|
||||
implements Converter<String, T> {
|
||||
|
||||
private final Class<T> enumType;
|
||||
|
||||
|
|
|
@ -1,5 +1,15 @@
|
|||
package run.halo.app.filter;
|
||||
|
||||
import static run.halo.app.model.support.HaloConst.ADMIN_TOKEN_HEADER_NAME;
|
||||
import static run.halo.app.model.support.HaloConst.API_ACCESS_KEY_HEADER_NAME;
|
||||
|
||||
import java.io.IOException;
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.ServletResponse;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.core.annotation.Order;
|
||||
|
@ -8,17 +18,6 @@ import org.springframework.stereotype.Component;
|
|||
import org.springframework.web.cors.CorsUtils;
|
||||
import org.springframework.web.filter.GenericFilterBean;
|
||||
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.ServletResponse;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
|
||||
import static run.halo.app.model.support.HaloConst.ADMIN_TOKEN_HEADER_NAME;
|
||||
import static run.halo.app.model.support.HaloConst.API_ACCESS_KEY_HEADER_NAME;
|
||||
|
||||
/**
|
||||
* Filter for CORS.
|
||||
*
|
||||
|
@ -28,20 +27,25 @@ import static run.halo.app.model.support.HaloConst.API_ACCESS_KEY_HEADER_NAME;
|
|||
@Order(Ordered.HIGHEST_PRECEDENCE + 10)
|
||||
public class CorsFilter extends GenericFilterBean {
|
||||
|
||||
private final static String ALLOW_HEADERS = StringUtils.joinWith(",", HttpHeaders.CONTENT_TYPE, ADMIN_TOKEN_HEADER_NAME, API_ACCESS_KEY_HEADER_NAME);
|
||||
private static final String ALLOW_HEADERS = StringUtils
|
||||
.joinWith(",", HttpHeaders.CONTENT_TYPE, ADMIN_TOKEN_HEADER_NAME,
|
||||
API_ACCESS_KEY_HEADER_NAME);
|
||||
|
||||
@Override
|
||||
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
|
||||
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
|
||||
throws IOException, ServletException {
|
||||
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
|
||||
HttpServletResponse httpServletResponse = (HttpServletResponse) response;
|
||||
|
||||
// Set customized header
|
||||
String originHeaderValue = httpServletRequest.getHeader(HttpHeaders.ORIGIN);
|
||||
if (StringUtils.isNotBlank(originHeaderValue)) {
|
||||
httpServletResponse.setHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN, originHeaderValue);
|
||||
httpServletResponse
|
||||
.setHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN, originHeaderValue);
|
||||
}
|
||||
httpServletResponse.setHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_HEADERS, ALLOW_HEADERS);
|
||||
httpServletResponse.setHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_METHODS, "GET, POST, PUT, DELETE, OPTIONS");
|
||||
httpServletResponse
|
||||
.setHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_METHODS, "GET, POST, PUT, DELETE, OPTIONS");
|
||||
httpServletResponse.setHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS, "true");
|
||||
httpServletResponse.setHeader(HttpHeaders.ACCESS_CONTROL_MAX_AGE, "3600");
|
||||
|
||||
|
|
|
@ -1,18 +1,17 @@
|
|||
package run.halo.app.filter;
|
||||
|
||||
import cn.hutool.extra.servlet.ServletUtil;
|
||||
import java.io.IOException;
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.filter.OncePerRequestFilter;
|
||||
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Filter for logging.
|
||||
*
|
||||
|
@ -24,14 +23,15 @@ import java.io.IOException;
|
|||
public class LogFilter extends OncePerRequestFilter {
|
||||
|
||||
@Override
|
||||
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
|
||||
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
|
||||
FilterChain filterChain) throws ServletException, IOException {
|
||||
|
||||
final String remoteAddr = ServletUtil.getClientIP(request);
|
||||
|
||||
log.debug("Starting url: [{}], method: [{}], ip: [{}]",
|
||||
request.getRequestURL(),
|
||||
request.getMethod(),
|
||||
remoteAddr);
|
||||
request.getRequestURL(),
|
||||
request.getMethod(),
|
||||
remoteAddr);
|
||||
|
||||
// Set start time
|
||||
final long startTime = System.currentTimeMillis();
|
||||
|
@ -40,10 +40,10 @@ public class LogFilter extends OncePerRequestFilter {
|
|||
filterChain.doFilter(request, response);
|
||||
|
||||
log.debug("Ending url: [{}], method: [{}], ip: [{}], status: [{}], usage: [{}] ms",
|
||||
request.getRequestURL(),
|
||||
request.getMethod(),
|
||||
remoteAddr,
|
||||
response.getStatus(),
|
||||
System.currentTimeMillis() - startTime);
|
||||
request.getRequestURL(),
|
||||
request.getMethod(),
|
||||
remoteAddr,
|
||||
response.getStatus(),
|
||||
System.currentTimeMillis() - startTime);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,13 +1,16 @@
|
|||
package run.halo.app.handler.file;
|
||||
|
||||
import static run.halo.app.model.support.HaloConst.URL_SEPARATOR;
|
||||
|
||||
import com.aliyun.oss.OSS;
|
||||
import com.aliyun.oss.OSSClientBuilder;
|
||||
import com.aliyun.oss.model.DeleteObjectsRequest;
|
||||
import com.aliyun.oss.model.PutObjectResult;
|
||||
import java.util.Objects;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.lang.NonNull;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.lang.NonNull;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
@ -19,10 +22,6 @@ import run.halo.app.service.OptionService;
|
|||
import run.halo.app.utils.FilenameUtils;
|
||||
import run.halo.app.utils.ImageUtils;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import static run.halo.app.model.support.HaloConst.URL_SEPARATOR;
|
||||
|
||||
/**
|
||||
* Ali oss file handler.
|
||||
*
|
||||
|
@ -45,15 +44,24 @@ public class AliOssFileHandler implements FileHandler {
|
|||
Assert.notNull(file, "Multipart file must not be null");
|
||||
|
||||
// Get config
|
||||
String protocol = optionService.getByPropertyOfNonNull(AliOssProperties.OSS_PROTOCOL).toString();
|
||||
String domain = optionService.getByPropertyOrDefault(AliOssProperties.OSS_DOMAIN, String.class, "");
|
||||
String source = optionService.getByPropertyOrDefault(AliOssProperties.OSS_SOURCE, String.class, "");
|
||||
String endPoint = optionService.getByPropertyOfNonNull(AliOssProperties.OSS_ENDPOINT).toString();
|
||||
String accessKey = optionService.getByPropertyOfNonNull(AliOssProperties.OSS_ACCESS_KEY).toString();
|
||||
String accessSecret = optionService.getByPropertyOfNonNull(AliOssProperties.OSS_ACCESS_SECRET).toString();
|
||||
String bucketName = optionService.getByPropertyOfNonNull(AliOssProperties.OSS_BUCKET_NAME).toString();
|
||||
String styleRule = optionService.getByPropertyOrDefault(AliOssProperties.OSS_STYLE_RULE, String.class, "");
|
||||
String thumbnailStyleRule = optionService.getByPropertyOrDefault(AliOssProperties.OSS_THUMBNAIL_STYLE_RULE, String.class, "");
|
||||
String protocol =
|
||||
optionService.getByPropertyOfNonNull(AliOssProperties.OSS_PROTOCOL).toString();
|
||||
String domain =
|
||||
optionService.getByPropertyOrDefault(AliOssProperties.OSS_DOMAIN, String.class, "");
|
||||
String source =
|
||||
optionService.getByPropertyOrDefault(AliOssProperties.OSS_SOURCE, String.class, "");
|
||||
String endPoint =
|
||||
optionService.getByPropertyOfNonNull(AliOssProperties.OSS_ENDPOINT).toString();
|
||||
String accessKey =
|
||||
optionService.getByPropertyOfNonNull(AliOssProperties.OSS_ACCESS_KEY).toString();
|
||||
String accessSecret =
|
||||
optionService.getByPropertyOfNonNull(AliOssProperties.OSS_ACCESS_SECRET).toString();
|
||||
String bucketName =
|
||||
optionService.getByPropertyOfNonNull(AliOssProperties.OSS_BUCKET_NAME).toString();
|
||||
String styleRule =
|
||||
optionService.getByPropertyOrDefault(AliOssProperties.OSS_STYLE_RULE, String.class, "");
|
||||
String thumbnailStyleRule = optionService
|
||||
.getByPropertyOrDefault(AliOssProperties.OSS_THUMBNAIL_STYLE_RULE, String.class, "");
|
||||
|
||||
// Init OSS client
|
||||
OSS ossClient = new OSSClientBuilder().build(endPoint, accessKey, accessSecret);
|
||||
|
@ -62,30 +70,31 @@ public class AliOssFileHandler implements FileHandler {
|
|||
|
||||
if (StringUtils.isNotEmpty(domain)) {
|
||||
basePath.append(domain)
|
||||
.append(URL_SEPARATOR);
|
||||
.append(URL_SEPARATOR);
|
||||
} else {
|
||||
basePath.append(bucketName)
|
||||
.append(".")
|
||||
.append(endPoint)
|
||||
.append(URL_SEPARATOR);
|
||||
.append(".")
|
||||
.append(endPoint)
|
||||
.append(URL_SEPARATOR);
|
||||
}
|
||||
|
||||
try {
|
||||
final String basename = FilenameUtils.getBasename(Objects.requireNonNull(file.getOriginalFilename()));
|
||||
final String basename =
|
||||
FilenameUtils.getBasename(Objects.requireNonNull(file.getOriginalFilename()));
|
||||
final String extension = FilenameUtils.getExtension(file.getOriginalFilename());
|
||||
final String timestamp = String.valueOf(System.currentTimeMillis());
|
||||
final StringBuilder upFilePath = new StringBuilder();
|
||||
|
||||
if (StringUtils.isNotEmpty(source)) {
|
||||
upFilePath.append(source)
|
||||
.append(URL_SEPARATOR);
|
||||
.append(URL_SEPARATOR);
|
||||
}
|
||||
|
||||
upFilePath.append(basename)
|
||||
.append("_")
|
||||
.append(timestamp)
|
||||
.append(".")
|
||||
.append(extension);
|
||||
.append("_")
|
||||
.append(timestamp)
|
||||
.append(".")
|
||||
.append(extension);
|
||||
|
||||
String filePath = StringUtils.join(basePath.toString(), upFilePath.toString());
|
||||
|
||||
|
@ -93,8 +102,8 @@ public class AliOssFileHandler implements FileHandler {
|
|||
|
||||
// Upload
|
||||
final PutObjectResult putObjectResult = ossClient.putObject(bucketName,
|
||||
upFilePath.toString(),
|
||||
file.getInputStream());
|
||||
upFilePath.toString(),
|
||||
file.getInputStream());
|
||||
|
||||
if (putObjectResult == null) {
|
||||
throw new FileOperationException("上传附件 " + file.getOriginalFilename() + " 到阿里云失败 ");
|
||||
|
@ -103,9 +112,11 @@ public class AliOssFileHandler implements FileHandler {
|
|||
// Response result
|
||||
final UploadResult uploadResult = new UploadResult();
|
||||
uploadResult.setFilename(basename);
|
||||
uploadResult.setFilePath(StringUtils.isBlank(styleRule) ? filePath : filePath + styleRule);
|
||||
uploadResult
|
||||
.setFilePath(StringUtils.isBlank(styleRule) ? filePath : filePath + styleRule);
|
||||
uploadResult.setKey(upFilePath.toString());
|
||||
uploadResult.setMediaType(MediaType.valueOf(Objects.requireNonNull(file.getContentType())));
|
||||
uploadResult
|
||||
.setMediaType(MediaType.valueOf(Objects.requireNonNull(file.getContentType())));
|
||||
uploadResult.setSuffix(extension);
|
||||
uploadResult.setSize(file.getSize());
|
||||
|
||||
|
@ -113,14 +124,16 @@ public class AliOssFileHandler implements FileHandler {
|
|||
if (ImageUtils.EXTENSION_ICO.equals(extension)) {
|
||||
return filePath;
|
||||
} else {
|
||||
return StringUtils.isBlank(thumbnailStyleRule) ? filePath : filePath + thumbnailStyleRule;
|
||||
return StringUtils.isBlank(thumbnailStyleRule) ? filePath :
|
||||
filePath + thumbnailStyleRule;
|
||||
}
|
||||
});
|
||||
|
||||
log.info("Uploaded file: [{}] successfully", file.getOriginalFilename());
|
||||
return uploadResult;
|
||||
} catch (Exception e) {
|
||||
throw new FileOperationException("上传附件 " + file.getOriginalFilename() + " 到阿里云失败 ", e).setErrorData(file.getOriginalFilename());
|
||||
throw new FileOperationException("上传附件 " + file.getOriginalFilename() + " 到阿里云失败 ", e)
|
||||
.setErrorData(file.getOriginalFilename());
|
||||
} finally {
|
||||
ossClient.shutdown();
|
||||
}
|
||||
|
@ -131,10 +144,14 @@ public class AliOssFileHandler implements FileHandler {
|
|||
Assert.notNull(key, "File key must not be blank");
|
||||
|
||||
// Get config
|
||||
String endPoint = optionService.getByPropertyOfNonNull(AliOssProperties.OSS_ENDPOINT).toString();
|
||||
String accessKey = optionService.getByPropertyOfNonNull(AliOssProperties.OSS_ACCESS_KEY).toString();
|
||||
String accessSecret = optionService.getByPropertyOfNonNull(AliOssProperties.OSS_ACCESS_SECRET).toString();
|
||||
String bucketName = optionService.getByPropertyOfNonNull(AliOssProperties.OSS_BUCKET_NAME).toString();
|
||||
String endPoint =
|
||||
optionService.getByPropertyOfNonNull(AliOssProperties.OSS_ENDPOINT).toString();
|
||||
String accessKey =
|
||||
optionService.getByPropertyOfNonNull(AliOssProperties.OSS_ACCESS_KEY).toString();
|
||||
String accessSecret =
|
||||
optionService.getByPropertyOfNonNull(AliOssProperties.OSS_ACCESS_SECRET).toString();
|
||||
String bucketName =
|
||||
optionService.getByPropertyOfNonNull(AliOssProperties.OSS_BUCKET_NAME).toString();
|
||||
|
||||
// Init OSS client
|
||||
OSS ossClient = new OSSClientBuilder().build(endPoint, accessKey, accessSecret);
|
||||
|
|
|
@ -5,6 +5,7 @@ import com.baidubce.auth.DefaultBceCredentials;
|
|||
import com.baidubce.services.bos.BosClient;
|
||||
import com.baidubce.services.bos.BosClientConfiguration;
|
||||
import com.baidubce.services.bos.model.PutObjectResponse;
|
||||
import java.util.Objects;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.http.MediaType;
|
||||
|
@ -19,8 +20,6 @@ import run.halo.app.service.OptionService;
|
|||
import run.halo.app.utils.FilenameUtils;
|
||||
import run.halo.app.utils.ImageUtils;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Baidu bos file handler.
|
||||
*
|
||||
|
@ -44,13 +43,20 @@ public class BaiduBosFileHandler implements FileHandler {
|
|||
|
||||
// Get config
|
||||
Object protocol = optionService.getByPropertyOfNonNull(BaiduBosProperties.BOS_PROTOCOL);
|
||||
String domain = optionService.getByPropertyOrDefault(BaiduBosProperties.BOS_DOMAIN, String.class, "");
|
||||
String endPoint = optionService.getByPropertyOfNonNull(BaiduBosProperties.BOS_ENDPOINT).toString();
|
||||
String accessKey = optionService.getByPropertyOfNonNull(BaiduBosProperties.BOS_ACCESS_KEY).toString();
|
||||
String secretKey = optionService.getByPropertyOfNonNull(BaiduBosProperties.BOS_SECRET_KEY).toString();
|
||||
String bucketName = optionService.getByPropertyOfNonNull(BaiduBosProperties.BOS_BUCKET_NAME).toString();
|
||||
String styleRule = optionService.getByPropertyOrDefault(BaiduBosProperties.BOS_STYLE_RULE, String.class, "");
|
||||
String thumbnailStyleRule = optionService.getByPropertyOrDefault(BaiduBosProperties.BOS_THUMBNAIL_STYLE_RULE, String.class, "");
|
||||
String domain =
|
||||
optionService.getByPropertyOrDefault(BaiduBosProperties.BOS_DOMAIN, String.class, "");
|
||||
String endPoint =
|
||||
optionService.getByPropertyOfNonNull(BaiduBosProperties.BOS_ENDPOINT).toString();
|
||||
String accessKey =
|
||||
optionService.getByPropertyOfNonNull(BaiduBosProperties.BOS_ACCESS_KEY).toString();
|
||||
String secretKey =
|
||||
optionService.getByPropertyOfNonNull(BaiduBosProperties.BOS_SECRET_KEY).toString();
|
||||
String bucketName =
|
||||
optionService.getByPropertyOfNonNull(BaiduBosProperties.BOS_BUCKET_NAME).toString();
|
||||
String styleRule = optionService
|
||||
.getByPropertyOrDefault(BaiduBosProperties.BOS_STYLE_RULE, String.class, "");
|
||||
String thumbnailStyleRule = optionService
|
||||
.getByPropertyOrDefault(BaiduBosProperties.BOS_THUMBNAIL_STYLE_RULE, String.class, "");
|
||||
String source = StringUtils.join(protocol, bucketName, "." + endPoint);
|
||||
|
||||
BosClientConfiguration config = new BosClientConfiguration();
|
||||
|
@ -63,14 +69,18 @@ public class BaiduBosFileHandler implements FileHandler {
|
|||
domain = protocol + domain;
|
||||
|
||||
try {
|
||||
String basename = FilenameUtils.getBasename(Objects.requireNonNull(file.getOriginalFilename()));
|
||||
String basename =
|
||||
FilenameUtils.getBasename(Objects.requireNonNull(file.getOriginalFilename()));
|
||||
String extension = FilenameUtils.getExtension(file.getOriginalFilename());
|
||||
String timestamp = String.valueOf(System.currentTimeMillis());
|
||||
String upFilePath = StringUtils.join(basename, "_", timestamp, ".", extension);
|
||||
String filePath = StringUtils.join(StringUtils.appendIfMissing(StringUtils.isNotBlank(domain) ? domain : source, "/"), upFilePath);
|
||||
String filePath = StringUtils.join(
|
||||
StringUtils.appendIfMissing(StringUtils.isNotBlank(domain) ? domain : source, "/"),
|
||||
upFilePath);
|
||||
|
||||
// Upload
|
||||
PutObjectResponse putObjectResponseFromInputStream = client.putObject(bucketName, upFilePath, file.getInputStream());
|
||||
PutObjectResponse putObjectResponseFromInputStream =
|
||||
client.putObject(bucketName, upFilePath, file.getInputStream());
|
||||
if (putObjectResponseFromInputStream == null) {
|
||||
throw new FileOperationException("上传附件 " + file.getOriginalFilename() + " 到百度云失败 ");
|
||||
}
|
||||
|
@ -78,9 +88,11 @@ public class BaiduBosFileHandler implements FileHandler {
|
|||
// Response result
|
||||
UploadResult uploadResult = new UploadResult();
|
||||
uploadResult.setFilename(basename);
|
||||
uploadResult.setFilePath(StringUtils.isBlank(styleRule) ? filePath : filePath + styleRule);
|
||||
uploadResult
|
||||
.setFilePath(StringUtils.isBlank(styleRule) ? filePath : filePath + styleRule);
|
||||
uploadResult.setKey(upFilePath);
|
||||
uploadResult.setMediaType(MediaType.valueOf(Objects.requireNonNull(file.getContentType())));
|
||||
uploadResult
|
||||
.setMediaType(MediaType.valueOf(Objects.requireNonNull(file.getContentType())));
|
||||
uploadResult.setSuffix(extension);
|
||||
uploadResult.setSize(file.getSize());
|
||||
|
||||
|
@ -89,7 +101,8 @@ public class BaiduBosFileHandler implements FileHandler {
|
|||
if (ImageUtils.EXTENSION_ICO.equals(extension)) {
|
||||
return filePath;
|
||||
} else {
|
||||
return StringUtils.isBlank(thumbnailStyleRule) ? filePath : filePath + thumbnailStyleRule;
|
||||
return StringUtils.isBlank(thumbnailStyleRule) ? filePath :
|
||||
filePath + thumbnailStyleRule;
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -106,10 +119,14 @@ public class BaiduBosFileHandler implements FileHandler {
|
|||
Assert.notNull(key, "File key must not be blank");
|
||||
|
||||
// Get config
|
||||
String endPoint = optionService.getByPropertyOfNonNull(BaiduBosProperties.BOS_ENDPOINT).toString();
|
||||
String accessKey = optionService.getByPropertyOfNonNull(BaiduBosProperties.BOS_ACCESS_KEY).toString();
|
||||
String secretKey = optionService.getByPropertyOfNonNull(BaiduBosProperties.BOS_SECRET_KEY).toString();
|
||||
String bucketName = optionService.getByPropertyOfNonNull(BaiduBosProperties.BOS_BUCKET_NAME).toString();
|
||||
String endPoint =
|
||||
optionService.getByPropertyOfNonNull(BaiduBosProperties.BOS_ENDPOINT).toString();
|
||||
String accessKey =
|
||||
optionService.getByPropertyOfNonNull(BaiduBosProperties.BOS_ACCESS_KEY).toString();
|
||||
String secretKey =
|
||||
optionService.getByPropertyOfNonNull(BaiduBosProperties.BOS_SECRET_KEY).toString();
|
||||
String bucketName =
|
||||
optionService.getByPropertyOfNonNull(BaiduBosProperties.BOS_BUCKET_NAME).toString();
|
||||
|
||||
BosClientConfiguration config = new BosClientConfiguration();
|
||||
config.setCredentials(new DefaultBceCredentials(accessKey, secretKey));
|
||||
|
|
|
@ -1,5 +1,11 @@
|
|||
package run.halo.app.handler.file;
|
||||
|
||||
import static run.halo.app.model.support.HaloConst.FILE_SEPARATOR;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.function.Supplier;
|
||||
import javax.imageio.ImageReader;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.http.MediaType;
|
||||
|
@ -12,13 +18,6 @@ import run.halo.app.model.enums.AttachmentType;
|
|||
import run.halo.app.model.support.UploadResult;
|
||||
import run.halo.app.utils.ImageUtils;
|
||||
|
||||
import javax.imageio.ImageReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import static run.halo.app.model.support.HaloConst.FILE_SEPARATOR;
|
||||
|
||||
/**
|
||||
* File handler interface.
|
||||
*
|
||||
|
@ -29,6 +28,19 @@ public interface FileHandler {
|
|||
|
||||
MediaType IMAGE_TYPE = MediaType.valueOf("image/*");
|
||||
|
||||
/**
|
||||
* Normalize directory full name, ensure the end path separator.
|
||||
*
|
||||
* @param dir directory full name must not be blank
|
||||
* @return normalized directory full name with end path separator
|
||||
*/
|
||||
@NonNull
|
||||
static String normalizeDirectory(@NonNull String dir) {
|
||||
Assert.hasText(dir, "Directory full name must not be blank");
|
||||
|
||||
return StringUtils.appendIfMissing(dir, FILE_SEPARATOR);
|
||||
}
|
||||
|
||||
/**
|
||||
* Uploads file.
|
||||
*
|
||||
|
@ -51,13 +63,13 @@ public interface FileHandler {
|
|||
}
|
||||
|
||||
/**
|
||||
* @param uploadResult updated result must not be null
|
||||
* @param file multipart file must not be null
|
||||
* @param uploadResult updated result must not be null
|
||||
* @param file multipart file must not be null
|
||||
* @param thumbnailSupplier thumbnail supplier
|
||||
*/
|
||||
default void handleImageMetadata(@NonNull MultipartFile file,
|
||||
@NonNull UploadResult uploadResult,
|
||||
@Nullable Supplier<String> thumbnailSupplier) {
|
||||
@NonNull UploadResult uploadResult,
|
||||
@Nullable Supplier<String> thumbnailSupplier) {
|
||||
if (isImageType(file)) {
|
||||
// Handle image
|
||||
try (InputStream is = file.getInputStream()) {
|
||||
|
@ -92,17 +104,4 @@ public interface FileHandler {
|
|||
*/
|
||||
AttachmentType getAttachmentType();
|
||||
|
||||
/**
|
||||
* Normalize directory full name, ensure the end path separator.
|
||||
*
|
||||
* @param dir directory full name must not be blank
|
||||
* @return normalized directory full name with end path separator
|
||||
*/
|
||||
@NonNull
|
||||
static String normalizeDirectory(@NonNull String dir) {
|
||||
Assert.hasText(dir, "Directory full name must not be blank");
|
||||
|
||||
return StringUtils.appendIfMissing(dir, FILE_SEPARATOR);
|
||||
}
|
||||
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue