feat: New SimpleGenerator
to generate the captcha
Signed-off-by: Awiteb <a@4rs.nl>
This commit is contained in:
parent
28425d939f
commit
c6956ad729
3 changed files with 134 additions and 40 deletions
|
@ -1,40 +0,0 @@
|
|||
// Copyright (c) 2024, Awiteb <a@4rs.nl>
|
||||
// A captcha middleware for Salvo framework.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
use crate::{CaptchaDifficulty, CaptchaName, CaptchaStorage};
|
||||
|
||||
/// Captcha generator, used to generate a new captcha image. This trait are implemented for all [`CaptchaStorage`].
|
||||
pub trait CaptchaGenerator: CaptchaStorage {
|
||||
/// Create a new captcha image and return the token and the image encoded as png. Will return None if the captcha crate failed to create the captcha.
|
||||
///
|
||||
/// The returned captcha image is 220x110 pixels.
|
||||
///
|
||||
/// For more information about the captcha name and difficulty, see the [`README.md`](https://git.4rs.nl/awiteb/salvo-captcha/#captcha-name-and-difficulty).
|
||||
fn new_captcha(
|
||||
&self,
|
||||
name: CaptchaName,
|
||||
difficulty: CaptchaDifficulty,
|
||||
) -> impl std::future::Future<Output = Result<Option<(String, Vec<u8>)>, Self::Error>> + Send
|
||||
{
|
||||
async {
|
||||
let Some((captcha_answer, captcha_image)) =
|
||||
captcha::by_name(difficulty, name).as_tuple()
|
||||
else {
|
||||
return Ok(None);
|
||||
};
|
||||
|
||||
let token = self.store_answer(captcha_answer).await?;
|
||||
Ok(Some((token, captcha_image)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> CaptchaGenerator for T where T: CaptchaStorage {}
|
27
src/captcha_gen/mod.rs
Normal file
27
src/captcha_gen/mod.rs
Normal file
|
@ -0,0 +1,27 @@
|
|||
// Copyright (c) 2024, Awiteb <a@4rs.nl>
|
||||
// A captcha middleware for Salvo framework.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#[cfg(feature = "simple_generator")]
|
||||
mod simple_generator;
|
||||
|
||||
#[cfg(feature = "simple_generator")]
|
||||
pub use simple_generator::*;
|
||||
|
||||
/// Captcha generator, used to generate a new captcha image and answer.
|
||||
pub trait CaptchaGenerator: Send {
|
||||
/// The error type of the captcha generator
|
||||
type Error: std::error::Error;
|
||||
|
||||
/// Create a new captcha image and return the answer and the image encoded as png
|
||||
fn new_captcha(
|
||||
&self,
|
||||
) -> impl std::future::Future<Output = Result<(String, Vec<u8>), Self::Error>> + Send;
|
||||
}
|
107
src/captcha_gen/simple_generator.rs
Normal file
107
src/captcha_gen/simple_generator.rs
Normal file
|
@ -0,0 +1,107 @@
|
|||
// Copyright (c) 2024, Awiteb <a@4rs.nl>
|
||||
// A captcha middleware for Salvo framework.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
use crate::CaptchaGenerator;
|
||||
|
||||
use std::fmt::Display;
|
||||
|
||||
/// Supported captcha names
|
||||
///
|
||||
/// See [`README.md`](https://git.4rs.nl/awiteb/salvo-captcha/#captcha-name-and-difficulty) for more information.
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub enum CaptchaName {
|
||||
/// Plain text, without any distortion
|
||||
Normal,
|
||||
/// Slightly twisted text
|
||||
SlightlyTwisted,
|
||||
/// Very twisted text
|
||||
VeryTwisted,
|
||||
}
|
||||
|
||||
/// Supported captcha difficulties
|
||||
///
|
||||
/// See [`README.md`](https://git.4rs.nl/awiteb/salvo-captcha/#captcha-name-and-difficulty) for more information.
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub enum CaptchaDifficulty {
|
||||
/// Easy to read text
|
||||
Easy,
|
||||
/// Medium difficulty text
|
||||
Medium,
|
||||
/// Hard to read text
|
||||
Hard,
|
||||
}
|
||||
|
||||
impl From<CaptchaName> for captcha::CaptchaName {
|
||||
/// Function to convert the [`CaptchaName`] to the [`captcha::CaptchaName`]
|
||||
fn from(value: CaptchaName) -> Self {
|
||||
match value {
|
||||
CaptchaName::Normal => Self::Lucy,
|
||||
CaptchaName::SlightlyTwisted => Self::Amelia,
|
||||
CaptchaName::VeryTwisted => Self::Mila,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<CaptchaDifficulty> for captcha::Difficulty {
|
||||
/// Function to convert the [`CaptchaDifficulty`] to the [`captcha::Difficulty`]
|
||||
fn from(value: CaptchaDifficulty) -> captcha::Difficulty {
|
||||
match value {
|
||||
CaptchaDifficulty::Easy => Self::Easy,
|
||||
CaptchaDifficulty::Medium => Self::Medium,
|
||||
CaptchaDifficulty::Hard => Self::Hard,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
/// Error type for the [`SimpleGenerator`]
|
||||
pub enum SimpleGeneratorError {
|
||||
/// Failed to encode the captcha to png image
|
||||
FaildEncodedToPng,
|
||||
}
|
||||
|
||||
impl Display for SimpleGeneratorError {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "Faild to encode the captcha to png image")
|
||||
}
|
||||
}
|
||||
|
||||
impl std::error::Error for SimpleGeneratorError {}
|
||||
|
||||
/// The simple captcha generator
|
||||
pub struct SimpleGenerator {
|
||||
name: CaptchaName,
|
||||
difficulty: CaptchaDifficulty,
|
||||
}
|
||||
|
||||
impl SimpleGenerator {
|
||||
/// Create new [`SimpleGenerator`] instance
|
||||
pub const fn new(name: CaptchaName, difficulty: CaptchaDifficulty) -> Self {
|
||||
Self { name, difficulty }
|
||||
}
|
||||
}
|
||||
|
||||
impl CaptchaGenerator for SimpleGenerator {
|
||||
type Error = SimpleGeneratorError;
|
||||
|
||||
/// The returned captcha image is 220x110 pixels in png format.
|
||||
///
|
||||
/// For more information about the captcha name and difficulty, see the [`README.md`](https://git.4rs.nl/awiteb/salvo-captcha/#captcha-name-and-difficulty).
|
||||
async fn new_captcha(&self) -> Result<(String, Vec<u8>), Self::Error> {
|
||||
let Some((captcha_answer, captcha_image)) =
|
||||
captcha::by_name(self.difficulty.into(), self.name.into()).as_tuple()
|
||||
else {
|
||||
return Err(SimpleGeneratorError::FaildEncodedToPng);
|
||||
};
|
||||
|
||||
Ok((captcha_answer, captcha_image))
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue