__( 'Aslansheed Login sign-in data', 'aslansheed-login' ), 'callback' => array( __CLASS__, 'export' ), ); return $exporters; } /** * Adds the eraser. * * @param array $erasers Registered erasers. * @return array */ public static function add_eraser( $erasers ) { $erasers['aslansheed-otp'] = array( 'eraser_friendly_name' => __( 'Aslansheed Login sign-in data', 'aslansheed-login' ), 'callback' => array( __CLASS__, 'erase' ), ); return $erasers; } /** * Exports the linked identities and sign-in events of a user. * * @param string $email Email address of the user. * @return array{data: array, done: bool} */ public static function export( $email ) { global $wpdb; $user = get_user_by( 'email', $email ); $data = array(); if ( ! $user ) { return array( 'data' => $data, 'done' => true, ); } foreach ( Identity_Store::all_for_user( (int) $user->ID ) as $identity ) { $data[] = array( 'group_id' => 'aslansheed-otp-identities', 'group_label' => __( 'Linked sign-in identities', 'aslansheed-login' ), 'item_id' => 'aslansheed-otp-identity-' . (int) $identity->id, 'data' => array( array( 'name' => __( 'Type', 'aslansheed-login' ), 'value' => (string) $identity->type, ), array( 'name' => __( 'Identifier', 'aslansheed-login' ), 'value' => (string) $identity->identifier, ), array( 'name' => __( 'Verified at (UTC)', 'aslansheed-login' ), 'value' => (string) $identity->verified_at, ), ), ); } $profile = array(); $labels = array( 'national' => __( 'National ID', 'aslansheed-login' ), 'postal' => __( 'Postal code', 'aslansheed-login' ), 'birth' => __( 'Birth date', 'aslansheed-login' ), ); $values = array( 'national' => Register_Fields::national_id( (int) $user->ID ), 'postal' => (string) get_user_meta( $user->ID, Register_Fields::META_POSTAL_CODE, true ), 'birth' => (string) get_user_meta( $user->ID, Register_Fields::META_BIRTH_DATE, true ), ); foreach ( Custom_Fields::values( (int) $user->ID ) as $index => $answer ) { $labels[ 'custom_' . $index ] = $answer['label']; $values[ 'custom_' . $index ] = $answer['value']; } $labels['twofa'] = __( 'Two-factor authentication (2FA)', 'aslansheed-login' ); $values['twofa'] = Two_Factor::is_enabled( (int) $user->ID ) ? __( 'On', 'aslansheed-login' ) : ''; foreach ( $values as $key => $value ) { if ( '' !== $value ) { $profile[] = array( 'name' => $labels[ $key ], 'value' => $value, ); } } if ( $profile ) { $data[] = array( 'group_id' => 'aslansheed-otp-profile', 'group_label' => __( 'Registration details', 'aslansheed-login' ), 'item_id' => 'aslansheed-otp-profile-' . (int) $user->ID, 'data' => $profile, ); } $table = Schema::table( 'audit_log' ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching,WordPress.DB.PreparedSQL.InterpolatedNotPrepared,PluginCheck.Security.DirectDB.UnescapedDBParameter -- Custom table; trusted table name. $events = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM {$table} WHERE user_id = %d ORDER BY id DESC LIMIT %d", (int) $user->ID, self::EXPORT_LIMIT ) ); foreach ( (array) $events as $event ) { $data[] = array( 'group_id' => 'aslansheed-otp-events', 'group_label' => __( 'Sign-in events', 'aslansheed-login' ), 'item_id' => 'aslansheed-otp-event-' . (int) $event->id, 'data' => array( array( 'name' => __( 'Event', 'aslansheed-login' ), 'value' => (string) $event->event, ), array( 'name' => __( 'IP address', 'aslansheed-login' ), 'value' => (string) $event->ip, ), array( 'name' => __( 'Time (UTC)', 'aslansheed-login' ), 'value' => (string) $event->created_at, ), ), ); } return array( 'data' => $data, 'done' => true, ); } /** * Erases the identities of a user and anonymizes their audit entries. * * @param string $email Email address of the user. * @return array{items_removed: int, items_retained: bool, messages: array, done: bool} */ public static function erase( $email ) { global $wpdb; $result = array( 'items_removed' => 0, 'items_retained' => false, 'messages' => array(), 'done' => true, ); $user = get_user_by( 'email', $email ); if ( ! $user ) { return $result; } $result['items_removed'] += count( Identity_Store::all_for_user( (int) $user->ID ) ); Identity_Store::delete_for_user( (int) $user->ID ); foreach ( array( Register_Fields::META_NATIONAL_ID, Register_Fields::META_NATIONAL_ID_INDEX, Register_Fields::META_POSTAL_CODE, Register_Fields::META_BIRTH_DATE, Two_Factor::META_SECRET, Two_Factor::META_ENABLED, Two_Factor::META_LAST_STEP, Two_Factor::META_RECOVERY, Two_Factor::META_SKIPPED ) as $meta_key ) { if ( metadata_exists( 'user', (int) $user->ID, $meta_key ) ) { delete_user_meta( (int) $user->ID, $meta_key ); ++$result['items_removed']; } } // Answers stored under the plugin's own prefix go; keys the owner chose, such as billing fields, belong to other plugins' erasers. foreach ( Custom_Fields::stored_keys( (int) $user->ID ) as $meta_key ) { if ( metadata_exists( 'user', (int) $user->ID, $meta_key ) ) { delete_user_meta( (int) $user->ID, $meta_key ); ++$result['items_removed']; } } $table = Schema::table( 'audit_log' ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching,WordPress.DB.PreparedSQL.InterpolatedNotPrepared,PluginCheck.Security.DirectDB.UnescapedDBParameter -- Custom table; trusted table name. $changed = $wpdb->query( $wpdb->prepare( "UPDATE {$table} SET user_id = 0, identifier = '', ip = '', user_agent = '' WHERE user_id = %d", (int) $user->ID ) ); $result['items_removed'] += (int) $changed; return $result; } /** * Suggests text for the site's privacy policy. * * @return void */ public static function add_policy_text() { if ( ! function_exists( 'wp_add_privacy_policy_content' ) ) { return; } wp_add_privacy_policy_content( 'Aslansheed Login', wp_kses_post( '

' . __( 'Suggested text for sites that use Aslansheed Login. Adjust it to the channels you enabled.', 'aslansheed-login' ) . '

' . '

' . __( 'When you sign in or register with your phone number or email, we store that identifier so we can recognise you. We send you a one-time code through the delivery service we use (for example an SMS provider, WhatsApp, Telegram or email), which receives your phone number or email address and the code. We keep a security log with the time, IP address and browser of sign-in events to protect your account. If you use Google sign-in, Google tells us your name and verified email address.', 'aslansheed-login' ) . '

' ) ); } }