Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(frontend): Botプロテクションの設定変更時は実際に検証を通過しないと保存できないようにする #15151

Open
wants to merge 17 commits into
base: develop
Choose a base branch
from

Conversation

samunohito
Copy link
Member

@samunohito samunohito commented Dec 19, 2024

What

コントロールパネル→セキュリティのページでBotプロテクションの設定項目を更新する際、実際にcaptchaによる検証を通過しないと設定の更新が行えないようにします。

Why

fix #15137
※セキュリティ的な物というより、実際に動作する環境であるか確認の取れた状態で確定するための意味合いが強いです

Additional info (optional)

実際に各captchaで動作確認(※確認中)

Checklist

  • Read the contribution guide
  • Test working in a local environment
  • (If needed) Add story of storybook
  • (If needed) Update CHANGELOG.md
  • (If possible) Add tests

@github-actions github-actions bot added the packages/frontend Client side specific issue/PR label Dec 19, 2024
@samunohito
Copy link
Member Author

(動確して不備がある or 何らかのレビューコメントが来る…でもない限り、コードを変えることはおそらくないと思います)

@samunohito samunohito added this to the v2024.12.0 milestone Dec 19, 2024
Copy link

codecov bot commented Dec 19, 2024

Codecov Report

Attention: Patch coverage is 60.57441% with 302 lines in your changes missing coverage. Please review.

Project coverage is 41.67%. Comparing base (f123be3) to head (1be6169).
Report is 1 commits behind head on develop.

Files with missing lines Patch % Lines
...ckages/frontend/src/pages/admin/bot-protection.vue 0.00% 177 Missing ⚠️
packages/frontend/src/components/MkCaptcha.vue 0.00% 59 Missing ⚠️
...end/src/server/api/endpoints/admin/captcha/save.ts 65.11% 45 Missing ⚠️
.../src/server/api/endpoints/admin/captcha/current.ts 88.57% 8 Missing ⚠️
packages/backend/src/core/CaptchaService.ts 97.88% 6 Missing ⚠️
packages/frontend/src/components/MkFormFooter.vue 0.00% 6 Missing ⚠️
packages/frontend/src/os.ts 66.66% 1 Missing ⚠️
Additional details and impacted files
@@             Coverage Diff             @@
##           develop   #15151      +/-   ##
===========================================
+ Coverage    39.95%   41.67%   +1.72%     
===========================================
  Files         1563     1569       +6     
  Lines       197878   204335    +6457     
  Branches      3635     3776     +141     
===========================================
+ Hits         79059    85155    +6096     
- Misses      118215   118605     +390     
+ Partials       604      575      -29     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

<div>サイトキーに"10000000-ffff-ffff-ffff-000000000001"と入力することで動作をテスト出来ます。<br/>本番運用時には必ず正規のサイトキーを設定してください。</div>
<div>ref: <a href="https://docs.hcaptcha.com/#integration-testing-test-keys" target="_blank">hCaptcha Developer Guide</a></div>
</div>
</MkInfo>
</template>
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

テスト用のサイトキーがデフォルトで入るようになっていたのをやめました。
実物のuiが表示されてしまい、正常に動作していると誤認しかねないと考えたため…

<template v-else-if="botProtectionForm.state.provider === 'testcaptcha'">
<MkInfo warn><span v-html="i18n.ts.testCaptchaWarning"></span></MkInfo>
<FormSlot>
<template #label>{{ i18n.ts.preview }}</template>
<MkCaptcha provider="testcaptcha"/>
<MkCaptcha v-model="testCaptchaResponse" provider="testcaptcha" :sitekey="null"/>
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

型エラーが出てたので

@@ -18,7 +18,7 @@
http-equiv="Content-Security-Policy"
content="default-src 'self' https://newassets.hcaptcha.com/ https://challenges.cloudflare.com/ http://localhost:7493/;
worker-src 'self';
script-src 'self' 'unsafe-eval' https://*.hcaptcha.com https://challenges.cloudflare.com https://esm.sh;
script-src 'self' 'unsafe-eval' https://*.hcaptcha.com https://*.recaptcha.net https://*.gstatic.com https://challenges.cloudflare.com https://esm.sh;
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

dev modeでreCAPTCHAが表示できなかったので

