راه
۴ کیو· سختپیشرفتهPYTHON۴ ثانیه · ۲۵۶ مگابایت

بازی پول

هدف این پروژه پیاده‌سازی سیستمی برای مدیریت کاربران یک وب‌سایت است. شما با تعریف دو کلاس اصلی Account برای مدیریت اطلاعات کاربران و Site برای مدیریت سایت و تعاملات کاربران، این سیستم را بنا می‌کنید. تمرکز اصلی بر روی پیاده‌سازی دقیق و ایمن فرایندهای ثبت‌نام، ورود و خروج کاربران، همراه با اعتبارسنجی دقیق و ذخیره‌سازی امن اطلاعات مانند رمز عبور است.


👤 کلاس Account

🔹 init(self, username, password, national_id, phone, email)

هر شیء از کلاس Account باید دارای ویژگی‌های زیر باشد که در متد __init__ مقداردهی اولیه می‌شوند:

  • username: نام کاربری (فرمت firstname_lastname)
  • password: رمز عبور (هش‌شده با SHA256)
  • national_id: کد ملی (۱۰ رقمی معتبر)
  • phone: شماره موبایل (فرمت 09xxxxxxxxx)
  • email: ایمیل (فرمت first@second.tld)

🔹 username_validation(self, username)

نام کاربری باید به فرمت firstname_lastname باشد. نام و نام‌خانوادگی فقط شامل حروف انگلیسی.

خطا: "Invalid username."

🔹 password_validation(self, password)

رمز عبور: حداقل ۸ کاراکتر، شامل حداقل یک حرف بزرگ، یک حرف کوچک و یک عدد. پس از اعتبارسنجی، با SHA256 هش می‌شود.

خطا: "Invalid password."

🔹 id_validation(self, national_id)

کد ملی: ۱۰ رقمی معتبر با الگوریتم کنترل (رقم دهم).

خطا: "Invalid national id."

🔹 phone_validation(self, phone)

شماره موبایل: +989xxxxxxxxx یا 09xxxxxxxxx، ذخیره به فرمت 09xxxxxxxxx.

خطا: "Invalid phone number."

🔹 email_validation(self, email)

ایمیل: فرمت first@second.tld، first و second شامل حروف، اعداد، _، - و .، tld شامل حروف با طول ۲ تا ۵.

خطا: "Invalid email."

🔹 set_new_password(self, new_password)

رمز عبور جدید را با همان قوانین اعتبارسنجی کرده، هش می‌کند و جایگزین رمز فعلی می‌کند.

خطا: "Invalid password."


🌐 کلاس Site

🔹 init(self, url)

  • url: آدرس سایت (تضمین شده)
  • registered_users: لیست کاربران ثبت‌نام‌شده (شروع: [])
  • active_users: لیست کاربران واردشده (شروع: [])

🔹 register(self, user)

کاربر را در registered_users ثبت می‌کند.

خطا: "User already registered."

موفقیت: "Register successful."

🔹 login(self, username=None, email=None, password=None)

کاربر را با ترکیب نام کاربری/ایمیل و رمز عبور وارد می‌کند. حالات معتبر:

  • username + password
  • email + password
  • username + email + password

خطا: "Invalid login."

توجه: "User already logged in."

موفقیت: "Login successful."

🔹 logout(self, user)

کاربر را از active_users خارج می‌کند.

توجه: "User is not logged in."

موفقیت: "Logout successful."


🎨 دکوراتورها

🔹 @show_welcome

روی تابع welcome(user) اعمال می‌شود. نام کاربری را فرمت می‌کند (_ → فاصله، حروف اول بزرگ) و در صورت طول بیشتر از ۱۵، ... اضافه می‌کند.

🔹 @verify_change_password(old_password)

روی تابع change_password(user, old_password, new_password) اعمال می‌شود.

  • رمز قدیمی را هش کرده و با رمز فعلی مقایسه می‌کند
  • در صورت صحیح بودن، رمز جدید را با set_new_password ثبت می‌کند
  • تابع اصلی را برای برگرداندن پیام موفقیت فراخوانی می‌کند

خطا: "Incorrect old password."


✅ پاسخ نهایی

python
import re
import hashlib
from functools import wraps

