Skip to content

Commit

Permalink
feat: allow inviting to scope via email
Browse files Browse the repository at this point in the history
  • Loading branch information
crowlKats committed Feb 28, 2024
1 parent d8309fc commit a53c834
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 22 deletions.
26 changes: 17 additions & 9 deletions api/src/api/scope.rs
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,7 @@ async fn invite_member_handler(
let scope = req.param_scope()?;
Span::current().record("scope", &field::display(&scope));

let ApiAddScopeMemberRequest { github_login } = decode_json(&mut req).await?;
let invite = decode_json::<ApiAddScopeMemberRequest>(&mut req).await?;

let iam = req.iam();
let current_user = iam.check_current_user_access()?.to_owned();
Expand All @@ -233,14 +233,22 @@ async fn invite_member_handler(
let iam = req.iam();
iam.check_scope_admin_access(&scope).await?;

let new_user = lookup_user_by_github_login(
db,
github_oauth2_client,
&current_user,
&github_login,
)
.await?
.ok_or(ApiError::UserNotFound)?;
let new_user = match invite {
ApiAddScopeMemberRequest::GithubLogin(github_login) => {
lookup_user_by_github_login(
db,
github_oauth2_client,
&current_user,
&github_login,
)
.await?
.ok_or(ApiError::UserNotFound)?
}
ApiAddScopeMemberRequest::Email(email) => db
.get_user_by_email(&email)
.await?
.ok_or(ApiError::UserNotFound)?,
};

if db.get_scope_member(&scope, new_user.id).await?.is_some() {
return Err(ApiError::AlreadyScopeMember);
Expand Down
5 changes: 3 additions & 2 deletions api/src/api/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -282,8 +282,9 @@ impl From<(ScopeMember, UserPublic)> for ApiScopeMember {

#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ApiAddScopeMemberRequest {
pub github_login: String,
pub enum ApiAddScopeMemberRequest {
GithubLogin(String),
Email(String),
}

#[derive(Debug, Deserialize)]
Expand Down
49 changes: 38 additions & 11 deletions frontend/routes/@[scope]/(_islands)/ScopeInviteForm.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// Copyright 2024 the JSR authors. All rights reserved. MIT license.
import { useSignal } from "@preact/signals";
import { useCallback } from "preact/hooks";
import { useCallback, useRef } from "preact/hooks";
import { JSX } from "preact/jsx-runtime";
import { ScopeInvite } from "../../../utils/api_types.ts";
import { api, path } from "../../../utils/api.ts";
Expand All @@ -12,18 +12,25 @@ interface ScopeInviteFormProps {
export function ScopeInviteForm(props: ScopeInviteFormProps) {
const submitting = useSignal(false);
const error = useSignal<string>("");
const kind = useSignal<"github" | "email">("github");
const inputRef = useRef<HTMLInputElement>(null);

const onSubmit = useCallback(
(e: JSX.TargetedEvent<HTMLFormElement>) => {
e.preventDefault();
const formData = new FormData(e.currentTarget);
const githubLogin = String(formData.get("githubLogin"));

const kind = String(formData.get("kind"));
const inviteValue = String(formData.get("inviteValue"));

submitting.value = true;

api.post<ScopeInvite>(
path`/scopes/${props.scope}/members`,
{ githubLogin },
{
githubLogin: kind === "github" ? inviteValue : undefined,
email: kind === "email" ? inviteValue : undefined,
},
).then((res) => {
submitting.value = false;
if (!res.ok) {
Expand All @@ -47,14 +54,34 @@ export function ScopeInviteForm(props: ScopeInviteFormProps) {
onSubmit={onSubmit}
>
<div class="mt-4 flex gap-4">
<input
class="block w-full max-w-sm p-1.5 input-container input"
type="text"
name="githubLogin"
placeholder="GitHub username"
required
disabled={submitting}
/>
<div class="flex">
<select
name="kind"
id="kind-select"
class="inline-block p-1.5 input-container input rounded-r-none border-r-0"
disabled={submitting}
onChange={(e) => {
if (kind.value !== e.currentTarget.value) {
kind.value = e.currentTarget.value as "github" | "email";
if (inputRef?.current) {
inputRef.current.value = "";
}
}
}}
>
<option value="github" selected>GitHub</option>
<option value="email">E-Mail</option>
</select>
<input
class="inline-block w-full max-w-sm p-1.5 input-container input rounded-l-none"
type="text"
name="inviteValue"
placeholder={kind.value === "github" ? "GitHub login" : "E-Mail"}
required
ref={inputRef}
disabled={submitting}
/>
</div>
<button
class="button-primary"
type="submit"
Expand Down

0 comments on commit a53c834

Please sign in to comment.