Quay lại danh sách bài viết

Dự án Phần mềm cho khách hàng: 📱 MÀN HÌNH ĐĂNG NHẬP - TÀI LIỆU CHI TIẾT

07 tháng 07, 2025
Admin
Dự án Phần mềm cho khách hàng: 📱 MÀN HÌNH ĐĂNG NHẬP - TÀI LIỆU CHI TIẾT
# 📱 MÀN HÌNH ĐĂNG NHẬP - TÀI LIỆU CHI TIẾT ## **📋 Mục Lục** 1. [Yêu Cầu Business](#yêu-cầu-business) 2. [Triển Khai Kỹ Thuật](#triển-khai-kỹ-thuật) 3. [Thiết Kế Database](#thiết-kế-database) 4. [Trải Nghiệm Người Dùng](#trải-nghiệm-người-dùng) 5. [Triển Khai Bảo Mật](#triển-khai-bảo-mật) 6. [Tài Liệu API](#tài-liệu-api) 7. [Hướng Dẫn Testing](#hướng-dẫn-testing) 8. [Hướng Dẫn Deploy](#hướng-dẫn-deploy) 9. [Khắc Phục Sự Cố](#khắc-phục-sự-cố) 10. [Bảo Trì & Cập Nhật](#bảo-trì--cập-nhật) --- ## **🎯 Yêu Cầu Business** ### **Yêu Cầu Chức Năng** #### **YC-001: Xác Thực Người Dùng** - **Mô tả**: Người dùng phải có thể đăng nhập bằng email và mật khẩu - **Độ ưu tiên**: Quan trọng nhất - **Tiêu chí chấp nhận**: - Người dùng nhập email đúng định dạng - Người dùng nhập mật khẩu (tối thiểu 6 ký tự) - Hệ thống xác thực với Supabase backend - Hệ thống chuyển đến dashboard khi đăng nhập thành công - Hệ thống hiển thị lỗi khi thông tin không đúng #### **YC-002: Tính Năng Ghi Nhớ Đăng Nhập** - **Mô tả**: Người dùng có thể chọn lưu thông tin đăng nhập cho lần sau - **Độ ưu tiên**: Cao - **Tiêu chí chấp nhận**: - Có checkbox "Ghi nhớ đăng nhập" trên form - Khi tick, email và mật khẩu được lưu cục bộ - Khi mở app lại, thông tin đã lưu tự động điền vào form - Người dùng có thể xóa thông tin đã lưu - Tính năng hoạt động offline (lưu trữ cục bộ) #### **YC-003: Kiểm Tra Quyền Admin** - **Mô tả**: Chỉ người dùng có quyền admin mới được truy cập ứng dụng - **Độ ưu tiên**: Quan trọng nhất - **Tiêu chí chấp nhận**: - Hệ thống kiểm tra profile người dùng sau khi xác thực - Chỉ người dùng có role = 'admin' được phép truy cập - Người dùng không phải admin nhận thông báo lỗi phù hợp - Trạng thái admin được xác minh từ bảng profiles trong database #### **YC-004: Kiểm Tra Dữ Liệu Đầu Vào** - **Mô tả**: Tất cả dữ liệu đầu vào phải được kiểm tra trước khi xử lý - **Độ ưu tiên**: Cao - **Tiêu chí chấp nhận**: - Kiểm tra định dạng email (chứa @) - Kiểm tra độ dài mật khẩu (tối thiểu 6 ký tự) - Kiểm tra trường bắt buộc - Phản hồi kiểm tra theo thời gian thực ### **Yêu Cầu Phi Chức Năng** #### **YC-001: Hiệu Suất** - Quá trình đăng nhập hoàn thành trong vòng 3 giây trong điều kiện mạng bình thường - App khởi động và tải thông tin đã lưu trong vòng 1 giây - Animation và chuyển cảnh mượt mà #### **YC-002: Bảo Mật** - Mật khẩu được truyền an toàn (HTTPS) - Lưu trữ cục bộ sử dụng bảo mật theo thiết bị - Không lưu mật khẩu dạng text thô trong logs - Session tokens có thời gian hết hạn phù hợp #### **YC-003: Khả Năng Sử Dụng** - Giao diện trực quan theo nguyên tắc thiết kế React Native - Dễ tiếp cận cho người khuyết tật - Thiết kế responsive cho các kích thước màn hình khác nhau - Thông báo lỗi rõ ràng và phản hồi người dùng #### **YC-004: Độ Tin Cậy** - 99.9% uptime cho dịch vụ xác thực - Xử lý lỗi mạng một cách graceful - Khả năng offline cho thông tin đã lưu --- ## **💻 Triển Khai Kỹ Thuật** ### **Tổng Quan Kiến Trúc** ``` ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ │ LoginScreen │───▶│ AuthContext │───▶│ AuthService │ │ (Tầng UI) │ │ (Quản lý State)│ │ (Tầng API) │ └─────────────────┘ └─────────────────┘ └─────────────────┘ │ │ │ ▼ ▼ ▼ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ │ AsyncStorage │ │ React Context │ │ Supabase API │ │ (Lưu trữ cục bộ)│ │ (Toàn cục) │ │ (Backend) │ └─────────────────┘ └─────────────────┘ └─────────────────┘ ``` ### **Cấu Trúc Component** #### **LoginScreen.js** ```javascript // Component đăng nhập chính const LoginScreen = ({ navigation }) => { // Quản lý state const [email, setEmail] = useState(''); const [password, setPassword] = useState(''); const [rememberMe, setRememberMe] = useState(false); const [showPassword, setShowPassword] = useState(false); const [justLoggedIn, setJustLoggedIn] = useState(false); // Context hooks const { login, isLoading, isAuthenticated } = useAuth(); // Effects useEffect(() => loadSavedLogin(), []); // Tải thông tin đã lưu khi mount // Functions const loadSavedLogin = async () => { /* Triển khai */ }; const saveLogin = async () => { /* Triển khai */ }; const handleLogin = async () => { /* Triển khai */ }; // Render UI }; ``` #### **AuthContext.js** ```javascript // Quản lý state xác thực toàn cục export const AuthProvider = ({ children }) => { const [user, setUser] = useState(null); const [isLoading, setIsLoading] = useState(true); const [isAuthenticated, setIsAuthenticated] = useState(false); const login = async (email, password) => { // Gọi AuthService, cập nhật state, xử lý lỗi }; const logout = async () => { // Xóa auth tokens, reset state }; const checkAuthStatus = async () => { // Xác minh xác thực hiện tại khi khởi động app }; }; ``` #### **AuthService.js** ```javascript // Tầng giao tiếp API class AuthService { async login(email, password) { // Xác thực Supabase // Kiểm tra profile // Lưu trữ token } async getProfile(userId) { // Lấy profile người dùng từ database // Kiểm tra quyền admin } async logout() { // Xóa stored tokens // Giữ thông tin đã lưu nếu "ghi nhớ đăng nhập" được bật } } ``` ### **Luồng Dữ Liệu** 1. **Khởi Động App**: ``` App Start → AuthContext.checkAuthStatus() → AuthService.isAuthenticated() ↓ LoginScreen.loadSavedLogin() → AsyncStorage.getItem() → Tự động điền form ``` 2. **Quá Trình Đăng Nhập**: ``` Input Người Dùng → LoginScreen.handleLogin() → AuthContext.login() ↓ AuthService.login() → Supabase API → Kiểm Tra Profile ↓ Thành Công → saveLogin() → AsyncStorage.setItem() → Chuyển đến Dashboard ``` 3. **Luồng Ghi Nhớ Đăng Nhập**: ``` Đăng Nhập Thành Công → saveLogin() → AsyncStorage.setItem('saved_email', 'saved_password') ↓ Khởi Động Lại App → loadSavedLogin() → AsyncStorage.getItem() → setEmail(), setPassword() ``` ### **Cấu Trúc File** ``` src/ ├── screens/ │ └── LoginScreen.js # Component UI đăng nhập chính ├── contexts/ │ └── AuthContext.js # Quản lý state auth toàn cục ├── services/ │ └── AuthService.js # Giao tiếp API └── components/ └── common/ # Components UI tái sử dụng ``` --- ## **🗄️ Thiết Kế Database** ### **Cấu Hình Supabase** #### **Bảng Authentication (auth.users)** ```sql -- Bảng built-in của Supabase CREATE TABLE auth.users ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), email VARCHAR(255) UNIQUE NOT NULL, encrypted_password VARCHAR(255), email_confirmed_at TIMESTAMPTZ, created_at TIMESTAMPTZ DEFAULT NOW(), updated_at TIMESTAMPTZ DEFAULT NOW() ); ``` #### **Bảng Profiles (public.profiles)** ```sql -- Bảng profile tùy chỉnh CREATE TABLE public.profiles ( id UUID PRIMARY KEY REFERENCES auth.users(id) ON DELETE CASCADE, email VARCHAR(255), role VARCHAR(50) DEFAULT 'user' CHECK (role IN ('admin', 'user', 'moderator')), full_name VARCHAR(255), avatar_url TEXT, phone VARCHAR(20), created_at TIMESTAMPTZ DEFAULT NOW(), updated_at TIMESTAMPTZ DEFAULT NOW() ); -- Indexes để tối ưu hiệu suất CREATE INDEX idx_profiles_email ON public.profiles(email); CREATE INDEX idx_profiles_role ON public.profiles(role); -- Row Level Security (RLS) ALTER TABLE public.profiles ENABLE ROW LEVEL SECURITY; -- RLS Policies CREATE POLICY "Người dùng có thể đọc profile của mình" ON public.profiles FOR SELECT TO authenticated USING (auth.uid() = id); CREATE POLICY "Admin có thể đọc tất cả profiles" ON public.profiles FOR SELECT TO authenticated USING ( EXISTS ( SELECT 1 FROM public.profiles WHERE id = auth.uid() AND role = 'admin' ) ); ``` ### **Hướng Dẫn Setup Database** #### **Bước 1: Tạo Admin User** ```sql -- Tạo user trong Supabase Auth Dashboard -- Email: admin@company.com -- Password: SecurePassword123 -- Email Confirmed: ✓ -- Sau đó tạo profile INSERT INTO public.profiles (id, email, role, full_name) VALUES ( '[USER_ID_TỪ_AUTH_USERS]', 'admin@company.com', 'admin', 'Quản Trị Viên Hệ Thống' ); ``` #### **Bước 2: Setup RLS Policies** ```sql -- Cho phép admin quản lý tất cả profiles CREATE POLICY "Admin có thể quản lý profiles" ON public.profiles FOR ALL TO authenticated USING ( EXISTS ( SELECT 1 FROM public.profiles WHERE id = auth.uid() AND role = 'admin' ) ); ``` #### **Bước 3: Tạo Functions (Tùy chọn)** ```sql -- Function tự động tạo profile khi user đăng ký CREATE OR REPLACE FUNCTION public.handle_new_user() RETURNS TRIGGER AS $$ BEGIN INSERT INTO public.profiles (id, email, role, full_name) VALUES (NEW.id, NEW.email, 'user', ''); RETURN NEW; END; $$ LANGUAGE plpgsql SECURITY DEFINER; -- Trigger để thực thi function CREATE TRIGGER on_auth_user_created AFTER INSERT ON auth.users FOR EACH ROW EXECUTE FUNCTION public.handle_new_user(); ``` ### **Mối Quan Hệ Dữ Liệu** ``` auth.users (1) ←──── (1) public.profiles │ │ │ ├── role (admin/user) │ ├── full_name │ ├── avatar_url │ └── phone │ └── Dùng cho xác thực ``` --- ## **🎨 Trải Nghiệm Người Dùng** ### **Đặc Tả UI/UX** #### **Thiết Kế Hình Ảnh** - **Bảng Màu**: - Chính: `#1e3a8a` (Xanh Dương) - Thành Công: `#16a34a` (Xanh Lá) - Lỗi: `#dc2626` (Đỏ) - Nền: `#f5f5f5` (Xám Nhạt) - Text: `#333333` (Xám Đậm) - **Typography**: - Tiêu đề: 28px, Đậm - Nhãn: 16px, Bán đậm - Input: 16px, Thường - Nút: 18px, Đậm - **Khoảng Cách**: - Padding container: 20px - Margin elements: 20px - Chiều cao nút: 50px - Chiều cao input: 48px #### **Cấu Trúc Layout** ``` ┌─────────────────────────────────┐ │ Logo (⚽) │ │ Admin Đặt Sân │ │ Hệ thống quản lý sân bóng │ ├─────────────────────────────────┤ │ ┌─────────────────────────────┐ │ │ │ Nhập Email │ │ │ │ ┌─────────────────────────┐ │ │ │ │ │ thanhdt9279@gmail.com │ │ │ │ │ └─────────────────────────┘ │ │ │ └─────────────────────────────┘ │ │ ┌─────────────────────────────┐ │ │ │ Nhập Mật Khẩu │ │ │ │ ┌─────────────────────┬─┐ │ │ │ │ │ **************** │👁│ │ │ │ │ └─────────────────────┴─┘ │ │ │ └─────────────────────────────┘ │ │ ┌─────────────────────────────┐ │ │ │ ☑ Ghi nhớ đăng nhập │ │ │ └─────────────────────────────┘ │ │ ┌─────────────────────────────┐ │ │ │ ĐĂNG NHẬP │ │ │ └─────────────────────────────┘ │ └─────────────────────────────────┘ ``` #### **Hành Trình Người Dùng** 1. **Khởi Động App**: - Người dùng mở app - Màn hình loading (1-2 giây) - Màn hình đăng nhập xuất hiện - Thông tin đã lưu tự động điền (nếu có) 2. **Đăng Nhập Lần Đầu**: - Người dùng thấy form trống - Người dùng nhập email và mật khẩu - Người dùng có thể tick "Ghi nhớ đăng nhập" - Người dùng nhấn "Đăng nhập" - Hiển thị loading indicator - Thành công → Chuyển đến dashboard - Lỗi → Hiển thị thông báo lỗi 3. **Người Dùng Quay Lại (với Ghi Nhớ Đăng Nhập)**: - Người dùng mở app - Email và mật khẩu tự động điền - Checkbox "Ghi nhớ đăng nhập" đã được tick - Người dùng có thể ngay lập tức nhấn "Đăng nhập" - Hoặc chỉnh sửa thông tin nếu cần 4. **Các Tình Huống Lỗi**: - Email sai định dạng → Viền đỏ, text lỗi - Trường trống → Alert dialog - Lỗi mạng → Tùy chọn thử lại - Sai thông tin đăng nhập → Xóa trường mật khẩu - Người dùng không phải admin → Thông báo lỗi cụ thể #### **Tính Năng Accessibility** - **Hỗ Trợ Screen Reader**: ```javascript <TextInput accessibilityLabel="Nhập địa chỉ email" accessibilityHint="Email để đăng nhập vào hệ thống" placeholder="Nhập email" /> ``` - **Điều Hướng Bàn Phím**: - Thứ tự tab: Email → Mật khẩu → Ghi nhớ đăng nhập → Đăng nhập - Phím Return: Chuyển trường tiếp theo - Submit ở trường cuối - **Hỗ Trợ High Contrast**: - Tỷ lệ tương phản màu đủ - Indicator focus rõ ràng - Touch targets lớn (tối thiểu 44px) --- ## **🔒 Triển Khai Bảo Mật** ### **Bảo Mật Xác Thực** #### **Yêu Cầu Mật Khẩu** - Tối thiểu 6 ký tự (có thể cấu hình) - Không giới hạn độ dài tối đa - Hỗ trợ ký tự đặc biệt - Kiểm tra phân biệt hoa thường #### **Giao Tiếp An Toàn** ```javascript // Tất cả API calls sử dụng HTTPS const API_BASE_URL = 'https://prmdkpesbdtqlysttxka.supabase.co'; // API Key được bao gồm trong headers headers: { 'Content-Type': 'application/json', 'apikey': API_KEY, 'Authorization': `Bearer ${token}` } ``` #### **Quản Lý Token** ```javascript // Lưu trữ token an toàn await AsyncStorage.setItem('authToken', data.access_token); await AsyncStorage.setItem('refreshToken', data.refresh_token); // Xử lý hết hạn token // Tokens tự động hết hạn theo cấu hình Supabase // Refresh tokens được sử dụng để gia hạn tự động ``` ### **Bảo Mật Lưu Trữ Cục Bộ** #### **Triển Khai Ghi Nhớ Đăng Nhập** ```javascript // Lưu trữ cục bộ trên thiết bị (được mã hóa bởi OS) const saveLogin = async () => { if (rememberMe) { await AsyncStorage.setItem('saved_email', email.trim()); await AsyncStorage.setItem('saved_password', password); // Cân nhắc mã hóa await AsyncStorage.setItem('remember_me', 'true'); } }; ``` #### **Những Điều Cần Cân Nhắc Về Bảo Mật** - **Bảo Mật Thiết Bị**: AsyncStorage được mã hóa bởi OS thiết bị - **Riêng Cho App**: Dữ liệu chỉ app này truy cập được - **Không Sync Cloud**: Dữ liệu ở lại trên thiết bị - **Cleanup Khi Gỡ**: Dữ liệu bị xóa khi gỡ app #### **Khuyến Nghị Cho Production** ```javascript // Cho production, cân nhắc mã hóa dữ liệu nhạy cảm import CryptoJS from 'crypto-js'; const encryptPassword = (password) => { return CryptoJS.AES.encrypt(password, deviceId).toString(); }; const decryptPassword = (encryptedPassword) => { const bytes = CryptoJS.AES.decrypt(encryptedPassword, deviceId); return bytes.toString(CryptoJS.enc.Utf8); }; ``` ### **Kiểm Soát Truy Cập Dựa Trên Vai Trò** #### **Kiểm Tra Admin** ```javascript // Kiểm tra phía server const profileResponse = await this.getProfile(data.user.id); if (profileResponse.success && profileResponse.profile.role === 'admin') { // Cho phép truy cập } else { throw new Error('Bạn không có quyền truy cập trang admin'); } ``` #### **Bảo Mật Database** ```sql -- Row Level Security đảm bảo users chỉ truy cập dữ liệu phù hợp ALTER TABLE public.profiles ENABLE ROW LEVEL SECURITY; -- Policy kiểm tra admin CREATE POLICY "Chỉ admin được truy cập" ON sensitive_table FOR ALL TO authenticated USING ( EXISTS ( SELECT 1 FROM public.profiles WHERE id = auth.uid() AND role = 'admin' ) ); ``` --- ## **🔌 Tài Liệu API** ### **Endpoints Xác Thực** #### **Endpoint Đăng Nhập** ```http POST https://prmdkpesbdtqlysttxka.supabase.co/auth/v1/token?grant_type=password Content-Type: application/json apikey: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9... { "email": "admin@company.com", "password": "password123" } ``` **Response (Thành Công - 200)**: ```json { "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", "token_type": "bearer", "expires_in": 3600, "refresh_token": "v1.MjAyNC0wMy0xNVQxMDowMDowMFo...", "user": { "id": "f47ac10b-58cc-4372-a567-0e02b2c3d479", "email": "admin@company.com", "email_confirmed_at": "2024-03-15T10:00:00Z", "created_at": "2024-03-15T10:00:00Z" } } ``` **Response (Lỗi - 400)**: ```json { "error": "invalid_grant", "error_description": "Invalid login credentials" } ``` #### **Endpoint Profile** ```http GET https://prmdkpesbdtqlysttxka.supabase.co/rest/v1/profiles?id=eq.f47ac10b-58cc-4372-a567-0e02b2c3d479&select=* apikey: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9... Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9... ``` **Response (Thành Công - 200)**: ```json [ { "id": "f47ac10b-58cc-4372-a567-0e02b2c3d479", "email": "admin@company.com", "role": "admin", "full_name": "Quản Trị Viên Hệ Thống", "avatar_url": null, "phone": "+84123456789", "created_at": "2024-03-15T10:00:00Z", "updated_at": "2024-03-15T10:00:00Z" } ] ``` ### **Mã Lỗi** | Mã | Mô Tả | Hành Động | |-----|-------|-----------| | 200 | Thành công | Tiếp tục luồng bình thường | | 400 | Thông tin đăng nhập không hợp lệ | Hiển thị lỗi, xóa mật khẩu | | 401 | Không được ủy quyền | Chuyển về đăng nhập | | 403 | Bị cấm (không phải admin) | Hiển thị lỗi quyền | | 404 | Không tìm thấy user | Hiển thị thông báo lỗi | | 500 | Lỗi server | Hiển thị tùy chọn thử lại | | Mạng | Kết nối thất bại | Hiển thị lỗi mạng | ### **Rate Limiting** - **Lần đăng nhập**: 5 lần/phút mỗi IP - **API calls**: 100 requests/phút mỗi user - **Chiến lược retry**: Exponential backoff --- ## **🧪 Hướng Dẫn Testing** ### **Unit Testing** #### **Tests LoginScreen Component** ```javascript // File test: __tests__/LoginScreen.test.js describe('LoginScreen', () => { test('render form đăng nhập đúng', () => { render(<LoginScreen />); expect(screen.getByPlaceholderText('Nhập email')).toBeInTheDocument(); expect(screen.getByPlaceholderText('Nhập mật khẩu')).toBeInTheDocument(); expect(screen.getByText('Ghi nhớ đăng nhập')).toBeInTheDocument(); }); test('kiểm tra định dạng email', async () => { render(<LoginScreen />); const emailInput = screen.getByPlaceholderText('Nhập email'); const loginButton = screen.getByText('Đăng nhập'); fireEvent.changeText(emailInput, 'email-không-hợp-lệ'); fireEvent.press(loginButton); await waitFor(() => { expect(screen.getByText('Email không hợp lệ')).toBeInTheDocument(); }); }); test('lưu đăng nhập khi tick ghi nhớ', async () => { const mockSaveLogin = jest.fn(); render(<LoginScreen />); // Điền form và tick ghi nhớ fireEvent.changeText(screen.getByPlaceholderText('Nhập email'), 'test@test.com'); fireEvent.changeText(screen.getByPlaceholderText('Nhập mật khẩu'), 'password'); fireEvent.press(screen.getByText('Ghi nhớ đăng nhập')); // Mock đăng nhập thành công mockLogin.mockResolvedValue({ success: true }); fireEvent.press(screen.getByText('Đăng nhập')); await waitFor(() => { expect(AsyncStorage.setItem).toHaveBeenCalledWith('saved_email', 'test@test.com'); }); }); }); ``` #### **Tests AuthService** ```javascript // File test: __tests__/AuthService.test.js describe('AuthService', () => { test('đăng nhập với thông tin hợp lệ', async () => { fetch.mockResolvedValueOnce({ status: 200, json: () => Promise.resolve(mockLoginResponse) }); const result = await AuthService.login('test@test.com', 'password'); expect(result.success).toBe(true); expect(result.user.email).toBe('test@test.com'); }); test('đăng nhập với thông tin không hợp lệ', async () => { fetch.mockResolvedValueOnce({ status: 400, json: () => Promise.resolve({ error_description: 'Invalid credentials' }) }); await expect(AuthService.login('sai@test.com', 'sai')) .rejects.toThrow('Invalid credentials'); }); test('kiểm tra quyền admin', async () => { const mockProfile = { success: true, profile: { role: 'user' } }; AuthService.getProfile = jest.fn().mockResolvedValue(mockProfile); await expect(AuthService.login('user@test.com', 'password')) .rejects.toThrow('Bạn không có quyền truy cập trang admin'); }); }); ``` ### **Integration Testing** #### **End-to-End Luồng Đăng Nhập** ```javascript // File test: e2e/LoginFlow.e2e.js describe('Luồng Đăng Nhập', () => { test('luồng đăng nhập hoàn chỉnh với ghi nhớ', async () => { // Khởi động app await device.launchApp(); // Điền form đăng nhập await element(by.id('email-input')).typeText('admin@test.com'); await element(by.id('password-input')).typeText('password123'); await element(by.id('remember-checkbox')).tap(); // Submit đăng nhập await element(by.id('login-button')).tap(); // Xác minh chuyển đến dashboard await waitFor(element(by.id('dashboard-screen'))) .toBeVisible() .withTimeout(5000); // Khởi động lại app await device.reloadReactNative(); // Xác minh tự động điền await expect(element(by.id('email-input'))).toHaveText('admin@test.com'); await expect(element(by.id('remember-checkbox'))).toHaveValue('1'); }); }); ``` ### **Checklist Testing Thủ Công** #### **Testing Chức Năng** - [ ] Đăng nhập với thông tin admin hợp lệ → Thành công - [ ] Đăng nhập với thông tin non-admin hợp lệ → Thông báo lỗi - [ ] Đăng nhập với email sai định dạng → Lỗi validation - [ ] Đăng nhập với trường trống → Lỗi trường bắt buộc - [ ] Đăng nhập với mật khẩu sai → Lỗi xác thực - [ ] Tick ghi nhớ đăng nhập → Thông tin được lưu - [ ] Không tick ghi nhớ → Thông tin không lưu - [ ] Tự động điền khi khởi động lại app → Thông tin đã lưu được tải - [ ] Xóa thông tin đã lưu → Dữ liệu bị xóa - [ ] Toggle hiển thị mật khẩu → Hiển thị/ẩn mật khẩu - [ ] Đăng xuất → Quay về màn hình đăng nhập #### **Testing UI/UX** - [ ] Responsive design trên các kích thước màn hình khác nhau - [ ] Animation và chuyển cảnh mượt mà - [ ] Loading indicators trong lúc gọi API - [ ] Thông báo lỗi rõ ràng và hữu ích - [ ] Phản hồi validation form ngay lập tức - [ ] Touch targets có kích thước phù hợp - [ ] Tính năng accessibility hoạt động đúng #### **Testing Hiệu Suất** - [ ] App khởi động trong vòng 2 giây - [ ] Đăng nhập hoàn thành trong vòng 3 giây - [ ] Cuộn và tương tác mượt mà - [ ] Sử dụng memory trong giới hạn chấp nhận được - [ ] Tối ưu hóa sử dụng pin #### **Testing Bảo Mật** - [ ] Mật khẩu không hiển thị trong logs - [ ] Giao tiếp HTTPS an toàn - [ ] Lưu trữ token an toàn - [ ] Session timeout hoạt động đúng - [ ] Bảo vệ SQL injection - [ ] Bảo vệ XSS ### **Dữ Liệu Test** #### **Tài Khoản Test Hợp Lệ** ```javascript const testAccounts = { admin: { email: 'admin@test.com', password: 'admin123', role: 'admin', expectedResult: 'thành công' }, user: { email: 'user@test.com', password: 'user123', role: 'user', expectedResult: 'từ chối quyền' }, invalid: { email: 'invalid@test.com', password: 'sai', role: null, expectedResult: 'xác thực thất bại' } }; ``` #### **Edge Cases** ```javascript const edgeCases = [ { email: '', password: '', expected: 'lỗi trường bắt buộc' }, { email: 'email-không-hợp-lệ', password: '123', expected: 'lỗi định dạng' }, { email: 'test@test.com', password: '', expected: 'lỗi trường bắt buộc' }, { email: 'email.rất.dài.vượt.quá.độ.dài.bình.thường@test.com', password: '123456', expected: 'thành công hoặc lỗi validation' }, { email: 'test@test.com', password: 'mật_khẩu_rất_dài_có_thể_gây_vấn_đề_với_một_số_hệ_thống', expected: 'thành công' } ]; ``` --- ## **🚀 Hướng Dẫn Deploy** ### **Setup Môi Trường** #### **Môi Trường Development** ```bash # Cài đặt dependencies npm install # Setup iOS cd ios && pod install && cd .. # Setup Android # Đảm bảo Android SDK và emulator đã được cài đặt # Khởi động Metro bundler npm start # Chạy trên iOS npm run ios # Chạy trên Android npm run android ``` #### **Môi Trường Staging** ```javascript // config/staging.js export const config = { API_BASE_URL: 'https://staging-api.company.com', API_KEY: 'staging_api_key_here', ENVIRONMENT: 'staging', DEBUG_MODE: true }; ``` #### **Môi Trường Production** ```javascript // config/production.js export const config = { API_BASE_URL: 'https://api.company.com', API_KEY: 'production_api_key_here', ENVIRONMENT: 'production', DEBUG_MODE: false }; ``` ### **Cấu Hình Build** #### **iOS Build** ```bash # Debug build npx react-native run-ios --configuration Debug # Release build npx react-native run-ios --configuration Release # Archive cho App Store # Sử dụng Xcode → Product → Archive ``` #### **Android Build** ```bash # Debug build npx react-native run-android --variant=debug # Release build cd android ./gradlew assembleRelease # Signed APK ./gradlew bundleRelease ``` ### **Environment Variables** ```javascript // .env.development API_BASE_URL=https://dev-api.company.com API_KEY=dev_api_key DEBUG_MODE=true // .env.production API_BASE_URL=https://api.company.com API_KEY=prod_api_key DEBUG_MODE=false ``` ### **Code Signing** #### **iOS Code Signing** ```xml <!-- ios/AdminDatSanSimple/Info.plist --> <key>CFBundleIdentifier</key> <string>com.company.admindatsan</string> <key>CFBundleVersion</key> <string>1.0.0</string> ``` #### **Android Code Signing** ```gradle // android/app/build.gradle android { signingConfigs { release { storeFile file('release.keystore') storePassword 'store_password' keyAlias 'key_alias' keyPassword 'key_password' } } buildTypes { release { signingConfig signingConfigs.release minifyEnabled true proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } } ``` ### **Checklist Deploy** #### **Trước Deploy** - [ ] Tất cả tests đều pass - [ ] Code review hoàn thành - [ ] Security audit hoàn thành - [ ] Performance testing hoàn thành - [ ] Database migrations sẵn sàng - [ ] Environment variables đã cấu hình - [ ] API keys đã cập nhật - [ ] Build configuration đã xác minh #### **Các Bước Deploy** 1. **Tạo Build** - Tạo signed builds cho cả hai platform - Xác minh tính toàn vẹn build - Test cài đặt trên thiết bị sạch 2. **Submit Store** - iOS: Submit lên App Store Connect - Android: Upload lên Google Play Console - Bao gồm mô tả app và screenshots 3. **Cập Nhật Backend** - Deploy các thay đổi API cần thiết - Cập nhật database schema nếu cần - Xác minh API endpoints có thể truy cập 4. **Setup Monitoring** - Cấu hình crash reporting - Setup analytics tracking - Monitor API performance #### **Sau Deploy** - [ ] Xác minh cài đặt app từ stores - [ ] Test các user flows quan trọng - [ ] Monitor crash reports - [ ] Kiểm tra metrics hiệu suất API - [ ] Thu thập feedback người dùng --- ## **🔧 Khắc Phục Sự Cố** ### **Các Vấn Đề Thường Gặp** #### **Vấn Đề Đăng Nhập** **Vấn đề**: Lỗi "Email không hợp lệ" - **Nguyên nhân**: Email validation thất bại - **Giải pháp**: Đảm bảo email chứa ký tự @ và đúng định dạng - **Kiểm tra code**: ```javascript if (!email.includes('@')) { Alert.alert('Lỗi', 'Email không hợp lệ'); } ``` **Vấn đề**: Lỗi "Đăng nhập thất bại" - **Nguyên nhân**: Thông tin đăng nhập không đúng hoặc vấn đề mạng - **Giải pháp**: 1. Xác minh thông tin trong Supabase dashboard 2. Kiểm tra kết nối mạng 3. Xác minh API endpoints có thể truy cập - **Debug**: Kiểm tra network tab cho API response **Vấn đề**: "Bạn không có quyền truy cập trang admin" - **Nguyên nhân**: User role không phải 'admin' - **Giải pháp**: Cập nhật user role trong bảng profiles - **SQL**: ```sql UPDATE profiles SET role = 'admin' WHERE email = 'user@example.com'; ``` #### **Vấn Đề Ghi Nhớ Đăng Nhập** **Vấn đề**: Thông tin không được lưu - **Nguyên nhân**: AsyncStorage permission hoặc chưa tick ghi nhớ - **Giải pháp**: 1. Xác minh checkbox ghi nhớ đã được tick 2. Kiểm tra AsyncStorage permissions 3. Test trên thiết bị thật (không phải simulator) - **Debug**: Sử dụng debug buttons để kiểm tra storage **Vấn đề**: Thông tin không load khi khởi động lại app - **Nguyên nhân**: AsyncStorage data không tồn tại - **Giải pháp**: 1. Kiểm tra device storage permissions 2. Xác minh app không bị force-close bởi hệ thống 3. Test function loadSavedLogin - **Debug**: Kiểm tra console logs cho loading errors #### **Vấn Đề Hiệu Suất** **Vấn đề**: Đăng nhập chậm - **Nguyên nhân**: Network latency hoặc hiệu suất API - **Giải pháp**: 1. Kiểm tra tốc độ mạng 2. Monitor thời gian phản hồi API 3. Implement request timeout - **Monitoring**: Thêm performance logging **Vấn đề**: App crash khi đăng nhập - **Nguyên nhân**: Vấn đề memory hoặc unhandled exceptions - **Giải pháp**: 1. Kiểm tra crash logs 2. Test trên các thiết bị khác nhau 3. Review error handling code - **Debug**: Sử dụng crash reporting tools ### **Debug Tools** #### **Console Logging** ```javascript // Bật detailed logging console.log('🔍 Đang tải thông tin đã lưu...'); console.log('📖 Tìm thấy dữ liệu đã lưu:', { savedEmail, savedPassword, remember }); console.log('✅ Login API thành công'); console.log('💾 Đang lưu thông tin đăng nhập... rememberMe:', rememberMe); ``` #### **Network Debugging** ```javascript // Thêm request/response logging const response = await fetch(url, options); console.log('API Request:', { url, options }); console.log('API Response:', { status: response.status, data: await response.json() }); ``` #### **AsyncStorage Debugging** ```javascript // Kiểm tra tất cả AsyncStorage keys const getAllKeys = async () => { const keys = await AsyncStorage.getAllKeys(); const items = await AsyncStorage.multiGet(keys); console.log('Nội dung AsyncStorage:', items); }; ``` #### **State Debugging** ```javascript // Monitor state changes useEffect(() => { console.log('State thay đổi:', { email, password, rememberMe, isAuthenticated }); }, [email, password, rememberMe, isAuthenticated]); ``` ### **Tham Chiếu Mã Lỗi** | Lỗi | Mã | Mô Tả | Giải Pháp | |-----|-----|-------|-----------| | INVALID_EMAIL | 001 | Email định dạng không hợp lệ | Kiểm tra định dạng email | | EMPTY_FIELDS | 002 | Thiếu trường bắt buộc | Điền tất cả trường bắt buộc | | AUTH_FAILED | 003 | Xác thực thất bại | Kiểm tra thông tin đăng nhập | | NO_ADMIN_ROLE | 004 | User không phải admin | Cập nhật user role | | NETWORK_ERROR | 005 | Vấn đề kết nối mạng | Kiểm tra kết nối internet | | API_ERROR | 006 | Lỗi server | Kiểm tra trạng thái API | | STORAGE_ERROR | 007 | Lỗi AsyncStorage | Kiểm tra permissions app | | UNKNOWN_ERROR | 999 | Lỗi không xác định | Kiểm tra logs và báo cáo | --- ## **📈 Bảo Trì & Cập Nhật** ### **Công Việc Bảo Trì Định Kỳ** #### **Công Việc Hàng Tuần** - [ ] Monitor crash reports và sửa các vấn đề critical - [ ] Review user feedback và support tickets - [ ] Kiểm tra metrics hiệu suất API - [ ] Cập nhật dependencies nếu có security patches #### **Công Việc Hàng Tháng** - [ ] Review và cập nhật user roles theo nhu cầu - [ ] Dọn dẹp các accounts không sử dụng trong database - [ ] Tối ưu hiệu suất dựa trên metrics - [ ] Security audit và review password policy - [ ] Cập nhật documentation với các thay đổi #### **Công Việc Hàng Quý** - [ ] Đánh giá bảo mật toàn diện - [ ] Performance benchmarking - [ ] Phân tích trải nghiệm người dùng - [ ] Cập nhật technology stack - [ ] Testing backup và disaster recovery ### **Quy Trình Cập Nhật** #### **Cập Nhật Nhỏ (Bug Fixes)** 1. **Xác Định Vấn Đề** - Review crash reports - Phân tích user feedback - Ưu tiên theo tác động 2. **Triển Khai Fix** - Tạo fix branch - Implement solution - Thêm unit tests - Code review 3. **Testing** - Unit testing - Integration testing - Manual testing trên nhiều thiết bị - Regression testing 4. **Deployment** - Deploy lên staging - User acceptance testing - Deploy lên production - Monitor các vấn đề #### **Cập Nhật Lớn (Thêm Tính Năng)** 1. **Giai Đoạn Planning** - Thu thập requirements - Thiết kế kỹ thuật - Impact assessment - Lập kế hoạch timeline 2. **Giai Đoạn Development** - Feature implementation - Comprehensive testing - Cập nhật documentation - Security review 3. **Giai Đoạn Release** - Staged rollout - Monitor key metrics - Thu thập user feedback - Post-release support ### **Quản Lý Version** #### **Semantic Versioning** - **MAJOR.MINOR.PATCH** (ví dụ: 1.2.3) - **MAJOR**: Breaking changes - **MINOR**: Tính năng mới (backward compatible) - **PATCH**: Bug fixes (backward compatible) #### **Template Release Notes** ```markdown # Phiên bản 1.2.3 - 15/03/2024 ## 🆕 Tính Năng Mới - Thêm tùy chọn xác thực sinh trắc học - Cải thiện validation độ mạnh mật khẩu ## 🐛 Bug Fixes - Sửa lỗi ghi nhớ đăng nhập không hoạt động trên iOS - Giải quyết vấn đề timeout đăng nhập ## 🔧 Cải Thiện - Nâng cao thông báo lỗi - Tối ưu thời gian khởi động app ## 🔒 Bảo Mật - Cập nhật thuật toán mã hóa - Nâng cao quản lý session ## 🛠️ Kỹ Thuật - Nâng cấp lên React Native 0.72 - Cập nhật Supabase client library ``` ### **Monitoring & Analytics** #### **Metrics Quan Trọng Cần Theo Dõi** - **User Metrics**: - Daily/Monthly active users - Tỷ lệ đăng nhập thành công - Tỷ lệ giữ chân người dùng - Thống kê sử dụng tính năng - **Performance Metrics**: - Thời gian khởi động app - Thời gian hoàn thành đăng nhập - Thời gian phản hồi API - Tỷ lệ crash - **Security Metrics**: - Số lần đăng nhập thất bại - Security incidents - Yêu cầu reset password - Patterns truy cập bất thường #### **Hệ Thống Alerting** ```javascript // Ví dụ cấu hình alerting const alerts = { loginFailureRate: { threshold: '> 5%', action: 'thông báo security team' }, apiResponseTime: { threshold: '> 3 giây', action: 'thông báo dev team' }, crashRate: { threshold: '> 1%', action: 'điều tra ngay lập tức' } }; ``` ### **Bảo Trì Documentation** #### **Cần Cập Nhật** - [ ] API documentation với các thay đổi endpoint - [ ] Database schema documentation - [ ] User guides và help documentation - [ ] Technical documentation cho developers - [ ] Security policies và procedures #### **Lịch Review** - **Hàng tháng**: User-facing documentation - **Hàng quý**: Technical documentation - **Hàng năm**: Complete documentation audit --- ## **📞 Thông Tin Hỗ Trợ & Liên Hệ** ### **Team Development** - **Lead Developer**: dev-lead@company.com - **Backend Developer**: backend-dev@company.com - **Mobile Developer**: mobile-dev@company.com - **QA Engineer**: qa@company.com ### **Team Business** - **Product Manager**: pm@company.com - **Business Analyst**: ba@company.com - **Project Manager**: project-mgr@company.com ### **Team Operations** - **DevOps Engineer**: devops@company.com - **Database Administrator**: dba@company.com - **Security Officer**: security@company.com ### **Liên Hệ Khẩn Cấp** - **Vấn Đề Nghiêm Trọng**: emergency@company.com - **Security Incidents**: security-incident@company.com - **Hỗ Trợ Ngoài Giờ**: +84-xxx-xxx-xxxx --- ## **📝 Thông Tin Tài Liệu** - **Phiên Bản Tài Liệu**: 1.0.0 - **Cập Nhật Lần Cuối**: 15 tháng 3, 2024 - **Ngày Review Tiếp Theo**: 15 tháng 6, 2024 - **Được Chuẩn Bị Bởi**: Development Team - **Được Phê Duyệt Bởi**: Technical Lead & Product Manager --- **© 2024 Company Name. Bảo lưu mọi quyền.**
Chia sẻ:

Bài viết liên quan

⚽ Dự Án Đặt Sân Thể Thao – Kiểm Thử API bằng Postman

⚽ Dự Án Đặt Sân Thể Thao – Kiểm Thử API bằng Postman

Học Python & Flutter – Có Dự Án Thực Tập Ngay!

Học Python & Flutter – Có Dự Án Thực Tập Ngay!

Ưu điểm của Agile so với Waterfall

So sánh chi tiết về phương pháp Agile và Waterfall trong quản lý dự án phần mềm