Repository: TabbyML/tabby
File: ee/tabby-webserver/src/service/background_job/third_party_integration/pulls.rs (Rust)

Code before:
                .pulls(&owner, &repo)
                .list()
                .state(octocrab::params::State::All)
                .page(page)
                .send()
                .await {
                    Ok(x) => x,
                    Err(e) => {
                        logkit::error!("Failed to fetch pull requests: {}", octocrab_error_message(e));
                        break;
                    }
            };

            let pages = response.number_of_pages().unwrap_or_default();

            for pull in response.items {
                let url = pull.html_url.map(|url| url.to_string()).unwrap_or_else(|| pull.url);
                let title = pull.title.clone().unwrap_or_default();
                let body = pull.body.clone().unwrap_or_default();

                let author = pull.user.as_ref().map(|user| user.login.clone()).unwrap_or_default();
                let email = if !author.is_empty() {
                    match octocrab.users(&author).profile().await {
                        Ok(profile) => {
                            profile.email.unwrap_or_default()
                        }
                        Err(e) => {
                            debug!("Failed to fetch user profile for {}: {}", author, e);
                            String::new()
                        }
                    }
                } else {
                    String::new()
                };

                let doc = StructuredDoc {
                    source_id: source_id.to_string(),
                    fields: StructuredDocFields::Pull(StructuredDocPullDocumentFields {
                        link: url.clone(),
                        title,
                        author_email: email.clone(),
                        body,
                        merged: pull.merged_at.is_some(),
                        diff: String::new(),
                    }),
                };

                // skip closed but not merged pulls
                if let Some(state) = pull.state {
                    if state == IssueState::Closed && pull.merged_at.is_none() {
                        yield (StructuredDocState{

Review comment (security):
if email doesn't present, should use None to represent (rather than use `""`).

This essentially make`author_email` as an optional field of `IssueDocument` / `PullDocument`

Code after:
                .pulls(&owner, &repo)
                .list()
                .state(octocrab::params::State::All)
                .page(page)
                .send()
                .await {
                    Ok(x) => x,
                    Err(e) => {
                        logkit::error!("Failed to fetch pull requests: {}", octocrab_error_message(e));
                        break;
                    }
            };

            let pages = response.number_of_pages().unwrap_or_default();

            for pull in response.items {
                let url = pull.html_url.map(|url| url.to_string()).unwrap_or_else(|| pull.url);
                let title = pull.title.clone().unwrap_or_default();
                let body = pull.body.clone().unwrap_or_default();

                let author = pull.user.as_ref().map(|user| user.login.clone());
                let email = if let Some(author) = author {
                    match octocrab.users(&author).profile().await {
                        Ok(profile) => {
                            profile.email
                        }
                        Err(e) => {
                            debug!("Failed to fetch user profile for {}: {}", author, e);
                            None
                        }
                    }
                } else {
                    None
                };

                let doc = StructuredDoc {
                    source_id: source_id.to_string(),
                    fields: StructuredDocFields::Pull(StructuredDocPullDocumentFields {
                        link: url.clone(),
                        title,
                        author_email: email.clone(),
                        body,
                        merged: pull.merged_at.is_some(),
                        diff: String::new(),
                    }),
                };

                // skip closed but not merged pulls
                if let Some(state) = pull.state {
                    if state == IssueState::Closed && pull.merged_at.is_none() {
                        yield (StructuredDocState{