-
-
Notifications
You must be signed in to change notification settings - Fork 948
feat: add RequireInvitation registration mode for invite-link-style signups #6450
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
0f257da
9a95334
5f6aa9b
3355031
b6280af
2f9b358
746b940
465f05a
b0dfeaf
f8ddd02
c719489
0e4c988
8904b68
c83e93e
9ba0ca6
f0567fb
5efce10
e560db9
7c514d5
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,57 @@ | ||
| use actix_web::web::{Data, Json}; | ||
| use lemmy_api_utils::{context::LemmyContext, utils::is_admin}; | ||
| use lemmy_db_schema::source::local_user_invite::{LocalUserInvite, LocalUserInviteInsertForm}; | ||
| use lemmy_db_views_local_user::LocalUserView; | ||
| use lemmy_db_views_local_user_invite::{ | ||
| api::{CreateInvitation, CreateInvitationResponse}, | ||
| impls::LocalUserInviteQuery, | ||
| }; | ||
| use lemmy_db_views_site::SiteView; | ||
| use lemmy_utils::error::{LemmyErrorType, LemmyResult}; | ||
| use rand::{RngExt, distr::Alphanumeric}; | ||
|
|
||
| pub async fn create_invitation( | ||
| Json(data): Json<CreateInvitation>, | ||
| context: Data<LemmyContext>, | ||
| local_user_view: LocalUserView, | ||
| ) -> LemmyResult<Json<CreateInvitationResponse>> { | ||
| let pool = &mut context.pool(); | ||
|
|
||
| let local_user_id = local_user_view.local_user.id; | ||
| let local_site = SiteView::read_local(pool).await?.local_site; | ||
|
|
||
| let active_invite_count = LocalUserInviteQuery { | ||
| local_user_id, | ||
| ..Default::default() | ||
| } | ||
| .count(pool) | ||
| .await?; | ||
|
|
||
| // admins bypass the max invite per user limit | ||
| if is_admin(&local_user_view).is_err() | ||
| && active_invite_count >= i64::from(local_site.max_invites_per_user_allowed) | ||
| { | ||
| return Err(LemmyErrorType::TooManyInvites.into()); | ||
| } | ||
|
|
||
| let token = generate_invite_token(); | ||
|
|
||
| let insert = LocalUserInviteInsertForm { | ||
| token, | ||
| local_user_id, | ||
| max_uses: data.max_uses, | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should be validate a max_uses? Seems like having a limit here might be a good idea.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I can add this in a subsequent PR along with a setting to control max
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes thats fine. |
||
| expires_at: data.expires_at, | ||
| }; | ||
|
|
||
| let invite = LocalUserInvite::create(pool, &insert).await?; | ||
|
|
||
| Ok(Json(CreateInvitationResponse { invite })) | ||
| } | ||
|
|
||
| fn generate_invite_token() -> String { | ||
| rand::rng() | ||
| .sample_iter(Alphanumeric) | ||
| .take(12) | ||
| .map(char::from) | ||
| .collect() | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,25 @@ | ||
| use actix_web::web::{Data, Json, Query}; | ||
| use lemmy_api_utils::context::LemmyContext; | ||
| use lemmy_db_schema::source::local_user_invite::LocalUserInvite; | ||
| use lemmy_db_views_local_user::LocalUserView; | ||
| use lemmy_db_views_local_user_invite::{api::ListInvitations, impls::LocalUserInviteQuery}; | ||
| use lemmy_diesel_utils::pagination::PagedResponse; | ||
| use lemmy_utils::error::LemmyResult; | ||
|
|
||
| pub async fn list_invitations( | ||
| data: Query<ListInvitations>, | ||
| context: Data<LemmyContext>, | ||
| local_user_view: LocalUserView, | ||
| ) -> LemmyResult<Json<PagedResponse<LocalUserInvite>>> { | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm returning |
||
| let pool = &mut context.pool(); | ||
|
|
||
| let paged = LocalUserInviteQuery { | ||
| local_user_id: local_user_view.local_user.id, | ||
| page_cursor: data.page_cursor.clone(), | ||
| limit: data.limit, | ||
| } | ||
| .list(pool) | ||
| .await?; | ||
|
|
||
| Ok(Json(paged)) | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| pub mod create; | ||
| pub mod list; | ||
| pub mod revoke; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,33 @@ | ||
| use actix_web::web::{Data, Json}; | ||
| use lemmy_api_utils::context::LemmyContext; | ||
| use lemmy_db_schema::source::local_user_invite::LocalUserInvite; | ||
| use lemmy_db_views_local_user::LocalUserView; | ||
| use lemmy_db_views_local_user_invite::api::RevokeInvitation; | ||
| use lemmy_db_views_site::api::SuccessResponse; | ||
| use lemmy_utils::error::{LemmyErrorType, LemmyResult}; | ||
|
|
||
| pub async fn revoke_invitation( | ||
| Json(data): Json<RevokeInvitation>, | ||
| context: Data<LemmyContext>, | ||
| local_user_view: LocalUserView, | ||
| ) -> LemmyResult<Json<SuccessResponse>> { | ||
| let pool = &mut context.pool(); | ||
|
|
||
| let invite = LocalUserInvite::read_by_token(pool, &data.token).await?; | ||
|
|
||
| check_valid_invite(&invite, &local_user_view)?; | ||
|
|
||
| LocalUserInvite::delete_by_token(pool, &data.token).await?; | ||
|
|
||
| Ok(Json(SuccessResponse::default())) | ||
| } | ||
|
|
||
| fn check_valid_invite( | ||
| invite: &LocalUserInvite, | ||
| local_user_view: &LocalUserView, | ||
| ) -> LemmyResult<()> { | ||
| if local_user_view.local_user.id != invite.local_user_id { | ||
| return Err(LemmyErrorType::InvalidInviteToken.into()); | ||
| } | ||
| Ok(()) | ||
| } |
Uh oh!
There was an error while loading. Please reload this page.