diff --git a/backend/src/backend/api/schema/mutation.cr b/backend/src/backend/api/schema/mutation.cr index 187a992..5eae02e 100644 --- a/backend/src/backend/api/schema/mutation.cr +++ b/backend/src/backend/api/schema/mutation.cr @@ -26,7 +26,7 @@ module Backend class Mutation < GraphQL::BaseMutation @[GraphQL::Field] # Logs in as *username* with credential *password* - def login(username : String, password : String) : LoginPayload + def login(username : String, password : String) : LoginPayload? raise Errors::Authentication.new if username.empty? || password.empty? user = Db::User.query.find { var(:username) == username } diff --git a/frontend/Cargo.toml b/frontend/Cargo.toml index ac9e44c..c5a3d22 100644 --- a/frontend/Cargo.toml +++ b/frontend/Cargo.toml @@ -9,11 +9,11 @@ wasm-logger = "0.2.0" log = "0.4.6" yew-router = "0.16.0" wee_alloc = "0.4.5" -graphql_client = { version = "0.11.0", features = ["reqwest"] } +graphql_client = { git = "https://github.com/graphql-rust/graphql-client.git", branch = "main", features = ["reqwest"] } reqwest = "0.11.12" -wasm-bindgen-futures = "0.4.33" serde = "1.0.147" web-sys = { version = "0.3.60", features = ["Window", "Location"] } wasm-cookies = "0.1.0" lazy_static = "1.4.0" const_format = "0.2.30" +yew-agent = "0.1.0" diff --git a/frontend/Dockerfile b/frontend/Dockerfile index 801bad2..703301c 100644 --- a/frontend/Dockerfile +++ b/frontend/Dockerfile @@ -21,6 +21,11 @@ COPY ./graphql ./graphql COPY ./src ./src RUN trunk build --release +FROM tdewolff/minify as public +WORKDIR /usr/src/public +COPY --from=builder /usr/src/frontend/dist . +RUN minify . -r -o . + FROM nginx:alpine as runner COPY ./nginx.conf /etc/nginx/nginx.conf -COPY --from=builder /usr/src/frontend/dist /var/www/html +COPY --from=public /usr/src/public /var/www/html diff --git a/frontend/graphql/mutations/login.graphql b/frontend/graphql/mutations/login.graphql new file mode 100644 index 0000000..64e3cd4 --- /dev/null +++ b/frontend/graphql/mutations/login.graphql @@ -0,0 +1,5 @@ +mutation Login($username: String!, $password: String!) { + login(username: $username, password: $password) { + token + } +} diff --git a/frontend/graphql/queries/me.graphql b/frontend/graphql/queries/me.graphql new file mode 100644 index 0000000..0ae661a --- /dev/null +++ b/frontend/graphql/queries/me.graphql @@ -0,0 +1,10 @@ +query Me { + me { + firstName + role + student { + vote + } + teacher + } +} diff --git a/frontend/graphql/schema.graphql b/frontend/graphql/schema.graphql index aca8292..30a7b87 100644 --- a/frontend/graphql/schema.graphql +++ b/frontend/graphql/schema.graphql @@ -78,7 +78,7 @@ type Mutation { createUser(checkLdap: Boolean! = true, input: UserCreateInput!): User! createVote(input: VoteCreateInput!): Vote! deleteUser(id: Int!): Int! - login(password: String!, username: String!): LoginPayload! + login(password: String!, username: String!): LoginPayload } input UserCreateInput { diff --git a/frontend/src/agents/logged_in.rs b/frontend/src/agents/logged_in.rs new file mode 100644 index 0000000..9c49dc7 --- /dev/null +++ b/frontend/src/agents/logged_in.rs @@ -0,0 +1,47 @@ +use serde::{Deserialize, Serialize}; +use std::collections::HashSet; +use yew_agent::{Agent, AgentLink, Context, HandlerId}; + +#[derive(Serialize, Deserialize, Debug)] +pub enum Request { + LoggedIn(bool), +} + +pub struct EventBus { + link: AgentLink, + subscribers: HashSet, +} + +impl Agent for EventBus { + type Reach = Context; + type Message = (); + type Input = Request; + type Output = bool; + + fn create(link: AgentLink) -> Self { + Self { + link, + subscribers: HashSet::new(), + } + } + + fn update(&mut self, _msg: Self::Message) {} + + fn handle_input(&mut self, msg: Self::Input, _id: HandlerId) { + match msg { + Request::LoggedIn(x) => { + for sub in self.subscribers.iter() { + self.link.respond(*sub, x); + } + } + } + } + + fn connected(&mut self, id: HandlerId) { + self.subscribers.insert(id); + } + + fn disconnected(&mut self, id: HandlerId) { + self.subscribers.remove(&id); + } +} diff --git a/frontend/src/agents/mod.rs b/frontend/src/agents/mod.rs new file mode 100644 index 0000000..a5931af --- /dev/null +++ b/frontend/src/agents/mod.rs @@ -0,0 +1 @@ +pub mod logged_in; diff --git a/frontend/src/components/logged_in_handler.rs b/frontend/src/components/logged_in_handler.rs new file mode 100644 index 0000000..d6205fc --- /dev/null +++ b/frontend/src/components/logged_in_handler.rs @@ -0,0 +1,54 @@ +use yew::prelude::*; +use yew_agent::{Bridge, Bridged}; +use yew_router::prelude::*; + +use crate::agents; +use crate::cookie_names; +use crate::routes; + +pub enum Msg { + LoggedIn(bool), +} + +#[derive(Properties, PartialEq)] +pub struct LoggedInHandlerProps { + pub logged_in: bool, +} + +pub struct LoggedInHandler { + logged_in: bool, + _logged_in_producer: Box>, +} + +impl Component for LoggedInHandler { + type Message = Msg; + type Properties = LoggedInHandlerProps; + + fn create(ctx: &Context) -> Self { + Self { + logged_in: ctx.props().logged_in, + _logged_in_producer: agents::logged_in::EventBus::bridge( + ctx.link().callback(Msg::LoggedIn), + ), + } + } + + fn update(&mut self, ctx: &Context, msg: Self::Message) -> bool { + match msg { + Msg::LoggedIn(x) => { + if self.logged_in && !x { + log::info!("Global logout!"); + wasm_cookies::delete(cookie_names::TOKEN); + ctx.link().history().unwrap().push(routes::Route::Login); + } + self.logged_in = x; + + false + } + } + } + + fn view(&self, _ctx: &Context) -> Html { + html! {} + } +} diff --git a/frontend/src/components/mod.rs b/frontend/src/components/mod.rs index e69de29..d22d293 100644 --- a/frontend/src/components/mod.rs +++ b/frontend/src/components/mod.rs @@ -0,0 +1 @@ +pub mod logged_in_handler; diff --git a/frontend/src/graphql/mod.rs b/frontend/src/graphql/mod.rs index 0b1a318..fba9b42 100644 --- a/frontend/src/graphql/mod.rs +++ b/frontend/src/graphql/mod.rs @@ -1,6 +1,7 @@ use lazy_static::lazy_static; use std::path::Path; +pub mod mutations; pub mod queries; lazy_static! { diff --git a/frontend/src/graphql/mutations/login.rs b/frontend/src/graphql/mutations/login.rs new file mode 100644 index 0000000..ac09e70 --- /dev/null +++ b/frontend/src/graphql/mutations/login.rs @@ -0,0 +1,9 @@ +use graphql_client::GraphQLQuery; + +#[derive(GraphQLQuery)] +#[graphql( + schema_path = "graphql/schema.graphql", + query_path = "graphql/mutations/login.graphql", + response_derives = "Debug,Serialize,Deserialize" +)] +pub struct Login; diff --git a/frontend/src/graphql/mutations/mod.rs b/frontend/src/graphql/mutations/mod.rs new file mode 100644 index 0000000..320cbbb --- /dev/null +++ b/frontend/src/graphql/mutations/mod.rs @@ -0,0 +1 @@ +pub mod login; diff --git a/frontend/src/graphql/queries/me.rs b/frontend/src/graphql/queries/me.rs new file mode 100644 index 0000000..ffa5508 --- /dev/null +++ b/frontend/src/graphql/queries/me.rs @@ -0,0 +1,9 @@ +use graphql_client::GraphQLQuery; + +#[derive(GraphQLQuery)] +#[graphql( + schema_path = "graphql/schema.graphql", + query_path = "graphql/queries/me.graphql", + response_derives = "Debug" +)] +pub struct Me; diff --git a/frontend/src/graphql/queries/mod.rs b/frontend/src/graphql/queries/mod.rs new file mode 100644 index 0000000..94e52cc --- /dev/null +++ b/frontend/src/graphql/queries/mod.rs @@ -0,0 +1,2 @@ +pub mod me; +pub mod ok; diff --git a/frontend/src/graphql/queries.rs b/frontend/src/graphql/queries/ok.rs similarity index 92% rename from frontend/src/graphql/queries.rs rename to frontend/src/graphql/queries/ok.rs index 22cef99..d3aba17 100644 --- a/frontend/src/graphql/queries.rs +++ b/frontend/src/graphql/queries/ok.rs @@ -6,4 +6,4 @@ use graphql_client::GraphQLQuery; query_path = "graphql/queries/ok.graphql", response_derives = "Debug" )] -pub struct Ok; +pub struct Ok; \ No newline at end of file diff --git a/frontend/src/layouts/logged_in.rs b/frontend/src/layouts/logged_in.rs new file mode 100644 index 0000000..cec31e4 --- /dev/null +++ b/frontend/src/layouts/logged_in.rs @@ -0,0 +1,58 @@ +use yew::prelude::*; +use yew_agent::{Bridge, Bridged}; +use yew_router::prelude::*; +use yew_router::scope_ext::RouterScopeExt; + +use crate::agents; +use crate::routes; + +pub enum Msg { + LoggedIn(bool), +} + +#[derive(Properties, PartialEq)] +pub struct LoggedInProps { + #[prop_or_default] + pub children: Children, + pub logged_in: bool, +} + +pub struct LoggedIn { + logged_in: bool, + _logged_in_producer: Box>, +} + +impl Component for LoggedIn { + type Message = Msg; + type Properties = LoggedInProps; + + fn create(ctx: &Context) -> Self { + Self { + logged_in: ctx.props().logged_in, + _logged_in_producer: agents::logged_in::EventBus::bridge( + ctx.link().callback(Msg::LoggedIn), + ), + } + } + + fn update(&mut self, _ctx: &Context, msg: Self::Message) -> bool { + match msg { + Msg::LoggedIn(x) => { + let prev = self.logged_in; + self.logged_in = x; + prev != self.logged_in + } + } + } + + fn view(&self, ctx: &Context) -> Html { + if !self.logged_in { + log::info!("Viewing logged in required site while not logged in!"); + ctx.link().history().unwrap().push(routes::Route::Login); + } + + html! { + { for ctx.props().children.iter() } + } + } +} diff --git a/frontend/src/layouts/main.rs b/frontend/src/layouts/main.rs index f2c3a8c..4bb7880 100644 --- a/frontend/src/layouts/main.rs +++ b/frontend/src/layouts/main.rs @@ -1,56 +1,79 @@ -use graphql_client::reqwest::post_graphql; -use wasm_bindgen_futures; use yew::prelude::*; +use yew_agent::{Dispatched, Dispatcher}; use yew_router::prelude::*; -use crate::cookie_names; -use crate::graphql; +use crate::agents; +use crate::components; use crate::routes; +pub enum Msg { + LogOut, +} + #[derive(Properties, PartialEq)] pub struct MainProps { + pub logged_in: bool, #[prop_or_default] pub children: Children, } -#[function_component(Main)] -pub fn main(props: &MainProps) -> Html { - let client = reqwest::Client::new(); - wasm_bindgen_futures::spawn_local(async move { - let response = post_graphql::( - &client, - graphql::URL.as_str(), - graphql::queries::ok::Variables {}, - ) - .await - .unwrap(); - log::debug!("{:?}", response); - log::debug!("{:?}", wasm_cookies::get(cookie_names::TOKEN)); - }); +pub struct Main { + logged_in: bool, + logged_in_event_bus: Dispatcher, +} - let history = use_history().unwrap(); - let loginout_onclick = Callback::once(move |_| history.push(routes::Route::Login)); +impl Component for Main { + type Message = Msg; + type Properties = MainProps; - html! { - <> - + fn create(ctx: &Context) -> Self { + Self { + logged_in: ctx.props().logged_in, + logged_in_event_bus: agents::logged_in::EventBus::dispatcher(), + } + } -
+ fn update(&mut self, _ctx: &Context, msg: Self::Message) -> bool { + match msg { + Msg::LogOut => { + self.logged_in_event_bus + .send(agents::logged_in::Request::LoggedIn(false)); + false + } + } + } -
- { for props.children.iter() } -
- + fn view(&self, ctx: &Context) -> Html { + let logout_onclick = ctx.link().callback(move |_| Msg::LogOut); + + html! { + <> + + +
+ + +
+ { for ctx.props().children.iter() } +
+ + } } } diff --git a/frontend/src/layouts/mod.rs b/frontend/src/layouts/mod.rs index 2a04341..1f60493 100644 --- a/frontend/src/layouts/mod.rs +++ b/frontend/src/layouts/mod.rs @@ -1 +1,2 @@ +pub mod logged_in; pub mod main; diff --git a/frontend/src/lib.rs b/frontend/src/lib.rs index 21496b8..b0dc0bd 100644 --- a/frontend/src/lib.rs +++ b/frontend/src/lib.rs @@ -1,3 +1,4 @@ +pub mod agents; pub mod components; pub mod cookie_names; pub mod graphql; diff --git a/frontend/src/main.rs b/frontend/src/main.rs index 6aaac67..6a361b8 100644 --- a/frontend/src/main.rs +++ b/frontend/src/main.rs @@ -1,17 +1,27 @@ use yew::prelude::*; use yew_router::prelude::*; +use frontend::routes; + #[global_allocator] static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT; -use frontend::routes; +pub struct App; -#[function_component(App)] -fn app() -> Html { - html! { - - render={Switch::render(routes::switch)} /> - +impl Component for App { + type Message = (); + type Properties = (); + + fn create(_ctx: &Context) -> Self { + Self + } + + fn view(&self, _ctx: &Context) -> Html { + html! { + + render={Switch::render(routes::switch)} /> + + } } } diff --git a/frontend/src/routes/home.rs b/frontend/src/routes/home.rs index 2d8f545..8606200 100644 --- a/frontend/src/routes/home.rs +++ b/frontend/src/routes/home.rs @@ -1,8 +1,100 @@ +use graphql_client::reqwest::post_graphql; use yew::prelude::*; -#[function_component(Home)] -pub fn home() -> Html { - html! { -

