Allow to add notes to generated invite codes

This commit is contained in:
silverpill 2023-03-02 17:24:32 +00:00
parent 721238d897
commit 1b1e2a1521
7 changed files with 57 additions and 15 deletions

View file

@ -6,6 +6,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
## [Unreleased] ## [Unreleased]
### Added
- Allow to add notes to generated invite codes.
## [1.15.0] - 2023-02-27 ## [1.15.0] - 2023-02-27
### Added ### Added

View file

@ -20,10 +20,10 @@ Generate RSA private key:
mitractl generate-rsa-key mitractl generate-rsa-key
``` ```
Generate invite code: Generate invite code (note is optional):
```shell ```shell
mitractl generate-invite-code mitractl generate-invite-code <note>
``` ```
List generated invites: List generated invites:

View file

@ -0,0 +1,2 @@
ALTER TABLE user_invite_code ADD COLUMN note VARCHAR(200);
ALTER TABLE user_invite_code ADD COLUMN created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP;

View file

@ -38,7 +38,9 @@ CREATE TABLE actor_profile (
CREATE TABLE user_invite_code ( CREATE TABLE user_invite_code (
code VARCHAR(100) PRIMARY KEY, code VARCHAR(100) PRIMARY KEY,
used BOOLEAN NOT NULL DEFAULT FALSE used BOOLEAN NOT NULL DEFAULT FALSE,
note VARCHAR(200),
created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP
); );
CREATE TABLE user_account ( CREATE TABLE user_account (

View file

@ -117,14 +117,19 @@ impl GenerateEthereumAddress {
/// Generate invite code /// Generate invite code
#[derive(Parser)] #[derive(Parser)]
pub struct GenerateInviteCode; pub struct GenerateInviteCode {
note: Option<String>,
}
impl GenerateInviteCode { impl GenerateInviteCode {
pub async fn execute( pub async fn execute(
&self, &self,
db_client: &impl DatabaseClient, db_client: &impl DatabaseClient,
) -> Result<(), Error> { ) -> Result<(), Error> {
let invite_code = create_invite_code(db_client).await?; let invite_code = create_invite_code(
db_client,
self.note.as_deref(),
).await?;
println!("generated invite code: {}", invite_code); println!("generated invite code: {}", invite_code);
Ok(()) Ok(())
} }
@ -144,8 +149,12 @@ impl ListInviteCodes {
println!("no invite codes found"); println!("no invite codes found");
return Ok(()); return Ok(());
}; };
for code in invite_codes { for invite_code in invite_codes {
println!("{}", code); if let Some(note) = invite_code.note {
println!("{} ({})", invite_code.code, note);
} else {
println!("{}", invite_code.code);
};
}; };
Ok(()) Ok(())
} }

View file

@ -12,36 +12,43 @@ use crate::models::{
profiles::queries::create_profile, profiles::queries::create_profile,
profiles::types::{DbActorProfile, ProfileCreateData}, profiles::types::{DbActorProfile, ProfileCreateData},
}; };
use super::types::{DbUser, Role, User, UserCreateData}; use super::types::{
DbInviteCode,
DbUser,
Role,
User,
UserCreateData,
};
use super::utils::generate_invite_code; use super::utils::generate_invite_code;
pub async fn create_invite_code( pub async fn create_invite_code(
db_client: &impl DatabaseClient, db_client: &impl DatabaseClient,
note: Option<&str>,
) -> Result<String, DatabaseError> { ) -> Result<String, DatabaseError> {
let invite_code = generate_invite_code(); let invite_code = generate_invite_code();
db_client.execute( db_client.execute(
" "
INSERT INTO user_invite_code (code) INSERT INTO user_invite_code (code, note)
VALUES ($1) VALUES ($1, $2)
", ",
&[&invite_code], &[&invite_code, &note],
).await?; ).await?;
Ok(invite_code) Ok(invite_code)
} }
pub async fn get_invite_codes( pub async fn get_invite_codes(
db_client: &impl DatabaseClient, db_client: &impl DatabaseClient,
) -> Result<Vec<String>, DatabaseError> { ) -> Result<Vec<DbInviteCode>, DatabaseError> {
let rows = db_client.query( let rows = db_client.query(
" "
SELECT code SELECT user_invite_code
FROM user_invite_code FROM user_invite_code
WHERE used = FALSE WHERE used = FALSE
", ",
&[], &[],
).await?; ).await?;
let codes: Vec<String> = rows.iter() let codes = rows.iter()
.map(|row| row.try_get("code")) .map(|row| row.try_get("user_invite_code"))
.collect::<Result<_, _>>()?; .collect::<Result<_, _>>()?;
Ok(codes) Ok(codes)
} }
@ -299,6 +306,14 @@ mod tests {
use crate::models::users::types::Role; use crate::models::users::types::Role;
use super::*; use super::*;
#[tokio::test]
#[serial]
async fn test_create_invite_code() {
let db_client = &mut create_test_database().await;
let code = create_invite_code(db_client, Some("test")).await.unwrap();
assert_eq!(code.len(), 32);
}
#[tokio::test] #[tokio::test]
#[serial] #[serial]
async fn test_create_user() { async fn test_create_user() {

View file

@ -13,6 +13,16 @@ use crate::errors::ValidationError;
use crate::identity::did::Did; use crate::identity::did::Did;
use crate::models::profiles::types::DbActorProfile; use crate::models::profiles::types::DbActorProfile;
#[allow(dead_code)]
#[derive(FromSql)]
#[postgres(name = "user_invite_code")]
pub struct DbInviteCode {
pub code: String,
used: bool,
pub note: Option<String>,
created_at: DateTime<Utc>,
}
#[derive(PartialEq)] #[derive(PartialEq)]
pub enum Permission { pub enum Permission {
CreateFollowRequest, CreateFollowRequest,