Bạn được giao xây dựng một module đăng ký tài khoản cho một hệ thống SaaS. Yêu cầu bao gồm:
1. Hash
- User nhập mật khẩu plaintext.
- Mật khẩu phải được băm (hash) bằng SHA-256 hoặc bcrypt trước khi lưu DB.
2. Encrypt
- Email của user phải được mã hoá (encrypt) bằng một secret key, để DB không lưu email dạng rõ ràng.
- Khi cần hiển thị email, phải decrypt.
3. Exception
Hệ thống phải ném Exception trong các trường hợp sau:
| Tình huống | Exception |
|---|---|
| Username chứa ký tự đặc biệt | InvalidUsernameException |
| Email không hợp lệ | InvalidEmailException |
| Mật khẩu ít hơn 6 ký tự | WeakPasswordException |
4. Dependency Injection
- Class
RegisterServicekhông được tự tạo thư viện mã hoá / mã hoá / hash - Phải inject chúng thông qua constructor
5. IoC Container
- Tạo một IoC Container tối giản để bind interface -> implementation:
HasherInterface->Sha256HasherEncryptorInterface->OpenSslEncryptor
Sau đó resolve RegisterService qua container.
6. Yêu cầu Code:
Bạn phải hiện thực các interface sau:
interface HasherInterface {
public function hash(string $value): string;
}
interface EncryptorInterface {
public function encrypt(string $value): string;
public function decrypt(string $value): string;
}
RegisterService:
class RegisterService
{
public function __construct(
HasherInterface $hasher,
EncryptorInterface $encryptor,
) {}
public function register(string $username, string $email, string $password): array
{
// TODO: validate & throw exception
// TODO: encrypt email
// TODO: hash password
// TODO: return mảng kết quả
/*
[
'username' => 'Ym9i',
'email' => 'ENCRYPTED_DATA',
'password' => 'HASHED_DATA'
]
*/
}
}
Bạn phải tự viết:
InvalidUsernameExceptionInvalidEmailExceptionWeakPasswordException
IoC Container tối giản:
class Container
{
protected array $bindings = [];
public function bind(string $abstract, string $concrete)
{
$this->bindings[$abstract] = $concrete;
}
public function make(string $abstract)
{
$concrete = $this->bindings[$abstract] ?? $abstract;
return new $concrete();
}
}
Sau khi hoàn tất, chạy code sau phải hoạt động:
$container = new Container();
$container->bind(HasherInterface::class, Sha256Hasher::class);
$container->bind(EncryptorInterface::class, OpenSslEncryptor::class);
$service = new RegisterService(
$container->make(HasherInterface::class),
$container->make(EncryptorInterface::class),
);
$result = $service->register("Bob", "bob@gmail.com", "secret123");
print_r($result);
Rule:
- Không được hardcode new object trong
RegisterService - Exception phải được ném ngay khi phát hiện lỗi (throw early)
- Encrypt email phải decrypt được
- Output phải tuân theo cấu trúc yêu cầu