{ "HOME!" }

+use crate::graphql; + +pub enum Msg { + DoneFetching { + errors: Option>, + data: graphql::queries::me::me::ResponseData, + }, +} + +#[derive(Properties, PartialEq)] +pub struct HomeProps { + pub token: String, +} + +enum State { + Fetching, + Done, +} + +pub struct Home { + state: State, + errors: Option>, + data: Option, +} + +impl Component for Home { + type Message = Msg; + type Properties = HomeProps; + + fn create(_ctx: &Context) -> Self { + Self { + state: State::Fetching, + errors: None, + data: None, + } + } + + fn update(&mut self, _ctx: &Context, msg: Self::Message) -> bool { + match msg { + Msg::DoneFetching { errors, data } => { + self.state = State::Done; + self.errors = errors; + true + } + } + } + + fn view(&self, ctx: &Context) -> Html { + match self.state { + State::Fetching => { + let mut headers = reqwest::header::HeaderMap::new(); + headers.insert( + "Authorization", + reqwest::header::HeaderValue::from_str(&format!( + "Bearer {}", + ctx.props().token + )) + .unwrap(), + ); + ctx.link().send_future(async move { + let response = post_graphql::( + &reqwest::Client::builder() + .default_headers(headers) + .build() + .unwrap(), + graphql::URL.as_str(), + graphql::queries::me::me::Variables, + ) + .await + .unwrap(); + log::debug!("{:?}", response.data); + + Msg::DoneFetching { + errors: response + .errors + .map(|x| x.iter().map(|e| e.message.to_owned()).collect()), + data: response.data.unwrap(), + } + }); + + html! { +

