You've already forked authentication-service
mirror of
https://github.com/matrix-org/matrix-authentication-service.git
synced 2025-08-07 17:03:01 +03:00
graphql: API to set the user displayname (#1412)
This commit is contained in:
115
crates/graphql/src/mutations/matrix.rs
Normal file
115
crates/graphql/src/mutations/matrix.rs
Normal file
@@ -0,0 +1,115 @@
|
|||||||
|
// Copyright 2023 The Matrix.org Foundation C.I.C.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
use anyhow::Context as _;
|
||||||
|
use async_graphql::{Context, Description, Enum, InputObject, Object, ID};
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
model::{NodeType, User},
|
||||||
|
state::ContextExt,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct MatrixMutations {
|
||||||
|
_private: (),
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The input for the `addEmail` mutation
|
||||||
|
#[derive(InputObject)]
|
||||||
|
struct SetDisplayNameInput {
|
||||||
|
/// The ID of the user to add the email address to
|
||||||
|
user_id: ID,
|
||||||
|
|
||||||
|
/// The display name to set. If `None`, the display name will be removed.
|
||||||
|
display_name: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The status of the `setDisplayName` mutation
|
||||||
|
#[derive(Enum, Copy, Clone, Eq, PartialEq)]
|
||||||
|
pub enum SetDisplayNameStatus {
|
||||||
|
/// The display name was set
|
||||||
|
Set,
|
||||||
|
/// The display name is invalid
|
||||||
|
Invalid,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The payload of the `setDisplayName` mutation
|
||||||
|
#[derive(Description)]
|
||||||
|
enum SetDisplayNamePayload {
|
||||||
|
Set(User),
|
||||||
|
Invalid,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[Object(use_type_description)]
|
||||||
|
impl SetDisplayNamePayload {
|
||||||
|
/// Status of the operation
|
||||||
|
async fn status(&self) -> SetDisplayNameStatus {
|
||||||
|
match self {
|
||||||
|
SetDisplayNamePayload::Set(_) => SetDisplayNameStatus::Set,
|
||||||
|
SetDisplayNamePayload::Invalid => SetDisplayNameStatus::Invalid,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The user that was updated
|
||||||
|
async fn user(&self) -> Option<&User> {
|
||||||
|
match self {
|
||||||
|
SetDisplayNamePayload::Set(user) => Some(user),
|
||||||
|
SetDisplayNamePayload::Invalid => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[Object]
|
||||||
|
impl MatrixMutations {
|
||||||
|
/// Set the display name of a user
|
||||||
|
async fn set_display_name(
|
||||||
|
&self,
|
||||||
|
ctx: &Context<'_>,
|
||||||
|
input: SetDisplayNameInput,
|
||||||
|
) -> Result<SetDisplayNamePayload, async_graphql::Error> {
|
||||||
|
let state = ctx.state();
|
||||||
|
let id = NodeType::User.extract_ulid(&input.user_id)?;
|
||||||
|
let requester = ctx.requester();
|
||||||
|
|
||||||
|
let user = requester.user().context("Unauthorized")?;
|
||||||
|
|
||||||
|
if user.id != id {
|
||||||
|
return Err(async_graphql::Error::new("Unauthorized"));
|
||||||
|
}
|
||||||
|
|
||||||
|
let conn = state.homeserver_connection();
|
||||||
|
let mxid = conn.mxid(&user.username);
|
||||||
|
|
||||||
|
if let Some(display_name) = &input.display_name {
|
||||||
|
// Let's do some basic validation on the display name
|
||||||
|
if display_name.len() > 256 {
|
||||||
|
return Ok(SetDisplayNamePayload::Invalid);
|
||||||
|
}
|
||||||
|
|
||||||
|
if display_name.is_empty() {
|
||||||
|
return Ok(SetDisplayNamePayload::Invalid);
|
||||||
|
}
|
||||||
|
|
||||||
|
conn.set_displayname(&mxid, display_name)
|
||||||
|
.await
|
||||||
|
.context("Failed to set display name")?;
|
||||||
|
} else {
|
||||||
|
conn.unset_displayname(&mxid)
|
||||||
|
.await
|
||||||
|
.context("Failed to unset display name")?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(SetDisplayNamePayload::Set(User(user.clone())))
|
||||||
|
}
|
||||||
|
}
|
@@ -14,6 +14,7 @@
|
|||||||
|
|
||||||
mod browser_session;
|
mod browser_session;
|
||||||
mod compat_session;
|
mod compat_session;
|
||||||
|
mod matrix;
|
||||||
mod oauth2_session;
|
mod oauth2_session;
|
||||||
mod user_email;
|
mod user_email;
|
||||||
|
|
||||||
@@ -26,6 +27,7 @@ pub struct Mutation(
|
|||||||
oauth2_session::OAuth2SessionMutations,
|
oauth2_session::OAuth2SessionMutations,
|
||||||
compat_session::CompatSessionMutations,
|
compat_session::CompatSessionMutations,
|
||||||
browser_session::BrowserSessionMutations,
|
browser_session::BrowserSessionMutations,
|
||||||
|
matrix::MatrixMutations,
|
||||||
);
|
);
|
||||||
|
|
||||||
impl Mutation {
|
impl Mutation {
|
||||||
|
@@ -119,9 +119,14 @@ struct SynapseUser {
|
|||||||
external_ids: Option<Vec<ExternalID>>,
|
external_ids: Option<Vec<ExternalID>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize)]
|
||||||
struct SynapseDevice {
|
struct SynapseDevice<'a> {
|
||||||
device_id: String,
|
device_id: &'a str,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize)]
|
||||||
|
struct SetDisplayNameRequest<'a> {
|
||||||
|
displayname: &'a str,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize)]
|
#[derive(Serialize)]
|
||||||
@@ -257,9 +262,7 @@ impl HomeserverConnection for SynapseConnection {
|
|||||||
|
|
||||||
let request = self
|
let request = self
|
||||||
.post(&format!("_synapse/admin/v2/users/{mxid}/devices"))
|
.post(&format!("_synapse/admin/v2/users/{mxid}/devices"))
|
||||||
.body(SynapseDevice {
|
.body(SynapseDevice { device_id })?;
|
||||||
device_id: device_id.to_owned(),
|
|
||||||
})?;
|
|
||||||
|
|
||||||
let response = client.ready().await?.call(request).await?;
|
let response = client.ready().await?.call(request).await?;
|
||||||
|
|
||||||
@@ -328,4 +331,48 @@ impl HomeserverConnection for SynapseConnection {
|
|||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tracing::instrument(
|
||||||
|
name = "homeserver.set_displayname",
|
||||||
|
skip_all,
|
||||||
|
fields(
|
||||||
|
matrix.homeserver = self.homeserver,
|
||||||
|
matrix.mxid = mxid,
|
||||||
|
matrix.displayname = displayname,
|
||||||
|
),
|
||||||
|
err(Display),
|
||||||
|
)]
|
||||||
|
async fn set_displayname(&self, mxid: &str, displayname: &str) -> Result<(), Self::Error> {
|
||||||
|
let mut client = self
|
||||||
|
.http_client_factory
|
||||||
|
.client()
|
||||||
|
.await?
|
||||||
|
.request_bytes_to_body()
|
||||||
|
.json_request();
|
||||||
|
|
||||||
|
let request = self
|
||||||
|
.put(&format!("_matrix/client/v3/profile/{mxid}/displayname"))
|
||||||
|
.body(SetDisplayNameRequest { displayname })?;
|
||||||
|
|
||||||
|
let response = client.ready().await?.call(request).await?;
|
||||||
|
|
||||||
|
if response.status() != StatusCode::OK {
|
||||||
|
return Err(anyhow::anyhow!("Failed to set displayname in Synapse"));
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tracing::instrument(
|
||||||
|
name = "homeserver.unset_displayname",
|
||||||
|
skip_all,
|
||||||
|
fields(
|
||||||
|
matrix.homeserver = self.homeserver,
|
||||||
|
matrix.mxid = mxid,
|
||||||
|
),
|
||||||
|
err(Display),
|
||||||
|
)]
|
||||||
|
async fn unset_displayname(&self, mxid: &str) -> Result<(), Self::Error> {
|
||||||
|
self.set_displayname(mxid, "").await
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -95,7 +95,10 @@ impl ProvisionRequest {
|
|||||||
/// # Parameters
|
/// # Parameters
|
||||||
///
|
///
|
||||||
/// * `callback` - The callback to call.
|
/// * `callback` - The callback to call.
|
||||||
pub fn on_displayname(&self, callback: impl FnOnce(Option<&str>)) -> &Self {
|
pub fn on_displayname<F>(&self, callback: F) -> &Self
|
||||||
|
where
|
||||||
|
F: FnOnce(Option<&str>),
|
||||||
|
{
|
||||||
match &self.displayname {
|
match &self.displayname {
|
||||||
FieldAction::Unset => callback(None),
|
FieldAction::Unset => callback(None),
|
||||||
FieldAction::Set(displayname) => callback(Some(displayname)),
|
FieldAction::Set(displayname) => callback(Some(displayname)),
|
||||||
@@ -128,7 +131,10 @@ impl ProvisionRequest {
|
|||||||
/// # Parameters
|
/// # Parameters
|
||||||
///
|
///
|
||||||
/// * `callback` - The callback to call.
|
/// * `callback` - The callback to call.
|
||||||
pub fn on_avatar_url(&self, callback: impl FnOnce(Option<&str>)) -> &Self {
|
pub fn on_avatar_url<F>(&self, callback: F) -> &Self
|
||||||
|
where
|
||||||
|
F: FnOnce(Option<&str>),
|
||||||
|
{
|
||||||
match &self.avatar_url {
|
match &self.avatar_url {
|
||||||
FieldAction::Unset => callback(None),
|
FieldAction::Unset => callback(None),
|
||||||
FieldAction::Set(avatar_url) => callback(Some(avatar_url)),
|
FieldAction::Set(avatar_url) => callback(Some(avatar_url)),
|
||||||
@@ -161,7 +167,10 @@ impl ProvisionRequest {
|
|||||||
/// # Parameters
|
/// # Parameters
|
||||||
///
|
///
|
||||||
/// * `callback` - The callback to call.
|
/// * `callback` - The callback to call.
|
||||||
pub fn on_emails(&self, callback: impl FnOnce(Option<&[String]>)) -> &Self {
|
pub fn on_emails<F>(&self, callback: F) -> &Self
|
||||||
|
where
|
||||||
|
F: FnOnce(Option<&[String]>),
|
||||||
|
{
|
||||||
match &self.emails {
|
match &self.emails {
|
||||||
FieldAction::Unset => callback(None),
|
FieldAction::Unset => callback(None),
|
||||||
FieldAction::Set(emails) => callback(Some(emails)),
|
FieldAction::Set(emails) => callback(Some(emails)),
|
||||||
@@ -252,6 +261,31 @@ pub trait HomeserverConnection: Send + Sync {
|
|||||||
/// Returns an error if the homeserver is unreachable or the user could not
|
/// Returns an error if the homeserver is unreachable or the user could not
|
||||||
/// be deleted.
|
/// be deleted.
|
||||||
async fn delete_user(&self, mxid: &str, erase: bool) -> Result<(), Self::Error>;
|
async fn delete_user(&self, mxid: &str, erase: bool) -> Result<(), Self::Error>;
|
||||||
|
|
||||||
|
/// Set the displayname of a user on the homeserver.
|
||||||
|
///
|
||||||
|
/// # Parameters
|
||||||
|
///
|
||||||
|
/// * `mxid` - The Matrix ID of the user to set the displayname for.
|
||||||
|
/// * `displayname` - The displayname to set.
|
||||||
|
///
|
||||||
|
/// # Errors
|
||||||
|
///
|
||||||
|
/// Returns an error if the homeserver is unreachable or the displayname
|
||||||
|
/// could not be set.
|
||||||
|
async fn set_displayname(&self, mxid: &str, displayname: &str) -> Result<(), Self::Error>;
|
||||||
|
|
||||||
|
/// Unset the displayname of a user on the homeserver.
|
||||||
|
///
|
||||||
|
/// # Parameters
|
||||||
|
///
|
||||||
|
/// * `mxid` - The Matrix ID of the user to unset the displayname for.
|
||||||
|
///
|
||||||
|
/// # Errors
|
||||||
|
///
|
||||||
|
/// Returns an error if the homeserver is unreachable or the displayname
|
||||||
|
/// could not be unset.
|
||||||
|
async fn unset_displayname(&self, mxid: &str) -> Result<(), Self::Error>;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait::async_trait]
|
#[async_trait::async_trait]
|
||||||
@@ -281,4 +315,12 @@ impl<T: HomeserverConnection + Send + Sync + ?Sized> HomeserverConnection for &T
|
|||||||
async fn delete_user(&self, mxid: &str, erase: bool) -> Result<(), Self::Error> {
|
async fn delete_user(&self, mxid: &str, erase: bool) -> Result<(), Self::Error> {
|
||||||
(**self).delete_user(mxid, erase).await
|
(**self).delete_user(mxid, erase).await
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn set_displayname(&self, mxid: &str, displayname: &str) -> Result<(), Self::Error> {
|
||||||
|
(**self).set_displayname(mxid, displayname).await
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn unset_displayname(&self, mxid: &str) -> Result<(), Self::Error> {
|
||||||
|
(**self).unset_displayname(mxid).await
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -122,6 +122,20 @@ impl crate::HomeserverConnection for HomeserverConnection {
|
|||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn set_displayname(&self, mxid: &str, displayname: &str) -> Result<(), Self::Error> {
|
||||||
|
let mut users = self.users.write().await;
|
||||||
|
let user = users.get_mut(mxid).context("User not found")?;
|
||||||
|
user.displayname = Some(displayname.to_owned());
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn unset_displayname(&self, mxid: &str) -> Result<(), Self::Error> {
|
||||||
|
let mut users = self.users.write().await;
|
||||||
|
let user = users.get_mut(mxid).context("User not found")?;
|
||||||
|
user.displayname = None;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
@@ -150,10 +164,22 @@ mod tests {
|
|||||||
let inserted = conn.provision_user(&request).await.unwrap();
|
let inserted = conn.provision_user(&request).await.unwrap();
|
||||||
assert!(inserted);
|
assert!(inserted);
|
||||||
|
|
||||||
let user = conn.query_user("@test:example.org").await.unwrap();
|
let user = conn.query_user(mxid).await.unwrap();
|
||||||
assert_eq!(user.displayname, Some("Test User".into()));
|
assert_eq!(user.displayname, Some("Test User".into()));
|
||||||
assert_eq!(user.avatar_url, Some("mxc://example.org/1234567890".into()));
|
assert_eq!(user.avatar_url, Some("mxc://example.org/1234567890".into()));
|
||||||
|
|
||||||
|
// Set the displayname again
|
||||||
|
assert!(conn.set_displayname(mxid, "John").await.is_ok());
|
||||||
|
|
||||||
|
let user = conn.query_user(mxid).await.unwrap();
|
||||||
|
assert_eq!(user.displayname, Some("John".into()));
|
||||||
|
|
||||||
|
// Unset the displayname
|
||||||
|
assert!(conn.unset_displayname(mxid).await.is_ok());
|
||||||
|
|
||||||
|
let user = conn.query_user(mxid).await.unwrap();
|
||||||
|
assert_eq!(user.displayname, None);
|
||||||
|
|
||||||
// Deleting a non-existent device should not fail
|
// Deleting a non-existent device should not fail
|
||||||
assert!(conn.delete_device(mxid, device).await.is_ok());
|
assert!(conn.delete_device(mxid, device).await.is_ok());
|
||||||
|
|
||||||
|
@@ -459,6 +459,10 @@ type Mutation {
|
|||||||
endOauth2Session(input: EndOAuth2SessionInput!): EndOAuth2SessionPayload!
|
endOauth2Session(input: EndOAuth2SessionInput!): EndOAuth2SessionPayload!
|
||||||
endCompatSession(input: EndCompatSessionInput!): EndCompatSessionPayload!
|
endCompatSession(input: EndCompatSessionInput!): EndCompatSessionPayload!
|
||||||
endBrowserSession(input: EndBrowserSessionInput!): EndBrowserSessionPayload!
|
endBrowserSession(input: EndBrowserSessionInput!): EndBrowserSessionPayload!
|
||||||
|
"""
|
||||||
|
Set the display name of a user
|
||||||
|
"""
|
||||||
|
setDisplayName(input: SetDisplayNameInput!): SetDisplayNamePayload!
|
||||||
}
|
}
|
||||||
|
|
||||||
"""
|
"""
|
||||||
@@ -757,6 +761,48 @@ enum SendVerificationEmailStatus {
|
|||||||
ALREADY_VERIFIED
|
ALREADY_VERIFIED
|
||||||
}
|
}
|
||||||
|
|
||||||
|
"""
|
||||||
|
The input for the `addEmail` mutation
|
||||||
|
"""
|
||||||
|
input SetDisplayNameInput {
|
||||||
|
"""
|
||||||
|
The ID of the user to add the email address to
|
||||||
|
"""
|
||||||
|
userId: ID!
|
||||||
|
"""
|
||||||
|
The display name to set. If `None`, the display name will be removed.
|
||||||
|
"""
|
||||||
|
displayName: String
|
||||||
|
}
|
||||||
|
|
||||||
|
"""
|
||||||
|
The payload of the `setDisplayName` mutation
|
||||||
|
"""
|
||||||
|
type SetDisplayNamePayload {
|
||||||
|
"""
|
||||||
|
Status of the operation
|
||||||
|
"""
|
||||||
|
status: SetDisplayNameStatus!
|
||||||
|
"""
|
||||||
|
The user that was updated
|
||||||
|
"""
|
||||||
|
user: User
|
||||||
|
}
|
||||||
|
|
||||||
|
"""
|
||||||
|
The status of the `setDisplayName` mutation
|
||||||
|
"""
|
||||||
|
enum SetDisplayNameStatus {
|
||||||
|
"""
|
||||||
|
The display name was set
|
||||||
|
"""
|
||||||
|
SET
|
||||||
|
"""
|
||||||
|
The display name is invalid
|
||||||
|
"""
|
||||||
|
INVALID
|
||||||
|
}
|
||||||
|
|
||||||
"""
|
"""
|
||||||
The input for the `setPrimaryEmail` mutation
|
The input for the `setPrimaryEmail` mutation
|
||||||
"""
|
"""
|
||||||
|
@@ -323,6 +323,8 @@ export type Mutation = {
|
|||||||
removeEmail: RemoveEmailPayload;
|
removeEmail: RemoveEmailPayload;
|
||||||
/** Send a verification code for an email address */
|
/** Send a verification code for an email address */
|
||||||
sendVerificationEmail: SendVerificationEmailPayload;
|
sendVerificationEmail: SendVerificationEmailPayload;
|
||||||
|
/** Set the display name of a user */
|
||||||
|
setDisplayName: SetDisplayNamePayload;
|
||||||
/** Set an email address as primary */
|
/** Set an email address as primary */
|
||||||
setPrimaryEmail: SetPrimaryEmailPayload;
|
setPrimaryEmail: SetPrimaryEmailPayload;
|
||||||
/** Submit a verification code for an email address */
|
/** Submit a verification code for an email address */
|
||||||
@@ -359,6 +361,11 @@ export type MutationSendVerificationEmailArgs = {
|
|||||||
input: SendVerificationEmailInput;
|
input: SendVerificationEmailInput;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** The mutations root of the GraphQL interface. */
|
||||||
|
export type MutationSetDisplayNameArgs = {
|
||||||
|
input: SetDisplayNameInput;
|
||||||
|
};
|
||||||
|
|
||||||
/** The mutations root of the GraphQL interface. */
|
/** The mutations root of the GraphQL interface. */
|
||||||
export type MutationSetPrimaryEmailArgs = {
|
export type MutationSetPrimaryEmailArgs = {
|
||||||
input: SetPrimaryEmailInput;
|
input: SetPrimaryEmailInput;
|
||||||
@@ -589,6 +596,31 @@ export enum SendVerificationEmailStatus {
|
|||||||
Sent = "SENT",
|
Sent = "SENT",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** The input for the `addEmail` mutation */
|
||||||
|
export type SetDisplayNameInput = {
|
||||||
|
/** The display name to set. If `None`, the display name will be removed. */
|
||||||
|
displayName?: InputMaybe<Scalars["String"]["input"]>;
|
||||||
|
/** The ID of the user to add the email address to */
|
||||||
|
userId: Scalars["ID"]["input"];
|
||||||
|
};
|
||||||
|
|
||||||
|
/** The payload of the `setDisplayName` mutation */
|
||||||
|
export type SetDisplayNamePayload = {
|
||||||
|
__typename?: "SetDisplayNamePayload";
|
||||||
|
/** Status of the operation */
|
||||||
|
status: SetDisplayNameStatus;
|
||||||
|
/** The user that was updated */
|
||||||
|
user?: Maybe<User>;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** The status of the `setDisplayName` mutation */
|
||||||
|
export enum SetDisplayNameStatus {
|
||||||
|
/** The display name is invalid */
|
||||||
|
Invalid = "INVALID",
|
||||||
|
/** The display name was set */
|
||||||
|
Set = "SET",
|
||||||
|
}
|
||||||
|
|
||||||
/** The input for the `setPrimaryEmail` mutation */
|
/** The input for the `setPrimaryEmail` mutation */
|
||||||
export type SetPrimaryEmailInput = {
|
export type SetPrimaryEmailInput = {
|
||||||
/** The ID of the email address to set as primary */
|
/** The ID of the email address to set as primary */
|
||||||
|
@@ -906,6 +906,29 @@ export default {
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "setDisplayName",
|
||||||
|
type: {
|
||||||
|
kind: "NON_NULL",
|
||||||
|
ofType: {
|
||||||
|
kind: "OBJECT",
|
||||||
|
name: "SetDisplayNamePayload",
|
||||||
|
ofType: null,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
args: [
|
||||||
|
{
|
||||||
|
name: "input",
|
||||||
|
type: {
|
||||||
|
kind: "NON_NULL",
|
||||||
|
ofType: {
|
||||||
|
kind: "SCALAR",
|
||||||
|
name: "Any",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "setPrimaryEmail",
|
name: "setPrimaryEmail",
|
||||||
type: {
|
type: {
|
||||||
@@ -1644,6 +1667,33 @@ export default {
|
|||||||
],
|
],
|
||||||
interfaces: [],
|
interfaces: [],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
kind: "OBJECT",
|
||||||
|
name: "SetDisplayNamePayload",
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
name: "status",
|
||||||
|
type: {
|
||||||
|
kind: "NON_NULL",
|
||||||
|
ofType: {
|
||||||
|
kind: "SCALAR",
|
||||||
|
name: "Any",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
args: [],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "user",
|
||||||
|
type: {
|
||||||
|
kind: "OBJECT",
|
||||||
|
name: "User",
|
||||||
|
ofType: null,
|
||||||
|
},
|
||||||
|
args: [],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
interfaces: [],
|
||||||
|
},
|
||||||
{
|
{
|
||||||
kind: "OBJECT",
|
kind: "OBJECT",
|
||||||
name: "SetPrimaryEmailPayload",
|
name: "SetPrimaryEmailPayload",
|
||||||
|
Reference in New Issue
Block a user