class Account:
    def __init__(self, username, password, national_id, phone, email):
        self.username = self.username_validation(username)
        self.password = self.password_validation(password)
        self.national_id = self.id_validation(national_id)
        self.phone = self.phone_validation(phone)
        self.email = self.email_validation(email)

    def _hash_password(self, password):
        return hashlib.sha256(password.encode('utf-8')).hexdigest()

    def username_validation(self, username):
        if not re.match(r'^[a-zA-Z]+_[a-zA-Z]+$', username):
            raise ValueError("Invalid username.")
        return username

    def password_validation(self, password):
        if len(password) < 8:
            raise ValueError("Invalid password.")
        if not re.search(r'[A-Z]', password):
            raise ValueError("Invalid password.")
        if not re.search(r'[a-z]', password):
            raise ValueError("Invalid password.")
        if not re.search(r'[0-9]', password):
            raise ValueError("Invalid password.")
        return self._hash_password(password)

    def id_validation(self, national_id):
        if not national_id.isdigit() or len(national_id) != 10:
            raise ValueError("Invalid national id.")

        digits = [int(ch) for ch in national_id]
        total = 0
        for i in range(9):
            total += digits[i] * (10 - i)

        remainder = total % 11
        if remainder < 2:
            control_digit = remainder
        else:
            control_digit = 11 - remainder

        if digits[9] != control_digit:
            raise ValueError("Invalid national id.")
        return national_id

    def phone_validation(self, phone):
        if re.match(r'^09[0-9]{9}$', phone):
            return phone
        if re.match(r'^\+989[0-9]{9}$', phone):
            return '0' + phone[3:]
        raise ValueError("Invalid phone number.")

    def email_validation(self, email):
        if not re.match(r'^[a-zA-Z0-9_.-]+@[a-zA-Z0-9_.-]+\.[a-zA-Z]{2,5}$', email):
            raise ValueError("Invalid email.")
        return email

    def set_new_password(self, new_password):
        self.password = self.password_validation(new_password)


class Site:
    def __init__(self, url):
        self.url = url
        self.registered_users = []
        self.active_users = []

    def register(self, user):
        if user in self.registered_users:
            raise ValueError("User already registered.")
        self.registered_users.append(user)
        return "Register successful."

    def login(self, username=None, email=None, password=None):
        hashed_password = hashlib.sha256(password.encode('utf-8')).hexdigest()

        for user in self.registered_users:
            username_match = True if username is None else user.username == username
            email_match = True if email is None else user.email == email
            password_match = user.password == hashed_password

            if username_match and email_match and password_match:
                if user in self.active_users:
                    return "User already logged in."
                self.active_users.append(user)
                return "Login successful."

        return "Invalid login."

    def logout(self, user):
        if user in self.active_users:
            self.active_users.remove(user)
            return "Logout successful."
        return "User is not logged in."


# دکوراتور @show_welcome
def show_welcome(func):
    def wrapper(user):
        name_parts = user.username.split('_')
        formatted_name = ' '.join([part.capitalize() for part in name_parts])

        if len(formatted_name) > 15:
            formatted_name = formatted_name[:15] + '...'

        return func(formatted_name)
    return wrapper


# دکوراتور @verify_change_password
def verify_change_password(old_password):
    def decorator(func):
        def wrapper(user, old_pass, new_pass):
            hashed_old = hashlib.sha256(old_pass.encode('utf-8')).hexdigest()
            if hashed_old != user.password:
                raise ValueError("Incorrect old password.")

            user.set_new_password(new_pass)
            return func(user, old_pass, new_pass)
        return wrapper
    return decorator

📄 main.py


