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 conflicts
pull/1242/head
John Niang 2021-01-24 17:11:10 +08:00 committed by GitHub
parent de5e968025
commit feab7c4b5f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
373 changed files with 7501 additions and 4972 deletions

510
.editorconfig Normal file
View File

@ -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

2
.github/FUNDING.yml vendored
View File

@ -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' ]

View File

@ -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
- 移除站点验证的设置选项百度Google360必应的站点验证
- 更换 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:
- 修复评论模块头像显示不正常的问题,需要同时更新主题。
## 升级注意
- 由于此次更新删除了百度Google360必应的站点验证设置选项所以更新前请备份你之前的设置更新之后你可以在博客设置中的其他设置里面将原先的内容放在自定义 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)

View File

@ -60,6 +60,7 @@ java -jar halo-latest.jar
> Halo 使用 GPL-v3.0 协议开源,请尽量遵守开源协议。
## 贡献
参考 [CONTRIBUTING](./CONTRIBUTING.md)。
## 捐赠

View File

@ -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]:

View File

@ -14,6 +14,12 @@ java {
sourceCompatibility = JavaVersion.VERSION_11
}
checkstyle {
toolVersion = "8.39"
showViolations = false
ignoreFailures = false
}
repositories {
mavenLocal()
maven {

View File

@ -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>

View File

@ -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);

View File

@ -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
*

View File

@ -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

View File

@ -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("禁止访问");

View File

@ -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);
}
}

View File

@ -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");

View File

@ -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) {

View File

@ -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.
*

View File

@ -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.

View File

@ -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;
}

View File

@ -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()));
}
}
}

View File

@ -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.

View File

@ -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();

View File

@ -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.

View File

@ -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;
}

View File

@ -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/");
}

View File

@ -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) {

View File

@ -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);
}
}

View File

@ -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.

View File

@ -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")

View File

@ -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));

View File

@ -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);
}

View File

@ -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));

View File

@ -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());

View File

@ -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);
}

View File

@ -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);

View File

@ -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);
}

View File

@ -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));
}

View File

@ -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.
*

View File

@ -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")

View File

@ -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);

View File

@ -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);
}

View File

@ -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);

View File

@ -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);

View File

@ -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

View File

@ -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);

View File

@ -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();

View File

@ -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);
}

View File

@ -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);

View File

@ -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);
}

View File

@ -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());
}

View File

@ -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);
}
}

View File

@ -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();
}

View File

@ -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);
}
}

View File

@ -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);

View File

@ -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));
}

View File

@ -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.
*

View File

@ -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);
}
}

View File

@ -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));
}

View File

@ -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.
*

View File

@ -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);
}
}

View File

@ -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));
}

View File

@ -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);
}
}

View File

@ -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));
}

View File

@ -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));
}
}

View File

@ -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);
}
}

View File

@ -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.
*

View File

@ -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();
}
}

View File

@ -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.

View File

@ -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);

View File

@ -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;
}

View File

@ -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);

View File

@ -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);

View File

@ -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");

View File

@ -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);

View File

@ -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();

View File

@ -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();

View File

@ -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("缺失请求主体");

View File

@ -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) {

View File

@ -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());

View File

@ -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.

View File

@ -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()));

View File

@ -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()));

View File

@ -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()));

View File

@ -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()));

View File

@ -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/");

View File

@ -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()));

View File

@ -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;

View File

@ -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());

View File

@ -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());

View File

@ -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);

View File

@ -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) {

View File

@ -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) {

View File

@ -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) {

View File

@ -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) {

View File

@ -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);

View File

@ -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) {

View File

@ -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;

View File

@ -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");

View File

@ -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);
}
}

View File

@ -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);

View File

@ -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));

View File

@ -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