{ "Fetching..." }

+ } + } + State::Done => html! { + if let Some(errors) = &self.errors { +

{ "Errors:" }

+
+ { for errors.iter().map(|e| html! {

{ e }

}) } +
+ } else { +

{ "Hey, !" }

+ } + }, + } } } diff --git a/frontend/src/routes/login.rs b/frontend/src/routes/login.rs index 72c9dea..dd4ad66 100644 --- a/frontend/src/routes/login.rs +++ b/frontend/src/routes/login.rs @@ -1,8 +1,123 @@ +use graphql_client::reqwest::post_graphql; +use web_sys::HtmlInputElement; use yew::prelude::*; +use yew_router::prelude::*; -#[function_component(Login)] -pub fn login() -> Html { - html! { -

{ "LOGIN!" }

+use crate::cookie_names; +use crate::graphql; +use crate::routes; + +pub enum Msg { + Submit, + Login(Option>), +} + +pub struct Login { + username: NodeRef, + password: NodeRef, + errors: Option>, +} + +impl Component for Login { + type Message = Msg; + type Properties = (); + + fn create(_ctx: &Context) -> Self { + Self { + username: NodeRef::default(), + password: NodeRef::default(), + errors: None, + } + } + + fn update(&mut self, ctx: &Context, msg: Self::Message) -> bool { + match msg { + Msg::Submit => { + if let (Some(username), Some(password)) = ( + self.username.cast::().map(|x| x.value()), + self.password.cast::().map(|x| x.value()), + ) { + if !username.is_empty() && !password.is_empty() { + ctx.link().send_future(async { + let response = post_graphql::( + &reqwest::Client::new(), + graphql::URL.as_str(), + graphql::mutations::login::login::Variables { username, password }, + ) + .await + .unwrap(); + + if response.errors.is_some() { + wasm_cookies::delete(cookie_names::TOKEN); + } else { + wasm_cookies::set( + cookie_names::TOKEN, + &response.data.unwrap().login.unwrap().token, + &wasm_cookies::CookieOptions::default(), + ) + } + + Msg::Login( + response + .errors + .map(|x| x.iter().map(|e| e.message.to_owned()).collect()), + ) + }); + } + } + + false + } + Msg::Login(errors) => { + self.errors = errors; + if self.errors.is_none() { + ctx.link().history().unwrap().push(routes::Route::Home); + false + } else { + true + } + } + } + } + + fn view(&self, ctx: &Context) -> Html { + let link = ctx.link(); + + let onsubmit = link.callback(|e: FocusEvent| { + e.prevent_default(); + + Msg::Submit + }); + + html! { + <> +
+ + +
+ + + +

+ + +
+ + if let Some(errors) = &self.errors { +
+ { for errors.iter().map(|e| html! {

{ e }

}) } +
+ } + + + } } } diff --git a/frontend/src/routes/mod.rs b/frontend/src/routes/mod.rs index 82de03a..ccf39f2 100644 --- a/frontend/src/routes/mod.rs +++ b/frontend/src/routes/mod.rs @@ -1,13 +1,14 @@ use yew::prelude::*; use yew_router::prelude::*; +use crate::cookie_names; use crate::layouts; pub mod home; pub mod login; pub mod not_found; -#[derive(Clone, Routable, PartialEq)] +#[derive(Clone, Routable, PartialEq, Eq)] pub enum Route { #[at("/")] Home, @@ -19,11 +20,40 @@ pub enum Route { } pub fn switch(routes: &Route) -> Html { - match routes { - Route::Home => html! { }, - Route::Login => html! { }, - Route::NotFound => { - html! { } + let token = { + let tmp = wasm_cookies::get(cookie_names::TOKEN); + if let Some(x) = tmp { + if let Ok(y) = x { + Some(y) + } else { + wasm_cookies::delete(cookie_names::TOKEN); + None + } + } else { + None } + }; + let logged_in = token.is_some(); + + match routes { + Route::Home => { + html! { + + + + + + } + } + Route::Login => html! { + + + + }, + Route::NotFound => html! { + + + + }, } } diff --git a/frontend_old/test.json b/frontend_old/test.json deleted file mode 100644 index fcf8f2c..0000000 --- a/frontend_old/test.json +++ /dev/null @@ -1,2085 +0,0 @@ -{ - "data": { - "__schema": { - "directives": [ - { - "args": [ - { - "defaultValue": null, - "description": null, - "name": "if", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "Boolean", - "ofType": null - } - } - } - ], - "description": null, - "locations": [ - "FIELD", - "FRAGMENT_SPREAD", - "INLINE_FRAGMENT" - ], - "name": "skip" - }, - { - "args": [ - { - "defaultValue": null, - "description": null, - "name": "if", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "Boolean", - "ofType": null - } - } - } - ], - "description": null, - "locations": [ - "FIELD", - "FRAGMENT_SPREAD", - "INLINE_FRAGMENT" - ], - "name": "include" - }, - { - "args": [ - { - "defaultValue": null, - "description": null, - "name": "reason", - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - } - ], - "description": null, - "locations": [ - "FIELD_DEFINITION", - "ENUM_VALUE" - ], - "name": "deprecated" - } - ], - "mutationType": { - "name": "Mutation" - }, - "queryType": { - "name": "Query" - }, - "subscriptionType": null, - "types": [ - { - "description": "The `Boolean` scalar type represents `true` or `false`.", - "enumValues": null, - "fields": null, - "inputFields": null, - "interfaces": null, - "kind": "SCALAR", - "name": "Boolean", - "possibleTypes": null - }, - { - "description": null, - "enumValues": null, - "fields": [ - { - "args": [], - "deprecationReason": null, - "description": null, - "isDeprecated": false, - "name": "minimumTeacherSelectionCount", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "Int", - "ofType": null - } - } - } - ], - "inputFields": null, - "interfaces": [], - "kind": "OBJECT", - "name": "Config", - "possibleTypes": null - }, - { - "description": "The `Float` scalar type represents signed double-precision fractional values as specified by [IEEE 754](https://en.wikipedia.org/wiki/IEEE_floating_point).", - "enumValues": null, - "fields": null, - "inputFields": null, - "interfaces": null, - "kind": "SCALAR", - "name": "Float", - "possibleTypes": null - }, - { - "description": "The `ID` scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as `\"4\"`) or integer (such as `4`) input value will be accepted as an ID.", - "enumValues": null, - "fields": null, - "inputFields": null, - "interfaces": null, - "kind": "SCALAR", - "name": "ID", - "possibleTypes": null - }, - { - "description": "The `Int` scalar type represents non-fractional signed whole numeric values. Int can represent values between -(2^31) and 2^31 - 1.", - "enumValues": null, - "fields": null, - "inputFields": null, - "interfaces": null, - "kind": "SCALAR", - "name": "Int", - "possibleTypes": null - }, - { - "description": null, - "enumValues": null, - "fields": [ - { - "args": [], - "deprecationReason": null, - "description": null, - "isDeprecated": false, - "name": "admins", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "User", - "ofType": null - } - } - } - } - }, - { - "args": [], - "deprecationReason": null, - "description": null, - "isDeprecated": false, - "name": "allStudentsVoted", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "Boolean", - "ofType": null - } - } - }, - { - "args": [], - "deprecationReason": null, - "description": null, - "isDeprecated": false, - "name": "config", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "Config", - "ofType": null - } - } - }, - { - "args": [], - "deprecationReason": null, - "description": null, - "isDeprecated": false, - "name": "me", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "User", - "ofType": null - } - } - }, - { - "args": [], - "deprecationReason": null, - "description": null, - "isDeprecated": false, - "name": "ok", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "Boolean", - "ofType": null - } - } - }, - { - "args": [ - { - "defaultValue": null, - "description": null, - "name": "id", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "Int", - "ofType": null - } - } - } - ], - "deprecationReason": null, - "description": null, - "isDeprecated": false, - "name": "student", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "Student", - "ofType": null - } - } - }, - { - "args": [], - "deprecationReason": null, - "description": null, - "isDeprecated": false, - "name": "students", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "Student", - "ofType": null - } - } - } - } - }, - { - "args": [], - "deprecationReason": null, - "description": null, - "isDeprecated": false, - "name": "studentsCanVote", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "Boolean", - "ofType": null - } - } - }, - { - "args": [ - { - "defaultValue": null, - "description": null, - "name": "id", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "Int", - "ofType": null - } - } - } - ], - "deprecationReason": null, - "description": null, - "isDeprecated": false, - "name": "teacher", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "Teacher", - "ofType": null - } - } - }, - { - "args": [ - { - "defaultValue": null, - "description": null, - "name": "id", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "Int", - "ofType": null - } - } - } - ], - "deprecationReason": null, - "description": null, - "isDeprecated": false, - "name": "teacherVote", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "TeacherVote", - "ofType": null - } - } - }, - { - "args": [], - "deprecationReason": null, - "description": null, - "isDeprecated": false, - "name": "teacherVotes", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "TeacherVote", - "ofType": null - } - } - } - } - }, - { - "args": [], - "deprecationReason": null, - "description": null, - "isDeprecated": false, - "name": "teachers", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "Teacher", - "ofType": null - } - } - } - } - }, - { - "args": [ - { - "defaultValue": null, - "description": null, - "name": "id", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "Int", - "ofType": null - } - } - } - ], - "deprecationReason": null, - "description": null, - "isDeprecated": false, - "name": "user", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "User", - "ofType": null - } - } - }, - { - "args": [ - { - "defaultValue": null, - "description": null, - "name": "username", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - } - } - ], - "deprecationReason": null, - "description": null, - "isDeprecated": false, - "name": "userByUsername", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "User", - "ofType": null - } - } - }, - { - "args": [], - "deprecationReason": null, - "description": null, - "isDeprecated": false, - "name": "users", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "User", - "ofType": null - } - } - } - } - }, - { - "args": [ - { - "defaultValue": null, - "description": null, - "name": "id", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "Int", - "ofType": null - } - } - } - ], - "deprecationReason": null, - "description": null, - "isDeprecated": false, - "name": "vote", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "Vote", - "ofType": null - } - } - }, - { - "args": [], - "deprecationReason": null, - "description": null, - "isDeprecated": false, - "name": "votes", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "Vote", - "ofType": null - } - } - } - } - } - ], - "inputFields": null, - "interfaces": [], - "kind": "OBJECT", - "name": "Query", - "possibleTypes": null - }, - { - "description": "The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.", - "enumValues": null, - "fields": null, - "inputFields": null, - "interfaces": null, - "kind": "SCALAR", - "name": "String", - "possibleTypes": null - }, - { - "description": null, - "enumValues": null, - "fields": [ - { - "args": [], - "deprecationReason": null, - "description": null, - "isDeprecated": false, - "name": "id", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "Int", - "ofType": null - } - } - }, - { - "args": [], - "deprecationReason": null, - "description": null, - "isDeprecated": false, - "name": "user", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "User", - "ofType": null - } - } - }, - { - "args": [], - "deprecationReason": null, - "description": null, - "isDeprecated": false, - "name": "vote", - "type": { - "kind": "OBJECT", - "name": "Vote", - "ofType": null - } - } - ], - "inputFields": null, - "interfaces": [], - "kind": "OBJECT", - "name": "Student", - "possibleTypes": null - }, - { - "description": null, - "enumValues": null, - "fields": [ - { - "args": [], - "deprecationReason": null, - "description": null, - "isDeprecated": false, - "name": "id", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "Int", - "ofType": null - } - } - }, - { - "args": [], - "deprecationReason": null, - "description": null, - "isDeprecated": false, - "name": "maxStudents", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "Int", - "ofType": null - } - } - }, - { - "args": [], - "deprecationReason": null, - "description": null, - "isDeprecated": false, - "name": "teacherVotes", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "TeacherVote", - "ofType": null - } - } - } - } - }, - { - "args": [], - "deprecationReason": null, - "description": null, - "isDeprecated": false, - "name": "user", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "User", - "ofType": null - } - } - } - ], - "inputFields": null, - "interfaces": [], - "kind": "OBJECT", - "name": "Teacher", - "possibleTypes": null - }, - { - "description": null, - "enumValues": null, - "fields": [ - { - "args": [], - "deprecationReason": null, - "description": null, - "isDeprecated": false, - "name": "id", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "Int", - "ofType": null - } - } - }, - { - "args": [], - "deprecationReason": null, - "description": null, - "isDeprecated": false, - "name": "priority", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "Int", - "ofType": null - } - } - }, - { - "args": [], - "deprecationReason": null, - "description": null, - "isDeprecated": false, - "name": "teacher", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "Teacher", - "ofType": null - } - } - }, - { - "args": [], - "deprecationReason": null, - "description": null, - "isDeprecated": false, - "name": "vote", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "Vote", - "ofType": null - } - } - } - ], - "inputFields": null, - "interfaces": [], - "kind": "OBJECT", - "name": "TeacherVote", - "possibleTypes": null - }, - { - "description": null, - "enumValues": null, - "fields": [ - { - "args": [], - "deprecationReason": null, - "description": null, - "isDeprecated": false, - "name": "admin", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "Boolean", - "ofType": null - } - } - }, - { - "args": [], - "deprecationReason": null, - "description": null, - "isDeprecated": false, - "name": "email", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - } - }, - { - "args": [], - "deprecationReason": null, - "description": null, - "isDeprecated": false, - "name": "externalId", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "Int", - "ofType": null - } - } - }, - { - "args": [], - "deprecationReason": null, - "description": null, - "isDeprecated": false, - "name": "firstName", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - } - }, - { - "args": [], - "deprecationReason": null, - "description": null, - "isDeprecated": false, - "name": "id", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "Int", - "ofType": null - } - } - }, - { - "args": [], - "deprecationReason": null, - "description": null, - "isDeprecated": false, - "name": "lastName", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - } - }, - { - "args": [ - { - "defaultValue": "true", - "description": null, - "name": "formal", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "Boolean", - "ofType": null - } - } - } - ], - "deprecationReason": null, - "description": null, - "isDeprecated": false, - "name": "name", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - } - }, - { - "args": [], - "deprecationReason": null, - "description": null, - "isDeprecated": false, - "name": "role", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "ENUM", - "name": "UserRole", - "ofType": null - } - } - }, - { - "args": [], - "deprecationReason": null, - "description": null, - "isDeprecated": false, - "name": "student", - "type": { - "kind": "OBJECT", - "name": "Student", - "ofType": null - } - }, - { - "args": [], - "deprecationReason": null, - "description": null, - "isDeprecated": false, - "name": "teacher", - "type": { - "kind": "OBJECT", - "name": "Teacher", - "ofType": null - } - }, - { - "args": [], - "deprecationReason": null, - "description": null, - "isDeprecated": false, - "name": "username", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - } - } - ], - "inputFields": null, - "interfaces": [], - "kind": "OBJECT", - "name": "User", - "possibleTypes": null - }, - { - "description": null, - "enumValues": [ - { - "deprecationReason": null, - "description": null, - "isDeprecated": false, - "name": "Student" - }, - { - "deprecationReason": null, - "description": null, - "isDeprecated": false, - "name": "Teacher" - } - ], - "fields": null, - "inputFields": null, - "interfaces": null, - "kind": "ENUM", - "name": "UserRole", - "possibleTypes": null - }, - { - "description": null, - "enumValues": null, - "fields": [ - { - "args": [], - "deprecationReason": null, - "description": null, - "isDeprecated": false, - "name": "id", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "Int", - "ofType": null - } - } - }, - { - "args": [], - "deprecationReason": null, - "description": null, - "isDeprecated": false, - "name": "student", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "Student", - "ofType": null - } - } - }, - { - "args": [], - "deprecationReason": null, - "description": null, - "isDeprecated": false, - "name": "teacherVotes", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "TeacherVote", - "ofType": null - } - } - } - } - } - ], - "inputFields": null, - "interfaces": [], - "kind": "OBJECT", - "name": "Vote", - "possibleTypes": null - }, - { - "description": null, - "enumValues": null, - "fields": [ - { - "args": [], - "deprecationReason": null, - "description": null, - "isDeprecated": false, - "name": "args", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "__InputValue", - "ofType": null - } - } - } - } - }, - { - "args": [], - "deprecationReason": null, - "description": null, - "isDeprecated": false, - "name": "description", - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - }, - { - "args": [], - "deprecationReason": null, - "description": null, - "isDeprecated": false, - "name": "locations", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - } - } - } - }, - { - "args": [], - "deprecationReason": null, - "description": null, - "isDeprecated": false, - "name": "name", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - } - } - ], - "inputFields": null, - "interfaces": [], - "kind": "OBJECT", - "name": "__Directive", - "possibleTypes": null - }, - { - "description": null, - "enumValues": null, - "fields": [ - { - "args": [], - "deprecationReason": null, - "description": null, - "isDeprecated": false, - "name": "deprecationReason", - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - }, - { - "args": [], - "deprecationReason": null, - "description": null, - "isDeprecated": false, - "name": "description", - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - }, - { - "args": [], - "deprecationReason": null, - "description": null, - "isDeprecated": false, - "name": "isDeprecated", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "Boolean", - "ofType": null - } - } - }, - { - "args": [], - "deprecationReason": null, - "description": null, - "isDeprecated": false, - "name": "name", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - } - } - ], - "inputFields": null, - "interfaces": [], - "kind": "OBJECT", - "name": "__EnumValue", - "possibleTypes": null - }, - { - "description": null, - "enumValues": null, - "fields": [ - { - "args": [], - "deprecationReason": null, - "description": null, - "isDeprecated": false, - "name": "args", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "__InputValue", - "ofType": null - } - } - } - } - }, - { - "args": [], - "deprecationReason": null, - "description": null, - "isDeprecated": false, - "name": "deprecationReason", - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - }, - { - "args": [], - "deprecationReason": null, - "description": null, - "isDeprecated": false, - "name": "description", - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - }, - { - "args": [], - "deprecationReason": null, - "description": null, - "isDeprecated": false, - "name": "isDeprecated", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "Boolean", - "ofType": null - } - } - }, - { - "args": [], - "deprecationReason": null, - "description": null, - "isDeprecated": false, - "name": "name", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - } - }, - { - "args": [], - "deprecationReason": null, - "description": null, - "isDeprecated": false, - "name": "type", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "__Type", - "ofType": null - } - } - } - ], - "inputFields": null, - "interfaces": [], - "kind": "OBJECT", - "name": "__Field", - "possibleTypes": null - }, - { - "description": null, - "enumValues": null, - "fields": [ - { - "args": [], - "deprecationReason": null, - "description": null, - "isDeprecated": false, - "name": "defaultValue", - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - }, - { - "args": [], - "deprecationReason": null, - "description": null, - "isDeprecated": false, - "name": "description", - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - }, - { - "args": [], - "deprecationReason": null, - "description": null, - "isDeprecated": false, - "name": "name", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - } - }, - { - "args": [], - "deprecationReason": null, - "description": null, - "isDeprecated": false, - "name": "type", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "__Type", - "ofType": null - } - } - } - ], - "inputFields": null, - "interfaces": [], - "kind": "OBJECT", - "name": "__InputValue", - "possibleTypes": null - }, - { - "description": null, - "enumValues": null, - "fields": [ - { - "args": [], - "deprecationReason": null, - "description": null, - "isDeprecated": false, - "name": "directives", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "__Directive", - "ofType": null - } - } - } - } - }, - { - "args": [], - "deprecationReason": null, - "description": null, - "isDeprecated": false, - "name": "mutationType", - "type": { - "kind": "OBJECT", - "name": "__Type", - "ofType": null - } - }, - { - "args": [], - "deprecationReason": null, - "description": null, - "isDeprecated": false, - "name": "queryType", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "__Type", - "ofType": null - } - } - }, - { - "args": [], - "deprecationReason": null, - "description": null, - "isDeprecated": false, - "name": "subscriptionType", - "type": { - "kind": "OBJECT", - "name": "__Type", - "ofType": null - } - }, - { - "args": [], - "deprecationReason": null, - "description": null, - "isDeprecated": false, - "name": "types", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "__Type", - "ofType": null - } - } - } - } - } - ], - "inputFields": null, - "interfaces": [], - "kind": "OBJECT", - "name": "__Schema", - "possibleTypes": null - }, - { - "description": null, - "enumValues": null, - "fields": [ - { - "args": [], - "deprecationReason": null, - "description": null, - "isDeprecated": false, - "name": "description", - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - }, - { - "args": [ - { - "defaultValue": "false", - "description": null, - "name": "includeDeprecated", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "Boolean", - "ofType": null - } - } - } - ], - "deprecationReason": null, - "description": null, - "isDeprecated": false, - "name": "enumValues", - "type": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "__EnumValue", - "ofType": null - } - } - } - }, - { - "args": [ - { - "defaultValue": "false", - "description": null, - "name": "includeDeprecated", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "Boolean", - "ofType": null - } - } - } - ], - "deprecationReason": null, - "description": null, - "isDeprecated": false, - "name": "fields", - "type": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "__Field", - "ofType": null - } - } - } - }, - { - "args": [], - "deprecationReason": null, - "description": null, - "isDeprecated": false, - "name": "inputFields", - "type": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "__InputValue", - "ofType": null - } - } - } - }, - { - "args": [], - "deprecationReason": null, - "description": null, - "isDeprecated": false, - "name": "interfaces", - "type": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "__Type", - "ofType": null - } - } - } - }, - { - "args": [], - "deprecationReason": null, - "description": null, - "isDeprecated": false, - "name": "kind", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "ENUM", - "name": "__TypeKind", - "ofType": null - } - } - }, - { - "args": [], - "deprecationReason": null, - "description": null, - "isDeprecated": false, - "name": "name", - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - }, - { - "args": [], - "deprecationReason": null, - "description": null, - "isDeprecated": false, - "name": "ofType", - "type": { - "kind": "OBJECT", - "name": "__Type", - "ofType": null - } - }, - { - "args": [], - "deprecationReason": null, - "description": null, - "isDeprecated": false, - "name": "possibleTypes", - "type": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "__Type", - "ofType": null - } - } - } - } - ], - "inputFields": null, - "interfaces": [], - "kind": "OBJECT", - "name": "__Type", - "possibleTypes": null - }, - { - "description": null, - "enumValues": [ - { - "deprecationReason": null, - "description": null, - "isDeprecated": false, - "name": "ENUM" - }, - { - "deprecationReason": null, - "description": null, - "isDeprecated": false, - "name": "INPUT_OBJECT" - }, - { - "deprecationReason": null, - "description": null, - "isDeprecated": false, - "name": "INTERFACE" - }, - { - "deprecationReason": null, - "description": null, - "isDeprecated": false, - "name": "LIST" - }, - { - "deprecationReason": null, - "description": null, - "isDeprecated": false, - "name": "NON_NULL" - }, - { - "deprecationReason": null, - "description": null, - "isDeprecated": false, - "name": "OBJECT" - }, - { - "deprecationReason": null, - "description": null, - "isDeprecated": false, - "name": "SCALAR" - }, - { - "deprecationReason": null, - "description": null, - "isDeprecated": false, - "name": "UNION" - } - ], - "fields": null, - "inputFields": null, - "interfaces": null, - "kind": "ENUM", - "name": "__TypeKind", - "possibleTypes": null - }, - { - "description": null, - "enumValues": null, - "fields": [ - { - "args": [], - "deprecationReason": null, - "description": null, - "isDeprecated": false, - "name": "bearer", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - } - }, - { - "args": [], - "deprecationReason": null, - "description": null, - "isDeprecated": false, - "name": "token", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - } - }, - { - "args": [], - "deprecationReason": null, - "description": null, - "isDeprecated": false, - "name": "user", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "User", - "ofType": null - } - } - } - ], - "inputFields": null, - "interfaces": [], - "kind": "OBJECT", - "name": "LoginPayload", - "possibleTypes": null - }, - { - "description": null, - "enumValues": null, - "fields": [ - { - "args": [], - "deprecationReason": null, - "description": null, - "isDeprecated": false, - "name": "assignStudents", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "Boolean", - "ofType": null - } - } - }, - { - "args": [ - { - "defaultValue": "true", - "description": null, - "name": "checkLdap", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "Boolean", - "ofType": null - } - } - }, - { - "defaultValue": null, - "description": null, - "name": "input", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "INPUT_OBJECT", - "name": "UserCreateInput", - "ofType": null - } - } - } - ], - "deprecationReason": null, - "description": null, - "isDeprecated": false, - "name": "createUser", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "User", - "ofType": null - } - } - }, - { - "args": [ - { - "defaultValue": null, - "description": null, - "name": "input", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "INPUT_OBJECT", - "name": "VoteCreateInput", - "ofType": null - } - } - } - ], - "deprecationReason": null, - "description": null, - "isDeprecated": false, - "name": "createVote", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "Vote", - "ofType": null - } - } - }, - { - "args": [ - { - "defaultValue": null, - "description": null, - "name": "id", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "Int", - "ofType": null - } - } - } - ], - "deprecationReason": null, - "description": null, - "isDeprecated": false, - "name": "deleteUser", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "Int", - "ofType": null - } - } - }, - { - "args": [ - { - "defaultValue": null, - "description": null, - "name": "password", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - } - }, - { - "defaultValue": null, - "description": null, - "name": "username", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - } - } - ], - "deprecationReason": null, - "description": null, - "isDeprecated": false, - "name": "login", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "LoginPayload", - "ofType": null - } - } - } - ], - "inputFields": null, - "interfaces": [], - "kind": "OBJECT", - "name": "Mutation", - "possibleTypes": null - }, - { - "description": null, - "enumValues": null, - "fields": null, - "inputFields": [ - { - "defaultValue": null, - "description": null, - "name": "username", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - } - }, - { - "defaultValue": null, - "description": null, - "name": "role", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "ENUM", - "name": "UserRole", - "ofType": null - } - } - }, - { - "defaultValue": "false", - "description": null, - "name": "admin", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "Boolean", - "ofType": null - } - } - } - ], - "interfaces": null, - "kind": "INPUT_OBJECT", - "name": "UserCreateInput", - "possibleTypes": null - }, - { - "description": null, - "enumValues": null, - "fields": null, - "inputFields": [ - { - "defaultValue": null, - "description": null, - "name": "teacherIds", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "Int", - "ofType": null - } - } - } - } - } - ], - "interfaces": null, - "kind": "INPUT_OBJECT", - "name": "VoteCreateInput", - "possibleTypes": null - } - ] - } - } -} \ No newline at end of file