📖 توضیح کد

  • کلاس Account: همه‌ی اعتبارسنجی‌ها در متدهای جداگانه انجام می‌شوند رمز عبور با hashlib.sha256 هش می‌شود کد ملی با الگوریتم کنترل (رقم دهم) اعتبارسنجی می‌شود شماره موبایل به فرمت 09xxxxxxxxx ذخیره می‌شود
  • کلاس Site: registered_users لیست کاربران ثبت‌نام‌شده active_users لیست کاربران واردشده ورود با نام کاربری یا ایمیل و رمز عبور انجام می‌شود
  • دکوراتور @show_welcome: نام کاربری را فرمت می‌کند (_ → فاصله، حروف اول بزرگ) در صورت طول بیشتر از ۱۵، ... اضافه می‌کند
  • دکوراتور @verify_change_password: رمز قدیمی را هش کرده و با رمز فعلی مقایسه می‌کند در صورت صحیح بودن، رمز جدید را با set_new_password ثبت می‌کند
  • رمزهای عبور هرگز به‌صورت متن ساده ذخیره نمی‌شوند
  • کدهای ملی با 0 شروع می‌شوند (رشته‌ای ذخیره می‌شوند)
  • در متد login، رمز ورودی قبل از مقایسه هش می‌شود

🚀 پس از تکمیل کلاس‌ها و دکوراتورها، می‌توانید سیستم را با کاربران مختلف تست کنید.

نمونه‌ها

ورودی نمونه ۱
import hashlib
a = Account("ali_alavi", "Passw0rd1", "0012345679", "+989121234567", "ali.alavi@example.com")
[a.username, a.national_id, a.phone, a.email]
a.password == hashlib.sha256(b"Passw0rd1").hexdigest()
خروجی نمونه ۱
['ali_alavi', '0012345679', '09121234567', 'ali.alavi@example.com']
True
ورودی نمونه ۲
bad = [
    ("ali-alavi", "Passw0rd1", "0012345679", "09121234567", "a@b.com"),
    ("ali_alavi", "password1", "0012345679", "09121234567", "a@b.com"),
    ("ali_alavi", "Passw0rd1", "0012345678", "09121234567", "a@b.com"),
    ("ali_alavi", "Passw0rd1", "0012345679", "0912123456", "a@b.com"),
    ("ali_alavi", "Passw0rd1", "0012345679", "09121234567", "a@b.c"),
]
for args in bad:
    try:
        Account(*args)
    except Exception as error:
        print(error)
خروجی نمونه ۲
Invalid username.
Invalid password.
Invalid national id.
Invalid phone number.
Invalid email.
ورودی نمونه ۳
site = Site("https://example.com")
ali = Account("ali_alavi", "Passw0rd1", "0012345679", "09121234567", "ali@example.com")
site.register(ali)
try:
    site.register(ali)
except Exception as error:
    print(error)
site.login(username="ali_alavi", password="Passw0rd1")
site.login(email="ali@example.com", password="Passw0rd1")
site.logout(ali)
site.logout(ali)
خروجی نمونه ۳
'Register successful.'
User already registered.
'Login successful.'
'User already logged in.'
'Logout successful.'
'User is not logged in.'
ورودی نمونه ۴
site = Site("https://example.com")
sara = Account("sara_rad", "Secret123", "1111111111", "09351112233", "sara@mail.co")
site.register(sara)
site.login(username="sara_rad", password="wrong")
site.login(username="sara_rad", email="sara@mail.co", password="Secret123")
site.login(username="nobody_here", password="Secret123")
خروجی نمونه ۴
'Register successful.'
'Invalid login.'
'Login successful.'
'Invalid login.'
ورودی نمونه ۵
@show_welcome
def welcome(name):
    return "Welcome " + name

welcome(Account("ali_alavi", "Passw0rd1", "0012345679", "09121234567", "ali@example.com"))
welcome(Account("mohammadreza_alavizadeh", "Passw0rd1", "0000000019", "09121234567", "m@example.com"))
خروجی نمونه ۵
'Welcome Ali Alavi'
'Welcome Mohammadreza Al...'
ورودی نمونه ۶
import hashlib

@verify_change_password("Passw0rd1")
def change_password(user, old_password, new_password):
    return "Password changed."

acc = Account("ali_alavi", "Passw0rd1", "0012345679", "09121234567", "ali@example.com")
change_password(acc, "Passw0rd1", "NewPassw0rd")
acc.password == hashlib.sha256(b"NewPassw0rd").hexdigest()
try:
    change_password(acc, "Passw0rd1", "Another1A")
except Exception as error:
    print(error)
خروجی نمونه ۶
'Password changed.'
True
Incorrect old password.

برای نوشتن پاسخ و دریافت امتیاز، ابتدا وارد حساب شوید.

ورود