Modpanel user index — last sign-in column & masked export
Jira: BIF-8736 · Epic: BIF-8695
Overview
Improve the Modpanel billing users index (https://moderator.qontak.com/billing/users) with a "Last Sign-In" (last login) column and a masked export, so internal admins can audit user activity without exposing full user details (email, name, phone).
Scope Changes
- Backend — last-login data + export generation with field masking.
- Frontend — new column and Export button on the users index.
8. User Stories + Acceptance Criteria
| User Story | Importance | Mockup / Technical Notes | Acceptance Criteria |
|---|---|---|---|
| [USRIDX-S01] — Last sign-in + masked export As an internal admin on the Modpanel billing users page, I want a "Last Sign-In" (last login) column and a masked export, so that I can audit user activity without exposing full user details. | Should Have | Page: /billing/users. Export format: CSV, current-filter only. Masking example: addo.hernando@mekari.com → ****.hernando@mekari.com; phone +6281377427042 → +****377427042. | — Happy Path — • AC-1: Given the users list at /billing/users, when it renders, then a "Last Sign-In" column shows each user's most recent login timestamp (last login, not last activity); show "Never"/empty when there is none. Timezone displayed is GMT+7 (Asia/Jakarta). • AC-2: Given the users page, when the admin clicks Export, then a CSV file is downloaded containing the user list (respecting the current search/filter) with columns in order: company_id, company_name (masked), user_name (masked), email (masked), phone (masked), exists_in (chat/crm/both), last_login_date_jakarta (YYYY-MM-DD, GMT+7), last_login_hour_jakarta (HH:MM:SS, GMT+7).• AC-3: Given a masked field ( company_name, user_name, email, phone), when it is written to the export, then the first 4 characters are replaced with **** and the remainder is preserved. For email, masking applies to the local part only and the full domain is preserved → addo.hernando@mekari.com becomes ****.hernando@mekari.com. For phone, the leading + is preserved then the first 4 digits are replaced → +6281377427042 becomes +****377427042.— Edge — • AC-4: Given a masked value with fewer than 4 characters to mask (e.g. email local part abc@…), when it is written to the export, then the entire value (local part, for email) is masked. |
Open questions — resolved
- Export format — CSV or XLSX? → CSV
- Masking rule → first 4 characters replaced with
****, remainder preserved (email: local part only, domain kept; phone:+kept); values shorter than 4 chars are fully masked. - Timezone used for the Last Sign-In display. → GMT+7 (Asia/Jakarta)
- Does Export respect the current search/filter on the page, or export all users? → Current filter only