@kakkokari-gtyih
Copy link
Contributor

kakkokari-gtyih commented Dec 19, 2024

実際に値を渡してサーバーサイドの検証まで通るのを確認する(Captcha保存用のAPIをadmin/update-metaから分離してCAPTCHAのリザルトも一緒に送信させるAPIを別途用意する)のを想定してたけどこれでも十分そうかしら

@Ruruke
Copy link

Ruruke commented Dec 19, 2024

自分の方で確認したところSitekeyを1文字でも残してコピーペーストするとPreviewがすごく増えますね。

確認に使用したブランチ

image

@samunohito
Copy link
Member Author

i18nもやらないと…

Copy link
Contributor

github-actions bot commented Dec 20, 2024

このPRによるapi.jsonの差分

差分はこちら
--- base
+++ head
@@ -4748,6 +4748,492 @@
         }
       }
     },
+    "/admin/captcha/current": {
+      "post": {
+        "operationId": "admin___captcha___current",
+        "summary": "admin/captcha/current",
+        "description": "No description provided.\n\n**Credential required**: *Yes* / **Permission**: *read:admin:meta*",
+        "externalDocs": {
+          "description": "Source code",
+          "url": "https://github.com/misskey-dev/misskey/blob/develop/packages/backend/src/server/api/endpoints/admin/captcha/current.ts"
+        },
+        "tags": [
+          "admin"
+        ],
+        "security": [
+          {
+            "bearerAuth": []
+          }
+        ],
+        "responses": {
+          "200": {
+            "description": "OK (with results)",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "type": "object",
+                  "properties": {
+                    "provider": {
+                      "type": "string",
+                      "enum": [
+                        "none",
+                        "hcaptcha",
+                        "mcaptcha",
+                        "recaptcha",
+                        "turnstile",
+                        "testcaptcha"
+                      ]
+                    },
+                    "hcaptcha": {
+                      "type": "object",
+                      "properties": {
+                        "siteKey": {
+                          "type": [
+                            "string",
+                            "null"
+                          ]
+                        },
+                        "secretKey": {
+                          "type": [
+                            "string",
+                            "null"
+                          ]
+                        }
+                      },
+                      "required": [
+                        "siteKey",
+                        "secretKey"
+                      ]
+                    },
+                    "mcaptcha": {
+                      "type": "object",
+                      "properties": {
+                        "siteKey": {
+                          "type": [
+                            "string",
+                            "null"
+                          ]
+                        },
+                        "secretKey": {
+                          "type": [
+                            "string",
+                            "null"
+                          ]
+                        },
+                        "instanceUrl": {
+                          "type": [
+                            "string",
+                            "null"
+                          ]
+                        }
+                      },
+                      "required": [
+                        "siteKey",
+                        "secretKey",
+                        "instanceUrl"
+                      ]
+                    },
+                    "recaptcha": {
+                      "type": "object",
+                      "properties": {
+                        "siteKey": {
+                          "type": [
+                            "string",
+                            "null"
+                          ]
+                        },
+                        "secretKey": {
+                          "type": [
+                            "string",
+                            "null"
+                          ]
+                        }
+                      },
+                      "required": [
+                        "siteKey",
+                        "secretKey"
+                      ]
+                    },
+                    "turnstile": {
+                      "type": "object",
+                      "properties": {
+                        "siteKey": {
+                          "type": [
+                            "string",
+                            "null"
+                          ]
+                        },
+                        "secretKey": {
+                          "type": [
+                            "string",
+                            "null"
+                          ]
+                        }
+                      },
+                      "required": [
+                        "siteKey",
+                        "secretKey"
+                      ]
+                    }
+                  },
+                  "required": [
+                    "provider",
+                    "hcaptcha",
+                    "mcaptcha",
+                    "recaptcha",
+                    "turnstile"
+                  ]
+                }
+              }
+            }
+          },
+          "400": {
+            "description": "Client error",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/Error"
+                },
+                "examples": {
+                  "INVALID_PARAM": {
+                    "value": {
+                      "error": {
+                        "message": "Invalid param.",
+                        "code": "INVALID_PARAM",
+                        "id": "3d81ceae-475f-4600-b2a8-2bc116157532"
+                      }
+                    }
+                  }
+                }
+              }
+            }
+          },
+          "401": {
+            "description": "Authentication error",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/Error"
+                },
+                "examples": {
+                  "CREDENTIAL_REQUIRED": {
+                    "value": {
+                      "error": {
+                        "message": "Credential required.",
+                        "code": "CREDENTIAL_REQUIRED",
+                        "id": "1384574d-a912-4b81-8601-c7b1c4085df1"
+                      }
+                    }
+                  }
+                }
+              }
+            }
+          },
+          "403": {
+            "description": "Forbidden error",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/Error"
+                },
+                "examples": {
+                  "AUTHENTICATION_FAILED": {
+                    "value": {
+                      "error": {
+                        "message": "Authentication failed. Please ensure your token is correct.",
+                        "code": "AUTHENTICATION_FAILED",
+                        "id": "b0a7f5f8-dc2f-4171-b91f-de88ad238e14"
+                      }
+                    }
+                  }
+                }
+              }
+            }
+          },
+          "418": {
+            "description": "I'm Ai",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/Error"
+                },
+                "examples": {
+                  "I_AM_AI": {
+                    "value": {
+                      "error": {
+                        "message": "You sent a request to Ai-chan, Misskey's showgirl, instead of the server.",
+                        "code": "I_AM_AI",
+                        "id": "60c46cd1-f23a-46b1-bebe-5d2b73951a84"
+                      }
+                    }
+                  }
+                }
+              }
+            }
+          },
+          "500": {
+            "description": "Internal server error",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/Error"
+                },
+                "examples": {
+                  "INTERNAL_ERROR": {
+                    "value": {
+                      "error": {
+                        "message": "Internal error occurred. Please contact us if the error persists.",
+                        "code": "INTERNAL_ERROR",
+                        "id": "5d37dbcb-891e-41ca-a3d6-e690c97775ac"
+                      }
+                    }
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+    },
+    "/admin/captcha/save": {
+      "post": {
+        "operationId": "admin___captcha___save",
+        "summary": "admin/captcha/save",
+        "description": "No description provided.\n\n**Credential required**: *Yes* / **Permission**: *write:admin:meta*",
+        "externalDocs": {
+          "description": "Source code",
+          "url": "https://github.com/misskey-dev/misskey/blob/develop/packages/backend/src/server/api/endpoints/admin/captcha/save.ts"
+        },
+        "tags": [
+          "admin"
+        ],
+        "security": [
+          {
+            "bearerAuth": []
+          }
+        ],
+        "requestBody": {
+          "required": true,
+          "content": {
+            "application/json": {
+              "schema": {
+                "type": "object",
+                "properties": {
+                  "provider": {
+                    "type": "string",
+                    "enum": [
+                      "none",
+                      "hcaptcha",
+                      "mcaptcha",
+                      "recaptcha",
+                      "turnstile",
+                      "testcaptcha"
+                    ]
+                  },
+                  "captchaResult": {
+                    "type": [
+                      "string",
+                      "null"
+                    ]
+                  },
+                  "sitekey": {
+                    "type": [
+                      "string",
+                      "null"
+                    ]
+                  },
+                  "secret": {
+                    "type": [
+                      "string",
+                      "null"
+                    ]
+                  },
+                  "instanceUrl": {
+                    "type": [
+                      "string",
+                      "null"
+                    ]
+                  }
+                },
+                "required": [
+                  "provider"
+                ]
+              }
+            }
+          }
+        },
+        "responses": {
+          "204": {
+            "description": "OK (without any results)"
+          },
+          "400": {
+            "description": "Client error",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/Error"
+                },
+                "examples": {
+                  "INVALID_PROVIDER": {
+                    "value": {
+                      "error": {
+                        "message": "Invalid provider.",
+                        "code": "INVALID_PROVIDER",
+                        "id": "14bf7ae1-80cc-4363-acb2-4fd61d086af0",
+                        "httpStatusCode": 400
+                      }
+                    }
+                  },
+                  "INVALID_PARAMETERS": {
+                    "value": {
+                      "error": {
+                        "message": "Invalid parameters.",
+                        "code": "INVALID_PARAMETERS",
+                        "id": "26654194-410e-44e2-b42e-460ff6f92476",
+                        "httpStatusCode": 400
+                      }
+                    }
+                  },
+                  "NO_RESPONSE_PROVIDED": {
+                    "value": {
+                      "error": {
+                        "message": "No response provided.",
+                        "code": "NO_RESPONSE_PROVIDED",
+                        "id": "40acbba8-0937-41fb-bb3f-474514d40afe",
+                        "httpStatusCode": 400
+                      }
+                    }
+                  },
+                  "REQUEST_FAILED": {
+                    "value": {
+                      "error": {
+                        "message": "Request failed.",
+                        "code": "REQUEST_FAILED",
+                        "id": "0f4fe2f1-2c15-4d6e-b714-efbfcde231cd",
+                        "httpStatusCode": 500
+                      }
+                    }
+                  },
+                  "VERIFICATION_FAILED": {
+                    "value": {
+                      "error": {
+                        "message": "Verification failed.",
+                        "code": "VERIFICATION_FAILED",
+                        "id": "c41c067f-24f3-4150-84b2-b5a3ae8c2214",
+                        "httpStatusCode": 400
+                      }
+                    }
+                  },
+                  "UNKNOWN": {
+                    "value": {
+                      "error": {
+                        "message": "unknown",
+                        "code": "UNKNOWN",
+                        "id": "f868d509-e257-42a9-99c1-42614b031a97",
+                        "httpStatusCode": 500
+                      }
+                    }
+                  },
+                  "INVALID_PARAM": {
+                    "value": {
+                      "error": {
+                        "message": "Invalid param.",
+                        "code": "INVALID_PARAM",
+                        "id": "3d81ceae-475f-4600-b2a8-2bc116157532"
+                      }
+                    }
+                  }
+                }
+              }
+            }
+          },
+          "401": {
+            "description": "Authentication error",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/Error"
+                },
+                "examples": {
+                  "CREDENTIAL_REQUIRED": {
+                    "value": {
+                      "error": {
+                        "message": "Credential required.",
+                        "code": "CREDENTIAL_REQUIRED",
+                        "id": "1384574d-a912-4b81-8601-c7b1c4085df1"
+                      }
+                    }
+                  }
+                }
+              }
+            }
+          },
+          "403": {
+            "description": "Forbidden error",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/Error"
+                },
+                "examples": {
+                  "AUTHENTICATION_FAILED": {
+                    "value": {
+                      "error": {
+                        "message": "Authentication failed. Please ensure your token is correct.",
+                        "code": "AUTHENTICATION_FAILED",
+                        "id": "b0a7f5f8-dc2f-4171-b91f-de88ad238e14"
+                      }
+                    }
+                  }
+                }
+              }
+            }
+          },
+          "418": {
+            "description": "I'm Ai",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/Error"
+                },
+                "examples": {
+                  "I_AM_AI": {
+                    "value": {
+                      "error": {
+                        "message": "You sent a request to Ai-chan, Misskey's showgirl, instead of the server.",
+                        "code": "I_AM_AI",
+                        "id": "60c46cd1-f23a-46b1-bebe-5d2b73951a84"
+                      }
+                    }
+                  }
+                }
+              }
+            }
+          },
+          "500": {
+            "description": "Internal server error",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/Error"
+                },
+                "examples": {
+                  "INTERNAL_ERROR": {
+                    "value": {
+                      "error": {
+                        "message": "Internal error occurred. Please contact us if the error persists.",
+                        "code": "INTERNAL_ERROR",
+                        "id": "5d37dbcb-891e-41ca-a3d6-e690c97775ac"
+                      }
+                    }
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+    },
     "/admin/delete-all-files-of-a-user": {
       "post": {
         "operationId": "admin___delete-all-files-of-a-user",

Get diff files from Workflow Page

@samunohito samunohito marked this pull request as ready for review December 21, 2024 01:48
@samunohito
Copy link
Member Author

open

@samunohito samunohito changed the title [wip] feat(frontend): Botプロテクションの設定変更時は実際に検証を通過しないと保存できないようにする feat(frontend): Botプロテクションの設定変更時は実際に検証を通過しないと保存できないようにする Dec 21, 2024
@samunohito
Copy link
Member Author

こんな感じになるイメージ
#15137 (comment)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Development

Successfully merging this pull request may close these issues.

Captchaの設定に不備があるとログインが行えなくなる
3 participants