collab: Restrict usage of the LLM service to accounts older than 30 days (#16133)

This PR restricts usage of the LLM service to accounts older than 30
days.

We now store the GitHub user's `created_at` timestamp to check the
GitHub account age. If this is not set—which it won't be for existing
users—then we use the `created_at` timestamp in the Zed database.

Release Notes:

- N/A

---------

Co-authored-by: Max <max@zed.dev>
This commit is contained in:
Marshall Bowers 2024-08-12 17:27:21 -04:00 committed by GitHub
parent f398ecc3fb
commit 98516b5527
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
12 changed files with 64 additions and 9 deletions

View file

@ -65,6 +65,7 @@ impl Database {
github_login: &str,
github_user_id: Option<i32>,
github_email: Option<&str>,
github_user_created_at: Option<DateTimeUtc>,
initial_channel_id: Option<ChannelId>,
) -> Result<()> {
self.transaction(|tx| async move {
@ -73,6 +74,7 @@ impl Database {
github_login,
github_user_id,
github_email,
github_user_created_at.map(|time| time.naive_utc()),
initial_channel_id,
&tx,
)

View file

@ -1,3 +1,5 @@
use chrono::NaiveDateTime;
use super::*;
impl Database {
@ -99,6 +101,7 @@ impl Database {
github_login: &str,
github_user_id: Option<i32>,
github_email: Option<&str>,
github_user_created_at: Option<DateTimeUtc>,
initial_channel_id: Option<ChannelId>,
) -> Result<User> {
self.transaction(|tx| async move {
@ -106,6 +109,7 @@ impl Database {
github_login,
github_user_id,
github_email,
github_user_created_at.map(|created_at| created_at.naive_utc()),
initial_channel_id,
&tx,
)
@ -119,6 +123,7 @@ impl Database {
github_login: &str,
github_user_id: Option<i32>,
github_email: Option<&str>,
github_user_created_at: Option<NaiveDateTime>,
initial_channel_id: Option<ChannelId>,
tx: &DatabaseTransaction,
) -> Result<User> {
@ -130,6 +135,10 @@ impl Database {
{
let mut user_by_github_user_id = user_by_github_user_id.into_active_model();
user_by_github_user_id.github_login = ActiveValue::set(github_login.into());
if github_user_created_at.is_some() {
user_by_github_user_id.github_user_created_at =
ActiveValue::set(github_user_created_at);
}
Ok(user_by_github_user_id.update(tx).await?)
} else if let Some(user_by_github_login) = user::Entity::find()
.filter(user::Column::GithubLogin.eq(github_login))
@ -138,12 +147,17 @@ impl Database {
{
let mut user_by_github_login = user_by_github_login.into_active_model();
user_by_github_login.github_user_id = ActiveValue::set(Some(github_user_id));
if github_user_created_at.is_some() {
user_by_github_login.github_user_created_at =
ActiveValue::set(github_user_created_at);
}
Ok(user_by_github_login.update(tx).await?)
} else {
let user = user::Entity::insert(user::ActiveModel {
email_address: ActiveValue::set(github_email.map(|email| email.into())),
github_login: ActiveValue::set(github_login.into()),
github_user_id: ActiveValue::set(Some(github_user_id)),
github_user_created_at: ActiveValue::set(github_user_created_at),
admin: ActiveValue::set(false),
invite_count: ActiveValue::set(0),
invite_code: ActiveValue::set(None),

View file

@ -1,4 +1,5 @@
use crate::db::UserId;
use chrono::NaiveDateTime;
use sea_orm::entity::prelude::*;
use serde::Serialize;
@ -10,6 +11,7 @@ pub struct Model {
pub id: UserId,
pub github_login: String,
pub github_user_id: Option<i32>,
pub github_user_created_at: Option<NaiveDateTime>,
pub email_address: Option<String>,
pub admin: bool,
pub invite_code: Option<String>,
@ -17,8 +19,8 @@ pub struct Model {
pub inviter_id: Option<UserId>,
pub connected_once: bool,
pub metrics_id: Uuid,
pub created_at: DateTime,
pub accepted_tos_at: Option<DateTime>,
pub created_at: NaiveDateTime,
pub accepted_tos_at: Option<NaiveDateTime>,
}
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]

View file

@ -1,3 +1,5 @@
use chrono::Utc;
use super::Database;
use crate::{db::NewUserParams, test_both_dbs};
use std::sync::Arc;
@ -22,7 +24,8 @@ async fn test_contributors(db: &Arc<Database>) {
assert_eq!(db.get_contributors().await.unwrap(), Vec::<String>::new());
db.add_contributor("user1", Some(1), None, None)
let user1_created_at = Utc::now();
db.add_contributor("user1", Some(1), None, Some(user1_created_at), None)
.await
.unwrap();
assert_eq!(
@ -30,7 +33,8 @@ async fn test_contributors(db: &Arc<Database>) {
vec!["user1".to_string()]
);
db.add_contributor("user2", Some(2), None, None)
let user2_created_at = Utc::now();
db.add_contributor("user2", Some(2), None, Some(user2_created_at), None)
.await
.unwrap();
assert_eq!(

View file

@ -1,5 +1,6 @@
use super::*;
use crate::test_both_dbs;
use chrono::Utc;
use pretty_assertions::{assert_eq, assert_ne};
use std::sync::Arc;
@ -100,7 +101,13 @@ async fn test_get_or_create_user_by_github_account(db: &Arc<Database>) {
.user_id;
let user = db
.get_or_create_user_by_github_account("the-new-login2", Some(102), None, None)
.get_or_create_user_by_github_account(
"the-new-login2",
Some(102),
None,
Some(Utc::now()),
None,
)
.await
.unwrap();
assert_eq!(user.id, user_id2);
@ -108,7 +115,13 @@ async fn test_get_or_create_user_by_github_account(db: &Arc<Database>) {
assert_eq!(user.github_user_id, Some(102));
let user = db
.get_or_create_user_by_github_account("login3", Some(103), Some("user3@example.com"), None)
.get_or_create_user_by_github_account(
"login3",
Some(103),
Some("user3@example.com"),
Some(Utc::now()),
None,
)
.await
.unwrap();
assert_eq!(&user.github_login, "login3");